|  | // Inflate.cs | 
|  | // ------------------------------------------------------------------ | 
|  | // | 
|  | // Copyright (c) 2009 Dino Chiesa and Microsoft Corporation. | 
|  | // All rights reserved. | 
|  | // | 
|  | // This code module is part of DotNetZip, a zipfile class library. | 
|  | // | 
|  | // ------------------------------------------------------------------ | 
|  | // | 
|  | // This code is licensed under the Microsoft Public License. | 
|  | // See the file License.txt for the license details. | 
|  | // More info on: http://dotnetzip.codeplex.com | 
|  | // | 
|  | // ------------------------------------------------------------------ | 
|  | // | 
|  | // last saved (in emacs): | 
|  | // Time-stamp: <2010-January-08 18:32:12> | 
|  | // | 
|  | // ------------------------------------------------------------------ | 
|  | // | 
|  | // This module defines classes for decompression. This code is derived | 
|  | // from the jzlib implementation of zlib, but significantly modified. | 
|  | // The object model is not the same, and many of the behaviors are | 
|  | // different.  Nonetheless, in keeping with the license for jzlib, I am | 
|  | // reproducing the copyright to that code here. | 
|  | // | 
|  | // ------------------------------------------------------------------ | 
|  | // | 
|  | // Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. | 
|  | // | 
|  | // Redistribution and use in source and binary forms, with or without | 
|  | // modification, are permitted provided that the following conditions are met: | 
|  | // | 
|  | // 1. Redistributions of source code must retain the above copyright notice, | 
|  | // this list of conditions and the following disclaimer. | 
|  | // | 
|  | // 2. Redistributions in binary form must reproduce the above copyright | 
|  | // notice, this list of conditions and the following disclaimer in | 
|  | // the documentation and/or other materials provided with the distribution. | 
|  | // | 
|  | // 3. The names of the authors may not be used to endorse or promote products | 
|  | // derived from this software without specific prior written permission. | 
|  | // | 
|  | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, | 
|  | // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | 
|  | // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, | 
|  | // INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, | 
|  | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
|  | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, | 
|  | // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 
|  | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
|  | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | 
|  | // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | // | 
|  | // ----------------------------------------------------------------------- | 
|  | // | 
|  | // This program is based on zlib-1.1.3; credit to authors | 
|  | // Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) | 
|  | // and contributors of zlib. | 
|  | // | 
|  | // ----------------------------------------------------------------------- | 
|  |  | 
|  |  | 
|  | using System; | 
|  | namespace OfficeOpenXml.Packaging.Ionic.Zlib | 
|  | { | 
|  | sealed class InflateBlocks | 
|  | { | 
|  | private const int MANY = 1440; | 
|  |  | 
|  | // Table for deflate from PKZIP's appnote.txt. | 
|  | internal static readonly int[] border = new int[] | 
|  | { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; | 
|  |  | 
|  | private enum InflateBlockMode | 
|  | { | 
|  | TYPE   = 0,                     // get type bits (3, including end bit) | 
|  | LENS   = 1,                     // get lengths for stored | 
|  | STORED = 2,                     // processing stored block | 
|  | TABLE  = 3,                     // get table lengths | 
|  | BTREE  = 4,                     // get bit lengths tree for a dynamic block | 
|  | DTREE  = 5,                     // get length, distance trees for a dynamic block | 
|  | CODES  = 6,                     // processing fixed or dynamic block | 
|  | DRY    = 7,                     // output remaining window bytes | 
|  | DONE   = 8,                     // finished last block, done | 
|  | BAD    = 9,                     // ot a data error--stuck here | 
|  | } | 
|  |  | 
|  | private InflateBlockMode mode;                    // current inflate_block mode | 
|  |  | 
|  | internal int left;                                // if STORED, bytes left to copy | 
|  |  | 
|  | internal int table;                               // table lengths (14 bits) | 
|  | internal int index;                               // index into blens (or border) | 
|  | internal int[] blens;                             // bit lengths of codes | 
|  | internal int[] bb = new int[1];                   // bit length tree depth | 
|  | internal int[] tb = new int[1];                   // bit length decoding tree | 
|  |  | 
|  | internal InflateCodes codes = new InflateCodes(); // if CODES, current state | 
|  |  | 
|  | internal int last;                                // true if this block is the last block | 
|  |  | 
|  | internal ZlibCodec _codec;                        // pointer back to this zlib stream | 
|  |  | 
|  | // mode independent information | 
|  | internal int bitk;                                // bits in bit buffer | 
|  | internal int bitb;                                // bit buffer | 
|  | internal int[] hufts;                             // single malloc for tree space | 
|  | internal byte[] window;                           // sliding window | 
|  | internal int end;                                 // one byte after sliding window | 
|  | internal int readAt;                              // window read pointer | 
|  | internal int writeAt;                             // window write pointer | 
|  | internal System.Object checkfn;                   // check function | 
|  | internal uint check;                              // check on output | 
|  |  | 
|  | internal InfTree inftree = new InfTree(); | 
|  |  | 
|  | internal InflateBlocks(ZlibCodec codec, System.Object checkfn, int w) | 
|  | { | 
|  | _codec = codec; | 
|  | hufts = new int[MANY * 3]; | 
|  | window = new byte[w]; | 
|  | end = w; | 
|  | this.checkfn = checkfn; | 
|  | mode = InflateBlockMode.TYPE; | 
|  | Reset(); | 
|  | } | 
|  |  | 
|  | internal uint Reset() | 
|  | { | 
|  | uint oldCheck = check; | 
|  | mode = InflateBlockMode.TYPE; | 
|  | bitk = 0; | 
|  | bitb = 0; | 
|  | readAt = writeAt = 0; | 
|  |  | 
|  | if (checkfn != null) | 
|  | _codec._Adler32 = check = Adler.Adler32(0, null, 0, 0); | 
|  | return oldCheck; | 
|  | } | 
|  |  | 
|  |  | 
|  | internal int Process(int r) | 
|  | { | 
|  | int t; // temporary storage | 
|  | int b; // bit buffer | 
|  | int k; // bits in bit buffer | 
|  | int p; // input data pointer | 
|  | int n; // bytes available there | 
|  | int q; // output window write pointer | 
|  | int m; // bytes to end of window or read pointer | 
|  |  | 
|  | // copy input/output information to locals (UPDATE macro restores) | 
|  |  | 
|  | p = _codec.NextIn; | 
|  | n = _codec.AvailableBytesIn; | 
|  | b = bitb; | 
|  | k = bitk; | 
|  |  | 
|  | q = writeAt; | 
|  | m = (int)(q < readAt ? readAt - q - 1 : end - q); | 
|  |  | 
|  |  | 
|  | // process input based on current state | 
|  | while (true) | 
|  | { | 
|  | switch (mode) | 
|  | { | 
|  | case InflateBlockMode.TYPE: | 
|  |  | 
|  | while (k < (3)) | 
|  | { | 
|  | if (n != 0) | 
|  | { | 
|  | r = ZlibConstants.Z_OK; | 
|  | } | 
|  | else | 
|  | { | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  |  | 
|  | n--; | 
|  | b |= (_codec.InputBuffer[p++] & 0xff) << k; | 
|  | k += 8; | 
|  | } | 
|  | t = (int)(b & 7); | 
|  | last = t & 1; | 
|  |  | 
|  | switch ((uint)t >> 1) | 
|  | { | 
|  | case 0:  // stored | 
|  | b >>= 3; k -= (3); | 
|  | t = k & 7; // go to byte boundary | 
|  | b >>= t; k -= t; | 
|  | mode = InflateBlockMode.LENS; // get length of stored block | 
|  | break; | 
|  |  | 
|  | case 1:  // fixed | 
|  | int[] bl = new int[1]; | 
|  | int[] bd = new int[1]; | 
|  | int[][] tl = new int[1][]; | 
|  | int[][] td = new int[1][]; | 
|  | InfTree.inflate_trees_fixed(bl, bd, tl, td, _codec); | 
|  | codes.Init(bl[0], bd[0], tl[0], 0, td[0], 0); | 
|  | b >>= 3; k -= 3; | 
|  | mode = InflateBlockMode.CODES; | 
|  | break; | 
|  |  | 
|  | case 2:  // dynamic | 
|  | b >>= 3; k -= 3; | 
|  | mode = InflateBlockMode.TABLE; | 
|  | break; | 
|  |  | 
|  | case 3:  // illegal | 
|  | b >>= 3; k -= 3; | 
|  | mode = InflateBlockMode.BAD; | 
|  | _codec.Message = "invalid block type"; | 
|  | r = ZlibConstants.Z_DATA_ERROR; | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case InflateBlockMode.LENS: | 
|  |  | 
|  | while (k < (32)) | 
|  | { | 
|  | if (n != 0) | 
|  | { | 
|  | r = ZlibConstants.Z_OK; | 
|  | } | 
|  | else | 
|  | { | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  | ; | 
|  | n--; | 
|  | b |= (_codec.InputBuffer[p++] & 0xff) << k; | 
|  | k += 8; | 
|  | } | 
|  |  | 
|  | if ( ( ((~b)>>16) & 0xffff) != (b & 0xffff)) | 
|  | { | 
|  | mode = InflateBlockMode.BAD; | 
|  | _codec.Message = "invalid stored block lengths"; | 
|  | r = ZlibConstants.Z_DATA_ERROR; | 
|  |  | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  | left = (b & 0xffff); | 
|  | b = k = 0; // dump bits | 
|  | mode = left != 0 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE); | 
|  | break; | 
|  |  | 
|  | case InflateBlockMode.STORED: | 
|  | if (n == 0) | 
|  | { | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  |  | 
|  | if (m == 0) | 
|  | { | 
|  | if (q == end && readAt != 0) | 
|  | { | 
|  | q = 0; m = (int)(q < readAt ? readAt - q - 1 : end - q); | 
|  | } | 
|  | if (m == 0) | 
|  | { | 
|  | writeAt = q; | 
|  | r = Flush(r); | 
|  | q = writeAt; m = (int)(q < readAt ? readAt - q - 1 : end - q); | 
|  | if (q == end && readAt != 0) | 
|  | { | 
|  | q = 0; m = (int)(q < readAt ? readAt - q - 1 : end - q); | 
|  | } | 
|  | if (m == 0) | 
|  | { | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  | } | 
|  | } | 
|  | r = ZlibConstants.Z_OK; | 
|  |  | 
|  | t = left; | 
|  | if (t > n) | 
|  | t = n; | 
|  | if (t > m) | 
|  | t = m; | 
|  | Array.Copy(_codec.InputBuffer, p, window, q, t); | 
|  | p += t; n -= t; | 
|  | q += t; m -= t; | 
|  | if ((left -= t) != 0) | 
|  | break; | 
|  | mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE; | 
|  | break; | 
|  |  | 
|  | case InflateBlockMode.TABLE: | 
|  |  | 
|  | while (k < (14)) | 
|  | { | 
|  | if (n != 0) | 
|  | { | 
|  | r = ZlibConstants.Z_OK; | 
|  | } | 
|  | else | 
|  | { | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  |  | 
|  | n--; | 
|  | b |= (_codec.InputBuffer[p++] & 0xff) << k; | 
|  | k += 8; | 
|  | } | 
|  |  | 
|  | table = t = (b & 0x3fff); | 
|  | if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) | 
|  | { | 
|  | mode = InflateBlockMode.BAD; | 
|  | _codec.Message = "too many length or distance symbols"; | 
|  | r = ZlibConstants.Z_DATA_ERROR; | 
|  |  | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  | t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); | 
|  | if (blens == null || blens.Length < t) | 
|  | { | 
|  | blens = new int[t]; | 
|  | } | 
|  | else | 
|  | { | 
|  | Array.Clear(blens, 0, t); | 
|  | // for (int i = 0; i < t; i++) | 
|  | // { | 
|  | //     blens[i] = 0; | 
|  | // } | 
|  | } | 
|  |  | 
|  | b >>= 14; | 
|  | k -= 14; | 
|  |  | 
|  |  | 
|  | index = 0; | 
|  | mode = InflateBlockMode.BTREE; | 
|  | goto case InflateBlockMode.BTREE; | 
|  |  | 
|  | case InflateBlockMode.BTREE: | 
|  | while (index < 4 + (table >> 10)) | 
|  | { | 
|  | while (k < (3)) | 
|  | { | 
|  | if (n != 0) | 
|  | { | 
|  | r = ZlibConstants.Z_OK; | 
|  | } | 
|  | else | 
|  | { | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  |  | 
|  | n--; | 
|  | b |= (_codec.InputBuffer[p++] & 0xff) << k; | 
|  | k += 8; | 
|  | } | 
|  |  | 
|  | blens[border[index++]] = b & 7; | 
|  |  | 
|  | b >>= 3; k -= 3; | 
|  | } | 
|  |  | 
|  | while (index < 19) | 
|  | { | 
|  | blens[border[index++]] = 0; | 
|  | } | 
|  |  | 
|  | bb[0] = 7; | 
|  | t = inftree.inflate_trees_bits(blens, bb, tb, hufts, _codec); | 
|  | if (t != ZlibConstants.Z_OK) | 
|  | { | 
|  | r = t; | 
|  | if (r == ZlibConstants.Z_DATA_ERROR) | 
|  | { | 
|  | blens = null; | 
|  | mode = InflateBlockMode.BAD; | 
|  | } | 
|  |  | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  |  | 
|  | index = 0; | 
|  | mode = InflateBlockMode.DTREE; | 
|  | goto case InflateBlockMode.DTREE; | 
|  |  | 
|  | case InflateBlockMode.DTREE: | 
|  | while (true) | 
|  | { | 
|  | t = table; | 
|  | if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))) | 
|  | { | 
|  | break; | 
|  | } | 
|  |  | 
|  | int i, j, c; | 
|  |  | 
|  | t = bb[0]; | 
|  |  | 
|  | while (k < t) | 
|  | { | 
|  | if (n != 0) | 
|  | { | 
|  | r = ZlibConstants.Z_OK; | 
|  | } | 
|  | else | 
|  | { | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  |  | 
|  | n--; | 
|  | b |= (_codec.InputBuffer[p++] & 0xff) << k; | 
|  | k += 8; | 
|  | } | 
|  |  | 
|  | t = hufts[(tb[0] + (b & InternalInflateConstants.InflateMask[t])) * 3 + 1]; | 
|  | c = hufts[(tb[0] + (b & InternalInflateConstants.InflateMask[t])) * 3 + 2]; | 
|  |  | 
|  | if (c < 16) | 
|  | { | 
|  | b >>= t; k -= t; | 
|  | blens[index++] = c; | 
|  | } | 
|  | else | 
|  | { | 
|  | // c == 16..18 | 
|  | i = c == 18 ? 7 : c - 14; | 
|  | j = c == 18 ? 11 : 3; | 
|  |  | 
|  | while (k < (t + i)) | 
|  | { | 
|  | if (n != 0) | 
|  | { | 
|  | r = ZlibConstants.Z_OK; | 
|  | } | 
|  | else | 
|  | { | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  |  | 
|  | n--; | 
|  | b |= (_codec.InputBuffer[p++] & 0xff) << k; | 
|  | k += 8; | 
|  | } | 
|  |  | 
|  | b >>= t; k -= t; | 
|  |  | 
|  | j += (b & InternalInflateConstants.InflateMask[i]); | 
|  |  | 
|  | b >>= i; k -= i; | 
|  |  | 
|  | i = index; | 
|  | t = table; | 
|  | if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1)) | 
|  | { | 
|  | blens = null; | 
|  | mode = InflateBlockMode.BAD; | 
|  | _codec.Message = "invalid bit length repeat"; | 
|  | r = ZlibConstants.Z_DATA_ERROR; | 
|  |  | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  |  | 
|  | c = (c == 16) ? blens[i-1] : 0; | 
|  | do | 
|  | { | 
|  | blens[i++] = c; | 
|  | } | 
|  | while (--j != 0); | 
|  | index = i; | 
|  | } | 
|  | } | 
|  |  | 
|  | tb[0] = -1; | 
|  | { | 
|  | int[] bl = new int[] { 9 };  // must be <= 9 for lookahead assumptions | 
|  | int[] bd = new int[] { 6 }; // must be <= 9 for lookahead assumptions | 
|  | int[] tl = new int[1]; | 
|  | int[] td = new int[1]; | 
|  |  | 
|  | t = table; | 
|  | t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl, bd, tl, td, hufts, _codec); | 
|  |  | 
|  | if (t != ZlibConstants.Z_OK) | 
|  | { | 
|  | if (t == ZlibConstants.Z_DATA_ERROR) | 
|  | { | 
|  | blens = null; | 
|  | mode = InflateBlockMode.BAD; | 
|  | } | 
|  | r = t; | 
|  |  | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  | codes.Init(bl[0], bd[0], hufts, tl[0], hufts, td[0]); | 
|  | } | 
|  | mode = InflateBlockMode.CODES; | 
|  | goto case InflateBlockMode.CODES; | 
|  |  | 
|  | case InflateBlockMode.CODES: | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  |  | 
|  | r = codes.Process(this, r); | 
|  | if (r != ZlibConstants.Z_STREAM_END) | 
|  | { | 
|  | return Flush(r); | 
|  | } | 
|  |  | 
|  | r = ZlibConstants.Z_OK; | 
|  | p = _codec.NextIn; | 
|  | n = _codec.AvailableBytesIn; | 
|  | b = bitb; | 
|  | k = bitk; | 
|  | q = writeAt; | 
|  | m = (int)(q < readAt ? readAt - q - 1 : end - q); | 
|  |  | 
|  | if (last == 0) | 
|  | { | 
|  | mode = InflateBlockMode.TYPE; | 
|  | break; | 
|  | } | 
|  | mode = InflateBlockMode.DRY; | 
|  | goto case InflateBlockMode.DRY; | 
|  |  | 
|  | case InflateBlockMode.DRY: | 
|  | writeAt = q; | 
|  | r = Flush(r); | 
|  | q = writeAt; m = (int)(q < readAt ? readAt - q - 1 : end - q); | 
|  | if (readAt != writeAt) | 
|  | { | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  | mode = InflateBlockMode.DONE; | 
|  | goto case InflateBlockMode.DONE; | 
|  |  | 
|  | case InflateBlockMode.DONE: | 
|  | r = ZlibConstants.Z_STREAM_END; | 
|  | bitb = b; | 
|  | bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  |  | 
|  | case InflateBlockMode.BAD: | 
|  | r = ZlibConstants.Z_DATA_ERROR; | 
|  |  | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  |  | 
|  |  | 
|  | default: | 
|  | r = ZlibConstants.Z_STREAM_ERROR; | 
|  |  | 
|  | bitb = b; bitk = k; | 
|  | _codec.AvailableBytesIn = n; | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | writeAt = q; | 
|  | return Flush(r); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | internal void Free() | 
|  | { | 
|  | Reset(); | 
|  | window = null; | 
|  | hufts = null; | 
|  | } | 
|  |  | 
|  | internal void SetDictionary(byte[] d, int start, int n) | 
|  | { | 
|  | Array.Copy(d, start, window, 0, n); | 
|  | readAt = writeAt = n; | 
|  | } | 
|  |  | 
|  | // Returns true if inflate is currently at the end of a block generated | 
|  | // by Z_SYNC_FLUSH or Z_FULL_FLUSH. | 
|  | internal int SyncPoint() | 
|  | { | 
|  | return mode == InflateBlockMode.LENS ? 1 : 0; | 
|  | } | 
|  |  | 
|  | // copy as much as possible from the sliding window to the output area | 
|  | internal int Flush(int r) | 
|  | { | 
|  | int nBytes; | 
|  |  | 
|  | for (int pass=0; pass < 2; pass++) | 
|  | { | 
|  | if (pass==0) | 
|  | { | 
|  | // compute number of bytes to copy as far as end of window | 
|  | nBytes = (int)((readAt <= writeAt ? writeAt : end) - readAt); | 
|  | } | 
|  | else | 
|  | { | 
|  | // compute bytes to copy | 
|  | nBytes = writeAt - readAt; | 
|  | } | 
|  |  | 
|  | // workitem 8870 | 
|  | if (nBytes == 0) | 
|  | { | 
|  | if (r == ZlibConstants.Z_BUF_ERROR) | 
|  | r = ZlibConstants.Z_OK; | 
|  | return r; | 
|  | } | 
|  |  | 
|  | if (nBytes > _codec.AvailableBytesOut) | 
|  | nBytes = _codec.AvailableBytesOut; | 
|  |  | 
|  | if (nBytes != 0 && r == ZlibConstants.Z_BUF_ERROR) | 
|  | r = ZlibConstants.Z_OK; | 
|  |  | 
|  | // update counters | 
|  | _codec.AvailableBytesOut -= nBytes; | 
|  | _codec.TotalBytesOut += nBytes; | 
|  |  | 
|  | // update check information | 
|  | if (checkfn != null) | 
|  | _codec._Adler32 = check = Adler.Adler32(check, window, readAt, nBytes); | 
|  |  | 
|  | // copy as far as end of window | 
|  | Array.Copy(window, readAt, _codec.OutputBuffer, _codec.NextOut, nBytes); | 
|  | _codec.NextOut += nBytes; | 
|  | readAt += nBytes; | 
|  |  | 
|  | // see if more to copy at beginning of window | 
|  | if (readAt == end && pass == 0) | 
|  | { | 
|  | // wrap pointers | 
|  | readAt = 0; | 
|  | if (writeAt == end) | 
|  | writeAt = 0; | 
|  | } | 
|  | else pass++; | 
|  | } | 
|  |  | 
|  | // done | 
|  | return r; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | internal static class InternalInflateConstants | 
|  | { | 
|  | // And'ing with mask[n] masks the lower n bits | 
|  | internal static readonly int[] InflateMask = new int[] { | 
|  | 0x00000000, 0x00000001, 0x00000003, 0x00000007, | 
|  | 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, | 
|  | 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, | 
|  | 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff }; | 
|  | } | 
|  |  | 
|  |  | 
|  | sealed class InflateCodes | 
|  | { | 
|  | // waiting for "i:"=input, | 
|  | //             "o:"=output, | 
|  | //             "x:"=nothing | 
|  | private const int START   = 0; // x: set up for LEN | 
|  | private const int LEN     = 1; // i: get length/literal/eob next | 
|  | private const int LENEXT  = 2; // i: getting length extra (have base) | 
|  | private const int DIST    = 3; // i: get distance next | 
|  | private const int DISTEXT = 4; // i: getting distance extra | 
|  | private const int COPY    = 5; // o: copying bytes in window, waiting for space | 
|  | private const int LIT     = 6; // o: got literal, waiting for output space | 
|  | private const int WASH    = 7; // o: got eob, possibly still output waiting | 
|  | private const int END     = 8; // x: got eob and all data flushed | 
|  | private const int BADCODE = 9; // x: got error | 
|  |  | 
|  | internal int mode;        // current inflate_codes mode | 
|  |  | 
|  | // mode dependent information | 
|  | internal int len; | 
|  |  | 
|  | internal int[] tree;      // pointer into tree | 
|  | internal int tree_index = 0; | 
|  | internal int need;        // bits needed | 
|  |  | 
|  | internal int lit; | 
|  |  | 
|  | // if EXT or COPY, where and how much | 
|  | internal int bitsToGet;   // bits to get for extra | 
|  | internal int dist;        // distance back to copy from | 
|  |  | 
|  | internal byte lbits;      // ltree bits decoded per branch | 
|  | internal byte dbits;      // dtree bits decoder per branch | 
|  | internal int[] ltree;     // literal/length/eob tree | 
|  | internal int ltree_index; // literal/length/eob tree | 
|  | internal int[] dtree;     // distance tree | 
|  | internal int dtree_index; // distance tree | 
|  |  | 
|  | internal InflateCodes() | 
|  | { | 
|  | } | 
|  |  | 
|  | internal void Init(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index) | 
|  | { | 
|  | mode = START; | 
|  | lbits = (byte)bl; | 
|  | dbits = (byte)bd; | 
|  | ltree = tl; | 
|  | ltree_index = tl_index; | 
|  | dtree = td; | 
|  | dtree_index = td_index; | 
|  | tree = null; | 
|  | } | 
|  |  | 
|  | internal int Process(InflateBlocks blocks, int r) | 
|  | { | 
|  | int j;      // temporary storage | 
|  | int tindex; // temporary pointer | 
|  | int e;      // extra bits or operation | 
|  | int b = 0;  // bit buffer | 
|  | int k = 0;  // bits in bit buffer | 
|  | int p = 0;  // input data pointer | 
|  | int n;      // bytes available there | 
|  | int q;      // output window write pointer | 
|  | int m;      // bytes to end of window or read pointer | 
|  | int f;      // pointer to copy strings from | 
|  |  | 
|  | ZlibCodec z = blocks._codec; | 
|  |  | 
|  | // copy input/output information to locals (UPDATE macro restores) | 
|  | p = z.NextIn; | 
|  | n = z.AvailableBytesIn; | 
|  | b = blocks.bitb; | 
|  | k = blocks.bitk; | 
|  | q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; | 
|  |  | 
|  | // process input and output based on current state | 
|  | while (true) | 
|  | { | 
|  | switch (mode) | 
|  | { | 
|  | // waiting for "i:"=input, "o:"=output, "x:"=nothing | 
|  | case START:  // x: set up for LEN | 
|  | if (m >= 258 && n >= 10) | 
|  | { | 
|  | blocks.bitb = b; blocks.bitk = k; | 
|  | z.AvailableBytesIn = n; | 
|  | z.TotalBytesIn += p - z.NextIn; | 
|  | z.NextIn = p; | 
|  | blocks.writeAt = q; | 
|  | r = InflateFast(lbits, dbits, ltree, ltree_index, dtree, dtree_index, blocks, z); | 
|  |  | 
|  | p = z.NextIn; | 
|  | n = z.AvailableBytesIn; | 
|  | b = blocks.bitb; | 
|  | k = blocks.bitk; | 
|  | q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; | 
|  |  | 
|  | if (r != ZlibConstants.Z_OK) | 
|  | { | 
|  | mode = (r == ZlibConstants.Z_STREAM_END) ? WASH : BADCODE; | 
|  | break; | 
|  | } | 
|  | } | 
|  | need = lbits; | 
|  | tree = ltree; | 
|  | tree_index = ltree_index; | 
|  |  | 
|  | mode = LEN; | 
|  | goto case LEN; | 
|  |  | 
|  | case LEN:  // i: get length/literal/eob next | 
|  | j = need; | 
|  |  | 
|  | while (k < j) | 
|  | { | 
|  | if (n != 0) | 
|  | r = ZlibConstants.Z_OK; | 
|  | else | 
|  | { | 
|  | blocks.bitb = b; blocks.bitk = k; | 
|  | z.AvailableBytesIn = n; | 
|  | z.TotalBytesIn += p - z.NextIn; | 
|  | z.NextIn = p; | 
|  | blocks.writeAt = q; | 
|  | return blocks.Flush(r); | 
|  | } | 
|  | n--; | 
|  | b |= (z.InputBuffer[p++] & 0xff) << k; | 
|  | k += 8; | 
|  | } | 
|  |  | 
|  | tindex = (tree_index + (b & InternalInflateConstants.InflateMask[j])) * 3; | 
|  |  | 
|  | b >>= (tree[tindex + 1]); | 
|  | k -= (tree[tindex + 1]); | 
|  |  | 
|  | e = tree[tindex]; | 
|  |  | 
|  | if (e == 0) | 
|  | { | 
|  | // literal | 
|  | lit = tree[tindex + 2]; | 
|  | mode = LIT; | 
|  | break; | 
|  | } | 
|  | if ((e & 16) != 0) | 
|  | { | 
|  | // length | 
|  | bitsToGet = e & 15; | 
|  | len = tree[tindex + 2]; | 
|  | mode = LENEXT; | 
|  | break; | 
|  | } | 
|  | if ((e & 64) == 0) | 
|  | { | 
|  | // next table | 
|  | need = e; | 
|  | tree_index = tindex / 3 + tree[tindex + 2]; | 
|  | break; | 
|  | } | 
|  | if ((e & 32) != 0) | 
|  | { | 
|  | // end of block | 
|  | mode = WASH; | 
|  | break; | 
|  | } | 
|  | mode = BADCODE; // invalid code | 
|  | z.Message = "invalid literal/length code"; | 
|  | r = ZlibConstants.Z_DATA_ERROR; | 
|  |  | 
|  | blocks.bitb = b; blocks.bitk = k; | 
|  | z.AvailableBytesIn = n; | 
|  | z.TotalBytesIn += p - z.NextIn; | 
|  | z.NextIn = p; | 
|  | blocks.writeAt = q; | 
|  | return blocks.Flush(r); | 
|  |  | 
|  |  | 
|  | case LENEXT:  // i: getting length extra (have base) | 
|  | j = bitsToGet; | 
|  |  | 
|  | while (k < j) | 
|  | { | 
|  | if (n != 0) | 
|  | r = ZlibConstants.Z_OK; | 
|  | else | 
|  | { | 
|  | blocks.bitb = b; blocks.bitk = k; | 
|  | z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; | 
|  | blocks.writeAt = q; | 
|  | return blocks.Flush(r); | 
|  | } | 
|  | n--; b |= (z.InputBuffer[p++] & 0xff) << k; | 
|  | k += 8; | 
|  | } | 
|  |  | 
|  | len += (b & InternalInflateConstants.InflateMask[j]); | 
|  |  | 
|  | b >>= j; | 
|  | k -= j; | 
|  |  | 
|  | need = dbits; | 
|  | tree = dtree; | 
|  | tree_index = dtree_index; | 
|  | mode = DIST; | 
|  | goto case DIST; | 
|  |  | 
|  | case DIST:  // i: get distance next | 
|  | j = need; | 
|  |  | 
|  | while (k < j) | 
|  | { | 
|  | if (n != 0) | 
|  | r = ZlibConstants.Z_OK; | 
|  | else | 
|  | { | 
|  | blocks.bitb = b; blocks.bitk = k; | 
|  | z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; | 
|  | blocks.writeAt = q; | 
|  | return blocks.Flush(r); | 
|  | } | 
|  | n--; b |= (z.InputBuffer[p++] & 0xff) << k; | 
|  | k += 8; | 
|  | } | 
|  |  | 
|  | tindex = (tree_index + (b & InternalInflateConstants.InflateMask[j])) * 3; | 
|  |  | 
|  | b >>= tree[tindex + 1]; | 
|  | k -= tree[tindex + 1]; | 
|  |  | 
|  | e = (tree[tindex]); | 
|  | if ((e & 0x10) != 0) | 
|  | { | 
|  | // distance | 
|  | bitsToGet = e & 15; | 
|  | dist = tree[tindex + 2]; | 
|  | mode = DISTEXT; | 
|  | break; | 
|  | } | 
|  | if ((e & 64) == 0) | 
|  | { | 
|  | // next table | 
|  | need = e; | 
|  | tree_index = tindex / 3 + tree[tindex + 2]; | 
|  | break; | 
|  | } | 
|  | mode = BADCODE; // invalid code | 
|  | z.Message = "invalid distance code"; | 
|  | r = ZlibConstants.Z_DATA_ERROR; | 
|  |  | 
|  | blocks.bitb = b; blocks.bitk = k; | 
|  | z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; | 
|  | blocks.writeAt = q; | 
|  | return blocks.Flush(r); | 
|  |  | 
|  |  | 
|  | case DISTEXT:  // i: getting distance extra | 
|  | j = bitsToGet; | 
|  |  | 
|  | while (k < j) | 
|  | { | 
|  | if (n != 0) | 
|  | r = ZlibConstants.Z_OK; | 
|  | else | 
|  | { | 
|  | blocks.bitb = b; blocks.bitk = k; | 
|  | z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; | 
|  | blocks.writeAt = q; | 
|  | return blocks.Flush(r); | 
|  | } | 
|  | n--; b |= (z.InputBuffer[p++] & 0xff) << k; | 
|  | k += 8; | 
|  | } | 
|  |  | 
|  | dist += (b & InternalInflateConstants.InflateMask[j]); | 
|  |  | 
|  | b >>= j; | 
|  | k -= j; | 
|  |  | 
|  | mode = COPY; | 
|  | goto case COPY; | 
|  |  | 
|  | case COPY:  // o: copying bytes in window, waiting for space | 
|  | f = q - dist; | 
|  | while (f < 0) | 
|  | { | 
|  | // modulo window size-"while" instead | 
|  | f += blocks.end; // of "if" handles invalid distances | 
|  | } | 
|  | while (len != 0) | 
|  | { | 
|  | if (m == 0) | 
|  | { | 
|  | if (q == blocks.end && blocks.readAt != 0) | 
|  | { | 
|  | q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; | 
|  | } | 
|  | if (m == 0) | 
|  | { | 
|  | blocks.writeAt = q; r = blocks.Flush(r); | 
|  | q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; | 
|  |  | 
|  | if (q == blocks.end && blocks.readAt != 0) | 
|  | { | 
|  | q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; | 
|  | } | 
|  |  | 
|  | if (m == 0) | 
|  | { | 
|  | blocks.bitb = b; blocks.bitk = k; | 
|  | z.AvailableBytesIn = n; | 
|  | z.TotalBytesIn += p - z.NextIn; | 
|  | z.NextIn = p; | 
|  | blocks.writeAt = q; | 
|  | return blocks.Flush(r); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | blocks.window[q++] = blocks.window[f++]; m--; | 
|  |  | 
|  | if (f == blocks.end) | 
|  | f = 0; | 
|  | len--; | 
|  | } | 
|  | mode = START; | 
|  | break; | 
|  |  | 
|  | case LIT:  // o: got literal, waiting for output space | 
|  | if (m == 0) | 
|  | { | 
|  | if (q == blocks.end && blocks.readAt != 0) | 
|  | { | 
|  | q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; | 
|  | } | 
|  | if (m == 0) | 
|  | { | 
|  | blocks.writeAt = q; r = blocks.Flush(r); | 
|  | q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; | 
|  |  | 
|  | if (q == blocks.end && blocks.readAt != 0) | 
|  | { | 
|  | q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; | 
|  | } | 
|  | if (m == 0) | 
|  | { | 
|  | blocks.bitb = b; blocks.bitk = k; | 
|  | z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; | 
|  | blocks.writeAt = q; | 
|  | return blocks.Flush(r); | 
|  | } | 
|  | } | 
|  | } | 
|  | r = ZlibConstants.Z_OK; | 
|  |  | 
|  | blocks.window[q++] = (byte)lit; m--; | 
|  |  | 
|  | mode = START; | 
|  | break; | 
|  |  | 
|  | case WASH:  // o: got eob, possibly more output | 
|  | if (k > 7) | 
|  | { | 
|  | // return unused byte, if any | 
|  | k -= 8; | 
|  | n++; | 
|  | p--; // can always return one | 
|  | } | 
|  |  | 
|  | blocks.writeAt = q; r = blocks.Flush(r); | 
|  | q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; | 
|  |  | 
|  | if (blocks.readAt != blocks.writeAt) | 
|  | { | 
|  | blocks.bitb = b; blocks.bitk = k; | 
|  | z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; | 
|  | blocks.writeAt = q; | 
|  | return blocks.Flush(r); | 
|  | } | 
|  | mode = END; | 
|  | goto case END; | 
|  |  | 
|  | case END: | 
|  | r = ZlibConstants.Z_STREAM_END; | 
|  | blocks.bitb = b; blocks.bitk = k; | 
|  | z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; | 
|  | blocks.writeAt = q; | 
|  | return blocks.Flush(r); | 
|  |  | 
|  | case BADCODE:  // x: got error | 
|  |  | 
|  | r = ZlibConstants.Z_DATA_ERROR; | 
|  |  | 
|  | blocks.bitb = b; blocks.bitk = k; | 
|  | z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; | 
|  | blocks.writeAt = q; | 
|  | return blocks.Flush(r); | 
|  |  | 
|  | default: | 
|  | r = ZlibConstants.Z_STREAM_ERROR; | 
|  |  | 
|  | blocks.bitb = b; blocks.bitk = k; | 
|  | z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; | 
|  | blocks.writeAt = q; | 
|  | return blocks.Flush(r); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | // Called with number of bytes left to write in window at least 258 | 
|  | // (the maximum string length) and number of input bytes available | 
|  | // at least ten.  The ten bytes are six bytes for the longest length/ | 
|  | // distance pair plus four bytes for overloading the bit buffer. | 
|  |  | 
|  | internal int InflateFast(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, InflateBlocks s, ZlibCodec z) | 
|  | { | 
|  | int t;        // temporary pointer | 
|  | int[] tp;     // temporary pointer | 
|  | int tp_index; // temporary pointer | 
|  | int e;        // extra bits or operation | 
|  | int b;        // bit buffer | 
|  | int k;        // bits in bit buffer | 
|  | int p;        // input data pointer | 
|  | int n;        // bytes available there | 
|  | int q;        // output window write pointer | 
|  | int m;        // bytes to end of window or read pointer | 
|  | int ml;       // mask for literal/length tree | 
|  | int md;       // mask for distance tree | 
|  | int c;        // bytes to copy | 
|  | int d;        // distance back to copy from | 
|  | int r;        // copy source pointer | 
|  |  | 
|  | int tp_index_t_3; // (tp_index+t)*3 | 
|  |  | 
|  | // load input, output, bit values | 
|  | p = z.NextIn; n = z.AvailableBytesIn; b = s.bitb; k = s.bitk; | 
|  | q = s.writeAt; m = q < s.readAt ? s.readAt - q - 1 : s.end - q; | 
|  |  | 
|  | // initialize masks | 
|  | ml = InternalInflateConstants.InflateMask[bl]; | 
|  | md = InternalInflateConstants.InflateMask[bd]; | 
|  |  | 
|  | // do until not enough input or output space for fast loop | 
|  | do | 
|  | { | 
|  | // assume called with m >= 258 && n >= 10 | 
|  | // get literal/length code | 
|  | while (k < (20)) | 
|  | { | 
|  | // max bits for literal/length code | 
|  | n--; | 
|  | b |= (z.InputBuffer[p++] & 0xff) << k; k += 8; | 
|  | } | 
|  |  | 
|  | t = b & ml; | 
|  | tp = tl; | 
|  | tp_index = tl_index; | 
|  | tp_index_t_3 = (tp_index + t) * 3; | 
|  | if ((e = tp[tp_index_t_3]) == 0) | 
|  | { | 
|  | b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]); | 
|  |  | 
|  | s.window[q++] = (byte)tp[tp_index_t_3 + 2]; | 
|  | m--; | 
|  | continue; | 
|  | } | 
|  | do | 
|  | { | 
|  |  | 
|  | b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]); | 
|  |  | 
|  | if ((e & 16) != 0) | 
|  | { | 
|  | e &= 15; | 
|  | c = tp[tp_index_t_3 + 2] + ((int)b & InternalInflateConstants.InflateMask[e]); | 
|  |  | 
|  | b >>= e; k -= e; | 
|  |  | 
|  | // decode distance base of block to copy | 
|  | while (k < 15) | 
|  | { | 
|  | // max bits for distance code | 
|  | n--; | 
|  | b |= (z.InputBuffer[p++] & 0xff) << k; k += 8; | 
|  | } | 
|  |  | 
|  | t = b & md; | 
|  | tp = td; | 
|  | tp_index = td_index; | 
|  | tp_index_t_3 = (tp_index + t) * 3; | 
|  | e = tp[tp_index_t_3]; | 
|  |  | 
|  | do | 
|  | { | 
|  |  | 
|  | b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]); | 
|  |  | 
|  | if ((e & 16) != 0) | 
|  | { | 
|  | // get extra bits to add to distance base | 
|  | e &= 15; | 
|  | while (k < e) | 
|  | { | 
|  | // get extra bits (up to 13) | 
|  | n--; | 
|  | b |= (z.InputBuffer[p++] & 0xff) << k; k += 8; | 
|  | } | 
|  |  | 
|  | d = tp[tp_index_t_3 + 2] + (b & InternalInflateConstants.InflateMask[e]); | 
|  |  | 
|  | b >>= e; k -= e; | 
|  |  | 
|  | // do the copy | 
|  | m -= c; | 
|  | if (q >= d) | 
|  | { | 
|  | // offset before dest | 
|  | //  just copy | 
|  | r = q - d; | 
|  | if (q - r > 0 && 2 > (q - r)) | 
|  | { | 
|  | s.window[q++] = s.window[r++]; // minimum count is three, | 
|  | s.window[q++] = s.window[r++]; // so unroll loop a little | 
|  | c -= 2; | 
|  | } | 
|  | else | 
|  | { | 
|  | Array.Copy(s.window, r, s.window, q, 2); | 
|  | q += 2; r += 2; c -= 2; | 
|  | } | 
|  | } | 
|  | else | 
|  | { | 
|  | // else offset after destination | 
|  | r = q - d; | 
|  | do | 
|  | { | 
|  | r += s.end; // force pointer in window | 
|  | } | 
|  | while (r < 0); // covers invalid distances | 
|  | e = s.end - r; | 
|  | if (c > e) | 
|  | { | 
|  | // if source crosses, | 
|  | c -= e; // wrapped copy | 
|  | if (q - r > 0 && e > (q - r)) | 
|  | { | 
|  | do | 
|  | { | 
|  | s.window[q++] = s.window[r++]; | 
|  | } | 
|  | while (--e != 0); | 
|  | } | 
|  | else | 
|  | { | 
|  | Array.Copy(s.window, r, s.window, q, e); | 
|  | q += e; r += e; e = 0; | 
|  | } | 
|  | r = 0; // copy rest from start of window | 
|  | } | 
|  | } | 
|  |  | 
|  | // copy all or what's left | 
|  | if (q - r > 0 && c > (q - r)) | 
|  | { | 
|  | do | 
|  | { | 
|  | s.window[q++] = s.window[r++]; | 
|  | } | 
|  | while (--c != 0); | 
|  | } | 
|  | else | 
|  | { | 
|  | Array.Copy(s.window, r, s.window, q, c); | 
|  | q += c; r += c; c = 0; | 
|  | } | 
|  | break; | 
|  | } | 
|  | else if ((e & 64) == 0) | 
|  | { | 
|  | t += tp[tp_index_t_3 + 2]; | 
|  | t += (b & InternalInflateConstants.InflateMask[e]); | 
|  | tp_index_t_3 = (tp_index + t) * 3; | 
|  | e = tp[tp_index_t_3]; | 
|  | } | 
|  | else | 
|  | { | 
|  | z.Message = "invalid distance code"; | 
|  |  | 
|  | c = z.AvailableBytesIn - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3); | 
|  |  | 
|  | s.bitb = b; s.bitk = k; | 
|  | z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; | 
|  | s.writeAt = q; | 
|  |  | 
|  | return ZlibConstants.Z_DATA_ERROR; | 
|  | } | 
|  | } | 
|  | while (true); | 
|  | break; | 
|  | } | 
|  |  | 
|  | if ((e & 64) == 0) | 
|  | { | 
|  | t += tp[tp_index_t_3 + 2]; | 
|  | t += (b & InternalInflateConstants.InflateMask[e]); | 
|  | tp_index_t_3 = (tp_index + t) * 3; | 
|  | if ((e = tp[tp_index_t_3]) == 0) | 
|  | { | 
|  | b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]); | 
|  | s.window[q++] = (byte)tp[tp_index_t_3 + 2]; | 
|  | m--; | 
|  | break; | 
|  | } | 
|  | } | 
|  | else if ((e & 32) != 0) | 
|  | { | 
|  | c = z.AvailableBytesIn - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3); | 
|  |  | 
|  | s.bitb = b; s.bitk = k; | 
|  | z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; | 
|  | s.writeAt = q; | 
|  |  | 
|  | return ZlibConstants.Z_STREAM_END; | 
|  | } | 
|  | else | 
|  | { | 
|  | z.Message = "invalid literal/length code"; | 
|  |  | 
|  | c = z.AvailableBytesIn - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3); | 
|  |  | 
|  | s.bitb = b; s.bitk = k; | 
|  | z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; | 
|  | s.writeAt = q; | 
|  |  | 
|  | return ZlibConstants.Z_DATA_ERROR; | 
|  | } | 
|  | } | 
|  | while (true); | 
|  | } | 
|  | while (m >= 258 && n >= 10); | 
|  |  | 
|  | // not enough input or output--restore pointers and return | 
|  | c = z.AvailableBytesIn - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3); | 
|  |  | 
|  | s.bitb = b; s.bitk = k; | 
|  | z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; | 
|  | s.writeAt = q; | 
|  |  | 
|  | return ZlibConstants.Z_OK; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | internal sealed class InflateManager | 
|  | { | 
|  | // preset dictionary flag in zlib header | 
|  | private const int PRESET_DICT = 0x20; | 
|  |  | 
|  | private const int Z_DEFLATED = 8; | 
|  |  | 
|  | private enum InflateManagerMode | 
|  | { | 
|  | METHOD = 0,  // waiting for method byte | 
|  | FLAG   = 1,  // waiting for flag byte | 
|  | DICT4  = 2,  // four dictionary check bytes to go | 
|  | DICT3  = 3,  // three dictionary check bytes to go | 
|  | DICT2  = 4,  // two dictionary check bytes to go | 
|  | DICT1  = 5,  // one dictionary check byte to go | 
|  | DICT0  = 6,  // waiting for inflateSetDictionary | 
|  | BLOCKS = 7,  // decompressing blocks | 
|  | CHECK4 = 8,  // four check bytes to go | 
|  | CHECK3 = 9,  // three check bytes to go | 
|  | CHECK2 = 10, // two check bytes to go | 
|  | CHECK1 = 11, // one check byte to go | 
|  | DONE   = 12, // finished check, done | 
|  | BAD    = 13, // got an error--stay here | 
|  | } | 
|  |  | 
|  | private InflateManagerMode mode; // current inflate mode | 
|  | internal ZlibCodec _codec; // pointer back to this zlib stream | 
|  |  | 
|  | // mode dependent information | 
|  | internal int method; // if FLAGS, method byte | 
|  |  | 
|  | // if CHECK, check values to compare | 
|  | internal uint computedCheck; // computed check value | 
|  | internal uint expectedCheck; // stream check value | 
|  |  | 
|  | // if BAD, inflateSync's marker bytes count | 
|  | internal int marker; | 
|  |  | 
|  | // mode independent information | 
|  | //internal int nowrap; // flag for no wrapper | 
|  | private bool _handleRfc1950HeaderBytes = true; | 
|  | internal bool HandleRfc1950HeaderBytes | 
|  | { | 
|  | get { return _handleRfc1950HeaderBytes; } | 
|  | set { _handleRfc1950HeaderBytes = value; } | 
|  | } | 
|  | internal int wbits; // log2(window size)  (8..15, defaults to 15) | 
|  |  | 
|  | internal InflateBlocks blocks; // current inflate_blocks state | 
|  |  | 
|  | public InflateManager() { } | 
|  |  | 
|  | public InflateManager(bool expectRfc1950HeaderBytes) | 
|  | { | 
|  | _handleRfc1950HeaderBytes = expectRfc1950HeaderBytes; | 
|  | } | 
|  |  | 
|  | internal int Reset() | 
|  | { | 
|  | _codec.TotalBytesIn = _codec.TotalBytesOut = 0; | 
|  | _codec.Message = null; | 
|  | mode = HandleRfc1950HeaderBytes ? InflateManagerMode.METHOD : InflateManagerMode.BLOCKS; | 
|  | blocks.Reset(); | 
|  | return ZlibConstants.Z_OK; | 
|  | } | 
|  |  | 
|  | internal int End() | 
|  | { | 
|  | if (blocks != null) | 
|  | blocks.Free(); | 
|  | blocks = null; | 
|  | return ZlibConstants.Z_OK; | 
|  | } | 
|  |  | 
|  | internal int Initialize(ZlibCodec codec, int w) | 
|  | { | 
|  | _codec = codec; | 
|  | _codec.Message = null; | 
|  | blocks = null; | 
|  |  | 
|  | // handle undocumented nowrap option (no zlib header or check) | 
|  | //nowrap = 0; | 
|  | //if (w < 0) | 
|  | //{ | 
|  | //    w = - w; | 
|  | //    nowrap = 1; | 
|  | //} | 
|  |  | 
|  | // set window size | 
|  | if (w < 8 || w > 15) | 
|  | { | 
|  | End(); | 
|  | throw new ZlibException("Bad window size."); | 
|  |  | 
|  | //return ZlibConstants.Z_STREAM_ERROR; | 
|  | } | 
|  | wbits = w; | 
|  |  | 
|  | blocks = new InflateBlocks(codec, | 
|  | HandleRfc1950HeaderBytes ? this : null, | 
|  | 1 << w); | 
|  |  | 
|  | // reset state | 
|  | Reset(); | 
|  | return ZlibConstants.Z_OK; | 
|  | } | 
|  |  | 
|  |  | 
|  | internal int Inflate(FlushType flush) | 
|  | { | 
|  | int b; | 
|  |  | 
|  | if (_codec.InputBuffer == null) | 
|  | throw new ZlibException("InputBuffer is null. "); | 
|  |  | 
|  | //             int f = (flush == FlushType.Finish) | 
|  | //                 ? ZlibConstants.Z_BUF_ERROR | 
|  | //                 : ZlibConstants.Z_OK; | 
|  |  | 
|  | // workitem 8870 | 
|  | int f = ZlibConstants.Z_OK; | 
|  | int r = ZlibConstants.Z_BUF_ERROR; | 
|  |  | 
|  | while (true) | 
|  | { | 
|  | switch (mode) | 
|  | { | 
|  | case InflateManagerMode.METHOD: | 
|  | if (_codec.AvailableBytesIn == 0) return r; | 
|  | r = f; | 
|  | _codec.AvailableBytesIn--; | 
|  | _codec.TotalBytesIn++; | 
|  | if (((method = _codec.InputBuffer[_codec.NextIn++]) & 0xf) != Z_DEFLATED) | 
|  | { | 
|  | mode = InflateManagerMode.BAD; | 
|  | _codec.Message = String.Format("unknown compression method (0x{0:X2})", method); | 
|  | marker = 5; // can't try inflateSync | 
|  | break; | 
|  | } | 
|  | if ((method >> 4) + 8 > wbits) | 
|  | { | 
|  | mode = InflateManagerMode.BAD; | 
|  | _codec.Message = String.Format("invalid window size ({0})", (method >> 4) + 8); | 
|  | marker = 5; // can't try inflateSync | 
|  | break; | 
|  | } | 
|  | mode = InflateManagerMode.FLAG; | 
|  | break; | 
|  |  | 
|  |  | 
|  | case InflateManagerMode.FLAG: | 
|  | if (_codec.AvailableBytesIn == 0) return r; | 
|  | r = f; | 
|  | _codec.AvailableBytesIn--; | 
|  | _codec.TotalBytesIn++; | 
|  | b = (_codec.InputBuffer[_codec.NextIn++]) & 0xff; | 
|  |  | 
|  | if ((((method << 8) + b) % 31) != 0) | 
|  | { | 
|  | mode = InflateManagerMode.BAD; | 
|  | _codec.Message = "incorrect header check"; | 
|  | marker = 5; // can't try inflateSync | 
|  | break; | 
|  | } | 
|  |  | 
|  | mode = ((b & PRESET_DICT) == 0) | 
|  | ? InflateManagerMode.BLOCKS | 
|  | : InflateManagerMode.DICT4; | 
|  | break; | 
|  |  | 
|  | case InflateManagerMode.DICT4: | 
|  | if (_codec.AvailableBytesIn == 0) return r; | 
|  | r = f; | 
|  | _codec.AvailableBytesIn--; | 
|  | _codec.TotalBytesIn++; | 
|  | expectedCheck = (uint)((_codec.InputBuffer[_codec.NextIn++] << 24) & 0xff000000); | 
|  | mode = InflateManagerMode.DICT3; | 
|  | break; | 
|  |  | 
|  | case InflateManagerMode.DICT3: | 
|  | if (_codec.AvailableBytesIn == 0) return r; | 
|  | r = f; | 
|  | _codec.AvailableBytesIn--; | 
|  | _codec.TotalBytesIn++; | 
|  | expectedCheck += (uint)((_codec.InputBuffer[_codec.NextIn++] << 16) & 0x00ff0000); | 
|  | mode = InflateManagerMode.DICT2; | 
|  | break; | 
|  |  | 
|  | case InflateManagerMode.DICT2: | 
|  |  | 
|  | if (_codec.AvailableBytesIn == 0) return r; | 
|  | r = f; | 
|  | _codec.AvailableBytesIn--; | 
|  | _codec.TotalBytesIn++; | 
|  | expectedCheck += (uint)((_codec.InputBuffer[_codec.NextIn++] << 8) & 0x0000ff00); | 
|  | mode = InflateManagerMode.DICT1; | 
|  | break; | 
|  |  | 
|  |  | 
|  | case InflateManagerMode.DICT1: | 
|  | if (_codec.AvailableBytesIn == 0) return r; | 
|  | r = f; | 
|  | _codec.AvailableBytesIn--; _codec.TotalBytesIn++; | 
|  | expectedCheck += (uint)(_codec.InputBuffer[_codec.NextIn++] & 0x000000ff); | 
|  | _codec._Adler32 = expectedCheck; | 
|  | mode = InflateManagerMode.DICT0; | 
|  | return ZlibConstants.Z_NEED_DICT; | 
|  |  | 
|  |  | 
|  | case InflateManagerMode.DICT0: | 
|  | mode = InflateManagerMode.BAD; | 
|  | _codec.Message = "need dictionary"; | 
|  | marker = 0; // can try inflateSync | 
|  | return ZlibConstants.Z_STREAM_ERROR; | 
|  |  | 
|  |  | 
|  | case InflateManagerMode.BLOCKS: | 
|  | r = blocks.Process(r); | 
|  | if (r == ZlibConstants.Z_DATA_ERROR) | 
|  | { | 
|  | mode = InflateManagerMode.BAD; | 
|  | marker = 0; // can try inflateSync | 
|  | break; | 
|  | } | 
|  |  | 
|  | if (r == ZlibConstants.Z_OK) r = f; | 
|  |  | 
|  | if (r != ZlibConstants.Z_STREAM_END) | 
|  | return r; | 
|  |  | 
|  | r = f; | 
|  | computedCheck = blocks.Reset(); | 
|  | if (!HandleRfc1950HeaderBytes) | 
|  | { | 
|  | mode = InflateManagerMode.DONE; | 
|  | return ZlibConstants.Z_STREAM_END; | 
|  | } | 
|  | mode = InflateManagerMode.CHECK4; | 
|  | break; | 
|  |  | 
|  | case InflateManagerMode.CHECK4: | 
|  | if (_codec.AvailableBytesIn == 0) return r; | 
|  | r = f; | 
|  | _codec.AvailableBytesIn--; | 
|  | _codec.TotalBytesIn++; | 
|  | expectedCheck = (uint)((_codec.InputBuffer[_codec.NextIn++] << 24) & 0xff000000); | 
|  | mode = InflateManagerMode.CHECK3; | 
|  | break; | 
|  |  | 
|  | case InflateManagerMode.CHECK3: | 
|  | if (_codec.AvailableBytesIn == 0) return r; | 
|  | r = f; | 
|  | _codec.AvailableBytesIn--; _codec.TotalBytesIn++; | 
|  | expectedCheck += (uint)((_codec.InputBuffer[_codec.NextIn++] << 16) & 0x00ff0000); | 
|  | mode = InflateManagerMode.CHECK2; | 
|  | break; | 
|  |  | 
|  | case InflateManagerMode.CHECK2: | 
|  | if (_codec.AvailableBytesIn == 0) return r; | 
|  | r = f; | 
|  | _codec.AvailableBytesIn--; | 
|  | _codec.TotalBytesIn++; | 
|  | expectedCheck += (uint)((_codec.InputBuffer[_codec.NextIn++] << 8) & 0x0000ff00); | 
|  | mode = InflateManagerMode.CHECK1; | 
|  | break; | 
|  |  | 
|  | case InflateManagerMode.CHECK1: | 
|  | if (_codec.AvailableBytesIn == 0) return r; | 
|  | r = f; | 
|  | _codec.AvailableBytesIn--; _codec.TotalBytesIn++; | 
|  | expectedCheck += (uint)(_codec.InputBuffer[_codec.NextIn++] & 0x000000ff); | 
|  | if (computedCheck != expectedCheck) | 
|  | { | 
|  | mode = InflateManagerMode.BAD; | 
|  | _codec.Message = "incorrect data check"; | 
|  | marker = 5; // can't try inflateSync | 
|  | break; | 
|  | } | 
|  | mode = InflateManagerMode.DONE; | 
|  | return ZlibConstants.Z_STREAM_END; | 
|  |  | 
|  | case InflateManagerMode.DONE: | 
|  | return ZlibConstants.Z_STREAM_END; | 
|  |  | 
|  | case InflateManagerMode.BAD: | 
|  | throw new ZlibException(String.Format("Bad state ({0})", _codec.Message)); | 
|  |  | 
|  | default: | 
|  | throw new ZlibException("Stream error."); | 
|  |  | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | internal int SetDictionary(byte[] dictionary) | 
|  | { | 
|  | int index = 0; | 
|  | int length = dictionary.Length; | 
|  | if (mode != InflateManagerMode.DICT0) | 
|  | throw new ZlibException("Stream error."); | 
|  |  | 
|  | if (Adler.Adler32(1, dictionary, 0, dictionary.Length) != _codec._Adler32) | 
|  | { | 
|  | return ZlibConstants.Z_DATA_ERROR; | 
|  | } | 
|  |  | 
|  | _codec._Adler32 = Adler.Adler32(0, null, 0, 0); | 
|  |  | 
|  | if (length >= (1 << wbits)) | 
|  | { | 
|  | length = (1 << wbits) - 1; | 
|  | index = dictionary.Length - length; | 
|  | } | 
|  | blocks.SetDictionary(dictionary, index, length); | 
|  | mode = InflateManagerMode.BLOCKS; | 
|  | return ZlibConstants.Z_OK; | 
|  | } | 
|  |  | 
|  |  | 
|  | private static readonly byte[] mark = new byte[] { 0, 0, 0xff, 0xff }; | 
|  |  | 
|  | internal int Sync() | 
|  | { | 
|  | int n; // number of bytes to look at | 
|  | int p; // pointer to bytes | 
|  | int m; // number of marker bytes found in a row | 
|  | long r, w; // temporaries to save total_in and total_out | 
|  |  | 
|  | // set up | 
|  | if (mode != InflateManagerMode.BAD) | 
|  | { | 
|  | mode = InflateManagerMode.BAD; | 
|  | marker = 0; | 
|  | } | 
|  | if ((n = _codec.AvailableBytesIn) == 0) | 
|  | return ZlibConstants.Z_BUF_ERROR; | 
|  | p = _codec.NextIn; | 
|  | m = marker; | 
|  |  | 
|  | // search | 
|  | while (n != 0 && m < 4) | 
|  | { | 
|  | if (_codec.InputBuffer[p] == mark[m]) | 
|  | { | 
|  | m++; | 
|  | } | 
|  | else if (_codec.InputBuffer[p] != 0) | 
|  | { | 
|  | m = 0; | 
|  | } | 
|  | else | 
|  | { | 
|  | m = 4 - m; | 
|  | } | 
|  | p++; n--; | 
|  | } | 
|  |  | 
|  | // restore | 
|  | _codec.TotalBytesIn += p - _codec.NextIn; | 
|  | _codec.NextIn = p; | 
|  | _codec.AvailableBytesIn = n; | 
|  | marker = m; | 
|  |  | 
|  | // return no joy or set up to restart on a new block | 
|  | if (m != 4) | 
|  | { | 
|  | return ZlibConstants.Z_DATA_ERROR; | 
|  | } | 
|  | r = _codec.TotalBytesIn; | 
|  | w = _codec.TotalBytesOut; | 
|  | Reset(); | 
|  | _codec.TotalBytesIn = r; | 
|  | _codec.TotalBytesOut = w; | 
|  | mode = InflateManagerMode.BLOCKS; | 
|  | return ZlibConstants.Z_OK; | 
|  | } | 
|  |  | 
|  |  | 
|  | // Returns true if inflate is currently at the end of a block generated | 
|  | // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP | 
|  | // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH | 
|  | // but removes the length bytes of the resulting empty stored block. When | 
|  | // decompressing, PPP checks that at the end of input packet, inflate is | 
|  | // waiting for these length bytes. | 
|  | internal int SyncPoint(ZlibCodec z) | 
|  | { | 
|  | return blocks.SyncPoint(); | 
|  | } | 
|  | } | 
|  | } |