2
Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
4
Redistribution and use in source and binary forms, with or without
5
modification, are permitted provided that the following conditions are met:
7
1. Redistributions of source code must retain the above copyright notice,
8
this list of conditions and the following disclaimer.
10
2. Redistributions in binary form must reproduce the above copyright
11
notice, this list of conditions and the following disclaimer in
12
the documentation and/or other materials provided with the distribution.
14
3. The names of the authors may not be used to endorse or promote products
15
derived from this software without specific prior written permission.
17
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
18
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
19
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
20
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
21
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
This program is based on zlib-1.1.3, so all credit should go authors
29
Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
30
and contributors of zlib.
38
internal sealed class Inflate
40
private const int MAX_WBITS = 15;
42
private const int PRESET_DICT = unchecked((int)(0x20));
44
internal const int Z_NO_FLUSH = 0;
46
internal const int Z_PARTIAL_FLUSH = 1;
48
internal const int Z_SYNC_FLUSH = 2;
50
internal const int Z_FULL_FLUSH = 3;
52
internal const int Z_FINISH = 4;
54
private const int Z_DEFLATED = 8;
56
private const int Z_OK = 0;
58
private const int Z_STREAM_END = 1;
60
private const int Z_NEED_DICT = 2;
62
private const int Z_ERRNO = -1;
64
private const int Z_STREAM_ERROR = -2;
66
private const int Z_DATA_ERROR = -3;
68
private const int Z_MEM_ERROR = -4;
70
private const int Z_BUF_ERROR = -5;
72
private const int Z_VERSION_ERROR = -6;
74
private const int METHOD = 0;
76
private const int FLAG = 1;
78
private const int DICT4 = 2;
80
private const int DICT3 = 3;
82
private const int DICT2 = 4;
84
private const int DICT1 = 5;
86
private const int DICT0 = 6;
88
private const int BLOCKS = 7;
90
private const int CHECK4 = 8;
92
private const int CHECK3 = 9;
94
private const int CHECK2 = 10;
96
private const int CHECK1 = 11;
98
private const int DONE = 12;
100
private const int BAD = 13;
106
internal long[] was = new long[1];
116
internal InfBlocks blocks;
119
// preset dictionary flag in zlib header
120
// waiting for method byte
121
// waiting for flag byte
122
// four dictionary check bytes to go
123
// three dictionary check bytes to go
124
// two dictionary check bytes to go
125
// one dictionary check byte to go
126
// waiting for inflateSetDictionary
127
// decompressing blocks
128
// four check bytes to go
129
// three check bytes to go
130
// two check bytes to go
131
// one check byte to go
132
// finished check, done
133
// got an error--stay here
134
// current inflate mode
135
// mode dependent information
136
// if FLAGS, method byte
137
// if CHECK, check values to compare
138
// computed check value
139
// stream check value
140
// if BAD, inflateSync's marker bytes count
141
// mode independent information
142
// flag for no wrapper
143
// log2(window size) (8..15, defaults to 15)
144
// current inflate_blocks state
145
internal int InflateReset(ZStream z)
147
if (z == null || z.istate == null)
149
return Z_STREAM_ERROR;
151
z.total_in = z.total_out = 0;
153
z.istate.mode = z.istate.nowrap != 0 ? BLOCKS : METHOD;
154
z.istate.blocks.Reset(z, null);
158
internal int InflateEnd(ZStream z)
165
// ZFREE(z, z->state);
169
internal int InflateInit(ZStream z, int w)
173
// handle undocumented nowrap option (no zlib header or check)
184
return Z_STREAM_ERROR;
187
z.istate.blocks = new InfBlocks(z, z.istate.nowrap != 0 ? null : this, 1 << w);
193
internal int DoInflate(ZStream z, int f)
197
if (z == null || z.istate == null || z.next_in == null)
199
return Z_STREAM_ERROR;
201
f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
205
switch (z.istate.mode)
209
//System.out.println("mode: "+z.istate.mode);
217
if (((z.istate.method = z.next_in[z.next_in_index++]) & unchecked((int)(0xf))) !=
221
z.msg = "unknown compression method";
223
// can't try inflateSync
226
if ((z.istate.method >> 4) + 8 > z.istate.wbits)
229
z.msg = "invalid window size";
231
// can't try inflateSync
234
z.istate.mode = FLAG;
247
b = (z.next_in[z.next_in_index++]) & unchecked((int)(0xff));
248
if ((((z.istate.method << 8) + b) % 31) != 0)
251
z.msg = "incorrect header check";
253
// can't try inflateSync
256
if ((b & PRESET_DICT) == 0)
258
z.istate.mode = BLOCKS;
261
z.istate.mode = DICT4;
274
z.istate.need = ((z.next_in[z.next_in_index++] & unchecked((int)(0xff))) << 24) &
275
unchecked((long)(0xff000000L));
276
z.istate.mode = DICT3;
289
z.istate.need += ((z.next_in[z.next_in_index++] & unchecked((int)(0xff))) << 16)
290
& unchecked((long)(0xff0000L));
291
z.istate.mode = DICT2;
304
z.istate.need += ((z.next_in[z.next_in_index++] & unchecked((int)(0xff))) << 8) &
305
unchecked((long)(0xff00L));
306
z.istate.mode = DICT1;
319
z.istate.need += (z.next_in[z.next_in_index++] & unchecked((long)(0xffL)));
320
z.adler = z.istate.need;
321
z.istate.mode = DICT0;
328
z.msg = "need dictionary";
330
// can try inflateSync
331
return Z_STREAM_ERROR;
336
r = z.istate.blocks.Proc(z, r);
337
if (r == Z_DATA_ERROR)
341
// can try inflateSync
348
if (r != Z_STREAM_END)
353
z.istate.blocks.Reset(z, z.istate.was);
354
if (z.istate.nowrap != 0)
356
z.istate.mode = DONE;
359
z.istate.mode = CHECK4;
372
z.istate.need = ((z.next_in[z.next_in_index++] & unchecked((int)(0xff))) << 24) &
373
unchecked((long)(0xff000000L));
374
z.istate.mode = CHECK3;
387
z.istate.need += ((z.next_in[z.next_in_index++] & unchecked((int)(0xff))) << 16)
388
& unchecked((long)(0xff0000L));
389
z.istate.mode = CHECK2;
402
z.istate.need += ((z.next_in[z.next_in_index++] & unchecked((int)(0xff))) << 8) &
403
unchecked((long)(0xff00L));
404
z.istate.mode = CHECK1;
417
z.istate.need += (z.next_in[z.next_in_index++] & unchecked((long)(0xffL)));
418
if (((int)(z.istate.was[0])) != ((int)(z.istate.need)))
421
z.msg = "incorrect data check";
423
// can't try inflateSync
426
z.istate.mode = DONE;
442
return Z_STREAM_ERROR;
449
internal int InflateSetDictionary(ZStream z, byte[] dictionary, int dictLength)
452
int length = dictLength;
453
if (z == null || z.istate == null || z.istate.mode != DICT0)
455
return Z_STREAM_ERROR;
457
if (z._adler.Adler(1L, dictionary, 0, dictLength) != z.adler)
461
z.adler = z._adler.Adler(0, null, 0, 0);
462
if (length >= (1 << z.istate.wbits))
464
length = (1 << z.istate.wbits) - 1;
465
index = dictLength - length;
467
z.istate.blocks.Set_dictionary(dictionary, index, length);
468
z.istate.mode = BLOCKS;
472
private static byte[] mark = new byte[] { unchecked((byte)0), unchecked((byte)0),
473
unchecked((byte)unchecked((int)(0xff))), unchecked((byte)unchecked((int)(0xff)))
476
internal int InflateSync(ZStream z)
479
// number of bytes to look at
483
// number of marker bytes found in a row
486
// temporaries to save total_in and total_out
488
if (z == null || z.istate == null)
490
return Z_STREAM_ERROR;
492
if (z.istate.mode != BAD)
497
if ((n = z.avail_in) == 0)
504
while (n != 0 && m < 4)
506
if (z.next_in[p] == mark[m])
512
if (z.next_in[p] != 0)
525
z.total_in += p - z.next_in_index;
529
// return no joy or set up to restart on a new block
539
z.istate.mode = BLOCKS;
543
// Returns true if inflate is currently at the end of a block generated
544
// by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
545
// implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
546
// but removes the length bytes of the resulting empty stored block. When
547
// decompressing, PPP checks that at the end of input packet, inflate is
548
// waiting for these length bytes.
549
internal int InflateSyncPoint(ZStream z)
551
if (z == null || z.istate == null || z.istate.blocks == null)
553
return Z_STREAM_ERROR;
555
return z.istate.blocks.Sync_point();