diff --git a/Utilities.cs b/Utilities.cs index 475cceb8..dddff8d2 100644 --- a/Utilities.cs +++ b/Utilities.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text.RegularExpressions; namespace DICUI { @@ -415,29 +416,27 @@ namespace DICUI switch (type) { case DiscType.CD: - return "cd"; + return Constants.CompactDiscCommand; case DiscType.DVD5: - return "dvd"; case DiscType.DVD9: - return "dvd"; + return Constants.DVDCommand; case DiscType.GDROM: - return "gd"; // TODO: "swap"? + return Constants.GDROMCommand; // TODO: Constants.GDROMSwapCommand? case DiscType.HDDVD: return null; case DiscType.BD25: - return "bd"; case DiscType.BD50: - return "bd"; + return Constants.BDCommand; // Special Formats case DiscType.GameCubeGameDisc: - return "dvd"; + return Constants.DVDCommand; case DiscType.UMD: return null; // Non-optical case DiscType.Floppy: - return "fd"; + return Constants.FloppyCommand; default: return null; @@ -464,21 +463,21 @@ namespace DICUI switch (type) { case DiscType.CD: - parameters.Add("/c2 20"); + parameters.Add(Constants.CDC2OpcodeFlag); parameters.Add("20"); switch (sys) { case KnownSystem.AppleMacintosh: case KnownSystem.IBMPCCompatible: - parameters.Add("/ns"); - parameters.Add("/sf"); - parameters.Add("/ss"); + parameters.Add(Constants.CDNoFixSubQSecuROMFlag); + parameters.Add(Constants.CDScanFileProtectFlag); + parameters.Add(Constants.CDScanSectorProtectFlag); break; case KnownSystem.NECPCEngineTurboGrafxCD: - parameters.Add("/m"); + parameters.Add(Constants.CDMCNFlag); break; case KnownSystem.SonyPlayStation: - parameters.Add("/am"); + parameters.Add(Constants.CDScanAnitModFlag); break; } break; @@ -489,7 +488,7 @@ namespace DICUI // Currently no defaults set break; case DiscType.GDROM: - parameters.Add("/c2 20"); + parameters.Add(Constants.CDC2OpcodeFlag); parameters.Add("20"); break; case DiscType.HDDVD: break; @@ -502,7 +501,7 @@ namespace DICUI // Special Formats case DiscType.GameCubeGameDisc: - parameters.Add("/raw"); + parameters.Add(Constants.DVDRawFlag); break; case DiscType.UMD: break; @@ -1257,5 +1256,357 @@ namespace DICUI return true; } + + /// + /// Validate that at string would be valid as input to DiscImageCreator + /// + /// String representing all parameters + /// True if it would be valid, false otherwise + public static bool ValidateParameters(string parameters) + { + // The string has to be valid by itself first + if (String.IsNullOrWhiteSpace(parameters)) + { + return false; + } + + // Now split the string into parts for easier validation + // https://stackoverflow.com/questions/14655023/split-a-string-that-has-white-spaces-unless-they-are-enclosed-within-quotes + parameters = parameters.Trim(); + List parts = Regex.Matches(parameters, @"[\""].+?[\""]|[^ ]+") + .Cast() + .Select(m => m.Value) + .ToList(); + + // Determine what the commandline should look like given the first item + switch (parts[0]) + { + case Constants.CompactDiscCommand: + if (!Regex.IsMatch(parts[1], @"[a-Z]:?\\?")) + { + return false; + } + else if (!File.Exists(parts[2].Trim('\"'))) + { + return false; + } + else if (!Int32.TryParse(parts[3], out int cdspeed)) + { + return false; + } + else if (cdspeed < 0 || cdspeed > 72) + { + return false; + } + + // Loop through all auxilary flags + for (int i = 4; i < parts.Count; i++) + { + switch (parts[i]) + { + case Constants.DisableBeepFlag: + case Constants.CDD8OpcodeFlag: + case Constants.CDMCNFlag: + case Constants.CDAMSFFlag: + case Constants.CDReverseFlag: + case Constants.CDMultiSessionFlag: + case Constants.CDScanSectorProtectFlag: + case Constants.CDScanAnitModFlag: + case Constants.CDNoFixSubPFlag: + case Constants.CDNoFixSubQFlag: + case Constants.CDNoFixSubRtoWFlag: + case Constants.CDNoFixSubQLibCryptFlag: + case Constants.CDNoFixSubQSecuROMFlag: + // No-op, all of these are single flags + break; + case Constants.CDScanFileProtectFlag: + // TODO: Check if next is a valid number (timeout) + break; + case Constants.ForceUnitAccessFlag: + // TODO: Check next as valid number + break; + case Constants.CDAddOffsetFlag: + // TODO: Check next as valid number + break; + case Constants.CDBEOpcodeFlag: + // TODO: Check next as valid (raw/pack) + break; + case Constants.CDC2OpcodeFlag: + // TODO: Check next (0-4) are valid numbers + break; + case Constants.CDSubchannelReadLevelFlag: + // TODO: Check next as valid number (0-2) + break; + default: + return false; + } + } + break; + case Constants.GDROMCommand: + if (!Regex.IsMatch(parts[1], @"[a-Z]:?\\?")) + { + return false; + } + else if (parts[2].Trim('\"').StartsWith("\\")) + { + return false; + } + else if (!Int32.TryParse(parts[3], out int cdspeed)) + { + return false; + } + else if (cdspeed < 0 || cdspeed > 72) + { + return false; + } + + // Loop through all auxilary flags + for (int i = 4; i < parts.Count; i++) + { + switch (parts[i]) + { + case Constants.DisableBeepFlag: + case Constants.CDD8OpcodeFlag: + case Constants.CDNoFixSubPFlag: + case Constants.CDNoFixSubQFlag: + case Constants.CDNoFixSubRtoWFlag: + case Constants.CDNoFixSubQSecuROMFlag: + // No-op, all of these are single flags + break; + case Constants.ForceUnitAccessFlag: + // TODO: Check next as valid number + break; + case Constants.CDBEOpcodeFlag: + // TODO: Check next as valid (raw/pack) + break; + case Constants.CDC2OpcodeFlag: + // TODO: Check next (0-4) are valid numbers + break; + case Constants.CDSubchannelReadLevelFlag: + // TODO: Check next as valid number (0-2) + break; + default: + return false; + } + } + break; + case Constants.DataCommand: + if (!Regex.IsMatch(parts[1], @"[a-Z]:?\\?")) + { + return false; + } + else if (parts[2].Trim('\"').StartsWith("\\")) + { + return false; + } + else if (!Int32.TryParse(parts[3], out int cdspeed)) + { + return false; + } + else if (cdspeed < 0 || cdspeed > 72) + { + return false; + } + else if (!Int32.TryParse(parts[4], out int startlba) + || !Int32.TryParse(parts[5], out int endlba)) + { + return false; + } + + // Loop through all auxilary flags + for (int i = 6; i < parts.Count; i++) + { + switch (parts[i]) + { + case Constants.DisableBeepFlag: + case Constants.CDD8OpcodeFlag: + case Constants.CDReverseFlag: + case Constants.CDScanSectorProtectFlag: + case Constants.CDNoFixSubPFlag: + case Constants.CDNoFixSubQFlag: + case Constants.CDNoFixSubRtoWFlag: + case Constants.CDNoFixSubQSecuROMFlag: + // No-op, all of these are single flags + break; + case Constants.ForceUnitAccessFlag: + // TODO: Check next as valid number + break; + case Constants.CDScanFileProtectFlag: + // TODO: Check if next is a valid number (timeout) + break; + case Constants.CDBEOpcodeFlag: + // TODO: Check next as valid (raw/pack) + break; + case Constants.CDC2OpcodeFlag: + // TODO: Check next (0-4) are valid numbers + break; + case Constants.CDSubchannelReadLevelFlag: + // TODO: Check next as valid number (0-2) + break; + default: + return false; + } + } + break; + case Constants.AudioCommand: + if (!Regex.IsMatch(parts[1], @"[a-Z]:?\\?")) + { + return false; + } + else if (parts[2].Trim('\"').StartsWith("\\")) + { + return false; + } + else if (!Int32.TryParse(parts[3], out int cdspeed)) + { + return false; + } + else if (cdspeed < 0 || cdspeed > 72) + { + return false; + } + else if (!Int32.TryParse(parts[4], out int startlba) + || !Int32.TryParse(parts[5], out int endlba)) + { + return false; + } + + // Loop through all auxilary flags + for (int i = 6; i < parts.Count; i++) + { + switch (parts[i]) + { + case Constants.DisableBeepFlag: + case Constants.CDD8OpcodeFlag: + case Constants.CDNoFixSubPFlag: + case Constants.CDNoFixSubQFlag: + case Constants.CDNoFixSubRtoWFlag: + case Constants.CDNoFixSubQSecuROMFlag: + // No-op, all of these are single flags + break; + case Constants.ForceUnitAccessFlag: + // TODO: Check next as valid number + break; + case Constants.CDAddOffsetFlag: + // TODO: Check next as valid number + break; + case Constants.CDBEOpcodeFlag: + // TODO: Check next as valid (raw/pack) + break; + case Constants.CDC2OpcodeFlag: + // TODO: Check next (0-4) are valid numbers + break; + case Constants.CDSubchannelReadLevelFlag: + // TODO: Check next as valid number (0-2) + break; + default: + return false; + } + } + break; + case Constants.DVDCommand: + if (!Regex.IsMatch(parts[1], @"[a-Z]:?\\?")) + { + return false; + } + else if (parts[2].Trim('\"').StartsWith("\\")) + { + return false; + } + else if (!Int32.TryParse(parts[3], out int dvdspeed)) + { + return false; + } + else if (dvdspeed < 0 || dvdspeed > 16) + { + return false; + } + + // Loop through all auxilary flags + for (int i = 4; i < parts.Count; i++) + { + switch (parts[i]) + { + case Constants.DisableBeepFlag: + case Constants.DVDCMIFlag: + case Constants.DVDRawFlag: + // No-op, all of these are single flags + break; + case Constants.ForceUnitAccessFlag: + // TODO: Check next as valid number + break; + default: + return false; + } + } + break; + case Constants.BDCommand: + if (!Regex.IsMatch(parts[1], @"[a-Z]:?\\?")) + { + return false; + } + else if (parts[2].Trim('\"').StartsWith("\\")) + { + return false; + } + + // Loop through all auxilary flags + for (int i = 3; i < parts.Count; i++) + { + switch (parts[i]) + { + case Constants.DisableBeepFlag: + // No-op, this is a single flag + break; + case Constants.ForceUnitAccessFlag: + // TODO: Check next as valid number + break; + default: + return false; + } + } + break; + case Constants.FloppyCommand: + if (!Regex.IsMatch(parts[1], @"[a-Z]:?\\?")) + { + return false; + } + else if (parts[2].Trim('\"').StartsWith("\\")) + { + return false; + } + else if (parts.Count > 3) + { + return false; + } + break; + case Constants.StopCommand: + case Constants.StartCommand: + case Constants.EjectCommand: + case Constants.CloseCommand: + case Constants.ResetCommand: + if (!Regex.IsMatch(parts[1], @"[a-Z]:?\\?")) + { + return false; + } + else if (parts.Count > 2) + { + return false; + } + break; + case Constants.SubCommand: + case Constants.MDSCommand: + if (parts[2].Trim('\"').StartsWith("\\")) + { + return false; + } + break; + case Constants.GDROMSwapCommand: // TODO: How to validate this? + default: + return false; + } + + return true; + } } }