You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

207 lines
7.9 KiB

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