예제 #1
0
        /// <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);
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        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();
        }
예제 #4
0
        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;
                    }
                }
            }
        }
예제 #5
0
        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();
        }
예제 #6
0
        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);
        }
예제 #7
0
        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()}");
        }
예제 #8
0
파일: Main.cs 프로젝트: wowdev/TACT.Net
        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());
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
            }
        }