123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- using System;
- using System.IO;
- using CommonMPQ.SharpZipLib.Checksums;
- using CommonMPQ.SharpZipLib.Zip.Compression;
- using CommonMPQ.SharpZipLib.Zip.Compression.Streams;
- namespace CommonMPQ.SharpZipLib.GZip
- {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public class GZipInputStream : InflaterInputStream
- {
- #region Instance Fields
-
-
-
- protected Crc32 crc;
-
-
-
-
-
- bool readGZIPHeader;
- #endregion
- #region Constructors
-
-
-
-
-
-
- public GZipInputStream(Stream baseInputStream)
- : this(baseInputStream, 4096)
- {
- }
-
-
-
-
-
-
-
-
-
-
- public GZipInputStream(Stream baseInputStream, int size)
- : base(baseInputStream, new Inflater(true), size)
- {
- }
- #endregion
- #region Stream overrides
-
-
-
-
-
-
-
-
-
-
-
-
-
- public override int Read(byte[] buffer, int offset, int count)
- {
-
-
-
- while (true) {
-
- if (! readGZIPHeader) {
-
-
- if (! ReadHeader()) {
- return 0;
- }
- }
-
- int bytesRead = base.Read(buffer, offset, count);
- if (bytesRead > 0) {
- crc.Update(buffer, offset, bytesRead);
- }
-
- if (inf.IsFinished) {
- ReadFooter();
- }
- if (bytesRead > 0) {
- return bytesRead;
- }
- }
- }
- #endregion
- #region Support routines
- bool ReadHeader()
- {
-
- crc = new Crc32();
-
-
- if (inputBuffer.Available <= 0) {
- inputBuffer.Fill();
- if (inputBuffer.Available <= 0) {
-
- return false;
- }
- }
-
- Crc32 headCRC = new Crc32();
- int magic = inputBuffer.ReadLeByte();
- if (magic < 0) {
- throw new EndOfStreamException("EOS reading GZIP header");
- }
- headCRC.Update(magic);
- if (magic != (GZipConstants.GZIP_MAGIC >> 8)) {
- throw new GZipException("Error GZIP header, first magic byte doesn't match");
- }
-
- magic = inputBuffer.ReadLeByte();
- if (magic < 0) {
- throw new EndOfStreamException("EOS reading GZIP header");
- }
- if (magic != (GZipConstants.GZIP_MAGIC & 0xFF)) {
- throw new GZipException("Error GZIP header, second magic byte doesn't match");
- }
- headCRC.Update(magic);
-
- int compressionType = inputBuffer.ReadLeByte();
- if ( compressionType < 0 ) {
- throw new EndOfStreamException("EOS reading GZIP header");
- }
- if ( compressionType != 8 ) {
- throw new GZipException("Error GZIP header, data not in deflate format");
- }
- headCRC.Update(compressionType);
-
- int flags = inputBuffer.ReadLeByte();
- if (flags < 0) {
- throw new EndOfStreamException("EOS reading GZIP header");
- }
- headCRC.Update(flags);
-
-
- if ((flags & 0xE0) != 0) {
- throw new GZipException("Reserved flag bits in GZIP header != 0");
- }
-
- for (int i=0; i< 6; i++) {
- int readByte = inputBuffer.ReadLeByte();
- if (readByte < 0) {
- throw new EndOfStreamException("EOS reading GZIP header");
- }
- headCRC.Update(readByte);
- }
-
- if ((flags & GZipConstants.FEXTRA) != 0) {
-
- int len1, len2;
- len1 = inputBuffer.ReadLeByte();
- len2 = inputBuffer.ReadLeByte();
- if ((len1 < 0) || (len2 < 0)) {
- throw new EndOfStreamException("EOS reading GZIP header");
- }
- headCRC.Update(len1);
- headCRC.Update(len2);
- int extraLen = (len2 << 8) | len1;
- for (int i = 0; i < extraLen;i++) {
- int readByte = inputBuffer.ReadLeByte();
- if (readByte < 0)
- {
- throw new EndOfStreamException("EOS reading GZIP header");
- }
- headCRC.Update(readByte);
- }
- }
-
- if ((flags & GZipConstants.FNAME) != 0) {
- int readByte;
- while ( (readByte = inputBuffer.ReadLeByte()) > 0) {
- headCRC.Update(readByte);
- }
- if (readByte < 0) {
- throw new EndOfStreamException("EOS reading GZIP header");
- }
- headCRC.Update(readByte);
- }
-
- if ((flags & GZipConstants.FCOMMENT) != 0) {
- int readByte;
- while ( (readByte = inputBuffer.ReadLeByte()) > 0) {
- headCRC.Update(readByte);
- }
- if (readByte < 0) {
- throw new EndOfStreamException("EOS reading GZIP header");
- }
- headCRC.Update(readByte);
- }
-
- if ((flags & GZipConstants.FHCRC) != 0) {
- int tempByte;
- int crcval = inputBuffer.ReadLeByte();
- if (crcval < 0) {
- throw new EndOfStreamException("EOS reading GZIP header");
- }
- tempByte = inputBuffer.ReadLeByte();
- if (tempByte < 0) {
- throw new EndOfStreamException("EOS reading GZIP header");
- }
- crcval = (crcval << 8) | tempByte;
- if (crcval != ((int) headCRC.Value & 0xffff)) {
- throw new GZipException("Header CRC value mismatch");
- }
- }
- readGZIPHeader = true;
- return true;
- }
-
- void ReadFooter()
- {
- byte[] footer = new byte[8];
-
- long bytesRead = inf.TotalOut & 0xffffffff;
- inputBuffer.Available += inf.RemainingInput;
- inf.Reset();
-
- int needed = 8;
- while (needed > 0) {
- int count = inputBuffer.ReadClearTextBuffer(footer, 8 - needed, needed);
- if (count <= 0) {
- throw new EndOfStreamException("EOS reading GZIP footer");
- }
- needed -= count;
- }
-
- int crcval = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8) | ((footer[2] & 0xff) << 16) | (footer[3] << 24);
- if (crcval != (int) crc.Value) {
- throw new GZipException("GZIP crc sum mismatch, theirs \"" + crcval + "\" and ours \"" + (int) crc.Value);
- }
-
- uint total =
- (uint)((uint)footer[4] & 0xff) |
- (uint)(((uint)footer[5] & 0xff) << 8) |
- (uint)(((uint)footer[6] & 0xff) << 16) |
- (uint)((uint)footer[7] << 24);
- if (bytesRead != total) {
- throw new GZipException("Number of bytes mismatch in footer");
- }
-
- readGZIPHeader = false;
- }
- #endregion
- }
- }
|