Annotation of embedaddon/php/ext/zip/zip_stream.c, revision 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>