Annotation of embedaddon/php/ext/zip/lib/zip_dirent.c, revision 1.1.1.2

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_write2(unsigned short, FILE *);
                     49: static void _zip_write4(unsigned int, FILE *);
                     50: 
                     51: 
                     52: 
                     53: void
                     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
                     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 *
                     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 ((cd->entry=(struct zip_dirent *)malloc(sizeof(*(cd->entry))*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
                    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
                    158: _zip_dirent_finalize(struct zip_dirent *zde)
                    159: {
1.1.1.2 ! misho     160:     if (zde->filename_len > 0) {
        !           161:         free(zde->filename);
        !           162:     }
1.1       misho     163:     zde->filename = NULL;
1.1.1.2 ! misho     164:     if (zde->extrafield_len > 0) {
        !           165:         free(zde->extrafield);
        !           166:     }
1.1       misho     167:     zde->extrafield = NULL;
1.1.1.2 ! misho     168:     if (zde->comment_len > 0) {
        !           169:         free(zde->comment);
        !           170:     }
1.1       misho     171:     zde->comment = NULL;
                    172: }
                    173: 
                    174: 
                    175: 
                    176: void
                    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
                    220: _zip_dirent_read(struct zip_dirent *zde, FILE *fp,
1.1.1.2 ! misho     221:                 unsigned char **bufp, zip_uint32_t *leftp, int local,
1.1       misho     222:                 struct zip_error *error)
                    223: {
                    224:     unsigned char buf[CDENTRYSIZE];
                    225:     unsigned char *cur;
                    226:     unsigned short dostime, dosdate;
1.1.1.2 ! misho     227:     zip_uint32_t size;
1.1       misho     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
                    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
                    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
                    479: _zip_d2u_time(int dtime, int ddate)
                    480: {
1.1.1.2 ! misho     481:     struct tm tm;
1.1       misho     482: 
1.1.1.2 ! misho     483:     memset(&tm, 0, sizeof(tm));
        !           484:     
1.1       misho     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
                    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
                    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 *
                    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 *
                    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
                    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
                    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: 
1.1.1.2 ! misho     608: void
1.1       misho     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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>