Annotation of embedaddon/php/ext/phar/func_interceptors.c, revision 1.1.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>