Exemplo n.º 1
0
        public DownloadHandler(BLTEStream blte)
        {
            if (CASContainer.BuildConfig["download-size"][0] != null && blte.Length != long.Parse(CASContainer.BuildConfig["download-size"][0]))
            {
                CASContainer.Settings?.Logger.LogAndThrow(Logging.LogType.Critical, "Download File is corrupt.");
            }

            using (var br = new BinaryReader(blte))
            {
                Header = new DownloadHeader()
                {
                    Header       = br.ReadBytes(2),
                    Version      = br.ReadByte(),
                    ChecksumSize = br.ReadByte(),
                    Unknown      = br.ReadByte(),
                    NumEntries   = br.ReadUInt32BE(),
                    NumTags      = br.ReadUInt16BE(),
                };

                // entries
                for (int i = 0; i < Header.NumEntries; i++)
                {
                    var entry = new DownloadEntry()
                    {
                        Unknown     = Header.Version > 1 ? br.ReadByte() : (byte)0,                     // new V2 field
                        Hash        = new MD5Hash(br),
                        FileSize    = br.ReadUInt40BE(),
                        Stage       = br.ReadByte(),
                        UnknownData = br.ReadBytes(4)
                    };

                    Entries.Add(entry);
                }

                // tags
                int numMaskBytes = ((int)Header.NumEntries + 7) / 8;
                for (int i = 0; i < Header.NumTags; i++)
                {
                    var tag = new DownloadTag()
                    {
                        Name    = br.ReadCString(),
                        Type    = br.ReadUInt16BE(),
                        BitMask = new BoolArray(br.ReadBytes(numMaskBytes))
                    };

                    Tags.Add(tag);
                }

                EncodingMap = blte.EncodingMap.ToArray();

                endofStageIndex = new int[]                 // store last indice of each stage
                {
                    Entries.FindLastIndex(x => x.Stage == 0),
                    Entries.FindLastIndex(x => x.Stage == 1)
                };
            }

            blte?.Dispose();
        }
Exemplo n.º 2
0
        public InstallHandler(BLTEStream blte)
        {
            if (CASContainer.BuildConfig["install-size"][0] != null && blte.Length != long.Parse(CASContainer.BuildConfig["install-size"][0]))
            {
                CASContainer.Settings?.Logger.LogAndThrow(Logging.LogType.Critical, "Install File is corrupt.");
            }

            BinaryReader stream = new BinaryReader(blte);

            Header = new InstallHeader()
            {
                Magic      = stream.ReadBytes(2),
                Version    = stream.ReadByte(),
                HashSize   = stream.ReadByte(),
                NumTags    = stream.ReadUInt16BE(),
                NumEntries = stream.ReadUInt32BE()
            };

            // tags
            int numMaskBytes = (int)(Header.NumEntries + 7) / 8;

            for (int i = 0; i < Header.NumTags; i++)
            {
                InstallTag tag = new InstallTag()
                {
                    Name    = stream.ReadCString(),
                    Type    = stream.ReadUInt16BE(),
                    BitMask = new BoolArray(stream.ReadBytes(numMaskBytes))
                };

                // We need to remove trailing bits from the padded byte array.
                while (tag.BitMask.Count != Header.NumEntries)
                {
                    tag.BitMask.RemoveAt(tag.BitMask.Count - 1);
                }

                Tags.Add(tag);
            }

            // entries
            for (int i = 0; i < Header.NumEntries; i++)
            {
                InstallEntry entry = new InstallEntry()
                {
                    Name  = stream.ReadCString(),
                    CEKey = new MD5Hash(stream),
                    Size  = stream.ReadUInt32BE()
                };

                InstallData.Add(entry);
            }

            EncodingMap = blte.EncodingMap.ToArray();

            stream?.Dispose();
            blte?.Dispose();
        }
Exemplo n.º 3
0
        public static void CompareIdx(string[] args)
        {
            string otherVerNum = args[2];

            HashSet <ulong> missingKeys = new HashSet <ulong>();

            Directory.CreateDirectory(RawIdxDir);
            Directory.CreateDirectory(ConvertIdxDir);

            string[] otherHashes;
            using (StreamReader reader = new StreamReader($"{otherVerNum}.idxhashes")) {
                otherHashes = reader.ReadToEnd().Split('\n').Select(x => x.TrimEnd('\r')).ToArray();
            }

            MD5Hash md5Obj = new MD5Hash();

            foreach (KeyValuePair <MD5Hash, IndexEntry> indexEntry in CASC.LocalIndex.Indices)
            {
                string md5 = indexEntry.Key.ToHexString();

                if (!otherHashes.Contains(md5))
                {
                    try {
                        Stream rawStream = CASC.LocalIndex.OpenIndexInfo(indexEntry.Value, md5Obj, false);

                        Stream stream = new BLTEStream(rawStream, md5Obj);

                        TryConvertFile(stream, ConvertIdxDir, md5);

                        //stream.Position = 0;
                        //using (Stream file = File.OpenWrite(Path.Combine(RawIdxDir, md5))) {
                        //    stream.CopyTo(file);
                        //}

                        rawStream.Dispose();
                        stream.Dispose();
                    } catch (Exception e) {
                        if (e is BLTEKeyException exception)
                        {
                            if (missingKeys.Add(exception.MissingKey))
                            {
                                Console.Out.WriteLine($"Missing key: {exception.MissingKey:X16}");
                            }
                        }
                        //else {
                        //    Console.Out.WriteLine(e);
                        //}
                    }
                }
            }

            Console.Write("done");
            Console.ReadLine();
        }
Exemplo n.º 4
0
        public static void Patch(string file, string host)
        {
            CASContainer.Logger.LogInformation($"Patching {Path.GetFileName(file)}");

            BLTEStream stream = OpenFile(file);

            if (stream == null)
            {
                return;
            }

            string outpath = Path.Combine(CASContainer.Settings.OutputPath, Helper.GetCDNPath(Path.GetFileName(file), "data"));

            using (var fs = new FileStream(outpath, FileMode.Create, FileAccess.Write, FileShare.Read))
                using (var bw = new BinaryWriter(fs))
                {
                    stream.CopyTo(fs);

                    stream.Position = 0;
                    byte[] content = new byte[stream.Length];
                    stream.Read(content, 0, content.Length);

                    var patches = BuildPatches(Encoding.UTF8.GetString(content), host);

                    foreach (var patch in patches)
                    {
                        long offset = SearchPattern(content, patch.Key);
                        if (offset >= 0)
                        {
                            fs.Position = offset;
                            bw.Write(patch.Value);
                        }
                    }

                    fs.Position = 0;
                    fs.Flush();
                }

            stream?.Dispose();
        }
Exemplo n.º 5
0
        public EncodingHandler(BLTEStream blte)
        {
            if (blte.Length != long.Parse(CASContainer.BuildConfig["encoding-size"][0]))
            {
                CASContainer.Settings?.Logger.LogAndThrow(Logging.LogType.Critical, "Encoding File is corrupt.");
            }

            BinaryReader stream = new BinaryReader(blte);

            Header = new EncodingHeader()
            {
                Magic          = stream.ReadBytes(2),
                Version        = stream.ReadByte(),
                ChecksumSizeC  = stream.ReadByte(),
                ChecksumSizeE  = stream.ReadByte(),
                PageSizeCEKey  = stream.ReadUInt16(),
                PageSizeEKey   = stream.ReadUInt16(),
                PageCountCEKey = stream.ReadUInt32BE(),
                PageCountEKey  = stream.ReadUInt32BE(),
                Unknown_x11    = stream.ReadByte(),
                ESpecBlockSize = stream.ReadUInt32BE()
            };

            // ESpec string table
            ESpecStringTable.AddRange(Encoding.ASCII.GetString(stream.ReadBytes((int)Header.ESpecBlockSize)).Split('\0'));

            // skip CE page table lookup
            stream.ReadBytes((int)Header.PageCountCEKey * 32);

            // read CE page table data
            for (int i = 0; i < Header.PageCountCEKey; i++)
            {
                long start = stream.BaseStream.Position;

                ushort keysCount;
                while ((keysCount = stream.ReadUInt16()) != 0)
                {
                    var entry = new EncodingCEKeyPageTable()
                    {
                        DecompressedSize = stream.ReadUInt32BE(),
                        CKey             = new MD5Hash(stream)
                    };

                    for (int ki = 0; ki < keysCount; ki++)
                    {
                        entry.EKeys.Add(new MD5Hash(stream));
                    }

                    CEKeys.Add(entry.CKey, entry);
                }

                if (stream.BaseStream.Position % CHUNK_SIZE != 0)
                {
                    stream.BaseStream.Position += CHUNK_SIZE - ((stream.BaseStream.Position - start) % CHUNK_SIZE);
                }
            }

            // skip EKey page table lookup
            stream.ReadBytes((int)Header.PageCountEKey * 32);

            // read EKey page table data
            for (int i = 0; i < Header.PageCountEKey; i++)
            {
                long start = stream.BaseStream.Position;

                MD5Hash hash;
                while (!(hash = new MD5Hash(stream)).IsEmpty)
                {
                    var entry = new EncodingEKeyPageTable()
                    {
                        EKey             = hash,
                        ESpecStringIndex = stream.ReadUInt32BE(),
                        FileSize         = stream.ReadUInt40BE()
                    };

                    EKeys.Add(entry.EKey, entry);
                }

                if (stream.BaseStream.Position % CHUNK_SIZE != 0)
                {
                    stream.BaseStream.Position += CHUNK_SIZE - ((stream.BaseStream.Position - start) % CHUNK_SIZE);
                }
            }

            // Encoding file ESpecStringTable
            stream.ReadBytes((int)(stream.BaseStream.Length - stream.BaseStream.Position));

            EncodingMap = blte.EncodingMap.ToArray();

            blte?.Dispose();
            stream?.Dispose();
        }
Exemplo n.º 6
0
        public DownloadHandler(BLTEStream blte)
        {
            if (CASContainer.BuildConfig["download-size"][0] != null && blte.Length != long.Parse(CASContainer.BuildConfig["download-size"][0]))
            {
                CASContainer.Settings?.Logger.LogAndThrow(Logging.LogType.Critical, "Download File is corrupt.");
            }

            using (var br = new BinaryReader(blte))
            {
                Header = new DownloadHeader()
                {
                    Header       = br.ReadBytes(2),
                    Version      = br.ReadByte(),
                    ChecksumSize = br.ReadByte(),
                    HasChecksum  = br.ReadByte(),
                    NumEntries   = br.ReadUInt32BE(),
                    NumTags      = br.ReadUInt16BE(),
                };

                if (Header.Version >= 2)
                {
                    Header.NumFlags = br.ReadByte();
                }

                if (Header.Version >= 3)
                {
                    // TODO do we have a version 3 file to test with?
                    //Header.BasePriority = br.ReadByte();
                    //Header.Unknown_0D = br.ReadBytes(3);
                    throw new NotImplementedException("Download file versions newer than 2 are not supported.");
                }

                // entries
                for (int i = 0; i < Header.NumEntries; i++)
                {
                    var entry = new DownloadEntry()
                    {
                        EKey     = new MD5Hash(br),
                        FileSize = br.ReadUInt40BE(),
                        Priority = br.ReadByte()
                    };

                    if (Header.HasChecksum != 0)
                    {
                        entry.Checksum = br.ReadUInt32BE();
                    }

                    if (Header.Version >= 2)
                    {
                        entry.Flags = (DownloadFlags[])(object)br.ReadBytes(Header.NumFlags);
                    }

                    Entries.Add(entry);
                }

                // tags
                int numMaskBytes = ((int)Header.NumEntries + 7) / 8;
                for (int i = 0; i < Header.NumTags; i++)
                {
                    var tag = new DownloadTag()
                    {
                        Name    = br.ReadCString(),
                        Type    = br.ReadUInt16BE(),
                        BitMask = new BoolArray(br.ReadBytes(numMaskBytes))
                    };

                    // We need to remove trailing bits from the padded byte array.
                    while (tag.BitMask.Count != Entries.Count)
                    {
                        tag.BitMask.RemoveAt(tag.BitMask.Count - 1);
                    }

                    Tags.Add(tag);
                }

                EncodingMap = blte.EncodingMap.ToArray();

                endofStageIndex = new int[]                 // store last indice of each stage
                {
                    Entries.FindLastIndex(x => x.Priority == 0),
                    Entries.FindLastIndex(x => x.Priority == 1)
                };
            }

            blte?.Dispose();
        }
Exemplo n.º 7
0
        public EncodingHandler(BLTEStream blte)
        {
            if (blte.Length != long.Parse(CASContainer.BuildConfig["encoding-size"][0]))
            {
                CASContainer.Settings?.Logger.LogAndThrow(Logging.LogType.Critical, "Encoding File is corrupt.");
            }

            BinaryReader stream = new BinaryReader(blte);

            Header = new EncodingHeader()
            {
                Magic           = stream.ReadBytes(2),
                Version         = stream.ReadByte(),
                ChecksumSizeA   = stream.ReadByte(),
                ChecksumSizeB   = stream.ReadByte(),
                FlagsA          = stream.ReadUInt16(),
                FlagsB          = stream.ReadUInt16(),
                NumEntriesA     = stream.ReadUInt32BE(),
                NumEntriesB     = stream.ReadUInt32BE(),
                StringBlockSize = stream.ReadUInt40BE()
            };

            // stringTableA
            LayoutStringTable.AddRange(Encoding.ASCII.GetString(stream.ReadBytes((int)Header.StringBlockSize)).Split('\0'));

            // skip header block A
            stream.ReadBytes((int)Header.NumEntriesA * 32);

            // encoding table entry block
            for (int i = 0; i < Header.NumEntriesA; i++)
            {
                long start = stream.BaseStream.Position;

                ushort keysCount;
                while ((keysCount = stream.ReadUInt16()) != 0)
                {
                    EncodingEntry entry = new EncodingEntry()
                    {
                        DecompressedSize = stream.ReadUInt32BE(),
                        Hash             = new MD5Hash(stream)
                    };

                    for (int ki = 0; ki < keysCount; ki++)
                    {
                        entry.Keys.Add(new MD5Hash(stream));
                    }

                    Data.Add(entry.Hash, entry);
                }

                if (stream.BaseStream.Position % CHUNK_SIZE != 0)
                {
                    stream.BaseStream.Position += CHUNK_SIZE - ((stream.BaseStream.Position - start) % CHUNK_SIZE);
                }
            }

            // skip header block B
            stream.ReadBytes((int)Header.NumEntriesB * 32);

            // layout table entry block
            for (int i = 0; i < Header.NumEntriesB; i++)
            {
                long start = stream.BaseStream.Position;

                MD5Hash hash;
                while (!(hash = new MD5Hash(stream)).IsEmpty)
                {
                    var entry = new EncodingLayout()
                    {
                        Hash        = hash,
                        StringIndex = stream.ReadUInt32BE(),
                        Size        = stream.ReadUInt40BE()
                    };

                    Layout.Add(entry.Hash, entry);
                }

                if (stream.BaseStream.Position % CHUNK_SIZE != 0)
                {
                    stream.BaseStream.Position += CHUNK_SIZE - ((stream.BaseStream.Position - start) % CHUNK_SIZE);
                }
            }

            stream.ReadBytes((int)(stream.BaseStream.Length - stream.BaseStream.Position)); //EncodingStringTable

            EncodingMap = blte.EncodingMap.ToArray();

            blte?.Dispose();
            stream?.Dispose();
        }