From 3d2ba9ec233f5db416215e9c1446138e6639da1a Mon Sep 17 00:00:00 2001 From: Miepee Date: Sat, 10 Dec 2022 15:21:15 +0100 Subject: [PATCH] better handle 1.1 verification --- AM2RModPacker/ModPacker.Designer.cs | 2 +- AM2RModPacker/ModPacker.cs | 9 +++ AM2RModPackerLib/Core.cs | 92 ++++++++++++++++++++++++----- 3 files changed, 87 insertions(+), 16 deletions(-) diff --git a/AM2RModPacker/ModPacker.Designer.cs b/AM2RModPacker/ModPacker.Designer.cs index 751569e..23e4854 100644 --- a/AM2RModPacker/ModPacker.Designer.cs +++ b/AM2RModPacker/ModPacker.Designer.cs @@ -12,7 +12,7 @@ public partial class ModPacker : Form profile = new ModProfileXML(); Title = "AM2R ModPacker " + version; - // Currently broken as I don't know how to do this from Rider + //TODO: Currently broken as I don't know how to do this from Rider //Icon = Icon.FromResource("icon64.ico"); MinimumSize = new Size(550, 400); diff --git a/AM2RModPacker/ModPacker.cs b/AM2RModPacker/ModPacker.cs index 7efbc1c..f696937 100644 --- a/AM2RModPacker/ModPacker.cs +++ b/AM2RModPacker/ModPacker.cs @@ -213,6 +213,15 @@ public partial class ModPacker : Form MessageBox.Show("Name contains invalid characters! These characters are not allowed:\n" + String.Join("\n", Path.GetInvalidFileNameChars())); return; } + + // Verify 1.1 + var result11 = Core.CheckIfZipIsAM2R11(originalPath); + if (result11 != IsZipAM2R11ReturnCodes.Successful) + { + MessageBox.Show("AM2R 1.1 zip is invalid! Error code: " + result11); + AbortPatch(); + return; + } createLabel.Visible = true; createLabel.Text = "Packaging mod(s)... This could take a while!"; diff --git a/AM2RModPackerLib/Core.cs b/AM2RModPackerLib/Core.cs index 4c8ce6d..1b0037f 100644 --- a/AM2RModPackerLib/Core.cs +++ b/AM2RModPackerLib/Core.cs @@ -14,6 +14,18 @@ public enum ProfileOperatingSystems Mac } +/// +/// An enum, that has possible return codes for . +/// +public enum IsZipAM2R11ReturnCodes +{ + Successful, + MissingOrInvalidAM2RExe, + MissingOrInvalidD3DX943Dll, + MissingOrInvalidDataWin, + GameIsInASubfolder +} + public static class Core { public static readonly string Version = "2.0.3"; @@ -53,21 +65,7 @@ public static class Core if (Directory.Exists(tempModPath + "/AM2R")) tempModPath += "/AM2R"; - - // Verify 1.1 with an MD5. If it does not match, exit cleanly and provide a warning window. - try - { - // TODO: dont. do what launcher does - string newMD5 = CalculateMD5(tempOriginalPath + "/data.win"); - - if (newMD5 != originalMD5) - return (false, "1.1 data.win does not meet MD5 checksum! Mod packaging aborted.\n1.1 MD5: " + originalMD5 + "\nYour MD5: " + newMD5); - } - catch (FileNotFoundException) - { - return (false, "data.win not found! Are you sure you selected AM2R 1.1? Mod packaging aborted."); - } - + switch (profile.OperatingSystem) { // Create AM2R.exe and data.win patches @@ -259,6 +257,70 @@ public static class Core } } + // Taken from AM2RLauncher + /// + /// Checks if a Zip file is a valid AM2R_1.1 zip. + /// + /// Full Path to the Zip file to validate. + /// detailing the result + public static IsZipAM2R11ReturnCodes CheckIfZipIsAM2R11(string zipPath) + { + const string d3dHash = "86e39e9161c3d930d93822f1563c280d"; + const string dataWinHash = "f2b84fe5ba64cb64e284be1066ca08ee"; + const string am2rHash = "15253f7a66d6ea3feef004ebbee9b438"; + string tmpPath = Path.GetTempPath() + Path.GetFileNameWithoutExtension(zipPath); + + // Clean up in case folder exists already + if (Directory.Exists(tmpPath)) + Directory.Delete(tmpPath, true); + Directory.CreateDirectory(tmpPath); + + // Open archive + ZipArchive am2rZip = ZipFile.OpenRead(zipPath); + + + // Check if exe exists anywhere + ZipArchiveEntry am2rExe = am2rZip.Entries.FirstOrDefault(x => x.FullName.Contains("AM2R.exe")); + if (am2rExe == null) + return IsZipAM2R11ReturnCodes.MissingOrInvalidAM2RExe; + + // Check if it's not in a subfolder. if it'd be in a subfolder, fullname would be "folder/AM2R.exe" + if (am2rExe.FullName != "AM2R.exe") + return IsZipAM2R11ReturnCodes.GameIsInASubfolder; + + // Check validity + am2rExe.ExtractToFile($"{tmpPath}/{am2rExe.FullName}"); + if (CalculateMD5($"{tmpPath}/{am2rExe.FullName}") != am2rHash) + return IsZipAM2R11ReturnCodes.MissingOrInvalidAM2RExe; + + + // Check if data.win exists / is valid + ZipArchiveEntry dataWin = am2rZip.Entries.FirstOrDefault(x => x.FullName == "data.win"); + if (dataWin == null) + return IsZipAM2R11ReturnCodes.MissingOrInvalidDataWin; + + dataWin.ExtractToFile($"{tmpPath}/{dataWin.FullName}"); + if (CalculateMD5($"{tmpPath}/{dataWin.FullName}") != dataWinHash) + return IsZipAM2R11ReturnCodes.MissingOrInvalidDataWin; + + + // Check if d3d.dll exists / is valid + ZipArchiveEntry d3dx = am2rZip.Entries.FirstOrDefault(x => x.FullName == "D3DX9_43.dll"); + if (d3dx == null) + return IsZipAM2R11ReturnCodes.MissingOrInvalidD3DX943Dll; + + d3dx.ExtractToFile($"{tmpPath}/{d3dx.FullName}"); + if (CalculateMD5($"{tmpPath}/{d3dx.FullName}") != d3dHash) + return IsZipAM2R11ReturnCodes.MissingOrInvalidD3DX943Dll; + + + // Clean up + Directory.Delete(tmpPath, true); + + // If we didn't exit before, everything is fine + return IsZipAM2R11ReturnCodes.Successful; + } + public static string CalculateMD5(string filename) { using var stream = File.OpenRead(filename);