Esempio n. 1
0
        public void Append(string path, string vfsPath, bool compress, byte[] content)
        {
            if (_inputStream != null)
            {
                throw new Exception("Tried to add CRAF entry while still in read mode");
            }
            if (IndexOf(vfsPath) != -1)
            {
                throw new Exception("Tried to add file to CRAF with same path as existing file");
            }

            var entry = new CrafEntry();

            entry.path    = path;
            entry.vfsPath = vfsPath;
            entry.flags   = compress ? (uint)2 : 0;
            _files.Add(entry);
            Replace(_files.Count - 1, content);
        }
Esempio n. 2
0
        private void ReadMetadata()
        {
            if (_inputStream is null)
            {
                throw new Exception("Tried to read CRAF metadata after reader was closed");
            }

            using (BinaryReader bin = new BinaryReader(_inputStream, Encoding.Default, true))
            {
                _inputStream.Seek(4, SeekOrigin.Begin);
                _versionMinor       = bin.ReadUInt16();
                _versionMajor       = bin.ReadByte();
                _metadataEncryption = bin.ReadByte();
                var fileCount = bin.ReadInt32();
                _files = new List <CrafEntry>(fileCount);
                _unk0  = bin.ReadUInt32();

                uint firstEntryOffset = bin.ReadUInt32();

                _inputStream.Seek(0x20, SeekOrigin.Begin);
                _flags      = bin.ReadUInt32();
                _unk1       = bin.ReadBytes(4);
                _archiveKey = bin.ReadInt64();
                _unk2       = bin.ReadBytes(16);

                Int64 rollingKey = MasterArchiveKey ^ _archiveKey;

                _inputStream.Seek(firstEntryOffset, SeekOrigin.Begin);

                for (var i = 0; i < fileCount; i++)
                {
                    var entry = new CrafEntry();
                    entry.entryKey            = bin.ReadInt64();
                    entry.uncompressedSize    = bin.ReadInt32();
                    entry.totalCompressedSize = bin.ReadInt32();
                    entry.flags = bin.ReadUInt32();
                    uint vfsPathOffset = bin.ReadUInt32();
                    entry.dataOffset = bin.ReadInt64();
                    uint pathOffset = bin.ReadUInt32();
                    entry.unk0     = bin.ReadUInt16();
                    entry.chunkKey = bin.ReadUInt16();

                    long entryEnd = _inputStream.Position;
                    _inputStream.Seek(vfsPathOffset, SeekOrigin.Begin);
                    entry.vfsPath = bin.ReadNullTerminatedString();
                    _inputStream.Seek(pathOffset, SeekOrigin.Begin);
                    entry.path = bin.ReadNullTerminatedString();
                    _inputStream.Seek(entryEnd, SeekOrigin.Begin);
                    _files.Add(entry);

                    if (MetadataEncrypted)
                    {
                        Int64 fileSizeKey         = (rollingKey * MasterEntryKey) ^ entry.entryKey;
                        int   uncompressedSizeKey = (int)(fileSizeKey >> 32);
                        int   compressedSizeKey   = (int)(fileSizeKey & 0xFFFFFFFF);
                        entry.uncompressedSize    ^= uncompressedSizeKey;
                        entry.totalCompressedSize ^= compressedSizeKey;
                        Int64 dataOffsetKey = (fileSizeKey * MasterEntryKey) ^ ~(entry.entryKey);
                        entry.dataOffset ^= dataOffsetKey;

                        rollingKey = dataOffsetKey;
                    }

                    if (entry.UseDataEncryption)
                    {
                        var pos = _inputStream.Position;
                        _inputStream.Seek(entry.dataOffset + entry.totalCompressedSize - 0x21, SeekOrigin.Begin);
                        entry.IV = bin.ReadBytes(16);
                        _inputStream.Seek(pos, SeekOrigin.Begin);
                    }
                }
            }
        }