/// <summary> /// Opens the CDNs, Versions from Ribbit and the config files from Blizzard's CDN /// </summary> public void OpenRemote(ManifestContainer manifestContainer) { if (manifestContainer?.VersionsFile == null || manifestContainer?.CDNsFile == null) { throw new Exception("Versions and CDNs files must be loaded first"); } if (!manifestContainer.VersionsFile.HasLocale(manifestContainer.Locale)) { throw new Exception($"Versions missing {manifestContainer.Locale} locale"); } var cdnClient = new CDNClient(manifestContainer); if (manifestContainer.BuildConfigMD5.Value != null) { string configUrl = Helpers.GetCDNUrl(manifestContainer.BuildConfigMD5.ToString(), "config"); BuildConfig = new KeyValueConfig(cdnClient.OpenStream(configUrl).Result, ConfigType.BuildConfig); } if (manifestContainer.CDNConfigMD5.Value != null) { string configUrl = Helpers.GetCDNUrl(manifestContainer.CDNConfigMD5.ToString(), "config"); CDNConfig = new KeyValueConfig(cdnClient.OpenStream(configUrl).Result, ConfigType.CDNConfig); } if (PatchConfigMD5.Value != null) { string configUrl = Helpers.GetCDNUrl(PatchConfigMD5.ToString(), "config"); PatchConfig = new KeyValueConfig(cdnClient.OpenStream(configUrl).Result, ConfigType.PatchConfig); } }
/// <summary> /// Opens a stream to an entry in a remote CDN's data archives /// </summary> /// <param name="type"></param> /// <param name="ekey"></param> /// <returns></returns> private Stream OpenRemoteFile(IndexType type, MD5Hash ekey) { var index = GetIndexFileAndEntry(type, ekey, out var indexEntry); if (index == null || indexEntry == null) { return(null); } string archive = index.IsLooseIndex ? ekey.ToString() : index.Checksum.ToString(); string url = Helpers.GetCDNUrl(archive, type.ToString().ToLowerInvariant()); var stream = _client.OpenStream(url, indexEntry.Offset, indexEntry.Offset + (long)indexEntry.CompressedSize - 1).Result; if (stream == null) { return(null); } switch (type) { case IndexType.Data: return(new BlockTableStreamReader(stream)); case IndexType.Patch: return(stream); default: stream.Dispose(); return(null); } }
/// <summary> /// Loads an existing PatchFile from a remote CDN /// </summary> /// <param name="client"></param> /// <param name="ekey"></param> public PatchFile(CDNClient client, MD5Hash ekey) : this() { string url = Helpers.GetCDNUrl(ekey.ToString(), "patch"); using (var stream = client.OpenStream(url).Result) Read(stream); }
/// <summary> /// Loads an existing DownloadFile from a remote CDN /// </summary> /// <param name="client"></param> /// <param name="ekey"></param> public DownloadFile(CDNClient client, MD5Hash ekey) : this() { string url = Helpers.GetCDNUrl(ekey.ToString(), "data"); using (var stream = client.OpenStream(url).Result) using (var bt = new BlockTableStreamReader(stream)) Read(bt); }
/// <summary> /// Loads an existing EncodingFile from a remote CDN /// </summary> /// <param name="client"></param> /// <param name="ekey"></param> /// <param name="partial">Only reads the mandatory information. Prevents write support</param> public EncodingFile(CDNClient client, MD5Hash ekey, bool partial = false) : this() { Partial = partial; string url = Helpers.GetCDNUrl(ekey.ToString(), "data"); using (var stream = client.OpenStream(url).Result) using (var bt = new BlockTableStreamReader(stream)) Read(bt); }
/// <summary> /// Opens the CDNs, Versions from Ribbit and the config files from Blizzard's CDN /// </summary> public void OpenRemote() { var ribbit = new RibbitClient(Locale); using (var cdnstream = ribbit.GetStream(RibbitCommand.CDNs, Product).Result) using (var verstream = ribbit.GetStream(RibbitCommand.Versions, Product).Result) { CDNsFile = new VariableConfig(cdnstream, ConfigType.CDNs); VersionsFile = new VariableConfig(verstream, ConfigType.Versions); if (!VersionsFile.HasLocale(Locale)) { throw new Exception($"Versions missing {Locale} locale"); } var cdnClient = new CDNClient(this); if (BuildConfigMD5.Value != null) { string configUrl = Helpers.GetCDNUrl(BuildConfigMD5.ToString(), "config"); BuildConfig = new KeyValueConfig(cdnClient.OpenStream(configUrl).Result, ConfigType.BuildConfig); } if (CDNConfigMD5.Value != null) { string configUrl = Helpers.GetCDNUrl(CDNConfigMD5.ToString(), "config"); CDNConfig = new KeyValueConfig(cdnClient.OpenStream(configUrl).Result, ConfigType.CDNConfig); } if (PatchConfigMD5.Value != null) { string configUrl = Helpers.GetCDNUrl(PatchConfigMD5.ToString(), "config"); PatchConfig = new KeyValueConfig(cdnClient.OpenStream(configUrl).Result, ConfigType.PatchConfig); } } }
/// <summary> /// Loads an IndexFile from a remote CDN /// </summary> /// <param name="stream"></param> public IndexFile(CDNClient client, string path, IndexType type) : this(IndexType.Unknown) { if (!path.EndsWith(".index", StringComparison.OrdinalIgnoreCase)) { path += ".index"; } string endpoint = type.HasFlag(IndexType.Data) ? "data" : "patch"; string url = Helpers.GetCDNUrl(path, endpoint); using (var stream = client.OpenStream(url).Result) Read(stream); Type = DetermineType(type); }
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); }