using System; using System.IO; using SabreTools.IO.Extensions; using SabreTools.Serialization.Wrappers; namespace ExtractionTool { class Program { static void Main(string[] args) { #if NET462_OR_GREATER || NETCOREAPP // Register the codepages System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); #endif // Get the options from the arguments var options = Options.ParseOptions(args); // If we have an invalid state if (options == null) { Options.DisplayHelp(); return; } // Loop through the input paths foreach (string inputPath in options.InputPaths) { ExtractPath(inputPath, options.OutputPath, options.Debug); } } /// /// Wrapper to extract data for a single path /// /// File or directory path /// Output directory path /// Enable including debug information private static void ExtractPath(string path, string outputDirectory, bool includeDebug) { // Normalize by getting the full path path = Path.GetFullPath(path); Console.WriteLine($"Checking possible path: {path}"); // Check if the file or directory exists if (File.Exists(path)) { ExtractFile(path, outputDirectory, includeDebug); } else if (Directory.Exists(path)) { foreach (string file in IOExtensions.SafeEnumerateFiles(path, "*", SearchOption.AllDirectories)) { ExtractFile(file, outputDirectory, includeDebug); } } else { Console.WriteLine($"{path} does not exist, skipping..."); } } /// /// Print information for a single file, if possible /// private static void ExtractFile(string file, string outputDirectory, bool includeDebug) { Console.WriteLine($"Attempting to extract all files from {file}"); using Stream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); // Get the extension for certain checks string extension = Path.GetExtension(file).ToLower().TrimStart('.'); // Get the first 16 bytes for matching byte[] magic = new byte[16]; try { int read = stream.Read(magic, 0, 16); stream.Seek(0, SeekOrigin.Begin); } catch (Exception ex) { if (includeDebug) Console.Error.WriteLine(ex); return; } // Get the file type WrapperType ft = WrapperFactory.GetFileType(magic, extension); var wrapper = WrapperFactory.CreateWrapper(ft, stream); // Create the output directory Directory.CreateDirectory(outputDirectory); // Print the preamble Console.WriteLine($"Attempting to extract from '{wrapper?.Description() ?? "UNKNOWN"}'"); Console.WriteLine(); switch (wrapper) { // 7-zip case SevenZip sz: sz.Extract(outputDirectory, includeDebug); break; // BFPK archive case BFPK bfpk: bfpk.Extract(outputDirectory, includeDebug); break; // BSP case BSP bsp: bsp.Extract(outputDirectory, includeDebug); break; // bzip2 case BZip2 bzip2: bzip2.Extract(outputDirectory, includeDebug); break; // CFB case CFB cfb: cfb.Extract(outputDirectory, includeDebug); break; // GCF case GCF gcf: gcf.Extract(outputDirectory, includeDebug); break; // gzip case GZip gzip: gzip.Extract(outputDirectory, includeDebug); break; // InstallShield Archive V3 (Z) case InstallShieldArchiveV3 isv3: isv3.Extract(outputDirectory, includeDebug); break; // IS-CAB archive case InstallShieldCabinet iscab: iscab.Extract(outputDirectory, includeDebug); break; // LZ-compressed file, KWAJ variant case LZKWAJ kwaj: kwaj.Extract(outputDirectory, includeDebug); break; // LZ-compressed file, QBasic variant case LZQBasic qbasic: qbasic.Extract(outputDirectory, includeDebug); break; // LZ-compressed file, SZDD variant case LZSZDD szdd: szdd.Extract(outputDirectory, includeDebug); break; // Microsoft Cabinet archive case MicrosoftCabinet mscab: mscab.Extract(outputDirectory, includeDebug); break; // MoPaQ (MPQ) archive case MoPaQ mpq: mpq.Extract(outputDirectory, includeDebug); break; // New Executable case NewExecutable nex: nex.Extract(outputDirectory, includeDebug); break; // PAK case PAK pak: pak.Extract(outputDirectory, includeDebug); break; // PFF case PFF pff: pff.Extract(outputDirectory, includeDebug); break; // PKZIP case PKZIP pkzip: pkzip.Extract(outputDirectory, includeDebug); break; // Portable Executable case PortableExecutable pex: pex.Extract(outputDirectory, includeDebug); break; // Quantum case Quantum quantum: quantum.Extract(outputDirectory, includeDebug); break; // RAR case RAR rar: rar.Extract(outputDirectory, includeDebug); break; // SGA case SGA sga: sga.Extract(outputDirectory, includeDebug); break; // Tape Archive case TapeArchive tar: tar.Extract(outputDirectory, includeDebug); break; // VBSP case VBSP vbsp: vbsp.Extract(outputDirectory, includeDebug); break; // VPK case VPK vpk: vpk.Extract(outputDirectory, includeDebug); break; // WAD3 case WAD3 wad: wad.Extract(outputDirectory, includeDebug); break; // xz case XZ xz: xz.Extract(outputDirectory, includeDebug); break; // XZP case XZP xzp: xzp.Extract(outputDirectory, includeDebug); break; // Everything else default: Console.WriteLine("Not a supported extractable file format, skipping..."); Console.WriteLine(); break; } } } }