Annotation of embedaddon/php/ext/zip/lib/zip_source_deflate.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:   zip_source_deflate.c -- deflate (de)compressoin routines
                      3:   Copyright (C) 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 <stdlib.h>
                     37: #include <string.h>
                     38: 
                     39: #include "zipint.h"
                     40: 
                     41: struct deflate {
                     42:     int e[2];
                     43: 
                     44:     int eof;
                     45:     int mem_level;
                     46:     zip_uint64_t size;
                     47:     char buffer[BUFSIZE];
                     48:     z_stream zstr;
                     49: };
                     50: 
                     51: static zip_int64_t compress_read(struct zip_source *, struct deflate *,
                     52:                                 void *, zip_uint64_t);
                     53: static zip_int64_t decompress_read(struct zip_source *, struct deflate *,
                     54:                                   void *, zip_uint64_t);
                     55: static zip_int64_t deflate_compress(struct zip_source *, void *, void *,
                     56:                                    zip_uint64_t, enum zip_source_cmd);
                     57: static zip_int64_t deflate_decompress(struct zip_source *, void *, void *,
                     58:                                      zip_uint64_t, enum zip_source_cmd);
                     59: static void deflate_free(struct deflate *);
                     60: 
                     61: 
                     62: 
                     63: ZIP_EXTERN(struct zip_source *)
                     64: zip_source_deflate(struct zip *za, struct zip_source *src,
                     65:                   zip_uint16_t cm, int flags)
                     66: {
                     67:     struct deflate *ctx;
                     68:     struct zip_source *s2;
                     69: 
                     70:     if (src == NULL || cm != ZIP_CM_DEFLATE) {
                     71:        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
                     72:        return NULL;
                     73:     }
                     74: 
                     75:     if ((ctx=(struct deflate *)malloc(sizeof(*ctx))) == NULL) {
                     76:        _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
                     77:        return NULL;
                     78:     }
                     79: 
                     80:     ctx->e[0] = ctx->e[1] = 0;
                     81:     ctx->eof = 0;
                     82:     if (flags & ZIP_CODEC_ENCODE) {
                     83:        if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
                     84:            ctx->mem_level = TORRENT_MEM_LEVEL;
                     85:        else
                     86:            ctx->mem_level = MAX_MEM_LEVEL;
                     87:     }
                     88: 
                     89:     if ((s2=zip_source_layered(za, src,
                     90:                               ((flags & ZIP_CODEC_ENCODE)
                     91:                                ? deflate_compress : deflate_decompress),
                     92:                               ctx)) == NULL) {
                     93:        deflate_free(ctx);
                     94:        return NULL;
                     95:     }
                     96: 
                     97:     return s2;
                     98: }
                     99: 
                    100: 
                    101: 
                    102: static zip_int64_t
                    103: compress_read(struct zip_source *src, struct deflate *ctx,
                    104:              void *data, zip_uint64_t len)
                    105: {
                    106:     int end, ret;
                    107:     zip_int64_t n;
                    108: 
                    109:     if (ctx->e[0] != 0)
                    110:        return -1;
                    111:     
                    112:     if (len == 0)
                    113:        return 0;
                    114:        
                    115:     ctx->zstr.next_out = (Bytef *)data;
                    116:     ctx->zstr.avail_out = len;
                    117: 
                    118:     end = 0;
                    119:     while (!end) {
                    120:        ret = deflate(&ctx->zstr, ctx->eof ? Z_FINISH : 0);
                    121: 
                    122:        switch (ret) {
                    123:        case Z_OK:
                    124:        case Z_STREAM_END:
                    125:            /* all ok */
                    126: 
                    127:            if (ctx->zstr.avail_out == 0
                    128:                || (ctx->eof && ctx->zstr.avail_in == 0))
                    129:                end = 1;
                    130:            break;
                    131: 
                    132:        case Z_BUF_ERROR:
                    133:            if (ctx->zstr.avail_in == 0) {
                    134:                if (ctx->eof) {
                    135:                    end = 1;
                    136:                    break;
                    137:                }
                    138: 
                    139:                if ((n=zip_source_read(src, ctx->buffer,
                    140:                                       sizeof(ctx->buffer))) < 0) {
                    141:                    zip_source_error(src, ctx->e, ctx->e+1);
                    142:                    end = 1;
                    143:                    break;
                    144:                }
                    145:                else if (n == 0) {
                    146:                    ctx->eof = 1;
                    147:                    ctx->size = ctx->zstr.total_in;
                    148:                    /* XXX: check against stat of src? */
                    149:                }
                    150:                else {
                    151:                    ctx->zstr.next_in = (Bytef *)ctx->buffer;
                    152:                    ctx->zstr.avail_in = n;
                    153:                }
                    154:                continue;
                    155:            }
                    156:            /* fallthrough */
                    157:        case Z_NEED_DICT:
                    158:        case Z_DATA_ERROR:
                    159:        case Z_STREAM_ERROR:
                    160:        case Z_MEM_ERROR:
                    161:            ctx->e[0] = ZIP_ER_ZLIB;
                    162:            ctx->e[1] = ret;
                    163: 
                    164:            end = 1;
                    165:            break;
                    166:        }
                    167:     }
                    168: 
                    169:     if (ctx->zstr.avail_out < len)
                    170:        return len - ctx->zstr.avail_out;
                    171: 
                    172:     return (ctx->e[0] == 0) ? 0 : -1;
                    173: }
                    174: 
                    175: 
                    176: 
                    177: static zip_int64_t
                    178: decompress_read(struct zip_source *src, struct deflate *ctx,
                    179:                void *data, zip_uint64_t len)
                    180: {
                    181:     int end, ret;
                    182:     zip_int64_t n;
                    183: 
                    184:     if (ctx->e[0] != 0)
                    185:        return -1;
                    186:     
                    187:     if (len == 0)
                    188:        return 0;
                    189:        
                    190:     ctx->zstr.next_out = (Bytef *)data;
                    191:     ctx->zstr.avail_out = len;
                    192: 
                    193:     end = 0;
                    194:     while (!end && ctx->zstr.avail_out) {
                    195:        ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
                    196: 
                    197:        switch (ret) {
                    198:        case Z_OK:
                    199:            break;
                    200:            
                    201:        case Z_STREAM_END:
                    202:            ctx->eof = 1;
                    203:            end = 1;
                    204:            break;
                    205: 
                    206:        case Z_BUF_ERROR:
                    207:            if (ctx->zstr.avail_in == 0) {
                    208:                if (ctx->eof) {
                    209:                    end = 1;
                    210:                    break;
                    211:                }
                    212: 
                    213:                if ((n=zip_source_read(src, ctx->buffer,
                    214:                            sizeof(ctx->buffer))) < 0) {
                    215:                    zip_source_error(src, ctx->e, ctx->e+1);
                    216:                    end = 1;
                    217:                    break;
                    218:                }
                    219:                else if (n == 0)
                    220:                    ctx->eof = 1;
                    221:                else {
                    222:                    ctx->zstr.next_in = (Bytef *)ctx->buffer;
                    223:                    ctx->zstr.avail_in = n;
                    224:                }
                    225:                continue;
                    226:            }
                    227:            /* fallthrough */
                    228:        case Z_NEED_DICT:
                    229:        case Z_DATA_ERROR:
                    230:        case Z_STREAM_ERROR:
                    231:        case Z_MEM_ERROR:
                    232:            ctx->e[0] = ZIP_ER_ZLIB;
                    233:            ctx->e[1] = ret;
                    234:            end = 1;
                    235:            break;
                    236:        }
                    237:     }
                    238: 
                    239:     if (ctx->zstr.avail_out < len)
                    240:        return len - ctx->zstr.avail_out;
                    241: 
                    242:     return (ctx->e[0] == 0) ? 0 : -1;
                    243: }
                    244: 
                    245: 
                    246: 
                    247: static zip_int64_t
                    248: deflate_compress(struct zip_source *src, void *ud, void *data,
                    249:                 zip_uint64_t len, enum zip_source_cmd cmd)
                    250: {
                    251:     struct deflate *ctx;
                    252:     int ret;
                    253: 
                    254:     ctx = (struct deflate *)ud;
                    255: 
                    256:     switch (cmd) {
                    257:     case ZIP_SOURCE_OPEN:
                    258:        ctx->zstr.zalloc = Z_NULL;
                    259:        ctx->zstr.zfree = Z_NULL;
                    260:        ctx->zstr.opaque = NULL;
                    261:        ctx->zstr.avail_in = 0;
                    262:        ctx->zstr.next_in = NULL;
                    263:        ctx->zstr.avail_out = 0;
                    264:        ctx->zstr.next_out = NULL;
                    265: 
                    266:        /* negative value to tell zlib not to write a header */
                    267:        if ((ret=deflateInit2(&ctx->zstr, Z_BEST_COMPRESSION, Z_DEFLATED,
                    268:                              -MAX_WBITS, ctx->mem_level,
                    269:                              Z_DEFAULT_STRATEGY)) != Z_OK) {
                    270:            ctx->e[0] = ZIP_ER_ZLIB;
                    271:            ctx->e[1] = ret;
                    272:            return -1;
                    273:        }
                    274: 
                    275:        return 0;
                    276: 
                    277:     case ZIP_SOURCE_READ:
                    278:        return compress_read(src, ctx, data, len);
                    279: 
                    280:     case ZIP_SOURCE_CLOSE:
                    281:        deflateEnd(&ctx->zstr);
                    282:        return 0;
                    283: 
                    284:     case ZIP_SOURCE_STAT:
                    285:        {
                    286:            struct zip_stat *st;
                    287: 
                    288:            st = (struct zip_stat *)data;
                    289: 
                    290:            st->comp_method = ZIP_CM_DEFLATE;
                    291:            st->valid |= ZIP_STAT_COMP_METHOD;
                    292:            if (ctx->eof) {
                    293:                st->comp_size = ctx->size;
                    294:                st->valid |= ZIP_STAT_COMP_SIZE;
                    295:            }
                    296:            else
                    297:                st->valid &= ~ZIP_STAT_COMP_SIZE;
                    298:        }
                    299:        return 0;
                    300: 
                    301:     case ZIP_SOURCE_ERROR:
                    302:        memcpy(data, ctx->e, sizeof(int)*2);
                    303:        return sizeof(int)*2;
                    304: 
                    305:     case ZIP_SOURCE_FREE:
                    306:        deflate_free(ctx);
                    307:        return 0;
                    308: 
                    309:     default:
                    310:        ctx->e[0] = ZIP_ER_INVAL;
                    311:        ctx->e[1] = 0;
                    312:        return -1;
                    313:     }
                    314: }
                    315: 
                    316: 
                    317: 
                    318: static zip_int64_t
                    319: deflate_decompress(struct zip_source *src, void *ud, void *data,
                    320:                   zip_uint64_t len, enum zip_source_cmd cmd)
                    321: {
                    322:     struct deflate *ctx;
                    323:     zip_int64_t n;
                    324:     int ret;
                    325: 
                    326:     ctx = (struct deflate *)ud;
                    327: 
                    328:     switch (cmd) {
                    329:     case ZIP_SOURCE_OPEN:
                    330:        if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0)
                    331:            return ZIP_SOURCE_ERR_LOWER;
                    332: 
                    333:        ctx->zstr.zalloc = Z_NULL;
                    334:        ctx->zstr.zfree = Z_NULL;
                    335:        ctx->zstr.opaque = NULL;
                    336:        ctx->zstr.next_in = (Bytef *)ctx->buffer;
                    337:        ctx->zstr.avail_in = n;
                    338: 
                    339:        /* negative value to tell zlib that there is no header */
                    340:        if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) {
                    341:            ctx->e[0] = ZIP_ER_ZLIB;
                    342:            ctx->e[1] = ret;
                    343: 
                    344:            return -1;
                    345:        }
                    346:        return 0;
                    347: 
                    348:     case ZIP_SOURCE_READ:
                    349:        return decompress_read(src, ctx, data, len);
                    350: 
                    351:     case ZIP_SOURCE_CLOSE:
                    352:        inflateEnd(&ctx->zstr);
                    353:        return 0;
                    354: 
                    355:     case ZIP_SOURCE_STAT:
                    356:        {
                    357:            struct zip_stat *st;
                    358: 
                    359:            st = (struct zip_stat *)data;
                    360: 
                    361:            st->comp_method = ZIP_CM_STORE;
                    362:            if (st->comp_size > 0 && st->size > 0)
                    363:                st->comp_size = st->size;
                    364:        }
                    365:        return 0;
                    366: 
                    367:     case ZIP_SOURCE_ERROR:
                    368:        if (len < sizeof(int)*2)
                    369:            return -1;
                    370: 
                    371:        memcpy(data, ctx->e, sizeof(int)*2);
                    372:        return sizeof(int)*2;
                    373: 
                    374:     case ZIP_SOURCE_FREE:
                    375:        /* XXX: inflateEnd if close was not called */
                    376:        free(ctx);
                    377:        return 0;
                    378: 
                    379:     default:
                    380:        ctx->e[0] = ZIP_ER_INVAL;
                    381:        ctx->e[1] = 0;
                    382:        return -1;
                    383:     }
                    384:     
                    385: }
                    386: 
                    387: 
                    388: 
                    389: static void
                    390: deflate_free(struct deflate *ctx)
                    391: {
                    392:     /* XXX: deflateEnd if close was not called */
                    393:     free(ctx);
                    394: }

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