예제 #1
0
        public bool ReadGzipHeader()
        {
            while (true)
            {
                int bits;
                switch (gzipHeaderSubstate)
                {
                case GZIPHeaderState.ReadingID1:
                    bits = input.GetBits(8);
                    if (bits < 0)
                    {
                        return(false);
                    }

                    if (bits != 0x1F)
                    {
                        throw new InvalidDataException("SR.CorruptedGZipHeader");
                    }
                    gzipHeaderSubstate = GZIPHeaderState.ReadingID2;
                    goto case GZIPHeaderState.ReadingID2;

                case GZIPHeaderState.ReadingID2:
                    bits = input.GetBits(8);
                    if (bits < 0)
                    {
                        return(false);
                    }

                    if (bits != 0x8b)
                    {
                        throw new InvalidDataException("SR.CorruptedGZipHeader");
                    }

                    gzipHeaderSubstate = GZIPHeaderState.ReadingCM;
                    goto case GZIPHeaderState.ReadingCM;

                case GZIPHeaderState.ReadingCM:
                    bits = input.GetBits(8);
                    if (bits < 0)
                    {
                        return(false);
                    }

                    if (bits != 0x8)
                    {             // compression mode must be 8 (deflate)
                        throw new InvalidDataException("SR.UnknownCompressionMode");
                    }

                    gzipHeaderSubstate = GZIPHeaderState.ReadingFLG;;
                    goto case GZIPHeaderState.ReadingFLG;

                case GZIPHeaderState.ReadingFLG:
                    bits = input.GetBits(8);
                    if (bits < 0)
                    {
                        return(false);
                    }

                    gzip_header_flag   = bits;
                    gzipHeaderSubstate = GZIPHeaderState.ReadingMMTime;
                    loopCounter        = 0; // 4 MMTIME bytes
                    goto case GZIPHeaderState.ReadingMMTime;

                case GZIPHeaderState.ReadingMMTime:
                    bits = 0;
                    while (loopCounter < 4)
                    {
                        bits = input.GetBits(8);
                        if (bits < 0)
                        {
                            return(false);
                        }

                        loopCounter++;
                    }

                    gzipHeaderSubstate = GZIPHeaderState.ReadingXFL;
                    loopCounter        = 0;
                    goto case GZIPHeaderState.ReadingXFL;

                case GZIPHeaderState.ReadingXFL:          // ignore XFL
                    bits = input.GetBits(8);
                    if (bits < 0)
                    {
                        return(false);
                    }

                    gzipHeaderSubstate = GZIPHeaderState.ReadingOS;
                    goto case GZIPHeaderState.ReadingOS;

                case GZIPHeaderState.ReadingOS:          // ignore OS
                    bits = input.GetBits(8);
                    if (bits < 0)
                    {
                        return(false);
                    }

                    gzipHeaderSubstate = GZIPHeaderState.ReadingXLen1;
                    goto case GZIPHeaderState.ReadingXLen1;

                case GZIPHeaderState.ReadingXLen1:
                    if ((gzip_header_flag & ExtraFieldsFlag) == 0)
                    {
                        goto case GZIPHeaderState.ReadingFileName;
                    }

                    bits = input.GetBits(8);
                    if (bits < 0)
                    {
                        return(false);
                    }

                    gzip_header_xlen   = bits;
                    gzipHeaderSubstate = GZIPHeaderState.ReadingXLen2;
                    goto case GZIPHeaderState.ReadingXLen2;

                case GZIPHeaderState.ReadingXLen2:
                    bits = input.GetBits(8);
                    if (bits < 0)
                    {
                        return(false);
                    }

                    gzip_header_xlen  |= (bits << 8);
                    gzipHeaderSubstate = GZIPHeaderState.ReadingXLenData;
                    loopCounter        = 0; // 0 bytes of XLEN data read so far
                    goto case GZIPHeaderState.ReadingXLenData;

                case GZIPHeaderState.ReadingXLenData:
                    bits = 0;
                    while (loopCounter < gzip_header_xlen)
                    {
                        bits = input.GetBits(8);
                        if (bits < 0)
                        {
                            return(false);
                        }

                        loopCounter++;
                    }
                    gzipHeaderSubstate = GZIPHeaderState.ReadingFileName;
                    loopCounter        = 0;
                    goto case GZIPHeaderState.ReadingFileName;

                case GZIPHeaderState.ReadingFileName:
                    if ((gzip_header_flag & FileNameFlag) == 0)
                    {
                        gzipHeaderSubstate = GZIPHeaderState.ReadingComment;
                        goto case GZIPHeaderState.ReadingComment;
                    }

                    do
                    {
                        bits = input.GetBits(8);
                        if (bits < 0)
                        {
                            return(false);
                        }

                        if (bits == 0)
                        {       // see '\0' in the file name string
                            break;
                        }
                    } while (true);

                    gzipHeaderSubstate = GZIPHeaderState.ReadingComment;
                    goto case GZIPHeaderState.ReadingComment;

                case GZIPHeaderState.ReadingComment:
                    if ((gzip_header_flag & CommentFlag) == 0)
                    {
                        gzipHeaderSubstate = GZIPHeaderState.ReadingCRC16Part1;
                        goto case GZIPHeaderState.ReadingCRC16Part1;
                    }

                    do
                    {
                        bits = input.GetBits(8);
                        if (bits < 0)
                        {
                            return(false);
                        }

                        if (bits == 0)
                        {       // see '\0' in the file name string
                            break;
                        }
                    } while (true);

                    gzipHeaderSubstate = GZIPHeaderState.ReadingCRC16Part1;
                    goto case GZIPHeaderState.ReadingCRC16Part1;

                case GZIPHeaderState.ReadingCRC16Part1:
                    if ((gzip_header_flag & CRCFlag) == 0)
                    {
                        gzipHeaderSubstate = GZIPHeaderState.Done;
                        goto case GZIPHeaderState.Done;
                    }

                    bits = input.GetBits(8);         // ignore crc
                    if (bits < 0)
                    {
                        return(false);
                    }

                    gzipHeaderSubstate = GZIPHeaderState.ReadingCRC16Part2;
                    goto case GZIPHeaderState.ReadingCRC16Part2;

                case GZIPHeaderState.ReadingCRC16Part2:
                    bits = input.GetBits(8);         // ignore crc
                    if (bits < 0)
                    {
                        return(false);
                    }

                    gzipHeaderSubstate = GZIPHeaderState.Done;
                    goto case GZIPHeaderState.Done;

                case GZIPHeaderState.Done:
                    return(true);

                default:
                    Debug.Assert(false, "We should not reach unknown state!");
                    throw new InvalidDataException("SR.UnknownState");
                }
            }
        }
예제 #2
0
        //Each block of compressed data begins with 3 header bits
        // containing the following data: 
        //    first bit       BFINAL
        //    next 2 bits     BTYPE
        // Note that the header bits do not necessarily begin on a byte
        // boundary, since a block does not necessarily occupy an integral 
        // number of bytes.
        // BFINAL is set if and only if this is the last block of the data 
        // set. 
        // BTYPE specifies how the data are compressed, as follows:
        //    00 - no compression 
        //    01 - compressed with fixed Huffman codes
        //    10 - compressed with dynamic Huffman codes
        //    11 - reserved (error)
        // The only difference between the two compressed cases is how the 
        // Huffman codes for the literal/length and distance alphabets are
        // defined. 
        // 
        // This function returns true for success (end of block or output window is full,)
        // false if we are short of input 
        //
        private bool Decode()
        {
            bool eob = false;
            bool result = false;

            if (Finished())
            {
                return true;
            }

            if (_usingGzip)
            {
                if (_state == InflaterState.ReadingGZIPHeader)
                {
                    if (!_gZipDecoder.ReadGzipHeader())
                    {
                        return false;
                    }
                    _state = InflaterState.ReadingBFinal;
                }
                else if (_state == InflaterState.StartReadingGZIPFooter || _state == InflaterState.ReadingGZIPFooter)
                {
                    if (!_gZipDecoder.ReadGzipFooter())
                        return false;

                    _state = InflaterState.VerifyingGZIPFooter;
                    return true;
                }
            }

            if (_state == InflaterState.ReadingBFinal)
            {
                // reading bfinal bit
                // Need 1 bit 
                if (!_input.EnsureBitsAvailable(1))
                    return false;

                _bfinal = _input.GetBits(1);
                _state = InflaterState.ReadingBType;
            }

            if (_state == InflaterState.ReadingBType)
            {
                // Need 2 bits 
                if (!_input.EnsureBitsAvailable(2))
                {
                    _state = InflaterState.ReadingBType;
                    return false;
                }

                blockType = (BlockType) _input.GetBits(2);
                if (blockType == BlockType.Dynamic)
                {
                    _state = InflaterState.ReadingNumLitCodes;
                }
                else if (blockType == BlockType.Static)
                {
                    _literalLengthTree = HuffmanTree.StaticLiteralLengthTree;
                    _distanceTree = HuffmanTree.StaticDistanceTree;
                    _state = InflaterState.DecodeTop;
                }
                else if (blockType == BlockType.Uncompressed)
                {
                    _state = InflaterState.UncompressedAligning;
                }
                else
                {
                    throw new InvalidDataException("SR.UnknownBlockType");
                }
            }

            if (blockType == BlockType.Dynamic)
            {
                if (_state < InflaterState.DecodeTop)
                {
                    // we are reading the header 
                    result = DecodeDynamicBlockHeader();
                }
                else
                {
                    result = DecodeBlock(out eob); // this can returns true when output is full 
                }
            }
            else if (blockType == BlockType.Static)
            {
                result = DecodeBlock(out eob);
            }
            else if (blockType == BlockType.Uncompressed)
            {
                result = DecodeUncompressedBlock(out eob);
            }
            else
            {
                throw new InvalidDataException("SR.UnknownBlockType");
            }

            //
            // If we reached the end of the block and the block we were decoding had 
            // bfinal=1 (final block)
            //
            if (eob && (_bfinal != 0))
            {
                if (_usingGzip)
                    _state = InflaterState.StartReadingGZIPFooter;
                else
                    _state = InflaterState.Done;
            }
            return result;
        }