- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# inflate.c

    00001 /* inflate.c -- zlib interface to inflate modules
    00002  * Copyright (C) 1995-2002 Mark Adler
    00003  * For conditions of distribution and use, see copyright notice in zlib.h
    00004  */
    00005
    00006 #include "zutil.h"
    00007 #include "infblock.h"
    00008
    00009 struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
    00010
    00011 typedef enum {
    00012       METHOD,   /* waiting for method byte */
    00013       FLAG,     /* waiting for flag byte */
    00014       DICT4,    /* four dictionary check bytes to go */
    00015       DICT3,    /* three dictionary check bytes to go */
    00016       DICT2,    /* two dictionary check bytes to go */
    00017       DICT1,    /* one dictionary check byte to go */
    00018       DICT0,    /* waiting for inflateSetDictionary */
    00019       BLOCKS,   /* decompressing blocks */
    00020       CHECK4,   /* four check bytes to go */
    00021       CHECK3,   /* three check bytes to go */
    00022       CHECK2,   /* two check bytes to go */
    00023       CHECK1,   /* one check byte to go */
    00024       DONE,     /* finished check, done */
    00025       BAD}      /* got an error--stay here */
    00026 inflate_mode;
    00027
    00028 /* inflate private state */
    00029 struct internal_state {
    00030
    00031   /* mode */
    00032   inflate_mode  mode;   /* current inflate mode */
    00033
    00034   /* mode dependent information */
    00035   union {
    00036     uInt method;        /* if FLAGS, method byte */
    00037     struct {
    00038       uLong was;                /* computed check value */
    00039       uLong need;               /* stream check value */
    00040     } check;            /* if CHECK, check values to compare */
    00041     uInt marker;        /* if BAD, inflateSync's marker bytes count */
    00042   } sub;        /* submode */
    00043
    00044   /* mode independent information */
    00045   int  nowrap;          /* flag for no wrapper */
    00046   uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
    00047   inflate_blocks_statef
    00048     *blocks;            /* current inflate_blocks state */
    00049
    00050 };
    00051
    00052
    00053 int ZEXPORT inflateReset(z)
    00054 z_streamp z;
    00055 {
    00056   if (z == Z_NULL || z->state == Z_NULL)
    00057     return Z_STREAM_ERROR;
    00058   z->total_in = z->total_out = 0;
    00059   z->msg = Z_NULL;
    00060   z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
    00061   inflate_blocks_reset(z->state->blocks, z, Z_NULL);
    00062   Tracev((stderr, "inflate: reset\n"));
    00063   return Z_OK;
    00064 }
    00065
    00066
    00067 int ZEXPORT inflateEnd(z)
    00068 z_streamp z;
    00069 {
    00070   if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
    00071     return Z_STREAM_ERROR;
    00072   if (z->state->blocks != Z_NULL)
    00073     inflate_blocks_free(z->state->blocks, z);
    00074   ZFREE(z, z->state);
    00075   z->state = Z_NULL;
    00076   Tracev((stderr, "inflate: end\n"));
    00077   return Z_OK;
    00078 }
    00079
    00080
    00081 int ZEXPORT inflateInit2_(z, w, version, stream_size)
    00082 z_streamp z;
    00083 int w;
    00084 const char *version;
    00085 int stream_size;
    00086 {
    00087   if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
    00088       stream_size != sizeof(z_stream))
    00089       return Z_VERSION_ERROR;
    00090
    00091   /* initialize state */
    00092   if (z == Z_NULL)
    00093     return Z_STREAM_ERROR;
    00094   z->msg = Z_NULL;
    00095   if (z->zalloc == Z_NULL)
    00096   {
    00097     z->zalloc = zcalloc;
    00098     z->opaque = (voidpf)0;
    00099   }
    00100   if (z->zfree == Z_NULL) z->zfree = zcfree;
    00101   if ((z->state = (struct internal_state FAR *)
    00102        ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
    00103     return Z_MEM_ERROR;
    00104   z->state->blocks = Z_NULL;
    00105
    00106   /* handle undocumented nowrap option (no zlib header or check) */
    00107   z->state->nowrap = 0;
    00108   if (w < 0)
    00109   {
    00110     w = - w;
    00111     z->state->nowrap = 1;
    00112   }
    00113
    00114   /* set window size */
    00115   if (w < 8 || w > 15)
    00116   {
    00117     inflateEnd(z);
    00118     return Z_STREAM_ERROR;
    00119   }
    00120   z->state->wbits = (uInt)w;
    00121
    00122   /* create inflate_blocks state */
    00123   if ((z->state->blocks =
    00124       inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
    00125       == Z_NULL)
    00126   {
    00127     inflateEnd(z);
    00128     return Z_MEM_ERROR;
    00129   }
    00130   Tracev((stderr, "inflate: allocated\n"));
    00131
    00132   /* reset state */
    00133   inflateReset(z);
    00134   return Z_OK;
    00135 }
    00136
    00137
    00138 int ZEXPORT inflateInit_(z, version, stream_size)
    00139 z_streamp z;
    00140 const char *version;
    00141 int stream_size;
    00142 {
    00143   return inflateInit2_(z, DEF_WBITS, version, stream_size);
    00144 }
    00145
    00146
    00147 #define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
    00148 #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
    00149
    00150 int ZEXPORT inflate(z, f)
    00151 z_streamp z;
    00152 int f;
    00153 {
    00154   int r;
    00155   uInt b;
    00156
    00157   if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
    00158     return Z_STREAM_ERROR;
    00159   f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
    00160   r = Z_BUF_ERROR;
    00161   while (1) switch (z->state->mode)
    00162   {
    00163     case METHOD:
    00164       NEEDBYTE
    00165       if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
    00166       {
    00167         z->state->mode = BAD;
    00168         z->msg = (char*)"unknown compression method";
    00169         z->state->sub.marker = 5;       /* can't try inflateSync */
    00170         break;
    00171       }
    00172       if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
    00173       {
    00174         z->state->mode = BAD;
    00175         z->msg = (char*)"invalid window size";
    00176         z->state->sub.marker = 5;       /* can't try inflateSync */
    00177         break;
    00178       }
    00179       z->state->mode = FLAG;
    00180     case FLAG:
    00181       NEEDBYTE
    00182       b = NEXTBYTE;
    00183       if (((z->state->sub.method << 8) + b) % 31)
    00184       {
    00185         z->state->mode = BAD;
    00186         z->msg = (char*)"incorrect header check";
    00187         z->state->sub.marker = 5;       /* can't try inflateSync */
    00188         break;
    00189       }
    00190       Tracev((stderr, "inflate: zlib header ok\n"));
    00191       if (!(b & PRESET_DICT))
    00192       {
    00193         z->state->mode = BLOCKS;
    00194         break;
    00195       }
    00196       z->state->mode = DICT4;
    00197     case DICT4:
    00198       NEEDBYTE
    00199       z->state->sub.check.need = (uLong)NEXTBYTE << 24;
    00200       z->state->mode = DICT3;
    00201     case DICT3:
    00202       NEEDBYTE
    00203       z->state->sub.check.need += (uLong)NEXTBYTE << 16;
    00204       z->state->mode = DICT2;
    00205     case DICT2:
    00206       NEEDBYTE
    00207       z->state->sub.check.need += (uLong)NEXTBYTE << 8;
    00208       z->state->mode = DICT1;
    00209     case DICT1:
    00210       NEEDBYTE
    00211       z->state->sub.check.need += (uLong)NEXTBYTE;
    00212       z->adler = z->state->sub.check.need;
    00213       z->state->mode = DICT0;
    00214       return Z_NEED_DICT;
    00215     case DICT0:
    00216       z->state->mode = BAD;
    00217       z->msg = (char*)"need dictionary";
    00218       z->state->sub.marker = 0;       /* can try inflateSync */
    00219       return Z_STREAM_ERROR;
    00220     case BLOCKS:
    00221       r = inflate_blocks(z->state->blocks, z, r);
    00222       if (r == Z_DATA_ERROR)
    00223       {
    00224         z->state->mode = BAD;
    00225         z->state->sub.marker = 0;       /* can try inflateSync */
    00226         break;
    00227       }
    00228       if (r == Z_OK)
    00229         r = f;
    00230       if (r != Z_STREAM_END)
    00231         return r;
    00232       r = f;
    00233       inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
    00234       if (z->state->nowrap)
    00235       {
    00236         z->state->mode = DONE;
    00237         break;
    00238       }
    00239       z->state->mode = CHECK4;
    00240     case CHECK4:
    00241       NEEDBYTE
    00242       z->state->sub.check.need = (uLong)NEXTBYTE << 24;
    00243       z->state->mode = CHECK3;
    00244     case CHECK3:
    00245       NEEDBYTE
    00246       z->state->sub.check.need += (uLong)NEXTBYTE << 16;
    00247       z->state->mode = CHECK2;
    00248     case CHECK2:
    00249       NEEDBYTE
    00250       z->state->sub.check.need += (uLong)NEXTBYTE << 8;
    00251       z->state->mode = CHECK1;
    00252     case CHECK1:
    00253       NEEDBYTE
    00254       z->state->sub.check.need += (uLong)NEXTBYTE;
    00255
    00256       if (z->state->sub.check.was != z->state->sub.check.need)
    00257       {
    00258         z->state->mode = BAD;
    00259         z->msg = (char*)"incorrect data check";
    00260         z->state->sub.marker = 5;       /* can't try inflateSync */
    00261         break;
    00262       }
    00263       Tracev((stderr, "inflate: zlib check ok\n"));
    00264       z->state->mode = DONE;
    00265     case DONE:
    00266       return Z_STREAM_END;
    00267     case BAD:
    00268       return Z_DATA_ERROR;
    00269     default:
    00270       return Z_STREAM_ERROR;
    00271   }
    00272 #ifdef NEED_DUMMY_RETURN
    00273   return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
    00274 #endif
    00275 }
    00276
    00277
    00278 int ZEXPORT inflateSetDictionary(z, dictionary, dictLength)
    00279 z_streamp z;
    00280 const Bytef *dictionary;
    00281 uInt  dictLength;
    00282 {
    00283   uInt length = dictLength;
    00284
    00285   if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
    00286     return Z_STREAM_ERROR;
    00287
    00288   if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
    00289   z->adler = 1L;
    00290
    00291   if (length >= ((uInt)1<<z->state->wbits))
    00292   {
    00293     length = (1<<z->state->wbits)-1;
    00294     dictionary += dictLength - length;
    00295   }
    00296   inflate_set_dictionary(z->state->blocks, dictionary, length);
    00297   z->state->mode = BLOCKS;
    00298   return Z_OK;
    00299 }
    00300
    00301
    00302 int ZEXPORT inflateSync(z)
    00303 z_streamp z;
    00304 {
    00305   uInt n;       /* number of bytes to look at */
    00306   Bytef *p;     /* pointer to bytes */
    00307   uInt m;       /* number of marker bytes found in a row */
    00308   uLong r, w;   /* temporaries to save total_in and total_out */
    00309
    00310   /* set up */
    00311   if (z == Z_NULL || z->state == Z_NULL)
    00312     return Z_STREAM_ERROR;
    00313   if (z->state->mode != BAD)
    00314   {
    00315     z->state->mode = BAD;
    00316     z->state->sub.marker = 0;
    00317   }
    00318   if ((n = z->avail_in) == 0)
    00319     return Z_BUF_ERROR;
    00320   p = z->next_in;
    00321   m = z->state->sub.marker;
    00322
    00323   /* search */
    00324   while (n && m < 4)
    00325   {
    00326     static const Byte mark[4] = {0, 0, 0xff, 0xff};
    00327     if (*p == mark[m])
    00328       m++;
    00329     else if (*p)
    00330       m = 0;
    00331     else
    00332       m = 4 - m;
    00333     p++, n--;
    00334   }
    00335
    00336   /* restore */
    00337   z->total_in += p - z->next_in;
    00338   z->next_in = p;
    00339   z->avail_in = n;
    00340   z->state->sub.marker = m;
    00341
    00342   /* return no joy or set up to restart on a new block */
    00343   if (m != 4)
    00344     return Z_DATA_ERROR;
    00345   r = z->total_in;  w = z->total_out;
    00346   inflateReset(z);
    00347   z->total_in = r;  z->total_out = w;
    00348   z->state->mode = BLOCKS;
    00349   return Z_OK;
    00350 }
    00351
    00352
    00353 /* Returns true if inflate is currently at the end of a block generated
    00354  * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
    00355  * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
    00356  * but removes the length bytes of the resulting empty stored block. When
    00357  * decompressing, PPP checks that at the end of input packet, inflate is
    00358  * waiting for these length bytes.
    00359  */
    00360 int ZEXPORT inflateSyncPoint(z)
    00361 z_streamp z;
    00362 {
    00363   if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
    00364     return Z_STREAM_ERROR;
    00365   return inflate_blocks_sync_point(z->state->blocks);
    00366 }