Files
SabreTools.Serialization/ExtractionTool/Program.cs
2025-08-29 09:37:03 -04:00

250 lines
8.0 KiB
C#

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);
}
}
/// <summary>
/// Wrapper to extract data for a single path
/// </summary>
/// <param name="path">File or directory path</param>
/// <param name="outputDirectory">Output directory path</param>
/// <param name="includeDebug">Enable including debug information</param>
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...");
}
}
/// <summary>
/// Print information for a single file, if possible
/// </summary>
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;
}
}
}
}