Example #1
0
        private Stream ReadData(Stream input)
        {
            input.Position = DataOffset;
            int    dataSize = (int)CompressedSize;
            Stream stream   = new Decrypt1Stream(input, (int)Version, dataSize, DataHash, hashLow: (uint)(Hash & 0xFFFFFFFF), streamMode: StreamMode.Read);

            if (Encryption == Cryptography.Magic1 || Encryption == Cryptography.Magic2)
            {
                int headerSize = Cryptography.GetHeaderSize(Encryption);
                stream.Read(new byte[headerSize], 0, headerSize);
                dataSize -= headerSize;
                stream    = new Decrypt2Stream(stream, dataSize, Key, StreamMode.Read);
            }

            if (Compressed)
            {
                stream = Compression.UncompressStream(stream);
            }

            return(stream);
        }
Example #2
0
        public void Write(Stream output, IDirectory inputDirectory)
        {
            using (Stream inputStream = inputDirectory.ReadFileStream(Hashing.NormalizeFilePath(FilePath)))
                using (Md5Stream md5OutputStream = new Md5Stream(output))
                {
                    long      headerPosition    = output.Position;
                    const int entryHeaderSize   = 32;
                    long      dataStartPosition = headerPosition + entryHeaderSize;
                    output.Position = dataStartPosition;

                    uint uncompressedSize = (uint)inputStream.Length;

                    Stream outputDataStream           = md5OutputStream;
                    Stream outputDataStreamCompressed = null;
                    if (Compressed)
                    {
                        outputDataStreamCompressed = Compression.CompressStream(outputDataStream);
                        outputDataStream           = outputDataStreamCompressed;
                    }

                    if (Encryption != 0)
                    {
                        int encryptionHeaderSize = Cryptography.GetHeaderSize(Encryption);
                        if (encryptionHeaderSize >= 8)
                        {
                            byte[] header = new byte[encryptionHeaderSize];
                            Buffer.BlockCopy(BitConverter.GetBytes(Encryption), 0, header, 0, sizeof(uint));
                            Buffer.BlockCopy(BitConverter.GetBytes(Key), 0, header, 4, sizeof(uint));
                            if (encryptionHeaderSize == 16)
                            {
                                Buffer.BlockCopy(BitConverter.GetBytes(uncompressedSize), 0, header, 8, sizeof(uint));
                                Buffer.BlockCopy(BitConverter.GetBytes(uncompressedSize), 0, header, 12, sizeof(uint));
                            }

                            using (var headerStream = new MemoryStream(header))
                            {
                                headerStream.CopyTo(outputDataStream);
                            }
                        }

                        outputDataStream = new Decrypt2Stream(outputDataStream, (int)uncompressedSize, Key, StreamMode.Write);
                    }

                    inputStream.CopyTo(outputDataStream);
                    outputDataStreamCompressed?.Close();

                    // TODO: HACK to support repacked files
                    if (DataHash == null)
                    {
                        md5OutputStream.Flush();
                        DataHash = md5OutputStream.Hash;
                    }

                    long dataEndPosition = output.Position;
                    uint compressedSize  = (uint)(dataEndPosition - dataStartPosition);
                    uncompressedSize = Compressed ? uncompressedSize : compressedSize;
                    using (var decrypt1Stream = new Decrypt1Stream(output, (int)Version, (int)compressedSize, DataHash, hashLow: (uint)(Hash & 0xFFFFFFFF), streamMode: StreamMode.Write))
                    {
                        CopyTo(output, decrypt1Stream, dataStartPosition, dataEndPosition);
                    }

                    output.Position = headerPosition;

                    const ulong  xorMask1Long = 0x4144104341441043;
                    const uint   xorMask1     = 0x41441043;
                    const uint   xorMask2     = 0x11C22050;
                    const uint   xorMask3     = 0xD05608C3;
                    const uint   xorMask4     = 0x532C7319;
                    BinaryWriter writer       = new BinaryWriter(output, Encoding.ASCII, true);
                    writer.Write(Hash ^ xorMask1Long);
                    writer.Write((Version != 2 ? uncompressedSize : compressedSize) ^ xorMask2);
                    writer.Write((Version != 2 ? compressedSize : uncompressedSize) ^ xorMask3);
                    writer.Write(BitConverter.ToUInt32(DataHash, 0) ^ xorMask4);
                    writer.Write(BitConverter.ToUInt32(DataHash, 4) ^ xorMask1);
                    writer.Write(BitConverter.ToUInt32(DataHash, 8) ^ xorMask1);
                    writer.Write(BitConverter.ToUInt32(DataHash, 12) ^ xorMask2);

                    output.Position = dataEndPosition;
                }
        }