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