Ejemplo n.º 1
0
        /// <summary>
        /// Writes the archive header.
        /// </summary>
        public void WriteHeader(byte[] aesKey = null, byte[] ngKey = null)
        {
            // backup position
            var positionBackup = BaseStream.Position;

            var writer = new DataWriter(BaseStream);


            var entries    = new List <IRageArchiveEntry7>();
            var stack      = new Stack <RageArchiveDirectory7>();
            var nameOffset = 1;


            entries.Add(Root);
            stack.Push(Root);

            var nameDict = new Dictionary <string, uint>();

            nameDict.Add("", 0);

            while (stack.Count > 0)
            {
                var directory = stack.Pop();

                directory.EntriesIndex = (uint)entries.Count;
                directory.EntriesCount = (uint)directory.Directories.Count + (uint)directory.Files.Count;

                var theList = new List <IRageArchiveEntry7>();

                foreach (var xd in directory.Directories)
                {
                    if (!nameDict.ContainsKey(xd.Name))
                    {
                        nameDict.Add(xd.Name, (uint)nameOffset);
                        nameOffset += xd.Name.Length + 1;
                    }
                    xd.NameOffset = nameDict[xd.Name];

                    //xd.NameOffset = (ushort)nameOffset;
                    //nameOffset += xd.Name.Length + 1;
                    //entries.Add(xd);
                    //stack.Push(xd);
                    theList.Add(xd);
                }

                foreach (var xf in directory.Files)
                {
                    if (!nameDict.ContainsKey(xf.Name))
                    {
                        nameDict.Add(xf.Name, (uint)nameOffset);
                        nameOffset += xf.Name.Length + 1;
                    }
                    xf.NameOffset = nameDict[xf.Name];

                    //xf.NameOffset = (ushort)nameOffset;
                    //nameOffset += xf.Name.Length + 1;
                    //entries.Add(xf);
                    theList.Add(xf);
                }

                theList.Sort(
                    delegate(IRageArchiveEntry7 a, IRageArchiveEntry7 b)
                {
                    return(string.CompareOrdinal(a.Name, b.Name));
                }
                    );
                foreach (var xx in theList)
                {
                    entries.Add(xx);
                }
                theList.Reverse();
                foreach (var xx in theList)
                {
                    if (xx is RageArchiveDirectory7)
                    {
                        stack.Push((RageArchiveDirectory7)xx);
                    }
                }
            }


            // there are sometimes resources with length>=0xffffff which actually
            // means length=0xffffff
            // -> we therefore just cut the file size
            foreach (var entry in entries)
            {
                if (entry is RageArchiveResourceFile7)
                {
                    var resource = entry as RageArchiveResourceFile7;
                    if (resource.FileSize > 0xFFFFFF)
                    {
                        var buf = new byte[16];
                        buf[7]  = (byte)((resource.FileSize >> 0) & 0xFF);
                        buf[14] = (byte)((resource.FileSize >> 8) & 0xFF);
                        buf[5]  = (byte)((resource.FileSize >> 16) & 0xFF);
                        buf[2]  = (byte)((resource.FileSize >> 24) & 0xFF);

                        if (writer.Length > 512 * resource.FileOffset)
                        {
                            writer.Position = 512 * resource.FileOffset;
                            writer.Write(buf);
                        }

                        resource.FileSize = 0xFFFFFF;
                    }
                }
            }


            // entries...
            var ent_str = new MemoryStream();
            var ent_wr  = new DataWriter(ent_str);

            foreach (var entry in entries)
            {
                entry.Write(ent_wr);
            }
            ent_str.Flush();

            var ent_buf = new byte[ent_str.Length];

            ent_str.Position = 0;
            ent_str.Read(ent_buf, 0, ent_buf.Length);

            if (Encryption == RageArchiveEncryption7.AES)
            {
                ent_buf = AesEncryption.EncryptData(ent_buf, aesKey);
            }
            else if (Encryption == RageArchiveEncryption7.NG)
            {
                ent_buf = GTA5Crypto.Encrypt(ent_buf, ngKey);
            }

            // names...
            var n_str = new MemoryStream();
            var n_wr  = new DataWriter(n_str);

            //foreach (var entry in entries)
            //    n_wr.Write(entry.Name);
            foreach (var entry in nameDict)
            {
                n_wr.Write(entry.Key);
            }
            var empty = new byte[16 - (n_wr.Length % 16)];

            n_wr.Write(empty);
            n_str.Flush();

            var n_buf = new byte[n_str.Length];

            n_str.Position = 0;
            n_str.Read(n_buf, 0, n_buf.Length);

            if (Encryption == RageArchiveEncryption7.AES)
            {
                n_buf = AesEncryption.EncryptData(n_buf, aesKey);
            }
            else if (Encryption == RageArchiveEncryption7.NG)
            {
                n_buf = GTA5Crypto.Encrypt(n_buf, ngKey);
            }

            writer.Position = 0;
            writer.Write((uint)IDENT);
            writer.Write((uint)entries.Count);
            writer.Write((uint)n_buf.Length);

            switch (Encryption)
            {
            case RageArchiveEncryption7.None:
                writer.Write((uint)0x04E45504F);
                break;

            case RageArchiveEncryption7.AES:
                writer.Write((uint)0x0ffffff9);
                break;

            case RageArchiveEncryption7.NG:
                writer.Write((uint)0x0fefffff);
                break;
            }

            writer.Write(ent_buf);
            writer.Write(n_buf);



            // restore position
            BaseStream.Position = positionBackup;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Writes the archive header.
        /// </summary>
        public void WriteHeader(byte[] aesKey = null, byte[] ngKey = null)
        {
            long       position   = this.BaseStream.Position;
            DataWriter dataWriter = new DataWriter(this.BaseStream, Endianess.LittleEndian);
            List <IRageArchiveEntry7>     list  = new List <IRageArchiveEntry7>();
            Stack <RageArchiveDirectory7> stack = new Stack <RageArchiveDirectory7>();
            int num = 1;

            list.Add(this.Root);
            stack.Push(this.Root);
            Dictionary <string, uint> dictionary = new Dictionary <string, uint>();

            dictionary.Add("", 0);
            while (stack.Count > 0)
            {
                RageArchiveDirectory7 rageArchiveDirectory = stack.Pop();
                rageArchiveDirectory.EntriesIndex = (uint)list.Count;
                rageArchiveDirectory.EntriesCount = (uint)(rageArchiveDirectory.Directories.Count + rageArchiveDirectory.Files.Count);
                List <IRageArchiveEntry7> list2 = new List <IRageArchiveEntry7>();
                foreach (RageArchiveDirectory7 rageArchiveDirectory2 in rageArchiveDirectory.Directories)
                {
                    if (!dictionary.ContainsKey(rageArchiveDirectory2.Name))
                    {
                        dictionary.Add(rageArchiveDirectory2.Name, (uint)num);
                        num += rageArchiveDirectory2.Name.Length + 1;
                    }
                    rageArchiveDirectory2.NameOffset = dictionary[rageArchiveDirectory2.Name];
                    list2.Add(rageArchiveDirectory2);
                }
                foreach (IRageArchiveEntry7 rageArchiveEntry in rageArchiveDirectory.Files)
                {
                    if (!dictionary.ContainsKey(rageArchiveEntry.Name))
                    {
                        dictionary.Add(rageArchiveEntry.Name, (uint)num);
                        num += rageArchiveEntry.Name.Length + 1;
                    }
                    rageArchiveEntry.NameOffset = dictionary[rageArchiveEntry.Name];
                    list2.Add(rageArchiveEntry);
                }
                list2.Sort((IRageArchiveEntry7 a, IRageArchiveEntry7 b) => string.CompareOrdinal(a.Name, b.Name));
                foreach (IRageArchiveEntry7 item in list2)
                {
                    list.Add(item);
                }
                list2.Reverse();
                foreach (IRageArchiveEntry7 rageArchiveEntry2 in list2)
                {
                    if (rageArchiveEntry2 is RageArchiveDirectory7)
                    {
                        stack.Push((RageArchiveDirectory7)rageArchiveEntry2);
                    }
                }
            }
            foreach (IRageArchiveEntry7 rageArchiveEntry3 in list)
            {
                if (rageArchiveEntry3 is RageArchiveResourceFile7)
                {
                    RageArchiveResourceFile7 rageArchiveResourceFile = rageArchiveEntry3 as RageArchiveResourceFile7;
                    if (rageArchiveResourceFile.FileSize > 0x00FFFFFF)
                    {
                        byte[] array = new byte[16];
                        array[7]  = (byte)(rageArchiveResourceFile.FileSize & 255);
                        array[14] = (byte)(rageArchiveResourceFile.FileSize >> 8 & 255);
                        array[5]  = (byte)(rageArchiveResourceFile.FileSize >> 16 & 255);
                        array[2]  = (byte)(rageArchiveResourceFile.FileSize >> 24 & 255);
                        if (dataWriter.Length > (512 * rageArchiveResourceFile.FileOffset))
                        {
                            dataWriter.Position = (512 * rageArchiveResourceFile.FileOffset);
                            dataWriter.Write(array);
                        }
                        rageArchiveResourceFile.FileSize = 0x00FFFFFF;
                    }
                }
            }
            MemoryStream memoryStream = new MemoryStream();
            DataWriter   writer       = new DataWriter(memoryStream, Endianess.LittleEndian);

            foreach (IRageArchiveEntry7 rageArchiveEntry4 in list)
            {
                rageArchiveEntry4.Write(writer);
            }
            memoryStream.Flush();
            byte[] array2 = new byte[memoryStream.Length];
            memoryStream.Position = 0L;
            memoryStream.Read(array2, 0, array2.Length);
            if (this.Encryption == RageArchiveEncryption7.AES)
            {
                array2 = AesEncryption.EncryptData(array2, aesKey, 1);
            }
            if (this.Encryption == RageArchiveEncryption7.NG)
            {
                array2 = GTA5Crypto.Encrypt(array2, ngKey);
            }
            MemoryStream memoryStream2 = new MemoryStream();
            DataWriter   dataWriter2   = new DataWriter(memoryStream2, Endianess.LittleEndian);

            foreach (KeyValuePair <string, uint> keyValuePair in dictionary)
            {
                dataWriter2.Write(keyValuePair.Key);
            }
            byte[] value = new byte[16L - dataWriter2.Length % 16L];
            dataWriter2.Write(value);
            memoryStream2.Flush();
            byte[] array3 = new byte[memoryStream2.Length];
            memoryStream2.Position = 0L;
            memoryStream2.Read(array3, 0, array3.Length);
            if (this.Encryption == RageArchiveEncryption7.AES)
            {
                array3 = AesEncryption.EncryptData(array3, aesKey, 1);
            }
            if (this.Encryption == RageArchiveEncryption7.NG)
            {
                array3 = GTA5Crypto.Encrypt(array3, ngKey);
            }
            dataWriter.Position = 0L;
            dataWriter.Write(0x52504637);
            dataWriter.Write((uint)list.Count);
            dataWriter.Write((uint)array3.Length);
            switch (this.Encryption)
            {
            case RageArchiveEncryption7.None:
                dataWriter.Write(0x4E45504F);
                break;

            case RageArchiveEncryption7.AES:
                dataWriter.Write(0x0FFFFFF9);
                break;

            case RageArchiveEncryption7.NG:
                dataWriter.Write(0x0FEFFFFF);
                break;
            }
            dataWriter.Write(array2);
            dataWriter.Write(array3);
            this.BaseStream.Position = position;
        }