public static Stream OpenWoWFile(byte[] key) { if (key == null) { return(null); } // trim the byte array encoding key to 9 bytes // var ninebyte = Strip9Bytes(key); var newString = ByteString(ninebyte); if (IndexBlockParser.LocalIndexData.ContainsKey(newString)) { var FileIndex = IndexBlockParser.LocalIndexData[newString].Index; var FileOffset = IndexBlockParser.LocalIndexData[newString].Offset; var FileSize = IndexBlockParser.LocalIndexData[newString].Size; Debug.Log(FileIndex + " " + FileOffset + " " + FileSize); var stream = GetDatafileStream(FileIndex); if (stream == null) { return(null); } stream.Position = FileOffset; stream.Position += 30; var blte = BLTE.OpenFile(stream, FileSize - 30); return(blte); } else { Debug.Log("Error : local index missing"); return(null); } }
public static void HandleDataBlock(byte[] data, int index, Stream stream) { switch (data[0]) { case 0x4E: // N stream.Write(data, 1, data.Length - 1); break; case 0x5A: // Z Casc.CopyTo(BLTE_Decompress(data), stream); break; case 0x45: // E (encrypted) byte[] decrypted = BLTE.Decrypt(data, index); if (decrypted == null) { break; } HandleDataBlock(decrypted, index, stream); break; default: Debug.Log("Error: BLTE_ExtractData - Unknown byte at switch case : " + data[0]); //might need return break; } }
public void DownloadFile(string remoteFileName, string localFileName) { if (string.IsNullOrEmpty(localFileName)) { localFileName = Path.GetFileName(remoteFileName.Replace("\\", "/")); } if (string.IsNullOrEmpty(localFileName)) { return; } var completeFilePath = Path.Combine(Scanner.Configuration.Proxy.MirrorRoot, VersionName, localFileName); var fileDirectory = Path.GetDirectoryName(completeFilePath); if (string.IsNullOrEmpty(fileDirectory)) { return; } if (!Directory.CreateDirectory(fileDirectory).Exists) { return; } if (File.Exists(completeFilePath)) { return; } var fileEntry = GetEntry(remoteFileName); if (fileEntry == null) { return; } using (var blte = new BLTE(CDN.Hosts[0])) { if (fileEntry.ArchiveIndex != -1) { blte.AddHeader("Range", $"bytes={fileEntry.Offset}-{fileEntry.Offset + fileEntry.Size - 1}"); } var archiveName = fileEntry.Hash.ToHexString(); if (fileEntry.ArchiveIndex != -1) { archiveName = Indices.Archives[fileEntry.ArchiveIndex].ToHexString(); } blte.Send($"/{CDN.Path}/data/{archiveName.Substring(0, 2)}/{archiveName.Substring(2, 2)}/{archiveName}"); Scanner.WriteLine($"[{VersionName}] Downloading {localFileName} from {blte.URL} ..."); using (var fileStream = File.OpenWrite(completeFilePath)) blte.PipeTo(fileStream); } }
private static void Process(HttpListenerContext context) { var tokens = context.Request.Url.AbsolutePath.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length == 0) { WriteError(context, "Badly formatted request.", HttpStatusCode.BadRequest); return; } var buildName = tokens[0]; var fileHash = ulong.Parse(tokens[1]); var fileName = tokens[2]; var buildInfo = RemoteBuildManager.GetBuild(buildName); if (buildInfo == null) { WriteError(context, "Unknown build.", HttpStatusCode.BadRequest); return; } var fileEntry = buildInfo.GetEntry(fileHash); if (fileEntry == null) { WriteError(context, "This build is currently loading. Try again later.", HttpStatusCode.BadRequest); return; } try { using (var blte = new BLTE(buildInfo.CDN.Hosts[0])) { if (fileEntry.ArchiveIndex != -1) { blte.AddHeader("Range", $"bytes={fileEntry.Offset}-{fileEntry.Offset + fileEntry.Size - 1}"); } var archiveName = fileEntry.Hash.ToHexString(); if (fileEntry.ArchiveIndex != -1) { archiveName = buildInfo.Indices.Archives[fileEntry.ArchiveIndex].ToHexString(); } blte.Send($"/{buildInfo.CDN.Path}/data/{archiveName.Substring(0, 2)}/{archiveName.Substring(2, 2)}/{archiveName}"); Scanner.WriteLine($"[PROXY] Serving {fileName} through {blte.URL}."); if (!blte.Failed) { context.Response.ContentType = "application/octet-stream"; context.Response.ContentLength64 = blte.DecompressedLength; context.Response.AddHeader("Date", blte.ResponseHeaders.Get("Date")); context.Response.AddHeader("ETag", blte.ResponseHeaders.Get("ETag")); context.Response.AddHeader("Last-Modified", DateTime.Now.ToString("r")); context.Response.AddHeader("Connection", "Keep-Alive"); context.Response.StatusCode = (int)HttpStatusCode.OK; Scanner.WriteLine($"[PROXY] Serving {fileName} to {context.Request.RemoteEndPoint} - {archiveName}"); blte.PipeTo(context.Response.OutputStream); } else { var sBuilder = new StringBuilder(); sBuilder.AppendLine($"File {fileName} cannot be downloaded - it might be an encrypted archive..."); sBuilder.AppendLine(); sBuilder.AppendLine($"Requested archive: {blte.URL}"); if (fileEntry.ArchiveIndex != -1) { sBuilder.AppendLine($"Range: {fileEntry.Offset}-{fileEntry.Offset + fileEntry.Size - 1}"); } WriteError(context, sBuilder.ToString(), HttpStatusCode.InternalServerError); } } } catch (IOException ioe) { Scanner.WriteLine("[PROXY] Remote client closed the connection."); } catch (Exception e) { Scanner.WriteLine(e.ToString()); WriteError(context, e.ToString(), HttpStatusCode.InternalServerError); } }
public override bool Initialize(string region) { var versions = new Versions(Game.ProgramCode); var cdns = new CDNs(Game.ProgramCode); if (!cdns.Records.TryGetValue(region, out ServerInfo)) { return(false); } Versions.Record versionInfo; if (!versions.Records.TryGetValue(region, out versionInfo)) { return(false); } BuildConfig = new BuildConfiguration(ServerInfo.Hosts[0], versionInfo.BuildConfig); ContentConfig = new ContentConfiguration(ServerInfo.Hosts[0], versionInfo.CDNConfig); _rootKey = BuildConfig.Root.ToByteArray(); _encodingKey = BuildConfig.Encoding[1].ToByteArray(); using (var encodingClient = new AsyncClient(ServerInfo.Hosts[0])) { encodingClient.Send($"/{ServerInfo.Path}/data/{_encodingKey[0]:x2}/{_encodingKey[1]:x2}/{_encodingKey}"); if (!encodingClient.Failed) { using (var encodingPack = new BLTE(encodingClient.Stream, 0, encodingClient.ContentLength)) if (!LoadEncoding(encodingPack)) { throw new InvalidOperationException("Unable to find encoding!"); } } } for (var i = 0; i < ContentConfig.Archives.Length; ++i) { var archiveHash = ContentConfig.Archives[i]; using (var archiveClient = new AsyncClient(ServerInfo.Hosts[0])) { archiveClient.Send($"/{ServerInfo.Path}/data/{archiveHash[0]:x2}/{archiveHash[1]:x2}/{archiveHash.ToHexString()}.index"); if (!archiveClient.Failed) { LoadIndex(archiveClient.Stream, archiveClient.ContentLength, i); } } } if (!_encodingEntries.ContainsKey(_rootKey)) { throw new InvalidOperationException("Root entry not found in encoding!"); } var encodingEntry = _encodingEntries[_rootKey]; foreach (var rootEncodingEntry in encodingEntry) { using (var rootClient = new AsyncClient(ServerInfo.Hosts[0])) { rootClient.Send($"/{ServerInfo.Path}/data/{rootEncodingEntry.Item2[0]:x2}/{rootEncodingEntry.Item2[1]:x2}/{rootEncodingEntry.Item2.ToHexString()}"); if (rootClient.Failed) { continue; } using (var rootBlte = new BLTE(rootClient.Stream, 0, rootClient.ContentLength)) if (LoadRoot(rootBlte)) { break; } } } return(_rootEntries.Count != 0); }
public override bool Initialize(string installationPath) { ArchivePath = Path.Combine(installationPath, @"Data\data"); #region Load .build.info and config var buildInfo = new TokenConfig(); using (var buildInfoReader = new StreamReader(File.OpenRead(Path.Combine(installationPath, ".build.info")))) buildInfo.Load(buildInfoReader); var buildKey = buildInfo["Build Key"].FirstOrDefault(); if (string.IsNullOrEmpty(buildKey)) { throw new InvalidOperationException(".build.info is missing a build key"); } var buildConfigPath = Path.Combine(installationPath, @"Data\config", buildKey.Substring(0, 2), buildKey.Substring(2, 2), buildKey); var buildConfig = new KeyValueConfig(); using (var buildConfigReader = new StreamReader(File.OpenRead(buildConfigPath))) buildConfig.Load(buildConfigReader); #endregion _rootKey = buildConfig["root"].FirstOrDefault().ToByteArray(); _encodingKey = buildConfig["encoding"].ElementAtOrDefault(1).ToByteArray(9); for (var i = 0; i < 0x10; ++i) { var indexFile = Directory.GetFiles(ArchivePath, $"{i:X2}*.idx").Last(); using (var indexFileStream = File.OpenRead(indexFile)) LoadIndex(indexFileStream); } var encodingEntry = _indexEntries[_encodingKey]; using (var encodingStream = new BLTE(GetArchive(encodingEntry.Item1), encodingEntry.Item2 + 30, encodingEntry.Item3 - 30, false)) if (!LoadEncoding(encodingStream)) { throw new InvalidOperationException("Unable to find encoding"); } // At this point, the only possibility for root to not load is // that it was parsed from encoding before being found in index // or that it was not loaded when found in encoding if (_rootEntries.Count == 0) { if (!_encodingEntries.ContainsKey(_rootKey)) { throw new InvalidOperationException("Root entry not found in encoding!"); } foreach (var rootEncodingEntry in _encodingEntries[_rootKey]) { Tuple <int, int, int> indexEntry; if (!_indexEntries.TryGetValue(rootEncodingEntry.Item2, out indexEntry)) { continue; } using (var rootStream = new BLTE(GetArchive(indexEntry.Item1), indexEntry.Item2 + 30, indexEntry.Item3 - 30)) if (LoadRoot(rootStream)) { break; } } } return(_rootEntries.Count != 0); }