aboutsummaryrefslogtreecommitdiff
path: root/source/unzip
diff options
context:
space:
mode:
authorKitty Draper2011-03-05 21:39:25 -0500
committerKitty Draper2011-03-05 21:39:25 -0500
commitd40ae99422e118188a7f48055dc340c6aca022aa (patch)
tree83ab93f49fd9e66e43bcd824091ae1dbcaa0c173 /source/unzip
downloadsnes9x2005-d40ae99422e118188a7f48055dc340c6aca022aa.tar.gz
snes9x2005-d40ae99422e118188a7f48055dc340c6aca022aa.tar.bz2
snes9x2005-d40ae99422e118188a7f48055dc340c6aca022aa.zip
first commit
Diffstat (limited to 'source/unzip')
-rw-r--r--source/unzip/explode.c1120
-rw-r--r--source/unzip/unreduce.c217
-rw-r--r--source/unzip/unshrink.c177
-rw-r--r--source/unzip/unz.h994
-rw-r--r--source/unzip/unzip.c1224
-rw-r--r--source/unzip/unzip.h285
-rw-r--r--source/unzip/unzipP.h125
7 files changed, 4142 insertions, 0 deletions
diff --git a/source/unzip/explode.c b/source/unzip/explode.c
new file mode 100644
index 0000000..6558a7b
--- /dev/null
+++ b/source/unzip/explode.c
@@ -0,0 +1,1120 @@
+/* explode.c -- Not copyrighted 1992 by Mark Adler
+ version c7, 27 June 1992 */
+
+
+/* You can do whatever you like with this source file, though I would
+ prefer that if you modify it and redistribute it that you include
+ comments to that effect with your name and the date. Thank you.
+
+ History:
+ vers date who what
+ ---- --------- -------------- ------------------------------------
+ c1 30 Mar 92 M. Adler explode that uses huft_build from inflate
+ (this gives over a 70% speed improvement
+ over the original unimplode.c, which
+ decoded a bit at a time)
+ c2 4 Apr 92 M. Adler fixed bug for file sizes a multiple of 32k.
+ c3 10 Apr 92 M. Adler added a little memory tracking if DEBUG
+ c4 11 Apr 92 M. Adler added NOMEMCPY do kill use of memcpy()
+ c5 21 Apr 92 M. Adler added the WSIZE #define to allow reducing
+ the 32K window size for specialized
+ applications.
+ c6 31 May 92 M. Adler added typecasts to eliminate some warnings
+ c7 27 Jun 92 G. Roelofs added more typecasts
+ */
+
+
+/*
+ Explode imploded (PKZIP method 6 compressed) data. This compression
+ method searches for as much of the current string of bytes (up to a length
+ of ~320) in the previous 4K or 8K bytes. If it doesn't find any matches
+ (of at least length 2 or 3), it codes the next byte. Otherwise, it codes
+ the length of the matched string and its distance backwards from the
+ current position. Single bytes ("literals") are preceded by a one (a
+ single bit) and are either uncoded (the eight bits go directly into the
+ compressed stream for a total of nine bits) or Huffman coded with a
+ supplied literal code tree. If literals are coded, then the minimum match
+ length is three, otherwise it is two.
+
+ There are therefore four kinds of imploded streams: 8K search with coded
+ literals (min match = 3), 4K search with coded literals (min match = 3),
+ 8K with uncoded literals (min match = 2), and 4K with uncoded literals
+ (min match = 2). The kind of stream is identified in two bits of a
+ general purpose bit flag that is outside of the compressed stream.
+
+ Distance-length pairs are always coded. Distance-length pairs for matched
+ strings are preceded by a zero bit (to distinguish them from literals) and
+ are always coded. The distance comes first and is either the low six (4K)
+ or low seven (8K) bits of the distance (uncoded), followed by the high six
+ bits of the distance coded. Then the length is six bits coded (0..63 +
+ min match length), and if the maximum such length is coded, then it's
+ followed by another eight bits (uncoded) to be added to the coded length.
+ This gives a match length range of 2..320 or 3..321 bytes.
+
+ The literal, length, and distance codes are all represented in a slightly
+ compressed form themselves. What is sent are the lengths of the codes for
+ each value, which is sufficient to construct the codes. Each byte of the
+ code representation is the code length (the low four bits representing
+ 1..16), and the number of values sequentially with that length (the high
+ four bits also representing 1..16). There are 256 literal code values (if
+ literals are coded), 64 length code values, and 64 distance code values,
+ in that order at the beginning of the compressed stream. Each set of code
+ values is preceded (redundantly) with a byte indicating how many bytes are
+ in the code description that follows, in the range 1..256.
+
+ The codes themselves are decoded using tables made by huft_build() from
+ the bit lengths. That routine and its comments are in the inflate.c
+ module.
+ */
+
+#include "unz.h" /* this must supply the slide[] (byte) array */
+#include "unzipP.h"
+//#include <stdlib.h>
+#include "ds2_malloc.h"
+
+#ifndef WSIZE
+# define WSIZE 0x8000 /* window size--must be a power of two, and at least
+ 8K for zip's implode method */
+#endif /* !WSIZE */
+
+
+struct huft {
+ byte e; /* number of extra bits or operation */
+ byte b; /* number of bits in this code or subcode */
+ union {
+ UWORD n; /* literal, length base, or distance base */
+ struct huft *t; /* pointer to next level of table */
+ } v;
+};
+
+/* Function prototypes */
+/* routines from inflate.c */
+extern unsigned hufts;
+int huft_build OF((unsigned *, unsigned, unsigned, UWORD *, UWORD *,
+ struct huft **, int *));
+int huft_free OF((struct huft *));
+void flush OF((unsigned));
+
+/* routines here */
+int get_tree OF((unsigned *, unsigned));
+int explode_lit8 OF((struct huft *, struct huft *, struct huft *,
+ int, int, int));
+int explode_lit4 OF((struct huft *, struct huft *, struct huft *,
+ int, int, int));
+int explode_nolit8 OF((struct huft *, struct huft *, int, int));
+int explode_nolit4 OF((struct huft *, struct huft *, int, int));
+int explode ();
+
+extern file_in_zip_read_info_s *pfile_in_zip_read_info;
+extern unz_s *pUnzip;
+
+/* The implode algorithm uses a sliding 4K or 8K byte window on the
+ uncompressed stream to find repeated byte strings. This is implemented
+ here as a circular buffer. The index is updated simply by incrementing
+ and then and'ing with 0x0fff (4K-1) or 0x1fff (8K-1). Here, the 32K
+ buffer of inflate is used, and it works just as well to always have
+ a 32K circular buffer, so the index is anded with 0x7fff. This is
+ done to allow the window to also be used as the output buffer. */
+/* This must be supplied in an external module useable like "byte slide[8192];"
+ or "byte *slide;", where the latter would be malloc'ed. In unzip, slide[]
+ is actually a 32K area for use by inflate, which uses a 32K sliding window.
+ */
+
+
+/* Tables for length and distance */
+UWORD cplen2[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65};
+UWORD cplen3[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66};
+UWORD extra[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 8};
+UWORD cpdist4[] = {1, 65, 129, 193, 257, 321, 385, 449, 513, 577, 641, 705,
+ 769, 833, 897, 961, 1025, 1089, 1153, 1217, 1281, 1345, 1409, 1473,
+ 1537, 1601, 1665, 1729, 1793, 1857, 1921, 1985, 2049, 2113, 2177,
+ 2241, 2305, 2369, 2433, 2497, 2561, 2625, 2689, 2753, 2817, 2881,
+ 2945, 3009, 3073, 3137, 3201, 3265, 3329, 3393, 3457, 3521, 3585,
+ 3649, 3713, 3777, 3841, 3905, 3969, 4033};
+UWORD cpdist8[] = {1, 129, 257, 385, 513, 641, 769, 897, 1025, 1153, 1281,
+ 1409, 1537, 1665, 1793, 1921, 2049, 2177, 2305, 2433, 2561, 2689,
+ 2817, 2945, 3073, 3201, 3329, 3457, 3585, 3713, 3841, 3969, 4097,
+ 4225, 4353, 4481, 4609, 4737, 4865, 4993, 5121, 5249, 5377, 5505,
+ 5633, 5761, 5889, 6017, 6145, 6273, 6401, 6529, 6657, 6785, 6913,
+ 7041, 7169, 7297, 7425, 7553, 7681, 7809, 7937, 8065};
+
+
+/* Macros for inflate() bit peeking and grabbing.
+ The usage is:
+
+ NEEDBITS(j)
+ x = b & mask_bits[j];
+ DUMPBITS(j)
+
+ where NEEDBITS makes sure that b has at least j bits in it, and
+ DUMPBITS removes the bits from b. The macros use the variable k
+ for the number of bits in b. Normally, b and k are register
+ variables for speed.
+ */
+
+extern UWORD bytebuf; /* (use the one in inflate.c) */
+#define NEXTBYTE (ReadByte(&bytebuf), bytebuf)
+#define NEEDBITS(n) {while(k<(n)){b|=((ULONG)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(n) {b>>=(n);k-=(n);}
+
+/* HERE */
+UWORD mask_bits[] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+union work area; /* see unzip.h for the definition of work */
+ULONG crc32val;
+ush bytebuf;
+ULONG bitbuf;
+int bits_left;
+boolean zipeof;
+
+int get_tree(l, n)
+unsigned *l; /* bit lengths */
+unsigned n; /* number expected */
+/* Get the bit lengths for a code representation from the compressed
+ stream. If get_tree() returns 4, then there is an error in the data.
+ Otherwise zero is returned. */
+{
+ unsigned i; /* bytes remaining in list */
+ unsigned k; /* lengths entered */
+ unsigned j; /* number of codes */
+ unsigned b; /* bit length for those codes */
+
+
+ /* get bit lengths */
+ ReadByte(&bytebuf);
+ i = bytebuf + 1; /* length/count pairs to read */
+ k = 0; /* next code */
+ do {
+ ReadByte(&bytebuf);
+ b = ((j = bytebuf) & 0xf) + 1; /* bits in code (1..16) */
+ j = ((j & 0xf0) >> 4) + 1; /* codes with those bits (1..16) */
+ if (k + j > n)
+ return 4; /* don't overflow l[] */
+ do {
+ l[k++] = b;
+ } while (--j);
+ } while (--i);
+ return k != n ? 4 : 0; /* should have read n of them */
+}
+
+
+
+int explode_lit8(tb, tl, td, bb, bl, bd)
+struct huft *tb, *tl, *td; /* literal, length, and distance tables */
+int bb, bl, bd; /* number of bits decoded by those */
+/* Decompress the imploded data using coded literals and an 8K sliding
+ window. */
+{
+ longint s; /* bytes to decompress */
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned mb, ml, md; /* masks for bb, bl, and bd bits */
+ register ULONG b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+ unsigned u; /* true if unflushed */
+
+
+ /* explode the coded data */
+ b = k = w = 0; /* initialize bit buffer, window */
+ u = 1; /* buffer unflushed */
+ mb = mask_bits[bb]; /* precompute masks for speed */
+ ml = mask_bits[bl];
+ md = mask_bits[bd];
+ s = pUnzip->pfile_in_zip_read->rest_read_uncompressed;
+ while (s > 0) /* do until ucsize bytes uncompressed */
+ {
+ NEEDBITS(1)
+ if (b & 1) /* then literal--decode it */
+ {
+ DUMPBITS(1)
+ s--;
+ NEEDBITS((unsigned)bb) /* get coded literal */
+ if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ slide[w++] = (byte)t->v.n;
+ if (w == WSIZE)
+ {
+ flush(w);
+ w = u = 0;
+ }
+ }
+ else /* else distance/length */
+ {
+ DUMPBITS(1)
+ NEEDBITS(7) /* get distance low bits */
+ d = (unsigned)b & 0x7f;
+ DUMPBITS(7)
+ NEEDBITS((unsigned)bd) /* get coded distance high bits */
+ if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ d = w - d - t->v.n; /* construct offset */
+ NEEDBITS((unsigned)bl) /* get coded length */
+ if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ n = t->v.n;
+ if (e) /* get length extra bits */
+ {
+ NEEDBITS(8)
+ n += (unsigned)b & 0xff;
+ DUMPBITS(8)
+ }
+
+ /* do the copy */
+ s -= n;
+ do {
+ n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
+ if (u && w <= d)
+ {
+ memset(slide + w, 0, e);
+ w += e;
+ d += e;
+ }
+ else
+#ifndef NOMEMCPY
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(slide + w, slide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ slide[w++] = slide[d++];
+ } while (--e);
+ if (w == WSIZE)
+ {
+ flush(w);
+ w = u = 0;
+ }
+ } while (n);
+ }
+ }
+
+ /* flush out slide */
+ flush(w);
+ return pfile_in_zip_read_info->rest_read_compressed ? 5 : 0; /* should have read csize bytes */
+}
+
+
+
+int explode_lit4(tb, tl, td, bb, bl, bd)
+struct huft *tb, *tl, *td; /* literal, length, and distance tables */
+int bb, bl, bd; /* number of bits decoded by those */
+/* Decompress the imploded data using coded literals and a 4K sliding
+ window. */
+{
+ longint s; /* bytes to decompress */
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned mb, ml, md; /* masks for bb, bl, and bd bits */
+ register ULONG b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+ unsigned u; /* true if unflushed */
+
+
+ /* explode the coded data */
+ b = k = w = 0; /* initialize bit buffer, window */
+ u = 1; /* buffer unflushed */
+ mb = mask_bits[bb]; /* precompute masks for speed */
+ ml = mask_bits[bl];
+ md = mask_bits[bd];
+ s = pUnzip->pfile_in_zip_read->rest_read_uncompressed;
+ while (s > 0) /* do until ucsize bytes uncompressed */
+ {
+ NEEDBITS(1)
+ if (b & 1) /* then literal--decode it */
+ {
+ DUMPBITS(1)
+ s--;
+ NEEDBITS((unsigned)bb) /* get coded literal */
+ if ((e = (t = tb + ((~(unsigned)b) & mb))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ slide[w++] = (byte)t->v.n;
+ if (w == WSIZE)
+ {
+ flush(w);
+ w = u = 0;
+ }
+ }
+ else /* else distance/length */
+ {
+ DUMPBITS(1)
+ NEEDBITS(6) /* get distance low bits */
+ d = (unsigned)b & 0x3f;
+ DUMPBITS(6)
+ NEEDBITS((unsigned)bd) /* get coded distance high bits */
+ if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ d = w - d - t->v.n; /* construct offset */
+ NEEDBITS((unsigned)bl) /* get coded length */
+ if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ n = t->v.n;
+ if (e) /* get length extra bits */
+ {
+ NEEDBITS(8)
+ n += (unsigned)b & 0xff;
+ DUMPBITS(8)
+ }
+
+ /* do the copy */
+ s -= n;
+ do {
+ n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
+ if (u && w <= d)
+ {
+ memset(slide + w, 0, e);
+ w += e;
+ d += e;
+ }
+ else
+#ifndef NOMEMCPY
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(slide + w, slide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ slide[w++] = slide[d++];
+ } while (--e);
+ if (w == WSIZE)
+ {
+ flush(w);
+ w = u = 0;
+ }
+ } while (n);
+ }
+ }
+
+ /* flush out slide */
+ flush(w);
+ return pfile_in_zip_read_info->rest_read_compressed ? 5 : 0; /* should have read csize bytes */
+}
+
+
+
+int explode_nolit8(tl, td, bl, bd)
+struct huft *tl, *td; /* length and distance decoder tables */
+int bl, bd; /* number of bits decoded by tl[] and td[] */
+/* Decompress the imploded data using uncoded literals and an 8K sliding
+ window. */
+{
+ longint s; /* bytes to decompress */
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned ml, md; /* masks for bl and bd bits */
+ register ULONG b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+ unsigned u; /* true if unflushed */
+
+
+ /* explode the coded data */
+ b = k = w = 0; /* initialize bit buffer, window */
+ u = 1; /* buffer unflushed */
+ ml = mask_bits[bl]; /* precompute masks for speed */
+ md = mask_bits[bd];
+ s = pUnzip->pfile_in_zip_read->rest_read_uncompressed;
+ while (s > 0) /* do until ucsize bytes uncompressed */
+ {
+ NEEDBITS(1)
+ if (b & 1) /* then literal--get eight bits */
+ {
+ DUMPBITS(1)
+ s--;
+ NEEDBITS(8)
+ slide[w++] = (byte)b;
+ if (w == WSIZE)
+ {
+ flush(w);
+ w = u = 0;
+ }
+ DUMPBITS(8)
+ }
+ else /* else distance/length */
+ {
+ DUMPBITS(1)
+ NEEDBITS(7) /* get distance low bits */
+ d = (unsigned)b & 0x7f;
+ DUMPBITS(7)
+ NEEDBITS((unsigned)bd) /* get coded distance high bits */
+ if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ d = w - d - t->v.n; /* construct offset */
+ NEEDBITS((unsigned)bl) /* get coded length */
+ if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ n = t->v.n;
+ if (e) /* get length extra bits */
+ {
+ NEEDBITS(8)
+ n += (unsigned)b & 0xff;
+ DUMPBITS(8)
+ }
+
+ /* do the copy */
+ s -= n;
+ do {
+ n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
+ if (u && w <= d)
+ {
+ memset(slide + w, 0, e);
+ w += e;
+ d += e;
+ }
+ else
+#ifndef NOMEMCPY
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(slide + w, slide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ slide[w++] = slide[d++];
+ } while (--e);
+ if (w == WSIZE)
+ {
+ flush(w);
+ w = u = 0;
+ }
+ } while (n);
+ }
+ }
+
+ /* flush out slide */
+ flush(w);
+ return pfile_in_zip_read_info->rest_read_compressed ? 5 : 0; /* should have read csize bytes */
+}
+
+
+
+int explode_nolit4(tl, td, bl, bd)
+struct huft *tl, *td; /* length and distance decoder tables */
+int bl, bd; /* number of bits decoded by tl[] and td[] */
+/* Decompress the imploded data using uncoded literals and a 4K sliding
+ window. */
+{
+ longint s; /* bytes to decompress */
+ register unsigned e; /* table entry flag/number of extra bits */
+ unsigned n, d; /* length and index for copy */
+ unsigned w; /* current window position */
+ struct huft *t; /* pointer to table entry */
+ unsigned ml, md; /* masks for bl and bd bits */
+ register ULONG b; /* bit buffer */
+ register unsigned k; /* number of bits in bit buffer */
+ unsigned u; /* true if unflushed */
+
+
+ /* explode the coded data */
+ b = k = w = 0; /* initialize bit buffer, window */
+ u = 1; /* buffer unflushed */
+ ml = mask_bits[bl]; /* precompute masks for speed */
+ md = mask_bits[bd];
+ s = pUnzip->pfile_in_zip_read->rest_read_uncompressed;
+ while (s > 0) /* do until ucsize bytes uncompressed */
+ {
+ NEEDBITS(1)
+ if (b & 1) /* then literal--get eight bits */
+ {
+ DUMPBITS(1)
+ s--;
+ NEEDBITS(8)
+ slide[w++] = (byte)b;
+ if (w == WSIZE)
+ {
+ flush(w);
+ w = u = 0;
+ }
+ DUMPBITS(8)
+ }
+ else /* else distance/length */
+ {
+ DUMPBITS(1)
+ NEEDBITS(6) /* get distance low bits */
+ d = (unsigned)b & 0x3f;
+ DUMPBITS(6)
+ NEEDBITS((unsigned)bd) /* get coded distance high bits */
+ if ((e = (t = td + ((~(unsigned)b) & md))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ d = w - d - t->v.n; /* construct offset */
+ NEEDBITS((unsigned)bl) /* get coded length */
+ if ((e = (t = tl + ((~(unsigned)b) & ml))->e) > 16)
+ do {
+ if (e == 99)
+ return 1;
+ DUMPBITS(t->b)
+ e -= 16;
+ NEEDBITS(e)
+ } while ((e = (t = t->v.t + ((~(unsigned)b) & mask_bits[e]))->e) > 16);
+ DUMPBITS(t->b)
+ n = t->v.n;
+ if (e) /* get length extra bits */
+ {
+ NEEDBITS(8)
+ n += (unsigned)b & 0xff;
+ DUMPBITS(8)
+ }
+
+ /* do the copy */
+ s -= n;
+ do {
+ n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
+ if (u && w <= d)
+ {
+ memset(slide + w, 0, e);
+ w += e;
+ d += e;
+ }
+ else
+#ifndef NOMEMCPY
+ if (w - d >= e) /* (this test assumes unsigned comparison) */
+ {
+ memcpy(slide + w, slide + d, e);
+ w += e;
+ d += e;
+ }
+ else /* do it slow to avoid memcpy() overlap */
+#endif /* !NOMEMCPY */
+ do {
+ slide[w++] = slide[d++];
+ } while (--e);
+ if (w == WSIZE)
+ {
+ flush(w);
+ w = u = 0;
+ }
+ } while (n);
+ }
+ }
+
+ /* flush out slide */
+ flush(w);
+ return pfile_in_zip_read_info->rest_read_compressed ? 5 : 0; /* should have read csize bytes */
+}
+
+
+
+int explode ()
+/* Explode an imploded compressed stream. Based on the general purpose
+ bit flag, decide on coded or uncoded literals, and an 8K or 4K sliding
+ window. Construct the literal (if any), length, and distance codes and
+ the tables needed to decode them (using huft_build() from inflate.c),
+ and call the appropriate routine for the type of data in the remainder
+ of the stream. The four routines are nearly identical, differing only
+ in whether the literal is decoded or simply read in, and in how many
+ bits are read in, uncoded, for the low distance bits. */
+{
+ unsigned r; /* return codes */
+ struct huft *tb; /* literal code table */
+ struct huft *tl; /* length code table */
+ struct huft *td; /* distance code table */
+ int bb; /* bits for tb */
+ int bl; /* bits for tl */
+ int bd; /* bits for td */
+ unsigned l[256]; /* bit lengths for codes */
+
+
+ /* Tune base table sizes. Note: I thought that to truly optimize speed,
+ I would have to select different bl, bd, and bb values for different
+ compressed file sizes. I was suprised to find out the the values of
+ 7, 7, and 9 worked best over a very wide range of sizes, except that
+ bd = 8 worked marginally better for large compressed sizes. */
+ bl = 7;
+ bd = pUnzip->pfile_in_zip_read->rest_read_compressed > 200000L ? 8 : 7;
+
+
+ /* With literal tree--minimum match length is 3 */
+ hufts = 0; /* initialze huft's malloc'ed */
+ if (pUnzip->cur_file_info.flag & 4)
+ {
+ bb = 9; /* base table size for literals */
+ if ((r = get_tree(l, 256)) != 0)
+ return r;
+ if ((r = huft_build(l, 256, 256, NULL, NULL, &tb, &bb)) != 0)
+ {
+ if (r == 1)
+ huft_free(tb);
+ return r;
+ }
+ if ((r = get_tree(l, 64)) != 0)
+ return r;
+ if ((r = huft_build(l, 64, 0, cplen3, extra, &tl, &bl)) != 0)
+ {
+ if (r == 1)
+ huft_free(tl);
+ huft_free(tb);
+ return r;
+ }
+ if ((r = get_tree(l, 64)) != 0)
+ return r;
+ if (pUnzip->cur_file_info.flag & 2) /* true if 8K */
+ {
+ if ((r = huft_build(l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
+ {
+ if (r == 1)
+ huft_free(td);
+ huft_free(tl);
+ huft_free(tb);
+ return r;
+ }
+ r = explode_lit8(tb, tl, td, bb, bl, bd);
+ }
+ else /* else 4K */
+ {
+ if ((r = huft_build(l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
+ {
+ if (r == 1)
+ huft_free(td);
+ huft_free(tl);
+ huft_free(tb);
+ return r;
+ }
+ r = explode_lit4(tb, tl, td, bb, bl, bd);
+ }
+ huft_free(td);
+ huft_free(tl);
+ huft_free(tb);
+ }
+ else
+
+
+ /* No literal tree--minimum match length is 2 */
+ {
+ if ((r = get_tree(l, 64)) != 0)
+ return r;
+ if ((r = huft_build(l, 64, 0, cplen2, extra, &tl, &bl)) != 0)
+ {
+ if (r == 1)
+ huft_free(tl);
+ return r;
+ }
+ if ((r = get_tree(l, 64)) != 0)
+ return r;
+ if (pUnzip->cur_file_info.flag & 2) /* true if 8K */
+ {
+ if ((r = huft_build(l, 64, 0, cpdist8, extra, &td, &bd)) != 0)
+ {
+ if (r == 1)
+ huft_free(td);
+ huft_free(tl);
+ return r;
+ }
+ r = explode_nolit8(tl, td, bl, bd);
+ }
+ else /* else 4K */
+ {
+ if ((r = huft_build(l, 64, 0, cpdist4, extra, &td, &bd)) != 0)
+ {
+ if (r == 1)
+ huft_free(td);
+ huft_free(tl);
+ return r;
+ }
+ r = explode_nolit4(tl, td, bl, bd);
+ }
+ huft_free(td);
+ huft_free(tl);
+ }
+#ifdef DEBUG
+ fprintf(stderr, "<%u > ", hufts);
+#endif /* DEBUG */
+ return r;
+}
+
+
+int ReadByte(x)
+ UWORD *x;
+{
+ /*
+ * read a byte; return 8 if byte available, 0 if not
+ */
+
+ if (pfile_in_zip_read_info->stream.avail_in == 0)
+ {
+ unsigned int uReadThis = UNZ_BUFSIZE;
+
+ if (pfile_in_zip_read_info->rest_read_compressed <= 0)
+ return (0);
+
+ if (pfile_in_zip_read_info->rest_read_compressed < uReadThis)
+ uReadThis = (uInt) pfile_in_zip_read_info->rest_read_compressed;
+ if (uReadThis == 0)
+ return UNZ_EOF;
+ if (fseek (pfile_in_zip_read_info->file,
+ pfile_in_zip_read_info->pos_in_zipfile +
+ pfile_in_zip_read_info->byte_before_the_zipfile, SEEK_SET) != 0)
+ return UNZ_ERRNO;
+ if (fread (pfile_in_zip_read_info->read_buffer, uReadThis, 1,
+ pfile_in_zip_read_info->file) != 1)
+ return UNZ_ERRNO;
+ pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+ pfile_in_zip_read_info->rest_read_compressed -= uReadThis;
+
+ pfile_in_zip_read_info->stream.next_in =
+ (Bytef *) pfile_in_zip_read_info->read_buffer;
+ pfile_in_zip_read_info->stream.avail_in = (uInt) uReadThis;
+ }
+
+ *x = *pfile_in_zip_read_info->stream.next_in++;
+ pfile_in_zip_read_info->stream.avail_in--;
+
+ return 8;
+}
+
+/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
+#define BMAX 16 /* maximum bit length of any code (16 for explode) */
+#define N_MAX 288 /* maximum number of codes in any set */
+
+unsigned hufts; /* track memory usage */
+
+
+int huft_build(b, n, s, d, e, t, m)
+unsigned *b; /* code lengths in bits (all assumed <= BMAX) */
+unsigned n; /* number of codes (assumed <= N_MAX) */
+unsigned s; /* number of simple-valued codes (0..s-1) */
+ush *d; /* list of base values for non-simple codes */
+ush *e; /* list of extra bits for non-simple codes */
+struct huft **t; /* result: starting table */
+int *m; /* maximum lookup bits, returns actual */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return zero on success, one if
+ the given code set is incomplete (the tables are still built in this
+ case), two if the input is invalid (all zero length codes or an
+ oversubscribed set of lengths), and three if not enough memory. */
+{
+ unsigned a; /* counter for codes of length k */
+ unsigned c[BMAX+1]; /* bit length count table */
+ unsigned f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register unsigned i; /* counter, current code */
+ register unsigned j; /* counter */
+ register int k; /* number of bits in current code */
+ int l; /* bits per table (returned in m) */
+ register unsigned *p; /* pointer into c[], b[], or v[] */
+ register struct huft *q; /* points to current table */
+ struct huft r; /* table entry for structure assignment */
+ struct huft *u[BMAX]; /* table stack */
+ unsigned v[N_MAX]; /* values in order of bit length */
+ register int w; /* bits before this table == (l * h) */
+ unsigned x[BMAX+1]; /* bit offsets, then code stack */
+ unsigned *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ unsigned z; /* number of entries in current table */
+
+
+ /* Generate counts for each bit length */
+ memset(c, 0, sizeof(c));
+ p = b; i = n;
+ do {
+ c[*p++]++; /* assume all entries <= BMAX */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (struct huft *)NULL;
+ *m = 0;
+ return 0;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ l = *m;
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((unsigned)l < j)
+ l = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((unsigned)l > i)
+ l = i;
+ *m = l;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return 2; /* bad input: more codes than bits */
+ if ((y -= c[i]) < 0)
+ return 2;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = -l; /* bits decoded == (l * h) */
+ u[0] = (struct huft *)NULL; /* just to keep compilers happy */
+ q = (struct huft *)NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l)
+ {
+ h++;
+ w += l; /* previous table always l bits */
+
+ /* compute minimum size table less than or equal to l bits */
+ z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ z = 1 << j; /* table entries for j-bit table */
+
+ /* allocate and link in new table */
+ if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
+ (struct huft *)NULL)
+ {
+ if (h)
+ huft_free(u[0]);
+ return 3; /* not enough memory */
+ }
+ hufts += z + 1; /* track memory usage */
+ *t = q + 1; /* link to list for huft_free() */
+ *(t = &(q->v.t)) = (struct huft *)NULL;
+ u[h] = ++q; /* table starts after link */
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.b = (uch)l; /* bits to dump before this table */
+ r.e = (uch)(16 + j); /* bits in this table */
+ r.v.t = q; /* pointer to this table */
+ j = i >> (w - l); /* (get around Turbo C bug) */
+ u[h-1][j] = r; /* connect to last table */
+ }
+ }
+
+ /* set up table entry in r */
+ r.b = (uch)(k - w);
+ if (p >= v + n)
+ r.e = 99; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
+ r.v.n = *p++; /* simple code is just the value */
+ }
+ else
+ {
+ r.e = (uch)e[*p - s]; /* non-simple--look up in lists */
+ r.v.n = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ while ((i & ((1 << w) - 1)) != x[h])
+ {
+ h--; /* don't need to update q */
+ w -= l;
+ }
+ }
+ }
+
+
+ /* Return true (1) if we were given an incomplete table */
+ return y != 0 && g != 1;
+}
+
+
+int huft_free(t)
+struct huft *t; /* table to free */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+ list of the tables it made, with the links in a dummy first entry of
+ each table. */
+{
+ register struct huft *p, *q;
+
+
+ /* Go through linked list, freeing from the malloced (t[-1]) address. */
+ p = t;
+ while (p != (struct huft *)NULL)
+ {
+ q = (--p)->v.t;
+ free(p);
+ p = q;
+ }
+ return 0;
+}
+
+void flush(w)
+unsigned w; /* number of bytes to flush */
+/* Do the equivalent of OUTB for the bytes slide[0..w-1]. */
+{
+ memmove (pfile_in_zip_read_info->stream.next_out, slide, w);
+ pfile_in_zip_read_info->crc32 = crc32 (pfile_in_zip_read_info->crc32,
+ pfile_in_zip_read_info->stream.next_out,
+ w);
+ pfile_in_zip_read_info->stream.next_out += w;
+ pfile_in_zip_read_info->stream.avail_out -= w;
+ pfile_in_zip_read_info->stream.total_out += w;
+}
+
+void flush_stack(w)
+unsigned w; /* number of bytes to flush */
+/* Do the equivalent of OUTB for the bytes slide[0..w-1]. */
+{
+ memmove (pfile_in_zip_read_info->stream.next_out, stack, w);
+ pfile_in_zip_read_info->crc32 = crc32 (pfile_in_zip_read_info->crc32,
+ pfile_in_zip_read_info->stream.next_out,
+ w);
+ pfile_in_zip_read_info->stream.next_out += w;
+ pfile_in_zip_read_info->stream.avail_out -= w;
+ pfile_in_zip_read_info->stream.total_out += w;
+}
+
+/****************************/
+/* Function FillBitBuffer() */
+/****************************/
+
+int FillBitBuffer()
+{
+ /*
+ * Fill bitbuf, which is 32 bits. This function is only used by the
+ * READBIT and PEEKBIT macros (which are used by all of the uncompression
+ * routines).
+ */
+ UWORD temp;
+
+ zipeof = 1;
+ while (bits_left < 25 && ReadByte(&temp) == 8)
+ {
+ bitbuf |= (ULONG)temp << bits_left;
+ bits_left += 8;
+ zipeof = 0;
+ }
+ return 0;
+}
+
diff --git a/source/unzip/unreduce.c b/source/unzip/unreduce.c
new file mode 100644
index 0000000..e978746
--- /dev/null
+++ b/source/unzip/unreduce.c
@@ -0,0 +1,217 @@
+/*---------------------------------------------------------------------------
+
+ unreduce.c
+
+ The Reducing algorithm is actually a combination of two distinct algorithms.
+ The first algorithm compresses repeated byte sequences, and the second al-
+ gorithm takes the compressed stream from the first algorithm and applies a
+ probabilistic compression method.
+
+ ---------------------------------------------------------------------------*/
+
+
+#include "unz.h"
+#include "unzipP.h"
+
+/**************************************/
+/* UnReduce Defines, Typedefs, etc. */
+/**************************************/
+
+#define DLE 144
+
+typedef byte f_array[64]; /* for followers[256][64] */
+
+static void LoadFollowers ();
+void flush OF((unsigned)); /* routine from inflate.c */
+
+extern file_in_zip_read_info_s *pfile_in_zip_read_info;
+extern unz_s *pUnzip;
+
+/*******************************/
+/* UnReduce Global Variables */
+/*******************************/
+
+#if (defined(MACOS) || defined(MTS))
+ f_array *followers; /* shared work space */
+#else
+ f_array *followers = (f_array *) (slide + 0x4000);
+#endif
+
+byte Slen[256];
+int factor;
+
+int L_table[] =
+{0, 0x7f, 0x3f, 0x1f, 0x0f};
+
+int D_shift[] =
+{0, 0x07, 0x06, 0x05, 0x04};
+int D_mask[] =
+{0, 0x01, 0x03, 0x07, 0x0f};
+
+int B_table[] =
+{8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8};
+
+
+
+
+
+/*************************/
+/* Function unReduce() */
+/*************************/
+
+void unReduce() /* expand probabilistically reduced data */
+{
+ register int lchar = 0;
+ int nchar;
+ int ExState = 0;
+ int V = 0;
+ int Len = 0;
+ longint s = pUnzip->pfile_in_zip_read->rest_read_compressed;
+ unsigned w = 0; /* position in output window slide[] */
+ unsigned u = 1; /* true if slide[] unflushed */
+
+
+#if (defined(MACOS) || defined(MTS))
+ followers = (f_array *) (slide + 0x4000);
+#endif
+
+ factor = pUnzip->cur_file_info.compression_method;
+ LoadFollowers();
+
+ while (s > 0 /* && (!zipeof) */) {
+ if (Slen[lchar] == 0)
+ READBIT(8, nchar) /* ; */
+ else {
+ READBIT(1, nchar);
+ if (nchar != 0)
+ READBIT(8, nchar) /* ; */
+ else {
+ int follower;
+ int bitsneeded = B_table[Slen[lchar]];
+ READBIT(bitsneeded, follower);
+ nchar = followers[lchar][follower];
+ }
+ }
+ /* expand the resulting byte */
+ switch (ExState) {
+
+ case 0:
+ if (nchar != DLE) {
+ s--;
+ slide[w++] = (byte) nchar;
+ if (w == 0x4000) {
+ flush(w);
+ w = u = 0;
+ }
+ }
+ else
+ ExState = 1;
+ break;
+
+ case 1:
+ if (nchar != 0) {
+ V = nchar;
+ Len = V & L_table[factor];
+ if (Len == L_table[factor])
+ ExState = 2;
+ else
+ ExState = 3;
+ } else {
+ s--;
+ slide[w++] = DLE;
+ if (w == 0x4000)
+ {
+ flush(w);
+ w = u = 0;
+ }
+ ExState = 0;
+ }
+ break;
+
+ case 2:{
+ Len += nchar;
+ ExState = 3;
+ }
+ break;
+
+ case 3:{
+ register unsigned e;
+ register unsigned n = Len + 3;
+ register unsigned d = w - ((((V >> D_shift[factor]) &
+ D_mask[factor]) << 8) + nchar + 1);
+
+ s -= n;
+ do {
+ n -= (e = (e = 0x4000 - ((d &= 0x3fff) > w ? d : w)) > n ?
+ n : e);
+ if (u && w <= d)
+ {
+ memset(slide + w, 0, e);
+ w += e;
+ d += e;
+ }
+ else
+ if (w - d < e) /* (assume unsigned comparison) */
+ do { /* slow to avoid memcpy() overlap */
+ slide[w++] = slide[d++];
+ } while (--e);
+ else
+ {
+ memcpy(slide + w, slide + d, e);
+ w += e;
+ d += e;
+ }
+ if (w == 0x4000)
+ {
+ flush(w);
+ w = u = 0;
+ }
+ } while (n);
+
+ ExState = 0;
+ }
+ break;
+ }
+
+ /* store character for next iteration */
+ lchar = nchar;
+ }
+
+ /* flush out slide */
+ flush(w);
+}
+
+
+
+
+
+/******************************/
+/* Function LoadFollowers() */
+/******************************/
+
+static void LoadFollowers()
+{
+ register int x;
+ register int i;
+
+ for (x = 255; x >= 0; x--) {
+ READBIT(6, Slen[x]);
+ for (i = 0; (byte) i < Slen[x]; i++) {
+ READBIT(8, followers[x][i]);
+ }
+ }
+}
diff --git a/source/unzip/unshrink.c b/source/unzip/unshrink.c
new file mode 100644
index 0000000..6deb4d4
--- /dev/null
+++ b/source/unzip/unshrink.c
@@ -0,0 +1,177 @@
+/*---------------------------------------------------------------------------
+
+ unshrink.c
+
+ Shrinking is a Dynamic Lempel-Ziv-Welch compression algorithm with partial
+ clearing.
+
+ ---------------------------------------------------------------------------*/
+
+
+#include "unz.h"
+void flush_stack (int);
+
+/*************************************/
+/* UnShrink Defines, Globals, etc. */
+/*************************************/
+
+/* MAX_BITS 13 (in unzip.h; defines size of global work area) */
+#define INIT_BITS 9
+#define FIRST_ENT 257
+#define CLEAR 256
+#define GetCode(dest) READBIT(codesize,dest)
+
+static void partial_clear ();
+
+int codesize, maxcode, maxcodemax, free_ent;
+
+
+
+
+/*************************/
+/* Function unShrink() */
+/*************************/
+
+void unShrink()
+{
+ register int code;
+ register int stackp;
+ int finchar;
+ int oldcode;
+ int incode;
+
+
+ /* decompress the file */
+ codesize = INIT_BITS;
+ maxcode = (1 << codesize) - 1;
+ maxcodemax = HSIZE; /* (1 << MAX_BITS) */
+ free_ent = FIRST_ENT;
+
+ code = maxcodemax;
+ do {
+ prefix_of[code] = -1;
+ } while (--code > 255);
+/*
+ OvdL: -Ox with SCO's 3.2.0 cc gives
+ a. warning: overflow in constant multiplication
+ b. segmentation fault (core dumped) when using the executable
+ for (code = maxcodemax; code > 255; code--)
+ prefix_of[code] = -1;
+ */
+
+ for (code = 255; code >= 0; code--) {
+ prefix_of[code] = 0;
+ suffix_of[code] = (byte) code;
+ }
+
+ GetCode(oldcode);
+ if (zipeof)
+ return;
+ finchar = oldcode;
+
+ stack[0] = finchar;
+ flush_stack (1);
+
+ stackp = HSIZE;
+
+ while (!zipeof) {
+ GetCode(code);
+ if (zipeof)
+ return;
+
+ while (code == CLEAR) {
+ GetCode(code);
+ switch (code) {
+ case 1:
+ codesize++;
+ if (codesize == MAX_BITS)
+ maxcode = maxcodemax;
+ else
+ maxcode = (1 << codesize) - 1;
+ break;
+
+ case 2:
+ partial_clear();
+ break;
+ }
+
+ GetCode(code);
+ if (zipeof)
+ return;
+ }
+
+
+ /* special case for KwKwK string */
+ incode = code;
+ if (prefix_of[code] == -1) {
+ stack[--stackp] = (byte) finchar;
+ code = oldcode;
+ }
+ /* generate output characters in reverse order */
+ while (code >= FIRST_ENT) {
+ if (prefix_of[code] == -1) {
+ stack[--stackp] = (byte) finchar;
+ code = oldcode;
+ } else {
+ stack[--stackp] = suffix_of[code];
+ code = prefix_of[code];
+ }
+ }
+
+ finchar = suffix_of[code];
+ stack[--stackp] = (byte) finchar;
+
+ /* and put them out in forward order, block copy */
+ flush_stack (HSIZE - stackp);
+ stackp = HSIZE;
+
+ /* generate new entry */
+ code = free_ent;
+ if (code < maxcodemax) {
+ prefix_of[code] = oldcode;
+ suffix_of[code] = (byte) finchar;
+
+ do
+ code++;
+ while ((code < maxcodemax) && (prefix_of[code] != -1));
+
+ free_ent = code;
+ }
+ /* remember previous code */
+ oldcode = incode;
+ }
+}
+
+
+
+/******************************/
+/* Function partial_clear() */
+/******************************/
+
+static void partial_clear()
+{
+ register int pr;
+ register int cd;
+
+ /* mark all nodes as potentially unused */
+ for (cd = FIRST_ENT; cd < free_ent; cd++)
+ prefix_of[cd] |= 0x8000;
+
+ /* unmark those that are used by other nodes */
+ for (cd = FIRST_ENT; cd < free_ent; cd++) {
+ pr = prefix_of[cd] & 0x7fff; /* reference to another node? */
+ if (pr >= FIRST_ENT) /* flag node as referenced */
+ prefix_of[pr] &= 0x7fff;
+ }
+
+ /* clear the ones that are still marked */
+ for (cd = FIRST_ENT; cd < free_ent; cd++)
+ if ((prefix_of[cd] & 0x8000) != 0)
+ prefix_of[cd] = -1;
+
+ /* find first cleared node as next free_ent */
+ cd = FIRST_ENT;
+ while ((cd < maxcodemax) && (prefix_of[cd] != -1))
+ cd++;
+ free_ent = cd;
+}
diff --git a/source/unzip/unz.h b/source/unzip/unz.h
new file mode 100644
index 0000000..1ea7478
--- /dev/null
+++ b/source/unzip/unz.h
@@ -0,0 +1,994 @@
+/*---------------------------------------------------------------------------
+
+ unzip.h
+
+ This header file is used by all of the unzip source files. Its contents
+ are divided into seven more-or-less separate sections: predefined macros,
+ OS-dependent includes, (mostly) OS-independent defines, typedefs, function
+ prototypes (or "prototypes," in the case of non-ANSI compilers), macros,
+ and global-variable declarations.
+
+ ---------------------------------------------------------------------------*/
+
+#include "zlib.h"
+
+/*****************************************/
+/* Predefined, Machine-specific Macros */
+/*****************************************/
+
+#if (defined(__GO32__) && defined(unix)) /* DOS extender */
+# undef unix
+#endif
+
+#if defined(unix) || defined(__convexc__) || defined(M_XENIX)
+# ifndef UNIX
+# define UNIX
+# endif /* !UNIX */
+#endif /* unix || __convexc__ || M_XENIX */
+
+/* Much of the following is swiped from zip's tailor.h: */
+
+/* define MSDOS for Turbo C (unless OS/2) and Power C as well as Microsoft C */
+#ifdef __POWERC
+# define __TURBOC__
+# define MSDOS
+#endif /* __POWERC */
+#if (defined(__TURBOC__) && defined(__MSDOS__) && !defined(MSDOS))
+# define MSDOS
+#endif
+
+/* use prototypes and ANSI libraries if __STDC__, or Microsoft or Borland C,
+ * or Silicon Graphics, or Convex, or IBM C Set/2, or GNU gcc under emx, or
+ * or Watcom C, or Macintosh, or Windows NT.
+ */
+#if (__STDC__ || defined(MSDOS) || defined(sgi) || defined(CONVEX) || defined(__sun))
+# ifndef PROTO
+# define PROTO
+# endif
+# define MODERN
+#endif
+#if (defined(__IBMC__) || defined(__EMX__) || defined(__WATCOMC__))
+# ifndef PROTO
+# define PROTO
+# endif
+# define MODERN
+#endif
+#if (defined(THINK_C) || defined(MPW) || defined(WIN32))
+# ifndef PROTO
+# define PROTO
+# endif
+# define MODERN
+#endif
+
+/* turn off prototypes if requested */
+#if (defined(NOPROTO) && defined(PROTO))
+# undef PROTO
+#endif
+
+#if (defined(ultrix) || defined(bsd4_2) || defined(sun) || defined(pyr))
+# if (!defined(BSD) && !defined(__SYSTEM_FIVE) && !defined(SYSV))
+# define BSD
+# endif /* !BSD && !__SYSTEM_FIVE && !SYSV */
+#endif /* ultrix || bsd4_2 || sun || pyr */
+
+#if (defined(CONVEX) || defined(CRAY) || defined(__SYSTEM_FIVE))
+# ifndef TERMIO
+# define TERMIO
+# endif /* !TERMIO */
+#endif /* CONVEX || CRAY || __SYSTEM_FIVE */
+
+#ifdef pyr /* Pyramid */
+# ifndef ZMEM
+# define ZMEM
+# endif /* !ZMEM */
+#endif /* pyr */
+
+#ifdef CRAY
+# ifdef ZMEM
+# undef ZMEM
+# endif /* ZMEM */
+#endif /* CRAY */
+
+/* the i386 test below is to catch SCO Unix (which has redefinition
+ * warnings if param.h is included), but it probably doesn't hurt if
+ * other 386 Unixes get nailed, too...except now that 386BSD and BSDI
+ * exist. Sigh. <sys/param.h> is mostly included for "BSD", I think.
+ * [An alternate fix for SCO Unix is below.]
+ */
+#if (defined(MINIX) || (defined(i386) && defined(unix)))
+# define NO_PARAM_H
+#endif /* MINIX || (i386 && unix) */
+
+
+
+
+
+/***************************/
+/* OS-Dependent Includes */
+/***************************/
+
+#ifndef MINIX /* Minix needs it after all the other includes (?) */
+# include <stdio.h>
+#endif
+#include <ctype.h> /* skip for VMS, to use tolower() function? */
+#include <errno.h> /* used in mapname() */
+#ifndef NO_ERRNO
+# define DECLARE_ERRNO /* everybody except MSC 6.0, SCO cc, Watcom C/386 */
+#endif /* !NO_ERRNO */
+#ifdef VMS
+# include <types.h> /* (placed up here instead of in VMS section below */
+# include <stat.h> /* because types.h is used in some other headers) */
+#else /* !VMS */
+# if !defined(THINK_C) && !defined(MPW)
+# include <sys/types.h> /* off_t, time_t, dev_t, ... */
+# include <sys/stat.h>
+# endif /* !THINK_C && !MPW */
+#endif /* ?VMS */
+
+#ifdef MODERN
+# if (!defined(M_XENIX) && !(defined(__GNUC__) && defined(sun)))
+# include <stddef.h>
+# endif
+# if (!defined(__GNUC__) && !defined(apollo)) /* both define __STDC__ */
+# include <stdlib.h> /* standard library prototypes, malloc(), etc. */
+# else
+# ifdef __EMX__
+# include <stdlib.h> /* emx IS gcc but has stdlib.h */
+# endif
+# endif
+# include <string.h> /* defines strcpy, strcmp, memcpy, etc. */
+ typedef size_t extent;
+#else /* !MODERN */
+ char *malloc();
+ char *strchr(), *strrchr();
+ long lseek();
+ typedef unsigned int extent;
+# define void int
+#endif /* ?MODERN */
+
+/* this include must be down here for SysV.4, for some reason... */
+#include <signal.h> /* used in unzip.c, file_io.c */
+
+
+
+/*---------------------------------------------------------------------------
+ Next, a word from our Unix (mostly) sponsors:
+ ---------------------------------------------------------------------------*/
+
+#ifdef UNIX
+# ifdef AMIGA
+# include <libraries/dos.h>
+# else /* !AMIGA */
+# ifndef NO_PARAM_H
+#if 0 /* [GRR: this is an alternate fix for SCO's redefinition bug] */
+# ifdef NGROUPS_MAX
+# undef NGROUPS_MAX /* SCO bug: defined again in <param.h> */
+# endif /* NGROUPS_MAX */
+#endif /* 0 */
+# include <sys/param.h> /* conflict with <sys/types.h>, some systems? */
+# endif /* !NO_PARAM_H */
+# endif /* ?AMIGA */
+
+# ifndef BSIZE
+# ifdef MINIX
+# define BSIZE 1024
+# else /* !MINIX */
+# define BSIZE DEV_BSIZE /* assume common for all Unix systems */
+# endif /* ?MINIX */
+# endif
+
+# ifndef BSD
+# if (!defined(AMIGA) && !defined(MINIX))
+# define NO_MKDIR /* for mapname() */
+# endif /* !AMIGA && !MINIX */
+# include <time.h>
+ struct tm *gmtime(), *localtime();
+# else /* BSD */
+# include <sys/time.h>
+# include <sys/timeb.h>
+# ifdef _AIX
+# include <time.h>
+# endif
+# endif
+
+#else /* !UNIX */
+# define BSIZE 512 /* disk block size */
+#endif /* ?UNIX */
+
+#if (defined(V7) || defined(BSD))
+# define strchr index
+# define strrchr rindex
+#endif
+
+/*---------------------------------------------------------------------------
+ And now, our MS-DOS and OS/2 corner:
+ ---------------------------------------------------------------------------*/
+
+#ifdef __TURBOC__
+# define DOS_OS2
+# include <sys/timeb.h> /* for structure ftime */
+# ifndef __BORLANDC__ /* there appears to be a bug (?) in Borland's */
+# include <mem.h> /* MEM.H related to __STDC__ and far poin- */
+# endif /* ters. (dpk) [mem.h included for memcpy] */
+# include <dos.h> /* for REGS macro (at least for Turbo C 2.0) */
+#else /* NOT Turbo C (or Power C)... */
+# ifdef MSDOS /* but still MS-DOS, so we'll assume it's */
+# ifndef MSC /* Microsoft's compiler and fake the ID, if */
+# define MSC /* necessary (it is in 5.0; apparently not */
+# endif /* in 5.1 and 6.0) */
+# include <dos.h> /* for _dos_setftime() */
+# endif
+#endif
+
+#if (defined(__IBMC__) && defined(__OS2__))
+# define DOS_OS2
+# define S_IFMT 0xF000
+# define timezone _timezone
+#endif
+
+#ifdef __WATCOMC__
+# define DOS_OS2
+# define __32BIT__
+# ifdef DECLARE_ERRNO
+# undef DECLARE_ERRNO
+# endif
+# undef far
+# define far
+#endif
+
+#ifdef __EMX__
+# define DOS_OS2
+# define __32BIT__
+# define far
+#endif /* __EMX__ */
+
+#ifdef MSC /* defined for all versions of MSC now */
+# define DOS_OS2 /* Turbo C under DOS, MSC under DOS or OS/2 */
+# if (defined(_MSC_VER) && (_MSC_VER >= 600)) /* new with 5.1 or 6.0 ... */
+# undef DECLARE_ERRNO /* errno is now a function in a dynamic link */
+# endif /* library (or something)--incompatible with */
+#endif /* the usual "extern int errno" declaration */
+
+#ifdef DOS_OS2 /* defined for all MS-DOS and OS/2 compilers */
+# include <io.h> /* lseek(), open(), setftime(), dup(), creat() */
+# include <time.h> /* localtime() */
+#endif
+
+#ifdef OS2 /* defined for all OS/2 compilers */
+# ifdef isupper
+# undef isupper
+# endif
+# ifdef tolower
+# undef tolower
+# endif
+# define isupper(x) IsUpperNLS((unsigned char)(x))
+# define tolower(x) ToLowerNLS((unsigned char)(x))
+#endif
+
+#ifdef WIN32
+# include <io.h> /* read(), open(), etc. */
+# include <time.h>
+# include <memory.h>
+# include <direct.h> /* mkdir() */
+# ifdef FILE_IO_C
+# include <fcntl.h>
+# include <conio.h>
+# include <sys\types.h>
+# include <sys\utime.h>
+# include <windows.h>
+# define DOS_OS2
+# define getch() getchar()
+# endif
+#endif
+
+/*---------------------------------------------------------------------------
+ Followed by some VMS (mostly) stuff:
+ ---------------------------------------------------------------------------*/
+
+#ifdef VMS
+# include <time.h> /* the usual non-BSD time functions */
+# include <file.h> /* same things as fcntl.h has */
+# include <rms.h>
+# define _MAX_PATH NAM$C_MAXRSS /* to define FILNAMSIZ below */
+# define UNIX /* can share most of same code from now on */
+# define RETURN return_VMS /* VMS interprets return codes incorrectly */
+#else /* !VMS */
+# ifndef THINK_C
+# define RETURN return /* only used in main() */
+# else
+# define RETURN(v) { int n;\
+ n = (v);\
+ fprintf(stderr, "\npress <return> to continue ");\
+ while (getc(stdin) != '\n');\
+ putc('\n', stderr);\
+ InitCursor();\
+ goto start;\
+ }
+# endif
+# ifdef V7
+# define O_RDONLY 0
+# define O_WRONLY 1
+# define O_RDWR 2
+# else /* !V7 */
+# ifdef MTS
+# include <sys/file.h> /* MTS uses this instead of fcntl.h */
+# include <timeb.h>
+# include <time.h>
+# else /* !MTS */
+# ifdef COHERENT /* Coherent 3.10/Mark Williams C */
+# include <sys/fcntl.h>
+# define SHORT_NAMES
+# define tzset settz
+# else /* !COHERENT */
+# include <fcntl.h> /* O_BINARY for open() w/o CR/LF translation */
+# endif /* ?COHERENT */
+# endif /* ?MTS */
+# endif /* ?V7 */
+#endif /* ?VMS */
+
+#if (defined(MSDOS) || defined(VMS))
+# define DOS_VMS
+#endif
+
+/*---------------------------------------------------------------------------
+ And some Mac stuff for good measure:
+ ---------------------------------------------------------------------------*/
+
+#ifdef THINK_C
+# define MACOS
+# ifndef __STDC__ /* if Think C hasn't defined __STDC__ ... */
+# define __STDC__ 1 /* make sure it's defined: it needs it */
+# else /* __STDC__ defined */
+# if !__STDC__ /* sometimes __STDC__ is defined as 0; */
+# undef __STDC__ /* it needs to be 1 or required header */
+# define __STDC__ 1 /* files are not properly included. */
+# endif /* !__STDC__ */
+# endif /* ?defined(__STDC__) */
+#endif /* THINK_C */
+
+#ifdef MPW
+# define MACOS
+# include <Errors.h>
+# include <Files.h>
+# include <Memory.h>
+# include <Quickdraw.h>
+# include <ToolUtils.h>
+# define CtoPstr c2pstr
+# define PtoCstr p2cstr
+# ifdef CR
+# undef CR
+# endif
+#endif /* MPW */
+
+#ifdef MACOS
+# define open(x,y) macopen(x,y, gnVRefNum, glDirID)
+# define close macclose
+# define read macread
+# define write macwrite
+# define lseek maclseek
+# define creat(x,y) maccreat(x, gnVRefNum, glDirID, gostCreator, gostType)
+# define stat(x,y) macstat(x,y,gnVRefNum, glDirID)
+
+# ifndef isascii
+# define isascii(c) ((unsigned char)(c) <= 0x3F)
+# endif
+
+# include "macstat.h"
+
+typedef struct _ZipExtraHdr {
+ unsigned short header; /* 2 bytes */
+ unsigned short data; /* 2 bytes */
+} ZIP_EXTRA_HEADER;
+
+typedef struct _MacInfoMin {
+ unsigned short header; /* 2 bytes */
+ unsigned short data; /* 2 bytes */
+ unsigned long signature; /* 4 bytes */
+ FInfo finfo; /* 16 bytes */
+ unsigned long lCrDat; /* 4 bytes */
+ unsigned long lMdDat; /* 4 bytes */
+ unsigned long flags ; /* 4 bytes */
+ unsigned long lDirID; /* 4 bytes */
+ /*------------*/
+} MACINFOMIN; /* = 40 bytes for size of data */
+
+typedef struct _MacInfo {
+ unsigned short header; /* 2 bytes */
+ unsigned short data; /* 2 bytes */
+ unsigned long signature; /* 4 bytes */
+ FInfo finfo; /* 16 bytes */
+ unsigned long lCrDat; /* 4 bytes */
+ unsigned long lMdDat; /* 4 bytes */
+ unsigned long flags ; /* 4 bytes */
+ unsigned long lDirID; /* 4 bytes */
+ char rguchVolName[28]; /* 28 bytes */
+ /*------------*/
+} MACINFO; /* = 68 bytes for size of data */
+#endif /* MACOS */
+
+/*---------------------------------------------------------------------------
+ And finally, some random extra stuff:
+ ---------------------------------------------------------------------------*/
+
+#ifdef MINIX
+# include <stdio.h>
+#endif
+
+#ifdef SHORT_NAMES /* Mark Williams C, ...? */
+# define extract_or_test_files xtr_or_tst_files
+# define extract_or_test_member xtr_or_tst_member
+#endif
+
+#ifdef MTS
+# include <unix.h> /* Some important non-ANSI routines */
+# define mkdir(s,n) (-1) /* No "make directory" capability */
+# define EBCDIC /* Set EBCDIC conversion on */
+#endif
+
+
+
+
+
+/*************/
+/* Defines */
+/*************/
+
+#ifndef WSIZE
+# define WSIZE 0x8000 /* window size--must be a power of two, and */
+#endif /* !WSIZE */ /* at least 32K for zip's deflate method */
+
+#define DIR_BLKSIZ 64 /* number of directory entries per block
+ * (should fit in 4096 bytes, usually) */
+#ifndef INBUFSIZ
+# define INBUFSIZ 2048 /* works for MS-DOS small model */
+#endif /* !INBUFSIZ */
+
+/*
+ * If <limits.h> exists on most systems, should include that, since it may
+ * define some or all of the following: NAME_MAX, PATH_MAX, _POSIX_NAME_MAX,
+ * _POSIX_PATH_MAX.
+ */
+#ifdef DOS_OS2
+# include <limits.h>
+#endif /* DOS_OS2 */
+
+#ifdef _MAX_PATH
+# define FILNAMSIZ (_MAX_PATH)
+#else /* !_MAX_PATH */
+# define FILNAMSIZ 1025
+#endif /* ?_MAX_PATH */
+
+#ifndef PATH_MAX
+# ifdef MAXPATHLEN /* defined in <sys/param.h> some systems */
+# define PATH_MAX MAXPATHLEN
+# else
+# if FILENAME_MAX > 255 /* used like PATH_MAX on some systems */
+# define PATH_MAX FILENAME_MAX
+# else
+# define PATH_MAX (FILNAMSIZ - 1)
+# endif
+# endif /* ?MAXPATHLEN */
+#endif /* !PATH_MAX */
+
+#define OUTBUFSIZ INBUFSIZ
+
+#define ZSUFX ".zip"
+#define CENTRAL_HDR_SIG "\113\001\002" /* the infamous "PK" signature */
+#define LOCAL_HDR_SIG "\113\003\004" /* bytes, sans "P" (so unzip */
+#define END_CENTRAL_SIG "\113\005\006" /* executable not mistaken for */
+#define EXTD_LOCAL_SIG "\113\007\010" /* zipfile itself) */
+
+#define SKIP 0 /* choice of activities for do_string() */
+#define DISPLAY 1
+#define FILENAME 2
+#define EXTRA_FIELD 3
+
+#define DOES_NOT_EXIST -1 /* return values for check_for_newer() */
+#define EXISTS_AND_OLDER 0
+#define EXISTS_AND_NEWER 1
+
+#define DOS_OS2_FAT_ 0 /* version_made_by codes (central dir) */
+#define AMIGA_ 1
+#define VMS_ 2 /* make sure these are not defined on */
+#define UNIX_ 3 /* the respective systems!! (like, for */
+#define VM_CMS_ 4 /* instance, "VMS", or "UNIX": CFLAGS = */
+#define ATARI_ 5 /* -O -DUNIX) */
+#define OS2_HPFS_ 6
+#define MAC_ 7
+#define Z_SYSTEM_ 8
+#define CPM_ 9
+/* #define TOPS20_ 10? (TOPS20_ is to be defined in PKZIP 2.0...) */
+#define NUM_HOSTS 10 /* index of last system + 1 */
+
+#define STORED 0 /* compression methods */
+#define SHRUNK 1
+#define REDUCED1 2
+#define REDUCED2 3
+#define REDUCED3 4
+#define REDUCED4 5
+#define IMPLODED 6
+#define TOKENIZED 7
+#define DEFLATED 8
+#define NUM_METHODS 9 /* index of last method + 1 */
+/* don't forget to update list_files() appropriately if NUM_METHODS changes */
+
+#define DF_MDY 0 /* date format 10/26/91 (USA only) */
+#define DF_DMY 1 /* date format 26/10/91 (most of the world) */
+#define DF_YMD 2 /* date format 91/10/26 (a few countries) */
+
+#define UNZIP_VERSION 20 /* compatible with PKUNZIP 2.0 */
+#define VMS_VERSION 42 /* if OS-needed-to-extract is VMS: can do */
+
+/*---------------------------------------------------------------------------
+ True sizes of the various headers, as defined by PKWare--so it is not
+ likely that these will ever change. But if they do, make sure both these
+ defines AND the typedefs below get updated accordingly.
+ ---------------------------------------------------------------------------*/
+#define LREC_SIZE 26 /* lengths of local file headers, central */
+#define CREC_SIZE 42 /* directory headers, and the end-of- */
+#define ECREC_SIZE 18 /* central-dir record, respectively */
+
+#define MAX_BITS 13 /* used in unShrink() */
+#define HSIZE (1 << MAX_BITS) /* size of global work area */
+
+#define LF 10 /* '\n' on ASCII machines. Must be 10 due to EBCDIC */
+#define CR 13 /* '\r' on ASCII machines. Must be 13 due to EBCDIC */
+#define CTRLZ 26 /* DOS & OS/2 EOF marker (used in file_io.c, vms.c) */
+
+#ifdef EBCDIC
+# define ascii_to_native(c) ebcdic[(c)]
+# define NATIVE "EBCDIC"
+#endif
+
+#if MPW
+# define FFLUSH putc('\n',stderr);
+#else /* !MPW */
+# define FFLUSH fflush(stderr);
+#endif /* ?MPW */
+
+#ifdef VMS
+# define ENV_UNZIP "UNZIP_OPTS" /* name of environment variable */
+# define ENV_ZIPINFO "ZIPINFO_OPTS"
+#else /* !VMS */
+# define ENV_UNZIP "UNZIP"
+# define ENV_ZIPINFO "ZIPINFO"
+#endif /* ?VMS */
+
+#ifdef CRYPT
+# define PWLEN 80
+# define DECRYPT(b) (update_keys(t=((b)&0xff)^decrypt_byte()),t)
+#endif /* CRYPT */
+
+#ifdef QQ /* Newtware version */
+# define QCOND (!quietflg) /* for no file comments with -vq or -vqq */
+#else /* (original) Bill Davidsen version */
+# define QCOND (which_hdr) /* no way to kill file comments with -v, -l */
+#endif
+
+#ifndef TRUE
+# define TRUE 1 /* sort of obvious */
+#endif
+#ifndef FALSE
+# define FALSE 0
+#endif
+
+#ifndef SEEK_SET /* These should all be declared in stdio.h! But */
+# define SEEK_SET 0 /* since they're not (in many cases), do so here. */
+# define SEEK_CUR 1
+# define SEEK_END 2
+#endif
+
+#ifndef S_IRUSR
+# define S_IRWXU 00700 /* read, write, execute: owner */
+# define S_IRUSR 00400 /* read permission: owner */
+# define S_IWUSR 00200 /* write permission: owner */
+# define S_IXUSR 00100 /* execute permission: owner */
+# define S_IRWXG 00070 /* read, write, execute: group */
+# define S_IRGRP 00040 /* read permission: group */
+# define S_IWGRP 00020 /* write permission: group */
+# define S_IXGRP 00010 /* execute permission: group */
+# define S_IRWXO 00007 /* read, write, execute: other */
+# define S_IROTH 00004 /* read permission: other */
+# define S_IWOTH 00002 /* write permission: other */
+# define S_IXOTH 00001 /* execute permission: other */
+#endif /* !S_IRUSR */
+
+#ifdef ZIPINFO /* these are individually checked because SysV doesn't */
+# ifndef S_IFBLK /* have some of them, Microsoft C others, etc. */
+# define S_IFBLK 0060000 /* block special */
+# endif
+# ifndef S_IFIFO /* in Borland C, not MSC */
+# define S_IFIFO 0010000 /* fifo */
+# endif
+# ifndef S_IFLNK /* in BSD, not SysV */
+# define S_IFLNK 0120000 /* symbolic link */
+# endif
+# ifndef S_IFSOCK /* in BSD, not SysV */
+# define S_IFSOCK 0140000 /* socket */
+# endif
+# ifndef S_ISUID
+# define S_ISUID 04000 /* set user id on execution */
+# endif
+# ifndef S_ISGID
+# define S_ISGID 02000 /* set group id on execution */
+# endif
+# ifndef S_ISVTX
+# define S_ISVTX 01000 /* directory permissions control */
+# endif
+# ifndef S_ENFMT
+# define S_ENFMT S_ISGID /* record locking enforcement flag */
+# endif
+#endif /* ZIPINFO */
+
+
+
+
+
+/**************/
+/* Typedefs */
+/**************/
+
+#ifndef _BULL_SOURCE /* Bull has it defined somewhere already */
+ typedef unsigned char byte; /* code assumes UNSIGNED bytes */
+#endif /* !_BULL_SOURCE */
+
+typedef char boolean;
+typedef long longint;
+typedef unsigned short UWORD;
+typedef unsigned long ULONG;
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+typedef struct min_info {
+ unsigned unix_attr;
+ unsigned dos_attr;
+ int hostnum;
+ longint offset;
+ ULONG compr_size; /* compressed size (needed if extended header) */
+ ULONG crc; /* crc (needed if extended header) */
+ unsigned encrypted : 1; /* file encrypted: decrypt before uncompressing */
+ unsigned ExtLocHdr : 1; /* use time instead of CRC for decrypt check */
+ unsigned text : 1; /* file is text or binary */
+ unsigned lcflag : 1; /* convert filename to lowercase */
+} min_info;
+
+typedef struct VMStimbuf {
+ char *revdate; /* (both correspond to Unix modtime/st_mtime) */
+ char *credate;
+} VMStimbuf;
+
+/*---------------------------------------------------------------------------
+ Zipfile layout declarations. If these headers ever change, make sure the
+ xxREC_SIZE defines (above) change with them!
+ ---------------------------------------------------------------------------*/
+
+ typedef byte local_byte_hdr[ LREC_SIZE ];
+# define L_VERSION_NEEDED_TO_EXTRACT_0 0
+# define L_VERSION_NEEDED_TO_EXTRACT_1 1
+# define L_GENERAL_PURPOSE_BIT_FLAG 2
+# define L_COMPRESSION_METHOD 4
+# define L_LAST_MOD_FILE_TIME 6
+# define L_LAST_MOD_FILE_DATE 8
+# define L_CRC32 10
+# define L_COMPRESSED_SIZE 14
+# define L_UNCOMPRESSED_SIZE 18
+# define L_FILENAME_LENGTH 22
+# define L_EXTRA_FIELD_LENGTH 24
+
+ typedef byte cdir_byte_hdr[ CREC_SIZE ];
+# define C_VERSION_MADE_BY_0 0
+# define C_VERSION_MADE_BY_1 1
+# define C_VERSION_NEEDED_TO_EXTRACT_0 2
+# define C_VERSION_NEEDED_TO_EXTRACT_1 3
+# define C_GENERAL_PURPOSE_BIT_FLAG 4
+# define C_COMPRESSION_METHOD 6
+# define C_LAST_MOD_FILE_TIME 8
+# define C_LAST_MOD_FILE_DATE 10
+# define C_CRC32 12
+# define C_COMPRESSED_SIZE 16
+# define C_UNCOMPRESSED_SIZE 20
+# define C_FILENAME_LENGTH 24
+# define C_EXTRA_FIELD_LENGTH 26
+# define C_FILE_COMMENT_LENGTH 28
+# define C_DISK_NUMBER_START 30
+# define C_INTERNAL_FILE_ATTRIBUTES 32
+# define C_EXTERNAL_FILE_ATTRIBUTES 34
+# define C_RELATIVE_OFFSET_LOCAL_HEADER 38
+
+ typedef byte ec_byte_rec[ ECREC_SIZE+4 ];
+/* define SIGNATURE 0 space-holder only */
+# define NUMBER_THIS_DISK 4
+# define NUM_DISK_WITH_START_CENTRAL_DIR 6
+# define NUM_ENTRIES_CENTRL_DIR_THS_DISK 8
+# define TOTAL_ENTRIES_CENTRAL_DIR 10
+# define SIZE_CENTRAL_DIRECTORY 12
+# define OFFSET_START_CENTRAL_DIRECTORY 16
+# define ZIPFILE_COMMENT_LENGTH 20
+
+
+ typedef struct local_file_header { /* LOCAL */
+ byte version_needed_to_extract[2];
+ UWORD general_purpose_bit_flag;
+ UWORD compression_method;
+ UWORD last_mod_file_time;
+ UWORD last_mod_file_date;
+ ULONG crc32;
+ ULONG compressed_size;
+ ULONG uncompressed_size;
+ UWORD filename_length;
+ UWORD extra_field_length;
+ } local_file_hdr;
+
+ typedef struct central_directory_file_header { /* CENTRAL */
+ byte version_made_by[2];
+ byte version_needed_to_extract[2];
+ UWORD general_purpose_bit_flag;
+ UWORD compression_method;
+ UWORD last_mod_file_time;
+ UWORD last_mod_file_date;
+ ULONG crc32;
+ ULONG compressed_size;
+ ULONG uncompressed_size;
+ UWORD filename_length;
+ UWORD extra_field_length;
+ UWORD file_comment_length;
+ UWORD disk_number_start;
+ UWORD internal_file_attributes;
+ ULONG external_file_attributes;
+ ULONG relative_offset_local_header;
+ } cdir_file_hdr;
+
+ typedef struct end_central_dir_record { /* END CENTRAL */
+ UWORD number_this_disk;
+ UWORD num_disk_with_start_central_dir;
+ UWORD num_entries_centrl_dir_ths_disk;
+ UWORD total_entries_central_dir;
+ ULONG size_central_directory;
+ ULONG offset_start_central_directory;
+ UWORD zipfile_comment_length;
+ } ecdir_rec;
+
+
+
+
+
+/*************************/
+/* Function Prototypes */
+/*************************/
+
+#ifndef __
+# define __ OF
+#endif
+
+/*---------------------------------------------------------------------------
+ Decompression functions:
+ ---------------------------------------------------------------------------*/
+
+int explode ();
+void unReduce ();
+void unShrink ();
+
+/*---------------------------------------------------------------------------
+ Functions in file_io.c and crypt.c:
+ ---------------------------------------------------------------------------*/
+
+int FillBitBuffer ();
+int ReadByte __((UWORD *x)); /* file_io.c */
+
+/************/
+/* Macros */
+/************/
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+# define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+
+#define LSEEK(abs_offset) {longint request=(abs_offset)+extra_bytes,\
+ inbuf_offset=request%INBUFSIZ, bufstart=request-inbuf_offset;\
+ if(request<0) {fprintf(stderr, SeekMsg, ReportMsg); return(3);}\
+ else if(bufstart!=cur_zipfile_bufstart)\
+ {cur_zipfile_bufstart=lseek(zipfd,bufstart,SEEK_SET);\
+ if((incnt=read(zipfd,(char *)inbuf,INBUFSIZ))<=0) return(51);\
+ inptr=inbuf+(int)inbuf_offset; incnt-=(int)inbuf_offset;} else\
+ {incnt+=(inptr-inbuf)-(int)inbuf_offset; inptr=inbuf+(int)inbuf_offset;}}
+
+/*
+ * Seek to the block boundary of the block which includes abs_offset,
+ * then read block into input buffer and set pointers appropriately.
+ * If block is already in the buffer, just set the pointers. This macro
+ * is used by process_end_central_dir (unzip.c) and do_string (misc.c).
+ * A slightly modified version is embedded within extract_or_test_files
+ * (unzip.c). ReadByte and readbuf (file_io.c) are compatible.
+ *
+ * macro LSEEK(abs_offset)
+ * ULONG abs_offset;
+ * {
+ * longint request = abs_offset + extra_bytes;
+ * longint inbuf_offset = request % INBUFSIZ;
+ * longint bufstart = request - inbuf_offset;
+ *
+ * if (request < 0) {
+ * fprintf(stderr, SeekMsg, ReportMsg);
+ * return(3); /-* 3: severe error in zipfile *-/
+ * } else if (bufstart != cur_zipfile_bufstart) {
+ * cur_zipfile_bufstart = lseek(zipfd, bufstart, SEEK_SET);
+ * if ((incnt = read(zipfd,inbuf,INBUFSIZ)) <= 0)
+ * return(51); /-* 51: unexpected EOF *-/
+ * inptr = inbuf + (int)inbuf_offset;
+ * incnt -= (int)inbuf_offset;
+ * } else {
+ * incnt += (inptr-inbuf) - (int)inbuf_offset;
+ * inptr = inbuf + (int)inbuf_offset;
+ * }
+ * }
+ *
+ */
+
+
+#define SKIP_(length) if(length&&((error=do_string(length,SKIP))!=0))\
+ {error_in_archive=error; if(error>1) return error;}
+
+/*
+ * Skip a variable-length field, and report any errors. Used in zipinfo.c
+ * and unzip.c in several functions.
+ *
+ * macro SKIP_(length)
+ * UWORD length;
+ * {
+ * if (length && ((error = do_string(length, SKIP)) != 0)) {
+ * error_in_archive = error; /-* might be warning *-/
+ * if (error > 1) /-* fatal *-/
+ * return (error);
+ * }
+ * }
+ *
+ */
+
+#define READBIT(nbits,zdest) {if(nbits>bits_left) FillBitBuffer();\
+ zdest=(int)((UWORD)bitbuf&mask_bits[nbits]);bitbuf>>=nbits;bits_left-=nbits;}
+
+/*
+ * macro READBIT(nbits,zdest)
+ * {
+ * if (nbits > bits_left)
+ * FillBitBuffer();
+ * zdest = (int)((UWORD)bitbuf & mask_bits[nbits]);
+ * bitbuf >>= nbits;
+ * bits_left -= nbits;
+ * }
+ *
+ */
+
+
+#define PEEKBIT(nbits) (nbits>bits_left? (FillBitBuffer(),\
+ (UWORD)bitbuf & mask_bits[nbits]) : (UWORD)bitbuf & mask_bits[nbits])
+
+
+#define NUKE_CRs(buf,len) {register int i,j; for (i=j=0; j<len;\
+ (buf)[i++]=(buf)[j++]) if ((buf)[j]=='\r') ++j; len=i;}
+
+/*
+ * Remove all the ASCII carriage returns from buffer buf (length len),
+ * shortening as necessary (note that len gets modified in the process,
+ * so it CANNOT be an expression). This macro is intended to be used
+ * BEFORE A_TO_N(); hence the check for CR instead of '\r'. NOTE: The
+ * if-test gets performed one time too many, but it doesn't matter.
+ *
+ * macro NUKE_CRs(buf,len)
+ * {
+ * register int i, j;
+ *
+ * for (i = j = 0; j < len; (buf)[i++] = (buf)[j++])
+ * if ((buf)[j] == CR)
+ * ++j;
+ * len = i;
+ * }
+ *
+ */
+
+
+#define TOLOWER(str1,str2) {char *ps1,*ps2; ps1=(str1)-1; ps2=(str2);\
+ while(*++ps1) *ps2++=(char)(isupper((int)(*ps1))?tolower((int)(*ps1)):*ps1);\
+ *ps2='\0';}
+
+/*
+ * Copy the zero-terminated string in str1 into str2, converting any
+ * uppercase letters to lowercase as we go. str2 gets zero-terminated
+ * as well, of course. str1 and str2 may be the same character array.
+ *
+ * macro TOLOWER( str1, str2 )
+ * {
+ * char *ps1, *ps2;
+ *
+ * ps1 = (str1) - 1;
+ * ps2 = (str2);
+ * while (*++ps1)
+ * *ps2++ = (char)(isupper((int)(*ps1))? tolower((int)(*ps1)) : *ps1);
+ * *ps2='\0';
+ * }
+ *
+ * NOTES: This macro makes no assumptions about the characteristics of
+ * the tolower() function or macro (beyond its existence), nor does it
+ * make assumptions about the structure of the character set (i.e., it
+ * should work on EBCDIC machines, too). The fact that either or both
+ * of isupper() and tolower() may be macros has been taken into account;
+ * watch out for "side effects" (in the C sense) when modifying this
+ * macro.
+ */
+
+
+#ifndef ascii_to_native
+# define ascii_to_native(c) (c)
+# define A_TO_N(str1)
+#else
+# ifndef NATIVE
+# define NATIVE "native chars"
+# endif
+# define A_TO_N(str1) {register unsigned char *ps1;\
+ for (ps1=str1; *ps1; ps1++) *ps1=ascii_to_native(*ps1);}
+#endif
+
+/*
+ * Translate the zero-terminated string in str1 from ASCII to the native
+ * character set. The translation is performed in-place and uses the
+ * ascii_to_native macro to translate each character.
+ *
+ * macro A_TO_N( str1 )
+ * {
+ * register unsigned char *ps1;
+ *
+ * for (ps1 = str1; *ps1; ++ps1)
+ * *ps1 = ascii_to_native(*ps1);
+ * }
+ *
+ * NOTE: Using the ascii_to_native macro means that is it the only part of
+ * unzip which knows which translation table (if any) is actually in use
+ * to produce the native character set. This makes adding new character
+ * set translation tables easy, insofar as all that is needed is an
+ * appropriate ascii_to_native macro definition and the translation
+ * table itself. Currently, the only non-ASCII native character set
+ * implemented is EBCDIC, but this may not always be so.
+ */
+
+/*************/
+/* Globals */
+/*************/
+
+#ifdef MACOS
+ union work {
+ struct {
+ short *Prefix_of; /* (8193 * sizeof(short)) */
+ byte *Suffix_of;
+ byte *Stack;
+ } shrink;
+ byte *Slide;
+ };
+#else
+ union work {
+ struct {
+ short Prefix_of[HSIZE + 2]; /* (8194 * sizeof(short)) */
+ byte Suffix_of[HSIZE + 2]; /* also s-f length_nodes (smaller) */
+ byte Stack[HSIZE + 2]; /* also s-f distance_nodes (smaller) */
+ } shrink;
+ byte Slide[WSIZE];
+ };
+#endif
+ extern union work area;
+
+# define prefix_of area.shrink.Prefix_of
+# define suffix_of area.shrink.Suffix_of
+# define stack area.shrink.Stack
+# define slide area.Slide
+
+ extern ULONG crc32val;
+ extern UWORD mask_bits[];
+ extern int bits_left;
+ extern ULONG bitbuf;
+ extern boolean zipeof;
+
diff --git a/source/unzip/unzip.c b/source/unzip/unzip.c
new file mode 100644
index 0000000..54695c2
--- /dev/null
+++ b/source/unzip/unzip.c
@@ -0,0 +1,1224 @@
+/*
+ * unzip.c -- IO on .zip files using zlib Version 0.15 beta, Mar 19th, 1998,
+ *
+ * Read unzip.h for more info
+ */
+
+
+//#include <stdio.h>
+//#include <stdlib.h>
+#include "fs_api.h"
+#include "ds2_malloc.h"
+#include <string.h>
+#include "zlib.h"
+#include "unzip.h"
+#include "unzipP.h"
+
+#ifdef STDC
+//#include <stddef.h>
+//#include <string.h>
+//#include <stdlib.h>
+#endif
+
+#ifdef NO_ERRNO_H
+extern int errno;
+#else
+#include <errno.h>
+#endif
+
+const char unz_copyright[] =
+" unzip 0.15 Copyright 1998 Gilles Vollant ";
+
+void unShrink ();
+void unReduce ();
+int explode ();
+
+/*
+ * ===========================================================================
+ * Read a byte from a gz_stream; update next_in and avail_in. Return EOF for
+ * end of file. IN assertion: the stream s has been sucessfully opened for
+ * reading.
+ */
+
+
+local int
+unzlocal_getByte (FILE * fin, int *pi)
+{
+ unsigned char c;
+ int err = fread (&c, 1, 1, fin);
+ if (err == 1)
+ {
+ *pi = (int) c;
+ return UNZ_OK;
+ } else
+ {
+ if (ferror (fin))
+ return UNZ_ERRNO;
+ else
+ return UNZ_EOF;
+ }
+}
+
+
+/*
+ * ===========================================================================
+ * Reads a long in LSB order from the given gz_stream. Sets
+ */
+local int
+unzlocal_getShort (FILE * fin, uLong * pX)
+{
+ uLong x;
+ int i;
+ int err;
+
+ err = unzlocal_getByte (fin, &i);
+ x = (uLong) i;
+
+ if (err == UNZ_OK)
+ err = unzlocal_getByte (fin, &i);
+ x += ((uLong) i) << 8;
+
+ if (err == UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+local int
+unzlocal_getLong (FILE * fin, uLong * pX)
+{
+ uLong x;
+ int i;
+ int err;
+
+ err = unzlocal_getByte (fin, &i);
+ x = (uLong) i;
+
+ if (err == UNZ_OK)
+ err = unzlocal_getByte (fin, &i);
+ x += ((uLong) i) << 8;
+
+ if (err == UNZ_OK)
+ err = unzlocal_getByte (fin, &i);
+ x += ((uLong) i) << 16;
+
+ if (err == UNZ_OK)
+ err = unzlocal_getByte (fin, &i);
+ x += ((uLong) i) << 24;
+
+ if (err == UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+
+/* My own strcmpi / strcasecmp */
+local int
+strcmpcasenosensitive_internal (const char *fileName1, const char *fileName2)
+{
+ for (;;)
+ {
+ char c1 = *(fileName1++);
+ char c2 = *(fileName2++);
+ if ((c1 >= 'a') && (c1 <= 'z'))
+ c1 -= 0x20;
+ if ((c2 >= 'a') && (c2 <= 'z'))
+ c2 -= 0x20;
+ if (c1 == '\0')
+ return ((c2 == '\0') ? 0 : -1);
+ if (c2 == '\0')
+ return 1;
+ if (c1 < c2)
+ return -1;
+ if (c1 > c2)
+ return 1;
+ }
+}
+
+
+#ifdef CASESENSITIVITYDEFAULT_NO
+#define CASESENSITIVITYDEFAULTVALUE 2
+#else
+#define CASESENSITIVITYDEFAULTVALUE 1
+#endif
+
+#ifndef STRCMPCASENOSENTIVEFUNCTION
+#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
+#endif
+
+/*
+ * Compare two filename (fileName1,fileName2). If iCaseSenisivity = 1,
+ * comparision is case sensitivity (like strcmp) If iCaseSenisivity = 2,
+ * comparision is not case sensitivity (like strcmpi or strcasecmp) If
+ * iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+ * (like 1 on Unix, 2 on Windows)
+ *
+ */
+extern int ZEXPORT
+unzStringFileNameCompare (const char *fileName1, const char *fileName2, int iCaseSensitivity)
+{
+ if (iCaseSensitivity == 0)
+ iCaseSensitivity = CASESENSITIVITYDEFAULTVALUE;
+
+ if (iCaseSensitivity == 1)
+ return strcmp (fileName1, fileName2);
+
+ return STRCMPCASENOSENTIVEFUNCTION (fileName1, fileName2);
+}
+
+#define BUFREADCOMMENT (0x400)
+
+/*
+ * Locate the Central directory of a zipfile (at the end, just before the
+ * global comment)
+ */
+local uLong
+unzlocal_SearchCentralDir (FILE * fin)
+{
+ unsigned char *buf;
+ uLong uSizeFile;
+ uLong uBackRead;
+ uLong uMaxBack = 0xffff; /* maximum size of global comment */
+ uLong uPosFound = 0;
+
+ if (fseek (fin, 0, SEEK_END) != 0)
+ return 0;
+
+ uSizeFile = ftell (fin);
+
+ if (uMaxBack > uSizeFile)
+ uMaxBack = uSizeFile;
+
+ buf = (unsigned char *) ALLOC (BUFREADCOMMENT + 4);
+ if (buf == NULL)
+ return 0;
+
+ uBackRead = 4;
+ while (uBackRead < uMaxBack)
+ {
+ uLong uReadSize, uReadPos;
+ int i;
+ if (uBackRead + BUFREADCOMMENT > uMaxBack)
+ uBackRead = uMaxBack;
+ else
+ uBackRead += BUFREADCOMMENT;
+ uReadPos = uSizeFile - uBackRead;
+
+ uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) ?
+ (BUFREADCOMMENT + 4) : (uSizeFile - uReadPos);
+ if (fseek (fin, uReadPos, SEEK_SET) != 0)
+ break;
+
+ if (fread (buf, (uInt) uReadSize, 1, fin) != 1)
+ break;
+
+ for (i = 0; i < (int) uReadSize - 3; i++)
+ if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) &&
+ ((*(buf + i + 2)) == 0x05) && ((*(buf + i + 3)) == 0x06))
+ {
+ uPosFound = uReadPos + i;
+ break;
+ }
+ if (uPosFound != 0)
+ break;
+ }
+ TRYFREE (buf);
+ return uPosFound;
+}
+
+/*
+ * Open a Zip file. path contain the full pathname (by example, on a Windows
+ * NT computer "c:\\test\\zlib109.zip" or on an Unix computer
+ * "zlib/zlib109.zip". If the zipfile cannot be opened (file don't exist or
+ * in not valid), the return value is NULL. Else, the return value is a
+ * unzFile Handle, usable with other function of this unzip package.
+ */
+extern unzFile ZEXPORT
+unzOpen (const char *path)
+{
+ unz_s us;
+ unz_s *s;
+ uLong central_pos, uL;
+ FILE *fin;
+
+ uLong number_disk;/* number of the current dist, used for
+ * spaning ZIP, unsupported, always 0 */
+ uLong number_disk_with_CD; /* number the the disk with
+ * central dir, used for
+ * spaning ZIP, unsupported,
+ * always 0 */
+ uLong number_entry_CD; /* total number of entries in the
+ * central dir (same than
+ * number_entry on nospan) */
+
+ int err = UNZ_OK;
+
+ if (unz_copyright[0] != ' ')
+ return NULL;
+
+ fin = fopen (path, "rb");
+ if (fin == NULL)
+ return NULL;
+
+ central_pos = unzlocal_SearchCentralDir (fin);
+ if (central_pos == 0)
+ err = UNZ_ERRNO;
+
+ if (fseek (fin, central_pos, SEEK_SET) != 0)
+ err = UNZ_ERRNO;
+
+ /* the signature, already checked */
+ if (unzlocal_getLong (fin, &uL) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ /* number of this disk */
+ if (unzlocal_getShort (fin, &number_disk) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ /* number of the disk with the start of the central directory */
+ if (unzlocal_getShort (fin, &number_disk_with_CD) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ /* total number of entries in the central dir on this disk */
+ if (unzlocal_getShort (fin, &us.gi.number_entry) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ /* total number of entries in the central dir */
+ if (unzlocal_getShort (fin, &number_entry_CD) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if ((number_entry_CD != us.gi.number_entry) ||
+ (number_disk_with_CD != 0) ||
+ (number_disk != 0))
+ err = UNZ_BADZIPFILE;
+
+ /* size of the central directory */
+ if (unzlocal_getLong (fin, &us.size_central_dir) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ /*
+ * offset of start of central directory with respect to the starting disk
+ * number
+ */
+ if (unzlocal_getLong (fin, &us.offset_central_dir) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ /* zipfile comment length */
+ if (unzlocal_getShort (fin, &us.gi.size_comment) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if ((central_pos < us.offset_central_dir + us.size_central_dir) &&
+ (err == UNZ_OK))
+ err = UNZ_BADZIPFILE;
+
+ if (err != UNZ_OK)
+ {
+ fclose (fin);
+ return NULL;
+ }
+ us.file = fin;
+ us.byte_before_the_zipfile = central_pos -
+ (us.offset_central_dir + us.size_central_dir);
+ us.central_pos = central_pos;
+ us.pfile_in_zip_read = NULL;
+
+
+ s = (unz_s *) ALLOC (sizeof (unz_s));
+ *s = us;
+ unzGoToFirstFile ((unzFile) s);
+ return (unzFile) s;
+}
+
+
+/*
+ * Close a ZipFile opened with unzipOpen. If there is files inside the .Zip
+ * opened with unzipOpenCurrentFile (see later), these files MUST be closed
+ * with unzipCloseCurrentFile before call unzipClose. return UNZ_OK if there
+ * is no problem.
+ */
+extern int ZEXPORT
+unzClose (unzFile file)
+{
+ unz_s *s;
+ if (file == NULL)
+ return UNZ_PARAMERROR;
+ s = (unz_s *) file;
+
+ if (s->pfile_in_zip_read != NULL)
+ unzCloseCurrentFile (file);
+
+ fclose (s->file);
+ TRYFREE (s);
+ return UNZ_OK;
+}
+
+
+/*
+ * Write info about the ZipFile in the *pglobal_info structure. No
+ * preparation of the structure is needed return UNZ_OK if there is no
+ * problem.
+ */
+extern int ZEXPORT
+unzGetGlobalInfo (unzFile file, unz_global_info * pglobal_info)
+{
+ unz_s *s;
+ if (file == NULL)
+ return UNZ_PARAMERROR;
+ s = (unz_s *) file;
+ *pglobal_info = s->gi;
+ return UNZ_OK;
+}
+
+
+/*
+ * Translate date/time from Dos format to tm_unz (readable more easilty)
+ */
+local void
+unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz * ptm)
+{
+ uLong uDate;
+ uDate = (uLong) (ulDosDate >> 16);
+ ptm->tm_mday = (uInt) (uDate & 0x1f);
+ ptm->tm_mon = (uInt) ((((uDate) & 0x1E0) / 0x20) - 1);
+ ptm->tm_year = (uInt) (((uDate & 0x0FE00) / 0x0200) + 1980);
+
+ ptm->tm_hour = (uInt) ((ulDosDate & 0xF800) / 0x800);
+ ptm->tm_min = (uInt) ((ulDosDate & 0x7E0) / 0x20);
+ ptm->tm_sec = (uInt) (2 * (ulDosDate & 0x1f));
+}
+
+/*
+ * Get Info about the current file in the zipfile, with internal only info
+ */
+local int unzlocal_GetCurrentFileInfoInternal
+OF ((unzFile file,
+ unz_file_info * pfile_info,
+ unz_file_info_internal
+ * pfile_info_internal,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+
+ local int unzlocal_GetCurrentFileInfoInternal (
+ unzFile file,
+ unz_file_info * pfile_info,
+ unz_file_info_internal * pfile_info_internal,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize)
+{
+ unz_s *s;
+ unz_file_info file_info;
+ unz_file_info_internal file_info_internal;
+ int err = UNZ_OK;
+ uLong uMagic;
+ long lSeek = 0;
+
+ if (file == NULL)
+ return UNZ_PARAMERROR;
+ s = (unz_s *) file;
+ if (fseek (s->file, s->pos_in_central_dir + s->byte_before_the_zipfile, SEEK_SET) != 0)
+ err = UNZ_ERRNO;
+
+
+ /* we check the magic */
+ if (err == UNZ_OK)
+ {
+ if (unzlocal_getLong (s->file, &uMagic) != UNZ_OK)
+ err = UNZ_ERRNO;
+ else if (uMagic != 0x02014b50)
+ err = UNZ_BADZIPFILE;
+ }
+ if (unzlocal_getShort (s->file, &file_info.version) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getShort (s->file, &file_info.version_needed) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getShort (s->file, &file_info.flag) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getShort (s->file, &file_info.compression_method) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getLong (s->file, &file_info.dosDate) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ unzlocal_DosDateToTmuDate (file_info.dosDate, &file_info.tmu_date);
+
+ if (unzlocal_getLong (s->file, &file_info.crc) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getLong (s->file, &file_info.compressed_size) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getLong (s->file, &file_info.uncompressed_size) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getShort (s->file, &file_info.size_filename) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getShort (s->file, &file_info.size_file_extra) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getShort (s->file, &file_info.size_file_comment) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getShort (s->file, &file_info.disk_num_start) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getShort (s->file, &file_info.internal_fa) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getLong (s->file, &file_info.external_fa) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getLong (s->file, &file_info_internal.offset_curfile) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ lSeek += file_info.size_filename;
+ if ((err == UNZ_OK) && (szFileName != NULL))
+ {
+ uLong uSizeRead;
+ if (file_info.size_filename < fileNameBufferSize)
+ {
+ *(szFileName + file_info.size_filename) = '\0';
+ uSizeRead = file_info.size_filename;
+ } else
+ uSizeRead = fileNameBufferSize;
+
+ if ((file_info.size_filename > 0) && (fileNameBufferSize > 0))
+ if (fread (szFileName, (uInt) uSizeRead, 1, s->file) != 1)
+ err = UNZ_ERRNO;
+ lSeek -= uSizeRead;
+ }
+ if ((err == UNZ_OK) && (extraField != NULL))
+ {
+ uLong uSizeRead;
+ if (file_info.size_file_extra < extraFieldBufferSize)
+ uSizeRead = file_info.size_file_extra;
+ else
+ uSizeRead = extraFieldBufferSize;
+
+ if (lSeek != 0)
+ {
+ if (fseek (s->file, lSeek, SEEK_CUR) == 0)
+ lSeek = 0;
+ else
+ err = UNZ_ERRNO;
+ }
+ if ((file_info.size_file_extra > 0) && (extraFieldBufferSize > 0))
+ if (fread (extraField, (uInt) uSizeRead, 1, s->file) != 1)
+ err = UNZ_ERRNO;
+ lSeek += file_info.size_file_extra - uSizeRead;
+ } else
+ lSeek += file_info.size_file_extra;
+
+
+ if ((err == UNZ_OK) && (szComment != NULL))
+ {
+ uLong uSizeRead;
+ if (file_info.size_file_comment < commentBufferSize)
+ {
+ *(szComment + file_info.size_file_comment) = '\0';
+ uSizeRead = file_info.size_file_comment;
+ } else
+ uSizeRead = commentBufferSize;
+
+ if (lSeek != 0)
+ {
+ if (fseek (s->file, lSeek, SEEK_CUR) == 0)
+ lSeek = 0;
+ else
+ err = UNZ_ERRNO;
+ }
+ if ((file_info.size_file_comment > 0) && (commentBufferSize > 0))
+ if (fread (szComment, (uInt) uSizeRead, 1, s->file) != 1)
+ err = UNZ_ERRNO;
+ lSeek += file_info.size_file_comment - uSizeRead;
+ } else
+ lSeek += file_info.size_file_comment;
+
+ if ((err == UNZ_OK) && (pfile_info != NULL))
+ *pfile_info = file_info;
+
+ if ((err == UNZ_OK) && (pfile_info_internal != NULL))
+ *pfile_info_internal = file_info_internal;
+
+ return err;
+}
+
+
+
+/*
+ * Write info about the ZipFile in the *pglobal_info structure. No
+ * preparation of the structure is needed return UNZ_OK if there is no
+ * problem.
+ */
+extern int ZEXPORT
+unzGetCurrentFileInfo (
+ unzFile file,
+ unz_file_info * pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize)
+{
+ return unzlocal_GetCurrentFileInfoInternal (file, pfile_info, NULL,
+ szFileName, fileNameBufferSize,
+ extraField, extraFieldBufferSize,
+ szComment, commentBufferSize);
+}
+
+/*
+ * Set the current file of the zipfile to the first file. return UNZ_OK if
+ * there is no problem
+ */
+extern int ZEXPORT
+unzGoToFirstFile (unzFile file)
+{
+ int err = UNZ_OK;
+ unz_s *s;
+ if (file == NULL)
+ return UNZ_PARAMERROR;
+ s = (unz_s *) file;
+ s->pos_in_central_dir = s->offset_central_dir;
+ s->num_file = 0;
+ err = unzlocal_GetCurrentFileInfoInternal (file, &s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL, 0, NULL, 0, NULL, 0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+
+/*
+ * Set the current file of the zipfile to the next file. return UNZ_OK if
+ * there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was
+ * the latest.
+ */
+extern int ZEXPORT
+unzGoToNextFile (unzFile file)
+{
+ unz_s *s;
+ int err;
+
+ if (file == NULL)
+ return UNZ_PARAMERROR;
+ s = (unz_s *) file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (s->num_file + 1 == s->gi.number_entry)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
+ s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment;
+ s->num_file++;
+ err = unzlocal_GetCurrentFileInfoInternal (file, &s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL, 0, NULL, 0, NULL, 0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+
+/*
+ * Try locate the file szFileName in the zipfile. For the iCaseSensitivity
+ * signification, see unzipStringFileNameCompare
+ *
+ * return value : UNZ_OK if the file is found. It becomes the current file.
+ * UNZ_END_OF_LIST_OF_FILE if the file is not found
+ */
+extern int ZEXPORT
+unzLocateFile (
+ unzFile file,
+ const char *szFileName,
+ int iCaseSensitivity)
+{
+ unz_s *s;
+ int err;
+
+
+ uLong num_fileSaved;
+ uLong pos_in_central_dirSaved;
+
+
+ if (file == NULL)
+ return UNZ_PARAMERROR;
+
+ if (strlen (szFileName) >= UNZ_MAXFILENAMEINZIP)
+ return UNZ_PARAMERROR;
+
+ s = (unz_s *) file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ num_fileSaved = s->num_file;
+ pos_in_central_dirSaved = s->pos_in_central_dir;
+
+ err = unzGoToFirstFile (file);
+
+ while (err == UNZ_OK)
+ {
+ char szCurrentFileName[UNZ_MAXFILENAMEINZIP + 1];
+ unzGetCurrentFileInfo (file, NULL,
+ szCurrentFileName, sizeof (szCurrentFileName) - 1,
+ NULL, 0, NULL, 0);
+ if (unzStringFileNameCompare (szCurrentFileName,
+ szFileName, iCaseSensitivity) == 0)
+ return UNZ_OK;
+ err = unzGoToNextFile (file);
+ }
+
+ s->num_file = num_fileSaved;
+ s->pos_in_central_dir = pos_in_central_dirSaved;
+ return err;
+}
+
+
+/*
+ * Read the local header of the current zipfile Check the coherency of the
+ * local header and info in the end of central directory about this file
+ * store in *piSizeVar the size of extra info in local header (filename and
+ * size of extra field data)
+ */
+local int
+unzlocal_CheckCurrentFileCoherencyHeader (
+ unz_s * s,
+ uInt * piSizeVar,
+ uLong * poffset_local_extrafield,
+ uInt * psize_local_extrafield)
+{
+ uLong uMagic, uData, uFlags;
+ uLong size_filename;
+ uLong size_extra_field;
+ int err = UNZ_OK;
+
+ *piSizeVar = 0;
+ *poffset_local_extrafield = 0;
+ *psize_local_extrafield = 0;
+
+ if (fseek (s->file, s->cur_file_info_internal.offset_curfile +
+ s->byte_before_the_zipfile, SEEK_SET) != 0)
+ return UNZ_ERRNO;
+
+
+ if (err == UNZ_OK)
+ {
+ if (unzlocal_getLong (s->file, &uMagic) != UNZ_OK)
+ err = UNZ_ERRNO;
+ else if (uMagic != 0x04034b50)
+ err = UNZ_BADZIPFILE;
+ }
+
+ if (unzlocal_getShort (s->file, &uData) != UNZ_OK)
+ err = UNZ_ERRNO;
+ /*
+ * else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
+ * err=UNZ_BADZIPFILE;
+ */
+ if (unzlocal_getShort (s->file, &uFlags) != UNZ_OK)
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getShort (s->file, &uData) != UNZ_OK)
+ err = UNZ_ERRNO;
+ else if ((err == UNZ_OK) && (uData != s->cur_file_info.compression_method))
+ err = UNZ_BADZIPFILE;
+
+ if ((err == UNZ_OK) &&
+ s->cur_file_info.compression_method > Z_DEFLATED)
+ err = UNZ_BADZIPFILE;
+
+ if (unzlocal_getLong (s->file, &uData) != UNZ_OK) /* date/time */
+ err = UNZ_ERRNO;
+
+ if (unzlocal_getLong (s->file, &uData) != UNZ_OK) /* crc */
+ err = UNZ_ERRNO;
+ else if ((err == UNZ_OK) && (uData != s->cur_file_info.crc) &&
+ ((uFlags & 8) == 0))
+ err = UNZ_BADZIPFILE;
+
+ if (unzlocal_getLong (s->file, &uData) != UNZ_OK) /* size compr */
+ err = UNZ_ERRNO;
+ else if ((err == UNZ_OK) && (uData != s->cur_file_info.compressed_size) &&
+ ((uFlags & 8) == 0))
+ err = UNZ_BADZIPFILE;
+
+ if (unzlocal_getLong (s->file, &uData) != UNZ_OK) /* size uncompr */
+ err = UNZ_ERRNO;
+ else if ((err == UNZ_OK) && (uData != s->cur_file_info.uncompressed_size) &&
+ ((uFlags & 8) == 0))
+ err = UNZ_BADZIPFILE;
+
+
+ if (unzlocal_getShort (s->file, &size_filename) != UNZ_OK)
+ err = UNZ_ERRNO;
+ else if ((err == UNZ_OK) && (size_filename != s->cur_file_info.size_filename))
+ err = UNZ_BADZIPFILE;
+
+ *piSizeVar += (uInt) size_filename;
+
+ if (unzlocal_getShort (s->file, &size_extra_field) != UNZ_OK)
+ err = UNZ_ERRNO;
+ *poffset_local_extrafield = s->cur_file_info_internal.offset_curfile +
+ SIZEZIPLOCALHEADER + size_filename;
+ *psize_local_extrafield = (uInt) size_extra_field;
+
+ *piSizeVar += (uInt) size_extra_field;
+
+ return err;
+}
+
+/*
+ * Open for reading data the current file in the zipfile. If there is no
+ * error and the file is opened, the return value is UNZ_OK.
+ */
+extern int ZEXPORT
+unzOpenCurrentFile (unzFile file)
+{
+ int err = UNZ_OK;
+ uInt iSizeVar;
+ unz_s *s;
+ file_in_zip_read_info_s *pfile_in_zip_read_info;
+ uLong offset_local_extrafield; /* offset of the local extra
+ * field */
+ uInt size_local_extrafield; /* size of the local extra
+ * field */
+
+ if (file == NULL)
+ return UNZ_PARAMERROR;
+ s = (unz_s *) file;
+ if (!s->current_file_ok)
+ return UNZ_PARAMERROR;
+
+ if (s->pfile_in_zip_read != NULL)
+ unzCloseCurrentFile (file);
+
+ if (unzlocal_CheckCurrentFileCoherencyHeader (s, &iSizeVar,
+ &offset_local_extrafield, &size_local_extrafield) != UNZ_OK)
+ return UNZ_BADZIPFILE;
+
+ pfile_in_zip_read_info = (file_in_zip_read_info_s *)
+ ALLOC (sizeof (file_in_zip_read_info_s));
+ if (pfile_in_zip_read_info == NULL)
+ return UNZ_INTERNALERROR;
+
+ pfile_in_zip_read_info->read_buffer = (char *) ALLOC (UNZ_BUFSIZE);
+ pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
+ pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
+ pfile_in_zip_read_info->pos_local_extrafield = 0;
+
+ if (pfile_in_zip_read_info->read_buffer == NULL)
+ {
+ TRYFREE (pfile_in_zip_read_info);
+ return UNZ_INTERNALERROR;
+ }
+ pfile_in_zip_read_info->stream_initialised = 0;
+
+ if (s->cur_file_info.compression_method > Z_DEFLATED)
+ err = UNZ_BADZIPFILE;
+
+ pfile_in_zip_read_info->crc32_wait = s->cur_file_info.crc;
+ pfile_in_zip_read_info->crc32 = 0;
+ pfile_in_zip_read_info->compression_method =
+ s->cur_file_info.compression_method;
+ pfile_in_zip_read_info->file = s->file;
+ pfile_in_zip_read_info->byte_before_the_zipfile = s->byte_before_the_zipfile;
+
+ pfile_in_zip_read_info->stream.total_out = 0;
+
+ switch (s->cur_file_info.compression_method)
+ {
+ case UNZ_STORED:
+ break;
+ case UNZ_SHRUNK:
+ break;
+ case UNZ_REDUCED1:
+ case UNZ_REDUCED2:
+ case UNZ_REDUCED3:
+ case UNZ_REDUCED4:
+ break;
+ case UNZ_IMPLODED:
+ break;
+ case UNZ_DEFLATED:
+ pfile_in_zip_read_info->stream.zalloc = (alloc_func) 0;
+ pfile_in_zip_read_info->stream.zfree = (free_func) 0;
+ pfile_in_zip_read_info->stream.opaque = (voidpf) 0;
+
+ err = inflateInit2 (&pfile_in_zip_read_info->stream, -MAX_WBITS);
+ if (err == Z_OK)
+ pfile_in_zip_read_info->stream_initialised = 1;
+ /*
+ * windowBits is passed < 0 to tell that there is no zlib header.
+ * Note that in this case inflate *requires* an extra "dummy" byte
+ * after the compressed stream in order to complete decompression and
+ * return Z_STREAM_END. In unzip, i don't wait absolutely
+ * Z_STREAM_END because I known the size of both compressed and
+ * uncompressed data
+ */
+ break;
+ default:
+ return UNZ_INTERNALERROR;
+ break;
+ }
+ pfile_in_zip_read_info->rest_read_compressed =
+ s->cur_file_info.compressed_size;
+ pfile_in_zip_read_info->rest_read_uncompressed =
+ s->cur_file_info.uncompressed_size;
+
+ pfile_in_zip_read_info->pos_in_zipfile =
+ s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
+ iSizeVar;
+
+ pfile_in_zip_read_info->stream.avail_in = (uInt) 0;
+ s->pfile_in_zip_read = pfile_in_zip_read_info;
+ return UNZ_OK;
+}
+
+
+/*
+ * Read bytes from the current file. buf contain buffer where data must be
+ * copied len the size of buf.
+ *
+ * return the number of byte copied if somes bytes are copied return 0 if the
+ * end of file was reached return <0 with error code if there is an error
+ * (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+ */
+
+file_in_zip_read_info_s *pfile_in_zip_read_info = NULL;
+unz_s *pUnzip = NULL;
+extern int ZEXPORT
+unzReadCurrentFile (
+ unzFile file,
+ voidp buf,
+ unsigned len)
+{
+ int err = UNZ_OK;
+ uInt iRead = 0;
+ unz_s *s;
+ if (file == NULL)
+ return UNZ_PARAMERROR;
+ s = (unz_s *) file;
+ pUnzip = s;
+ pfile_in_zip_read_info = s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info == NULL)
+ return UNZ_PARAMERROR;
+
+
+ if ((pfile_in_zip_read_info->read_buffer == NULL))
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (len == 0)
+ return 0;
+
+ pfile_in_zip_read_info->stream.next_out = (Bytef *) buf;
+
+ pfile_in_zip_read_info->stream.avail_out = (uInt) len;
+
+ if (len > pfile_in_zip_read_info->rest_read_uncompressed)
+ pfile_in_zip_read_info->stream.avail_out =
+ (uInt) pfile_in_zip_read_info->rest_read_uncompressed;
+
+ while (pfile_in_zip_read_info->stream.avail_out > 0 && err == UNZ_OK)
+ {
+ switch (pfile_in_zip_read_info->compression_method)
+ {
+ case UNZ_STORED:
+ case UNZ_DEFLATED:
+ if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
+ (pfile_in_zip_read_info->rest_read_compressed > 0))
+ {
+ uInt uReadThis = UNZ_BUFSIZE;
+ if (pfile_in_zip_read_info->rest_read_compressed < uReadThis)
+ uReadThis = (uInt) pfile_in_zip_read_info->rest_read_compressed;
+ if (uReadThis == 0)
+ return UNZ_EOF;
+ if (fseek (pfile_in_zip_read_info->file,
+ pfile_in_zip_read_info->pos_in_zipfile +
+ pfile_in_zip_read_info->byte_before_the_zipfile, SEEK_SET) != 0)
+ return UNZ_ERRNO;
+ if (fread (pfile_in_zip_read_info->read_buffer, uReadThis, 1,
+ pfile_in_zip_read_info->file) != 1)
+ return UNZ_ERRNO;
+ pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+ pfile_in_zip_read_info->rest_read_compressed -= uReadThis;
+
+ pfile_in_zip_read_info->stream.next_in =
+ (Bytef *) pfile_in_zip_read_info->read_buffer;
+ pfile_in_zip_read_info->stream.avail_in = (uInt) uReadThis;
+ }
+ break;
+ }
+ switch (pfile_in_zip_read_info->compression_method)
+ {
+ case UNZ_STORED:
+ {
+ uInt uDoCopy, i;
+ if (pfile_in_zip_read_info->stream.avail_out <
+ pfile_in_zip_read_info->stream.avail_in)
+ uDoCopy = pfile_in_zip_read_info->stream.avail_out;
+ else
+ uDoCopy = pfile_in_zip_read_info->stream.avail_in;
+
+ for (i = 0; i < uDoCopy; i++)
+ *(pfile_in_zip_read_info->stream.next_out + i) =
+ *(pfile_in_zip_read_info->stream.next_in + i);
+
+ pfile_in_zip_read_info->crc32 = crc32 (pfile_in_zip_read_info->crc32,
+ pfile_in_zip_read_info->stream.next_out,
+ uDoCopy);
+ pfile_in_zip_read_info->rest_read_uncompressed -= uDoCopy;
+ pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
+ pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
+ pfile_in_zip_read_info->stream.next_out += uDoCopy;
+ pfile_in_zip_read_info->stream.next_in += uDoCopy;
+ pfile_in_zip_read_info->stream.total_out += uDoCopy;
+ iRead += uDoCopy;
+ break;
+ }
+ case UNZ_SHRUNK:
+ iRead = pfile_in_zip_read_info->rest_read_uncompressed;
+ unShrink ();
+ break;
+ case UNZ_REDUCED1:
+ case UNZ_REDUCED2:
+ case UNZ_REDUCED3:
+ case UNZ_REDUCED4:
+ iRead = pfile_in_zip_read_info->rest_read_uncompressed;
+ unReduce ();
+ break;
+ case UNZ_IMPLODED:
+ iRead = pfile_in_zip_read_info->rest_read_uncompressed;
+ err = explode ();
+ break;
+ case UNZ_DEFLATED:
+ {
+ uLong uTotalOutBefore, uTotalOutAfter;
+ const Bytef *bufBefore;
+ uLong uOutThis;
+ int flush = Z_SYNC_FLUSH;
+
+ uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
+ bufBefore = pfile_in_zip_read_info->stream.next_out;
+
+ /*
+ * if ((pfile_in_zip_read_info->rest_read_uncompressed ==
+ * pfile_in_zip_read_info->stream.avail_out) &&
+ * (pfile_in_zip_read_info->rest_read_compressed == 0)) flush =
+ * Z_FINISH;
+ */
+ err = inflate (&pfile_in_zip_read_info->stream, flush);
+
+ uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+ uOutThis = uTotalOutAfter - uTotalOutBefore;
+
+ pfile_in_zip_read_info->crc32 =
+ crc32 (pfile_in_zip_read_info->crc32, bufBefore,
+ (uInt) (uOutThis));
+
+ pfile_in_zip_read_info->rest_read_uncompressed -=
+ uOutThis;
+
+ iRead += (uInt) (uTotalOutAfter - uTotalOutBefore);
+
+ if (err == Z_STREAM_END)
+ return (iRead == 0) ? UNZ_EOF : iRead;
+ if (err != Z_OK)
+ break;
+ break;
+ }
+ default:
+ return (UNZ_EOF);
+ }
+ }
+
+ if (err == Z_OK)
+ return iRead;
+ return err;
+}
+
+
+/*
+ * Give the current position in uncompressed data
+ */
+extern z_off_t ZEXPORT
+unztell (unzFile file)
+{
+ unz_s *s;
+ file_in_zip_read_info_s *pfile_in_zip_read_info;
+ if (file == NULL)
+ return UNZ_PARAMERROR;
+ s = (unz_s *) file;
+ pfile_in_zip_read_info = s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info == NULL)
+ return UNZ_PARAMERROR;
+
+ return (z_off_t) pfile_in_zip_read_info->stream.total_out;
+}
+
+
+/*
+ * return 1 if the end of file was reached, 0 elsewhere
+ */
+extern int ZEXPORT
+unzeof (unzFile file)
+{
+ unz_s *s;
+ file_in_zip_read_info_s *pfile_in_zip_read_info;
+ if (file == NULL)
+ return UNZ_PARAMERROR;
+ s = (unz_s *) file;
+ pfile_in_zip_read_info = s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info == NULL)
+ return UNZ_PARAMERROR;
+
+ if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+ return 1;
+ else
+ return 0;
+}
+
+
+
+/*
+ * Read extra field from the current file (opened by unzOpenCurrentFile) This
+ * is the local-header version of the extra field (sometimes, there is more
+ * info in the local-header version than in the central-header)
+ *
+ * if buf==NULL, it return the size of the local extra field that can be read
+ *
+ * if buf!=NULL, len is the size of the buffer, the extra header is copied in
+ * buf. the return value is the number of bytes copied in buf, or (if <0) the
+ * error code
+ */
+extern int ZEXPORT
+unzGetLocalExtrafield (
+ unzFile file,
+ voidp buf,
+ unsigned len)
+{
+ unz_s *s;
+ file_in_zip_read_info_s *pfile_in_zip_read_info;
+ uInt read_now;
+ uLong size_to_read;
+
+ if (file == NULL)
+ return UNZ_PARAMERROR;
+ s = (unz_s *) file;
+ pfile_in_zip_read_info = s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info == NULL)
+ return UNZ_PARAMERROR;
+
+ size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
+ pfile_in_zip_read_info->pos_local_extrafield);
+
+ if (buf == NULL)
+ return (int) size_to_read;
+
+ if (len > size_to_read)
+ read_now = (uInt) size_to_read;
+ else
+ read_now = (uInt) len;
+
+ if (read_now == 0)
+ return 0;
+
+ if (fseek (pfile_in_zip_read_info->file,
+ pfile_in_zip_read_info->offset_local_extrafield +
+ pfile_in_zip_read_info->pos_local_extrafield, SEEK_SET) != 0)
+ return UNZ_ERRNO;
+
+ if (fread (buf, (uInt) size_to_read, 1, pfile_in_zip_read_info->file) != 1)
+ return UNZ_ERRNO;
+
+ return (int) read_now;
+}
+
+/*
+ * Close the file in zip opened with unzipOpenCurrentFile Return UNZ_CRCERROR
+ * if all the file was read but the CRC is not good
+ */
+extern int ZEXPORT
+unzCloseCurrentFile (unzFile file)
+{
+ int err = UNZ_OK;
+
+ unz_s *s;
+ file_in_zip_read_info_s *pfile_in_zip_read_info;
+ if (file == NULL)
+ return UNZ_PARAMERROR;
+ s = (unz_s *) file;
+ pfile_in_zip_read_info = s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info == NULL)
+ return UNZ_PARAMERROR;
+
+
+ if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+ {
+ if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
+ err = UNZ_CRCERROR;
+ }
+ TRYFREE (pfile_in_zip_read_info->read_buffer);
+ pfile_in_zip_read_info->read_buffer = NULL;
+ if (pfile_in_zip_read_info->stream_initialised)
+ inflateEnd (&pfile_in_zip_read_info->stream);
+
+ pfile_in_zip_read_info->stream_initialised = 0;
+ TRYFREE (pfile_in_zip_read_info);
+
+ s->pfile_in_zip_read = NULL;
+
+ return err;
+}
+
+
+/*
+ * Get the global comment string of the ZipFile, in the szComment buffer.
+ * uSizeBuf is the size of the szComment buffer. return the number of byte
+ * copied or an error code <0
+ */
+extern int ZEXPORT
+unzGetGlobalComment (
+ unzFile file,
+ char *szComment,
+ uLong uSizeBuf)
+{
+ unz_s *s;
+ uLong uReadThis;
+ if (file == NULL)
+ return UNZ_PARAMERROR;
+ s = (unz_s *) file;
+
+ uReadThis = uSizeBuf;
+ if (uReadThis > s->gi.size_comment)
+ uReadThis = s->gi.size_comment;
+
+ if (fseek (s->file, s->central_pos + 22, SEEK_SET) != 0)
+ return UNZ_ERRNO;
+
+ if (uReadThis > 0)
+ {
+ *szComment = '\0';
+ if (fread (szComment, (uInt) uReadThis, 1, s->file) != 1)
+ return UNZ_ERRNO;
+ }
+ if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
+ *(szComment + s->gi.size_comment) = '\0';
+ return (int) uReadThis;
+}
diff --git a/source/unzip/unzip.h b/source/unzip/unzip.h
new file mode 100644
index 0000000..f629782
--- /dev/null
+++ b/source/unzip/unzip.h
@@ -0,0 +1,285 @@
+/* unzip.h -- IO for uncompress .zip files using zlib
+ Version 0.15 beta, Mar 19th, 1998,
+
+ Copyright (C) 1998 Gilles Vollant
+
+ This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
+ WinZip, InfoZip tools and compatible.
+ Encryption and multi volume ZipFile (span) are not supported.
+ Old compressions used by old PKZip 1.x are not supported
+
+ THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
+ CAN CHANGE IN FUTURE VERSION !!
+ I WAIT FEEDBACK at mail info@winimage.com
+ Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
+
+ Condition of use and distribution are the same than zlib :
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+
+*/
+/* for more info about .ZIP format, see
+ ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
+ PkWare has also a specification at :
+ ftp://ftp.pkware.com/probdesc.zip */
+
+#ifndef _unz_H
+#define _unz_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ZLIB_H
+#include "zlib.h"
+#endif
+
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+ from (void*) without cast */
+typedef struct TagunzFile__ { int unused; } unzFile__;
+typedef unzFile__ *unzFile;
+#else
+typedef voidp unzFile;
+#endif
+
+
+#define UNZ_OK (0)
+#define UNZ_END_OF_LIST_OF_FILE (-100)
+#define UNZ_ERRNO (Z_ERRNO)
+#define UNZ_EOF (0)
+#define UNZ_PARAMERROR (-102)
+#define UNZ_BADZIPFILE (-103)
+#define UNZ_INTERNALERROR (-104)
+#define UNZ_CRCERROR (-105)
+
+#define UNZ_STORED 0 /* compression methods */
+#define UNZ_SHRUNK 1
+#define UNZ_REDUCED1 2
+#define UNZ_REDUCED2 3
+#define UNZ_REDUCED3 4
+#define UNZ_REDUCED4 5
+#define UNZ_IMPLODED 6
+#define UNZ_TOKENIZED 7
+#define UNZ_DEFLATED 8
+
+/* tm_unz contain date/time info */
+typedef struct tm_unz_s
+{
+ uInt tm_sec; /* seconds after the minute - [0,59] */
+ uInt tm_min; /* minutes after the hour - [0,59] */
+ uInt tm_hour; /* hours since midnight - [0,23] */
+ uInt tm_mday; /* day of the month - [1,31] */
+ uInt tm_mon; /* months since January - [0,11] */
+ uInt tm_year; /* years - [1980..2044] */
+} tm_unz;
+
+/* unz_global_info structure contain global data about the ZIPfile
+ These data comes from the end of central dir */
+typedef struct unz_global_info_s
+{
+ uLong number_entry; /* total number of entries in
+ the central dir on this disk */
+ uLong size_comment; /* size of the global comment of the zipfile */
+} unz_global_info;
+
+
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info_s
+{
+ uLong version; /* version made by 2 bytes */
+ uLong version_needed; /* version needed to extract 2 bytes */
+ uLong flag; /* general purpose bit flag 2 bytes */
+ uLong compression_method; /* compression method 2 bytes */
+ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
+ uLong crc; /* crc-32 4 bytes */
+ uLong compressed_size; /* compressed size 4 bytes */
+ uLong uncompressed_size; /* uncompressed size 4 bytes */
+ uLong size_filename; /* filename length 2 bytes */
+ uLong size_file_extra; /* extra field length 2 bytes */
+ uLong size_file_comment; /* file comment length 2 bytes */
+
+ uLong disk_num_start; /* disk number start 2 bytes */
+ uLong internal_fa; /* internal file attributes 2 bytes */
+ uLong external_fa; /* external file attributes 4 bytes */
+
+ tm_unz tmu_date;
+} unz_file_info;
+
+extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
+ const char* fileName2,
+ int iCaseSensitivity));
+/*
+ Compare two filename (fileName1,fileName2).
+ If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+ If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+ or strcasecmp)
+ If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+ (like 1 on Unix, 2 on Windows)
+*/
+
+
+extern unzFile ZEXPORT unzOpen OF((const char *path));
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
+ "zlib/zlib111.zip".
+ If the zipfile cannot be opened (file don't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+*/
+
+extern int ZEXPORT unzClose OF((unzFile file));
+/*
+ Close a ZipFile opened with unzipOpen.
+ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+ these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+ return UNZ_OK if there is no problem. */
+
+extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
+ unz_global_info *pglobal_info));
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+
+
+extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
+ char *szComment,
+ uLong uSizeBuf));
+/*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+ return the number of byte copied or an error code <0
+*/
+
+
+/***************************************************************************/
+/* Unzip package allow you browse the directory of the zipfile */
+
+extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
+/*
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+
+extern int ZEXPORT unzGoToNextFile OF((unzFile file));
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
+extern int ZEXPORT unzLocateFile OF((unzFile file,
+ const char *szFileName,
+ int iCaseSensitivity));
+/*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+ return value :
+ UNZ_OK if the file is found. It becomes the current file.
+ UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+
+
+extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
+ unz_file_info *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+/*
+ Get Info about the current file
+ if pfile_info!=NULL, the *pfile_info structure will contain somes info about
+ the current file
+ if szFileName!=NULL, the filemane string will be copied in szFileName
+ (fileNameBufferSize is the size of the buffer)
+ if extraField!=NULL, the extra field information will be copied in extraField
+ (extraFieldBufferSize is the size of the buffer).
+ This is the Central-header version of the extra field
+ if szComment!=NULL, the comment string of the file will be copied in szComment
+ (commentBufferSize is the size of the buffer)
+*/
+
+/***************************************************************************/
+/* for reading the content of the current zipfile, you can open it, read data
+ from it, and close it (you can close it before reading all the file)
+ */
+
+extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
+/*
+ Open for reading data the current file in the zipfile.
+ If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
+/*
+ Close the file in zip opened with unzOpenCurrentFile
+ Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+
+
+extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
+ voidp buf,
+ unsigned len));
+/*
+ Read bytes from the current file (opened by unzOpenCurrentFile)
+ buf contain buffer where data must be copied
+ len the size of buf.
+
+ return the number of byte copied if somes bytes are copied
+ return 0 if the end of file was reached
+ return <0 with error code if there is an error
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+
+extern z_off_t ZEXPORT unztell OF((unzFile file));
+/*
+ Give the current position in uncompressed data
+*/
+
+extern int ZEXPORT unzeof OF((unzFile file));
+/*
+ return 1 if the end of file was reached, 0 elsewhere
+*/
+
+extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
+ voidp buf,
+ unsigned len));
+/*
+ Read extra field from the current file (opened by unzOpenCurrentFile)
+ This is the local-header version of the extra field (sometimes, there is
+ more info in the local-header version than in the central-header)
+
+ if buf==NULL, it return the size of the local extra field
+
+ if buf!=NULL, len is the size of the buffer, the extra header is copied in
+ buf.
+ the return value is the number of bytes copied in buf, or (if <0)
+ the error code
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _unz_H */
diff --git a/source/unzip/unzipP.h b/source/unzip/unzipP.h
new file mode 100644
index 0000000..c44e3cb
--- /dev/null
+++ b/source/unzip/unzipP.h
@@ -0,0 +1,125 @@
+#ifndef _UNZIPP_H_
+#define _UNZIPP_H_
+
+#include "ds2_malloc.h"
+#include "unzip.h"
+
+#ifndef local
+#define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+
+
+#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
+ !defined(CASESENSITIVITYDEFAULT_NO)
+#define CASESENSITIVITYDEFAULT_NO
+#endif
+
+
+#ifndef UNZ_BUFSIZE
+#define UNZ_BUFSIZE (16384)
+#endif
+
+#ifndef UNZ_MAXFILENAMEINZIP
+#define UNZ_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+#define ALLOC(size) (malloc(size))
+#endif
+#ifndef TRYFREE
+#define TRYFREE(p) {if (p) free(p);}
+#endif
+
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+
+
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+/* unz_file_info_interntal contain internal info about a file in zipfile */
+typedef struct unz_file_info_internal_s
+{
+ uLong offset_curfile; /* relative offset of local header 4
+ * bytes */
+} unz_file_info_internal;
+
+
+/*
+ * file_in_zip_read_info_s contain internal information about a file in
+ * zipfile, when reading and decompress it
+ */
+typedef struct
+{
+ char *read_buffer;/* internal buffer for compressed data */
+ z_stream stream; /* zLib stream structure for inflate */
+
+ uLong pos_in_zipfile; /* position in byte on the zipfile,
+ * for fseek */
+ uLong stream_initialised; /* flag set if stream structure is
+ * initialised */
+
+ uLong offset_local_extrafield; /* offset of the local extra
+ * field */
+ uInt size_local_extrafield; /* size of the local extra
+ * field */
+ uLong pos_local_extrafield; /* position in the local
+ * extra field in read */
+
+ uLong crc32; /* crc32 of all data uncompressed */
+ uLong crc32_wait; /* crc32 we must obtain after decompress all */
+ uLong rest_read_compressed; /* number of byte to be
+ * decompressed */
+ uLong rest_read_uncompressed; /* number of byte to be
+ * obtained after decomp */
+ FILE *file; /* io structore of the zipfile */
+ uLong compression_method; /* compression method (0==store) */
+ uLong byte_before_the_zipfile; /* byte before the zipfile,
+ * (>0 for sfx) */
+} file_in_zip_read_info_s;
+
+
+/*
+ * unz_s contain internal information about the zipfile
+ */
+typedef struct
+{
+ FILE *file; /* io structore of the zipfile */
+ unz_global_info gi; /* public global information */
+ uLong byte_before_the_zipfile; /* byte before the zipfile,
+ * (>0 for sfx) */
+ uLong num_file; /* number of the current file in the zipfile */
+ uLong pos_in_central_dir; /* pos of the current file in the
+ * central dir */
+ uLong current_file_ok; /* flag about the usability of the
+ * current file */
+ uLong central_pos;/* position of the beginning of the central
+ * dir */
+
+ uLong size_central_dir; /* size of the central directory */
+ uLong offset_central_dir; /* offset of start of central
+ * directory with respect to the
+ * starting disk number */
+
+ unz_file_info cur_file_info; /* public info about the current file
+ * in zip */
+ unz_file_info_internal cur_file_info_internal; /* private info about it */
+ file_in_zip_read_info_s *pfile_in_zip_read; /* structure about the
+ * current file if we are
+ * decompressing it */
+} unz_s;
+
+#endif