line source
+ − /* -*-mode:java; c-basic-offset:2; -*- */
+ − /*
+ − Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+ −
+ − Redistribution and use in source and binary forms, with or without
+ − modification, are permitted provided that the following conditions are met:
+ −
+ − 1. Redistributions of source code must retain the above copyright notice,
+ − this list of conditions and the following disclaimer.
+ −
+ − 2. Redistributions in binary form must reproduce the above copyright
+ − notice, this list of conditions and the following disclaimer in
+ − the documentation and/or other materials provided with the distribution.
+ −
+ − 3. The names of the authors may not be used to endorse or promote products
+ − derived from this software without specific prior written permission.
+ −
+ − THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ − INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ − FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+ − INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+ − INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ − LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ − OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ − LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ − NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ − EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ − */
+ − /*
+ − * This program is based on zlib-1.1.3, so all credit should go authors
+ − * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ − * and contributors of zlib.
+ − */
+ −
+ − package com.jcraft.jzlib;
+ −
+ − final class Inflate {
+ −
+ − static final private int MAX_WBITS = 15; // 32K LZ77 window
+ −
+ − // preset dictionary flag in zlib header
+ − static final private int PRESET_DICT = 0x20;
+ −
+ − static final int Z_NO_FLUSH = 0;
+ − static final int Z_PARTIAL_FLUSH = 1;
+ − static final int Z_SYNC_FLUSH = 2;
+ − static final int Z_FULL_FLUSH = 3;
+ − static final int Z_FINISH = 4;
+ −
+ − static final private int Z_DEFLATED = 8;
+ −
+ − static final private int Z_OK = 0;
+ − static final private int Z_STREAM_END = 1;
+ − static final private int Z_NEED_DICT = 2;
+ − static final private int Z_ERRNO = -1;
+ − static final private int Z_STREAM_ERROR = -2;
+ − static final private int Z_DATA_ERROR = -3;
+ − static final private int Z_MEM_ERROR = -4;
+ − static final private int Z_BUF_ERROR = -5;
+ − static final private int Z_VERSION_ERROR = -6;
+ −
+ − static final private int METHOD = 0; // waiting for method byte
+ − static final private int FLAG = 1; // waiting for flag byte
+ − static final private int DICT4 = 2; // four dictionary check bytes to go
+ − static final private int DICT3 = 3; // three dictionary check bytes to go
+ − static final private int DICT2 = 4; // two dictionary check bytes to go
+ − static final private int DICT1 = 5; // one dictionary check byte to go
+ − static final private int DICT0 = 6; // waiting for inflateSetDictionary
+ − static final private int BLOCKS = 7; // decompressing blocks
+ − static final private int CHECK4 = 8; // four check bytes to go
+ − static final private int CHECK3 = 9; // three check bytes to go
+ − static final private int CHECK2 = 10; // two check bytes to go
+ − static final private int CHECK1 = 11; // one check byte to go
+ − static final private int DONE = 12; // finished check, done
+ − static final private int BAD = 13; // got an error--stay here
+ −
+ − int mode; // current inflate mode
+ −
+ − // mode dependent information
+ − int method; // if FLAGS, method byte
+ −
+ − // if CHECK, check values to compare
+ − long[] was = new long[1] ; // computed check value
+ − long need; // stream check value
+ −
+ − // if BAD, inflateSync's marker bytes count
+ − int marker;
+ −
+ − // mode independent information
+ − int nowrap; // flag for no wrapper
+ − int wbits; // log2(window size) (8..15, defaults to 15)
+ −
+ − InfBlocks blocks; // current inflate_blocks state
+ −
+ − 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;
+ − }
+ −
+ − int inflateEnd(ZStream z) {
+ − if (blocks != null)
+ − blocks.free(z);
+ −
+ − blocks = null;
+ − // ZFREE(z, z->state);
+ − return Z_OK;
+ − }
+ −
+ − int inflateInit(ZStream z, int w) {
+ − z.msg = null;
+ − blocks = null;
+ − // handle undocumented nowrap option (no zlib header or check)
+ − nowrap = 0;
+ −
+ − if (w < 0) {
+ − w = - w;
+ − nowrap = 1;
+ − }
+ −
+ − // set window size
+ − if (w < 8 || w > 15) {
+ − inflateEnd(z);
+ − return Z_STREAM_ERROR;
+ − }
+ −
+ − wbits = w;
+ − z.istate.blocks = new InfBlocks(z,
+ − z.istate.nowrap != 0 ? null : this,
+ − 1 << w);
+ − // reset state
+ − inflateReset(z);
+ − return Z_OK;
+ − }
+ −
+ − 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;
+ −
+ − 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;
+ −
+ − 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) & 0xff000000L;
+ − z.istate.mode = 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;
+ −
+ − 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;
+ −
+ − 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;
+ −
+ − 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) & 0xff000000L;
+ − z.istate.mode = 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;
+ −
+ − 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;
+ −
+ − 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;
+ −
+ − case DONE:
+ − return Z_STREAM_END;
+ −
+ − case BAD:
+ − return Z_DATA_ERROR;
+ −
+ − default:
+ − return Z_STREAM_ERROR;
+ − }
+ − }
+ − }
+ −
+ −
+ − int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength) {
+ − int index = 0;
+ − int length = dictLength;
+ −
+ − if (z == null || z.istate == null || z.istate.mode != DICT0)
+ − return Z_STREAM_ERROR;
+ −
+ − if (z._adler.adler32(1L, dictionary, 0, dictLength) != z.adler) {
+ − return Z_DATA_ERROR;
+ − }
+ −
+ − z.adler = z._adler.adler32(0, null, 0, 0);
+ −
+ − if (length >= (1 << z.istate.wbits)) {
+ − length = (1 << z.istate.wbits) - 1;
+ − index = dictLength - length;
+ − }
+ −
+ − z.istate.blocks.set_dictionary(dictionary, index, length);
+ − z.istate.mode = BLOCKS;
+ − return Z_OK;
+ − }
+ −
+ − static private byte[] mark = { (byte)0, (byte)0, (byte)0xff, (byte)0xff};
+ −
+ − int inflateSync(ZStream z) {
+ − int n; // number of bytes to look at
+ − int p; // pointer to bytes
+ − int m; // number of marker bytes found in a row
+ − long r, w; // temporaries to save total_in and total_out
+ −
+ − // set up
+ − if (z == null || z.istate == null)
+ − return Z_STREAM_ERROR;
+ −
+ − if (z.istate.mode != BAD) {
+ − z.istate.mode = BAD;
+ − z.istate.marker = 0;
+ − }
+ −
+ − if ((n = z.avail_in) == 0)
+ − return Z_BUF_ERROR;
+ −
+ − p = z.next_in_index;
+ − m = z.istate.marker;
+ −
+ − // search
+ − while (n != 0 && m < 4) {
+ − if (z.next_in[p] == mark[m]) {
+ − m++;
+ − }
+ − else if (z.next_in[p] != 0) {
+ − m = 0;
+ − }
+ − else {
+ − m = 4 - m;
+ − }
+ −
+ − p++; n--;
+ − }
+ −
+ − // restore
+ − z.total_in += p - z.next_in_index;
+ − z.next_in_index = p;
+ − z.avail_in = n;
+ − z.istate.marker = m;
+ −
+ − // return no joy or set up to restart on a new block
+ − if (m != 4) {
+ − return Z_DATA_ERROR;
+ − }
+ −
+ − r = z.total_in; w = z.total_out;
+ − inflateReset(z);
+ − z.total_in = r; z.total_out = w;
+ − z.istate.mode = BLOCKS;
+ − return Z_OK;
+ − }
+ −
+ − // Returns true if inflate is currently at the end of a block generated
+ − // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ − // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
+ − // but removes the length bytes of the resulting empty stored block. When
+ − // decompressing, PPP checks that at the end of input packet, inflate is
+ − // waiting for these length bytes.
+ − int inflateSyncPoint(ZStream z) {
+ − if (z == null || z.istate == null || z.istate.blocks == null)
+ − return Z_STREAM_ERROR;
+ −
+ − return z.istate.blocks.sync_point();
+ − }
+ − }