Reset() public method

Resets the inflater so that a new stream can be decompressed. All pending input and output will be discarded.
public Reset ( ) : void
return void
			public void CopyTo(Stream dest)
			{
				if ((fileDes.Flags & FileCompressed) != 0)
				{
					var inf = new Inflater(true);
					var buffer = new byte[165535];
					do
					{
						var bytesToExtract = cabFile.ReadUInt16();
						RemainingArchiveStream -= 2u;
						RemainingFileStream -= 2u;
						inf.SetInput(GetBytes(bytesToExtract));
						RemainingFileStream -= bytesToExtract;
						while (!inf.IsNeedingInput)
						{
							var inflated = inf.Inflate(buffer);
							dest.Write(buffer, 0, inflated);
						}

						inf.Reset();
					}
					while (RemainingFileStream > 0);
				}
				else
				{
					do
					{
						RemainingFileStream -= RemainingArchiveStream;
						dest.Write(GetBytes(RemainingArchiveStream), 0, (int)RemainingArchiveStream);
					}
					while (RemainingFileStream > 0);
				}
			}
            public void CopyTo(Stream output, Action<int> onProgress)
            {
                if (file.Flags.HasFlag(CABFlags.FileCompressed))
                {
                    var inf = new Inflater(true);
                    var buffer = new byte[165535];
                    do
                    {
                        var bytesToExtract = currentVolume.ReadUInt16();
                        remainingInArchive -= 2;
                        toExtract -= 2;
                        inf.SetInput(GetBytes(bytesToExtract));
                        toExtract -= bytesToExtract;
                        while (!inf.IsNeedingInput)
                        {
                            if (onProgress != null)
                                onProgress((int)(100 * output.Position / file.ExpandedSize));

                            var inflated = inf.Inflate(buffer);
                            output.Write(buffer, 0, inflated);
                        }

                        inf.Reset();
                    } while (toExtract > 0);
                }
                else
                {
                    do
                    {
                        if (onProgress != null)
                            onProgress((int)(100 * output.Position / file.ExpandedSize));

                        toExtract -= remainingInArchive;
                        output.Write(GetBytes(remainingInArchive), 0, (int)remainingInArchive);
                    } while (toExtract > 0);
                }
            }
Beispiel #3
0
		/// <summary>
		/// Reads a MPK from a binary reader
		/// </summary>
		/// <param name="rdr">The binary reader pointing to the MPK</param>
		private void ReadArchive(BinaryReader rdr)
		{
			_files.Clear();

			_crc.Value = 0;
			_sizeDir = 0;
			_sizeName = 0;
			_numFiles = 0;

			var buf = new byte[16];
			rdr.Read(buf, 0, 16);

			for (byte i = 0; i < 16; ++i)
			{
				buf[i] ^= i;
			}

			_crc.Value = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
			_sizeDir = ((buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]);
			_sizeName = ((buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11]);
			_numFiles = ((buf[12] << 24) | (buf[13] << 16) | (buf[14] << 8) | buf[15]);

			buf = new byte[_sizeName];
			rdr.Read(buf, 0, _sizeName);

			var inf = new Inflater();
			inf.SetInput(buf);
			buf = new byte[1024];
			inf.Inflate(buf);
			buf[inf.TotalOut] = 0;

			_name = Marshal.ConvertToString(buf);

			long totalin = 0;
			buf = ReadDirectory(rdr, ref totalin);

			using (var directory = new MemoryStream(buf))
			{
				long pos = rdr.BaseStream.Position;
				long len = rdr.BaseStream.Seek(0, SeekOrigin.End);
				rdr.BaseStream.Position = pos;

				buf = new byte[len - pos];
				rdr.Read(buf, 0, buf.Length);

				using (var files = new MemoryStream(buf))
				{
					rdr.BaseStream.Position = pos - totalin;
					buf = new byte[totalin];
					rdr.Read(buf, 0, buf.Length);

					var crc = new Crc32();
					crc.Reset();
					crc.Update(buf);

					if (crc.Value != _crc.Value)
					{
						throw new Exception("Invalid or corrupt MPK");
					}

					while (directory.Position < directory.Length && files.Position < files.Length)
					{
						crc.Reset();

						buf = new byte[MPKFileHeader.MaxSize];
						directory.Read(buf, 0, MPKFileHeader.MaxSize);

						MPKFileHeader hdr;

						using (var hdrStream = new MemoryStream(buf))
						{
							using (var hdrRdr = new BinaryReader(hdrStream, Encoding.UTF8))
							{
								hdr = new MPKFileHeader(hdrRdr);
							}
						}

						var compbuf = new byte[hdr.CompressedSize];
						files.Read(compbuf, 0, compbuf.Length);

						crc.Update(compbuf, 0, compbuf.Length);

						inf.Reset();
						inf.SetInput(compbuf, 0, compbuf.Length);
						buf = new byte[hdr.UncompressedSize];
						inf.Inflate(buf, 0, buf.Length);

						var file = new MPKFile(compbuf, buf, hdr);

						if (crc.Value != hdr.CRC.Value)
						{
							OnInvalidFile(file);
							continue;
						}

						_files.Add(hdr.Name.ToLower(), file);
					}
				}
			}
		}
Beispiel #4
0
 /**
  * Release an inflater previously obtained from this cache.
  *
  * @param i
  *            the inflater to return. May be null, in which case this method
  *            does nothing.
  */
 public void release(Inflater i)
 {
     if (i != null)
     {
         i.Reset();
         releaseImpl(i);
      }
 }
Beispiel #5
0
        // make string large to orginal size
        public string Inflate(string input)
        {
            byte[] inputData = System.Convert.FromBase64String(input);
            Inflater inflater = new Inflater(false);
            using (var inputStream = new MemoryStream(inputData))
            using (var ms = new MemoryStream())
            {
                var inputBuffer = new byte[4096];
                var outputBuffer = new byte[4096];

                while (inputStream.Position < inputData.Length)
                {
                    var read = inputStream.Read(inputBuffer, 0, inputBuffer.Length);

                    inflater.SetInput(inputBuffer, 0, read);

                    while (inflater.IsNeedingInput == false)
                    {
                        var written = inflater.Inflate(outputBuffer, 0, outputBuffer.Length);

                        if (written == 0)
                            break;

                        ms.Write(outputBuffer, 0, written);
                    }

                    if (inflater.IsFinished == true)
                        break;
                }

                inflater.Reset();

                return Convert.ToBase64String( ms.ToArray());
            }
        }
Beispiel #6
0
 /// <summary>Release an inflater previously obtained from this cache.</summary>
 /// <remarks>Release an inflater previously obtained from this cache.</remarks>
 /// <param name="i">
 /// the inflater to return. May be null, in which case this method
 /// does nothing.
 /// </param>
 public static void Release(Inflater i)
 {
     if (i != null)
     {
         i.Reset();
         if (ReleaseImpl(i))
         {
             i.Finish();
         }
     }
 }
Beispiel #7
0
        //...........................................................

        /// <summary>
        /// Get an uncompressed blob from PAK_STREAM using the meta-data in ENTRY.
        /// </summary>
        /// <returns>A MemoryStream if possible, otherwise a FileStream to a auto-delete temp file.</returns>
        protected Stream Decompress(Stream PAK_STREAM, cmk.NMS.PAK.Item.Info ENTRY)
        {
            if (PAK_STREAM == null)
            {
                return(null);
            }

            Stream entry;

            if (ENTRY.Length < Int32.MaxValue)
            {
                entry = new MemoryStream((int)ENTRY.Length);
            }
            else
            {
                var temp = System.IO.Path.GetTempFileName();
                entry = new FileStream(temp,
                                       FileMode.Open,
                                       FileAccess.ReadWrite,
                                       FileShare.None,
                                       m_block_size,
                                       FileOptions.DeleteOnClose
                                       );
            }

            // m_block_size is the max decompressed size of a block.
            // each compressed block will be this size or smaller.
            var compressed   = new byte [m_block_size];
            var decompressed = new byte [m_block_size];
            var inflater     = new zlib.Inflater();
            // using System.IO.Compression.DeflateStream.Read fails to parse the data,
            // even though it supposidly uses zlib behind the scenes.
            // todo: assume used it incorrectly, would prefer using built-in API instead of nuget zlib.

            var index  = ENTRY.Index;               // index of first block for ENTRY
            var offset = ENTRY.Offset;              // where the first block ( m_blocks[index]) starts

            // e.g. ENTRY: Index = 7, Offset = 123456, Length = 123456:
            // - m_blocks[7] = 12345, m_blocks[8] = 6789  (example compressed sizes)
            //   these would (likely) decompress to: 65536 and 57920 bytes = 123456 bytes Length.
            // - offset = 123456 is where m_blocks[7] 12345 bytes of compressed data starts,
            //   m_blocks[8]  6789 bytes of compressed data will immediately follow
            //   m_blocks[7] 12345 bytes, and so on.

            for ( ; entry.Length < ENTRY.Length; ++index)
            {
                PAK_STREAM.Position = offset;

                // current block is uncompressed full block, just copy to output
                if (m_blocks[index] == 0)
                {
                    PAK_STREAM.Read(compressed, 0, m_block_size);
                    entry.Write(compressed, 0, m_block_size);
                    offset += m_block_size;
                    continue;
                }

                PAK_STREAM.Read(compressed, 0, (int)m_blocks[index]);                  // read compressed data for current block
                offset += m_blocks[index];                                             // update offset for next block

                // if it's not an uncompressed full block we MUST assume it's a 'compressed' block (has compression header).
                // we have no way to differentiate a compression header from valid uncompressed data.
                //
                // original psarc.exe code assumes that if the compressed block does not
                // start with 0x78da then it's an uncompressed partial block - ugghhh.
                //
                // https://stackoverflow.com/questions/9050260/what-does-a-zlib-header-look-like
                // Level | ZLIB  | GZIP
                // 1     | 78 01 | 1F 8B - No Compression/low
                // 2     | 78 5E | 1F 8B - Fastest Compression
                // 3     | 78 5E | 1F 8B
                // 4     | 78 5E | 1F 8B
                // 5     | 78 5E | 1F 8B
                // 6     | 78 9C | 1F 8B - Default Compression
                // 7     | 78 DA | 1F 8B - Best Compression (Slowest)
                // 8     | 78 DA | 1F 8B
                // 9     | 78 DA | 1F 8B
                //
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(compressed, 0x00, 2);
                }
                var is_compressed = BitConverter.ToUInt16(compressed, 0);
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(compressed, 0x00, 2);
                }

                if (is_compressed != 0x7801 &&
                    is_compressed != 0x785e &&
                    is_compressed != 0x789c &&
                    is_compressed != 0x78da
                    )
                {
                    // MessageBox.Show("Surprise, uncompressed partial ... maybe");
                    // ... turns out these exist
                    entry.Write(compressed, 0, (int)m_blocks[index]);
                    continue;
                }

                // ??? wtf ???
                // for blocks that inflate to a full block size (65536) we end up with 4 bytes
                // in RemainingInput after first Inflate call, the second call results in 0 bytes inflated.
                // the resulting data in uncompressed_file seems good though, no missing data.
                // if there was padding added by Deflate i'd expect it to be consumed by first Inflate.
                // maybe it's the 4 byte adler checksum ???
                inflater.SetInput(compressed, 0, (int)m_blocks[index]);

                var length = inflater.Inflate(decompressed);
                entry.Write(decompressed, 0, length);

                inflater.Reset();
            }

            entry.Position = 0;
            return(entry);
        }
Beispiel #8
0
        public void ExtractFile(string filename, Stream output, Action<int> onProgress = null)
        {
            var file = files.FirstOrDefault(f => f.FileName == filename);
            if (file == null)
                throw new FileNotFoundException(filename);

            var folder = folders[file.FolderIndex];
            stream.Seek(folder.BlockOffset, SeekOrigin.Begin);

            var inflater = new Inflater(true);
            var buffer = new byte[4096];
            var decompressedBytes = 0;
            for (var i = 0; i < folder.BlockCount; i++)
            {
                if (onProgress != null)
                    onProgress((int)(100 * output.Position / file.DecompressedLength));

                // Ignore checksums
                stream.Position += 4;
                var blockLength = stream.ReadUInt16();
                stream.Position += 4;

                using (var batch = new MemoryStream(stream.ReadBytes(blockLength - 2)))
                using (var inflaterStream = new InflaterInputStream(batch, inflater))
                {
                    int n;
                    while ((n = inflaterStream.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        var offset = Math.Max(0, file.DecompressedOffset - decompressedBytes);
                        var count = Math.Min(n - offset, file.DecompressedLength - decompressedBytes);
                        if (offset < n)
                            output.Write(buffer, (int)offset, (int)count);

                        decompressedBytes += n;
                    }
                }

                inflater.Reset();
            }
        }