2019-02-10 14:47:53 -08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.IO;
|
2023-10-26 00:57:23 -04:00
|
|
|
|
using BinaryObjectScanner;
|
2024-05-23 15:40:12 -04:00
|
|
|
|
using MPF.Frontend;
|
2024-05-28 14:19:59 -04:00
|
|
|
|
using MPF.Frontend.Tools;
|
2024-06-25 16:48:24 -04:00
|
|
|
|
using SabreTools.RedumpLib;
|
2023-09-05 00:08:09 -04:00
|
|
|
|
using SabreTools.RedumpLib.Data;
|
|
|
|
|
|
using SabreTools.RedumpLib.Web;
|
2019-02-10 14:47:53 -08:00
|
|
|
|
|
2020-11-10 17:43:21 -08:00
|
|
|
|
namespace MPF.Check
|
2019-02-10 14:47:53 -08:00
|
|
|
|
{
|
|
|
|
|
|
public class Program
|
|
|
|
|
|
{
|
|
|
|
|
|
public static void Main(string[] args)
|
|
|
|
|
|
{
|
2022-04-12 12:06:45 -07:00
|
|
|
|
// Try processing the standalone arguments
|
2023-10-11 12:54:40 -04:00
|
|
|
|
bool? standaloneProcessed = OptionsLoader.ProcessStandaloneArguments(args);
|
|
|
|
|
|
if (standaloneProcessed != false)
|
2023-10-10 15:15:42 -04:00
|
|
|
|
{
|
2023-10-11 12:54:40 -04:00
|
|
|
|
if (standaloneProcessed == null)
|
|
|
|
|
|
DisplayHelp();
|
2019-04-04 00:37:17 -07:00
|
|
|
|
return;
|
2023-10-10 15:15:42 -04:00
|
|
|
|
}
|
2019-04-04 00:37:17 -07:00
|
|
|
|
|
2022-04-12 12:06:45 -07:00
|
|
|
|
// Try processing the common arguments
|
2023-10-10 23:22:21 -04:00
|
|
|
|
(bool success, MediaType mediaType, RedumpSystem? knownSystem, var error) = OptionsLoader.ProcessCommonArguments(args);
|
2022-04-12 12:06:45 -07:00
|
|
|
|
if (!success)
|
2023-10-10 15:15:42 -04:00
|
|
|
|
{
|
|
|
|
|
|
DisplayHelp(error);
|
2019-04-04 00:37:17 -07:00
|
|
|
|
return;
|
2023-10-10 15:15:42 -04:00
|
|
|
|
}
|
2019-04-04 00:37:17 -07:00
|
|
|
|
|
2020-08-07 21:15:36 -07:00
|
|
|
|
// Loop through and process options
|
2024-06-25 16:48:24 -04:00
|
|
|
|
(var options, var seedInfo, var path, int startIndex) = LoadFromArguments(args, startIndex: 2);
|
2023-08-15 00:30:30 -04:00
|
|
|
|
if (options.InternalProgram == InternalProgram.NONE)
|
|
|
|
|
|
{
|
|
|
|
|
|
DisplayHelp("A program name needs to be provided");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2019-05-14 01:46:10 -07:00
|
|
|
|
|
2020-08-07 21:15:36 -07:00
|
|
|
|
// Make new Progress objects
|
2024-05-22 14:49:45 -04:00
|
|
|
|
var resultProgress = new Progress<ResultEventArgs>();
|
2023-10-10 15:15:42 -04:00
|
|
|
|
resultProgress.ProgressChanged += ConsoleLogger.ProgressUpdated;
|
2021-01-22 12:03:12 -08:00
|
|
|
|
var protectionProgress = new Progress<ProtectionProgress>();
|
2023-10-10 15:15:42 -04:00
|
|
|
|
protectionProgress.ProgressChanged += ConsoleLogger.ProgressUpdated;
|
2019-02-10 14:47:53 -08:00
|
|
|
|
|
2022-04-12 11:27:10 -07:00
|
|
|
|
// Validate the supplied credentials
|
2023-11-14 23:53:15 -05:00
|
|
|
|
#if NETFRAMEWORK
|
|
|
|
|
|
(bool? _, string? message) = RedumpWebClient.ValidateCredentials(options.RedumpUsername ?? string.Empty, options.RedumpPassword ?? string.Empty);
|
|
|
|
|
|
#else
|
2023-10-10 23:22:21 -04:00
|
|
|
|
(bool? _, string? message) = RedumpHttpClient.ValidateCredentials(options.RedumpUsername ?? string.Empty, options.RedumpPassword ?? string.Empty).ConfigureAwait(false).GetAwaiter().GetResult();
|
2023-11-14 23:53:15 -05:00
|
|
|
|
#endif
|
2023-11-22 15:56:43 -05:00
|
|
|
|
if (!string.IsNullOrEmpty(message))
|
2022-04-12 12:01:26 -07:00
|
|
|
|
Console.WriteLine(message);
|
2020-06-16 11:16:39 -07:00
|
|
|
|
|
2019-02-10 14:47:53 -08:00
|
|
|
|
// Loop through all the rest of the args
|
2019-05-14 01:46:10 -07:00
|
|
|
|
for (int i = startIndex; i < args.Length; i++)
|
2019-02-10 14:47:53 -08:00
|
|
|
|
{
|
2019-03-30 21:44:57 -07:00
|
|
|
|
// Check for a file
|
2020-06-16 13:25:45 -07:00
|
|
|
|
if (!File.Exists(args[i].Trim('"')))
|
2019-02-10 14:47:53 -08:00
|
|
|
|
{
|
2020-06-16 13:25:45 -07:00
|
|
|
|
DisplayHelp($"{args[i].Trim('"')} does not exist");
|
2019-02-10 14:47:53 -08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-04-20 22:03:23 -07:00
|
|
|
|
// Get the full file path
|
2020-06-16 13:25:45 -07:00
|
|
|
|
string filepath = Path.GetFullPath(args[i].Trim('"'));
|
2019-04-20 22:03:23 -07:00
|
|
|
|
|
2019-02-10 14:47:53 -08:00
|
|
|
|
// Now populate an environment
|
2023-10-10 23:22:21 -04:00
|
|
|
|
Drive? drive = null;
|
2023-11-22 15:56:43 -05:00
|
|
|
|
if (!string.IsNullOrEmpty(path))
|
2023-11-14 23:53:15 -05:00
|
|
|
|
drive = Drive.Create(null, path!);
|
2020-08-07 21:15:36 -07:00
|
|
|
|
|
2023-04-11 11:15:53 -04:00
|
|
|
|
var env = new DumpEnvironment(options, filepath, drive, knownSystem, mediaType, internalProgram: null, parameters: null);
|
2019-02-10 14:47:53 -08:00
|
|
|
|
|
|
|
|
|
|
// Finally, attempt to do the output dance
|
2023-11-22 23:38:59 -05:00
|
|
|
|
#if NET40
|
2023-11-22 16:02:08 -05:00
|
|
|
|
var resultTask = env.VerifyAndSaveDumpOutput(resultProgress, protectionProgress);
|
|
|
|
|
|
resultTask.Wait();
|
|
|
|
|
|
var result = resultTask.Result;
|
2023-11-21 11:13:58 -05:00
|
|
|
|
#else
|
2020-08-07 21:15:36 -07:00
|
|
|
|
var result = env.VerifyAndSaveDumpOutput(resultProgress, protectionProgress).ConfigureAwait(false).GetAwaiter().GetResult();
|
2023-11-21 11:13:58 -05:00
|
|
|
|
#endif
|
2019-02-10 14:47:53 -08:00
|
|
|
|
Console.WriteLine(result.Message);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-04-04 00:37:17 -07:00
|
|
|
|
/// <summary>
|
2020-11-10 17:43:21 -08:00
|
|
|
|
/// Display help for MPF.Check
|
2019-04-04 00:37:17 -07:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="error">Error string to prefix the help text with</param>
|
2023-10-10 23:22:21 -04:00
|
|
|
|
private static void DisplayHelp(string? error = null)
|
2019-02-10 14:47:53 -08:00
|
|
|
|
{
|
|
|
|
|
|
if (error != null)
|
|
|
|
|
|
Console.WriteLine(error);
|
|
|
|
|
|
|
|
|
|
|
|
Console.WriteLine("Usage:");
|
2024-06-24 10:37:05 -04:00
|
|
|
|
Console.WriteLine("MPF.Check <mediatype> <system> [options] </path/to/output.cue/iso> ...");
|
2019-02-10 14:47:53 -08:00
|
|
|
|
Console.WriteLine();
|
2020-08-07 21:15:36 -07:00
|
|
|
|
Console.WriteLine("Standalone Options:");
|
|
|
|
|
|
Console.WriteLine("-h, -? Show this help text");
|
2024-05-15 15:49:40 -04:00
|
|
|
|
Console.WriteLine("-lc, --listcodes List supported comment/content site codes");
|
2020-08-07 21:15:36 -07:00
|
|
|
|
Console.WriteLine("-lm, --listmedia List supported media types");
|
|
|
|
|
|
Console.WriteLine("-ls, --listsystems List supported system types");
|
|
|
|
|
|
Console.WriteLine("-lp, --listprograms List supported dumping program outputs");
|
2020-05-07 14:23:49 -07:00
|
|
|
|
Console.WriteLine();
|
2022-04-12 11:27:10 -07:00
|
|
|
|
|
2020-08-07 21:15:36 -07:00
|
|
|
|
Console.WriteLine("Check Options:");
|
2024-06-25 16:48:24 -04:00
|
|
|
|
Console.WriteLine("-u, --use <program> Dumping program output type [REQUIRED]");
|
|
|
|
|
|
Console.WriteLine("-c, --credentials <user> <pw> Redump username and password");
|
|
|
|
|
|
Console.WriteLine("-a, --pull-all Pull all information from Redump (requires --credentials)");
|
|
|
|
|
|
Console.WriteLine("-p, --path <drivepath> Physical drive path for additional checks");
|
|
|
|
|
|
Console.WriteLine("-s, --scan Enable copy protection scan (requires --path)");
|
|
|
|
|
|
Console.WriteLine("-g, --hide-drive-letters Hide drive letters from scan output (requires --protect-file)");
|
|
|
|
|
|
Console.WriteLine("-l, --load-seed <path> Load a seed submission JSON for user information");
|
|
|
|
|
|
Console.WriteLine("-x, --suffix Enable adding filename suffix");
|
|
|
|
|
|
Console.WriteLine("-j, --json Enable submission JSON output");
|
|
|
|
|
|
Console.WriteLine("-z, --zip Enable log file compression");
|
|
|
|
|
|
Console.WriteLine("-d, --delete Enable unnecessary file deletion");
|
|
|
|
|
|
Console.WriteLine();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Load the current set of options from application arguments
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private static (Frontend.Options, SubmissionInfo?, string?, int) LoadFromArguments(string[] args, int startIndex = 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Create the output values with defaults
|
|
|
|
|
|
var options = new Frontend.Options()
|
2022-04-12 11:27:10 -07:00
|
|
|
|
{
|
2024-06-25 16:48:24 -04:00
|
|
|
|
RedumpUsername = null,
|
|
|
|
|
|
RedumpPassword = null,
|
|
|
|
|
|
InternalProgram = InternalProgram.NONE,
|
|
|
|
|
|
AddFilenameSuffix = false,
|
|
|
|
|
|
OutputSubmissionJSON = false,
|
|
|
|
|
|
CompressLogFiles = false,
|
|
|
|
|
|
DeleteUnnecessaryFiles = false,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Create the submission info to return, if necessary
|
|
|
|
|
|
SubmissionInfo? info = null;
|
|
|
|
|
|
string? parsedPath = null;
|
|
|
|
|
|
|
|
|
|
|
|
// These values require multiple parts to be active
|
|
|
|
|
|
bool scan = false, hideDriveLetters = false;
|
|
|
|
|
|
|
|
|
|
|
|
// If we have no arguments, just return
|
|
|
|
|
|
if (args == null || args.Length == 0)
|
|
|
|
|
|
return (options, null, null, 0);
|
|
|
|
|
|
|
|
|
|
|
|
// If we have an invalid start index, just return
|
|
|
|
|
|
if (startIndex < 0 || startIndex >= args.Length)
|
|
|
|
|
|
return (options, null, null, startIndex);
|
|
|
|
|
|
|
|
|
|
|
|
// Loop through the arguments and parse out values
|
|
|
|
|
|
for (; startIndex < args.Length; startIndex++)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Use specific program
|
|
|
|
|
|
if (args[startIndex].StartsWith("-u=") || args[startIndex].StartsWith("--use="))
|
|
|
|
|
|
{
|
|
|
|
|
|
string internalProgram = args[startIndex].Split('=')[1];
|
|
|
|
|
|
options.InternalProgram = Frontend.Options.ToInternalProgram(internalProgram);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (args[startIndex] == "-u" || args[startIndex] == "--use")
|
|
|
|
|
|
{
|
|
|
|
|
|
string internalProgram = args[startIndex + 1];
|
|
|
|
|
|
options.InternalProgram = Frontend.Options.ToInternalProgram(internalProgram);
|
|
|
|
|
|
startIndex++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Redump login
|
|
|
|
|
|
else 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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Pull all information (requires Redump login)
|
|
|
|
|
|
else if (args[startIndex].Equals("-a") || args[startIndex].Equals("--pull-all"))
|
|
|
|
|
|
{
|
|
|
|
|
|
options.PullAllInformation = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Hide drive letters from scan output (requires --protect-file)
|
|
|
|
|
|
else if (args[startIndex].Equals("-g") || args[startIndex].Equals("--hide-drive-letters"))
|
|
|
|
|
|
{
|
|
|
|
|
|
hideDriveLetters = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Include seed info file
|
|
|
|
|
|
else if (args[startIndex].StartsWith("-l=") || args[startIndex].StartsWith("--load-seed="))
|
|
|
|
|
|
{
|
|
|
|
|
|
string seedInfo = args[startIndex].Split('=')[1];
|
|
|
|
|
|
info = Builder.CreateFromFile(seedInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (args[startIndex] == "-l" || args[startIndex] == "--load-seed")
|
|
|
|
|
|
{
|
|
|
|
|
|
string seedInfo = args[startIndex + 1];
|
|
|
|
|
|
info = Builder.CreateFromFile(seedInfo);
|
|
|
|
|
|
startIndex++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Add filename suffix
|
|
|
|
|
|
else if (args[startIndex].Equals("-x") || args[startIndex].Equals("--suffix"))
|
|
|
|
|
|
{
|
|
|
|
|
|
options.AddFilenameSuffix = 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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Delete unnecessary files files
|
|
|
|
|
|
else if (args[startIndex].Equals("-d") || args[startIndex].Equals("--delete"))
|
|
|
|
|
|
{
|
|
|
|
|
|
options.DeleteUnnecessaryFiles = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Default, we fall out
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2022-04-12 11:27:10 -07:00
|
|
|
|
}
|
2024-06-25 16:48:24 -04:00
|
|
|
|
|
|
|
|
|
|
// Now deal with the complex options
|
|
|
|
|
|
options.ScanForProtection = scan && !string.IsNullOrEmpty(parsedPath);
|
|
|
|
|
|
options.HideDriveLetters = hideDriveLetters && scan && !string.IsNullOrEmpty(parsedPath);
|
|
|
|
|
|
|
|
|
|
|
|
return (options, info, parsedPath, startIndex);
|
2019-02-10 14:47:53 -08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|