Example #1
0
    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);
        }
    }
Example #2
0
    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;
        }
    }
Example #3
0
        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);
            }
        }
Example #4
0
        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);
            }
        }
Example #5
0
        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);
        }
Example #6
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);
        }