diff --git a/Deheader/Headerer.cs b/Deheader/Headerer.cs index b3ce7a54..a52846ef 100644 --- a/Deheader/Headerer.cs +++ b/Deheader/Headerer.cs @@ -254,7 +254,7 @@ namespace SabreTools } // Now add the information to the database if it's not already there - Rom rom = RomTools.GetSingleFileInfo(newfile); + Rom rom = FileTools.GetSingleFileInfo(newfile); AddHeaderToDatabase(hstr, rom.HashData.SHA1, type); } @@ -309,7 +309,7 @@ namespace SabreTools public bool ReplaceHeader(string file) { // First, get the SHA-1 hash of the file - Rom rom = RomTools.GetSingleFileInfo(file); + Rom rom = FileTools.GetSingleFileInfo(file); // Then try to pull the corresponding headers from the database string header = ""; diff --git a/SabreTools.Helper/Tools/DatTools.cs b/SabreTools.Helper/Tools/DatTools.cs index cac4e613..c848fcc0 100644 --- a/SabreTools.Helper/Tools/DatTools.cs +++ b/SabreTools.Helper/Tools/DatTools.cs @@ -295,9 +295,9 @@ namespace SabreTools.Helper } // Sanitize the hashes from null, hex sizes, and "true blank" strings - rom.HashData.CRC = RomTools.CleanHashData(rom.HashData.CRC, Constants.CRCLength); - rom.HashData.MD5 = RomTools.CleanHashData(rom.HashData.MD5, Constants.MD5Length); - rom.HashData.SHA1 = RomTools.CleanHashData(rom.HashData.SHA1, Constants.SHA1Length); + rom.HashData.CRC = Style.CleanHashData(rom.HashData.CRC, Constants.CRCLength); + rom.HashData.MD5 = Style.CleanHashData(rom.HashData.MD5, Constants.MD5Length); + rom.HashData.SHA1 = Style.CleanHashData(rom.HashData.SHA1, Constants.SHA1Length); // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info if (rom.Type == ItemType.Rom && (rom.HashData.Size == 0 || rom.HashData.Size == -1) && ((rom.HashData.CRC == Constants.CRCZero || rom.HashData.CRC == "") || rom.HashData.MD5 == Constants.MD5Zero || rom.HashData.SHA1 == Constants.SHA1Zero)) @@ -583,9 +583,9 @@ namespace SabreTools.Helper }; // Sanitize the hashes from null, hex sizes, and "true blank" strings - rom.HashData.CRC = RomTools.CleanHashData(rom.HashData.CRC, Constants.CRCLength); - rom.HashData.MD5 = RomTools.CleanHashData(rom.HashData.MD5, Constants.MD5Length); - rom.HashData.SHA1 = RomTools.CleanHashData(rom.HashData.SHA1, Constants.SHA1Length); + rom.HashData.CRC = Style.CleanHashData(rom.HashData.CRC, Constants.CRCLength); + rom.HashData.MD5 = Style.CleanHashData(rom.HashData.MD5, Constants.MD5Length); + rom.HashData.SHA1 = Style.CleanHashData(rom.HashData.SHA1, Constants.SHA1Length); // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info if (rom.Type == ItemType.Rom && (rom.HashData.Size == 0 || rom.HashData.Size == -1) && ((rom.HashData.CRC == Constants.CRCZero || rom.HashData.CRC == "") || rom.HashData.MD5 == Constants.MD5Zero || rom.HashData.SHA1 == Constants.SHA1Zero)) @@ -1089,9 +1089,9 @@ namespace SabreTools.Helper } // Sanitize the hashes from null, hex sizes, and "true blank" strings - crc = RomTools.CleanHashData(subreader.GetAttribute("crc"), Constants.CRCLength); - md5 = RomTools.CleanHashData(subreader.GetAttribute("md5"), Constants.MD5Length); - sha1 = RomTools.CleanHashData(subreader.GetAttribute("sha1"), Constants.SHA1Length); + crc = Style.CleanHashData(subreader.GetAttribute("crc"), Constants.CRCLength); + md5 = Style.CleanHashData(subreader.GetAttribute("md5"), Constants.MD5Length); + sha1 = Style.CleanHashData(subreader.GetAttribute("sha1"), Constants.SHA1Length); // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info if (subreader.Name == "rom" && (size == 0 || size == -1) && @@ -1320,9 +1320,9 @@ namespace SabreTools.Helper } // Sanitize the hashes from null, hex sizes, and "true blank" strings - crc = RomTools.CleanHashData(xtr.GetAttribute("crc"), Constants.CRCLength); - md5 = RomTools.CleanHashData(xtr.GetAttribute("md5"), Constants.MD5Length); - sha1 = RomTools.CleanHashData(xtr.GetAttribute("sha1"), Constants.SHA1Length); + crc = Style.CleanHashData(xtr.GetAttribute("crc"), Constants.CRCLength); + md5 = Style.CleanHashData(xtr.GetAttribute("md5"), Constants.MD5Length); + sha1 = Style.CleanHashData(xtr.GetAttribute("sha1"), Constants.SHA1Length); // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info if (xtr.GetAttribute("type") == "rom" && (size == 0 || size == -1) && ((crc == Constants.CRCZero || crc == "") || md5 == Constants.MD5Zero || sha1 == Constants.SHA1Zero)) @@ -2519,9 +2519,9 @@ namespace SabreTools.Helper } // Sanitize the hashes from null, hex sizes, and "true blank" strings - hashData.CRC = RomTools.CleanHashData(hashData.CRC, Constants.CRCBytesLength); - hashData.MD5 = RomTools.CleanHashData(hashData.MD5, Constants.MD5BytesLength); - hashData.SHA1 = RomTools.CleanHashData(hashData.SHA1, Constants.SHA1BytesLength); + hashData.CRC = Style.CleanHashData(hashData.CRC, Constants.CRCBytesLength); + hashData.MD5 = Style.CleanHashData(hashData.MD5, Constants.MD5BytesLength); + hashData.SHA1 = Style.CleanHashData(hashData.SHA1, Constants.SHA1BytesLength); // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info if (romData.Type == ItemType.Rom @@ -2806,9 +2806,9 @@ namespace SabreTools.Helper }; // Sanitize the hashes from null, hex sizes, and "true blank" strings - hashData.CRC = RomTools.CleanHashData(hashData.CRC, Constants.CRCBytesLength); - hashData.MD5 = RomTools.CleanHashData(hashData.MD5, Constants.MD5BytesLength); - hashData.SHA1 = RomTools.CleanHashData(hashData.SHA1, Constants.SHA1BytesLength); + hashData.CRC = Style.CleanHashData(hashData.CRC, Constants.CRCBytesLength); + hashData.MD5 = Style.CleanHashData(hashData.MD5, Constants.MD5BytesLength); + hashData.SHA1 = Style.CleanHashData(hashData.SHA1, Constants.SHA1BytesLength); // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info if (romData.Type == ItemType.Rom @@ -3299,9 +3299,9 @@ namespace SabreTools.Helper } // Sanitize the hashes from null, hex sizes, and "true blank" strings - crc = RomTools.CleanHashData(subreader.GetAttribute("crc"), Constants.CRCLength); - md5 = RomTools.CleanHashData(subreader.GetAttribute("md5"), Constants.MD5Length); - sha1 = RomTools.CleanHashData(subreader.GetAttribute("sha1"), Constants.SHA1Length); + crc = Style.CleanHashData(subreader.GetAttribute("crc"), Constants.CRCLength); + md5 = Style.CleanHashData(subreader.GetAttribute("md5"), Constants.MD5Length); + sha1 = Style.CleanHashData(subreader.GetAttribute("sha1"), Constants.SHA1Length); // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info if (subreader.Name == "rom" && (size == 0 || size == -1) && @@ -3353,9 +3353,9 @@ namespace SabreTools.Helper HashData hashData = new HashData { Size = size, - CRC = RomTools.CleanHashData(Style.StringToByteArray(crc), Constants.CRCBytesLength), - MD5 = RomTools.CleanHashData(Style.StringToByteArray(md5), Constants.MD5BytesLength), - SHA1 = RomTools.CleanHashData(Style.StringToByteArray(sha1), Constants.SHA1BytesLength), + CRC = Style.CleanHashData(Style.StringToByteArray(crc), Constants.CRCBytesLength), + MD5 = Style.CleanHashData(Style.StringToByteArray(md5), Constants.MD5BytesLength), + SHA1 = Style.CleanHashData(Style.StringToByteArray(sha1), Constants.SHA1BytesLength), Roms = new List(), }; hashData.Roms.Add(romData); @@ -3513,9 +3513,9 @@ namespace SabreTools.Helper } // Sanitize the hashes from null, hex sizes, and "true blank" strings - crc = RomTools.CleanHashData(xtr.GetAttribute("crc"), Constants.CRCLength); - md5 = RomTools.CleanHashData(xtr.GetAttribute("md5"), Constants.MD5Length); - sha1 = RomTools.CleanHashData(xtr.GetAttribute("sha1"), Constants.SHA1Length); + crc = Style.CleanHashData(xtr.GetAttribute("crc"), Constants.CRCLength); + md5 = Style.CleanHashData(xtr.GetAttribute("md5"), Constants.MD5Length); + sha1 = Style.CleanHashData(xtr.GetAttribute("sha1"), Constants.SHA1Length); // If we have a rom and it's missing size AND the hashes match a 0-byte file, fill in the rest of the info if (xtr.GetAttribute("type") == "rom" && (size == 0 || size == -1) && ((crc == Constants.CRCZero || crc == "") || md5 == Constants.MD5Zero || sha1 == Constants.SHA1Zero)) @@ -3575,9 +3575,9 @@ namespace SabreTools.Helper HashData hashData = new HashData { Size = size, - CRC = RomTools.CleanHashData(Style.StringToByteArray(crc), Constants.CRCBytesLength), - MD5 = RomTools.CleanHashData(Style.StringToByteArray(md5), Constants.MD5BytesLength), - SHA1 = RomTools.CleanHashData(Style.StringToByteArray(sha1), Constants.SHA1BytesLength), + CRC = Style.CleanHashData(Style.StringToByteArray(crc), Constants.CRCBytesLength), + MD5 = Style.CleanHashData(Style.StringToByteArray(md5), Constants.MD5BytesLength), + SHA1 = Style.CleanHashData(Style.StringToByteArray(sha1), Constants.SHA1BytesLength), Roms = new List(), }; hashData.Roms.Add(romData); diff --git a/SabreTools.Helper/Tools/FileTools.cs b/SabreTools.Helper/Tools/FileTools.cs index 2f6dd4ac..2ac33722 100644 --- a/SabreTools.Helper/Tools/FileTools.cs +++ b/SabreTools.Helper/Tools/FileTools.cs @@ -1,4 +1,5 @@ -using SharpCompress.Archive; +using DamienG.Security.Cryptography; +using SharpCompress.Archive; using SharpCompress.Archive.SevenZip; using SharpCompress.Common; using SharpCompress.Reader; @@ -7,6 +8,7 @@ using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; +using System.Security.Cryptography; using System.Text.RegularExpressions; namespace SabreTools.Helper @@ -141,7 +143,7 @@ namespace SabreTools.Helper outdir = Path.GetFullPath(outdir); // Now get the Rom info for the file so we have hashes and size - Rom rom = RomTools.GetSingleFileInfo(input); + Rom rom = FileTools.GetSingleFileInfo(input); // If it doesn't exist, create the output file and then write string outfile = Path.Combine(outdir, rom.HashData.SHA1 + ".gz"); @@ -575,6 +577,86 @@ namespace SabreTools.Helper #region File Information Methods + /// + /// Retrieve file information for a single file + /// + /// Filename to get information from + /// True if MD5 hashes should not be calculated, false otherwise + /// True if SHA-1 hashes should not be calcluated, false otherwise + /// Populated RomData object if success, empty one on error + /// Add read-offset for hash info + public static Rom GetSingleFileInfo(string input, bool noMD5 = false, bool noSHA1 = false, long offset = 0) + { + // Add safeguard if file doesn't exist + if (!File.Exists(input)) + { + return new Rom(); + } + + Rom rom = new Rom + { + Name = Path.GetFileName(input), + Type = ItemType.Rom, + HashData = new Hash + { + Size = (new FileInfo(input)).Length, + CRC = string.Empty, + MD5 = string.Empty, + SHA1 = string.Empty, + } + }; + + try + { + using (Crc32 crc = new Crc32()) + using (MD5 md5 = MD5.Create()) + using (SHA1 sha1 = SHA1.Create()) + using (FileStream fs = File.OpenRead(input)) + { + // Seek to the starting position, if one is set + if (offset > 0) + { + fs.Seek(offset, SeekOrigin.Begin); + } + + byte[] buffer = new byte[1024]; + int read; + while ((read = fs.Read(buffer, 0, buffer.Length)) > 0) + { + crc.TransformBlock(buffer, 0, read, buffer, 0); + if (!noMD5) + { + md5.TransformBlock(buffer, 0, read, buffer, 0); + } + if (!noSHA1) + { + sha1.TransformBlock(buffer, 0, read, buffer, 0); + } + } + + crc.TransformFinalBlock(buffer, 0, 0); + rom.HashData.CRC = BitConverter.ToString(crc.Hash).Replace("-", "").ToLowerInvariant(); + + if (!noMD5) + { + md5.TransformFinalBlock(buffer, 0, 0); + rom.HashData.MD5 = BitConverter.ToString(md5.Hash).Replace("-", "").ToLowerInvariant(); + } + if (!noSHA1) + { + sha1.TransformFinalBlock(buffer, 0, 0); + rom.HashData.SHA1 = BitConverter.ToString(sha1.Hash).Replace("-", "").ToLowerInvariant(); + } + } + } + catch (IOException) + { + return new Rom(); + } + + return rom; + } + /// /// Generate a list of RomData objects from the header values in an archive /// diff --git a/SabreTools.Helper/Tools/RomTools.cs b/SabreTools.Helper/Tools/RomTools.cs index 65297061..9bbc7758 100644 --- a/SabreTools.Helper/Tools/RomTools.cs +++ b/SabreTools.Helper/Tools/RomTools.cs @@ -1,95 +1,12 @@ -using DamienG.Security.Cryptography; -using System; +using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Security.Cryptography; using System.Text.RegularExpressions; namespace SabreTools.Helper { public class RomTools { - /// - /// Retrieve file information for a single file - /// - /// Filename to get information from - /// True if MD5 hashes should not be calculated, false otherwise - /// True if SHA-1 hashes should not be calcluated, false otherwise - /// Populated RomData object if success, empty one on error - /// Add read-offset for hash info - public static Rom GetSingleFileInfo(string input, bool noMD5 = false, bool noSHA1 = false, long offset = 0) - { - // Add safeguard if file doesn't exist - if (!File.Exists(input)) - { - return new Rom(); - } - - Rom rom = new Rom - { - Name = Path.GetFileName(input), - Type = ItemType.Rom, - HashData = new Hash - { - Size = (new FileInfo(input)).Length, - CRC = string.Empty, - MD5 = string.Empty, - SHA1 = string.Empty, - } - }; - - try - { - using (Crc32 crc = new Crc32()) - using (MD5 md5 = MD5.Create()) - using (SHA1 sha1 = SHA1.Create()) - using (FileStream fs = File.OpenRead(input)) - { - // Seek to the starting position, if one is set - if (offset > 0) - { - fs.Seek(offset, SeekOrigin.Begin); - } - - byte[] buffer = new byte[1024]; - int read; - while ((read = fs.Read(buffer, 0, buffer.Length)) > 0) - { - crc.TransformBlock(buffer, 0, read, buffer, 0); - if (!noMD5) - { - md5.TransformBlock(buffer, 0, read, buffer, 0); - } - if (!noSHA1) - { - sha1.TransformBlock(buffer, 0, read, buffer, 0); - } - } - - crc.TransformFinalBlock(buffer, 0, 0); - rom.HashData.CRC = BitConverter.ToString(crc.Hash).Replace("-", "").ToLowerInvariant(); - - if (!noMD5) - { - md5.TransformFinalBlock(buffer, 0, 0); - rom.HashData.MD5 = BitConverter.ToString(md5.Hash).Replace("-", "").ToLowerInvariant(); - } - if (!noSHA1) - { - sha1.TransformFinalBlock(buffer, 0, 0); - rom.HashData.SHA1 = BitConverter.ToString(sha1.Hash).Replace("-", "").ToLowerInvariant(); - } - } - } - catch (IOException) - { - return new Rom(); - } - - return rom; - } - /// /// Merge an arbitrary set of ROMs based on the supplied information /// @@ -488,75 +405,5 @@ namespace SabreTools.Helper }); return true; } - - /// - /// Clean a hash string and pad to the correct size - /// - /// Hash string to sanitize - /// Amount of characters to pad to - /// Cleaned string - public static string CleanHashData(string hash, int padding) - { - // First get the hash to the correct length - hash = (String.IsNullOrEmpty(hash) ? "" : hash.Trim()); - hash = (hash.StartsWith("0x") ? hash.Remove(0, 2) : hash); - hash = (hash == "-" ? "" : hash); - hash = (String.IsNullOrEmpty(hash) ? "" : hash.PadLeft(padding, '0')); - hash = hash.ToLowerInvariant(); - - // Then make sure that it has the correct characters - if (!Regex.IsMatch(hash, "[0-9a-f]{" + padding + "}")) - { - hash = ""; - } - - return hash; - } - - /// - /// Clean a hash byte array and pad to the correct size - /// - /// Hash byte array to sanitize - /// Amount of bytes to pad to - /// Cleaned byte array - public static byte[] CleanHashData(byte[] hash, int padding) - { - // If we have a null hash or a <=0 padding, return the hash - if (hash == null || padding <= 0) - { - return hash; - } - - // If we have a hash longer than the padding, trim and return - if (hash.Length > padding) - { - return hash.Take(padding).ToArray(); - } - - // If we have a hash of the correct length, return - if (hash.Length == padding) - { - return hash; - } - - // Otherwise get the output byte array of the correct length - byte[] newhash = new byte[padding]; - - // Then write the proper number of empty bytes - int padNeeded = padding - hash.Length; - int index = 0; - for (index = 0; index < padNeeded; index++) - { - newhash[index] = 0x00; - } - - // Now add the original hash - for (int i = 0; i < hash.Length; i++) - { - newhash[index + i] = hash[index]; - } - - return newhash; - } } } diff --git a/SabreTools.Helper/Tools/Style.cs b/SabreTools.Helper/Tools/Style.cs index d7d8cb58..0fc6a8f2 100644 --- a/SabreTools.Helper/Tools/Style.cs +++ b/SabreTools.Helper/Tools/Style.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Linq; using System.Text.RegularExpressions; namespace SabreTools.Helper @@ -210,6 +211,76 @@ namespace SabreTools.Helper return outgame; } + /// + /// Clean a hash string and pad to the correct size + /// + /// Hash string to sanitize + /// Amount of characters to pad to + /// Cleaned string + public static string CleanHashData(string hash, int padding) + { + // First get the hash to the correct length + hash = (String.IsNullOrEmpty(hash) ? "" : hash.Trim()); + hash = (hash.StartsWith("0x") ? hash.Remove(0, 2) : hash); + hash = (hash == "-" ? "" : hash); + hash = (String.IsNullOrEmpty(hash) ? "" : hash.PadLeft(padding, '0')); + hash = hash.ToLowerInvariant(); + + // Then make sure that it has the correct characters + if (!Regex.IsMatch(hash, "[0-9a-f]{" + padding + "}")) + { + hash = ""; + } + + return hash; + } + + /// + /// Clean a hash byte array and pad to the correct size + /// + /// Hash byte array to sanitize + /// Amount of bytes to pad to + /// Cleaned byte array + public static byte[] CleanHashData(byte[] hash, int padding) + { + // If we have a null hash or a <=0 padding, return the hash + if (hash == null || padding <= 0) + { + return hash; + } + + // If we have a hash longer than the padding, trim and return + if (hash.Length > padding) + { + return hash.Take(padding).ToArray(); + } + + // If we have a hash of the correct length, return + if (hash.Length == padding) + { + return hash; + } + + // Otherwise get the output byte array of the correct length + byte[] newhash = new byte[padding]; + + // Then write the proper number of empty bytes + int padNeeded = padding - hash.Length; + int index = 0; + for (index = 0; index < padNeeded; index++) + { + newhash[index] = 0x00; + } + + // Now add the original hash + for (int i = 0; i < hash.Length; i++) + { + newhash[index + i] = hash[index]; + } + + return newhash; + } + #region Externally sourced methods /// diff --git a/SabreTools/DATFromDir.cs b/SabreTools/DATFromDir.cs index 7a649bc3..8239e005 100644 --- a/SabreTools/DATFromDir.cs +++ b/SabreTools/DATFromDir.cs @@ -462,7 +462,7 @@ namespace SabreTools private string ProcessFile(string item, StreamWriter sw, string basepath, string parent, Dat datdata, string lastparent) { _logger.Log(Path.GetFileName(item) + " treated like a file"); - Rom rom = RomTools.GetSingleFileInfo(item, _noMD5, _noSHA1); + Rom rom = FileTools.GetSingleFileInfo(item, _noMD5, _noSHA1); return ProcessFileHelper(item, rom, sw, basepath, parent, datdata, lastparent); } diff --git a/SimpleSort/SimpleSort.cs b/SimpleSort/SimpleSort.cs index 9837da78..6194c268 100644 --- a/SimpleSort/SimpleSort.cs +++ b/SimpleSort/SimpleSort.cs @@ -492,7 +492,7 @@ namespace SabreTools // Hash and match the external files if (shouldExternalScan) { - Rom rom = RomTools.GetSingleFileInfo(input); + Rom rom = FileTools.GetSingleFileInfo(input); // If we have a blank RomData, it's an error if (rom.Name == null) @@ -558,7 +558,7 @@ namespace SabreTools // Otherwise, apply the rule ot the file string newinput = input + ".new"; Skippers.TransformFile(input, newinput, rule, _logger); - Rom drom = RomTools.GetSingleFileInfo(newinput); + Rom drom = FileTools.GetSingleFileInfo(newinput); // If we have a blank RomData, it's an error if (drom.Name == null) @@ -841,7 +841,7 @@ namespace SabreTools FileTools.ExtractArchive(Path.GetFullPath(archive), temparcdir, _logger); foreach (string tempfile in Directory.EnumerateFiles(temparcdir, "*", SearchOption.AllDirectories)) { - roms.Add(RomTools.GetSingleFileInfo(Path.GetFullPath(tempfile))); + roms.Add(FileTools.GetSingleFileInfo(Path.GetFullPath(tempfile))); } // Clear the temporary archive directory