1/*
2  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.
3
4  See the accompanying file LICENSE, version 2000-Apr-09 or later
5  (the contents of which are also included in unzip.h) for terms of use.
6  If, for some reason, all these files are missing, the Info-ZIP license
7  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
8*/
9/* funzip.c -- by Mark Adler */
10
11#define VERSION "3.94 of 20 January 2002"
12
13
14/* Copyright history:
15   - Starting with UnZip 5.41 of 16-April-2000, this source file
16     is covered by the Info-Zip LICENSE cited above.
17   - Prior versions of this source file, found in UnZip source packages
18     up to UnZip 5.40, were put in the public domain.
19     The original copyright note by Mark Adler was:
20         "You can do whatever you like with this source file,
21         though I would prefer that if you modify it and
22         redistribute it that you include comments to that effect
23         with your name and the date.  Thank you."
24
25   History:
26   vers     date          who           what
27   ----   ---------  --------------  ------------------------------------
28   1.0    13 Aug 92  M. Adler        really simple unzip filter.
29   1.1    13 Aug 92  M. Adler        cleaned up somewhat, give help if
30                                     stdin not redirected, warn if more
31                                     zip file entries after the first.
32   1.2    15 Aug 92  M. Adler        added check of lengths for stored
33                                     entries, added more help.
34   1.3    16 Aug 92  M. Adler        removed redundant #define's, added
35                                     decryption.
36   1.4    27 Aug 92  G. Roelofs      added exit(0).
37   1.5     1 Sep 92  K. U. Rommel    changed read/write modes for OS/2.
38   1.6     6 Sep 92  G. Roelofs      modified to use dummy crypt.c and
39                                     crypt.h instead of -DCRYPT.
40   1.7    23 Sep 92  G. Roelofs      changed to use DOS_OS2; included
41                                     crypt.c under MS-DOS.
42   1.8     9 Oct 92  M. Adler        improved inflation error msgs.
43   1.9    17 Oct 92  G. Roelofs      changed ULONG/UWORD/byte to ulg/ush/uch;
44                                     renamed inflate_entry() to inflate();
45                                     adapted to use new, in-place zdecode.
46   2.0    22 Oct 92  M. Adler        allow filename argument, prompt for
47                                     passwords and don't echo, still allow
48                                     command-line password entry, but as an
49                                     option.
50   2.1    23 Oct 92  J-l. Gailly     fixed crypt/store bug,
51                     G. Roelofs      removed crypt.c under MS-DOS, fixed
52                                     decryption check to compare single byte.
53   2.2    28 Oct 92  G. Roelofs      removed declaration of key.
54   2.3    14 Dec 92  M. Adler        replaced fseek (fails on stdin for SCO
55                                     Unix V.3.2.4).  added quietflg for
56                                     inflate.c.
57   3.0    11 May 93  M. Adler        added gzip support
58   3.1     9 Jul 93  K. U. Rommel    fixed OS/2 pipe bug (PIPE_ERROR)
59   3.2     4 Sep 93  G. Roelofs      moved crc_32_tab[] to tables.h; used FOPx
60                                     from unzip.h; nuked OUTB macro and outbuf;
61                                     replaced flush(); inlined FlushOutput();
62                                     renamed decrypt to encrypted
63   3.3    29 Sep 93  G. Roelofs      replaced ReadByte() with NEXTBYTE macro;
64                                     revised (restored?) flush(); added FUNZIP
65   3.4    21 Oct 93  G. Roelofs      renamed quietflg to qflag; changed outcnt,
66                     H. Gessau       second updcrc() arg and flush() arg to ulg;
67                                     added inflate_free(); added "g =" to null
68                                     getc(in) to avoid compiler warnings
69   3.5    31 Oct 93  H. Gessau       changed DOS_OS2 to DOS_NT_OS2
70   3.6     6 Dec 93  H. Gessau       added "near" to mask_bits[]
71   3.7     9 Dec 93  G. Roelofs      added extent typecasts to fwrite() checks
72   3.8    28 Jan 94  GRR/JlG         initialized g variable in main() for gcc
73   3.81   22 Feb 94  M. Hanning-Lee  corrected usage message
74   3.82   27 Feb 94  G. Roelofs      added some typecasts to avoid warnings
75   3.83   22 Jul 94  G. Roelofs      changed fprintf to macro for DLLs
76    -      2 Aug 94  -               public release with UnZip 5.11
77    -     28 Aug 94  -               public release with UnZip 5.12
78   3.84    1 Oct 94  K. U. Rommel    changes for Metaware High C
79   3.85   29 Oct 94  G. Roelofs      changed fprintf macro to Info
80   3.86    7 May 95  K. Davis        RISCOS patches;
81                     P. Kienitz      Amiga patches
82   3.87   12 Aug 95  G. Roelofs      inflate_free(), DESTROYGLOBALS fixes
83   3.88    4 Sep 95  C. Spieler      reordered macro to work around MSC 5.1 bug
84   3.89   22 Nov 95  PK/CS           ifdef'd out updcrc() for ASM_CRC
85   3.9    17 Dec 95  G. Roelofs      modified for USE_ZLIB (new fillinbuf())
86    -     30 Apr 96  -               public release with UnZip 5.2
87   3.91   17 Aug 96  G. Roelofs      main() -> return int (Peter Seebach)
88   3.92   13 Apr 97  G. Roelofs      minor cosmetic fixes to messages
89    -     22 Apr 97  -               public release with UnZip 5.3
90    -     31 May 97  -               public release with UnZip 5.31
91   3.93   20 Sep 97  G. Roelofs      minor cosmetic fixes to messages
92    -      3 Nov 97  -               public release with UnZip 5.32
93    -     28 Nov 98  -               public release with UnZip 5.4
94    -     16 Apr 00  -               public release with UnZip 5.41
95    -     14 Jan 01  -               public release with UnZip 5.42
96   3.94   20 Feb 01  C. Spieler      added support for Deflate64(tm)
97 */
98
99
100/*
101
102   All funzip does is take a zipfile from stdin and decompress the
103   first entry to stdout.  The entry has to be either deflated or
104   stored.  If the entry is encrypted, then the decryption password
105   must be supplied on the command line as the first argument.
106
107   funzip needs to be linked with inflate.o and crypt.o compiled from
108   the unzip source.  If decryption is desired, the full version of
109   crypt.c (and crypt.h) from zcrypt28.zip or later must be used.
110
111 */
112
113#ifndef FUNZIP
114#  define FUNZIP
115#endif
116#define UNZIP_INTERNAL
117#include "unzip.h"
118#include "crypt.h"
119#include "ttyio.h"
120
121#ifdef EBCDIC
122#  undef EBCDIC                 /* don't need ebcdic[] */
123#endif
124#include "tables.h"             /* crc_32_tab[] */
125
126#ifndef USE_ZLIB  /* zlib's function is called inflate(), too */
127#  define UZinflate inflate
128#endif
129
130/* PKZIP header definitions */
131#define ZIPMAG 0x4b50           /* two-byte zip lead-in */
132#define LOCREM 0x0403           /* remaining two bytes in zip signature */
133#define LOCSIG 0x04034b50L      /* full signature */
134#define LOCFLG 4                /* offset of bit flag */
135#define  CRPFLG 1               /*  bit for encrypted entry */
136#define  EXTFLG 8               /*  bit for extended local header */
137#define LOCHOW 6                /* offset of compression method */
138#define LOCTIM 8                /* file mod time (for decryption) */
139#define LOCCRC 12               /* offset of crc */
140#define LOCSIZ 16               /* offset of compressed size */
141#define LOCLEN 20               /* offset of uncompressed length */
142#define LOCFIL 24               /* offset of file name field length */
143#define LOCEXT 26               /* offset of extra field length */
144#define LOCHDR 28               /* size of local header, including LOCREM */
145#define EXTHDR 16               /* size of extended local header, inc sig */
146
147/* GZIP header definitions */
148#define GZPMAG 0x8b1f           /* two-byte gzip lead-in */
149#define GZPHOW 0                /* offset of method number */
150#define GZPFLG 1                /* offset of gzip flags */
151#define  GZPMUL 2               /* bit for multiple-part gzip file */
152#define  GZPISX 4               /* bit for extra field present */
153#define  GZPISF 8               /* bit for filename present */
154#define  GZPISC 16              /* bit for comment present */
155#define  GZPISE 32              /* bit for encryption */
156#define GZPTIM 2                /* offset of Unix file modification time */
157#define GZPEXF 6                /* offset of extra flags */
158#define GZPCOS 7                /* offset of operating system compressed on */
159#define GZPHDR 8                /* length of minimal gzip header */
160
161#ifdef THEOS
162/* Macros cause stack overflow in compiler */
163ush SH(uch* p) { return ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8)); }
164ulg LG(uch* p) { return ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16)); }
165#else /* !THEOS */
166/* Macros for getting two-byte and four-byte header values */
167#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
168#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
169#endif /* ?THEOS */
170
171/* Function prototypes */
172static void err OF((int, char *));
173#if (defined(USE_DEFLATE64) && defined(__16BIT__))
174static int partflush OF((uch *rawbuf, unsigned w));
175#endif
176int main OF((int, char **));
177
178/* Globals */
179FILE *out;                      /* output file (*in moved to G struct) */
180ulg outsiz;                     /* total bytes written to out */
181int encrypted;                  /* flag to turn on decryption */
182
183/* Masks for inflate.c */
184ZCONST ush near mask_bits[] = {
185    0x0000,
186    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
187    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
188};
189
190
191#ifdef USE_ZLIB
192
193int fillinbuf(__G)
194__GDEF
195/* Fill input buffer for pull-model inflate() in zlib.  Return the number of
196 * bytes in inbuf. */
197{
198/*   GRR: check return value from fread(): same as read()?  check errno? */
199  if ((G.incnt = fread((char *)G.inbuf, 1, INBUFSIZ, G.in)) <= 0)
200    return 0;
201  G.inptr = G.inbuf;
202
203#if CRYPT
204  if (encrypted) {
205    uch *p;
206    int n;
207
208    for (n = G.incnt, p = G.inptr;  n--;  p++)
209      zdecode(*p);
210  }
211#endif /* CRYPT */
212
213  return G.incnt;
214
215}
216
217#endif /* USE_ZLIB */
218
219
220#if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB))
221#ifdef USE_ZLIB
222ZCONST uLongf *get_crc_table()
223{
224  return (ZCONST uLongf *)crc_32_tab;
225}
226#else /* !USE_ZLIB */
227ZCONST ulg near *get_crc_table()
228{
229  return crc_32_tab;
230}
231#endif /* ?USE_ZLIB */
232#endif /* !USE_ZLIB || USE_OWN_CRCTAB */
233
234
235static void err(n, m)
236int n;
237char *m;
238/* Exit on error with a message and a code */
239{
240  Info(slide, 1, ((char *)slide, "funzip error: %s\n", m));
241  DESTROYGLOBALS();
242  EXIT(n);
243}
244
245
246#if (defined(USE_DEFLATE64) && defined(__16BIT__))
247
248static int partflush(rawbuf, w)
249uch *rawbuf;     /* start of buffer area to flush */
250extent w;       /* number of bytes to flush */
251{
252  G.crc32val = crc32(G.crc32val, rawbuf, (extent)w);
253  if (fwrite((char *)rawbuf,1,(extent)w,out) != (extent)w && !PIPE_ERROR)
254    err(9, "out of space on stdout");
255  outsiz += w;
256  return 0;
257}
258
259
260int flush(w)    /* used by inflate.c (FLUSH macro) */
261ulg w;          /* number of bytes to flush */
262{
263    uch *rawbuf;
264    int ret;
265
266    /* On 16-bit systems (MSDOS, OS/2 1.x), the standard C library functions
267     * cannot handle writes of 64k blocks at once.  For these systems, the
268     * blocks to flush are split into pieces of 32k or less.
269     */
270    rawbuf = slide;
271    while (w > 0x8000L) {
272        ret = partflush(rawbuf, 0x8000);
273        if (ret != PK_OK)
274            return ret;
275        w -= 0x8000L;
276        rawbuf += (unsigned)0x8000;
277    }
278    return partflush(rawbuf, (extent)w);
279} /* end function flush() */
280
281#else /* !(USE_DEFLATE64 && __16BIT__) */
282
283int flush(w)    /* used by inflate.c (FLUSH macro) */
284ulg w;          /* number of bytes to flush */
285{
286  G.crc32val = crc32(G.crc32val, slide, (extent)w);
287  if (fwrite((char *)slide,1,(extent)w,out) != (extent)w && !PIPE_ERROR)
288    err(9, "out of space on stdout");
289  outsiz += w;
290  return 0;
291}
292
293#endif /* ?(USE_DEFLATE64 && __16BIT__) */
294
295
296int main(argc, argv)
297int argc;
298char **argv;
299/* Given a zipfile on stdin, decompress the first entry to stdout. */
300{
301  ush n;
302  uch h[LOCHDR];                /* first local header (GZPHDR < LOCHDR) */
303  int g = 0;                    /* true if gzip format */
304  unsigned method = 0;          /* initialized here to shut up gcc warning */
305#if CRYPT
306  char *s = " [-password]";
307  char *p;                      /* password */
308#else /* !CRYPT */
309  char *s = "";
310#endif /* ?CRYPT */
311  CONSTRUCTGLOBALS();
312
313  /* skip executable name */
314  argc--;
315  argv++;
316
317#if CRYPT
318  /* get the command line password, if any */
319  p = (char *)NULL;
320  if (argc && **argv == '-')
321  {
322    argc--;
323    p = 1 + *argv++;
324  }
325#endif /* CRYPT */
326
327#ifdef MALLOC_WORK
328  /* The following expression is a cooked-down simplyfication of the
329     calculation for the work area size of UnZip (see unzip.c).  For
330     fUnZip, the work area does not need to match the granularity
331     of the complex unshrink structures, because it only supports
332     inflation.  But, like in UnZip, the zcalloc() wrapper function
333     is needed for the allocation, to support the 64kByte buffer on
334     16-bit systems.
335   */
336# define UZ_SLIDE_CHUNK (sizeof(shrint)+sizeof(uch)+sizeof(uch))
337# define UZ_NUMOF_CHUNKS (unsigned)( (WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK )
338  G.area.Slide = (uch *)zcalloc(UZ_NUMOF_CHUNKS, UZ_SLIDE_CHUNK);
339# undef UZ_SLIDE_CHUNK
340# undef UZ_NUMOF_CHUNKS
341#endif
342
343  /* if no file argument and stdin not redirected, give the user help */
344  if (argc == 0 && isatty(0))
345  {
346    Info(slide, 1, ((char *)slide, "fUnZip (filter UnZip), version %s\n",
347      VERSION));
348    Info(slide, 1, ((char *)slide, "usage: ... | funzip%s | ...\n", s));
349    Info(slide, 1, ((char *)slide, "       ... | funzip%s > outfile\n", s));
350    Info(slide, 1, ((char *)slide, "       funzip%s infile.zip > outfile\n",s));
351    Info(slide, 1, ((char *)slide, "       funzip%s infile.gz > outfile\n", s));
352    Info(slide, 1, ((char *)slide, "Extracts to stdout the gzip file or first\
353 zip entry of stdin or the given file.\n"));
354    DESTROYGLOBALS();
355    EXIT(3);
356  }
357
358  /* prepare to be a binary filter */
359  if (argc)
360  {
361    if ((G.in = fopen(*argv, FOPR)) == (FILE *)NULL)
362      err(2, "cannot find input file");
363  }
364  else
365  {
366#ifdef DOS_FLX_NLM_OS2_W32
367#if (defined(__HIGHC__) && !defined(FLEXOS))
368    setmode(stdin, _BINARY);
369#else
370    setmode(0, O_BINARY);  /* some buggy C libraries require BOTH setmode() */
371#endif                     /*  call AND the fdopen() in binary mode :-( */
372#endif /* DOS_FLX_NLM_OS2_W32 */
373
374#ifdef RISCOS
375    G.in = stdin;
376#else
377    if ((G.in = fdopen(0, FOPR)) == (FILE *)NULL)
378      err(2, "cannot find stdin");
379#endif
380  }
381
382#ifdef DOS_FLX_H68_NLM_OS2_W32
383#if (defined(__HIGHC__) && !defined(FLEXOS))
384  setmode(stdout, _BINARY);
385#else
386  setmode(1, O_BINARY);
387#endif
388#endif /* DOS_FLX_H68_NLM_OS2_W32 */
389
390#ifdef RISCOS
391  out = stdout;
392#else
393  if ((out = fdopen(1, FOPW)) == (FILE *)NULL)
394    err(2, "cannot write to stdout");
395#endif
396
397  /* read local header, check validity, and skip name and extra fields */
398  n = getc(G.in);  n |= getc(G.in) << 8;
399  if (n == ZIPMAG)
400  {
401    if (fread((char *)h, 1, LOCHDR, G.in) != LOCHDR || SH(h) != LOCREM)
402      err(3, "invalid zipfile");
403    switch (method = SH(h + LOCHOW)) {
404      case STORED:
405      case DEFLATED:
406#ifdef USE_DEFLATE64
407      case ENHDEFLATED:
408#endif
409        break;
410      default:
411        err(3, "first entry not deflated or stored--cannot unpack");
412        break;
413    }
414    for (n = SH(h + LOCFIL); n--; ) g = getc(G.in);
415    for (n = SH(h + LOCEXT); n--; ) g = getc(G.in);
416    g = 0;
417    encrypted = h[LOCFLG] & CRPFLG;
418  }
419  else if (n == GZPMAG)
420  {
421    if (fread((char *)h, 1, GZPHDR, G.in) != GZPHDR)
422      err(3, "invalid gzip file");
423    if ((method = h[GZPHOW]) != DEFLATED && method != ENHDEFLATED)
424      err(3, "gzip file not deflated");
425    if (h[GZPFLG] & GZPMUL)
426      err(3, "cannot handle multi-part gzip files");
427    if (h[GZPFLG] & GZPISX)
428    {
429      n = getc(G.in);  n |= getc(G.in) << 8;
430      while (n--) g = getc(G.in);
431    }
432    if (h[GZPFLG] & GZPISF)
433      while ((g = getc(G.in)) != 0 && g != EOF) ;
434    if (h[GZPFLG] & GZPISC)
435      while ((g = getc(G.in)) != 0 && g != EOF) ;
436    g = 1;
437    encrypted = h[GZPFLG] & GZPISE;
438  }
439  else
440    err(3, "input not a zip or gzip file");
441
442  /* if entry encrypted, decrypt and validate encryption header */
443  if (encrypted)
444#if CRYPT
445    {
446      ush i, e;
447
448      if (p == (char *)NULL) {
449        if ((p = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL)
450          err(1, "out of memory");
451        else if ((p = getp("Enter password: ", p, IZ_PWLEN+1)) == (char *)NULL)
452          err(1, "no tty to prompt for password");
453      }
454#if (defined(USE_ZLIB) && !defined(USE_OWN_CRCTAB))
455      /* initialize crc_32_tab pointer for decryption */
456      CRC_32_TAB = (ZCONST ulg Far *)get_crc_table();
457#endif
458      init_keys(p);
459      for (i = 0; i < RAND_HEAD_LEN; i++)
460        e = NEXTBYTE;
461      if (e != (ush)(h[LOCFLG] & EXTFLG ? h[LOCTIM + 1] : h[LOCCRC + 3]))
462        err(3, "incorrect password for first entry");
463    }
464#else /* !CRYPT */
465    err(3, "cannot decrypt entry (need to recompile with full crypt.c)");
466#endif /* ?CRYPT */
467
468  /* prepare output buffer and crc */
469  G.outptr = slide;
470  G.outcnt = 0L;
471  outsiz = 0L;
472  G.crc32val = CRCVAL_INITIAL;
473
474  /* decompress */
475  if (g || h[LOCHOW])
476  {                             /* deflated entry */
477    int r;
478
479#ifdef USE_ZLIB
480    /* need to allocate and prepare input buffer */
481    if ((G.inbuf = (uch *)malloc(INBUFSIZ)) == (uch *)NULL)
482       err(1, "out of memory");
483#endif /* USE_ZLIB */
484    if ((r = UZinflate(__G__ (method == ENHDEFLATED))) != 0) {
485      if (r == 3)
486        err(1, "out of memory");
487      else
488        err(4, "invalid compressed data--format violated");
489    }
490    inflate_free(__G);
491  }
492  else
493  {                             /* stored entry */
494    register ulg n;
495
496    n = LG(h + LOCLEN);
497#if CRYPT
498    if (n != LG(h + LOCSIZ) - (encrypted ? RAND_HEAD_LEN : 0)) {
499#else
500    if (n != LG(h + LOCSIZ)) {
501#endif
502      Info(slide, 1, ((char *)slide, "len %ld, siz %ld\n", n, LG(h + LOCSIZ)));
503      err(4, "invalid compressed data--length mismatch");
504    }
505    while (n--) {
506      ush c = getc(G.in);
507#if CRYPT
508      if (encrypted)
509        zdecode(c);
510#endif
511      *G.outptr++ = (uch)c;
512#if (defined(USE_DEFLATE64) && defined(__16BIT__))
513      if (++G.outcnt == (WSIZE>>1))     /* do FlushOutput() */
514#else
515      if (++G.outcnt == WSIZE)    /* do FlushOutput() */
516#endif
517      {
518        G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt);
519        if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt
520            && !PIPE_ERROR)
521          err(9, "out of space on stdout");
522        outsiz += G.outcnt;
523        G.outptr = slide;
524        G.outcnt = 0L;
525      }
526    }
527  }
528  if (G.outcnt)   /* flush one last time; no need to reset G.outptr/outcnt */
529  {
530    G.crc32val = crc32(G.crc32val, slide, (extent)G.outcnt);
531    if (fwrite((char *)slide, 1,(extent)G.outcnt,out) != (extent)G.outcnt
532        && !PIPE_ERROR)
533      err(9, "out of space on stdout");
534    outsiz += G.outcnt;
535  }
536  fflush(out);
537
538  /* if extended header, get it */
539  if (g)
540  {
541    if (fread((char *)h + LOCCRC, 1, 8, G.in) != 8)
542      err(3, "gzip file ended prematurely");
543  }
544  else
545    if ((h[LOCFLG] & EXTFLG) &&
546        fread((char *)h + LOCCRC - 4, 1, EXTHDR, G.in) != EXTHDR)
547      err(3, "zipfile ended prematurely");
548
549  /* validate decompression */
550  if (LG(h + LOCCRC) != G.crc32val)
551    err(4, "invalid compressed data--crc error");
552  if (LG((g ? (h + LOCSIZ) : (h + LOCLEN))) != outsiz)
553    err(4, "invalid compressed data--length error");
554
555  /* check if there are more entries */
556  if (!g && fread((char *)h, 1, 4, G.in) == 4 && LG(h) == LOCSIG)
557    Info(slide, 1, ((char *)slide,
558      "funzip warning: zipfile has more than one entry--rest ignored\n"));
559
560  DESTROYGLOBALS();
561  RETURN (0);
562}
563