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(); }
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(); }
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[] zLengths, uint blockSize) { foreach (Entry current in this.Entries) { current.Data = new Entry.DataPointer(current, reader, zLengths, blockSize); } }
public DataPointer(Entry entry, BigEndianBinaryReader reader, uint[] zLengths, uint blockSize) { this.entry = entry; this.reader = reader; this.zLengths = zLengths; this.blockSize = blockSize; }
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); } }