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); }
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); } } } }