Пример #1
0
        private static void WriteFileHeader(BinaryWriter writer, EArchive archive, EArchiveFileCreation file, ref long rollingKey)
        {
            long fileSizeKey   = (rollingKey * MasterFileKey) ^ file.Hash,
                 dataOffsetKey = (fileSizeKey * MasterFileKey) ^ ~(file.Hash);

            int uncompressedKey = (int)(fileSizeKey >> 32),
                compressedKey   = (int)(fileSizeKey & 0xFFFFFFFF);

            file.SizeUncompressed ^= uncompressedKey;
            file.SizeCompressed   ^= compressedKey;
            file.DataOffset       ^= dataOffsetKey;

            rollingKey = dataOffsetKey;

            writer.Write(file.Hash);
            writer.Write(file.SizeUncompressed);
            writer.Write(file.SizeCompressed);

            writer.Write(file.Flags);
            writer.Write(file.DataPathOffset);
            writer.Write(file.DataOffset);
            writer.Write(file.PathOffset);
            writer.Write(file.LocalizeType);
            writer.Write(file.Locale);
            writer.Write(file.ChunkKey);
        }
Пример #2
0
 private static void WriteUncompressedFile(BinaryWriter writer, EArchiveFileCreation file)
 {
     //* create a stream to read the file contents
     using (Stream input = File.OpenRead(file.FilePath)) {
         using (BinaryReader reader = new BinaryReader(input)) {
             while (reader.BaseStream.Position < reader.BaseStream.Length)
             {
                 writer.Write(reader.ReadByte());
             }
         }
     }
 }
Пример #3
0
        private static void WriteFilePath(BinaryWriter writer, EArchiveFileCreation file)
        {
            //* store the path offset
            file.PathOffset = (uint)writer.BaseStream.Position;

            //* write the data path
            writer.Write(Encoding.UTF8.GetBytes(file.Path));

            //* zero terminate
            writer.Write((byte)0x00);

            //* align for next one
            Align(writer, 8);
        }
Пример #4
0
        private static void WriteFileDataPath(BinaryWriter writer, EArchiveFileCreation file)
        {
            //* store our data path offset
            file.DataPathOffset = (uint)writer.BaseStream.Position;

            //* write the data path
            if (string.IsNullOrWhiteSpace(file.DataPath))
            {
                writer.Write(Encoding.UTF8.GetBytes("data://" + file.Path));
            }
            else
            {
                writer.Write(Encoding.UTF8.GetBytes(file.DataPath));
            }

            //* zero terminate
            writer.Write((byte)0x00);

            //* align for next one
            Align(writer, 8);
        }
Пример #5
0
        private static void WriteCompressedFile(BinaryWriter writer, EArchive archive, EArchiveFileCreation file)
        {
            using (Stream input = File.OpenRead(file.FilePath)) {
                using (BinaryReader reader = new BinaryReader(input)) {
                    int chunkSize = (int)archive.ChunkSize * 1024;

                    file.SizeUncompressedOriginal = (int)input.Length;
                    file.SizeUncompressed         = (int)input.Length;

                    //* get the number of chunks
                    int chunks    = (int)input.Length / chunkSize,
                        remaining = (int)input.Length;

                    //* if the integer division wasn't even, add a chunk
                    if (input.Length % chunkSize != 0)
                    {
                        chunks++;
                    }

                    //* set compressed size to zero and sum as we go
                    file.SizeCompressed = 0;

                    if (file.ChunkKey == 0)
                    {
                        file.ChunkKey = (ushort)(new Random().Next(0, ushort.MaxValue));
                    }

                    for (int chunk = 0; chunk < chunks; chunk++)
                    {
                        //* use a memory stream for chunking
                        using (MemoryStream memory = new MemoryStream()) {
                            int read = (remaining > chunkSize) ? chunkSize : remaining;

                            //* store the chunk of compressed data to a memory stream
                            memory.Write(reader.ReadBytes(read), 0, read);

                            //* move to the start of the chunk
                            memory.Seek(0, SeekOrigin.Begin);

                            //* now compress it and write it to our compressed stream
                            using (MemoryStream compressed = new MemoryStream()) {
                                using (ZLibStream compressor = new ZLibStream(compressed, CompressionMode.Compress, CompressionLevel.Best, true))
                                    memory.CopyTo(compressor);

                                compressed.Seek(0, SeekOrigin.Begin);

                                int sizeCompressed   = (int)compressed.Length,
                                    sizeUncompressed = read;

                                //* write chunk sizes
                                if (chunk == 0)
                                {
                                    //* for the first one we need to encrypt it
                                    long chunkKey = (MasterChunkKeyA * file.ChunkKey) + MasterChunkKeyB;

                                    int compressedKey   = (int)(chunkKey >> 32);
                                    int uncompressedKey = (int)(chunkKey & 0xFFFFFFFF);

                                    sizeCompressed   ^= compressedKey;
                                    sizeUncompressed ^= uncompressedKey;
                                }

                                writer.Write(sizeCompressed);
                                writer.Write(sizeUncompressed);

                                for (int position = 0; position < compressed.Length; position++)
                                {
                                    writer.Write((byte)compressed.ReadByte());
                                }

                                //* align for next chunk
                                int alignment = Align(writer, 4);

                                file.SizeCompressed += (int)compressed.Length + 8 + alignment;
                            }

                            remaining -= read;
                        }
                    }
                }
            }
        }
Пример #6
0
        private static void CopyFileFromArchive(BinaryWriter writer, EArchive archive, EArchiveFileCreation file)
        {
            if (file.FilePath == file.Path)
            {
                EArchive     existing = Open(file.ArchivePath);
                EArchiveFile old      = null;

                foreach (EArchiveFile previous in existing.Files)
                {
                    if (previous.Path == file.Path)
                    {
                        old = previous;
                        break;
                    }
                }

                if (old == null)
                {
                    throw new FileNotFoundException();
                }

                using (Stream input = File.OpenRead(file.ArchivePath)) {
                    input.Seek(old.DataOffset, SeekOrigin.Begin);

                    using (BinaryReader reader = new BinaryReader(input)) {
                        for (int index = 0; index < old.SizeCompressed; index++)
                        {
                            writer.Write(reader.ReadByte());
                        }
                    }
                }

                file.SizeCompressed           = old.SizeCompressed;
                file.SizeUncompressed         = old.SizeUncompressed;
                file.SizeUncompressedOriginal = old.SizeUncompressed;

                return;
            }
        }
Пример #7
0
        private static void WriteEncryptedFile(BinaryWriter writer, EArchive archive, EArchiveFileCreation file)
        {
            Aes aes = Aes.Create();

            aes.Mode    = CipherMode.CBC;
            aes.Padding = PaddingMode.Zeros;

            if (file.IV == null)
            {
                aes.GenerateIV();
                file.IV = aes.IV;
            }

            ICryptoTransform transform = aes.CreateEncryptor(AESKey, file.IV);

            using (Stream input = File.OpenRead(file.FilePath)) {
                using (BinaryReader inputReader = new BinaryReader(input)) {
                    using (MemoryStream msEncrypted = new MemoryStream()) {
                        using (CryptoStream csEncrypted = new CryptoStream(msEncrypted, transform, CryptoStreamMode.Write)) {
                            using (BinaryWriter bwEncrypted = new BinaryWriter(csEncrypted, Encoding.Default, true)) {
                                while (input.Position < input.Length)
                                {
                                    bwEncrypted.Write(inputReader.ReadByte());
                                }
                            }

                            if (!csEncrypted.HasFlushedFinalBlock)
                            {
                                csEncrypted.FlushFinalBlock();
                            }

                            msEncrypted.Seek(0, SeekOrigin.Begin);

                            while (msEncrypted.Position < msEncrypted.Length)
                            {
                                writer.Write((byte)msEncrypted.ReadByte());
                            }
                        }
                    }
                }
            }

            int alignment = 16 - (file.SizeUncompressedOriginal % 16);

            if (alignment == 16)
            {
                alignment = 0;
            }

            writer.Write(file.IV);
            file.SizeCompressed = file.SizeUncompressedOriginal + alignment + 33;
        }