Annotation of embedaddon/php/ext/zip/lib/zip_dirent.c, revision 1.1.1.1
1.1 misho 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_u2d_time(time_t, unsigned short *, unsigned short *);
49: static void _zip_write2(unsigned short, FILE *);
50: static void _zip_write4(unsigned int, FILE *);
51:
52:
53:
54: void
55: _zip_cdir_free(struct zip_cdir *cd)
56: {
57: int i;
58:
59: if (!cd)
60: return;
61:
62: for (i=0; i<cd->nentry; i++)
63: _zip_dirent_finalize(cd->entry+i);
64: free(cd->comment);
65: free(cd->entry);
66: free(cd);
67: }
68:
69:
70:
71: int
72: _zip_cdir_grow(struct zip_cdir *cd, int nentry, struct zip_error *error)
73: {
74: struct zip_dirent *entry;
75:
76: if (nentry < cd->nentry) {
77: _zip_error_set(error, ZIP_ER_INTERNAL, 0);
78: return -1;
79: }
80:
81: if ((entry=((struct zip_dirent *)
82: realloc(cd->entry, sizeof(*(cd->entry))*nentry))) == NULL) {
83: _zip_error_set(error, ZIP_ER_MEMORY, 0);
84: return -1;
85: }
86:
87: cd->nentry = nentry;
88: cd->entry = entry;
89:
90: return 0;
91: }
92:
93:
94:
95: struct zip_cdir *
96: _zip_cdir_new(int nentry, struct zip_error *error)
97: {
98: struct zip_cdir *cd;
99:
100: if ((cd=(struct zip_cdir *)malloc(sizeof(*cd))) == NULL) {
101: _zip_error_set(error, ZIP_ER_MEMORY, 0);
102: return NULL;
103: }
104:
105: if ((cd->entry=(struct zip_dirent *)malloc(sizeof(*(cd->entry))*nentry))
106: == NULL) {
107: _zip_error_set(error, ZIP_ER_MEMORY, 0);
108: free(cd);
109: return NULL;
110: }
111:
112: /* entries must be initialized by caller */
113:
114: cd->nentry = nentry;
115: cd->size = cd->offset = 0;
116: cd->comment = NULL;
117: cd->comment_len = 0;
118:
119: return cd;
120: }
121:
122:
123:
124: int
125: _zip_cdir_write(struct zip_cdir *cd, FILE *fp, struct zip_error *error)
126: {
127: int i;
128:
129: cd->offset = ftello(fp);
130:
131: for (i=0; i<cd->nentry; i++) {
132: if (_zip_dirent_write(cd->entry+i, fp, 0, error) != 0)
133: return -1;
134: }
135:
136: cd->size = ftello(fp) - cd->offset;
137:
138: /* clearerr(fp); */
139: fwrite(EOCD_MAGIC, 1, 4, fp);
140: _zip_write4(0, fp);
141: _zip_write2((unsigned short)cd->nentry, fp);
142: _zip_write2((unsigned short)cd->nentry, fp);
143: _zip_write4(cd->size, fp);
144: _zip_write4(cd->offset, fp);
145: _zip_write2(cd->comment_len, fp);
146: fwrite(cd->comment, 1, cd->comment_len, fp);
147:
148: if (ferror(fp)) {
149: _zip_error_set(error, ZIP_ER_WRITE, errno);
150: return -1;
151: }
152:
153: return 0;
154: }
155:
156:
157:
158: void
159: _zip_dirent_finalize(struct zip_dirent *zde)
160: {
161: free(zde->filename);
162: zde->filename = NULL;
163: free(zde->extrafield);
164: zde->extrafield = NULL;
165: free(zde->comment);
166: zde->comment = NULL;
167: }
168:
169:
170:
171: void
172: _zip_dirent_init(struct zip_dirent *de)
173: {
174: de->version_madeby = 0;
175: de->version_needed = 20; /* 2.0 */
176: de->bitflags = 0;
177: de->comp_method = 0;
178: de->last_mod = 0;
179: de->crc = 0;
180: de->comp_size = 0;
181: de->uncomp_size = 0;
182: de->filename = NULL;
183: de->filename_len = 0;
184: de->extrafield = NULL;
185: de->extrafield_len = 0;
186: de->comment = NULL;
187: de->comment_len = 0;
188: de->disk_number = 0;
189: de->int_attrib = 0;
190: de->ext_attrib = 0;
191: de->offset = 0;
192: }
193:
194:
195:
196: /* _zip_dirent_read(zde, fp, bufp, left, localp, error):
197: Fills the zip directory entry zde.
198:
199: If bufp is non-NULL, data is taken from there and bufp is advanced
200: by the amount of data used; otherwise data is read from fp as needed.
201:
202: if leftp is non-NULL, no more bytes than specified by it are used,
203: and *leftp is reduced by the number of bytes used.
204:
205: If local != 0, it reads a local header instead of a central
206: directory entry.
207:
208: Returns 0 if successful. On error, error is filled in and -1 is
209: returned.
210:
211: XXX: leftp and file position undefined on error.
212: */
213:
214: int
215: _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
216: unsigned char **bufp, unsigned int *leftp, int local,
217: struct zip_error *error)
218: {
219: unsigned char buf[CDENTRYSIZE];
220: unsigned char *cur;
221: unsigned short dostime, dosdate;
222: unsigned int size;
223:
224: if (local)
225: size = LENTRYSIZE;
226: else
227: size = CDENTRYSIZE;
228:
229: if (leftp && (*leftp < size)) {
230: _zip_error_set(error, ZIP_ER_NOZIP, 0);
231: return -1;
232: }
233:
234: if (bufp) {
235: /* use data from buffer */
236: cur = *bufp;
237: }
238: else {
239: /* read entry from disk */
240: if ((fread(buf, 1, size, fp)<size)) {
241: _zip_error_set(error, ZIP_ER_READ, errno);
242: return -1;
243: }
244: cur = buf;
245: }
246:
247: if (memcmp(cur, (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) {
248: _zip_error_set(error, ZIP_ER_NOZIP, 0);
249: return -1;
250: }
251: cur += 4;
252:
253:
254: /* convert buffercontents to zip_dirent */
255:
256: if (!local)
257: zde->version_madeby = _zip_read2(&cur);
258: else
259: zde->version_madeby = 0;
260: zde->version_needed = _zip_read2(&cur);
261: zde->bitflags = _zip_read2(&cur);
262: zde->comp_method = _zip_read2(&cur);
263:
264: /* convert to time_t */
265: dostime = _zip_read2(&cur);
266: dosdate = _zip_read2(&cur);
267: zde->last_mod = _zip_d2u_time(dostime, dosdate);
268:
269: zde->crc = _zip_read4(&cur);
270: zde->comp_size = _zip_read4(&cur);
271: zde->uncomp_size = _zip_read4(&cur);
272:
273: zde->filename_len = _zip_read2(&cur);
274: zde->extrafield_len = _zip_read2(&cur);
275:
276: if (local) {
277: zde->comment_len = 0;
278: zde->disk_number = 0;
279: zde->int_attrib = 0;
280: zde->ext_attrib = 0;
281: zde->offset = 0;
282: } else {
283: zde->comment_len = _zip_read2(&cur);
284: zde->disk_number = _zip_read2(&cur);
285: zde->int_attrib = _zip_read2(&cur);
286: zde->ext_attrib = _zip_read4(&cur);
287: zde->offset = _zip_read4(&cur);
288: }
289:
290: zde->filename = NULL;
291: zde->extrafield = NULL;
292: zde->comment = NULL;
293:
294: size += zde->filename_len+zde->extrafield_len+zde->comment_len;
295:
296: if (leftp && (*leftp < size)) {
297: _zip_error_set(error, ZIP_ER_NOZIP, 0);
298: return -1;
299: }
300:
301: if (bufp) {
302: if (zde->filename_len) {
303: zde->filename = _zip_readstr(&cur, zde->filename_len, 1, error);
304: if (!zde->filename)
305: return -1;
306: }
307:
308: if (zde->extrafield_len) {
309: zde->extrafield = _zip_readstr(&cur, zde->extrafield_len, 0,
310: error);
311: if (!zde->extrafield)
312: return -1;
313: }
314:
315: if (zde->comment_len) {
316: zde->comment = _zip_readstr(&cur, zde->comment_len, 0, error);
317: if (!zde->comment)
318: return -1;
319: }
320: }
321: else {
322: if (zde->filename_len) {
323: zde->filename = _zip_readfpstr(fp, zde->filename_len, 1, error);
324: if (!zde->filename)
325: return -1;
326: }
327:
328: if (zde->extrafield_len) {
329: zde->extrafield = _zip_readfpstr(fp, zde->extrafield_len, 0,
330: error);
331: if (!zde->extrafield)
332: return -1;
333: }
334:
335: if (zde->comment_len) {
336: zde->comment = _zip_readfpstr(fp, zde->comment_len, 0, error);
337: if (!zde->comment)
338: return -1;
339: }
340: }
341:
342: if (bufp)
343: *bufp = cur;
344: if (leftp)
345: *leftp -= size;
346:
347: return 0;
348: }
349:
350:
351:
352: /* _zip_dirent_torrent_normalize(de);
353: Set values suitable for torrentzip.
354: */
355:
356: void
357: _zip_dirent_torrent_normalize(struct zip_dirent *de)
358: {
359: static struct tm torrenttime;
360: static time_t last_mod = 0;
361:
362: if (last_mod == 0) {
363: #ifdef HAVE_STRUCT_TM_TM_ZONE
364: time_t now;
365: struct tm *l;
366: #endif
367:
368: torrenttime.tm_sec = 0;
369: torrenttime.tm_min = 32;
370: torrenttime.tm_hour = 23;
371: torrenttime.tm_mday = 24;
372: torrenttime.tm_mon = 11;
373: torrenttime.tm_year = 96;
374: torrenttime.tm_wday = 0;
375: torrenttime.tm_yday = 0;
376: torrenttime.tm_isdst = 0;
377:
378: #ifdef HAVE_STRUCT_TM_TM_ZONE
379: time(&now);
380: l = localtime(&now);
381: torrenttime.tm_gmtoff = l->tm_gmtoff;
382: torrenttime.tm_zone = l->tm_zone;
383: #endif
384:
385: last_mod = mktime(&torrenttime);
386: }
387:
388: de->version_madeby = 0;
389: de->version_needed = 20; /* 2.0 */
390: de->bitflags = 2; /* maximum compression */
391: de->comp_method = ZIP_CM_DEFLATE;
392: de->last_mod = last_mod;
393:
394: de->disk_number = 0;
395: de->int_attrib = 0;
396: de->ext_attrib = 0;
397: de->offset = 0;
398:
399: free(de->extrafield);
400: de->extrafield = NULL;
401: de->extrafield_len = 0;
402: free(de->comment);
403: de->comment = NULL;
404: de->comment_len = 0;
405: }
406:
407:
408:
409: /* _zip_dirent_write(zde, fp, localp, error):
410: Writes zip directory entry zde to file fp.
411:
412: If localp != 0, it writes a local header instead of a central
413: directory entry.
414:
415: Returns 0 if successful. On error, error is filled in and -1 is
416: returned.
417: */
418:
419: int
420: _zip_dirent_write(struct zip_dirent *zde, FILE *fp, int localp,
421: struct zip_error *error)
422: {
423: unsigned short dostime, dosdate;
424:
425: fwrite(localp ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp);
426:
427: if (!localp)
428: _zip_write2(zde->version_madeby, fp);
429: _zip_write2(zde->version_needed, fp);
430: _zip_write2(zde->bitflags, fp);
431: _zip_write2(zde->comp_method, fp);
432:
433: _zip_u2d_time(zde->last_mod, &dostime, &dosdate);
434: _zip_write2(dostime, fp);
435: _zip_write2(dosdate, fp);
436:
437: _zip_write4(zde->crc, fp);
438: _zip_write4(zde->comp_size, fp);
439: _zip_write4(zde->uncomp_size, fp);
440:
441: _zip_write2(zde->filename_len, fp);
442: _zip_write2(zde->extrafield_len, fp);
443:
444: if (!localp) {
445: _zip_write2(zde->comment_len, fp);
446: _zip_write2(zde->disk_number, fp);
447: _zip_write2(zde->int_attrib, fp);
448: _zip_write4(zde->ext_attrib, fp);
449: _zip_write4(zde->offset, fp);
450: }
451:
452: if (zde->filename_len)
453: fwrite(zde->filename, 1, zde->filename_len, fp);
454:
455: if (zde->extrafield_len)
456: fwrite(zde->extrafield, 1, zde->extrafield_len, fp);
457:
458: if (!localp) {
459: if (zde->comment_len)
460: fwrite(zde->comment, 1, zde->comment_len, fp);
461: }
462:
463: if (ferror(fp)) {
464: _zip_error_set(error, ZIP_ER_WRITE, errno);
465: return -1;
466: }
467:
468: return 0;
469: }
470:
471:
472:
473: static time_t
474: _zip_d2u_time(int dtime, int ddate)
475: {
476: struct tm tm = {0};
477:
478: /* let mktime decide if DST is in effect */
479: tm.tm_isdst = -1;
480:
481: tm.tm_year = ((ddate>>9)&127) + 1980 - 1900;
482: tm.tm_mon = ((ddate>>5)&15) - 1;
483: tm.tm_mday = ddate&31;
484:
485: tm.tm_hour = (dtime>>11)&31;
486: tm.tm_min = (dtime>>5)&63;
487: tm.tm_sec = (dtime<<1)&62;
488:
489: return mktime(&tm);
490: }
491:
492:
493:
494: unsigned short
495: _zip_read2(unsigned char **a)
496: {
497: unsigned short ret;
498:
499: ret = (*a)[0]+((*a)[1]<<8);
500: *a += 2;
501:
502: return ret;
503: }
504:
505:
506:
507: unsigned int
508: _zip_read4(unsigned char **a)
509: {
510: unsigned int ret;
511:
512: ret = ((((((*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0];
513: *a += 4;
514:
515: return ret;
516: }
517:
518:
519:
520: static char *
521: _zip_readfpstr(FILE *fp, unsigned int len, int nulp, struct zip_error *error)
522: {
523: char *r, *o;
524:
525: r = (char *)malloc(nulp ? len+1 : len);
526: if (!r) {
527: _zip_error_set(error, ZIP_ER_MEMORY, 0);
528: return NULL;
529: }
530:
531: if (fread(r, 1, len, fp)<len) {
532: free(r);
533: _zip_error_set(error, ZIP_ER_READ, errno);
534: return NULL;
535: }
536:
537: if (nulp) {
538: /* replace any in-string NUL characters with spaces */
539: r[len] = 0;
540: for (o=r; o<r+len; o++)
541: if (*o == '\0')
542: *o = ' ';
543: }
544:
545: return r;
546: }
547:
548:
549:
550: static char *
551: _zip_readstr(unsigned char **buf, int len, int nulp, struct zip_error *error)
552: {
553: char *r, *o;
554:
555: r = (char *)malloc(nulp ? len+1 : len);
556: if (!r) {
557: _zip_error_set(error, ZIP_ER_MEMORY, 0);
558: return NULL;
559: }
560:
561: memcpy(r, *buf, len);
562: *buf += len;
563:
564: if (nulp) {
565: /* replace any in-string NUL characters with spaces */
566: r[len] = 0;
567: for (o=r; o<r+len; o++)
568: if (*o == '\0')
569: *o = ' ';
570: }
571:
572: return r;
573: }
574:
575:
576:
577: static void
578: _zip_write2(unsigned short i, FILE *fp)
579: {
580: putc(i&0xff, fp);
581: putc((i>>8)&0xff, fp);
582:
583: return;
584: }
585:
586:
587:
588: static void
589: _zip_write4(unsigned int i, FILE *fp)
590: {
591: putc(i&0xff, fp);
592: putc((i>>8)&0xff, fp);
593: putc((i>>16)&0xff, fp);
594: putc((i>>24)&0xff, fp);
595:
596: return;
597: }
598:
599:
600:
601: static void
602: _zip_u2d_time(time_t time, unsigned short *dtime, unsigned short *ddate)
603: {
604: struct tm *tm;
605:
606: tm = localtime(&time);
607: *ddate = ((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5)
608: + tm->tm_mday;
609: *dtime = ((tm->tm_hour)<<11) + ((tm->tm_min)<<5)
610: + ((tm->tm_sec)>>1);
611:
612: return;
613: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>