diff --git a/CHANGELIST.md b/CHANGELIST.md index a3e80255..d4a88a1e 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -52,6 +52,7 @@ - Rename MPF.GUI to MPF.UI - Add multisession pseudo-tag - Add multisession helper method skeleton +- Move and update options loader; clean up Check ### 2.3 (2022-02-05) - Start overhauling Redump information pulling, again diff --git a/MPF.Check/Program.cs b/MPF.Check/Program.cs index 67ac3b00..822eb328 100644 --- a/MPF.Check/Program.cs +++ b/MPF.Check/Program.cs @@ -15,34 +15,11 @@ namespace MPF.Check { public static void Main(string[] args) { - // Help options - if (args.Length == 0 || args[0] == "-h" || args[0] == "-?") - { - DisplayHelp(); + // Try processing the standalone arguments first + if (ProcessStandaloneArguments(args)) return; - } - // List options - if (args[0] == "-lm" || args[0] == "--listmedia") - { - ListMediaTypes(); - Console.ReadLine(); - return; - } - else if (args[0] == "-lp" || args[0] == "--listprograms") - { - ListPrograms(); - Console.ReadLine(); - return; - } - else if (args[0] == "-ls" || args[0] == "--listsystems") - { - ListSystems(); - Console.ReadLine(); - return; - } - - // Normal operation check + // All other use requires at least 3 arguments if (args.Length < 3) { DisplayHelp("Invalid number of arguments"); @@ -65,82 +42,8 @@ namespace MPF.Check return; } - // Default values - string username = null, password = null; - string internalProgram = "DiscImageCreator"; - string path = string.Empty; - bool scan = false, protectFile = false, compress = false, json = false; - // Loop through and process options - int startIndex = 2; - for (; startIndex < args.Length; startIndex++) - { - // Redump login - if (args[startIndex].StartsWith("-c=") || args[startIndex].StartsWith("--credentials=")) - { - string[] credentials = args[startIndex].Split('=')[1].Split(';'); - username = credentials[0]; - password = credentials[1]; - } - else if (args[startIndex] == "-c" || args[startIndex] == "--credentials") - { - username = args[startIndex + 1]; - password = args[startIndex + 2]; - startIndex += 2; - } - - // Use specific program - else if (args[startIndex].StartsWith("-u=") || args[startIndex].StartsWith("--use=")) - { - internalProgram = args[startIndex].Split('=')[1]; - } - else if (args[startIndex] == "-u" || args[startIndex] == "--use") - { - internalProgram = args[startIndex + 1]; - startIndex++; - } - - // Use a device path for physical checks - else if (args[startIndex].StartsWith("-p=") || args[startIndex].StartsWith("--path=")) - { - path = args[startIndex].Split('=')[1]; - } - else if (args[startIndex] == "-p" || args[startIndex] == "--path") - { - path = args[startIndex + 1]; - startIndex++; - } - - // Scan for protection (requires device path) - else if (args[startIndex].Equals("-s") || args[startIndex].Equals("--scan")) - { - scan = true; - } - - // Output protection to separate file (requires scan for protection) - else if (args[startIndex].Equals("-f") || args[startIndex].Equals("--protect-file")) - { - protectFile = true; - } - - // Output submission JSON - else if (args[startIndex].Equals("-j") || args[startIndex].Equals("--json")) - { - json = true; - } - - // Compress log and extraneous files - else if (args[startIndex].Equals("-z") || args[startIndex].Equals("--zip")) - { - compress = true; - } - - // Default, we fall out - else - { - break; - } - } + (Options options, string path, int startIndex) = OptionsLoader.LoadFromArguments(args, startIndex: 2); // Make new Progress objects var resultProgress = new Progress(); @@ -148,20 +51,8 @@ namespace MPF.Check var protectionProgress = new Progress(); protectionProgress.ProgressChanged += ProgressUpdated; - // If credentials are invalid, alert the user - if (!string.IsNullOrWhiteSpace(username) && !string.IsNullOrWhiteSpace(password)) - { - using (RedumpWebClient wc = new RedumpWebClient()) - { - bool? loggedIn = wc.Login(username, password); - if (loggedIn == true) - Console.WriteLine("Redump username and password accepted!"); - else if (loggedIn == false) - Console.WriteLine("Redump username and password denied!"); - else - Console.WriteLine("An error occurred validating your crendentials!"); - } - } + // Validate the supplied credentials + ValidateCredentials(options); // Loop through all the rest of the args for (int i = startIndex; i < args.Length; i++) @@ -177,20 +68,6 @@ namespace MPF.Check string filepath = Path.GetFullPath(args[i].Trim('"')); // Now populate an environment - var options = new Options - { - InternalProgram = EnumConverter.ToInternalProgram(internalProgram), - ScanForProtection = scan && !string.IsNullOrWhiteSpace(path), - OutputSeparateProtectionFile = scan && protectFile && !string.IsNullOrWhiteSpace(path), - PromptForDiscInformation = false, - ShowDiscEjectReminder = false, - OutputSubmissionJSON = json, - CompressLogFiles = compress, - - RedumpUsername = username, - RedumpPassword = password, - }; - Drive drive = null; if (!string.IsNullOrWhiteSpace(path)) drive = new Drive(null, new DriveInfo(path)); @@ -221,20 +98,20 @@ namespace MPF.Check Console.WriteLine("-ls, --listsystems List supported system types"); Console.WriteLine("-lp, --listprograms List supported dumping program outputs"); Console.WriteLine(); + Console.WriteLine("Check Options:"); - Console.WriteLine("-c, --credentials Redump username and password"); - Console.WriteLine("-u, --use Dumping program output type"); - Console.WriteLine("-p, --path Physical drive path for additional checks"); - Console.WriteLine("-s, --scan Enable copy protection scan (requires --path)"); - Console.WriteLine("-f, --protect-file Output protection to separate file (requires --scan)"); - Console.WriteLine("-j, --json Enable submission JSON output"); - Console.WriteLine("-z, --zip Enable log file compression"); + var supportedArguments = OptionsLoader.PrintSupportedArguments(); + foreach (string argument in supportedArguments) + { + Console.WriteLine(argument); + } Console.WriteLine(); } /// /// List all media types with their short usable names /// + /// TODO: Move to a common location private static void ListMediaTypes() { Console.WriteLine("Supported Media Types:"); @@ -250,6 +127,7 @@ namespace MPF.Check /// /// List all programs with their short usable names /// + /// TODO: Move to a common location private static void ListPrograms() { Console.WriteLine("Supported Programs:"); @@ -265,6 +143,7 @@ namespace MPF.Check /// /// List all systems with their short usable names /// + /// TODO: Move to a common location private static void ListSystems() { Console.WriteLine("Supported Known Systems:"); @@ -279,6 +158,42 @@ namespace MPF.Check } } + /// + /// Process any standalone arguments for the program + /// + /// True if one of the arguments was processed, false otherwise + private static bool ProcessStandaloneArguments(string[] args) + { + // Help options + if (args.Length == 0 || args[0] == "-h" || args[0] == "-?") + { + DisplayHelp(); + return true; + } + + // List options + if (args[0] == "-lm" || args[0] == "--listmedia") + { + ListMediaTypes(); + Console.ReadLine(); + return true; + } + else if (args[0] == "-lp" || args[0] == "--listprograms") + { + ListPrograms(); + Console.ReadLine(); + return true; + } + else if (args[0] == "-ls" || args[0] == "--listsystems") + { + ListSystems(); + Console.ReadLine(); + return true; + } + + return false; + } + /// /// Simple process counter to write to console /// @@ -294,5 +209,28 @@ namespace MPF.Check { Console.WriteLine($"{value.Percentage * 100:N2}%: {value.Filename} - {value.Protection}"); } + + /// + /// Validate supplied credentials + /// + /// TODO: Move to a common location + private static void ValidateCredentials(Options options) + { + // If options are invalid or we're missing something key, just return + if (string.IsNullOrWhiteSpace(options?.RedumpUsername) || string.IsNullOrWhiteSpace(options?.RedumpPassword)) + return; + + // Try logging in with the supplied credentials otherwise + using (RedumpWebClient wc = new RedumpWebClient()) + { + bool? loggedIn = wc.Login(options.RedumpUsername, options.RedumpPassword); + if (loggedIn == true) + Console.WriteLine("Redump username and password accepted!"); + else if (loggedIn == false) + Console.WriteLine("Redump username and password denied!"); + else + Console.WriteLine("An error occurred validating your crendentials!"); + } + } } } diff --git a/MPF.Core/MPF.Core.csproj b/MPF.Core/MPF.Core.csproj index ec3624e8..62ed4bcb 100644 --- a/MPF.Core/MPF.Core.csproj +++ b/MPF.Core/MPF.Core.csproj @@ -51,6 +51,7 @@ + diff --git a/MPF.Core/Utilities/OptionsLoader.cs b/MPF.Core/Utilities/OptionsLoader.cs new file mode 100644 index 00000000..9ff9aac9 --- /dev/null +++ b/MPF.Core/Utilities/OptionsLoader.cs @@ -0,0 +1,174 @@ +using System.Collections.Generic; +using System.Configuration; +using MPF.Core.Converters; +using MPF.Core.Data; + +namespace MPF.Core.Utilities +{ + public static class OptionsLoader + { + #region Arguments + + /// + /// Load the current set of options from application arguments + /// + public static (Options, string, int) LoadFromArguments(string[] args, int startIndex = 0) + { + // Create the output values + var options = new Options(); + string parsedPath = null; + + // These values require multiple parts to be active + bool scan = false, protectFile = false; + + // If we have no arguments, just return + if (args == null || args.Length == 0) + return (options, null, 0); + + // If we have an invalid start index, just return + if (startIndex < 0 || startIndex >= args.Length) + return (options, null, startIndex); + + // Loop through the arguments and parse out values + for (; startIndex < args.Length; startIndex++) + { + // Redump login + if (args[startIndex].StartsWith("-c=") || args[startIndex].StartsWith("--credentials=")) + { + string[] credentials = args[startIndex].Split('=')[1].Split(';'); + options.RedumpUsername = credentials[0]; + options.RedumpPassword = credentials[1]; + } + else if (args[startIndex] == "-c" || args[startIndex] == "--credentials") + { + options.RedumpUsername = args[startIndex + 1]; + options.RedumpPassword = args[startIndex + 2]; + startIndex += 2; + } + + // Use specific program + else if (args[startIndex].StartsWith("-u=") || args[startIndex].StartsWith("--use=")) + { + string internalProgram = args[startIndex].Split('=')[1]; + options.InternalProgram = EnumConverter.ToInternalProgram(internalProgram); + } + else if (args[startIndex] == "-u" || args[startIndex] == "--use") + { + string internalProgram = args[startIndex + 1]; + options.InternalProgram = EnumConverter.ToInternalProgram(internalProgram); + startIndex++; + } + + // Use a device path for physical checks + else if (args[startIndex].StartsWith("-p=") || args[startIndex].StartsWith("--path=")) + { + parsedPath = args[startIndex].Split('=')[1]; + } + else if (args[startIndex] == "-p" || args[startIndex] == "--path") + { + parsedPath = args[startIndex + 1]; + startIndex++; + } + + // Scan for protection (requires device path) + else if (args[startIndex].Equals("-s") || args[startIndex].Equals("--scan")) + { + scan = true; + } + + // Output protection to separate file (requires scan for protection) + else if (args[startIndex].Equals("-f") || args[startIndex].Equals("--protect-file")) + { + protectFile = true; + } + + // Output submission JSON + else if (args[startIndex].Equals("-j") || args[startIndex].Equals("--json")) + { + options.OutputSubmissionJSON = true; + } + + // Compress log and extraneous files + else if (args[startIndex].Equals("-z") || args[startIndex].Equals("--zip")) + { + options.CompressLogFiles = true; + } + + // Default, we fall out + else + { + break; + } + } + + // We default to DiscImageCreator currently + if (options.InternalProgram == InternalProgram.NONE) + options.InternalProgram = InternalProgram.DiscImageCreator; + + // Now deal with the complex options + options.ScanForProtection = scan && !string.IsNullOrWhiteSpace(parsedPath); + options.OutputSeparateProtectionFile = scan && protectFile && !string.IsNullOrWhiteSpace(parsedPath); + + return (options, parsedPath, startIndex); + } + + /// + /// Return a list of supported arguments and descriptions + /// + public static List PrintSupportedArguments() + { + var supportedArguments = new List(); + + supportedArguments.Add("-c, --credentials Redump username and password"); + supportedArguments.Add("-u, --use Dumping program output type"); + supportedArguments.Add("-p, --path Physical drive path for additional checks"); + supportedArguments.Add("-s, --scan Enable copy protection scan (requires --path)"); + supportedArguments.Add("-f, --protect-file Output protection to separate file (requires --scan)"); + supportedArguments.Add("-j, --json Enable submission JSON output"); + supportedArguments.Add("-z, --zip Enable log file compression"); + + return supportedArguments; + } + + #endregion + + #region Configuration + + /// + /// Load the current set of options from the application configuration + /// + public static Options LoadFromConfig() + { + Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + + var settings = configFile.AppSettings.Settings; + var dict = new Dictionary(); + + foreach (string key in settings.AllKeys) + { + dict[key] = settings[key]?.Value ?? string.Empty; + } + + return new Options(dict); + } + + /// + /// Save the current set of options to the application configuration + /// + public static void SaveToConfig(Options options) + { + Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + + // Loop through all settings in Options and save them, overwriting existing settings + foreach (var kvp in options) + { + configFile.AppSettings.Settings.Remove(kvp.Key); + configFile.AppSettings.Settings.Add(kvp.Key, kvp.Value); + } + + configFile.Save(ConfigurationSaveMode.Modified); + } + + #endregion + } +} diff --git a/MPF/App.xaml.cs b/MPF/App.xaml.cs index 879b6121..8f966dd6 100644 --- a/MPF/App.xaml.cs +++ b/MPF/App.xaml.cs @@ -1,5 +1,6 @@ using System.Windows; using MPF.Core.Data; +using MPF.Core.Utilities; using MPF.UI.ViewModels; using MPF.Windows; diff --git a/MPF/OptionsLoader.cs b/MPF/OptionsLoader.cs deleted file mode 100644 index 5af4c4e6..00000000 --- a/MPF/OptionsLoader.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Collections.Generic; -using System.Configuration; -using MPF.Core.Data; - -namespace MPF -{ - public static class OptionsLoader - { - /// - /// Load the current set of options from the application configuration - /// - public static Options LoadFromConfig() - { - Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); - - var settings = configFile.AppSettings.Settings; - var dict = new Dictionary(); - - foreach (string key in settings.AllKeys) - { - dict[key] = settings[key]?.Value ?? string.Empty; - } - - return new Options(dict); - } - - /// - /// Save the current set of options to the application configuration - /// - public static void SaveToConfig(Options options) - { - Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); - - // Loop through all settings in Options and save them, overwriting existing settings - foreach (var kvp in options) - { - configFile.AppSettings.Settings.Remove(kvp.Key); - configFile.AppSettings.Settings.Add(kvp.Key, kvp.Value); - } - - configFile.Save(ConfigurationSaveMode.Modified); - } - } -}