Path: blob/main/epkcompiler/src/com/jcraft/jzlib/Inflate.java
8645 views
/* -*-mode:java; c-basic-offset:2; -*- */1/*2Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.34Redistribution and use in source and binary forms, with or without5modification, are permitted provided that the following conditions are met:671. Redistributions of source code must retain the above copyright notice,8this list of conditions and the following disclaimer.9102. Redistributions in binary form must reproduce the above copyright11notice, this list of conditions and the following disclaimer in12the documentation and/or other materials provided with the distribution.13143. The names of the authors may not be used to endorse or promote products15derived from this software without specific prior written permission.1617THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,18INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND19FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,20INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,21INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT22LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,23OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF24LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING25NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,26EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.27*/28/*29* This program is based on zlib-1.1.3, so all credit should go authors30* Jean-loup Gailly([email protected]) and Mark Adler([email protected])31* and contributors of zlib.32*/3334package com.jcraft.jzlib;3536final class Inflate{3738static final private int MAX_WBITS=15; // 32K LZ77 window3940// preset dictionary flag in zlib header41static final private int PRESET_DICT=0x20;4243static final int Z_NO_FLUSH=0;44static final int Z_PARTIAL_FLUSH=1;45static final int Z_SYNC_FLUSH=2;46static final int Z_FULL_FLUSH=3;47static final int Z_FINISH=4;4849static final private int Z_DEFLATED=8;5051static final private int Z_OK=0;52static final private int Z_STREAM_END=1;53static final private int Z_NEED_DICT=2;54static final private int Z_ERRNO=-1;55static final private int Z_STREAM_ERROR=-2;56static final private int Z_DATA_ERROR=-3;57static final private int Z_MEM_ERROR=-4;58static final private int Z_BUF_ERROR=-5;59static final private int Z_VERSION_ERROR=-6;6061static final private int METHOD=0; // waiting for method byte62static final private int FLAG=1; // waiting for flag byte63static final private int DICT4=2; // four dictionary check bytes to go64static final private int DICT3=3; // three dictionary check bytes to go65static final private int DICT2=4; // two dictionary check bytes to go66static final private int DICT1=5; // one dictionary check byte to go67static final private int DICT0=6; // waiting for inflateSetDictionary68static final private int BLOCKS=7; // decompressing blocks69static final private int CHECK4=8; // four check bytes to go70static final private int CHECK3=9; // three check bytes to go71static final private int CHECK2=10; // two check bytes to go72static final private int CHECK1=11; // one check byte to go73static final private int DONE=12; // finished check, done74static final private int BAD=13; // got an error--stay here7576static final private int HEAD=14;77static final private int LENGTH=15;78static final private int TIME=16;79static final private int OS=17;80static final private int EXLEN=18;81static final private int EXTRA=19;82static final private int NAME=20;83static final private int COMMENT=21;84static final private int HCRC=22;85static final private int FLAGS=23;8687static final int INFLATE_ANY=0x40000000;8889int mode; // current inflate mode9091// mode dependent information92int method; // if FLAGS, method byte9394// if CHECK, check values to compare95long was = -1; // computed check value96long need; // stream check value9798// if BAD, inflateSync's marker bytes count99int marker;100101// mode independent information102int wrap; // flag for no wrapper103// 0: no wrapper104// 1: zlib header105// 2: gzip header106// 4: auto detection107108int wbits; // log2(window size) (8..15, defaults to 15)109110InfBlocks blocks; // current inflate_blocks state111112private final ZStream z;113114private int flags;115116private int need_bytes = -1;117private byte[] crcbuf=new byte[4];118119GZIPHeader gheader = null;120121int inflateReset(){122if(z == null) return Z_STREAM_ERROR;123124z.total_in = z.total_out = 0;125z.msg = null;126this.mode = HEAD;127this.need_bytes = -1;128this.blocks.reset();129return Z_OK;130}131132int inflateEnd(){133if(blocks != null){134blocks.free();135}136return Z_OK;137}138139Inflate(ZStream z){140this.z=z;141}142143int inflateInit(int w){144z.msg = null;145blocks = null;146147// handle undocumented wrap option (no zlib header or check)148wrap = 0;149if(w < 0){150w = - w;151}152else if((w&INFLATE_ANY) != 0){153wrap = 4;154w &= ~INFLATE_ANY;155if(w < 48)156w &= 15;157}158else if((w & ~31) != 0) { // for example, DEF_WBITS + 32159wrap = 4; // zlib and gzip wrapped data should be accepted.160w &= 15;161}162else {163wrap = (w >> 4) + 1;164if(w < 48)165w &= 15;166}167168if(w<8 ||w>15){169inflateEnd();170return Z_STREAM_ERROR;171}172if(blocks != null && wbits != w){173blocks.free();174blocks=null;175}176177// set window size178wbits=w;179180this.blocks=new InfBlocks(z, 1<<w);181182// reset state183inflateReset();184185return Z_OK;186}187188int inflate(int f){189int hold = 0;190191int r;192int b;193194if(z == null || z.next_in == null){195if(f == Z_FINISH && this.mode==HEAD)196return Z_OK;197return Z_STREAM_ERROR;198}199200f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;201r = Z_BUF_ERROR;202while (true){203204switch (this.mode){205case HEAD:206if(wrap==0){207this.mode = BLOCKS;208break;209}210211try { r=readBytes(2, r, f); }212catch(Return e){ return e.r; }213214if((wrap == 4 || (wrap&2)!=0) &&215this.need == 0x8b1fL) { // gzip header216if(wrap == 4){217wrap = 2;218}219z.adler=new CRC32();220checksum(2, this.need);221222if(gheader==null)223gheader=new GZIPHeader();224225this.mode = FLAGS;226break;227}228229if((wrap&2) != 0){230this.mode = BAD;231z.msg = "incorrect header check";232break;233}234235flags = 0;236237this.method = ((int)this.need)&0xff;238b=((int)(this.need>>8))&0xff;239240if(((wrap&1)==0 || // check if zlib header allowed241(((this.method << 8)+b) % 31)!=0) &&242(this.method&0xf)!=Z_DEFLATED){243if(wrap == 4){244z.next_in_index -= 2;245z.avail_in += 2;246z.total_in -= 2;247wrap = 0;248this.mode = BLOCKS;249break;250}251this.mode = BAD;252z.msg = "incorrect header check";253// since zlib 1.2, it is allowted to inflateSync for this case.254/*255this.marker = 5; // can't try inflateSync256*/257break;258}259260if((this.method&0xf)!=Z_DEFLATED){261this.mode = BAD;262z.msg="unknown compression method";263// since zlib 1.2, it is allowted to inflateSync for this case.264/*265this.marker = 5; // can't try inflateSync266*/267break;268}269270if(wrap == 4){271wrap = 1;272}273274if((this.method>>4)+8>this.wbits){275this.mode = BAD;276z.msg="invalid window size";277// since zlib 1.2, it is allowted to inflateSync for this case.278/*279this.marker = 5; // can't try inflateSync280*/281break;282}283284z.adler=new Adler32();285286if((b&PRESET_DICT)==0){287this.mode = BLOCKS;288break;289}290this.mode = DICT4;291case DICT4:292293if(z.avail_in==0)return r;r=f;294295z.avail_in--; z.total_in++;296this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;297this.mode=DICT3;298case DICT3:299300if(z.avail_in==0)return r;r=f;301302z.avail_in--; z.total_in++;303this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;304this.mode=DICT2;305case DICT2:306307if(z.avail_in==0)return r;r=f;308309z.avail_in--; z.total_in++;310this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;311this.mode=DICT1;312case DICT1:313314if(z.avail_in==0)return r;r=f;315316z.avail_in--; z.total_in++;317this.need += (z.next_in[z.next_in_index++]&0xffL);318z.adler.reset(this.need);319this.mode = DICT0;320return Z_NEED_DICT;321case DICT0:322this.mode = BAD;323z.msg = "need dictionary";324this.marker = 0; // can try inflateSync325return Z_STREAM_ERROR;326case BLOCKS:327r = this.blocks.proc(r);328if(r == Z_DATA_ERROR){329this.mode = BAD;330this.marker = 0; // can try inflateSync331break;332}333if(r == Z_OK){334r = f;335}336if(r != Z_STREAM_END){337return r;338}339r = f;340this.was=z.adler.getValue();341this.blocks.reset();342if(this.wrap==0){343this.mode=DONE;344break;345}346this.mode=CHECK4;347case CHECK4:348349if(z.avail_in==0)return r;r=f;350351z.avail_in--; z.total_in++;352this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;353this.mode=CHECK3;354case CHECK3:355356if(z.avail_in==0)return r;r=f;357358z.avail_in--; z.total_in++;359this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;360this.mode = CHECK2;361case CHECK2:362363if(z.avail_in==0)return r;r=f;364365z.avail_in--; z.total_in++;366this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;367this.mode = CHECK1;368case CHECK1:369370if(z.avail_in==0)return r;r=f;371372z.avail_in--; z.total_in++;373this.need+=(z.next_in[z.next_in_index++]&0xffL);374375if(flags!=0){ // gzip376this.need = ((this.need&0xff000000)>>24 |377(this.need&0x00ff0000)>>8 |378(this.need&0x0000ff00)<<8 |379(this.need&0x0000ffff)<<24)&0xffffffffL;380}381382if(((int)(this.was)) != ((int)(this.need))){383z.msg = "incorrect data check";384// chack is delayed385/*386this.mode = BAD;387this.marker = 5; // can't try inflateSync388break;389*/390}391else if(flags!=0 && gheader!=null){392gheader.crc = this.need;393}394395this.mode = LENGTH;396case LENGTH:397if (wrap!=0 && flags!=0) {398399try { r=readBytes(4, r, f); }400catch(Return e){ return e.r; }401402if(z.msg!=null && z.msg.equals("incorrect data check")){403this.mode = BAD;404this.marker = 5; // can't try inflateSync405break;406}407408if (this.need != (z.total_out & 0xffffffffL)) {409z.msg = "incorrect length check";410this.mode = BAD;411break;412}413z.msg = null;414}415else {416if(z.msg!=null && z.msg.equals("incorrect data check")){417this.mode = BAD;418this.marker = 5; // can't try inflateSync419break;420}421}422423this.mode = DONE;424case DONE:425return Z_STREAM_END;426case BAD:427return Z_DATA_ERROR;428429case FLAGS:430431try { r=readBytes(2, r, f); }432catch(Return e){ return e.r; }433434flags = ((int)this.need)&0xffff;435436if ((flags & 0xff) != Z_DEFLATED) {437z.msg = "unknown compression method";438this.mode = BAD;439break;440}441if ((flags & 0xe000)!=0) {442z.msg = "unknown header flags set";443this.mode = BAD;444break;445}446447if ((flags & 0x0200)!=0){448checksum(2, this.need);449}450451this.mode = TIME;452453case TIME:454try { r=readBytes(4, r, f); }455catch(Return e){ return e.r; }456if(gheader!=null)457gheader.time = this.need;458if ((flags & 0x0200)!=0){459checksum(4, this.need);460}461this.mode = OS;462case OS:463try { r=readBytes(2, r, f); }464catch(Return e){ return e.r; }465if(gheader!=null){466gheader.xflags = ((int)this.need)&0xff;467gheader.os = (((int)this.need)>>8)&0xff;468}469if ((flags & 0x0200)!=0){470checksum(2, this.need);471}472this.mode = EXLEN;473case EXLEN:474if ((flags & 0x0400)!=0) {475try { r=readBytes(2, r, f); }476catch(Return e){ return e.r; }477if(gheader!=null){478gheader.extra = new byte[((int)this.need)&0xffff];479}480if ((flags & 0x0200)!=0){481checksum(2, this.need);482}483}484else if(gheader!=null){485gheader.extra=null;486}487this.mode = EXTRA;488489case EXTRA:490if ((flags & 0x0400)!=0) {491try {492r=readBytes(r, f);493if(gheader!=null){494byte[] foo = tmp_string.toByteArray();495tmp_string=null;496if(foo.length == gheader.extra.length){497System.arraycopy(foo, 0, gheader.extra, 0, foo.length);498}499else{500z.msg = "bad extra field length";501this.mode = BAD;502break;503}504}505}506catch(Return e){ return e.r; }507}508else if(gheader!=null){509gheader.extra=null;510}511this.mode = NAME;512case NAME:513if ((flags & 0x0800)!=0) {514try {515r=readString(r, f);516if(gheader!=null){517gheader.name=tmp_string.toByteArray();518}519tmp_string=null;520}521catch(Return e){ return e.r; }522}523else if(gheader!=null){524gheader.name=null;525}526this.mode = COMMENT;527case COMMENT:528if ((flags & 0x1000)!=0) {529try {530r=readString(r, f);531if(gheader!=null){532gheader.comment=tmp_string.toByteArray();533}534tmp_string=null;535}536catch(Return e){ return e.r; }537}538else if(gheader!=null){539gheader.comment=null;540}541this.mode = HCRC;542case HCRC:543if ((flags & 0x0200)!=0) {544try { r=readBytes(2, r, f); }545catch(Return e){ return e.r; }546if(gheader!=null){547gheader.hcrc=(int)(this.need&0xffff);548}549if(this.need != (z.adler.getValue()&0xffffL)){550this.mode = BAD;551z.msg = "header crc mismatch";552this.marker = 5; // can't try inflateSync553break;554}555}556z.adler = new CRC32();557558this.mode = BLOCKS;559break;560default:561return Z_STREAM_ERROR;562}563}564}565566int inflateSetDictionary(byte[] dictionary, int dictLength){567if(z==null || (this.mode != DICT0 && this.wrap != 0)){568return Z_STREAM_ERROR;569}570571int index=0;572int length = dictLength;573574if(this.mode==DICT0){575long adler_need=z.adler.getValue();576z.adler.reset();577z.adler.update(dictionary, 0, dictLength);578if(z.adler.getValue()!=adler_need){579return Z_DATA_ERROR;580}581}582583z.adler.reset();584585if(length >= (1<<this.wbits)){586length = (1<<this.wbits)-1;587index=dictLength - length;588}589this.blocks.set_dictionary(dictionary, index, length);590this.mode = BLOCKS;591return Z_OK;592}593594static private byte[] mark = {(byte)0, (byte)0, (byte)0xff, (byte)0xff};595596int inflateSync(){597int n; // number of bytes to look at598int p; // pointer to bytes599int m; // number of marker bytes found in a row600long r, w; // temporaries to save total_in and total_out601602// set up603if(z == null)604return Z_STREAM_ERROR;605if(this.mode != BAD){606this.mode = BAD;607this.marker = 0;608}609if((n=z.avail_in)==0)610return Z_BUF_ERROR;611612p=z.next_in_index;613m=this.marker;614// search615while (n!=0 && m < 4){616if(z.next_in[p] == mark[m]){617m++;618}619else if(z.next_in[p]!=0){620m = 0;621}622else{623m = 4 - m;624}625p++; n--;626}627628// restore629z.total_in += p-z.next_in_index;630z.next_in_index = p;631z.avail_in = n;632this.marker = m;633634// return no joy or set up to restart on a new block635if(m != 4){636return Z_DATA_ERROR;637}638r=z.total_in; w=z.total_out;639inflateReset();640z.total_in=r; z.total_out = w;641this.mode = BLOCKS;642643return Z_OK;644}645646// Returns true if inflate is currently at the end of a block generated647// by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP648// implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH649// but removes the length bytes of the resulting empty stored block. When650// decompressing, PPP checks that at the end of input packet, inflate is651// waiting for these length bytes.652int inflateSyncPoint(){653if(z == null || this.blocks == null)654return Z_STREAM_ERROR;655return this.blocks.sync_point();656}657658private int readBytes(int n, int r, int f) throws Return{659if(need_bytes == -1){660need_bytes=n;661this.need=0;662}663while(need_bytes>0){664if(z.avail_in==0){ throw new Return(r); }; r=f;665z.avail_in--; z.total_in++;666this.need = this.need |667((z.next_in[z.next_in_index++]&0xff)<<((n-need_bytes)*8));668need_bytes--;669}670if(n==2){671this.need&=0xffffL;672}673else if(n==4) {674this.need&=0xffffffffL;675}676need_bytes=-1;677return r;678}679class Return extends Exception{680int r;681Return(int r){this.r=r; }682}683684private java.io.ByteArrayOutputStream tmp_string = null;685private int readString(int r, int f) throws Return{686if(tmp_string == null){687tmp_string=new java.io.ByteArrayOutputStream();688}689int b=0;690do {691if(z.avail_in==0){ throw new Return(r); }; r=f;692z.avail_in--; z.total_in++;693b = z.next_in[z.next_in_index];694if(b!=0) tmp_string.write(z.next_in, z.next_in_index, 1);695z.adler.update(z.next_in, z.next_in_index, 1);696z.next_in_index++;697}while(b!=0);698return r;699}700701private int readBytes(int r, int f) throws Return{702if(tmp_string == null){703tmp_string=new java.io.ByteArrayOutputStream();704}705int b=0;706while(this.need>0){707if(z.avail_in==0){ throw new Return(r); }; r=f;708z.avail_in--; z.total_in++;709b = z.next_in[z.next_in_index];710tmp_string.write(z.next_in, z.next_in_index, 1);711z.adler.update(z.next_in, z.next_in_index, 1);712z.next_in_index++;713this.need--;714}715return r;716}717718private void checksum(int n, long v){719for(int i=0; i<n; i++){720crcbuf[i]=(byte)(v&0xff);721v>>=8;722}723z.adler.update(crcbuf, 0, n);724}725726public GZIPHeader getGZIPHeader(){727return gheader;728}729730boolean inParsingHeader(){731switch(mode){732case HEAD:733case DICT4:734case DICT3:735case DICT2:736case DICT1:737case FLAGS:738case TIME:739case OS:740case EXLEN:741case EXTRA:742case NAME:743case COMMENT:744case HCRC:745return true;746default:747return false;748}749}750}751752753