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

1.1       misho       1: /* $Id: zip_stream.c 307917 2011-02-01 14:44:29Z cataphract $ */
                      2: #ifdef HAVE_CONFIG_H
                      3: #   include "config.h"
                      4: #endif
                      5: #include "php.h"
                      6: #if HAVE_ZIP
                      7: #ifdef ZEND_ENGINE_2
                      8: 
                      9: #include "lib/zip.h"
                     10: 
                     11: #include "php_streams.h"
                     12: #include "ext/standard/file.h"
                     13: #include "ext/standard/php_string.h"
                     14: #include "fopen_wrappers.h"
                     15: #include "php_zip.h"
                     16: 
                     17: #include "ext/standard/url.h"
                     18: 
                     19: struct php_zip_stream_data_t {
                     20:        struct zip *za;
                     21:        struct zip_file *zf;
                     22:        size_t cursor;
                     23:        php_stream *stream;
                     24: };
                     25: 
                     26: #define STREAM_DATA_FROM_STREAM() \
                     27:        struct php_zip_stream_data_t *self = (struct php_zip_stream_data_t *) stream->abstract;
                     28: 
                     29: 
                     30: /* {{{ php_zip_ops_read */
                     31: static size_t php_zip_ops_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
                     32: {
                     33:        ssize_t n = 0;
                     34:        STREAM_DATA_FROM_STREAM();
                     35: 
                     36:        if (self->za && self->zf) {
                     37:                n = zip_fread(self->zf, buf, count);
                     38:                if (n < 0) {
                     39:                        int ze, se;
                     40:                        zip_file_error_get(self->zf, &ze, &se);
                     41:                        stream->eof = 1;
                     42:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zip stream error: %s", zip_file_strerror(self->zf));
                     43:                        return 0;
                     44:                }
                     45:                /* cast count to signed value to avoid possibly negative n
                     46:                 * being cast to unsigned value */
                     47:                if (n == 0 || n < (ssize_t)count) {
                     48:                        stream->eof = 1;
                     49:                } else {
                     50:                        self->cursor += n;
                     51:                }
                     52:        }
                     53:        return (n < 1 ? 0 : (size_t)n);
                     54: }
                     55: /* }}} */
                     56: 
                     57: /* {{{ php_zip_ops_write */
                     58: static size_t php_zip_ops_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
                     59: {
                     60:        if (!stream) {
                     61:                return 0;
                     62:        }
                     63: 
                     64:        return count;
                     65: }
                     66: /* }}} */
                     67: 
                     68: /* {{{ php_zip_ops_close */
                     69: static int php_zip_ops_close(php_stream *stream, int close_handle TSRMLS_DC)
                     70: {
                     71:        STREAM_DATA_FROM_STREAM();
                     72:        if (close_handle) {
                     73:                if (self->zf) {
                     74:                        zip_fclose(self->zf);
                     75:                        self->zf = NULL;
                     76:                }
                     77: 
                     78:                if (self->za) {
                     79:                        zip_close(self->za);
                     80:                        self->za = NULL;
                     81:                }
                     82:        }
                     83:        efree(self);
                     84:        stream->abstract = NULL;
                     85:        return EOF;
                     86: }
                     87: /* }}} */
                     88: 
                     89: /* {{{ php_zip_ops_flush */
                     90: static int php_zip_ops_flush(php_stream *stream TSRMLS_DC)
                     91: {
                     92:        if (!stream) {
                     93:                return 0;
                     94:        }
                     95: 
                     96:        return 0;
                     97: }
                     98: /* }}} */
                     99: 
                    100: static int php_zip_ops_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) /* {{{ */
                    101: {
                    102:        struct zip_stat sb;
                    103:        const char *path = stream->orig_path;
                    104:        int path_len = strlen(stream->orig_path);
                    105:        char *file_basename;
                    106:        size_t file_basename_len;
                    107:        char file_dirname[MAXPATHLEN];
                    108:        struct zip *za;
                    109:        char *fragment;
                    110:        int fragment_len;
                    111:        int err;
                    112: 
                    113:        fragment = strchr(path, '#');
                    114:        if (!fragment) {
                    115:                return -1;
                    116:        }
                    117: 
                    118: 
                    119:        if (strncasecmp("zip://", path, 6) == 0) {
                    120:                path += 6;
                    121:        }
                    122: 
                    123:        fragment_len = strlen(fragment);
                    124: 
                    125:        if (fragment_len < 1) {
                    126:                return -1;
                    127:        }
                    128:        path_len = strlen(path);
                    129:        if (path_len >= MAXPATHLEN) {
                    130:                return -1;
                    131:        }
                    132: 
                    133:        memcpy(file_dirname, path, path_len - fragment_len);
                    134:        file_dirname[path_len - fragment_len] = '\0';
                    135: 
                    136:        php_basename((char *)path, path_len - fragment_len, NULL, 0, &file_basename, &file_basename_len TSRMLS_CC);
                    137:        fragment++;
                    138: 
                    139:        if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname)) {
                    140:                efree(file_basename);
                    141:                return -1;
                    142:        }
                    143: 
                    144:        za = zip_open(file_dirname, ZIP_CREATE, &err);
                    145:        if (za) {
                    146:                memset(ssb, 0, sizeof(php_stream_statbuf));
                    147:                if (zip_stat(za, fragment, ZIP_FL_NOCASE, &sb) != 0) {
                    148:                        efree(file_basename);
                    149:                        return -1;
                    150:                }
                    151:                zip_close(za);
                    152: 
                    153:                if (path[path_len-1] != '/') {
                    154:                        ssb->sb.st_size = sb.size;
                    155:                        ssb->sb.st_mode |= S_IFREG; /* regular file */
                    156:                } else {
                    157:                        ssb->sb.st_size = 0;
                    158:                        ssb->sb.st_mode |= S_IFDIR; /* regular directory */
                    159:                }
                    160: 
                    161:                ssb->sb.st_mtime = sb.mtime;
                    162:                ssb->sb.st_atime = sb.mtime;
                    163:                ssb->sb.st_ctime = sb.mtime;
                    164:                ssb->sb.st_nlink = 1;
                    165:                ssb->sb.st_rdev = -1;
                    166: #ifndef PHP_WIN32
                    167:                ssb->sb.st_blksize = -1;
                    168:                ssb->sb.st_blocks = -1;
                    169: #endif
                    170:                ssb->sb.st_ino = -1;
                    171:        }
                    172:        efree(file_basename);
                    173:        return 0;
                    174: }
                    175: /* }}} */
                    176: 
                    177: php_stream_ops php_stream_zipio_ops = {
                    178:        php_zip_ops_write, php_zip_ops_read,
                    179:        php_zip_ops_close, php_zip_ops_flush,
                    180:        "zip",
                    181:        NULL, /* seek */
                    182:        NULL, /* cast */
                    183:        php_zip_ops_stat, /* stat */
                    184:        NULL  /* set_option */
                    185: };
                    186: 
                    187: /* {{{ php_stream_zip_open */
                    188: php_stream *php_stream_zip_open(char *filename, char *path, char *mode STREAMS_DC TSRMLS_DC)
                    189: {
                    190:        struct zip_file *zf = NULL;
                    191:        int err = 0;
                    192: 
                    193:        php_stream *stream = NULL;
                    194:        struct php_zip_stream_data_t *self;
                    195:        struct zip *stream_za;
                    196: 
                    197:        if (strncmp(mode,"r", strlen("r")) != 0) {
                    198:                return NULL;
                    199:        }
                    200: 
                    201:        if (filename) {
                    202:                if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
                    203:                        return NULL;
                    204:                }
                    205: 
                    206:                /* duplicate to make the stream za independent (esp. for MSHUTDOWN) */
                    207:                stream_za = zip_open(filename, ZIP_CREATE, &err);
                    208:                if (!stream_za) {
                    209:                        return NULL;
                    210:                }
                    211: 
                    212:                zf = zip_fopen(stream_za, path, 0);
                    213:                if (zf) {
                    214:                        self = emalloc(sizeof(*self));
                    215: 
                    216:                        self->za = stream_za;
                    217:                        self->zf = zf; 
                    218:                        self->stream = NULL;
                    219:                        self->cursor = 0;
                    220:                        stream = php_stream_alloc(&php_stream_zipio_ops, self, NULL, mode);
                    221:                        stream->orig_path = estrdup(path);
                    222:                } else {
                    223:                        zip_close(stream_za);
                    224:                }
                    225:        }
                    226: 
                    227:        if (!stream) {
                    228:                return NULL;
                    229:        } else {
                    230:                return stream;
                    231:        }
                    232: 
                    233: }
                    234: /* }}} */
                    235: 
                    236: /* {{{ php_stream_zip_opener */
                    237: php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper,
                    238:                                                                                        char *path,
                    239:                                                                                        char *mode,
                    240:                                                                                        int options,
                    241:                                                                                        char **opened_path,
                    242:                                                                                        php_stream_context *context STREAMS_DC TSRMLS_DC)
                    243: {
                    244:        int path_len;
                    245: 
                    246:        char *file_basename;
                    247:        size_t file_basename_len;
                    248:        char file_dirname[MAXPATHLEN];
                    249: 
                    250:        struct zip *za;
                    251:        struct zip_file *zf = NULL;
                    252:        char *fragment;
                    253:        int fragment_len;
                    254:        int err;
                    255: 
                    256:        php_stream *stream = NULL;
                    257:        struct php_zip_stream_data_t *self;
                    258: 
                    259:        fragment = strchr(path, '#');
                    260:        if (!fragment) {
                    261:                return NULL;
                    262:        }
                    263: 
                    264:        if (strncasecmp("zip://", path, 6) == 0) {
                    265:                path += 6;
                    266:        }
                    267: 
                    268:        fragment_len = strlen(fragment);
                    269: 
                    270:        if (fragment_len < 1) {
                    271:                return NULL;
                    272:        }
                    273:        path_len = strlen(path);
                    274:        if (path_len >= MAXPATHLEN || mode[0] != 'r') {
                    275:                return NULL;
                    276:        }
                    277: 
                    278:        memcpy(file_dirname, path, path_len - fragment_len);
                    279:        file_dirname[path_len - fragment_len] = '\0';
                    280: 
                    281:        php_basename(path, path_len - fragment_len, NULL, 0, &file_basename, &file_basename_len TSRMLS_CC);
                    282:        fragment++;
                    283: 
                    284:        if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname)) {
                    285:                efree(file_basename);
                    286:                return NULL;
                    287:        }
                    288: 
                    289:        za = zip_open(file_dirname, ZIP_CREATE, &err);
                    290:        if (za) {
                    291:                zf = zip_fopen(za, fragment, 0);
                    292:                if (zf) {
                    293:                        self = emalloc(sizeof(*self));
                    294: 
                    295:                        self->za = za;
                    296:                        self->zf = zf; 
                    297:                        self->stream = NULL;
                    298:                        self->cursor = 0;
                    299:                        stream = php_stream_alloc(&php_stream_zipio_ops, self, NULL, mode);
                    300: 
                    301:                        if (opened_path) {
                    302:                                *opened_path = estrdup(path);
                    303:                        }
                    304:                } else {
                    305:                        zip_close(za);
                    306:                }
                    307:        }
                    308: 
                    309:        efree(file_basename);
                    310: 
                    311:        if (!stream) {
                    312:                return NULL;
                    313:        } else {
                    314:                return stream;
                    315:        }
                    316: }
                    317: /* }}} */
                    318: 
                    319: static php_stream_wrapper_ops zip_stream_wops = {
                    320:        php_stream_zip_opener,
                    321:        NULL,   /* close */
                    322:        NULL,   /* fstat */
                    323:        NULL,   /* stat */
                    324:        NULL,   /* opendir */
                    325:        "zip wrapper",
                    326:        NULL,   /* unlink */
                    327:        NULL,   /* rename */
                    328:        NULL,   /* mkdir */
                    329:        NULL    /* rmdir */
                    330: };
                    331: 
                    332: php_stream_wrapper php_stream_zip_wrapper = {
                    333:        &zip_stream_wops,
                    334:        NULL,
                    335:        0 /* is_url */
                    336: };
                    337: #endif /* ZEND_ENGINE_2 */
                    338: #endif /* HAVE_ZIP */

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