inflate.c revision 17651
1/* inflate.c -- zlib interface to inflate modules
2 * Copyright (C) 1995-1996 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
9struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
10
11/* inflate private state */
12struct internal_state {
13
14  /* mode */
15  enum {
16      METHOD,   /* waiting for method byte */
17      FLAG,     /* waiting for flag byte */
18      DICT4,    /* four dictionary check bytes to go */
19      DICT3,    /* three dictionary check bytes to go */
20      DICT2,    /* two dictionary check bytes to go */
21      DICT1,    /* one dictionary check byte to go */
22      DICT0,    /* waiting for inflateSetDictionary */
23      BLOCKS,   /* decompressing blocks */
24      CHECK4,   /* four check bytes to go */
25      CHECK3,   /* three check bytes to go */
26      CHECK2,   /* two check bytes to go */
27      CHECK1,   /* one check byte to go */
28      DONE,     /* finished check, done */
29      BAD}      /* got an error--stay here */
30    mode;               /* current inflate mode */
31
32  /* mode dependent information */
33  union {
34    uInt method;        /* if FLAGS, method byte */
35    struct {
36      uLong was;                /* computed check value */
37      uLong need;               /* stream check value */
38    } check;            /* if CHECK, check values to compare */
39    uInt marker;        /* if BAD, inflateSync's marker bytes count */
40  } sub;        /* submode */
41
42  /* mode independent information */
43  int  nowrap;          /* flag for no wrapper */
44  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
45  inflate_blocks_statef
46    *blocks;            /* current inflate_blocks state */
47
48};
49
50
51int inflateReset(z)
52z_streamp z;
53{
54  uLong c;
55
56  if (z == Z_NULL || z->state == Z_NULL)
57    return Z_STREAM_ERROR;
58  z->total_in = z->total_out = 0;
59  z->msg = Z_NULL;
60  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
61  inflate_blocks_reset(z->state->blocks, z, &c);
62  Trace((stderr, "inflate: reset\n"));
63  return Z_OK;
64}
65
66
67int inflateEnd(z)
68z_streamp z;
69{
70  uLong c;
71
72  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
73    return Z_STREAM_ERROR;
74  if (z->state->blocks != Z_NULL)
75    inflate_blocks_free(z->state->blocks, z, &c);
76  ZFREE(z, z->state);
77  z->state = Z_NULL;
78  Trace((stderr, "inflate: end\n"));
79  return Z_OK;
80}
81
82
83int inflateInit2_(z, w, version, stream_size)
84z_streamp z;
85int w;
86const char *version;
87int stream_size;
88{
89  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
90      stream_size != sizeof(z_stream))
91      return Z_VERSION_ERROR;
92
93  /* initialize state */
94  if (z == Z_NULL)
95    return Z_STREAM_ERROR;
96  z->msg = Z_NULL;
97  if (z->zalloc == Z_NULL)
98  {
99    z->zalloc = zcalloc;
100    z->opaque = (voidpf)0;
101  }
102  if (z->zfree == Z_NULL) z->zfree = zcfree;
103  if ((z->state = (struct internal_state FAR *)
104       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
105    return Z_MEM_ERROR;
106  z->state->blocks = Z_NULL;
107
108  /* handle undocumented nowrap option (no zlib header or check) */
109  z->state->nowrap = 0;
110  if (w < 0)
111  {
112    w = - w;
113    z->state->nowrap = 1;
114  }
115
116  /* set window size */
117  if (w < 8 || w > 15)
118  {
119    inflateEnd(z);
120    return Z_STREAM_ERROR;
121  }
122  z->state->wbits = (uInt)w;
123
124  /* create inflate_blocks state */
125  if ((z->state->blocks =
126      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
127      == Z_NULL)
128  {
129    inflateEnd(z);
130    return Z_MEM_ERROR;
131  }
132  Trace((stderr, "inflate: allocated\n"));
133
134  /* reset state */
135  inflateReset(z);
136  return Z_OK;
137}
138
139
140int inflateInit_(z, version, stream_size)
141z_streamp z;
142const char *version;
143int stream_size;
144{
145  return inflateInit2_(z, DEF_WBITS, version, stream_size);
146}
147
148
149#define NEEDBYTE {if(z->avail_in==0)return r;r=Z_OK;}
150#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
151
152int inflate(z, f)
153z_streamp z;
154int f;
155{
156  int r;
157  uInt b;
158
159  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL || f < 0)
160    return Z_STREAM_ERROR;
161  r = Z_BUF_ERROR;
162  while (1) switch (z->state->mode)
163  {
164    case METHOD:
165      NEEDBYTE
166      if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
167      {
168        z->state->mode = BAD;
169        z->msg = (char*)"unknown compression method";
170        z->state->sub.marker = 5;       /* can't try inflateSync */
171        break;
172      }
173      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
174      {
175        z->state->mode = BAD;
176        z->msg = (char*)"invalid window size";
177        z->state->sub.marker = 5;       /* can't try inflateSync */
178        break;
179      }
180      z->state->mode = FLAG;
181    case FLAG:
182      NEEDBYTE
183      b = NEXTBYTE;
184      if (((z->state->sub.method << 8) + b) % 31)
185      {
186        z->state->mode = BAD;
187        z->msg = (char*)"incorrect header check";
188        z->state->sub.marker = 5;       /* can't try inflateSync */
189        break;
190      }
191      Trace((stderr, "inflate: zlib header ok\n"));
192      if (!(b & PRESET_DICT))
193      {
194        z->state->mode = BLOCKS;
195	break;
196      }
197      z->state->mode = DICT4;
198    case DICT4:
199      NEEDBYTE
200      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
201      z->state->mode = DICT3;
202    case DICT3:
203      NEEDBYTE
204      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
205      z->state->mode = DICT2;
206    case DICT2:
207      NEEDBYTE
208      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
209      z->state->mode = DICT1;
210    case DICT1:
211      NEEDBYTE
212      z->state->sub.check.need += (uLong)NEXTBYTE;
213      z->adler = z->state->sub.check.need;
214      z->state->mode = DICT0;
215      return Z_NEED_DICT;
216    case DICT0:
217      z->state->mode = BAD;
218      z->msg = (char*)"need dictionary";
219      z->state->sub.marker = 0;       /* can try inflateSync */
220      return Z_STREAM_ERROR;
221    case BLOCKS:
222      r = inflate_blocks(z->state->blocks, z, r);
223      if (r == Z_DATA_ERROR)
224      {
225        z->state->mode = BAD;
226        z->state->sub.marker = 0;       /* can try inflateSync */
227        break;
228      }
229      if (r != Z_STREAM_END)
230        return r;
231      r = Z_OK;
232      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
233      if (z->state->nowrap)
234      {
235        z->state->mode = DONE;
236        break;
237      }
238      z->state->mode = CHECK4;
239    case CHECK4:
240      NEEDBYTE
241      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
242      z->state->mode = CHECK3;
243    case CHECK3:
244      NEEDBYTE
245      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
246      z->state->mode = CHECK2;
247    case CHECK2:
248      NEEDBYTE
249      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
250      z->state->mode = CHECK1;
251    case CHECK1:
252      NEEDBYTE
253      z->state->sub.check.need += (uLong)NEXTBYTE;
254
255      if (z->state->sub.check.was != z->state->sub.check.need)
256      {
257        z->state->mode = BAD;
258        z->msg = (char*)"incorrect data check";
259        z->state->sub.marker = 5;       /* can't try inflateSync */
260        break;
261      }
262      Trace((stderr, "inflate: zlib check ok\n"));
263      z->state->mode = DONE;
264    case DONE:
265      return Z_STREAM_END;
266    case BAD:
267      return Z_DATA_ERROR;
268    default:
269      return Z_STREAM_ERROR;
270  }
271}
272
273
274int inflateSetDictionary(z, dictionary, dictLength)
275z_streamp z;
276const Bytef *dictionary;
277uInt  dictLength;
278{
279  uInt length = dictLength;
280
281  if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
282    return Z_STREAM_ERROR;
283
284  if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
285  z->adler = 1L;
286
287  if (length >= ((uInt)1<<z->state->wbits))
288  {
289    length = (1<<z->state->wbits)-1;
290    dictionary += dictLength - length;
291  }
292  inflate_set_dictionary(z->state->blocks, dictionary, length);
293  z->state->mode = BLOCKS;
294  return Z_OK;
295}
296
297
298int inflateSync(z)
299z_streamp z;
300{
301  uInt n;       /* number of bytes to look at */
302  Bytef *p;     /* pointer to bytes */
303  uInt m;       /* number of marker bytes found in a row */
304  uLong r, w;   /* temporaries to save total_in and total_out */
305
306  /* set up */
307  if (z == Z_NULL || z->state == Z_NULL)
308    return Z_STREAM_ERROR;
309  if (z->state->mode != BAD)
310  {
311    z->state->mode = BAD;
312    z->state->sub.marker = 0;
313  }
314  if ((n = z->avail_in) == 0)
315    return Z_BUF_ERROR;
316  p = z->next_in;
317  m = z->state->sub.marker;
318
319  /* search */
320  while (n && m < 4)
321  {
322    if (*p == (Byte)(m < 2 ? 0 : 0xff))
323      m++;
324    else if (*p)
325      m = 0;
326    else
327      m = 4 - m;
328    p++, n--;
329  }
330
331  /* restore */
332  z->total_in += p - z->next_in;
333  z->next_in = p;
334  z->avail_in = n;
335  z->state->sub.marker = m;
336
337  /* return no joy or set up to restart on a new block */
338  if (m != 4)
339    return Z_DATA_ERROR;
340  r = z->total_in;  w = z->total_out;
341  inflateReset(z);
342  z->total_in = r;  z->total_out = w;
343  z->state->mode = BLOCKS;
344  return Z_OK;
345}
346