/// <summary> /// Download and open an remote TACT container /// <para>Note: This will download the entire CDN so will take a while</para> /// </summary> /// <param name="url"></param> /// <param name="tprDirectory"></param> /// <param name="product"></param> /// <param name="locale"></param> public void DownloadRemote(string tprDirectory, string product, Locale locale, bool systemFileOnly = false) { ManifestContainer = new Configs.ManifestContainer(product, locale); ManifestContainer.DownloadRemote(BaseDirectory); ConfigContainer = new Configs.ConfigContainer(); ConfigContainer.DownloadRemote(tprDirectory, ManifestContainer); var cdnClient = new CDNClient(ManifestContainer); var queuedDownload = new QueuedDownloader(tprDirectory, cdnClient); if (ConfigContainer.EncodingEKey.Value != null) { // Download encoding file var encodingEKey = DownloadSystemFile(ConfigContainer.EncodingEKey, cdnClient, tprDirectory); if (encodingEKey.Value != null) { EncodingFile = new Encoding.EncodingFile(tprDirectory, encodingEKey, true); } // Download PatchFile DownloadSystemFile(ConfigContainer.PatchEKey, cdnClient, tprDirectory, "patch"); // Download RootFile if (EncodingFile.TryGetCKeyEntry(ConfigContainer.RootCKey, out var ekeyEntry)) { ekeyEntry.EKeys.ForEach(x => queuedDownload.Enqueue(x.Value.ToString())); } // Download InstallFile if (EncodingFile.TryGetCKeyEntry(ConfigContainer.InstallCKey, out ekeyEntry)) { ekeyEntry.EKeys.ForEach(x => queuedDownload.Enqueue(x.Value.ToString())); } // Download DownloadFile if (EncodingFile.TryGetCKeyEntry(ConfigContainer.DownloadCKey, out ekeyEntry)) { ekeyEntry.EKeys.ForEach(x => queuedDownload.Enqueue(x.Value.ToString())); } // Download DownloadSizeFile if (EncodingFile.TryGetCKeyEntry(ConfigContainer.DownloadSizeCKey, out ekeyEntry)) { ekeyEntry.EKeys.ForEach(x => queuedDownload.Enqueue(x.Value.ToString())); } queuedDownload.Download("data"); } // Download Indices and archives if (!systemFileOnly) { IndexContainer = new Indices.IndexContainer(); IndexContainer.DownloadRemote(tprDirectory, ConfigContainer, ManifestContainer); } Open(tprDirectory); }
/// <summary> /// Download and open an remote TACT container /// <para>Note: This will download the entire CDN so will take a while</para> /// </summary> /// <param name="url"></param> /// <param name="directory"></param> /// <param name="product"></param> /// <param name="locale"></param> public void DownloadRemote(string directory, string product, Locale locale) { ConfigContainer = new Configs.ConfigContainer(product, locale); ConfigContainer.DownloadRemote(directory); var cdnClient = new CDNClient(ConfigContainer); var queuedDownload = new QueuedDownloader(directory, cdnClient); if (ConfigContainer.EncodingEKey.Value != null) { // Download encoding file var encodingEKey = DownloadSystemFile(ConfigContainer.EncodingEKey, cdnClient, directory); if (encodingEKey.Value != null) { EncodingFile = new Encoding.EncodingFile(BaseDirectory, encodingEKey, true); } // Download PatchFile DownloadSystemFile(ConfigContainer.PatchEKey, cdnClient, directory, "patch"); // Download RootFile if (EncodingFile.TryGetCKeyEntry(ConfigContainer.RootCKey, out var ekeyEntry)) { queuedDownload.Enqueue(ekeyEntry.EKey.ToString()); } // Download InstallFile if (EncodingFile.TryGetCKeyEntry(ConfigContainer.InstallCKey, out ekeyEntry)) { queuedDownload.Enqueue(ekeyEntry.EKey.ToString()); } // Download DownloadFile if (EncodingFile.TryGetCKeyEntry(ConfigContainer.DownloadCKey, out ekeyEntry)) { queuedDownload.Enqueue(ekeyEntry.EKey.ToString()); } // Download DownloadSizeFile if (EncodingFile.TryGetCKeyEntry(ConfigContainer.DownloadSizeCKey, out ekeyEntry)) { queuedDownload.Enqueue(ekeyEntry.EKey.ToString()); } queuedDownload.Download("data"); } // Download Indices and archives IndexContainer = new Indices.IndexContainer(); IndexContainer.DownloadRemote(directory, ConfigContainer); Open(directory, product, locale); }
public void Save(string directory) { IndexContainer?.Save(directory, ConfigContainer); RootFile?.Write(directory, this); DownloadFile?.Write(directory, this); DownloadSizeFile?.Write(directory, this); InstallFile?.Write(directory, this); EncodingFile?.Write(directory, ConfigContainer); ConfigContainer?.Save(directory); RootFile?.FileLookup?.Close(); }
private async Task ExtractFiles(UnshippedBuild model, EncodingFile encoding) { var install = new InstallFile(Helpers.GetTempPath(model.Install)); foreach (var file in install.Files) { if (!Helpers.HasAnyWildcard(file.FilePath, Consts.FileWildcards)) { continue; } if (!encoding.TryGetCKeyEntry(file.CKey, out var contentEntry)) { continue; } if (contentEntry.EKeys.Count == 0) { continue; } var filepath = Path.Combine(Consts.TempDir, file.FilePath); Directory.CreateDirectory(Path.GetDirectoryName(filepath)); // download the first one foreach (var ekey in contentEntry.EKeys) { if (await DownloadFile(ekey.ToString(), filepath)) { try { // decode file, using swap temp to avoid rw conflicts BlockTableEncoder.DecodeAndExport(filepath, filepath + "_temp"); File.Copy(filepath + "_temp", filepath, true); } finally { File.Delete(filepath + "_temp"); } // extract build info if (file.FilePath.EndsWith(".exe") && File.Exists(filepath)) { model.Build ??= FileVersionInfo.GetVersionInfo(filepath)?.FileVersion; model.Product ??= Helpers.GetProductType(file.FilePath); } break; } } } }
public void Save(string directory) { // if this field exists and mismatches the generated file; the client will error // if this field is missing the client will generate the file and variable itself ConfigContainer?.CDNConfig?.GetValues("archive-group")?.Clear(); IndexContainer?.Save(directory, ConfigContainer); RootFile?.Write(directory, this); DownloadFile?.Write(directory, this); DownloadSizeFile?.Write(directory, this); InstallFile?.Write(directory, this); EncodingFile?.Write(directory, ConfigContainer); ConfigContainer?.Save(directory); RootFile?.FileLookup?.Close(); }
public static void BuildConfig(UnshippedBuild model, EncodingFile encoding, long eSize, long eCompressedSize) { var config = new KeyValueConfig(ConfigType.BuildConfig); SetFileInfo(config, "root", model.Root, encoding); SetFileInfo(config, "install", model.Install, encoding); SetFileInfo(config, "download", model.Download, encoding); SetFileInfo(config, "size", model.Size, encoding); config.SetValue("encoding", encoding.Checksum, 0); config.SetValue("encoding", model.Encoding, 1); config.SetValue("encoding-size", eSize, 0); config.SetValue("encoding-size", eCompressedSize, 1); config.SetValue("build-name", GetBuildName(model.Product, model.Build)); config.SetValue("build-uid", model.Product); config.Write(Consts.TempDir); }
public async Task AttemptReconstruction(UnshippedBuild model) { Directory.CreateDirectory(Consts.TempDir); if (!await DownloadFile(model.Encoding, Helpers.GetTempPath(model.Encoding))) { return; } if (!await DownloadFile(model.Install, Helpers.GetTempPath(model.Install))) { return; } Console.WriteLine($"Processing Encoding {model.Encoding}"); // these files are less important await DownloadFile(model.Download, Helpers.GetTempPath(model.Download)); await DownloadFile(model.Size, Helpers.GetTempPath(model.Size)); // load encoding file using var fs = File.OpenRead(Helpers.GetTempPath(model.Encoding)); using var blte = new BlockTableStreamReader(fs); var eSize = blte.Length; var ecSize = fs.Length; var encoding = new EncodingFile(blte); // extract all binaries await ExtractFiles(model, encoding); // attempt to find and download root if (await TryGetRoot(model, encoding)) { await DownloadFile(model.Root, Helpers.GetTempPath(model.Root)); } // generate buildconfig ConfigGenerator.BuildConfig(model, encoding, eSize, ecSize); Directory.Move(Consts.TempDir, model.GetDirectoryName()); Console.WriteLine($"{model.Encoding} moved to {model.GetDirectoryName()}"); }
public void TestCKeys() { // WOW-28807patch8.1.0_PTR string ckey = "0105f03cb8b8faceda8ea099c2f2f476"; Indices.IndexFile index = new Indices.IndexFile(Path.Combine(PATH, @"data\01\05", "0105f03cb8b8faceda8ea099c2f2f476.index")); index.Write("test"); Assert.AreEqual(ckey, index.Checksum.ToString()); //ckey = "1228b5ef225fa4b85eebc5e32b1ca238"; //RootFile rootFile = new RootFile(PATH, new MD5Hash("fc52ef45efbbc6beca39076f89bad99f")); //Assert.AreEqual(ckey, rootFile.Write(@"test").CKey.ToString()); ckey = "1de5b9ebaa9c117f0c2d5430f8b296d4"; RootFile rootFileV2 = new RootFile(PATH, new MD5Hash("923b2669b887c65b2271405ce51a052b")); Assert.AreEqual(ckey, rootFileV2.Write("test").CKey.ToString()); ckey = "9faeafadd4ee3fa03de41eb2360e7f46"; EncodingFile encodingFile = new EncodingFile(PATH, new MD5Hash("c08602c3fe517a2a2eec27f6cffbb627")); Assert.AreEqual(ckey, encodingFile.Write("test").CKey.ToString()); ckey = "22c7766aae84c1efb081c458d43a5bc7"; Install.InstallFile installFile = new Install.InstallFile(PATH, new MD5Hash("c6ebc4d0b75f279b7d8259715d76107a")); Assert.AreEqual(ckey, installFile.Write("test").CKey.ToString()); ckey = "21f3d8cf8c1e49ce90aa81cec19eef89"; Download.DownloadFile downloadFile = new Download.DownloadFile(PATH, new MD5Hash("b8e459cff125e452e404714d29bc20e3")); downloadFile.DownloadHeader.IncludeChecksum = true; Assert.AreEqual(ckey, downloadFile.Write("test").CKey.ToString()); ckey = "a934b6684ac4fd35a9cde796fc5d3f25"; Download.DownloadSizeFile downloadSizeFile = new Download.DownloadSizeFile(PATH, new MD5Hash("001cc5c73390ac2f5882d65edea4751b")); Assert.AreEqual(ckey, downloadSizeFile.Write("test").CKey.ToString()); }
private async Task <bool> TryGetRoot(UnshippedBuild model, EncodingFile encoding) { // find the zlib espec only used for a few files // namely root and world/liquid.tex var espec = encoding.ESpecStringTable.IndexOf("z"); // attemp to filter out just the root with min size var files = encoding.EKeyEntries .Where(x => x.ESpecIndex == espec && x.CompressedSize > Consts.MinRootSize) .ToArray(); if (files.Length == 0) { return(false); } // read the magic of each file var buffer = new byte[4]; for (var i = 0; i < files.Length; i++) { var endpoint = Helpers.GetCDNUrl(files[i].EKey.ToString(), "data"); var stream = await Client.OpenStream(endpoint, 0, 0x1000); // arbitary peek size var blte = new BlockTableStreamReader(stream); blte.Read(buffer); if (BitConverter.ToUInt32(buffer) == Consts.RootMagic) { model.Root = files[i].EKey.ToString(); return(true); } } return(false); }
private static void SetFileInfo(KeyValueConfig config, string type, string hash, EncodingFile encoding) { if (!MD5Hash.TryParse(hash, out var ekey)) { return; } if (!encoding.TryGetEKeyEntry(ekey, out var encodedEntry)) { return; } var contentEntry = encoding.GetCKeyEntryByEKey(ekey); if (contentEntry == null) { return; } config.SetValue(type, contentEntry.CKey, 0); if (type != "root") { config.SetValue(type, hash, 1); config.SetValue(type + "-size", contentEntry.DecompressedSize, 0); config.SetValue(type + "-size", encodedEntry.CompressedSize, 1); } }