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>