d46af3415f14f7cd425d2dee921a20b8d23bf1bb
[pspp] / src / libpspp / zip-reader.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2011, 2013, 2014 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include <inttypes.h>
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include <errno.h>
26 #include <xalloc.h>
27 #include <libpspp/assertion.h>
28 #include <libpspp/compiler.h>
29
30 #include <byteswap.h>
31
32 #include "str.h"
33
34 #include "zip-reader.h"
35 #include "zip-private.h"
36
37 #include "gettext.h"
38 #define _(msgid) gettext (msgid)
39 #define N_(msgid) (msgid)
40
41 struct zip_member
42 {
43   char *file_name;             /* File name. */
44   char *member_name;          /* Member name. */
45   FILE *fp;                   /* The stream from which the data is read */
46   uint32_t offset;            /* Starting offset in file. */
47   uint32_t comp_size;         /* Length of member file data, in bytes. */
48   uint32_t ucomp_size;        /* Uncompressed length of member file data, in bytes. */
49   const struct decompressor *decompressor;
50
51   size_t bytes_unread;       /* Number of bytes left in the member available for reading */
52   struct string *errmsgs;    /* A string to hold error messages.
53                                 This string is NOT owned by this object. */
54   void *aux;
55 };
56
57 struct decompressor
58 {
59   bool (*init) (struct zip_member *);
60   int  (*read) (struct zip_member *, void *, size_t);
61   void (*finish) (struct zip_member *);
62 };
63 static const struct decompressor stored_decompressor;
64 static const struct decompressor inflate_decompressor;
65
66 static bool find_eocd (FILE *fp, off_t *off);
67
68 static const struct decompressor *
69 get_decompressor (uint16_t c)
70 {
71   switch (c)
72     {
73     case 0:
74       return &stored_decompressor;
75
76     case 8:
77       return &inflate_decompressor;
78
79     default:
80       return NULL;
81     }
82 }
83
84 struct zip_reader
85 {
86   char *file_name;                  /* The name of the file from which the data is read */
87   uint16_t n_entries;              /* Number of directory entries. */
88   struct zip_entry *entries;       /* Directory entries. */
89   struct string *errs;             /* A string to hold error messages.  This
90                                       string is NOT owned by this object. */
91 };
92
93 struct zip_entry
94 {
95   uint32_t offset;            /* Starting offset in file. */
96   uint32_t comp_size;         /* Length of member file data, in bytes. */
97   uint32_t ucomp_size;        /* Uncompressed length of member file data, in bytes. */
98   char *name;                 /* Name of member file. */
99 };
100
101 void
102 zip_member_finish (struct zip_member *zm)
103 {
104   if (zm)
105     {
106       free (zm->file_name);
107       free (zm->member_name);
108       ds_clear (zm->errmsgs);
109       zm->decompressor->finish (zm);
110       fclose (zm->fp);
111       free (zm);
112     }
113 }
114
115 /* Destroy the zip reader */
116 void
117 zip_reader_destroy (struct zip_reader *zr)
118 {
119   int i;
120   if (zr == NULL)
121     return;
122
123   free (zr->file_name);
124
125   for (i = 0; i < zr->n_entries; ++i)
126     {
127       struct zip_entry *ze = &zr->entries[i];
128       free (ze->name);
129     }
130   free (zr->entries);
131   free (zr);
132 }
133
134
135 /* Skip N bytes in F */
136 static void
137 skip_bytes (FILE *f, size_t n)
138 {
139   fseeko (f, n, SEEK_CUR);
140 }
141
142 static bool get_bytes (FILE *f, void *x, size_t n) WARN_UNUSED_RESULT;
143
144
145 /* Read N bytes from F, storing the result in X */
146 static bool
147 get_bytes (FILE *f, void *x, size_t n)
148 {
149   return (n == fread (x, 1, n, f));
150 }
151
152 static bool get_u32 (FILE *f, uint32_t *v) WARN_UNUSED_RESULT;
153
154
155 /* Read a 32 bit value from F */
156 static bool
157 get_u32 (FILE *f, uint32_t *v)
158 {
159   uint32_t x;
160   if (!get_bytes (f, &x, sizeof x))
161     return false;
162 #ifdef WORDS_BIGENDIAN
163   *v = bswap_32 (x);
164 #else
165   *v = x;
166 #endif
167   return true;
168 }
169
170 static bool get_u16 (FILE *f, uint16_t *v) WARN_UNUSED_RESULT;
171
172
173 /* Read a 16 bit value from F */
174 static bool
175 get_u16 (FILE *f, uint16_t *v)
176 {
177   uint16_t x;
178   if (!get_bytes (f, &x, sizeof x))
179     return false;
180 #ifdef WORDS_BIGENDIAN
181   *v = bswap_16 (x);
182 #else
183   *v = x;
184 #endif
185   return true;
186 }
187
188
189 /* Read 32 bit integer and compare it with EXPECTED.
190    place an error string in ERR if necessary. */
191 static bool
192 check_magic (FILE *f, const char *file_name,
193              uint32_t expected, struct string *err)
194 {
195   uint32_t magic;
196
197   if (! get_u32 (f, &magic)) return false;
198
199   if ((expected != magic))
200     {
201       ds_put_format (err,
202                      _("%s: corrupt archive at 0x%llx: "
203                        "expected %#"PRIx32" but got %#"PRIx32),
204                      file_name,
205                      (long long int) ftello (f) - sizeof (uint32_t),
206                      expected, magic);
207
208       return false;
209     }
210   return true;
211 }
212
213
214 /* Reads upto BYTES bytes from ZM and puts them in BUF.
215    Returns the number of bytes read, or -1 on error */
216 int
217 zip_member_read (struct zip_member *zm, void *buf, size_t bytes)
218 {
219   int bytes_read = 0;
220
221   ds_clear (zm->errmsgs);
222
223   if ( bytes > zm->bytes_unread)
224     bytes = zm->bytes_unread;
225
226   bytes_read  = zm->decompressor->read (zm, buf, bytes);
227   if ( bytes_read < 0)
228     return bytes_read;
229
230   zm->bytes_unread -= bytes_read;
231
232   return bytes_read;
233 }
234
235 /* Read all of ZM into memory, storing the data in *DATAP and its size in *NP.
236    Returns NULL if successful, otherwise an error string that the caller
237    must eventually free(). */
238 char * WARN_UNUSED_RESULT
239 zip_member_read_all (struct zip_reader *zr, const char *member_name,
240                      void **datap, size_t *np)
241 {
242   struct zip_member *zm = zip_member_open (zr, member_name);
243   if (!zm)
244     {
245       *datap = NULL;
246       *np = 0;
247       return ds_steal_cstr (zr->errs);
248     }
249
250   *datap = xmalloc (zm->ucomp_size);
251   *np = zm->ucomp_size;
252
253   uint8_t *data = *datap;
254   while (zm->bytes_unread)
255     if (zip_member_read (zm, data + (zm->ucomp_size - zm->bytes_unread),
256                          zm->bytes_unread) == -1)
257       {
258         zip_member_finish (zm);
259         free (*datap);
260         *datap = NULL;
261         *np = 0;
262         return ds_steal_cstr (zr->errs);
263       }
264
265   zip_member_finish (zm);
266   return NULL;
267 }
268
269 /* Read a central directory header from FILE and initializes ZE with it.
270    Returns true if successful, false otherwise.  On error, appends error
271    messages to ERRS. */
272 static bool
273 zip_header_read_next (FILE *file, const char *file_name,
274                       struct zip_entry *ze, struct string *errs)
275 {
276   uint16_t v, nlen, extralen;
277   uint16_t gp, time, date;
278   uint32_t expected_crc;
279
280   uint16_t clen, diskstart, iattr;
281   uint32_t eattr;
282   uint16_t comp_type;
283
284   if ( ! check_magic (file, file_name, MAGIC_SOCD, errs))
285     return false;
286
287   if (! get_u16 (file, &v)) return false;
288   if (! get_u16 (file, &v)) return false;
289   if (! get_u16 (file, &gp)) return false;
290   if (! get_u16 (file, &comp_type)) return false;
291   if (! get_u16 (file, &time)) return false;
292   if (! get_u16 (file, &date)) return false;
293   if (! get_u32 (file, &expected_crc)) return false;
294   if (! get_u32 (file, &ze->comp_size)) return false;
295   if (! get_u32 (file, &ze->ucomp_size)) return false;
296   if (! get_u16 (file, &nlen)) return false;
297   if (! get_u16 (file, &extralen)) return false;
298   if (! get_u16 (file, &clen)) return false;
299   if (! get_u16 (file, &diskstart)) return false;
300   if (! get_u16 (file, &iattr)) return false;
301   if (! get_u32 (file, &eattr)) return false;
302   if (! get_u32 (file, &ze->offset)) return false;
303
304   ze->name = xzalloc (nlen + 1);
305   if (! get_bytes (file, ze->name, nlen)) return false;
306
307   skip_bytes (file, extralen);
308
309   return true;
310 }
311
312
313 /* Create a reader from the zip called FILE_NAME */
314 struct zip_reader *
315 zip_reader_create (const char *file_name, struct string *errs)
316 {
317   uint16_t disknum, n_members, total_members;
318   off_t offset = 0;
319   uint32_t central_dir_start, central_dir_length;
320
321   struct zip_reader *zr = xzalloc (sizeof *zr);
322   zr->errs = errs;
323   if ( zr->errs)
324     ds_init_empty (zr->errs);
325
326   FILE *file = fopen (file_name, "rb");
327   if (!file)
328     {
329       ds_put_format (zr->errs, _("%s: open failed (%s)"),
330                      file_name, strerror (errno));
331       free (zr);
332       return NULL;
333     }
334
335   if ( ! check_magic (file, file_name, MAGIC_LHDR, zr->errs))
336     {
337       fclose (file);
338       free (zr);
339       return NULL;
340     }
341
342   if ( ! find_eocd (file, &offset))
343     {
344       ds_put_format (zr->errs, _("%s: cannot find central directory"),
345                      file_name);
346       fclose (file);
347       free (zr);
348       return NULL;
349     }
350
351   if ( 0 != fseeko (file, offset, SEEK_SET))
352     {
353       ds_put_format (zr->errs, _("%s: seek failed (%s)"),
354                      file_name, strerror (errno));
355       fclose (file);
356       free (zr);
357       return NULL;
358     }
359
360
361   if ( ! check_magic (file, file_name, MAGIC_EOCD, zr->errs))
362     {
363       fclose (file);
364       free (zr);
365       return NULL;
366     }
367
368   if (! get_u16 (file, &disknum)
369       || ! get_u16 (file, &disknum)
370
371       || ! get_u16 (file, &n_members)
372       || ! get_u16 (file, &total_members)
373
374       || ! get_u32 (file, &central_dir_length)
375       || ! get_u32 (file, &central_dir_start))
376     {
377       fclose (file);
378       free (zr);
379       return NULL;
380     }
381
382   if ( 0 != fseeko (file, central_dir_start, SEEK_SET))
383     {
384       ds_put_format (zr->errs, _("%s: seek failed (%s)"),
385                      file_name, strerror (errno));
386       fclose (file);
387       free (zr);
388       return NULL;
389     }
390
391   zr->file_name = xstrdup (file_name);
392
393   zr->entries = xcalloc (n_members, sizeof *zr->entries);
394   for (int i = 0; i < n_members; i++)
395     {
396       if (!zip_header_read_next (file, file_name,
397                                  &zr->entries[zr->n_entries], errs))
398         {
399           fclose (file);
400           zip_reader_destroy (zr);
401           return NULL;
402         }
403       zr->n_entries++;
404     }
405
406   return zr;
407 }
408
409 static struct zip_entry *
410 zip_entry_find (struct zip_reader *zr, const char *member)
411 {
412   for (int i = 0; i < zr->n_entries; ++i)
413     {
414       struct zip_entry *ze = &zr->entries[i];
415       if (0 == strcmp (ze->name, member))
416         return ze;
417     }
418   return NULL;
419 }
420
421 const char *
422 zip_reader_get_member_name(const struct zip_reader *zr, size_t idx)
423 {
424   return idx < zr->n_entries ? zr->entries[idx].name : NULL;
425 }
426
427 /* Return the member called MEMBER from the reader ZR  */
428 struct zip_member *
429 zip_member_open (struct zip_reader *zr, const char *member)
430 {
431   struct zip_entry *ze = zip_entry_find (zr, member);
432   if ( ze == NULL)
433     {
434       ds_put_format (zr->errs, _("%s: unknown member \"%s\""),
435                      zr->file_name, member);
436       return NULL;
437     }
438
439   FILE *fp = fopen (zr->file_name, "rb");
440   if (!fp)
441     {
442       ds_put_format (zr->errs, _("%s: open failed (%s)"),
443                      zr->file_name, strerror (errno));
444       return NULL;
445     }
446
447   struct zip_member *zm = xmalloc (sizeof *zm);
448   zm->file_name = xstrdup (zr->file_name);
449   zm->member_name = xstrdup (member);
450   zm->fp = fp;
451   zm->offset = ze->offset;
452   zm->comp_size = ze->comp_size;
453   zm->ucomp_size = ze->ucomp_size;
454   zm->decompressor = NULL;
455   zm->bytes_unread = ze->ucomp_size;
456   zm->errmsgs = zr->errs;
457   zm->aux = NULL;
458
459   if ( 0 != fseeko (zm->fp, zm->offset, SEEK_SET))
460     {
461       ds_put_format (zr->errs, _("%s: seek failed (%s)"),
462                      ze->name, strerror (errno));
463       goto error;
464     }
465
466   if ( ! check_magic (zm->fp, zr->file_name, MAGIC_LHDR, zr->errs))
467     goto error;
468
469   uint16_t v, nlen, extra_len;
470   uint16_t gp, comp_type, time, date;
471   uint32_t ucomp_size, comp_size;
472   uint32_t crc;
473   if (! get_u16 (zm->fp, &v)) goto error;
474   if (! get_u16 (zm->fp, &gp)) goto error;
475   if (! get_u16 (zm->fp, &comp_type)) goto error;
476   zm->decompressor = get_decompressor (comp_type);
477   if (! zm->decompressor) goto error;
478   if (! get_u16 (zm->fp, &time)) goto error;
479   if (! get_u16 (zm->fp, &date)) goto error;
480   if (! get_u32 (zm->fp, &crc)) goto error;
481   if (! get_u32 (zm->fp, &comp_size)) goto error;
482
483   if (! get_u32 (zm->fp, &ucomp_size)) goto error;
484   if (! get_u16 (zm->fp, &nlen)) goto error;
485   if (! get_u16 (zm->fp, &extra_len)) goto error;
486
487   char *name = xzalloc (nlen + 1);
488   if (! get_bytes (zm->fp, name, nlen))
489     {
490       free (name);
491       goto error;
492     }
493   if (strcmp (name, ze->name) != 0)
494     {
495       ds_put_format (zm->errmsgs,
496                      _("%s: name mismatch betwen central directory (%s) "
497                        "and local file header (%s)"),
498                      zm->file_name, ze->name, name);
499       free (name);
500       goto error;
501     }
502   free (name);
503
504   skip_bytes (zm->fp, extra_len);
505
506   if (!zm->decompressor->init (zm) )
507     goto error;
508
509   return zm;
510
511 error:
512   fclose (zm->fp);
513   free (zm->file_name);
514   free (zm->member_name);
515   free (zm);
516   return NULL;
517 }
518
519 \f
520
521 static bool probe_magic (FILE *fp, uint32_t magic, off_t start, off_t stop, off_t *off);
522
523
524 /* Search for something that looks like the End Of Central Directory in FP.
525    If found, the offset of the record will be placed in OFF.
526    Returns true if found false otherwise.
527 */
528 static bool
529 find_eocd (FILE *fp, off_t *off)
530 {
531   off_t start, stop;
532   const uint32_t magic = MAGIC_EOCD;
533   bool found = false;
534
535   /* The magic cannot be more than 22 bytes from the end of the file,
536      because that is the minimum length of the EndOfCentralDirectory
537      record.
538    */
539   if ( 0 > fseeko (fp, -22, SEEK_END))
540     {
541       return false;
542     }
543   start = ftello (fp);
544   stop = start + sizeof (magic);
545   do
546     {
547       found = probe_magic (fp, magic, start, stop, off);
548       /* FIXME: For extra confidence lookup the directory start record here*/
549       if ( start == 0)
550         break;
551       stop = start + sizeof (magic);
552       start >>= 1;
553     }
554   while (!found );
555
556   return found;
557 }
558
559
560 /*
561   Search FP for MAGIC starting at START and reaching until STOP.
562   Returns true iff MAGIC is found.  False otherwise.
563   OFF receives the location of the magic.
564 */
565 static bool
566 probe_magic (FILE *fp, uint32_t magic, off_t start, off_t stop, off_t *off)
567 {
568   int i;
569   int state = 0;
570   unsigned char seq[4];
571   unsigned char byte;
572
573   if ( 0 > fseeko (fp, start, SEEK_SET))
574     {
575       return -1;
576     }
577
578   for (i = 0; i < 4 ; ++i)
579     {
580       seq[i] = (magic >> i * 8) & 0xFF;
581     }
582
583   do
584     {
585       if (1 != fread (&byte, 1, 1, fp))
586         break;
587
588       if ( byte == seq[state])
589         state++;
590       else
591         state = 0;
592
593       if ( state == 4)
594         {
595           *off = ftello (fp) - 4;
596           return true;
597         }
598       start++;
599       if ( start >= stop)
600         break;
601     }
602   while (!feof (fp));
603
604   return false;
605 }
606 \f
607 /* Null decompressor. */
608
609 static int
610 stored_read (struct zip_member *zm, void *buf, size_t n)
611 {
612   return fread (buf, 1, n, zm->fp);
613 }
614
615 static bool
616 stored_init (struct zip_member *zm UNUSED)
617 {
618   return true;
619 }
620
621 static void
622 stored_finish (struct zip_member *zm UNUSED)
623 {
624   /* Nothing required */
625 }
626
627 static const struct decompressor stored_decompressor =
628   {stored_init, stored_read, stored_finish};
629 \f
630 /* Inflate decompressor. */
631
632 #undef crc32
633 #include <zlib.h>
634
635 #define UCOMPSIZE 4096
636
637 struct inflator
638 {
639   z_stream zss;
640   int state;
641   unsigned char ucomp[UCOMPSIZE];
642   size_t bytes_uncomp;
643   size_t ucomp_bytes_read;
644
645   /* Two bitfields as defined by RFC1950 */
646   uint16_t cmf_flg ;
647 };
648
649 static void
650 inflate_finish (struct zip_member *zm)
651 {
652   struct inflator *inf = zm->aux;
653
654   inflateEnd (&inf->zss);
655
656   free (inf);
657 }
658
659 static bool
660 inflate_init (struct zip_member *zm)
661 {
662   int r;
663   struct inflator *inf = xzalloc (sizeof *inf);
664
665   uint16_t flg = 0 ;
666   uint16_t cmf = 0x8; /* Always 8 for inflate */
667
668   const uint16_t cinfo = 7;  /* log_2(Window size) - 8 */
669
670   cmf |= cinfo << 4;     /* Put cinfo into the high nibble */
671
672   /* make these into a 16 bit word */
673   inf->cmf_flg = (cmf << 8 ) | flg;
674
675   /* Set the check bits */
676   inf->cmf_flg += 31 - (inf->cmf_flg % 31);
677   assert (inf->cmf_flg % 31 == 0);
678
679   inf->zss.next_in = Z_NULL;
680   inf->zss.avail_in = 0;
681   inf->zss.zalloc = Z_NULL;
682   inf->zss.zfree  = Z_NULL;
683   inf->zss.opaque = Z_NULL;
684   r = inflateInit (&inf->zss);
685
686   if ( Z_OK != r)
687     {
688       ds_put_format (zm->errmsgs,
689                      _("%s: cannot initialize inflator (%s)"),
690                      zm->file_name, zError (r));
691       return false;
692     }
693
694   zm->aux = inf;
695
696   return true;
697 }
698
699 static int
700 inflate_read (struct zip_member *zm, void *buf, size_t n)
701 {
702   int r;
703   struct inflator *inf = zm->aux;
704
705   if (inf->zss.avail_in == 0)
706     {
707       int bytes_read;
708       int bytes_to_read;
709       int pad = 0;
710
711       if ( inf->state == 0)
712         {
713           inf->ucomp[1] = inf->cmf_flg ;
714           inf->ucomp[0] = inf->cmf_flg >> 8 ;
715
716           pad = 2;
717           inf->state++;
718         }
719
720       bytes_to_read = zm->comp_size - inf->ucomp_bytes_read;
721
722       if (bytes_to_read == 0)
723         return 0;
724
725       if (bytes_to_read > UCOMPSIZE)
726         bytes_to_read = UCOMPSIZE;
727
728       bytes_read = fread (inf->ucomp + pad, 1, bytes_to_read - pad, zm->fp);
729
730       inf->ucomp_bytes_read += bytes_read;
731
732       inf->zss.avail_in = bytes_read + pad;
733       inf->zss.next_in = inf->ucomp;
734     }
735   inf->zss.avail_out = n;
736   inf->zss.next_out = buf;
737
738   r = inflate (&inf->zss, Z_NO_FLUSH);
739   if ( Z_OK == r)
740     {
741       return n - inf->zss.avail_out;
742     }
743
744   ds_put_format (zm->errmsgs, _("%s: error inflating \"%s\" (%s)"),
745                  zm->file_name, zm->member_name, zError (r));
746
747   return -1;
748 }
749
750 static const struct decompressor inflate_decompressor =
751   {inflate_init, inflate_read, inflate_finish};
752