mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
BTar files are integrated into the extractor code
This commit is contained in:
parent
30b29d890d
commit
379337d0b6
@ -69,6 +69,7 @@ internal class Program
|
||||
services.AddSingleton<IVerb, SteamDownloadFile>();
|
||||
services.AddSingleton<IVerb, UploadToNexus>();
|
||||
services.AddSingleton<IVerb, ListCreationClubContent>();
|
||||
services.AddSingleton<IVerb, Extract>();
|
||||
|
||||
services.AddSingleton<IUserInterventionHandler, UserInterventionHandler>();
|
||||
}).Build();
|
||||
|
49
Wabbajack.CLI/Verbs/Extract.cs
Normal file
49
Wabbajack.CLI/Verbs/Extract.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.CommandLine;
|
||||
using System.CommandLine.Invocation;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Downloaders;
|
||||
using Wabbajack.DTOs;
|
||||
using Wabbajack.Paths;
|
||||
using Wabbajack.Paths.IO;
|
||||
|
||||
namespace Wabbajack.CLI.Verbs;
|
||||
|
||||
public class Extract : IVerb
|
||||
{
|
||||
|
||||
private readonly ILogger<DownloadUrl> _logger;
|
||||
private readonly FileExtractor.FileExtractor _extractor;
|
||||
|
||||
public Extract(ILogger<DownloadUrl> logger, FileExtractor.FileExtractor extractor)
|
||||
{
|
||||
_logger = logger;
|
||||
_extractor = extractor;
|
||||
}
|
||||
|
||||
public Command MakeCommand()
|
||||
{
|
||||
var command = new Command("extract");
|
||||
command.Add(new Option<AbsolutePath>(new[] {"-i", "-input"}, "Input Archive"));
|
||||
command.Add(new Option<AbsolutePath>(new[] {"-o", "-output"}, "Output folder"));
|
||||
command.Description = "Extracts the contents of an archive into a folder";
|
||||
command.Handler = CommandHandler.Create(Run);
|
||||
return command;
|
||||
}
|
||||
|
||||
private async Task<int> Run(AbsolutePath input, AbsolutePath output, CancellationToken token)
|
||||
{
|
||||
if (!output.DirectoryExists())
|
||||
output.Parent.CreateDirectory();
|
||||
|
||||
await _extractor.ExtractAll(input, output, token, f =>
|
||||
{
|
||||
Console.WriteLine($" - {f}");
|
||||
return true;
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -5,3 +5,4 @@ Relaxed RAR format,52 61 72 21,RAR
|
||||
RAR5 or newer, 52 61 72 21 1A 07 01 00,RAR_NEW
|
||||
RAR4 or older, 52 61 72 21 1A 07 00,RAR_OLD
|
||||
DDS, 44 44 53 20,DDS
|
||||
Bethesda Tar, 42 54 41 52, BTAR
|
@ -1,7 +1,7 @@
|
||||
namespace Wabbajack.Common.FileSignatures;
|
||||
|
||||
namespace Wabbajack.Common.FileSignatures {
|
||||
|
||||
public enum FileType
|
||||
{
|
||||
public enum FileType { BTAR,
|
||||
_123,
|
||||
_386,
|
||||
_3G2,
|
||||
@ -431,13 +431,13 @@ public enum FileType
|
||||
XZ,
|
||||
ZAP,
|
||||
ZIP,
|
||||
ZOO
|
||||
ZOO,
|
||||
}
|
||||
|
||||
public static class Definitions
|
||||
{
|
||||
public static (FileType, byte[])[] Signatures =
|
||||
{
|
||||
public static class Definitions {
|
||||
|
||||
|
||||
public static (FileType, byte[])[] Signatures = {
|
||||
// Morrowind BSA
|
||||
(FileType.TES3, new byte[] {0x00, 0x01, 0x00, 0x00}),
|
||||
|
||||
@ -459,6 +459,9 @@ public static class Definitions
|
||||
// DDS
|
||||
(FileType.DDS, new byte[] {0x44, 0x44, 0x53, 0x20}),
|
||||
|
||||
// Bethesda Tar
|
||||
(FileType. BTAR, new byte[] {0x42, 0x54, 0x41, 0x52}),
|
||||
|
||||
// JPEG2000 image files
|
||||
(FileType.JP2, new byte[] {0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20}),
|
||||
|
||||
@ -481,12 +484,7 @@ public static class Definitions
|
||||
(FileType.TBI, new byte[] {0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00}),
|
||||
|
||||
// Bitcoin Core wallet.dat file
|
||||
(FileType.DAT,
|
||||
new byte[]
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x62, 0x31, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
}),
|
||||
(FileType.DAT, new byte[] {0x00, 0x00, 0x00, 0x00, 0x62, 0x31, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
|
||||
// MPEG-4 video_1
|
||||
(FileType._3GP5, new byte[] {0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70}),
|
||||
@ -534,11 +532,7 @@ public static class Definitions
|
||||
(FileType.CUR, new byte[] {0x00, 0x00, 0x02, 0x00}),
|
||||
|
||||
// Compucon-Singer embroidery design file
|
||||
(FileType.XXX,
|
||||
new byte[]
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
}),
|
||||
(FileType.XXX, new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
|
||||
// QuattroPro spreadsheet
|
||||
(FileType.WB2, new byte[] {0x00, 0x00, 0x02, 0x00}),
|
||||
@ -574,28 +568,13 @@ public static class Definitions
|
||||
(FileType.TTF, new byte[] {0x00, 0x01, 0x00, 0x00, 0x00}),
|
||||
|
||||
// Microsoft Money file
|
||||
(FileType.MNY,
|
||||
new byte[]
|
||||
{
|
||||
0x00, 0x01, 0x00, 0x00, 0x4D, 0x53, 0x49, 0x53, 0x41, 0x4D, 0x20, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61,
|
||||
0x73, 0x65
|
||||
}),
|
||||
(FileType.MNY, new byte[] {0x00, 0x01, 0x00, 0x00, 0x4D, 0x53, 0x49, 0x53, 0x41, 0x4D, 0x20, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65}),
|
||||
|
||||
// Microsoft Access 2007
|
||||
(FileType.ACCDB,
|
||||
new byte[]
|
||||
{
|
||||
0x00, 0x01, 0x00, 0x00, 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0x20, 0x41, 0x43, 0x45, 0x20,
|
||||
0x44, 0x42
|
||||
}),
|
||||
(FileType.ACCDB, new byte[] {0x00, 0x01, 0x00, 0x00, 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0x20, 0x41, 0x43, 0x45, 0x20, 0x44, 0x42}),
|
||||
|
||||
// Microsoft Access
|
||||
(FileType.MDB,
|
||||
new byte[]
|
||||
{
|
||||
0x00, 0x01, 0x00, 0x00, 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0x20, 0x4A, 0x65, 0x74, 0x20,
|
||||
0x44, 0x42
|
||||
}),
|
||||
(FileType.MDB, new byte[] {0x00, 0x01, 0x00, 0x00, 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0x20, 0x4A, 0x65, 0x74, 0x20, 0x44, 0x42}),
|
||||
|
||||
// Palm Address Book Archive
|
||||
(FileType.ABA, new byte[] {0x00, 0x01, 0x42, 0x41}),
|
||||
@ -604,11 +583,7 @@ public static class Definitions
|
||||
(FileType.DBA, new byte[] {0x00, 0x01, 0x42, 0x44}),
|
||||
|
||||
// Netscape Navigator (v4) database
|
||||
(FileType.DB,
|
||||
new byte[]
|
||||
{
|
||||
0x00, 0x06, 0x15, 0x61, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0xD2, 0x00, 0x00, 0x10, 0x00
|
||||
}),
|
||||
(FileType.DB, new byte[] {0x00, 0x06, 0x15, 0x61, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0xD2, 0x00, 0x00, 0x10, 0x00}),
|
||||
|
||||
// FLIC animation
|
||||
(FileType.FLI, new byte[] {0x00, 0x11}),
|
||||
@ -662,11 +637,7 @@ public static class Definitions
|
||||
(FileType.DB4, new byte[] {0x04}),
|
||||
|
||||
// Adobe InDesign
|
||||
(FileType.INDD,
|
||||
new byte[]
|
||||
{
|
||||
0x06, 0x06, 0xED, 0xF5, 0xD8, 0x1D, 0x46, 0xE5, 0xBD, 0x31, 0xEF, 0xE7, 0xFE, 0x74, 0xB7, 0x1D
|
||||
}),
|
||||
(FileType.INDD, new byte[] {0x06, 0x06, 0xED, 0xF5, 0xD8, 0x1D, 0x46, 0xE5, 0xBD, 0x31, 0xEF, 0xE7, 0xFE, 0x74, 0xB7, 0x1D}),
|
||||
|
||||
// Material Exchange Format
|
||||
(FileType.MXF, new byte[] {0x06, 0x0E, 0x2B, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0D, 0x01, 0x02, 0x01, 0x01, 0x02}),
|
||||
@ -696,11 +667,7 @@ public static class Definitions
|
||||
(FileType.PCX, new byte[] {0x0A, 0x05, 0x01, 0x01}),
|
||||
|
||||
// MultiBit Bitcoin wallet file
|
||||
(FileType.WALLET,
|
||||
new byte[]
|
||||
{
|
||||
0x0A, 0x16, 0x6F, 0x72, 0x67, 0x2E, 0x62, 0x69, 0x74, 0x63, 0x6F, 0x69, 0x6E, 0x2E, 0x70, 0x72
|
||||
}),
|
||||
(FileType.WALLET, new byte[] {0x0A, 0x16, 0x6F, 0x72, 0x67, 0x2E, 0x62, 0x69, 0x74, 0x63, 0x6F, 0x69, 0x6E, 0x2E, 0x70, 0x72}),
|
||||
|
||||
// Monochrome Picture TIFF bitmap
|
||||
(FileType.MP, new byte[] {0x0C, 0xED}),
|
||||
@ -865,12 +832,7 @@ public static class Definitions
|
||||
(FileType.AU, new byte[] {0x2E, 0x73, 0x6E, 0x64}),
|
||||
|
||||
// Thunderbird-Mozilla Mail Summary File
|
||||
(FileType.MSF,
|
||||
new byte[]
|
||||
{
|
||||
0x2F, 0x2F, 0x20, 0x3C, 0x21, 0x2D, 0x2D, 0x20, 0x3C, 0x6D, 0x64, 0x62, 0x3A, 0x6D, 0x6F, 0x72, 0x6B,
|
||||
0x3A, 0x7A
|
||||
}),
|
||||
(FileType.MSF, new byte[] {0x2F, 0x2F, 0x20, 0x3C, 0x21, 0x2D, 0x2D, 0x20, 0x3C, 0x6D, 0x64, 0x62, 0x3A, 0x6D, 0x6F, 0x72, 0x6B, 0x3A, 0x7A}),
|
||||
|
||||
// MS security catalog file
|
||||
(FileType.CAT, new byte[] {0x30}),
|
||||
@ -900,11 +862,7 @@ public static class Definitions
|
||||
(FileType.WRI, new byte[] {0x32, 0xBE}),
|
||||
|
||||
// Pfaff Home Embroidery
|
||||
(FileType.PCS,
|
||||
new byte[]
|
||||
{
|
||||
0x32, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xFF, 0x00
|
||||
}),
|
||||
(FileType.PCS, new byte[] {0x32, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xFF, 0x00}),
|
||||
|
||||
// 7-Zip compressed file
|
||||
(FileType._7Z, new byte[] {0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C}),
|
||||
@ -928,40 +886,19 @@ public static class Definitions
|
||||
(FileType.WSC, new byte[] {0x3C, 0x3F}),
|
||||
|
||||
// Windows Visual Stylesheet
|
||||
(FileType.MANIFEST,
|
||||
new byte[] {0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D}),
|
||||
(FileType.MANIFEST, new byte[] {0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D}),
|
||||
|
||||
// User Interface Language
|
||||
(FileType.XML,
|
||||
new byte[]
|
||||
{
|
||||
0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E,
|
||||
0x30, 0x22, 0x3F, 0x3E
|
||||
}),
|
||||
(FileType.XML, new byte[] {0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x3F, 0x3E}),
|
||||
|
||||
// MMC Snap-in Control file
|
||||
(FileType.MSC,
|
||||
new byte[]
|
||||
{
|
||||
0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E,
|
||||
0x30, 0x22, 0x3F, 0x3E, 0x0D, 0x0A, 0x3C, 0x4D, 0x4D, 0x43, 0x5F, 0x43, 0x6F, 0x6E, 0x73, 0x6F, 0x6C,
|
||||
0x65, 0x46, 0x69, 0x6C, 0x65, 0x20, 0x43, 0x6F, 0x6E, 0x73, 0x6F, 0x6C, 0x65, 0x56, 0x65, 0x72, 0x73,
|
||||
0x69, 0x6F, 0x6E, 0x3D, 0x22
|
||||
}),
|
||||
(FileType.MSC, new byte[] {0x3C, 0x3F, 0x78, 0x6D, 0x6C, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E, 0x30, 0x22, 0x3F, 0x3E, 0x0D, 0x0A, 0x3C, 0x4D, 0x4D, 0x43, 0x5F, 0x43, 0x6F, 0x6E, 0x73, 0x6F, 0x6C, 0x65, 0x46, 0x69, 0x6C, 0x65, 0x20, 0x43, 0x6F, 0x6E, 0x73, 0x6F, 0x6C, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22}),
|
||||
|
||||
// Picasa movie project file
|
||||
(FileType.MXF,
|
||||
new byte[]
|
||||
{
|
||||
0x3C, 0x43, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x54, 0x69, 0x6D, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x3E
|
||||
}),
|
||||
(FileType.MXF, new byte[] {0x3C, 0x43, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x54, 0x69, 0x6D, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x3E}),
|
||||
|
||||
// Csound music
|
||||
(FileType.CSD,
|
||||
new byte[]
|
||||
{
|
||||
0x3C, 0x43, 0x73, 0x6F, 0x75, 0x6E, 0x64, 0x53, 0x79, 0x6E, 0x74, 0x68, 0x65, 0x73, 0x69, 0x7A
|
||||
}),
|
||||
(FileType.CSD, new byte[] {0x3C, 0x43, 0x73, 0x6F, 0x75, 0x6E, 0x64, 0x53, 0x79, 0x6E, 0x74, 0x68, 0x65, 0x73, 0x69, 0x7A}),
|
||||
|
||||
// Adobe FrameMaker
|
||||
(FileType.FM, new byte[] {0x3C, 0x4D, 0x61, 0x6B, 0x65, 0x72, 0x46, 0x69}),
|
||||
@ -970,11 +907,7 @@ public static class Definitions
|
||||
(FileType.MIF, new byte[] {0x3C, 0x4D, 0x61, 0x6B, 0x65, 0x72, 0x46, 0x69}),
|
||||
|
||||
// GPS Exchange (v1.1)
|
||||
(FileType.GPX,
|
||||
new byte[]
|
||||
{
|
||||
0x3C, 0x67, 0x70, 0x78, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E
|
||||
}),
|
||||
(FileType.GPX, new byte[] {0x3C, 0x67, 0x70, 0x78, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E}),
|
||||
|
||||
// BASE85 file
|
||||
(FileType.B85, new byte[] {0x3C, 0x7E, 0x36, 0x3C, 0x5C, 0x25, 0x5F, 0x30, 0x67, 0x53, 0x71, 0x68, 0x3B}),
|
||||
@ -1142,11 +1075,7 @@ public static class Definitions
|
||||
(FileType.SWF, new byte[] {0x43, 0x57, 0x53}),
|
||||
|
||||
// Calculux Indoor lighting project file
|
||||
(FileType.CIN,
|
||||
new byte[]
|
||||
{
|
||||
0x43, 0x61, 0x6C, 0x63, 0x75, 0x6C, 0x75, 0x78, 0x20, 0x49, 0x6E, 0x64, 0x6F, 0x6F, 0x72, 0x20
|
||||
}),
|
||||
(FileType.CIN, new byte[] {0x43, 0x61, 0x6C, 0x63, 0x75, 0x6C, 0x75, 0x78, 0x20, 0x49, 0x6E, 0x64, 0x6F, 0x6F, 0x72, 0x20}),
|
||||
|
||||
// WhereIsIt Catalog
|
||||
(FileType.CTF, new byte[] {0x43, 0x61, 0x74, 0x61, 0x6C, 0x6F, 0x67, 0x20}),
|
||||
@ -1158,11 +1087,7 @@ public static class Definitions
|
||||
(FileType.CRX, new byte[] {0x43, 0x72, 0x32, 0x34}),
|
||||
|
||||
// Creative Voice
|
||||
(FileType.VOC,
|
||||
new byte[]
|
||||
{
|
||||
0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x56, 0x6F, 0x69, 0x63, 0x65, 0x20, 0x46
|
||||
}),
|
||||
(FileType.VOC, new byte[] {0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x56, 0x6F, 0x69, 0x63, 0x65, 0x20, 0x46}),
|
||||
|
||||
// PowerISO Direct-Access-Archive image
|
||||
(FileType.DAA, new byte[] {0x44, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00}),
|
||||
@ -1258,18 +1183,10 @@ public static class Definitions
|
||||
(FileType.GX2, new byte[] {0x47, 0x58, 0x32}),
|
||||
|
||||
// Genetec video archive
|
||||
(FileType.G64,
|
||||
new byte[]
|
||||
{
|
||||
0x47, 0x65, 0x6E, 0x65, 0x74, 0x65, 0x63, 0x20, 0x4F, 0x6D, 0x6E, 0x69, 0x63, 0x61, 0x73, 0x74
|
||||
}),
|
||||
(FileType.G64, new byte[] {0x47, 0x65, 0x6E, 0x65, 0x74, 0x65, 0x63, 0x20, 0x4F, 0x6D, 0x6E, 0x69, 0x63, 0x61, 0x73, 0x74}),
|
||||
|
||||
// SAS Transport dataset
|
||||
(FileType.XPT,
|
||||
new byte[]
|
||||
{
|
||||
0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x20, 0x52, 0x45, 0x43, 0x4F, 0x52, 0x44, 0x2A, 0x2A, 0x2A
|
||||
}),
|
||||
(FileType.XPT, new byte[] {0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x20, 0x52, 0x45, 0x43, 0x4F, 0x52, 0x44, 0x2A, 0x2A, 0x2A}),
|
||||
|
||||
// Harvard Graphics presentation file
|
||||
(FileType.SH3, new byte[] {0x48, 0x48, 0x47, 0x42, 0x31}),
|
||||
@ -1317,11 +1234,7 @@ public static class Definitions
|
||||
(FileType.DAT, new byte[] {0x49, 0x6E, 0x6E, 0x6F, 0x20, 0x53, 0x65, 0x74}),
|
||||
|
||||
// Inter@ctive Pager Backup (BlackBerry file
|
||||
(FileType.IPD,
|
||||
new byte[]
|
||||
{
|
||||
0x49, 0x6E, 0x74, 0x65, 0x72, 0x40, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x50, 0x61, 0x67, 0x65
|
||||
}),
|
||||
(FileType.IPD, new byte[] {0x49, 0x6E, 0x74, 0x65, 0x72, 0x40, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x50, 0x61, 0x67, 0x65}),
|
||||
|
||||
// JARCS compressed archive
|
||||
(FileType.JAR, new byte[] {0x4A, 0x41, 0x52, 0x43, 0x53, 0x00}),
|
||||
@ -1375,22 +1288,13 @@ public static class Definitions
|
||||
(FileType.MAR, new byte[] {0x4D, 0x41, 0x52, 0x43}),
|
||||
|
||||
// MATLAB v5 workspace
|
||||
(FileType.MAT,
|
||||
new byte[]
|
||||
{
|
||||
0x4D, 0x41, 0x54, 0x4C, 0x41, 0x42, 0x20, 0x35, 0x2E, 0x30, 0x20, 0x4D, 0x41, 0x54, 0x2D, 0x66, 0x69,
|
||||
0x6C, 0x65
|
||||
}),
|
||||
(FileType.MAT, new byte[] {0x4D, 0x41, 0x54, 0x4C, 0x41, 0x42, 0x20, 0x35, 0x2E, 0x30, 0x20, 0x4D, 0x41, 0x54, 0x2D, 0x66, 0x69, 0x6C, 0x65}),
|
||||
|
||||
// MAr compressed archive
|
||||
(FileType.MAR, new byte[] {0x4D, 0x41, 0x72, 0x30, 0x00}),
|
||||
|
||||
// TargetExpress target file
|
||||
(FileType.MTE,
|
||||
new byte[]
|
||||
{
|
||||
0x4D, 0x43, 0x57, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x67, 0x6F, 0x6C, 0x69, 0x65, 0x73
|
||||
}),
|
||||
(FileType.MTE, new byte[] {0x4D, 0x43, 0x57, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x67, 0x6F, 0x6C, 0x69, 0x65, 0x73}),
|
||||
|
||||
// Windows dump file
|
||||
(FileType.DMP, new byte[] {0x4D, 0x44, 0x4D, 0x50, 0x93, 0xA7}),
|
||||
@ -1534,26 +1438,13 @@ public static class Definitions
|
||||
(FileType.ZAP, new byte[] {0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF}),
|
||||
|
||||
// MS C++ debugging symbols file
|
||||
(FileType.PDB,
|
||||
new byte[]
|
||||
{
|
||||
0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x2F, 0x43, 0x2B, 0x2B, 0x20
|
||||
}),
|
||||
(FileType.PDB, new byte[] {0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x2F, 0x43, 0x2B, 0x2B, 0x20}),
|
||||
|
||||
// Visual Studio .NET file
|
||||
(FileType.SLN,
|
||||
new byte[]
|
||||
{
|
||||
0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x56, 0x69, 0x73, 0x75, 0x61, 0x6C
|
||||
}),
|
||||
(FileType.SLN, new byte[] {0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x56, 0x69, 0x73, 0x75, 0x61, 0x6C}),
|
||||
|
||||
// Windows Media Player playlist
|
||||
(FileType.WPL,
|
||||
new byte[]
|
||||
{
|
||||
0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73,
|
||||
0x20, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x20, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x20, 0x2D, 0x2D, 0x20
|
||||
}),
|
||||
(FileType.WPL, new byte[] {0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x4D, 0x65, 0x64, 0x69, 0x61, 0x20, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72, 0x20, 0x2D, 0x2D, 0x20}),
|
||||
|
||||
// VMapSource GPS Waypoint Database
|
||||
(FileType.GDB, new byte[] {0x4D, 0x73, 0x52, 0x63, 0x66}),
|
||||
@ -1751,12 +1642,7 @@ public static class Definitions
|
||||
(FileType.QSD, new byte[] {0x51, 0x57, 0x20, 0x56, 0x65, 0x72, 0x2E, 0x20}),
|
||||
|
||||
// Outlook-Exchange message subheader
|
||||
(FileType.MSG,
|
||||
new byte[]
|
||||
{
|
||||
0x52, 0x00, 0x6F, 0x00, 0x6F, 0x00, 0x74, 0x00, 0x20, 0x00, 0x45, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x72,
|
||||
0x00, 0x79, 0x00
|
||||
}),
|
||||
(FileType.MSG, new byte[] {0x52, 0x00, 0x6F, 0x00, 0x6F, 0x00, 0x74, 0x00, 0x20, 0x00, 0x45, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x72, 0x00, 0x79, 0x00}),
|
||||
|
||||
// Shareaza (P2P) thumbnail
|
||||
(FileType.DAT, new byte[] {0x52, 0x41, 0x5A, 0x41, 0x54, 0x44, 0x42, 0x31}),
|
||||
@ -1840,12 +1726,7 @@ public static class Definitions
|
||||
(FileType.CPI, new byte[] {0x53, 0x49, 0x45, 0x54, 0x52, 0x4F, 0x4E, 0x49}),
|
||||
|
||||
// Flexible Image Transport System (FITS) file
|
||||
(FileType.FITS,
|
||||
new byte[]
|
||||
{
|
||||
0x53, 0x49, 0x4D, 0x50, 0x4C, 0x45, 0x20, 0x20, 0x3D, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54
|
||||
}),
|
||||
(FileType.FITS, new byte[] {0x53, 0x49, 0x4D, 0x50, 0x4C, 0x45, 0x20, 0x20, 0x3D, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54}),
|
||||
|
||||
// StuffIt archive
|
||||
(FileType.SIT, new byte[] {0x53, 0x49, 0x54, 0x21, 0x00}),
|
||||
@ -1860,11 +1741,7 @@ public static class Definitions
|
||||
(FileType.SPVB, new byte[] {0x53, 0x50, 0x56, 0x42}),
|
||||
|
||||
// SQLite database file
|
||||
(FileType.DB,
|
||||
new byte[]
|
||||
{
|
||||
0x53, 0x51, 0x4C, 0x69, 0x74, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x20, 0x33, 0x00
|
||||
}),
|
||||
(FileType.DB, new byte[] {0x53, 0x51, 0x4C, 0x69, 0x74, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x20, 0x33, 0x00}),
|
||||
|
||||
// DB2 conversion file
|
||||
(FileType.CNV, new byte[] {0x53, 0x51, 0x4C, 0x4F, 0x43, 0x4F, 0x4E, 0x56}),
|
||||
@ -1900,11 +1777,7 @@ public static class Definitions
|
||||
(FileType.MIF, new byte[] {0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20}),
|
||||
|
||||
// SPSS template
|
||||
(FileType.SCT,
|
||||
new byte[]
|
||||
{
|
||||
0x57, 0x04, 0x00, 0x00, 0x53, 0x50, 0x53, 0x53, 0x20, 0x74, 0x65, 0x6D, 0x70, 0x6C, 0x61, 0x74
|
||||
}),
|
||||
(FileType.SCT, new byte[] {0x57, 0x04, 0x00, 0x00, 0x53, 0x50, 0x53, 0x53, 0x20, 0x74, 0x65, 0x6D, 0x70, 0x6C, 0x61, 0x74}),
|
||||
|
||||
// RIFF Windows Audio
|
||||
(FileType.WAV, new byte[] {0x57, 0x41, 0x56, 0x45, 0x66, 0x6D, 0x74, 0x20}),
|
||||
@ -2153,12 +2026,7 @@ public static class Definitions
|
||||
(FileType.PSP, new byte[] {0x7E, 0x42, 0x4B, 0x00}),
|
||||
|
||||
// Easy Street Draw diagram file
|
||||
(FileType.ESD,
|
||||
new byte[]
|
||||
{
|
||||
0x7E, 0x45, 0x53, 0x44, 0x77, 0xF6, 0x85, 0x3E, 0xBF, 0x6A, 0xD2, 0x11, 0x45, 0x61, 0x73, 0x79, 0x20,
|
||||
0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x20, 0x44, 0x72, 0x61, 0x77
|
||||
}),
|
||||
(FileType.ESD, new byte[] {0x7E, 0x45, 0x53, 0x44, 0x77, 0xF6, 0x85, 0x3E, 0xBF, 0x6A, 0xD2, 0x11, 0x45, 0x61, 0x73, 0x79, 0x20, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x20, 0x44, 0x72, 0x61, 0x77}),
|
||||
|
||||
// Digital Watchdog DW-TP-500G audio
|
||||
(FileType.IMG, new byte[] {0x7E, 0x74, 0x2C, 0x01, 0x50, 0x70, 0x02, 0x4D, 0x52}),
|
||||
@ -2236,11 +2104,7 @@ public static class Definitions
|
||||
(FileType.WRI, new byte[] {0xBE, 0x00, 0x00, 0x00, 0xAB}),
|
||||
|
||||
// Palm Desktop DateBook
|
||||
(FileType.DAT,
|
||||
new byte[]
|
||||
{
|
||||
0xBE, 0xBA, 0xFE, 0xCA, 0x0F, 0x50, 0x61, 0x6C, 0x6D, 0x53, 0x47, 0x20, 0x44, 0x61, 0x74, 0x61
|
||||
}),
|
||||
(FileType.DAT, new byte[] {0xBE, 0xBA, 0xFE, 0xCA, 0x0F, 0x50, 0x61, 0x6C, 0x6D, 0x53, 0x47, 0x20, 0x44, 0x61, 0x74, 0x61}),
|
||||
|
||||
// MS Agent Character file
|
||||
(FileType.ACS, new byte[] {0xC3, 0xAB, 0xCD, 0xAB}),
|
||||
@ -2510,6 +2374,7 @@ public static class Definitions
|
||||
(FileType.MOF, new byte[] {0xFF, 0xFE, 0x23, 0x00, 0x6C, 0x00, 0x69, 0x00}),
|
||||
|
||||
// DOS system driver
|
||||
(FileType.SYS, new byte[] {0xFF, 0xFF, 0xFF, 0xFF})
|
||||
};
|
||||
}
|
||||
(FileType.SYS, new byte[] {0xFF, 0xFF, 0xFF, 0xFF}),
|
||||
|
||||
|
||||
};}}
|
@ -1,5 +1,8 @@
|
||||
<#@ template language="C#" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ import namespace="System.Collections.Generic" #>
|
||||
<#@ import namespace="System.IO" #>
|
||||
<#@ import namespace="System.Linq" #>
|
||||
|
||||
<#
|
||||
byte[] StringToByteArray(string hex)
|
||||
|
@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@ -11,8 +13,10 @@ using OMODFramework;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Common.FileSignatures;
|
||||
using Wabbajack.Compression.BSA;
|
||||
using Wabbajack.Compression.BSA.FO4Archive;
|
||||
using Wabbajack.DTOs.Streams;
|
||||
using Wabbajack.FileExtractor.ExtractedFiles;
|
||||
using Wabbajack.IO.Async;
|
||||
using Wabbajack.Paths;
|
||||
using Wabbajack.Paths.IO;
|
||||
using Wabbajack.RateLimiter;
|
||||
@ -24,6 +28,7 @@ public class FileExtractor
|
||||
public static readonly SignatureChecker ArchiveSigs = new(FileType.TES3,
|
||||
FileType.BSA,
|
||||
FileType.BA2,
|
||||
FileType.BTAR,
|
||||
FileType.ZIP,
|
||||
//FileType.EXE,
|
||||
FileType.RAR_OLD,
|
||||
@ -43,6 +48,7 @@ public class FileExtractor
|
||||
new Extension(".7zip"),
|
||||
new Extension(".rar"),
|
||||
new Extension(".zip"),
|
||||
new Extension(".btar"),
|
||||
OMODExtension,
|
||||
FOMODExtension
|
||||
};
|
||||
@ -98,6 +104,9 @@ public class FileExtractor
|
||||
|
||||
break;
|
||||
}
|
||||
case FileType.BTAR:
|
||||
results = await GatheringExtractWithBTAR(sFn, shouldExtract, mapfn, token);
|
||||
break;
|
||||
|
||||
case FileType.BSA:
|
||||
case FileType.BA2:
|
||||
@ -120,6 +129,75 @@ public class FileExtractor
|
||||
return results;
|
||||
}
|
||||
|
||||
private async Task<IDictionary<RelativePath,T>> GatheringExtractWithBTAR<T>
|
||||
(IStreamFactory sFn, Predicate<RelativePath> shouldExtract, Func<RelativePath,IExtractedFile,ValueTask<T>> mapfn, CancellationToken token)
|
||||
{
|
||||
await using var strm = await sFn.GetStream();
|
||||
var astrm = new AsyncBinaryReader(strm);
|
||||
var magic = BinaryPrimitives.ReadUInt32BigEndian(await astrm.ReadBytes(4));
|
||||
// BTAR Magic
|
||||
if (magic != 0x42544152) throw new Exception("Not a valid BTAR file");
|
||||
if (await astrm.ReadUInt16() != 1) throw new Exception("Invalid BTAR major version, should be 1");
|
||||
var minorVersion = await astrm.ReadUInt16();
|
||||
if (minorVersion is < 2 or > 4) throw new Exception("Invalid BTAR minor version");
|
||||
|
||||
var results = new Dictionary<RelativePath, T>();
|
||||
|
||||
while (astrm.Position < astrm.Length)
|
||||
{
|
||||
var nameLength = await astrm.ReadUInt16();
|
||||
var name = Encoding.UTF8.GetString(await astrm.ReadBytes(nameLength)).ToRelativePath();
|
||||
var dataLength = await astrm.ReadUInt64();
|
||||
var newPos = astrm.Position + (long)dataLength;
|
||||
if (!shouldExtract(name))
|
||||
{
|
||||
astrm.Position += (long)dataLength;
|
||||
continue;
|
||||
}
|
||||
|
||||
var result = await mapfn(name, new BTARExtractedFile(sFn, name, astrm, astrm.Position, (long) dataLength));
|
||||
results.Add(name, result);
|
||||
astrm.Position = newPos;
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private class BTARExtractedFile : IExtractedFile
|
||||
{
|
||||
private readonly IStreamFactory _parent;
|
||||
private readonly AsyncBinaryReader _rdr;
|
||||
private readonly long _start;
|
||||
private readonly long _length;
|
||||
private readonly RelativePath _name;
|
||||
|
||||
public BTARExtractedFile(IStreamFactory parent, RelativePath name, AsyncBinaryReader rdr, long startingPosition, long length)
|
||||
{
|
||||
_name = name;
|
||||
_parent = parent;
|
||||
_rdr = rdr;
|
||||
_start = startingPosition;
|
||||
_length = length;
|
||||
}
|
||||
|
||||
public DateTime LastModifiedUtc => _parent.LastModifiedUtc;
|
||||
public IPath Name => _name;
|
||||
public async ValueTask<Stream> GetStream()
|
||||
{
|
||||
_rdr.Position = _start;
|
||||
var data = await _rdr.ReadBytes((int) _length);
|
||||
return new MemoryStream(data);
|
||||
}
|
||||
|
||||
public bool CanMove { get; set; } = true;
|
||||
public async ValueTask Move(AbsolutePath newPath, CancellationToken token)
|
||||
{
|
||||
await using var output = newPath.Open(FileMode.Create, FileAccess.Read, FileShare.Read);
|
||||
_rdr.Position = _start;
|
||||
await _rdr.BaseStream.CopyToLimitAsync(output, (int)_length, token);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Dictionary<RelativePath, T>> GatheringExtractWithOMOD<T>
|
||||
(Stream archive, Predicate<RelativePath> shouldExtract, Func<RelativePath, IExtractedFile, ValueTask<T>> mapfn,
|
||||
CancellationToken token)
|
||||
|
Loading…
Reference in New Issue
Block a user