public void InflateEntry(Entry entry, BigEndianBinaryReader reader, uint[] zLenghts, uint blockSize, Stream output)
 {
     if (entry.Length != 0)
     {
         reader.BaseStream.Position = (long)entry.Offset;
         uint num = entry.zIndex;
         do
         {
             if (zLenghts[num] == 0)
             {
                 byte[] array = reader.ReadBytes((int)blockSize);
                 output.Write(array, 0, (int)blockSize);
             }
             else
             {
                 ushort num2 = reader.ReadUInt16();
                 reader.BaseStream.Position -= 2;
                 byte[] array = reader.ReadBytes((int)zLenghts[num]);
                 if (num2 == 30938)
                 {
                     ZOutputStream zOutputStream = new ZOutputStream(output);
                     zOutputStream.Write(array, 0, array.Length);
                     zOutputStream.Flush();
                 }
                 else
                 {
                     output.Write(array, 0, array.Length);
                 }
             }
             num += 1;
         }
         while (output.Length < (long)entry.Length);
     }
     output.Flush();
     output.Seek(0, SeekOrigin.Begin);
 }
        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();
        }
        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();
        }
Example #4
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();
        }
Example #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();
		}
Example #6
0
 private void inflateEntries(BigEndianBinaryReader reader, uint[] zLengths, uint blockSize)
 {
     foreach (Entry current in this.Entries)
     {
         current.Data = new Entry.DataPointer(current, reader, zLengths, blockSize);
     }
 }
Example #7
0
 public DataPointer(Entry entry, BigEndianBinaryReader reader, uint[] zLengths, uint blockSize)
 {
     this.entry = entry;
     this.reader = reader;
     this.zLengths = zLengths;
     this.blockSize = blockSize;
 }
Example #8
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();
        }
 private void inflateEntries(BigEndianBinaryReader reader, uint[] zLenghts, uint blockSize)
 {
     foreach (Entry current in this.Entries)
     {
         current.Data = new TempFileStream();
         this.InflateEntry(current, reader, zLenghts, blockSize, current.Data);
     }
 }