From 5e1e0ec527db34d5c9fdad134318fa818337d288 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Thu, 10 Feb 2022 16:57:44 -0700 Subject: [PATCH 1/7] Can login to Bethesda.Net and get CC data --- Wabbajack.App.Blazor/App.xaml.cs | 1 + .../Browser/ViewModels/BethesdaNetLogin.cs | 75 +++++++++ Wabbajack.App.Blazor/Pages/Settings.razor | 5 + Wabbajack.CLI/Program.cs | 1 + .../Verbs/ListCreationClubContent.cs | 53 ++++++ .../Logins/BethesdaNet/BeamLogin.cs | 12 ++ .../Logins/BethesdaNet/BeamLoginResponse.cs | 33 ++++ .../Logins/BethesdaNet/CDPAuthPost.cs | 9 ++ .../Logins/BethesdaNet/CDPAuthResponse.cs | 19 +++ Wabbajack.DTOs/Logins/BethesdaNetLogin.cs | 10 ++ Wabbajack.Networking.BethesdaNet/Client.cs | 136 ++++++++++++++++ .../DTOs/ListSubscribeResponse.cs | 151 ++++++++++++++++++ .../ServiceExtensions.cs | 11 ++ .../ServiceExtensions.cs | 3 + .../BethesdaNetTokenProvider.cs | 13 ++ .../Wabbajack.Services.OSIntegrated.csproj | 1 + Wabbajack.sln | 7 + 17 files changed, 540 insertions(+) create mode 100644 Wabbajack.App.Blazor/Browser/ViewModels/BethesdaNetLogin.cs create mode 100644 Wabbajack.CLI/Verbs/ListCreationClubContent.cs create mode 100644 Wabbajack.DTOs/Logins/BethesdaNet/BeamLogin.cs create mode 100644 Wabbajack.DTOs/Logins/BethesdaNet/BeamLoginResponse.cs create mode 100644 Wabbajack.DTOs/Logins/BethesdaNet/CDPAuthPost.cs create mode 100644 Wabbajack.DTOs/Logins/BethesdaNet/CDPAuthResponse.cs create mode 100644 Wabbajack.DTOs/Logins/BethesdaNetLogin.cs create mode 100644 Wabbajack.Networking.BethesdaNet/Client.cs create mode 100644 Wabbajack.Networking.BethesdaNet/DTOs/ListSubscribeResponse.cs create mode 100644 Wabbajack.Networking.BethesdaNet/ServiceExtensions.cs create mode 100644 Wabbajack.Services.OSIntegrated/TokenProviders/BethesdaNetTokenProvider.cs diff --git a/Wabbajack.App.Blazor/App.xaml.cs b/Wabbajack.App.Blazor/App.xaml.cs index 7ed412bb..0e64922f 100644 --- a/Wabbajack.App.Blazor/App.xaml.cs +++ b/Wabbajack.App.Blazor/App.xaml.cs @@ -76,6 +76,7 @@ public partial class App services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddSingleton(); services.AddSingleton(); return services; diff --git a/Wabbajack.App.Blazor/Browser/ViewModels/BethesdaNetLogin.cs b/Wabbajack.App.Blazor/Browser/ViewModels/BethesdaNetLogin.cs new file mode 100644 index 00000000..de3c5e54 --- /dev/null +++ b/Wabbajack.App.Blazor/Browser/ViewModels/BethesdaNetLogin.cs @@ -0,0 +1,75 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Web.WebView2.Core; +using Wabbajack.Common; +using Wabbajack.Networking.BethesdaNet; +using Wabbajack.Services.OSIntegrated; + +namespace Wabbajack.App.Blazor.Browser.ViewModels; + +public class BethesdaNetLogin : BrowserTabViewModel +{ + private readonly EncryptedJsonTokenProvider _tokenProvider; + private readonly Client _client; + + public BethesdaNetLogin(EncryptedJsonTokenProvider tokenProvider, Wabbajack.Networking.BethesdaNet.Client client) + { + _tokenProvider = tokenProvider; + _client = client; + HeaderText = "Bethesda Net Login"; + } + protected override async Task Run(CancellationToken token) + { + await WaitForReady(); + Instructions = "Please log in to Bethesda.net"; + + string requestJson = ""; + + Browser.Browser.CoreWebView2.AddWebResourceRequestedFilter("*", CoreWebView2WebResourceContext.All); + Browser.Browser.CoreWebView2.WebResourceRequested += (sender, args) => + { + if (args.Request.Uri == "https://api.bethesda.net/dwemer/attunement/v1/authenticate" && args.Request.Method == "POST") + { + requestJson = args.Request.Content.ReadAllText(); + args.Request.Content = new MemoryStream(Encoding.UTF8.GetBytes(requestJson)); + } + }; + + await NavigateTo(new Uri("https://bethesda.net/en/dashboard")); + + while (true) + { + var code = await GetCookies("bethesda.net", token); + if (code.Any(c => c.Name == "bnet-session")) break; + + } + + var data = JsonSerializer.Deserialize(requestJson); + + var provider = new Wabbajack.DTOs.Logins.BethesdaNetLoginState() + { + Username = data.UserName, + Password = data.Password + }; + await _tokenProvider.SetToken(provider); + await _client.Login(token); + + await Task.Delay(10); + + } + + public class LoginRequest + { + [JsonPropertyName("username")] + public string UserName { get; set; } + [JsonPropertyName("password")] + public string Password { get; set; } + } + +} diff --git a/Wabbajack.App.Blazor/Pages/Settings.razor b/Wabbajack.App.Blazor/Pages/Settings.razor index 8fc742d5..fe5ad736 100644 --- a/Wabbajack.App.Blazor/Pages/Settings.razor +++ b/Wabbajack.App.Blazor/Pages/Settings.razor @@ -13,6 +13,7 @@ + @@ -32,4 +33,8 @@ { MessageBus.Current.SendMessage(new OpenBrowserTab(_serviceProvider.GetRequiredService())); } + public void LoginToBethesdaNet() + { + MessageBus.Current.SendMessage(new OpenBrowserTab(_serviceProvider.GetRequiredService())); + } } diff --git a/Wabbajack.CLI/Program.cs b/Wabbajack.CLI/Program.cs index d0e83053..7d59a672 100644 --- a/Wabbajack.CLI/Program.cs +++ b/Wabbajack.CLI/Program.cs @@ -68,6 +68,7 @@ internal class Program services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); }).Build(); diff --git a/Wabbajack.CLI/Verbs/ListCreationClubContent.cs b/Wabbajack.CLI/Verbs/ListCreationClubContent.cs new file mode 100644 index 00000000..4d61c40f --- /dev/null +++ b/Wabbajack.CLI/Verbs/ListCreationClubContent.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Invocation; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Wabbajack.Common; +using Wabbajack.DTOs; +using Wabbajack.Networking.BethesdaNet; +using Wabbajack.Paths; + +namespace Wabbajack.CLI.Verbs; + +public class ListCreationClubContent : IVerb +{ + private readonly ILogger _logger; + private readonly Client _client; + + public ListCreationClubContent(ILogger logger, Client wjClient) + { + _logger = logger; + _client = wjClient; + } + public Command MakeCommand() + { + var command = new Command("list-creation-club-content"); + command.Description = "Lists all known creation club content"; + command.Handler = CommandHandler.Create(Run); + return command; + } + + public async Task Run(CancellationToken token) + { + _logger.LogInformation("Getting list of content"); + var skyrimContent = (await _client.ListContent(Game.SkyrimSpecialEdition, token)) + .Select(f => (Game.SkyrimSpecialEdition, f)); + var falloutContent = (await _client.ListContent(Game.Fallout4, token)) + .Select(f => (Game.Fallout4, f)); + + foreach (var (game, content) in skyrimContent.Concat(falloutContent).OrderBy(f => f.f.Name)) + { + Console.WriteLine($"Game: {game}"); + Console.WriteLine($"Name: {content.Name}"); + Console.WriteLine($"Download Size: {content.DepotSize.ToFileSizeString()}"); + Console.WriteLine($"Uri: bethesda://{game}/{content.ContentId}"); + Console.WriteLine("-----------------------------------"); + } + + return 0; + } +} \ No newline at end of file diff --git a/Wabbajack.DTOs/Logins/BethesdaNet/BeamLogin.cs b/Wabbajack.DTOs/Logins/BethesdaNet/BeamLogin.cs new file mode 100644 index 00000000..07aa97c6 --- /dev/null +++ b/Wabbajack.DTOs/Logins/BethesdaNet/BeamLogin.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace Wabbajack.DTOs.Logins.BethesdaNet; + +public class BeamLogin +{ + [JsonPropertyName("password")] + public string Password { get; set; } + + [JsonPropertyName("language")] + public string Language { get; set; } = "en"; +} \ No newline at end of file diff --git a/Wabbajack.DTOs/Logins/BethesdaNet/BeamLoginResponse.cs b/Wabbajack.DTOs/Logins/BethesdaNet/BeamLoginResponse.cs new file mode 100644 index 00000000..2ee273b3 --- /dev/null +++ b/Wabbajack.DTOs/Logins/BethesdaNet/BeamLoginResponse.cs @@ -0,0 +1,33 @@ +using System.Text.Json.Serialization; + +namespace Wabbajack.DTOs.Logins.BethesdaNet; + +public class BeamLoginResponse +{ + [JsonPropertyName("access_token")] + public string AccessToken { get; set; } + + [JsonPropertyName("account")] + public BeamAccount Account { get; set; } +} + +public class BeamAccount +{ + [JsonPropertyName("admin")] + public bool Admin { get; set; } + + [JsonPropertyName("admin_read_only")] + public bool AdminReadOnly { get; set; } + + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("mfa_enabled")] + public bool MFAEnabled { get; set; } + + [JsonPropertyName("sms_enabled_number")] + public object sms_enabled_number { get; set; } + + [JsonPropertyName("username")] + public string UserName { get; set; } +} \ No newline at end of file diff --git a/Wabbajack.DTOs/Logins/BethesdaNet/CDPAuthPost.cs b/Wabbajack.DTOs/Logins/BethesdaNet/CDPAuthPost.cs new file mode 100644 index 00000000..ae1fb596 --- /dev/null +++ b/Wabbajack.DTOs/Logins/BethesdaNet/CDPAuthPost.cs @@ -0,0 +1,9 @@ +using System.Text.Json.Serialization; + +namespace Wabbajack.DTOs.Logins.BethesdaNet; + +public class CDPAuthPost +{ + [JsonPropertyName("access_token")] + public string AccessToken { get; set; } +} \ No newline at end of file diff --git a/Wabbajack.DTOs/Logins/BethesdaNet/CDPAuthResponse.cs b/Wabbajack.DTOs/Logins/BethesdaNet/CDPAuthResponse.cs new file mode 100644 index 00000000..25abf449 --- /dev/null +++ b/Wabbajack.DTOs/Logins/BethesdaNet/CDPAuthResponse.cs @@ -0,0 +1,19 @@ +using System.Text.Json.Serialization; + +namespace Wabbajack.DTOs.Logins.BethesdaNet; + +public class CDPAuthResponse +{ + [JsonPropertyName("entitlement_ids")] + public int[] EntitlementIds { get; set; } + [JsonPropertyName("beam_client_api_key")] + public string BeamClientApiKey { get; set; } + [JsonPropertyName("session_id")] + public string SessionId { get; set; } + [JsonPropertyName("token")] + public string Token { get; set; } + [JsonPropertyName("beam_token")] + public string[] BeamToken { get; set; } + [JsonPropertyName("oauth_token")] + public string OAuthToken { get; set; } +} \ No newline at end of file diff --git a/Wabbajack.DTOs/Logins/BethesdaNetLogin.cs b/Wabbajack.DTOs/Logins/BethesdaNetLogin.cs new file mode 100644 index 00000000..4f17b842 --- /dev/null +++ b/Wabbajack.DTOs/Logins/BethesdaNetLogin.cs @@ -0,0 +1,10 @@ +using Wabbajack.DTOs.Logins.BethesdaNet; + +namespace Wabbajack.DTOs.Logins; + +public class BethesdaNetLoginState +{ + public string Username { get; set; } + public string Password { get; set; } + public BeamLoginResponse? BeamResponse { get; set; } +} \ No newline at end of file diff --git a/Wabbajack.Networking.BethesdaNet/Client.cs b/Wabbajack.Networking.BethesdaNet/Client.cs new file mode 100644 index 00000000..0eff7ccc --- /dev/null +++ b/Wabbajack.Networking.BethesdaNet/Client.cs @@ -0,0 +1,136 @@ +using System.Net.Http.Json; +using System.Text; +using System.Text.Encodings.Web; +using System.Text.Json; +using Microsoft.Extensions.Logging; +using Wabbajack.DTOs; +using Wabbajack.DTOs.Logins; +using Wabbajack.DTOs.Logins.BethesdaNet; +using Wabbajack.Networking.BethesdaNet.DTOs; +using Wabbajack.Networking.Http; +using Wabbajack.Networking.Http.Interfaces; + +namespace Wabbajack.Networking.BethesdaNet; + + + +public class Client +{ + private readonly ITokenProvider _tokenProvider; + private readonly ILogger _logger; + private readonly HttpClient _httpClient; + private readonly JsonSerializerOptions _jsonOptions; + private CDPAuthResponse? _entitlementData = null; + public const string AgentPlatform = "WINDOWS"; + public const string AgentProduct = "FALLOUT4"; + public const string AgentLanguage = "en"; + private const string ClientAPIKey = "FeBqmQA8wxd94RtqymKwzmtcQcaA5KHOpDkQBSegx4WePeluZTCIm5scoeKTbmGl"; + private const string ClientId = "95578d65-45bf-4a03-b7f7-a43d29b9467d"; + private const string AgentVersion = $"{AgentProduct};;BDK;1.0013.99999.1;{AgentPlatform}"; + private string FingerprintKey { get; set; } + + + public Client(ILogger logger, HttpClient client, ITokenProvider tokenProvider) + { + _tokenProvider = tokenProvider; + _logger = logger; + _httpClient = client; + _jsonOptions = new JsonSerializerOptions + { + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + }; + SetFingerprint(); + } + + public async Task Login(CancellationToken token) + { + var loginData = await _tokenProvider.Get(); + var msg = MakeMessage(HttpMethod.Post, new Uri($"https://api.bethesda.net/beam/accounts/login/{loginData!.Username}")); + msg.Headers.Add("X-Client-API-key", ClientAPIKey); + msg.Headers.Add("x-src-fp", FingerprintKey); + msg.Headers.Add("X-Platform", AgentPlatform); + msg.Content = new StringContent(JsonSerializer.Serialize(new BeamLogin + { + Password = loginData!.Password, + Language = AgentLanguage + }, _jsonOptions), Encoding.UTF8, "application/json"); + + var result = await _httpClient.SendAsync(msg, token); + if (!result.IsSuccessStatusCode) + throw new HttpException(result); + + var response = await result.Content.ReadFromJsonAsync(_jsonOptions, token); + loginData.BeamResponse = response; + + await _tokenProvider.SetToken(loginData); + } + + public async Task CDPAuth(CancellationToken token) + { + var state = await _tokenProvider.Get(); + if (string.IsNullOrEmpty(state.BeamResponse?.AccessToken)) + throw new Exception("Can't get CDPAuth before Bethesda Net login"); + + var msg = MakeMessage(HttpMethod.Post, new Uri("https://api.bethesda.net/cdp-user/auth")); + msg.Headers.Add("x-src-fp", FingerprintKey); + msg.Headers.Add("x-cdp-app", "UGC SDK"); + msg.Headers.Add("x-cdp-app-ver", "0.9.11314/debug"); + msg.Headers.Add("x-cdp-lib-ver", "0.9.11314/debug"); + msg.Headers.Add("x-cdp-platform", "Win/32"); + msg.Content = new StringContent(JsonSerializer.Serialize(new CDPAuthPost() + {AccessToken = state.BeamResponse.AccessToken}), Encoding.UTF8, "application/json"); + + var request = await _httpClient.SendAsync(msg, token); + if (!request.IsSuccessStatusCode) + throw new HttpException(request); + + _entitlementData = await request.Content.ReadFromJsonAsync(_jsonOptions, token); + + } + + private HttpRequestMessage MakeMessage(HttpMethod method, Uri uri) + { + var msg = new HttpRequestMessage(method, uri); + msg.Headers.Add("User-Agent", "bnet"); + msg.Headers.Add("Accept", "application/json"); + msg.Headers.Add("X-BNET-Agent", AgentVersion); + return msg; + } + + private void SetFingerprint() + { + var keyBytes = new byte[20]; + using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider()) + rng.GetBytes(keyBytes); + + FingerprintKey = string.Concat(Array.ConvertAll(keyBytes, x => x.ToString("X2"))); + } + + public async Task> ListContent(Game game, CancellationToken token) + { + var gameKey = game switch + { + Game.SkyrimSpecialEdition => "SKYRIM", + Game.Fallout4 => "FALLOUT4", + _ => throw new InvalidOperationException("Only Skyrim and Fallout 4 are supported for Bethesda Net content") + }; + + await EnsureAuthed(token); + var authData = await _tokenProvider.Get(); + var msg = MakeMessage(HttpMethod.Get, + new Uri( + $"https://api.bethesda.net/mods/ugc-workshop/list?page=1;sort=alpha;order=asc;number_results=500;platform=WINDOWS;product={gameKey};cc_mod=true")); + msg.Headers.Add("X-Access-Token", authData!.BeamResponse!.AccessToken); + var request = await _httpClient.SendAsync(msg, token); + if (!request.IsSuccessStatusCode) + throw new HttpException(request); + var response = await request.Content.ReadFromJsonAsync(_jsonOptions, token); + return response!.Platform.Response.Content; + } + + private async Task EnsureAuthed(CancellationToken token) + { + if (_entitlementData == null) + await CDPAuth(token); + } +} \ No newline at end of file diff --git a/Wabbajack.Networking.BethesdaNet/DTOs/ListSubscribeResponse.cs b/Wabbajack.Networking.BethesdaNet/DTOs/ListSubscribeResponse.cs new file mode 100644 index 00000000..9b67d2f5 --- /dev/null +++ b/Wabbajack.Networking.BethesdaNet/DTOs/ListSubscribeResponse.cs @@ -0,0 +1,151 @@ +using System.Text.Json.Serialization; + +namespace Wabbajack.Networking.BethesdaNet.DTOs; + +public class Price +{ + [JsonPropertyName("currency_id")] + public int CurrencyId { get; set; } + + [JsonPropertyName("price_id")] + public int PriceId { get; set; } + + [JsonPropertyName("sale")] + public bool Sale { get; set; } + + [JsonPropertyName("currency_name")] + public string CurrencyName { get; set; } + + [JsonPropertyName("currency_type")] + public string CurrencyType { get; set; } + + [JsonPropertyName("amount")] + public int Amount { get; set; } + + [JsonPropertyName("original_amount")] + public int OriginalAmount { get; set; } +} + +public class Content +{ + [JsonPropertyName("rating")] + public double Rating { get; set; } + + [JsonPropertyName("version")] + public int Version { get; set; } + + [JsonPropertyName("depot_size")] + public int DepotSize { get; set; } + + [JsonPropertyName("is_subscribed")] + public bool IsSubscribed { get; set; } + + [JsonPropertyName("preview_file_size")] + public int PreviewFileSize { get; set; } + + [JsonPropertyName("preview_file_url")] + public string PreviewFileUrl { get; set; } + + [JsonPropertyName("is_following")] + public bool IsFollowing { get; set; } + + [JsonPropertyName("wip")] + public bool Wip { get; set; } + + [JsonPropertyName("is_published")] + public bool IsPublished { get; set; } + + [JsonPropertyName("user_rating")] + public int UserRating { get; set; } + + [JsonPropertyName("platform")] + public List Platform { get; set; } + + [JsonPropertyName("state")] + public int State { get; set; } + + [JsonPropertyName("rating_count")] + public int RatingCount { get; set; } + + [JsonPropertyName("cdp_branch_id")] + public int CdpBranchId { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("username")] + public string Username { get; set; } + + [JsonPropertyName("product")] + public string Product { get; set; } + + [JsonPropertyName("updated")] + public string Updated { get; set; } + + [JsonPropertyName("cc_mod")] + public bool CcMod { get; set; } + + [JsonPropertyName("bundle")] + public bool Bundle { get; set; } + + [JsonPropertyName("prices")] + public List Prices { get; set; } + + [JsonPropertyName("is_public")] + public bool IsPublic { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("catalog_item_id")] + public int CatalogItemId { get; set; } + + [JsonPropertyName("is_auto_moderated")] + public bool IsAutoModerated { get; set; } + + [JsonPropertyName("content_id")] + public string ContentId { get; set; } + + [JsonPropertyName("cdp_product_id")] + public int CdpProductId { get; set; } +} + +public class Response +{ + [JsonPropertyName("product")] + public List Product { get; set; } + + [JsonPropertyName("total_results_count")] + public int TotalResultsCount { get; set; } + + [JsonPropertyName("content")] + public List Content { get; set; } + + [JsonPropertyName("platform")] + public List Platform { get; set; } + + [JsonPropertyName("page_results_count")] + public int PageResultsCount { get; set; } + + [JsonPropertyName("page")] + public int Page { get; set; } +} + +public class Platform +{ + [JsonPropertyName("message")] + public string Message { get; set; } + + [JsonPropertyName("code")] + public int Code { get; set; } + + [JsonPropertyName("response")] + public Response Response { get; set; } +} + +public class ListSubscribeResponse +{ + [JsonPropertyName("platform")] + public Platform Platform { get; set; } +} + diff --git a/Wabbajack.Networking.BethesdaNet/ServiceExtensions.cs b/Wabbajack.Networking.BethesdaNet/ServiceExtensions.cs new file mode 100644 index 00000000..087792eb --- /dev/null +++ b/Wabbajack.Networking.BethesdaNet/ServiceExtensions.cs @@ -0,0 +1,11 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Wabbajack.Networking.BethesdaNet; + +public static class ServiceExtensions +{ + public static void AddBethesdaNet(this IServiceCollection services) + { + services.AddSingleton(); + } +} \ No newline at end of file diff --git a/Wabbajack.Services.OSIntegrated/ServiceExtensions.cs b/Wabbajack.Services.OSIntegrated/ServiceExtensions.cs index 3f344507..896fc6a1 100644 --- a/Wabbajack.Services.OSIntegrated/ServiceExtensions.cs +++ b/Wabbajack.Services.OSIntegrated/ServiceExtensions.cs @@ -11,6 +11,7 @@ using Wabbajack.Downloaders.GameFile; using Wabbajack.DTOs; using Wabbajack.DTOs.Logins; using Wabbajack.Installer; +using Wabbajack.Networking.BethesdaNet; using Wabbajack.Networking.Discord; using Wabbajack.Networking.Http; using Wabbajack.Networking.Http.Interfaces; @@ -111,9 +112,11 @@ public static class ServiceExtensions service.AddSingleton(); service.AddSingleton(); + service.AddBethesdaNet(); // Token Providers service.AddAllSingleton, EncryptedJsonTokenProvider, NexusApiTokenProvider>(); + service.AddAllSingleton, EncryptedJsonTokenProvider, BethesdaNetTokenProvider>(); service .AddAllSingleton, EncryptedJsonTokenProvider, LoversLabTokenProvider>(); diff --git a/Wabbajack.Services.OSIntegrated/TokenProviders/BethesdaNetTokenProvider.cs b/Wabbajack.Services.OSIntegrated/TokenProviders/BethesdaNetTokenProvider.cs new file mode 100644 index 00000000..d4acc198 --- /dev/null +++ b/Wabbajack.Services.OSIntegrated/TokenProviders/BethesdaNetTokenProvider.cs @@ -0,0 +1,13 @@ +using Microsoft.Extensions.Logging; +using Wabbajack.DTOs.JsonConverters; +using Wabbajack.DTOs.Logins; + +namespace Wabbajack.Services.OSIntegrated.TokenProviders; + +public class BethesdaNetTokenProvider : EncryptedJsonTokenProvider +{ + public BethesdaNetTokenProvider(ILogger logger, DTOSerializer dtos) : base(logger, dtos, + "bethesda-net") + { + } +} \ No newline at end of file diff --git a/Wabbajack.Services.OSIntegrated/Wabbajack.Services.OSIntegrated.csproj b/Wabbajack.Services.OSIntegrated/Wabbajack.Services.OSIntegrated.csproj index e263452d..b05a7d48 100644 --- a/Wabbajack.Services.OSIntegrated/Wabbajack.Services.OSIntegrated.csproj +++ b/Wabbajack.Services.OSIntegrated/Wabbajack.Services.OSIntegrated.csproj @@ -20,6 +20,7 @@ + diff --git a/Wabbajack.sln b/Wabbajack.sln index c91fb041..c07b9be4 100644 --- a/Wabbajack.sln +++ b/Wabbajack.sln @@ -133,6 +133,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.IO.Async", "Wabba EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Compression.Zip.Test", "Wabbajack.Compression.Zip.Test\Wabbajack.Compression.Zip.Test.csproj", "{6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Networking.BethesdaNet", "Wabbajack.Networking.BethesdaNet\Wabbajack.Networking.BethesdaNet.csproj", "{A3813D73-9A8E-4CE7-861A-C59043DFFC14}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -363,6 +365,10 @@ Global {6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C}.Debug|Any CPU.Build.0 = Debug|Any CPU {6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C}.Release|Any CPU.ActiveCfg = Release|Any CPU {6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C}.Release|Any CPU.Build.0 = Release|Any CPU + {A3813D73-9A8E-4CE7-861A-C59043DFFC14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3813D73-9A8E-4CE7-861A-C59043DFFC14}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3813D73-9A8E-4CE7-861A-C59043DFFC14}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3813D73-9A8E-4CE7-861A-C59043DFFC14}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -408,6 +414,7 @@ Global {10165025-D30B-44B7-A764-50E15603AE56} = {F677890D-5109-43BC-97C7-C4CD47C8EE0C} {64AD7E26-5643-4969-A61C-E0A90FA25FCB} = {F677890D-5109-43BC-97C7-C4CD47C8EE0C} {6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C} = {F677890D-5109-43BC-97C7-C4CD47C8EE0C} + {A3813D73-9A8E-4CE7-861A-C59043DFFC14} = {F01F8595-5FD7-4506-8469-F4A5522DACC1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0AA30275-0F38-4A7D-B645-F5505178DDE8} From 9288d05c2b302998ec33c94aaf9314b7d4793bf3 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Thu, 10 Feb 2022 20:38:27 -0700 Subject: [PATCH 2/7] Fix the schema --- .../Verbs/ListCreationClubContent.cs | 2 +- .../Wabbajack.Networking.BethesdaNet.csproj | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 Wabbajack.Networking.BethesdaNet/Wabbajack.Networking.BethesdaNet.csproj diff --git a/Wabbajack.CLI/Verbs/ListCreationClubContent.cs b/Wabbajack.CLI/Verbs/ListCreationClubContent.cs index 4d61c40f..256d393e 100644 --- a/Wabbajack.CLI/Verbs/ListCreationClubContent.cs +++ b/Wabbajack.CLI/Verbs/ListCreationClubContent.cs @@ -44,7 +44,7 @@ public class ListCreationClubContent : IVerb Console.WriteLine($"Game: {game}"); Console.WriteLine($"Name: {content.Name}"); Console.WriteLine($"Download Size: {content.DepotSize.ToFileSizeString()}"); - Console.WriteLine($"Uri: bethesda://{game}/{content.ContentId}"); + Console.WriteLine($"Uri: bethesda://{game}/cc/{content.ContentId}"); Console.WriteLine("-----------------------------------"); } diff --git a/Wabbajack.Networking.BethesdaNet/Wabbajack.Networking.BethesdaNet.csproj b/Wabbajack.Networking.BethesdaNet/Wabbajack.Networking.BethesdaNet.csproj new file mode 100644 index 00000000..e4645b99 --- /dev/null +++ b/Wabbajack.Networking.BethesdaNet/Wabbajack.Networking.BethesdaNet.csproj @@ -0,0 +1,21 @@ + + + + net6.0 + enable + enable + + + + + ..\..\..\Program Files\dotnet\shared\Microsoft.AspNetCore.App\6.0.1\Microsoft.Extensions.Logging.Abstractions.dll + + + + + + + + + + From 442fd646feb91acff50ad4dc0b3fa000e4263ae7 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Thu, 10 Feb 2022 22:05:51 -0700 Subject: [PATCH 3/7] Implement bethesda downloader, and depot handling --- .../Verbs/ListCreationClubContent.cs | 15 ++- Wabbajack.CLI/Wabbajack.CLI.csproj | 1 + Wabbajack.DTOs/DownloadStates/Bethesda.cs | 16 +++ .../BethesdaDownloader.cs | 115 ++++++++++++++++++ .../ServiceExtensions.cs | 13 ++ .../Wabbajack.Downloaders.Bethesda.csproj | 14 +++ .../DownloaderTests.cs | 28 +++++ .../ServiceExtensions.cs | 2 + .../Wabbajack.Downloaders.Dispatcher.csproj | 1 + .../Wabbajack.Downloaders.Http.csproj | 1 + Wabbajack.Networking.BethesdaNet/Client.cs | 42 ++++++- .../DTOs/Depot.cs | 66 ++++++++++ .../DTOs/ListSubscribeResponse.cs | 4 +- Wabbajack.sln | 7 ++ 14 files changed, 315 insertions(+), 10 deletions(-) create mode 100644 Wabbajack.DTOs/DownloadStates/Bethesda.cs create mode 100644 Wabbajack.Downloaders.Bethesda/BethesdaDownloader.cs create mode 100644 Wabbajack.Downloaders.Bethesda/ServiceExtensions.cs create mode 100644 Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj create mode 100644 Wabbajack.Networking.BethesdaNet/DTOs/Depot.cs diff --git a/Wabbajack.CLI/Verbs/ListCreationClubContent.cs b/Wabbajack.CLI/Verbs/ListCreationClubContent.cs index 256d393e..e6a78079 100644 --- a/Wabbajack.CLI/Verbs/ListCreationClubContent.cs +++ b/Wabbajack.CLI/Verbs/ListCreationClubContent.cs @@ -7,7 +7,10 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Wabbajack.Common; +using Wabbajack.Downloaders.Bethesda; using Wabbajack.DTOs; +using Wabbajack.DTOs.DownloadStates; +using Wabbajack.DTOs.Logins.BethesdaNet; using Wabbajack.Networking.BethesdaNet; using Wabbajack.Paths; @@ -17,11 +20,13 @@ public class ListCreationClubContent : IVerb { private readonly ILogger _logger; private readonly Client _client; + private readonly BethesdaDownloader _downloader; - public ListCreationClubContent(ILogger logger, Client wjClient) + public ListCreationClubContent(ILogger logger, Client wjClient, Wabbajack.Downloaders.Bethesda.BethesdaDownloader downloader) { _logger = logger; _client = wjClient; + _downloader = downloader; } public Command MakeCommand() { @@ -39,12 +44,12 @@ public class ListCreationClubContent : IVerb var falloutContent = (await _client.ListContent(Game.Fallout4, token)) .Select(f => (Game.Fallout4, f)); - foreach (var (game, content) in skyrimContent.Concat(falloutContent).OrderBy(f => f.f.Name)) + foreach (var (game, content) in skyrimContent.Concat(falloutContent).OrderBy(f => f.f.Content.Name)) { Console.WriteLine($"Game: {game}"); - Console.WriteLine($"Name: {content.Name}"); - Console.WriteLine($"Download Size: {content.DepotSize.ToFileSizeString()}"); - Console.WriteLine($"Uri: bethesda://{game}/cc/{content.ContentId}"); + Console.WriteLine($"Name: {content.Content.Name}"); + Console.WriteLine($"Download Size: {content.Content.DepotSize.ToFileSizeString()}"); + Console.WriteLine($"Uri: {_downloader.UnParse(content.State)}"); Console.WriteLine("-----------------------------------"); } diff --git a/Wabbajack.CLI/Wabbajack.CLI.csproj b/Wabbajack.CLI/Wabbajack.CLI.csproj index a536036d..19bc0a15 100644 --- a/Wabbajack.CLI/Wabbajack.CLI.csproj +++ b/Wabbajack.CLI/Wabbajack.CLI.csproj @@ -22,6 +22,7 @@ + diff --git a/Wabbajack.DTOs/DownloadStates/Bethesda.cs b/Wabbajack.DTOs/DownloadStates/Bethesda.cs new file mode 100644 index 00000000..792baabd --- /dev/null +++ b/Wabbajack.DTOs/DownloadStates/Bethesda.cs @@ -0,0 +1,16 @@ +using Wabbajack.DTOs.JsonConverters; + +namespace Wabbajack.DTOs.DownloadStates; + +[JsonName("Bethesda")] +public class Bethesda : ADownloadState +{ + public override string TypeName { get; } = "Bethesda"; + public override object[] PrimaryKey => new object[] {Game, IsCCMod, ProductId, BranchID, ContentId}; + public Game Game { get; set; } + public bool IsCCMod { get; set; } + public string ContentId { get; set; } + public long ProductId { get; set; } + public long BranchID { get; set; } + public string Name { get; set; } +} \ No newline at end of file diff --git a/Wabbajack.Downloaders.Bethesda/BethesdaDownloader.cs b/Wabbajack.Downloaders.Bethesda/BethesdaDownloader.cs new file mode 100644 index 00000000..b482995e --- /dev/null +++ b/Wabbajack.Downloaders.Bethesda/BethesdaDownloader.cs @@ -0,0 +1,115 @@ +using Microsoft.Extensions.Logging; +using Wabbajack.Downloaders.Interfaces; +using Wabbajack.DTOs; +using Wabbajack.DTOs.DownloadStates; +using Wabbajack.DTOs.Validation; +using Wabbajack.Hashing.xxHash64; +using Wabbajack.Networking.BethesdaNet; +using Wabbajack.Paths; +using Wabbajack.Paths.IO; +using Wabbajack.RateLimiter; + +namespace Wabbajack.Downloaders.Bethesda; + +public class BethesdaDownloader : ADownloader, IUrlDownloader, IChunkedSeekableStreamDownloader +{ + private readonly Client _client; + private readonly IResource _limiter; + private readonly HttpClient _httpClient; + private readonly ILogger _logger; + + public BethesdaDownloader(ILogger logger, Client client, HttpClient httpClient, IResource limiter) + { + _logger = logger; + _client = client; + _limiter = limiter; + _httpClient = httpClient; + } + + + public override async Task Download(Archive archive, DTOs.DownloadStates.Bethesda state, AbsolutePath destination, IJob job, CancellationToken token) + { + + var depot = await _client.GetDepots(state, token); + + return default; + } + + public override async Task Prepare() + { + await _client.CDPAuth(CancellationToken.None); + return true; + } + + public override bool IsAllowed(ServerAllowList allowList, IDownloadState state) + { + return true; + } + + public override IDownloadState? Resolve(IReadOnlyDictionary iniData) + { + if (iniData.ContainsKey("directURL") && Uri.TryCreate(iniData["directURL"], UriKind.Absolute, out var uri)) + { + return Parse(uri); + } + return null; + } + + public override Priority Priority => Priority.Normal; + + public override async Task Verify(Archive archive, DTOs.DownloadStates.Bethesda state, IJob job, CancellationToken token) + { + await _client.GetDepots(state, token); + throw new NotImplementedException(); + } + + public override IEnumerable MetaIni(Archive a, DTOs.DownloadStates.Bethesda state) + { + return new[] {$"directURL={UnParse(state)}"}; + } + + public IDownloadState? Parse(Uri uri) + { + if (uri.Scheme != "bethesda") return null; + var path = uri.PathAndQuery.Split("/", StringSplitOptions.RemoveEmptyEntries); + if (path.Length != 4) return null; + var game = GameRegistry.TryGetByFuzzyName(uri.Host); + if (game == null) return null; + + if (!long.TryParse(path[1], out var productId)) return null; + if (!long.TryParse(path[2], out var branchId)) return null; + + bool isCCMod = false; + switch (path[0]) + { + case "cc": + isCCMod = true; + break; + case "mod": + isCCMod = false; + break; + default: + return null; + } + + return new DTOs.DownloadStates.Bethesda + { + Game = game.Game, + IsCCMod = isCCMod, + ProductId = productId, + BranchID = branchId, + ContentId = path[3] + }; + } + + public Uri UnParse(IDownloadState state) + { + var cstate = (DTOs.DownloadStates.Bethesda) state; + return new Uri($"bethesda://{cstate.Game}/{(cstate.IsCCMod ? "cc" : "mod")}/{cstate.ProductId}/{cstate.BranchID}/{cstate.ContentId}"); + } + + public ValueTask GetChunkedSeekableStream(Archive archive, CancellationToken token) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/Wabbajack.Downloaders.Bethesda/ServiceExtensions.cs b/Wabbajack.Downloaders.Bethesda/ServiceExtensions.cs new file mode 100644 index 00000000..444edfa1 --- /dev/null +++ b/Wabbajack.Downloaders.Bethesda/ServiceExtensions.cs @@ -0,0 +1,13 @@ +using Microsoft.Extensions.DependencyInjection; +using Wabbajack.Downloaders.Interfaces; +using Wabbajack.DTOs; + +namespace Wabbajack.Downloaders.Bethesda; + +public static class ServiceExtensions +{ + public static IServiceCollection AddBethesdaDownloader(this IServiceCollection services) + { + return services.AddAllSingleton, IUrlDownloader, BethesdaDownloader>(); + } +} \ No newline at end of file diff --git a/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj b/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj new file mode 100644 index 00000000..a3799d4d --- /dev/null +++ b/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj @@ -0,0 +1,14 @@ + + + + net6.0 + enable + enable + + + + + + + + diff --git a/Wabbajack.Downloaders.Dispatcher.Test/DownloaderTests.cs b/Wabbajack.Downloaders.Dispatcher.Test/DownloaderTests.cs index 463056b7..7964ebe7 100644 --- a/Wabbajack.Downloaders.Dispatcher.Test/DownloaderTests.cs +++ b/Wabbajack.Downloaders.Dispatcher.Test/DownloaderTests.cs @@ -180,6 +180,34 @@ public class DownloaderTests "https://authored-files.wabbajack.org/Tonal%20Architect_WJ_TEST_FILES.zip_9cb97a01-3354-4077-9e4a-7e808d47794fFFOOO") } } + }, + // Bethesda + new object[] + { + new Archive + { + Hash = default, + State = new DTOs.DownloadStates.Bethesda + { + Game = Game.SkyrimSpecialEdition, + IsCCMod = true, + ProductId = 4, + BranchID = 90898, + ContentId = "4059054" + } + }, + new Archive + { + Hash = default, + State = new DTOs.DownloadStates.Bethesda + { + Game = Game.SkyrimSpecialEdition, + IsCCMod = true, + ProductId = 6, + BranchID = 9898, + ContentId = "059054" + } + }, } }; diff --git a/Wabbajack.Downloaders.Dispatcher/ServiceExtensions.cs b/Wabbajack.Downloaders.Dispatcher/ServiceExtensions.cs index a7329e4f..67acd7d9 100644 --- a/Wabbajack.Downloaders.Dispatcher/ServiceExtensions.cs +++ b/Wabbajack.Downloaders.Dispatcher/ServiceExtensions.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.DependencyInjection; +using Wabbajack.Downloaders.Bethesda; using Wabbajack.Downloaders.Http; using Wabbajack.Downloaders.IPS4OAuth2Downloader; using Wabbajack.Downloaders.MediaFire; @@ -24,6 +25,7 @@ public static class ServiceExtensions .AddIPS4OAuth2Downloaders() .AddWabbajackCDNDownloader() .AddGameFileDownloader() + .AddBethesdaDownloader() .AddWabbajackClient() .AddSingleton(); } diff --git a/Wabbajack.Downloaders.Dispatcher/Wabbajack.Downloaders.Dispatcher.csproj b/Wabbajack.Downloaders.Dispatcher/Wabbajack.Downloaders.Dispatcher.csproj index a65ca26d..95fa78f6 100644 --- a/Wabbajack.Downloaders.Dispatcher/Wabbajack.Downloaders.Dispatcher.csproj +++ b/Wabbajack.Downloaders.Dispatcher/Wabbajack.Downloaders.Dispatcher.csproj @@ -8,6 +8,7 @@ + diff --git a/Wabbajack.Downloaders.Http/Wabbajack.Downloaders.Http.csproj b/Wabbajack.Downloaders.Http/Wabbajack.Downloaders.Http.csproj index 9271a41e..f6810846 100644 --- a/Wabbajack.Downloaders.Http/Wabbajack.Downloaders.Http.csproj +++ b/Wabbajack.Downloaders.Http/Wabbajack.Downloaders.Http.csproj @@ -11,6 +11,7 @@ + diff --git a/Wabbajack.Networking.BethesdaNet/Client.cs b/Wabbajack.Networking.BethesdaNet/Client.cs index 0eff7ccc..ed90e823 100644 --- a/Wabbajack.Networking.BethesdaNet/Client.cs +++ b/Wabbajack.Networking.BethesdaNet/Client.cs @@ -2,8 +2,10 @@ using System.Net.Http.Json; using System.Text; using System.Text.Encodings.Web; using System.Text.Json; +using System.Text.Json.Serialization; using Microsoft.Extensions.Logging; using Wabbajack.DTOs; +using Wabbajack.DTOs.DownloadStates; using Wabbajack.DTOs.Logins; using Wabbajack.DTOs.Logins.BethesdaNet; using Wabbajack.Networking.BethesdaNet.DTOs; @@ -37,7 +39,8 @@ public class Client _httpClient = client; _jsonOptions = new JsonSerializerOptions { - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + NumberHandling = JsonNumberHandling.AllowReadingFromString, }; SetFingerprint(); } @@ -106,7 +109,7 @@ public class Client FingerprintKey = string.Concat(Array.ConvertAll(keyBytes, x => x.ToString("X2"))); } - public async Task> ListContent(Game game, CancellationToken token) + public async Task> ListContent(Game game, CancellationToken token) { var gameKey = game switch { @@ -125,7 +128,15 @@ public class Client if (!request.IsSuccessStatusCode) throw new HttpException(request); var response = await request.Content.ReadFromJsonAsync(_jsonOptions, token); - return response!.Platform.Response.Content; + return response!.Platform.Response.Content + .Select(c => (c, new Bethesda + { + Game = game, + ContentId = c.ContentId, + IsCCMod = c.CcMod, + ProductId = c.CdpProductId, + BranchID = c.CdpBranchId + })); } private async Task EnsureAuthed(CancellationToken token) @@ -133,4 +144,29 @@ public class Client if (_entitlementData == null) await CDPAuth(token); } + + private int ProductId(Game game) + { + if (game == Game.SkyrimSpecialEdition) return 4; + return 0; + } + + public async Task GetDepots(Bethesda state, CancellationToken token) + { + await EnsureAuthed(token); + var msg = MakeMessage(HttpMethod.Get, new Uri($"https://api.bethesda.net/cdp-user/projects/{state.ProductId}/branches/{state.BranchID}/depots/.json")); + msg.Headers.Add("x-src-fp", FingerprintKey); + msg.Headers.Add("x-cdp-app", "UGC SDK"); + msg.Headers.Add("x-cdp-app-ver", "0.9.11314/debug"); + msg.Headers.Add("x-cdp-lib-ver", "0.9.11314/debug"); + msg.Headers.Add("x-cdp-platform", "Win/32"); + msg.Headers.Add("Authorization", $"Token {_entitlementData!.Token}"); + + using var request = await _httpClient.SendAsync(msg, token); + if (!request.IsSuccessStatusCode) + throw new HttpException(request); + + var response = await request.Content.ReadFromJsonAsync>(_jsonOptions, token); + return response!.Values.First(); + } } \ No newline at end of file diff --git a/Wabbajack.Networking.BethesdaNet/DTOs/Depot.cs b/Wabbajack.Networking.BethesdaNet/DTOs/Depot.cs new file mode 100644 index 00000000..d97a6708 --- /dev/null +++ b/Wabbajack.Networking.BethesdaNet/DTOs/Depot.cs @@ -0,0 +1,66 @@ +using System.Text.Json.Serialization; + +namespace Wabbajack.Networking.BethesdaNet.DTOs; + +public class Depot +{ + [JsonPropertyName("id")] + public int Id { get; set; } + + [JsonPropertyName("properties_id")] + public int PropertiesId { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("build")] + public int Build { get; set; } + + [JsonPropertyName("bytes_per_chunk")] + public int BytesPerChunk { get; set; } + + [JsonPropertyName("size_on_disk")] + public int SizeOnDisk { get; set; } + + [JsonPropertyName("download_size")] + public int DownloadSize { get; set; } + + [JsonPropertyName("depot_type")] + public int DepotType { get; set; } + + [JsonPropertyName("deployment_order")] + public int DeploymentOrder { get; set; } + + [JsonPropertyName("compression_type")] + public int CompressionType { get; set; } + + [JsonPropertyName("encryption_type")] + public int EncryptionType { get; set; } + + [JsonPropertyName("language")] + public int Language { get; set; } + + [JsonPropertyName("region")] + public int Region { get; set; } + + [JsonPropertyName("default_region")] + public bool DefaultRegion { get; set; } + + [JsonPropertyName("default_language")] + public bool DefaultLanguage { get; set; } + + [JsonPropertyName("platform")] + public int Platform { get; set; } + + [JsonPropertyName("architecture")] + public int Architecture { get; set; } + + [JsonPropertyName("ex_info_A")] + public List ExInfoA { get; set; } + + [JsonPropertyName("ex_info_B")] + public List ExInfoB { get; set; } + + [JsonPropertyName("is_dlc")] + public bool IsDlc { get; set; } +} \ No newline at end of file diff --git a/Wabbajack.Networking.BethesdaNet/DTOs/ListSubscribeResponse.cs b/Wabbajack.Networking.BethesdaNet/DTOs/ListSubscribeResponse.cs index 9b67d2f5..2f9e432c 100644 --- a/Wabbajack.Networking.BethesdaNet/DTOs/ListSubscribeResponse.cs +++ b/Wabbajack.Networking.BethesdaNet/DTOs/ListSubscribeResponse.cs @@ -68,7 +68,7 @@ public class Content public int RatingCount { get; set; } [JsonPropertyName("cdp_branch_id")] - public int CdpBranchId { get; set; } + public long CdpBranchId { get; set; } [JsonPropertyName("type")] public string Type { get; set; } @@ -107,7 +107,7 @@ public class Content public string ContentId { get; set; } [JsonPropertyName("cdp_product_id")] - public int CdpProductId { get; set; } + public long CdpProductId { get; set; } } public class Response diff --git a/Wabbajack.sln b/Wabbajack.sln index c07b9be4..d2207d28 100644 --- a/Wabbajack.sln +++ b/Wabbajack.sln @@ -135,6 +135,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Compression.Zip.T EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Networking.BethesdaNet", "Wabbajack.Networking.BethesdaNet\Wabbajack.Networking.BethesdaNet.csproj", "{A3813D73-9A8E-4CE7-861A-C59043DFFC14}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Downloaders.Bethesda", "Wabbajack.Downloaders.Bethesda\Wabbajack.Downloaders.Bethesda.csproj", "{B10BB6D6-B3FC-4A76-8A07-6A0A0ADDE198}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -369,6 +371,10 @@ Global {A3813D73-9A8E-4CE7-861A-C59043DFFC14}.Debug|Any CPU.Build.0 = Debug|Any CPU {A3813D73-9A8E-4CE7-861A-C59043DFFC14}.Release|Any CPU.ActiveCfg = Release|Any CPU {A3813D73-9A8E-4CE7-861A-C59043DFFC14}.Release|Any CPU.Build.0 = Release|Any CPU + {B10BB6D6-B3FC-4A76-8A07-6A0A0ADDE198}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B10BB6D6-B3FC-4A76-8A07-6A0A0ADDE198}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B10BB6D6-B3FC-4A76-8A07-6A0A0ADDE198}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B10BB6D6-B3FC-4A76-8A07-6A0A0ADDE198}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -415,6 +421,7 @@ Global {64AD7E26-5643-4969-A61C-E0A90FA25FCB} = {F677890D-5109-43BC-97C7-C4CD47C8EE0C} {6D7EA87E-6ABE-4BA3-B93A-BE5E71A4DE7C} = {F677890D-5109-43BC-97C7-C4CD47C8EE0C} {A3813D73-9A8E-4CE7-861A-C59043DFFC14} = {F01F8595-5FD7-4506-8469-F4A5522DACC1} + {B10BB6D6-B3FC-4A76-8A07-6A0A0ADDE198} = {98B731EE-4FC0-4482-A069-BCBA25497871} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0AA30275-0F38-4A7D-B645-F5505178DDE8} From b923cac804e06a66f39d903f739e3ede76763c0d Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Fri, 11 Feb 2022 07:03:16 -0700 Subject: [PATCH 4/7] Start to implement downloading --- .../BethesdaDownloader.cs | 35 +++- .../Wabbajack.Downloaders.Bethesda.csproj | 1 + Wabbajack.Networking.BethesdaNet/Client.cs | 19 +- Wabbajack.Networking.BethesdaNet/DTOs/Tree.cs | 194 ++++++++++++++++++ 4 files changed, 243 insertions(+), 6 deletions(-) create mode 100644 Wabbajack.Networking.BethesdaNet/DTOs/Tree.cs diff --git a/Wabbajack.Downloaders.Bethesda/BethesdaDownloader.cs b/Wabbajack.Downloaders.Bethesda/BethesdaDownloader.cs index b482995e..91b1d5bc 100644 --- a/Wabbajack.Downloaders.Bethesda/BethesdaDownloader.cs +++ b/Wabbajack.Downloaders.Bethesda/BethesdaDownloader.cs @@ -1,10 +1,13 @@ using Microsoft.Extensions.Logging; +using Wabbajack.Common; using Wabbajack.Downloaders.Interfaces; using Wabbajack.DTOs; using Wabbajack.DTOs.DownloadStates; using Wabbajack.DTOs.Validation; using Wabbajack.Hashing.xxHash64; using Wabbajack.Networking.BethesdaNet; +using Wabbajack.Networking.BethesdaNet.DTOs; +using Wabbajack.Networking.Http; using Wabbajack.Paths; using Wabbajack.Paths.IO; using Wabbajack.RateLimiter; @@ -31,10 +34,38 @@ public class BethesdaDownloader : ADownloader, IUr { var depot = await _client.GetDepots(state, token); + var tree = await _client.GetTree(state, token); + var chunks = tree!.DepotList.First().FileList.First().ChunkList; + + await chunks.PMapAll(async chunk => + { + var data = await GetChunk(state, chunk, token); + var reported = job.Report(data.Length, token); + +// Decrypt and Decompress + + await reported; + return data; + }); + return default; } + private async Task GetChunk(DTOs.DownloadStates.Bethesda state, Chunk chunk, + CancellationToken token) + { + var uri = new Uri($"https://content.cdp.bethesda.net/{state.ProductId}/{state.BranchID}/{chunk.Sha}"); + var msg = new HttpRequestMessage(HttpMethod.Get, uri); + msg.Headers.Add("User-Agent", "bnet"); + using var job = await _limiter.Begin("Getting chunk", chunk.ChunkSize, token); + using var response = await _httpClient.GetAsync(uri, token); + if (!response.IsSuccessStatusCode) + throw new HttpException(response); + await job.Report(chunk.ChunkSize, token); + return await response.Content.ReadAsByteArrayAsync(token); + } + public override async Task Prepare() { await _client.CDPAuth(CancellationToken.None); @@ -59,8 +90,8 @@ public class BethesdaDownloader : ADownloader, IUr public override async Task Verify(Archive archive, DTOs.DownloadStates.Bethesda state, IJob job, CancellationToken token) { - await _client.GetDepots(state, token); - throw new NotImplementedException(); + var depot = await _client.GetDepots(state, token); + return depot != null; } public override IEnumerable MetaIni(Archive a, DTOs.DownloadStates.Bethesda state) diff --git a/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj b/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj index a3799d4d..3affa506 100644 --- a/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj +++ b/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj @@ -7,6 +7,7 @@ + diff --git a/Wabbajack.Networking.BethesdaNet/Client.cs b/Wabbajack.Networking.BethesdaNet/Client.cs index ed90e823..80120b30 100644 --- a/Wabbajack.Networking.BethesdaNet/Client.cs +++ b/Wabbajack.Networking.BethesdaNet/Client.cs @@ -152,9 +152,20 @@ public class Client } public async Task GetDepots(Bethesda state, CancellationToken token) + { + return (await MakeCdpRequest>(state, "depots", token))?.Values.First(); + } + + public async Task GetTree(Bethesda state, CancellationToken token) + { + return await MakeCdpRequest(state, "tree", token); + } + + private async Task MakeCdpRequest(Bethesda state, string type, CancellationToken token) { await EnsureAuthed(token); - var msg = MakeMessage(HttpMethod.Get, new Uri($"https://api.bethesda.net/cdp-user/projects/{state.ProductId}/branches/{state.BranchID}/depots/.json")); + var msg = MakeMessage(HttpMethod.Get, + new Uri($"https://api.bethesda.net/cdp-user/projects/{state.ProductId}/branches/{state.BranchID}/{type}/.json")); msg.Headers.Add("x-src-fp", FingerprintKey); msg.Headers.Add("x-cdp-app", "UGC SDK"); msg.Headers.Add("x-cdp-app-ver", "0.9.11314/debug"); @@ -165,8 +176,8 @@ public class Client using var request = await _httpClient.SendAsync(msg, token); if (!request.IsSuccessStatusCode) throw new HttpException(request); - - var response = await request.Content.ReadFromJsonAsync>(_jsonOptions, token); - return response!.Values.First(); + + var response = await request.Content.ReadFromJsonAsync(_jsonOptions, token); + return response; } } \ No newline at end of file diff --git a/Wabbajack.Networking.BethesdaNet/DTOs/Tree.cs b/Wabbajack.Networking.BethesdaNet/DTOs/Tree.cs new file mode 100644 index 00000000..8c864a50 --- /dev/null +++ b/Wabbajack.Networking.BethesdaNet/DTOs/Tree.cs @@ -0,0 +1,194 @@ +using System.Text.Json.Serialization; + +namespace Wabbajack.Networking.BethesdaNet.DTOs; + + +public class BuildHistory +{ + [JsonPropertyName("id")] + public int Id { get; set; } + + [JsonPropertyName("description")] + public string Description { get; set; } +} + +public class BuildFields +{ + [JsonPropertyName("id")] + public int Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("create_date")] + public string CreateDate { get; set; } + + [JsonPropertyName("description")] + public string Description { get; set; } + + [JsonPropertyName("build_type")] + public int BuildType { get; set; } + + [JsonPropertyName("locked")] + public bool Locked { get; set; } + + [JsonPropertyName("storage_key")] + public string StorageKey { get; set; } + + [JsonPropertyName("major")] + public bool Major { get; set; } +} + +public class Chunk +{ + [JsonPropertyName("index")] + public int Index { get; set; } + + [JsonPropertyName("chunk_size")] + public int ChunkSize { get; set; } + + [JsonPropertyName("uncompressed_size")] + public int UncompressedSize { get; set; } + + [JsonPropertyName("sha")] + public string Sha { get; set; } +} + +public class FileList +{ + [JsonPropertyName("file_id")] + public int FileId { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("sha")] + public string Sha { get; set; } + + [JsonPropertyName("file_size")] + public int FileSize { get; set; } + + [JsonPropertyName("compressed_size")] + public int CompressedSize { get; set; } + + [JsonPropertyName("chunk_count")] + public int ChunkCount { get; set; } + + [JsonPropertyName("modifiable")] + public bool Modifiable { get; set; } + + [JsonPropertyName("chunk_list")] + public Chunk[] ChunkList { get; set; } +} + +public class DepotList +{ + [JsonPropertyName("id")] + public int Id { get; set; } + + [JsonPropertyName("properties_id")] + public int PropertiesId { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("build")] + public int Build { get; set; } + + [JsonPropertyName("bytes_per_chunk")] + public int BytesPerChunk { get; set; } + + [JsonPropertyName("size_on_disk")] + public int SizeOnDisk { get; set; } + + [JsonPropertyName("download_size")] + public int DownloadSize { get; set; } + + [JsonPropertyName("depot_type")] + public int DepotType { get; set; } + + [JsonPropertyName("deployment_order")] + public int DeploymentOrder { get; set; } + + [JsonPropertyName("compression_type")] + public int CompressionType { get; set; } + + [JsonPropertyName("encryption_type")] + public int EncryptionType { get; set; } + + [JsonPropertyName("language")] + public int Language { get; set; } + + [JsonPropertyName("region")] + public int Region { get; set; } + + [JsonPropertyName("default_region")] + public bool DefaultRegion { get; set; } + + [JsonPropertyName("default_language")] + public bool DefaultLanguage { get; set; } + + [JsonPropertyName("platform")] + public int Platform { get; set; } + + [JsonPropertyName("architecture")] + public int Architecture { get; set; } + + [JsonPropertyName("is_dlc")] + public bool IsDlc { get; set; } + + [JsonPropertyName("file_list")] + public FileList[] FileList { get; set; } +} + +public class Tree +{ + [JsonPropertyName("id")] + public int Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("entitlement_id")] + public int EntitlementId { get; set; } + + [JsonPropertyName("branch_type")] + public int BranchType { get; set; } + + [JsonPropertyName("project")] + public int Project { get; set; } + + [JsonPropertyName("build")] + public int Build { get; set; } + + [JsonPropertyName("available")] + public bool Available { get; set; } + + [JsonPropertyName("preload")] + public bool Preload { get; set; } + + [JsonPropertyName("preload_ondeck")] + public bool PreloadOndeck { get; set; } + + [JsonPropertyName("diff_type")] + public int DiffType { get; set; } + + [JsonPropertyName("build_history_length")] + public int BuildHistoryLength { get; set; } + + [JsonPropertyName("promote_ondeck_after_diff")] + public bool PromoteOndeckAfterDiff { get; set; } + + [JsonPropertyName("storage_url")] + public string StorageUrl { get; set; } + + [JsonPropertyName("build_history")] + public List BuildHistory { get; set; } + + [JsonPropertyName("build_fields")] + public BuildFields BuildFields { get; set; } + + [JsonPropertyName("depot_list")] + public List DepotList { get; set; } +} + From 30b29d890df508a0866b176a573c5cc24ac38f5f Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Fri, 11 Feb 2022 16:40:38 -0700 Subject: [PATCH 5/7] Can download Bethesda.NET CC files --- Wabbajack.CLI/Verbs/DownloadUrl.cs | 5 +- Wabbajack.DTOs/DownloadStates/Bethesda.cs | 4 +- .../BethesdaDownloader.cs | 48 +++++++++++++++---- .../Wabbajack.Downloaders.Bethesda.csproj | 5 ++ Wabbajack.Networking.BethesdaNet/Client.cs | 4 +- 5 files changed, 53 insertions(+), 13 deletions(-) diff --git a/Wabbajack.CLI/Verbs/DownloadUrl.cs b/Wabbajack.CLI/Verbs/DownloadUrl.cs index af6fc344..b800e967 100644 --- a/Wabbajack.CLI/Verbs/DownloadUrl.cs +++ b/Wabbajack.CLI/Verbs/DownloadUrl.cs @@ -4,9 +4,11 @@ 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; @@ -42,7 +44,8 @@ public class DownloadUrl : IVerb } var archive = new Archive() {State = parsed, Name = output.FileName.ToString()}; - await _dispatcher.Download(archive, output, CancellationToken.None); + var hash = await _dispatcher.Download(archive, output, CancellationToken.None); ; + Console.WriteLine($"Download complete: {output.Size().ToFileSizeString()} {hash} {hash.ToHex()} {(long)hash}"); return 0; } } \ No newline at end of file diff --git a/Wabbajack.DTOs/DownloadStates/Bethesda.cs b/Wabbajack.DTOs/DownloadStates/Bethesda.cs index 792baabd..c0af7fd8 100644 --- a/Wabbajack.DTOs/DownloadStates/Bethesda.cs +++ b/Wabbajack.DTOs/DownloadStates/Bethesda.cs @@ -6,11 +6,11 @@ namespace Wabbajack.DTOs.DownloadStates; public class Bethesda : ADownloadState { public override string TypeName { get; } = "Bethesda"; - public override object[] PrimaryKey => new object[] {Game, IsCCMod, ProductId, BranchID, ContentId}; + public override object[] PrimaryKey => new object[] {Game, IsCCMod, ProductId, BranchId, ContentId}; public Game Game { get; set; } public bool IsCCMod { get; set; } public string ContentId { get; set; } public long ProductId { get; set; } - public long BranchID { get; set; } + public long BranchId { get; set; } public string Name { get; set; } } \ No newline at end of file diff --git a/Wabbajack.Downloaders.Bethesda/BethesdaDownloader.cs b/Wabbajack.Downloaders.Bethesda/BethesdaDownloader.cs index 91b1d5bc..82099a55 100644 --- a/Wabbajack.Downloaders.Bethesda/BethesdaDownloader.cs +++ b/Wabbajack.Downloaders.Bethesda/BethesdaDownloader.cs @@ -1,3 +1,7 @@ +using System.IO.Compression; +using System.Security.Cryptography; +using CS_AES_CTR; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; using Microsoft.Extensions.Logging; using Wabbajack.Common; using Wabbajack.Downloaders.Interfaces; @@ -38,28 +42,56 @@ public class BethesdaDownloader : ADownloader, IUr var chunks = tree!.DepotList.First().FileList.First().ChunkList; + using var os = destination.Open(FileMode.Create, FileAccess.ReadWrite, FileShare.Read); + + var hasher = new xxHashAlgorithm(0); + Hash finalHash = default; + + var aesKey = depot.ExInfoA.ToArray(); + var aesIV = depot.ExInfoB.Take(16).ToArray(); + await chunks.PMapAll(async chunk => { - var data = await GetChunk(state, chunk, token); + var data = await GetChunk(state, chunk, depot.PropertiesId, token); var reported = job.Report(data.Length, token); -// Decrypt and Decompress + var aesCtr = new AES_CTR(aesKey, aesIV, false); + data = aesCtr.DecryptBytes(data); + if (chunk.UncompressedSize != chunk.ChunkSize) + { + var inflater = new InflaterInputStream(new MemoryStream(data)); + data = await inflater.ReadAllAsync(); + } + await reported; return data; + }) + .Do(async data => + { + if (data.Length < tree.DepotList.First().BytesPerChunk) + { + hasher.HashBytes(data); + } + else + { + finalHash = Hash.FromULong(hasher.FinalizeHashValueInternal(data)); + } + + await os.WriteAsync(data, token); }); - return default; + return finalHash; } - private async Task GetChunk(DTOs.DownloadStates.Bethesda state, Chunk chunk, + private async Task GetChunk(DTOs.DownloadStates.Bethesda state, Chunk chunk, long propertiesId, CancellationToken token) { - var uri = new Uri($"https://content.cdp.bethesda.net/{state.ProductId}/{state.BranchID}/{chunk.Sha}"); + var uri = new Uri($"https://content.cdp.bethesda.net/{state.ProductId}/{propertiesId}/{chunk.Sha}"); var msg = new HttpRequestMessage(HttpMethod.Get, uri); msg.Headers.Add("User-Agent", "bnet"); using var job = await _limiter.Begin("Getting chunk", chunk.ChunkSize, token); - using var response = await _httpClient.GetAsync(uri, token); + using var response = await _httpClient.SendAsync(msg, token); if (!response.IsSuccessStatusCode) throw new HttpException(response); await job.Report(chunk.ChunkSize, token); @@ -128,7 +160,7 @@ public class BethesdaDownloader : ADownloader, IUr Game = game.Game, IsCCMod = isCCMod, ProductId = productId, - BranchID = branchId, + BranchId = branchId, ContentId = path[3] }; } @@ -136,7 +168,7 @@ public class BethesdaDownloader : ADownloader, IUr public Uri UnParse(IDownloadState state) { var cstate = (DTOs.DownloadStates.Bethesda) state; - return new Uri($"bethesda://{cstate.Game}/{(cstate.IsCCMod ? "cc" : "mod")}/{cstate.ProductId}/{cstate.BranchID}/{cstate.ContentId}"); + return new Uri($"bethesda://{cstate.Game}/{(cstate.IsCCMod ? "cc" : "mod")}/{cstate.ProductId}/{cstate.BranchId}/{cstate.ContentId}"); } public ValueTask GetChunkedSeekableStream(Archive archive, CancellationToken token) diff --git a/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj b/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj index 3affa506..8126cfb1 100644 --- a/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj +++ b/Wabbajack.Downloaders.Bethesda/Wabbajack.Downloaders.Bethesda.csproj @@ -12,4 +12,9 @@ + + + + + diff --git a/Wabbajack.Networking.BethesdaNet/Client.cs b/Wabbajack.Networking.BethesdaNet/Client.cs index 80120b30..0f4132c2 100644 --- a/Wabbajack.Networking.BethesdaNet/Client.cs +++ b/Wabbajack.Networking.BethesdaNet/Client.cs @@ -135,7 +135,7 @@ public class Client ContentId = c.ContentId, IsCCMod = c.CcMod, ProductId = c.CdpProductId, - BranchID = c.CdpBranchId + BranchId = c.CdpBranchId })); } @@ -165,7 +165,7 @@ public class Client { await EnsureAuthed(token); var msg = MakeMessage(HttpMethod.Get, - new Uri($"https://api.bethesda.net/cdp-user/projects/{state.ProductId}/branches/{state.BranchID}/{type}/.json")); + new Uri($"https://api.bethesda.net/cdp-user/projects/{state.ProductId}/branches/{state.BranchId}/{type}/.json")); msg.Headers.Add("x-src-fp", FingerprintKey); msg.Headers.Add("x-cdp-app", "UGC SDK"); msg.Headers.Add("x-cdp-app-ver", "0.9.11314/debug"); From 379337d0b68e88dc20eea0b08b36011068132354 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Fri, 11 Feb 2022 17:47:02 -0700 Subject: [PATCH 6/7] BTar files are integrated into the extractor code --- Wabbajack.CLI/Program.cs | 1 + Wabbajack.CLI/Verbs/Extract.cs | 49 + .../FileSignatures/Definitions/bsasigs.txt | 3 +- Wabbajack.Common/FileSignatures/Signatures.cs | 2379 ++++++++--------- Wabbajack.Common/FileSignatures/Signatures.tt | 3 + Wabbajack.FileExtractor/FileExtractor.cs | 78 + 6 files changed, 1255 insertions(+), 1258 deletions(-) create mode 100644 Wabbajack.CLI/Verbs/Extract.cs diff --git a/Wabbajack.CLI/Program.cs b/Wabbajack.CLI/Program.cs index 7d59a672..e3cf38da 100644 --- a/Wabbajack.CLI/Program.cs +++ b/Wabbajack.CLI/Program.cs @@ -69,6 +69,7 @@ internal class Program services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); }).Build(); diff --git a/Wabbajack.CLI/Verbs/Extract.cs b/Wabbajack.CLI/Verbs/Extract.cs new file mode 100644 index 00000000..9530ca26 --- /dev/null +++ b/Wabbajack.CLI/Verbs/Extract.cs @@ -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 _logger; + private readonly FileExtractor.FileExtractor _extractor; + + public Extract(ILogger logger, FileExtractor.FileExtractor extractor) + { + _logger = logger; + _extractor = extractor; + } + + public Command MakeCommand() + { + var command = new Command("extract"); + command.Add(new Option(new[] {"-i", "-input"}, "Input Archive")); + command.Add(new Option(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 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; + } +} \ No newline at end of file diff --git a/Wabbajack.Common/FileSignatures/Definitions/bsasigs.txt b/Wabbajack.Common/FileSignatures/Definitions/bsasigs.txt index 06073ddf..5bb0723d 100644 --- a/Wabbajack.Common/FileSignatures/Definitions/bsasigs.txt +++ b/Wabbajack.Common/FileSignatures/Definitions/bsasigs.txt @@ -4,4 +4,5 @@ FO4 BSA,42 54 44 58,BA2 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 \ No newline at end of file +DDS, 44 44 53 20,DDS +Bethesda Tar, 42 54 41 52, BTAR \ No newline at end of file diff --git a/Wabbajack.Common/FileSignatures/Signatures.cs b/Wabbajack.Common/FileSignatures/Signatures.cs index 80d30734..ed17d29c 100644 --- a/Wabbajack.Common/FileSignatures/Signatures.cs +++ b/Wabbajack.Common/FileSignatures/Signatures.cs @@ -1,2515 +1,2380 @@ -namespace Wabbajack.Common.FileSignatures; + +namespace Wabbajack.Common.FileSignatures { -public enum FileType -{ - _123, - _386, - _3G2, - _3GG, - _3GP, - _3GP5, - _4XM, - _7Z, - AAC, - ABA, - ABD, - ABI, - ABY, - AC, - AC_, - ACCDB, - ACM, - ACS, - AD, - ADF, - ADP, - ADX, - AIFF, - AIN, - AMR, - ANI, - ANM, - API, - APK, - APR, - APUF, - ARC, - ARF, - ARJ, - ARL, - ASF, - AST, - ASX, - attachment, - AU, - AUT, - AVI, - AW, - AX, - b64, - B85, - BA2, - BAG, - BDR, - BIN, - BLI, - BMP, - BPG, - BSA, - BSB, - BZ2, - CAB, - CAF, - CAL, - CAP, - CAS, - CAT, - CBD, - CBK, - CDA, - CDR, - CFG, - CHI, - CHM, - CIN, - CL5, - CLASS, - CLB, - CMX, - CNV, - COD, - COM, - CPE, - CPI, - CPL, - CPT, - CPX, - CRU, - CRW, - CRX, - CSD, - CSH, - CSO, - CTF, - CTL, - CUR, - DAA, - DAT, - DAX, - DB, - DB3, - DB4, - DBA, - DBB, - DBF, - DBX, - DCI, - DCX, - DDS, - dex, - DIB, - DLL, - DMG, - DMP, - DMS, - DOC, - DOCX, - DOT, - DPX, - DRV, - DRW, - DS4, - DSF, - DSN, - DSP, - DSS, - DST, - DSW, - DTD, - DUN, - DVF, - DVR, - DW4, - DWG, - E01, - ECF, - EFX, - EML, - ENL, - EPS, - EPUB, - ESD, - ETH, - EVT, - EVTX, - Ex01, - EXE, - EXR, - FBM, - FDB, - FDF, - FITS, - FLAC, - FLI, - FLT, - FLV, - FM, - FON, - FTR, - G64, - GDB, - GED, - GHO, - GHS, - GID, - GIF, - GPG, - GPX, - GRB, - GRP, - GX2, - GZ, - HAP, - HDMP, - HDR, - HLP, - HQX, - HUS, - ICO, - IDX, - IFF, - IFO, - IMG, - IND, - INDD, - INFO, - INS, - IPD, - ISO, - IVR, - JAR, - JB2, - JCEKS, - JFIF, - JG, - JNT, - JP2, - JPE, - JPEG, - JPG, - JTP, - KGB, - KMZ, - KOZ, - KWD, - LBK, - LGC, - LGD, - LHA, - LIB, - LIT, - LNK, - LOG, - LWP, - LZH, - M4A, - M4V, - MANIFEST, - MAR, - MAT, - MDB, - MDF, - MDI, - MID, - MIDI, - MIF, - MKV, - MLS, - MMF, - MNY, - MOF, - MOV, - MP, - MP3, - MP4, - MPG, - MSC, - MSF, - MSG, - MSI, - MSP, - MSV, - MTE, - MTW, - MXD, - MXF, - NRI, - NSF, - NTF, - NVRAM, - OBJ, - OCX, - ODP, - ODT, - OGA, - OGG, - OGV, - OGX, - OLB, - ONE, - ONEPKG, - OPT, - ORG, - OST, - OTF, - OTT, - OXPS, - P10, - PAK, - PAT, - PAX, - PCH, - PCS, - PCX, - PDB, - PDF, - PEC, - PES, - PF, - PFC, - PGD, - PGM, - PIF, - PKR, - PLS, - PMOCCMOC, - PNG, - PPS, - PPT, - PPTX, - PPZ, - PRC, - PSD, - PSP, - PUB, - PUF, - PWI, - PWL, - QBB, - QCP, - QDF, - QEL, - QEMU, - QPH, - QRP, - QSD, - QTS, - QTX, - QXD, - RA, - RAM, - RAR, - RAR_NEW, - RAR_OLD, - RBI, - RDATA, - REG, - RGB, - RM, - RMI, - RMVB, - RPM, - RTD, - RTF, - RVT, - SAM, - SAV, - SCR, - SCT, - SDPX, - SDR, - SH3, - SHD, - SHW, - SIB, - SIL, - SIT, - SKF, - SKR, - SLE, - SLN, - SNM, - SNP, - SOU, - SPF, - SPL, - SPO, - SPVB, - STL, - SUD, - SUO, - SWF, - SXC, - SXD, - SXI, - SXW, - SYS, - SYW, - TAR, - TARZ, - TB2, - TBI, - TBZ2, - TES3, - THP, - TIB, - TIF, - TIFF, - TLB, - TORRENT, - TPL, - TR1, - TTF, - UCE, - UFA, - VBE, - VBX, - VCD, - VCF, - VCW, - VHD, - VLT, - VMD, - VMDK, - VOB, - VOC, - VSD, - VXD, - WAB, - WALLET, - WAV, - WB2, - WB3, - WEBM, - WEBP, - WIM, - WIZ, - WK1, - WK3, - WK4, - WK5, - WKS, - WMA, - WMF, - WMV, - WMZ, - WP, - WP5, - WP6, - WPD, - WPF, - WPG, - WPL, - WPP, - WPS, - WRI, - WS, - WS2, - WSC, - WSF, - XAR, - XCF, - XDR, - XLA, - XLS, - XLSX, - XML, - XPI, - XPS, - XPT, - XXX, - XZ, - ZAP, - ZIP, - ZOO -} + public enum FileType { BTAR, + _123, + _386, + _3G2, + _3GG, + _3GP, + _3GP5, + _4XM, + _7Z, + AAC, + ABA, + ABD, + ABI, + ABY, + AC, + AC_, + ACCDB, + ACM, + ACS, + AD, + ADF, + ADP, + ADX, + AIFF, + AIN, + AMR, + ANI, + ANM, + API, + APK, + APR, + APUF, + ARC, + ARF, + ARJ, + ARL, + ASF, + AST, + ASX, + attachment, + AU, + AUT, + AVI, + AW, + AX, + b64, + B85, + BA2, + BAG, + BDR, + BIN, + BLI, + BMP, + BPG, + BSA, + BSB, + BZ2, + CAB, + CAF, + CAL, + CAP, + CAS, + CAT, + CBD, + CBK, + CDA, + CDR, + CFG, + CHI, + CHM, + CIN, + CL5, + CLASS, + CLB, + CMX, + CNV, + COD, + COM, + CPE, + CPI, + CPL, + CPT, + CPX, + CRU, + CRW, + CRX, + CSD, + CSH, + CSO, + CTF, + CTL, + CUR, + DAA, + DAT, + DAX, + DB, + DB3, + DB4, + DBA, + DBB, + DBF, + DBX, + DCI, + DCX, + DDS, + dex, + DIB, + DLL, + DMG, + DMP, + DMS, + DOC, + DOCX, + DOT, + DPX, + DRV, + DRW, + DS4, + DSF, + DSN, + DSP, + DSS, + DST, + DSW, + DTD, + DUN, + DVF, + DVR, + DW4, + DWG, + E01, + ECF, + EFX, + EML, + ENL, + EPS, + EPUB, + ESD, + ETH, + EVT, + EVTX, + Ex01, + EXE, + EXR, + FBM, + FDB, + FDF, + FITS, + FLAC, + FLI, + FLT, + FLV, + FM, + FON, + FTR, + G64, + GDB, + GED, + GHO, + GHS, + GID, + GIF, + GPG, + GPX, + GRB, + GRP, + GX2, + GZ, + HAP, + HDMP, + HDR, + HLP, + HQX, + HUS, + ICO, + IDX, + IFF, + IFO, + IMG, + IND, + INDD, + INFO, + INS, + IPD, + ISO, + IVR, + JAR, + JB2, + JCEKS, + JFIF, + JG, + JNT, + JP2, + JPE, + JPEG, + JPG, + JTP, + KGB, + KMZ, + KOZ, + KWD, + LBK, + LGC, + LGD, + LHA, + LIB, + LIT, + LNK, + LOG, + LWP, + LZH, + M4A, + M4V, + MANIFEST, + MAR, + MAT, + MDB, + MDF, + MDI, + MID, + MIDI, + MIF, + MKV, + MLS, + MMF, + MNY, + MOF, + MOV, + MP, + MP3, + MP4, + MPG, + MSC, + MSF, + MSG, + MSI, + MSP, + MSV, + MTE, + MTW, + MXD, + MXF, + NRI, + NSF, + NTF, + NVRAM, + OBJ, + OCX, + ODP, + ODT, + OGA, + OGG, + OGV, + OGX, + OLB, + ONE, + ONEPKG, + OPT, + ORG, + OST, + OTF, + OTT, + OXPS, + P10, + PAK, + PAT, + PAX, + PCH, + PCS, + PCX, + PDB, + PDF, + PEC, + PES, + PF, + PFC, + PGD, + PGM, + PIF, + PKR, + PLS, + PMOCCMOC, + PNG, + PPS, + PPT, + PPTX, + PPZ, + PRC, + PSD, + PSP, + PUB, + PUF, + PWI, + PWL, + QBB, + QCP, + QDF, + QEL, + QEMU, + QPH, + QRP, + QSD, + QTS, + QTX, + QXD, + RA, + RAM, + RAR, + RAR_NEW, + RAR_OLD, + RBI, + RDATA, + REG, + RGB, + RM, + RMI, + RMVB, + RPM, + RTD, + RTF, + RVT, + SAM, + SAV, + SCR, + SCT, + SDPX, + SDR, + SH3, + SHD, + SHW, + SIB, + SIL, + SIT, + SKF, + SKR, + SLE, + SLN, + SNM, + SNP, + SOU, + SPF, + SPL, + SPO, + SPVB, + STL, + SUD, + SUO, + SWF, + SXC, + SXD, + SXI, + SXW, + SYS, + SYW, + TAR, + TARZ, + TB2, + TBI, + TBZ2, + TES3, + THP, + TIB, + TIF, + TIFF, + TLB, + TORRENT, + TPL, + TR1, + TTF, + UCE, + UFA, + VBE, + VBX, + VCD, + VCF, + VCW, + VHD, + VLT, + VMD, + VMDK, + VOB, + VOC, + VSD, + VXD, + WAB, + WALLET, + WAV, + WB2, + WB3, + WEBM, + WEBP, + WIM, + WIZ, + WK1, + WK3, + WK4, + WK5, + WKS, + WMA, + WMF, + WMV, + WMZ, + WP, + WP5, + WP6, + WPD, + WPF, + WPG, + WPL, + WPP, + WPS, + WRI, + WS, + WS2, + WSC, + WSF, + XAR, + XCF, + XDR, + XLA, + XLS, + XLSX, + XML, + XPI, + XPS, + XPT, + XXX, + XZ, + ZAP, + ZIP, + ZOO, + } -public static class Definitions -{ - public static (FileType, byte[])[] Signatures = - { - // Morrowind BSA + public static class Definitions { + + + public static (FileType, byte[])[] Signatures = { + // Morrowind BSA (FileType.TES3, new byte[] {0x00, 0x01, 0x00, 0x00}), - // TES 4-5 and FO 3 BSA + // TES 4-5 and FO 3 BSA (FileType.BSA, new byte[] {0x42, 0x53, 0x41, 0x00}), - // FO4 BSA + // FO4 BSA (FileType.BA2, new byte[] {0x42, 0x54, 0x44, 0x58}), - // Relaxed RAR format + // Relaxed RAR format (FileType.RAR, new byte[] {0x52, 0x61, 0x72, 0x21}), - // RAR5 or newer + // RAR5 or newer (FileType.RAR_NEW, new byte[] {0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00}), - // RAR4 or older + // RAR4 or older (FileType.RAR_OLD, new byte[] {0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00}), - // DDS + // DDS (FileType.DDS, new byte[] {0x44, 0x44, 0x53, 0x20}), - // JPEG2000 image files + // 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}), - // 3GPP multimedia files + // 3GPP multimedia files (FileType._3GP, new byte[] {0x00, 0x00, 0x00, 0x14, 0x66, 0x74, 0x79, 0x70}), - // MPEG-4 v1 + // MPEG-4 v1 (FileType.MP4, new byte[] {0x00, 0x00, 0x00, 0x14, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6F, 0x6D}), - // 3rd Generation Partnership Project 3GPP + // 3rd Generation Partnership Project 3GPP (FileType._3GG, new byte[] {0x00, 0x00, 0x00, 0x14, 0x66, 0x74, 0x79, 0x70}), - // 3rd Generation Partnership Project 3GPP + // 3rd Generation Partnership Project 3GPP (FileType._3GP, new byte[] {0x00, 0x00, 0x00, 0x14, 0x66, 0x74, 0x79, 0x70}), - // 3rd Generation Partnership Project 3GPP + // 3rd Generation Partnership Project 3GPP (FileType._3G2, new byte[] {0x00, 0x00, 0x00, 0x14, 0x66, 0x74, 0x79, 0x70}), - // Windows Disk Image + // Windows Disk Image (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 - }), + // 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}), - // MPEG-4 video_1 + // MPEG-4 video_1 (FileType._3GP5, new byte[] {0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70}), - // MPEG-4 video_1 + // MPEG-4 video_1 (FileType.M4V, new byte[] {0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70}), - // MPEG-4 video_1 + // MPEG-4 video_1 (FileType.MP4, new byte[] {0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70}), - // MPEG-4 video_2 + // MPEG-4 video_2 (FileType.MP4, new byte[] {0x00, 0x00, 0x00, 0x1C, 0x66, 0x74, 0x79, 0x70}), - // 3GPP2 multimedia files + // 3GPP2 multimedia files (FileType._3GP, new byte[] {0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70}), - // Apple audio and video + // Apple audio and video (FileType.M4A, new byte[] {0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41}), - // 3rd Generation Partnership Project 3GPP2 + // 3rd Generation Partnership Project 3GPP2 (FileType._3GG, new byte[] {0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70}), - // 3rd Generation Partnership Project 3GPP2 + // 3rd Generation Partnership Project 3GPP2 (FileType._3GP, new byte[] {0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70}), - // 3rd Generation Partnership Project 3GPP2 + // 3rd Generation Partnership Project 3GPP2 (FileType._3G2, new byte[] {0x00, 0x00, 0x00, 0x20, 0x66, 0x74, 0x79, 0x70}), - // Windows icon|printer spool file + // Windows icon|printer spool file (FileType.ICO, new byte[] {0x00, 0x00, 0x01, 0x00}), - // Windows icon|printer spool file + // Windows icon|printer spool file (FileType.SPL, new byte[] {0x00, 0x00, 0x01, 0x00}), - // MPEG video file + // MPEG video file (FileType.MPG, new byte[] {0x00, 0x00, 0x01, 0xB3}), - // DVD video file + // DVD video file (FileType.MPG, new byte[] {0x00, 0x00, 0x01, 0xBA}), - // DVD video file + // DVD video file (FileType.VOB, new byte[] {0x00, 0x00, 0x01, 0xBA}), - // Windows cursor + // Windows cursor (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 - }), + // 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}), - // QuattroPro spreadsheet + // QuattroPro spreadsheet (FileType.WB2, new byte[] {0x00, 0x00, 0x02, 0x00}), - // Wii images container + // Wii images container (FileType.TPL, new byte[] {0x00, 0x20, 0xAF, 0x30}), - // Lotus 1-2-3 (v1) + // Lotus 1-2-3 (v1) (FileType.WK1, new byte[] {0x00, 0x00, 0x02, 0x00, 0x06, 0x04, 0x06, 0x00}), - // Lotus 1-2-3 (v3) + // Lotus 1-2-3 (v3) (FileType.WK3, new byte[] {0x00, 0x00, 0x1A, 0x00, 0x00, 0x10, 0x04, 0x00}), - // Lotus 1-2-3 (v4-v5) + // Lotus 1-2-3 (v4-v5) (FileType.WK4, new byte[] {0x00, 0x00, 0x1A, 0x00, 0x02, 0x10, 0x04, 0x00}), - // Lotus 1-2-3 (v4-v5) + // Lotus 1-2-3 (v4-v5) (FileType.WK5, new byte[] {0x00, 0x00, 0x1A, 0x00, 0x02, 0x10, 0x04, 0x00}), - // Lotus 1-2-3 (v9) + // Lotus 1-2-3 (v9) (FileType._123, new byte[] {0x00, 0x00, 0x1A, 0x00, 0x05, 0x10, 0x04}), - // Quark Express (Intel) + // Quark Express (Intel) (FileType.QXD, new byte[] {0x00, 0x00, 0x49, 0x49, 0x58, 0x50, 0x52}), - // Quark Express (Motorola) + // Quark Express (Motorola) (FileType.QXD, new byte[] {0x00, 0x00, 0x4D, 0x4D, 0x58, 0x50, 0x52}), - // Windows Help file_1 + // Windows Help file_1 (FileType.HLP, new byte[] {0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}), - // TrueType font file + // TrueType font file (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 - }), + // 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}), - // 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 - }), + // 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}), - // 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 - }), + // 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}), - // Palm Address Book Archive + // Palm Address Book Archive (FileType.ABA, new byte[] {0x00, 0x01, 0x42, 0x41}), - // Palm DateBook Archive + // Palm DateBook Archive (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 - }), + // Netscape Navigator (v4) database + (FileType.DB, new byte[] {0x00, 0x06, 0x15, 0x61, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0xD2, 0x00, 0x00, 0x10, 0x00}), - // FLIC animation + // FLIC animation (FileType.FLI, new byte[] {0x00, 0x11}), - // Netscape Communicator (v4) mail folder + // Netscape Communicator (v4) mail folder (FileType.SNM, new byte[] {0x00, 0x1E, 0x84, 0x90, 0x00, 0x00, 0x00, 0x00}), - // PowerPoint presentation subheader_1 + // PowerPoint presentation subheader_1 (FileType.PPT, new byte[] {0x00, 0x6E, 0x1E, 0xF0}), - // Webex Advanced Recording Format + // Webex Advanced Recording Format (FileType.ARF, new byte[] {0x01, 0x00, 0x02, 0x00}), - // Firebird and Interbase database files + // Firebird and Interbase database files (FileType.FDB, new byte[] {0x01, 0x00, 0x39, 0x30}), - // Firebird and Interbase database files + // Firebird and Interbase database files (FileType.GDB, new byte[] {0x01, 0x00, 0x39, 0x30}), - // The Bat! Message Base Index + // The Bat! Message Base Index (FileType.TBI, new byte[] {0x01, 0x01, 0x47, 0x19, 0xA4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), - // SQL Data Base + // SQL Data Base (FileType.MDF, new byte[] {0x01, 0x0F, 0x00, 0x00}), - // Novell LANalyzer capture file + // Novell LANalyzer capture file (FileType.TR1, new byte[] {0x01, 0x10}), - // Silicon Graphics RGB Bitmap + // Silicon Graphics RGB Bitmap (FileType.RGB, new byte[] {0x01, 0xDA, 0x01, 0x01, 0x00, 0x03}), - // Micrografx vector graphic file + // Micrografx vector graphic file (FileType.DRW, new byte[] {0x01, 0xFF, 0x02, 0x04, 0x03, 0x02}), - // Digital Speech Standard file + // Digital Speech Standard file (FileType.DSS, new byte[] {0x02, 0x64, 0x73, 0x73}), - // MapInfo Native Data Format + // MapInfo Native Data Format (FileType.DAT, new byte[] {0x03}), - // dBASE III file + // dBASE III file (FileType.DB3, new byte[] {0x03}), - // Quicken price history + // Quicken price history (FileType.QPH, new byte[] {0x03, 0x00, 0x00, 0x00}), - // Approach index file + // Approach index file (FileType.ADX, new byte[] {0x03, 0x00, 0x00, 0x00, 0x41, 0x50, 0x50, 0x52}), - // dBASE IV file + // dBASE IV file (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 - }), + // Adobe InDesign + (FileType.INDD, new byte[] {0x06, 0x06, 0xED, 0xF5, 0xD8, 0x1D, 0x46, 0xE5, 0xBD, 0x31, 0xEF, 0xE7, 0xFE, 0x74, 0xB7, 0x1D}), - // Material Exchange Format + // Material Exchange Format (FileType.MXF, new byte[] {0x06, 0x0E, 0x2B, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0D, 0x01, 0x02, 0x01, 0x01, 0x02}), - // Generic drawing programs + // Generic drawing programs (FileType.DRW, new byte[] {0x07}), - // SkinCrafter skin + // SkinCrafter skin (FileType.SKF, new byte[] {0x07, 0x53, 0x4B, 0x46}), - // DesignTools 2D Design file + // DesignTools 2D Design file (FileType.DTD, new byte[] {0x07, 0x64, 0x74, 0x32, 0x64, 0x64, 0x74, 0x64}), - // dBASE IV or dBFast configuration file + // dBASE IV or dBFast configuration file (FileType.DB, new byte[] {0x08}), - // Excel spreadsheet subheader_1 + // Excel spreadsheet subheader_1 (FileType.XLS, new byte[] {0x09, 0x08, 0x10, 0x00, 0x00, 0x06, 0x05, 0x00}), - // ZSOFT Paintbrush file_1 + // ZSOFT Paintbrush file_1 (FileType.PCX, new byte[] {0x0A, 0x02, 0x01, 0x01}), - // ZSOFT Paintbrush file_2 + // ZSOFT Paintbrush file_2 (FileType.PCX, new byte[] {0x0A, 0x03, 0x01, 0x01}), - // ZSOFT Paintbrush file_3 + // ZSOFT Paintbrush file_3 (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 - }), + // MultiBit Bitcoin wallet file + (FileType.WALLET, new byte[] {0x0A, 0x16, 0x6F, 0x72, 0x67, 0x2E, 0x62, 0x69, 0x74, 0x63, 0x6F, 0x69, 0x6E, 0x2E, 0x70, 0x72}), - // Monochrome Picture TIFF bitmap + // Monochrome Picture TIFF bitmap (FileType.MP, new byte[] {0x0C, 0xED}), - // DeskMate Document + // DeskMate Document (FileType.DOC, new byte[] {0x0D, 0x44, 0x4F, 0x43}), - // Nero CD compilation + // Nero CD compilation (FileType.NRI, new byte[] {0x0E, 0x4E, 0x65, 0x72, 0x6F, 0x49, 0x53, 0x4F}), - // DeskMate Worksheet + // DeskMate Worksheet (FileType.WKS, new byte[] {0x0E, 0x57, 0x4B, 0x53}), - // PowerPoint presentation subheader_2 + // PowerPoint presentation subheader_2 (FileType.PPT, new byte[] {0x0F, 0x00, 0xE8, 0x03}), - // Sibelius Music - Score + // Sibelius Music - Score (FileType.SIB, new byte[] {0x0F, 0x53, 0x49, 0x42, 0x45, 0x4C, 0x49, 0x55, 0x53}), - // Easy CD Creator 5 Layout file + // Easy CD Creator 5 Layout file (FileType.CL5, new byte[] {0x10, 0x00, 0x00, 0x00}), - // Windows prefetch file + // Windows prefetch file (FileType.PF, new byte[] {0x11, 0x00, 0x00, 0x00, 0x53, 0x43, 0x43, 0x41}), - // Lotus Notes database template + // Lotus Notes database template (FileType.NTF, new byte[] {0x1A, 0x00, 0x00}), - // Lotus Notes database + // Lotus Notes database (FileType.NSF, new byte[] {0x1A, 0x00, 0x00, 0x04, 0x00, 0x00}), - // LH archive (old vers.-type 1) + // LH archive (old vers.-type 1) (FileType.ARC, new byte[] {0x1A, 0x02}), - // LH archive (old vers.-type 2) + // LH archive (old vers.-type 2) (FileType.ARC, new byte[] {0x1A, 0x03}), - // LH archive (old vers.-type 3) + // LH archive (old vers.-type 3) (FileType.ARC, new byte[] {0x1A, 0x04}), - // LH archive (old vers.-type 4) + // LH archive (old vers.-type 4) (FileType.ARC, new byte[] {0x1A, 0x08}), - // LH archive (old vers.-type 5) + // LH archive (old vers.-type 5) (FileType.ARC, new byte[] {0x1A, 0x09}), - // Compressed archive file + // Compressed archive file (FileType.PAK, new byte[] {0x1A, 0x0B}), - // WinPharoah capture file + // WinPharoah capture file (FileType.ETH, new byte[] {0x1A, 0x35, 0x01, 0x00}), - // WebM video file + // WebM video file (FileType.WEBM, new byte[] {0x1A, 0x45, 0xDF, 0xA3}), - // Matroska stream file_1 + // Matroska stream file_1 (FileType.MKV, new byte[] {0x1A, 0x45, 0xDF, 0xA3}), - // Matroska stream file_2 + // Matroska stream file_2 (FileType.MKV, new byte[] {0x1A, 0x45, 0xDF, 0xA3, 0x93, 0x42, 0x82, 0x88}), - // Runtime Software disk image + // Runtime Software disk image (FileType.DAT, new byte[] {0x1A, 0x52, 0x54, 0x53, 0x20, 0x43, 0x4F, 0x4D}), - // WordStar Version 5.0-6.0 document + // WordStar Version 5.0-6.0 document (FileType.WS, new byte[] {0x1D, 0x7D}), - // GZIP archive file + // GZIP archive file (FileType.GZ, new byte[] {0x1F, 0x8B, 0x08}), - // VLC Player Skin file + // VLC Player Skin file (FileType.VLT, new byte[] {0x1F, 0x8B, 0x08}), - // Compressed tape archive_1 + // Compressed tape archive_1 (FileType.TARZ, new byte[] {0x1F, 0x9D, 0x90}), - // Compressed tape archive_2 + // Compressed tape archive_2 (FileType.TARZ, new byte[] {0x1F, 0xA0}), - // MapInfo Sea Chart + // MapInfo Sea Chart (FileType.BSB, new byte[] {0x21}), - // AIN Compressed Archive + // AIN Compressed Archive (FileType.AIN, new byte[] {0x21, 0x12}), - // Unix archiver (ar)-MS Program Library Common Object File Format (COFF) + // Unix archiver (ar)-MS Program Library Common Object File Format (COFF) (FileType.LIB, new byte[] {0x21, 0x3C, 0x61, 0x72, 0x63, 0x68, 0x3E, 0x0A}), - // Microsoft Outlook Exchange Offline Storage Folder + // Microsoft Outlook Exchange Offline Storage Folder (FileType.OST, new byte[] {0x21, 0x42, 0x44, 0x4E}), - // Cerius2 file + // Cerius2 file (FileType.MSI, new byte[] {0x23, 0x20}), - // VMware 4 Virtual Disk description + // VMware 4 Virtual Disk description (FileType.VMDK, new byte[] {0x23, 0x20, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x44}), - // MS Developer Studio project file + // MS Developer Studio project file (FileType.DSP, new byte[] {0x23, 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73}), - // Adaptive Multi-Rate ACELP Codec (GSM) + // Adaptive Multi-Rate ACELP Codec (GSM) (FileType.AMR, new byte[] {0x23, 0x21, 0x41, 0x4D, 0x52}), - // Skype audio compression + // Skype audio compression (FileType.SIL, new byte[] {0x23, 0x21, 0x53, 0x49, 0x4C, 0x4B, 0x0A}), - // Radiance High Dynamic Range image file + // Radiance High Dynamic Range image file (FileType.HDR, new byte[] {0x23, 0x3F, 0x52, 0x41, 0x44, 0x49, 0x41, 0x4E}), - // VBScript Encoded script + // VBScript Encoded script (FileType.VBE, new byte[] {0x23, 0x40, 0x7E, 0x5E}), - // Brother-Babylock-Bernina Home Embroidery + // Brother-Babylock-Bernina Home Embroidery (FileType.PEC, new byte[] {0x23, 0x50, 0x45, 0x43, 0x30, 0x30, 0x30, 0x31}), - // Brother-Babylock-Bernina Home Embroidery + // Brother-Babylock-Bernina Home Embroidery (FileType.PES, new byte[] {0x23, 0x50, 0x45, 0x53, 0x30}), - // SPSS Data file + // SPSS Data file (FileType.SAV, new byte[] {0x24, 0x46, 0x4C, 0x32, 0x40, 0x28, 0x23, 0x29}), - // Encapsulated PostScript file + // Encapsulated PostScript file (FileType.EPS, new byte[] {0x25, 0x21, 0x50, 0x53, 0x2D, 0x41, 0x64, 0x6F}), - // PDF file + // PDF file (FileType.PDF, new byte[] {0x25, 0x50, 0x44, 0x46}), - // PDF file + // PDF file (FileType.FDF, new byte[] {0x25, 0x50, 0x44, 0x46}), - // Fuzzy bitmap (FBM) file + // Fuzzy bitmap (FBM) file (FileType.FBM, new byte[] {0x25, 0x62, 0x69, 0x74, 0x6D, 0x61, 0x70}), - // BinHex 4 Compressed Archive + // BinHex 4 Compressed Archive (FileType.HQX, new byte[] {0x28, 0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69}), - // Symantec Wise Installer log + // Symantec Wise Installer log (FileType.LOG, new byte[] {0x2A, 0x2A, 0x2A, 0x20, 0x20, 0x49, 0x6E, 0x73}), - // Compressed archive + // Compressed archive (FileType.LHA, new byte[] {0x2D, 0x6C, 0x68}), - // Compressed archive + // Compressed archive (FileType.LZH, new byte[] {0x2D, 0x6C, 0x68}), - // RealPlayer video file (V11+) + // RealPlayer video file (V11+) (FileType.IVR, new byte[] {0x2E, 0x52, 0x45, 0x43}), - // RealMedia streaming media + // RealMedia streaming media (FileType.RM, new byte[] {0x2E, 0x52, 0x4D, 0x46}), - // RealMedia streaming media + // RealMedia streaming media (FileType.RMVB, new byte[] {0x2E, 0x52, 0x4D, 0x46}), - // RealAudio file + // RealAudio file (FileType.RA, new byte[] {0x2E, 0x52, 0x4D, 0x46, 0x00, 0x00, 0x00, 0x12}), - // RealAudio streaming media + // RealAudio streaming media (FileType.RA, new byte[] {0x2E, 0x72, 0x61, 0xFD, 0x00}), - // NeXT-Sun Microsystems audio file + // NeXT-Sun Microsystems audio file (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 - }), + // 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}), - // MS security catalog file + // MS security catalog file (FileType.CAT, new byte[] {0x30}), - // Windows Event Viewer file + // Windows Event Viewer file (FileType.EVT, new byte[] {0x30, 0x00, 0x00, 0x00, 0x4C, 0x66, 0x4C, 0x65}), - // GEnealogical Data COMmunication (GEDCOM) file + // GEnealogical Data COMmunication (GEDCOM) file (FileType.GED, new byte[] {0x30, 0x20, 0x48, 0x45, 0x41, 0x44}), - // Windows Media Audio-Video File + // Windows Media Audio-Video File (FileType.ASF, new byte[] {0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11}), - // Windows Media Audio-Video File + // Windows Media Audio-Video File (FileType.WMA, new byte[] {0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11}), - // Windows Media Audio-Video File + // Windows Media Audio-Video File (FileType.WMV, new byte[] {0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11}), - // National Transfer Format Map + // National Transfer Format Map (FileType.NTF, new byte[] {0x30, 0x31, 0x4F, 0x52, 0x44, 0x4E, 0x41, 0x4E}), - // MS Write file_1 + // MS Write file_1 (FileType.WRI, new byte[] {0x31, 0xBE}), - // MS Write file_2 + // MS Write file_2 (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 - }), + // Pfaff Home Embroidery + (FileType.PCS, new byte[] {0x32, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xFF, 0x00}), - // 7-Zip compressed file + // 7-Zip compressed file (FileType._7Z, new byte[] {0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C}), - // Photoshop image + // Photoshop image (FileType.PSD, new byte[] {0x38, 0x42, 0x50, 0x53}), - // Surfplan kite project file + // Surfplan kite project file (FileType.SLE, new byte[] {0x3A, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4F, 0x4E}), - // Advanced Stream Redirector + // Advanced Stream Redirector (FileType.ASX, new byte[] {0x3C}), - // BizTalk XML-Data Reduced Schema + // BizTalk XML-Data Reduced Schema (FileType.XDR, new byte[] {0x3C}), - // AOL HTML mail + // AOL HTML mail (FileType.DCI, new byte[] {0x3C, 0x21, 0x64, 0x6F, 0x63, 0x74, 0x79, 0x70}), - // Windows Script Component + // Windows Script Component (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}), + // Windows Visual Stylesheet + (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 - }), + // 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}), - // 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 - }), + // 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}), - // Picasa movie project file - (FileType.MXF, - new byte[] - { - 0x3C, 0x43, 0x54, 0x72, 0x61, 0x6E, 0x73, 0x54, 0x69, 0x6D, 0x65, 0x6C, 0x69, 0x6E, 0x65, 0x3E - }), + // Picasa movie project file + (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 - }), + // Csound music + (FileType.CSD, new byte[] {0x3C, 0x43, 0x73, 0x6F, 0x75, 0x6E, 0x64, 0x53, 0x79, 0x6E, 0x74, 0x68, 0x65, 0x73, 0x69, 0x7A}), - // Adobe FrameMaker + // Adobe FrameMaker (FileType.FM, new byte[] {0x3C, 0x4D, 0x61, 0x6B, 0x65, 0x72, 0x46, 0x69}), - // Adobe FrameMaker + // Adobe FrameMaker (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 - }), + // GPS Exchange (v1.1) + (FileType.GPX, new byte[] {0x3C, 0x67, 0x70, 0x78, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3D, 0x22, 0x31, 0x2E}), - // BASE85 file + // BASE85 file (FileType.B85, new byte[] {0x3C, 0x7E, 0x36, 0x3C, 0x5C, 0x25, 0x5F, 0x30, 0x67, 0x53, 0x71, 0x68, 0x3B}), - // Quatro Pro for Windows 7.0 + // Quatro Pro for Windows 7.0 (FileType.WB3, new byte[] {0x3E, 0x00, 0x03, 0x00, 0xFE, 0xFF, 0x09, 0x00, 0x06}), - // Windows Help file_2 + // Windows Help file_2 (FileType.GID, new byte[] {0x3F, 0x5F, 0x03, 0x00}), - // Windows Help file_2 + // Windows Help file_2 (FileType.HLP, new byte[] {0x3F, 0x5F, 0x03, 0x00}), - // EndNote Library File + // EndNote Library File (FileType.ENL, new byte[] {0x40, 0x40, 0x40, 0x20, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40}), - // Generic AutoCAD drawing + // Generic AutoCAD drawing (FileType.DWG, new byte[] {0x41, 0x43, 0x31, 0x30}), - // Steganos virtual secure drive + // Steganos virtual secure drive (FileType.SLE, new byte[] {0x41, 0x43, 0x76}), - // Harvard Graphics symbol graphic + // Harvard Graphics symbol graphic (FileType.SYW, new byte[] {0x41, 0x4D, 0x59, 0x4F}), - // AOL config files + // AOL config files (FileType.ABI, new byte[] {0x41, 0x4F, 0x4C}), - // AOL config files + // AOL config files (FileType.ABY, new byte[] {0x41, 0x4F, 0x4C}), - // AOL config files + // AOL config files (FileType.BAG, new byte[] {0x41, 0x4F, 0x4C}), - // AOL config files + // AOL config files (FileType.IDX, new byte[] {0x41, 0x4F, 0x4C}), - // AOL config files + // AOL config files (FileType.IND, new byte[] {0x41, 0x4F, 0x4C}), - // AOL config files + // AOL config files (FileType.PFC, new byte[] {0x41, 0x4F, 0x4C}), - // AOL and AIM buddy list + // AOL and AIM buddy list (FileType.BAG, new byte[] {0x41, 0x4F, 0x4C, 0x20, 0x46, 0x65, 0x65, 0x64}), - // AOL address book + // AOL address book (FileType.ABY, new byte[] {0x41, 0x4F, 0x4C, 0x44, 0x42}), - // AOL user configuration + // AOL user configuration (FileType.IDX, new byte[] {0x41, 0x4F, 0x4C, 0x44, 0x42}), - // AOL client preferences-settings file + // AOL client preferences-settings file (FileType.IND, new byte[] {0x41, 0x4F, 0x4C, 0x49, 0x44, 0x58}), - // AOL address book index + // AOL address book index (FileType.ABI, new byte[] {0x41, 0x4F, 0x4C, 0x49, 0x4E, 0x44, 0x45, 0x58}), - // AOL personal file cabinet + // AOL personal file cabinet (FileType.ORG, new byte[] {0x41, 0x4F, 0x4C, 0x56, 0x4D, 0x31, 0x30, 0x30}), - // AOL personal file cabinet + // AOL personal file cabinet (FileType.PFC, new byte[] {0x41, 0x4F, 0x4C, 0x56, 0x4D, 0x31, 0x30, 0x30}), - // AVG6 Integrity database + // AVG6 Integrity database (FileType.DAT, new byte[] {0x41, 0x56, 0x47, 0x36, 0x5F, 0x49, 0x6E, 0x74}), - // RIFF Windows Audio + // RIFF Windows Audio (FileType.AVI, new byte[] {0x41, 0x56, 0x49, 0x20, 0x4C, 0x49, 0x53, 0x54}), - // FreeArc compressed file + // FreeArc compressed file (FileType.ARC, new byte[] {0x41, 0x72, 0x43, 0x01}), - // vCard + // vCard (FileType.VCF, new byte[] {0x42, 0x45, 0x47, 0x49, 0x4E, 0x3A, 0x56, 0x43}), - // Speedtouch router firmware + // Speedtouch router firmware (FileType.BIN, new byte[] {0x42, 0x4C, 0x49, 0x32, 0x32, 0x33}), - // Speedtouch router firmware + // Speedtouch router firmware (FileType.BLI, new byte[] {0x42, 0x4C, 0x49, 0x32, 0x32, 0x33}), - // Speedtouch router firmware + // Speedtouch router firmware (FileType.RBI, new byte[] {0x42, 0x4C, 0x49, 0x32, 0x32, 0x33}), - // Bitmap image + // Bitmap image (FileType.BMP, new byte[] {0x42, 0x4D}), - // Bitmap image + // Bitmap image (FileType.DIB, new byte[] {0x42, 0x4D}), - // Palmpilot resource file + // Palmpilot resource file (FileType.PRC, new byte[] {0x42, 0x4F, 0x4F, 0x4B, 0x4D, 0x4F, 0x42, 0x49}), - // Better Portable Graphics + // Better Portable Graphics (FileType.BPG, new byte[] {0x42, 0x50, 0x47, 0xFB}), - // bzip2 compressed archive + // bzip2 compressed archive (FileType.BZ2, new byte[] {0x42, 0x5A, 0x68}), - // bzip2 compressed archive + // bzip2 compressed archive (FileType.TAR, new byte[] {0x42, 0x5A, 0x68}), - // bzip2 compressed archive + // bzip2 compressed archive (FileType.BZ2, new byte[] {0x42, 0x5A, 0x68}), - // bzip2 compressed archive + // bzip2 compressed archive (FileType.TBZ2, new byte[] {0x42, 0x5A, 0x68}), - // bzip2 compressed archive + // bzip2 compressed archive (FileType.TB2, new byte[] {0x42, 0x5A, 0x68}), - // Mac Disk image (BZ2 compressed) + // Mac Disk image (BZ2 compressed) (FileType.DMG, new byte[] {0x42, 0x5A, 0x68}), - // Puffer ASCII encrypted archive + // Puffer ASCII encrypted archive (FileType.APUF, new byte[] {0x42, 0x65, 0x67, 0x69, 0x6E, 0x20, 0x50, 0x75, 0x66, 0x66, 0x65, 0x72}), - // Blink compressed archive + // Blink compressed archive (FileType.BLI, new byte[] {0x42, 0x6C, 0x69, 0x6E, 0x6B}), - // RagTime document + // RagTime document (FileType.RTD, new byte[] {0x43, 0x23, 0x2B, 0x44, 0xA4, 0x43, 0x4D, 0xA5}), - // EA Interchange Format File (IFF)_3 + // EA Interchange Format File (IFF)_3 (FileType.IFF, new byte[] {0x43, 0x41, 0x54, 0x20}), - // WordPerfect dictionary + // WordPerfect dictionary (FileType.CBD, new byte[] {0x43, 0x42, 0x46, 0x49, 0x4C, 0x45}), - // ISO-9660 CD Disc Image + // ISO-9660 CD Disc Image (FileType.ISO, new byte[] {0x43, 0x44, 0x30, 0x30, 0x31}), - // RIFF CD audio + // RIFF CD audio (FileType.CDA, new byte[] {0x43, 0x44, 0x44, 0x41, 0x66, 0x6D, 0x74, 0x20}), - // Compressed ISO CD image + // Compressed ISO CD image (FileType.CSO, new byte[] {0x43, 0x49, 0x53, 0x4F}), - // Windows 7 thumbnail + // Windows 7 thumbnail (FileType.DB, new byte[] {0x43, 0x4D, 0x4D, 0x4D, 0x15, 0x00, 0x00, 0x00}), - // Corel Binary metafile + // Corel Binary metafile (FileType.CLB, new byte[] {0x43, 0x4D, 0x58, 0x31}), - // COM+ Catalog + // COM+ Catalog (FileType.CLB, new byte[] {0x43, 0x4F, 0x4D, 0x2B}), - // VMware 3 Virtual Disk + // VMware 3 Virtual Disk (FileType.VMDK, new byte[] {0x43, 0x4F, 0x57, 0x44}), - // Corel Photopaint file_1 + // Corel Photopaint file_1 (FileType.CPT, new byte[] {0x43, 0x50, 0x54, 0x37, 0x46, 0x49, 0x4C, 0x45}), - // Corel Photopaint file_2 + // Corel Photopaint file_2 (FileType.CPT, new byte[] {0x43, 0x50, 0x54, 0x46, 0x49, 0x4C, 0x45}), - // Win9x registry hive + // Win9x registry hive (FileType.DAT, new byte[] {0x43, 0x52, 0x45, 0x47}), - // Crush compressed archive + // Crush compressed archive (FileType.CRU, new byte[] {0x43, 0x52, 0x55, 0x53, 0x48, 0x20, 0x76}), - // Shockwave Flash file + // Shockwave Flash file (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 - }), + // 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}), - // WhereIsIt Catalog + // WhereIsIt Catalog (FileType.CTF, new byte[] {0x43, 0x61, 0x74, 0x61, 0x6C, 0x6F, 0x67, 0x20}), - // IE History file + // IE History file (FileType.DAT, new byte[] {0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x55}), - // Google Chrome Extension + // Google Chrome Extension (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 - }), + // Creative Voice + (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 + // PowerISO Direct-Access-Archive image (FileType.DAA, new byte[] {0x44, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00}), - // DAX Compressed CD image + // DAX Compressed CD image (FileType.DAX, new byte[] {0x44, 0x41, 0x58, 0x00}), - // Palm Zire photo database + // Palm Zire photo database (FileType.DB, new byte[] {0x44, 0x42, 0x46, 0x48}), - // Amiga DiskMasher compressed archive + // Amiga DiskMasher compressed archive (FileType.DMS, new byte[] {0x44, 0x4D, 0x53, 0x21}), - // Amiga disk file + // Amiga disk file (FileType.ADF, new byte[] {0x44, 0x4F, 0x53}), - // DST Compression + // DST Compression (FileType.DST, new byte[] {0x44, 0x53, 0x54, 0x62}), - // DVR-Studio stream file + // DVR-Studio stream file (FileType.DVR, new byte[] {0x44, 0x56, 0x44}), - // DVD info file + // DVD info file (FileType.IFO, new byte[] {0x44, 0x56, 0x44}), - // Elite Plus Commander game file + // Elite Plus Commander game file (FileType.CDR, new byte[] {0x45, 0x4C, 0x49, 0x54, 0x45, 0x20, 0x43, 0x6F}), - // VideoVCD-VCDImager file + // VideoVCD-VCDImager file (FileType.VCD, new byte[] {0x45, 0x4E, 0x54, 0x52, 0x59, 0x56, 0x43, 0x44}), - // Apple ISO 9660-HFS hybrid CD image + // Apple ISO 9660-HFS hybrid CD image (FileType.ISO, new byte[] {0x45, 0x52, 0x02, 0x00, 0x00}), - // EasyRecovery Saved State file + // EasyRecovery Saved State file (FileType.DAT, new byte[] {0x45, 0x52, 0x46, 0x53, 0x53, 0x41, 0x56, 0x45}), - // DSD Storage Facility audio file + // DSD Storage Facility audio file (FileType.DSF, new byte[] {0x44, 0x53, 0x44, 0x20}), - // MS Document Imaging file + // MS Document Imaging file (FileType.MDI, new byte[] {0x45, 0x50}), - // Expert Witness Compression Format + // Expert Witness Compression Format (FileType.E01, new byte[] {0x45, 0x56, 0x46, 0x09, 0x0D, 0x0A, 0xFF, 0x00}), - // EnCase Evidence File Format V2 + // EnCase Evidence File Format V2 (FileType.Ex01, new byte[] {0x45, 0x56, 0x46, 0x32, 0x0D, 0x0A, 0x81}), - // Windows Vista event log + // Windows Vista event log (FileType.EVTX, new byte[] {0x45, 0x6C, 0x66, 0x46, 0x69, 0x6C, 0x65, 0x00}), - // QuickBooks backup + // QuickBooks backup (FileType.QBB, new byte[] {0x45, 0x86, 0x00, 0x00, 0x06, 0x00}), - // MS Fax Cover Sheet + // MS Fax Cover Sheet (FileType.CPE, new byte[] {0x46, 0x41, 0x58, 0x43, 0x4F, 0x56, 0x45, 0x52}), - // Fiasco database definition file + // Fiasco database definition file (FileType.FDB, new byte[] {0x46, 0x44, 0x42, 0x48, 0x00}), - // Flash video file + // Flash video file (FileType.FLV, new byte[] {0x46, 0x4C, 0x56}), - // IFF ANIM file + // IFF ANIM file (FileType.ANM, new byte[] {0x46, 0x4F, 0x52, 0x4D}), - // EA Interchange Format File (IFF)_1 + // EA Interchange Format File (IFF)_1 (FileType.IFF, new byte[] {0x46, 0x4F, 0x52, 0x4D}), - // Audio Interchange File + // Audio Interchange File (FileType.AIFF, new byte[] {0x46, 0x4F, 0x52, 0x4D, 0x00}), - // DAKX Compressed Audio + // DAKX Compressed Audio (FileType.DAX, new byte[] {0x46, 0x4F, 0x52, 0x4D, 0x00}), - // Shockwave Flash player + // Shockwave Flash player (FileType.SWF, new byte[] {0x46, 0x57, 0x53}), - // Generic e-mail_2 + // Generic e-mail_2 (FileType.EML, new byte[] {0x46, 0x72, 0x6F, 0x6D}), - // GIF file + // GIF file (FileType.GIF, new byte[] {0x47, 0x49, 0x46, 0x38}), - // GIMP pattern file + // GIMP pattern file (FileType.PAT, new byte[] {0x47, 0x50, 0x41, 0x54}), - // General Regularly-distributed Information (GRIdded) Binary + // General Regularly-distributed Information (GRIdded) Binary (FileType.GRB, new byte[] {0x47, 0x52, 0x49, 0x42}), - // Show Partner graphics file + // Show Partner graphics file (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 - }), + // Genetec video archive + (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 - }), + // SAS Transport dataset + (FileType.XPT, new byte[] {0x48, 0x45, 0x41, 0x44, 0x45, 0x52, 0x20, 0x52, 0x45, 0x43, 0x4F, 0x52, 0x44, 0x2A, 0x2A, 0x2A}), - // Harvard Graphics presentation file + // Harvard Graphics presentation file (FileType.SH3, new byte[] {0x48, 0x48, 0x47, 0x42, 0x31}), - // TIFF file_1 + // TIFF file_1 (FileType.TIF, new byte[] {0x49, 0x20, 0x49}), - // TIFF file_1 + // TIFF file_1 (FileType.TIFF, new byte[] {0x49, 0x20, 0x49}), - // MP3 audio file + // MP3 audio file (FileType.MP3, new byte[] {0x49, 0x44, 0x33}), - // Sprint Music Store audio + // Sprint Music Store audio (FileType.KOZ, new byte[] {0x49, 0x44, 0x33, 0x03, 0x00, 0x00, 0x00}), - // Canon RAW file + // Canon RAW file (FileType.CRW, new byte[] {0x49, 0x49, 0x1A, 0x00, 0x00, 0x00, 0x48, 0x45}), - // TIFF file_2 + // TIFF file_2 (FileType.TIF, new byte[] {0x49, 0x49, 0x2A, 0x00}), - // TIFF file_2 + // TIFF file_2 (FileType.TIFF, new byte[] {0x49, 0x49, 0x2A, 0x00}), - // Windows 7 thumbnail_2 + // Windows 7 thumbnail_2 (FileType.DB, new byte[] {0x49, 0x4D, 0x4D, 0x4D, 0x15, 0x00, 0x00, 0x00}), - // Install Shield compressed file + // Install Shield compressed file (FileType.CAB, new byte[] {0x49, 0x53, 0x63, 0x28}), - // Install Shield compressed file + // Install Shield compressed file (FileType.HDR, new byte[] {0x49, 0x53, 0x63, 0x28}), - // MS Reader eBook + // MS Reader eBook (FileType.LIT, new byte[] {0x49, 0x54, 0x4F, 0x4C, 0x49, 0x54, 0x4C, 0x53}), - // MS Compiled HTML Help File + // MS Compiled HTML Help File (FileType.CHI, new byte[] {0x49, 0x54, 0x53, 0x46}), - // MS Compiled HTML Help File + // MS Compiled HTML Help File (FileType.CHM, new byte[] {0x49, 0x54, 0x53, 0x46}), - // Inno Setup Uninstall Log + // Inno Setup Uninstall Log (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 - }), + // 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}), - // JARCS compressed archive + // JARCS compressed archive (FileType.JAR, new byte[] {0x4A, 0x41, 0x52, 0x43, 0x53, 0x00}), - // AOL ART file_1 + // AOL ART file_1 (FileType.JG, new byte[] {0x4A, 0x47, 0x03, 0x0E}), - // AOL ART file_2 + // AOL ART file_2 (FileType.JG, new byte[] {0x4A, 0x47, 0x04, 0x0E}), - // VMware 4 Virtual Disk + // VMware 4 Virtual Disk (FileType.VMDK, new byte[] {0x4B, 0x44, 0x4D}), - // KGB archive + // KGB archive (FileType.KGB, new byte[] {0x4B, 0x47, 0x42, 0x5F, 0x61, 0x72, 0x63, 0x68}), - // Win9x printer spool file + // Win9x printer spool file (FileType.SHD, new byte[] {0x4B, 0x49, 0x00, 0x00}), - // Windows shortcut file + // Windows shortcut file (FileType.LNK, new byte[] {0x4C, 0x00, 0x00, 0x00, 0x01, 0x14, 0x02, 0x00}), - // MS COFF relocatable object code + // MS COFF relocatable object code (FileType.OBJ, new byte[] {0x4C, 0x01}), - // Tajima emboridery + // Tajima emboridery (FileType.DST, new byte[] {0x4C, 0x41, 0x3A}), - // Windows help file_3 + // Windows help file_3 (FileType.GID, new byte[] {0x4C, 0x4E, 0x02, 0x00}), - // Windows help file_3 + // Windows help file_3 (FileType.HLP, new byte[] {0x4C, 0x4E, 0x02, 0x00}), - // EA Interchange Format File (IFF)_2 + // EA Interchange Format File (IFF)_2 (FileType.IFF, new byte[] {0x4C, 0x49, 0x53, 0x54}), - // DeluxePaint Animation + // DeluxePaint Animation (FileType.ANM, new byte[] {0x4C, 0x50, 0x46, 0x20, 0x00, 0x01}), - // Logical File Evidence Format + // Logical File Evidence Format (FileType.E01, new byte[] {0x4C, 0x56, 0x46, 0x09, 0x0D, 0x0A, 0xFF, 0x00}), - // Merriam-Webster Pocket Dictionary + // Merriam-Webster Pocket Dictionary (FileType.PDB, new byte[] {0x4D, 0x2D, 0x57, 0x20, 0x50, 0x6F, 0x63, 0x6B}), - // Mozilla archive + // Mozilla archive (FileType.MAR, new byte[] {0x4D, 0x41, 0x52, 0x31, 0x00}), - // Microsoft-MSN MARC archive + // Microsoft-MSN MARC archive (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 - }), + // 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}), - // MAr compressed archive + // 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 - }), + // TargetExpress target file + (FileType.MTE, new byte[] {0x4D, 0x43, 0x57, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x67, 0x6F, 0x6C, 0x69, 0x65, 0x73}), - // Windows dump file + // Windows dump file (FileType.DMP, new byte[] {0x4D, 0x44, 0x4D, 0x50, 0x93, 0xA7}), - // Windows dump file + // Windows dump file (FileType.HDMP, new byte[] {0x4D, 0x44, 0x4D, 0x50, 0x93, 0xA7}), - // Milestones project management file + // Milestones project management file (FileType.MLS, new byte[] {0x4D, 0x49, 0x4C, 0x45, 0x53}), - // Skype localization data file + // Skype localization data file (FileType.MLS, new byte[] {0x4D, 0x4C, 0x53, 0x57}), - // TIFF file_3 + // TIFF file_3 (FileType.TIF, new byte[] {0x4D, 0x4D, 0x00, 0x2A}), - // TIFF file_3 + // TIFF file_3 (FileType.TIFF, new byte[] {0x4D, 0x4D, 0x00, 0x2A}), - // TIFF file_4 + // TIFF file_4 (FileType.TIF, new byte[] {0x4D, 0x4D, 0x00, 0x2B}), - // TIFF file_4 + // TIFF file_4 (FileType.TIFF, new byte[] {0x4D, 0x4D, 0x00, 0x2B}), - // Yamaha Synthetic music Mobile Application Format + // Yamaha Synthetic music Mobile Application Format (FileType.MMF, new byte[] {0x4D, 0x4D, 0x4D, 0x44, 0x00, 0x00}), - // VMware BIOS state file + // VMware BIOS state file (FileType.NVRAM, new byte[] {0x4D, 0x52, 0x56, 0x4E}), - // Microsoft cabinet file + // Microsoft cabinet file (FileType.CAB, new byte[] {0x4D, 0x53, 0x43, 0x46}), - // OneNote Package + // OneNote Package (FileType.ONEPKG, new byte[] {0x4D, 0x53, 0x43, 0x46}), - // Powerpoint Packaged Presentation + // Powerpoint Packaged Presentation (FileType.PPZ, new byte[] {0x4D, 0x53, 0x43, 0x46}), - // MS Access Snapshot Viewer file + // MS Access Snapshot Viewer file (FileType.SNP, new byte[] {0x4D, 0x53, 0x43, 0x46}), - // OLE-SPSS-Visual C++ library file + // OLE-SPSS-Visual C++ library file (FileType.TLB, new byte[] {0x4D, 0x53, 0x46, 0x54, 0x02, 0x00, 0x01, 0x00}), - // Microsoft Windows Imaging Format + // Microsoft Windows Imaging Format (FileType.WIM, new byte[] {0x4D, 0x53, 0x57, 0x49, 0x4D}), - // Sony Compressed Voice File + // Sony Compressed Voice File (FileType.CDR, new byte[] {0x4D, 0x53, 0x5F, 0x56, 0x4F, 0x49, 0x43, 0x45}), - // Sony Compressed Voice File + // Sony Compressed Voice File (FileType.DVF, new byte[] {0x4D, 0x53, 0x5F, 0x56, 0x4F, 0x49, 0x43, 0x45}), - // Sony Compressed Voice File + // Sony Compressed Voice File (FileType.MSV, new byte[] {0x4D, 0x53, 0x5F, 0x56, 0x4F, 0x49, 0x43, 0x45}), - // MIDI sound file + // MIDI sound file (FileType.MID, new byte[] {0x4D, 0x54, 0x68, 0x64}), - // MIDI sound file + // MIDI sound file (FileType.MIDI, new byte[] {0x4D, 0x54, 0x68, 0x64}), - // Yamaha Piano + // Yamaha Piano (FileType.PCS, new byte[] {0x4D, 0x54, 0x68, 0x64}), - // CD Stomper Pro label file + // CD Stomper Pro label file (FileType.DSN, new byte[] {0x4D, 0x56}), - // Milestones project management file_1 + // Milestones project management file_1 (FileType.MLS, new byte[] {0x4D, 0x56, 0x32, 0x31, 0x34}), - // Milestones project management file_2 + // Milestones project management file_2 (FileType.MLS, new byte[] {0x4D, 0x56, 0x32, 0x43}), - // Windows-DOS executable file + // Windows-DOS executable file (FileType.COM, new byte[] {0x4D, 0x5A}), - // Windows-DOS executable file + // Windows-DOS executable file (FileType.DLL, new byte[] {0x4D, 0x5A}), - // Windows-DOS executable file + // Windows-DOS executable file (FileType.DRV, new byte[] {0x4D, 0x5A}), - // Windows-DOS executable file + // Windows-DOS executable file (FileType.EXE, new byte[] {0x4D, 0x5A}), - // Windows-DOS executable file + // Windows-DOS executable file (FileType.PIF, new byte[] {0x4D, 0x5A}), - // Windows-DOS executable file + // Windows-DOS executable file (FileType.QTS, new byte[] {0x4D, 0x5A}), - // Windows-DOS executable file + // Windows-DOS executable file (FileType.QTX, new byte[] {0x4D, 0x5A}), - // Windows-DOS executable file + // Windows-DOS executable file (FileType.SYS, new byte[] {0x4D, 0x5A}), - // MS audio compression manager driver + // MS audio compression manager driver (FileType.ACM, new byte[] {0x4D, 0x5A}), - // Library cache file + // Library cache file (FileType.AX, new byte[] {0x4D, 0x5A}), - // Control panel application + // Control panel application (FileType.CPL, new byte[] {0x4D, 0x5A}), - // Font file + // Font file (FileType.FON, new byte[] {0x4D, 0x5A}), - // ActiveX-OLE Custom Control + // ActiveX-OLE Custom Control (FileType.OCX, new byte[] {0x4D, 0x5A}), - // OLE object library + // OLE object library (FileType.OLB, new byte[] {0x4D, 0x5A}), - // Screen saver + // Screen saver (FileType.SCR, new byte[] {0x4D, 0x5A}), - // VisualBASIC application + // VisualBASIC application (FileType.VBX, new byte[] {0x4D, 0x5A}), - // Windows virtual device drivers + // Windows virtual device drivers (FileType.VXD, new byte[] {0x4D, 0x5A}), - // Windows virtual device drivers + // Windows virtual device drivers (FileType._386, new byte[] {0x4D, 0x5A}), - // Acrobat plug-in + // Acrobat plug-in (FileType.API, new byte[] {0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00}), - // DirectShow filter + // DirectShow filter (FileType.AX, new byte[] {0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00}), - // Audition graphic filter + // Audition graphic filter (FileType.FLT, new byte[] {0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00}), - // ZoneAlam data file + // ZoneAlam data file (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 - }), + // 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}), - // Visual Studio .NET file - (FileType.SLN, - new byte[] - { - 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x56, 0x69, 0x73, 0x75, 0x61, 0x6C - }), + // Visual Studio .NET file + (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 - }), + // 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}), - // VMapSource GPS Waypoint Database + // VMapSource GPS Waypoint Database (FileType.GDB, new byte[] {0x4D, 0x73, 0x52, 0x63, 0x66}), - // TomTom traffic data + // TomTom traffic data (FileType.DAT, new byte[] {0x4E, 0x41, 0x56, 0x54, 0x52, 0x41, 0x46, 0x46}), - // MS Windows journal + // MS Windows journal (FileType.JNT, new byte[] {0x4E, 0x42, 0x2A, 0x00}), - // MS Windows journal + // MS Windows journal (FileType.JTP, new byte[] {0x4E, 0x42, 0x2A, 0x00}), - // NES Sound file + // NES Sound file (FileType.NSF, new byte[] {0x4E, 0x45, 0x53, 0x4D, 0x1A, 0x01}), - // National Imagery Transmission Format file + // National Imagery Transmission Format file (FileType.NTF, new byte[] {0x4E, 0x49, 0x54, 0x46, 0x30}), - // Agent newsreader character map + // Agent newsreader character map (FileType.COD, new byte[] {0x4E, 0x61, 0x6D, 0x65, 0x3A, 0x20}), - // 1Password 4 Cloud Keychain + // 1Password 4 Cloud Keychain (FileType.attachment, new byte[] {0x4F, 0x50, 0x43, 0x4C, 0x44, 0x41, 0x54}), - // Psion Series 3 Database + // Psion Series 3 Database (FileType.DBF, new byte[] {0x4F, 0x50, 0x4C, 0x44, 0x61, 0x74, 0x61, 0x62}), - // OpenType font + // OpenType font (FileType.OTF, new byte[] {0x4F, 0x54, 0x54, 0x4F, 0x00}), - // Ogg Vorbis Codec compressed file + // Ogg Vorbis Codec compressed file (FileType.OGA, new byte[] {0x4F, 0x67, 0x67, 0x53, 0x00, 0x02, 0x00, 0x00}), - // Ogg Vorbis Codec compressed file + // Ogg Vorbis Codec compressed file (FileType.OGG, new byte[] {0x4F, 0x67, 0x67, 0x53, 0x00, 0x02, 0x00, 0x00}), - // Ogg Vorbis Codec compressed file + // Ogg Vorbis Codec compressed file (FileType.OGV, new byte[] {0x4F, 0x67, 0x67, 0x53, 0x00, 0x02, 0x00, 0x00}), - // Ogg Vorbis Codec compressed file + // Ogg Vorbis Codec compressed file (FileType.OGX, new byte[] {0x4F, 0x67, 0x67, 0x53, 0x00, 0x02, 0x00, 0x00}), - // Visio-DisplayWrite 4 text file + // Visio-DisplayWrite 4 text file (FileType.DW4, new byte[] {0x4F, 0x7B}), - // Quicken QuickFinder Information File + // Quicken QuickFinder Information File (FileType.IDX, new byte[] {0x50, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}), - // Portable Graymap Graphic + // Portable Graymap Graphic (FileType.PGM, new byte[] {0x50, 0x35, 0x0A}), - // Quake archive file + // Quake archive file (FileType.PAK, new byte[] {0x50, 0x41, 0x43, 0x4B}), - // Windows memory dump + // Windows memory dump (FileType.DMP, new byte[] {0x50, 0x41, 0x47, 0x45, 0x44, 0x55}), - // PAX password protected bitmap + // PAX password protected bitmap (FileType.PAX, new byte[] {0x50, 0x41, 0x58}), - // PestPatrol data-scan strings + // PestPatrol data-scan strings (FileType.DAT, new byte[] {0x50, 0x45, 0x53, 0x54}), - // PGP disk image + // PGP disk image (FileType.PGD, new byte[] {0x50, 0x47, 0x50, 0x64, 0x4D, 0x41, 0x49, 0x4E}), - // ChromaGraph Graphics Card Bitmap + // ChromaGraph Graphics Card Bitmap (FileType.IMG, new byte[] {0x50, 0x49, 0x43, 0x54, 0x00, 0x08}), - // PKZIP archive_1 + // PKZIP archive_1 (FileType.ZIP, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // Android package + // Android package (FileType.APK, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // MacOS X Dashboard Widget + // MacOS X Dashboard Widget (FileType.ZIP, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // MS Office Open XML Format Document + // MS Office Open XML Format Document (FileType.DOCX, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // MS Office Open XML Format Document + // MS Office Open XML Format Document (FileType.PPTX, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // MS Office Open XML Format Document + // MS Office Open XML Format Document (FileType.XLSX, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // Java archive_1 + // Java archive_1 (FileType.JAR, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // Google Earth session file + // Google Earth session file (FileType.KMZ, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // KWord document + // KWord document (FileType.KWD, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // OpenDocument template + // OpenDocument template (FileType.ODT, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // OpenDocument template + // OpenDocument template (FileType.ODP, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // OpenDocument template + // OpenDocument template (FileType.OTT, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // Microsoft Open XML paper specification + // Microsoft Open XML paper specification (FileType.OXPS, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // OpenOffice documents + // OpenOffice documents (FileType.SXC, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // OpenOffice documents + // OpenOffice documents (FileType.SXD, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // OpenOffice documents + // OpenOffice documents (FileType.SXI, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // OpenOffice documents + // OpenOffice documents (FileType.SXW, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // StarOffice spreadsheet + // StarOffice spreadsheet (FileType.SXC, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // Windows Media compressed skin file + // Windows Media compressed skin file (FileType.WMZ, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // Mozilla Browser Archive + // Mozilla Browser Archive (FileType.XPI, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // XML paper specification file + // XML paper specification file (FileType.XPS, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // eXact Packager Models + // eXact Packager Models (FileType.XPT, new byte[] {0x50, 0x4B, 0x03, 0x04}), - // Open Publication Structure eBook + // Open Publication Structure eBook (FileType.EPUB, new byte[] {0x50, 0x4B, 0x03, 0x04, 0x0A, 0x00, 0x02, 0x00}), - // ZLock Pro encrypted ZIP + // ZLock Pro encrypted ZIP (FileType.ZIP, new byte[] {0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x01, 0x00}), - // MS Office 2007 documents + // MS Office 2007 documents (FileType.DOCX, new byte[] {0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00}), - // MS Office 2007 documents + // MS Office 2007 documents (FileType.PPTX, new byte[] {0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00}), - // MS Office 2007 documents + // MS Office 2007 documents (FileType.XLSX, new byte[] {0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x06, 0x00}), - // Java archive_2 + // Java archive_2 (FileType.JAR, new byte[] {0x50, 0x4B, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00}), - // PKZIP archive_2 + // PKZIP archive_2 (FileType.ZIP, new byte[] {0x50, 0x4B, 0x05, 0x06}), - // PKZIP archive_3 + // PKZIP archive_3 (FileType.ZIP, new byte[] {0x50, 0x4B, 0x07, 0x08}), - // PKLITE archive + // PKLITE archive (FileType.ZIP, new byte[] {0x50, 0x4B, 0x4C, 0x49, 0x54, 0x45}), - // PKSFX self-extracting archive + // PKSFX self-extracting archive (FileType.ZIP, new byte[] {0x50, 0x4B, 0x53, 0x70, 0x58}), - // Windows Program Manager group file + // Windows Program Manager group file (FileType.GRP, new byte[] {0x50, 0x4D, 0x43, 0x43}), - // Norton Disk Doctor undo file + // Norton Disk Doctor undo file (FileType.DAT, new byte[] {0x50, 0x4E, 0x43, 0x49, 0x55, 0x4E, 0x44, 0x4F}), - // Microsoft Windows User State Migration Tool + // Microsoft Windows User State Migration Tool (FileType.PMOCCMOC, new byte[] {0x50, 0x4D, 0x4F, 0x43, 0x43, 0x4D, 0x4F, 0x43}), - // Dreamcast Sound Format + // Dreamcast Sound Format (FileType.DSF, new byte[] {0x50, 0x53, 0x46, 0x12}), - // Puffer encrypted archive + // Puffer encrypted archive (FileType.PUF, new byte[] {0x50, 0x55, 0x46, 0x58}), - // Quicken data + // Quicken data (FileType.QEL, new byte[] {0x51, 0x45, 0x4C, 0x20}), - // Qcow Disk Image + // Qcow Disk Image (FileType.QEMU, new byte[] {0x51, 0x46, 0x49}), - // RIFF Qualcomm PureVoice + // RIFF Qualcomm PureVoice (FileType.QCP, new byte[] {0x51, 0x4C, 0x43, 0x4D, 0x66, 0x6D, 0x74, 0x20}), - // Quicken data file + // Quicken data file (FileType.ABD, new byte[] {0x51, 0x57, 0x20, 0x56, 0x65, 0x72, 0x2E, 0x20}), - // Quicken data file + // Quicken data file (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 - }), + // 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}), - // Shareaza (P2P) thumbnail + // Shareaza (P2P) thumbnail (FileType.DAT, new byte[] {0x52, 0x41, 0x5A, 0x41, 0x54, 0x44, 0x42, 0x31}), - // R saved work space + // R saved work space (FileType.RDATA, new byte[] {0x52, 0x44, 0x58, 0x32, 0x0A}), - // WinNT Registry-Registry Undo files + // WinNT Registry-Registry Undo files (FileType.REG, new byte[] {0x52, 0x45, 0x47, 0x45, 0x44, 0x49, 0x54}), - // WinNT Registry-Registry Undo files + // WinNT Registry-Registry Undo files (FileType.SUD, new byte[] {0x52, 0x45, 0x47, 0x45, 0x44, 0x49, 0x54}), - // Antenna data file + // Antenna data file (FileType.AD, new byte[] {0x52, 0x45, 0x56, 0x4E, 0x55, 0x4D, 0x3A, 0x2C}), - // Windows animated cursor + // Windows animated cursor (FileType.ANI, new byte[] {0x52, 0x49, 0x46, 0x46}), - // Corel Presentation Exchange metadata + // Corel Presentation Exchange metadata (FileType.CMX, new byte[] {0x52, 0x49, 0x46, 0x46}), - // CorelDraw document + // CorelDraw document (FileType.CDR, new byte[] {0x52, 0x49, 0x46, 0x46}), - // Video CD MPEG movie + // Video CD MPEG movie (FileType.DAT, new byte[] {0x52, 0x49, 0x46, 0x46}), - // Micrografx Designer graphic + // Micrografx Designer graphic (FileType.DS4, new byte[] {0x52, 0x49, 0x46, 0x46}), - // 4X Movie video + // 4X Movie video (FileType._4XM, new byte[] {0x52, 0x49, 0x46, 0x46}), - // Resource Interchange File Format + // Resource Interchange File Format (FileType.AVI, new byte[] {0x52, 0x49, 0x46, 0x46}), - // Resource Interchange File Format + // Resource Interchange File Format (FileType.CDA, new byte[] {0x52, 0x49, 0x46, 0x46}), - // Resource Interchange File Format + // Resource Interchange File Format (FileType.QCP, new byte[] {0x52, 0x49, 0x46, 0x46}), - // Resource Interchange File Format + // Resource Interchange File Format (FileType.RMI, new byte[] {0x52, 0x49, 0x46, 0x46}), - // Resource Interchange File Format + // Resource Interchange File Format (FileType.WAV, new byte[] {0x52, 0x49, 0x46, 0x46}), - // Resource Interchange File Format + // Resource Interchange File Format (FileType.WEBP, new byte[] {0x52, 0x49, 0x46, 0x46}), - // RIFF Windows MIDI + // RIFF Windows MIDI (FileType.RMI, new byte[] {0x52, 0x4D, 0x49, 0x44, 0x64, 0x61, 0x74, 0x61}), - // WinNT Netmon capture file + // WinNT Netmon capture file (FileType.CAP, new byte[] {0x52, 0x54, 0x53, 0x53}), - // WinRAR compressed archive + // WinRAR compressed archive (FileType.RAR, new byte[] {0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00}), - // Generic e-mail_1 + // Generic e-mail_1 (FileType.EML, new byte[] {0x52, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x2D, 0x50}), - // Windows prefetch + // Windows prefetch (FileType.PF, new byte[] {0x53, 0x43, 0x43, 0x41}), - // Underground Audio + // Underground Audio (FileType.AST, new byte[] {0x53, 0x43, 0x48, 0x6C}), - // Img Software Bitmap + // Img Software Bitmap (FileType.IMG, new byte[] {0x53, 0x43, 0x4D, 0x49}), - // SMPTE DPX (big endian) + // SMPTE DPX (big endian) (FileType.SDPX, new byte[] {0x53, 0x44, 0x50, 0x58}), - // Harvard Graphics presentation + // Harvard Graphics presentation (FileType.SHW, new byte[] {0x53, 0x48, 0x4F, 0x57}), - // Sietronics CPI XRD document + // Sietronics CPI XRD document (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 - }), + // 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}), - // StuffIt archive + // StuffIt archive (FileType.SIT, new byte[] {0x53, 0x49, 0x54, 0x21, 0x00}), - // SmartDraw Drawing file + // SmartDraw Drawing file (FileType.SDR, new byte[] {0x53, 0x4D, 0x41, 0x52, 0x54, 0x44, 0x52, 0x57}), - // StorageCraft ShadownProtect backup file + // StorageCraft ShadownProtect backup file (FileType.SPF, new byte[] {0x53, 0x50, 0x46, 0x49, 0x00}), - // MultiBit Bitcoin blockchain file + // MultiBit Bitcoin blockchain file (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 - }), + // SQLite database file + (FileType.DB, new byte[] {0x53, 0x51, 0x4C, 0x69, 0x74, 0x65, 0x20, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x20, 0x33, 0x00}), - // DB2 conversion file + // DB2 conversion file (FileType.CNV, new byte[] {0x53, 0x51, 0x4C, 0x4F, 0x43, 0x4F, 0x4E, 0x56}), - // StuffIt compressed archive + // StuffIt compressed archive (FileType.SIT, new byte[] {0x53, 0x74, 0x75, 0x66, 0x66, 0x49, 0x74, 0x20}), - // SuperCalc worksheet + // SuperCalc worksheet (FileType.CAL, new byte[] {0x53, 0x75, 0x70, 0x65, 0x72, 0x43, 0x61, 0x6C}), - // Wii-GameCube + // Wii-GameCube (FileType.THP, new byte[] {0x54, 0x48, 0x50, 0x00}), - // GNU Info Reader file + // GNU Info Reader file (FileType.INFO, new byte[] {0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20}), - // Unicode extensions + // Unicode extensions (FileType.UCE, new byte[] {0x55, 0x43, 0x45, 0x58}), - // UFA compressed archive + // UFA compressed archive (FileType.UFA, new byte[] {0x55, 0x46, 0x41, 0xC6, 0xD2, 0xC1}), - // UFO Capture map file + // UFO Capture map file (FileType.DAT, new byte[] {0x55, 0x46, 0x4F, 0x4F, 0x72, 0x62, 0x69, 0x74}), - // Visual C PreCompiled header + // Visual C PreCompiled header (FileType.PCH, new byte[] {0x56, 0x43, 0x50, 0x43, 0x48, 0x30}), - // Visual Basic User-defined Control file + // Visual Basic User-defined Control file (FileType.CTL, new byte[] {0x56, 0x45, 0x52, 0x53, 0x49, 0x4F, 0x4E, 0x20}), - // MapInfo Interchange Format file + // MapInfo Interchange Format file (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 - }), + // SPSS template + (FileType.SCT, new byte[] {0x57, 0x04, 0x00, 0x00, 0x53, 0x50, 0x53, 0x53, 0x20, 0x74, 0x65, 0x6D, 0x70, 0x6C, 0x61, 0x74}), - // RIFF Windows Audio + // RIFF Windows Audio (FileType.WAV, new byte[] {0x57, 0x41, 0x56, 0x45, 0x66, 0x6D, 0x74, 0x20}), - // RIFF WebP + // RIFF WebP (FileType.WEBP, new byte[] {0x57, 0x45, 0x42, 0x50}), - // Walkman MP3 file + // Walkman MP3 file (FileType.DAT, new byte[] {0x57, 0x4D, 0x4D, 0x50}), - // WordStar for Windows file + // WordStar for Windows file (FileType.WS2, new byte[] {0x57, 0x53, 0x32, 0x30, 0x30, 0x30}), - // WinZip compressed archive + // WinZip compressed archive (FileType.ZIP, new byte[] {0x57, 0x69, 0x6E, 0x5A, 0x69, 0x70}), - // Lotus WordPro file + // Lotus WordPro file (FileType.LWP, new byte[] {0x57, 0x6F, 0x72, 0x64, 0x50, 0x72, 0x6F}), - // Exchange e-mail + // Exchange e-mail (FileType.EML, new byte[] {0x58, 0x2D}), - // Packet sniffer files + // Packet sniffer files (FileType.CAP, new byte[] {0x58, 0x43, 0x50, 0x00}), - // XPCOM libraries + // XPCOM libraries (FileType.XPT, new byte[] {0x58, 0x50, 0x43, 0x4F, 0x4D, 0x0A, 0x54, 0x79}), - // SMPTE DPX file (little endian) + // SMPTE DPX file (little endian) (FileType.DPX, new byte[] {0x58, 0x50, 0x44, 0x53}), - // MS Publisher + // MS Publisher (FileType.BDR, new byte[] {0x58, 0x54}), - // ZOO compressed archive + // ZOO compressed archive (FileType.ZOO, new byte[] {0x5A, 0x4F, 0x4F, 0x20}), - // Macromedia Shockwave Flash + // Macromedia Shockwave Flash (FileType.SWF, new byte[] {0x5A, 0x57, 0x53}), - // MS Exchange configuration file + // MS Exchange configuration file (FileType.ECF, new byte[] {0x5B, 0x47, 0x65, 0x6E, 0x65, 0x72, 0x61, 0x6C}), - // Visual C++ Workbench Info File + // Visual C++ Workbench Info File (FileType.VCW, new byte[] {0x5B, 0x4D, 0x53, 0x56, 0x43}), - // Dial-up networking file + // Dial-up networking file (FileType.DUN, new byte[] {0x5B, 0x50, 0x68, 0x6F, 0x6E, 0x65, 0x5D}), - // Lotus AMI Pro document_1 + // Lotus AMI Pro document_1 (FileType.SAM, new byte[] {0x5B, 0x56, 0x45, 0x52, 0x5D}), - // VocalTec VoIP media file + // VocalTec VoIP media file (FileType.VMD, new byte[] {0x5B, 0x56, 0x4D, 0x44, 0x5D}), - // Microsoft Code Page Translation file + // Microsoft Code Page Translation file (FileType.CPX, new byte[] {0x5B, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73}), - // Flight Simulator Aircraft Configuration + // Flight Simulator Aircraft Configuration (FileType.CFG, new byte[] {0x5B, 0x66, 0x6C, 0x74, 0x73, 0x69, 0x6D, 0x2E}), - // WinAmp Playlist + // WinAmp Playlist (FileType.PLS, new byte[] {0x5B, 0x70, 0x6C, 0x61, 0x79, 0x6C, 0x69, 0x73, 0x74, 0x5D}), - // Lotus AMI Pro document_2 + // Lotus AMI Pro document_2 (FileType.SAM, new byte[] {0x5B, 0x76, 0x65, 0x72, 0x5D}), - // Husqvarna Designer + // Husqvarna Designer (FileType.HUS, new byte[] {0x5D, 0xFC, 0xC8, 0x00}), - // Jar archive + // Jar archive (FileType.JAR, new byte[] {0x5F, 0x27, 0xA8, 0x89}), - // EnCase case file + // EnCase case file (FileType.CAS, new byte[] {0x5F, 0x43, 0x41, 0x53, 0x45, 0x5F}), - // EnCase case file + // EnCase case file (FileType.CBK, new byte[] {0x5F, 0x43, 0x41, 0x53, 0x45, 0x5F}), - // Compressed archive file + // Compressed archive file (FileType.ARJ, new byte[] {0x60, 0xEA}), - // UUencoded BASE64 file + // UUencoded BASE64 file (FileType.b64, new byte[] {0x62, 0x65, 0x67, 0x69, 0x6E, 0x2D, 0x62, 0x61, 0x73, 0x65, 0x36, 0x34}), - // Apple Core Audio File + // Apple Core Audio File (FileType.CAF, new byte[] {0x63, 0x61, 0x66, 0x66}), - // Macintosh encrypted Disk image (v1) + // Macintosh encrypted Disk image (v1) (FileType.DMG, new byte[] {0x63, 0x64, 0x73, 0x61, 0x65, 0x6E, 0x63, 0x72}), - // Virtual PC HD image + // Virtual PC HD image (FileType.VHD, new byte[] {0x63, 0x6F, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x78}), - // Photoshop Custom Shape + // Photoshop Custom Shape (FileType.CSH, new byte[] {0x63, 0x75, 0x73, 0x68, 0x00, 0x00, 0x00, 0x02}), - // Intel PROset-Wireless Profile + // Intel PROset-Wireless Profile (FileType.P10, new byte[] {0x64, 0x00, 0x00, 0x00}), - // Torrent file + // Torrent file (FileType.TORRENT, new byte[] {0x64, 0x38, 0x3A, 0x61, 0x6E, 0x6E, 0x6F, 0x75, 0x6E, 0x63, 0x65}), - // Dalvik (Android) executable file + // Dalvik (Android) executable file (FileType.dex, new byte[] {0x64, 0x65, 0x78, 0x0A}), - // Audacity audio file + // Audacity audio file (FileType.AU, new byte[] {0x64, 0x6E, 0x73, 0x2E}), - // MS Visual Studio workspace file + // MS Visual Studio workspace file (FileType.DSW, new byte[] {0x64, 0x73, 0x77, 0x66, 0x69, 0x6C, 0x65}), - // Macintosh encrypted Disk image (v2) + // Macintosh encrypted Disk image (v2) (FileType.DMG, new byte[] {0x65, 0x6E, 0x63, 0x72, 0x63, 0x64, 0x73, 0x61}), - // WinNT printer spool file + // WinNT printer spool file (FileType.SHD, new byte[] {0x66, 0x49, 0x00, 0x00}), - // Free Lossless Audio Codec file + // Free Lossless Audio Codec file (FileType.FLAC, new byte[] {0x66, 0x4C, 0x61, 0x43, 0x00, 0x00, 0x00, 0x22}), - // MPEG-4 video file_1 + // MPEG-4 video file_1 (FileType.MP4, new byte[] {0x66, 0x74, 0x79, 0x70, 0x33, 0x67, 0x70, 0x35}), - // Apple Lossless Audio Codec file + // Apple Lossless Audio Codec file (FileType.M4A, new byte[] {0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x41, 0x20}), - // ISO Media-MPEG v4-iTunes AVC-LC + // ISO Media-MPEG v4-iTunes AVC-LC (FileType.FLV, new byte[] {0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x56, 0x20}), - // ISO Media-MPEG v4-iTunes AVC-LC + // ISO Media-MPEG v4-iTunes AVC-LC (FileType.M4V, new byte[] {0x66, 0x74, 0x79, 0x70, 0x4D, 0x34, 0x56, 0x20}), - // MPEG-4 video file_2 + // MPEG-4 video file_2 (FileType.MP4, new byte[] {0x66, 0x74, 0x79, 0x70, 0x4D, 0x53, 0x4E, 0x56}), - // ISO Base Media file (MPEG-4) v1 + // ISO Base Media file (MPEG-4) v1 (FileType.MP4, new byte[] {0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6F, 0x6D}), - // MPEG-4 video-QuickTime file + // MPEG-4 video-QuickTime file (FileType.M4V, new byte[] {0x66, 0x74, 0x79, 0x70, 0x6D, 0x70, 0x34, 0x32}), - // QuickTime movie_7 + // QuickTime movie_7 (FileType.MOV, new byte[] {0x66, 0x74, 0x79, 0x70, 0x71, 0x74, 0x20, 0x20}), - // Win2000-XP printer spool file + // Win2000-XP printer spool file (FileType.SHD, new byte[] {0x67, 0x49, 0x00, 0x00}), - // GIMP file + // GIMP file (FileType.XCF, new byte[] {0x67, 0x69, 0x6d, 0x70, 0x20, 0x78, 0x63, 0x66}), - // Win Server 2003 printer spool file + // Win Server 2003 printer spool file (FileType.SHD, new byte[] {0x68, 0x49, 0x00, 0x00}), - // Skype user data file + // Skype user data file (FileType.DBB, new byte[] {0x6C, 0x33, 0x33, 0x6C}), - // QuickTime movie_1 + // QuickTime movie_1 (FileType.MOV, new byte[] {0x6D, 0x6F, 0x6F, 0x76}), - // QuickTime movie_2 + // QuickTime movie_2 (FileType.MOV, new byte[] {0x66, 0x72, 0x65, 0x65}), - // QuickTime movie_3 + // QuickTime movie_3 (FileType.MOV, new byte[] {0x6D, 0x64, 0x61, 0x74}), - // QuickTime movie_4 + // QuickTime movie_4 (FileType.MOV, new byte[] {0x77, 0x69, 0x64, 0x65}), - // QuickTime movie_5 + // QuickTime movie_5 (FileType.MOV, new byte[] {0x70, 0x6E, 0x6F, 0x74}), - // QuickTime movie_6 + // QuickTime movie_6 (FileType.MOV, new byte[] {0x73, 0x6B, 0x69, 0x70}), - // Internet Explorer v11 Tracking Protection List + // Internet Explorer v11 Tracking Protection List (FileType.TPL, new byte[] {0x6D, 0x73, 0x46, 0x69, 0x6C, 0x74, 0x65, 0x72, 0x4C, 0x69, 0x73, 0x74}), - // MultiBit Bitcoin wallet information + // MultiBit Bitcoin wallet information (FileType.INFO, new byte[] {0x6D, 0x75, 0x6C, 0x74, 0x69, 0x42, 0x69, 0x74, 0x2E, 0x69, 0x6E, 0x66, 0x6F}), - // WinNT registry file + // WinNT registry file (FileType.DAT, new byte[] {0x72, 0x65, 0x67, 0x66}), - // Sonic Foundry Acid Music File + // Sonic Foundry Acid Music File (FileType.AC, new byte[] {0x72, 0x69, 0x66, 0x66}), - // RealMedia metafile + // RealMedia metafile (FileType.RAM, new byte[] {0x72, 0x74, 0x73, 0x70, 0x3A, 0x2F, 0x2F}), - // Allegro Generic Packfile (compressed) + // Allegro Generic Packfile (compressed) (FileType.DAT, new byte[] {0x73, 0x6C, 0x68, 0x21}), - // Allegro Generic Packfile (uncompressed) + // Allegro Generic Packfile (uncompressed) (FileType.DAT, new byte[] {0x73, 0x6C, 0x68, 0x2E}), - // PalmOS SuperMemo + // PalmOS SuperMemo (FileType.PDB, new byte[] {0x73, 0x6D, 0x5F}), - // STL (STereoLithography) file + // STL (STereoLithography) file (FileType.STL, new byte[] {0x73, 0x6F, 0x6C, 0x69, 0x64}), - // CALS raster bitmap + // CALS raster bitmap (FileType.CAL, new byte[] {0x73, 0x72, 0x63, 0x64, 0x6F, 0x63, 0x69, 0x64}), - // PowerBASIC Debugger Symbols + // PowerBASIC Debugger Symbols (FileType.PDB, new byte[] {0x73, 0x7A, 0x65, 0x7A}), - // PathWay Map file + // PathWay Map file (FileType.PRC, new byte[] {0x74, 0x42, 0x4D, 0x50, 0x4B, 0x6E, 0x57, 0x72}), - // TrueType font + // TrueType font (FileType.TTF, new byte[] {0x74, 0x72, 0x75, 0x65, 0x00}), - // Tape Archive + // Tape Archive (FileType.TAR, new byte[] {0x75, 0x73, 0x74, 0x61, 0x72}), - // OpenEXR bitmap image + // OpenEXR bitmap image (FileType.EXR, new byte[] {0x76, 0x2F, 0x31, 0x01}), - // Qimage filter + // Qimage filter (FileType.FLT, new byte[] {0x76, 0x32, 0x30, 0x30, 0x33, 0x2E, 0x31, 0x30}), - // MacOS X image file + // MacOS X image file (FileType.DMG, new byte[] {0x78, 0x01, 0x73, 0x0D, 0x62, 0x62, 0x60}), - // eXtensible ARchive file + // eXtensible ARchive file (FileType.XAR, new byte[] {0x78, 0x61, 0x72, 0x21}), - // ZoomBrowser Image Index + // ZoomBrowser Image Index (FileType.INFO, new byte[] {0x7A, 0x62, 0x65, 0x78}), - // Windows application log + // Windows application log (FileType.LGC, new byte[] {0x7B, 0x0D, 0x0A, 0x6F, 0x20}), - // Windows application log + // Windows application log (FileType.LGD, new byte[] {0x7B, 0x0D, 0x0A, 0x6F, 0x20}), - // MS WinMobile personal note + // MS WinMobile personal note (FileType.PWI, new byte[] {0x7B, 0x5C, 0x70, 0x77, 0x69}), - // Rich Text Format + // Rich Text Format (FileType.RTF, new byte[] {0x7B, 0x5C, 0x72, 0x74, 0x66, 0x31}), - // Corel Paint Shop Pro image + // Corel Paint Shop Pro image (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 - }), + // 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}), - // Digital Watchdog DW-TP-500G audio + // Digital Watchdog DW-TP-500G audio (FileType.IMG, new byte[] {0x7E, 0x74, 0x2C, 0x01, 0x50, 0x70, 0x02, 0x4D, 0x52}), - // Relocatable object code + // Relocatable object code (FileType.OBJ, new byte[] {0x80}), - // Dreamcast audio + // Dreamcast audio (FileType.ADX, new byte[] {0x80, 0x00, 0x00, 0x20, 0x03, 0x12, 0x04}), - // Kodak Cineon image + // Kodak Cineon image (FileType.CIN, new byte[] {0x80, 0x2A, 0x5F, 0xD7}), - // Outlook Express address book (Win95) + // Outlook Express address book (Win95) (FileType.WAB, new byte[] {0x81, 0x32, 0x84, 0xC1, 0x85, 0x05, 0xD0, 0x11}), - // WordPerfect text + // WordPerfect text (FileType.WPF, new byte[] {0x81, 0xCD, 0xAB}), - // PNG image + // PNG image (FileType.PNG, new byte[] {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}), - // MS Answer Wizard + // MS Answer Wizard (FileType.AW, new byte[] {0x8A, 0x01, 0x09, 0x00, 0x00, 0x00, 0xE1, 0x08}), - // Hamarsoft compressed archive + // Hamarsoft compressed archive (FileType.HAP, new byte[] {0x91, 0x33, 0x48, 0x46}), - // PGP secret keyring_1 + // PGP secret keyring_1 (FileType.SKR, new byte[] {0x95, 0x00}), - // PGP secret keyring_2 + // PGP secret keyring_2 (FileType.SKR, new byte[] {0x95, 0x01}), - // JBOG2 image file + // JBOG2 image file (FileType.JB2, new byte[] {0x97, 0x4A, 0x42, 0x32, 0x0D, 0x0A, 0x1A, 0x0A}), - // GPG public keyring + // GPG public keyring (FileType.GPG, new byte[] {0x99}), - // PGP public keyring + // PGP public keyring (FileType.PKR, new byte[] {0x99, 0x01}), - // Outlook address file + // Outlook address file (FileType.WAB, new byte[] {0x9C, 0xCB, 0xCB, 0x8D, 0x13, 0x75, 0xD2, 0x11}), - // Access Data FTK evidence + // Access Data FTK evidence (FileType.DAT, new byte[] {0xA9, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), - // Quicken data + // Quicken data (FileType.QDF, new byte[] {0xAC, 0x9E, 0xBD, 0x8F, 0x00, 0x00}), - // PowerPoint presentation subheader_3 + // PowerPoint presentation subheader_3 (FileType.PPT, new byte[] {0xA0, 0x46, 0x1D, 0xF0}), - // BGBlitz position database file + // BGBlitz position database file (FileType.PDB, new byte[] {0xAC, 0xED, 0x00, 0x05, 0x73, 0x72, 0x00, 0x12}), - // Win95 password file + // Win95 password file (FileType.PWL, new byte[] {0xB0, 0x4D, 0x46, 0x43}), - // PCX bitmap + // PCX bitmap (FileType.DCX, new byte[] {0xB1, 0x68, 0xDE, 0x3A}), - // Acronis True Image_1 + // Acronis True Image_1 (FileType.TIB, new byte[] {0xB4, 0x6E, 0x68, 0x44}), - // Windows calendar + // Windows calendar (FileType.CAL, new byte[] {0xB5, 0xA2, 0xB0, 0xB3, 0xB3, 0xB0, 0xA5, 0xB5}), - // InstallShield Script + // InstallShield Script (FileType.INS, new byte[] {0xB8, 0xC9, 0x0C, 0x00}), - // MS Write file_3 + // MS Write file_3 (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 - }), + // Palm Desktop DateBook + (FileType.DAT, new byte[] {0xBE, 0xBA, 0xFE, 0xCA, 0x0F, 0x50, 0x61, 0x6C, 0x6D, 0x53, 0x47, 0x20, 0x44, 0x61, 0x74, 0x61}), - // MS Agent Character file + // MS Agent Character file (FileType.ACS, new byte[] {0xC3, 0xAB, 0xCD, 0xAB}), - // Adobe encapsulated PostScript + // Adobe encapsulated PostScript (FileType.EPS, new byte[] {0xC5, 0xD0, 0xD3, 0xC6}), - // Jeppesen FliteLog file + // Jeppesen FliteLog file (FileType.LBK, new byte[] {0xC8, 0x00, 0x79, 0x00}), - // Java bytecode + // Java bytecode (FileType.CLASS, new byte[] {0xCA, 0xFE, 0xBA, 0xBE}), - // Acronis True Image_2 + // Acronis True Image_2 (FileType.TIB, new byte[] {0xCE, 0x24, 0xB9, 0xA2, 0x20, 0x00, 0x00, 0x00}), - // Java Cryptography Extension keystore + // Java Cryptography Extension keystore (FileType.JCEKS, new byte[] {0xCE, 0xCE, 0xCE, 0xCE}), - // Perfect Office document + // Perfect Office document (FileType.DOC, new byte[] {0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1, 0x00}), - // Outlook Express e-mail folder + // Outlook Express e-mail folder (FileType.DBX, new byte[] {0xCF, 0xAD, 0x12, 0xFE}), - // Microsoft Office document + // Microsoft Office document (FileType.DOC, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Microsoft Office document + // Microsoft Office document (FileType.DOT, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Microsoft Office document + // Microsoft Office document (FileType.PPS, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Microsoft Office document + // Microsoft Office document (FileType.PPT, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Microsoft Office document + // Microsoft Office document (FileType.XLA, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Microsoft Office document + // Microsoft Office document (FileType.XLS, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Microsoft Office document + // Microsoft Office document (FileType.WIZ, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // CaseWare Working Papers + // CaseWare Working Papers (FileType.AC_, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Access project file + // Access project file (FileType.ADP, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Lotus-IBM Approach 97 file + // Lotus-IBM Approach 97 file (FileType.APR, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // MSWorks database file + // MSWorks database file (FileType.DB, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Microsoft Common Console Document + // Microsoft Common Console Document (FileType.MSC, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Microsoft Installer package + // Microsoft Installer package (FileType.MSI, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Microsoft Installer Patch + // Microsoft Installer Patch (FileType.MSP, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Minitab data file + // Minitab data file (FileType.MTW, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // ArcMap GIS project file + // ArcMap GIS project file (FileType.MXD, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Developer Studio File Options file + // Developer Studio File Options file (FileType.OPT, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // MS Publisher file + // MS Publisher file (FileType.PUB, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Revit Project file + // Revit Project file (FileType.RVT, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Visual Studio Solution User Options file + // Visual Studio Solution User Options file (FileType.SOU, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // SPSS output file + // SPSS output file (FileType.SPO, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // Visio file + // Visio file (FileType.VSD, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // MSWorks text document + // MSWorks text document (FileType.WPS, new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1}), - // WinPharoah filter file + // WinPharoah filter file (FileType.FTR, new byte[] {0xD2, 0x0A, 0x00, 0x00}), - // AOL history|typed URL files + // AOL history|typed URL files (FileType.ARL, new byte[] {0xD4, 0x2A}), - // AOL history|typed URL files + // AOL history|typed URL files (FileType.AUT, new byte[] {0xD4, 0x2A}), - // Windows graphics metafile + // Windows graphics metafile (FileType.WMF, new byte[] {0xD7, 0xCD, 0xC6, 0x9A}), - // Word 2.0 file + // Word 2.0 file (FileType.DOC, new byte[] {0xDB, 0xA5, 0x2D, 0x00}), - // Corel color palette + // Corel color palette (FileType.CPL, new byte[] {0xDC, 0xDC}), - // eFax file + // eFax file (FileType.EFX, new byte[] {0xDC, 0xFE}), - // Amiga icon + // Amiga icon (FileType.INFO, new byte[] {0xE3, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}), - // Win98 password file + // Win98 password file (FileType.PWL, new byte[] {0xE3, 0x82, 0x85, 0x96}), - // MS OneNote note + // MS OneNote note (FileType.ONE, new byte[] {0xE4, 0x52, 0x5C, 0x7B, 0x8C, 0xD8, 0xA7, 0x4D}), - // Windows executable file_1 + // Windows executable file_1 (FileType.COM, new byte[] {0xE8}), - // Windows executable file_1 + // Windows executable file_1 (FileType.SYS, new byte[] {0xE8}), - // Windows executable file_2 + // Windows executable file_2 (FileType.COM, new byte[] {0xE9}), - // Windows executable file_2 + // Windows executable file_2 (FileType.SYS, new byte[] {0xE9}), - // Windows executable file_3 + // Windows executable file_3 (FileType.COM, new byte[] {0xEB}), - // Windows executable file_3 + // Windows executable file_3 (FileType.SYS, new byte[] {0xEB}), - // GEM Raster file + // GEM Raster file (FileType.IMG, new byte[] {0xEB, 0x3C, 0x90, 0x2A}), - // Word document subheader + // Word document subheader (FileType.DOC, new byte[] {0xEC, 0xA5, 0xC1, 0x00}), - // RedHat Package Manager + // RedHat Package Manager (FileType.RPM, new byte[] {0xED, 0xAB, 0xEE, 0xDB}), - // Windows Script Component (UTF-8)_1 + // Windows Script Component (UTF-8)_1 (FileType.WSF, new byte[] {0xEF, 0xBB, 0xBF, 0x3C}), - // Windows Script Component (UTF-8)_2 + // Windows Script Component (UTF-8)_2 (FileType.WSC, new byte[] {0xEF, 0xBB, 0xBF, 0x3C, 0x3F}), - // Bitcoin-Qt blockchain block file + // Bitcoin-Qt blockchain block file (FileType.DAT, new byte[] {0xF9, 0xBE, 0xB4, 0xD9}), - // XZ archive + // XZ archive (FileType.XZ, new byte[] {0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}), - // MS Publisher subheader + // MS Publisher subheader (FileType.PUB, new byte[] {0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}), - // Thumbs.db subheader + // Thumbs.db subheader (FileType.DB, new byte[] {0xFD, 0xFF, 0xFF, 0xFF}), - // MS Publisher file subheader + // MS Publisher file subheader (FileType.PUB, new byte[] {0xFD, 0xFF, 0xFF, 0xFF, 0x02}), - // Visual Studio Solution subheader + // Visual Studio Solution subheader (FileType.SUO, new byte[] {0xFD, 0xFF, 0xFF, 0xFF, 0x04}), - // PowerPoint presentation subheader_4 + // PowerPoint presentation subheader_4 (FileType.PPT, new byte[] {0xFD, 0xFF, 0xFF, 0xFF, 0x0E, 0x00, 0x00, 0x00}), - // Excel spreadsheet subheader_2 + // Excel spreadsheet subheader_2 (FileType.XLS, new byte[] {0xFD, 0xFF, 0xFF, 0xFF, 0x10}), - // PowerPoint presentation subheader_5 + // PowerPoint presentation subheader_5 (FileType.PPT, new byte[] {0xFD, 0xFF, 0xFF, 0xFF, 0x1C, 0x00, 0x00, 0x00}), - // Excel spreadsheet subheader_3 + // Excel spreadsheet subheader_3 (FileType.XLS, new byte[] {0xFD, 0xFF, 0xFF, 0xFF, 0x1F}), - // Developer Studio subheader + // Developer Studio subheader (FileType.OPT, new byte[] {0xFD, 0xFF, 0xFF, 0xFF, 0x20}), - // Excel spreadsheet subheader_4 + // Excel spreadsheet subheader_4 (FileType.XLS, new byte[] {0xFD, 0xFF, 0xFF, 0xFF, 0x22}), - // Excel spreadsheet subheader_5 + // Excel spreadsheet subheader_5 (FileType.XLS, new byte[] {0xFD, 0xFF, 0xFF, 0xFF, 0x23}), - // Excel spreadsheet subheader_6 + // Excel spreadsheet subheader_6 (FileType.XLS, new byte[] {0xFD, 0xFF, 0xFF, 0xFF, 0x28}), - // Excel spreadsheet subheader_7 + // Excel spreadsheet subheader_7 (FileType.XLS, new byte[] {0xFD, 0xFF, 0xFF, 0xFF, 0x29}), - // PowerPoint presentation subheader_6 + // PowerPoint presentation subheader_6 (FileType.PPT, new byte[] {0xFD, 0xFF, 0xFF, 0xFF, 0x43, 0x00, 0x00, 0x00}), - // Symantex Ghost image file + // Symantex Ghost image file (FileType.GHO, new byte[] {0xFE, 0xEF}), - // Symantex Ghost image file + // Symantex Ghost image file (FileType.GHS, new byte[] {0xFE, 0xEF}), - // Windows executable + // Windows executable (FileType.SYS, new byte[] {0xFF}), - // Works for Windows spreadsheet + // Works for Windows spreadsheet (FileType.WKS, new byte[] {0xFF, 0x00, 0x02, 0x00, 0x04, 0x04, 0x05, 0x54}), - // QuickReport Report + // QuickReport Report (FileType.QRP, new byte[] {0xFF, 0x0A, 0x00}), - // Windows international code page + // Windows international code page (FileType.CPI, new byte[] {0xFF, 0x46, 0x4F, 0x4E, 0x54}), - // Keyboard driver file + // Keyboard driver file (FileType.SYS, new byte[] {0xFF, 0x4B, 0x45, 0x59, 0x42, 0x20, 0x20, 0x20}), - // WordPerfect text and graphics + // WordPerfect text and graphics (FileType.WP, new byte[] {0xFF, 0x57, 0x50, 0x43}), - // WordPerfect text and graphics + // WordPerfect text and graphics (FileType.WPD, new byte[] {0xFF, 0x57, 0x50, 0x43}), - // WordPerfect text and graphics + // WordPerfect text and graphics (FileType.WPG, new byte[] {0xFF, 0x57, 0x50, 0x43}), - // WordPerfect text and graphics + // WordPerfect text and graphics (FileType.WPP, new byte[] {0xFF, 0x57, 0x50, 0x43}), - // WordPerfect text and graphics + // WordPerfect text and graphics (FileType.WP5, new byte[] {0xFF, 0x57, 0x50, 0x43}), - // WordPerfect text and graphics + // WordPerfect text and graphics (FileType.WP6, new byte[] {0xFF, 0x57, 0x50, 0x43}), - // JPEG-EXIF-SPIFF images + // JPEG-EXIF-SPIFF images (FileType.JFIF, new byte[] {0xFF, 0xD8, 0xFF}), - // JPEG-EXIF-SPIFF images + // JPEG-EXIF-SPIFF images (FileType.JPE, new byte[] {0xFF, 0xD8, 0xFF}), - // JPEG-EXIF-SPIFF images + // JPEG-EXIF-SPIFF images (FileType.JPEG, new byte[] {0xFF, 0xD8, 0xFF}), - // JPEG-EXIF-SPIFF images + // JPEG-EXIF-SPIFF images (FileType.JPG, new byte[] {0xFF, 0xD8, 0xFF}), - // MPEG-4 AAC audio + // MPEG-4 AAC audio (FileType.AAC, new byte[] {0xFF, 0xF1}), - // MPEG-2 AAC audio + // MPEG-2 AAC audio (FileType.AAC, new byte[] {0xFF, 0xF9}), - // Windows Registry file + // Windows Registry file (FileType.REG, new byte[] {0xFF, 0xFE}), - // MSinfo file + // MSinfo file (FileType.MOF, new byte[] {0xFF, 0xFE, 0x23, 0x00, 0x6C, 0x00, 0x69, 0x00}), - // DOS system driver - (FileType.SYS, new byte[] {0xFF, 0xFF, 0xFF, 0xFF}) - }; -} \ No newline at end of file + // DOS system driver + (FileType.SYS, new byte[] {0xFF, 0xFF, 0xFF, 0xFF}), + + + };}} \ No newline at end of file diff --git a/Wabbajack.Common/FileSignatures/Signatures.tt b/Wabbajack.Common/FileSignatures/Signatures.tt index 6cde1cc8..ee5d8a73 100644 --- a/Wabbajack.Common/FileSignatures/Signatures.tt +++ b/Wabbajack.Common/FileSignatures/Signatures.tt @@ -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) diff --git a/Wabbajack.FileExtractor/FileExtractor.cs b/Wabbajack.FileExtractor/FileExtractor.cs index 9a7347c8..7203418d 100644 --- a/Wabbajack.FileExtractor/FileExtractor.cs +++ b/Wabbajack.FileExtractor/FileExtractor.cs @@ -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> GatheringExtractWithBTAR + (IStreamFactory sFn, Predicate shouldExtract, Func> 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(); + + 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 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> GatheringExtractWithOMOD (Stream archive, Predicate shouldExtract, Func> mapfn, CancellationToken token) From e174510a34d65b0cedbf9244f42ec582bc2b0ad0 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Fri, 11 Feb 2022 22:57:49 -0700 Subject: [PATCH 7/7] Add note about where I got the source from --- Wabbajack.Networking.BethesdaNet/Client.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Wabbajack.Networking.BethesdaNet/Client.cs b/Wabbajack.Networking.BethesdaNet/Client.cs index 0f4132c2..c87d3d8a 100644 --- a/Wabbajack.Networking.BethesdaNet/Client.cs +++ b/Wabbajack.Networking.BethesdaNet/Client.cs @@ -16,6 +16,9 @@ namespace Wabbajack.Networking.BethesdaNet; +/// +/// This code is heavily based on code researched and prototyped by Nukem9 https://github.com/Nukem9/bethnet_cli +/// public class Client { private readonly ITokenProvider _tokenProvider;