Ejemplo n.º 1
0
        public void Read(Stream psarc, bool lazy = false)
        {
            _toc.Clear();
            _reader             = new BigEndianBinaryReader(psarc);
            _header.MagicNumber = _reader.ReadUInt32();
            if (_header.MagicNumber == 1347633490U)//PSAR (BE)
            {
                //Parse Header
                _header.VersionNumber     = _reader.ReadUInt32();
                _header.CompressionMethod = _reader.ReadUInt32();
                _header.TotalTOCSize      = _reader.ReadUInt32();
                _header.TOCEntrySize      = _reader.ReadUInt32();
                _header.NumFiles          = _reader.ReadUInt32();
                _header.BlockSizeAlloc    = _reader.ReadUInt32();
                _header.ArchiveFlags      = _reader.ReadUInt32();
                //Read TOC
                int tocSize = (int)(_header.TotalTOCSize - 32U);
                if (_header.ArchiveFlags == 4) //TOC_ENCRYPTED
                {                              // Decrypt TOC
                    var tocStream = new MemoryStream();
                    using (var decStream = new MemoryStream())
                    {
                        RijndaelEncryptor.DecryptPSARC(psarc, decStream, _header.TotalTOCSize);

                        int bytesRead;
                        int decSize = 0;
                        var buffer  = new byte[_header.BlockSizeAlloc];
                        while ((bytesRead = decStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            decSize += bytesRead;
                            if (decSize > tocSize)
                            {
                                bytesRead = tocSize - (decSize - bytesRead);
                            }
                            tocStream.Write(buffer, 0, bytesRead);
                        }
                    }
                    tocStream.Position = 0;
                    _reader            = new BigEndianBinaryReader(tocStream);
                }
                ParseTOC();
                //Parse zBlocksSizeList
                int tocChunkSize = (int)(_header.NumFiles * _header.TOCEntrySize);//(int)_reader.BaseStream.Position //don't alter this with. causes issues
                int zNum         = (tocSize - tocChunkSize) / bNum;
                var zLengths     = new uint[zNum];
                for (int i = 0; i < zNum; i++)
                {
                    switch (bNum)
                    {
                    case 2:    //64KB
                        zLengths[i] = _reader.ReadUInt16();
                        break;

                    case 3:    //16MB
                        zLengths[i] = _reader.ReadUInt24();
                        break;

                    case 4:    //4GB
                        zLengths[i] = _reader.ReadUInt32();
                        break;
                    }
                }
                _zBlocksSizeList = zLengths; //TODO: validate

                _reader.BaseStream.Flush();  //Free tocStream resources
                _reader = new BigEndianBinaryReader(psarc);

                // Validate psarc size
                // if (psarc.Length < RequiredPsarcSize())
                // throw new InvalidDataException("Truncated psarc.");
                // try to unpack corrupt CDLC for now

                switch (_header.CompressionMethod)
                {
                case 2053925218:     //zlib (BE)
                    ReadManifest();
                    psarc.Seek(_header.TotalTOCSize, SeekOrigin.Begin);
                    if (!lazy)
                    {    // Decompress Data
                        InflateEntries();
                    }
                    break;

                case 1819962721:     //lzma (BE)
                    throw new NotImplementedException("LZMA compression not supported.");

                default:
                    throw new InvalidDataException("Unknown compression.");
                }
            }
            psarc.Flush();
        }
Ejemplo n.º 2
0
        public void Write(Stream str, bool encrypt)
        {
            if (encrypt)
            {
                this.header.archiveFlags = 4;
            }
            this.header.TOCEntrySize = 30;
            this.UpdateManifest();
            Dictionary <Entry, byte[]> dictionary;
            List <uint> list;

            this.deflateEntries(out dictionary, out list, this.header.blockSize);
            byte b   = 1;
            uint num = 256;

            do
            {
                num *= 256;
                b   += 1;
            }while (num < this.header.blockSize);
            BigEndianBinaryWriter bigEndianBinaryWriter = new BigEndianBinaryWriter(str);

            this.header.TotalTOCSize = (uint)(32 + this.header.TOCEntrySize * (this.Entries.Count) + ((int)b * list.Count));
            this.Entries[0].Offset   = (ulong)this.header.TotalTOCSize;
            for (int i = 1; i < this.Entries.Count; i++)
            {
                this.Entries[i].Offset = this.Entries[i - 1].Offset + (ulong)(dictionary[this.Entries[i - 1]].Length);
            }
            bigEndianBinaryWriter.Write(this.header.MagicNumber);
            bigEndianBinaryWriter.Write(this.header.VersionNumber);
            bigEndianBinaryWriter.Write(this.header.CompressionMethod);
            bigEndianBinaryWriter.Write(this.header.TotalTOCSize);
            bigEndianBinaryWriter.Write(this.header.TOCEntrySize);
            bigEndianBinaryWriter.Write(this.Entries.Count);
            bigEndianBinaryWriter.Write(this.header.blockSize);
            bigEndianBinaryWriter.Write(this.header.archiveFlags);
            foreach (Entry current in this.Entries)
            {
                current.UpdateNameMD5();
                bigEndianBinaryWriter.Write((current.id == 0) ? new byte[16] : current.MD5);
                bigEndianBinaryWriter.Write(current.zIndex);
                bigEndianBinaryWriter.WriteUInt40((ulong)current.Data.Length);
                bigEndianBinaryWriter.WriteUInt40(current.Offset);
            }
            foreach (uint current2 in list)
            {
                switch (b)
                {
                case 2:
                    bigEndianBinaryWriter.Write((ushort)current2);
                    break;

                case 3:
                    bigEndianBinaryWriter.WriteUInt24(current2);
                    break;

                case 4:
                    bigEndianBinaryWriter.Write(current2);
                    break;
                }
            }
            foreach (Entry current in this.Entries)
            {
                bigEndianBinaryWriter.Write(dictionary[current]);
            }

            if (encrypt)
            {
                var encStream = new MemoryStreamExtension();
                using (var outputStream = new MemoryStreamExtension())
                {
                    str.Seek(32, SeekOrigin.Begin);
                    RijndaelEncryptor.EncryptPSARC(str, outputStream, this.header.TotalTOCSize);

                    int    bytesRead;
                    byte[] buffer = new byte[30000];

                    str.Seek(0, SeekOrigin.Begin);
                    while ((bytesRead = str.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        encStream.Write(buffer, 0, bytesRead);
                    }
                    int decMax  = (int)this.header.TotalTOCSize - 32;
                    int decSize = 0;
                    outputStream.Seek(0, SeekOrigin.Begin);
                    encStream.Seek(32, SeekOrigin.Begin);
                    while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        decSize += bytesRead;
                        if (decSize > decMax)
                        {
                            bytesRead = decMax - (decSize - bytesRead);
                        }
                        encStream.Write(buffer, 0, bytesRead);
                    }
                }

                str.Seek(0, SeekOrigin.Begin);
                encStream.Seek(0, SeekOrigin.Begin);
                encStream.CopyTo(str);
            }

            str.Flush();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Packs Entries to zStream
        /// </summary>
        /// <param name="entryDeflatedData">zStreams</param>
        /// <param name="zLengths">zBlocksSizeList</param>
        private void DeflateEntries(out Dictionary <Entry, byte[]> entryDeflatedData, out List <uint> zLengths)
        {
            // TODO: This produces perfect results for song archives (original vs repacked)
            // there are slight differences in the binary of large archives (original vs repacked).  WHY?
            //
            entryDeflatedData = new Dictionary <Entry, byte[]>();
            uint blockSize = _header.BlockSizeAlloc;

            zLengths = new List <uint>();

            var    ndx      = 0; // for debugging
            var    step     = Math.Round(1.0 / (_toc.Count + 2) * 100, 3);
            double progress = 0;

            GlobalExtension.ShowProgress("Deflating Entries ...");

            foreach (Entry entry in _toc)
            {
                var zList = new List <Tuple <byte[], int> >();
                entry.zIndexBegin = (uint)zLengths.Count;
                entry.Data.Seek(0, SeekOrigin.Begin);

                while (entry.Data.Position < entry.Data.Length)
                {
                    var array_i      = new byte[blockSize];
                    var array_o      = new byte[blockSize * 2];
                    var memoryStream = new MemoryStream(array_o);

                    int plain_len  = entry.Data.Read(array_i, 0, array_i.Length);
                    int packed_len = (int)RijndaelEncryptor.Zip(array_i, memoryStream, plain_len, false);

                    if (packed_len >= plain_len)
                    {// If packed data "worse" than plain (i.e. already packed) z = 0
                        zList.Add(new Tuple <byte[], int>(array_i, plain_len));
                    }
                    else
                    {     // If packed data is good
                        if (packed_len < (blockSize - 1))
                        { // If packed data fits maximum packed block size z = packed_len
                            zList.Add(new Tuple <byte[], int>(array_o, packed_len));
                        }
                        else
                        {// Write plain. z = 0
                            zList.Add(new Tuple <byte[], int>(array_i, plain_len));
                        }
                    }
                }

                int zSisesSum = 0;
                foreach (var zSize in zList)
                {
                    zSisesSum += zSize.Item2;
                    zLengths.Add((uint)zSize.Item2);
                }

                var array3        = new byte[zSisesSum];
                var memoryStream2 = new MemoryStream(array3);
                foreach (var entryblock in zList)
                {
                    memoryStream2.Write(entryblock.Item1, 0, entryblock.Item2);
                }

                entryDeflatedData.Add(entry, array3);
                progress += step;
                GlobalExtension.UpdateProgress.Value = (int)progress;
                Debug.WriteLine("Deflating: " + ndx++);
            }
        }
Ejemplo n.º 4
0
 public static string Decrypt(string cipherText)
 {
     return(RijndaelEncryptor.Decrypt(cipherText));
 }
Ejemplo n.º 5
0
        public void Read(Stream str)
        {
            this.Entries.Clear();
            BigEndianBinaryReader bigEndianBinaryReader = new BigEndianBinaryReader(str);

            this.header.MagicNumber       = bigEndianBinaryReader.ReadUInt32();
            this.header.VersionNumber     = bigEndianBinaryReader.ReadUInt32();
            this.header.CompressionMethod = bigEndianBinaryReader.ReadUInt32();
            this.header.TotalTOCSize      = bigEndianBinaryReader.ReadUInt32();
            this.header.TOCEntrySize      = bigEndianBinaryReader.ReadUInt32();
            this.header.numFiles          = bigEndianBinaryReader.ReadUInt32();
            this.header.blockSize         = bigEndianBinaryReader.ReadUInt32();
            this.header.archiveFlags      = bigEndianBinaryReader.ReadUInt32();

            var tocStream = str;
            BigEndianBinaryReader bigEndianBinaryReaderTOC = bigEndianBinaryReader;

            if (this.header.archiveFlags == 4)
            {
                var decStream = new TempFileStream();
                using (var outputStream = new MemoryStream())
                {
                    RijndaelEncryptor.DecryptPSARC(str, outputStream, this.header.TotalTOCSize);

                    int    bytesRead;
                    byte[] buffer = new byte[30000];

                    int decMax  = (int)this.header.TotalTOCSize - 32;
                    int decSize = 0;
                    outputStream.Seek(0, SeekOrigin.Begin);
                    while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        decSize += bytesRead;
                        if (decSize > decMax)
                        {
                            bytesRead = decMax - (decSize - bytesRead);
                        }
                        decStream.Write(buffer, 0, bytesRead);
                    }
                }

                decStream.Seek(0, SeekOrigin.Begin);
                str.Seek(this.header.TotalTOCSize, SeekOrigin.Begin);
                tocStream = decStream;
                bigEndianBinaryReaderTOC = new BigEndianBinaryReader(tocStream);
            }

            if (this.header.MagicNumber == 1347633490)
            {
                if (this.header.CompressionMethod == 2053925218)
                {
                    byte b   = 1;
                    uint num = 256;
                    do
                    {
                        num *= 256;
                        b   += 1;
                    }while (num < this.header.blockSize);
                    int num2 = 0;
                    while (num2 < this.header.numFiles)
                    {
                        this.Entries.Add(new Entry
                        {
                            id     = num2,
                            MD5    = bigEndianBinaryReaderTOC.ReadBytes(16),
                            zIndex = bigEndianBinaryReaderTOC.ReadUInt32(),
                            Length = bigEndianBinaryReaderTOC.ReadUInt40(),
                            Offset = bigEndianBinaryReaderTOC.ReadUInt40()
                        });
                        num2++;
                    }

                    long   decMax = (this.header.archiveFlags == 4) ? 32 : 0;
                    uint   num3   = (this.header.TotalTOCSize - (uint)(tocStream.Position + decMax)) / (uint)b;
                    uint[] array  = new uint[num3];
                    num2 = 0;
                    while (num2 < num3)
                    {
                        switch (b)
                        {
                        case 2:
                            array[num2] = (uint)bigEndianBinaryReaderTOC.ReadUInt16();
                            break;

                        case 3:
                            array[num2] = bigEndianBinaryReaderTOC.ReadUInt24();
                            break;

                        case 4:
                            array[num2] = bigEndianBinaryReaderTOC.ReadUInt32();
                            break;
                        }
                        num2++;
                    }
                    this.inflateEntries(bigEndianBinaryReader, array.ToArray <uint>(), this.header.blockSize);
                    this.ReadNames();
                }
            }
            str.Flush();
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Writes to the inputStream
        /// <para>Default 'seek' is true, flushes and seeks to the end of stream after write is finished</para>
        /// <para>Eliminates the need for coding output.Flush() followed by output.Seek(0, SeekOrigin.Begin)</para>
        /// </summary>
        /// <param name="inputStream"></param>
        /// <param name="encrypt"></param>
        /// <param name="seek"></param>
        public void Write(Stream inputStream, bool encrypt = false, bool seek = true)
        {
            _header.ArchiveFlags = encrypt ? 4U : 0U;
            _header.TOCEntrySize = 30U;

            // track artifacts
            WriteManifest();

            //Pack entries
            List <uint> zLengths;
            Dictionary <Entry, byte[]> zStreams;

            DeflateEntries(out zStreams, out zLengths);

            //Build zLengths
            _writer = new BigEndianBinaryWriter(inputStream);
            _header.TotalTOCSize = (uint)(32 + _toc.Count * _header.TOCEntrySize + zLengths.Count * bNum);
            _toc[0].Offset       = _header.TotalTOCSize;

            for (int i = 1; i < _toc.Count; i++)
            {
                _toc[i].Offset = _toc[i - 1].Offset + (ulong)(zStreams[_toc[i - 1]].Length);
            }

            //Write Header
            _writer.Write(_header.MagicNumber);
            _writer.Write(_header.VersionNumber);
            _writer.Write(_header.CompressionMethod);
            _writer.Write(_header.TotalTOCSize);
            _writer.Write(_header.TOCEntrySize);
            _writer.Write(_toc.Count);
            _writer.Write(_header.BlockSizeAlloc);
            _writer.Write(_header.ArchiveFlags);

            var    step     = Math.Round(1D / (this.TOC.Count + 2) * 100, 3);
            double progress = 0;

            GlobalExtension.ShowProgress("Writing tocData ...");

            //Write Table of contents
            foreach (Entry entry in _toc)
            {
                entry.UpdateNameMD5();
                _writer.Write(entry.MD5);
                _writer.Write(entry.zIndexBegin);
                _writer.WriteUInt40((ulong)entry.Data.Length);
                _writer.WriteUInt40(entry.Offset);

                progress += step;
                GlobalExtension.UpdateProgress.Value = (int)progress;
                Console.WriteLine("Writing tocData: " + entry.Id);
            }

            foreach (uint zLen in zLengths)
            {
                switch (bNum)
                {
                case 2:     //16bit
                    _writer.Write((ushort)zLen);
                    break;

                case 3:     //24bit
                    _writer.WriteUInt24(zLen);
                    break;

                case 4:     //32bit
                    _writer.Write(zLen);
                    break;
                }
            }

            zLengths = null;
            progress = 0;
            GlobalExtension.ShowProgress("Writing zData ...");

            // Write zData
            foreach (Entry entry in _toc)
            {
                // skip NamesBlock.bin
                //if (current.Name == "NamesBlock.bin")
                //    continue;

                //try
                //{
                // use chunk write method to avoid OOM Exceptions
                var z   = zStreams[entry];
                var len = z.Length;
                if (len > _header.BlockSizeAlloc)
                {
                    using (var msInput = new MemoryStreamExtension(z))
                        using (var msExt = new MemoryStreamExtension())
                            using (var _writer2 = new BigEndianBinaryWriter(msExt))
                            {
                                int bytesRead;
                                int totalBytesRead = 0;
                                var buffer         = new byte[_header.BlockSizeAlloc];
                                while ((bytesRead = msInput.Read(buffer, 0, buffer.Length)) > 0)
                                {
                                    totalBytesRead += bytesRead;
                                    if (totalBytesRead > len)
                                    {
                                        bytesRead = len - (totalBytesRead - bytesRead);
                                    }

                                    using (var msOutput = new MemoryStreamExtension())
                                    {
                                        msOutput.Write(buffer, 0, bytesRead);
                                        _writer2.Write(msOutput.ToArray());
                                    }
                                }

                                _writer.Write(msExt.ToArray());
                            }
                }
                else
                {
                    _writer.Write(zStreams[entry]);
                }

                if (entry.Data != null)
                {
                    entry.Data.Close();
                }
                //}
                //catch (Exception ex)
                //{
                //    Console.WriteLine("<ERROR> _writer.Write: " + ex.Message);
                //    _writer.Flush();
                //    _writer.Dispose();
                //    break;
                //}

                progress += step;
                GlobalExtension.UpdateProgress.Value = (int)progress;
                Console.WriteLine("Writing zData: " + entry.Id);
            }

            zStreams = null;

            if (encrypt) // Encrypt TOC
            {
                using (var outputStream = new MemoryStreamExtension())
                    using (var encStream = new MemoryStreamExtension())
                    {
                        inputStream.Position = 32L;
                        RijndaelEncryptor.EncryptPSARC(inputStream, outputStream, _header.TotalTOCSize);
                        inputStream.Position = 0L;

                        // quick copy header from input stream
                        var buffer = new byte[32];
                        encStream.Write(buffer, 0, inputStream.Read(buffer, 0, buffer.Length));
                        encStream.Position = 32; //sanity check ofc
                        inputStream.Flush();

                        int tocSize = (int)_header.TotalTOCSize - 32;
                        int decSize = 0;
                        buffer = new byte[1024 * 16]; // more efficient use of memory

                        var ndx = 0;                  // for debugging
                        step     = Math.Round(1D / (((double)tocSize / buffer.Length) + 2) * 100, 3);
                        progress = 0;
                        GlobalExtension.ShowProgress("Writing encryptedData ...");

                        int bytesRead;
                        while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            decSize += bytesRead;
                            if (decSize > tocSize)
                            {
                                bytesRead = tocSize - (decSize - bytesRead);
                            }

                            encStream.Write(buffer, 0, bytesRead);

                            progress += step;
                            GlobalExtension.UpdateProgress.Value = (int)progress;
                            Console.WriteLine("Writing encryptedData: " + ndx++);
                        }

                        inputStream.Position = 0;
                        encStream.Position   = 0;
                        encStream.CopyTo(inputStream, (int)_header.BlockSizeAlloc);
                    }
            }

            if (seek)
            {
                inputStream.Flush();
                inputStream.Seek(0, SeekOrigin.Begin);
            }

            //GlobalExtension.HideProgress();
        }
Ejemplo n.º 7
0
 public static string Encrypt(string plainText)
 {
     return(RijndaelEncryptor.Encrypt(plainText));
 }
Ejemplo n.º 8
0
        public static string GetValue(string key, bool reload)
        {
            if (appSettings != null &&
                appSettings.ContainsKey(key) &&
                !reload)
            {
                return(appSettings[key]);
            }
            else
            {
                Init();

                string masterEncryptedAppHash = serverKey.EncryptWithPublicKey(config.ApplicationHash);
                //RSAKeyPair tempKey = new RSAKeyPair();
                //RijndaelKeyVectorPair clientKey = GetClientKey(masterEncryptedAppHash, tempKey);

                ConfigurationResponse valueResponse = client.GetValue(masterEncryptedAppHash, RijndaelEncryptor.Encrypt(key, clientKey.Base64Key, clientKey.Base64InitializationVector));

                string retVal = string.Empty;
                if (!string.IsNullOrEmpty(valueResponse.SettingValue))
                {
                    retVal = RijndaelEncryptor.Decrypt(valueResponse.SettingValue, clientKey.Base64Key, clientKey.Base64InitializationVector);
                }

                if (appSettings.ContainsKey(key))
                {
                    appSettings[key] = retVal;
                }
                else
                {
                    appSettings.Add(key, retVal);
                }

                lastResponse = valueResponse;
                return(retVal);
            }
        }
Ejemplo n.º 9
0
 public string Encrypt(string clearText, string strKey, string strIv)
 {
     return(RijndaelEncryptor.Encrypt(clearText, strKey, strIv));
 }
Ejemplo n.º 10
0
        public void Read(Stream psarc, bool lazy = false)
        {
            this.TOC.Clear();
            _reader = new BigEndianBinaryReader(psarc);
            this.header.MagicNumber = _reader.ReadUInt32();
            if (this.header.MagicNumber == 1347633490)//PSAR (BE)
            {
                //Parse Header
                this.header.VersionNumber     = _reader.ReadUInt32();
                this.header.CompressionMethod = _reader.ReadUInt32();
                this.header.TotalTOCSize      = _reader.ReadUInt32();
                this.header.TOCEntrySize      = _reader.ReadUInt32();
                this.header.numFiles          = _reader.ReadUInt32();
                this.header.blockSizeAlloc    = _reader.ReadUInt32();
                this.header.archiveFlags      = _reader.ReadUInt32();
                //Read TOC
                const int headerSize = 32;
                int       tocSize    = (int)this.header.TotalTOCSize - headerSize;
                if (this.header.archiveFlags == 4) //TOC_ENCRYPTED
                {                                  // Decrypt TOC
                    var tocStream = new MemoryStream();
                    using (var decStream = new MemoryStream())
                    {
                        RijndaelEncryptor.DecryptPSARC(psarc, decStream, this.header.TotalTOCSize);

                        int bytesRead;
                        int decSize = 0;
                        var buffer  = new byte[this.header.blockSizeAlloc];
                        while ((bytesRead = decStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            decSize += bytesRead;
                            if (decSize > tocSize)
                            {
                                bytesRead = tocSize - (decSize - bytesRead);
                            }
                            tocStream.Write(buffer, 0, bytesRead);
                        }
                    }
                    tocStream.Seek(0, SeekOrigin.Begin);
                    _reader = new BigEndianBinaryReader(tocStream);
                }
                ParseTOC();
                //Parse zBlocksSizeList
                int zNum     = (int)((tocSize - this.header.numFiles * this.header.TOCEntrySize) / bNum);
                var zLengths = new uint[zNum];
                for (int i = 0; i < zNum; i++)
                {
                    switch (bNum)
                    {
                    case 2:    //64KB
                        zLengths[i] = _reader.ReadUInt16();
                        break;

                    case 3:    //16MB
                        zLengths[i] = _reader.ReadUInt24();
                        break;

                    case 4:    //4GB
                        zLengths[i] = _reader.ReadUInt32();
                        break;
                    }
                }
                this.zBlocksSizeList = zLengths.ToArray();
                _reader.BaseStream.Flush();
                _reader = new BigEndianBinaryReader(psarc);

                // Validate psarc size
                // if (psarc.Length < RequiredPsarcSize())
                // throw new InvalidDataException("Truncated psarc.");
                // try to unpack corrupt CDLC for now

                if (this.header.CompressionMethod == 2053925218) //zlib (BE)
                {                                                //Read Filenames
                    ReadManifest();
                    psarc.Seek(this.header.TotalTOCSize, SeekOrigin.Begin);
                    if (!lazy)
                    {// Read Data
                        InflateEntries();
                    }
                }
                else if (this.header.CompressionMethod == 1819962721)//lzma (BE)
                {
                    throw new NotImplementedException("LZMA compression not supported.");
                }
            }
            psarc.Flush();
        }
Ejemplo n.º 11
0
        public void Write(Stream psarc, bool encrypt)
        {
            this.header.archiveFlags = encrypt ? 4U : 0U;
            this.header.TOCEntrySize = 30;
            this.WriteManifest();
            //Pack entries
            Dictionary <Entry, byte[]> zStreams; List <uint> zLengths;

            DeflateEntries(out zStreams, out zLengths);
            //Build zLengths
            _writer = new BigEndianBinaryWriter(psarc);
            this.header.TotalTOCSize = (uint)(32 + this.TOC.Count * this.header.TOCEntrySize + zLengths.Count * bNum);
            this.TOC[0].Offset       = (ulong)this.header.TotalTOCSize;
            for (int i = 1; i < this.TOC.Count; i++)
            {
                this.TOC[i].Offset = this.TOC[i - 1].Offset + (ulong)(zStreams[this.TOC[i - 1]].Length);
            }
            //Write Header
            _writer.Write(this.header.MagicNumber);
            _writer.Write(this.header.VersionNumber);
            _writer.Write(this.header.CompressionMethod);
            _writer.Write(this.header.TotalTOCSize);
            _writer.Write(this.header.TOCEntrySize);
            _writer.Write(this.TOC.Count);
            _writer.Write(this.header.blockSizeAlloc);
            _writer.Write(this.header.archiveFlags);
            //Write Table of contents
            foreach (Entry current in this.TOC)
            {
                current.UpdateNameMD5();
                _writer.Write((current.Id == 0) ? new byte[16] : current.MD5);
                _writer.Write(current.zIndexBegin);
                _writer.WriteUInt40((ulong)current.Data.Length);
                _writer.WriteUInt40(current.Offset);
            }
            foreach (uint zLen in zLengths)
            {
                switch (bNum)
                {
                case 2:
                    _writer.Write((ushort)zLen);
                    break;

                case 3:
                    _writer.WriteUInt24(zLen);
                    break;

                case 4:
                    _writer.Write(zLen);
                    break;
                }
            }
            //Write zData
            foreach (Entry current in this.TOC)
            {
                _writer.Write(zStreams[current]);
                current.Data.Close();
            }
            if (encrypt)
            {// Encrypt TOC
                var encStream = new MemoryStreamExtension();
                using (var outputStream = new MemoryStreamExtension())
                {
                    int bytesRead;
                    int decSize = 0;
                    var buffer  = new byte[30000];
                    int tocSize = (int)this.header.TotalTOCSize - 32;

                    psarc.Seek(32, SeekOrigin.Begin);
                    RijndaelEncryptor.EncryptPSARC(psarc, outputStream, this.header.TotalTOCSize);

                    psarc.Seek(0, SeekOrigin.Begin);
                    while ((bytesRead = psarc.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        encStream.Write(buffer, 0, bytesRead);
                    }

                    outputStream.Seek(0, SeekOrigin.Begin);
                    encStream.Seek(32, SeekOrigin.Begin);
                    while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        decSize += bytesRead;
                        if (decSize > tocSize)
                        {
                            bytesRead = tocSize - (decSize - bytesRead);
                        }
                        encStream.Write(buffer, 0, bytesRead);
                    }
                }

                psarc.Seek(0, SeekOrigin.Begin);
                encStream.Seek(0, SeekOrigin.Begin);
                encStream.CopyTo(psarc, (int)this.header.blockSizeAlloc);
            }
            psarc.Flush();
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Inflates selected entry.
        /// </summary>
        /// <param name="entry">Entry to unpack.</param>
        /// <param name = "destfilepath">Destination file used instead of the temp file.</param>
        public void InflateEntry(Entry entry, string destfilepath = "")
        {
            if (entry.Length == 0)
            {
                return;                   //skip empty files
            }
            // Decompress Entry
            const int zHeader   = 0x78DA;
            uint      zChunkID  = entry.zIndexBegin;
            int       blockSize = (int)_header.BlockSizeAlloc;

            //bool isZlib = _header.CompressionMethod == 2053925218;
            if (destfilepath.Length > 0)
            {
                entry.Data = new FileStream(destfilepath, FileMode.Create, FileAccess.Write, FileShare.Read);
            }
            else
            {
                if (UseMemory)
                {
                    entry.Data = new MemoryStreamExtension();
                }
                else
                {
                    entry.Data = new TempFileStream();
                }
            }

            _reader.BaseStream.Position = (long)entry.Offset;

            do
            {
                // check for corrupt CDLC content and catch exceptions
                try
                {
                    if (_zBlocksSizeList[zChunkID] == 0U) // raw. full cluster used.
                    {
                        entry.Data.Write(_reader.ReadBytes(blockSize), 0, blockSize);
                    }
                    else
                    {
                        var num = _reader.ReadUInt16();
                        _reader.BaseStream.Position -= 2L;

                        var array = _reader.ReadBytes((int)_zBlocksSizeList[zChunkID]);
                        if (num == zHeader)
                        {
                            // compressed
                            try
                            {
                                RijndaelEncryptor.Unzip(array, entry.Data, false);
                            }
                            catch (Exception ex) //IOException
                            {
                                // corrupt CDLC zlib.net exception ... try to unpack
                                if (String.IsNullOrEmpty(entry.Name))
                                {
                                    ErrMsg.AppendLine(String.Format(@"CDLC contains a zlib exception.{1}Warning: {0}", ex.Message, Environment.NewLine));
                                }
                                else
                                {
                                    ErrMsg.AppendLine(String.Format(@"CDLC contains a broken datachunk in file '{0}'.{2}Warning Type 1: {1}", entry.Name.Split('/').Last(), ex.Message, Environment.NewLine));
                                }

                                Debug.Write(ErrMsg.ToString());
                            }
                        }
                        else // raw. used only for data(chunks) smaller than 64 kb
                        {
                            entry.Data.Write(array, 0, array.Length);
                        }
                    }

                    zChunkID += 1;
                }
                catch (Exception ex) // index is outside the bounds of the array
                {
                    // corrupt CDLC data length ... try to unpack
                    ErrMsg.AppendLine(String.Format(@"CDLC contains a broken datachunk in file '{0}'.{2}Warning Type 2: {1}", entry.Name.Split('/').Last(), ex.Message, Environment.NewLine));
                    Debug.Write(ErrMsg.ToString());
                    break;
                }
            } while (entry.Data.Length < (long)entry.Length);

            entry.Data.Seek(0, SeekOrigin.Begin);
            entry.Data.Flush();
        }
Ejemplo n.º 13
0
        static void Main(string[] args)
        {
            var arguments = new Arguments();
            var options   = GetOptions(arguments);

            if (args.Length == 0)
            {
                options.WriteOptionDescriptions(Console.Out);
                return;
            }
            try
            {
                options.Parse(args);
                if (arguments.ShowHelp)
                {
                    options.WriteOptionDescriptions(Console.Out);
                    return;
                }

                var inputFiles = arguments.InputFiles.ToList();
                if (!arguments.InputFiles.Any() && args.Length > 0)
                {
                    inputFiles.Add(args.First());
                }
                foreach (var file in inputFiles)
                {
                    FileAttributes attr = File.GetAttributes(Path.GetFullPath(file));
                    if ((attr & FileAttributes.Directory) == FileAttributes.Directory && Directory.Exists(file))
                    {
                        foreach (var file1 in Directory.EnumerateFiles(file, "*.*", SearchOption.AllDirectories))
                        {
                            if (File.Exists(file1))
                            {
                                arguments.InputFiles.Add(file1);
                            }
                        }
                    }
                    else
                    {
                        arguments.InputFiles.Add(file);
                    }
                }

                var missingFiles = arguments.InputFiles.Where(i => !File.Exists(i)).ToList();
                if (missingFiles.Any())
                {
                    var message = "The specified input file(s) do not exist: \n"
                                  + string.Join("\n", missingFiles.Select(f => "\t" + f));
                    ShowHelpfulError(message);
                }
            }
            catch (OptionException ex)
            {
                ShowHelpfulError(ex.Message);
                return;
            }

            foreach (var inputPath in arguments.InputFiles)
            {
                var outputDirectory = Path.GetDirectoryName(inputPath);
                using (var inputStream = File.OpenRead(inputPath))
                {
                    if (!arguments.Encrypt)
                    {
                        var outputFilename = Path.GetFileName(inputPath) + ".decrypted";
                        var outputPath     = Path.Combine(outputDirectory, outputFilename);

                        Directory.CreateDirectory(outputDirectory);
                        using (var outputStream = File.Create(outputPath))
                            RijndaelEncryptor.DecryptFile(inputStream, outputStream, RijndaelEncryptor.PCFilesKey);
                    }
                    if (arguments.Encrypt)
                    {
                        var outputFilename = Path.GetFileName(inputPath) + ".encrypted";
                        var outputPath     = Path.Combine(outputDirectory, outputFilename);

                        Directory.CreateDirectory(outputDirectory);
                        using (var outputStream = File.Create(outputPath))
                            RijndaelEncryptor.EncryptFile(inputStream, outputStream, RijndaelEncryptor.PCFilesKey);
                    }
                }
            }
        }
Ejemplo n.º 14
0
        public static void PackSng(Stream input, Stream output, Platform platform)
        {
            EndianBitConverter conv;
            Int32 platformHeader;

            switch (platform.platform)
            {
            case GamePlatform.Pc:
            case GamePlatform.Mac:
                // Desktop
                conv           = EndianBitConverter.Little;
                platformHeader = 3;
                break;

            case GamePlatform.XBox360:
            case GamePlatform.PS3:
                // Console
                conv           = EndianBitConverter.Big;
                platformHeader = 1;
                break;

            default:
                conv           = EndianBitConverter.Little;
                platformHeader = 3;
                break;
            }

            using (EndianBinaryWriter w = new EndianBinaryWriter(conv, output)) {
                w.Write((Int32)0x4A);
                w.Write(platformHeader);

                byte[] inputChartData = null;
                using (var mStream = new MemoryStream())
                {
                    input.CopyTo(mStream);
                    inputChartData = mStream.ToArray();
                }

                // pack with zlib
                MemoryStream  zData = new MemoryStream();
                ZOutputStream zOut  = new ZOutputStream(zData, zlib.zlibConst.Z_BEST_COMPRESSION);
                zOut.Write(inputChartData, 0, inputChartData.Length);
                zOut.finish();
                byte[] packed = zData.ToArray();

                if (platformHeader == 3)
                {
                    MemoryStream encrypted = new MemoryStream();
                    MemoryStream plain     = new MemoryStream();
                    var          encw      = new EndianBinaryWriter(conv, plain);
                    // write size of uncompressed data and packed data itself
                    encw.Write((Int32)inputChartData.Length);
                    encw.Write(packed);
                    encw.Flush();
                    MemoryStream inputPlainStream = new MemoryStream(plain.ToArray());

                    // choose key
                    byte[] key;
                    switch (platform.platform)
                    {
                    case GamePlatform.Mac:
                        key = RijndaelEncryptor.SngKeyMac;
                        break;

                    default:     //PC
                        key = RijndaelEncryptor.SngKeyPC;
                        break;
                    }

                    // encrypt (writes 16B IV and encrypted data)
                    RijndaelEncryptor.EncryptSngData(inputPlainStream, encrypted, key);
                    w.Write(encrypted.ToArray());
                    // append zero signature
                    w.Write(new Byte[56]);
                }
                else
                {
                    // unencrypted and unsigned
                    w.Write((Int32)inputChartData.Length);
                    w.Write(packed);
                }

                output.Flush();
            }
        }
Ejemplo n.º 15
0
        public void Write(Stream inputStream, bool encrypt = false, bool seek = true)
        {
            _header.ArchiveFlags = encrypt ? 4U : 0U;
            _header.TOCEntrySize = 30U;
            WriteManifest();
            //Pack entries
            List <uint> zLengths;
            Dictionary <Entry, byte[]> zStreams;

            DeflateEntries(out zStreams, out zLengths);
            //Build zLengths
            _writer = new BigEndianBinaryWriter(inputStream);
            _header.TotalTOCSize = (uint)(32 + _toc.Count * _header.TOCEntrySize + zLengths.Count * bNum);
            _toc[0].Offset       = _header.TotalTOCSize;
            for (int i = 1; i < _toc.Count; i++)
            {
                _toc[i].Offset = _toc[i - 1].Offset + (ulong)(zStreams[_toc[i - 1]].Length);
            }
            //Write Header
            _writer.Write(_header.MagicNumber);
            _writer.Write(_header.VersionNumber);
            _writer.Write(_header.CompressionMethod);
            _writer.Write(_header.TotalTOCSize);
            _writer.Write(_header.TOCEntrySize);
            _writer.Write(_toc.Count);
            _writer.Write(_header.BlockSizeAlloc);
            _writer.Write(_header.ArchiveFlags);
            //Write Table of contents
            foreach (Entry current in _toc)
            {
                current.UpdateNameMD5();
                _writer.Write(current.MD5);
                _writer.Write(current.zIndexBegin);
                _writer.WriteUInt40((ulong)current.Data.Length);//current.Length
                _writer.WriteUInt40(current.Offset);
            }
            foreach (uint zLen in zLengths)
            {
                switch (bNum)
                {
                case 2:    //16bit
                    _writer.Write((ushort)zLen);
                    break;

                case 3:    //24bit
                    _writer.WriteUInt24(zLen);
                    break;

                case 4:    //32bit
                    _writer.Write(zLen);
                    break;
                }
            }
            zLengths = null;

            // Write zData
            var    ndx      = 0; // for debugging
            var    step     = Math.Round(1D / (this.TOC.Count + 2) * 100, 3);
            double progress = 0;

            GlobalExtension.ShowProgress("Writing Zipped Data ...");

            foreach (Entry current in _toc)
            {
                _writer.Write(zStreams[current]);
                progress += step;
                GlobalExtension.UpdateProgress.Value = (int)progress;
                Debug.WriteLine("Zipped: " + ndx++);
                current.Data.Close();
            }
            zStreams = null;

            if (encrypt) // Encrypt TOC
            {
                using (var outputStream = new MemoryStreamExtension())
                {
                    var encStream = new MemoryStreamExtension();
                    inputStream.Position = 32L;
                    RijndaelEncryptor.EncryptPSARC(inputStream, outputStream, _header.TotalTOCSize);
                    inputStream.Position = 0L;

                    // quick copy header from input stream
                    var buffer = new byte[32];
                    encStream.Write(buffer, 0, inputStream.Read(buffer, 0, buffer.Length));
                    encStream.Position = 32; //sanity check ofc
                    inputStream.Flush();

                    int tocSize = (int)_header.TotalTOCSize - 32;
                    int decSize = 0;
                    buffer = new byte[1024 * 16]; // more efficient use of memory

                    ndx      = 0;                 // for debugging
                    step     = Math.Round(1D / (((double)tocSize / buffer.Length) + 2) * 100, 3);
                    progress = 0;
                    GlobalExtension.ShowProgress("Writing Encrypted Data ...");

                    int bytesRead;
                    while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        decSize += bytesRead;
                        if (decSize > tocSize)
                        {
                            bytesRead = tocSize - (decSize - bytesRead);
                        }

                        encStream.Write(buffer, 0, bytesRead);

                        progress += step;
                        GlobalExtension.UpdateProgress.Value = (int)progress;
                        Debug.WriteLine("Encrypted: " + ndx++);
                    }

                    inputStream.Position = 0;
                    encStream.Position   = 0;
                    encStream.CopyTo(inputStream, (int)_header.BlockSizeAlloc);
                }
            }
            if (seek) // May be redundant
            {
                inputStream.Flush();
                inputStream.Position = 0;
            }
            //GlobalExtension.HideProgress();
        }
Ejemplo n.º 16
0
 public string Decrypt(string cipherText, string strKey, string strIv)
 {
     return(RijndaelEncryptor.Decrypt(cipherText, strKey, strIv));
 }
Ejemplo n.º 17
0
        /// <summary>
        /// Inflates selected entry.
        /// </summary>
        /// <param name="entry">Enty to unpack.</param>
        /// <param name = "destfilepath">Destanation file used instead of the temp file.</param>
        public void InflateEntry(Entry entry, string destfilepath = "")
        {
            if (entry.Length > 0)
            {// Decompress Entry
                uint      zChunkID  = entry.zIndexBegin;
                int       blockSize = (int)this.header.blockSizeAlloc;
                bool      isZlib    = this.header.CompressionMethod == 2053925218;
                const int zHeader   = 0x78DA;

                if (destfilepath.Length > 0)
                {
                    entry.Data = new FileStream(destfilepath, FileMode.Create, FileAccess.Write, FileShare.Read);
                }
                else
                {
                    entry.Data = new TempFileStream();
                }

                var data = entry.Data;
                _reader.BaseStream.Position = (long)entry.Offset;

                do
                {
                    // check for corrupt CDLC content and catch exceptions
                    try
                    {
                        if (this.zBlocksSizeList[zChunkID] == 0)
                        {
                            // raw
                            byte[] array = _reader.ReadBytes(blockSize);
                            data.Write(array, 0, blockSize);
                        }
                        else
                        {
                            var num = _reader.ReadUInt16();
                            _reader.BaseStream.Position -= 2;

                            byte[] array = _reader.ReadBytes((int)this.zBlocksSizeList[zChunkID]);
                            if (num == zHeader)
                            {
                                // compressed
                                try
                                {
                                    RijndaelEncryptor.Unzip(array, data, false);
                                }
                                catch (Exception ex)
                                {
                                    // corrupt CDLC zlib.net exception ... try to unpack
                                    if (String.IsNullOrEmpty(entry.Name))
                                    {
                                        ErrMSG = String.Format(@"{1}CDLC contains a zlib exception.{1}Warning: {0}{1}", ex.Message, Environment.NewLine);
                                    }
                                    else
                                    {
                                        ErrMSG = String.Format(@"{2}CDLC contains a broken datachunk in file '{0}'.{2}Warning: {1}{2}", entry.Name.Split('/').Last(), ex.Message, Environment.NewLine);
                                    }

                                    Console.Write(ErrMSG);
                                }
                            }
                            else
                            {
                                // raw. used only after 0?
                                data.Write(array, 0, array.Length);
                            }
                        }
                        zChunkID += 1;
                    }
                    catch (Exception ex) // index is outside the bounds of the array
                    {
                        // corrupt CDLC data length ... try to unpack
                        ErrMSG = String.Format(@"{2}CDLC contains a broken datachunk in file '{0}'.{2}Warning: {1}{2}", entry.Name.Split('/').Last(), ex.Message, Environment.NewLine);
                        Console.Write(ErrMSG + Environment.NewLine);
                        break;
                    }
                }while (data.Length < (long)entry.Length);
                data.Seek(0, SeekOrigin.Begin);
                data.Flush();
            }
        }
Ejemplo n.º 18
0
        public void Write(Stream inputStream, bool encrypt)
        {
            // TODO: This produces perfect results for song archives (original vs repacked)
            // there are slight differences in the binary of large archives (original vs repacked).  WHY?
            //
            this.header.archiveFlags = encrypt ? 4U : 0U;
            this.header.TOCEntrySize = 30;
            this.WriteManifest();
            //Pack entries
            Dictionary <Entry, byte[]> zStreams; List <uint> zLengths;

            DeflateEntries(out zStreams, out zLengths);
            //Build zLengths
            _writer = new BigEndianBinaryWriter(inputStream);
            this.header.TotalTOCSize = (uint)(32 + this.TOC.Count * this.header.TOCEntrySize + zLengths.Count * bNum);
            this.TOC[0].Offset       = (ulong)this.header.TotalTOCSize;
            for (int i = 1; i < this.TOC.Count; i++)
            {
                this.TOC[i].Offset = this.TOC[i - 1].Offset + (ulong)(zStreams[this.TOC[i - 1]].Length);
            }
            //Write Header
            _writer.Write(this.header.MagicNumber);
            _writer.Write(this.header.VersionNumber);
            _writer.Write(this.header.CompressionMethod);
            _writer.Write(this.header.TotalTOCSize);
            _writer.Write(this.header.TOCEntrySize);
            _writer.Write(this.TOC.Count);
            _writer.Write(this.header.blockSizeAlloc);
            _writer.Write(this.header.archiveFlags);
            //Write Table of contents
            foreach (Entry current in this.TOC)
            {
                current.UpdateNameMD5();
                _writer.Write((current.Id == 0) ? new byte[16] : current.MD5);
                _writer.Write(current.zIndexBegin);
                _writer.WriteUInt40((ulong)current.Data.Length);
                _writer.WriteUInt40(current.Offset);
            }
            foreach (uint zLen in zLengths)
            {
                switch (bNum)
                {
                case 2:
                    _writer.Write((ushort)zLen);
                    break;

                case 3:
                    _writer.WriteUInt24(zLen);
                    break;

                case 4:
                    _writer.Write(zLen);
                    break;
                }
            }

            // Write zData
            var    ndx      = 0; // for debugging
            var    step     = Math.Round(1.0 / (this.TOC.Count + 2) * 100, 3);
            double progress = 0;

            GlobalExtension.ShowProgress("Writing Zipped Data ...");

            foreach (Entry current in this.TOC)
            {
                _writer.Write(zStreams[current]);
                progress += step;
                GlobalExtension.UpdateProgress.Value = (int)progress;
                Debug.WriteLine("Zipped: " + ndx++);
                current.Data.Close();
            }

            if (encrypt) // Encrypt TOC
            {
                using (var outputStream = new MemoryStreamExtension())
                {
                    var encStream = new MemoryStreamExtension();
                    inputStream.Seek(32, SeekOrigin.Begin);
                    RijndaelEncryptor.EncryptPSARC(inputStream, outputStream, this.header.TotalTOCSize);
                    inputStream.Seek(0, SeekOrigin.Begin);

                    int bytesRead;
                    var buffer = new byte[32];
                    bytesRead = inputStream.Read(buffer, 0, buffer.Length);
                    inputStream.Flush();
                    // quick copy header from input stream
                    encStream.Write(buffer, 0, bytesRead);
                    encStream.Seek(32, SeekOrigin.Begin);

                    int tocSize = (int)this.header.TotalTOCSize - 32;
                    int decSize = 0;
                    buffer = new byte[1024 * 16]; // more effecient use of memory

                    ndx      = 0;                 // for debuging
                    step     = Math.Round(1.0 / ((tocSize / buffer.Length) + 2) * 100, 3);
                    progress = 0;
                    GlobalExtension.ShowProgress("Writing Encrypted Data ...");

                    while ((bytesRead = outputStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        decSize += bytesRead;
                        if (decSize > tocSize)
                        {
                            bytesRead = tocSize - (decSize - bytesRead);
                        }

                        encStream.Write(buffer, 0, bytesRead);

                        progress += step;
                        GlobalExtension.UpdateProgress.Value = (int)progress;
                        Debug.WriteLine("Encrypted: " + ndx++);
                    }

                    inputStream.Seek(0, SeekOrigin.Begin);
                    encStream.Seek(0, SeekOrigin.Begin);
                    encStream.CopyTo(inputStream, (int)this.header.blockSizeAlloc);
                }
            }

            inputStream.Flush();
            GlobalExtension.HideProgress();
        }