From 78f4d6facaa095d97fcd5429546b5c44c9bd2b1b Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Thu, 31 Jul 2025 10:26:03 -0400 Subject: [PATCH] Add file hashing option to InfoPrint --- InfoPrint/InfoPrint.csproj | 1 + InfoPrint/Options.cs | 11 +++++ InfoPrint/Program.cs | 93 +++++++++++++++++++++++++++++++++++--- 3 files changed, 98 insertions(+), 7 deletions(-) diff --git a/InfoPrint/InfoPrint.csproj b/InfoPrint/InfoPrint.csproj index a93a591a..0b8f8cb1 100644 --- a/InfoPrint/InfoPrint.csproj +++ b/InfoPrint/InfoPrint.csproj @@ -32,6 +32,7 @@ + \ No newline at end of file diff --git a/InfoPrint/Options.cs b/InfoPrint/Options.cs index b0ffe96e..a83e3d84 100644 --- a/InfoPrint/Options.cs +++ b/InfoPrint/Options.cs @@ -15,6 +15,11 @@ namespace InfoPrint /// public bool Debug { get; private set; } = false; + /// + /// Print external file hashes + /// + public bool Hash { get; private set; } = false; + /// /// Set of input paths to use for operations /// @@ -74,6 +79,11 @@ namespace InfoPrint options.Debug = true; break; + case "-c": + case "--hash": + options.Hash = true; + break; + case "-j": case "--json": #if NETCOREAPP @@ -111,6 +121,7 @@ namespace InfoPrint Console.WriteLine("Options:"); Console.WriteLine("-?, -h, --help Display this help text and quit"); Console.WriteLine("-d, --debug Enable debug mode"); + Console.WriteLine("-c, --hash Output file hashes"); #if NETCOREAPP Console.WriteLine("-j, --json Print info as JSON"); #endif diff --git a/InfoPrint/Program.cs b/InfoPrint/Program.cs index 1459be9a..ac21a934 100644 --- a/InfoPrint/Program.cs +++ b/InfoPrint/Program.cs @@ -1,5 +1,7 @@ using System; using System.IO; +using System.Text; +using SabreTools.Hashing; using SabreTools.IO.Extensions; using SabreTools.Serialization; using SabreTools.Serialization.Wrappers; @@ -24,9 +26,9 @@ namespace InfoPrint foreach (string inputPath in options.InputPaths) { #if NETFRAMEWORK || NETSTANDARD2_0_OR_GREATER - PrintPathInfo(inputPath, false, options.Debug); + PrintPathInfo(inputPath, false, options.Debug, options.Hash); #else - PrintPathInfo(inputPath, options.Json, options.Debug); + PrintPathInfo(inputPath, options.Json, options.Debug, options.Hash); #endif } } @@ -37,20 +39,21 @@ namespace InfoPrint /// File or directory path /// Enable JSON output, if supported /// Enable debug output - private static void PrintPathInfo(string path, bool json, bool debug) + /// Enable hash output + private static void PrintPathInfo(string path, bool json, bool debug, bool hash) { Console.WriteLine($"Checking possible path: {path}"); // Check if the file or directory exists if (File.Exists(path)) { - PrintFileInfo(path, json, debug); + PrintFileInfo(path, json, debug, hash); } else if (Directory.Exists(path)) { foreach (string file in IOExtensions.SafeEnumerateFiles(path, "*", SearchOption.AllDirectories)) { - PrintFileInfo(file, json, debug); + PrintFileInfo(file, json, debug, hash); } } else @@ -62,10 +65,19 @@ namespace InfoPrint /// /// Print information for a single file, if possible /// - private static void PrintFileInfo(string file, bool json, bool debug) + /// File path + /// Enable JSON output, if supported + /// Enable debug output + /// Enable hash output + private static void PrintFileInfo(string file, bool json, bool debug, bool hash) { Console.WriteLine($"Attempting to print info for {file}"); + // Retrieve hashes before anything else, if required + StringBuilder? hashBuilder = null; + if (hash) + hashBuilder = PrintHashInfo(file, debug); + try { using Stream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); @@ -101,7 +113,6 @@ namespace InfoPrint { // Create the output data string serializedData = wrapper.ExportJSON(); - Console.WriteLine(serializedData); // Write the output data using var jsw = new StreamWriter(File.OpenWrite($"{filenameBase}.json")); @@ -118,9 +129,19 @@ namespace InfoPrint } // Write the output data + if (hashBuilder != null) + { + Console.WriteLine(hashBuilder); + Console.WriteLine(); + } + Console.WriteLine(builder); using var sw = new StreamWriter(File.OpenWrite($"{filenameBase}.txt")); + if (hashBuilder != null) + sw.WriteLine(hashBuilder.ToString()); + sw.WriteLine(builder.ToString()); + sw.Flush(); } catch (Exception ex) { @@ -128,5 +149,63 @@ namespace InfoPrint Console.WriteLine(); } } + + /// + /// Print hash information for a single file, if possible + /// + /// File path + /// Enable debug output + /// StringBuilder representing the hash information, if possible + private static StringBuilder? PrintHashInfo(string file, bool debug) + { + // Ignore missing files + if (!File.Exists(file)) + return null; + + Console.WriteLine($"Attempting to hash {file}, this may take a while..."); + + try + { + // Get all file hashes for flexibility + var hashes = HashTool.GetFileHashes(file); + if (hashes == null) + { + if (debug) Console.WriteLine($"Hashes for {file} could not be retrieved"); + return null; + } + + // Output subset of available hashes + var builder = new StringBuilder(); + if (hashes.TryGetValue(HashType.CRC16, out string? crc16) && crc16 != null) + builder.AppendLine($"CRC-16 checksum: {crc16}"); + if (hashes.TryGetValue(HashType.CRC32, out string? crc32) && crc32 != null) + builder.AppendLine($"CRC-32 checksum: {crc32}"); + if (hashes.TryGetValue(HashType.MD2, out string? md2) && md2 != null) + builder.AppendLine($"MD2 hash: {md2}"); + if (hashes.TryGetValue(HashType.MD4, out string? md4) && md4 != null) + builder.AppendLine($"MD4 hash: {md4}"); + if (hashes.TryGetValue(HashType.MD5, out string? md5) && md5 != null) + builder.AppendLine($"MD5 hash: {md5}"); + if (hashes.TryGetValue(HashType.RIPEMD128, out string? ripemd128) && ripemd128 != null) + builder.AppendLine($"RIPEMD-128 hash: {ripemd128}"); + if (hashes.TryGetValue(HashType.RIPEMD160, out string? ripemd160) && ripemd160 != null) + builder.AppendLine($"RIPEMD-160 hash: {ripemd160}"); + if (hashes.TryGetValue(HashType.SHA1, out string? sha1) && sha1 != null) + builder.AppendLine($"SHA-1 hash: {sha1}"); + if (hashes.TryGetValue(HashType.SHA256, out string? sha256) && sha256 != null) + builder.AppendLine($"SHA-256 hash: {sha256}"); + if (hashes.TryGetValue(HashType.SHA384, out string? sha384) && sha384 != null) + builder.AppendLine($"SHA-384 hash: {sha384}"); + if (hashes.TryGetValue(HashType.SHA512, out string? sha512) && sha512 != null) + builder.AppendLine($"SHA-512 hash: {sha512}"); + + return builder; + } + catch (Exception ex) + { + Console.WriteLine(debug ? ex : "[Exception opening file, please try again]"); + return null; + } + } } }