comparison app/src/main/java/com/jcraft/jzlib/Inflate.java @ 438:d29cce60f393

migrate from Eclipse to Android Studio
author Carl Byington <carl@five-ten-sg.com>
date Thu, 03 Dec 2015 11:23:55 -0800
parents src/com/jcraft/jzlib/Inflate.java@46c2115ae1c8
children
comparison
equal deleted inserted replaced
437:208b31032318 438:d29cce60f393
1 /* -*-mode:java; c-basic-offset:2; -*- */
2 /*
3 Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 1. Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in
13 the documentation and/or other materials provided with the distribution.
14
15 3. The names of the authors may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
19 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
21 INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 /*
30 * This program is based on zlib-1.1.3, so all credit should go authors
31 * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
32 * and contributors of zlib.
33 */
34
35 package com.jcraft.jzlib;
36
37 final class Inflate{
38
39 static final private int MAX_WBITS=15; // 32K LZ77 window
40
41 // preset dictionary flag in zlib header
42 static final private int PRESET_DICT=0x20;
43
44 static final int Z_NO_FLUSH=0;
45 static final int Z_PARTIAL_FLUSH=1;
46 static final int Z_SYNC_FLUSH=2;
47 static final int Z_FULL_FLUSH=3;
48 static final int Z_FINISH=4;
49
50 static final private int Z_DEFLATED=8;
51
52 static final private int Z_OK=0;
53 static final private int Z_STREAM_END=1;
54 static final private int Z_NEED_DICT=2;
55 static final private int Z_ERRNO=-1;
56 static final private int Z_STREAM_ERROR=-2;
57 static final private int Z_DATA_ERROR=-3;
58 static final private int Z_MEM_ERROR=-4;
59 static final private int Z_BUF_ERROR=-5;
60 static final private int Z_VERSION_ERROR=-6;
61
62 static final private int METHOD=0; // waiting for method byte
63 static final private int FLAG=1; // waiting for flag byte
64 static final private int DICT4=2; // four dictionary check bytes to go
65 static final private int DICT3=3; // three dictionary check bytes to go
66 static final private int DICT2=4; // two dictionary check bytes to go
67 static final private int DICT1=5; // one dictionary check byte to go
68 static final private int DICT0=6; // waiting for inflateSetDictionary
69 static final private int BLOCKS=7; // decompressing blocks
70 static final private int CHECK4=8; // four check bytes to go
71 static final private int CHECK3=9; // three check bytes to go
72 static final private int CHECK2=10; // two check bytes to go
73 static final private int CHECK1=11; // one check byte to go
74 static final private int DONE=12; // finished check, done
75 static final private int BAD=13; // got an error--stay here
76
77 static final private int HEAD=14;
78 static final private int LENGTH=15;
79 static final private int TIME=16;
80 static final private int OS=17;
81 static final private int EXLEN=18;
82 static final private int EXTRA=19;
83 static final private int NAME=20;
84 static final private int COMMENT=21;
85 static final private int HCRC=22;
86 static final private int FLAGS=23;
87
88 static final int INFLATE_ANY=0x40000000;
89
90 int mode; // current inflate mode
91
92 // mode dependent information
93 int method; // if FLAGS, method byte
94
95 // if CHECK, check values to compare
96 long was = -1; // computed check value
97 long need; // stream check value
98
99 // if BAD, inflateSync's marker bytes count
100 int marker;
101
102 // mode independent information
103 int wrap; // flag for no wrapper
104 // 0: no wrapper
105 // 1: zlib header
106 // 2: gzip header
107 // 4: auto detection
108
109 int wbits; // log2(window size) (8..15, defaults to 15)
110
111 InfBlocks blocks; // current inflate_blocks state
112
113 private final ZStream z;
114
115 private int flags;
116
117 private int need_bytes = -1;
118 private byte[] crcbuf=new byte[4];
119
120 GZIPHeader gheader = null;
121
122 int inflateReset(){
123 if(z == null) return Z_STREAM_ERROR;
124
125 z.total_in = z.total_out = 0;
126 z.msg = null;
127 this.mode = HEAD;
128 this.need_bytes = -1;
129 this.blocks.reset();
130 return Z_OK;
131 }
132
133 int inflateEnd(){
134 if(blocks != null){
135 blocks.free();
136 }
137 return Z_OK;
138 }
139
140 Inflate(ZStream z){
141 this.z=z;
142 }
143
144 int inflateInit(int w){
145 z.msg = null;
146 blocks = null;
147
148 // handle undocumented wrap option (no zlib header or check)
149 wrap = 0;
150 if(w < 0){
151 w = - w;
152 }
153 else if((w&INFLATE_ANY) != 0){
154 wrap = 4;
155 w &= ~INFLATE_ANY;
156 if(w < 48)
157 w &= 15;
158 }
159 else if((w & ~31) != 0) { // for example, DEF_WBITS + 32
160 wrap = 4; // zlib and gzip wrapped data should be accepted.
161 w &= 15;
162 }
163 else {
164 wrap = (w >> 4) + 1;
165 if(w < 48)
166 w &= 15;
167 }
168
169 if(w<8 ||w>15){
170 inflateEnd();
171 return Z_STREAM_ERROR;
172 }
173 if(blocks != null && wbits != w){
174 blocks.free();
175 blocks=null;
176 }
177
178 // set window size
179 wbits=w;
180
181 this.blocks=new InfBlocks(z, 1<<w);
182
183 // reset state
184 inflateReset();
185
186 return Z_OK;
187 }
188
189 int inflate(int f){
190 int hold = 0;
191
192 int r;
193 int b;
194
195 if(z == null || z.next_in == null){
196 if(f == Z_FINISH && this.mode==HEAD)
197 return Z_OK;
198 return Z_STREAM_ERROR;
199 }
200
201 f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
202 r = Z_BUF_ERROR;
203 while (true){
204
205 switch (this.mode){
206 case HEAD:
207 if(wrap==0){
208 this.mode = BLOCKS;
209 break;
210 }
211
212 try { r=readBytes(2, r, f); }
213 catch(Return e){ return e.r; }
214
215 if((wrap == 4 || (wrap&2)!=0) &&
216 this.need == 0x8b1fL) { // gzip header
217 if(wrap == 4){
218 wrap = 2;
219 }
220 z.adler=new CRC32();
221 checksum(2, this.need);
222
223 if(gheader==null)
224 gheader=new GZIPHeader();
225
226 this.mode = FLAGS;
227 break;
228 }
229
230 if((wrap&2) != 0){
231 this.mode = BAD;
232 z.msg = "incorrect header check";
233 break;
234 }
235
236 flags = 0;
237
238 this.method = ((int)this.need)&0xff;
239 b=((int)(this.need>>8))&0xff;
240
241 if(((wrap&1)==0 || // check if zlib header allowed
242 (((this.method << 8)+b) % 31)!=0) &&
243 (this.method&0xf)!=Z_DEFLATED){
244 if(wrap == 4){
245 z.next_in_index -= 2;
246 z.avail_in += 2;
247 z.total_in -= 2;
248 wrap = 0;
249 this.mode = BLOCKS;
250 break;
251 }
252 this.mode = BAD;
253 z.msg = "incorrect header check";
254 // since zlib 1.2, it is allowted to inflateSync for this case.
255 /*
256 this.marker = 5; // can't try inflateSync
257 */
258 break;
259 }
260
261 if((this.method&0xf)!=Z_DEFLATED){
262 this.mode = BAD;
263 z.msg="unknown compression method";
264 // since zlib 1.2, it is allowted to inflateSync for this case.
265 /*
266 this.marker = 5; // can't try inflateSync
267 */
268 break;
269 }
270
271 if(wrap == 4){
272 wrap = 1;
273 }
274
275 if((this.method>>4)+8>this.wbits){
276 this.mode = BAD;
277 z.msg="invalid window size";
278 // since zlib 1.2, it is allowted to inflateSync for this case.
279 /*
280 this.marker = 5; // can't try inflateSync
281 */
282 break;
283 }
284
285 z.adler=new Adler32();
286
287 if((b&PRESET_DICT)==0){
288 this.mode = BLOCKS;
289 break;
290 }
291 this.mode = DICT4;
292 case DICT4:
293
294 if(z.avail_in==0)return r;r=f;
295
296 z.avail_in--; z.total_in++;
297 this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
298 this.mode=DICT3;
299 case DICT3:
300
301 if(z.avail_in==0)return r;r=f;
302
303 z.avail_in--; z.total_in++;
304 this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
305 this.mode=DICT2;
306 case DICT2:
307
308 if(z.avail_in==0)return r;r=f;
309
310 z.avail_in--; z.total_in++;
311 this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
312 this.mode=DICT1;
313 case DICT1:
314
315 if(z.avail_in==0)return r;r=f;
316
317 z.avail_in--; z.total_in++;
318 this.need += (z.next_in[z.next_in_index++]&0xffL);
319 z.adler.reset(this.need);
320 this.mode = DICT0;
321 return Z_NEED_DICT;
322 case DICT0:
323 this.mode = BAD;
324 z.msg = "need dictionary";
325 this.marker = 0; // can try inflateSync
326 return Z_STREAM_ERROR;
327 case BLOCKS:
328 r = this.blocks.proc(r);
329 if(r == Z_DATA_ERROR){
330 this.mode = BAD;
331 this.marker = 0; // can try inflateSync
332 break;
333 }
334 if(r == Z_OK){
335 r = f;
336 }
337 if(r != Z_STREAM_END){
338 return r;
339 }
340 r = f;
341 this.was=z.adler.getValue();
342 this.blocks.reset();
343 if(this.wrap==0){
344 this.mode=DONE;
345 break;
346 }
347 this.mode=CHECK4;
348 case CHECK4:
349
350 if(z.avail_in==0)return r;r=f;
351
352 z.avail_in--; z.total_in++;
353 this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
354 this.mode=CHECK3;
355 case CHECK3:
356
357 if(z.avail_in==0)return r;r=f;
358
359 z.avail_in--; z.total_in++;
360 this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
361 this.mode = CHECK2;
362 case CHECK2:
363
364 if(z.avail_in==0)return r;r=f;
365
366 z.avail_in--; z.total_in++;
367 this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
368 this.mode = CHECK1;
369 case CHECK1:
370
371 if(z.avail_in==0)return r;r=f;
372
373 z.avail_in--; z.total_in++;
374 this.need+=(z.next_in[z.next_in_index++]&0xffL);
375
376 if(flags!=0){ // gzip
377 this.need = ((this.need&0xff000000)>>24 |
378 (this.need&0x00ff0000)>>8 |
379 (this.need&0x0000ff00)<<8 |
380 (this.need&0x0000ffff)<<24)&0xffffffffL;
381 }
382
383 if(((int)(this.was)) != ((int)(this.need))){
384 z.msg = "incorrect data check";
385 // chack is delayed
386 /*
387 this.mode = BAD;
388 this.marker = 5; // can't try inflateSync
389 break;
390 */
391 }
392 else if(flags!=0 && gheader!=null){
393 gheader.crc = this.need;
394 }
395
396 this.mode = LENGTH;
397 case LENGTH:
398 if (wrap!=0 && flags!=0) {
399
400 try { r=readBytes(4, r, f); }
401 catch(Return e){ return e.r; }
402
403 if(z.msg!=null && z.msg.equals("incorrect data check")){
404 this.mode = BAD;
405 this.marker = 5; // can't try inflateSync
406 break;
407 }
408
409 if (this.need != (z.total_out & 0xffffffffL)) {
410 z.msg = "incorrect length check";
411 this.mode = BAD;
412 break;
413 }
414 z.msg = null;
415 }
416 else {
417 if(z.msg!=null && z.msg.equals("incorrect data check")){
418 this.mode = BAD;
419 this.marker = 5; // can't try inflateSync
420 break;
421 }
422 }
423
424 this.mode = DONE;
425 case DONE:
426 return Z_STREAM_END;
427 case BAD:
428 return Z_DATA_ERROR;
429
430 case FLAGS:
431
432 try { r=readBytes(2, r, f); }
433 catch(Return e){ return e.r; }
434
435 flags = ((int)this.need)&0xffff;
436
437 if ((flags & 0xff) != Z_DEFLATED) {
438 z.msg = "unknown compression method";
439 this.mode = BAD;
440 break;
441 }
442 if ((flags & 0xe000)!=0) {
443 z.msg = "unknown header flags set";
444 this.mode = BAD;
445 break;
446 }
447
448 if ((flags & 0x0200)!=0){
449 checksum(2, this.need);
450 }
451
452 this.mode = TIME;
453
454 case TIME:
455 try { r=readBytes(4, r, f); }
456 catch(Return e){ return e.r; }
457 if(gheader!=null)
458 gheader.time = this.need;
459 if ((flags & 0x0200)!=0){
460 checksum(4, this.need);
461 }
462 this.mode = OS;
463 case OS:
464 try { r=readBytes(2, r, f); }
465 catch(Return e){ return e.r; }
466 if(gheader!=null){
467 gheader.xflags = ((int)this.need)&0xff;
468 gheader.os = (((int)this.need)>>8)&0xff;
469 }
470 if ((flags & 0x0200)!=0){
471 checksum(2, this.need);
472 }
473 this.mode = EXLEN;
474 case EXLEN:
475 if ((flags & 0x0400)!=0) {
476 try { r=readBytes(2, r, f); }
477 catch(Return e){ return e.r; }
478 if(gheader!=null){
479 gheader.extra = new byte[((int)this.need)&0xffff];
480 }
481 if ((flags & 0x0200)!=0){
482 checksum(2, this.need);
483 }
484 }
485 else if(gheader!=null){
486 gheader.extra=null;
487 }
488 this.mode = EXTRA;
489
490 case EXTRA:
491 if ((flags & 0x0400)!=0) {
492 try {
493 r=readBytes(r, f);
494 if(gheader!=null){
495 byte[] foo = tmp_string.toByteArray();
496 tmp_string=null;
497 if(foo.length == gheader.extra.length){
498 System.arraycopy(foo, 0, gheader.extra, 0, foo.length);
499 }
500 else{
501 z.msg = "bad extra field length";
502 this.mode = BAD;
503 break;
504 }
505 }
506 }
507 catch(Return e){ return e.r; }
508 }
509 else if(gheader!=null){
510 gheader.extra=null;
511 }
512 this.mode = NAME;
513 case NAME:
514 if ((flags & 0x0800)!=0) {
515 try {
516 r=readString(r, f);
517 if(gheader!=null){
518 gheader.name=tmp_string.toByteArray();
519 }
520 tmp_string=null;
521 }
522 catch(Return e){ return e.r; }
523 }
524 else if(gheader!=null){
525 gheader.name=null;
526 }
527 this.mode = COMMENT;
528 case COMMENT:
529 if ((flags & 0x1000)!=0) {
530 try {
531 r=readString(r, f);
532 if(gheader!=null){
533 gheader.comment=tmp_string.toByteArray();
534 }
535 tmp_string=null;
536 }
537 catch(Return e){ return e.r; }
538 }
539 else if(gheader!=null){
540 gheader.comment=null;
541 }
542 this.mode = HCRC;
543 case HCRC:
544 if ((flags & 0x0200)!=0) {
545 try { r=readBytes(2, r, f); }
546 catch(Return e){ return e.r; }
547 if(gheader!=null){
548 gheader.hcrc=(int)(this.need&0xffff);
549 }
550 if(this.need != (z.adler.getValue()&0xffffL)){
551 this.mode = BAD;
552 z.msg = "header crc mismatch";
553 this.marker = 5; // can't try inflateSync
554 break;
555 }
556 }
557 z.adler = new CRC32();
558
559 this.mode = BLOCKS;
560 break;
561 default:
562 return Z_STREAM_ERROR;
563 }
564 }
565 }
566
567 int inflateSetDictionary(byte[] dictionary, int dictLength){
568 if(z==null || (this.mode != DICT0 && this.wrap != 0)){
569 return Z_STREAM_ERROR;
570 }
571
572 int index=0;
573 int length = dictLength;
574
575 if(this.mode==DICT0){
576 long adler_need=z.adler.getValue();
577 z.adler.reset();
578 z.adler.update(dictionary, 0, dictLength);
579 if(z.adler.getValue()!=adler_need){
580 return Z_DATA_ERROR;
581 }
582 }
583
584 z.adler.reset();
585
586 if(length >= (1<<this.wbits)){
587 length = (1<<this.wbits)-1;
588 index=dictLength - length;
589 }
590 this.blocks.set_dictionary(dictionary, index, length);
591 this.mode = BLOCKS;
592 return Z_OK;
593 }
594
595 static private byte[] mark = {(byte)0, (byte)0, (byte)0xff, (byte)0xff};
596
597 int inflateSync(){
598 int n; // number of bytes to look at
599 int p; // pointer to bytes
600 int m; // number of marker bytes found in a row
601 long r, w; // temporaries to save total_in and total_out
602
603 // set up
604 if(z == null)
605 return Z_STREAM_ERROR;
606 if(this.mode != BAD){
607 this.mode = BAD;
608 this.marker = 0;
609 }
610 if((n=z.avail_in)==0)
611 return Z_BUF_ERROR;
612
613 p=z.next_in_index;
614 m=this.marker;
615 // search
616 while (n!=0 && m < 4){
617 if(z.next_in[p] == mark[m]){
618 m++;
619 }
620 else if(z.next_in[p]!=0){
621 m = 0;
622 }
623 else{
624 m = 4 - m;
625 }
626 p++; n--;
627 }
628
629 // restore
630 z.total_in += p-z.next_in_index;
631 z.next_in_index = p;
632 z.avail_in = n;
633 this.marker = m;
634
635 // return no joy or set up to restart on a new block
636 if(m != 4){
637 return Z_DATA_ERROR;
638 }
639 r=z.total_in; w=z.total_out;
640 inflateReset();
641 z.total_in=r; z.total_out = w;
642 this.mode = BLOCKS;
643
644 return Z_OK;
645 }
646
647 // Returns true if inflate is currently at the end of a block generated
648 // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
649 // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
650 // but removes the length bytes of the resulting empty stored block. When
651 // decompressing, PPP checks that at the end of input packet, inflate is
652 // waiting for these length bytes.
653 int inflateSyncPoint(){
654 if(z == null || this.blocks == null)
655 return Z_STREAM_ERROR;
656 return this.blocks.sync_point();
657 }
658
659 private int readBytes(int n, int r, int f) throws Return{
660 if(need_bytes == -1){
661 need_bytes=n;
662 this.need=0;
663 }
664 while(need_bytes>0){
665 if(z.avail_in==0){ throw new Return(r); }; r=f;
666 z.avail_in--; z.total_in++;
667 this.need = this.need |
668 ((z.next_in[z.next_in_index++]&0xff)<<((n-need_bytes)*8));
669 need_bytes--;
670 }
671 if(n==2){
672 this.need&=0xffffL;
673 }
674 else if(n==4) {
675 this.need&=0xffffffffL;
676 }
677 need_bytes=-1;
678 return r;
679 }
680 class Return extends Exception{
681 int r;
682 Return(int r){this.r=r; }
683 }
684
685 private java.io.ByteArrayOutputStream tmp_string = null;
686 private int readString(int r, int f) throws Return{
687 if(tmp_string == null){
688 tmp_string=new java.io.ByteArrayOutputStream();
689 }
690 int b=0;
691 do {
692 if(z.avail_in==0){ throw new Return(r); }; r=f;
693 z.avail_in--; z.total_in++;
694 b = z.next_in[z.next_in_index];
695 if(b!=0) tmp_string.write(z.next_in, z.next_in_index, 1);
696 z.adler.update(z.next_in, z.next_in_index, 1);
697 z.next_in_index++;
698 }while(b!=0);
699 return r;
700 }
701
702 private int readBytes(int r, int f) throws Return{
703 if(tmp_string == null){
704 tmp_string=new java.io.ByteArrayOutputStream();
705 }
706 int b=0;
707 while(this.need>0){
708 if(z.avail_in==0){ throw new Return(r); }; r=f;
709 z.avail_in--; z.total_in++;
710 b = z.next_in[z.next_in_index];
711 tmp_string.write(z.next_in, z.next_in_index, 1);
712 z.adler.update(z.next_in, z.next_in_index, 1);
713 z.next_in_index++;
714 this.need--;
715 }
716 return r;
717 }
718
719 private void checksum(int n, long v){
720 for(int i=0; i<n; i++){
721 crcbuf[i]=(byte)(v&0xff);
722 v>>=8;
723 }
724 z.adler.update(crcbuf, 0, n);
725 }
726
727 public GZIPHeader getGZIPHeader(){
728 return gheader;
729 }
730
731 boolean inParsingHeader(){
732 switch(mode){
733 case HEAD:
734 case DICT4:
735 case DICT3:
736 case DICT2:
737 case DICT1:
738 case FLAGS:
739 case TIME:
740 case OS:
741 case EXLEN:
742 case EXTRA:
743 case NAME:
744 case COMMENT:
745 case HCRC:
746 return true;
747 default:
748 return false;
749 }
750 }
751 }