namespace com.hitrust.util.Zip.Compression.Streams { using com.hitrust.util; using com.hitrust.util.Checksums; using com.hitrust.util.Zip.Compression; using System; using System.IO; public class InflaterInputStream : Stream { protected Stream baseInputStream; protected byte[] buf; protected byte[] cryptbuffer; protected long csize; protected Inflater inf; private bool isStreamOwner; private uint[] keys; protected int len; private byte[] onebytebuffer; private int readChunkSize; public InflaterInputStream(Stream baseInputStream) : this(baseInputStream, new Inflater(), 0x1000) { } public InflaterInputStream(Stream baseInputStream, Inflater inf) : this(baseInputStream, inf, 0x1000) { } public InflaterInputStream(Stream baseInputStream, Inflater inflater, int bufferSize) { this.onebytebuffer = new byte[1]; this.isStreamOwner = true; this.readChunkSize = 0; this.cryptbuffer = null; this.keys = null; if (baseInputStream == null) { throw new ArgumentNullException("InflaterInputStream baseInputStream is null"); } if (inflater == null) { throw new ArgumentNullException("InflaterInputStream Inflater is null"); } if (bufferSize <= 0) { throw new ArgumentOutOfRangeException("bufferSize"); } this.baseInputStream = baseInputStream; this.inf = inflater; this.buf = new byte[bufferSize]; if (baseInputStream.CanSeek) { this.len = (int) baseInputStream.Length; } else { this.len = 0; } } public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { throw new NotSupportedException("InflaterInputStream BeginWrite not supported"); } public override void Close() { if (this.isStreamOwner) { this.baseInputStream.Close(); } } protected void DecryptBlock(byte[] buf, int off, int len) { for (int i = off; i < (off + len); i++) { byte[] buffer; IntPtr ptr; (buffer = buf)[(int) (ptr = (IntPtr) i)] = (byte) (buffer[(int) ptr] ^ this.DecryptByte()); this.UpdateKeys(buf[i]); } } protected byte DecryptByte() { uint num = (this.keys[2] & 0xffff) | 2; return (byte) ((num * (num ^ 1)) >> 8); } protected void Fill() { this.FillInputBuffer(); if (this.keys != null) { this.DecryptBlock(this.buf, 0, this.len); } if (this.len <= 0) { throw new SharpZipBaseException("Deflated stream ends early."); } this.inf.SetInput(this.buf, 0, this.len); } protected void FillInputBuffer() { if (this.readChunkSize <= 0) { this.len = this.baseInputStream.Read(this.buf, 0, this.buf.Length); } else { this.len = this.baseInputStream.Read(this.buf, 0, this.readChunkSize); } } public override void Flush() { this.baseInputStream.Flush(); } protected void InitializePassword(string password) { this.keys = new uint[] { 0x12345678, 0x23456789, 0x34567890 }; for (int i = 0; i < password.Length; i++) { this.UpdateKeys((byte) password[i]); } } public override int Read(byte[] b, int off, int len) { while (true) { int num; try { num = this.inf.Inflate(b, off, len); } catch (Exception exception) { throw new SharpZipBaseException(exception.ToString()); } if (num > 0) { return num; } if (this.inf.IsNeedingDictionary) { throw new SharpZipBaseException("Need a dictionary"); } if (this.inf.IsFinished) { return 0; } if (!this.inf.IsNeedingInput) { throw new InvalidOperationException("Don't know what to do"); } this.Fill(); } } public override int ReadByte() { if (this.Read(this.onebytebuffer, 0, 1) > 0) { return (this.onebytebuffer[0] & 0xff); } return -1; } public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException("Seek not supported"); } public override void SetLength(long val) { throw new NotSupportedException("InflaterInputStream SetLength not supported"); } public long Skip(long n) { if (n <= 0L) { throw new ArgumentOutOfRangeException("n"); } if (this.baseInputStream.CanSeek) { this.baseInputStream.Seek(n, SeekOrigin.Current); return n; } int num = 0x800; if (n < num) { num = (int) n; } byte[] buffer = new byte[num]; return (long) this.baseInputStream.Read(buffer, 0, buffer.Length); } protected void StopDecrypting() { this.keys = null; this.cryptbuffer = null; } protected void UpdateKeys(byte ch) { this.keys[0] = Crc32.ComputeCrc32(this.keys[0], ch); this.keys[1] += (byte) this.keys[0]; this.keys[1] = (this.keys[1] * 0x8088405) + 1; this.keys[2] = Crc32.ComputeCrc32(this.keys[2], (byte) (this.keys[1] >> 0x18)); } public override void Write(byte[] array, int offset, int count) { throw new NotSupportedException("InflaterInputStream Write not supported"); } public override void WriteByte(byte val) { throw new NotSupportedException("InflaterInputStream WriteByte not supported"); } public virtual int Available { get { if (!this.inf.IsFinished) { return 1; } return 0; } } protected int BufferReadSize { get { return this.readChunkSize; } set { this.readChunkSize = value; } } public override bool CanRead { get { return this.baseInputStream.CanRead; } } public override bool CanSeek { get { return false; } } public override bool CanWrite { get { return false; } } public bool IsStreamOwner { get { return this.isStreamOwner; } set { this.isStreamOwner = value; } } public override long Length { get { return (long) this.len; } } public override long Position { get { return this.baseInputStream.Position; } set { throw new NotSupportedException("InflaterInputStream Position not supported"); } } } }