public ZlibStream(Stream innerStream) { _innerStream = innerStream; if(_innerStream.CanRead) { _in = new ZStream(); int ret = _in.inflateInit(); if (ret != zlibConst.Z_OK) throw new ZStreamException("Unable to initialize inflate"); _inBuff = new byte[_buffSize]; _in.avail_in = 0; _in.next_in = _inBuff; _in.next_in_index = 0; } if(_innerStream.CanWrite) { _out = new ZStream(); int ret = _out.deflateInit(zlibConst.Z_DEFAULT_COMPRESSION); if (ret != zlibConst.Z_OK) throw new ZStreamException("Unable to initialize deflate"); _outBuff = new byte[_buffSize]; _out.next_out = _outBuff; } }
internal int inflateEnd(ZStream z) { if (blocks != null) blocks.free(z); blocks = null; // ZFREE(z, z->state); return Z_OK; }
internal long check; // check on output internal InfBlocks(ZStream z, System.Object checkfn, int w) { hufts = new int[MANY * 3]; window = new byte[w]; end = w; this.checkfn = checkfn; mode = TYPE; reset(z, null); }
internal InfCodes(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, ZStream z) { this.mode = 0; this.lbits = (byte) bl; this.dbits = (byte) bd; this.ltree = tl; this.ltree_index = tl_index; this.dtree = td; this.dtree_index = td_index; }
internal InfCodes(int bl, int bd, int[] tl, int[] td, ZStream z) { mode = START; lbits = (byte) bl; dbits = (byte) bd; ltree = tl; ltree_index = 0; dtree = td; dtree_index = 0; }
internal InfBlocks blocks; // current inflate_blocks state internal int inflateReset(ZStream z) { if (z == null || z.istate == null) return Z_STREAM_ERROR; z.total_in = z.total_out = 0; z.msg = null; z.istate.mode = z.istate.nowrap != 0?BLOCKS:METHOD; z.istate.blocks.reset(z, null); return Z_OK; }
internal InfBlocks(ZStream z, object checkfn, int w) { this.bb = new int[1]; this.tb = new int[1]; this.hufts = new int[0x10e0]; this.window = new byte[w]; this.end = w; this.checkfn = checkfn; this.mode = 0; this.reset(z, null); }
internal int inflate_flush(ZStream z, int r) { int num2 = z.next_out_index; int num3 = this.read; int num1 = ((num3 <= this.write) ? this.write : this.end) - num3; if (num1 > z.avail_out) { num1 = z.avail_out; } if ((num1 != 0) && (r == -5)) { r = 0; } z.avail_out -= num1; z.total_out += num1; if (this.checkfn != null) { z.adler = this.check = z._adler.adler32(this.check, this.window, num3, num1); } Array.Copy(this.window, num3, z.next_out, num2, num1); num2 += num1; num3 += num1; if (num3 == this.end) { num3 = 0; if (this.write == this.end) { this.write = 0; } num1 = this.write - num3; if (num1 > z.avail_out) { num1 = z.avail_out; } if ((num1 != 0) && (r == -5)) { r = 0; } z.avail_out -= num1; z.total_out += num1; if (this.checkfn != null) { z.adler = this.check = z._adler.adler32(this.check, this.window, num3, num1); } Array.Copy(this.window, num3, z.next_out, num2, num1); num2 += num1; num3 += num1; } z.next_out_index = num2; this.read = num3; return r; }
internal void reset(ZStream z, long[] c) { if (c != null) c[0] = check; if (mode == BTREE || mode == DTREE) { blens = null; } if (mode == CODES) { codes.free(z); } mode = TYPE; bitk = 0; bitb = 0; read = write = 0; if (checkfn != null) z.adler = check = z._adler.adler32(0L, null, 0, 0); }
internal static int inflate_trees_dynamic(int nl, int nd, int[] c, int[] bl, int[] bd, int[] tl, int[] td, int[] hp, ZStream z) { int r; int[] hn = new int[1]; // hufts used in space int[] v = new int[288]; // work area for huft_build // build literal/length tree r = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v); if (r != Z_OK || bl[0] == 0) { if (r == Z_DATA_ERROR) { z.msg = "oversubscribed literal/length tree"; } else if (r != Z_MEM_ERROR) { z.msg = "incomplete literal/length tree"; r = Z_DATA_ERROR; } return r; } // build distance tree r = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v); if (r != Z_OK || (bd[0] == 0 && nl > 257)) { if (r == Z_DATA_ERROR) { z.msg = "oversubscribed distance tree"; } else if (r == Z_BUF_ERROR) { z.msg = "incomplete distance tree"; r = Z_DATA_ERROR; } else if (r != Z_MEM_ERROR) { z.msg = "empty distance tree with lengths"; r = Z_DATA_ERROR; } return r; } return Z_OK; }
internal int deflate(ZStream strm, int flush) { int old_flush; if (flush > Z_FINISH || flush < 0) { return Z_STREAM_ERROR; } if (strm.next_out == null || (strm.next_in == null && strm.avail_in != 0) || (status == FINISH_STATE && flush != Z_FINISH)) { strm.msg = z_errmsg[Z_NEED_DICT - (Z_STREAM_ERROR)]; return Z_STREAM_ERROR; } if (strm.avail_out == 0) { strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)]; return Z_BUF_ERROR; } this.strm = strm; // just in case old_flush = last_flush; last_flush = flush; // Write the zlib header if (status == INIT_STATE) { int header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8; int level_flags = ((level - 1) & 0xff) >> 1; if (level_flags > 3) level_flags = 3; header |= (level_flags << 6); if (strstart != 0) header |= PRESET_DICT; header += 31 - (header % 31); status = BUSY_STATE; putShortMSB(header); // Save the adler32 of the preset dictionary: if (strstart != 0) { putShortMSB((int) (SupportClass.URShift(strm.adler, 16))); putShortMSB((int) (strm.adler & 0xffff)); } strm.adler = strm._adler.adler32(0, null, 0, 0); } // Flush as much pending output as possible if (pending != 0) { strm.flush_pending(); if (strm.avail_out == 0) { //System.out.println(" avail_out==0"); // Since avail_out is 0, deflate will be called again with // more output space, but possibly with both pending and // avail_in equal to zero. There won't be anything to do, // but this is not an error situation so make sure we // return OK instead of BUF_ERROR at next call of deflate: last_flush = - 1; return Z_OK; } // Make sure there is something to do and avoid duplicate consecutive // flushes. For repeated and useless calls with Z_FINISH, we keep // returning Z_STREAM_END instead of Z_BUFF_ERROR. } else if (strm.avail_in == 0 && flush <= old_flush && flush != Z_FINISH) { strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)]; return Z_BUF_ERROR; } // User must not provide more input after the first FINISH: if (status == FINISH_STATE && strm.avail_in != 0) { strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)]; return Z_BUF_ERROR; } // Start a new block or continue the current one. if (strm.avail_in != 0 || lookahead != 0 || (flush != Z_NO_FLUSH && status != FINISH_STATE)) { int bstate = - 1; switch (config_table[level].func) { case STORED: bstate = deflate_stored(flush); break; case FAST: bstate = deflate_fast(flush); break; case SLOW: bstate = deflate_slow(flush); break; default: break; } if (bstate == FinishStarted || bstate == FinishDone) { status = FINISH_STATE; } if (bstate == NeedMore || bstate == FinishStarted) { if (strm.avail_out == 0) { last_flush = - 1; // avoid BUF_ERROR next call, see above } return Z_OK; // If flush != Z_NO_FLUSH && avail_out == 0, the next call // of deflate should use the same flush parameter to make sure // that the flush is complete. So we don't have to output an // empty block here, this will be done at next call. This also // ensures that for a very small output buffer, we emit at most // one empty block. } if (bstate == BlockDone) { if (flush == Z_PARTIAL_FLUSH) { _tr_align(); } else { // FULL_FLUSH or SYNC_FLUSH _tr_stored_block(0, 0, false); // For a full flush, this empty block will be recognized // as a special marker by inflate_sync(). if (flush == Z_FULL_FLUSH) { //state.head[s.hash_size-1]=0; for (int i = 0; i < hash_size; i++) // forget history head[i] = 0; } } strm.flush_pending(); if (strm.avail_out == 0) { last_flush = - 1; // avoid BUF_ERROR at next call, see above return Z_OK; } } } if (flush != Z_FINISH) return Z_OK; if (noheader != 0) return Z_STREAM_END; // Write the zlib trailer (adler32) putShortMSB((int) (SupportClass.URShift(strm.adler, 16))); putShortMSB((int) (strm.adler & 0xffff)); strm.flush_pending(); // If avail_out is zero, the application will call deflate again // to flush the rest. noheader = - 1; // write the trailer only once! return pending != 0?Z_OK:Z_STREAM_END; }
internal int deflateParams(ZStream strm, int _level, int _strategy) { int err = Z_OK; if (_level == Z_DEFAULT_COMPRESSION) { _level = 6; } if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) { return Z_STREAM_ERROR; } if (config_table[level].func != config_table[_level].func && strm.total_in != 0) { // Flush the last buffer: err = strm.deflate(Z_PARTIAL_FLUSH); } if (level != _level) { level = _level; max_lazy_match = config_table[level].max_lazy; good_match = config_table[level].good_length; nice_match = config_table[level].nice_length; max_chain_length = config_table[level].max_chain; } strategy = _strategy; return err; }
internal int deflateInit2(ZStream strm, int level, int method, int windowBits, int memLevel, int strategy) { int noheader = 0; // byte[] my_version=ZLIB_VERSION; // // if (version == null || version[0] != my_version[0] // || stream_size != sizeof(z_stream)) { // return Z_VERSION_ERROR; // } strm.msg = null; if (level == Z_DEFAULT_COMPRESSION) level = 6; if (windowBits < 0) { // undocumented feature: suppress zlib header noheader = 1; windowBits = - windowBits; } if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { return Z_STREAM_ERROR; } strm.dstate = (Deflate) this; this.noheader = noheader; w_bits = windowBits; w_size = 1 << w_bits; w_mask = w_size - 1; hash_bits = memLevel + 7; hash_size = 1 << hash_bits; hash_mask = hash_size - 1; hash_shift = ((hash_bits + MIN_MATCH - 1) / MIN_MATCH); window = new byte[w_size * 2]; prev = new short[w_size]; head = new short[hash_size]; lit_bufsize = 1 << (memLevel + 6); // 16K elements by default // We overlay pending_buf and d_buf+l_buf. This works since the average // output size for (length,distance) codes is <= 24 bits. pending_buf = new byte[lit_bufsize * 4]; pending_buf_size = lit_bufsize * 4; d_buf = lit_bufsize / 2; l_buf = (1 + 2) * lit_bufsize; this.level = level; //System.out.println("level="+level); this.strategy = strategy; this.method = (byte) method; return deflateReset(strm); }
internal static int inflate_trees_fixed(int[] bl, int[] bd, int[][] tl, int[][] td, ZStream z) { bl[0] = fixed_bl; bd[0] = fixed_bd; tl[0] = fixed_tl; td[0] = fixed_td; return(Z_OK); }
internal int inflate(ZStream z, int f) { int r; int b; if (z == null || z.istate == null || z.next_in == null) { return(Z_STREAM_ERROR); } f = f == Z_FINISH?Z_BUF_ERROR:Z_OK; r = Z_BUF_ERROR; while (true) { //System.out.println("mode: "+z.istate.mode); switch (z.istate.mode) { case METHOD: if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; if (((z.istate.method = z.next_in[z.next_in_index++]) & 0xf) != Z_DEFLATED) { z.istate.mode = BAD; z.msg = "unknown compression method"; z.istate.marker = 5; // can't try inflateSync break; } if ((z.istate.method >> 4) + 8 > z.istate.wbits) { z.istate.mode = BAD; z.msg = "invalid window size"; z.istate.marker = 5; // can't try inflateSync break; } z.istate.mode = FLAG; goto case FLAG; case FLAG: if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; b = (z.next_in[z.next_in_index++]) & 0xff; if ((((z.istate.method << 8) + b) % 31) != 0) { z.istate.mode = BAD; z.msg = "incorrect header check"; z.istate.marker = 5; // can't try inflateSync break; } if ((b & PRESET_DICT) == 0) { z.istate.mode = BLOCKS; break; } z.istate.mode = DICT4; goto case DICT4; case DICT4: if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & unchecked ((int)0xff000000L); z.istate.mode = DICT3; goto case DICT3; case DICT3: if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; z.istate.need += (((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L); z.istate.mode = DICT2; goto case DICT2; case DICT2: if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; z.istate.need += (((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L); z.istate.mode = DICT1; goto case DICT1; case DICT1: if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; z.istate.need += (z.next_in[z.next_in_index++] & 0xffL); z.adler = z.istate.need; z.istate.mode = DICT0; return(Z_NEED_DICT); case DICT0: z.istate.mode = BAD; z.msg = "need dictionary"; z.istate.marker = 0; // can try inflateSync return(Z_STREAM_ERROR); case BLOCKS: r = z.istate.blocks.proc(z, r); if (r == Z_DATA_ERROR) { z.istate.mode = BAD; z.istate.marker = 0; // can try inflateSync break; } if (r == Z_OK) { r = f; } if (r != Z_STREAM_END) { return(r); } r = f; z.istate.blocks.reset(z, z.istate.was); if (z.istate.nowrap != 0) { z.istate.mode = DONE; break; } z.istate.mode = CHECK4; goto case CHECK4; case CHECK4: if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & unchecked ((int)0xff000000L); z.istate.mode = CHECK3; goto case CHECK3; case CHECK3: if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; z.istate.need += (((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L); z.istate.mode = CHECK2; goto case CHECK2; case CHECK2: if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; z.istate.need += (((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L); z.istate.mode = CHECK1; goto case CHECK1; case CHECK1: if (z.avail_in == 0) { return(r); } r = f; z.avail_in--; z.total_in++; z.istate.need += (z.next_in[z.next_in_index++] & 0xffL); if (((int)(z.istate.was[0])) != ((int)(z.istate.need))) { z.istate.mode = BAD; z.msg = "incorrect data check"; z.istate.marker = 5; // can't try inflateSync break; } z.istate.mode = DONE; goto case DONE; case DONE: return(Z_STREAM_END); case BAD: return(Z_DATA_ERROR); default: return(Z_STREAM_ERROR); } } }
// 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 inflate_fast(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, InfBlocks s, ZStream 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 // load input, output, bit values p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk; q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; // initialize masks ml = inflate_mask[bl]; md = inflate_mask[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.next_in[p++] & 0xff) << k; k += 8; } t = b & ml; tp = tl; tp_index = tl_index; 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 & inflate_mask[e]); b >>= e; k -= e; // decode distance base of block to copy while (k < (15)) { // max bits for distance code n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } t = b & md; tp = td; tp_index = td_index; 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.next_in[p++] & 0xff) << k; k += 8; } d = tp[(tp_index + t) * 3 + 2] + (b & inflate_mask[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++]; c--; // minimum count is three, s.window[q++] = s.window[r++]; c--; // so unroll loop a little } 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 & inflate_mask[e]); e = tp[(tp_index + t) * 3]; } else { z.msg = "invalid distance code"; c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3); s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return Z_DATA_ERROR; } } while (true); break; } if ((e & 64) == 0) { t += tp[(tp_index + t) * 3 + 2]; t += (b & inflate_mask[e]); 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.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3); s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return Z_STREAM_END; } else { z.msg = "invalid literal/length code"; c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3); s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return Z_DATA_ERROR; } } while (true); } while (m >= 258 && n >= 10); // not enough input or output--restore pointers and return c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3); s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return Z_OK; }
// copy as much as possible from the sliding window to the output area internal int inflate_flush(ZStream z, int r) { int n; int p; int q; // local copies of source and destination pointers p = z.next_out_index; q = read; // compute number of bytes to copy as far as end of window n = (int)((q <= write?write:end) - q); if (n > z.avail_out) { n = z.avail_out; } if (n != 0 && r == Z_BUF_ERROR) { r = Z_OK; } // update counters z.avail_out -= n; z.total_out += n; // update check information if (checkfn != null) { z.adler = check = z._adler.adler32(check, window, q, n); } // copy as far as end of window Array.Copy(window, q, z.next_out, p, n); p += n; q += n; // see if more to copy at beginning of window if (q == end) { // wrap pointers q = 0; if (write == end) { write = 0; } // compute bytes to copy n = write - q; if (n > z.avail_out) { n = z.avail_out; } if (n != 0 && r == Z_BUF_ERROR) { r = Z_OK; } // update counters z.avail_out -= n; z.total_out += n; // update check information if (checkfn != null) { z.adler = check = z._adler.adler32(check, window, q, n); } // copy Array.Copy(window, q, z.next_out, p, n); p += n; q += n; } // update pointers z.next_out_index = p; read = q; // done return(r); }
internal int proc(ZStream z, 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 = z.next_in_index; n = z.avail_in; b = bitb; k = bitk; } { q = write; m = (int)(q < read?read - q - 1:end - q); } // process input based on current state while (true) { switch (mode) { case TYPE: while (k < (3)) { if (n != 0) { r = Z_OK; } else { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } t = (int)(b & 7); last = t & 1; switch (SupportClass.URShift(t, 1)) { case 0: // stored { b = SupportClass.URShift(b, (3)); k -= (3); } t = k & 7; // go to byte boundary { b = SupportClass.URShift(b, (t)); k -= (t); } mode = 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, z); codes = new InfCodes(bl[0], bd[0], tl[0], td[0], z); } { b = SupportClass.URShift(b, (3)); k -= (3); } mode = CODES; break; case 2: // dynamic { b = SupportClass.URShift(b, (3)); k -= (3); } mode = TABLE; break; case 3: // illegal { b = SupportClass.URShift(b, (3)); k -= (3); } mode = BAD; z.msg = "invalid block type"; r = Z_DATA_ERROR; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } break; case LENS: while (k < (32)) { if (n != 0) { r = Z_OK; } else { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } if (((SupportClass.URShift((~b), 16)) & 0xffff) != (b & 0xffff)) { mode = BAD; z.msg = "invalid stored block lengths"; r = Z_DATA_ERROR; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } left = (b & 0xffff); b = k = 0; // dump bits mode = left != 0?STORED:(last != 0?DRY:TYPE); break; case STORED: if (n == 0) { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } if (m == 0) { if (q == end && read != 0) { q = 0; m = (int)(q < read?read - q - 1:end - q); } if (m == 0) { write = q; r = inflate_flush(z, r); q = write; m = (int)(q < read?read - q - 1:end - q); if (q == end && read != 0) { q = 0; m = (int)(q < read?read - q - 1:end - q); } if (m == 0) { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } } } r = Z_OK; t = left; if (t > n) { t = n; } if (t > m) { t = m; } Array.Copy(z.next_in, p, window, q, t); p += t; n -= t; q += t; m -= t; if ((left -= t) != 0) { break; } mode = last != 0?DRY:TYPE; break; case TABLE: while (k < (14)) { if (n != 0) { r = Z_OK; } else { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } table = t = (b & 0x3fff); if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) { mode = BAD; z.msg = "too many length or distance symbols"; r = Z_DATA_ERROR; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); blens = new int[t]; { b = SupportClass.URShift(b, (14)); k -= (14); } index = 0; mode = BTREE; goto case BTREE; case BTREE: while (index < 4 + (SupportClass.URShift(table, 10))) { while (k < (3)) { if (n != 0) { r = Z_OK; } else { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } blens[border[index++]] = b & 7; { b = SupportClass.URShift(b, (3)); k -= (3); } } while (index < 19) { blens[border[index++]] = 0; } bb[0] = 7; t = InfTree.inflate_trees_bits(blens, bb, tb, hufts, z); if (t != Z_OK) { r = t; if (r == Z_DATA_ERROR) { blens = null; mode = BAD; } bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } index = 0; mode = DTREE; goto case DTREE; case 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 = Z_OK; } else { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } if (tb[0] == -1) { //System.err.println("null..."); } t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1]; c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2]; if (c < 16) { b = SupportClass.URShift(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 = Z_OK; } else { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } b = SupportClass.URShift(b, (t)); k -= (t); j += (b & inflate_mask[i]); b = SupportClass.URShift(b, (i)); k -= (i); i = index; t = table; if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1)) { blens = null; mode = BAD; z.msg = "invalid bit length repeat"; r = Z_DATA_ERROR; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } c = c == 16?blens[i - 1]:0; do { blens[i++] = c; }while (--j != 0); index = i; } } tb[0] = -1; { int[] bl = new int[1]; int[] bd = new int[1]; int[] tl = new int[1]; int[] td = new int[1]; bl[0] = 9; // must be <= 9 for lookahead assumptions bd[0] = 6; // must be <= 9 for lookahead assumptions t = table; t = InfTree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl, bd, tl, td, hufts, z); if (t != Z_OK) { if (t == Z_DATA_ERROR) { blens = null; mode = BAD; } r = t; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } codes = new InfCodes(bl[0], bd[0], hufts, tl[0], hufts, td[0], z); } blens = null; mode = CODES; goto case CODES; case CODES: bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; if ((r = codes.proc(this, z, r)) != Z_STREAM_END) { return(inflate_flush(z, r)); } r = Z_OK; codes.free(z); p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk; q = write; m = (int)(q < read?read - q - 1:end - q); if (last == 0) { mode = TYPE; break; } mode = DRY; goto case DRY; case DRY: write = q; r = inflate_flush(z, r); q = write; m = (int)(q < read?read - q - 1:end - q); if (read != write) { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } mode = DONE; goto case DONE; case DONE: r = Z_STREAM_END; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); case BAD: r = Z_DATA_ERROR; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); default: r = Z_STREAM_ERROR; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return(inflate_flush(z, r)); } } }
internal InfCodes(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, ZStream z) { this.mode = 0; this.lbits = (byte)bl; this.dbits = (byte)bd; this.ltree = tl; this.ltree_index = tl_index; this.dtree = td; this.dtree_index = td_index; }
internal int inflate_fast(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, InfBlocks s, ZStream z) { int num = z.next_in_index; int num2 = z.avail_in; int num3 = s.bitb; int i = s.bitk; int num4 = s.write; int num5 = (num4 < s.read) ? (s.read - num4 - 1) : (s.end - num4); int num6 = InfCodes.inflate_mask[bl]; int num7 = InfCodes.inflate_mask[bd]; int num9; int num10; while (true) { if (i >= 20) { int num8 = num3 & num6; if ((num9 = tl[(tl_index + num8) * 3]) == 0) { num3 >>= tl[(tl_index + num8) * 3 + 1]; i -= tl[(tl_index + num8) * 3 + 1]; s.window[num4++] = (byte)tl[(tl_index + num8) * 3 + 2]; num5--; } else { while (true) { num3 >>= tl[(tl_index + num8) * 3 + 1]; i -= tl[(tl_index + num8) * 3 + 1]; if ((num9 & 16) != 0) { break; } if ((num9 & 64) != 0) { goto IL_4D3; } num8 += tl[(tl_index + num8) * 3 + 2]; num8 += (num3 & InfCodes.inflate_mask[num9]); if ((num9 = tl[(tl_index + num8) * 3]) == 0) { goto Block_20; } } num9 &= 15; num10 = tl[(tl_index + num8) * 3 + 2] + (num3 & InfCodes.inflate_mask[num9]); num3 >>= num9; for (i -= num9; i < 15; i += 8) { num2--; num3 |= (int)(z.next_in[num++] & 255) << i; } num8 = (num3 & num7); num9 = td[(td_index + num8) * 3]; while (true) { num3 >>= td[(td_index + num8) * 3 + 1]; i -= td[(td_index + num8) * 3 + 1]; if ((num9 & 16) != 0) { break; } if ((num9 & 64) != 0) { goto IL_3D9; } num8 += td[(td_index + num8) * 3 + 2]; num8 += (num3 & InfCodes.inflate_mask[num9]); num9 = td[(td_index + num8) * 3]; } num9 &= 15; while (i < num9) { num2--; num3 |= (int)(z.next_in[num++] & 255) << i; i += 8; } int num11 = td[(td_index + num8) * 3 + 2] + (num3 & InfCodes.inflate_mask[num9]); num3 >>= num9; i -= num9; num5 -= num10; int num12; if (num4 >= num11) { num12 = num4 - num11; if (num4 - num12 > 0 && 2 > num4 - num12) { s.window[num4++] = s.window[num12++]; num10--; s.window[num4++] = s.window[num12++]; num10--; } else { Array.Copy(s.window, num12, s.window, num4, 2); num4 += 2; num12 += 2; num10 -= 2; } } else { num12 = num4 - num11; do { num12 += s.end; }while (num12 < 0); num9 = s.end - num12; if (num10 > num9) { num10 -= num9; if (num4 - num12 > 0 && num9 > num4 - num12) { do { s.window[num4++] = s.window[num12++]; }while (--num9 != 0); } else { Array.Copy(s.window, num12, s.window, num4, num9); num4 += num9; num12 += num9; } num12 = 0; } } if (num4 - num12 > 0 && num10 > num4 - num12) { do { s.window[num4++] = s.window[num12++]; }while (--num10 != 0); goto IL_5E0; } Array.Copy(s.window, num12, s.window, num4, num10); num4 += num10; num12 += num10; goto IL_5E0; Block_20: num3 >>= tl[(tl_index + num8) * 3 + 1]; i -= tl[(tl_index + num8) * 3 + 1]; s.window[num4++] = (byte)tl[(tl_index + num8) * 3 + 2]; num5--; } IL_5E0: if (num5 < 258 || num2 < 10) { goto IL_5F2; } } else { num2--; num3 |= (int)(z.next_in[num++] & 255) << i; i += 8; } } IL_3D9: z.msg = "invalid distance code"; num10 = z.avail_in - num2; num10 = ((i >> 3 < num10) ? (i >> 3) : num10); num2 += num10; num -= num10; i -= num10 << 3; s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(-3); IL_4D3: if ((num9 & 32) != 0) { num10 = z.avail_in - num2; num10 = ((i >> 3 < num10) ? (i >> 3) : num10); num2 += num10; num -= num10; i -= num10 << 3; s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(1); } z.msg = "invalid literal/length code"; num10 = z.avail_in - num2; num10 = ((i >> 3 < num10) ? (i >> 3) : num10); num2 += num10; num -= num10; i -= num10 << 3; s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(-3); IL_5F2: num10 = z.avail_in - num2; num10 = ((i >> 3 < num10) ? (i >> 3) : num10); num2 += num10; num -= num10; i -= num10 << 3; s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(0); }
internal void free(ZStream z) { }
internal int proc(InfBlocks s, ZStream z, int r) { int num = z.next_in_index; int num2 = z.avail_in; int num3 = s.bitb; int i = s.bitk; int num4 = s.write; int num5 = (num4 < s.read) ? (s.read - num4 - 1) : (s.end - num4); while (true) { int num6; switch (this.mode) { case 0: if (num5 >= 258 && num2 >= 10) { s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; r = this.inflate_fast((int)this.lbits, (int)this.dbits, this.ltree, this.ltree_index, this.dtree, this.dtree_index, s, z); num = z.next_in_index; num2 = z.avail_in; num3 = s.bitb; i = s.bitk; num4 = s.write; num5 = ((num4 < s.read) ? (s.read - num4 - 1) : (s.end - num4)); if (r != 0) { this.mode = ((r == 1) ? 7 : 9); continue; } } this.need = (int)this.lbits; this.tree = this.ltree; this.tree_index = this.ltree_index; this.mode = 1; goto IL_199; case 1: goto IL_199; case 2: num6 = this.get_Renamed; while (i < num6) { if (num2 == 0) { goto IL_34F; } r = 0; num2--; num3 |= (int)(z.next_in[num++] & 255) << i; i += 8; } this.len += (num3 & InfCodes.inflate_mask[num6]); num3 >>= num6; i -= num6; this.need = (int)this.dbits; this.tree = this.dtree; this.tree_index = this.dtree_index; this.mode = 3; goto IL_412; case 3: goto IL_412; case 4: num6 = this.get_Renamed; while (i < num6) { if (num2 == 0) { goto IL_596; } r = 0; num2--; num3 |= (int)(z.next_in[num++] & 255) << i; i += 8; } this.dist += (num3 & InfCodes.inflate_mask[num6]); num3 >>= num6; i -= num6; this.mode = 5; goto IL_635; case 5: goto IL_635; case 6: if (num5 == 0) { if (num4 == s.end && s.read != 0) { num4 = 0; num5 = ((num4 < s.read) ? (s.read - num4 - 1) : (s.end - num4)); } if (num5 == 0) { s.write = num4; r = s.inflate_flush(z, r); num4 = s.write; num5 = ((num4 < s.read) ? (s.read - num4 - 1) : (s.end - num4)); if (num4 == s.end && s.read != 0) { num4 = 0; num5 = ((num4 < s.read) ? (s.read - num4 - 1) : (s.end - num4)); } if (num5 == 0) { goto Block_44; } } } r = 0; s.window[num4++] = (byte)this.lit; num5--; this.mode = 0; continue; case 7: goto IL_8DB; case 8: goto IL_98A; case 9: goto IL_9D4; } break; IL_199: num6 = this.need; while (i < num6) { if (num2 == 0) { goto IL_1AB; } r = 0; num2--; num3 |= (int)(z.next_in[num++] & 255) << i; i += 8; } int num7 = (this.tree_index + (num3 & InfCodes.inflate_mask[num6])) * 3; num3 = SupportClass.URShift(num3, this.tree[num7 + 1]); i -= this.tree[num7 + 1]; int num8 = this.tree[num7]; if (num8 == 0) { this.lit = this.tree[num7 + 2]; this.mode = 6; continue; } if ((num8 & 16) != 0) { this.get_Renamed = (num8 & 15); this.len = this.tree[num7 + 2]; this.mode = 2; continue; } if ((num8 & 64) == 0) { this.need = num8; this.tree_index = num7 / 3 + this.tree[num7 + 2]; continue; } if ((num8 & 32) != 0) { this.mode = 7; continue; } goto IL_2DF; IL_412: num6 = this.need; while (i < num6) { if (num2 == 0) { goto IL_424; } r = 0; num2--; num3 |= (int)(z.next_in[num++] & 255) << i; i += 8; } num7 = (this.tree_index + (num3 & InfCodes.inflate_mask[num6])) * 3; num3 >>= this.tree[num7 + 1]; i -= this.tree[num7 + 1]; num8 = this.tree[num7]; if ((num8 & 16) != 0) { this.get_Renamed = (num8 & 15); this.dist = this.tree[num7 + 2]; this.mode = 4; continue; } if ((num8 & 64) == 0) { this.need = num8; this.tree_index = num7 / 3 + this.tree[num7 + 2]; continue; } goto IL_526; IL_635: int j; for (j = num4 - this.dist; j < 0; j += s.end) { } while (this.len != 0) { if (num5 == 0) { if (num4 == s.end && s.read != 0) { num4 = 0; num5 = ((num4 < s.read) ? (s.read - num4 - 1) : (s.end - num4)); } if (num5 == 0) { s.write = num4; r = s.inflate_flush(z, r); num4 = s.write; num5 = ((num4 < s.read) ? (s.read - num4 - 1) : (s.end - num4)); if (num4 == s.end && s.read != 0) { num4 = 0; num5 = ((num4 < s.read) ? (s.read - num4 - 1) : (s.end - num4)); } if (num5 == 0) { goto Block_32; } } } s.window[num4++] = s.window[j++]; num5--; if (j == s.end) { j = 0; } this.len--; } this.mode = 0; } r = -2; s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(s.inflate_flush(z, r)); IL_1AB: s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(s.inflate_flush(z, r)); IL_2DF: this.mode = 9; z.msg = "invalid literal/length code"; r = -3; s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(s.inflate_flush(z, r)); IL_34F: s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(s.inflate_flush(z, r)); IL_424: s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(s.inflate_flush(z, r)); IL_526: this.mode = 9; z.msg = "invalid distance code"; r = -3; s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(s.inflate_flush(z, r)); IL_596: s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(s.inflate_flush(z, r)); Block_32: s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(s.inflate_flush(z, r)); Block_44: s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(s.inflate_flush(z, r)); IL_8DB: if (i > 7) { i -= 8; num2++; num--; } s.write = num4; r = s.inflate_flush(z, r); num4 = s.write; int arg_92C_0 = (num4 < s.read) ? (s.read - num4 - 1) : (s.end - num4); if (s.read != s.write) { s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(s.inflate_flush(z, r)); } this.mode = 8; IL_98A: r = 1; s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(s.inflate_flush(z, r)); IL_9D4: r = -3; s.bitb = num3; s.bitk = i; z.avail_in = num2; z.total_in += (long)(num - z.next_in_index); z.next_in_index = num; s.write = num4; return(s.inflate_flush(z, r)); }
IEnumerable<WebSocketsFrame> IExtension.ApplyOutgoing(NetContext context, WebSocketConnection connection, WebSocketsFrame frame) { if (!frame.IsControlFrame && frame.PayloadLength > parent.compressMessagesLargerThanBytes) { if (frame.Reserved1) { throw new InvalidOperationException("Reserved1 flag is already set; extension conflict?"); } int headerBytes = 0; if (outbound == null) { outbound = new ZStream(); const int BITS = 12; // 4096 byte outbound buffer (instead of full 32k=15) outbound.deflateInit(zlibConst.Z_BEST_COMPRESSION, BITS); headerBytes = 2; } BufferStream tmp = null; var payload = frame.Payload; payload.Position = 0; byte[] inBuffer = null, outBuffer = null; try { inBuffer = context.GetBuffer(); outBuffer = context.GetBuffer(); tmp = new BufferStream(context, 0); outbound.next_out = outBuffer; outbound.next_in = inBuffer; int remaining = frame.PayloadLength; while (remaining > 0) { int readCount = payload.Read(inBuffer, 0, inBuffer.Length); if (readCount <= 0) break; remaining -= readCount; outbound.next_in_index = 0; outbound.avail_in = readCount; do { outbound.next_out_index = 0; outbound.avail_out = outBuffer.Length; long priorOut = outbound.total_out; int err = outbound.deflate(remaining == 0 ? zlibConst.Z_SYNC_FLUSH : zlibConst.Z_NO_FLUSH); if (err != zlibConst.Z_OK && err != zlibConst.Z_STREAM_END) throw new ZStreamException("deflating: " + outbound.msg); int outCount = (int)(outbound.total_out - priorOut); if (outCount > 0) { if (headerBytes == 0) { tmp.Write(outBuffer, 0, outCount); } else { if (outCount < headerBytes) { throw new InvalidOperationException("Failed to write entire header"); } // check the generated header meets our expectations // CMF is very specific - CM must be 8, and CINFO must be <=7 (for 32k window) if ((outBuffer[0] & 15) != 8) { throw new InvalidOperationException("Zlib CM header was incorrect"); } if ((outBuffer[0] & 128) != 0) // if msb set, is > 7 - invalid { throw new InvalidOperationException("Zlib CINFO header was incorrect"); } // FLG is less important; FCHECK is irrelevent, FLEVEL doesn't matter; but // FDICT must be zero, to ensure that we aren't expecting a an initialization dictionary if ((outBuffer[1] & 32) != 0) { throw new InvalidOperationException("Zlib FLG.FDICT header was set (must not be)"); } // skip the header, and write anything else outCount -= headerBytes; if (outCount > 0) { tmp.Write(outBuffer, headerBytes, outCount); } headerBytes = 0; // all written now } } } while (outbound.avail_in > 0 || outbound.avail_out == 0); } if (remaining != 0) throw new EndOfStreamException(); if (headerBytes != 0) throw new InvalidOperationException("Zlib header was not written"); // verify the last 4 bytes, then drop them tmp.Position = tmp.Length - 4; NetContext.Fill(tmp, outBuffer, 4); if (!(outBuffer[0] == 0x00 && outBuffer[1] == 0x00 && outBuffer[2] == 0xFF && outBuffer[3] == 0xFF)) { throw new InvalidOperationException("expectation failed: 0000FFFF in the tail"); } if (parent.disableContextTakeover && tmp.Length >= frame.PayloadLength) { // compressing it didn't do anything useful; since we're going to discard // the compression context, we might as well stick with the original data payload.Position = 0; payload = null; // so that it doesn't get disposed } else { // set our final output tmp.Position = 0; tmp.SetLength(tmp.Length - 4); long bytesSaved = frame.PayloadLength - tmp.Length; frame.Payload = tmp; frame.PayloadLength = (int)tmp.Length; frame.Reserved1 = true; tmp = payload as BufferStream; parent.RegisterOutboundBytesSaved(bytesSaved); } } #if DEBUG catch (Exception ex) { Debug.WriteLine(ex); throw; } #endif finally { if (outbound != null) { outbound.next_out = null; outbound.next_in = null; } if (tmp != null) tmp.Dispose(); if (inBuffer != null) context.Recycle(inBuffer); if (outBuffer != null) context.Recycle(outBuffer); if (parent.disableContextTakeover) ClearContext(false, true); } } yield return frame; }
IEnumerable<WebSocketsFrame> IExtension.ApplyIncoming(NetContext context, WebSocketConnection connection, WebSocketsFrame frame) { if (frame.Reserved1 && !frame.IsControlFrame) { BufferStream tmp = null; var payload = frame.Payload; payload.Position = 0; byte[] inBuffer = null, outBuffer = null; try { outBuffer = context.GetBuffer(); inBuffer = context.GetBuffer(); tmp = new BufferStream(context, 0); if (inbound == null) { inbound = new ZStream(); inbound.inflateInit(); // fake a zlib header with: // CMF: // CM = 8 (deflate) // CINFO = 7 (32k window) // FLG: // FCHECK: 26 (checksum of other bits) // FDICT: 0 (no dictionary) // FLEVEL: 3 (maximum) inBuffer[0] = 120; inBuffer[1] = 218; inbound.next_in = inBuffer; int chk = Inflate(tmp, outBuffer, 2); if (chk != 0) throw new InvalidOperationException("Spoofed zlib header suggested data"); } inbound.next_in = inBuffer; int remaining = frame.PayloadLength; //bool first = true; while (remaining > 0) { int readCount = payload.Read(inBuffer, 0, inBuffer.Length); if (readCount <= 0) break; remaining -= readCount; //if (first) //{ // kill the BFINAL flag from the first block, if set; we don't want zlib // // trying to verify the ADLER checksum; unfortunately, a frame can contain // // multiple blocks, and a *later* block could have BFINAL set. That sucks. // inBuffer[0] &= 254; // first = false; //} Inflate(tmp, outBuffer, readCount); } if (remaining != 0) throw new EndOfStreamException(); // spoof the missing 4 bytes from the tail inBuffer[0] = inBuffer[1] = 0x00; inBuffer[2] = inBuffer[3] = 0xFF; Inflate(tmp, outBuffer, 4); // set our final output tmp.Position = 0; frame.Payload = tmp; long bytesSaved = tmp.Length - frame.PayloadLength; frame.PayloadLength = (int)tmp.Length; frame.Reserved1 = false; tmp = payload as BufferStream; parent.RegisterInboundBytesSaved(bytesSaved); } #if DEBUG catch (Exception ex) { Debug.WriteLine(ex); throw; } #endif finally { if (inbound != null) { inbound.next_out = null; inbound.next_in = null; } if (tmp != null) tmp.Dispose(); if (inBuffer != null) context.Recycle(inBuffer); if (outBuffer != null) context.Recycle(outBuffer); if (parent.disableContextTakeover) ClearContext(true, false); } } yield return frame; }
internal static int inflate_trees_bits(int[] c, int[] bb, int[] tb, int[] hp, ZStream z) { int r; int[] hn = new int[1]; // hufts used in space int[] v = new int[19]; // work area for huft_build r = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v); if (r == Z_DATA_ERROR) { z.msg = "oversubscribed dynamic bit lengths tree"; } else if (r == Z_BUF_ERROR || bb[0] == 0) { z.msg = "incomplete dynamic bit lengths tree"; r = Z_DATA_ERROR; } return(r); }
internal static int inflate_trees_dynamic(int nl, int nd, int[] c, int[] bl, int[] bd, int[] tl, int[] td, int[] hp, ZStream z) { int[] hn = new int[1]; int[] v = new int[288]; int num = InfTree.huft_build(c, 0, nl, 257, InfTree.cplens, InfTree.cplext, tl, bl, hp, hn, v); if (num != 0 || bl[0] == 0) { if (num == -3) { z.msg = "oversubscribed literal/length tree"; } else { if (num != -4) { z.msg = "incomplete literal/length tree"; num = -3; } } return(num); } num = InfTree.huft_build(c, nl, nd, 0, InfTree.cpdist, InfTree.cpdext, td, bd, hp, hn, v); if (num != 0 || (bd[0] == 0 && nl > 257)) { if (num == -3) { z.msg = "oversubscribed distance tree"; } else { if (num == -5) { z.msg = "incomplete distance tree"; num = -3; } else { if (num != -4) { z.msg = "empty distance tree with lengths"; num = -3; } } } return(num); } return(0); }
internal int inflate(ZStream z, int f) { if (z == null || z.istate == null || z.next_in == null) { return(-2); } f = ((f == 4) ? -5 : 0); int num = -5; while (true) { switch (z.istate.mode) { case 0: if (z.avail_in == 0) { return(num); } num = f; z.avail_in--; z.total_in += 1L; if (((z.istate.method = (int)z.next_in[z.next_in_index++]) & 15) != 8) { z.istate.mode = 13; z.msg = "unknown compression method"; z.istate.marker = 5; continue; } if ((z.istate.method >> 4) + 8 > z.istate.wbits) { z.istate.mode = 13; z.msg = "invalid window size"; z.istate.marker = 5; continue; } z.istate.mode = 1; goto IL_144; case 1: goto IL_144; case 2: goto IL_1EE; case 3: goto IL_258; case 4: goto IL_2CA; case 5: goto IL_33B; case 6: goto IL_3B7; case 7: num = z.istate.blocks.proc(z, num); if (num == -3) { z.istate.mode = 13; z.istate.marker = 0; continue; } if (num == 0) { num = f; } if (num != 1) { return(num); } num = f; z.istate.blocks.reset(z, z.istate.was); if (z.istate.nowrap != 0) { z.istate.mode = 12; continue; } z.istate.mode = 8; goto IL_468; case 8: goto IL_468; case 9: goto IL_4D3; case 10: goto IL_546; case 11: goto IL_5B8; case 12: return(1); case 13: return(-3); } break; IL_144: if (z.avail_in == 0) { return(num); } num = f; z.avail_in--; z.total_in += 1L; int num2 = (int)(z.next_in[z.next_in_index++] & 255); if (((z.istate.method << 8) + num2) % 31 != 0) { z.istate.mode = 13; z.msg = "incorrect header check"; z.istate.marker = 5; continue; } if ((num2 & 32) == 0) { z.istate.mode = 7; continue; } goto IL_1E2; IL_5B8: if (z.avail_in == 0) { return(num); } num = f; z.avail_in--; z.total_in += 1L; z.istate.need += (long)((ulong)z.next_in[z.next_in_index++] & 255uL); if ((int)z.istate.was[0] != (int)z.istate.need) { z.istate.mode = 13; z.msg = "incorrect data check"; z.istate.marker = 5; continue; } goto IL_65A; IL_546: if (z.avail_in == 0) { return(num); } num = f; z.avail_in--; z.total_in += 1L; z.istate.need += ((long)((long)(z.next_in[z.next_in_index++] & 255) << 8) & 65280L); z.istate.mode = 11; goto IL_5B8; IL_4D3: if (z.avail_in == 0) { return(num); } num = f; z.avail_in--; z.total_in += 1L; z.istate.need += ((long)((long)(z.next_in[z.next_in_index++] & 255) << 16) & 16711680L); z.istate.mode = 10; goto IL_546; IL_468: if (z.avail_in == 0) { return(num); } num = f; z.avail_in--; z.total_in += 1L; z.istate.need = (long)((int)(z.next_in[z.next_in_index++] & 255) << 24 & -16777216); z.istate.mode = 9; goto IL_4D3; } return(-2); IL_1E2: z.istate.mode = 2; IL_1EE: if (z.avail_in == 0) { return(num); } num = f; z.avail_in--; z.total_in += 1L; z.istate.need = (long)((int)(z.next_in[z.next_in_index++] & 255) << 24 & -16777216); z.istate.mode = 3; IL_258: if (z.avail_in == 0) { return(num); } num = f; z.avail_in--; z.total_in += 1L; z.istate.need += ((long)((long)(z.next_in[z.next_in_index++] & 255) << 16) & 16711680L); z.istate.mode = 4; IL_2CA: if (z.avail_in == 0) { return(num); } num = f; z.avail_in--; z.total_in += 1L; z.istate.need += ((long)((long)(z.next_in[z.next_in_index++] & 255) << 8) & 65280L); z.istate.mode = 5; IL_33B: if (z.avail_in == 0) { return(num); } z.avail_in--; z.total_in += 1L; z.istate.need += (long)((ulong)z.next_in[z.next_in_index++] & 255uL); z.adler = z.istate.need; z.istate.mode = 6; return(2); IL_3B7: z.istate.mode = 13; z.msg = "need dictionary"; z.istate.marker = 0; return(-2); IL_65A: z.istate.mode = 12; return(1); }
public virtual void end() { if (compress) { z.deflateEnd(); } else { z.inflateEnd(); } z.free(); z = null; }
internal static int inflate_trees_dynamic(int nl, int nd, int[] c, int[] bl, int[] bd, int[] tl, int[] td, int[] hp, ZStream z) { int r; int[] hn = new int[1]; // hufts used in space int[] v = new int[288]; // work area for huft_build // build literal/length tree r = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v); if (r != Z_OK || bl[0] == 0) { if (r == Z_DATA_ERROR) { z.msg = "oversubscribed literal/length tree"; } else if (r != Z_MEM_ERROR) { z.msg = "incomplete literal/length tree"; r = Z_DATA_ERROR; } return(r); } // build distance tree r = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v); if (r != Z_OK || (bd[0] == 0 && nl > 257)) { if (r == Z_DATA_ERROR) { z.msg = "oversubscribed distance tree"; } else if (r == Z_BUF_ERROR) { z.msg = "incomplete distance tree"; r = Z_DATA_ERROR; } else if (r != Z_MEM_ERROR) { z.msg = "empty distance tree with lengths"; r = Z_DATA_ERROR; } return(r); } return(Z_OK); }
internal static int inflate_trees_fixed(int[] bl, int[] bd, int[][] tl, int[][] td, ZStream z) { bl[0] = 9; bd[0] = 5; tl[0] = InfTree.fixed_tl; td[0] = InfTree.fixed_td; return(0); }
// copy as much as possible from the sliding window to the output area internal int inflate_flush(ZStream z, int r) { int n; int p; int q; // local copies of source and destination pointers p = z.next_out_index; q = read; // compute number of bytes to copy as far as end of window n = (int) ((q <= write?write:end) - q); if (n > z.avail_out) n = z.avail_out; if (n != 0 && r == Z_BUF_ERROR) r = Z_OK; // update counters z.avail_out -= n; z.total_out += n; // update check information if (checkfn != null) z.adler = check = z._adler.adler32(check, window, q, n); // copy as far as end of window Array.Copy(window, q, z.next_out, p, n); p += n; q += n; // see if more to copy at beginning of window if (q == end) { // wrap pointers q = 0; if (write == end) write = 0; // compute bytes to copy n = write - q; if (n > z.avail_out) n = z.avail_out; if (n != 0 && r == Z_BUF_ERROR) r = Z_OK; // update counters z.avail_out -= n; z.total_out += n; // update check information if (checkfn != null) z.adler = check = z._adler.adler32(check, window, q, n); // copy Array.Copy(window, q, z.next_out, p, n); p += n; q += n; } // update pointers z.next_out_index = p; read = q; // done return r; }
internal int deflateSetDictionary(ZStream strm, byte[] dictionary, int dictLength) { int num1 = dictLength; int num2 = 0; if ((dictionary == null) || (this.status != 0x2a)) { return -2; } strm.adler = strm._adler.adler32(strm.adler, dictionary, 0, dictLength); if (num1 >= 3) { if (num1 > (this.w_size - Deflate.MIN_LOOKAHEAD)) { num1 = this.w_size - Deflate.MIN_LOOKAHEAD; num2 = dictLength - num1; } Array.Copy(dictionary, num2, this.window, 0, num1); this.strstart = num1; this.block_start = num1; this.ins_h = this.window[0] & 0xff; this.ins_h = ((this.ins_h << (this.hash_shift & 0x1f)) ^ (this.window[1] & 0xff)) & this.hash_mask; for (int num3 = 0; num3 <= (num1 - 3); num3++) { this.ins_h = ((this.ins_h << (this.hash_shift & 0x1f)) ^ (this.window[num3 + 2] & 0xff)) & this.hash_mask; this.prev[num3 & this.w_mask] = this.head[this.ins_h]; this.head[this.ins_h] = (short) num3; } } return 0; }
internal int deflateInit(ZStream strm, int level, int bits) { return deflateInit2(strm, level, Z_DEFLATED, bits, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); }
internal void free(ZStream z) { reset(z, null); window = null; hufts = null; //ZFREE(z, s); }
internal int deflate(ZStream strm, int flush) { if ((flush > 4) || (flush < 0)) { return(-2); } if (((strm.next_out == null) || ((strm.next_in == null) && (strm.avail_in != 0))) || ((this.status == 0x29a) && (flush != 4))) { strm.msg = Deflate.z_errmsg[4]; return(-2); } if (strm.avail_out == 0) { strm.msg = Deflate.z_errmsg[7]; return(-5); } this.strm = strm; int num1 = this.last_flush; this.last_flush = flush; if (this.status == 0x2a) { int num2 = (8 + ((this.w_bits - 8) << 4)) << 8; int num3 = ((this.level - 1) & 0xff) >> 1; if (num3 > 3) { num3 = 3; } num2 |= num3 << 6; if (this.strstart != 0) { num2 |= 0x20; } num2 += 0x1f - (num2 % 0x1f); this.status = 0x71; this.putShortMSB(num2); if (this.strstart != 0) { this.putShortMSB((int)SupportClass.URShift(strm.adler, 0x10)); this.putShortMSB(((int)strm.adler) & 0xffff); } strm.adler = strm._adler.adler32((long)0, null, 0, 0); } if (this.pending != 0) { strm.flush_pending(); if (strm.avail_out == 0) { this.last_flush = -1; return(0); } } else if (((strm.avail_in == 0) && (flush <= num1)) && (flush != 4)) { strm.msg = Deflate.z_errmsg[7]; return(-5); } if ((this.status == 0x29a) && (strm.avail_in != 0)) { strm.msg = Deflate.z_errmsg[7]; return(-5); } if (((strm.avail_in != 0) || (this.lookahead != 0)) || ((flush != 0) && (this.status != 0x29a))) { int num4 = -1; switch (Deflate.config_table[this.level].func) { case 0: num4 = this.deflate_stored(flush); break; case 1: num4 = this.deflate_fast(flush); break; case 2: num4 = this.deflate_slow(flush); break; } switch (num4) { case 2: case 3: this.status = 0x29a; break; } switch (num4) { case 0: case 2: if (strm.avail_out == 0) { this.last_flush = -1; } return(0); default: if (num4 == 1) { if (flush == 1) { this._tr_align(); } else { this._tr_stored_block(0, 0, false); if (flush == 3) { for (int num5 = 0; num5 < this.hash_size; num5++) { this.head[num5] = 0; } } } strm.flush_pending(); if (strm.avail_out == 0) { this.last_flush = -1; return(0); } } break; } } if (flush == 4) { if (this.noheader != 0) { return(1); } this.putShortMSB((int)SupportClass.URShift(strm.adler, 0x10)); this.putShortMSB(((int)strm.adler) & 0xffff); strm.flush_pending(); this.noheader = -1; if (this.pending == 0) { return(1); } } return(0); }
internal int proc(ZStream z, 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 = z.next_in_index; n = z.avail_in; b = bitb; k = bitk; } { q = write; m = (int) (q < read?read - q - 1:end - q); } // process input based on current state while (true) { switch (mode) { case TYPE: while (k < (3)) { if (n != 0) { r = Z_OK; } else { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } t = (int) (b & 7); last = t & 1; switch (SupportClass.URShift(t, 1)) { case 0: // stored { b = SupportClass.URShift(b, (3)); k -= (3); } t = k & 7; // go to byte boundary { b = SupportClass.URShift(b, (t)); k -= (t); } mode = 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, z); codes = new InfCodes(bl[0], bd[0], tl[0], td[0], z); } { b = SupportClass.URShift(b, (3)); k -= (3); } mode = CODES; break; case 2: // dynamic { b = SupportClass.URShift(b, (3)); k -= (3); } mode = TABLE; break; case 3: // illegal { b = SupportClass.URShift(b, (3)); k -= (3); } mode = BAD; z.msg = "invalid block type"; r = Z_DATA_ERROR; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } break; case LENS: while (k < (32)) { if (n != 0) { r = Z_OK; } else { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } if (((SupportClass.URShift((~ b), 16)) & 0xffff) != (b & 0xffff)) { mode = BAD; z.msg = "invalid stored block lengths"; r = Z_DATA_ERROR; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } left = (b & 0xffff); b = k = 0; // dump bits mode = left != 0?STORED:(last != 0?DRY:TYPE); break; case STORED: if (n == 0) { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } if (m == 0) { if (q == end && read != 0) { q = 0; m = (int) (q < read?read - q - 1:end - q); } if (m == 0) { write = q; r = inflate_flush(z, r); q = write; m = (int) (q < read?read - q - 1:end - q); if (q == end && read != 0) { q = 0; m = (int) (q < read?read - q - 1:end - q); } if (m == 0) { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } } } r = Z_OK; t = left; if (t > n) t = n; if (t > m) t = m; Array.Copy(z.next_in, p, window, q, t); p += t; n -= t; q += t; m -= t; if ((left -= t) != 0) break; mode = last != 0?DRY:TYPE; break; case TABLE: while (k < (14)) { if (n != 0) { r = Z_OK; } else { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } table = t = (b & 0x3fff); if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) { mode = BAD; z.msg = "too many length or distance symbols"; r = Z_DATA_ERROR; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); blens = new int[t]; { b = SupportClass.URShift(b, (14)); k -= (14); } index = 0; mode = BTREE; goto case BTREE; case BTREE: while (index < 4 + (SupportClass.URShift(table, 10))) { while (k < (3)) { if (n != 0) { r = Z_OK; } else { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } blens[border[index++]] = b & 7; { b = SupportClass.URShift(b, (3)); k -= (3); } } while (index < 19) { blens[border[index++]] = 0; } bb[0] = 7; t = InfTree.inflate_trees_bits(blens, bb, tb, hufts, z); if (t != Z_OK) { r = t; if (r == Z_DATA_ERROR) { blens = null; mode = BAD; } bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } index = 0; mode = DTREE; goto case DTREE; case 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 = Z_OK; } else { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } if (tb[0] == - 1) { //System.err.println("null..."); } t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1]; c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2]; if (c < 16) { b = SupportClass.URShift(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 = Z_OK; } else { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } ; n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } b = SupportClass.URShift(b, (t)); k -= (t); j += (b & inflate_mask[i]); b = SupportClass.URShift(b, (i)); k -= (i); i = index; t = table; if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1)) { blens = null; mode = BAD; z.msg = "invalid bit length repeat"; r = Z_DATA_ERROR; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } c = c == 16?blens[i - 1]:0; do { blens[i++] = c; } while (--j != 0); index = i; } } tb[0] = - 1; { int[] bl = new int[1]; int[] bd = new int[1]; int[] tl = new int[1]; int[] td = new int[1]; bl[0] = 9; // must be <= 9 for lookahead assumptions bd[0] = 6; // must be <= 9 for lookahead assumptions t = table; t = InfTree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl, bd, tl, td, hufts, z); if (t != Z_OK) { if (t == Z_DATA_ERROR) { blens = null; mode = BAD; } r = t; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } codes = new InfCodes(bl[0], bd[0], hufts, tl[0], hufts, td[0], z); } blens = null; mode = CODES; goto case CODES; case CODES: bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; if ((r = codes.proc(this, z, r)) != Z_STREAM_END) { return inflate_flush(z, r); } r = Z_OK; codes.free(z); p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk; q = write; m = (int) (q < read?read - q - 1:end - q); if (last == 0) { mode = TYPE; break; } mode = DRY; goto case DRY; case DRY: write = q; r = inflate_flush(z, r); q = write; m = (int) (q < read?read - q - 1:end - q); if (read != write) { bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } mode = DONE; goto case DONE; case DONE: r = Z_STREAM_END; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); case BAD: r = Z_DATA_ERROR; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); default: r = Z_STREAM_ERROR; bitb = b; bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; write = q; return inflate_flush(z, r); } } }
internal int deflateInit(ZStream strm, int level) { return(this.deflateInit(strm, level, 15)); }
internal int deflateInit(ZStream strm, int level) { return deflateInit(strm, level, MAX_WBITS); }
internal int deflateInit(ZStream strm, int level, int bits) { return(this.deflateInit2(strm, level, 8, bits, 8, 0)); }
internal int deflateReset(ZStream strm) { strm.total_in = strm.total_out = 0; strm.msg = null; // strm.data_type = Z_UNKNOWN; pending = 0; pending_out = 0; if (noheader < 0) { noheader = 0; // was set to -1 by deflate(..., Z_FINISH); } status = (noheader != 0)?BUSY_STATE:INIT_STATE; strm.adler = strm._adler.adler32(0, null, 0, 0); last_flush = Z_NO_FLUSH; tr_init(); lm_init(); return Z_OK; }
internal void free(ZStream z) { this.reset(z, null); this.window = null; this.hufts = null; }
internal int deflateSetDictionary(ZStream strm, byte[] dictionary, int dictLength) { int length = dictLength; int index = 0; if (dictionary == null || status != INIT_STATE) return Z_STREAM_ERROR; strm.adler = strm._adler.adler32(strm.adler, dictionary, 0, dictLength); if (length < MIN_MATCH) return Z_OK; if (length > w_size - MIN_LOOKAHEAD) { length = w_size - MIN_LOOKAHEAD; index = dictLength - length; // use the tail of the dictionary } Array.Copy(dictionary, index, window, 0, length); strstart = length; block_start = length; // Insert all strings in the hash table (except for the last two bytes). // s->lookahead stays null, so s->ins_h will be recomputed at the next // call of fill_window. ins_h = window[0] & 0xff; ins_h = (((ins_h) << hash_shift) ^ (window[1] & 0xff)) & hash_mask; for (int n = 0; n <= length - MIN_MATCH; n++) { ins_h = (((ins_h) << hash_shift) ^ (window[(n) + (MIN_MATCH - 1)] & 0xff)) & hash_mask; prev[n & w_mask] = head[ins_h]; head[ins_h] = (short) n; } return Z_OK; }
internal int proc(ZStream z, int r) { int num1; int num4 = z.next_in_index; int num5 = z.avail_in; int num2 = this.bitb; int num3 = this.bitk; int num6 = this.write; int num7 = (num6 < this.read) ? ((this.read - num6) - 1) : (this.end - num6); Label_0047: switch (this.mode) { case 0: while (num3 < 3) { if (num5 != 0) { r = 0; } else { this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } num5--; num2 |= (z.next_in[num4++] & 0xff) << (num3 & 0x1f); num3 += 8; } num1 = num2 & 7; this.last = num1 & 1; switch (SupportClass.URShift(num1, 1)) { case 0: num2 = SupportClass.URShift(num2, 3); num3 -= 3; num1 = num3 & 7; num2 = SupportClass.URShift(num2, num1); num3 -= num1; this.mode = 1; goto Label_0047; case 1: { int[] numArray1 = new int[1]; int[] numArray2 = new int[1]; int[][] numArrayArray1 = new int[1][]; int[][] numArrayArray2 = new int[1][]; InfTree.inflate_trees_fixed(numArray1, numArray2, numArrayArray1, numArrayArray2, z); this.codes = new InfCodes(numArray1[0], numArray2[0], numArrayArray1[0], numArrayArray2[0], z); num2 = SupportClass.URShift(num2, 3); num3 -= 3; this.mode = 6; goto Label_0047; } case 2: num2 = SupportClass.URShift(num2, 3); num3 -= 3; this.mode = 3; goto Label_0047; case 3: num2 = SupportClass.URShift(num2, 3); num3 -= 3; this.mode = 9; z.msg = "invalid block type"; r = -3; this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } goto Label_0047; case 1: while (num3 < 0x20) { if (num5 != 0) { r = 0; } else { this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } num5--; num2 |= (z.next_in[num4++] & 0xff) << (num3 & 0x1f); num3 += 8; } if ((SupportClass.URShift(~num2, 0x10) & 0xffff) != (num2 & 0xffff)) { this.mode = 9; z.msg = "invalid stored block lengths"; r = -3; this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } this.left = num2 & 0xffff; num2 = num3 = 0; this.mode = (this.left != 0) ? 2 : ((this.last != 0) ? 7 : 0); goto Label_0047; case 2: if (num5 == 0) { this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } if (num7 == 0) { if ((num6 == this.end) && (this.read != 0)) { num6 = 0; num7 = (num6 < this.read) ? ((this.read - num6) - 1) : (this.end - num6); } if (num7 == 0) { this.write = num6; r = this.inflate_flush(z, r); num6 = this.write; num7 = (num6 < this.read) ? ((this.read - num6) - 1) : (this.end - num6); if ((num6 == this.end) && (this.read != 0)) { num6 = 0; num7 = (num6 < this.read) ? ((this.read - num6) - 1) : (this.end - num6); } if (num7 == 0) { this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } } } r = 0; num1 = this.left; if (num1 > num5) { num1 = num5; } if (num1 > num7) { num1 = num7; } Array.Copy(z.next_in, num4, this.window, num6, num1); num4 += num1; num5 -= num1; num6 += num1; num7 -= num1; this.left -= num1; if (this.left == 0) { this.mode = (this.last != 0) ? 7 : 0; } goto Label_0047; case 3: while (num3 < 14) { if (num5 != 0) { r = 0; } else { this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } num5--; num2 |= (z.next_in[num4++] & 0xff) << (num3 & 0x1f); num3 += 8; } this.table = num1 = num2 & 0x3fff; if (((num1 & 0x1f) > 0x1d) || (((num1 >> 5) & 0x1f) > 0x1d)) { this.mode = 9; z.msg = "too many length or distance symbols"; r = -3; this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } num1 = (0x102 + (num1 & 0x1f)) + ((num1 >> 5) & 0x1f); this.blens = new int[num1]; num2 = SupportClass.URShift(num2, 14); num3 -= 14; this.index = 0; this.mode = 4; goto Label_06E1; case 4: goto Label_06E1; case 5: goto Label_07B9; case 6: goto Label_0B63; case 7: goto Label_0C2C; case 8: goto Label_0CC1; case 9: r = -3; this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); default: r = -2; this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } Label_06E1: if (this.index < (4 + SupportClass.URShift(this.table, 10))) { while (num3 < 3) { if (num5 != 0) { r = 0; } else { this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } num5--; num2 |= (z.next_in[num4++] & 0xff) << (num3 & 0x1f); num3 += 8; } this.blens[InfBlocks.border[this.index++]] = num2 & 7; num2 = SupportClass.URShift(num2, 3); num3 -= 3; goto Label_06E1; } while (this.index < 0x13) { this.blens[InfBlocks.border[this.index++]] = 0; } this.bb[0] = 7; num1 = InfTree.inflate_trees_bits(this.blens, this.bb, this.tb, this.hufts, z); if (num1 != 0) { r = num1; if (r == -3) { this.blens = null; this.mode = 9; } this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } this.index = 0; this.mode = 5; Label_07B9: num1 = this.table; if (this.index < ((0x102 + (num1 & 0x1f)) + ((num1 >> 5) & 0x1f))) { num1 = this.bb[0]; while (num3 < num1) { if (num5 != 0) { r = 0; } else { this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } num5--; num2 |= (z.next_in[num4++] & 0xff) << (num3 & 0x1f); num3 += 8; } int num17 = this.tb[0]; num1 = this.hufts[((this.tb[0] + (num2 & InfBlocks.inflate_mask[num1])) * 3) + 1]; int num10 = this.hufts[((this.tb[0] + (num2 & InfBlocks.inflate_mask[num1])) * 3) + 2]; if (num10 < 0x10) { num2 = SupportClass.URShift(num2, num1); num3 -= num1; this.blens[this.index++] = num10; goto Label_07B9; } int num8 = (num10 == 0x12) ? 7 : (num10 - 14); int num9 = (num10 == 0x12) ? 11 : 3; while (num3 < (num1 + num8)) { if (num5 != 0) { r = 0; } else { this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } num5--; num2 |= (z.next_in[num4++] & 0xff) << (num3 & 0x1f); num3 += 8; } num2 = SupportClass.URShift(num2, num1); num3 -= num1; num9 += num2 & InfBlocks.inflate_mask[num8]; num2 = SupportClass.URShift(num2, num8); num3 -= num8; num8 = this.index; num1 = this.table; if (((num8 + num9) > ((0x102 + (num1 & 0x1f)) + ((num1 >> 5) & 0x1f))) || ((num10 == 0x10) && (num8 < 1))) { this.blens = null; this.mode = 9; z.msg = "invalid bit length repeat"; r = -3; this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } num10 = (num10 == 0x10) ? this.blens[num8 - 1] : 0; do { this.blens[num8++] = num10; }while (--num9 != 0); this.index = num8; goto Label_07B9; } this.tb[0] = -1; int[] numArray3 = new int[1]; int[] numArray4 = new int[1]; int[] numArray5 = new int[1]; int[] numArray6 = new int[1]; numArray3[0] = 9; numArray4[0] = 6; num1 = this.table; num1 = InfTree.inflate_trees_dynamic(0x101 + (num1 & 0x1f), 1 + ((num1 >> 5) & 0x1f), this.blens, numArray3, numArray4, numArray5, numArray6, this.hufts, z); switch (num1) { case 0: this.codes = new InfCodes(numArray3[0], numArray4[0], this.hufts, numArray5[0], this.hufts, numArray6[0], z); this.blens = null; this.mode = 6; goto Label_0B63; case -3: this.blens = null; this.mode = 9; break; } r = num1; this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); Label_0B63: this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; if ((r = this.codes.proc(this, z, r)) != 1) { return(this.inflate_flush(z, r)); } r = 0; this.codes.free(z); num4 = z.next_in_index; num5 = z.avail_in; num2 = this.bitb; num3 = this.bitk; num6 = this.write; num7 = (num6 < this.read) ? ((this.read - num6) - 1) : (this.end - num6); if (this.last == 0) { this.mode = 0; goto Label_0047; } this.mode = 7; Label_0C2C: this.write = num6; r = this.inflate_flush(z, r); num6 = this.write; num7 = (num6 < this.read) ? ((this.read - num6) - 1) : (this.end - num6); if (this.read != this.write) { this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); } this.mode = 8; Label_0CC1: r = 1; this.bitb = num2; this.bitk = num3; z.avail_in = num5; z.total_in += num4 - z.next_in_index; z.next_in_index = num4; this.write = num6; return(this.inflate_flush(z, r)); }
internal static int inflate_trees_bits(int[] c, int[] bb, int[] tb, int[] hp, ZStream z) { int r; int[] hn = new int[1]; // hufts used in space int[] v = new int[19]; // work area for huft_build r = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v); if (r == Z_DATA_ERROR) { z.msg = "oversubscribed dynamic bit lengths tree"; } else if (r == Z_BUF_ERROR || bb[0] == 0) { z.msg = "incomplete dynamic bit lengths tree"; r = Z_DATA_ERROR; } return r; }
internal int proc(InfBlocks s, ZStream z, int r) { int j; // temporary storage //int[] t; // temporary pointer int tindex; // temporary pointer int e; // extra bits or operation var b = 0; // bit buffer var k = 0; // bits in bit buffer var 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 // copy input/output information to locals (UPDATE macro restores) p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk; q = s.write; m = q < s.read?s.read - q - 1:s.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) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; r = inflate_fast(lbits, dbits, ltree, ltree_index, dtree, dtree_index, s, z); p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk; q = s.write; m = q < s.read?s.read - q - 1:s.end - q; if (r != Z_OK) { mode = r == 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 = Z_OK; } else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } tindex = (tree_index + (b & inflate_mask[j])) * 3; b = SupportClass.URShift(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 get_Renamed = 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.msg = "invalid literal/length code"; r = Z_DATA_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); case LENEXT: // i: getting length extra (have base) j = get_Renamed; while (k < (j)) { if (n != 0) { r = Z_OK; } else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } len += (b & inflate_mask[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 = Z_OK; } else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } tindex = (tree_index + (b & inflate_mask[j])) * 3; b >>= tree[tindex + 1]; k -= tree[tindex + 1]; e = (tree[tindex]); if ((e & 16) != 0) { // distance get_Renamed = 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.msg = "invalid distance code"; r = Z_DATA_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); case DISTEXT: // i: getting distance extra j = get_Renamed; while (k < (j)) { if (n != 0) { r = Z_OK; } else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } dist += (b & inflate_mask[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 += s.end; // of "if" handles invalid distances } while (len != 0) { if (m == 0) { if (q == s.end && s.read != 0) { q = 0; m = q < s.read?s.read - q - 1:s.end - q; } if (m == 0) { s.write = q; r = s.inflate_flush(z, r); q = s.write; m = q < s.read?s.read - q - 1:s.end - q; if (q == s.end && s.read != 0) { q = 0; m = q < s.read?s.read - q - 1:s.end - q; } if (m == 0) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } } } s.window[q++] = s.window[f++]; m--; if (f == s.end) { f = 0; } len--; } mode = START; break; case LIT: // o: got literal, waiting for output space if (m == 0) { if (q == s.end && s.read != 0) { q = 0; m = q < s.read?s.read - q - 1:s.end - q; } if (m == 0) { s.write = q; r = s.inflate_flush(z, r); q = s.write; m = q < s.read?s.read - q - 1:s.end - q; if (q == s.end && s.read != 0) { q = 0; m = q < s.read?s.read - q - 1:s.end - q; } if (m == 0) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } } } r = Z_OK; s.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 } s.write = q; r = s.inflate_flush(z, r); q = s.write; m = q < s.read?s.read - q - 1:s.end - q; if (s.read != s.write) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } mode = END; goto case END; case END: r = Z_STREAM_END; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); case BADCODE: // x: got error r = Z_DATA_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); default: r = Z_STREAM_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(s.inflate_flush(z, r)); } } }
internal static int inflate_trees_fixed(int[] bl, int[] bd, int[][] tl, int[][] td, ZStream z) { bl[0] = fixed_bl; bd[0] = fixed_bd; tl[0] = fixed_tl; td[0] = fixed_td; return Z_OK; }
internal void free(ZStream z) { // ZFREE(z, c); }
void ClearContext(bool @in, bool @out) { if (@in && inbound != null) { inbound.free(); inbound = null; } if (@out && outbound != null) { outbound.free(); outbound = null; } }
// 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 inflate_fast(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, InfBlocks s, ZStream 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 // load input, output, bit values p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk; q = s.write; m = q < s.read?s.read - q - 1:s.end - q; // initialize masks ml = inflate_mask[bl]; md = inflate_mask[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.next_in[p++] & 0xff) << k; k += 8; } t = b & ml; tp = tl; tp_index = tl_index; 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 & inflate_mask[e]); b >>= e; k -= e; // decode distance base of block to copy while (k < (15)) { // max bits for distance code n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } t = b & md; tp = td; tp_index = td_index; 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.next_in[p++] & 0xff) << k; k += 8; } d = tp[(tp_index + t) * 3 + 2] + (b & inflate_mask[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++]; c--; // minimum count is three, s.window[q++] = s.window[r++]; c--; // so unroll loop a little } 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 & inflate_mask[e]); e = tp[(tp_index + t) * 3]; } else { z.msg = "invalid distance code"; c = z.avail_in - n; c = (k >> 3) < c?k >> 3:c; n += c; p -= c; k -= (c << 3); s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(Z_DATA_ERROR); } }while (true); break; } if ((e & 64) == 0) { t += tp[(tp_index + t) * 3 + 2]; t += (b & inflate_mask[e]); 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.avail_in - n; c = (k >> 3) < c?k >> 3:c; n += c; p -= c; k -= (c << 3); s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(Z_STREAM_END); } else { z.msg = "invalid literal/length code"; c = z.avail_in - n; c = (k >> 3) < c?k >> 3:c; n += c; p -= c; k -= (c << 3); s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(Z_DATA_ERROR); } }while (true); }while (m >= 258 && n >= 10); // not enough input or output--restore pointers and return c = z.avail_in - n; c = (k >> 3) < c?k >> 3:c; n += c; p -= c; k -= (c << 3); s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return(Z_OK); }
internal int dtree_index; // distance tree internal InfCodes(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, ZStream z) { mode = START; lbits = (byte)bl; dbits = (byte)bd; ltree = tl; ltree_index = tl_index; dtree = td; dtree_index = td_index; }
internal int proc(InfBlocks s, ZStream z, int r) { int j; // temporary storage //int[] t; // temporary pointer 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 // copy input/output information to locals (UPDATE macro restores) p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk; q = s.write; m = q < s.read ? s.read - q - 1 : s.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) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; r = inflate_fast(lbits, dbits, ltree, ltree_index, dtree, dtree_index, s, z); p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk; q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; if (r != Z_OK) { mode = r == 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 = Z_OK; else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } tindex = (tree_index + (b & inflate_mask[j])) * 3; b = SupportClass.URShift(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 get_Renamed = 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.msg = "invalid literal/length code"; r = Z_DATA_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); case LENEXT: // i: getting length extra (have base) j = get_Renamed; while (k < (j)) { if (n != 0) r = Z_OK; else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } len += (b & inflate_mask[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 = Z_OK; else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } tindex = (tree_index + (b & inflate_mask[j])) * 3; b >>= tree[tindex + 1]; k -= tree[tindex + 1]; e = (tree[tindex]); if ((e & 16) != 0) { // distance get_Renamed = 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.msg = "invalid distance code"; r = Z_DATA_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); case DISTEXT: // i: getting distance extra j = get_Renamed; while (k < (j)) { if (n != 0) r = Z_OK; else { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } n--; b |= (z.next_in[p++] & 0xff) << k; k += 8; } dist += (b & inflate_mask[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 += s.end; // of "if" handles invalid distances } while (len != 0) { if (m == 0) { if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; } if (m == 0) { s.write = q; r = s.inflate_flush(z, r); q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; } if (m == 0) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } } } s.window[q++] = s.window[f++]; m--; if (f == s.end) f = 0; len--; } mode = START; break; case LIT: // o: got literal, waiting for output space if (m == 0) { if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; } if (m == 0) { s.write = q; r = s.inflate_flush(z, r); q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; } if (m == 0) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } } } r = Z_OK; s.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 } s.write = q; r = s.inflate_flush(z, r); q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q; if (s.read != s.write) { s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } mode = END; goto case END; case END: r = Z_STREAM_END; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); case BADCODE: // x: got error r = Z_DATA_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); default: r = Z_STREAM_ERROR; s.bitb = b; s.bitk = k; z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; s.write = q; return s.inflate_flush(z, r); } } }
internal static int inflate_trees_bits(int[] c, int[] bb, int[] tb, int[] hp, ZStream z) { int[] hn = new int[1]; int[] v = new int[19]; int num = InfTree.huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v); if (num == -3) { z.msg = "oversubscribed dynamic bit lengths tree"; } else { if (num == -5 || bb[0] == 0) { z.msg = "incomplete dynamic bit lengths tree"; num = -3; } } return(num); }