using com.hitrust.util.Zip.Compression; namespace com.hitrust.util.GZip { using com.hitrust.util.Checksums; using com.hitrust.util.Zip.Compression.Streams; using System; using System.IO; public class GZipInputStream : InflaterInputStream { protected Crc32 crc; protected bool eos; private bool readGZIPHeader; public GZipInputStream(Stream baseInputStream) : this(baseInputStream, 0x1000) { } public GZipInputStream(Stream baseInputStream, int size) : base(baseInputStream, new Inflater(true), size) { this.crc = new Crc32(); } public override int Read(byte[] buf, int offset, int len) { if (!this.readGZIPHeader) { this.ReadHeader(); } if (this.eos) { return 0; } int numRead = base.Read(buf, offset, len); if (numRead > 0) { this.crc.Update(buf, offset, numRead); } if (base.inf.IsFinished) { this.ReadFooter(); } return numRead; } private void ReadFooter() { int count; byte[] footer = new byte[8]; int avail = base.inf.RemainingInput; if (avail > 8) { avail = 8; } Array.Copy(base.buf, base.len - base.inf.RemainingInput, footer, 0, avail); for (int needed = 8 - avail; needed > 0; needed -= count) { count = base.baseInputStream.Read(footer, 8 - needed, needed); if (count <= 0) { throw new GZipException("Early EOF baseInputStream GZIP footer"); } } int crcval = (((footer[0] & 0xff) | ((footer[1] & 0xff) << 8)) | ((footer[2] & 0xff) << 0x10)) | (footer[3] << 0x18); if (crcval != ((int) this.crc.Value)) { throw new GZipException(string.Concat(new object[] { "GZIP crc sum mismatch, theirs \"", crcval, "\" and ours \"", (int) this.crc.Value })); } int total = (((footer[4] & 0xff) | ((footer[5] & 0xff) << 8)) | ((footer[6] & 0xff) << 0x10)) | (footer[7] << 0x18); if (total != base.inf.TotalOut) { throw new GZipException("Number of bytes mismatch"); } this.eos = true; } private void ReadHeader() { Crc32 headCRC = new Crc32(); int magic = base.baseInputStream.ReadByte(); if (magic < 0) { this.eos = true; } else { int i; int readByte; headCRC.Update(magic); if (magic != (GZipConstants.GZIP_MAGIC >> 8)) { throw new GZipException("Error baseInputStream GZIP header, first byte doesn't match"); } magic = base.baseInputStream.ReadByte(); if (magic != (GZipConstants.GZIP_MAGIC & 0xff)) { throw new GZipException("Error baseInputStream GZIP header, second byte doesn't match"); } headCRC.Update(magic); int CM = base.baseInputStream.ReadByte(); if (CM != 8) { throw new GZipException("Error baseInputStream GZIP header, data not baseInputStream deflate format"); } headCRC.Update(CM); int flags = base.baseInputStream.ReadByte(); if (flags < 0) { throw new GZipException("Early EOF baseInputStream GZIP header"); } headCRC.Update(flags); if ((flags & 0xd0) != 0) { throw new GZipException("Reserved flag bits baseInputStream GZIP header != 0"); } for (i = 0; i < 6; i++) { readByte = base.baseInputStream.ReadByte(); if (readByte < 0) { throw new GZipException("Early EOF baseInputStream GZIP header"); } headCRC.Update(readByte); } if ((flags & 4) != 0) { for (i = 0; i < 2; i++) { readByte = base.baseInputStream.ReadByte(); if (readByte < 0) { throw new GZipException("Early EOF baseInputStream GZIP header"); } headCRC.Update(readByte); } if ((base.baseInputStream.ReadByte() < 0) || (base.baseInputStream.ReadByte() < 0)) { throw new GZipException("Early EOF baseInputStream GZIP header"); } int len1 = base.baseInputStream.ReadByte(); int len2 = base.baseInputStream.ReadByte(); if ((len1 < 0) || (len2 < 0)) { throw new GZipException("Early EOF baseInputStream GZIP header"); } headCRC.Update(len1); headCRC.Update(len2); int extraLen = (len1 << 8) | len2; for (i = 0; i < extraLen; i++) { readByte = base.baseInputStream.ReadByte(); if (readByte < 0) { throw new GZipException("Early EOF baseInputStream GZIP header"); } headCRC.Update(readByte); } } if ((flags & 8) != 0) { while ((readByte = base.baseInputStream.ReadByte()) > 0) { headCRC.Update(readByte); } if (readByte < 0) { throw new GZipException("Early EOF baseInputStream GZIP file name"); } headCRC.Update(readByte); } if ((flags & 0x10) != 0) { while ((readByte = base.baseInputStream.ReadByte()) > 0) { headCRC.Update(readByte); } if (readByte < 0) { throw new GZipException("Early EOF baseInputStream GZIP comment"); } headCRC.Update(readByte); } if ((flags & 2) != 0) { int crcval = base.baseInputStream.ReadByte(); if (crcval < 0) { throw new GZipException("Early EOF baseInputStream GZIP header"); } int tempByte = base.baseInputStream.ReadByte(); if (tempByte < 0) { throw new GZipException("Early EOF baseInputStream GZIP header"); } crcval = (crcval << 8) | tempByte; if (crcval != (((int) headCRC.Value) & 0xffff)) { throw new GZipException("Header CRC value mismatch"); } } this.readGZIPHeader = true; } } } }