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