]>
Commit | Line | Data |
---|---|---|
0763e16d JW |
1 | /* -*-mode:java; c-basic-offset:2; -*- */ |
2 | /* | |
3 | Copyright (c) 2000,2001,2002,2003 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 | int mode; // current inflate mode | |
78 | ||
79 | // mode dependent information | |
80 | int method; // if FLAGS, method byte | |
81 | ||
82 | // if CHECK, check values to compare | |
83 | long[] was=new long[1] ; // computed check value | |
84 | long need; // stream check value | |
85 | ||
86 | // if BAD, inflateSync's marker bytes count | |
87 | int marker; | |
88 | ||
89 | // mode independent information | |
90 | int nowrap; // flag for no wrapper | |
91 | int wbits; // log2(window size) (8..15, defaults to 15) | |
92 | ||
93 | InfBlocks blocks; // current inflate_blocks state | |
94 | ||
95 | int inflateReset(ZStream z){ | |
96 | if(z == null || z.istate == null) return Z_STREAM_ERROR; | |
97 | ||
98 | z.total_in = z.total_out = 0; | |
99 | z.msg = null; | |
100 | z.istate.mode = z.istate.nowrap!=0 ? BLOCKS : METHOD; | |
101 | z.istate.blocks.reset(z, null); | |
102 | return Z_OK; | |
103 | } | |
104 | ||
105 | int inflateEnd(ZStream z){ | |
106 | if(blocks != null) | |
107 | blocks.free(z); | |
108 | blocks=null; | |
109 | // ZFREE(z, z->state); | |
110 | return Z_OK; | |
111 | } | |
112 | ||
113 | int inflateInit(ZStream z, int w){ | |
114 | z.msg = null; | |
115 | blocks = null; | |
116 | ||
117 | // handle undocumented nowrap option (no zlib header or check) | |
118 | nowrap = 0; | |
119 | if(w < 0){ | |
120 | w = - w; | |
121 | nowrap = 1; | |
122 | } | |
123 | ||
124 | // set window size | |
125 | if(w<8 ||w>15){ | |
126 | inflateEnd(z); | |
127 | return Z_STREAM_ERROR; | |
128 | } | |
129 | wbits=w; | |
130 | ||
131 | z.istate.blocks=new InfBlocks(z, | |
132 | z.istate.nowrap!=0 ? null : this, | |
133 | 1<<w); | |
134 | ||
135 | // reset state | |
136 | inflateReset(z); | |
137 | return Z_OK; | |
138 | } | |
139 | ||
140 | int inflate(ZStream z, int f){ | |
141 | int r; | |
142 | int b; | |
143 | ||
144 | if(z == null || z.istate == null || z.next_in == null) | |
145 | return Z_STREAM_ERROR; | |
146 | f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; | |
147 | r = Z_BUF_ERROR; | |
148 | while (true){ | |
149 | //System.out.println("mode: "+z.istate.mode); | |
150 | switch (z.istate.mode){ | |
151 | case METHOD: | |
152 | ||
153 | if(z.avail_in==0)return r;r=f; | |
154 | ||
155 | z.avail_in--; z.total_in++; | |
156 | if(((z.istate.method = z.next_in[z.next_in_index++])&0xf)!=Z_DEFLATED){ | |
157 | z.istate.mode = BAD; | |
158 | z.msg="unknown compression method"; | |
159 | z.istate.marker = 5; // can't try inflateSync | |
160 | break; | |
161 | } | |
162 | if((z.istate.method>>4)+8>z.istate.wbits){ | |
163 | z.istate.mode = BAD; | |
164 | z.msg="invalid window size"; | |
165 | z.istate.marker = 5; // can't try inflateSync | |
166 | break; | |
167 | } | |
168 | z.istate.mode=FLAG; | |
169 | case FLAG: | |
170 | ||
171 | if(z.avail_in==0)return r;r=f; | |
172 | ||
173 | z.avail_in--; z.total_in++; | |
174 | b = (z.next_in[z.next_in_index++])&0xff; | |
175 | ||
176 | if((((z.istate.method << 8)+b) % 31)!=0){ | |
177 | z.istate.mode = BAD; | |
178 | z.msg = "incorrect header check"; | |
179 | z.istate.marker = 5; // can't try inflateSync | |
180 | break; | |
181 | } | |
182 | ||
183 | if((b&PRESET_DICT)==0){ | |
184 | z.istate.mode = BLOCKS; | |
185 | break; | |
186 | } | |
187 | z.istate.mode = DICT4; | |
188 | case DICT4: | |
189 | ||
190 | if(z.avail_in==0)return r;r=f; | |
191 | ||
192 | z.avail_in--; z.total_in++; | |
193 | z.istate.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; | |
194 | z.istate.mode=DICT3; | |
195 | case DICT3: | |
196 | ||
197 | if(z.avail_in==0)return r;r=f; | |
198 | ||
199 | z.avail_in--; z.total_in++; | |
200 | z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; | |
201 | z.istate.mode=DICT2; | |
202 | case DICT2: | |
203 | ||
204 | if(z.avail_in==0)return r;r=f; | |
205 | ||
206 | z.avail_in--; z.total_in++; | |
207 | z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; | |
208 | z.istate.mode=DICT1; | |
209 | case DICT1: | |
210 | ||
211 | if(z.avail_in==0)return r;r=f; | |
212 | ||
213 | z.avail_in--; z.total_in++; | |
214 | z.istate.need += (z.next_in[z.next_in_index++]&0xffL); | |
215 | z.adler = z.istate.need; | |
216 | z.istate.mode = DICT0; | |
217 | return Z_NEED_DICT; | |
218 | case DICT0: | |
219 | z.istate.mode = BAD; | |
220 | z.msg = "need dictionary"; | |
221 | z.istate.marker = 0; // can try inflateSync | |
222 | return Z_STREAM_ERROR; | |
223 | case BLOCKS: | |
224 | ||
225 | r = z.istate.blocks.proc(z, r); | |
226 | if(r == Z_DATA_ERROR){ | |
227 | z.istate.mode = BAD; | |
228 | z.istate.marker = 0; // can try inflateSync | |
229 | break; | |
230 | } | |
231 | if(r == Z_OK){ | |
232 | r = f; | |
233 | } | |
234 | if(r != Z_STREAM_END){ | |
235 | return r; | |
236 | } | |
237 | r = f; | |
238 | z.istate.blocks.reset(z, z.istate.was); | |
239 | if(z.istate.nowrap!=0){ | |
240 | z.istate.mode=DONE; | |
241 | break; | |
242 | } | |
243 | z.istate.mode=CHECK4; | |
244 | case CHECK4: | |
245 | ||
246 | if(z.avail_in==0)return r;r=f; | |
247 | ||
248 | z.avail_in--; z.total_in++; | |
249 | z.istate.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; | |
250 | z.istate.mode=CHECK3; | |
251 | case CHECK3: | |
252 | ||
253 | if(z.avail_in==0)return r;r=f; | |
254 | ||
255 | z.avail_in--; z.total_in++; | |
256 | z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; | |
257 | z.istate.mode = CHECK2; | |
258 | case CHECK2: | |
259 | ||
260 | if(z.avail_in==0)return r;r=f; | |
261 | ||
262 | z.avail_in--; z.total_in++; | |
263 | z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; | |
264 | z.istate.mode = CHECK1; | |
265 | case CHECK1: | |
266 | ||
267 | if(z.avail_in==0)return r;r=f; | |
268 | ||
269 | z.avail_in--; z.total_in++; | |
270 | z.istate.need+=(z.next_in[z.next_in_index++]&0xffL); | |
271 | ||
272 | if(((int)(z.istate.was[0])) != ((int)(z.istate.need))){ | |
273 | z.istate.mode = BAD; | |
274 | z.msg = "incorrect data check"; | |
275 | z.istate.marker = 5; // can't try inflateSync | |
276 | break; | |
277 | } | |
278 | ||
279 | z.istate.mode = DONE; | |
280 | case DONE: | |
281 | return Z_STREAM_END; | |
282 | case BAD: | |
283 | return Z_DATA_ERROR; | |
284 | default: | |
285 | return Z_STREAM_ERROR; | |
286 | } | |
287 | } | |
288 | } | |
289 | ||
290 | ||
291 | int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength){ | |
292 | int index=0; | |
293 | int length = dictLength; | |
294 | if(z==null || z.istate == null|| z.istate.mode != DICT0) | |
295 | return Z_STREAM_ERROR; | |
296 | ||
297 | if(z._adler.adler32(1L, dictionary, 0, dictLength)!=z.adler){ | |
298 | return Z_DATA_ERROR; | |
299 | } | |
300 | ||
301 | z.adler = z._adler.adler32(0, null, 0, 0); | |
302 | ||
303 | if(length >= (1<<z.istate.wbits)){ | |
304 | length = (1<<z.istate.wbits)-1; | |
305 | index=dictLength - length; | |
306 | } | |
307 | z.istate.blocks.set_dictionary(dictionary, index, length); | |
308 | z.istate.mode = BLOCKS; | |
309 | return Z_OK; | |
310 | } | |
311 | ||
312 | static private byte[] mark = {(byte)0, (byte)0, (byte)0xff, (byte)0xff}; | |
313 | ||
314 | int inflateSync(ZStream z){ | |
315 | int n; // number of bytes to look at | |
316 | int p; // pointer to bytes | |
317 | int m; // number of marker bytes found in a row | |
318 | long r, w; // temporaries to save total_in and total_out | |
319 | ||
320 | // set up | |
321 | if(z == null || z.istate == null) | |
322 | return Z_STREAM_ERROR; | |
323 | if(z.istate.mode != BAD){ | |
324 | z.istate.mode = BAD; | |
325 | z.istate.marker = 0; | |
326 | } | |
327 | if((n=z.avail_in)==0) | |
328 | return Z_BUF_ERROR; | |
329 | p=z.next_in_index; | |
330 | m=z.istate.marker; | |
331 | ||
332 | // search | |
333 | while (n!=0 && m < 4){ | |
334 | if(z.next_in[p] == mark[m]){ | |
335 | m++; | |
336 | } | |
337 | else if(z.next_in[p]!=0){ | |
338 | m = 0; | |
339 | } | |
340 | else{ | |
341 | m = 4 - m; | |
342 | } | |
343 | p++; n--; | |
344 | } | |
345 | ||
346 | // restore | |
347 | z.total_in += p-z.next_in_index; | |
348 | z.next_in_index = p; | |
349 | z.avail_in = n; | |
350 | z.istate.marker = m; | |
351 | ||
352 | // return no joy or set up to restart on a new block | |
353 | if(m != 4){ | |
354 | return Z_DATA_ERROR; | |
355 | } | |
356 | r=z.total_in; w=z.total_out; | |
357 | inflateReset(z); | |
358 | z.total_in=r; z.total_out = w; | |
359 | z.istate.mode = BLOCKS; | |
360 | return Z_OK; | |
361 | } | |
362 | ||
363 | // Returns true if inflate is currently at the end of a block generated | |
364 | // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP | |
365 | // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH | |
366 | // but removes the length bytes of the resulting empty stored block. When | |
367 | // decompressing, PPP checks that at the end of input packet, inflate is | |
368 | // waiting for these length bytes. | |
369 | int inflateSyncPoint(ZStream z){ | |
370 | if(z == null || z.istate == null || z.istate.blocks == null) | |
371 | return Z_STREAM_ERROR; | |
372 | return z.istate.blocks.sync_point(); | |
373 | } | |
374 | } |