From 81f04007902bcbf34cdc4c7dc2defed6c7c4a8c5 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Sat, 31 Oct 2020 14:00:31 -0700 Subject: [PATCH] Pass-thru scanner, better return types --- BurnOutSharp/FileType/BFPK.cs | 12 +- BurnOutSharp/FileType/BZip2.cs | 12 +- BurnOutSharp/FileType/Executable.cs | 174 +-- BurnOutSharp/FileType/GZIP.cs | 12 +- BurnOutSharp/FileType/InstallShieldCAB.cs | 12 +- BurnOutSharp/FileType/MPQ.cs | 12 +- BurnOutSharp/FileType/MSI.cs | 12 +- BurnOutSharp/FileType/MicrosoftCAB.cs | 12 +- BurnOutSharp/FileType/PKZIP.cs | 12 +- BurnOutSharp/FileType/RAR.cs | 13 +- BurnOutSharp/FileType/SevenZip.cs | 12 +- BurnOutSharp/FileType/TapeArchive.cs | 12 +- BurnOutSharp/FileType/Textfile.cs | 2 +- BurnOutSharp/FileType/Valve.cs | 12 +- BurnOutSharp/FileType/XZ.cs | 12 +- BurnOutSharp/ProtectionFind.cs | 1120 +++++++++--------- BurnOutSharp/ProtectionType/WiseInstaller.cs | 26 +- BurnOutSharp/Scanner.cs | 155 +-- BurnOutSharp/Utilities.cs | 57 +- Test/Program.cs | 30 +- 20 files changed, 829 insertions(+), 892 deletions(-) diff --git a/BurnOutSharp/FileType/BFPK.cs b/BurnOutSharp/FileType/BFPK.cs index 4d28a71e..030848ca 100644 --- a/BurnOutSharp/FileType/BFPK.cs +++ b/BurnOutSharp/FileType/BFPK.cs @@ -17,7 +17,7 @@ namespace BurnOutSharp.FileType return false; } - public static Dictionary> Scan(Scanner parentScanner, Stream stream) + public static Dictionary> Scan(Scanner scanner, Stream stream) { // If the BFPK file itself fails try @@ -25,14 +25,6 @@ namespace BurnOutSharp.FileType string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - // Create a new scanner for the new temp path - Scanner subScanner = new Scanner(parentScanner.FileProgress) - { - IncludePosition = parentScanner.IncludePosition, - ScanAllFiles = parentScanner.ScanAllFiles, - ScanArchives = parentScanner.ScanArchives, - }; - using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true)) { br.ReadBytes(4); // Skip magic number @@ -101,7 +93,7 @@ namespace BurnOutSharp.FileType } // Collect and format all found protections - var protections = subScanner.GetProtections(tempPath); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try diff --git a/BurnOutSharp/FileType/BZip2.cs b/BurnOutSharp/FileType/BZip2.cs index 111b1877..5aee4645 100644 --- a/BurnOutSharp/FileType/BZip2.cs +++ b/BurnOutSharp/FileType/BZip2.cs @@ -17,7 +17,7 @@ namespace BurnOutSharp.FileType return false; } - public static Dictionary> Scan(Scanner parentScanner, Stream stream) + public static Dictionary> Scan(Scanner scanner, Stream stream) { // If the 7-zip file itself fails try @@ -25,14 +25,6 @@ namespace BurnOutSharp.FileType string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - // Create a new scanner for the new temp path - Scanner subScanner = new Scanner(parentScanner.FileProgress) - { - IncludePosition = parentScanner.IncludePosition, - ScanAllFiles = parentScanner.ScanAllFiles, - ScanArchives = parentScanner.ScanArchives, - }; - using (BZip2Stream bz2File = new BZip2Stream(stream, CompressionMode.Decompress, true)) { // If an individual entry fails @@ -48,7 +40,7 @@ namespace BurnOutSharp.FileType } // Collect and format all found protections - var protections = subScanner.GetProtections(tempPath); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try diff --git a/BurnOutSharp/FileType/Executable.cs b/BurnOutSharp/FileType/Executable.cs index ab34d1d5..f887b952 100644 --- a/BurnOutSharp/FileType/Executable.cs +++ b/BurnOutSharp/FileType/Executable.cs @@ -41,7 +41,7 @@ namespace BurnOutSharp.FileType return false; } - public static List Scan(Stream stream, string file = null, bool includePosition = false) + public static Dictionary> Scan(Scanner scanner, Stream stream, string file = null) { // Load the current file content byte[] fileContent = null; @@ -55,191 +55,191 @@ namespace BurnOutSharp.FileType stream.Seek(0, SeekOrigin.Begin); // Files can be protected in multiple ways - List protections = new List(); - List subProtections = new List(); + var protections = new Dictionary>(); + var subProtections = new Dictionary>(); string protection; #region Protections // 3PLock - protection = ThreePLock.CheckContents(fileContent, includePosition); + protection = ThreePLock.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // 321Studios Online Activation - protection = ThreeTwoOneStudios.CheckContents(fileContent, includePosition); + protection = ThreeTwoOneStudios.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // ActiveMARK - protection = ActiveMARK.CheckContents(fileContent, includePosition); + protection = ActiveMARK.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // Alpha-ROM - protection = AlphaROM.CheckContents(fileContent, includePosition); + protection = AlphaROM.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // Cactus Data Shield - protection = CactusDataShield.CheckContents(fileContent, includePosition); + protection = CactusDataShield.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // CD-Cops - protection = CDCops.CheckContents(fileContent, includePosition); + protection = CDCops.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // CD-Lock - protection = CDLock.CheckContents(fileContent, includePosition); + protection = CDLock.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // CDSHiELD SE - protection = CDSHiELDSE.CheckContents(fileContent, includePosition); + protection = CDSHiELDSE.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // CD Check - protection = CDCheck.CheckContents(fileContent, includePosition); + protection = CDCheck.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // Cenega ProtectDVD - protection = CengaProtectDVD.CheckContents(fileContent, includePosition); + protection = CengaProtectDVD.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // Code Lock - protection = CodeLock.CheckContents(fileContent, includePosition); + protection = CodeLock.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // CopyKiller - protection = CopyKiller.CheckContents(fileContent, includePosition); + protection = CopyKiller.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // DVD-Cops - protection = DVDCops.CheckContents(fileContent, includePosition); + protection = DVDCops.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // EA Protections - protection = ElectronicArts.CheckContents(file, fileContent, includePosition); + protection = ElectronicArts.CheckContents(file, fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // Games for Windows - Live - protection = GFWL.CheckContents(fileContent, includePosition); + protection = GFWL.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // Impulse Reactor - protection = ImpulseReactor.CheckContents(file, fileContent, includePosition); + protection = ImpulseReactor.CheckContents(file, fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // Inno Setup - protection = InnoSetup.CheckContents(fileContent, includePosition); + protection = InnoSetup.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // JoWooD X-Prot - protection = JoWooDXProt.CheckContents(fileContent, includePosition); + protection = JoWooDXProt.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // Key-Lock (Dongle) - protection = KeyLock.CheckContents(fileContent, includePosition); + protection = KeyLock.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // LaserLock - protection = LaserLock.CheckContents(file, fileContent, includePosition); + protection = LaserLock.CheckContents(file, fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // ProtectDisc - protection = ProtectDisc.CheckContents(file, fileContent, includePosition); + protection = ProtectDisc.CheckContents(file, fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // Ring PROTECH - protection = RingPROTECH.CheckContents(fileContent, includePosition); + protection = RingPROTECH.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // SafeDisc / SafeCast - protection = SafeDisc.CheckContents(file, fileContent, includePosition); + protection = SafeDisc.CheckContents(file, fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // SafeLock - protection = SafeLock.CheckContents(fileContent, includePosition); + protection = SafeLock.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // SecuROM - protection = SecuROM.CheckContents(file, fileContent, includePosition); + protection = SecuROM.CheckContents(file, fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // SmartE - protection = SmartE.CheckContents(fileContent, includePosition); + protection = SmartE.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // SolidShield - protection = SolidShield.CheckContents(file, fileContent, includePosition); + protection = SolidShield.CheckContents(file, fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // StarForce - protection = StarForce.CheckContents(file, fileContent, includePosition); + protection = StarForce.CheckContents(file, fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // SVK Protector - protection = SVKProtector.CheckContents(fileContent, includePosition); + protection = SVKProtector.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // Sysiphus / Sysiphus DVD - protection = Sysiphus.CheckContents(fileContent, includePosition); + protection = Sysiphus.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // TAGES - protection = Tages.CheckContents(file, fileContent, includePosition); + protection = Tages.CheckContents(file, fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // VOB ProtectCD/DVD - protection = VOBProtectCDDVD.CheckContents(file, fileContent, includePosition); + protection = VOBProtectCDDVD.CheckContents(file, fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // Wise Installer - subProtections = WiseInstaller.CheckContents(file, fileContent, includePosition); + subProtections = WiseInstaller.CheckContents(scanner, file, fileContent); if (subProtections != null && subProtections.Count > 0) - protections.AddRange(subProtections); + Utilities.AppendToDictionary(protections, subProtections); // WTM CD Protect - protection = WTMCDProtect.CheckContents(fileContent, includePosition); + protection = WTMCDProtect.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // XCP 1/2 - protection = XCP.CheckContents(fileContent, includePosition); + protection = XCP.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // Xtreme-Protector - protection = XtremeProtector.CheckContents(fileContent, includePosition); + protection = XtremeProtector.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); #endregion @@ -247,34 +247,34 @@ namespace BurnOutSharp.FileType #region Packers // Armadillo - protection = Armadillo.CheckContents(fileContent, includePosition); + protection = Armadillo.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // dotFuscator - protection = dotFuscator.CheckContents(fileContent, includePosition); + protection = dotFuscator.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // EXE Stealth - protection = EXEStealth.CheckContents(fileContent, includePosition); + protection = EXEStealth.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // NSIS - protection = NSIS.CheckContents(fileContent, includePosition); + protection = NSIS.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // PE Compact - protection = PECompact.CheckContents(fileContent, includePosition); + protection = PECompact.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); // UPX - protection = UPX.CheckContents(fileContent, includePosition); + protection = UPX.CheckContents(fileContent, scanner.IncludePosition); if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); + Utilities.AppendToDictionary(protections, file, protection); #endregion diff --git a/BurnOutSharp/FileType/GZIP.cs b/BurnOutSharp/FileType/GZIP.cs index f81465c4..e1e3aac7 100644 --- a/BurnOutSharp/FileType/GZIP.cs +++ b/BurnOutSharp/FileType/GZIP.cs @@ -16,7 +16,7 @@ namespace BurnOutSharp.FileType return false; } - public static Dictionary> Scan(Scanner parentScanner, Stream stream) + public static Dictionary> Scan(Scanner scanner, Stream stream) { // If the gzip file itself fails try @@ -24,14 +24,6 @@ namespace BurnOutSharp.FileType string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - // Create a new scanner for the new temp path - Scanner subScanner = new Scanner(parentScanner.FileProgress) - { - IncludePosition = parentScanner.IncludePosition, - ScanAllFiles = parentScanner.ScanAllFiles, - ScanArchives = parentScanner.ScanArchives, - }; - using (GZipArchive zipFile = GZipArchive.Open(stream)) { foreach (var entry in zipFile.Entries) @@ -51,7 +43,7 @@ namespace BurnOutSharp.FileType } // Collect and format all found protections - var protections = subScanner.GetProtections(tempPath); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try diff --git a/BurnOutSharp/FileType/InstallShieldCAB.cs b/BurnOutSharp/FileType/InstallShieldCAB.cs index 2aefbac7..d90ffb55 100644 --- a/BurnOutSharp/FileType/InstallShieldCAB.cs +++ b/BurnOutSharp/FileType/InstallShieldCAB.cs @@ -17,7 +17,7 @@ namespace BurnOutSharp.FileType } // TODO: Add stream opening support - public static Dictionary> Scan(Scanner parentScanner, string file) + public static Dictionary> Scan(Scanner scanner, string file) { // Get the name of the first cabinet file or header string directory = Path.GetDirectoryName(file); @@ -39,14 +39,6 @@ namespace BurnOutSharp.FileType string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - // Create a new scanner for the new temp path - Scanner subScanner = new Scanner(parentScanner.FileProgress) - { - IncludePosition = parentScanner.IncludePosition, - ScanAllFiles = parentScanner.ScanAllFiles, - ScanArchives = parentScanner.ScanArchives, - }; - UnshieldCabinet cabfile = UnshieldCabinet.Open(file); for (int i = 0; i < cabfile.FileCount; i++) { @@ -60,7 +52,7 @@ namespace BurnOutSharp.FileType } // Collect and format all found protections - var protections = subScanner.GetProtections(tempPath); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try diff --git a/BurnOutSharp/FileType/MPQ.cs b/BurnOutSharp/FileType/MPQ.cs index cd98a1a6..e791db4e 100644 --- a/BurnOutSharp/FileType/MPQ.cs +++ b/BurnOutSharp/FileType/MPQ.cs @@ -16,7 +16,7 @@ namespace BurnOutSharp.FileType } // TODO: Add stream opening support - public static Dictionary> Scan(Scanner parentScanner, string file) + public static Dictionary> Scan(Scanner scanner, string file) { // If the mpq file itself fails try @@ -24,14 +24,6 @@ namespace BurnOutSharp.FileType string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - // Create a new scanner for the new temp path - Scanner subScanner = new Scanner(parentScanner.FileProgress) - { - IncludePosition = parentScanner.IncludePosition, - ScanAllFiles = parentScanner.ScanAllFiles, - ScanArchives = parentScanner.ScanArchives, - }; - using (MpqArchive mpqArchive = new MpqArchive(file, FileAccess.Read)) { string listfile = null; @@ -59,7 +51,7 @@ namespace BurnOutSharp.FileType } // Collect and format all found protections - var protections = subScanner.GetProtections(tempPath); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try diff --git a/BurnOutSharp/FileType/MSI.cs b/BurnOutSharp/FileType/MSI.cs index fd12be8c..f04af890 100644 --- a/BurnOutSharp/FileType/MSI.cs +++ b/BurnOutSharp/FileType/MSI.cs @@ -16,7 +16,7 @@ namespace BurnOutSharp.FileType } // TODO: Add stream opening support - public static Dictionary> Scan(Scanner parentScanner, string file) + public static Dictionary> Scan(Scanner scanner, string file) { // If the MSI file itself fails try @@ -24,21 +24,13 @@ namespace BurnOutSharp.FileType string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - // Create a new scanner for the new temp path - Scanner subScanner = new Scanner(parentScanner.FileProgress) - { - IncludePosition = parentScanner.IncludePosition, - ScanAllFiles = parentScanner.ScanAllFiles, - ScanArchives = parentScanner.ScanArchives, - }; - using (Database msidb = new Database(file, DatabaseOpenMode.ReadOnly)) { msidb.ExportAll(tempPath); } // Collect and format all found protections - var protections = subScanner.GetProtections(tempPath); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try diff --git a/BurnOutSharp/FileType/MicrosoftCAB.cs b/BurnOutSharp/FileType/MicrosoftCAB.cs index b16ea7f2..78a54099 100644 --- a/BurnOutSharp/FileType/MicrosoftCAB.cs +++ b/BurnOutSharp/FileType/MicrosoftCAB.cs @@ -16,7 +16,7 @@ namespace BurnOutSharp.FileType } // TODO: Add stream opening support - public static Dictionary> Scan(Scanner parentScanner, string file) + public static Dictionary> Scan(Scanner scanner, string file) { // If the cab file itself fails try @@ -24,14 +24,6 @@ namespace BurnOutSharp.FileType string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - // Create a new scanner for the new temp path - Scanner subScanner = new Scanner(parentScanner.FileProgress) - { - IncludePosition = parentScanner.IncludePosition, - ScanAllFiles = parentScanner.ScanAllFiles, - ScanArchives = parentScanner.ScanArchives, - }; - using (MSCabinet cabfile = new MSCabinet(file)) { foreach (var sub in cabfile.GetFiles()) @@ -47,7 +39,7 @@ namespace BurnOutSharp.FileType } // Collect and format all found protections - var protections = subScanner.GetProtections(tempPath); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try diff --git a/BurnOutSharp/FileType/PKZIP.cs b/BurnOutSharp/FileType/PKZIP.cs index 1ce74cb6..ece85434 100644 --- a/BurnOutSharp/FileType/PKZIP.cs +++ b/BurnOutSharp/FileType/PKZIP.cs @@ -25,7 +25,7 @@ namespace BurnOutSharp.FileType return false; } - public static Dictionary> Scan(Scanner parentScanner, Stream stream) + public static Dictionary> Scan(Scanner scanner, Stream stream) { // If the zip file itself fails try @@ -33,14 +33,6 @@ namespace BurnOutSharp.FileType string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - // Create a new scanner for the new temp path - Scanner subScanner = new Scanner(parentScanner.FileProgress) - { - IncludePosition = parentScanner.IncludePosition, - ScanAllFiles = parentScanner.ScanAllFiles, - ScanArchives = parentScanner.ScanArchives, - }; - using (ZipArchive zipFile = ZipArchive.Open(stream)) { foreach (var entry in zipFile.Entries) @@ -60,7 +52,7 @@ namespace BurnOutSharp.FileType } // Collect and format all found protections - var protections = subScanner.GetProtections(tempPath); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try diff --git a/BurnOutSharp/FileType/RAR.cs b/BurnOutSharp/FileType/RAR.cs index 0cdc573a..6f71727d 100644 --- a/BurnOutSharp/FileType/RAR.cs +++ b/BurnOutSharp/FileType/RAR.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using SharpCompress.Archives; using SharpCompress.Archives.Rar; @@ -22,7 +21,7 @@ namespace BurnOutSharp.FileType return false; } - public static Dictionary> Scan(Scanner parentScanner, Stream stream) + public static Dictionary> Scan(Scanner scanner, Stream stream) { // If the rar file itself fails try @@ -30,14 +29,6 @@ namespace BurnOutSharp.FileType string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - // Create a new scanner for the new temp path - Scanner subScanner = new Scanner(parentScanner.FileProgress) - { - IncludePosition = parentScanner.IncludePosition, - ScanAllFiles = parentScanner.ScanAllFiles, - ScanArchives = parentScanner.ScanArchives, - }; - using (RarArchive zipFile = RarArchive.Open(stream)) { foreach (var entry in zipFile.Entries) @@ -57,7 +48,7 @@ namespace BurnOutSharp.FileType } // Collect and format all found protections - var protections = subScanner.GetProtections(tempPath); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try diff --git a/BurnOutSharp/FileType/SevenZip.cs b/BurnOutSharp/FileType/SevenZip.cs index df0e4396..77813321 100644 --- a/BurnOutSharp/FileType/SevenZip.cs +++ b/BurnOutSharp/FileType/SevenZip.cs @@ -16,7 +16,7 @@ namespace BurnOutSharp.FileType return false; } - public static Dictionary> Scan(Scanner parentScanner, Stream stream) + public static Dictionary> Scan(Scanner scanner, Stream stream) { // If the 7-zip file itself fails try @@ -24,14 +24,6 @@ namespace BurnOutSharp.FileType string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - // Create a new scanner for the new temp path - Scanner subScanner = new Scanner(parentScanner.FileProgress) - { - IncludePosition = parentScanner.IncludePosition, - ScanAllFiles = parentScanner.ScanAllFiles, - ScanArchives = parentScanner.ScanArchives, - }; - using (SevenZipArchive sevenZipFile = SevenZipArchive.Open(stream)) { foreach (var entry in sevenZipFile.Entries) @@ -50,7 +42,7 @@ namespace BurnOutSharp.FileType } // Collect and format all found protections - var protections = subScanner.GetProtections(tempPath); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try diff --git a/BurnOutSharp/FileType/TapeArchive.cs b/BurnOutSharp/FileType/TapeArchive.cs index 97e678a5..5e8c2b98 100644 --- a/BurnOutSharp/FileType/TapeArchive.cs +++ b/BurnOutSharp/FileType/TapeArchive.cs @@ -19,7 +19,7 @@ namespace BurnOutSharp.FileType return false; } - public static Dictionary> Scan(Scanner parentScanner, Stream stream) + public static Dictionary> Scan(Scanner scanner, Stream stream) { // If the tar file itself fails try @@ -27,14 +27,6 @@ namespace BurnOutSharp.FileType string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - // Create a new scanner for the new temp path - Scanner subScanner = new Scanner(parentScanner.FileProgress) - { - IncludePosition = parentScanner.IncludePosition, - ScanAllFiles = parentScanner.ScanAllFiles, - ScanArchives = parentScanner.ScanArchives, - }; - using (TarArchive tarFile = TarArchive.Open(stream)) { foreach (var entry in tarFile.Entries) @@ -54,7 +46,7 @@ namespace BurnOutSharp.FileType } // Collect and format all found protections - var protections = subScanner.GetProtections(tempPath); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try diff --git a/BurnOutSharp/FileType/Textfile.cs b/BurnOutSharp/FileType/Textfile.cs index e2e535b3..5c8c9c41 100644 --- a/BurnOutSharp/FileType/Textfile.cs +++ b/BurnOutSharp/FileType/Textfile.cs @@ -32,7 +32,7 @@ namespace BurnOutSharp.FileType return false; } - public static List Scan(Stream stream, bool includePosition = false) + public static List Scan(Stream stream) { List protections = new List(); diff --git a/BurnOutSharp/FileType/Valve.cs b/BurnOutSharp/FileType/Valve.cs index d22c84bd..9aa534fc 100644 --- a/BurnOutSharp/FileType/Valve.cs +++ b/BurnOutSharp/FileType/Valve.cs @@ -33,19 +33,11 @@ namespace BurnOutSharp.FileType } // TODO: Add stream opening support - public static Dictionary> Scan(Scanner parentScanner, string file) + public static Dictionary> Scan(Scanner scanner, string file) { string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - // Create a new scanner for the new temp path - Scanner subScanner = new Scanner(parentScanner.FileProgress) - { - IncludePosition = parentScanner.IncludePosition, - ScanAllFiles = parentScanner.ScanAllFiles, - ScanArchives = parentScanner.ScanArchives, - }; - string[] args = new string[] { "-p", file, @@ -58,7 +50,7 @@ namespace BurnOutSharp.FileType HLExtractProgram.Process(args); // Collect and format all found protections - var protections = subScanner.GetProtections(tempPath); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try diff --git a/BurnOutSharp/FileType/XZ.cs b/BurnOutSharp/FileType/XZ.cs index d0afd46e..fc73ad66 100644 --- a/BurnOutSharp/FileType/XZ.cs +++ b/BurnOutSharp/FileType/XZ.cs @@ -15,7 +15,7 @@ namespace BurnOutSharp.FileType return false; } - public static Dictionary> Scan(Scanner parentScanner, Stream stream) + public static Dictionary> Scan(Scanner scanner, Stream stream) { // If the xz file itself fails try @@ -23,14 +23,6 @@ namespace BurnOutSharp.FileType string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - // Create a new scanner for the new temp path - Scanner subScanner = new Scanner(parentScanner.FileProgress) - { - IncludePosition = parentScanner.IncludePosition, - ScanAllFiles = parentScanner.ScanAllFiles, - ScanArchives = parentScanner.ScanArchives, - }; - using (XZStream xzFile = new XZStream(stream)) { // If an individual entry fails @@ -46,7 +38,7 @@ namespace BurnOutSharp.FileType } // Collect and format all found protections - var protections = subScanner.GetProtections(tempPath); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try diff --git a/BurnOutSharp/ProtectionFind.cs b/BurnOutSharp/ProtectionFind.cs index ae4ddeb7..fa766acd 100644 --- a/BurnOutSharp/ProtectionFind.cs +++ b/BurnOutSharp/ProtectionFind.cs @@ -1,560 +1,560 @@ -//this file is part of BurnOut -//Copyright (C)2005-2010 Gernot Knippen -//Ported code with augments Copyright (C)2018 Matt Nadareski -// -//This program is free software; you can redistribute it and/or -//modify it under the terms of the GNU General Public License -//as published by the Free Software Foundation; either -//version 2 of the License, or (at your option) any later version. -// -//This program is distributed in the hope that it will be useful, -//but WITHOUT ANY WARRANTY; without even the implied warranty of -//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -//GNU General Public License for more details. -// -//You can get a copy of the GNU General Public License -//by writing to the Free Software -//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using BurnOutSharp.FileType; -using BurnOutSharp.ProtectionType; - -namespace BurnOutSharp -{ - public static class ProtectionFind - { - /// - /// Progress indicator - /// - private static IProgress FileProgress = null; - - /// - /// Scan a path to find any known copy protection(s) - /// - /// Path to scan for protection(s) - /// True to include scanned copy protection position, false otherwise (default) - /// Optional progress indicator that will return a float in the range from 0 to 1 - /// Dictionary of filename to protection mappings, if possible - public static Dictionary Scan(string path, bool includePosition = false, IProgress progress = null) - { - // Set the progress indicator, if it's not set already - if (FileProgress == null) - FileProgress = progress; - - // Initialize the protections dictionary - var protections = new Dictionary(); - - // Checkpoint - FileProgress?.Report(new FileProtection(null, 0, null)); - - // Temp variables for reporting - string tempFilePath = Path.GetTempPath(); - string tempFilePathWithGuid = Path.Combine(tempFilePath, Guid.NewGuid().ToString()); - - // If we have a file - if (File.Exists(path)) - { - // Get the reportable file name - string reportableFileName = path; - if (reportableFileName.StartsWith(tempFilePath)) - reportableFileName = reportableFileName.Substring(tempFilePathWithGuid.Length); - - // Checkpoint - FileProgress?.Report(new FileProtection(reportableFileName, 1, "Checking file" + (path != reportableFileName ? " from archive" : string.Empty))); - - // Try using just the file first to get protection info - string fileProtection = ScanPath(path, false); - if (!string.IsNullOrWhiteSpace(fileProtection)) - protections[path] = fileProtection; - - // Now check to see if the file contains any additional information - string contentProtection = ScanContent(path, includePosition)?.Replace("" + (char)0x00, ""); - if (!string.IsNullOrWhiteSpace(contentProtection)) - { - if (protections.ContainsKey(path)) - protections[path] += $", {contentProtection}"; - else - protections[path] = contentProtection; - } - - // Checkpoint - protections.TryGetValue(path, out string fullProtection); - FileProgress?.Report(new FileProtection(reportableFileName, 1, fullProtection ?? string.Empty)); - } - // If we have a directory - else if (Directory.Exists(path)) - { - // Get the lists of files to be used - var files = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories); - - // Try using just the path first to get protection info - string pathProtection = ScanPath(path, true); - if (!string.IsNullOrWhiteSpace(pathProtection)) - protections[path] = pathProtection; - - // Loop through all files and scan their contents - for (int i = 0; i < files.Count(); i++) - { - // Get the current file - string file = files.ElementAt(i); - - // Get the reportable file name - string reportableFileName = file; - if (reportableFileName.StartsWith(tempFilePath)) - reportableFileName = reportableFileName.Substring(tempFilePathWithGuid.Length); - - // Checkpoint - FileProgress?.Report(new FileProtection(reportableFileName, i / (float)files.Count(), "Checking file" + (file != reportableFileName ? " from archive" : string.Empty))); - - // Try using just the file first to get protection info - string fileProtection = ScanPath(file, false); - if (!string.IsNullOrWhiteSpace(fileProtection)) - protections[file] = fileProtection; - - // Now check to see if the file contains any additional information - string contentProtection = ScanContent(file, includePosition)?.Replace("" + (char)0x00, ""); - if (!string.IsNullOrWhiteSpace(contentProtection)) - { - if (protections.ContainsKey(file)) - protections[file] += $", {contentProtection}"; - else - protections[file] = contentProtection; - } - - // Checkpoint - protections.TryGetValue(file, out string fullProtection); - FileProgress?.Report(new FileProtection(reportableFileName, (i + 1) / (float)files.Count(), fullProtection ?? string.Empty)); - } - } - - // If we have an empty list, we need to take care of that - if (protections.Count(p => !string.IsNullOrWhiteSpace(p.Value)) == 0) - { - protections = new Dictionary(); - } - - return protections; - } - - /// - /// Scan a path for indications of copy protection - /// - /// Path to scan file and folder names - /// True if the path is a directory, false otherwise - /// - public static string ScanPath(string path, bool isDirectory) - { - List protections = new List(); - string protection; - - // If we have a directory, get the files in the directory for searching - IEnumerable files = null; - if (isDirectory) - files = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories); - - // AACS - protection = AACS.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Alpha-DVD - protection = AlphaDVD.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Bitpool - protection = Bitpool.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // ByteShield - protection = ByteShield.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Cactus Data Shield - protection = CactusDataShield.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // CD-Cops - protection = CDCops.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // CD-Lock - protection = CDLock.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // CD-Protector - protection = CDProtector.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // CD-X - protection = CDX.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - /* - // CopyKiller - protection = CopyKiller.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - */ - - // DiscGuard - protection = DiscGuard.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // DVD Crypt - protection = DVDCrypt.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // DVD-Movie-PROTECT - protection = DVDMoviePROTECT.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // FreeLock - protection = FreeLock.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Games for Windows - Live - protection = GFWL.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Hexalock AutoLock - protection = HexalockAutoLock.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Impulse Reactor - protection = ImpulseReactor.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // IndyVCD - protection = IndyVCD.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Key2Audio XS - protection = Key2AudioXS.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // LaserLock - protection = LaserLock.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // MediaCloQ - protection = MediaCloQ.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // MediaMax CD3 - protection = MediaMaxCD3.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Origin - protection = Origin.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Protect DVD-Video - protection = ProtectDVDVideo.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // SafeCast - protection = SafeCast.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // SafeDisc - protection = SafeDisc.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // SafeDisc Lite - protection = SafeDiscLite.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // SafeLock - protection = SafeLock.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // SecuROM - protection = SecuROM.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // SmartE - protection = SmartE.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // SoftLock - protection = SoftLock.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // SolidShield - protection = SolidShield.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // StarForce - protection = StarForce.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Steam - protection = Steam.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // TAGES - protection = Tages.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // TZCopyProtector - protection = TZCopyProtector.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Uplay - protection = Uplay.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // VOB ProtectCD/DVD - protection = VOBProtectCDDVD.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Winlock - protection = Winlock.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // WTM CD Protect - protection = WTMCDProtect.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // XCP - protection = XCP.CheckPath(path, files, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Zzxzz - protection = Zzxzz.CheckPath(path, isDirectory); - if (!string.IsNullOrWhiteSpace(protection)) - protections.Add(protection); - - // Now combine any found protections, or null if empty - if (protections.Count() == 0) - return null; - else - return string.Join(", ", protections); - } - - /// - /// Scan an individual file for copy protection - /// - /// File path for scanning - /// True to include scanned copy protection position, false otherwise (default) - public static string ScanContent(string file, bool includePosition = false) - { - try - { - using (FileStream fs = File.OpenRead(file)) - { - return ScanContent(fs, file, includePosition); - } - } - catch - { - return null; - } - } - - /// - /// Scan an individual stream for copy protection - /// - /// Generic stream to scan - /// File path to be used for name checks (optional) - /// True to include scanned copy protection position, false otherwise (default) - public static string ScanContent(Stream stream, string file = null, bool includePosition = false) - { - // Get the extension for certain checks - string extension = Path.GetExtension(file).ToLower().TrimStart('.'); - - // Assume the first part of the stream is the start of a file - byte[] magic = new byte[16]; - try - { - stream.Read(magic, 0, 16); - stream.Seek(-16, SeekOrigin.Current); - } - catch - { - // We don't care what the issue was, we can't read or seek the file - return null; - } - - // Files can be protected in multiple ways - List protections = new List(); - - #region Non-Archive Formats - - // Executable - if (Executable.ShouldScan(magic)) - protections.AddRange(Executable.Scan(stream, file, includePosition)); - - // Text-based files - if (Textfile.ShouldScan(magic, extension)) - protections.AddRange(Textfile.Scan(stream, includePosition)); - - #endregion - - #region Archive Formats - - // 7-Zip archive - if (SevenZip.ShouldScan(magic)) - protections.AddRange(SevenZip.Scan(stream, includePosition)); - - // BFPK archive - if (BFPK.ShouldScan(magic)) - protections.AddRange(BFPK.Scan(stream, includePosition)); - - // BZip2 - if (BZip2.ShouldScan(magic)) - protections.AddRange(BZip2.Scan(stream, includePosition)); - - // GZIP - if (GZIP.ShouldScan(magic)) - protections.AddRange(GZIP.Scan(stream, includePosition)); - - // InstallShield Cabinet - if (file != null && InstallShieldCAB.ShouldScan(magic)) - protections.AddRange(InstallShieldCAB.Scan(file, includePosition)); - - // Microsoft Cabinet - if (file != null && MicrosoftCAB.ShouldScan(magic)) - protections.AddRange(MicrosoftCAB.Scan(file, includePosition)); - - // MSI - if (file != null && MSI.ShouldScan(magic)) - protections.AddRange(MSI.Scan(file, includePosition)); - - // MPQ archive - if (file != null && MPQ.ShouldScan(magic)) - protections.AddRange(MPQ.Scan(file, includePosition)); - - // PKZIP archive (and derivatives) - if (PKZIP.ShouldScan(magic)) - protections.AddRange(PKZIP.Scan(stream, includePosition)); - - // RAR archive - if (RAR.ShouldScan(magic)) - protections.AddRange(RAR.Scan(stream, includePosition)); - - // Tape Archive - if (TapeArchive.ShouldScan(magic)) - protections.AddRange(TapeArchive.Scan(stream, includePosition)); - - // Valve archive formats - if (file != null && Valve.ShouldScan(magic)) - protections.AddRange(Valve.Scan(file, includePosition)); - - // XZ - if (XZ.ShouldScan(magic)) - protections.AddRange(XZ.Scan(stream, includePosition)); - - #endregion - - // Return blank if nothing found, or comma-separated list of protections - if (protections.Count() == 0) - return string.Empty; - else - return string.Join(", ", protections); - } - - /// - /// Scan a disc sector by sector for protection - /// - /// - /// https://stackoverflow.com/questions/8819188/c-sharp-classes-to-undelete-files/8820157#8820157 - /// TODO: Finish implementation - /// - private static string ScanSectors(char driveLetter, int sectorsize) - { - string fsName = Utilities.GetFileSystemName(driveLetter); - - // Gets a handle to the physical disk - IntPtr hDisk = Utilities.CreateFile($"\\\\.\\{driveLetter}:", - FileAccess.Read, - FileShare.ReadWrite, - IntPtr.Zero, - FileMode.Open, - 0, - IntPtr.Zero); - - // If we have a good pointer - if (hDisk.ToInt32() != -1) - { - // Setup vars - byte[] buffer = new byte[sectorsize]; - IntPtr pt = IntPtr.Zero; - NativeOverlapped no = new NativeOverlapped(); - - // Set initial offset - Utilities.SetFilePointerEx( - hDisk, - 0, - ref pt, - Utilities.FileBegin); - - // Read a whole sector - while (true) - { - buffer = new byte[sectorsize]; - Utilities.ReadFileEx( - hDisk, - buffer, - (uint)sectorsize, - ref no, - null); - - Utilities.SetFilePointerEx( - hDisk, - sectorsize, - ref pt, - Utilities.FileCurrent); - } - } - - Utilities.CloseHandle(hDisk); - - return null; - } - } -} +////this file is part of BurnOut +////Copyright (C)2005-2010 Gernot Knippen +////Ported code with augments Copyright (C)2018 Matt Nadareski +//// +////This program is free software; you can redistribute it and/or +////modify it under the terms of the GNU General Public License +////as published by the Free Software Foundation; either +////version 2 of the License, or (at your option) any later version. +//// +////This program is distributed in the hope that it will be useful, +////but WITHOUT ANY WARRANTY; without even the implied warranty of +////MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +////GNU General Public License for more details. +//// +////You can get a copy of the GNU General Public License +////by writing to the Free Software +////Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +//using System; +//using System.Collections.Generic; +//using System.IO; +//using System.Linq; +//using System.Threading; +//using BurnOutSharp.FileType; +//using BurnOutSharp.ProtectionType; + +//namespace BurnOutSharp +//{ +// public static class ProtectionFind +// { +// /// +// /// Progress indicator +// /// +// private static IProgress FileProgress = null; + +// /// +// /// Scan a path to find any known copy protection(s) +// /// +// /// Path to scan for protection(s) +// /// True to include scanned copy protection position, false otherwise (default) +// /// Optional progress indicator that will return a float in the range from 0 to 1 +// /// Dictionary of filename to protection mappings, if possible +// public static Dictionary Scan(string path, bool includePosition = false, IProgress progress = null) +// { +// // Set the progress indicator, if it's not set already +// if (FileProgress == null) +// FileProgress = progress; + +// // Initialize the protections dictionary +// var protections = new Dictionary(); + +// // Checkpoint +// FileProgress?.Report(new FileProtection(null, 0, null)); + +// // Temp variables for reporting +// string tempFilePath = Path.GetTempPath(); +// string tempFilePathWithGuid = Path.Combine(tempFilePath, Guid.NewGuid().ToString()); + +// // If we have a file +// if (File.Exists(path)) +// { +// // Get the reportable file name +// string reportableFileName = path; +// if (reportableFileName.StartsWith(tempFilePath)) +// reportableFileName = reportableFileName.Substring(tempFilePathWithGuid.Length); + +// // Checkpoint +// FileProgress?.Report(new FileProtection(reportableFileName, 1, "Checking file" + (path != reportableFileName ? " from archive" : string.Empty))); + +// // Try using just the file first to get protection info +// string fileProtection = ScanPath(path, false); +// if (!string.IsNullOrWhiteSpace(fileProtection)) +// protections[path] = fileProtection; + +// // Now check to see if the file contains any additional information +// string contentProtection = ScanContent(path, includePosition)?.Replace("" + (char)0x00, ""); +// if (!string.IsNullOrWhiteSpace(contentProtection)) +// { +// if (protections.ContainsKey(path)) +// protections[path] += $", {contentProtection}"; +// else +// protections[path] = contentProtection; +// } + +// // Checkpoint +// protections.TryGetValue(path, out string fullProtection); +// FileProgress?.Report(new FileProtection(reportableFileName, 1, fullProtection ?? string.Empty)); +// } +// // If we have a directory +// else if (Directory.Exists(path)) +// { +// // Get the lists of files to be used +// var files = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories); + +// // Try using just the path first to get protection info +// string pathProtection = ScanPath(path, true); +// if (!string.IsNullOrWhiteSpace(pathProtection)) +// protections[path] = pathProtection; + +// // Loop through all files and scan their contents +// for (int i = 0; i < files.Count(); i++) +// { +// // Get the current file +// string file = files.ElementAt(i); + +// // Get the reportable file name +// string reportableFileName = file; +// if (reportableFileName.StartsWith(tempFilePath)) +// reportableFileName = reportableFileName.Substring(tempFilePathWithGuid.Length); + +// // Checkpoint +// FileProgress?.Report(new FileProtection(reportableFileName, i / (float)files.Count(), "Checking file" + (file != reportableFileName ? " from archive" : string.Empty))); + +// // Try using just the file first to get protection info +// string fileProtection = ScanPath(file, false); +// if (!string.IsNullOrWhiteSpace(fileProtection)) +// protections[file] = fileProtection; + +// // Now check to see if the file contains any additional information +// string contentProtection = ScanContent(file, includePosition)?.Replace("" + (char)0x00, ""); +// if (!string.IsNullOrWhiteSpace(contentProtection)) +// { +// if (protections.ContainsKey(file)) +// protections[file] += $", {contentProtection}"; +// else +// protections[file] = contentProtection; +// } + +// // Checkpoint +// protections.TryGetValue(file, out string fullProtection); +// FileProgress?.Report(new FileProtection(reportableFileName, (i + 1) / (float)files.Count(), fullProtection ?? string.Empty)); +// } +// } + +// // If we have an empty list, we need to take care of that +// if (protections.Count(p => !string.IsNullOrWhiteSpace(p.Value)) == 0) +// { +// protections = new Dictionary(); +// } + +// return protections; +// } + +// /// +// /// Scan a path for indications of copy protection +// /// +// /// Path to scan file and folder names +// /// True if the path is a directory, false otherwise +// /// +// public static string ScanPath(string path, bool isDirectory) +// { +// List protections = new List(); +// string protection; + +// // If we have a directory, get the files in the directory for searching +// IEnumerable files = null; +// if (isDirectory) +// files = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories); + +// // AACS +// protection = AACS.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Alpha-DVD +// protection = AlphaDVD.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Bitpool +// protection = Bitpool.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // ByteShield +// protection = ByteShield.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Cactus Data Shield +// protection = CactusDataShield.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // CD-Cops +// protection = CDCops.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // CD-Lock +// protection = CDLock.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // CD-Protector +// protection = CDProtector.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // CD-X +// protection = CDX.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// /* +// // CopyKiller +// protection = CopyKiller.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); +// */ + +// // DiscGuard +// protection = DiscGuard.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // DVD Crypt +// protection = DVDCrypt.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // DVD-Movie-PROTECT +// protection = DVDMoviePROTECT.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // FreeLock +// protection = FreeLock.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Games for Windows - Live +// protection = GFWL.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Hexalock AutoLock +// protection = HexalockAutoLock.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Impulse Reactor +// protection = ImpulseReactor.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // IndyVCD +// protection = IndyVCD.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Key2Audio XS +// protection = Key2AudioXS.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // LaserLock +// protection = LaserLock.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // MediaCloQ +// protection = MediaCloQ.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // MediaMax CD3 +// protection = MediaMaxCD3.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Origin +// protection = Origin.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Protect DVD-Video +// protection = ProtectDVDVideo.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // SafeCast +// protection = SafeCast.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // SafeDisc +// protection = SafeDisc.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // SafeDisc Lite +// protection = SafeDiscLite.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // SafeLock +// protection = SafeLock.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // SecuROM +// protection = SecuROM.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // SmartE +// protection = SmartE.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // SoftLock +// protection = SoftLock.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // SolidShield +// protection = SolidShield.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // StarForce +// protection = StarForce.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Steam +// protection = Steam.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // TAGES +// protection = Tages.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // TZCopyProtector +// protection = TZCopyProtector.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Uplay +// protection = Uplay.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // VOB ProtectCD/DVD +// protection = VOBProtectCDDVD.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Winlock +// protection = Winlock.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // WTM CD Protect +// protection = WTMCDProtect.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // XCP +// protection = XCP.CheckPath(path, files, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Zzxzz +// protection = Zzxzz.CheckPath(path, isDirectory); +// if (!string.IsNullOrWhiteSpace(protection)) +// protections.Add(protection); + +// // Now combine any found protections, or null if empty +// if (protections.Count() == 0) +// return null; +// else +// return string.Join(", ", protections); +// } + +// /// +// /// Scan an individual file for copy protection +// /// +// /// File path for scanning +// /// True to include scanned copy protection position, false otherwise (default) +// public static string ScanContent(string file, bool includePosition = false) +// { +// try +// { +// using (FileStream fs = File.OpenRead(file)) +// { +// return ScanContent(fs, file, includePosition); +// } +// } +// catch +// { +// return null; +// } +// } + +// /// +// /// Scan an individual stream for copy protection +// /// +// /// Generic stream to scan +// /// File path to be used for name checks (optional) +// /// True to include scanned copy protection position, false otherwise (default) +// public static string ScanContent(Stream stream, string file = null, bool includePosition = false) +// { +// // Get the extension for certain checks +// string extension = Path.GetExtension(file).ToLower().TrimStart('.'); + +// // Assume the first part of the stream is the start of a file +// byte[] magic = new byte[16]; +// try +// { +// stream.Read(magic, 0, 16); +// stream.Seek(-16, SeekOrigin.Current); +// } +// catch +// { +// // We don't care what the issue was, we can't read or seek the file +// return null; +// } + +// // Files can be protected in multiple ways +// List protections = new List(); + +// #region Non-Archive Formats + +// // Executable +// if (Executable.ShouldScan(magic)) +// protections.AddRange(Executable.Scan(stream, file, includePosition)); + +// // Text-based files +// if (Textfile.ShouldScan(magic, extension)) +// protections.AddRange(Textfile.Scan(stream, includePosition)); + +// #endregion + +// #region Archive Formats + +// // 7-Zip archive +// if (SevenZip.ShouldScan(magic)) +// protections.AddRange(SevenZip.Scan(stream, includePosition)); + +// // BFPK archive +// if (BFPK.ShouldScan(magic)) +// protections.AddRange(BFPK.Scan(stream, includePosition)); + +// // BZip2 +// if (BZip2.ShouldScan(magic)) +// protections.AddRange(BZip2.Scan(stream, includePosition)); + +// // GZIP +// if (GZIP.ShouldScan(magic)) +// protections.AddRange(GZIP.Scan(stream, includePosition)); + +// // InstallShield Cabinet +// if (file != null && InstallShieldCAB.ShouldScan(magic)) +// protections.AddRange(InstallShieldCAB.Scan(file, includePosition)); + +// // Microsoft Cabinet +// if (file != null && MicrosoftCAB.ShouldScan(magic)) +// protections.AddRange(MicrosoftCAB.Scan(file, includePosition)); + +// // MSI +// if (file != null && MSI.ShouldScan(magic)) +// protections.AddRange(MSI.Scan(file, includePosition)); + +// // MPQ archive +// if (file != null && MPQ.ShouldScan(magic)) +// protections.AddRange(MPQ.Scan(file, includePosition)); + +// // PKZIP archive (and derivatives) +// if (PKZIP.ShouldScan(magic)) +// protections.AddRange(PKZIP.Scan(stream, includePosition)); + +// // RAR archive +// if (RAR.ShouldScan(magic)) +// protections.AddRange(RAR.Scan(stream, includePosition)); + +// // Tape Archive +// if (TapeArchive.ShouldScan(magic)) +// protections.AddRange(TapeArchive.Scan(stream, includePosition)); + +// // Valve archive formats +// if (file != null && Valve.ShouldScan(magic)) +// protections.AddRange(Valve.Scan(file, includePosition)); + +// // XZ +// if (XZ.ShouldScan(magic)) +// protections.AddRange(XZ.Scan(stream, includePosition)); + +// #endregion + +// // Return blank if nothing found, or comma-separated list of protections +// if (protections.Count() == 0) +// return string.Empty; +// else +// return string.Join(", ", protections); +// } + +// /// +// /// Scan a disc sector by sector for protection +// /// +// /// +// /// https://stackoverflow.com/questions/8819188/c-sharp-classes-to-undelete-files/8820157#8820157 +// /// TODO: Finish implementation +// /// +// private static string ScanSectors(char driveLetter, int sectorsize) +// { +// string fsName = Utilities.GetFileSystemName(driveLetter); + +// // Gets a handle to the physical disk +// IntPtr hDisk = Utilities.CreateFile($"\\\\.\\{driveLetter}:", +// FileAccess.Read, +// FileShare.ReadWrite, +// IntPtr.Zero, +// FileMode.Open, +// 0, +// IntPtr.Zero); + +// // If we have a good pointer +// if (hDisk.ToInt32() != -1) +// { +// // Setup vars +// byte[] buffer = new byte[sectorsize]; +// IntPtr pt = IntPtr.Zero; +// NativeOverlapped no = new NativeOverlapped(); + +// // Set initial offset +// Utilities.SetFilePointerEx( +// hDisk, +// 0, +// ref pt, +// Utilities.FileBegin); + +// // Read a whole sector +// while (true) +// { +// buffer = new byte[sectorsize]; +// Utilities.ReadFileEx( +// hDisk, +// buffer, +// (uint)sectorsize, +// ref no, +// null); + +// Utilities.SetFilePointerEx( +// hDisk, +// sectorsize, +// ref pt, +// Utilities.FileCurrent); +// } +// } + +// Utilities.CloseHandle(hDisk); + +// return null; +// } +// } +//} diff --git a/BurnOutSharp/ProtectionType/WiseInstaller.cs b/BurnOutSharp/ProtectionType/WiseInstaller.cs index 59b8b173..e25ef44a 100644 --- a/BurnOutSharp/ProtectionType/WiseInstaller.cs +++ b/BurnOutSharp/ProtectionType/WiseInstaller.cs @@ -1,24 +1,28 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using Wise = WiseUnpacker.WiseUnpacker; namespace BurnOutSharp.ProtectionType { public class WiseInstaller { - public static List CheckContents(string file, byte[] fileContent, bool includePosition = false) + public static Dictionary> CheckContents(Scanner scanner, string file, byte[] fileContent) { - // "WiseMain" + // WiseMain byte[] check = new byte[] { 0x57, 0x69, 0x73, 0x65, 0x4D, 0x61, 0x69, 0x6E }; if (fileContent.Contains(check, out int position)) { - List protections = new List { "Wise Installation Wizard Module" + (includePosition ? $" (Index {position})" : string.Empty) }; - if (!File.Exists(file)) + Dictionary> protections = new Dictionary> + { + [file ?? "NO FILENAME"] = new List { "Wise Installation Wizard Module" + (scanner.IncludePosition ? $" (Index {position})" : string.Empty) }, + }; + + if (file == null || !File.Exists(file)) return protections; - protections.AddRange(WiseInstaller.Scan(file, includePosition)); + var subProtections = Scan(scanner, file); + Utilities.AppendToDictionary(protections, subProtections); return protections; } @@ -26,10 +30,8 @@ namespace BurnOutSharp.ProtectionType return null; } - public static List Scan(string file, bool includePosition = false) + public static Dictionary> Scan(Scanner scanner, string file) { - List protections = new List(); - // If the installer file itself fails try { @@ -40,7 +42,7 @@ namespace BurnOutSharp.ProtectionType unpacker.ExtractTo(file, tempPath); // Collect and format all found protections - var protections = subScanner.GetProtections(); + var protections = scanner.GetProtections(tempPath); // If temp directory cleanup fails try @@ -48,10 +50,12 @@ namespace BurnOutSharp.ProtectionType Directory.Delete(tempPath, true); } catch { } + + return protections; } catch { } - return protections; + return null; } } diff --git a/BurnOutSharp/Scanner.cs b/BurnOutSharp/Scanner.cs index 29eddec6..b88f4f26 100644 --- a/BurnOutSharp/Scanner.cs +++ b/BurnOutSharp/Scanner.cs @@ -8,7 +8,6 @@ using BurnOutSharp.ProtectionType; namespace BurnOutSharp { // TODO: Use the file progress everywhere - // TODO: Re-enable direct stream scanning // TODO: Should FileTypes be exposed directly as well so the scans can be exposed easier? public class Scanner { @@ -61,6 +60,13 @@ namespace BurnOutSharp if (paths == null || !paths.Any()) return null; + // Checkpoint + FileProgress?.Report(new FileProtection(null, 0, null)); + + // Temp variables for reporting + string tempFilePath = Path.GetTempPath(); + string tempFilePathWithGuid = Path.Combine(tempFilePath, Guid.NewGuid().ToString()); + // Loop through each path and get the returned values var protections = new Dictionary>(); foreach (string path in paths) @@ -73,32 +79,25 @@ namespace BurnOutSharp // Scan for path-detectable protections var directoryPathProtections = GetPathProtections(path, files); - if (directoryPathProtections != null && directoryPathProtections.Any()) - { - foreach (string key in directoryPathProtections.Keys) - { - if (!protections.ContainsKey(key)) - protections[key] = new List(); - - protections[key].AddRange(directoryPathProtections[key]); - } - } + Utilities.AppendToDictionary(protections, directoryPathProtections); // Scan each file in directory separately - foreach (string file in files) + for (int i = 0; i < files.Count(); i++) { + // Get the current file + string file = files.ElementAt(i); + + // Get the reportable file name + string reportableFileName = file; + if (reportableFileName.StartsWith(tempFilePath)) + reportableFileName = reportableFileName.Substring(tempFilePathWithGuid.Length); + + // Checkpoint + FileProgress?.Report(new FileProtection(reportableFileName, i / (float)files.Count(), "Checking file" + (file != reportableFileName ? " from archive" : string.Empty))); + // Scan for path-detectable protections var filePathProtections = GetPathProtections(file); - if (filePathProtections != null && filePathProtections.Any()) - { - foreach (string key in filePathProtections.Keys) - { - if (!protections.ContainsKey(key)) - protections[key] = new List(); - - protections[key].AddRange(filePathProtections[key]); - } - } + Utilities.AppendToDictionary(protections, filePathProtections); // Scan for content-detectable protections var fileProtections = GetInternalProtections(file); @@ -112,24 +111,28 @@ namespace BurnOutSharp protections[key].AddRange(fileProtections[key]); } } - } + + // Checkpoint + protections.TryGetValue(file, out List fullProtectionList); + string fullProtection = (fullProtectionList != null && fullProtectionList.Any() ? string.Join(", ", fullProtectionList) : null); + FileProgress?.Report(new FileProtection(reportableFileName, (i + 1) / (float)files.Count(), fullProtection ?? string.Empty)); + } } // Scan a single file by itself else if (File.Exists(path)) { + // Get the reportable file name + string reportableFileName = path; + if (reportableFileName.StartsWith(tempFilePath)) + reportableFileName = reportableFileName.Substring(tempFilePathWithGuid.Length); + + // Checkpoint + FileProgress?.Report(new FileProtection(reportableFileName, 0, "Checking file" + (path != reportableFileName ? " from archive" : string.Empty))); + // Scan for path-detectable protections var filePathProtections = GetPathProtections(path); - if (filePathProtections != null && filePathProtections.Any()) - { - foreach (string key in filePathProtections.Keys) - { - if (!protections.ContainsKey(key)) - protections[key] = new List(); - - protections[key].AddRange(filePathProtections[key]); - } - } + Utilities.AppendToDictionary(protections, filePathProtections); // Scan for content-detectable protections var fileProtections = GetInternalProtections(path); @@ -143,12 +146,17 @@ namespace BurnOutSharp protections[key].AddRange(fileProtections[key]); } } + + // Checkpoint + protections.TryGetValue(path, out List fullProtectionList); + string fullProtection = (fullProtectionList != null && fullProtectionList.Any() ? string.Join(", ", fullProtectionList) : null); + FileProgress?.Report(new FileProtection(reportableFileName, 1, fullProtection ?? string.Empty)); } // Throw on an invalid path else { - throw new FileNotFoundException($"{path} is not a directory or file, skipping..."); + // throw new FileNotFoundException($"{path} is not a directory or file, skipping..."); } } @@ -428,21 +436,15 @@ namespace BurnOutSharp // Executable if (ScanAllFiles || Executable.ShouldScan(magic)) { - var subProtections = Executable.Scan(fs, file, IncludePosition); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + var subProtections = Executable.Scan(this, fs, file); + Utilities.AppendToDictionary(protections, subProtections); } // Text-based files if (ScanAllFiles || Textfile.ShouldScan(magic, extension)) { - var subProtections = Executable.Scan(fs, file, IncludePosition); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + var subProtections = Textfile.Scan(fs); + Utilities.AppendToDictionary(protections, file, subProtections); } #endregion @@ -457,130 +459,91 @@ namespace BurnOutSharp if (SevenZip.ShouldScan(magic)) { var subProtections = SevenZip.Scan(this, fs); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + Utilities.AppendToDictionary(protections, subProtections); } // BFPK archive if (BFPK.ShouldScan(magic)) { var subProtections = BFPK.Scan(this, fs); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + Utilities.AppendToDictionary(protections, subProtections); } // BZip2 if (BZip2.ShouldScan(magic)) { var subProtections = BZip2.Scan(this, fs); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + Utilities.AppendToDictionary(protections, subProtections); } // GZIP if (GZIP.ShouldScan(magic)) { var subProtections = GZIP.Scan(this, fs); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + Utilities.AppendToDictionary(protections, subProtections); } // InstallShield Cabinet if (file != null && InstallShieldCAB.ShouldScan(magic)) { var subProtections = InstallShieldCAB.Scan(this, file); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + Utilities.AppendToDictionary(protections, subProtections); } // Microsoft Cabinet if (file != null && MicrosoftCAB.ShouldScan(magic)) { var subProtections = MicrosoftCAB.Scan(this, file); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + Utilities.AppendToDictionary(protections, subProtections); } // MSI if (file != null && MSI.ShouldScan(magic)) { var subProtections = MSI.Scan(this, file); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + Utilities.AppendToDictionary(protections, subProtections); } // MPQ archive if (file != null && MPQ.ShouldScan(magic)) { var subProtections = MPQ.Scan(this, file); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + Utilities.AppendToDictionary(protections, subProtections); } // PKZIP archive (and derivatives) if (PKZIP.ShouldScan(magic)) { var subProtections = PKZIP.Scan(this, fs); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + Utilities.AppendToDictionary(protections, subProtections); } // RAR archive if (RAR.ShouldScan(magic)) { var subProtections = RAR.Scan(this, fs); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + Utilities.AppendToDictionary(protections, subProtections); } // Tape Archive if (TapeArchive.ShouldScan(magic)) { var subProtections = TapeArchive.Scan(this, fs); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + Utilities.AppendToDictionary(protections, subProtections); } // Valve archive formats if (file != null && Valve.ShouldScan(magic)) { var subProtections = Valve.Scan(this, file); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + Utilities.AppendToDictionary(protections, subProtections); } // XZ if (XZ.ShouldScan(magic)) { var subProtections = XZ.Scan(this, fs); - if (!protections.ContainsKey(file)) - protections[file] = new List(); - - protections[file] = subProtections; + Utilities.AppendToDictionary(protections, subProtections); } } diff --git a/BurnOutSharp/Utilities.cs b/BurnOutSharp/Utilities.cs index 035db71a..0e80c59b 100644 --- a/BurnOutSharp/Utilities.cs +++ b/BurnOutSharp/Utilities.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; @@ -7,7 +8,7 @@ using System.Threading; namespace BurnOutSharp { - public static class Utilities + internal static class Utilities { /// /// Search for a byte array in another array @@ -109,6 +110,60 @@ namespace BurnOutSharp return fsName; } + /// + /// Append one result to a results dictionary + /// + /// Dictionary to append to + /// Key to add information to + /// String value to add + public static void AppendToDictionary(Dictionary> original, string key, string value) + { + AppendToDictionary(original, key, new List { value }); + } + + /// + /// Append one result to a results dictionary + /// + /// Dictionary to append to + /// Key to add information to + /// String value to add + public static void AppendToDictionary(Dictionary> original, string key, List values) + { + // If the dictionary is null, just return + if (original == null) + return; + + // Use a placeholder value if the key is null + key = key ?? "NO FILENAME"; + + // Add the key if needed and then append the lists + if (!original.ContainsKey(key)) + original[key] = new List(); + + original[key].AddRange(values); + } + + /// + /// Append one results dictionary to another + /// + /// Dictionary to append to + /// Dictionary to pull from + public static void AppendToDictionary(Dictionary> original, Dictionary> addition) + { + // If either dictionary is missing, just return + if (original == null || addition == null) + return; + + // Loop through each of the addition keys and add accordingly + foreach (string key in addition.Keys) + { + if (!original.ContainsKey(key)) + original[key] = new List(); + + original[key].AddRange(addition[key]); + } + } + #region P/Invoke // https://stackoverflow.com/questions/8819188/c-sharp-classes-to-undelete-files/8820157#8820157 diff --git a/Test/Program.cs b/Test/Program.cs index 6bc21ca6..ac68f297 100644 --- a/Test/Program.cs +++ b/Test/Program.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Linq; using BurnOutSharp; namespace Test @@ -9,15 +8,36 @@ namespace Test { static void Main(string[] args) { + // Create progress indicator var p = new Progress(); p.ProgressChanged += Changed; + + // Create scanner to be shared + var scanner = new Scanner(p) + { + IncludePosition = true, + ScanAllFiles = false, + ScanArchives = true, + }; + foreach (string arg in args) { - string protections = string.Join("\r\n", ProtectionFind.Scan(arg, true, p).Select(kvp => kvp.Key + ": " + kvp.Value.TrimEnd())); - Console.WriteLine(protections); - using (StreamWriter sw = new StreamWriter(File.OpenWrite($"{DateTime.Now:yyyy-MM-dd_HHmmss}.txt"))) + var protections = scanner.GetProtections(arg); + if (protections != null) { - sw.WriteLine(protections); + using (StreamWriter sw = new StreamWriter(File.OpenWrite($"{DateTime.Now:yyyy-MM-dd_HHmmss}.txt"))) + { + foreach (string key in protections.Keys) + { + string line = $"{key}: {string.Join(", ", protections[key])}"; + Console.WriteLine(line); + sw.WriteLine(line); + } + } + } + else + { + Console.WriteLine($"No protections found for {arg}"); } }