xref: /PHP-5.5/ext/zip/lib/zip_dirent.c (revision ef8fc4b5)
1 /*
2   zip_dirent.c -- read directory entry (local or central), clean dirent
3   Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
4 
5   This file is part of libzip, a library to manipulate ZIP archives.
6   The authors can be contacted at <libzip@nih.at>
7 
8   Redistribution and use in source and binary forms, with or without
9   modification, are permitted provided that the following conditions
10   are met:
11   1. Redistributions of source code must retain the above copyright
12      notice, this list of conditions and the following disclaimer.
13   2. Redistributions in binary form must reproduce the above copyright
14      notice, this list of conditions and the following disclaimer in
15      the documentation and/or other materials provided with the
16      distribution.
17   3. The names of the authors may not be used to endorse or promote
18      products derived from this software without specific prior
19      written permission.
20 
21   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <errno.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 
43 #include "zipint.h"
44 
45 static time_t _zip_d2u_time(int, int);
46 static char *_zip_readfpstr(FILE *, unsigned int, int, struct zip_error *);
47 static char *_zip_readstr(unsigned char **, int, int, struct zip_error *);
48 static void _zip_write2(unsigned short, FILE *);
49 static void _zip_write4(unsigned int, FILE *);
50 
51 
52 
53 void
_zip_cdir_free(struct zip_cdir * cd)54 _zip_cdir_free(struct zip_cdir *cd)
55 {
56     int i;
57 
58     if (!cd)
59 	return;
60 
61     for (i=0; i<cd->nentry; i++)
62 	_zip_dirent_finalize(cd->entry+i);
63     free(cd->comment);
64     free(cd->entry);
65     free(cd);
66 }
67 
68 
69 
70 int
_zip_cdir_grow(struct zip_cdir * cd,int nentry,struct zip_error * error)71 _zip_cdir_grow(struct zip_cdir *cd, int nentry, struct zip_error *error)
72 {
73     struct zip_dirent *entry;
74 
75     if (nentry < cd->nentry) {
76 	_zip_error_set(error, ZIP_ER_INTERNAL, 0);
77 	return -1;
78     }
79 
80     if ((entry=((struct zip_dirent *)
81 		realloc(cd->entry, sizeof(*(cd->entry))*nentry))) == NULL) {
82 	_zip_error_set(error, ZIP_ER_MEMORY, 0);
83 	return -1;
84     }
85 
86     cd->nentry = nentry;
87     cd->entry = entry;
88 
89     return 0;
90 }
91 
92 
93 
94 struct zip_cdir *
_zip_cdir_new(int nentry,struct zip_error * error)95 _zip_cdir_new(int nentry, struct zip_error *error)
96 {
97     struct zip_cdir *cd;
98 
99     if ((cd=(struct zip_cdir *)malloc(sizeof(*cd))) == NULL) {
100 	_zip_error_set(error, ZIP_ER_MEMORY, 0);
101 	return NULL;
102     }
103 
104     if ( nentry > ((size_t)-1)/sizeof(*(cd->entry)) || (cd->entry=(struct zip_dirent *)malloc(sizeof(*(cd->entry))*(size_t)nentry))
105 	== NULL) {
106 	_zip_error_set(error, ZIP_ER_MEMORY, 0);
107 	free(cd);
108 	return NULL;
109     }
110 
111     /* entries must be initialized by caller */
112 
113     cd->nentry = nentry;
114     cd->size = cd->offset = 0;
115     cd->comment = NULL;
116     cd->comment_len = 0;
117 
118     return cd;
119 }
120 
121 
122 
123 int
_zip_cdir_write(struct zip_cdir * cd,FILE * fp,struct zip_error * error)124 _zip_cdir_write(struct zip_cdir *cd, FILE *fp, struct zip_error *error)
125 {
126     int i;
127 
128     cd->offset = ftello(fp);
129 
130     for (i=0; i<cd->nentry; i++) {
131 	if (_zip_dirent_write(cd->entry+i, fp, 0, error) != 0)
132 	    return -1;
133     }
134 
135     cd->size = ftello(fp) - cd->offset;
136 
137     /* clearerr(fp); */
138     fwrite(EOCD_MAGIC, 1, 4, fp);
139     _zip_write4(0, fp);
140     _zip_write2((unsigned short)cd->nentry, fp);
141     _zip_write2((unsigned short)cd->nentry, fp);
142     _zip_write4(cd->size, fp);
143     _zip_write4(cd->offset, fp);
144     _zip_write2(cd->comment_len, fp);
145     fwrite(cd->comment, 1, cd->comment_len, fp);
146 
147     if (ferror(fp)) {
148 	_zip_error_set(error, ZIP_ER_WRITE, errno);
149 	return -1;
150     }
151 
152     return 0;
153 }
154 
155 
156 
157 void
_zip_dirent_finalize(struct zip_dirent * zde)158 _zip_dirent_finalize(struct zip_dirent *zde)
159 {
160     if (zde->filename_len > 0) {
161         free(zde->filename);
162     }
163     zde->filename = NULL;
164     if (zde->extrafield_len > 0) {
165         free(zde->extrafield);
166     }
167     zde->extrafield = NULL;
168     if (zde->comment_len > 0) {
169         free(zde->comment);
170     }
171     zde->comment = NULL;
172 }
173 
174 
175 
176 void
_zip_dirent_init(struct zip_dirent * de)177 _zip_dirent_init(struct zip_dirent *de)
178 {
179     de->version_madeby = 0;
180     de->version_needed = 20; /* 2.0 */
181     de->bitflags = 0;
182     de->comp_method = 0;
183     de->last_mod = 0;
184     de->crc = 0;
185     de->comp_size = 0;
186     de->uncomp_size = 0;
187     de->filename = NULL;
188     de->filename_len = 0;
189     de->extrafield = NULL;
190     de->extrafield_len = 0;
191     de->comment = NULL;
192     de->comment_len = 0;
193     de->disk_number = 0;
194     de->int_attrib = 0;
195     de->ext_attrib = 0;
196     de->offset = 0;
197 }
198 
199 
200 
201 /* _zip_dirent_read(zde, fp, bufp, left, localp, error):
202    Fills the zip directory entry zde.
203 
204    If bufp is non-NULL, data is taken from there and bufp is advanced
205    by the amount of data used; otherwise data is read from fp as needed.
206 
207    if leftp is non-NULL, no more bytes than specified by it are used,
208    and *leftp is reduced by the number of bytes used.
209 
210    If local != 0, it reads a local header instead of a central
211    directory entry.
212 
213    Returns 0 if successful. On error, error is filled in and -1 is
214    returned.
215 
216    XXX: leftp and file position undefined on error.
217 */
218 
219 int
_zip_dirent_read(struct zip_dirent * zde,FILE * fp,unsigned char ** bufp,zip_uint32_t * leftp,int local,struct zip_error * error)220 _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
221 		 unsigned char **bufp, zip_uint32_t *leftp, int local,
222 		 struct zip_error *error)
223 {
224     unsigned char buf[CDENTRYSIZE];
225     unsigned char *cur;
226     unsigned short dostime, dosdate;
227     zip_uint32_t size;
228 
229     if (local)
230 	size = LENTRYSIZE;
231     else
232 	size = CDENTRYSIZE;
233 
234     if (leftp && (*leftp < size)) {
235 	_zip_error_set(error, ZIP_ER_NOZIP, 0);
236 	return -1;
237     }
238 
239     if (bufp) {
240 	/* use data from buffer */
241 	cur = *bufp;
242     }
243     else {
244 	/* read entry from disk */
245 	if ((fread(buf, 1, size, fp)<size)) {
246 	    _zip_error_set(error, ZIP_ER_READ, errno);
247 	    return -1;
248 	}
249 	cur = buf;
250     }
251 
252     if (memcmp(cur, (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
253 	_zip_error_set(error, ZIP_ER_NOZIP, 0);
254 	return -1;
255     }
256     cur += 4;
257 
258 
259     /* convert buffercontents to zip_dirent */
260 
261     if (!local)
262 	zde->version_madeby = _zip_read2(&cur);
263     else
264 	zde->version_madeby = 0;
265     zde->version_needed = _zip_read2(&cur);
266     zde->bitflags = _zip_read2(&cur);
267     zde->comp_method = _zip_read2(&cur);
268 
269     /* convert to time_t */
270     dostime = _zip_read2(&cur);
271     dosdate = _zip_read2(&cur);
272     zde->last_mod = _zip_d2u_time(dostime, dosdate);
273 
274     zde->crc = _zip_read4(&cur);
275     zde->comp_size = _zip_read4(&cur);
276     zde->uncomp_size = _zip_read4(&cur);
277 
278     zde->filename_len = _zip_read2(&cur);
279     zde->extrafield_len = _zip_read2(&cur);
280 
281     if (local) {
282 	zde->comment_len = 0;
283 	zde->disk_number = 0;
284 	zde->int_attrib = 0;
285 	zde->ext_attrib = 0;
286 	zde->offset = 0;
287     } else {
288 	zde->comment_len = _zip_read2(&cur);
289 	zde->disk_number = _zip_read2(&cur);
290 	zde->int_attrib = _zip_read2(&cur);
291 	zde->ext_attrib = _zip_read4(&cur);
292 	zde->offset = _zip_read4(&cur);
293     }
294 
295     zde->filename = NULL;
296     zde->extrafield = NULL;
297     zde->comment = NULL;
298 
299     size += zde->filename_len+zde->extrafield_len+zde->comment_len;
300 
301     if (leftp && (*leftp < size)) {
302 	_zip_error_set(error, ZIP_ER_NOZIP, 0);
303 	return -1;
304     }
305 
306     if (bufp) {
307 	if (zde->filename_len) {
308 	    zde->filename = _zip_readstr(&cur, zde->filename_len, 1, error);
309 	    if (!zde->filename)
310 		    return -1;
311 	}
312 
313 	if (zde->extrafield_len) {
314 	    zde->extrafield = _zip_readstr(&cur, zde->extrafield_len, 0,
315 					   error);
316 	    if (!zde->extrafield)
317 		return -1;
318 	}
319 
320 	if (zde->comment_len) {
321 	    zde->comment = _zip_readstr(&cur, zde->comment_len, 0, error);
322 	    if (!zde->comment)
323 		return -1;
324 	}
325     }
326     else {
327 	if (zde->filename_len) {
328 	    zde->filename = _zip_readfpstr(fp, zde->filename_len, 1, error);
329 	    if (!zde->filename)
330 		    return -1;
331 	}
332 
333 	if (zde->extrafield_len) {
334 	    zde->extrafield = _zip_readfpstr(fp, zde->extrafield_len, 0,
335 					     error);
336 	    if (!zde->extrafield)
337 		return -1;
338 	}
339 
340 	if (zde->comment_len) {
341 	    zde->comment = _zip_readfpstr(fp, zde->comment_len, 0, error);
342 	    if (!zde->comment)
343 		return -1;
344 	}
345     }
346 
347     if (bufp)
348       *bufp = cur;
349     if (leftp)
350 	*leftp -= size;
351 
352     return 0;
353 }
354 
355 
356 
357 /* _zip_dirent_torrent_normalize(de);
358    Set values suitable for torrentzip.
359 */
360 
361 void
_zip_dirent_torrent_normalize(struct zip_dirent * de)362 _zip_dirent_torrent_normalize(struct zip_dirent *de)
363 {
364     static struct tm torrenttime;
365     static time_t last_mod = 0;
366 
367     if (last_mod == 0) {
368 #ifdef HAVE_STRUCT_TM_TM_ZONE
369 	time_t now;
370 	struct tm *l;
371 #endif
372 
373 	torrenttime.tm_sec = 0;
374 	torrenttime.tm_min = 32;
375 	torrenttime.tm_hour = 23;
376 	torrenttime.tm_mday = 24;
377 	torrenttime.tm_mon = 11;
378 	torrenttime.tm_year = 96;
379 	torrenttime.tm_wday = 0;
380 	torrenttime.tm_yday = 0;
381 	torrenttime.tm_isdst = 0;
382 
383 #ifdef HAVE_STRUCT_TM_TM_ZONE
384 	time(&now);
385 	l = localtime(&now);
386 	torrenttime.tm_gmtoff = l->tm_gmtoff;
387 	torrenttime.tm_zone = l->tm_zone;
388 #endif
389 
390 	last_mod = mktime(&torrenttime);
391     }
392 
393     de->version_madeby = 0;
394     de->version_needed = 20; /* 2.0 */
395     de->bitflags = 2; /* maximum compression */
396     de->comp_method = ZIP_CM_DEFLATE;
397     de->last_mod = last_mod;
398 
399     de->disk_number = 0;
400     de->int_attrib = 0;
401     de->ext_attrib = 0;
402     de->offset = 0;
403 
404     free(de->extrafield);
405     de->extrafield = NULL;
406     de->extrafield_len = 0;
407     free(de->comment);
408     de->comment = NULL;
409     de->comment_len = 0;
410 }
411 
412 
413 
414 /* _zip_dirent_write(zde, fp, localp, error):
415    Writes zip directory entry zde to file fp.
416 
417    If localp != 0, it writes a local header instead of a central
418    directory entry.
419 
420    Returns 0 if successful. On error, error is filled in and -1 is
421    returned.
422 */
423 
424 int
_zip_dirent_write(struct zip_dirent * zde,FILE * fp,int localp,struct zip_error * error)425 _zip_dirent_write(struct zip_dirent *zde, FILE *fp, int localp,
426 		  struct zip_error *error)
427 {
428     unsigned short dostime, dosdate;
429 
430     fwrite(localp ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp);
431 
432     if (!localp)
433 	_zip_write2(zde->version_madeby, fp);
434     _zip_write2(zde->version_needed, fp);
435     _zip_write2(zde->bitflags, fp);
436     _zip_write2(zde->comp_method, fp);
437 
438     _zip_u2d_time(zde->last_mod, &dostime, &dosdate);
439     _zip_write2(dostime, fp);
440     _zip_write2(dosdate, fp);
441 
442     _zip_write4(zde->crc, fp);
443     _zip_write4(zde->comp_size, fp);
444     _zip_write4(zde->uncomp_size, fp);
445 
446     _zip_write2(zde->filename_len, fp);
447     _zip_write2(zde->extrafield_len, fp);
448 
449     if (!localp) {
450 	_zip_write2(zde->comment_len, fp);
451 	_zip_write2(zde->disk_number, fp);
452 	_zip_write2(zde->int_attrib, fp);
453 	_zip_write4(zde->ext_attrib, fp);
454 	_zip_write4(zde->offset, fp);
455     }
456 
457     if (zde->filename_len)
458 	fwrite(zde->filename, 1, zde->filename_len, fp);
459 
460     if (zde->extrafield_len)
461 	fwrite(zde->extrafield, 1, zde->extrafield_len, fp);
462 
463     if (!localp) {
464 	if (zde->comment_len)
465 	    fwrite(zde->comment, 1, zde->comment_len, fp);
466     }
467 
468     if (ferror(fp)) {
469 	_zip_error_set(error, ZIP_ER_WRITE, errno);
470 	return -1;
471     }
472 
473     return 0;
474 }
475 
476 
477 
478 static time_t
_zip_d2u_time(int dtime,int ddate)479 _zip_d2u_time(int dtime, int ddate)
480 {
481     struct tm tm;
482 
483     memset(&tm, 0, sizeof(tm));
484 
485     /* let mktime decide if DST is in effect */
486     tm.tm_isdst = -1;
487 
488     tm.tm_year = ((ddate>>9)&127) + 1980 - 1900;
489     tm.tm_mon = ((ddate>>5)&15) - 1;
490     tm.tm_mday = ddate&31;
491 
492     tm.tm_hour = (dtime>>11)&31;
493     tm.tm_min = (dtime>>5)&63;
494     tm.tm_sec = (dtime<<1)&62;
495 
496     return mktime(&tm);
497 }
498 
499 
500 
501 unsigned short
_zip_read2(unsigned char ** a)502 _zip_read2(unsigned char **a)
503 {
504     unsigned short ret;
505 
506     ret = (*a)[0]+((*a)[1]<<8);
507     *a += 2;
508 
509     return ret;
510 }
511 
512 
513 
514 unsigned int
_zip_read4(unsigned char ** a)515 _zip_read4(unsigned char **a)
516 {
517     unsigned int ret;
518 
519     ret = ((((((*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0];
520     *a += 4;
521 
522     return ret;
523 }
524 
525 
526 
527 static char *
_zip_readfpstr(FILE * fp,unsigned int len,int nulp,struct zip_error * error)528 _zip_readfpstr(FILE *fp, unsigned int len, int nulp, struct zip_error *error)
529 {
530     char *r, *o;
531 
532     r = (char *)malloc(nulp ? len+1 : len);
533     if (!r) {
534 	_zip_error_set(error, ZIP_ER_MEMORY, 0);
535 	return NULL;
536     }
537 
538     if (fread(r, 1, len, fp)<len) {
539 	free(r);
540 	_zip_error_set(error, ZIP_ER_READ, errno);
541 	return NULL;
542     }
543 
544     if (nulp) {
545 	/* replace any in-string NUL characters with spaces */
546 	r[len] = 0;
547 	for (o=r; o<r+len; o++)
548 	    if (*o == '\0')
549 		*o = ' ';
550     }
551 
552     return r;
553 }
554 
555 
556 
557 static char *
_zip_readstr(unsigned char ** buf,int len,int nulp,struct zip_error * error)558 _zip_readstr(unsigned char **buf, int len, int nulp, struct zip_error *error)
559 {
560     char *r, *o;
561 
562     r = (char *)malloc(nulp ? len+1 : len);
563     if (!r) {
564 	_zip_error_set(error, ZIP_ER_MEMORY, 0);
565 	return NULL;
566     }
567 
568     memcpy(r, *buf, len);
569     *buf += len;
570 
571     if (nulp) {
572 	/* replace any in-string NUL characters with spaces */
573 	r[len] = 0;
574 	for (o=r; o<r+len; o++)
575 	    if (*o == '\0')
576 		*o = ' ';
577     }
578 
579     return r;
580 }
581 
582 
583 
584 static void
_zip_write2(unsigned short i,FILE * fp)585 _zip_write2(unsigned short i, FILE *fp)
586 {
587     putc(i&0xff, fp);
588     putc((i>>8)&0xff, fp);
589 
590     return;
591 }
592 
593 
594 
595 static void
_zip_write4(unsigned int i,FILE * fp)596 _zip_write4(unsigned int i, FILE *fp)
597 {
598     putc(i&0xff, fp);
599     putc((i>>8)&0xff, fp);
600     putc((i>>16)&0xff, fp);
601     putc((i>>24)&0xff, fp);
602 
603     return;
604 }
605 
606 
607 
608 void
_zip_u2d_time(time_t time,unsigned short * dtime,unsigned short * ddate)609 _zip_u2d_time(time_t time, unsigned short *dtime, unsigned short *ddate)
610 {
611     struct tm *tm;
612 
613     tm = localtime(&time);
614     *ddate = ((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5)
615 	+ tm->tm_mday;
616     *dtime = ((tm->tm_hour)<<11) + ((tm->tm_min)<<5)
617 	+ ((tm->tm_sec)>>1);
618 
619     return;
620 }
621