Example #1
0
        /// <summary>
        /// Reads the archive header.
        /// </summary>
        public void ReadHeader(byte[] aesKey = null, byte[] ngKey = null)
        {
            var reader = new DataReader(BaseStream);
            var posbak = reader.Position;

            reader.Position = 0;

            uint header_identifier = reader.ReadUInt32(); // 0x52504637

            if (header_identifier != IDENT)
            {
                throw new Exception("The identifier " + header_identifier.ToString("X8") + " did not match the expected value of 0x52504637");
            }

            uint header_entriesCount = reader.ReadUInt32();
            uint header_namesLength  = reader.ReadUInt32();
            uint header_encryption   = reader.ReadUInt32();

            byte[] entries_data_dec = null;
            byte[] names_data_dec   = null;

            if (header_encryption == 0x04E45504F) // for OpenIV compatibility
            {
                // no encryption...
                Encryption       = RageArchiveEncryption7.None;
                entries_data_dec = reader.ReadBytes(16 * (int)header_entriesCount);
                names_data_dec   = reader.ReadBytes((int)header_namesLength);
            }
            else if (header_encryption == 0x0ffffff9)
            {
                // AES enceyption...

                Encryption = RageArchiveEncryption7.AES;

                var entries_data = reader.ReadBytes(16 * (int)header_entriesCount);
                entries_data_dec = AesEncryption.DecryptData(entries_data, aesKey);

                var names_data = reader.ReadBytes((int)header_namesLength);
                names_data_dec = AesEncryption.DecryptData(names_data, aesKey);
            }
            else
            {
                // NG encryption...

                Encryption = RageArchiveEncryption7.NG;

                var entries_data = reader.ReadBytes(16 * (int)header_entriesCount);
                entries_data_dec = GTA5Crypto.Decrypt(entries_data, ngKey);

                var names_data = reader.ReadBytes((int)header_namesLength);
                names_data_dec = GTA5Crypto.Decrypt(names_data, ngKey);
            }

            var entries_reader = new DataReader(new MemoryStream(entries_data_dec));
            var names_reader   = new DataReader(new MemoryStream(names_data_dec));

            var entries = new List <IRageArchiveEntry7>();

            for (var index = 0; index < header_entriesCount; index++)
            {
                entries_reader.Position += 4;
                int x = entries_reader.ReadInt32();
                entries_reader.Position -= 8;

                if (x == 0x7fffff00)
                {
                    // directory
                    var e = new RageArchiveDirectory7();
                    e.Read(entries_reader);

                    names_reader.Position = e.NameOffset;
                    e.Name = names_reader.ReadString();

                    entries.Add(e);
                }
                else
                {
                    if ((x & 0x80000000) == 0)
                    {
                        // binary file
                        var e = new RageArchiveBinaryFile7();
                        e.Read(entries_reader);

                        names_reader.Position = e.NameOffset;
                        e.Name = names_reader.ReadString();

                        entries.Add(e);
                    }
                    else
                    {
                        // resource file
                        var e = new RageArchiveResourceFile7();
                        e.Read(entries_reader);

                        // there are sometimes resources with length=0xffffff which actually
                        // means length>=0xffffff
                        if (e.FileSize == 0xFFFFFF)
                        {
                            reader.Position = 512 * e.FileOffset;
                            var buf = reader.ReadBytes(16);
                            e.FileSize = ((uint)buf[7] << 0) | ((uint)buf[14] << 8) | ((uint)buf[5] << 16) | ((uint)buf[2] << 24);
                        }

                        names_reader.Position = e.NameOffset;
                        e.Name = names_reader.ReadString();

                        entries.Add(e);
                    }
                }
            }

            var stack = new Stack <RageArchiveDirectory7>();

            stack.Push((RageArchiveDirectory7)entries[0]);
            Root = (RageArchiveDirectory7)entries[0];
            while (stack.Count > 0)
            {
                var item = stack.Pop();

                for (int index = (int)item.EntriesIndex; index < (item.EntriesIndex + item.EntriesCount); index++)
                {
                    if (entries[index] is RageArchiveDirectory7)
                    {
                        item.Directories.Add(entries[index] as RageArchiveDirectory7);
                        stack.Push(entries[index] as RageArchiveDirectory7);
                    }
                    else
                    {
                        item.Files.Add(entries[index]);
                    }
                }
            }

            reader.Position = posbak;
        }
Example #2
0
        /// <summary>
        /// Reads the archive header.
        /// </summary>
        public void ReadHeader(byte[] aesKey = null, byte[] ngKey = null)
        {
            var reader = new DataReader(BaseStream);
            var posbak = reader.Position;
            reader.Position = 0;

            uint header_identifier = reader.ReadUInt32(); // 0x52504637
            if (header_identifier != IDENT)
                throw new Exception("The identifier " + header_identifier.ToString("X8") + " did not match the expected value of 0x52504637");

            uint header_entriesCount = reader.ReadUInt32();
            uint header_namesLength = reader.ReadUInt32();
            uint header_encryption = reader.ReadUInt32();

            byte[] entries_data_dec = null;
            byte[] names_data_dec = null;

            if (header_encryption == 0x04E45504F) // for OpenIV compatibility
            {
                // no encryption...
                Encryption = RageArchiveEncryption7.None;
                entries_data_dec = reader.ReadBytes(16 * (int)header_entriesCount);
                names_data_dec = reader.ReadBytes((int)header_namesLength);

            }
            else if (header_encryption == 0x0ffffff9)
            {
                // AES enceyption...                

                Encryption = RageArchiveEncryption7.AES;

                var entries_data = reader.ReadBytes(16 * (int)header_entriesCount);
                entries_data_dec = AesEncryption.DecryptData(entries_data, aesKey);

                var names_data = reader.ReadBytes((int)header_namesLength);
                names_data_dec = AesEncryption.DecryptData(names_data, aesKey);
            }
            else
            {
                // NG encryption...

                Encryption = RageArchiveEncryption7.NG;

                var entries_data = reader.ReadBytes(16 * (int)header_entriesCount);
                entries_data_dec = GTA5Crypto.Decrypt(entries_data, ngKey);

                var names_data = reader.ReadBytes((int)header_namesLength);
                names_data_dec = GTA5Crypto.Decrypt(names_data, ngKey);
            }

            var entries_reader = new DataReader(new MemoryStream(entries_data_dec));
            var names_reader = new DataReader(new MemoryStream(names_data_dec));

            var entries = new List<IRageArchiveEntry7>();
            for (var index = 0; index < header_entriesCount; index++)
            {
                entries_reader.Position += 4;
                int x = entries_reader.ReadInt32();
                entries_reader.Position -= 8;

                if (x == 0x7fffff00)
                {
                    // directory
                    var e = new RageArchiveDirectory7();
                    e.Read(entries_reader);

                    names_reader.Position = e.NameOffset;
                    e.Name = names_reader.ReadString();

                    entries.Add(e);
                }
                else
                {
                    if ((x & 0x80000000) == 0)
                    {
                        // binary file
                        var e = new RageArchiveBinaryFile7();
                        e.Read(entries_reader);

                        names_reader.Position = e.NameOffset;
                        e.Name = names_reader.ReadString();

                        entries.Add(e);
                    }
                    else
                    {
                        // resource file
                        var e = new RageArchiveResourceFile7();
                        e.Read(entries_reader);

                        // there are sometimes resources with length=0xffffff which actually
                        // means length>=0xffffff
                        if (e.FileSize == 0xFFFFFF)
                        {
                            reader.Position = 512 * e.FileOffset;
                            var buf = reader.ReadBytes(16);
                            e.FileSize = ((uint)buf[7] << 0) | ((uint)buf[14] << 8) | ((uint)buf[5] << 16) | ((uint)buf[2] << 24);
                        }

                        names_reader.Position = e.NameOffset;
                        e.Name = names_reader.ReadString();
                        
                        entries.Add(e);
                    }
                }
            }

            var stack = new Stack<RageArchiveDirectory7>();
            stack.Push((RageArchiveDirectory7)entries[0]);
            Root = (RageArchiveDirectory7)entries[0];
            while (stack.Count > 0)
            {
                var item = stack.Pop();

                for (int index = (int)item.EntriesIndex; index < (item.EntriesIndex + item.EntriesCount); index++)
                {
                    if (entries[index] is RageArchiveDirectory7)
                    {
                        item.Directories.Add(entries[index] as RageArchiveDirectory7);
                        stack.Push(entries[index] as RageArchiveDirectory7);
                    }
                    else
                    {
                        item.Files.Add(entries[index]);
                    }
                }
            }

            reader.Position = posbak;
        }
Example #3
0
        /// <summary>
        /// Reads the archive header.
        /// </summary>
        public void ReadHeader(byte[] aesKey = null, byte[] ngKey = null)
        {
            DataReader dataReader = new DataReader(this.BaseStream, Endianess.LittleEndian);
            long       position   = dataReader.Position;

            dataReader.Position = 0L;
            uint num = dataReader.ReadUInt32();

            if (num != 0x52504637)
            {
                throw new Exception("The identifier " + num.ToString("X8") + " did not match the expected value of 0x52504637");
            }
            uint num2  = dataReader.ReadUInt32();
            uint count = dataReader.ReadUInt32();
            uint num3  = dataReader.ReadUInt32();

            byte[] buffer;
            byte[] buffer2;
            if (num3 == 0x4E45504F)
            {
                this.Encryption = RageArchiveEncryption7.None;
                buffer          = dataReader.ReadBytes(16 * (int)num2);
                buffer2         = dataReader.ReadBytes((int)count);
            }
            else if (num3 == 0x0FFFFFF9)
            {
                this.Encryption = RageArchiveEncryption7.AES;
                byte[] data = dataReader.ReadBytes(16 * (int)num2);
                buffer = AesEncryption.DecryptData(data, aesKey, 1);
                byte[] data2 = dataReader.ReadBytes((int)count);
                buffer2 = AesEncryption.DecryptData(data2, aesKey, 1);
            }
            else
            {
                this.Encryption = RageArchiveEncryption7.NG;
                byte[] data3 = dataReader.ReadBytes(16 * (int)num2);
                buffer = GTA5Crypto.Decrypt(data3, ngKey);
                byte[] data4 = dataReader.ReadBytes((int)count);
                buffer2 = GTA5Crypto.Decrypt(data4, ngKey);
            }
            DataReader dataReader2         = new DataReader(new MemoryStream(buffer), Endianess.LittleEndian);
            DataReader dataReader3         = new DataReader(new MemoryStream(buffer2), Endianess.LittleEndian);
            List <IRageArchiveEntry7> list = new List <IRageArchiveEntry7>();
            int num4 = 0;

            while (num4 < num2)
            {
                dataReader2.Position += 4L;
                int num5 = dataReader2.ReadInt32();
                dataReader2.Position -= 8L;
                if (num5 == 0x7FFFFF00)
                {
                    RageArchiveDirectory7 rageArchiveDirectory = new RageArchiveDirectory7();
                    rageArchiveDirectory.Read(dataReader2);
                    dataReader3.Position      = (long)((ulong)rageArchiveDirectory.NameOffset);
                    rageArchiveDirectory.Name = dataReader3.ReadString();
                    list.Add(rageArchiveDirectory);
                }
                else if ((num5 & 0x80000000) == 0L)
                {
                    RageArchiveBinaryFile7 rageArchiveBinaryFile = new RageArchiveBinaryFile7();
                    rageArchiveBinaryFile.Read(dataReader2);
                    dataReader3.Position       = rageArchiveBinaryFile.NameOffset;
                    rageArchiveBinaryFile.Name = dataReader3.ReadString();
                    list.Add(rageArchiveBinaryFile);
                }
                else
                {
                    RageArchiveResourceFile7 rageArchiveResourceFile = new RageArchiveResourceFile7();
                    rageArchiveResourceFile.Read(dataReader2);
                    if (rageArchiveResourceFile.FileSize == 0x00FFFFFF)
                    {
                        dataReader.Position = 512 * rageArchiveResourceFile.FileOffset;
                        byte[] array = dataReader.ReadBytes(16);
                        rageArchiveResourceFile.FileSize = (uint)(array[7] | array[14] << 8 | array[5] << 16 | array[2] << 24);
                    }
                    dataReader3.Position         = rageArchiveResourceFile.NameOffset;
                    rageArchiveResourceFile.Name = dataReader3.ReadString();
                    list.Add(rageArchiveResourceFile);
                }
                num4++;
            }
            Stack <RageArchiveDirectory7> stack = new Stack <RageArchiveDirectory7>();

            stack.Push((RageArchiveDirectory7)list[0]);
            this.Root = (RageArchiveDirectory7)list[0];
            while (stack.Count > 0)
            {
                RageArchiveDirectory7 rageArchiveDirectory2 = stack.Pop();
                int num6 = (int)rageArchiveDirectory2.EntriesIndex;
                while ((long)num6 < (long)((ulong)(rageArchiveDirectory2.EntriesIndex + rageArchiveDirectory2.EntriesCount)))
                {
                    if (list[num6] is RageArchiveDirectory7)
                    {
                        rageArchiveDirectory2.Directories.Add(list[num6] as RageArchiveDirectory7);
                        stack.Push(list[num6] as RageArchiveDirectory7);
                    }
                    else
                    {
                        rageArchiveDirectory2.Files.Add(list[num6]);
                    }
                    num6++;
                }
            }
            dataReader.Position = position;
        }
 internal RageArchiveBinaryFileWrapper7(RageArchiveWrapper7 archiveWrapper, RageArchiveBinaryFile7 file)
 {
     this.archiveWrapper = archiveWrapper;
     this.file = file;
 }
        /// <summary>
        /// Creates a new binary file inside this directory.
        /// </summary>
        public IArchiveBinaryFile CreateBinaryFile()
        {
            RageArchiveBinaryFile7 realF = new RageArchiveBinaryFile7();
            RageArchiveBinaryFileWrapper7 wrD = new RageArchiveBinaryFileWrapper7(archiveWrapper, realF);


            realF.Name = "";
            var offset = archiveWrapper.FindSpace(64);
            realF.FileOffset = (uint)(offset / 512);

            directory.Files.Add(realF);

            return wrD;
        }
        public void RequestBytes(RageArchiveBinaryFile7 file_, long newLength)
        {
            // determine header size...
            long x = GetHeaderSize();

            DataBlock thisBlock = null;
            var blocks = GetBlocks();
            foreach (var q in blocks)
                if (q.Tag == file_)
                    thisBlock = q;

            long maxlength = ArchiveHelpers.FindSpace(blocks, thisBlock);
            if (maxlength < newLength)
            {
                // move...

                long offset = ArchiveHelpers.FindOffset(blocks, newLength, 512);
                ArchiveHelpers.MoveBytes(archive_.BaseStream, thisBlock.Offset, offset, thisBlock.Length);
                ((IRageArchiveFileEntry7)thisBlock.Tag).FileOffset = (uint)offset / 512;

            }

            if (file_.FileSize != 0)
                file_.FileSize = (uint)newLength;
            else
                file_.FileUncompressedSize = (uint)newLength;
        }
        /////////////////////////////////////////////////////////////////////////////
        // helper functions
        /////////////////////////////////////////////////////////////////////////////

        internal Stream GetStream(RageArchiveBinaryFile7 file_)
        {

            return new PartialStream(
                    archive_.BaseStream,
                    delegate () // offset
                    {
                        return 512 * file_.FileOffset;
                    },
                    delegate () // size
                    {
                        if (file_.FileSize != 0)
                            return file_.FileSize; // compressed
                        else
                            return file_.FileUncompressedSize; // uncompressed
                    },
                    delegate (long newLength)
                    {
                        RequestBytes(file_, newLength);
                    }
                );

        }