0f8c26332868f83699e460474e6c635ec5288d04
[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)
358       || ! get_u16 (zr->fr, &disknum)
359
360       || ! get_u16 (zr->fr, &zr->n_members)
361       || ! get_u16 (zr->fr, &total_members)
362
363       || ! get_u32 (zr->fr, &central_dir_length)
364       || ! get_u32 (zr->fr, &central_dir_start))
365     {
366       fclose (zr->fr);
367       free (zr);
368       return NULL;
369     }
370
371   if ( 0 != fseeko (zr->fr, central_dir_start, SEEK_SET))
372     {
373       const char *mm = strerror (errno);
374       ds_put_format (zr->errs, _("Failed to seek to central directory: %s"), mm);
375       fclose (zr->fr);
376       free (zr);
377       return NULL;
378     }
379
380   zr->members = xcalloc (zr->n_members, sizeof (*zr->members));
381   memset (zr->members, 0, zr->n_members * sizeof (*zr->members));
382
383   zr->filename = xstrdup (filename);
384
385   return zr;
386 }
387
388
389
390 /* Return the member called MEMBER from the reader ZR  */
391 struct zip_member *
392 zip_member_open (struct zip_reader *zr, const char *member)
393 {
394   uint16_t v, nlen, extra_len;
395   uint16_t gp, comp_type, time, date;
396   uint32_t ucomp_size, comp_size;
397
398   uint32_t crc;
399   bool new_member = false;
400   char *name = NULL;
401
402   int i;
403   struct zip_member *zm = NULL;
404
405   if ( zr == NULL)
406     return NULL;
407
408   for (i = 0; i < zr->n_members; ++i)
409   {
410     zm = zr->members[i];
411
412     if (zm == NULL)
413       {
414         zm = zr->members[i] = zip_header_read_next (zr);
415         new_member = true;
416       }
417     if (zm && 0 == strcmp (zm->name, member))
418       break;
419     else
420       zm = NULL;
421   }
422
423   if ( zm == NULL)
424     return NULL;
425
426   if ( 0 != fseeko (zm->fp, zm->offset, SEEK_SET))
427     {
428       const char *mm = strerror (errno);
429       ds_put_format (zm->errmsgs, _("Failed to seek to start of member `%s': %s"), zm->name, mm);
430       return NULL;
431     }
432
433   if ( ! check_magic (zm->fp, MAGIC_LHDR, zr->errs))
434     {
435       return NULL;
436     }
437
438   if (! get_u16 (zm->fp, &v)) return NULL;
439   if (! get_u16 (zm->fp, &gp)) return NULL;
440   if (! get_u16 (zm->fp, &comp_type)) return NULL;
441   zm->decompressor = get_decompressor (zm, comp_type);
442   if (! zm->decompressor) return NULL;
443   if (! get_u16 (zm->fp, &time)) return NULL;
444   if (! get_u16 (zm->fp, &date)) return NULL;
445   if (! get_u32 (zm->fp, &crc)) return NULL;
446   if (! get_u32 (zm->fp, &comp_size)) return NULL;
447
448   if (! get_u32 (zm->fp, &ucomp_size)) return NULL;
449   if (! get_u16 (zm->fp, &nlen)) return NULL;
450   if (! get_u16 (zm->fp, &extra_len)) return NULL;
451
452   name = xzalloc (nlen + 1);
453
454   if (! get_bytes (zm->fp, name, nlen)) return NULL;
455
456   skip_bytes (zm->fp, extra_len);
457
458   if (strcmp (name, zm->name) != 0)
459     {
460       ds_put_format (zm->errmsgs,
461                      _("Name mismatch in zip archive. Central directory says `%s'; local file header says `%s'"),
462                      zm->name, name);
463       free (name);
464       free (zm);
465       return NULL;
466     }
467
468   free (name);
469
470   zm->bytes_unread = zm->ucomp_size;
471
472   if ( !new_member)
473     zm->decompressor->finish (zm);
474
475   if (!zm->decompressor->init (zm) )
476     return NULL;
477
478   return zm;
479 }
480
481 void
482 zip_member_ref (struct zip_member *zm)
483 {
484   zm->ref_cnt++;
485 }
486
487
488
489
490 void
491 zip_member_unref (struct zip_member *zm)
492 {
493   if ( zm == NULL)
494     return;
495
496   if (--zm->ref_cnt == 0)
497     {
498       zm->decompressor->finish (zm);
499       if (zm->fp)
500         fclose (zm->fp);
501       free (zm->name);
502       free (zm);
503     }
504 }
505
506
507 \f
508
509 static bool probe_magic (FILE *fp, uint32_t magic, off_t start, off_t stop, off_t *off);
510
511
512 /* Search for something that looks like the End Of Central Directory in FP.
513    If found, the offset of the record will be placed in OFF.
514    Returns true if found false otherwise.
515 */
516 static bool
517 find_eocd (FILE *fp, off_t *off)
518 {
519   off_t start, stop;
520   const uint32_t magic = MAGIC_EOCD;
521   bool found = false;
522
523   /* The magic cannot be more than 22 bytes from the end of the file,
524      because that is the minimum length of the EndOfCentralDirectory
525      record.
526    */
527   if ( 0 > fseeko (fp, -22, SEEK_END))
528     {
529       return false;
530     }
531   start = ftello (fp);
532   stop = start + sizeof (magic);
533   do
534     {
535       found = probe_magic (fp, magic, start, stop, off);
536       /* FIXME: For extra confidence lookup the directory start record here*/
537       if ( start == 0)
538         break;
539       stop = start + sizeof (magic);
540       start >>= 1;
541     }
542   while (!found );
543
544   return found;
545 }
546
547
548 /*
549   Search FP for MAGIC starting at START and reaching until STOP.
550   Returns true iff MAGIC is found.  False otherwise.
551   OFF receives the location of the magic.
552 */
553 static bool
554 probe_magic (FILE *fp, uint32_t magic, off_t start, off_t stop, off_t *off)
555 {
556   int i;
557   int state = 0;
558   unsigned char seq[4];
559   unsigned char byte;
560
561   if ( 0 > fseeko (fp, start, SEEK_SET))
562     {
563       return -1;
564     }
565
566   for (i = 0; i < 4 ; ++i)
567     {
568       seq[i] = (magic >> i * 8) & 0xFF;
569     }
570
571   do
572     {
573       if (1 != fread (&byte, 1, 1, fp))
574         break;
575
576       if ( byte == seq[state])
577         state++;
578       else
579         state = 0;
580
581       if ( state == 4)
582         {
583           *off = ftello (fp) - 4;
584           return true;
585         }
586       start++;
587       if ( start >= stop)
588         break;
589     }
590   while (!feof (fp));
591
592   return false;
593 }
594 \f
595 /* Null decompressor. */
596
597 static int
598 stored_read (struct zip_member *zm, void *buf, size_t n)
599 {
600   return fread (buf, 1, n, zm->fp);
601 }
602
603 static bool
604 stored_init (struct zip_member *zm UNUSED)
605 {
606   return true;
607 }
608
609 static void
610 stored_finish (struct zip_member *zm UNUSED)
611 {
612   /* Nothing required */
613 }
614
615 static const struct decompressor stored_decompressor =
616   {stored_init, stored_read, stored_finish};
617 \f
618 /* Inflate decompressor. */
619
620 #undef crc32
621 #include <zlib.h>
622
623 #define UCOMPSIZE 4096
624
625 struct inflator
626 {
627   z_stream zss;
628   int state;
629   unsigned char ucomp[UCOMPSIZE];
630   size_t bytes_uncomp;
631   size_t ucomp_bytes_read;
632
633   /* Two bitfields as defined by RFC1950 */
634   uint16_t cmf_flg ;
635 };
636
637 static void
638 inflate_finish (struct zip_member *zm)
639 {
640   struct inflator *inf = zm->aux;
641
642   inflateEnd (&inf->zss);
643
644   free (inf);
645 }
646
647 static bool
648 inflate_init (struct zip_member *zm)
649 {
650   int r;
651   struct inflator *inf = xzalloc (sizeof *inf);
652
653   uint16_t flg = 0 ;
654   uint16_t cmf = 0x8; /* Always 8 for inflate */
655
656   const uint16_t cinfo = 7;  /* log_2(Window size) - 8 */
657
658   cmf |= cinfo << 4;     /* Put cinfo into the high nibble */
659
660   /* make these into a 16 bit word */
661   inf->cmf_flg = (cmf << 8 ) | flg;
662
663   /* Set the check bits */
664   inf->cmf_flg += 31 - (inf->cmf_flg % 31);
665   assert (inf->cmf_flg % 31 == 0);
666
667   inf->zss.next_in = Z_NULL;
668   inf->zss.avail_in = 0;
669   inf->zss.zalloc = Z_NULL;
670   inf->zss.zfree  = Z_NULL;
671   inf->zss.opaque = Z_NULL;
672   r = inflateInit (&inf->zss);
673
674   if ( Z_OK != r)
675     {
676       ds_put_format (zm->errmsgs, _("Cannot initialize inflator: %s"), zError (r));
677       return false;
678     }
679
680   zm->aux = inf;
681
682   return true;
683 }
684
685 static int
686 inflate_read (struct zip_member *zm, void *buf, size_t n)
687 {
688   int r;
689   struct inflator *inf = zm->aux;
690
691   if (inf->zss.avail_in == 0)
692     {
693       int bytes_read;
694       int bytes_to_read;
695       int pad = 0;
696
697       if ( inf->state == 0)
698         {
699           inf->ucomp[1] = inf->cmf_flg ;
700           inf->ucomp[0] = inf->cmf_flg >> 8 ;
701
702           pad = 2;
703           inf->state++;
704         }
705
706       bytes_to_read = zm->comp_size - inf->ucomp_bytes_read;
707
708       if (bytes_to_read == 0)
709         return 0;
710
711       if (bytes_to_read > UCOMPSIZE)
712         bytes_to_read = UCOMPSIZE;
713
714       bytes_read = fread (inf->ucomp + pad, 1, bytes_to_read - pad, zm->fp);
715
716       inf->ucomp_bytes_read += bytes_read;
717
718       inf->zss.avail_in = bytes_read + pad;
719       inf->zss.next_in = inf->ucomp;
720     }
721   inf->zss.avail_out = n;
722   inf->zss.next_out = buf;
723
724   r = inflate (&inf->zss, Z_NO_FLUSH);
725   if ( Z_OK == r)
726     {
727       return n - inf->zss.avail_out;
728     }
729
730   ds_put_format (zm->errmsgs, _("Error inflating: %s"), zError (r));
731
732   return -1;
733 }
734
735 static const struct decompressor inflate_decompressor =
736   {inflate_init, inflate_read, inflate_finish};
737