Beispiel #1
0
        /// <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);
        }
Beispiel #3
0
        /// <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);
        }
Beispiel #4
0
        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;
        }