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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|