Annotation of embedaddon/php/ext/phar/func_interceptors.c, revision 1.1

1.1     ! misho       1: /*
        !             2:   +----------------------------------------------------------------------+
        !             3:   | phar php single-file executable PHP extension                        |
        !             4:   +----------------------------------------------------------------------+
        !             5:   | Copyright (c) 2005-2012 The PHP Group                                |
        !             6:   +----------------------------------------------------------------------+
        !             7:   | This source file is subject to version 3.01 of the PHP license,      |
        !             8:   | that is bundled with this package in the file LICENSE, and is        |
        !             9:   | available through the world-wide-web at the following url:           |
        !            10:   | http://www.php.net/license/3_01.txt.                                 |
        !            11:   | If you did not receive a copy of the PHP license and are unable to   |
        !            12:   | obtain it through the world-wide-web, please send a note to          |
        !            13:   | license@php.net so we can mail you a copy immediately.               |
        !            14:   +----------------------------------------------------------------------+
        !            15:   | Authors: Gregory Beaver <cellog@php.net>                             |
        !            16:   +----------------------------------------------------------------------+
        !            17: */
        !            18: 
        !            19: /* $Id: func_interceptors.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            20: 
        !            21: #include "phar_internal.h"
        !            22: 
        !            23: #define PHAR_FUNC(name) \
        !            24:        static PHP_NAMED_FUNCTION(name)
        !            25: 
        !            26: PHAR_FUNC(phar_opendir) /* {{{ */
        !            27: {
        !            28:        char *filename;
        !            29:        int filename_len;
        !            30:        zval *zcontext = NULL;
        !            31: 
        !            32:        if (!PHAR_G(intercepted)) {
        !            33:                goto skip_phar;
        !            34:        }
        !            35: 
        !            36:        if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
        !            37:                && !cached_phars.arBuckets) {
        !            38:                goto skip_phar;
        !            39:        }
        !            40: 
        !            41:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &filename, &filename_len, &zcontext) == FAILURE) {
        !            42:                return;
        !            43:        }
        !            44: 
        !            45:        if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
        !            46:                char *arch, *entry, *fname;
        !            47:                int arch_len, entry_len, fname_len;
        !            48:                fname = zend_get_executed_filename(TSRMLS_C);
        !            49: 
        !            50:                /* we are checking for existence of a file within the relative path.  Chances are good that this is
        !            51:                   retrieving something from within the phar archive */
        !            52: 
        !            53:                if (strncasecmp(fname, "phar://", 7)) {
        !            54:                        goto skip_phar;
        !            55:                }
        !            56:                fname_len = strlen(fname);
        !            57:                if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
        !            58:                        php_stream_context *context = NULL;
        !            59:                        php_stream *stream;
        !            60:                        char *name;
        !            61: 
        !            62:                        efree(entry);
        !            63:                        entry = estrndup(filename, filename_len);
        !            64:                        /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
        !            65:                        entry_len = filename_len;
        !            66:                        /* retrieving a file within the current directory, so use this if possible */
        !            67:                        entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC);
        !            68: 
        !            69:                        if (entry[0] == '/') {
        !            70:                                spprintf(&name, 4096, "phar://%s%s", arch, entry);
        !            71:                        } else {
        !            72:                                spprintf(&name, 4096, "phar://%s/%s", arch, entry);
        !            73:                        }
        !            74:                        efree(entry);
        !            75:                        efree(arch);
        !            76:                        if (zcontext) {
        !            77:                                context = php_stream_context_from_zval(zcontext, 0);
        !            78:                        }
        !            79:                        stream = php_stream_opendir(name, REPORT_ERRORS, context);
        !            80:                        efree(name);
        !            81:                        if (!stream) {
        !            82:                                RETURN_FALSE;
        !            83:                        }
        !            84:                        php_stream_to_zval(stream, return_value);
        !            85:                        return;
        !            86:                }
        !            87:        }
        !            88: skip_phar:
        !            89:        PHAR_G(orig_opendir)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
        !            90:        return;
        !            91: }
        !            92: /* }}} */
        !            93: 
        !            94: PHAR_FUNC(phar_file_get_contents) /* {{{ */
        !            95: {
        !            96:        char *filename;
        !            97:        int filename_len;
        !            98:        char *contents;
        !            99:        zend_bool use_include_path = 0;
        !           100:        php_stream *stream;
        !           101:        int len;
        !           102:        long offset = -1;
        !           103:        long maxlen = PHP_STREAM_COPY_ALL;
        !           104:        zval *zcontext = NULL;
        !           105: 
        !           106:        if (!PHAR_G(intercepted)) {
        !           107:                goto skip_phar;
        !           108:        }
        !           109: 
        !           110:        if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
        !           111:                && !cached_phars.arBuckets) {
        !           112:                goto skip_phar;
        !           113:        }
        !           114: 
        !           115:        /* Parse arguments */
        !           116:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s|br!ll", &filename, &filename_len, &use_include_path, &zcontext, &offset, &maxlen) == FAILURE) {
        !           117:                goto skip_phar;
        !           118:        }
        !           119: 
        !           120:        if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
        !           121:                char *arch, *entry, *fname;
        !           122:                int arch_len, entry_len, fname_len;
        !           123:                php_stream_context *context = NULL;
        !           124: 
        !           125:                fname = zend_get_executed_filename(TSRMLS_C);
        !           126: 
        !           127:                if (strncasecmp(fname, "phar://", 7)) {
        !           128:                        goto skip_phar;
        !           129:                }
        !           130:                fname_len = strlen(fname);
        !           131:                if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
        !           132:                        char *name;
        !           133:                        phar_archive_data *phar;
        !           134: 
        !           135:                        efree(entry);
        !           136:                        entry = filename;
        !           137:                        /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
        !           138:                        entry_len = filename_len;
        !           139: 
        !           140:                        if (ZEND_NUM_ARGS() == 5 && maxlen < 0) {
        !           141:                                efree(arch);
        !           142:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater than or equal to zero");
        !           143:                                RETURN_FALSE;
        !           144:                        }
        !           145: 
        !           146:                        /* retrieving a file defaults to within the current directory, so use this if possible */
        !           147:                        if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
        !           148:                                efree(arch);
        !           149:                                goto skip_phar;
        !           150:                        }
        !           151:                        if (use_include_path) {
        !           152:                                if ((entry = phar_find_in_include_path(entry, entry_len, NULL TSRMLS_CC))) {
        !           153:                                        name = entry;
        !           154:                                        goto phar_it;
        !           155:                                } else {
        !           156:                                        /* this file is not in the phar, use the original path */
        !           157:                                        efree(arch);
        !           158:                                        goto skip_phar;
        !           159:                                }
        !           160:                        } else {
        !           161:                                entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
        !           162:                                if (entry[0] == '/') {
        !           163:                                        if (!zend_hash_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
        !           164:                                                /* this file is not in the phar, use the original path */
        !           165: notfound:
        !           166:                                                efree(arch);
        !           167:                                                efree(entry);
        !           168:                                                goto skip_phar;
        !           169:                                        }
        !           170:                                } else {
        !           171:                                        if (!zend_hash_exists(&(phar->manifest), entry, entry_len)) {
        !           172:                                                goto notfound;
        !           173:                                        }
        !           174:                                }
        !           175:                                /* auto-convert to phar:// */
        !           176:                                if (entry[0] == '/') {
        !           177:                                        spprintf(&name, 4096, "phar://%s%s", arch, entry);
        !           178:                                } else {
        !           179:                                        spprintf(&name, 4096, "phar://%s/%s", arch, entry);
        !           180:                                }
        !           181:                                if (entry != filename) {
        !           182:                                        efree(entry);
        !           183:                                }
        !           184:                        }
        !           185: 
        !           186: phar_it:
        !           187:                        efree(arch);
        !           188:                        if (zcontext) {
        !           189:                                context = php_stream_context_from_zval(zcontext, 0);
        !           190:                        }
        !           191:                        stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context);
        !           192:                        efree(name);
        !           193: 
        !           194:                        if (!stream) {
        !           195:                                RETURN_FALSE;
        !           196:                        }
        !           197: 
        !           198:                        if (offset > 0 && php_stream_seek(stream, offset, SEEK_SET) < 0) {
        !           199:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to seek to position %ld in the stream", offset);
        !           200:                                php_stream_close(stream);
        !           201:                                RETURN_FALSE;
        !           202:                        }
        !           203: 
        !           204:                        /* uses mmap if possible */
        !           205:                        if ((len = php_stream_copy_to_mem(stream, &contents, maxlen, 0)) > 0) {
        !           206: #if PHP_MAJOR_VERSION < 6
        !           207:                                if (PG(magic_quotes_runtime)) {
        !           208:                                        int newlen;
        !           209:                                        contents = php_addslashes(contents, len, &newlen, 1 TSRMLS_CC); /* 1 = free source string */
        !           210:                                        len = newlen;
        !           211:                                }
        !           212: #endif
        !           213:                                RETVAL_STRINGL(contents, len, 0);
        !           214:                        } else if (len == 0) {
        !           215:                                RETVAL_EMPTY_STRING();
        !           216:                        } else {
        !           217:                                RETVAL_FALSE;
        !           218:                        }
        !           219: 
        !           220:                        php_stream_close(stream);
        !           221:                        return;
        !           222:                }
        !           223:        }
        !           224: skip_phar:
        !           225:        PHAR_G(orig_file_get_contents)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
        !           226:        return;
        !           227: }
        !           228: /* }}} */
        !           229: 
        !           230: PHAR_FUNC(phar_readfile) /* {{{ */
        !           231: {
        !           232:        char *filename;
        !           233:        int filename_len;
        !           234:        int size = 0;
        !           235:        zend_bool use_include_path = 0;
        !           236:        zval *zcontext = NULL;
        !           237:        php_stream *stream;
        !           238: 
        !           239:        if (!PHAR_G(intercepted)) {
        !           240:                goto skip_phar;
        !           241:        }
        !           242: 
        !           243:        if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
        !           244:                && !cached_phars.arBuckets) {
        !           245:                goto skip_phar;
        !           246:        }
        !           247:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s|br!", &filename, &filename_len, &use_include_path, &zcontext) == FAILURE) {
        !           248:                goto skip_phar;
        !           249:        }
        !           250:        if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
        !           251:                char *arch, *entry, *fname;
        !           252:                int arch_len, entry_len, fname_len;
        !           253:                php_stream_context *context = NULL;
        !           254:                char *name;
        !           255:                phar_archive_data *phar;
        !           256:                fname = zend_get_executed_filename(TSRMLS_C);
        !           257: 
        !           258:                if (strncasecmp(fname, "phar://", 7)) {
        !           259:                        goto skip_phar;
        !           260:                }
        !           261:                fname_len = strlen(fname);
        !           262:                if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
        !           263:                        goto skip_phar;
        !           264:                }
        !           265: 
        !           266:                efree(entry);
        !           267:                entry = filename;
        !           268:                /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
        !           269:                entry_len = filename_len;
        !           270:                /* retrieving a file defaults to within the current directory, so use this if possible */
        !           271:                if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
        !           272:                        efree(arch);
        !           273:                        goto skip_phar;
        !           274:                }
        !           275:                if (use_include_path) {
        !           276:                        if (!(entry = phar_find_in_include_path(entry, entry_len, NULL TSRMLS_CC))) {
        !           277:                                /* this file is not in the phar, use the original path */
        !           278:                                efree(arch);
        !           279:                                goto skip_phar;
        !           280:                        } else {
        !           281:                                name = entry;
        !           282:                        }
        !           283:                } else {
        !           284:                        entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
        !           285:                        if (entry[0] == '/') {
        !           286:                                if (!zend_hash_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
        !           287:                                        /* this file is not in the phar, use the original path */
        !           288: notfound:
        !           289:                                        efree(entry);
        !           290:                                        efree(arch);
        !           291:                                        goto skip_phar;
        !           292:                                }
        !           293:                        } else {
        !           294:                                if (!zend_hash_exists(&(phar->manifest), entry, entry_len)) {
        !           295:                                        goto notfound;
        !           296:                                }
        !           297:                        }
        !           298:                        /* auto-convert to phar:// */
        !           299:                        if (entry[0] == '/') {
        !           300:                                spprintf(&name, 4096, "phar://%s%s", arch, entry);
        !           301:                        } else {
        !           302:                                spprintf(&name, 4096, "phar://%s/%s", arch, entry);
        !           303:                        }
        !           304:                        efree(entry);
        !           305:                }
        !           306: 
        !           307:                efree(arch);
        !           308:                context = php_stream_context_from_zval(zcontext, 0);
        !           309:                stream = php_stream_open_wrapper_ex(name, "rb", 0 | REPORT_ERRORS, NULL, context);
        !           310:                efree(name);
        !           311:                if (stream == NULL) {
        !           312:                        RETURN_FALSE;
        !           313:                }
        !           314:                size = php_stream_passthru(stream);
        !           315:                php_stream_close(stream);
        !           316:                RETURN_LONG(size);
        !           317:        }
        !           318: 
        !           319: skip_phar:
        !           320:        PHAR_G(orig_readfile)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
        !           321:        return;
        !           322: 
        !           323: }
        !           324: /* }}} */
        !           325: 
        !           326: PHAR_FUNC(phar_fopen) /* {{{ */
        !           327: {
        !           328:        char *filename, *mode;
        !           329:        int filename_len, mode_len;
        !           330:        zend_bool use_include_path = 0;
        !           331:        zval *zcontext = NULL;
        !           332:        php_stream *stream;
        !           333: 
        !           334:        if (!PHAR_G(intercepted)) {
        !           335:                goto skip_phar;
        !           336:        }
        !           337: 
        !           338:        if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
        !           339:                && !cached_phars.arBuckets) {
        !           340:                /* no need to check, include_path not even specified in fopen/ no active phars */
        !           341:                goto skip_phar;
        !           342:        }
        !           343:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "ss|br", &filename, &filename_len, &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) {
        !           344:                goto skip_phar;
        !           345:        }
        !           346:        if (use_include_path || (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://"))) {
        !           347:                char *arch, *entry, *fname;
        !           348:                int arch_len, entry_len, fname_len;
        !           349:                php_stream_context *context = NULL;
        !           350:                char *name;
        !           351:                phar_archive_data *phar;
        !           352:                fname = zend_get_executed_filename(TSRMLS_C);
        !           353: 
        !           354:                if (strncasecmp(fname, "phar://", 7)) {
        !           355:                        goto skip_phar;
        !           356:                }
        !           357:                fname_len = strlen(fname);
        !           358:                if (FAILURE == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
        !           359:                        goto skip_phar;
        !           360:                }
        !           361: 
        !           362:                efree(entry);
        !           363:                entry = filename;
        !           364:                /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
        !           365:                entry_len = filename_len;
        !           366:                /* retrieving a file defaults to within the current directory, so use this if possible */
        !           367:                if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
        !           368:                        efree(arch);
        !           369:                        goto skip_phar;
        !           370:                }
        !           371:                if (use_include_path) {
        !           372:                        if (!(entry = phar_find_in_include_path(entry, entry_len, NULL TSRMLS_CC))) {
        !           373:                                /* this file is not in the phar, use the original path */
        !           374:                                efree(arch);
        !           375:                                goto skip_phar;
        !           376:                        } else {
        !           377:                                name = entry;
        !           378:                        }
        !           379:                } else {
        !           380:                        entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
        !           381:                        if (entry[0] == '/') {
        !           382:                                if (!zend_hash_exists(&(phar->manifest), entry + 1, entry_len - 1)) {
        !           383:                                        /* this file is not in the phar, use the original path */
        !           384: notfound:
        !           385:                                        efree(entry);
        !           386:                                        efree(arch);
        !           387:                                        goto skip_phar;
        !           388:                                }
        !           389:                        } else {
        !           390:                                if (!zend_hash_exists(&(phar->manifest), entry, entry_len)) {
        !           391:                                        /* this file is not in the phar, use the original path */
        !           392:                                        goto notfound;
        !           393:                                }
        !           394:                        }
        !           395:                        /* auto-convert to phar:// */
        !           396:                        if (entry[0] == '/') {
        !           397:                                spprintf(&name, 4096, "phar://%s%s", arch, entry);
        !           398:                        } else {
        !           399:                                spprintf(&name, 4096, "phar://%s/%s", arch, entry);
        !           400:                        }
        !           401:                        efree(entry);
        !           402:                }
        !           403: 
        !           404:                efree(arch);
        !           405:                context = php_stream_context_from_zval(zcontext, 0);
        !           406:                stream = php_stream_open_wrapper_ex(name, mode, 0 | REPORT_ERRORS, NULL, context);
        !           407:                efree(name);
        !           408:                if (stream == NULL) {
        !           409:                        RETURN_FALSE;
        !           410:                }
        !           411:                php_stream_to_zval(stream, return_value);
        !           412:                if (zcontext) {
        !           413:                        zend_list_addref(Z_RESVAL_P(zcontext));
        !           414:                }
        !           415:                return;
        !           416:        }
        !           417: skip_phar:
        !           418:        PHAR_G(orig_fopen)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
        !           419:        return;
        !           420: }
        !           421: /* }}} */
        !           422: 
        !           423: #ifndef S_ISDIR
        !           424: #define S_ISDIR(mode)  (((mode)&S_IFMT) == S_IFDIR)
        !           425: #endif
        !           426: #ifndef S_ISREG
        !           427: #define S_ISREG(mode)  (((mode)&S_IFMT) == S_IFREG)
        !           428: #endif
        !           429: #ifndef S_ISLNK
        !           430: #define S_ISLNK(mode)  (((mode)&S_IFMT) == S_IFLNK)
        !           431: #endif
        !           432: 
        !           433: #define S_IXROOT ( S_IXUSR | S_IXGRP | S_IXOTH )
        !           434: 
        !           435: #define IS_LINK_OPERATION(__t) ((__t) == FS_TYPE || (__t) == FS_IS_LINK || (__t) == FS_LSTAT)
        !           436: #define IS_EXISTS_CHECK(__t) ((__t) == FS_EXISTS  || (__t) == FS_IS_W || (__t) == FS_IS_R || (__t) == FS_IS_X || (__t) == FS_IS_FILE || (__t) == FS_IS_DIR || (__t) == FS_IS_LINK)
        !           437: #define IS_ABLE_CHECK(__t) ((__t) == FS_IS_R || (__t) == FS_IS_W || (__t) == FS_IS_X)
        !           438: #define IS_ACCESS_CHECK(__t) (IS_ABLE_CHECK(type) || (__t) == FS_EXISTS)
        !           439: 
        !           440: /* {{{ php_stat
        !           441:  */
        !           442: static void phar_fancy_stat(struct stat *stat_sb, int type, zval *return_value TSRMLS_DC)
        !           443: {
        !           444:        zval *stat_dev, *stat_ino, *stat_mode, *stat_nlink, *stat_uid, *stat_gid, *stat_rdev,
        !           445:                 *stat_size, *stat_atime, *stat_mtime, *stat_ctime, *stat_blksize, *stat_blocks;
        !           446:        int rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */
        !           447:        char *stat_sb_names[13] = {
        !           448:                "dev", "ino", "mode", "nlink", "uid", "gid", "rdev",
        !           449:                "size", "atime", "mtime", "ctime", "blksize", "blocks"
        !           450:        };
        !           451: 
        !           452: #ifndef NETWARE
        !           453:        if (type >= FS_IS_W && type <= FS_IS_X) {
        !           454:                if(stat_sb->st_uid==getuid()) {
        !           455:                        rmask=S_IRUSR;
        !           456:                        wmask=S_IWUSR;
        !           457:                        xmask=S_IXUSR;
        !           458:                } else if(stat_sb->st_gid==getgid()) {
        !           459:                        rmask=S_IRGRP;
        !           460:                        wmask=S_IWGRP;
        !           461:                        xmask=S_IXGRP;
        !           462:                } else {
        !           463:                        int   groups, n, i;
        !           464:                        gid_t *gids;
        !           465: 
        !           466:                        groups = getgroups(0, NULL);
        !           467:                        if(groups > 0) {
        !           468:                                gids=(gid_t *)safe_emalloc(groups, sizeof(gid_t), 0);
        !           469:                                n=getgroups(groups, gids);
        !           470:                                for(i=0;i<n;++i){
        !           471:                                        if(stat_sb->st_gid==gids[i]) {
        !           472:                                                rmask=S_IRGRP;
        !           473:                                                wmask=S_IWGRP;
        !           474:                                                xmask=S_IXGRP;
        !           475:                                                break;
        !           476:                                        }
        !           477:                                }
        !           478:                                efree(gids);
        !           479:                        }
        !           480:                }
        !           481:        }
        !           482: #endif
        !           483: 
        !           484:        switch (type) {
        !           485:        case FS_PERMS:
        !           486:                RETURN_LONG((long)stat_sb->st_mode);
        !           487:        case FS_INODE:
        !           488:                RETURN_LONG((long)stat_sb->st_ino);
        !           489:        case FS_SIZE:
        !           490:                RETURN_LONG((long)stat_sb->st_size);
        !           491:        case FS_OWNER:
        !           492:                RETURN_LONG((long)stat_sb->st_uid);
        !           493:        case FS_GROUP:
        !           494:                RETURN_LONG((long)stat_sb->st_gid);
        !           495:        case FS_ATIME:
        !           496: #ifdef NETWARE
        !           497:                RETURN_LONG((long)stat_sb->st_atime.tv_sec);
        !           498: #else
        !           499:                RETURN_LONG((long)stat_sb->st_atime);
        !           500: #endif
        !           501:        case FS_MTIME:
        !           502: #ifdef NETWARE
        !           503:                RETURN_LONG((long)stat_sb->st_mtime.tv_sec);
        !           504: #else
        !           505:                RETURN_LONG((long)stat_sb->st_mtime);
        !           506: #endif
        !           507:        case FS_CTIME:
        !           508: #ifdef NETWARE
        !           509:                RETURN_LONG((long)stat_sb->st_ctime.tv_sec);
        !           510: #else
        !           511:                RETURN_LONG((long)stat_sb->st_ctime);
        !           512: #endif
        !           513:        case FS_TYPE:
        !           514:                if (S_ISLNK(stat_sb->st_mode)) {
        !           515:                        RETURN_STRING("link", 1);
        !           516:                }
        !           517:                switch(stat_sb->st_mode & S_IFMT) {
        !           518:                case S_IFDIR: RETURN_STRING("dir", 1);
        !           519:                case S_IFREG: RETURN_STRING("file", 1);
        !           520:                }
        !           521:                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown file type (%u)", stat_sb->st_mode & S_IFMT);
        !           522:                RETURN_STRING("unknown", 1);
        !           523:        case FS_IS_W:
        !           524:                RETURN_BOOL((stat_sb->st_mode & wmask) != 0);
        !           525:        case FS_IS_R:
        !           526:                RETURN_BOOL((stat_sb->st_mode&rmask)!=0);
        !           527:        case FS_IS_X:
        !           528:                RETURN_BOOL((stat_sb->st_mode&xmask)!=0 && !S_ISDIR(stat_sb->st_mode));
        !           529:        case FS_IS_FILE:
        !           530:                RETURN_BOOL(S_ISREG(stat_sb->st_mode));
        !           531:        case FS_IS_DIR:
        !           532:                RETURN_BOOL(S_ISDIR(stat_sb->st_mode));
        !           533:        case FS_IS_LINK:
        !           534:                RETURN_BOOL(S_ISLNK(stat_sb->st_mode));
        !           535:        case FS_EXISTS:
        !           536:                RETURN_TRUE; /* the false case was done earlier */
        !           537:        case FS_LSTAT:
        !           538:                /* FALLTHROUGH */
        !           539:        case FS_STAT:
        !           540:                array_init(return_value);
        !           541: 
        !           542:                MAKE_LONG_ZVAL_INCREF(stat_dev, stat_sb->st_dev);
        !           543:                MAKE_LONG_ZVAL_INCREF(stat_ino, stat_sb->st_ino);
        !           544:                MAKE_LONG_ZVAL_INCREF(stat_mode, stat_sb->st_mode);
        !           545:                MAKE_LONG_ZVAL_INCREF(stat_nlink, stat_sb->st_nlink);
        !           546:                MAKE_LONG_ZVAL_INCREF(stat_uid, stat_sb->st_uid);
        !           547:                MAKE_LONG_ZVAL_INCREF(stat_gid, stat_sb->st_gid);
        !           548: #ifdef HAVE_ST_RDEV
        !           549:                MAKE_LONG_ZVAL_INCREF(stat_rdev, stat_sb->st_rdev);
        !           550: #else
        !           551:                MAKE_LONG_ZVAL_INCREF(stat_rdev, -1);
        !           552: #endif
        !           553:                MAKE_LONG_ZVAL_INCREF(stat_size, stat_sb->st_size);
        !           554: #ifdef NETWARE
        !           555:                MAKE_LONG_ZVAL_INCREF(stat_atime, (stat_sb->st_atime).tv_sec);
        !           556:                MAKE_LONG_ZVAL_INCREF(stat_mtime, (stat_sb->st_mtime).tv_sec);
        !           557:                MAKE_LONG_ZVAL_INCREF(stat_ctime, (stat_sb->st_ctime).tv_sec);
        !           558: #else
        !           559:                MAKE_LONG_ZVAL_INCREF(stat_atime, stat_sb->st_atime);
        !           560:                MAKE_LONG_ZVAL_INCREF(stat_mtime, stat_sb->st_mtime);
        !           561:                MAKE_LONG_ZVAL_INCREF(stat_ctime, stat_sb->st_ctime);
        !           562: #endif
        !           563: #ifdef HAVE_ST_BLKSIZE
        !           564:                MAKE_LONG_ZVAL_INCREF(stat_blksize, stat_sb->st_blksize);
        !           565: #else
        !           566:                MAKE_LONG_ZVAL_INCREF(stat_blksize,-1);
        !           567: #endif
        !           568: #ifdef HAVE_ST_BLOCKS
        !           569:                MAKE_LONG_ZVAL_INCREF(stat_blocks, stat_sb->st_blocks);
        !           570: #else
        !           571:                MAKE_LONG_ZVAL_INCREF(stat_blocks,-1);
        !           572: #endif
        !           573:                /* Store numeric indexes in propper order */
        !           574:                zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_dev, sizeof(zval *), NULL);
        !           575:                zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ino, sizeof(zval *), NULL);
        !           576:                zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mode, sizeof(zval *), NULL);
        !           577:                zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_nlink, sizeof(zval *), NULL);
        !           578:                zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_uid, sizeof(zval *), NULL);
        !           579:                zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_gid, sizeof(zval *), NULL);
        !           580: 
        !           581:                zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_rdev, sizeof(zval *), NULL);
        !           582:                zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_size, sizeof(zval *), NULL);
        !           583:                zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_atime, sizeof(zval *), NULL);
        !           584:                zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_mtime, sizeof(zval *), NULL);
        !           585:                zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_ctime, sizeof(zval *), NULL);
        !           586:                zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blksize, sizeof(zval *), NULL);
        !           587:                zend_hash_next_index_insert(HASH_OF(return_value), (void *)&stat_blocks, sizeof(zval *), NULL);
        !           588: 
        !           589:                /* Store string indexes referencing the same zval*/
        !           590:                zend_hash_update(HASH_OF(return_value), stat_sb_names[0], strlen(stat_sb_names[0])+1, (void *) &stat_dev, sizeof(zval *), NULL);
        !           591:                zend_hash_update(HASH_OF(return_value), stat_sb_names[1], strlen(stat_sb_names[1])+1, (void *) &stat_ino, sizeof(zval *), NULL);
        !           592:                zend_hash_update(HASH_OF(return_value), stat_sb_names[2], strlen(stat_sb_names[2])+1, (void *) &stat_mode, sizeof(zval *), NULL);
        !           593:                zend_hash_update(HASH_OF(return_value), stat_sb_names[3], strlen(stat_sb_names[3])+1, (void *) &stat_nlink, sizeof(zval *), NULL);
        !           594:                zend_hash_update(HASH_OF(return_value), stat_sb_names[4], strlen(stat_sb_names[4])+1, (void *) &stat_uid, sizeof(zval *), NULL);
        !           595:                zend_hash_update(HASH_OF(return_value), stat_sb_names[5], strlen(stat_sb_names[5])+1, (void *) &stat_gid, sizeof(zval *), NULL);
        !           596:                zend_hash_update(HASH_OF(return_value), stat_sb_names[6], strlen(stat_sb_names[6])+1, (void *) &stat_rdev, sizeof(zval *), NULL);
        !           597:                zend_hash_update(HASH_OF(return_value), stat_sb_names[7], strlen(stat_sb_names[7])+1, (void *) &stat_size, sizeof(zval *), NULL);
        !           598:                zend_hash_update(HASH_OF(return_value), stat_sb_names[8], strlen(stat_sb_names[8])+1, (void *) &stat_atime, sizeof(zval *), NULL);
        !           599:                zend_hash_update(HASH_OF(return_value), stat_sb_names[9], strlen(stat_sb_names[9])+1, (void *) &stat_mtime, sizeof(zval *), NULL);
        !           600:                zend_hash_update(HASH_OF(return_value), stat_sb_names[10], strlen(stat_sb_names[10])+1, (void *) &stat_ctime, sizeof(zval *), NULL);
        !           601:                zend_hash_update(HASH_OF(return_value), stat_sb_names[11], strlen(stat_sb_names[11])+1, (void *) &stat_blksize, sizeof(zval *), NULL);
        !           602:                zend_hash_update(HASH_OF(return_value), stat_sb_names[12], strlen(stat_sb_names[12])+1, (void *) &stat_blocks, sizeof(zval *), NULL);
        !           603: 
        !           604:                return;
        !           605:        }
        !           606:        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Didn't understand stat call");
        !           607:        RETURN_FALSE;
        !           608: }
        !           609: /* }}} */
        !           610: 
        !           611: static void phar_file_stat(const char *filename, php_stat_len filename_length, int type, void (*orig_stat_func)(INTERNAL_FUNCTION_PARAMETERS), INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
        !           612: {
        !           613:        if (!filename_length) {
        !           614:                RETURN_FALSE;
        !           615:        }
        !           616: 
        !           617:        if (!IS_ABSOLUTE_PATH(filename, filename_length) && !strstr(filename, "://")) {
        !           618:                char *arch, *entry, *fname;
        !           619:                int arch_len, entry_len, fname_len;
        !           620:                struct stat sb = {0};
        !           621:                phar_entry_info *data = NULL;
        !           622:                phar_archive_data *phar;
        !           623: 
        !           624:                fname = zend_get_executed_filename(TSRMLS_C);
        !           625: 
        !           626:                /* we are checking for existence of a file within the relative path.  Chances are good that this is
        !           627:                   retrieving something from within the phar archive */
        !           628: 
        !           629:                if (strncasecmp(fname, "phar://", 7)) {
        !           630:                        goto skip_phar;
        !           631:                }
        !           632:                fname_len = strlen(fname);
        !           633:                if (PHAR_G(last_phar) && fname_len - 7 >= PHAR_G(last_phar_name_len) && !memcmp(fname + 7, PHAR_G(last_phar_name), PHAR_G(last_phar_name_len))) {
        !           634:                        arch = estrndup(PHAR_G(last_phar_name), PHAR_G(last_phar_name_len));
        !           635:                        arch_len = PHAR_G(last_phar_name_len);
        !           636:                        entry = estrndup(filename, filename_length);
        !           637:                        /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
        !           638:                        entry_len = (int) filename_length;
        !           639:                        phar = PHAR_G(last_phar);
        !           640:                        goto splitted;
        !           641:                }
        !           642:                if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
        !           643: 
        !           644:                        efree(entry);
        !           645:                        entry = estrndup(filename, filename_length);
        !           646:                        /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
        !           647:                        entry_len = (int) filename_length;
        !           648:                        if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
        !           649:                                efree(arch);
        !           650:                                efree(entry);
        !           651:                                goto skip_phar;
        !           652:                        }
        !           653: splitted:
        !           654:                        entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC);
        !           655:                        if (entry[0] == '/') {
        !           656:                                if (SUCCESS == zend_hash_find(&(phar->manifest), entry + 1, entry_len - 1, (void **) &data)) {
        !           657:                                        efree(entry);
        !           658:                                        goto stat_entry;
        !           659:                                }
        !           660:                                goto notfound;
        !           661:                        }
        !           662:                        if (SUCCESS == zend_hash_find(&(phar->manifest), entry, entry_len, (void **) &data)) {
        !           663:                                efree(entry);
        !           664:                                goto stat_entry;
        !           665:                        }
        !           666:                        if (zend_hash_exists(&(phar->virtual_dirs), entry, entry_len)) {
        !           667:                                efree(entry);
        !           668:                                efree(arch);
        !           669:                                if (IS_EXISTS_CHECK(type)) {
        !           670:                                        RETURN_TRUE;
        !           671:                                }
        !           672:                                sb.st_size = 0;
        !           673:                                sb.st_mode = 0777;
        !           674:                                sb.st_mode |= S_IFDIR; /* regular directory */
        !           675: #ifdef NETWARE
        !           676:                                sb.st_mtime.tv_sec = phar->max_timestamp;
        !           677:                                sb.st_atime.tv_sec = phar->max_timestamp;
        !           678:                                sb.st_ctime.tv_sec = phar->max_timestamp;
        !           679: #else
        !           680:                                sb.st_mtime = phar->max_timestamp;
        !           681:                                sb.st_atime = phar->max_timestamp;
        !           682:                                sb.st_ctime = phar->max_timestamp;
        !           683: #endif
        !           684:                                goto statme_baby;
        !           685:                        } else {
        !           686:                                char *save;
        !           687:                                int save_len;
        !           688: 
        !           689: notfound:
        !           690:                                efree(entry);
        !           691:                                save = PHAR_G(cwd);
        !           692:                                save_len = PHAR_G(cwd_len);
        !           693:                                /* this file is not in the current directory, use the original path */
        !           694:                                entry = estrndup(filename, filename_length);
        !           695:                                entry_len = filename_length;
        !           696:                                PHAR_G(cwd) = "/";
        !           697:                                PHAR_G(cwd_len) = 0;
        !           698:                                /* clean path without cwd */
        !           699:                                entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC);
        !           700:                                if (SUCCESS == zend_hash_find(&(phar->manifest), entry + 1, entry_len - 1, (void **) &data)) {
        !           701:                                        PHAR_G(cwd) = save;
        !           702:                                        PHAR_G(cwd_len) = save_len;
        !           703:                                        efree(entry);
        !           704:                                        if (IS_EXISTS_CHECK(type)) {
        !           705:                                                efree(arch);
        !           706:                                                RETURN_TRUE;
        !           707:                                        }
        !           708:                                        goto stat_entry;
        !           709:                                }
        !           710:                                if (zend_hash_exists(&(phar->virtual_dirs), entry + 1, entry_len - 1)) {
        !           711:                                        PHAR_G(cwd) = save;
        !           712:                                        PHAR_G(cwd_len) = save_len;
        !           713:                                        efree(entry);
        !           714:                                        efree(arch);
        !           715:                                        if (IS_EXISTS_CHECK(type)) {
        !           716:                                                RETURN_TRUE;
        !           717:                                        }
        !           718:                                        sb.st_size = 0;
        !           719:                                        sb.st_mode = 0777;
        !           720:                                        sb.st_mode |= S_IFDIR; /* regular directory */
        !           721: #ifdef NETWARE
        !           722:                                        sb.st_mtime.tv_sec = phar->max_timestamp;
        !           723:                                        sb.st_atime.tv_sec = phar->max_timestamp;
        !           724:                                        sb.st_ctime.tv_sec = phar->max_timestamp;
        !           725: #else
        !           726:                                        sb.st_mtime = phar->max_timestamp;
        !           727:                                        sb.st_atime = phar->max_timestamp;
        !           728:                                        sb.st_ctime = phar->max_timestamp;
        !           729: #endif
        !           730:                                        goto statme_baby;
        !           731:                                }
        !           732:                                PHAR_G(cwd) = save;
        !           733:                                PHAR_G(cwd_len) = save_len;
        !           734:                                efree(entry);
        !           735:                                efree(arch);
        !           736:                                /* Error Occured */
        !           737:                                if (!IS_EXISTS_CHECK(type)) {
        !           738:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename);
        !           739:                                }
        !           740:                                RETURN_FALSE;
        !           741:                        }
        !           742: stat_entry:
        !           743:                        efree(arch);
        !           744:                        if (!data->is_dir) {
        !           745:                                sb.st_size = data->uncompressed_filesize;
        !           746:                                sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
        !           747:                                if (data->link) {
        !           748:                                        sb.st_mode |= S_IFREG|S_IFLNK; /* regular file */
        !           749:                                } else {
        !           750:                                        sb.st_mode |= S_IFREG; /* regular file */
        !           751:                                }
        !           752:                                /* timestamp is just the timestamp when this was added to the phar */
        !           753: #ifdef NETWARE
        !           754:                                sb.st_mtime.tv_sec = data->timestamp;
        !           755:                                sb.st_atime.tv_sec = data->timestamp;
        !           756:                                sb.st_ctime.tv_sec = data->timestamp;
        !           757: #else
        !           758:                                sb.st_mtime = data->timestamp;
        !           759:                                sb.st_atime = data->timestamp;
        !           760:                                sb.st_ctime = data->timestamp;
        !           761: #endif
        !           762:                        } else {
        !           763:                                sb.st_size = 0;
        !           764:                                sb.st_mode = data->flags & PHAR_ENT_PERM_MASK;
        !           765:                                sb.st_mode |= S_IFDIR; /* regular directory */
        !           766:                                if (data->link) {
        !           767:                                        sb.st_mode |= S_IFLNK;
        !           768:                                }
        !           769:                                /* timestamp is just the timestamp when this was added to the phar */
        !           770: #ifdef NETWARE
        !           771:                                sb.st_mtime.tv_sec = data->timestamp;
        !           772:                                sb.st_atime.tv_sec = data->timestamp;
        !           773:                                sb.st_ctime.tv_sec = data->timestamp;
        !           774: #else
        !           775:                                sb.st_mtime = data->timestamp;
        !           776:                                sb.st_atime = data->timestamp;
        !           777:                                sb.st_ctime = data->timestamp;
        !           778: #endif
        !           779:                        }
        !           780: 
        !           781: statme_baby:
        !           782:                        if (!phar->is_writeable) {
        !           783:                                sb.st_mode = (sb.st_mode & 0555) | (sb.st_mode & ~0777);
        !           784:                        }
        !           785: 
        !           786:                        sb.st_nlink = 1;
        !           787:                        sb.st_rdev = -1;
        !           788:                        /* this is only for APC, so use /dev/null device - no chance of conflict there! */
        !           789:                        sb.st_dev = 0xc;
        !           790:                        /* generate unique inode number for alias/filename, so no phars will conflict */
        !           791:                        if (data) {
        !           792:                                sb.st_ino = data->inode;
        !           793:                        }
        !           794: #ifndef PHP_WIN32
        !           795:                        sb.st_blksize = -1;
        !           796:                        sb.st_blocks = -1;
        !           797: #endif
        !           798:                        phar_fancy_stat(&sb, type, return_value TSRMLS_CC);
        !           799:                        return;
        !           800:                }
        !           801:        }
        !           802: skip_phar:
        !           803:        orig_stat_func(INTERNAL_FUNCTION_PARAM_PASSTHRU);
        !           804:        return;
        !           805: }
        !           806: /* }}} */
        !           807: 
        !           808: #define PharFileFunction(fname, funcnum, orig) \
        !           809: void fname(INTERNAL_FUNCTION_PARAMETERS) { \
        !           810:        if (!PHAR_G(intercepted)) { \
        !           811:                PHAR_G(orig)(INTERNAL_FUNCTION_PARAM_PASSTHRU); \
        !           812:        } else { \
        !           813:                char *filename; \
        !           814:                int filename_len; \
        !           815:                \
        !           816:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { \
        !           817:                        return; \
        !           818:                } \
        !           819:                \
        !           820:                phar_file_stat(filename, (php_stat_len) filename_len, funcnum, PHAR_G(orig), INTERNAL_FUNCTION_PARAM_PASSTHRU); \
        !           821:        } \
        !           822: }
        !           823: /* }}} */
        !           824: 
        !           825: /* {{{ proto int fileperms(string filename)
        !           826:    Get file permissions */
        !           827: PharFileFunction(phar_fileperms, FS_PERMS, orig_fileperms)
        !           828: /* }}} */
        !           829: 
        !           830: /* {{{ proto int fileinode(string filename)
        !           831:    Get file inode */
        !           832: PharFileFunction(phar_fileinode, FS_INODE, orig_fileinode)
        !           833: /* }}} */
        !           834: 
        !           835: /* {{{ proto int filesize(string filename)
        !           836:    Get file size */
        !           837: PharFileFunction(phar_filesize, FS_SIZE, orig_filesize)
        !           838: /* }}} */
        !           839: 
        !           840: /* {{{ proto int fileowner(string filename)
        !           841:    Get file owner */
        !           842: PharFileFunction(phar_fileowner, FS_OWNER, orig_fileowner)
        !           843: /* }}} */
        !           844: 
        !           845: /* {{{ proto int filegroup(string filename)
        !           846:    Get file group */
        !           847: PharFileFunction(phar_filegroup, FS_GROUP, orig_filegroup)
        !           848: /* }}} */
        !           849: 
        !           850: /* {{{ proto int fileatime(string filename)
        !           851:    Get last access time of file */
        !           852: PharFileFunction(phar_fileatime, FS_ATIME, orig_fileatime)
        !           853: /* }}} */
        !           854: 
        !           855: /* {{{ proto int filemtime(string filename)
        !           856:    Get last modification time of file */
        !           857: PharFileFunction(phar_filemtime, FS_MTIME, orig_filemtime)
        !           858: /* }}} */
        !           859: 
        !           860: /* {{{ proto int filectime(string filename)
        !           861:    Get inode modification time of file */
        !           862: PharFileFunction(phar_filectime, FS_CTIME, orig_filectime)
        !           863: /* }}} */
        !           864: 
        !           865: /* {{{ proto string filetype(string filename)
        !           866:    Get file type */
        !           867: PharFileFunction(phar_filetype, FS_TYPE, orig_filetype)
        !           868: /* }}} */
        !           869: 
        !           870: /* {{{ proto bool is_writable(string filename)
        !           871:    Returns true if file can be written */
        !           872: PharFileFunction(phar_is_writable, FS_IS_W, orig_is_writable)
        !           873: /* }}} */
        !           874: 
        !           875: /* {{{ proto bool is_readable(string filename)
        !           876:    Returns true if file can be read */
        !           877: PharFileFunction(phar_is_readable, FS_IS_R, orig_is_readable)
        !           878: /* }}} */
        !           879: 
        !           880: /* {{{ proto bool is_executable(string filename)
        !           881:    Returns true if file is executable */
        !           882: PharFileFunction(phar_is_executable, FS_IS_X, orig_is_executable)
        !           883: /* }}} */
        !           884: 
        !           885: /* {{{ proto bool file_exists(string filename)
        !           886:    Returns true if filename exists */
        !           887: PharFileFunction(phar_file_exists, FS_EXISTS, orig_file_exists)
        !           888: /* }}} */
        !           889: 
        !           890: /* {{{ proto bool is_dir(string filename)
        !           891:    Returns true if file is directory */
        !           892: PharFileFunction(phar_is_dir, FS_IS_DIR, orig_is_dir)
        !           893: /* }}} */
        !           894: 
        !           895: PHAR_FUNC(phar_is_file) /* {{{ */
        !           896: {
        !           897:        char *filename;
        !           898:        int filename_len;
        !           899: 
        !           900:        if (!PHAR_G(intercepted)) {
        !           901:                goto skip_phar;
        !           902:        }
        !           903: 
        !           904:        if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
        !           905:                && !cached_phars.arBuckets) {
        !           906:                goto skip_phar;
        !           907:        }
        !           908:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
        !           909:                goto skip_phar;
        !           910:        }
        !           911:        if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
        !           912:                char *arch, *entry, *fname;
        !           913:                int arch_len, entry_len, fname_len;
        !           914:                fname = zend_get_executed_filename(TSRMLS_C);
        !           915: 
        !           916:                /* we are checking for existence of a file within the relative path.  Chances are good that this is
        !           917:                   retrieving something from within the phar archive */
        !           918: 
        !           919:                if (strncasecmp(fname, "phar://", 7)) {
        !           920:                        goto skip_phar;
        !           921:                }
        !           922:                fname_len = strlen(fname);
        !           923:                if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
        !           924:                        phar_archive_data *phar;
        !           925: 
        !           926:                        efree(entry);
        !           927:                        entry = filename;
        !           928:                        /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
        !           929:                        entry_len = filename_len;
        !           930:                        /* retrieving a file within the current directory, so use this if possible */
        !           931:                        if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
        !           932:                                phar_entry_info *etemp;
        !           933: 
        !           934:                                entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
        !           935:                                if (entry[0] == '/') {
        !           936:                                        if (SUCCESS == zend_hash_find(&(phar->manifest), entry + 1, entry_len - 1, (void **) &etemp)) {
        !           937:                                                /* this file is not in the current directory, use the original path */
        !           938: found_it:
        !           939:                                                efree(entry);
        !           940:                                                efree(arch);
        !           941:                                                RETURN_BOOL(!etemp->is_dir);
        !           942:                                        }
        !           943:                                } else {
        !           944:                                        if (SUCCESS == zend_hash_find(&(phar->manifest), entry, entry_len, (void **) &etemp)) {
        !           945:                                                goto found_it;
        !           946:                                        }
        !           947:                                }
        !           948:                        }
        !           949:                        if (entry != filename) {
        !           950:                                efree(entry);
        !           951:                        }
        !           952:                        efree(arch);
        !           953:                        RETURN_FALSE;
        !           954:                }
        !           955:        }
        !           956: skip_phar:
        !           957:        PHAR_G(orig_is_file)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
        !           958:        return;
        !           959: }
        !           960: /* }}} */
        !           961: 
        !           962: PHAR_FUNC(phar_is_link) /* {{{ */
        !           963: {
        !           964:        char *filename;
        !           965:        int filename_len;
        !           966: 
        !           967:        if (!PHAR_G(intercepted)) {
        !           968:                goto skip_phar;
        !           969:        }
        !           970: 
        !           971:        if ((PHAR_GLOBALS->phar_fname_map.arBuckets && !zend_hash_num_elements(&(PHAR_GLOBALS->phar_fname_map)))
        !           972:                && !cached_phars.arBuckets) {
        !           973:                goto skip_phar;
        !           974:        }
        !           975:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
        !           976:                goto skip_phar;
        !           977:        }
        !           978:        if (!IS_ABSOLUTE_PATH(filename, filename_len) && !strstr(filename, "://")) {
        !           979:                char *arch, *entry, *fname;
        !           980:                int arch_len, entry_len, fname_len;
        !           981:                fname = zend_get_executed_filename(TSRMLS_C);
        !           982: 
        !           983:                /* we are checking for existence of a file within the relative path.  Chances are good that this is
        !           984:                   retrieving something from within the phar archive */
        !           985: 
        !           986:                if (strncasecmp(fname, "phar://", 7)) {
        !           987:                        goto skip_phar;
        !           988:                }
        !           989:                fname_len = strlen(fname);
        !           990:                if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
        !           991:                        phar_archive_data *phar;
        !           992: 
        !           993:                        efree(entry);
        !           994:                        entry = filename;
        !           995:                        /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
        !           996:                        entry_len = filename_len;
        !           997:                        /* retrieving a file within the current directory, so use this if possible */
        !           998:                        if (SUCCESS == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL TSRMLS_CC)) {
        !           999:                                phar_entry_info *etemp;
        !          1000: 
        !          1001:                                entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC);
        !          1002:                                if (entry[0] == '/') {
        !          1003:                                        if (SUCCESS == zend_hash_find(&(phar->manifest), entry + 1, entry_len - 1, (void **) &etemp)) {
        !          1004:                                                /* this file is not in the current directory, use the original path */
        !          1005: found_it:
        !          1006:                                                efree(entry);
        !          1007:                                                efree(arch);
        !          1008:                                                RETURN_BOOL(etemp->link);
        !          1009:                                        }
        !          1010:                                } else {
        !          1011:                                        if (SUCCESS == zend_hash_find(&(phar->manifest), entry, entry_len, (void **) &etemp)) {
        !          1012:                                                goto found_it;
        !          1013:                                        }
        !          1014:                                }
        !          1015:                        }
        !          1016:                        efree(entry);
        !          1017:                        efree(arch);
        !          1018:                        RETURN_FALSE;
        !          1019:                }
        !          1020:        }
        !          1021: skip_phar:
        !          1022:        PHAR_G(orig_is_link)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
        !          1023:        return;
        !          1024: }
        !          1025: /* }}} */
        !          1026: 
        !          1027: /* {{{ proto array lstat(string filename)
        !          1028:    Give information about a file or symbolic link */
        !          1029: PharFileFunction(phar_lstat, FS_LSTAT, orig_lstat)
        !          1030: /* }}} */
        !          1031: 
        !          1032: /* {{{ proto array stat(string filename)
        !          1033:    Give information about a file */
        !          1034: PharFileFunction(phar_stat, FS_STAT, orig_stat)
        !          1035: /* }}} */
        !          1036: 
        !          1037: /* {{{ void phar_intercept_functions(TSRMLS_D) */
        !          1038: void phar_intercept_functions(TSRMLS_D)
        !          1039: {
        !          1040:        if (!PHAR_G(request_init)) {
        !          1041:                PHAR_G(cwd) = NULL;
        !          1042:                PHAR_G(cwd_len) = 0;
        !          1043:        }
        !          1044:        PHAR_G(intercepted) = 1;
        !          1045: }
        !          1046: /* }}} */
        !          1047: 
        !          1048: /* {{{ void phar_release_functions(TSRMLS_D) */
        !          1049: void phar_release_functions(TSRMLS_D)
        !          1050: {
        !          1051:        PHAR_G(intercepted) = 0;
        !          1052: }
        !          1053: /* }}} */
        !          1054: 
        !          1055: /* {{{ void phar_intercept_functions_init(TSRMLS_D) */
        !          1056: #define PHAR_INTERCEPT(func) \
        !          1057:        PHAR_G(orig_##func) = NULL; \
        !          1058:        if (SUCCESS == zend_hash_find(CG(function_table), #func, sizeof(#func), (void **)&orig)) { \
        !          1059:                PHAR_G(orig_##func) = orig->internal_function.handler; \
        !          1060:                orig->internal_function.handler = phar_##func; \
        !          1061:        }
        !          1062: 
        !          1063: void phar_intercept_functions_init(TSRMLS_D)
        !          1064: {
        !          1065:        zend_function *orig;
        !          1066: 
        !          1067:        PHAR_INTERCEPT(fopen);
        !          1068:        PHAR_INTERCEPT(file_get_contents);
        !          1069:        PHAR_INTERCEPT(is_file);
        !          1070:        PHAR_INTERCEPT(is_link);
        !          1071:        PHAR_INTERCEPT(is_dir);
        !          1072:        PHAR_INTERCEPT(opendir);
        !          1073:        PHAR_INTERCEPT(file_exists);
        !          1074:        PHAR_INTERCEPT(fileperms);
        !          1075:        PHAR_INTERCEPT(fileinode);
        !          1076:        PHAR_INTERCEPT(filesize);
        !          1077:        PHAR_INTERCEPT(fileowner);
        !          1078:        PHAR_INTERCEPT(filegroup);
        !          1079:        PHAR_INTERCEPT(fileatime);
        !          1080:        PHAR_INTERCEPT(filemtime);
        !          1081:        PHAR_INTERCEPT(filectime);
        !          1082:        PHAR_INTERCEPT(filetype);
        !          1083:        PHAR_INTERCEPT(is_writable);
        !          1084:        PHAR_INTERCEPT(is_readable);
        !          1085:        PHAR_INTERCEPT(is_executable);
        !          1086:        PHAR_INTERCEPT(lstat);
        !          1087:        PHAR_INTERCEPT(stat);
        !          1088:        PHAR_INTERCEPT(readfile);
        !          1089:        PHAR_G(intercepted) = 0;
        !          1090: }
        !          1091: /* }}} */
        !          1092: 
        !          1093: /* {{{ void phar_intercept_functions_shutdown(TSRMLS_D) */
        !          1094: #define PHAR_RELEASE(func) \
        !          1095:        if (PHAR_G(orig_##func) && SUCCESS == zend_hash_find(CG(function_table), #func, sizeof(#func), (void **)&orig)) { \
        !          1096:                orig->internal_function.handler = PHAR_G(orig_##func); \
        !          1097:        } \
        !          1098:        PHAR_G(orig_##func) = NULL;
        !          1099: 
        !          1100: void phar_intercept_functions_shutdown(TSRMLS_D)
        !          1101: {
        !          1102:        zend_function *orig;
        !          1103: 
        !          1104:        PHAR_RELEASE(fopen);
        !          1105:        PHAR_RELEASE(file_get_contents);
        !          1106:        PHAR_RELEASE(is_file);
        !          1107:        PHAR_RELEASE(is_dir);
        !          1108:        PHAR_RELEASE(opendir);
        !          1109:        PHAR_RELEASE(file_exists);
        !          1110:        PHAR_RELEASE(fileperms);
        !          1111:        PHAR_RELEASE(fileinode);
        !          1112:        PHAR_RELEASE(filesize);
        !          1113:        PHAR_RELEASE(fileowner);
        !          1114:        PHAR_RELEASE(filegroup);
        !          1115:        PHAR_RELEASE(fileatime);
        !          1116:        PHAR_RELEASE(filemtime);
        !          1117:        PHAR_RELEASE(filectime);
        !          1118:        PHAR_RELEASE(filetype);
        !          1119:        PHAR_RELEASE(is_writable);
        !          1120:        PHAR_RELEASE(is_readable);
        !          1121:        PHAR_RELEASE(is_executable);
        !          1122:        PHAR_RELEASE(lstat);
        !          1123:        PHAR_RELEASE(stat);
        !          1124:        PHAR_RELEASE(readfile);
        !          1125:        PHAR_G(intercepted) = 0;
        !          1126: }
        !          1127: /* }}} */
        !          1128: 
        !          1129: static struct _phar_orig_functions {
        !          1130:        void        (*orig_fopen)(INTERNAL_FUNCTION_PARAMETERS);
        !          1131:        void        (*orig_file_get_contents)(INTERNAL_FUNCTION_PARAMETERS);
        !          1132:        void        (*orig_is_file)(INTERNAL_FUNCTION_PARAMETERS);
        !          1133:        void        (*orig_is_link)(INTERNAL_FUNCTION_PARAMETERS);
        !          1134:        void        (*orig_is_dir)(INTERNAL_FUNCTION_PARAMETERS);
        !          1135:        void        (*orig_opendir)(INTERNAL_FUNCTION_PARAMETERS);
        !          1136:        void        (*orig_file_exists)(INTERNAL_FUNCTION_PARAMETERS);
        !          1137:        void        (*orig_fileperms)(INTERNAL_FUNCTION_PARAMETERS);
        !          1138:        void        (*orig_fileinode)(INTERNAL_FUNCTION_PARAMETERS);
        !          1139:        void        (*orig_filesize)(INTERNAL_FUNCTION_PARAMETERS);
        !          1140:        void        (*orig_fileowner)(INTERNAL_FUNCTION_PARAMETERS);
        !          1141:        void        (*orig_filegroup)(INTERNAL_FUNCTION_PARAMETERS);
        !          1142:        void        (*orig_fileatime)(INTERNAL_FUNCTION_PARAMETERS);
        !          1143:        void        (*orig_filemtime)(INTERNAL_FUNCTION_PARAMETERS);
        !          1144:        void        (*orig_filectime)(INTERNAL_FUNCTION_PARAMETERS);
        !          1145:        void        (*orig_filetype)(INTERNAL_FUNCTION_PARAMETERS);
        !          1146:        void        (*orig_is_writable)(INTERNAL_FUNCTION_PARAMETERS);
        !          1147:        void        (*orig_is_readable)(INTERNAL_FUNCTION_PARAMETERS);
        !          1148:        void        (*orig_is_executable)(INTERNAL_FUNCTION_PARAMETERS);
        !          1149:        void        (*orig_lstat)(INTERNAL_FUNCTION_PARAMETERS);
        !          1150:        void        (*orig_readfile)(INTERNAL_FUNCTION_PARAMETERS);
        !          1151:        void        (*orig_stat)(INTERNAL_FUNCTION_PARAMETERS);
        !          1152: } phar_orig_functions = {NULL};
        !          1153: 
        !          1154: void phar_save_orig_functions(TSRMLS_D) /* {{{ */
        !          1155: {
        !          1156:        phar_orig_functions.orig_fopen             = PHAR_G(orig_fopen);
        !          1157:        phar_orig_functions.orig_file_get_contents = PHAR_G(orig_file_get_contents);
        !          1158:        phar_orig_functions.orig_is_file           = PHAR_G(orig_is_file);
        !          1159:        phar_orig_functions.orig_is_link           = PHAR_G(orig_is_link);
        !          1160:        phar_orig_functions.orig_is_dir            = PHAR_G(orig_is_dir);
        !          1161:        phar_orig_functions.orig_opendir           = PHAR_G(orig_opendir);
        !          1162:        phar_orig_functions.orig_file_exists       = PHAR_G(orig_file_exists);
        !          1163:        phar_orig_functions.orig_fileperms         = PHAR_G(orig_fileperms);
        !          1164:        phar_orig_functions.orig_fileinode         = PHAR_G(orig_fileinode);
        !          1165:        phar_orig_functions.orig_filesize          = PHAR_G(orig_filesize);
        !          1166:        phar_orig_functions.orig_fileowner         = PHAR_G(orig_fileowner);
        !          1167:        phar_orig_functions.orig_filegroup         = PHAR_G(orig_filegroup);
        !          1168:        phar_orig_functions.orig_fileatime         = PHAR_G(orig_fileatime);
        !          1169:        phar_orig_functions.orig_filemtime         = PHAR_G(orig_filemtime);
        !          1170:        phar_orig_functions.orig_filectime         = PHAR_G(orig_filectime);
        !          1171:        phar_orig_functions.orig_filetype          = PHAR_G(orig_filetype);
        !          1172:        phar_orig_functions.orig_is_writable       = PHAR_G(orig_is_writable);
        !          1173:        phar_orig_functions.orig_is_readable       = PHAR_G(orig_is_readable);
        !          1174:        phar_orig_functions.orig_is_executable     = PHAR_G(orig_is_executable);
        !          1175:        phar_orig_functions.orig_lstat             = PHAR_G(orig_lstat);
        !          1176:        phar_orig_functions.orig_readfile          = PHAR_G(orig_readfile);
        !          1177:        phar_orig_functions.orig_stat              = PHAR_G(orig_stat);
        !          1178: }
        !          1179: /* }}} */
        !          1180: 
        !          1181: void phar_restore_orig_functions(TSRMLS_D) /* {{{ */
        !          1182: {
        !          1183:        PHAR_G(orig_fopen)             = phar_orig_functions.orig_fopen;
        !          1184:        PHAR_G(orig_file_get_contents) = phar_orig_functions.orig_file_get_contents;
        !          1185:        PHAR_G(orig_is_file)           = phar_orig_functions.orig_is_file;
        !          1186:        PHAR_G(orig_is_link)           = phar_orig_functions.orig_is_link;
        !          1187:        PHAR_G(orig_is_dir)            = phar_orig_functions.orig_is_dir;
        !          1188:        PHAR_G(orig_opendir)           = phar_orig_functions.orig_opendir;
        !          1189:        PHAR_G(orig_file_exists)       = phar_orig_functions.orig_file_exists;
        !          1190:        PHAR_G(orig_fileperms)         = phar_orig_functions.orig_fileperms;
        !          1191:        PHAR_G(orig_fileinode)         = phar_orig_functions.orig_fileinode;
        !          1192:        PHAR_G(orig_filesize)          = phar_orig_functions.orig_filesize;
        !          1193:        PHAR_G(orig_fileowner)         = phar_orig_functions.orig_fileowner;
        !          1194:        PHAR_G(orig_filegroup)         = phar_orig_functions.orig_filegroup;
        !          1195:        PHAR_G(orig_fileatime)         = phar_orig_functions.orig_fileatime;
        !          1196:        PHAR_G(orig_filemtime)         = phar_orig_functions.orig_filemtime;
        !          1197:        PHAR_G(orig_filectime)         = phar_orig_functions.orig_filectime;
        !          1198:        PHAR_G(orig_filetype)          = phar_orig_functions.orig_filetype;
        !          1199:        PHAR_G(orig_is_writable)       = phar_orig_functions.orig_is_writable;
        !          1200:        PHAR_G(orig_is_readable)       = phar_orig_functions.orig_is_readable;
        !          1201:        PHAR_G(orig_is_executable)     = phar_orig_functions.orig_is_executable;
        !          1202:        PHAR_G(orig_lstat)             = phar_orig_functions.orig_lstat;
        !          1203:        PHAR_G(orig_readfile)          = phar_orig_functions.orig_readfile;
        !          1204:        PHAR_G(orig_stat)              = phar_orig_functions.orig_stat;
        !          1205: }
        !          1206: /* }}} */
        !          1207: 
        !          1208: /*
        !          1209:  * Local variables:
        !          1210:  * tab-width: 4
        !          1211:  * c-basic-offset: 4
        !          1212:  * End:
        !          1213:  * vim600: noet sw=4 ts=4 fdm=marker
        !          1214:  * vim<600: noet sw=4 ts=4
        !          1215:  */
        !          1216: 

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