/// <summary> /// Reads uncompressed data into an array of bytes /// </summary> /// <param name="buffer"> /// The buffer to read uncompressed data into /// </param> /// <param name="offset"> /// The offset indicating where the data should be placed /// </param> /// <param name="count"> /// The number of uncompressed bytes to be read /// </param> /// <returns>Returns the number of bytes actually read.</returns> public override int Read(byte[] buffer, int offset, int count) { // We first have to read the GZIP header, then we feed all the // rest of the data to the base class. // // As we do that we continually update the Crc32Checksum. Once the data is // finished, we check the Crc32Checksum // // This means we don't need our own buffer, as everything is done // in baseInputStream the superclass. if (!readGZIPHeader) { ReadHeader(); } if (eos) { return(0); } // We don't have to read the header, so we just grab data from the superclass int bytesRead = base.Read(buffer, offset, count); if (bytesRead > 0) { crc.Update(buffer, offset, bytesRead); } if (inf.IsFinished) { ReadFooter(); } return(bytesRead); }
/// <summary> /// Write given buffer to output updating crc /// </summary> /// <param name="buffer">Buffer to write</param> /// <param name="offset">Offset of first byte in buf to write</param> /// <param name="count">Number of bytes to write</param> public override void Write(byte[] buffer, int offset, int count) { if (state_ == OutputState.Header) { WriteHeader(); } if (state_ != OutputState.Footer) { throw new InvalidOperationException("Write not permitted in current state"); } crc.Update(buffer, offset, count); base.Write(buffer, offset, count); }
/// <summary> /// Reads a block of bytes from the current zip entry. /// </summary> /// <returns> /// The number of bytes read (this may be less than the length requested, even before the end of stream), or 0 on end of stream. /// </returns> /// <exception name="IOException"> /// An i/o error occured. /// </exception> /// <exception cref="ZipException"> /// The deflated stream is corrupted. /// </exception> /// <exception cref="InvalidOperationException"> /// The stream is not open. /// </exception> int BodyRead(byte[] buffer, int offset, int count) { if (crc == null) { throw new InvalidOperationException("Closed"); } if ((entry == null) || (count <= 0)) { return(0); } if (offset + count > buffer.Length) { throw new ArgumentException("Offset + count exceeds buffer size"); } bool finished = false; switch (method) { case (int)CompressionMethod.Deflated: count = base.Read(buffer, offset, count); if (count <= 0) { if (!inf.IsFinished) { throw new ZipException("Inflater not finished!"); } inputBuffer.Available = inf.RemainingInput; if ((flags & 8) == 0 && (inf.TotalIn != csize || inf.TotalOut != size)) { throw new ZipException("Size mismatch: " + csize + ";" + size + " <-> " + inf.TotalIn + ";" + inf.TotalOut); } inf.Reset(); finished = true; } break; case (int)CompressionMethod.Stored: if ((count > csize) && (csize >= 0)) { count = (int)csize; } if (count > 0) { count = inputBuffer.ReadClearTextBuffer(buffer, offset, count); if (count > 0) { csize -= count; size -= count; } } if (csize == 0) { finished = true; } else { if (count < 0) { throw new ZipException("EOF in stored block"); } } break; } if (count > 0) { crc.Update(buffer, offset, count); } if (finished) { CompleteCloseEntry(true); } return(count); }
void ReadHeader() { // 1. Check the two magic bytes Crc32Checksum headCRC = new Crc32Checksum(); int magic = baseInputStream.ReadByte(); if (magic < 0) { throw new EndOfStreamException("EOS reading GZIP header"); } headCRC.Update(magic); if (magic != (GZipConstants.GzipMagic >> 8)) { throw new GZipException("Error GZIP header, first magic byte doesn't match"); } magic = baseInputStream.ReadByte(); if (magic < 0) { throw new EndOfStreamException("EOS reading GZIP header"); } if (magic != (GZipConstants.GzipMagic & 0xFF)) { throw new GZipException("Error GZIP header, second magic byte doesn't match"); } headCRC.Update(magic); // 2. Check the compression type (must be 8) int compressionType = baseInputStream.ReadByte(); 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); // 3. Check the flags int flags = baseInputStream.ReadByte(); if (flags < 0) { throw new EndOfStreamException("EOS reading GZIP header"); } headCRC.Update(flags); /* This flag byte is divided into individual bits as follows: * * bit 0 FTEXT * bit 1 FHCRC * bit 2 FEXTRA * bit 3 FNAME * bit 4 FCOMMENT * bit 5 reserved * bit 6 reserved * bit 7 reserved */ // 3.1 Check the reserved bits are zero if ((flags & 0xE0) != 0) { throw new GZipException("Reserved flag bits in GZIP header != 0"); } // 4.-6. Skip the modification time, extra flags, and OS type for (int i = 0; i < 6; i++) { int readByte = baseInputStream.ReadByte(); if (readByte < 0) { throw new EndOfStreamException("EOS reading GZIP header"); } headCRC.Update(readByte); } // 7. Read extra field if ((flags & GZipConstants.FEXTRA) != 0) { // Skip subfield id for (int i = 0; i < 2; i++) { int readByte = baseInputStream.ReadByte(); if (readByte < 0) { throw new EndOfStreamException("EOS reading GZIP header"); } headCRC.Update(readByte); } if (baseInputStream.ReadByte() < 0 || baseInputStream.ReadByte() < 0) { throw new EndOfStreamException("EOS reading GZIP header"); } int len1, len2; len1 = baseInputStream.ReadByte(); len2 = baseInputStream.ReadByte(); if ((len1 < 0) || (len2 < 0)) { throw new EndOfStreamException("EOS reading GZIP header"); } headCRC.Update(len1); headCRC.Update(len2); int extraLen = (len1 << 8) | len2; for (int i = 0; i < extraLen; i++) { int readByte = baseInputStream.ReadByte(); if (readByte < 0) { throw new EndOfStreamException("EOS reading GZIP header"); } headCRC.Update(readByte); } } // 8. Read file name if ((flags & GZipConstants.FNAME) != 0) { int readByte; while ((readByte = baseInputStream.ReadByte()) > 0) { headCRC.Update(readByte); } if (readByte < 0) { throw new EndOfStreamException("EOS reading GZIP header"); } headCRC.Update(readByte); } // 9. Read comment if ((flags & GZipConstants.FCOMMENT) != 0) { int readByte; while ((readByte = baseInputStream.ReadByte()) > 0) { headCRC.Update(readByte); } if (readByte < 0) { throw new EndOfStreamException("EOS reading GZIP header"); } headCRC.Update(readByte); } // 10. Read header CRC if ((flags & GZipConstants.FHCRC) != 0) { int tempByte; int crcval = baseInputStream.ReadByte(); if (crcval < 0) { throw new EndOfStreamException("EOS reading GZIP header"); } tempByte = baseInputStream.ReadByte(); 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; }