1 | /* inflate.c -- zlib interface to inflate modules |
2 | * Copyright (C) 1995-2002 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ |
5 | |
6 | #include "zutil.h" |
7 | #include "infblock.h" |
8 | |
9 | #define DONE INFLATE_DONE |
10 | #define BAD INFLATE_BAD |
11 | |
12 | typedef enum { |
13 | METHOD, /* waiting for method byte */ |
14 | FLAG, /* waiting for flag byte */ |
15 | DICT4, /* four dictionary check bytes to go */ |
16 | DICT3, /* three dictionary check bytes to go */ |
17 | DICT2, /* two dictionary check bytes to go */ |
18 | DICT1, /* one dictionary check byte to go */ |
19 | DICT0, /* waiting for inflateSetDictionary */ |
20 | BLOCKS, /* decompressing blocks */ |
21 | CHECK4, /* four check bytes to go */ |
22 | CHECK3, /* three check bytes to go */ |
23 | CHECK2, /* two check bytes to go */ |
24 | CHECK1, /* one check byte to go */ |
25 | DONE, /* finished check, done */ |
26 | BAD} /* got an error--stay here */ |
27 | inflate_mode; |
28 | |
29 | /* inflate private state */ |
30 | struct internal_state { |
31 | |
32 | /* mode */ |
33 | inflate_mode mode; /* current inflate mode */ |
34 | |
35 | /* mode dependent information */ |
36 | union { |
37 | uInt method; /* if FLAGS, method byte */ |
38 | struct { |
39 | uLong was; /* computed check value */ |
40 | uLong need; /* stream check value */ |
41 | } check; /* if CHECK, check values to compare */ |
42 | uInt marker; /* if BAD, inflateSync's marker bytes count */ |
43 | } sub; /* submode */ |
44 | |
45 | /* mode independent information */ |
46 | int nowrap; /* flag for no wrapper */ |
47 | uInt wbits; /* log2(window size) (8..15, defaults to 15) */ |
48 | inflate_blocks_statef |
49 | *blocks; /* current inflate_blocks state */ |
50 | |
51 | }; |
52 | |
53 | |
54 | ZEXPORT(int) inflateReset( /* z) */ |
55 | z_streamp z ) |
56 | { |
57 | if (z == Z_NULL || z->state == Z_NULL) |
58 | return Z_STREAM_ERROR; |
59 | z->total_in = z->total_out = 0; |
60 | z->msg = Z_NULL; |
61 | z->state->mode = z->state->nowrap ? BLOCKS : METHOD; |
62 | inflate_blocks_reset(z->state->blocks, z, Z_NULL); |
63 | Tracev((stderr, "inflate: reset\n" )); |
64 | return Z_OK; |
65 | } |
66 | |
67 | |
68 | ZEXPORT(int) inflateEnd( /* z) */ |
69 | z_streamp z ) |
70 | { |
71 | if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) |
72 | return Z_STREAM_ERROR; |
73 | if (z->state->blocks != Z_NULL) |
74 | inflate_blocks_free(z->state->blocks, z); |
75 | ZFREE(z, z->state); |
76 | z->state = Z_NULL; |
77 | Tracev((stderr, "inflate: end\n" )); |
78 | return Z_OK; |
79 | } |
80 | |
81 | |
82 | ZEXPORT(int) inflateInit2_( /* z, w, version, stream_size) */ |
83 | z_streamp z, |
84 | int w, |
85 | const char *version, |
86 | int stream_size ) |
87 | { |
88 | if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || |
89 | stream_size != sizeof(z_stream)) |
90 | return Z_VERSION_ERROR; |
91 | |
92 | /* initialize state */ |
93 | if (z == Z_NULL) |
94 | return Z_STREAM_ERROR; |
95 | z->msg = Z_NULL; |
96 | if (z->zalloc == Z_NULL) |
97 | { |
98 | z->zalloc = zcalloc; |
99 | z->opaque = (voidpf)0; |
100 | } |
101 | if (z->zfree == Z_NULL) z->zfree = zcfree; |
102 | if ((z->state = (struct internal_state FAR *) |
103 | ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) |
104 | return Z_MEM_ERROR; |
105 | z->state->blocks = Z_NULL; |
106 | |
107 | /* handle undocumented nowrap option (no zlib header or check) */ |
108 | z->state->nowrap = 0; |
109 | if (w < 0) |
110 | { |
111 | w = - w; |
112 | z->state->nowrap = 1; |
113 | } |
114 | |
115 | /* set window size */ |
116 | if (w < 8 || w > 15) |
117 | { |
118 | inflateEnd(z); |
119 | return Z_STREAM_ERROR; |
120 | } |
121 | z->state->wbits = (uInt)w; |
122 | |
123 | /* create inflate_blocks state */ |
124 | if ((z->state->blocks = |
125 | inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) |
126 | == Z_NULL) |
127 | { |
128 | inflateEnd(z); |
129 | return Z_MEM_ERROR; |
130 | } |
131 | Tracev((stderr, "inflate: allocated\n" )); |
132 | |
133 | /* reset state */ |
134 | inflateReset(z); |
135 | return Z_OK; |
136 | } |
137 | |
138 | |
139 | |
140 | #undef NEEDBYTE |
141 | #define NEEDBYTE {if(z->avail_in==0)return r;r=f;} |
142 | |
143 | #undef NEXTBYTE |
144 | #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) |
145 | |
146 | |
147 | ZEXPORT(int) inflate( /* z, f) */ |
148 | z_streamp z, |
149 | int f ) |
150 | { |
151 | int r; |
152 | uInt b; |
153 | |
154 | if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) |
155 | return Z_STREAM_ERROR; |
156 | f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; |
157 | r = Z_BUF_ERROR; |
158 | while (1) switch (z->state->mode) |
159 | { |
160 | case METHOD: |
161 | NEEDBYTE |
162 | if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) |
163 | { |
164 | z->state->mode = BAD; |
165 | z->msg = (char*)"unknown compression method" ; |
166 | z->state->sub.marker = 5; /* can't try inflateSync */ |
167 | break; |
168 | } |
169 | if ((z->state->sub.method >> 4) + 8 > z->state->wbits) |
170 | { |
171 | z->state->mode = BAD; |
172 | z->msg = (char*)"invalid window size" ; |
173 | z->state->sub.marker = 5; /* can't try inflateSync */ |
174 | break; |
175 | } |
176 | z->state->mode = FLAG; |
177 | case FLAG: |
178 | NEEDBYTE |
179 | b = NEXTBYTE; |
180 | if (((z->state->sub.method << 8) + b) % 31) |
181 | { |
182 | z->state->mode = BAD; |
183 | z->msg = (char*)"incorrect header check" ; |
184 | z->state->sub.marker = 5; /* can't try inflateSync */ |
185 | break; |
186 | } |
187 | Tracev((stderr, "inflate: zlib header ok\n" )); |
188 | if (!(b & PRESET_DICT)) |
189 | { |
190 | z->state->mode = BLOCKS; |
191 | break; |
192 | } |
193 | z->state->mode = DICT4; |
194 | case DICT4: |
195 | NEEDBYTE |
196 | z->state->sub.check.need = (uLong)NEXTBYTE << 24; |
197 | z->state->mode = DICT3; |
198 | case DICT3: |
199 | NEEDBYTE |
200 | z->state->sub.check.need += (uLong)NEXTBYTE << 16; |
201 | z->state->mode = DICT2; |
202 | case DICT2: |
203 | NEEDBYTE |
204 | z->state->sub.check.need += (uLong)NEXTBYTE << 8; |
205 | z->state->mode = DICT1; |
206 | case DICT1: |
207 | NEEDBYTE |
208 | z->state->sub.check.need += (uLong)NEXTBYTE; |
209 | z->adler = z->state->sub.check.need; |
210 | z->state->mode = DICT0; |
211 | return Z_NEED_DICT; |
212 | case DICT0: |
213 | z->state->mode = BAD; |
214 | z->msg = (char*)"need dictionary" ; |
215 | z->state->sub.marker = 0; /* can try inflateSync */ |
216 | return Z_STREAM_ERROR; |
217 | case BLOCKS: |
218 | r = inflate_blocks(z->state->blocks, z, r); |
219 | if (r == Z_DATA_ERROR) |
220 | { |
221 | z->state->mode = BAD; |
222 | z->state->sub.marker = 0; /* can try inflateSync */ |
223 | break; |
224 | } |
225 | if (r == Z_OK) |
226 | r = f; |
227 | if (r != Z_STREAM_END) |
228 | return r; |
229 | r = f; |
230 | inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); |
231 | if (z->state->nowrap) |
232 | { |
233 | z->state->mode = DONE; |
234 | break; |
235 | } |
236 | z->state->mode = CHECK4; |
237 | case CHECK4: |
238 | NEEDBYTE |
239 | z->state->sub.check.need = (uLong)NEXTBYTE << 24; |
240 | z->state->mode = CHECK3; |
241 | case CHECK3: |
242 | NEEDBYTE |
243 | z->state->sub.check.need += (uLong)NEXTBYTE << 16; |
244 | z->state->mode = CHECK2; |
245 | case CHECK2: |
246 | NEEDBYTE |
247 | z->state->sub.check.need += (uLong)NEXTBYTE << 8; |
248 | z->state->mode = CHECK1; |
249 | case CHECK1: |
250 | NEEDBYTE |
251 | z->state->sub.check.need += (uLong)NEXTBYTE; |
252 | |
253 | if (z->state->sub.check.was != z->state->sub.check.need) |
254 | { |
255 | z->state->mode = BAD; |
256 | z->msg = (char*)"incorrect data check" ; |
257 | z->state->sub.marker = 5; /* can't try inflateSync */ |
258 | break; |
259 | } |
260 | Tracev((stderr, "inflate: zlib check ok\n" )); |
261 | z->state->mode = DONE; |
262 | case DONE: |
263 | return Z_STREAM_END; |
264 | case BAD: |
265 | return Z_DATA_ERROR; |
266 | default: |
267 | return Z_STREAM_ERROR; |
268 | } |
269 | #ifdef NEED_DUMMY_RETURN |
270 | return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ |
271 | #endif |
272 | } |
273 | |
274 | |