using System; using System.Collections.Generic; using System.IO; using System.Text; using Ionic.Crc; namespace Ionic.Zlib { internal class ZlibBaseStream : Stream { internal int Crc32 { get { bool flag = this.crc == null; int result; if (flag) { result = 0; } else { result = this.crc.Crc32Result; } return result; } } protected internal bool _wantCompress { get { return this._compressionMode == CompressionMode.Compress; } } private ZlibCodec z { get { bool flag = this._z == null; if (flag) { bool flag2 = this._flavor == ZlibStreamFlavor.ZLIB; this._z = new ZlibCodec(); bool flag3 = this._compressionMode == CompressionMode.Decompress; if (flag3) { this._z.InitializeInflate(flag2); } else { this._z.Strategy = this.Strategy; this._z.InitializeDeflate(this._level, flag2); } } return this._z; } } private byte[] workingBuffer { get { bool flag = this._workingBuffer == null; if (flag) { this._workingBuffer = new byte[this._bufferSize]; } return this._workingBuffer; } } public override bool CanRead { get { return this._stream.CanRead; } } public override bool CanSeek { get { return this._stream.CanSeek; } } public override bool CanWrite { get { return this._stream.CanWrite; } } public override long Length { get { return this._stream.Length; } } public override long Position { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } protected internal ZlibCodec _z = null; protected internal ZlibBaseStream.StreamMode _streamMode = ZlibBaseStream.StreamMode.Undefined; protected internal FlushType _flushMode; protected internal ZlibStreamFlavor _flavor; protected internal CompressionMode _compressionMode; protected internal CompressionLevel _level; protected internal bool _leaveOpen; protected internal byte[] _workingBuffer; protected internal int _bufferSize = 16384; protected internal byte[] _buf1 = new byte[1]; protected internal Stream _stream; protected internal CompressionStrategy Strategy = CompressionStrategy.Default; private CRC32 crc; protected internal string _GzipFileName; protected internal string _GzipComment; protected internal DateTime _GzipMtime; protected internal int _gzipHeaderByteCount; private bool nomoreinput = false; internal enum StreamMode { Writer, Reader, Undefined } public ZlibBaseStream(Stream stream, CompressionMode compressionMode, CompressionLevel level, ZlibStreamFlavor flavor, bool leaveOpen) { this._flushMode = FlushType.None; this._stream = stream; this._leaveOpen = leaveOpen; this._compressionMode = compressionMode; this._flavor = flavor; this._level = level; bool flag = flavor == ZlibStreamFlavor.GZIP; if (flag) { this.crc = new CRC32(); } } public override void Write(byte[] buffer, int offset, int count) { bool flag = this.crc != null; if (flag) { this.crc.SlurpBlock(buffer, offset, count); } bool flag2 = this._streamMode == ZlibBaseStream.StreamMode.Undefined; if (flag2) { this._streamMode = ZlibBaseStream.StreamMode.Writer; } else { bool flag3 = this._streamMode > ZlibBaseStream.StreamMode.Writer; if (flag3) { throw new ZlibException("Cannot Write after Reading."); } } bool flag4 = count == 0; if (!flag4) { this.z.InputBuffer = buffer; this._z.Reset(); this._z.NextIn = offset; this._z.AvailableBytesIn = count; for (;;) { this._z.OutputBuffer = this.workingBuffer; this._z.NextOut = 0; this._z.AvailableBytesOut = this._workingBuffer.Length; int num = this._wantCompress ? this._z.Deflate(this._flushMode) : this._z.Inflate(this._flushMode); bool flag5 = num != 0 && num != 1; if (flag5) { break; } this._stream.Write(this._workingBuffer, 0, this._workingBuffer.Length - this._z.AvailableBytesOut); bool flag6 = this._z.AvailableBytesIn == 0 && this._z.AvailableBytesOut != 0; bool flag7 = this._flavor == ZlibStreamFlavor.GZIP && !this._wantCompress; if (flag7) { flag6 = (this._z.AvailableBytesIn == 8 && this._z.AvailableBytesOut != 0); } if (flag6) { return; } } throw new ZlibException((this._wantCompress ? "de" : "in") + "flating: " + this._z.Message); } } private void finish() { bool flag = this._z == null; if (!flag) { bool flag2 = this._streamMode == ZlibBaseStream.StreamMode.Writer; if (flag2) { int num; for (;;) { this._z.OutputBuffer = this.workingBuffer; this._z.NextOut = 0; this._z.AvailableBytesOut = this._workingBuffer.Length; num = (this._wantCompress ? this._z.Deflate(FlushType.Finish) : this._z.Inflate(FlushType.Finish)); bool flag3 = num != 1 && num != 0; if (flag3) { break; } bool flag4 = this._workingBuffer.Length - this._z.AvailableBytesOut > 0; if (flag4) { this._stream.Write(this._workingBuffer, 0, this._workingBuffer.Length - this._z.AvailableBytesOut); } bool flag5 = this._z.AvailableBytesIn == 0 && this._z.AvailableBytesOut != 0; bool flag6 = this._flavor == ZlibStreamFlavor.GZIP && !this._wantCompress; if (flag6) { flag5 = (this._z.AvailableBytesIn == 8 && this._z.AvailableBytesOut != 0); } if (flag5) { goto Block_12; } } string text = (this._wantCompress ? "de" : "in") + "flating"; bool flag7 = this._z.Message == null; if (flag7) { throw new ZlibException(string.Format("{0}: (rc = {1})", text, num)); } throw new ZlibException(text + ": " + this._z.Message); Block_12: this.Flush(); bool flag8 = this._flavor == ZlibStreamFlavor.GZIP; if (flag8) { bool wantCompress = this._wantCompress; if (!wantCompress) { throw new ZlibException("Writing with decompression is not supported."); } int crc32Result = this.crc.Crc32Result; this._stream.Write(BitConverter.GetBytes(crc32Result), 0, 4); int value = (int)(this.crc.TotalBytesRead & (long)(-1)); //! this._stream.Write(BitConverter.GetBytes(value), 0, 4); } } else { bool flag9 = this._streamMode == ZlibBaseStream.StreamMode.Reader; if (flag9) { bool flag10 = this._flavor == ZlibStreamFlavor.GZIP; if (flag10) { bool flag11 = !this._wantCompress; if (!flag11) { throw new ZlibException("Reading with compression is not supported."); } bool flag12 = this._z.TotalBytesOut == 0L; if (!flag12) { byte[] array = new byte[8]; bool flag13 = this._z.AvailableBytesIn < 8; if (flag13) { Array.Copy(this._z.InputBuffer, this._z.NextIn, array, 0, this._z.AvailableBytesIn); int num2 = 8 - this._z.AvailableBytesIn; int num3 = this._stream.Read(array, this._z.AvailableBytesIn, num2); bool flag14 = num2 != num3; if (flag14) { throw new ZlibException(string.Format("Missing or incomplete GZIP trailer. Expected 8 bytes, got {0}.", this._z.AvailableBytesIn + num3)); } } else { Array.Copy(this._z.InputBuffer, this._z.NextIn, array, 0, array.Length); } int num4 = BitConverter.ToInt32(array, 0); int crc32Result2 = this.crc.Crc32Result; int num5 = BitConverter.ToInt32(array, 4); int num6 = (int)(this._z.TotalBytesOut & (long)(-1)); //! bool flag15 = crc32Result2 != num4; if (flag15) { throw new ZlibException(string.Format("Bad CRC32 in GZIP trailer. (actual({0:X8})!=expected({1:X8}))", crc32Result2, num4)); } bool flag16 = num6 != num5; if (flag16) { throw new ZlibException(string.Format("Bad size in GZIP trailer. (actual({0})!=expected({1}))", num6, num5)); } } } } } } } private void end() { bool flag = this.z == null; if (!flag) { bool wantCompress = this._wantCompress; if (wantCompress) { this._z.EndDeflate(); } else { this._z.EndInflate(); } this._z = null; } } public override void Close() { bool flag = this._stream == null; if (!flag) { try { this.finish(); } finally { this.end(); bool flag2 = !this._leaveOpen; if (flag2) { this._stream.Close(); } this._stream = null; } } } public override void Flush() { this._stream.Flush(); } public override long Seek(long offset, SeekOrigin origin) { return this._stream.Seek(offset, origin); } public override void SetLength(long value) { this._stream.SetLength(value); } private string ReadZeroTerminatedString() { List list = new List(); bool flag = false; for (;;) { int num = this._stream.Read(this._buf1, 0, 1); bool flag2 = num != 1; if (flag2) { break; } bool flag3 = this._buf1[0] == 0; if (flag3) { flag = true; } else { list.Add(this._buf1[0]); } if (flag) { goto Block_3; } } throw new ZlibException("Unexpected EOF reading GZIP header."); Block_3: byte[] array = list.ToArray(); return GZipStream.iso8859dash1.GetString(array, 0, array.Length); } private int _ReadAndValidateGzipHeader() { int num = 0; byte[] array = new byte[10]; int num2 = this._stream.Read(array, 0, array.Length); bool flag = num2 == 0; int result; if (flag) { result = 0; } else { bool flag2 = num2 != 10; if (flag2) { throw new ZlibException("Not a valid GZIP stream."); } bool flag3 = array[0] != 31 || array[1] != 139 || array[2] != 8; if (flag3) { throw new ZlibException("Bad GZIP header."); } int num3 = BitConverter.ToInt32(array, 4); this._GzipMtime = GZipStream._unixEpoch.AddSeconds((double)num3); num += num2; bool flag4 = (array[3] & 4) == 4; if (flag4) { num2 = this._stream.Read(array, 0, 2); num += num2; short num4 = (short)((int)array[0] + (int)array[1] * 256); byte[] array2 = new byte[(int)num4]; num2 = this._stream.Read(array2, 0, array2.Length); bool flag5 = num2 != (int)num4; if (flag5) { throw new ZlibException("Unexpected end-of-file reading GZIP header."); } num += num2; } bool flag6 = (array[3] & 8) == 8; if (flag6) { this._GzipFileName = this.ReadZeroTerminatedString(); } bool flag7 = (array[3] & 16) == 16; if (flag7) { this._GzipComment = this.ReadZeroTerminatedString(); } bool flag8 = (array[3] & 2) == 2; if (flag8) { this.Read(this._buf1, 0, 1); } result = num; } return result; } public override int Read(byte[] buffer, int offset, int count) { bool flag = this._streamMode == ZlibBaseStream.StreamMode.Undefined; if (flag) { bool flag2 = !this._stream.CanRead; if (flag2) { throw new ZlibException("The stream is not readable."); } this._streamMode = ZlibBaseStream.StreamMode.Reader; this.z.AvailableBytesIn = 0; bool flag3 = this._flavor == ZlibStreamFlavor.GZIP; if (flag3) { this._gzipHeaderByteCount = this._ReadAndValidateGzipHeader(); bool flag4 = this._gzipHeaderByteCount == 0; if (flag4) { return 0; } } } bool flag5 = this._streamMode != ZlibBaseStream.StreamMode.Reader; if (flag5) { throw new ZlibException("Cannot Read after Writing."); } bool flag6 = count == 0; int result = 0; if (flag6) { result = 0; } else { bool flag7 = this.nomoreinput && this._wantCompress; if (flag7) { result = 0; } else { bool flag8 = buffer == null; if (flag8) { throw new ArgumentNullException("buffer"); } bool flag9 = count < 0; if (flag9) { throw new ArgumentOutOfRangeException("count"); } bool flag10 = offset < buffer.GetLowerBound(0); if (flag10) { throw new ArgumentOutOfRangeException("offset"); } bool flag11 = offset + count > buffer.GetLength(0); if (flag11) { throw new ArgumentOutOfRangeException("count"); } this._z.OutputBuffer = buffer; this._z.NextOut = offset; this._z.AvailableBytesOut = count; this._z.InputBuffer = this.workingBuffer; int num; for (;;) { bool flag12 = this._z.AvailableBytesIn == 0 && !this.nomoreinput; if (flag12) { this._z.NextIn = 0; this._z.AvailableBytesIn = this._stream.Read(this._workingBuffer, 0, this._workingBuffer.Length); bool flag13 = this._z.AvailableBytesIn == 0; if (flag13) { this.nomoreinput = true; } } num = (this._wantCompress ? this._z.Deflate(this._flushMode) : this._z.Inflate(this._flushMode)); bool flag14 = this.nomoreinput && num == -5; if (flag14) { break; } bool flag15 = num != 0 && num != 1; if (flag15) { goto Block_20; } bool flag16 = (this.nomoreinput || num == 1) && this._z.AvailableBytesOut == count; if (flag16) { goto Block_23; } if (this._z.AvailableBytesOut <= 0 || this.nomoreinput || num != 0) { goto IL_2AA; } } return 0; Block_20: throw new ZlibException(string.Format("{0}flating: rc={1} msg={2}", this._wantCompress ? "de" : "in", num, this._z.Message)); Block_23: IL_2AA: bool flag17 = this._z.AvailableBytesOut > 0; if (flag17) { bool flag18 = num == 0 && this._z.AvailableBytesIn == 0; if (flag18) { } bool flag19 = this.nomoreinput; if (flag19) { bool wantCompress = this._wantCompress; if (wantCompress) { num = this._z.Deflate(FlushType.Finish); bool flag20 = num != 0 && num != 1; if (flag20) { throw new ZlibException(string.Format("Deflating: rc={0} msg={1}", num, this._z.Message)); } } } } num = count - this._z.AvailableBytesOut; bool flag21 = this.crc != null; if (flag21) { this.crc.SlurpBlock(buffer, offset, num); } result = num; } } return result; } public static void CompressString(string s, Stream compressor) { byte[] bytes = Encoding.UTF8.GetBytes(s); try { compressor.Write(bytes, 0, bytes.Length); } finally { if (compressor != null) { ((IDisposable)compressor).Dispose(); } } } public static void CompressBuffer(byte[] b, Stream compressor) { try { compressor.Write(b, 0, b.Length); } finally { if (compressor != null) { ((IDisposable)compressor).Dispose(); } } } public static string UncompressString(byte[] compressed, Stream decompressor) { byte[] array = new byte[1024]; Encoding utf = Encoding.UTF8; string result; using (MemoryStream memoryStream = new MemoryStream()) { try { int count; while ((count = decompressor.Read(array, 0, array.Length)) != 0) { memoryStream.Write(array, 0, count); } } finally { if (decompressor != null) { ((IDisposable)decompressor).Dispose(); } } memoryStream.Seek(0L, SeekOrigin.Begin); StreamReader streamReader = new StreamReader(memoryStream, utf); result = streamReader.ReadToEnd(); } return result; } public static byte[] UncompressBuffer(byte[] compressed, Stream decompressor) { byte[] array = new byte[1024]; byte[] result; using (MemoryStream memoryStream = new MemoryStream()) { try { int count; while ((count = decompressor.Read(array, 0, array.Length)) != 0) { memoryStream.Write(array, 0, count); } } finally { if (decompressor != null) { ((IDisposable)decompressor).Dispose(); } } result = memoryStream.ToArray(); } return result; } } }