View Javadoc

1   /*
2    * Copyright 2009 Red Hat, Inc.
3    *
4    * Red Hat licenses this file to you under the Apache License, version 2.0
5    * (the "License"); you may not use this file except in compliance with the
6    * License.  You may obtain a copy of the License at:
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  /*
17  Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
18  
19  Redistribution and use in source and binary forms, with or without
20  modification, are permitted provided that the following conditions are met:
21  
22    1. Redistributions of source code must retain the above copyright notice,
23       this list of conditions and the following disclaimer.
24  
25    2. Redistributions in binary form must reproduce the above copyright
26       notice, this list of conditions and the following disclaimer in
27       the documentation and/or other materials provided with the distribution.
28  
29    3. The names of the authors may not be used to endorse or promote products
30       derived from this software without specific prior written permission.
31  
32  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
33  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
35  INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
36  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
37  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
38  OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
39  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
40  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
41  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42   */
43  /*
44   * This program is based on zlib-1.1.3, so all credit should go authors
45   * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
46   * and contributors of zlib.
47   */
48  
49  package org.jboss.netty.util.internal.jzlib;
50  
51  import org.jboss.netty.util.internal.jzlib.JZlib.WrapperType;
52  
53  final class Inflate {
54  
55      private static final int METHOD = 0; // waiting for method byte
56      private static final int FLAG = 1; // waiting for flag byte
57      private static final int DICT4 = 2; // four dictionary check bytes to go
58      private static final int DICT3 = 3; // three dictionary check bytes to go
59      private static final int DICT2 = 4; // two dictionary check bytes to go
60      private static final int DICT1 = 5; // one dictionary check byte to go
61      private static final int DICT0 = 6; // waiting for inflateSetDictionary
62      private static final int BLOCKS = 7; // decompressing blocks
63      private static final int CHECK4 = 8; // four check bytes to go
64      private static final int CHECK3 = 9; // three check bytes to go
65      private static final int CHECK2 = 10; // two check bytes to go
66      private static final int CHECK1 = 11; // one check byte to go
67      private static final int DONE = 12; // finished check, done
68      private static final int BAD = 13; // got an error--stay here
69  
70      private static final int GZIP_ID1 = 14;
71      private static final int GZIP_ID2 = 15;
72      private static final int GZIP_CM = 16;
73      private static final int GZIP_FLG = 17;
74      private static final int GZIP_MTIME_XFL_OS = 18;
75      private static final int GZIP_XLEN = 19;
76      private static final int GZIP_FEXTRA = 20;
77      private static final int GZIP_FNAME = 21;
78      private static final int GZIP_FCOMMENT = 22;
79      private static final int GZIP_FHCRC = 23;
80      private static final int GZIP_CRC32= 24;
81      private static final int GZIP_ISIZE = 25;
82  
83      private int mode; // current inflate mode
84      // mode dependent information
85      private int method; // if FLAGS, method byte
86      // if CHECK, check values to compare
87      private final long[] was = new long[1]; // computed check value
88      private long need; // stream check value
89      // if BAD, inflateSync's marker bytes count
90      private int marker;
91      // mode independent information
92      private WrapperType wrapperType;
93      private int wbits; // log2(window size)  (8..15, defaults to 15)
94      private InfBlocks blocks; // current inflate_blocks state
95      private int gzipFlag;
96      private int gzipBytesToRead;
97      private int gzipXLen;
98      private int gzipUncompressedBytes;
99      private int gzipCRC32;
100     private int gzipISize;
101 
102     private int inflateReset(ZStream z) {
103         if (z == null || z.istate == null) {
104             return JZlib.Z_STREAM_ERROR;
105         }
106 
107         z.total_in = z.total_out = 0;
108         z.msg = null;
109         switch (wrapperType) {
110         case NONE:
111             z.istate.mode = BLOCKS;
112             break;
113         case ZLIB:
114             z.istate.mode = METHOD;
115             break;
116         case GZIP:
117             z.istate.mode = GZIP_ID1;
118             break;
119         }
120         z.istate.blocks.reset(z, null);
121         gzipUncompressedBytes = 0;
122         return JZlib.Z_OK;
123     }
124 
125     int inflateEnd(ZStream z) {
126         if (blocks != null) {
127             blocks.free(z);
128         }
129         blocks = null;
130         //    ZFREE(z, z->state);
131         return JZlib.Z_OK;
132     }
133 
134     int inflateInit(ZStream z, int w, WrapperType wrapperType) {
135         z.msg = null;
136         blocks = null;
137 
138         this.wrapperType = wrapperType;
139 
140         if (w < 0) {
141             throw new IllegalArgumentException("w: " + w);
142         }
143 
144         // set window size
145         if (w < 8 || w > 15) {
146             inflateEnd(z);
147             return JZlib.Z_STREAM_ERROR;
148         }
149         wbits = w;
150 
151         z.istate.blocks = new InfBlocks(
152                 z, z.istate.wrapperType == WrapperType.NONE? null : this,
153                 1 << w);
154 
155         // reset state
156         inflateReset(z);
157         return JZlib.Z_OK;
158     }
159 
160     int inflate(ZStream z, int f) {
161         int r;
162         int b;
163 
164         if (z == null || z.istate == null || z.next_in == null) {
165             return JZlib.Z_STREAM_ERROR;
166         }
167         f = f == JZlib.Z_FINISH? JZlib.Z_BUF_ERROR : JZlib.Z_OK;
168         r = JZlib.Z_BUF_ERROR;
169         while (true) {
170             //System.out.println("mode: "+z.istate.mode);
171             switch (z.istate.mode) {
172             case METHOD:
173 
174                 if (z.avail_in == 0) {
175                     return r;
176                 }
177                 r = f;
178 
179                 z.avail_in --;
180                 z.total_in ++;
181                 if (((z.istate.method = z.next_in[z.next_in_index ++]) & 0xf) != JZlib.Z_DEFLATED) {
182                     z.istate.mode = BAD;
183                     z.msg = "unknown compression method";
184                     z.istate.marker = 5; // can't try inflateSync
185                     break;
186                 }
187                 if ((z.istate.method >> 4) + 8 > z.istate.wbits) {
188                     z.istate.mode = BAD;
189                     z.msg = "invalid window size";
190                     z.istate.marker = 5; // can't try inflateSync
191                     break;
192                 }
193                 z.istate.mode = FLAG;
194             case FLAG:
195 
196                 if (z.avail_in == 0) {
197                     return r;
198                 }
199                 r = f;
200 
201                 z.avail_in --;
202                 z.total_in ++;
203                 b = z.next_in[z.next_in_index ++] & 0xff;
204 
205                 if (((z.istate.method << 8) + b) % 31 != 0) {
206                     z.istate.mode = BAD;
207                     z.msg = "incorrect header check";
208                     z.istate.marker = 5; // can't try inflateSync
209                     break;
210                 }
211 
212                 if ((b & JZlib.PRESET_DICT) == 0) {
213                     z.istate.mode = BLOCKS;
214                     break;
215                 }
216                 z.istate.mode = DICT4;
217             case DICT4:
218 
219                 if (z.avail_in == 0) {
220                     return r;
221                 }
222                 r = f;
223 
224                 z.avail_in --;
225                 z.total_in ++;
226                 z.istate.need = (z.next_in[z.next_in_index ++] & 0xff) << 24 & 0xff000000L;
227                 z.istate.mode = DICT3;
228             case DICT3:
229 
230                 if (z.avail_in == 0) {
231                     return r;
232                 }
233                 r = f;
234 
235                 z.avail_in --;
236                 z.total_in ++;
237                 z.istate.need += (z.next_in[z.next_in_index ++] & 0xff) << 16 & 0xff0000L;
238                 z.istate.mode = DICT2;
239             case DICT2:
240 
241                 if (z.avail_in == 0) {
242                     return r;
243                 }
244                 r = f;
245 
246                 z.avail_in --;
247                 z.total_in ++;
248                 z.istate.need += (z.next_in[z.next_in_index ++] & 0xff) << 8 & 0xff00L;
249                 z.istate.mode = DICT1;
250             case DICT1:
251 
252                 if (z.avail_in == 0) {
253                     return r;
254                 }
255 
256                 z.avail_in --;
257                 z.total_in ++;
258                 z.istate.need += z.next_in[z.next_in_index ++] & 0xffL;
259                 z.adler = z.istate.need;
260                 z.istate.mode = DICT0;
261                 return JZlib.Z_NEED_DICT;
262             case DICT0:
263                 z.istate.mode = BAD;
264                 z.msg = "need dictionary";
265                 z.istate.marker = 0; // can try inflateSync
266                 return JZlib.Z_STREAM_ERROR;
267             case BLOCKS:
268                 int old_next_out_index = z.next_out_index;
269                 try {
270                     r = z.istate.blocks.proc(z, r);
271                     if (r == JZlib.Z_DATA_ERROR) {
272                         z.istate.mode = BAD;
273                         z.istate.marker = 0; // can try inflateSync
274                         break;
275                     }
276                     if (r == JZlib.Z_OK) {
277                         r = f;
278                     }
279                     if (r != JZlib.Z_STREAM_END) {
280                         return r;
281                     }
282                     r = f;
283                     z.istate.blocks.reset(z, z.istate.was);
284                 } finally {
285                     int decompressedBytes = z.next_out_index - old_next_out_index;
286                     gzipUncompressedBytes += decompressedBytes;
287                     z.crc32 = CRC32.crc32(z.crc32, z.next_out, old_next_out_index, decompressedBytes);
288                 }
289                 if (z.istate.wrapperType == WrapperType.NONE) {
290                     z.istate.mode = DONE;
291                     break;
292                 } else if (z.istate.wrapperType == WrapperType.ZLIB) {
293                     z.istate.mode = CHECK4;
294                 } else {
295                     gzipCRC32 = 0;
296                     gzipISize = 0;
297                     gzipBytesToRead = 4;
298                     z.istate.mode = GZIP_CRC32;
299                     break;
300                 }
301             case CHECK4:
302                 if (z.avail_in == 0) {
303                     return r;
304                 }
305                 r = f;
306 
307                 z.avail_in --;
308                 z.total_in ++;
309                 z.istate.need = (z.next_in[z.next_in_index ++] & 0xff) << 24 & 0xff000000L;
310                 z.istate.mode = CHECK3;
311             case CHECK3:
312                 if (z.avail_in == 0) {
313                     return r;
314                 }
315                 r = f;
316 
317                 z.avail_in --;
318                 z.total_in ++;
319                 z.istate.need += (z.next_in[z.next_in_index ++] & 0xff) << 16 & 0xff0000L;
320                 z.istate.mode = CHECK2;
321             case CHECK2:
322                 if (z.avail_in == 0) {
323                     return r;
324                 }
325                 r = f;
326 
327                 z.avail_in --;
328                 z.total_in ++;
329                 z.istate.need += (z.next_in[z.next_in_index ++] & 0xff) << 8 & 0xff00L;
330                 z.istate.mode = CHECK1;
331             case CHECK1:
332                 if (z.avail_in == 0) {
333                     return r;
334                 }
335                 r = f;
336 
337                 z.avail_in --;
338                 z.total_in ++;
339                 z.istate.need += z.next_in[z.next_in_index ++] & 0xffL;
340 
341                 if ((int) z.istate.was[0] != (int) z.istate.need) {
342                     z.istate.mode = BAD;
343                     z.msg = "incorrect data check";
344                     z.istate.marker = 5; // can't try inflateSync
345                     break;
346                 }
347 
348                 z.istate.mode = DONE;
349             case DONE:
350                 return JZlib.Z_STREAM_END;
351             case BAD:
352                 return JZlib.Z_DATA_ERROR;
353             case GZIP_ID1:
354                 if (z.avail_in == 0) {
355                     return r;
356                 }
357                 r = f;
358                 z.avail_in --;
359                 z.total_in ++;
360 
361                 if ((z.next_in[z.next_in_index ++] & 0xff) != 31) {
362                     z.istate.mode = BAD;
363                     z.msg = "not a gzip stream";
364                     z.istate.marker = 5; // can't try inflateSync
365                     break;
366                 }
367                 z.istate.mode = GZIP_ID2;
368             case GZIP_ID2:
369                 if (z.avail_in == 0) {
370                     return r;
371                 }
372                 r = f;
373                 z.avail_in --;
374                 z.total_in ++;
375 
376                 if ((z.next_in[z.next_in_index ++] & 0xff) != 139) {
377                     z.istate.mode = BAD;
378                     z.msg = "not a gzip stream";
379                     z.istate.marker = 5; // can't try inflateSync
380                     break;
381                 }
382                 z.istate.mode = GZIP_CM;
383             case GZIP_CM:
384                 if (z.avail_in == 0) {
385                     return r;
386                 }
387                 r = f;
388                 z.avail_in --;
389                 z.total_in ++;
390 
391                 if ((z.next_in[z.next_in_index ++] & 0xff) != JZlib.Z_DEFLATED) {
392                     z.istate.mode = BAD;
393                     z.msg = "unknown compression method";
394                     z.istate.marker = 5; // can't try inflateSync
395                     break;
396                 }
397                 z.istate.mode = GZIP_FLG;
398             case GZIP_FLG:
399                 if (z.avail_in == 0) {
400                     return r;
401                 }
402                 r = f;
403                 z.avail_in --;
404                 z.total_in ++;
405                 gzipFlag = z.next_in[z.next_in_index ++] & 0xff;
406 
407                 if ((gzipFlag & 0xE2) != 0) {
408                     z.istate.mode = BAD;
409                     z.msg = "unsupported flag";
410                     z.istate.marker = 5; // can't try inflateSync
411                     break;
412                 }
413                 gzipBytesToRead = 6;
414                 z.istate.mode = GZIP_MTIME_XFL_OS;
415             case GZIP_MTIME_XFL_OS:
416                 while (gzipBytesToRead > 0) {
417                     if (z.avail_in == 0) {
418                         return r;
419                     }
420                     r = f;
421                     z.avail_in --;
422                     z.total_in ++;
423                     z.next_in_index ++;
424                     gzipBytesToRead --;
425                 }
426                 z.istate.mode = GZIP_XLEN;
427                 gzipXLen = 0;
428                 gzipBytesToRead = 2;
429             case GZIP_XLEN:
430                 if ((gzipFlag & 4) != 0) {
431                     while (gzipBytesToRead > 0) {
432                         if (z.avail_in == 0) {
433                             return r;
434                         }
435                         r = f;
436                         z.avail_in --;
437                         z.total_in ++;
438                         gzipXLen |= (z.next_in[z.next_in_index ++] & 0xff) << (1 - gzipBytesToRead) * 8;
439                         gzipBytesToRead --;
440                     }
441                     gzipBytesToRead = gzipXLen;
442                     z.istate.mode = GZIP_FEXTRA;
443                 } else {
444                     z.istate.mode = GZIP_FNAME;
445                     break;
446                 }
447             case GZIP_FEXTRA:
448                 while (gzipBytesToRead > 0) {
449                     if (z.avail_in == 0) {
450                         return r;
451                     }
452                     r = f;
453                     z.avail_in --;
454                     z.total_in ++;
455                     z.next_in_index ++;
456                     gzipBytesToRead --;
457                 }
458                 z.istate.mode = GZIP_FNAME;
459             case GZIP_FNAME:
460                 if ((gzipFlag & 8) != 0) {
461                     do {
462                         if (z.avail_in == 0) {
463                             return r;
464                         }
465                         r = f;
466                         z.avail_in --;
467                         z.total_in ++;
468                     } while (z.next_in[z.next_in_index ++] != 0);
469                 }
470                 z.istate.mode = GZIP_FCOMMENT;
471             case GZIP_FCOMMENT:
472                 if ((gzipFlag & 16) != 0) {
473                     do {
474                         if (z.avail_in == 0) {
475                             return r;
476                         }
477                         r = f;
478                         z.avail_in --;
479                         z.total_in ++;
480                     } while (z.next_in[z.next_in_index ++] != 0);
481                 }
482                 gzipBytesToRead = 2;
483                 z.istate.mode = GZIP_FHCRC;
484             case GZIP_FHCRC:
485                 if ((gzipFlag & 2) != 0) {
486                     while (gzipBytesToRead > 0) {
487                         if (z.avail_in == 0) {
488                             return r;
489                         }
490                         r = f;
491                         z.avail_in --;
492                         z.total_in ++;
493                         z.next_in_index ++;
494                         gzipBytesToRead --;
495                     }
496                 }
497                 z.istate.mode = BLOCKS;
498                 break;
499             case GZIP_CRC32:
500                 while (gzipBytesToRead > 0) {
501                     if (z.avail_in == 0) {
502                         return r;
503                     }
504                     r = f;
505                     z.avail_in --;
506                     z.total_in ++;
507                     gzipBytesToRead --;
508                     z.istate.gzipCRC32 |= (z.next_in[z.next_in_index ++] & 0xff) << (3 - gzipBytesToRead) * 8;
509                 }
510 
511                 if (z.crc32 != z.istate.gzipCRC32) {
512                     z.istate.mode = BAD;
513                     z.msg = "incorrect CRC32 checksum";
514                     z.istate.marker = 5; // can't try inflateSync
515                     break;
516                 }
517                 gzipBytesToRead = 4;
518                 z.istate.mode = GZIP_ISIZE;
519             case GZIP_ISIZE:
520                 while (gzipBytesToRead > 0) {
521                     if (z.avail_in == 0) {
522                         return r;
523                     }
524                     r = f;
525                     z.avail_in --;
526                     z.total_in ++;
527                     gzipBytesToRead --;
528                     z.istate.gzipISize |= (z.next_in[z.next_in_index ++] & 0xff) << (3 - gzipBytesToRead) * 8;
529                 }
530 
531                 if (gzipUncompressedBytes != z.istate.gzipISize) {
532                     z.istate.mode = BAD;
533                     z.msg = "incorrect ISIZE checksum";
534                     z.istate.marker = 5; // can't try inflateSync
535                     break;
536                 }
537 
538                 z.istate.mode = DONE;
539                 break;
540             default:
541                 return JZlib.Z_STREAM_ERROR;
542             }
543         }
544     }
545 
546     int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength) {
547         int index = 0;
548         int length = dictLength;
549         if (z == null || z.istate == null || z.istate.mode != DICT0) {
550             return JZlib.Z_STREAM_ERROR;
551         }
552 
553         if (Adler32.adler32(1L, dictionary, 0, dictLength) != z.adler) {
554             return JZlib.Z_DATA_ERROR;
555         }
556 
557         z.adler = Adler32.adler32(0, null, 0, 0);
558 
559         if (length >= 1 << z.istate.wbits) {
560             length = (1 << z.istate.wbits) - 1;
561             index = dictLength - length;
562         }
563         z.istate.blocks.set_dictionary(dictionary, index, length);
564         z.istate.mode = BLOCKS;
565         return JZlib.Z_OK;
566     }
567 
568     private static final byte[] mark = { (byte) 0, (byte) 0, (byte) 0xff, (byte) 0xff };
569 
570     int inflateSync(ZStream z) {
571         int n; // number of bytes to look at
572         int p; // pointer to bytes
573         int m; // number of marker bytes found in a row
574         long r, w; // temporaries to save total_in and total_out
575 
576         // set up
577         if (z == null || z.istate == null) {
578             return JZlib.Z_STREAM_ERROR;
579         }
580         if (z.istate.mode != BAD) {
581             z.istate.mode = BAD;
582             z.istate.marker = 0;
583         }
584         if ((n = z.avail_in) == 0) {
585             return JZlib.Z_BUF_ERROR;
586         }
587         p = z.next_in_index;
588         m = z.istate.marker;
589 
590         // search
591         while (n != 0 && m < 4) {
592             if (z.next_in[p] == mark[m]) {
593                 m ++;
594             } else if (z.next_in[p] != 0) {
595                 m = 0;
596             } else {
597                 m = 4 - m;
598             }
599             p ++;
600             n --;
601         }
602 
603         // restore
604         z.total_in += p - z.next_in_index;
605         z.next_in_index = p;
606         z.avail_in = n;
607         z.istate.marker = m;
608 
609         // return no joy or set up to restart on a new block
610         if (m != 4) {
611             return JZlib.Z_DATA_ERROR;
612         }
613         r = z.total_in;
614         w = z.total_out;
615         inflateReset(z);
616         z.total_in = r;
617         z.total_out = w;
618         z.istate.mode = BLOCKS;
619         return JZlib.Z_OK;
620     }
621 }