inflate.c 8.6 KB
Newer Older
M
Mark Adler 已提交
1
/* inflate.c -- zlib interface to inflate modules
M
Mark Adler 已提交
2
 * Copyright (C) 1995-1996 Mark Adler
M
Mark Adler 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15
 * For conditions of distribution and use, see copyright notice in zlib.h 
 */

#include "zutil.h"
#include "infblock.h"

struct inflate_blocks_state {int dummy;}; /* for buggy compilers */

/* inflate private state */
struct internal_state {

  /* mode */
  enum {
M
Mark Adler 已提交
16 17
      METHOD,   /* waiting for method byte */
      FLAG,     /* waiting for flag byte */
M
Mark Adler 已提交
18 19 20 21 22
      DICT4,    /* four dictionary check bytes to go */
      DICT3,    /* three dictionary check bytes to go */
      DICT2,    /* two dictionary check bytes to go */
      DICT1,    /* one dictionary check byte to go */
      DICT0,    /* waiting for inflateSetDictionary */
M
Mark Adler 已提交
23 24 25 26 27 28 29 30
      BLOCKS,   /* decompressing blocks */
      CHECK4,   /* four check bytes to go */
      CHECK3,   /* three check bytes to go */
      CHECK2,   /* two check bytes to go */
      CHECK1,   /* one check byte to go */
      DONE,     /* finished check, done */
      BAD}      /* got an error--stay here */
    mode;               /* current inflate mode */
M
Mark Adler 已提交
31 32 33

  /* mode dependent information */
  union {
M
Mark Adler 已提交
34
    uInt method;        /* if FLAGS, method byte */
M
Mark Adler 已提交
35
    struct {
M
Mark Adler 已提交
36 37 38
      uLong was;                /* computed check value */
      uLong need;               /* stream check value */
    } check;            /* if CHECK, check values to compare */
M
Mark Adler 已提交
39 40
    uInt marker;        /* if BAD, inflateSync's marker bytes count */
  } sub;        /* submode */
M
Mark Adler 已提交
41 42

  /* mode independent information */
M
Mark Adler 已提交
43 44
  int  nowrap;          /* flag for no wrapper */
  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
M
Mark Adler 已提交
45
  inflate_blocks_statef 
M
Mark Adler 已提交
46
    *blocks;            /* current inflate_blocks state */
M
Mark Adler 已提交
47

M
Mark Adler 已提交
48 49 50
};


M
Mark Adler 已提交
51
int inflateReset(z)
M
Mark Adler 已提交
52
z_stream *z;
M
Mark Adler 已提交
53
{
M
Mark Adler 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
  uLong c;

  if (z == Z_NULL || z->state == Z_NULL)
    return Z_STREAM_ERROR;
  z->total_in = z->total_out = 0;
  z->msg = Z_NULL;
  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
  inflate_blocks_reset(z->state->blocks, z, &c);
  Trace((stderr, "inflate: reset\n"));
  return Z_OK;
}


int inflateEnd(z)
z_stream *z;
{
  uLong c;

  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
    return Z_STREAM_ERROR;
  if (z->state->blocks != Z_NULL)
    inflate_blocks_free(z->state->blocks, z, &c);
  ZFREE(z, z->state);
  z->state = Z_NULL;
  Trace((stderr, "inflate: end\n"));
  return Z_OK;
M
Mark Adler 已提交
80 81
}

M
Mark Adler 已提交
82

M
Mark Adler 已提交
83
int inflateInit2_(z, w, version, stream_size)
M
Mark Adler 已提交
84
z_stream *z;
M
Mark Adler 已提交
85
int w;
M
Mark Adler 已提交
86 87
const char *version;
int stream_size;
M
Mark Adler 已提交
88
{
M
Mark Adler 已提交
89 90 91 92
  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
      stream_size != sizeof(z_stream))
      return Z_VERSION_ERROR;

M
Mark Adler 已提交
93
  /* initialize state */
M
Mark Adler 已提交
94 95
  if (z == Z_NULL)
    return Z_STREAM_ERROR;
M
Mark Adler 已提交
96 97 98 99 100 101
  z->msg = Z_NULL;
  if (z->zalloc == Z_NULL)
  {
    z->zalloc = zcalloc;
    z->opaque = (voidpf)0;
  }
M
Mark Adler 已提交
102
  if (z->zfree == Z_NULL) z->zfree = zcfree;
M
Mark Adler 已提交
103
  if ((z->state = (struct internal_state FAR *)
M
Mark Adler 已提交
104 105
       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
    return Z_MEM_ERROR;
M
Mark Adler 已提交
106
  z->state->blocks = Z_NULL;
M
Mark Adler 已提交
107

M
Mark Adler 已提交
108 109 110 111 112 113
  /* handle undocumented nowrap option (no zlib header or check) */
  z->state->nowrap = 0;
  if (w < 0)
  {
    w = - w;
    z->state->nowrap = 1;
M
Mark Adler 已提交
114
  }
M
Mark Adler 已提交
115 116 117 118

  /* set window size */
  if (w < 8 || w > 15)
  {
M
Mark Adler 已提交
119 120 121
    inflateEnd(z);
    return Z_STREAM_ERROR;
  }
M
Mark Adler 已提交
122 123 124 125
  z->state->wbits = (uInt)w;

  /* create inflate_blocks state */
  if ((z->state->blocks =
M
Mark Adler 已提交
126
      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
M
Mark Adler 已提交
127 128 129 130 131 132 133 134 135
      == Z_NULL)
  {
    inflateEnd(z);
    return Z_MEM_ERROR;
  }
  Trace((stderr, "inflate: allocated\n"));

  /* reset state */
  inflateReset(z);
M
Mark Adler 已提交
136 137 138 139
  return Z_OK;
}


M
Mark Adler 已提交
140
int inflateInit_(z, version, stream_size)
M
Mark Adler 已提交
141
z_stream *z;
M
Mark Adler 已提交
142 143
const char *version;
int stream_size;
M
Mark Adler 已提交
144
{
M
Mark Adler 已提交
145
  return inflateInit2_(z, DEF_WBITS, version, stream_size);
M
Mark Adler 已提交
146 147 148 149
}


#define NEEDBYTE {if(z->avail_in==0)return r;r=Z_OK;}
M
Mark Adler 已提交
150 151 152 153 154 155
#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)

int inflate(z, f)
z_stream *z;
int f;
{
M
Mark Adler 已提交
156
  int r = f;    /* to avoid warning about unused f */
M
Mark Adler 已提交
157 158
  uInt b;

M
Mark Adler 已提交
159
  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
M
Mark Adler 已提交
160 161 162 163 164
    return Z_STREAM_ERROR;
  r = Z_BUF_ERROR;
  while (1) switch (z->state->mode)
  {
    case METHOD:
M
Mark Adler 已提交
165
      NEEDBYTE
M
Mark Adler 已提交
166
      if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
M
Mark Adler 已提交
167
      {
M
Mark Adler 已提交
168
        z->state->mode = BAD;
M
Mark Adler 已提交
169
        z->msg = (char*)"unknown compression method";
M
Mark Adler 已提交
170 171
        z->state->sub.marker = 5;       /* can't try inflateSync */
        break;
M
Mark Adler 已提交
172
      }
M
Mark Adler 已提交
173
      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
M
Mark Adler 已提交
174
      {
M
Mark Adler 已提交
175
        z->state->mode = BAD;
M
Mark Adler 已提交
176
        z->msg = (char*)"invalid window size";
M
Mark Adler 已提交
177 178
        z->state->sub.marker = 5;       /* can't try inflateSync */
        break;
M
Mark Adler 已提交
179 180 181
      }
      z->state->mode = FLAG;
    case FLAG:
M
Mark Adler 已提交
182
      NEEDBYTE
M
Mark Adler 已提交
183
      b = NEXTBYTE;
M
Mark Adler 已提交
184 185
      if (((z->state->sub.method << 8) + b) % 31)
      {
M
Mark Adler 已提交
186
        z->state->mode = BAD;
M
Mark Adler 已提交
187
        z->msg = (char*)"incorrect header check";
M
Mark Adler 已提交
188 189
        z->state->sub.marker = 5;       /* can't try inflateSync */
        break;
M
Mark Adler 已提交
190
      }
M
Mark Adler 已提交
191
      Trace((stderr, "inflate: zlib header ok\n"));
M
Mark Adler 已提交
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
      if (!(b & PRESET_DICT))
      {
        z->state->mode = BLOCKS;
	break;
      }
      z->state->mode = DICT4;
    case DICT4:
      NEEDBYTE
      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
      z->state->mode = DICT3;
    case DICT3:
      NEEDBYTE
      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
      z->state->mode = DICT2;
    case DICT2:
      NEEDBYTE
      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
      z->state->mode = DICT1;
    case DICT1:
      NEEDBYTE
      z->state->sub.check.need += (uLong)NEXTBYTE;
      z->adler = z->state->sub.check.need;
      z->state->mode = DICT0;
      return Z_NEED_DICT;
    case DICT0:
      z->state->mode = BAD;
      z->msg = (char*)"need dictionary";
      z->state->sub.marker = 0;       /* can try inflateSync */
      return Z_STREAM_ERROR;
M
Mark Adler 已提交
221
    case BLOCKS:
M
Mark Adler 已提交
222 223 224 225
      r = inflate_blocks(z->state->blocks, z, r);
      if (r == Z_DATA_ERROR)
      {
        z->state->mode = BAD;
M
Mark Adler 已提交
226 227
        z->state->sub.marker = 0;       /* can try inflateSync */
        break;
M
Mark Adler 已提交
228 229
      }
      if (r != Z_STREAM_END)
M
Mark Adler 已提交
230
        return r;
M
Mark Adler 已提交
231 232
      r = Z_OK;
      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
M
Mark Adler 已提交
233 234
      if (z->state->nowrap)
      {
M
Mark Adler 已提交
235 236
        z->state->mode = DONE;
        break;
M
Mark Adler 已提交
237 238 239
      }
      z->state->mode = CHECK4;
    case CHECK4:
M
Mark Adler 已提交
240
      NEEDBYTE
M
Mark Adler 已提交
241 242 243
      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
      z->state->mode = CHECK3;
    case CHECK3:
M
Mark Adler 已提交
244
      NEEDBYTE
M
Mark Adler 已提交
245 246 247
      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
      z->state->mode = CHECK2;
    case CHECK2:
M
Mark Adler 已提交
248
      NEEDBYTE
M
Mark Adler 已提交
249 250 251
      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
      z->state->mode = CHECK1;
    case CHECK1:
M
Mark Adler 已提交
252
      NEEDBYTE
M
Mark Adler 已提交
253
      z->state->sub.check.need += (uLong)NEXTBYTE;
M
Mark Adler 已提交
254

M
Mark Adler 已提交
255 256
      if (z->state->sub.check.was != z->state->sub.check.need)
      {
M
Mark Adler 已提交
257
        z->state->mode = BAD;
M
Mark Adler 已提交
258
        z->msg = (char*)"incorrect data check";
M
Mark Adler 已提交
259 260
        z->state->sub.marker = 5;       /* can't try inflateSync */
        break;
M
Mark Adler 已提交
261
      }
M
Mark Adler 已提交
262
      Trace((stderr, "inflate: zlib check ok\n"));
M
Mark Adler 已提交
263 264 265
      z->state->mode = DONE;
    case DONE:
      return Z_STREAM_END;
M
Mark Adler 已提交
266
    case BAD:
M
Mark Adler 已提交
267 268 269 270 271 272 273
      return Z_DATA_ERROR;
    default:
      return Z_STREAM_ERROR;
  }
}


M
Mark Adler 已提交
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
int inflateSetDictionary(z, dictionary, dictLength)
z_stream *z;
const Bytef *dictionary;
uInt  dictLength;
{
  uInt length = dictLength;

  if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
    return Z_STREAM_ERROR;
  if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
  z->adler = 1L;

  if (length >= (1<<z->state->wbits))
  {
    length = (1<<z->state->wbits)-1;
    dictionary += dictLength - length;
  }
  inflate_set_dictionary(z->state->blocks, z, dictionary, length);
  z->state->mode = BLOCKS;
  return Z_OK;
}


M
Mark Adler 已提交
297
int inflateSync(z)
M
Mark Adler 已提交
298 299
z_stream *z;
{
M
Mark Adler 已提交
300
  uInt n;       /* number of bytes to look at */
M
Mark Adler 已提交
301
  Bytef *p;     /* pointer to bytes */
M
Mark Adler 已提交
302 303
  uInt m;       /* number of marker bytes found in a row */
  uLong r, w;   /* temporaries to save total_in and total_out */
M
Mark Adler 已提交
304

M
Mark Adler 已提交
305 306
  /* set up */
  if (z == Z_NULL || z->state == Z_NULL)
M
Mark Adler 已提交
307
    return Z_STREAM_ERROR;
M
Mark Adler 已提交
308
  if (z->state->mode != BAD)
M
Mark Adler 已提交
309 310
  {
    z->state->mode = BAD;
M
Mark Adler 已提交
311
    z->state->sub.marker = 0;
M
Mark Adler 已提交
312
  }
M
Mark Adler 已提交
313 314 315 316
  if ((n = z->avail_in) == 0)
    return Z_BUF_ERROR;
  p = z->next_in;
  m = z->state->sub.marker;
M
Mark Adler 已提交
317

M
Mark Adler 已提交
318 319 320
  /* search */
  while (n && m < 4)
  {
M
Mark Adler 已提交
321
    if (*p == (Byte)(m < 2 ? 0 : 0xff))
M
Mark Adler 已提交
322
      m++;
M
Mark Adler 已提交
323
    else if (*p)
M
Mark Adler 已提交
324
      m = 0;
M
Mark Adler 已提交
325 326
    else
      m = 4 - m;
M
Mark Adler 已提交
327 328
    p++, n--;
  }
M
Mark Adler 已提交
329

M
Mark Adler 已提交
330 331 332 333 334
  /* restore */
  z->total_in += p - z->next_in;
  z->next_in = p;
  z->avail_in = n;
  z->state->sub.marker = m;
M
Mark Adler 已提交
335

M
Mark Adler 已提交
336 337 338 339 340 341 342 343
  /* return no joy or set up to restart on a new block */
  if (m != 4)
    return Z_DATA_ERROR;
  r = z->total_in;  w = z->total_out;
  inflateReset(z);
  z->total_in = r;  z->total_out = w;
  z->state->mode = BLOCKS;
  return Z_OK;
M
Mark Adler 已提交
344
}