Annotation of embedaddon/php/ext/phar/phar_object.c, revision 1.1.1.2

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:   |          Marcus Boerger <helly@php.net>                              |
                     17:   +----------------------------------------------------------------------+
                     18: */
                     19: 
1.1.1.2 ! misho      20: /* $Id$ */
1.1       misho      21: 
                     22: #include "phar_internal.h"
                     23: #include "func_interceptors.h"
                     24: 
                     25: static zend_class_entry *phar_ce_archive;
                     26: static zend_class_entry *phar_ce_data;
                     27: static zend_class_entry *phar_ce_PharException;
                     28: 
                     29: #if HAVE_SPL
                     30: static zend_class_entry *phar_ce_entry;
                     31: #endif
                     32: 
                     33: #if PHP_MAJOR_VERSION > 5 || ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION >= 3))
                     34: # define PHAR_ARG_INFO
                     35: #else
                     36: # define PHAR_ARG_INFO static
                     37: #endif
                     38: 
                     39: static int phar_file_type(HashTable *mimes, char *file, char **mime_type TSRMLS_DC) /* {{{ */
                     40: {
                     41:        char *ext;
                     42:        phar_mime_type *mime;
                     43:        ext = strrchr(file, '.');
                     44:        if (!ext) {
                     45:                *mime_type = "text/plain";
                     46:                /* no file extension = assume text/plain */
                     47:                return PHAR_MIME_OTHER;
                     48:        }
                     49:        ++ext;
                     50:        if (SUCCESS != zend_hash_find(mimes, ext, strlen(ext), (void **) &mime)) {
                     51:                *mime_type = "application/octet-stream";
                     52:                return PHAR_MIME_OTHER;
                     53:        }
                     54:        *mime_type = mime->mime;
                     55:        return mime->type;
                     56: }
                     57: /* }}} */
                     58: 
                     59: static void phar_mung_server_vars(char *fname, char *entry, int entry_len, char *basename, int request_uri_len TSRMLS_DC) /* {{{ */
                     60: {
                     61: #if PHP_MAJOR_VERSION >= 6
                     62:        int is_unicode = 0;
                     63: #endif
                     64:        HashTable *_SERVER;
                     65:        zval **stuff;
                     66:        char *path_info;
                     67:        int basename_len = strlen(basename);
                     68:        int code;
                     69:        zval *temp;
                     70: 
                     71:        /* "tweak" $_SERVER variables requested in earlier call to Phar::mungServer() */
                     72:        if (!PG(http_globals)[TRACK_VARS_SERVER]) {
                     73:                return;
                     74:        }
                     75: 
                     76:        _SERVER = Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]);
                     77: 
                     78:        /* PATH_INFO and PATH_TRANSLATED should always be munged */
                     79: #if PHP_MAJOR_VERSION >= 6
                     80:        if (phar_find_key(_SERVER, "PATH_INFO", sizeof("PATH_INFO"), (void **) &stuff TSRMLS_CC)) {
                     81:                if (Z_TYPE_PP(stuff) == IS_UNICODE) {
                     82:                        is_unicode = 1;
                     83:                        zval_unicode_to_string(*stuff TSRMLS_CC);
                     84:                } else {
                     85:                        is_unicode = 0;
                     86:                }
                     87: #else
                     88:        if (SUCCESS == zend_hash_find(_SERVER, "PATH_INFO", sizeof("PATH_INFO"), (void **) &stuff)) {
                     89: #endif
                     90: 
                     91:                path_info = Z_STRVAL_PP(stuff);
                     92:                code = Z_STRLEN_PP(stuff);
                     93: 
                     94:                if (Z_STRLEN_PP(stuff) > entry_len && !memcmp(Z_STRVAL_PP(stuff), entry, entry_len)) {
                     95:                        ZVAL_STRINGL(*stuff, Z_STRVAL_PP(stuff) + entry_len, request_uri_len, 1);
                     96: 
                     97:                        MAKE_STD_ZVAL(temp);
                     98:                        ZVAL_STRINGL(temp, path_info, code, 0);
                     99: #if PHP_MAJOR_VERSION >= 6
                    100:                        if (is_unicode) {
                    101:                                zval_string_to_unicode(*stuff TSRMLS_CC);
                    102:                        }
                    103: #endif
                    104:                        zend_hash_update(_SERVER, "PHAR_PATH_INFO", sizeof("PHAR_PATH_INFO"), &temp, sizeof(zval **), NULL);
                    105:                }
                    106:        }
                    107: 
                    108: #if PHP_MAJOR_VERSION >= 6
                    109:        if (phar_find_key(_SERVER, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"), (void **) &stuff TSRMLS_CC)) {
                    110:                if (Z_TYPE_PP(stuff) == IS_UNICODE) {
                    111:                        is_unicode = 1;
                    112:                        zval_unicode_to_string(*stuff TSRMLS_CC);
                    113:                } else {
                    114:                        is_unicode = 0;
                    115:                }
                    116: #else
                    117:        if (SUCCESS == zend_hash_find(_SERVER, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED"), (void **) &stuff)) {
                    118: #endif
                    119: 
                    120:                path_info = Z_STRVAL_PP(stuff);
                    121:                code = Z_STRLEN_PP(stuff);
                    122:                Z_STRLEN_PP(stuff) = spprintf(&(Z_STRVAL_PP(stuff)), 4096, "phar://%s%s", fname, entry);
                    123: 
                    124:                MAKE_STD_ZVAL(temp);
                    125:                ZVAL_STRINGL(temp, path_info, code, 0);
                    126: #if PHP_MAJOR_VERSION >= 6
                    127:                if (is_unicode) {
                    128:                        zval_string_to_unicode(*stuff TSRMLS_CC);
                    129:                }
                    130: #endif
                    131:                zend_hash_update(_SERVER, "PHAR_PATH_TRANSLATED", sizeof("PHAR_PATH_TRANSLATED"), (void *) &temp, sizeof(zval **), NULL);
                    132:        }
                    133: 
                    134:        if (!PHAR_GLOBALS->phar_SERVER_mung_list) {
                    135:                return;
                    136:        }
                    137: 
                    138:        if (PHAR_GLOBALS->phar_SERVER_mung_list & PHAR_MUNG_REQUEST_URI) {
                    139: #if PHP_MAJOR_VERSION >= 6
                    140:                if (phar_find_key(_SERVER, "REQUEST_URI", sizeof("REQUEST_URI"), (void **) &stuff TSRMLS_CC)) {
                    141:                if (Z_TYPE_PP(stuff) == IS_UNICODE) {
                    142:                        is_unicode = 1;
                    143:                        zval_unicode_to_string(*stuff TSRMLS_CC);
                    144:                } else {
                    145:                        is_unicode = 0;
                    146:                }
                    147: #else
                    148:                if (SUCCESS == zend_hash_find(_SERVER, "REQUEST_URI", sizeof("REQUEST_URI"), (void **) &stuff)) {
                    149: #endif
                    150: 
                    151:                        path_info = Z_STRVAL_PP(stuff);
                    152:                        code = Z_STRLEN_PP(stuff);
                    153: 
                    154:                        if (Z_STRLEN_PP(stuff) > basename_len && !memcmp(Z_STRVAL_PP(stuff), basename, basename_len)) {
                    155:                                ZVAL_STRINGL(*stuff, Z_STRVAL_PP(stuff) + basename_len, Z_STRLEN_PP(stuff) - basename_len, 1);
                    156: 
                    157:                                MAKE_STD_ZVAL(temp);
                    158:                                ZVAL_STRINGL(temp, path_info, code, 0);
                    159: #if PHP_MAJOR_VERSION >= 6
                    160:                                if (is_unicode) {
                    161:                                        zval_string_to_unicode(*stuff TSRMLS_CC);
                    162:                                }
                    163: #endif
                    164:                                zend_hash_update(_SERVER, "PHAR_REQUEST_URI", sizeof("PHAR_REQUEST_URI"), (void *) &temp, sizeof(zval **), NULL);
                    165:                        }
                    166:                }
                    167:        }
                    168: 
                    169:        if (PHAR_GLOBALS->phar_SERVER_mung_list & PHAR_MUNG_PHP_SELF) {
                    170: #if PHP_MAJOR_VERSION >= 6
                    171:                if (phar_find_key(_SERVER, "PHP_SELF", sizeof("PHP_SELF"), (void **) &stuff TSRMLS_CC)) {
                    172:                if (Z_TYPE_PP(stuff) == IS_UNICODE) {
                    173:                        is_unicode = 1;
                    174:                        zval_unicode_to_string(*stuff TSRMLS_CC);
                    175:                } else {
                    176:                        is_unicode = 0;
                    177:                }
                    178: #else
                    179:                if (SUCCESS == zend_hash_find(_SERVER, "PHP_SELF", sizeof("PHP_SELF"), (void **) &stuff)) {
                    180: #endif
                    181: 
                    182:                        path_info = Z_STRVAL_PP(stuff);
                    183:                        code = Z_STRLEN_PP(stuff);
                    184: 
                    185:                        if (Z_STRLEN_PP(stuff) > basename_len && !memcmp(Z_STRVAL_PP(stuff), basename, basename_len)) {
                    186:                                ZVAL_STRINGL(*stuff, Z_STRVAL_PP(stuff) + basename_len, Z_STRLEN_PP(stuff) - basename_len, 1);
                    187: 
                    188:                                MAKE_STD_ZVAL(temp);
                    189:                                ZVAL_STRINGL(temp, path_info, code, 0);
                    190: #if PHP_MAJOR_VERSION >= 6
                    191:                                if (is_unicode) {
                    192:                                        zval_string_to_unicode(*stuff TSRMLS_CC);
                    193:                                }
                    194: #endif
                    195:                                zend_hash_update(_SERVER, "PHAR_PHP_SELF", sizeof("PHAR_PHP_SELF"), (void *) &temp, sizeof(zval **), NULL);
                    196:                        }
                    197:                }
                    198:        }
                    199: 
                    200:        if (PHAR_GLOBALS->phar_SERVER_mung_list & PHAR_MUNG_SCRIPT_NAME) {
                    201: #if PHP_MAJOR_VERSION >= 6
                    202:                if (phar_find_key(_SERVER, "SCRIPT_NAME", sizeof("SCRIPT_NAME"), (void **) &stuff TSRMLS_CC)) {
                    203:                if (Z_TYPE_PP(stuff) == IS_UNICODE) {
                    204:                        is_unicode = 1;
                    205:                        zval_unicode_to_string(*stuff TSRMLS_CC);
                    206:                } else {
                    207:                        is_unicode = 0;
                    208:                }
                    209: #else
                    210:                if (SUCCESS == zend_hash_find(_SERVER, "SCRIPT_NAME", sizeof("SCRIPT_NAME"), (void **) &stuff)) {
                    211: #endif
                    212: 
                    213:                        path_info = Z_STRVAL_PP(stuff);
                    214:                        code = Z_STRLEN_PP(stuff);
                    215:                        ZVAL_STRINGL(*stuff, entry, entry_len, 1);
                    216: 
                    217:                        MAKE_STD_ZVAL(temp);
                    218:                        ZVAL_STRINGL(temp, path_info, code, 0);
                    219: #if PHP_MAJOR_VERSION >= 6
                    220:                        if (is_unicode) {
                    221:                                zval_string_to_unicode(*stuff TSRMLS_CC);
                    222:                        }
                    223: #endif
                    224:                        zend_hash_update(_SERVER, "PHAR_SCRIPT_NAME", sizeof("PHAR_SCRIPT_NAME"), (void *) &temp, sizeof(zval **), NULL);
                    225:                }
                    226:        }
                    227: 
                    228:        if (PHAR_GLOBALS->phar_SERVER_mung_list & PHAR_MUNG_SCRIPT_FILENAME) {
                    229: #if PHP_MAJOR_VERSION >= 6
                    230:                if (phar_find_key(_SERVER, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &stuff TSRMLS_CC)) {
                    231:                if (Z_TYPE_PP(stuff) == IS_UNICODE) {
                    232:                        is_unicode = 1;
                    233:                        zval_unicode_to_string(*stuff TSRMLS_CC);
                    234:                } else {
                    235:                        is_unicode = 0;
                    236:                }
                    237: #else
                    238:                if (SUCCESS == zend_hash_find(_SERVER, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &stuff)) {
                    239: #endif
                    240: 
                    241:                        path_info = Z_STRVAL_PP(stuff);
                    242:                        code = Z_STRLEN_PP(stuff);
                    243:                        Z_STRLEN_PP(stuff) = spprintf(&(Z_STRVAL_PP(stuff)), 4096, "phar://%s%s", fname, entry);
                    244: 
                    245:                        MAKE_STD_ZVAL(temp);
                    246:                        ZVAL_STRINGL(temp, path_info, code, 0);
                    247: #if PHP_MAJOR_VERSION >= 6
                    248:                        if (is_unicode) {
                    249:                                zval_string_to_unicode(*stuff TSRMLS_CC);
                    250:                        }
                    251: #endif
                    252:                        zend_hash_update(_SERVER, "PHAR_SCRIPT_FILENAME", sizeof("PHAR_SCRIPT_FILENAME"), (void *) &temp, sizeof(zval **), NULL);
                    253:                }
                    254:        }
                    255: }
                    256: /* }}} */
                    257: 
                    258: static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char *mime_type, int code, char *entry, int entry_len, char *arch, char *basename, char *ru, int ru_len TSRMLS_DC) /* {{{ */
                    259: {
1.1.1.2 ! misho     260:        char *name = NULL, buf[8192];
        !           261:        const char *cwd;
1.1       misho     262:        zend_syntax_highlighter_ini syntax_highlighter_ini;
                    263:        sapi_header_line ctr = {0};
                    264:        size_t got;
                    265:        int dummy = 1, name_len;
                    266:        zend_file_handle file_handle;
                    267:        zend_op_array *new_op_array;
                    268:        zval *result = NULL;
                    269:        php_stream *fp;
                    270:        off_t position;
                    271: 
                    272:        switch (code) {
                    273:                case PHAR_MIME_PHPS:
                    274:                        efree(basename);
                    275:                        /* highlight source */
                    276:                        if (entry[0] == '/') {
                    277:                                name_len = spprintf(&name, 4096, "phar://%s%s", arch, entry);
                    278:                        } else {
                    279:                                name_len = spprintf(&name, 4096, "phar://%s/%s", arch, entry);
                    280:                        }
                    281:                        php_get_highlight_struct(&syntax_highlighter_ini);
                    282: 
                    283:                        highlight_file(name, &syntax_highlighter_ini TSRMLS_CC);
                    284: 
                    285:                        efree(name);
                    286: #ifdef PHP_WIN32
                    287:                        efree(arch);
                    288: #endif
                    289:                        zend_bailout();
                    290:                case PHAR_MIME_OTHER:
                    291:                        /* send headers, output file contents */
                    292:                        efree(basename);
                    293:                        ctr.line_len = spprintf(&(ctr.line), 0, "Content-type: %s", mime_type);
                    294:                        sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
                    295:                        efree(ctr.line);
                    296:                        ctr.line_len = spprintf(&(ctr.line), 0, "Content-length: %u", info->uncompressed_filesize);
                    297:                        sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
                    298:                        efree(ctr.line);
                    299: 
                    300:                        if (FAILURE == sapi_send_headers(TSRMLS_C)) {
                    301:                                zend_bailout();
                    302:                        }
                    303: 
                    304:                        /* prepare to output  */
                    305:                        fp = phar_get_efp(info, 1 TSRMLS_CC);
                    306: 
                    307:                        if (!fp) {
                    308:                                char *error;
                    309:                                if (!phar_open_jit(phar, info, &error TSRMLS_CC)) {
                    310:                                        if (error) {
                    311:                                                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                    312:                                                efree(error);
                    313:                                        }
                    314:                                        return -1;
                    315:                                }
                    316:                                fp = phar_get_efp(info, 1 TSRMLS_CC);
                    317:                        }
                    318:                        position = 0;
                    319:                        phar_seek_efp(info, 0, SEEK_SET, 0, 1 TSRMLS_CC);
                    320: 
                    321:                        do {
                    322:                                got = php_stream_read(fp, buf, MIN(8192, info->uncompressed_filesize - position));
                    323:                                if (got > 0) {
                    324:                                        PHPWRITE(buf, got);
                    325:                                        position += got;
                    326:                                        if (position == (off_t) info->uncompressed_filesize) {
                    327:                                                break;
                    328:                                        }
                    329:                                }
                    330:                        } while (1);
                    331: 
                    332:                        zend_bailout();
                    333:                case PHAR_MIME_PHP:
                    334:                        if (basename) {
                    335:                                phar_mung_server_vars(arch, entry, entry_len, basename, ru_len TSRMLS_CC);
                    336:                                efree(basename);
                    337:                        }
                    338: 
                    339:                        if (entry[0] == '/') {
                    340:                                name_len = spprintf(&name, 4096, "phar://%s%s", arch, entry);
                    341:                        } else {
                    342:                                name_len = spprintf(&name, 4096, "phar://%s/%s", arch, entry);
                    343:                        }
                    344: 
                    345:                        file_handle.type = ZEND_HANDLE_FILENAME;
                    346:                        file_handle.handle.fd = 0;
                    347:                        file_handle.filename = name;
                    348:                        file_handle.opened_path = NULL;
                    349:                        file_handle.free_filename = 0;
                    350: 
                    351:                        PHAR_G(cwd) = NULL;
                    352:                        PHAR_G(cwd_len) = 0;
                    353: 
                    354:                        if (zend_hash_add(&EG(included_files), name, name_len+1, (void *)&dummy, sizeof(int), NULL) == SUCCESS) {
                    355:                                if ((cwd = zend_memrchr(entry, '/', entry_len))) {
                    356:                                        PHAR_G(cwd_init) = 1;
                    357:                                        if (entry == cwd) {
                    358:                                                /* root directory */
                    359:                                                PHAR_G(cwd_len) = 0;
                    360:                                                PHAR_G(cwd) = NULL;
                    361:                                        } else if (entry[0] == '/') {
                    362:                                                PHAR_G(cwd_len) = cwd - (entry + 1);
                    363:                                                PHAR_G(cwd) = estrndup(entry + 1, PHAR_G(cwd_len));
                    364:                                        } else {
                    365:                                                PHAR_G(cwd_len) = cwd - entry;
                    366:                                                PHAR_G(cwd) = estrndup(entry, PHAR_G(cwd_len));
                    367:                                        }
                    368:                                }
                    369: 
                    370:                                new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
                    371: 
                    372:                                if (!new_op_array) {
                    373:                                        zend_hash_del(&EG(included_files), name, name_len+1);
                    374:                                }
                    375: 
                    376:                                zend_destroy_file_handle(&file_handle TSRMLS_CC);
                    377: 
                    378:                        } else {
                    379:                                efree(name);
                    380:                                new_op_array = NULL;
                    381:                        }
                    382: #ifdef PHP_WIN32
                    383:                        efree(arch);
                    384: #endif
                    385:                        if (new_op_array) {
                    386:                                EG(return_value_ptr_ptr) = &result;
                    387:                                EG(active_op_array) = new_op_array;
                    388: 
                    389:                                zend_try {
                    390:                                        zend_execute(new_op_array TSRMLS_CC);
                    391:                                        if (PHAR_G(cwd)) {
                    392:                                                efree(PHAR_G(cwd));
                    393:                                                PHAR_G(cwd) = NULL;
                    394:                                                PHAR_G(cwd_len) = 0;
                    395:                                        }
                    396: 
                    397:                                        PHAR_G(cwd_init) = 0;
                    398:                                        efree(name);
                    399:                                        destroy_op_array(new_op_array TSRMLS_CC);
                    400:                                        efree(new_op_array);
                    401: 
                    402: 
                    403:                                        if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) {
                    404:                                                zval_ptr_dtor(EG(return_value_ptr_ptr));
                    405:                                        }
                    406:                                } zend_catch {
                    407:                                        if (PHAR_G(cwd)) {
                    408:                                                efree(PHAR_G(cwd));
                    409:                                                PHAR_G(cwd) = NULL;
                    410:                                                PHAR_G(cwd_len) = 0;
                    411:                                        }
                    412: 
                    413:                                        PHAR_G(cwd_init) = 0;
                    414:                                        efree(name);
                    415:                                } zend_end_try();
                    416: 
                    417:                                zend_bailout();
                    418:                        }
                    419: 
                    420:                        return PHAR_MIME_PHP;
                    421:        }
                    422:        return -1;
                    423: }
                    424: /* }}} */
                    425: 
                    426: static void phar_do_403(char *entry, int entry_len TSRMLS_DC) /* {{{ */
                    427: {
                    428:        sapi_header_line ctr = {0};
                    429: 
                    430:        ctr.response_code = 403;
1.1.1.2 ! misho     431:        ctr.line_len = sizeof("HTTP/1.0 403 Access Denied")-1;
1.1       misho     432:        ctr.line = "HTTP/1.0 403 Access Denied";
                    433:        sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
                    434:        sapi_send_headers(TSRMLS_C);
                    435:        PHPWRITE("<html>\n <head>\n  <title>Access Denied</title>\n </head>\n <body>\n  <h1>403 - File ", sizeof("<html>\n <head>\n  <title>Access Denied</title>\n </head>\n <body>\n  <h1>403 - File ") - 1);
                    436:        PHPWRITE(entry, entry_len);
                    437:        PHPWRITE(" Access Denied</h1>\n </body>\n</html>", sizeof(" Access Denied</h1>\n </body>\n</html>") - 1);
                    438: }
                    439: /* }}} */
                    440: 
                    441: static void phar_do_404(phar_archive_data *phar, char *fname, int fname_len, char *f404, int f404_len, char *entry, int entry_len TSRMLS_DC) /* {{{ */
                    442: {
                    443:        sapi_header_line ctr = {0};
                    444:        phar_entry_info *info;
                    445: 
                    446:        if (phar && f404_len) {
                    447:                info = phar_get_entry_info(phar, f404, f404_len, NULL, 1 TSRMLS_CC);
                    448: 
                    449:                if (info) {
                    450:                        phar_file_action(phar, info, "text/html", PHAR_MIME_PHP, f404, f404_len, fname, NULL, NULL, 0 TSRMLS_CC);
                    451:                        return;
                    452:                }
                    453:        }
                    454: 
                    455:        ctr.response_code = 404;
1.1.1.2 ! misho     456:        ctr.line_len = sizeof("HTTP/1.0 404 Not Found")-1;
1.1       misho     457:        ctr.line = "HTTP/1.0 404 Not Found";
                    458:        sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
                    459:        sapi_send_headers(TSRMLS_C);
                    460:        PHPWRITE("<html>\n <head>\n  <title>File Not Found</title>\n </head>\n <body>\n  <h1>404 - File ", sizeof("<html>\n <head>\n  <title>File Not Found</title>\n </head>\n <body>\n  <h1>404 - File ") - 1);
                    461:        PHPWRITE(entry, entry_len);
                    462:        PHPWRITE(" Not Found</h1>\n </body>\n</html>",  sizeof(" Not Found</h1>\n </body>\n</html>") - 1);
                    463: }
                    464: /* }}} */
                    465: 
                    466: /* post-process REQUEST_URI and retrieve the actual request URI.  This is for
                    467:    cases like http://localhost/blah.phar/path/to/file.php/extra/stuff
                    468:    which calls "blah.phar" file "path/to/file.php" with PATH_INFO "/extra/stuff" */
                    469: static void phar_postprocess_ru_web(char *fname, int fname_len, char **entry, int *entry_len, char **ru, int *ru_len TSRMLS_DC) /* {{{ */
                    470: {
                    471:        char *e = *entry + 1, *u = NULL, *u1 = NULL, *saveu = NULL;
                    472:        int e_len = *entry_len - 1, u_len = 0;
                    473:        phar_archive_data **pphar = NULL;
                    474: 
                    475:        /* we already know we can retrieve the phar if we reach here */
                    476:        zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, (void **) &pphar);
                    477: 
                    478:        if (!pphar && PHAR_G(manifest_cached)) {
                    479:                zend_hash_find(&cached_phars, fname, fname_len, (void **) &pphar);
                    480:        }
                    481: 
                    482:        do {
                    483:                if (zend_hash_exists(&((*pphar)->manifest), e, e_len)) {
                    484:                        if (u) {
                    485:                                u[0] = '/';
                    486:                                *ru = estrndup(u, u_len+1);
                    487:                                ++u_len;
                    488:                                u[0] = '\0';
                    489:                        } else {
                    490:                                *ru = NULL;
                    491:                        }
                    492:                        *ru_len = u_len;
                    493:                        *entry_len = e_len + 1;
                    494:                        return;
                    495:                }
                    496: 
                    497:                if (u) {
                    498:                        u1 = strrchr(e, '/');
                    499:                        u[0] = '/';
                    500:                        saveu = u;
                    501:                        e_len += u_len + 1;
                    502:                        u = u1;
                    503:                        if (!u) {
                    504:                                return;
                    505:                        }
                    506:                } else {
                    507:                        u = strrchr(e, '/');
                    508:                        if (!u) {
                    509:                                if (saveu) {
                    510:                                        saveu[0] = '/';
                    511:                                }
                    512:                                return;
                    513:                        }
                    514:                }
                    515: 
                    516:                u[0] = '\0';
                    517:                u_len = strlen(u + 1);
                    518:                e_len -= u_len + 1;
                    519: 
                    520:                if (e_len < 0) {
                    521:                        if (saveu) {
                    522:                                saveu[0] = '/';
                    523:                        }
                    524:                        return;
                    525:                }
                    526:        } while (1);
                    527: }
                    528: /* }}} */
                    529: 
                    530: /* {{{ proto void Phar::running([bool retphar = true])
                    531:  * return the name of the currently running phar archive.  If the optional parameter
                    532:  * is set to true, return the phar:// URL to the currently running phar
                    533:  */
                    534: PHP_METHOD(Phar, running)
                    535: {
                    536:        char *fname, *arch, *entry;
                    537:        int fname_len, arch_len, entry_len;
                    538:        zend_bool retphar = 1;
                    539: 
                    540:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &retphar) == FAILURE) {
                    541:                return;
                    542:        }
                    543: 
1.1.1.2 ! misho     544:        fname = (char*)zend_get_executed_filename(TSRMLS_C);
1.1       misho     545:        fname_len = strlen(fname);
                    546: 
                    547:        if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
                    548:                efree(entry);
                    549:                if (retphar) {
                    550:                        RETVAL_STRINGL(fname, arch_len + 7, 1);
                    551:                        efree(arch);
                    552:                        return;
                    553:                } else {
                    554:                        RETURN_STRINGL(arch, arch_len, 0);
                    555:                }
                    556:        }
                    557: 
                    558:        RETURN_STRINGL("", 0, 1);
                    559: }
                    560: /* }}} */
                    561: 
                    562: /* {{{ proto void Phar::mount(string pharpath, string externalfile)
                    563:  * mount an external file or path to a location within the phar.  This maps
                    564:  * an external file or directory to a location within the phar archive, allowing
                    565:  * reference to an external location as if it were within the phar archive.  This
                    566:  * is useful for writable temp files like databases
                    567:  */
                    568: PHP_METHOD(Phar, mount)
                    569: {
                    570:        char *fname, *arch = NULL, *entry = NULL, *path, *actual;
                    571:        int fname_len, arch_len, entry_len, path_len, actual_len;
                    572:        phar_archive_data **pphar;
                    573: 
                    574:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &path, &path_len, &actual, &actual_len) == FAILURE) {
                    575:                return;
                    576:        }
                    577: 
1.1.1.2 ! misho     578:        fname = (char*)zend_get_executed_filename(TSRMLS_C);
1.1       misho     579:        fname_len = strlen(fname);
                    580: 
                    581: #ifdef PHP_WIN32
                    582:        phar_unixify_path_separators(fname, fname_len);
                    583: #endif
                    584: 
                    585:        if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
                    586:                efree(entry);
                    587:                entry = NULL;
                    588: 
                    589:                if (path_len > 7 && !memcmp(path, "phar://", 7)) {
                    590:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Can only mount internal paths within a phar archive, use a relative path instead of \"%s\"", path);
                    591:                        efree(arch);
                    592:                        return;
                    593:                }
                    594: carry_on2:
                    595:                if (SUCCESS != zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **)&pphar)) {
                    596:                        if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_find(&cached_phars, arch, arch_len, (void **)&pphar)) {
                    597:                                if (SUCCESS == phar_copy_on_write(pphar TSRMLS_CC)) {
                    598:                                        goto carry_on;
                    599:                                }
                    600:                        }
                    601: 
                    602:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s is not a phar archive, cannot mount", arch);
                    603: 
                    604:                        if (arch) {
                    605:                                efree(arch);
                    606:                        }
                    607:                        return;
                    608:                }
                    609: carry_on:
                    610:                if (SUCCESS != phar_mount_entry(*pphar, actual, actual_len, path, path_len TSRMLS_CC)) {
                    611:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Mounting of %s to %s within phar %s failed", path, actual, arch);
                    612:                        if (path && path == entry) {
                    613:                                efree(entry);
                    614:                        }
                    615: 
                    616:                        if (arch) {
                    617:                                efree(arch);
                    618:                        }
                    619: 
                    620:                        return;
                    621:                }
                    622: 
                    623:                if (entry && path && path == entry) {
                    624:                        efree(entry);
                    625:                }
                    626: 
                    627:                if (arch) {
                    628:                        efree(arch);
                    629:                }
                    630: 
                    631:                return;
                    632:        } else if (PHAR_GLOBALS->phar_fname_map.arBuckets && SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), fname, fname_len, (void **)&pphar)) {
                    633:                goto carry_on;
                    634:        } else if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_find(&cached_phars, fname, fname_len, (void **)&pphar)) {
                    635:                if (SUCCESS == phar_copy_on_write(pphar TSRMLS_CC)) {
                    636:                        goto carry_on;
                    637:                }
                    638: 
                    639:                goto carry_on;
                    640:        } else if (SUCCESS == phar_split_fname(path, path_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
                    641:                path = entry;
                    642:                path_len = entry_len;
                    643:                goto carry_on2;
                    644:        }
                    645: 
                    646:        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Mounting of %s to %s failed", path, actual);
                    647: }
                    648: /* }}} */
                    649: 
                    650: /* {{{ proto void Phar::webPhar([string alias, [string index, [string f404, [array mimetypes, [callback rewrites]]]]])
                    651:  * mapPhar for web-based phars. Reads the currently executed file (a phar)
                    652:  * and registers its manifest. When executed in the CLI or CGI command-line sapi,
                    653:  * this works exactly like mapPhar().  When executed by a web-based sapi, this
                    654:  * reads $_SERVER['REQUEST_URI'] (the actual original value) and parses out the
                    655:  * intended internal file.
                    656:  */
                    657: PHP_METHOD(Phar, webPhar)
                    658: {
                    659:        zval *mimeoverride = NULL, *rewrite = NULL;
                    660:        char *alias = NULL, *error, *index_php = NULL, *f404 = NULL, *ru = NULL;
                    661:        int alias_len = 0, ret, f404_len = 0, free_pathinfo = 0, ru_len = 0;
1.1.1.2 ! misho     662:        char *fname, *path_info, *mime_type = NULL, *entry, *pt;
        !           663:        const char *basename;
1.1       misho     664:        int fname_len, entry_len, code, index_php_len = 0, not_cgi;
                    665:        phar_archive_data *phar = NULL;
                    666:        phar_entry_info *info = NULL;
                    667: 
                    668:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!saz", &alias, &alias_len, &index_php, &index_php_len, &f404, &f404_len, &mimeoverride, &rewrite) == FAILURE) {
                    669:                return;
                    670:        }
                    671: 
                    672:        phar_request_initialize(TSRMLS_C);
1.1.1.2 ! misho     673:        fname = (char*)zend_get_executed_filename(TSRMLS_C);
1.1       misho     674:        fname_len = strlen(fname);
                    675: 
                    676:        if (phar_open_executed_filename(alias, alias_len, &error TSRMLS_CC) != SUCCESS) {
                    677:                if (error) {
                    678:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                    679:                        efree(error);
                    680:                }
                    681:                return;
                    682:        }
                    683: 
                    684:        /* retrieve requested file within phar */
                    685:        if (!(SG(request_info).request_method && SG(request_info).request_uri && (!strcmp(SG(request_info).request_method, "GET") || !strcmp(SG(request_info).request_method, "POST")))) {
                    686:                return;
                    687:        }
                    688: 
                    689: #ifdef PHP_WIN32
                    690:        fname = estrndup(fname, fname_len);
                    691:        phar_unixify_path_separators(fname, fname_len);
                    692: #endif
                    693:        basename = zend_memrchr(fname, '/', fname_len);
                    694: 
                    695:        if (!basename) {
                    696:                basename = fname;
                    697:        } else {
                    698:                ++basename;
                    699:        }
                    700: 
                    701:        if ((strlen(sapi_module.name) == sizeof("cgi-fcgi")-1 && !strncmp(sapi_module.name, "cgi-fcgi", sizeof("cgi-fcgi")-1))
                    702:                || (strlen(sapi_module.name) == sizeof("cgi")-1 && !strncmp(sapi_module.name, "cgi", sizeof("cgi")-1))) {
                    703: 
                    704:                if (PG(http_globals)[TRACK_VARS_SERVER]) {
                    705:                        HashTable *_server = Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]);
                    706:                        zval **z_script_name, **z_path_info;
                    707: 
                    708:                        if (SUCCESS != zend_hash_find(_server, "SCRIPT_NAME", sizeof("SCRIPT_NAME"), (void**)&z_script_name) ||
                    709:                                IS_STRING != Z_TYPE_PP(z_script_name) ||
                    710:                                !strstr(Z_STRVAL_PP(z_script_name), basename)) {
                    711:                                return;
                    712:                        }
                    713: 
                    714:                        if (SUCCESS == zend_hash_find(_server, "PATH_INFO", sizeof("PATH_INFO"), (void**)&z_path_info) &&
                    715:                                IS_STRING == Z_TYPE_PP(z_path_info)) {
                    716:                                entry_len = Z_STRLEN_PP(z_path_info);
                    717:                                entry = estrndup(Z_STRVAL_PP(z_path_info), entry_len);
                    718:                                path_info = emalloc(Z_STRLEN_PP(z_script_name) + entry_len + 1);
                    719:                                memcpy(path_info, Z_STRVAL_PP(z_script_name), Z_STRLEN_PP(z_script_name));
                    720:                                memcpy(path_info + Z_STRLEN_PP(z_script_name), entry, entry_len + 1);
                    721:                                free_pathinfo = 1;
                    722:                        } else {
                    723:                                entry_len = 0;
                    724:                                entry = estrndup("", 0);
                    725:                                path_info = Z_STRVAL_PP(z_script_name);
                    726:                        }
                    727: 
                    728:                        pt = estrndup(Z_STRVAL_PP(z_script_name), Z_STRLEN_PP(z_script_name));
                    729: 
                    730:                } else {
                    731:                        char *testit;
                    732: 
                    733:                        testit = sapi_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1 TSRMLS_CC);
                    734:                        if (!(pt = strstr(testit, basename))) {
                    735:                                efree(testit);
                    736:                                return;
                    737:                        }
                    738: 
                    739:                        path_info = sapi_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC);
                    740: 
                    741:                        if (path_info) {
                    742:                                entry = path_info;
                    743:                                entry_len = strlen(entry);
                    744:                                spprintf(&path_info, 0, "%s%s", testit, path_info);
                    745:                                free_pathinfo = 1;
                    746:                        } else {
                    747:                                path_info = testit;
                    748:                                free_pathinfo = 1;
                    749:                                entry = estrndup("", 0);
                    750:                                entry_len = 0;
                    751:                        }
                    752: 
                    753:                        pt = estrndup(testit, (pt - testit) + (fname_len - (basename - fname)));
                    754:                }
                    755:                not_cgi = 0;
                    756:        } else {
                    757:                path_info = SG(request_info).request_uri;
                    758: 
                    759:                if (!(pt = strstr(path_info, basename))) {
                    760:                        /* this can happen with rewrite rules - and we have no idea what to do then, so return */
                    761:                        return;
                    762:                }
                    763: 
                    764:                entry_len = strlen(path_info);
                    765:                entry_len -= (pt - path_info) + (fname_len - (basename - fname));
                    766:                entry = estrndup(pt + (fname_len - (basename - fname)), entry_len);
                    767: 
                    768:                pt = estrndup(path_info, (pt - path_info) + (fname_len - (basename - fname)));
                    769:                not_cgi = 1;
                    770:        }
                    771: 
                    772:        if (rewrite) {
                    773:                zend_fcall_info fci;
                    774:                zend_fcall_info_cache fcc;
                    775:                zval *params, *retval_ptr, **zp[1];
                    776: 
                    777:                MAKE_STD_ZVAL(params);
                    778:                ZVAL_STRINGL(params, entry, entry_len, 1);
                    779:                zp[0] = &params;
                    780: 
                    781: #if PHP_VERSION_ID < 50300
                    782:                if (FAILURE == zend_fcall_info_init(rewrite, &fci, &fcc TSRMLS_CC)) {
                    783: #else
                    784:                if (FAILURE == zend_fcall_info_init(rewrite, 0, &fci, &fcc, NULL, NULL TSRMLS_CC)) {
                    785: #endif
                    786:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar error: invalid rewrite callback");
                    787: 
                    788:                        if (free_pathinfo) {
                    789:                                efree(path_info);
                    790:                        }
                    791: 
                    792:                        return;
                    793:                }
                    794: 
                    795:                fci.param_count = 1;
                    796:                fci.params = zp;
                    797: #if PHP_VERSION_ID < 50300
                    798:                ++(params->refcount);
                    799: #else
                    800:                Z_ADDREF_P(params);
                    801: #endif
                    802:                fci.retval_ptr_ptr = &retval_ptr;
                    803: 
                    804:                if (FAILURE == zend_call_function(&fci, &fcc TSRMLS_CC)) {
                    805:                        if (!EG(exception)) {
                    806:                                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar error: failed to call rewrite callback");
                    807:                        }
                    808: 
                    809:                        if (free_pathinfo) {
                    810:                                efree(path_info);
                    811:                        }
                    812: 
                    813:                        return;
                    814:                }
                    815: 
                    816:                if (!fci.retval_ptr_ptr || !retval_ptr) {
                    817:                        if (free_pathinfo) {
                    818:                                efree(path_info);
                    819:                        }
                    820:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar error: rewrite callback must return a string or false");
                    821:                        return;
                    822:                }
                    823: 
                    824:                switch (Z_TYPE_P(retval_ptr)) {
                    825: #if PHP_VERSION_ID >= 60000
                    826:                        case IS_UNICODE:
                    827:                                zval_unicode_to_string(retval_ptr TSRMLS_CC);
                    828:                                /* break intentionally omitted */
                    829: #endif
                    830:                        case IS_STRING:
                    831:                                efree(entry);
                    832: 
                    833:                                if (fci.retval_ptr_ptr != &retval_ptr) {
                    834:                                        entry = estrndup(Z_STRVAL_PP(fci.retval_ptr_ptr), Z_STRLEN_PP(fci.retval_ptr_ptr));
                    835:                                        entry_len = Z_STRLEN_PP(fci.retval_ptr_ptr);
                    836:                                } else {
                    837:                                        entry = Z_STRVAL_P(retval_ptr);
                    838:                                        entry_len = Z_STRLEN_P(retval_ptr);
                    839:                                }
                    840: 
                    841:                                break;
                    842:                        case IS_BOOL:
                    843:                                phar_do_403(entry, entry_len TSRMLS_CC);
                    844: 
                    845:                                if (free_pathinfo) {
                    846:                                        efree(path_info);
                    847:                                }
                    848: 
                    849:                                zend_bailout();
                    850:                                return;
                    851:                        default:
                    852:                                efree(retval_ptr);
                    853: 
                    854:                                if (free_pathinfo) {
                    855:                                        efree(path_info);
                    856:                                }
                    857: 
                    858:                                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar error: rewrite callback must return a string or false");
                    859:                                return;
                    860:                }
                    861:        }
                    862: 
                    863:        if (entry_len) {
                    864:                phar_postprocess_ru_web(fname, fname_len, &entry, &entry_len, &ru, &ru_len TSRMLS_CC);
                    865:        }
                    866: 
                    867:        if (!entry_len || (entry_len == 1 && entry[0] == '/')) {
                    868:                efree(entry);
                    869:                /* direct request */
                    870:                if (index_php_len) {
                    871:                        entry = index_php;
                    872:                        entry_len = index_php_len;
                    873:                        if (entry[0] != '/') {
                    874:                                spprintf(&entry, 0, "/%s", index_php);
                    875:                                ++entry_len;
                    876:                        }
                    877:                } else {
                    878:                        /* assume "index.php" is starting point */
                    879:                        entry = estrndup("/index.php", sizeof("/index.php"));
                    880:                        entry_len = sizeof("/index.php")-1;
                    881:                }
                    882: 
                    883:                if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL TSRMLS_CC) ||
                    884:                        (info = phar_get_entry_info(phar, entry, entry_len, NULL, 0 TSRMLS_CC)) == NULL) {
                    885:                        phar_do_404(phar, fname, fname_len, f404, f404_len, entry, entry_len TSRMLS_CC);
                    886: 
                    887:                        if (free_pathinfo) {
                    888:                                efree(path_info);
                    889:                        }
                    890: 
                    891:                        zend_bailout();
                    892:                } else {
                    893:                        char *tmp = NULL, sa = '\0';
                    894:                        sapi_header_line ctr = {0};
                    895:                        ctr.response_code = 301;
1.1.1.2 ! misho     896:                        ctr.line_len = sizeof("HTTP/1.1 301 Moved Permanently")-1;
1.1       misho     897:                        ctr.line = "HTTP/1.1 301 Moved Permanently";
                    898:                        sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
                    899: 
                    900:                        if (not_cgi) {
                    901:                                tmp = strstr(path_info, basename) + fname_len;
                    902:                                sa = *tmp;
                    903:                                *tmp = '\0';
                    904:                        }
                    905: 
                    906:                        ctr.response_code = 0;
                    907: 
                    908:                        if (path_info[strlen(path_info)-1] == '/') {
                    909:                                ctr.line_len = spprintf(&(ctr.line), 4096, "Location: %s%s", path_info, entry + 1);
                    910:                        } else {
                    911:                                ctr.line_len = spprintf(&(ctr.line), 4096, "Location: %s%s", path_info, entry);
                    912:                        }
                    913: 
                    914:                        if (not_cgi) {
                    915:                                *tmp = sa;
                    916:                        }
                    917: 
                    918:                        if (free_pathinfo) {
                    919:                                efree(path_info);
                    920:                        }
                    921: 
                    922:                        sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
                    923:                        sapi_send_headers(TSRMLS_C);
                    924:                        efree(ctr.line);
                    925:                        zend_bailout();
                    926:                }
                    927:        }
                    928: 
                    929:        if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL TSRMLS_CC) ||
                    930:                (info = phar_get_entry_info(phar, entry, entry_len, NULL, 0 TSRMLS_CC)) == NULL) {
                    931:                phar_do_404(phar, fname, fname_len, f404, f404_len, entry, entry_len TSRMLS_CC);
                    932: #ifdef PHP_WIN32
                    933:                efree(fname);
                    934: #endif
                    935:                zend_bailout();
                    936:        }
                    937: 
                    938:        if (mimeoverride && zend_hash_num_elements(Z_ARRVAL_P(mimeoverride))) {
1.1.1.2 ! misho     939:                const char *ext = zend_memrchr(entry, '.', entry_len);
1.1       misho     940:                zval **val;
                    941: 
                    942:                if (ext) {
                    943:                        ++ext;
                    944: 
                    945: #if PHP_MAJOR_VERSION >= 6
                    946:                        if (phar_find_key(Z_ARRVAL_P(mimeoverride), ext, strlen(ext)+1, (void **) &val TSRMLS_CC)) {
                    947: #else
                    948:                        if (SUCCESS == zend_hash_find(Z_ARRVAL_P(mimeoverride), ext, strlen(ext)+1, (void **) &val)) {
                    949: #endif
                    950:                                switch (Z_TYPE_PP(val)) {
                    951:                                        case IS_LONG:
                    952:                                                if (Z_LVAL_PP(val) == PHAR_MIME_PHP || Z_LVAL_PP(val) == PHAR_MIME_PHPS) {
                    953:                                                        mime_type = "";
                    954:                                                        code = Z_LVAL_PP(val);
                    955:                                                } else {
                    956:                                                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Unknown mime type specifier used, only Phar::PHP, Phar::PHPS and a mime type string are allowed");
                    957: #ifdef PHP_WIN32
                    958:                                                        efree(fname);
                    959: #endif
                    960:                                                        RETURN_FALSE;
                    961:                                                }
                    962:                                                break;
                    963: #if PHP_MAJOR_VERSION >= 6
                    964:                                        case IS_UNICODE:
                    965:                                                zval_unicode_to_string(*(val) TSRMLS_CC);
                    966:                                                /* break intentionally omitted */
                    967: #endif
                    968:                                        case IS_STRING:
                    969:                                                mime_type = Z_STRVAL_PP(val);
                    970:                                                code = PHAR_MIME_OTHER;
                    971:                                                break;
                    972:                                        default:
                    973:                                                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Unknown mime type specifier used (not a string or int), only Phar::PHP, Phar::PHPS and a mime type string are allowed");
                    974: #ifdef PHP_WIN32
                    975:                                                efree(fname);
                    976: #endif
                    977:                                                RETURN_FALSE;
                    978:                                }
                    979:                        }
                    980:                }
                    981:        }
                    982: 
                    983:        if (!mime_type) {
                    984:                code = phar_file_type(&PHAR_G(mime_types), entry, &mime_type TSRMLS_CC);
                    985:        }
                    986:        ret = phar_file_action(phar, info, mime_type, code, entry, entry_len, fname, pt, ru, ru_len TSRMLS_CC);
                    987: }
                    988: /* }}} */
                    989: 
                    990: /* {{{ proto void Phar::mungServer(array munglist)
                    991:  * Defines a list of up to 4 $_SERVER variables that should be modified for execution
                    992:  * to mask the presence of the phar archive.  This should be used in conjunction with
                    993:  * Phar::webPhar(), and has no effect otherwise
                    994:  * SCRIPT_NAME, PHP_SELF, REQUEST_URI and SCRIPT_FILENAME
                    995:  */
                    996: PHP_METHOD(Phar, mungServer)
                    997: {
                    998:        zval *mungvalues;
                    999: 
                   1000:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &mungvalues) == FAILURE) {
                   1001:                return;
                   1002:        }
                   1003: 
                   1004:        if (!zend_hash_num_elements(Z_ARRVAL_P(mungvalues))) {
                   1005:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "No values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
                   1006:                return;
                   1007:        }
                   1008: 
                   1009:        if (zend_hash_num_elements(Z_ARRVAL_P(mungvalues)) > 4) {
                   1010:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Too many values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
                   1011:                return;
                   1012:        }
                   1013: 
                   1014:        phar_request_initialize(TSRMLS_C);
                   1015: 
                   1016:        for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(mungvalues)); SUCCESS == zend_hash_has_more_elements(Z_ARRVAL_P(mungvalues)); zend_hash_move_forward(Z_ARRVAL_P(mungvalues))) {
                   1017:                zval **data = NULL;
                   1018: #if PHP_MAJOR_VERSION >= 6
                   1019:                zval *unicopy = NULL;
                   1020: #endif
                   1021: 
                   1022:                if (SUCCESS != zend_hash_get_current_data(Z_ARRVAL_P(mungvalues), (void **) &data)) {
                   1023:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "unable to retrieve array value in Phar::mungServer()");
                   1024:                        return;
                   1025:                }
                   1026: 
                   1027: #if PHP_MAJOR_VERSION >= 6
                   1028:                if (Z_TYPE_PP(data) == IS_UNICODE) {
                   1029:                        MAKE_STD_ZVAL(unicopy);
                   1030:                        *unicopy = **data;
                   1031:                        zval_copy_ctor(unicopy);
                   1032:                        INIT_PZVAL(unicopy);
                   1033:                        zval_unicode_to_string(unicopy TSRMLS_CC);
                   1034:                        data = &unicopy;
                   1035:                }
                   1036: #endif
                   1037: 
                   1038:                if (Z_TYPE_PP(data) != IS_STRING) {
                   1039:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Non-string value passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
                   1040:                        return;
                   1041:                }
                   1042: 
                   1043:                if (Z_STRLEN_PP(data) == sizeof("PHP_SELF")-1 && !strncmp(Z_STRVAL_PP(data), "PHP_SELF", sizeof("PHP_SELF")-1)) {
                   1044:                        PHAR_GLOBALS->phar_SERVER_mung_list |= PHAR_MUNG_PHP_SELF;
                   1045:                }
                   1046: 
                   1047:                if (Z_STRLEN_PP(data) == sizeof("REQUEST_URI")-1) {
                   1048:                        if (!strncmp(Z_STRVAL_PP(data), "REQUEST_URI", sizeof("REQUEST_URI")-1)) {
                   1049:                                PHAR_GLOBALS->phar_SERVER_mung_list |= PHAR_MUNG_REQUEST_URI;
                   1050:                        }
                   1051:                        if (!strncmp(Z_STRVAL_PP(data), "SCRIPT_NAME", sizeof("SCRIPT_NAME")-1)) {
                   1052:                                PHAR_GLOBALS->phar_SERVER_mung_list |= PHAR_MUNG_SCRIPT_NAME;
                   1053:                        }
                   1054:                }
                   1055: 
                   1056:                if (Z_STRLEN_PP(data) == sizeof("SCRIPT_FILENAME")-1 && !strncmp(Z_STRVAL_PP(data), "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1)) {
                   1057:                        PHAR_GLOBALS->phar_SERVER_mung_list |= PHAR_MUNG_SCRIPT_FILENAME;
                   1058:                }
                   1059: #if PHP_MAJOR_VERSION >= 6
                   1060:                if (unicopy) {
                   1061:                        zval_ptr_dtor(&unicopy);
                   1062:                }
                   1063: #endif
                   1064:        }
                   1065: }
                   1066: /* }}} */
                   1067: 
                   1068: /* {{{ proto void Phar::interceptFileFuncs()
                   1069:  * instructs phar to intercept fopen, file_get_contents, opendir, and all of the stat-related functions
                   1070:  * and return stat on files within the phar for relative paths
                   1071:  *
                   1072:  * Once called, this cannot be reversed, and continue until the end of the request.
                   1073:  *
                   1074:  * This allows legacy scripts to be pharred unmodified
                   1075:  */
                   1076: PHP_METHOD(Phar, interceptFileFuncs)
                   1077: {
                   1078:        if (zend_parse_parameters_none() == FAILURE) {
                   1079:                return;
                   1080:        }
                   1081:        phar_intercept_functions(TSRMLS_C);
                   1082: }
                   1083: /* }}} */
                   1084: 
                   1085: /* {{{ proto array Phar::createDefaultStub([string indexfile[, string webindexfile]])
                   1086:  * Return a stub that can be used to run a phar-based archive without the phar extension
                   1087:  * indexfile is the CLI startup filename, which defaults to "index.php", webindexfile
                   1088:  * is the web startup filename, and also defaults to "index.php"
                   1089:  */
                   1090: PHP_METHOD(Phar, createDefaultStub)
                   1091: {
                   1092:        char *index = NULL, *webindex = NULL, *stub, *error;
                   1093:        int index_len = 0, webindex_len = 0;
                   1094:        size_t stub_len;
                   1095: 
                   1096:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &index, &index_len, &webindex, &webindex_len) == FAILURE) {
                   1097:                return;
                   1098:        }
                   1099: 
                   1100:        stub = phar_create_default_stub(index, webindex, &stub_len, &error TSRMLS_CC);
                   1101: 
                   1102:        if (error) {
                   1103:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   1104:                efree(error);
                   1105:                return;
                   1106:        }
                   1107:        RETURN_STRINGL(stub, stub_len, 0);
                   1108: }
                   1109: /* }}} */
                   1110: 
                   1111: /* {{{ proto mixed Phar::mapPhar([string alias, [int dataoffset]])
                   1112:  * Reads the currently executed file (a phar) and registers its manifest */
                   1113: PHP_METHOD(Phar, mapPhar)
                   1114: {
                   1115:        char *alias = NULL, *error;
                   1116:        int alias_len = 0;
                   1117:        long dataoffset = 0;
                   1118: 
                   1119:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!l", &alias, &alias_len, &dataoffset) == FAILURE) {
                   1120:                return;
                   1121:        }
                   1122: 
                   1123:        phar_request_initialize(TSRMLS_C);
                   1124: 
                   1125:        RETVAL_BOOL(phar_open_executed_filename(alias, alias_len, &error TSRMLS_CC) == SUCCESS);
                   1126: 
                   1127:        if (error) {
                   1128:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   1129:                efree(error);
                   1130:        }
                   1131: } /* }}} */
                   1132: 
                   1133: /* {{{ proto mixed Phar::loadPhar(string filename [, string alias])
                   1134:  * Loads any phar archive with an alias */
                   1135: PHP_METHOD(Phar, loadPhar)
                   1136: {
                   1137:        char *fname, *alias = NULL, *error;
                   1138:        int fname_len, alias_len = 0;
                   1139: 
                   1140:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &fname, &fname_len, &alias, &alias_len) == FAILURE) {
                   1141:                return;
                   1142:        }
                   1143: 
                   1144:        phar_request_initialize(TSRMLS_C);
                   1145: 
                   1146:        RETVAL_BOOL(phar_open_from_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL, &error TSRMLS_CC) == SUCCESS);
                   1147: 
                   1148:        if (error) {
                   1149:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   1150:                efree(error);
                   1151:        }
                   1152: } /* }}} */
                   1153: 
                   1154: /* {{{ proto string Phar::apiVersion()
                   1155:  * Returns the api version */
                   1156: PHP_METHOD(Phar, apiVersion)
                   1157: {
                   1158:        if (zend_parse_parameters_none() == FAILURE) {
                   1159:                return;
                   1160:        }
                   1161:        RETURN_STRINGL(PHP_PHAR_API_VERSION, sizeof(PHP_PHAR_API_VERSION)-1, 1);
                   1162: }
                   1163: /* }}}*/
                   1164: 
                   1165: /* {{{ proto bool Phar::canCompress([int method])
                   1166:  * Returns whether phar extension supports compression using zlib/bzip2 */
                   1167: PHP_METHOD(Phar, canCompress)
                   1168: {
                   1169:        long method = 0;
                   1170: 
                   1171:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &method) == FAILURE) {
                   1172:                return;
                   1173:        }
                   1174: 
                   1175:        phar_request_initialize(TSRMLS_C);
                   1176:        switch (method) {
                   1177:        case PHAR_ENT_COMPRESSED_GZ:
                   1178:                if (PHAR_G(has_zlib)) {
                   1179:                        RETURN_TRUE;
                   1180:                } else {
                   1181:                        RETURN_FALSE;
                   1182:                }
                   1183:        case PHAR_ENT_COMPRESSED_BZ2:
                   1184:                if (PHAR_G(has_bz2)) {
                   1185:                        RETURN_TRUE;
                   1186:                } else {
                   1187:                        RETURN_FALSE;
                   1188:                }
                   1189:        default:
                   1190:                if (PHAR_G(has_zlib) || PHAR_G(has_bz2)) {
                   1191:                        RETURN_TRUE;
                   1192:                } else {
                   1193:                        RETURN_FALSE;
                   1194:                }
                   1195:        }
                   1196: }
                   1197: /* }}} */
                   1198: 
                   1199: /* {{{ proto bool Phar::canWrite()
                   1200:  * Returns whether phar extension supports writing and creating phars */
                   1201: PHP_METHOD(Phar, canWrite)
                   1202: {
                   1203:        if (zend_parse_parameters_none() == FAILURE) {
                   1204:                return;
                   1205:        }
                   1206:        RETURN_BOOL(!PHAR_G(readonly));
                   1207: }
                   1208: /* }}} */
                   1209: 
                   1210: /* {{{ proto bool Phar::isValidPharFilename(string filename[, bool executable = true])
                   1211:  * Returns whether the given filename is a valid phar filename */
                   1212: PHP_METHOD(Phar, isValidPharFilename)
                   1213: {
                   1214:        char *fname;
                   1215:        const char *ext_str;
                   1216:        int fname_len, ext_len, is_executable;
                   1217:        zend_bool executable = 1;
                   1218: 
                   1219:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &fname, &fname_len, &executable) == FAILURE) {
                   1220:                return;
                   1221:        }
                   1222: 
                   1223:        is_executable = executable;
                   1224:        RETVAL_BOOL(phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, is_executable, 2, 1 TSRMLS_CC) == SUCCESS);
                   1225: }
                   1226: /* }}} */
                   1227: 
                   1228: #if HAVE_SPL
                   1229: /**
                   1230:  * from spl_directory
                   1231:  */
                   1232: static void phar_spl_foreign_dtor(spl_filesystem_object *object TSRMLS_DC) /* {{{ */
                   1233: {
                   1234:        phar_archive_data *phar = (phar_archive_data *) object->oth;
                   1235: 
                   1236:        if (!phar->is_persistent) {
                   1237:                phar_archive_delref(phar TSRMLS_CC);
                   1238:        }
                   1239: 
                   1240:        object->oth = NULL;
                   1241: }
                   1242: /* }}} */
                   1243: 
                   1244: /**
                   1245:  * from spl_directory
                   1246:  */
                   1247: static void phar_spl_foreign_clone(spl_filesystem_object *src, spl_filesystem_object *dst TSRMLS_DC) /* {{{ */
                   1248: {
                   1249:        phar_archive_data *phar_data = (phar_archive_data *) dst->oth;
                   1250: 
                   1251:        if (!phar_data->is_persistent) {
                   1252:                ++(phar_data->refcount);
                   1253:        }
                   1254: }
                   1255: /* }}} */
                   1256: 
                   1257: static spl_other_handler phar_spl_foreign_handler = {
                   1258:        phar_spl_foreign_dtor,
                   1259:        phar_spl_foreign_clone
                   1260: };
                   1261: #endif /* HAVE_SPL */
                   1262: 
                   1263: /* {{{ proto void Phar::__construct(string fname [, int flags [, string alias]])
                   1264:  * Construct a Phar archive object
                   1265:  *
                   1266:  * proto void PharData::__construct(string fname [[, int flags [, string alias]], int file format = Phar::TAR])
                   1267:  * Construct a PharData archive object
                   1268:  *
                   1269:  * This function is used as the constructor for both the Phar and PharData
                   1270:  * classes, hence the two prototypes above.
                   1271:  */
                   1272: PHP_METHOD(Phar, __construct)
                   1273: {
                   1274: #if !HAVE_SPL
                   1275:        zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Cannot instantiate Phar object without SPL extension");
                   1276: #else
                   1277:        char *fname, *alias = NULL, *error, *arch = NULL, *entry = NULL, *save_fname;
                   1278:        int fname_len, alias_len = 0, arch_len, entry_len, is_data;
                   1279: #if PHP_VERSION_ID < 50300
                   1280:        long flags = 0;
                   1281: #else
                   1282:        long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS;
                   1283: #endif
                   1284:        long format = 0;
                   1285:        phar_archive_object *phar_obj;
                   1286:        phar_archive_data   *phar_data;
                   1287:        zval *zobj = getThis(), arg1, arg2;
                   1288: 
                   1289:        phar_obj = (phar_archive_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                   1290: 
                   1291:        is_data = instanceof_function(Z_OBJCE_P(zobj), phar_ce_data TSRMLS_CC);
                   1292: 
                   1293:        if (is_data) {
                   1294:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls!l", &fname, &fname_len, &flags, &alias, &alias_len, &format) == FAILURE) {
                   1295:                        return;
                   1296:                }
                   1297:        } else {
                   1298:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls!", &fname, &fname_len, &flags, &alias, &alias_len) == FAILURE) {
                   1299:                        return;
                   1300:                }
                   1301:        }
                   1302: 
                   1303:        if (phar_obj->arc.archive) {
                   1304:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot call constructor twice");
                   1305:                return;
                   1306:        }
                   1307: 
                   1308:        save_fname = fname;
                   1309:        if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, !is_data, 2 TSRMLS_CC)) {
                   1310:                /* use arch (the basename for the archive) for fname instead of fname */
                   1311:                /* this allows support for RecursiveDirectoryIterator of subdirectories */
                   1312: #ifdef PHP_WIN32
                   1313:                phar_unixify_path_separators(arch, arch_len);
                   1314: #endif
                   1315:                fname = arch;
                   1316:                fname_len = arch_len;
                   1317: #ifdef PHP_WIN32
                   1318:        } else {
                   1319:                arch = estrndup(fname, fname_len);
                   1320:                arch_len = fname_len;
                   1321:                fname = arch;
                   1322:                phar_unixify_path_separators(arch, arch_len);
                   1323: #endif
                   1324:        }
                   1325: 
                   1326:        if (phar_open_or_create_filename(fname, fname_len, alias, alias_len, is_data, REPORT_ERRORS, &phar_data, &error TSRMLS_CC) == FAILURE) {
                   1327: 
                   1328:                if (fname == arch && fname != save_fname) {
                   1329:                        efree(arch);
                   1330:                        fname = save_fname;
                   1331:                }
                   1332: 
                   1333:                if (entry) {
                   1334:                        efree(entry);
                   1335:                }
                   1336: 
                   1337:                if (error) {
                   1338:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   1339:                                "%s", error);
                   1340:                        efree(error);
                   1341:                } else {
                   1342:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   1343:                                "Phar creation or opening failed");
                   1344:                }
                   1345: 
                   1346:                return;
                   1347:        }
                   1348: 
                   1349:        if (is_data && phar_data->is_tar && phar_data->is_brandnew && format == PHAR_FORMAT_ZIP) {
                   1350:                phar_data->is_zip = 1;
                   1351:                phar_data->is_tar = 0;
                   1352:        }
                   1353: 
                   1354:        if (fname == arch) {
                   1355:                efree(arch);
                   1356:                fname = save_fname;
                   1357:        }
                   1358: 
                   1359:        if ((is_data && !phar_data->is_data) || (!is_data && phar_data->is_data)) {
                   1360:                if (is_data) {
                   1361:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   1362:                                "PharData class can only be used for non-executable tar and zip archives");
                   1363:                } else {
                   1364:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   1365:                                "Phar class can only be used for executable tar and zip archives");
                   1366:                }
                   1367:                efree(entry);
                   1368:                return;
                   1369:        }
                   1370: 
                   1371:        is_data = phar_data->is_data;
                   1372: 
                   1373:        if (!phar_data->is_persistent) {
                   1374:                ++(phar_data->refcount);
                   1375:        }
                   1376: 
                   1377:        phar_obj->arc.archive = phar_data;
                   1378:        phar_obj->spl.oth_handler = &phar_spl_foreign_handler;
                   1379: 
                   1380:        if (entry) {
                   1381:                fname_len = spprintf(&fname, 0, "phar://%s%s", phar_data->fname, entry);
                   1382:                efree(entry);
                   1383:        } else {
                   1384:                fname_len = spprintf(&fname, 0, "phar://%s", phar_data->fname);
                   1385:        }
                   1386: 
                   1387:        INIT_PZVAL(&arg1);
                   1388:        ZVAL_STRINGL(&arg1, fname, fname_len, 0);
                   1389:        INIT_PZVAL(&arg2);
                   1390:        ZVAL_LONG(&arg2, flags);
                   1391: 
                   1392:        zend_call_method_with_2_params(&zobj, Z_OBJCE_P(zobj), 
                   1393:                &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg1, &arg2);
                   1394: 
                   1395:        if (!phar_data->is_persistent) {
                   1396:                phar_obj->arc.archive->is_data = is_data;
                   1397:        } else if (!EG(exception)) {
                   1398:                /* register this guy so we can modify if necessary */
                   1399:                zend_hash_add(&PHAR_GLOBALS->phar_persist_map, (const char *) phar_obj->arc.archive, sizeof(phar_obj->arc.archive), (void *) &phar_obj, sizeof(phar_archive_object **), NULL);
                   1400:        }
                   1401: 
                   1402:        phar_obj->spl.info_class = phar_ce_entry;
                   1403:        efree(fname);
                   1404: #endif /* HAVE_SPL */
                   1405: }
                   1406: /* }}} */
                   1407: 
                   1408: /* {{{ proto array Phar::getSupportedSignatures()
                   1409:  * Return array of supported signature types
                   1410:  */
                   1411: PHP_METHOD(Phar, getSupportedSignatures)
                   1412: {
                   1413:        if (zend_parse_parameters_none() == FAILURE) {
                   1414:                return;
                   1415:        }
                   1416:        
                   1417:        array_init(return_value);
                   1418: 
                   1419:        add_next_index_stringl(return_value, "MD5", 3, 1);
                   1420:        add_next_index_stringl(return_value, "SHA-1", 5, 1);
                   1421: #ifdef PHAR_HASH_OK
                   1422:        add_next_index_stringl(return_value, "SHA-256", 7, 1);
                   1423:        add_next_index_stringl(return_value, "SHA-512", 7, 1);
                   1424: #endif
                   1425: #if PHAR_HAVE_OPENSSL
                   1426:        add_next_index_stringl(return_value, "OpenSSL", 7, 1);
                   1427: #else
                   1428:        if (zend_hash_exists(&module_registry, "openssl", sizeof("openssl"))) {
                   1429:                add_next_index_stringl(return_value, "OpenSSL", 7, 1);
                   1430:        }
                   1431: #endif
                   1432: }
                   1433: /* }}} */
                   1434: 
                   1435: /* {{{ proto array Phar::getSupportedCompression()
                   1436:  * Return array of supported comparession algorithms
                   1437:  */
                   1438: PHP_METHOD(Phar, getSupportedCompression)
                   1439: {
                   1440:        if (zend_parse_parameters_none() == FAILURE) {
                   1441:                return;
                   1442:        }
                   1443:        
                   1444:        array_init(return_value);
                   1445:        phar_request_initialize(TSRMLS_C);
                   1446: 
                   1447:        if (PHAR_G(has_zlib)) {
                   1448:                add_next_index_stringl(return_value, "GZ", 2, 1);
                   1449:        }
                   1450: 
                   1451:        if (PHAR_G(has_bz2)) {
                   1452:                add_next_index_stringl(return_value, "BZIP2", 5, 1);
                   1453:        }
                   1454: }
                   1455: /* }}} */
                   1456: 
                   1457: /* {{{ proto array Phar::unlinkArchive(string archive)
                   1458:  * Completely remove a phar archive from memory and disk
                   1459:  */
                   1460: PHP_METHOD(Phar, unlinkArchive)
                   1461: {
                   1462:        char *fname, *error, *zname, *arch, *entry;
                   1463:        int fname_len, zname_len, arch_len, entry_len;
                   1464:        phar_archive_data *phar;
                   1465: 
                   1466:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
                   1467:                RETURN_FALSE;
                   1468:        }
                   1469: 
                   1470:        if (!fname_len) {
                   1471:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Unknown phar archive \"\"");
                   1472:                return;
                   1473:        }
                   1474: 
                   1475:        if (FAILURE == phar_open_from_filename(fname, fname_len, NULL, 0, REPORT_ERRORS, &phar, &error TSRMLS_CC)) {
                   1476:                if (error) {
                   1477:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Unknown phar archive \"%s\": %s", fname, error);
                   1478:                        efree(error);
                   1479:                } else {
                   1480:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Unknown phar archive \"%s\"", fname);
                   1481:                }
                   1482:                return;
                   1483:        }
                   1484: 
1.1.1.2 ! misho    1485:        zname = (char*)zend_get_executed_filename(TSRMLS_C);
1.1       misho    1486:        zname_len = strlen(zname);
                   1487: 
                   1488:        if (zname_len > 7 && !memcmp(zname, "phar://", 7) && SUCCESS == phar_split_fname(zname, zname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) {
                   1489:                if (arch_len == fname_len && !memcmp(arch, fname, arch_len)) {
                   1490:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar archive \"%s\" cannot be unlinked from within itself", fname);
                   1491:                        efree(arch);
                   1492:                        efree(entry);
                   1493:                        return;
                   1494:                }
                   1495:                efree(arch);
                   1496:                efree(entry);
                   1497:        }
                   1498: 
                   1499:        if (phar->is_persistent) {
                   1500:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar archive \"%s\" is in phar.cache_list, cannot unlinkArchive()", fname);
                   1501:                return;
                   1502:        }
                   1503: 
                   1504:        if (phar->refcount) {
                   1505:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar archive \"%s\" has open file handles or objects.  fclose() all file handles, and unset() all objects prior to calling unlinkArchive()", fname);
                   1506:                return;
                   1507:        }
                   1508: 
                   1509:        fname = estrndup(phar->fname, phar->fname_len);
                   1510: 
                   1511:        /* invalidate phar cache */
                   1512:        PHAR_G(last_phar) = NULL;
                   1513:        PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
                   1514: 
                   1515:        phar_archive_delref(phar TSRMLS_CC);
                   1516:        unlink(fname);
                   1517:        efree(fname);
                   1518:        RETURN_TRUE;
                   1519: }
                   1520: /* }}} */
                   1521: 
                   1522: #if HAVE_SPL
                   1523: 
                   1524: #define PHAR_ARCHIVE_OBJECT() \
                   1525:        phar_archive_object *phar_obj = (phar_archive_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
                   1526:        if (!phar_obj->arc.archive) { \
                   1527:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
                   1528:                        "Cannot call method on an uninitialized Phar object"); \
                   1529:                return; \
                   1530:        }
                   1531: 
                   1532: /* {{{ proto void Phar::__destruct()
                   1533:  * if persistent, remove from the cache
                   1534:  */
                   1535: PHP_METHOD(Phar, __destruct)
                   1536: {
                   1537:        phar_archive_object *phar_obj = (phar_archive_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                   1538: 
                   1539:        if (phar_obj->arc.archive && phar_obj->arc.archive->is_persistent) {
                   1540:                zend_hash_del(&PHAR_GLOBALS->phar_persist_map, (const char *) phar_obj->arc.archive, sizeof(phar_obj->arc.archive));
                   1541:        }
                   1542: }
                   1543: /* }}} */
                   1544: 
                   1545: struct _phar_t {
                   1546:        phar_archive_object *p;
                   1547:        zend_class_entry *c;
                   1548:        char *b;
                   1549:        uint l;
                   1550:        zval *ret;
                   1551:        int count;
                   1552:        php_stream *fp;
                   1553: };
                   1554: 
                   1555: static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ */
                   1556: {
                   1557:        zval **value;
                   1558:        zend_uchar key_type;
                   1559:        zend_bool close_fp = 1;
                   1560:        ulong int_key;
                   1561:        struct _phar_t *p_obj = (struct _phar_t*) puser;
                   1562:        uint str_key_len, base_len = p_obj->l, fname_len;
                   1563:        phar_entry_data *data;
                   1564:        php_stream *fp;
                   1565:        size_t contents_len;
                   1566:        char *fname, *error = NULL, *base = p_obj->b, *opened, *save = NULL, *temp = NULL;
                   1567:        phar_zstr key;
                   1568:        char *str_key;
                   1569:        zend_class_entry *ce = p_obj->c;
                   1570:        phar_archive_object *phar_obj = p_obj->p;
                   1571:        char *str = "[stream]";
                   1572: 
                   1573:        iter->funcs->get_current_data(iter, &value TSRMLS_CC);
                   1574: 
                   1575:        if (EG(exception)) {
                   1576:                return ZEND_HASH_APPLY_STOP;
                   1577:        }
                   1578: 
                   1579:        if (!value) {
                   1580:                /* failure in get_current_data */
                   1581:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned no value", ce->name);
                   1582:                return ZEND_HASH_APPLY_STOP;
                   1583:        }
                   1584: 
                   1585:        switch (Z_TYPE_PP(value)) {
                   1586: #if PHP_VERSION_ID >= 60000
                   1587:                case IS_UNICODE:
                   1588:                        zval_unicode_to_string(*(value) TSRMLS_CC);
                   1589:                        /* break intentionally omitted */
                   1590: #endif
                   1591:                case IS_STRING:
                   1592:                        break;
                   1593:                case IS_RESOURCE:
                   1594:                        php_stream_from_zval_no_verify(fp, value);
                   1595: 
                   1596:                        if (!fp) {
                   1597:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Iterator %v returned an invalid stream handle", ce->name);
                   1598:                                return ZEND_HASH_APPLY_STOP;
                   1599:                        }
                   1600: 
                   1601:                        if (iter->funcs->get_current_key) {
                   1602:                                key_type = iter->funcs->get_current_key(iter, &key, &str_key_len, &int_key TSRMLS_CC);
                   1603: 
                   1604:                                if (EG(exception)) {
                   1605:                                        return ZEND_HASH_APPLY_STOP;
                   1606:                                }
                   1607: 
                   1608:                                if (key_type == HASH_KEY_IS_LONG) {
                   1609:                                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
                   1610:                                        return ZEND_HASH_APPLY_STOP;
                   1611:                                }
                   1612: 
                   1613:                                if (key_type > 9) { /* IS_UNICODE == 10 */
                   1614: #if PHP_VERSION_ID < 60000
                   1615: /* this can never happen, but fixes a compile warning */
                   1616:                                        spprintf(&str_key, 0, "%s", key);
                   1617: #else
                   1618:                                        spprintf(&str_key, 0, "%v", key);
                   1619:                                        ezfree(key);
                   1620: #endif
                   1621:                                } else {
                   1622:                                        PHAR_STR(key, str_key);
                   1623:                                }
                   1624: 
                   1625:                                save = str_key;
                   1626: 
                   1627:                                if (str_key[str_key_len - 1] == '\0') {
                   1628:                                        str_key_len--;
                   1629:                                }
                   1630: 
                   1631:                        } else {
                   1632:                                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
                   1633:                                return ZEND_HASH_APPLY_STOP;
                   1634:                        }
                   1635: 
                   1636:                        close_fp = 0;
                   1637:                        opened = (char *) estrndup(str, sizeof("[stream]") + 1);
                   1638:                        goto after_open_fp;
                   1639:                case IS_OBJECT:
                   1640:                        if (instanceof_function(Z_OBJCE_PP(value), spl_ce_SplFileInfo TSRMLS_CC)) {
                   1641:                                char *test = NULL;
                   1642:                                zval dummy;
                   1643:                                spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(*value TSRMLS_CC);
                   1644: 
                   1645:                                if (!base_len) {
                   1646:                                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Iterator %v returns an SplFileInfo object, so base directory must be specified", ce->name);
                   1647:                                        return ZEND_HASH_APPLY_STOP;
                   1648:                                }
                   1649: 
                   1650:                                switch (intern->type) {
                   1651:                                        case SPL_FS_DIR:
                   1652: #if PHP_VERSION_ID >= 60000
                   1653:                                                test = spl_filesystem_object_get_path(intern, NULL, NULL TSRMLS_CC).s;
                   1654: #elif PHP_VERSION_ID >= 50300
                   1655:                                                test = spl_filesystem_object_get_path(intern, NULL TSRMLS_CC);
                   1656: #else
                   1657:                                                test = intern->path;
                   1658: #endif
                   1659:                                                fname_len = spprintf(&fname, 0, "%s%c%s", test, DEFAULT_SLASH, intern->u.dir.entry.d_name);
                   1660:                                                php_stat(fname, fname_len, FS_IS_DIR, &dummy TSRMLS_CC);
                   1661: 
                   1662:                                                if (Z_BVAL(dummy)) {
                   1663:                                                        /* ignore directories */
                   1664:                                                        efree(fname);
                   1665:                                                        return ZEND_HASH_APPLY_KEEP;
                   1666:                                                }
                   1667: 
                   1668:                                                test = expand_filepath(fname, NULL TSRMLS_CC);
                   1669:                                                efree(fname);
                   1670: 
                   1671:                                                if (test) {
                   1672:                                                        fname = test;
                   1673:                                                        fname_len = strlen(fname);
                   1674:                                                } else {
                   1675:                                                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Could not resolve file path");
                   1676:                                                        return ZEND_HASH_APPLY_STOP;
                   1677:                                                }
                   1678: 
                   1679:                                                save = fname;
                   1680:                                                goto phar_spl_fileinfo;
                   1681:                                        case SPL_FS_INFO:
                   1682:                                        case SPL_FS_FILE:
                   1683: #if PHP_VERSION_ID >= 60000
                   1684:                                                if (intern->file_name_type == IS_UNICODE) {
                   1685:                                                        zval zv;
                   1686: 
                   1687:                                                        INIT_ZVAL(zv);
                   1688:                                                        Z_UNIVAL(zv) = intern->file_name;
                   1689:                                                        Z_UNILEN(zv) = intern->file_name_len;
                   1690:                                                        Z_TYPE(zv) = IS_UNICODE;
                   1691: 
                   1692:                                                        zval_copy_ctor(&zv);
                   1693:                                                        zval_unicode_to_string(&zv TSRMLS_CC);
                   1694:                                                        fname = expand_filepath(Z_STRVAL(zv), NULL TSRMLS_CC);
                   1695:                                                        ezfree(Z_UNIVAL(zv));
                   1696:                                                } else {
                   1697:                                                        fname = expand_filepath(intern->file_name.s, NULL TSRMLS_CC);
                   1698:                                                }
                   1699: #else
                   1700:                                                fname = expand_filepath(intern->file_name, NULL TSRMLS_CC);
                   1701: #endif
                   1702:                                                if (!fname) {
                   1703:                                                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Could not resolve file path");
                   1704:                                                        return ZEND_HASH_APPLY_STOP;
                   1705:                                                }
                   1706: 
                   1707:                                                fname_len = strlen(fname);
                   1708:                                                save = fname;
                   1709:                                                goto phar_spl_fileinfo;
                   1710:                                }
                   1711:                        }
                   1712:                        /* fall-through */
                   1713:                default:
                   1714:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid value (must return a string)", ce->name);
                   1715:                        return ZEND_HASH_APPLY_STOP;
                   1716:        }
                   1717: 
                   1718:        fname = Z_STRVAL_PP(value);
                   1719:        fname_len = Z_STRLEN_PP(value);
                   1720: 
                   1721: phar_spl_fileinfo:
                   1722:        if (base_len) {
                   1723:                temp = expand_filepath(base, NULL TSRMLS_CC);
                   1724:                if (!temp) {
                   1725:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Could not resolve file path");
                   1726:                        if (save) {
                   1727:                                efree(save);
                   1728:                        }
                   1729:                        return ZEND_HASH_APPLY_STOP;
                   1730:                }
                   1731:                
                   1732:                base = temp;
                   1733:                base_len = strlen(base);
                   1734: 
                   1735:                if (strstr(fname, base)) {
                   1736:                        str_key_len = fname_len - base_len;
                   1737: 
                   1738:                        if (str_key_len <= 0) {
                   1739:                                if (save) {
                   1740:                                        efree(save);
                   1741:                                        efree(temp);
                   1742:                                }
                   1743:                                return ZEND_HASH_APPLY_KEEP;
                   1744:                        }
                   1745: 
                   1746:                        str_key = fname + base_len;
                   1747: 
                   1748:                        if (*str_key == '/' || *str_key == '\\') {
                   1749:                                str_key++;
                   1750:                                str_key_len--;
                   1751:                        }
                   1752: 
                   1753:                } else {
                   1754:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned a path \"%s\" that is not in the base directory \"%s\"", ce->name, fname, base);
                   1755: 
                   1756:                        if (save) {
                   1757:                                efree(save);
                   1758:                                efree(temp);
                   1759:                        }
                   1760: 
                   1761:                        return ZEND_HASH_APPLY_STOP;
                   1762:                }
                   1763:        } else {
                   1764:                if (iter->funcs->get_current_key) {
                   1765:                        key_type = iter->funcs->get_current_key(iter, &key, &str_key_len, &int_key TSRMLS_CC);
                   1766: 
                   1767:                        if (EG(exception)) {
                   1768:                                return ZEND_HASH_APPLY_STOP;
                   1769:                        }
                   1770: 
                   1771:                        if (key_type == HASH_KEY_IS_LONG) {
                   1772:                                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
                   1773:                                return ZEND_HASH_APPLY_STOP;
                   1774:                        }
                   1775: 
                   1776:                        if (key_type > 9) { /* IS_UNICODE == 10 */
                   1777: #if PHP_VERSION_ID < 60000
                   1778: /* this can never happen, but fixes a compile warning */
                   1779:                                spprintf(&str_key, 0, "%s", key);
                   1780: #else
                   1781:                                spprintf(&str_key, 0, "%v", key);
                   1782:                                ezfree(key);
                   1783: #endif
                   1784:                        } else {
                   1785:                                PHAR_STR(key, str_key);
                   1786:                        }
                   1787: 
                   1788:                        save = str_key;
                   1789: 
                   1790:                        if (str_key[str_key_len - 1] == '\0') str_key_len--;
                   1791:                } else {
                   1792:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned an invalid key (must return a string)", ce->name);
                   1793:                        return ZEND_HASH_APPLY_STOP;
                   1794:                }
                   1795:        }
                   1796: #if PHP_API_VERSION < 20100412
                   1797:        if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
                   1798:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned a path \"%s\" that safe mode prevents opening", ce->name, fname);
                   1799: 
                   1800:                if (save) {
                   1801:                        efree(save);
                   1802:                }
                   1803: 
                   1804:                if (temp) {
                   1805:                        efree(temp);
                   1806:                }
                   1807: 
                   1808:                return ZEND_HASH_APPLY_STOP;
                   1809:        }
                   1810: #endif
                   1811: 
                   1812:        if (php_check_open_basedir(fname TSRMLS_CC)) {
                   1813:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned a path \"%s\" that open_basedir prevents opening", ce->name, fname);
                   1814: 
                   1815:                if (save) {
                   1816:                        efree(save);
                   1817:                }
                   1818: 
                   1819:                if (temp) {
                   1820:                        efree(temp);
                   1821:                }
                   1822: 
                   1823:                return ZEND_HASH_APPLY_STOP;
                   1824:        }
                   1825: 
                   1826:        /* try to open source file, then create internal phar file and copy contents */
                   1827:        fp = php_stream_open_wrapper(fname, "rb", STREAM_MUST_SEEK|0, &opened);
                   1828: 
                   1829:        if (!fp) {
                   1830:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %v returned a file that could not be opened \"%s\"", ce->name, fname);
                   1831: 
                   1832:                if (save) {
                   1833:                        efree(save);
                   1834:                }
                   1835: 
                   1836:                if (temp) {
                   1837:                        efree(temp);
                   1838:                }
                   1839: 
                   1840:                return ZEND_HASH_APPLY_STOP;
                   1841:        }
                   1842: after_open_fp:
                   1843:        if (str_key_len >= sizeof(".phar")-1 && !memcmp(str_key, ".phar", sizeof(".phar")-1)) {
                   1844:                /* silently skip any files that would be added to the magic .phar directory */
                   1845:                if (save) {
                   1846:                        efree(save);
                   1847:                }
                   1848: 
                   1849:                if (temp) {
                   1850:                        efree(temp);
                   1851:                }
                   1852: 
                   1853:                if (opened) {
                   1854:                        efree(opened);
                   1855:                }
                   1856: 
                   1857:                if (close_fp) {
                   1858:                        php_stream_close(fp);
                   1859:                }
                   1860: 
                   1861:                return ZEND_HASH_APPLY_KEEP;
                   1862:        }
                   1863: 
                   1864:        if (!(data = phar_get_or_create_entry_data(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, str_key, str_key_len, "w+b", 0, &error, 1 TSRMLS_CC))) {
                   1865:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s cannot be created: %s", str_key, error);
                   1866:                efree(error);
                   1867: 
                   1868:                if (save) {
                   1869:                        efree(save);
                   1870:                }
                   1871: 
                   1872:                if (opened) {
                   1873:                        efree(opened);
                   1874:                }
                   1875: 
                   1876:                if (temp) {
                   1877:                        efree(temp);
                   1878:                }
                   1879: 
                   1880:                if (close_fp) {
                   1881:                        php_stream_close(fp);
                   1882:                }
                   1883: 
                   1884:                return ZEND_HASH_APPLY_STOP;
                   1885: 
                   1886:        } else {
                   1887:                if (error) {
                   1888:                        efree(error);
                   1889:                }
                   1890:                /* convert to PHAR_UFP */
                   1891:                if (data->internal_file->fp_type == PHAR_MOD) {
                   1892:                        php_stream_close(data->internal_file->fp);
                   1893:                }
                   1894: 
                   1895:                data->internal_file->fp = NULL;
                   1896:                data->internal_file->fp_type = PHAR_UFP;
                   1897:                data->internal_file->offset_abs = data->internal_file->offset = php_stream_tell(p_obj->fp);
                   1898:                data->fp = NULL;
                   1899:                phar_stream_copy_to_stream(fp, p_obj->fp, PHP_STREAM_COPY_ALL, &contents_len);
                   1900:                data->internal_file->uncompressed_filesize = data->internal_file->compressed_filesize =
                   1901:                        php_stream_tell(p_obj->fp) - data->internal_file->offset;
                   1902:        }
                   1903: 
                   1904:        if (close_fp) {
                   1905:                php_stream_close(fp);
                   1906:        }
                   1907: 
                   1908:        add_assoc_string(p_obj->ret, str_key, opened, 0);
                   1909: 
                   1910:        if (save) {
                   1911:                efree(save);
                   1912:        }
                   1913: 
                   1914:        if (temp) {
                   1915:                efree(temp);
                   1916:        }
                   1917: 
                   1918:        data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len;
                   1919:        phar_entry_delref(data TSRMLS_CC);
                   1920: 
                   1921:        return ZEND_HASH_APPLY_KEEP;
                   1922: }
                   1923: /* }}} */
                   1924: 
                   1925: /* {{{ proto array Phar::buildFromDirectory(string base_dir[, string regex])
                   1926:  * Construct a phar archive from an existing directory, recursively.
                   1927:  * Optional second parameter is a regular expression for filtering directory contents.
                   1928:  * 
                   1929:  * Return value is an array mapping phar index to actual files added.
                   1930:  */
                   1931: PHP_METHOD(Phar, buildFromDirectory)
                   1932: {
                   1933:        char *dir, *error, *regex = NULL;
                   1934:        int dir_len, regex_len = 0;
                   1935:        zend_bool apply_reg = 0;
                   1936:        zval arg, arg2, *iter, *iteriter, *regexiter = NULL;
                   1937:        struct _phar_t pass;
                   1938: 
                   1939:        PHAR_ARCHIVE_OBJECT();
                   1940: 
                   1941:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   1942:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   1943:                        "Cannot write to archive - write operations restricted by INI setting");
                   1944:                return;
                   1945:        }
                   1946: 
                   1947:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &dir, &dir_len, &regex, &regex_len) == FAILURE) {
                   1948:                RETURN_FALSE;
                   1949:        }
                   1950: 
                   1951:        MAKE_STD_ZVAL(iter);
                   1952: 
                   1953:        if (SUCCESS != object_init_ex(iter, spl_ce_RecursiveDirectoryIterator)) {
                   1954:                zval_ptr_dtor(&iter);
                   1955:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Unable to instantiate directory iterator for %s", phar_obj->arc.archive->fname);
                   1956:                RETURN_FALSE;
                   1957:        }
                   1958: 
                   1959:        INIT_PZVAL(&arg);
                   1960:        ZVAL_STRINGL(&arg, dir, dir_len, 0);
                   1961:        INIT_PZVAL(&arg2);
                   1962: #if PHP_VERSION_ID < 50300
                   1963:        ZVAL_LONG(&arg2, 0);
                   1964: #else
                   1965:        ZVAL_LONG(&arg2, SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS);
                   1966: #endif
                   1967: 
                   1968:        zend_call_method_with_2_params(&iter, spl_ce_RecursiveDirectoryIterator, 
                   1969:                        &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg, &arg2);
                   1970: 
                   1971:        if (EG(exception)) {
                   1972:                zval_ptr_dtor(&iter);
                   1973:                RETURN_FALSE;
                   1974:        }
                   1975: 
                   1976:        MAKE_STD_ZVAL(iteriter);
                   1977: 
                   1978:        if (SUCCESS != object_init_ex(iteriter, spl_ce_RecursiveIteratorIterator)) {
                   1979:                zval_ptr_dtor(&iter);
                   1980:                zval_ptr_dtor(&iteriter);
                   1981:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Unable to instantiate directory iterator for %s", phar_obj->arc.archive->fname);
                   1982:                RETURN_FALSE;
                   1983:        }
                   1984: 
                   1985:        zend_call_method_with_1_params(&iteriter, spl_ce_RecursiveIteratorIterator, 
                   1986:                        &spl_ce_RecursiveIteratorIterator->constructor, "__construct", NULL, iter);
                   1987: 
                   1988:        if (EG(exception)) {
                   1989:                zval_ptr_dtor(&iter);
                   1990:                zval_ptr_dtor(&iteriter);
                   1991:                RETURN_FALSE;
                   1992:        }
                   1993: 
                   1994:        zval_ptr_dtor(&iter);
                   1995: 
                   1996:        if (regex_len > 0) {
                   1997:                apply_reg = 1;
                   1998:                MAKE_STD_ZVAL(regexiter);
                   1999: 
                   2000:                if (SUCCESS != object_init_ex(regexiter, spl_ce_RegexIterator)) {
                   2001:                        zval_ptr_dtor(&iteriter);
                   2002:                        zval_dtor(regexiter);
                   2003:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Unable to instantiate regex iterator for %s", phar_obj->arc.archive->fname);
                   2004:                        RETURN_FALSE;
                   2005:                }
                   2006: 
                   2007:                INIT_PZVAL(&arg2);
                   2008:                ZVAL_STRINGL(&arg2, regex, regex_len, 0);
                   2009: 
                   2010:                zend_call_method_with_2_params(&regexiter, spl_ce_RegexIterator, 
                   2011:                        &spl_ce_RegexIterator->constructor, "__construct", NULL, iteriter, &arg2);
                   2012:        }
                   2013: 
                   2014:        array_init(return_value);
                   2015: 
                   2016:        pass.c = apply_reg ? Z_OBJCE_P(regexiter) : Z_OBJCE_P(iteriter);
                   2017:        pass.p = phar_obj;
                   2018:        pass.b = dir;
                   2019:        pass.l = dir_len;
                   2020:        pass.count = 0;
                   2021:        pass.ret = return_value;
                   2022:        pass.fp = php_stream_fopen_tmpfile();
                   2023: 
                   2024:        if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
                   2025:                zval_ptr_dtor(&iteriter);
                   2026:                if (apply_reg) {
                   2027:                        zval_ptr_dtor(&regexiter);
                   2028:                }
                   2029:                php_stream_close(pass.fp);
                   2030:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
                   2031:                return;
                   2032:        }
                   2033: 
                   2034:        if (SUCCESS == spl_iterator_apply((apply_reg ? regexiter : iteriter), (spl_iterator_apply_func_t) phar_build, (void *) &pass TSRMLS_CC)) {
                   2035:                zval_ptr_dtor(&iteriter);
                   2036: 
                   2037:                if (apply_reg) {
                   2038:                        zval_ptr_dtor(&regexiter);
                   2039:                }
                   2040: 
                   2041:                phar_obj->arc.archive->ufp = pass.fp;
                   2042:                phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
                   2043: 
                   2044:                if (error) {
                   2045:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   2046:                        efree(error);
                   2047:                }
                   2048: 
                   2049:        } else {
                   2050:                zval_ptr_dtor(&iteriter);
                   2051:                if (apply_reg) {
                   2052:                        zval_ptr_dtor(&regexiter);
                   2053:                }
                   2054:                php_stream_close(pass.fp);
                   2055:        }
                   2056: }
                   2057: /* }}} */
                   2058: 
                   2059: /* {{{ proto array Phar::buildFromIterator(Iterator iter[, string base_directory])
                   2060:  * Construct a phar archive from an iterator.  The iterator must return a series of strings
                   2061:  * that are full paths to files that should be added to the phar.  The iterator key should
                   2062:  * be the path that the file will have within the phar archive.
                   2063:  *
                   2064:  * If base directory is specified, then the key will be ignored, and instead the portion of
                   2065:  * the current value minus the base directory will be used
                   2066:  *
                   2067:  * Returned is an array mapping phar index to actual file added
                   2068:  */
                   2069: PHP_METHOD(Phar, buildFromIterator)
                   2070: {
                   2071:        zval *obj;
                   2072:        char *error;
                   2073:        uint base_len = 0;
                   2074:        char *base = NULL;
                   2075:        struct _phar_t pass;
                   2076: 
                   2077:        PHAR_ARCHIVE_OBJECT();
                   2078: 
                   2079:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   2080:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   2081:                        "Cannot write out phar archive, phar is read-only");
                   2082:                return;
                   2083:        }
                   2084: 
                   2085:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|s", &obj, zend_ce_traversable, &base, &base_len) == FAILURE) {
                   2086:                RETURN_FALSE;
                   2087:        }
                   2088: 
                   2089:        if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
                   2090:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
                   2091:                return;
                   2092:        }
                   2093: 
                   2094:        array_init(return_value);
                   2095: 
                   2096:        pass.c = Z_OBJCE_P(obj);
                   2097:        pass.p = phar_obj;
                   2098:        pass.b = base;
                   2099:        pass.l = base_len;
                   2100:        pass.ret = return_value;
                   2101:        pass.count = 0;
                   2102:        pass.fp = php_stream_fopen_tmpfile();
                   2103: 
                   2104:        if (SUCCESS == spl_iterator_apply(obj, (spl_iterator_apply_func_t) phar_build, (void *) &pass TSRMLS_CC)) {
                   2105:                phar_obj->arc.archive->ufp = pass.fp;
                   2106:                phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
                   2107:                if (error) {
                   2108:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   2109:                        efree(error);
                   2110:                }
                   2111:        } else {
                   2112:                php_stream_close(pass.fp);
                   2113:        }
                   2114: }
                   2115: /* }}} */
                   2116: 
                   2117: /* {{{ proto int Phar::count()
                   2118:  * Returns the number of entries in the Phar archive
                   2119:  */
                   2120: PHP_METHOD(Phar, count)
                   2121: {
                   2122:        PHAR_ARCHIVE_OBJECT();
                   2123:        
                   2124:        if (zend_parse_parameters_none() == FAILURE) {
                   2125:                return;
                   2126:        }
                   2127: 
                   2128:        RETURN_LONG(zend_hash_num_elements(&phar_obj->arc.archive->manifest));
                   2129: }
                   2130: /* }}} */
                   2131: 
                   2132: /* {{{ proto bool Phar::isFileFormat(int format)
                   2133:  * Returns true if the phar archive is based on the tar/zip/phar file format depending
                   2134:  * on whether Phar::TAR, Phar::ZIP or Phar::PHAR was passed in
                   2135:  */
                   2136: PHP_METHOD(Phar, isFileFormat)
                   2137: {
                   2138:        long type;
                   2139:        PHAR_ARCHIVE_OBJECT();
                   2140: 
                   2141:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type) == FAILURE) {
                   2142:                RETURN_FALSE;
                   2143:        }
                   2144: 
                   2145:        switch (type) {
                   2146:                case PHAR_FORMAT_TAR:
                   2147:                        RETURN_BOOL(phar_obj->arc.archive->is_tar);
                   2148:                case PHAR_FORMAT_ZIP:
                   2149:                        RETURN_BOOL(phar_obj->arc.archive->is_zip);
                   2150:                case PHAR_FORMAT_PHAR:
                   2151:                        RETURN_BOOL(!phar_obj->arc.archive->is_tar && !phar_obj->arc.archive->is_zip);
                   2152:                default:
                   2153:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Unknown file format specified");
                   2154:        }
                   2155: }
                   2156: /* }}} */
                   2157: 
                   2158: static int phar_copy_file_contents(phar_entry_info *entry, php_stream *fp TSRMLS_DC) /* {{{ */
                   2159: {
                   2160:        char *error;
                   2161:        off_t offset;
                   2162:        phar_entry_info *link;
                   2163: 
                   2164:        if (FAILURE == phar_open_entry_fp(entry, &error, 1 TSRMLS_CC)) {
                   2165:                if (error) {
                   2166:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   2167:                                "Cannot convert phar archive \"%s\", unable to open entry \"%s\" contents: %s", entry->phar->fname, entry->filename, error);
                   2168:                        efree(error);
                   2169:                } else {
                   2170:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   2171:                                "Cannot convert phar archive \"%s\", unable to open entry \"%s\" contents", entry->phar->fname, entry->filename);
                   2172:                }
                   2173:                return FAILURE;
                   2174:        }
                   2175: 
                   2176:        /* copy old contents in entirety */
                   2177:        phar_seek_efp(entry, 0, SEEK_SET, 0, 1 TSRMLS_CC);
                   2178:        offset = php_stream_tell(fp);
                   2179:        link = phar_get_link_source(entry TSRMLS_CC);
                   2180: 
                   2181:        if (!link) {
                   2182:                link = entry;
                   2183:        }
                   2184: 
                   2185:        if (SUCCESS != phar_stream_copy_to_stream(phar_get_efp(link, 0 TSRMLS_CC), fp, link->uncompressed_filesize, NULL)) {
                   2186:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   2187:                        "Cannot convert phar archive \"%s\", unable to copy entry \"%s\" contents", entry->phar->fname, entry->filename);
                   2188:                return FAILURE;
                   2189:        }
                   2190: 
                   2191:        if (entry->fp_type == PHAR_MOD) {
                   2192:                /* save for potential restore on error */
                   2193:                entry->cfp = entry->fp;
                   2194:                entry->fp = NULL;
                   2195:        }
                   2196: 
                   2197:        /* set new location of file contents */
                   2198:        entry->fp_type = PHAR_FP;
                   2199:        entry->offset = offset;
                   2200:        return SUCCESS;
                   2201: }
                   2202: /* }}} */
                   2203: 
                   2204: static zval *phar_rename_archive(phar_archive_data *phar, char *ext, zend_bool compress TSRMLS_DC) /* {{{ */
                   2205: {
1.1.1.2 ! misho    2206:        const char *oldname = NULL;
        !          2207:        char *oldpath = NULL;
1.1       misho    2208:        char *basename = NULL, *basepath = NULL;
                   2209:        char *newname = NULL, *newpath = NULL;
                   2210:        zval *ret, arg1;
                   2211:        zend_class_entry *ce;
                   2212:        char *error;
                   2213:        const char *pcr_error;
                   2214:        int ext_len = ext ? strlen(ext) : 0;
                   2215:        int oldname_len;
                   2216:        phar_archive_data **pphar = NULL;
                   2217:        php_stream_statbuf ssb;
                   2218: 
                   2219:        if (!ext) {
                   2220:                if (phar->is_zip) {
                   2221: 
                   2222:                        if (phar->is_data) {
                   2223:                                ext = "zip";
                   2224:                        } else {
                   2225:                                ext = "phar.zip";
                   2226:                        }
                   2227: 
                   2228:                } else if (phar->is_tar) {
                   2229: 
                   2230:                        switch (phar->flags) {
                   2231:                                case PHAR_FILE_COMPRESSED_GZ:
                   2232:                                        if (phar->is_data) {
                   2233:                                                ext = "tar.gz";
                   2234:                                        } else {
                   2235:                                                ext = "phar.tar.gz";
                   2236:                                        }
                   2237:                                        break;
                   2238:                                case PHAR_FILE_COMPRESSED_BZ2:
                   2239:                                        if (phar->is_data) {
                   2240:                                                ext = "tar.bz2";
                   2241:                                        } else {
                   2242:                                                ext = "phar.tar.bz2";
                   2243:                                        }
                   2244:                                        break;
                   2245:                                default:
                   2246:                                        if (phar->is_data) {
                   2247:                                                ext = "tar";
                   2248:                                        } else {
                   2249:                                                ext = "phar.tar";
                   2250:                                        }
                   2251:                        }
                   2252:                } else {
                   2253: 
                   2254:                        switch (phar->flags) {
                   2255:                                case PHAR_FILE_COMPRESSED_GZ:
                   2256:                                        ext = "phar.gz";
                   2257:                                        break;
                   2258:                                case PHAR_FILE_COMPRESSED_BZ2:
                   2259:                                        ext = "phar.bz2";
                   2260:                                        break;
                   2261:                                default:
                   2262:                                        ext = "phar";
                   2263:                        }
                   2264:                }
                   2265:        } else if (phar_path_check(&ext, &ext_len, &pcr_error) > pcr_is_ok) {
                   2266: 
                   2267:                if (phar->is_data) {
                   2268:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "data phar converted from \"%s\" has invalid extension %s", phar->fname, ext);
                   2269:                } else {
                   2270:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "phar converted from \"%s\" has invalid extension %s", phar->fname, ext);
                   2271:                }
                   2272:                return NULL;
                   2273:        }
                   2274: 
                   2275:        if (ext[0] == '.') {
                   2276:                ++ext;
                   2277:        }
                   2278: 
                   2279:        oldpath = estrndup(phar->fname, phar->fname_len);
                   2280:        oldname = zend_memrchr(phar->fname, '/', phar->fname_len);
                   2281:        ++oldname;
                   2282:        oldname_len = strlen(oldname);
                   2283: 
                   2284:        basename = estrndup(oldname, oldname_len);
                   2285:        spprintf(&newname, 0, "%s.%s", strtok(basename, "."), ext);
                   2286:        efree(basename);
                   2287: 
                   2288:        
                   2289: 
                   2290:        basepath = estrndup(oldpath, (strlen(oldpath) - oldname_len));
                   2291:        phar->fname_len = spprintf(&newpath, 0, "%s%s", basepath, newname);
                   2292:        phar->fname = newpath;
                   2293:        phar->ext = newpath + phar->fname_len - strlen(ext) - 1;
                   2294:        efree(basepath);
                   2295:        efree(newname);
                   2296: 
                   2297:        if (PHAR_G(manifest_cached) && SUCCESS == zend_hash_find(&cached_phars, newpath, phar->fname_len, (void **) &pphar)) {
                   2298:                efree(oldpath);
                   2299:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Unable to add newly converted phar \"%s\" to the list of phars, new phar name is in phar.cache_list", phar->fname);
                   2300:                return NULL;
                   2301:        }
                   2302: 
                   2303:        if (SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), newpath, phar->fname_len, (void **) &pphar)) {
                   2304:                if ((*pphar)->fname_len == phar->fname_len && !memcmp((*pphar)->fname, phar->fname, phar->fname_len)) {
                   2305:                        if (!zend_hash_num_elements(&phar->manifest)) {
                   2306:                                (*pphar)->is_tar = phar->is_tar;
                   2307:                                (*pphar)->is_zip = phar->is_zip;
                   2308:                                (*pphar)->is_data = phar->is_data;
                   2309:                                (*pphar)->flags = phar->flags;
                   2310:                                (*pphar)->fp = phar->fp;
                   2311:                                phar->fp = NULL;
                   2312:                                phar_destroy_phar_data(phar TSRMLS_CC);
                   2313:                                phar = *pphar;
                   2314:                                phar->refcount++;
                   2315:                                newpath = oldpath;
                   2316:                                goto its_ok;
                   2317:                        }
                   2318:                }
                   2319: 
                   2320:                efree(oldpath);
                   2321:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Unable to add newly converted phar \"%s\" to the list of phars, a phar with that name already exists", phar->fname);
                   2322:                return NULL;
                   2323:        }
                   2324: its_ok:
                   2325:        if (SUCCESS == php_stream_stat_path(newpath, &ssb)) {
                   2326:                efree(oldpath);
                   2327:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "phar \"%s\" exists and must be unlinked prior to conversion", newpath);
                   2328:                return NULL;
                   2329:        }
                   2330:        if (!phar->is_data) {
                   2331:                if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &(phar->ext_len), 1, 1, 1 TSRMLS_CC)) {
                   2332:                        efree(oldpath);
                   2333:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "phar \"%s\" has invalid extension %s", phar->fname, ext);
                   2334:                        return NULL;
                   2335:                }
                   2336: 
                   2337:                if (phar->alias) {
                   2338:                        if (phar->is_temporary_alias) {
                   2339:                                phar->alias = NULL;
                   2340:                                phar->alias_len = 0;
                   2341:                        } else {
                   2342:                                phar->alias = estrndup(newpath, strlen(newpath));
                   2343:                                phar->alias_len = strlen(newpath);
                   2344:                                phar->is_temporary_alias = 1;
                   2345:                                zend_hash_update(&(PHAR_GLOBALS->phar_alias_map), newpath, phar->fname_len, (void*)&phar, sizeof(phar_archive_data*), NULL);
                   2346:                        }
                   2347:                }
                   2348: 
                   2349:        } else {
                   2350: 
                   2351:                if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &(phar->ext_len), 0, 1, 1 TSRMLS_CC)) {
                   2352:                        efree(oldpath);
                   2353:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "data phar \"%s\" has invalid extension %s", phar->fname, ext);
                   2354:                        return NULL;
                   2355:                }
                   2356: 
                   2357:                phar->alias = NULL;
                   2358:                phar->alias_len = 0;
                   2359:        }
                   2360: 
                   2361:        if ((!pphar || phar == *pphar) && SUCCESS != zend_hash_update(&(PHAR_GLOBALS->phar_fname_map), newpath, phar->fname_len, (void*)&phar, sizeof(phar_archive_data*), NULL)) {
                   2362:                efree(oldpath);
                   2363:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Unable to add newly converted phar \"%s\" to the list of phars", phar->fname);
                   2364:                return NULL;
                   2365:        }
                   2366: 
                   2367:        phar_flush(phar, 0, 0, 1, &error TSRMLS_CC);
                   2368: 
                   2369:        if (error) {
                   2370:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s", error);
                   2371:                efree(error);
                   2372:                efree(oldpath);
                   2373:                return NULL;
                   2374:        }
                   2375: 
                   2376:        efree(oldpath);
                   2377: 
                   2378:        if (phar->is_data) {
                   2379:                ce = phar_ce_data;
                   2380:        } else {
                   2381:                ce = phar_ce_archive;
                   2382:        }
                   2383: 
                   2384:        MAKE_STD_ZVAL(ret);
                   2385: 
                   2386:        if (SUCCESS != object_init_ex(ret, ce)) {
                   2387:                zval_dtor(ret);
                   2388:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Unable to instantiate phar object when converting archive \"%s\"", phar->fname);
                   2389:                return NULL;
                   2390:        }
                   2391: 
                   2392:        INIT_PZVAL(&arg1);
                   2393:        ZVAL_STRINGL(&arg1, phar->fname, phar->fname_len, 0);
                   2394: 
                   2395:        zend_call_method_with_1_params(&ret, ce, &ce->constructor, "__construct", NULL, &arg1);
                   2396:        return ret;
                   2397: }
                   2398: /* }}} */
                   2399: 
                   2400: static zval *phar_convert_to_other(phar_archive_data *source, int convert, char *ext, php_uint32 flags TSRMLS_DC) /* {{{ */
                   2401: {
                   2402:        phar_archive_data *phar;
                   2403:        phar_entry_info *entry, newentry;
                   2404:        zval *ret;
                   2405: 
                   2406:        /* invalidate phar cache */
                   2407:        PHAR_G(last_phar) = NULL;
                   2408:        PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
                   2409: 
                   2410:        phar = (phar_archive_data *) ecalloc(1, sizeof(phar_archive_data));
                   2411:        /* set whole-archive compression and type from parameter */
                   2412:        phar->flags = flags;
                   2413:        phar->is_data = source->is_data;
                   2414: 
                   2415:        switch (convert) {
                   2416:                case PHAR_FORMAT_TAR:
                   2417:                        phar->is_tar = 1;
                   2418:                        break;
                   2419:                case PHAR_FORMAT_ZIP:
                   2420:                        phar->is_zip = 1;
                   2421:                        break;
                   2422:                default:
                   2423:                        phar->is_data = 0;
                   2424:                        break;
                   2425:        }
                   2426: 
                   2427:        zend_hash_init(&(phar->manifest), sizeof(phar_entry_info),
                   2428:                zend_get_hash_value, destroy_phar_manifest_entry, 0);
                   2429:        zend_hash_init(&phar->mounted_dirs, sizeof(char *),
                   2430:                zend_get_hash_value, NULL, 0);
                   2431:        zend_hash_init(&phar->virtual_dirs, sizeof(char *),
                   2432:                zend_get_hash_value, NULL, 0);
                   2433: 
                   2434:        phar->fp = php_stream_fopen_tmpfile();
                   2435:        phar->fname = source->fname;
                   2436:        phar->fname_len = source->fname_len;
                   2437:        phar->is_temporary_alias = source->is_temporary_alias;
                   2438:        phar->alias = source->alias;
                   2439: 
                   2440:        if (source->metadata) {
                   2441:                zval *t;
                   2442: 
                   2443:                t = source->metadata;
                   2444:                ALLOC_ZVAL(phar->metadata);
                   2445:                *phar->metadata = *t;
                   2446:                zval_copy_ctor(phar->metadata);
                   2447: #if PHP_VERSION_ID < 50300
                   2448:                phar->metadata->refcount = 1;
                   2449: #else
                   2450:                Z_SET_REFCOUNT_P(phar->metadata, 1);
                   2451: #endif
                   2452: 
                   2453:                phar->metadata_len = 0;
                   2454:        }
                   2455: 
                   2456:        /* first copy each file's uncompressed contents to a temporary file and set per-file flags */
                   2457:        for (zend_hash_internal_pointer_reset(&source->manifest); SUCCESS == zend_hash_has_more_elements(&source->manifest); zend_hash_move_forward(&source->manifest)) {
                   2458: 
                   2459:                if (FAILURE == zend_hash_get_current_data(&source->manifest, (void **) &entry)) {
                   2460:                        zend_hash_destroy(&(phar->manifest));
                   2461:                        php_stream_close(phar->fp);
                   2462:                        efree(phar);
                   2463:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   2464:                                "Cannot convert phar archive \"%s\"", source->fname);
                   2465:                        return NULL;
                   2466:                }
                   2467: 
                   2468:                newentry = *entry;
                   2469: 
                   2470:                if (newentry.link) {
                   2471:                        newentry.link = estrdup(newentry.link);
                   2472:                        goto no_copy;
                   2473:                }
                   2474: 
                   2475:                if (newentry.tmp) {
                   2476:                        newentry.tmp = estrdup(newentry.tmp);
                   2477:                        goto no_copy;
                   2478:                }
                   2479: 
                   2480:                newentry.metadata_str.c = 0;
                   2481: 
                   2482:                if (FAILURE == phar_copy_file_contents(&newentry, phar->fp TSRMLS_CC)) {
                   2483:                        zend_hash_destroy(&(phar->manifest));
                   2484:                        php_stream_close(phar->fp);
                   2485:                        efree(phar);
                   2486:                        /* exception already thrown */
                   2487:                        return NULL;
                   2488:                }
                   2489: no_copy:
                   2490:                newentry.filename = estrndup(newentry.filename, newentry.filename_len);
                   2491: 
                   2492:                if (newentry.metadata) {
                   2493:                        zval *t;
                   2494: 
                   2495:                        t = newentry.metadata;
                   2496:                        ALLOC_ZVAL(newentry.metadata);
                   2497:                        *newentry.metadata = *t;
                   2498:                        zval_copy_ctor(newentry.metadata);
                   2499: #if PHP_VERSION_ID < 50300
                   2500:                        newentry.metadata->refcount = 1;
                   2501: #else
                   2502:                        Z_SET_REFCOUNT_P(newentry.metadata, 1);
                   2503: #endif
                   2504: 
                   2505:                        newentry.metadata_str.c = NULL;
                   2506:                        newentry.metadata_str.len = 0;
                   2507:                }
                   2508: 
                   2509:                newentry.is_zip = phar->is_zip;
                   2510:                newentry.is_tar = phar->is_tar;
                   2511: 
                   2512:                if (newentry.is_tar) {
                   2513:                        newentry.tar_type = (entry->is_dir ? TAR_DIR : TAR_FILE);
                   2514:                }
                   2515: 
                   2516:                newentry.is_modified = 1;
                   2517:                newentry.phar = phar;
                   2518:                newentry.old_flags = newentry.flags & ~PHAR_ENT_COMPRESSION_MASK; /* remove compression from old_flags */
                   2519:                phar_set_inode(&newentry TSRMLS_CC);
                   2520:                zend_hash_add(&(phar->manifest), newentry.filename, newentry.filename_len, (void*)&newentry, sizeof(phar_entry_info), NULL);
                   2521:                phar_add_virtual_dirs(phar, newentry.filename, newentry.filename_len TSRMLS_CC);
                   2522:        }
                   2523: 
                   2524:        if ((ret = phar_rename_archive(phar, ext, 0 TSRMLS_CC))) {
                   2525:                return ret;
                   2526:        } else {
                   2527:                zend_hash_destroy(&(phar->manifest));
                   2528:                zend_hash_destroy(&(phar->mounted_dirs));
                   2529:                zend_hash_destroy(&(phar->virtual_dirs));
                   2530:                php_stream_close(phar->fp);
                   2531:                efree(phar->fname);
                   2532:                efree(phar);
                   2533:                return NULL;
                   2534:        }
                   2535: }
                   2536: /* }}} */
                   2537: 
                   2538: /* {{{ proto object Phar::convertToExecutable([int format[, int compression [, string file_ext]]])
                   2539:  * Convert a phar.tar or phar.zip archive to the phar file format. The
                   2540:  * optional parameter allows the user to determine the new
                   2541:  * filename extension (default is phar).
                   2542:  */
                   2543: PHP_METHOD(Phar, convertToExecutable)
                   2544: {
                   2545:        char *ext = NULL;
                   2546:        int is_data, ext_len = 0;
                   2547:        php_uint32 flags;
                   2548:        zval *ret;
                   2549:        /* a number that is not 0, 1 or 2 (Which is also Greg's birthday, so there) */
                   2550:        long format = 9021976, method = 9021976;
                   2551:        PHAR_ARCHIVE_OBJECT();
                   2552: 
                   2553:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lls", &format, &method, &ext, &ext_len) == FAILURE) {
                   2554:                return;
                   2555:        }
                   2556: 
                   2557:        if (PHAR_G(readonly)) {
                   2558:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   2559:                        "Cannot write out executable phar archive, phar is read-only");
                   2560:                return;
                   2561:        }
                   2562: 
                   2563:        switch (format) {
                   2564:                case 9021976:
                   2565:                case PHAR_FORMAT_SAME: /* null is converted to 0 */
                   2566:                        /* by default, use the existing format */
                   2567:                        if (phar_obj->arc.archive->is_tar) {
                   2568:                                format = PHAR_FORMAT_TAR;
                   2569:                        } else if (phar_obj->arc.archive->is_zip) {
                   2570:                                format = PHAR_FORMAT_ZIP;
                   2571:                        } else {
                   2572:                                format = PHAR_FORMAT_PHAR;
                   2573:                        }
                   2574:                        break;
                   2575:                case PHAR_FORMAT_PHAR:
                   2576:                case PHAR_FORMAT_TAR:
                   2577:                case PHAR_FORMAT_ZIP:
                   2578:                        break;
                   2579:                default:
                   2580:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   2581:                                "Unknown file format specified, please pass one of Phar::PHAR, Phar::TAR or Phar::ZIP");
                   2582:                        return;
                   2583:        }
                   2584: 
                   2585:        switch (method) {
                   2586:                case 9021976:
                   2587:                        flags = phar_obj->arc.archive->flags & PHAR_FILE_COMPRESSION_MASK;
                   2588:                        break;
                   2589:                case 0:
                   2590:                        flags = PHAR_FILE_COMPRESSED_NONE;
                   2591:                        break;
                   2592:                case PHAR_ENT_COMPRESSED_GZ:
                   2593:                        if (format == PHAR_FORMAT_ZIP) {
                   2594:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   2595:                                        "Cannot compress entire archive with gzip, zip archives do not support whole-archive compression");
                   2596:                                return;
                   2597:                        }
                   2598: 
                   2599:                        if (!PHAR_G(has_zlib)) {
                   2600:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   2601:                                        "Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
                   2602:                                return;
                   2603:                        }
                   2604: 
                   2605:                        flags = PHAR_FILE_COMPRESSED_GZ;
                   2606:                        break;
                   2607:                case PHAR_ENT_COMPRESSED_BZ2:
                   2608:                        if (format == PHAR_FORMAT_ZIP) {
                   2609:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   2610:                                        "Cannot compress entire archive with bz2, zip archives do not support whole-archive compression");
                   2611:                                return;
                   2612:                        }
                   2613: 
                   2614:                        if (!PHAR_G(has_bz2)) {
                   2615:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   2616:                                        "Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
                   2617:                                return;
                   2618:                        }
                   2619: 
                   2620:                        flags = PHAR_FILE_COMPRESSED_BZ2;
                   2621:                        break;
                   2622:                default:
                   2623:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   2624:                                "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
                   2625:                        return;
                   2626:        }
                   2627: 
                   2628:        is_data = phar_obj->arc.archive->is_data;
                   2629:        phar_obj->arc.archive->is_data = 0;
                   2630:        ret = phar_convert_to_other(phar_obj->arc.archive, format, ext, flags TSRMLS_CC);
                   2631:        phar_obj->arc.archive->is_data = is_data;
                   2632: 
                   2633:        if (ret) {
                   2634:                RETURN_ZVAL(ret, 1, 1);
                   2635:        } else {
                   2636:                RETURN_NULL();
                   2637:        }
                   2638: }
                   2639: /* }}} */
                   2640: 
                   2641: /* {{{ proto object Phar::convertToData([int format[, int compression [, string file_ext]]])
                   2642:  * Convert an archive to a non-executable .tar or .zip.
                   2643:  * The optional parameter allows the user to determine the new
                   2644:  * filename extension (default is .zip or .tar).
                   2645:  */
                   2646: PHP_METHOD(Phar, convertToData)
                   2647: {
                   2648:        char *ext = NULL;
                   2649:        int is_data, ext_len = 0;
                   2650:        php_uint32 flags;
                   2651:        zval *ret;
                   2652:        /* a number that is not 0, 1 or 2 (Which is also Greg's birthday so there) */
                   2653:        long format = 9021976, method = 9021976;
                   2654:        PHAR_ARCHIVE_OBJECT();
                   2655: 
                   2656:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lls", &format, &method, &ext, &ext_len) == FAILURE) {
                   2657:                return;
                   2658:        }
                   2659: 
                   2660:        switch (format) {
                   2661:                case 9021976:
                   2662:                case PHAR_FORMAT_SAME: /* null is converted to 0 */
                   2663:                        /* by default, use the existing format */
                   2664:                        if (phar_obj->arc.archive->is_tar) {
                   2665:                                format = PHAR_FORMAT_TAR;
                   2666:                        } else if (phar_obj->arc.archive->is_zip) {
                   2667:                                format = PHAR_FORMAT_ZIP;
                   2668:                        } else {
                   2669:                                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   2670:                                        "Cannot write out data phar archive, use Phar::TAR or Phar::ZIP");
                   2671:                                return;
                   2672:                        }
                   2673:                        break;
                   2674:                case PHAR_FORMAT_PHAR:
                   2675:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   2676:                                "Cannot write out data phar archive, use Phar::TAR or Phar::ZIP");
                   2677:                        return;
                   2678:                case PHAR_FORMAT_TAR:
                   2679:                case PHAR_FORMAT_ZIP:
                   2680:                        break;
                   2681:                default:
                   2682:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   2683:                                "Unknown file format specified, please pass one of Phar::TAR or Phar::ZIP");
                   2684:                        return;
                   2685:        }
                   2686: 
                   2687:        switch (method) {
                   2688:                case 9021976:
                   2689:                        flags = phar_obj->arc.archive->flags & PHAR_FILE_COMPRESSION_MASK;
                   2690:                        break;
                   2691:                case 0:
                   2692:                        flags = PHAR_FILE_COMPRESSED_NONE;
                   2693:                        break;
                   2694:                case PHAR_ENT_COMPRESSED_GZ:
                   2695:                        if (format == PHAR_FORMAT_ZIP) {
                   2696:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   2697:                                        "Cannot compress entire archive with gzip, zip archives do not support whole-archive compression");
                   2698:                                return;
                   2699:                        }
                   2700: 
                   2701:                        if (!PHAR_G(has_zlib)) {
                   2702:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   2703:                                        "Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
                   2704:                                return;
                   2705:                        }
                   2706: 
                   2707:                        flags = PHAR_FILE_COMPRESSED_GZ;
                   2708:                        break;
                   2709:                case PHAR_ENT_COMPRESSED_BZ2:
                   2710:                        if (format == PHAR_FORMAT_ZIP) {
                   2711:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   2712:                                        "Cannot compress entire archive with bz2, zip archives do not support whole-archive compression");
                   2713:                                return;
                   2714:                        }
                   2715: 
                   2716:                        if (!PHAR_G(has_bz2)) {
                   2717:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   2718:                                        "Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
                   2719:                                return;
                   2720:                        }
                   2721: 
                   2722:                        flags = PHAR_FILE_COMPRESSED_BZ2;
                   2723:                        break;
                   2724:                default:
                   2725:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   2726:                                "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
                   2727:                        return;
                   2728:        }
                   2729: 
                   2730:        is_data = phar_obj->arc.archive->is_data;
                   2731:        phar_obj->arc.archive->is_data = 1;
                   2732:        ret = phar_convert_to_other(phar_obj->arc.archive, format, ext, flags TSRMLS_CC);
                   2733:        phar_obj->arc.archive->is_data = is_data;
                   2734: 
                   2735:        if (ret) {
                   2736:                RETURN_ZVAL(ret, 1, 1);
                   2737:        } else {
                   2738:                RETURN_NULL();
                   2739:        }
                   2740: }
                   2741: /* }}} */
                   2742: 
                   2743: /* {{{ proto int|false Phar::isCompressed()
                   2744:  * Returns Phar::GZ or PHAR::BZ2 if the entire archive is compressed
                   2745:  * (.tar.gz/tar.bz2 and so on), or FALSE otherwise.
                   2746:  */
                   2747: PHP_METHOD(Phar, isCompressed)
                   2748: {
                   2749:        PHAR_ARCHIVE_OBJECT();
                   2750:        
                   2751:        if (zend_parse_parameters_none() == FAILURE) {
                   2752:                return;
                   2753:        }
                   2754: 
                   2755:        if (phar_obj->arc.archive->flags & PHAR_FILE_COMPRESSED_GZ) {
                   2756:                RETURN_LONG(PHAR_ENT_COMPRESSED_GZ);
                   2757:        }
                   2758: 
                   2759:        if (phar_obj->arc.archive->flags & PHAR_FILE_COMPRESSED_BZ2) {
                   2760:                RETURN_LONG(PHAR_ENT_COMPRESSED_BZ2);
                   2761:        }
                   2762: 
                   2763:        RETURN_FALSE;
                   2764: }
                   2765: /* }}} */
                   2766: 
                   2767: /* {{{ proto bool Phar::isWritable()
                   2768:  * Returns true if phar.readonly=0 or phar is a PharData AND the actual file is writable.
                   2769:  */
                   2770: PHP_METHOD(Phar, isWritable)
                   2771: {
                   2772:        php_stream_statbuf ssb;
                   2773:        PHAR_ARCHIVE_OBJECT();
                   2774:        
                   2775:        if (zend_parse_parameters_none() == FAILURE) {
                   2776:                return;
                   2777:        }
                   2778: 
                   2779:        if (!phar_obj->arc.archive->is_writeable) {
                   2780:                RETURN_FALSE;
                   2781:        }
                   2782: 
                   2783:        if (SUCCESS != php_stream_stat_path(phar_obj->arc.archive->fname, &ssb)) {
                   2784:                if (phar_obj->arc.archive->is_brandnew) {
                   2785:                        /* assume it works if the file doesn't exist yet */
                   2786:                        RETURN_TRUE;
                   2787:                }
                   2788:                RETURN_FALSE;
                   2789:        }
                   2790: 
                   2791:        RETURN_BOOL((ssb.sb.st_mode & (S_IWOTH | S_IWGRP | S_IWUSR)) != 0);
                   2792: }
                   2793: /* }}} */
                   2794: 
                   2795: /* {{{ proto bool Phar::delete(string entry)
                   2796:  * Deletes a named file within the archive.
                   2797:  */
                   2798: PHP_METHOD(Phar, delete)
                   2799: {
                   2800:        char *fname;
                   2801:        int fname_len;
                   2802:        char *error;
                   2803:        phar_entry_info *entry;
                   2804:        PHAR_ARCHIVE_OBJECT();
                   2805: 
                   2806:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   2807:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   2808:                        "Cannot write out phar archive, phar is read-only");
                   2809:                return;
                   2810:        }
                   2811: 
                   2812:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
                   2813:                RETURN_FALSE;
                   2814:        }
                   2815: 
                   2816:        if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
                   2817:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
                   2818:                return;
                   2819:        }
                   2820:        if (zend_hash_exists(&phar_obj->arc.archive->manifest, fname, (uint) fname_len)) {
                   2821:                if (SUCCESS == zend_hash_find(&phar_obj->arc.archive->manifest, fname, (uint) fname_len, (void**)&entry)) {
                   2822:                        if (entry->is_deleted) {
                   2823:                                /* entry is deleted, but has not been flushed to disk yet */
                   2824:                                RETURN_TRUE;
                   2825:                        } else {
                   2826:                                entry->is_deleted = 1;
                   2827:                                entry->is_modified = 1;
                   2828:                                phar_obj->arc.archive->is_modified = 1;
                   2829:                        }
                   2830:                }
                   2831:        } else {
                   2832:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist and cannot be deleted", fname);
                   2833:                RETURN_FALSE;
                   2834:        }
                   2835: 
                   2836:        phar_flush(phar_obj->arc.archive, NULL, 0, 0, &error TSRMLS_CC);
                   2837:        if (error) {
                   2838:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   2839:                efree(error);
                   2840:        }
                   2841: 
                   2842:        RETURN_TRUE;
                   2843: }
                   2844: /* }}} */
                   2845: 
                   2846: /* {{{ proto int Phar::getAlias()
                   2847:  * Returns the alias for the Phar or NULL.
                   2848:  */
                   2849: PHP_METHOD(Phar, getAlias)
                   2850: {
                   2851:        PHAR_ARCHIVE_OBJECT();
                   2852:        
                   2853:        if (zend_parse_parameters_none() == FAILURE) {
                   2854:                return;
                   2855:        }
                   2856: 
                   2857:        if (phar_obj->arc.archive->alias && phar_obj->arc.archive->alias != phar_obj->arc.archive->fname) {
                   2858:                RETURN_STRINGL(phar_obj->arc.archive->alias, phar_obj->arc.archive->alias_len, 1);
                   2859:        }
                   2860: }
                   2861: /* }}} */
                   2862: 
                   2863: /* {{{ proto int Phar::getPath()
                   2864:  * Returns the real path to the phar archive on disk
                   2865:  */
                   2866: PHP_METHOD(Phar, getPath)
                   2867: {
                   2868:        PHAR_ARCHIVE_OBJECT();
                   2869:        
                   2870:        if (zend_parse_parameters_none() == FAILURE) {
                   2871:                return;
                   2872:        }
                   2873: 
                   2874:        RETURN_STRINGL(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, 1);
                   2875: }
                   2876: /* }}} */
                   2877: 
                   2878: /* {{{ proto bool Phar::setAlias(string alias)
                   2879:  * Sets the alias for a Phar archive. The default value is the full path
                   2880:  * to the archive.
                   2881:  */
                   2882: PHP_METHOD(Phar, setAlias)
                   2883: {
                   2884:        char *alias, *error, *oldalias;
                   2885:        phar_archive_data **fd_ptr;
                   2886:        int alias_len, oldalias_len, old_temp, readd = 0;
                   2887: 
                   2888:        PHAR_ARCHIVE_OBJECT();
                   2889: 
                   2890:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   2891:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   2892:                        "Cannot write out phar archive, phar is read-only");
                   2893:                RETURN_FALSE;
                   2894:        }
                   2895: 
                   2896:        /* invalidate phar cache */
                   2897:        PHAR_G(last_phar) = NULL;
                   2898:        PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
                   2899: 
                   2900:        if (phar_obj->arc.archive->is_data) {
                   2901:                if (phar_obj->arc.archive->is_tar) {
                   2902:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   2903:                                "A Phar alias cannot be set in a plain tar archive");
                   2904:                } else {
                   2905:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   2906:                                "A Phar alias cannot be set in a plain zip archive");
                   2907:                }
                   2908:                RETURN_FALSE;
                   2909:        }
                   2910: 
                   2911:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &alias, &alias_len) == SUCCESS) {
                   2912:                if (alias_len == phar_obj->arc.archive->alias_len && memcmp(phar_obj->arc.archive->alias, alias, alias_len) == 0) {
                   2913:                        RETURN_TRUE;
                   2914:                }
                   2915:                if (alias_len && SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void**)&fd_ptr)) {
                   2916:                        spprintf(&error, 0, "alias \"%s\" is already used for archive \"%s\" and cannot be used for other archives", alias, (*fd_ptr)->fname);
                   2917:                        if (SUCCESS == phar_free_alias(*fd_ptr, alias, alias_len TSRMLS_CC)) {
                   2918:                                efree(error);
                   2919:                                goto valid_alias;
                   2920:                        }
                   2921:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   2922:                        efree(error);
                   2923:                        RETURN_FALSE;
                   2924:                }
                   2925:                if (!phar_validate_alias(alias, alias_len)) {
                   2926:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   2927:                                "Invalid alias \"%s\" specified for phar \"%s\"", alias, phar_obj->arc.archive->fname);
                   2928:                        RETURN_FALSE;
                   2929:                }
                   2930: valid_alias:
                   2931:                if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
                   2932:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
                   2933:                        return;
                   2934:                }
                   2935:                if (phar_obj->arc.archive->alias_len && SUCCESS == zend_hash_find(&(PHAR_GLOBALS->phar_alias_map), phar_obj->arc.archive->alias, phar_obj->arc.archive->alias_len, (void**)&fd_ptr)) {
                   2936:                        zend_hash_del(&(PHAR_GLOBALS->phar_alias_map), phar_obj->arc.archive->alias, phar_obj->arc.archive->alias_len);
                   2937:                        readd = 1;
                   2938:                }
                   2939: 
                   2940:                oldalias = phar_obj->arc.archive->alias;
                   2941:                oldalias_len = phar_obj->arc.archive->alias_len;
                   2942:                old_temp = phar_obj->arc.archive->is_temporary_alias;
                   2943: 
                   2944:                if (alias_len) {
                   2945:                        phar_obj->arc.archive->alias = estrndup(alias, alias_len);
                   2946:                } else {
                   2947:                        phar_obj->arc.archive->alias = NULL;
                   2948:                }
                   2949: 
                   2950:                phar_obj->arc.archive->alias_len = alias_len;
                   2951:                phar_obj->arc.archive->is_temporary_alias = 0;
                   2952:                phar_flush(phar_obj->arc.archive, NULL, 0, 0, &error TSRMLS_CC);
                   2953: 
                   2954:                if (error) {
                   2955:                        phar_obj->arc.archive->alias = oldalias;
                   2956:                        phar_obj->arc.archive->alias_len = oldalias_len;
                   2957:                        phar_obj->arc.archive->is_temporary_alias = old_temp;
                   2958:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   2959:                        if (readd) {
                   2960:                                zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), oldalias, oldalias_len, (void*)&(phar_obj->arc.archive), sizeof(phar_archive_data*), NULL);
                   2961:                        }
                   2962:                        efree(error);
                   2963:                        RETURN_FALSE;
                   2964:                }
                   2965: 
                   2966:                zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&(phar_obj->arc.archive), sizeof(phar_archive_data*), NULL);
                   2967: 
                   2968:                if (oldalias) {
                   2969:                        efree(oldalias);
                   2970:                }
                   2971: 
                   2972:                RETURN_TRUE;
                   2973:        }
                   2974: 
                   2975:        RETURN_FALSE;
                   2976: }
                   2977: /* }}} */
                   2978: 
                   2979: /* {{{ proto string Phar::getVersion()
                   2980:  * Return version info of Phar archive
                   2981:  */
                   2982: PHP_METHOD(Phar, getVersion)
                   2983: {
                   2984:        PHAR_ARCHIVE_OBJECT();
                   2985:        
                   2986:        if (zend_parse_parameters_none() == FAILURE) {
                   2987:                return;
                   2988:        }
                   2989: 
                   2990:        RETURN_STRING(phar_obj->arc.archive->version, 1);
                   2991: }
                   2992: /* }}} */
                   2993: 
                   2994: /* {{{ proto void Phar::startBuffering()
                   2995:  * Do not flush a writeable phar (save its contents) until explicitly requested
                   2996:  */
                   2997: PHP_METHOD(Phar, startBuffering)
                   2998: {
                   2999:        PHAR_ARCHIVE_OBJECT();
                   3000:        
                   3001:        if (zend_parse_parameters_none() == FAILURE) {
                   3002:                return;
                   3003:        }
                   3004: 
                   3005:        phar_obj->arc.archive->donotflush = 1;
                   3006: }
                   3007: /* }}} */
                   3008: 
                   3009: /* {{{ proto bool Phar::isBuffering()
                   3010:  * Returns whether write operations are flushing to disk immediately.
                   3011:  */
                   3012: PHP_METHOD(Phar, isBuffering)
                   3013: {
                   3014:        PHAR_ARCHIVE_OBJECT();
                   3015:        
                   3016:        if (zend_parse_parameters_none() == FAILURE) {
                   3017:                return;
                   3018:        }
                   3019: 
                   3020:        RETURN_BOOL(phar_obj->arc.archive->donotflush);
                   3021: }
                   3022: /* }}} */
                   3023: 
                   3024: /* {{{ proto bool Phar::stopBuffering()
                   3025:  * Saves the contents of a modified archive to disk.
                   3026:  */
                   3027: PHP_METHOD(Phar, stopBuffering)
                   3028: {
                   3029:        char *error;
                   3030: 
                   3031:        PHAR_ARCHIVE_OBJECT();
                   3032:        
                   3033:        if (zend_parse_parameters_none() == FAILURE) {
                   3034:                return;
                   3035:        }
                   3036: 
                   3037:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   3038:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3039:                        "Cannot write out phar archive, phar is read-only");
                   3040:                return;
                   3041:        }
                   3042: 
                   3043:        phar_obj->arc.archive->donotflush = 0;
                   3044:        phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
                   3045: 
                   3046:        if (error) {
                   3047:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   3048:                efree(error);
                   3049:        }
                   3050: }
                   3051: /* }}} */
                   3052: 
                   3053: /* {{{ proto bool Phar::setStub(string|stream stub [, int len])
                   3054:  * Change the stub in a phar, phar.tar or phar.zip archive to something other
                   3055:  * than the default. The stub *must* end with a call to __HALT_COMPILER().
                   3056:  */
                   3057: PHP_METHOD(Phar, setStub)
                   3058: {
                   3059:        zval *zstub;
                   3060:        char *stub, *error;
                   3061:        int stub_len;
                   3062:        long len = -1;
                   3063:        php_stream *stream;
                   3064:        PHAR_ARCHIVE_OBJECT();
                   3065: 
                   3066:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   3067:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3068:                        "Cannot change stub, phar is read-only");
                   3069:                return;
                   3070:        }
                   3071: 
                   3072:        if (phar_obj->arc.archive->is_data) {
                   3073:                if (phar_obj->arc.archive->is_tar) {
                   3074:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3075:                                "A Phar stub cannot be set in a plain tar archive");
                   3076:                } else {
                   3077:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3078:                                "A Phar stub cannot be set in a plain zip archive");
                   3079:                }
                   3080:                return;
                   3081:        }
                   3082: 
                   3083:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zstub, &len) == SUCCESS) {
                   3084:                if ((php_stream_from_zval_no_verify(stream, &zstub)) != NULL) {
                   3085:                        if (len > 0) {
                   3086:                                len = -len;
                   3087:                        } else {
                   3088:                                len = -1;
                   3089:                        }
                   3090:                        if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
                   3091:                                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
                   3092:                                return;
                   3093:                        }
                   3094:                        phar_flush(phar_obj->arc.archive, (char *) &zstub, len, 0, &error TSRMLS_CC);
                   3095:                        if (error) {
                   3096:                                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   3097:                                efree(error);
                   3098:                        }
                   3099:                        RETURN_TRUE;
                   3100:                } else {
                   3101:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3102:                                "Cannot change stub, unable to read from input stream");
                   3103:                }
                   3104:        } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &stub, &stub_len) == SUCCESS) {
                   3105:                if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
                   3106:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
                   3107:                        return;
                   3108:                }
                   3109:                phar_flush(phar_obj->arc.archive, stub, stub_len, 0, &error TSRMLS_CC);
                   3110: 
                   3111:                if (error) {
                   3112:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   3113:                        efree(error);
                   3114:                }
                   3115: 
                   3116:                RETURN_TRUE;
                   3117:        }
                   3118: 
                   3119:        RETURN_FALSE;
                   3120: }
                   3121: /* }}} */
                   3122: 
                   3123: /* {{{ proto bool Phar::setDefaultStub([string index[, string webindex]])
                   3124:  * In a pure phar archive, sets a stub that can be used to run the archive
                   3125:  * regardless of whether the phar extension is available. The first parameter
                   3126:  * is the CLI startup filename, which defaults to "index.php". The second
                   3127:  * parameter is the web startup filename and also defaults to "index.php"
                   3128:  * (falling back to CLI behaviour).
                   3129:  * Both parameters are optional.
                   3130:  * In a phar.zip or phar.tar archive, the default stub is used only to
                   3131:  * identify the archive to the extension as a Phar object. This allows the
                   3132:  * extension to treat phar.zip and phar.tar types as honorary phars. Since
                   3133:  * files cannot be loaded via this kind of stub, no parameters are accepted
                   3134:  * when the Phar object is zip- or tar-based.
                   3135:  */
                   3136: PHP_METHOD(Phar, setDefaultStub)
                   3137: {
                   3138:        char *index = NULL, *webindex = NULL, *error = NULL, *stub = NULL;
                   3139:        int index_len = 0, webindex_len = 0, created_stub = 0;
                   3140:        size_t stub_len = 0;
                   3141:        PHAR_ARCHIVE_OBJECT();
                   3142: 
                   3143:        if (phar_obj->arc.archive->is_data) {
                   3144:                if (phar_obj->arc.archive->is_tar) {
                   3145:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3146:                                "A Phar stub cannot be set in a plain tar archive");
                   3147:                } else {
                   3148:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3149:                                "A Phar stub cannot be set in a plain zip archive");
                   3150:                }
                   3151:                return;
                   3152:        }
                   3153: 
                   3154:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s", &index, &index_len, &webindex, &webindex_len) == FAILURE) {
                   3155:                RETURN_FALSE;
                   3156:        }
                   3157: 
                   3158:        if (ZEND_NUM_ARGS() > 0 && (phar_obj->arc.archive->is_tar || phar_obj->arc.archive->is_zip)) {
                   3159:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "method accepts no arguments for a tar- or zip-based phar stub, %d given", ZEND_NUM_ARGS());
                   3160:                RETURN_FALSE;
                   3161:        }
                   3162: 
                   3163:        if (PHAR_G(readonly)) {
                   3164:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3165:                        "Cannot change stub: phar.readonly=1");
                   3166:                RETURN_FALSE;
                   3167:        }
                   3168: 
                   3169:        if (!phar_obj->arc.archive->is_tar && !phar_obj->arc.archive->is_zip) {
                   3170:                stub = phar_create_default_stub(index, webindex, &stub_len, &error TSRMLS_CC);
                   3171: 
                   3172:                if (error) {
                   3173:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "%s", error);
                   3174:                        efree(error);
                   3175:                        if (stub) {
                   3176:                                efree(stub);
                   3177:                        }
                   3178:                        RETURN_FALSE;
                   3179:                }
                   3180: 
                   3181:                created_stub = 1;
                   3182:        }
                   3183: 
                   3184:        if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
                   3185:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
                   3186:                return;
                   3187:        }
                   3188:        phar_flush(phar_obj->arc.archive, stub, stub_len, 1, &error TSRMLS_CC);
                   3189: 
                   3190:        if (created_stub) {
                   3191:                efree(stub);
                   3192:        }
                   3193: 
                   3194:        if (error) {
                   3195:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   3196:                efree(error);
                   3197:                RETURN_FALSE;
                   3198:        }
                   3199: 
                   3200:        RETURN_TRUE;
                   3201: }
                   3202: /* }}} */
                   3203: 
                   3204: /* {{{ proto array Phar::setSignatureAlgorithm(int sigtype[, string privatekey])
                   3205:  * Sets the signature algorithm for a phar and applies it. The signature
                   3206:  * algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256,
                   3207:  * Phar::SHA512, or Phar::OPENSSL. Note that zip- based phar archives
                   3208:  * cannot support signatures.
                   3209:  */
                   3210: PHP_METHOD(Phar, setSignatureAlgorithm)
                   3211: {
                   3212:        long algo;
                   3213:        char *error, *key = NULL;
                   3214:        int key_len = 0;
                   3215: 
                   3216:        PHAR_ARCHIVE_OBJECT();
                   3217: 
                   3218:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   3219:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3220:                        "Cannot set signature algorithm, phar is read-only");
                   3221:                return;
                   3222:        }
                   3223: 
                   3224:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &algo, &key, &key_len) != SUCCESS) {
                   3225:                return;
                   3226:        }
                   3227: 
                   3228:        switch (algo) {
                   3229:                case PHAR_SIG_SHA256:
                   3230:                case PHAR_SIG_SHA512:
                   3231: #ifndef PHAR_HASH_OK
                   3232:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3233:                                "SHA-256 and SHA-512 signatures are only supported if the hash extension is enabled and built non-shared");
                   3234:                        return;
                   3235: #endif
                   3236:                case PHAR_SIG_MD5:
                   3237:                case PHAR_SIG_SHA1:
                   3238:                case PHAR_SIG_OPENSSL:
                   3239:                        if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
                   3240:                                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
                   3241:                                return;
                   3242:                        }
                   3243:                        phar_obj->arc.archive->sig_flags = algo;
                   3244:                        phar_obj->arc.archive->is_modified = 1;
                   3245:                        PHAR_G(openssl_privatekey) = key;
                   3246:                        PHAR_G(openssl_privatekey_len) = key_len;
                   3247: 
                   3248:                        phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
                   3249:                        if (error) {
                   3250:                                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   3251:                                efree(error);
                   3252:                        }
                   3253:                        break;
                   3254:                default:
                   3255:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3256:                                "Unknown signature algorithm specified");
                   3257:        }
                   3258: }
                   3259: /* }}} */
                   3260: 
                   3261: /* {{{ proto array|false Phar::getSignature()
                   3262:  * Returns a hash signature, or FALSE if the archive is unsigned.
                   3263:  */
                   3264: PHP_METHOD(Phar, getSignature)
                   3265: {
                   3266:        PHAR_ARCHIVE_OBJECT();
                   3267:        
                   3268:        if (zend_parse_parameters_none() == FAILURE) {
                   3269:                return;
                   3270:        }
                   3271: 
                   3272:        if (phar_obj->arc.archive->signature) {
                   3273:                char *unknown;
                   3274:                int unknown_len;
                   3275: 
                   3276:                array_init(return_value);
                   3277:                add_assoc_stringl(return_value, "hash", phar_obj->arc.archive->signature, phar_obj->arc.archive->sig_len, 1);
                   3278:                switch(phar_obj->arc.archive->sig_flags) {
                   3279:                        case PHAR_SIG_MD5:
                   3280:                                add_assoc_stringl(return_value, "hash_type", "MD5", 3, 1);
                   3281:                                break;
                   3282:                        case PHAR_SIG_SHA1:
                   3283:                                add_assoc_stringl(return_value, "hash_type", "SHA-1", 5, 1);
                   3284:                                break;
                   3285:                        case PHAR_SIG_SHA256:
                   3286:                                add_assoc_stringl(return_value, "hash_type", "SHA-256", 7, 1);
                   3287:                                break;
                   3288:                        case PHAR_SIG_SHA512:
                   3289:                                add_assoc_stringl(return_value, "hash_type", "SHA-512", 7, 1);
                   3290:                                break;
                   3291:                        case PHAR_SIG_OPENSSL:
                   3292:                                add_assoc_stringl(return_value, "hash_type", "OpenSSL", 7, 1);
                   3293:                                break;
                   3294:                        default:
                   3295:                                unknown_len = spprintf(&unknown, 0, "Unknown (%u)", phar_obj->arc.archive->sig_flags);
                   3296:                                add_assoc_stringl(return_value, "hash_type", unknown, unknown_len, 0);
                   3297:                                break;
                   3298:                }
                   3299:        } else {
                   3300:                RETURN_FALSE;
                   3301:        }
                   3302: }
                   3303: /* }}} */
                   3304: 
                   3305: /* {{{ proto bool Phar::getModified()
                   3306:  * Return whether phar was modified
                   3307:  */
                   3308: PHP_METHOD(Phar, getModified)
                   3309: {
                   3310:        PHAR_ARCHIVE_OBJECT();
                   3311:        
                   3312:        if (zend_parse_parameters_none() == FAILURE) {
                   3313:                return;
                   3314:        }
                   3315: 
                   3316:        RETURN_BOOL(phar_obj->arc.archive->is_modified);
                   3317: }
                   3318: /* }}} */
                   3319: 
                   3320: static int phar_set_compression(void *pDest, void *argument TSRMLS_DC) /* {{{ */
                   3321: {
                   3322:        phar_entry_info *entry = (phar_entry_info *)pDest;
                   3323:        php_uint32 compress = *(php_uint32 *)argument;
                   3324: 
                   3325:        if (entry->is_deleted) {
                   3326:                return ZEND_HASH_APPLY_KEEP;
                   3327:        }
                   3328: 
                   3329:        entry->old_flags = entry->flags;
                   3330:        entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
                   3331:        entry->flags |= compress;
                   3332:        entry->is_modified = 1;
                   3333:        return ZEND_HASH_APPLY_KEEP;
                   3334: }
                   3335: /* }}} */
                   3336: 
                   3337: static int phar_test_compression(void *pDest, void *argument TSRMLS_DC) /* {{{ */
                   3338: {
                   3339:        phar_entry_info *entry = (phar_entry_info *)pDest;
                   3340: 
                   3341:        if (entry->is_deleted) {
                   3342:                return ZEND_HASH_APPLY_KEEP;
                   3343:        }
                   3344: 
                   3345:        if (!PHAR_G(has_bz2)) {
                   3346:                if (entry->flags & PHAR_ENT_COMPRESSED_BZ2) {
                   3347:                        *(int *) argument = 0;
                   3348:                }
                   3349:        }
                   3350: 
                   3351:        if (!PHAR_G(has_zlib)) {
                   3352:                if (entry->flags & PHAR_ENT_COMPRESSED_GZ) {
                   3353:                        *(int *) argument = 0;
                   3354:                }
                   3355:        }
                   3356: 
                   3357:        return ZEND_HASH_APPLY_KEEP;
                   3358: }
                   3359: /* }}} */
                   3360: 
                   3361: static void pharobj_set_compression(HashTable *manifest, php_uint32 compress TSRMLS_DC) /* {{{ */
                   3362: {
                   3363:        zend_hash_apply_with_argument(manifest, phar_set_compression, &compress TSRMLS_CC);
                   3364: }
                   3365: /* }}} */
                   3366: 
                   3367: static int pharobj_cancompress(HashTable *manifest TSRMLS_DC) /* {{{ */
                   3368: {
                   3369:        int test;
                   3370: 
                   3371:        test = 1;
                   3372:        zend_hash_apply_with_argument(manifest, phar_test_compression, &test TSRMLS_CC);
                   3373:        return test;
                   3374: }
                   3375: /* }}} */
                   3376: 
                   3377: /* {{{ proto object Phar::compress(int method[, string extension])
                   3378:  * Compress a .tar, or .phar.tar with whole-file compression
                   3379:  * The parameter can be one of Phar::GZ or Phar::BZ2 to specify
                   3380:  * the kind of compression desired
                   3381:  */
                   3382: PHP_METHOD(Phar, compress)
                   3383: {
                   3384:        long method;
                   3385:        char *ext = NULL;
                   3386:        int ext_len = 0;
                   3387:        php_uint32 flags;
                   3388:        zval *ret;
                   3389:        PHAR_ARCHIVE_OBJECT();
                   3390: 
                   3391:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &method, &ext, &ext_len) == FAILURE) {
                   3392:                return;
                   3393:        }
                   3394: 
                   3395:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   3396:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3397:                        "Cannot compress phar archive, phar is read-only");
                   3398:                return;
                   3399:        }
                   3400: 
                   3401:        if (phar_obj->arc.archive->is_zip) {
                   3402:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3403:                        "Cannot compress zip-based archives with whole-archive compression");
                   3404:                return;
                   3405:        }
                   3406: 
                   3407:        switch (method) {
                   3408:                case 0:
                   3409:                        flags = PHAR_FILE_COMPRESSED_NONE;
                   3410:                        break;
                   3411:                case PHAR_ENT_COMPRESSED_GZ:
                   3412:                        if (!PHAR_G(has_zlib)) {
                   3413:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   3414:                                        "Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
                   3415:                                return;
                   3416:                        }
                   3417:                        flags = PHAR_FILE_COMPRESSED_GZ;
                   3418:                        break;
                   3419: 
                   3420:                case PHAR_ENT_COMPRESSED_BZ2:
                   3421:                        if (!PHAR_G(has_bz2)) {
                   3422:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   3423:                                        "Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
                   3424:                                return;
                   3425:                        }
                   3426:                        flags = PHAR_FILE_COMPRESSED_BZ2;
                   3427:                        break;
                   3428:                default:
                   3429:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   3430:                                "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
                   3431:                        return;
                   3432:        }
                   3433: 
                   3434:        if (phar_obj->arc.archive->is_tar) {
                   3435:                ret = phar_convert_to_other(phar_obj->arc.archive, PHAR_FORMAT_TAR, ext, flags TSRMLS_CC);
                   3436:        } else {
                   3437:                ret = phar_convert_to_other(phar_obj->arc.archive, PHAR_FORMAT_PHAR, ext, flags TSRMLS_CC);
                   3438:        }
                   3439: 
                   3440:        if (ret) {
                   3441:                RETURN_ZVAL(ret, 1, 1);
                   3442:        } else {
                   3443:                RETURN_NULL();
                   3444:        }
                   3445: }
                   3446: /* }}} */
                   3447: 
                   3448: /* {{{ proto object Phar::decompress([string extension])
                   3449:  * Decompress a .tar, or .phar.tar with whole-file compression
                   3450:  */
                   3451: PHP_METHOD(Phar, decompress)
                   3452: {
                   3453:        char *ext = NULL;
                   3454:        int ext_len = 0;
                   3455:        zval *ret;
                   3456:        PHAR_ARCHIVE_OBJECT();
                   3457: 
                   3458:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ext, &ext_len) == FAILURE) {
                   3459:                return;
                   3460:        }
                   3461: 
                   3462:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   3463:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3464:                        "Cannot decompress phar archive, phar is read-only");
                   3465:                return;
                   3466:        }
                   3467: 
                   3468:        if (phar_obj->arc.archive->is_zip) {
                   3469:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3470:                        "Cannot decompress zip-based archives with whole-archive compression");
                   3471:                return;
                   3472:        }
                   3473: 
                   3474:        if (phar_obj->arc.archive->is_tar) {
                   3475:                ret = phar_convert_to_other(phar_obj->arc.archive, PHAR_FORMAT_TAR, ext, PHAR_FILE_COMPRESSED_NONE TSRMLS_CC);
                   3476:        } else {
                   3477:                ret = phar_convert_to_other(phar_obj->arc.archive, PHAR_FORMAT_PHAR, ext, PHAR_FILE_COMPRESSED_NONE TSRMLS_CC);
                   3478:        }
                   3479: 
                   3480:        if (ret) {
                   3481:                RETURN_ZVAL(ret, 1, 1);
                   3482:        } else {
                   3483:                RETURN_NULL();
                   3484:        }
                   3485: }
                   3486: /* }}} */
                   3487: 
                   3488: /* {{{ proto object Phar::compressFiles(int method)
                   3489:  * Compress all files within a phar or zip archive using the specified compression
                   3490:  * The parameter can be one of Phar::GZ or Phar::BZ2 to specify
                   3491:  * the kind of compression desired
                   3492:  */
                   3493: PHP_METHOD(Phar, compressFiles)
                   3494: {
                   3495:        char *error;
                   3496:        php_uint32 flags;
                   3497:        long method;
                   3498:        PHAR_ARCHIVE_OBJECT();
                   3499: 
                   3500:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method) == FAILURE) {
                   3501:                return;
                   3502:        }
                   3503: 
                   3504:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   3505:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   3506:                        "Phar is readonly, cannot change compression");
                   3507:                return;
                   3508:        }
                   3509: 
                   3510:        switch (method) {
                   3511:                case PHAR_ENT_COMPRESSED_GZ:
                   3512:                        if (!PHAR_G(has_zlib)) {
                   3513:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   3514:                                        "Cannot compress files within archive with gzip, enable ext/zlib in php.ini");
                   3515:                                return;
                   3516:                        }
                   3517:                        flags = PHAR_ENT_COMPRESSED_GZ;
                   3518:                        break;
                   3519: 
                   3520:                case PHAR_ENT_COMPRESSED_BZ2:
                   3521:                        if (!PHAR_G(has_bz2)) {
                   3522:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   3523:                                        "Cannot compress files within archive with bz2, enable ext/bz2 in php.ini");
                   3524:                                return;
                   3525:                        }
                   3526:                        flags = PHAR_ENT_COMPRESSED_BZ2;
                   3527:                        break;
                   3528:                default:
                   3529:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   3530:                                "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
                   3531:                        return;
                   3532:        }
                   3533: 
                   3534:        if (phar_obj->arc.archive->is_tar) {
                   3535:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   3536:                        "Cannot compress with Gzip compression, tar archives cannot compress individual files, use compress() to compress the whole archive");
                   3537:                return;
                   3538:        }
                   3539: 
                   3540:        if (!pharobj_cancompress(&phar_obj->arc.archive->manifest TSRMLS_CC)) {
                   3541:                if (flags == PHAR_FILE_COMPRESSED_GZ) {
                   3542:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   3543:                                "Cannot compress all files as Gzip, some are compressed as bzip2 and cannot be decompressed");
                   3544:                } else {
                   3545:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   3546:                                "Cannot compress all files as Bzip2, some are compressed as gzip and cannot be decompressed");
                   3547:                }
                   3548:                return;
                   3549:        }
                   3550: 
                   3551:        if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
                   3552:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
                   3553:                return;
                   3554:        }
                   3555:        pharobj_set_compression(&phar_obj->arc.archive->manifest, flags TSRMLS_CC);
                   3556:        phar_obj->arc.archive->is_modified = 1;
                   3557:        phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
                   3558: 
                   3559:        if (error) {
                   3560:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s", error);
                   3561:                efree(error);
                   3562:        }
                   3563: }
                   3564: /* }}} */
                   3565: 
                   3566: /* {{{ proto bool Phar::decompressFiles()
                   3567:  * decompress every file
                   3568:  */
                   3569: PHP_METHOD(Phar, decompressFiles)
                   3570: {
                   3571:        char *error;
                   3572:        PHAR_ARCHIVE_OBJECT();
                   3573:        
                   3574:        if (zend_parse_parameters_none() == FAILURE) {
                   3575:                return;
                   3576:        }
                   3577: 
                   3578:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   3579:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   3580:                        "Phar is readonly, cannot change compression");
                   3581:                return;
                   3582:        }
                   3583: 
                   3584:        if (!pharobj_cancompress(&phar_obj->arc.archive->manifest TSRMLS_CC)) {
                   3585:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   3586:                        "Cannot decompress all files, some are compressed as bzip2 or gzip and cannot be decompressed");
                   3587:                return;
                   3588:        }
                   3589: 
                   3590:        if (phar_obj->arc.archive->is_tar) {
                   3591:                RETURN_TRUE;
                   3592:        } else {
                   3593:                if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
                   3594:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
                   3595:                        return;
                   3596:                }
                   3597:                pharobj_set_compression(&phar_obj->arc.archive->manifest, PHAR_ENT_COMPRESSED_NONE TSRMLS_CC);
                   3598:        }
                   3599: 
                   3600:        phar_obj->arc.archive->is_modified = 1;
                   3601:        phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
                   3602: 
                   3603:        if (error) {
                   3604:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "%s", error);
                   3605:                efree(error);
                   3606:        }
                   3607: 
                   3608:        RETURN_TRUE;
                   3609: }
                   3610: /* }}} */
                   3611: 
                   3612: /* {{{ proto bool Phar::copy(string oldfile, string newfile)
                   3613:  * copy a file internal to the phar archive to another new file within the phar
                   3614:  */
                   3615: PHP_METHOD(Phar, copy)
                   3616: {
                   3617:        char *oldfile, *newfile, *error;
                   3618:        const char *pcr_error;
                   3619:        int oldfile_len, newfile_len;
                   3620:        phar_entry_info *oldentry, newentry = {0}, *temp;
                   3621: 
                   3622:        PHAR_ARCHIVE_OBJECT();
                   3623: 
                   3624:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &oldfile, &oldfile_len, &newfile, &newfile_len) == FAILURE) {
                   3625:                return;
                   3626:        }
                   3627: 
                   3628:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   3629:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3630:                        "Cannot copy \"%s\" to \"%s\", phar is read-only", oldfile, newfile);
                   3631:                RETURN_FALSE;
                   3632:        }
                   3633: 
                   3634:        if (oldfile_len >= sizeof(".phar")-1 && !memcmp(oldfile, ".phar", sizeof(".phar")-1)) {
                   3635:                /* can't copy a meta file */
                   3636:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3637:                        "file \"%s\" cannot be copied to file \"%s\", cannot copy Phar meta-file in %s", oldfile, newfile, phar_obj->arc.archive->fname);
                   3638:                RETURN_FALSE;
                   3639:        }
                   3640: 
                   3641:        if (newfile_len >= sizeof(".phar")-1 && !memcmp(newfile, ".phar", sizeof(".phar")-1)) {
                   3642:                /* can't copy a meta file */
                   3643:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3644:                        "file \"%s\" cannot be copied to file \"%s\", cannot copy to Phar meta-file in %s", oldfile, newfile, phar_obj->arc.archive->fname);
                   3645:                RETURN_FALSE;
                   3646:        }
                   3647: 
                   3648:        if (!zend_hash_exists(&phar_obj->arc.archive->manifest, oldfile, (uint) oldfile_len) || SUCCESS != zend_hash_find(&phar_obj->arc.archive->manifest, oldfile, (uint) oldfile_len, (void**)&oldentry) || oldentry->is_deleted) {
                   3649:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3650:                        "file \"%s\" cannot be copied to file \"%s\", file does not exist in %s", oldfile, newfile, phar_obj->arc.archive->fname);
                   3651:                RETURN_FALSE;
                   3652:        }
                   3653: 
                   3654:        if (zend_hash_exists(&phar_obj->arc.archive->manifest, newfile, (uint) newfile_len)) {
                   3655:                if (SUCCESS == zend_hash_find(&phar_obj->arc.archive->manifest, newfile, (uint) newfile_len, (void**)&temp) || !temp->is_deleted) {
                   3656:                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3657:                                "file \"%s\" cannot be copied to file \"%s\", file must not already exist in phar %s", oldfile, newfile, phar_obj->arc.archive->fname);
                   3658:                        RETURN_FALSE;
                   3659:                }
                   3660:        }
                   3661: 
                   3662:        if (phar_path_check(&newfile, &newfile_len, &pcr_error) > pcr_is_ok) {
                   3663:                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC,
                   3664:                                "file \"%s\" contains invalid characters %s, cannot be copied from \"%s\" in phar %s", newfile, pcr_error, oldfile, phar_obj->arc.archive->fname);
                   3665:                RETURN_FALSE;
                   3666:        }
                   3667: 
                   3668:        if (phar_obj->arc.archive->is_persistent) {
                   3669:                if (FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
                   3670:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
                   3671:                        return;
                   3672:                }
                   3673:                /* re-populate with copied-on-write entry */
                   3674:                zend_hash_find(&phar_obj->arc.archive->manifest, oldfile, (uint) oldfile_len, (void**)&oldentry);
                   3675:        }
                   3676: 
                   3677:        memcpy((void *) &newentry, oldentry, sizeof(phar_entry_info));
                   3678: 
                   3679:        if (newentry.metadata) {
                   3680:                zval *t;
                   3681: 
                   3682:                t = newentry.metadata;
                   3683:                ALLOC_ZVAL(newentry.metadata);
                   3684:                *newentry.metadata = *t;
                   3685:                zval_copy_ctor(newentry.metadata);
                   3686: #if PHP_VERSION_ID < 50300
                   3687:                newentry.metadata->refcount = 1;
                   3688: #else
                   3689:                Z_SET_REFCOUNT_P(newentry.metadata, 1);
                   3690: #endif
                   3691: 
                   3692:                newentry.metadata_str.c = NULL;
                   3693:                newentry.metadata_str.len = 0;
                   3694:        }
                   3695: 
                   3696:        newentry.filename = estrndup(newfile, newfile_len);
                   3697:        newentry.filename_len = newfile_len;
                   3698:        newentry.fp_refcount = 0;
                   3699: 
                   3700:        if (oldentry->fp_type != PHAR_FP) {
                   3701:                if (FAILURE == phar_copy_entry_fp(oldentry, &newentry, &error TSRMLS_CC)) {
                   3702:                        efree(newentry.filename);
                   3703:                        php_stream_close(newentry.fp);
                   3704:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   3705:                        efree(error);
                   3706:                        return;
                   3707:                }
                   3708:        }
                   3709: 
                   3710:        zend_hash_add(&oldentry->phar->manifest, newfile, newfile_len, (void*)&newentry, sizeof(phar_entry_info), NULL);
                   3711:        phar_obj->arc.archive->is_modified = 1;
                   3712:        phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
                   3713: 
                   3714:        if (error) {
                   3715:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   3716:                efree(error);
                   3717:        }
                   3718: 
                   3719:        RETURN_TRUE;
                   3720: }
                   3721: /* }}} */
                   3722: 
                   3723: /* {{{ proto int Phar::offsetExists(string entry)
                   3724:  * determines whether a file exists in the phar
                   3725:  */
                   3726: PHP_METHOD(Phar, offsetExists)
                   3727: {
                   3728:        char *fname;
                   3729:        int fname_len;
                   3730:        phar_entry_info *entry;
                   3731: 
                   3732:        PHAR_ARCHIVE_OBJECT();
                   3733: 
                   3734:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
                   3735:                return;
                   3736:        }
                   3737: 
                   3738:        if (zend_hash_exists(&phar_obj->arc.archive->manifest, fname, (uint) fname_len)) {
                   3739:                if (SUCCESS == zend_hash_find(&phar_obj->arc.archive->manifest, fname, (uint) fname_len, (void**)&entry)) {
                   3740:                        if (entry->is_deleted) {
                   3741:                                /* entry is deleted, but has not been flushed to disk yet */
                   3742:                                RETURN_FALSE;
                   3743:                        }
                   3744:                }
                   3745: 
                   3746:                if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
                   3747:                        /* none of these are real files, so they don't exist */
                   3748:                        RETURN_FALSE;
                   3749:                }
                   3750:                RETURN_TRUE;
                   3751:        } else {
                   3752:                if (zend_hash_exists(&phar_obj->arc.archive->virtual_dirs, fname, (uint) fname_len)) {
                   3753:                        RETURN_TRUE;
                   3754:                }
                   3755:                RETURN_FALSE;
                   3756:        }
                   3757: }
                   3758: /* }}} */
                   3759: 
                   3760: /* {{{ proto int Phar::offsetGet(string entry)
                   3761:  * get a PharFileInfo object for a specific file
                   3762:  */
                   3763: PHP_METHOD(Phar, offsetGet)
                   3764: {
                   3765:        char *fname, *error;
                   3766:        int fname_len;
                   3767:        zval *zfname;
                   3768:        phar_entry_info *entry;
                   3769:        PHAR_ARCHIVE_OBJECT();
                   3770: 
                   3771:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
                   3772:                return;
                   3773:        }
                   3774: 
                   3775:        /* security is 0 here so that we can get a better error message than "entry doesn't exist" */
                   3776:        if (!(entry = phar_get_entry_info_dir(phar_obj->arc.archive, fname, fname_len, 1, &error, 0 TSRMLS_CC))) {
                   3777:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist%s%s", fname, error?", ":"", error?error:"");
                   3778:        } else {
                   3779:                if (fname_len == sizeof(".phar/stub.php")-1 && !memcmp(fname, ".phar/stub.php", sizeof(".phar/stub.php")-1)) {
                   3780:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot get stub \".phar/stub.php\" directly in phar \"%s\", use getStub", phar_obj->arc.archive->fname);
                   3781:                        return;
                   3782:                }
                   3783: 
                   3784:                if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
                   3785:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot get alias \".phar/alias.txt\" directly in phar \"%s\", use getAlias", phar_obj->arc.archive->fname);
                   3786:                        return;
                   3787:                }
                   3788: 
                   3789:                if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
                   3790:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot directly get any files or directories in magic \".phar\" directory", phar_obj->arc.archive->fname);
                   3791:                        return;
                   3792:                }
                   3793: 
                   3794:                if (entry->is_temp_dir) {
                   3795:                        efree(entry->filename);
                   3796:                        efree(entry);
                   3797:                }
                   3798: 
                   3799:                fname_len = spprintf(&fname, 0, "phar://%s/%s", phar_obj->arc.archive->fname, fname);
                   3800:                MAKE_STD_ZVAL(zfname);
                   3801:                ZVAL_STRINGL(zfname, fname, fname_len, 0);
                   3802:                spl_instantiate_arg_ex1(phar_obj->spl.info_class, &return_value, 0, zfname TSRMLS_CC);
                   3803:                zval_ptr_dtor(&zfname);
                   3804:        }
                   3805: }
                   3806: /* }}} */
                   3807: 
                   3808: /* {{{ add a file within the phar archive from a string or resource
                   3809:  */
                   3810: static void phar_add_file(phar_archive_data **pphar, char *filename, int filename_len, char *cont_str, int cont_len, zval *zresource TSRMLS_DC)
                   3811: {
                   3812:        char *error;
                   3813:        size_t contents_len;
                   3814:        phar_entry_data *data;
                   3815:        php_stream *contents_file;
                   3816: 
                   3817:        if (filename_len >= sizeof(".phar")-1 && !memcmp(filename, ".phar", sizeof(".phar")-1)) {
                   3818:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot create any files in magic \".phar\" directory", (*pphar)->fname);
                   3819:                return;
                   3820:        }
                   3821: 
                   3822:        if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, filename, filename_len, "w+b", 0, &error, 1 TSRMLS_CC))) {
                   3823:                if (error) {
                   3824:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist and cannot be created: %s", filename, error);
                   3825:                        efree(error);
                   3826:                } else {
                   3827:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist and cannot be created", filename);
                   3828:                }
                   3829:                return;
                   3830:        } else {
                   3831:                if (error) {
                   3832:                        efree(error);
                   3833:                }
                   3834: 
                   3835:                if (!data->internal_file->is_dir) {
                   3836:                        if (cont_str) {
                   3837:                                contents_len = php_stream_write(data->fp, cont_str, cont_len);
                   3838:                                if (contents_len != cont_len) {
                   3839:                                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s could not be written to", filename);
                   3840:                                        return;
                   3841:                                }
                   3842:                        } else {
                   3843:                                if (!(php_stream_from_zval_no_verify(contents_file, &zresource))) {
                   3844:                                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s could not be written to", filename);
                   3845:                                        return;
                   3846:                                }
                   3847:                                phar_stream_copy_to_stream(contents_file, data->fp, PHP_STREAM_COPY_ALL, &contents_len);
                   3848:                        }
                   3849: 
                   3850:                        data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len;
                   3851:                }
                   3852: 
                   3853:                /* check for copy-on-write */
                   3854:                if (pphar[0] != data->phar) {
                   3855:                        *pphar = data->phar;
                   3856:                }
                   3857:                phar_entry_delref(data TSRMLS_CC);
                   3858:                phar_flush(*pphar, 0, 0, 0, &error TSRMLS_CC);
                   3859: 
                   3860:                if (error) {
                   3861:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   3862:                        efree(error);
                   3863:                }
                   3864:        }
                   3865: }
                   3866: /* }}} */
                   3867: 
                   3868: /* {{{ create a directory within the phar archive
                   3869:  */
                   3870: static void phar_mkdir(phar_archive_data **pphar, char *dirname, int dirname_len TSRMLS_DC)
                   3871: {
                   3872:        char *error;
                   3873:        phar_entry_data *data;
                   3874: 
                   3875:        if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, dirname, dirname_len, "w+b", 2, &error, 1 TSRMLS_CC))) {
                   3876:                if (error) {
                   3877:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Directory %s does not exist and cannot be created: %s", dirname, error);
                   3878:                        efree(error);
                   3879:                } else {
                   3880:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Directory %s does not exist and cannot be created", dirname);
                   3881:                }
                   3882: 
                   3883:                return;
                   3884:        } else {
                   3885:                if (error) {
                   3886:                        efree(error);
                   3887:                }
                   3888: 
                   3889:                /* check for copy on write */
                   3890:                if (data->phar != *pphar) {
                   3891:                        *pphar = data->phar;
                   3892:                }
                   3893:                phar_entry_delref(data TSRMLS_CC);
                   3894:                phar_flush(*pphar, 0, 0, 0, &error TSRMLS_CC);
                   3895: 
                   3896:                if (error) {
                   3897:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   3898:                        efree(error);
                   3899:                }
                   3900:        }
                   3901: }
                   3902: /* }}} */
                   3903: 
                   3904: /* {{{ proto int Phar::offsetSet(string entry, string value)
                   3905:  * set the contents of an internal file to those of an external file
                   3906:  */
                   3907: PHP_METHOD(Phar, offsetSet)
                   3908: {
                   3909:        char *fname, *cont_str = NULL;
                   3910:        int fname_len, cont_len;
                   3911:        zval *zresource;
                   3912:        PHAR_ARCHIVE_OBJECT();
                   3913: 
                   3914:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   3915:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by the php.ini setting phar.readonly");
                   3916:                return;
                   3917:        }
                   3918: 
                   3919:        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "sr", &fname, &fname_len, &zresource) == FAILURE
                   3920:        && zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &fname, &fname_len, &cont_str, &cont_len) == FAILURE) {
                   3921:                return;
                   3922:        }
                   3923: 
                   3924:        if (fname_len == sizeof(".phar/stub.php")-1 && !memcmp(fname, ".phar/stub.php", sizeof(".phar/stub.php")-1)) {
                   3925:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot set stub \".phar/stub.php\" directly in phar \"%s\", use setStub", phar_obj->arc.archive->fname);
                   3926:                return;
                   3927:        }
                   3928: 
                   3929:        if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
                   3930:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot set alias \".phar/alias.txt\" directly in phar \"%s\", use setAlias", phar_obj->arc.archive->fname);
                   3931:                return;
                   3932:        }
                   3933: 
                   3934:        if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
                   3935:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot set any files or directories in magic \".phar\" directory", phar_obj->arc.archive->fname);
                   3936:                return;
                   3937:        }
                   3938: 
                   3939:        phar_add_file(&(phar_obj->arc.archive), fname, fname_len, cont_str, cont_len, zresource TSRMLS_CC);
                   3940: }
                   3941: /* }}} */
                   3942: 
                   3943: /* {{{ proto int Phar::offsetUnset(string entry)
                   3944:  * remove a file from a phar
                   3945:  */
                   3946: PHP_METHOD(Phar, offsetUnset)
                   3947: {
                   3948:        char *fname, *error;
                   3949:        int fname_len;
                   3950:        phar_entry_info *entry;
                   3951:        PHAR_ARCHIVE_OBJECT();
                   3952: 
                   3953:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   3954:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by the php.ini setting phar.readonly");
                   3955:                return;
                   3956:        }
                   3957: 
                   3958:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
                   3959:                return;
                   3960:        }
                   3961: 
                   3962:        if (zend_hash_exists(&phar_obj->arc.archive->manifest, fname, (uint) fname_len)) {
                   3963:                if (SUCCESS == zend_hash_find(&phar_obj->arc.archive->manifest, fname, (uint) fname_len, (void**)&entry)) {
                   3964:                        if (entry->is_deleted) {
                   3965:                                /* entry is deleted, but has not been flushed to disk yet */
                   3966:                                return;
                   3967:                        }
                   3968: 
                   3969:                        if (phar_obj->arc.archive->is_persistent) {
                   3970:                                if (FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
                   3971:                                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
                   3972:                                        return;
                   3973:                                }
                   3974:                                /* re-populate entry after copy on write */
                   3975:                                zend_hash_find(&phar_obj->arc.archive->manifest, fname, (uint) fname_len, (void **)&entry);
                   3976:                        }
                   3977:                        entry->is_modified = 0;
                   3978:                        entry->is_deleted = 1;
                   3979:                        /* we need to "flush" the stream to save the newly deleted file on disk */
                   3980:                        phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
                   3981: 
                   3982:                        if (error) {
                   3983:                                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   3984:                                efree(error);
                   3985:                        }
                   3986: 
                   3987:                        RETURN_TRUE;
                   3988:                }
                   3989:        } else {
                   3990:                RETURN_FALSE;
                   3991:        }
                   3992: }
                   3993: /* }}} */
                   3994: 
                   3995: /* {{{ proto string Phar::addEmptyDir(string dirname)
                   3996:  * Adds an empty directory to the phar archive
                   3997:  */
                   3998: PHP_METHOD(Phar, addEmptyDir)
                   3999: {
                   4000:        char *dirname;
                   4001:        int dirname_len;
                   4002: 
                   4003:        PHAR_ARCHIVE_OBJECT();
                   4004: 
                   4005:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &dirname, &dirname_len) == FAILURE) {
                   4006:                return;
                   4007:        }
                   4008: 
                   4009:        if (dirname_len >= sizeof(".phar")-1 && !memcmp(dirname, ".phar", sizeof(".phar")-1)) {
                   4010:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot create a directory in magic \".phar\" directory");
                   4011:                return;
                   4012:        }
                   4013: 
                   4014:        phar_mkdir(&phar_obj->arc.archive, dirname, dirname_len TSRMLS_CC);
                   4015: }
                   4016: /* }}} */
                   4017: 
                   4018: /* {{{ proto string Phar::addFile(string filename[, string localname])
                   4019:  * Adds a file to the archive using the filename, or the second parameter as the name within the archive
                   4020:  */
                   4021: PHP_METHOD(Phar, addFile)
                   4022: {
                   4023:        char *fname, *localname = NULL;
                   4024:        int fname_len, localname_len = 0;
                   4025:        php_stream *resource;
                   4026:        zval *zresource;
                   4027: 
                   4028:        PHAR_ARCHIVE_OBJECT();
                   4029: 
                   4030:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &fname, &fname_len, &localname, &localname_len) == FAILURE) {
                   4031:                return;
                   4032:        }
                   4033: 
                   4034: #if PHP_API_VERSION < 20100412
                   4035:        if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) {
                   4036:                zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "phar error: unable to open file \"%s\" to add to phar archive, safe_mode restrictions prevent this", fname);
                   4037:                return;
                   4038:        }
                   4039: #endif
                   4040: 
                   4041:        if (!strstr(fname, "://") && php_check_open_basedir(fname TSRMLS_CC)) {
                   4042:                zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "phar error: unable to open file \"%s\" to add to phar archive, open_basedir restrictions prevent this", fname);
                   4043:                return;
                   4044:        }
                   4045: 
                   4046:        if (!(resource = php_stream_open_wrapper(fname, "rb", 0, NULL))) {
                   4047:                zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC, "phar error: unable to open file \"%s\" to add to phar archive", fname);
                   4048:                return;
                   4049:        }
                   4050: 
                   4051:        if (localname) {
                   4052:                fname = localname;
                   4053:                fname_len = localname_len;
                   4054:        }
                   4055: 
                   4056:        MAKE_STD_ZVAL(zresource);
                   4057:        php_stream_to_zval(resource, zresource);
                   4058:        phar_add_file(&(phar_obj->arc.archive), fname, fname_len, NULL, 0, zresource TSRMLS_CC);
                   4059:        efree(zresource);
                   4060:        php_stream_close(resource);
                   4061: }
                   4062: /* }}} */
                   4063: 
                   4064: /* {{{ proto string Phar::addFromString(string localname, string contents)
                   4065:  * Adds a file to the archive using its contents as a string
                   4066:  */
                   4067: PHP_METHOD(Phar, addFromString)
                   4068: {
                   4069:        char *localname, *cont_str;
                   4070:        int localname_len, cont_len;
                   4071: 
                   4072:        PHAR_ARCHIVE_OBJECT();
                   4073: 
                   4074:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &localname, &localname_len, &cont_str, &cont_len) == FAILURE) {
                   4075:                return;
                   4076:        }
                   4077: 
                   4078:        phar_add_file(&(phar_obj->arc.archive), localname, localname_len, cont_str, cont_len, NULL TSRMLS_CC);
                   4079: }
                   4080: /* }}} */
                   4081: 
                   4082: /* {{{ proto string Phar::getStub()
                   4083:  * Returns the stub at the head of a phar archive as a string.
                   4084:  */
                   4085: PHP_METHOD(Phar, getStub)
                   4086: {
                   4087:        size_t len;
                   4088:        char *buf;
                   4089:        php_stream *fp;
                   4090:        php_stream_filter *filter = NULL;
                   4091:        phar_entry_info *stub;
                   4092: 
                   4093:        PHAR_ARCHIVE_OBJECT();
                   4094:        
                   4095:        if (zend_parse_parameters_none() == FAILURE) {
                   4096:                return;
                   4097:        }
                   4098: 
                   4099:        if (phar_obj->arc.archive->is_tar || phar_obj->arc.archive->is_zip) {
                   4100: 
                   4101:                if (SUCCESS == zend_hash_find(&(phar_obj->arc.archive->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1, (void **)&stub)) {
                   4102:                        if (phar_obj->arc.archive->fp && !phar_obj->arc.archive->is_brandnew && !(stub->flags & PHAR_ENT_COMPRESSION_MASK)) {
                   4103:                                fp = phar_obj->arc.archive->fp;
                   4104:                        } else {
                   4105:                                if (!(fp = php_stream_open_wrapper(phar_obj->arc.archive->fname, "rb", 0, NULL))) {
                   4106:                                        zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "phar error: unable to open phar \"%s\"", phar_obj->arc.archive->fname);
                   4107:                                        return;
                   4108:                                }
                   4109:                                if (stub->flags & PHAR_ENT_COMPRESSION_MASK) {
                   4110:                                        char *filter_name;
                   4111: 
                   4112:                                        if ((filter_name = phar_decompress_filter(stub, 0)) != NULL) {
                   4113:                                                filter = php_stream_filter_create(filter_name, NULL, php_stream_is_persistent(fp) TSRMLS_CC);
                   4114:                                        } else {
                   4115:                                                filter = NULL;
                   4116:                                        }
                   4117:                                        if (!filter) {
                   4118:                                                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "phar error: unable to read stub of phar \"%s\" (cannot create %s filter)", phar_obj->arc.archive->fname, phar_decompress_filter(stub, 1));
                   4119:                                                return;
                   4120:                                        }
                   4121:                                        php_stream_filter_append(&fp->readfilters, filter);
                   4122:                                }
                   4123:                        }
                   4124: 
                   4125:                        if (!fp)  {
                   4126:                                zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC,
                   4127:                                        "Unable to read stub");
                   4128:                                return;
                   4129:                        }
                   4130: 
                   4131:                        php_stream_seek(fp, stub->offset_abs, SEEK_SET);
                   4132:                        len = stub->uncompressed_filesize;
                   4133:                        goto carry_on;
                   4134:                } else {
                   4135:                        RETURN_STRINGL("", 0, 1);
                   4136:                }
                   4137:        }
                   4138:        len = phar_obj->arc.archive->halt_offset;
                   4139: 
                   4140:        if (phar_obj->arc.archive->fp && !phar_obj->arc.archive->is_brandnew) {
                   4141:                fp = phar_obj->arc.archive->fp;
                   4142:        } else {
                   4143:                fp = php_stream_open_wrapper(phar_obj->arc.archive->fname, "rb", 0, NULL);
                   4144:        }
                   4145: 
                   4146:        if (!fp)  {
                   4147:                zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC,
                   4148:                        "Unable to read stub");
                   4149:                return;
                   4150:        }
                   4151: 
                   4152:        php_stream_rewind(fp);
                   4153: carry_on:
                   4154:        buf = safe_emalloc(len, 1, 1);
                   4155: 
                   4156:        if (len != php_stream_read(fp, buf, len)) {
                   4157:                if (fp != phar_obj->arc.archive->fp) {
                   4158:                        php_stream_close(fp);
                   4159:                }
                   4160:                zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC,
                   4161:                        "Unable to read stub");
                   4162:                efree(buf);
                   4163:                return;
                   4164:        }
                   4165: 
                   4166:        if (filter) {
                   4167:                php_stream_filter_flush(filter, 1);
                   4168:                php_stream_filter_remove(filter, 1 TSRMLS_CC);
                   4169:        }
                   4170: 
                   4171:        if (fp != phar_obj->arc.archive->fp) {
                   4172:                php_stream_close(fp);
                   4173:        }
                   4174: 
                   4175:        buf[len] = '\0';
                   4176:        RETURN_STRINGL(buf, len, 0);
                   4177: }
                   4178: /* }}}*/
                   4179: 
                   4180: /* {{{ proto int Phar::hasMetaData()
                   4181:  * Returns TRUE if the phar has global metadata, FALSE otherwise.
                   4182:  */
                   4183: PHP_METHOD(Phar, hasMetadata)
                   4184: {
                   4185:        PHAR_ARCHIVE_OBJECT();
                   4186: 
                   4187:        RETURN_BOOL(phar_obj->arc.archive->metadata != NULL);
                   4188: }
                   4189: /* }}} */
                   4190: 
                   4191: /* {{{ proto int Phar::getMetaData()
                   4192:  * Returns the global metadata of the phar
                   4193:  */
                   4194: PHP_METHOD(Phar, getMetadata)
                   4195: {
                   4196:        PHAR_ARCHIVE_OBJECT();
                   4197:        
                   4198:        if (zend_parse_parameters_none() == FAILURE) {
                   4199:                return;
                   4200:        }
                   4201: 
                   4202:        if (phar_obj->arc.archive->metadata) {
                   4203:                if (phar_obj->arc.archive->is_persistent) {
                   4204:                        zval *ret;
                   4205:                        char *buf = estrndup((char *) phar_obj->arc.archive->metadata, phar_obj->arc.archive->metadata_len);
                   4206:                        /* assume success, we would have failed before */
                   4207:                        phar_parse_metadata(&buf, &ret, phar_obj->arc.archive->metadata_len TSRMLS_CC);
                   4208:                        efree(buf);
                   4209:                        RETURN_ZVAL(ret, 0, 1);
                   4210:                }
                   4211:                RETURN_ZVAL(phar_obj->arc.archive->metadata, 1, 0);
                   4212:        }
                   4213: }
                   4214: /* }}} */
                   4215: 
                   4216: /* {{{ proto int Phar::setMetaData(mixed $metadata)
                   4217:  * Sets the global metadata of the phar
                   4218:  */
                   4219: PHP_METHOD(Phar, setMetadata)
                   4220: {
                   4221:        char *error;
                   4222:        zval *metadata;
                   4223: 
                   4224:        PHAR_ARCHIVE_OBJECT();
                   4225: 
                   4226:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   4227:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by the php.ini setting phar.readonly");
                   4228:                return;
                   4229:        }
                   4230: 
                   4231:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &metadata) == FAILURE) {
                   4232:                return;
                   4233:        }
                   4234: 
                   4235:        if (phar_obj->arc.archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->arc.archive) TSRMLS_CC)) {
                   4236:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar_obj->arc.archive->fname);
                   4237:                return;
                   4238:        }
                   4239:        if (phar_obj->arc.archive->metadata) {
                   4240:                zval_ptr_dtor(&phar_obj->arc.archive->metadata);
                   4241:                phar_obj->arc.archive->metadata = NULL;
                   4242:        }
                   4243: 
                   4244:        MAKE_STD_ZVAL(phar_obj->arc.archive->metadata);
                   4245:        ZVAL_ZVAL(phar_obj->arc.archive->metadata, metadata, 1, 0);
                   4246:        phar_obj->arc.archive->is_modified = 1;
                   4247:        phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
                   4248: 
                   4249:        if (error) {
                   4250:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   4251:                efree(error);
                   4252:        }
                   4253: }
                   4254: /* }}} */
                   4255: 
                   4256: /* {{{ proto int Phar::delMetadata()
                   4257:  * Deletes the global metadata of the phar
                   4258:  */
                   4259: PHP_METHOD(Phar, delMetadata)
                   4260: {
                   4261:        char *error;
                   4262: 
                   4263:        PHAR_ARCHIVE_OBJECT();
                   4264: 
                   4265:        if (PHAR_G(readonly) && !phar_obj->arc.archive->is_data) {
                   4266:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by the php.ini setting phar.readonly");
                   4267:                return;
                   4268:        }
                   4269: 
                   4270:        if (phar_obj->arc.archive->metadata) {
                   4271:                zval_ptr_dtor(&phar_obj->arc.archive->metadata);
                   4272:                phar_obj->arc.archive->metadata = NULL;
                   4273:                phar_obj->arc.archive->is_modified = 1;
                   4274:                phar_flush(phar_obj->arc.archive, 0, 0, 0, &error TSRMLS_CC);
                   4275: 
                   4276:                if (error) {
                   4277:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   4278:                        efree(error);
                   4279:                        RETURN_FALSE;
                   4280:                } else {
                   4281:                        RETURN_TRUE;
                   4282:                }
                   4283: 
                   4284:        } else {
                   4285:                RETURN_TRUE;
                   4286:        }
                   4287: }
                   4288: /* }}} */
                   4289: #if PHP_API_VERSION < 20100412
                   4290: #define PHAR_OPENBASEDIR_CHECKPATH(filename) \
                   4291:        (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC)
                   4292: #else
                   4293: #define PHAR_OPENBASEDIR_CHECKPATH(filename) \
                   4294:        php_check_open_basedir(filename TSRMLS_CC)
                   4295: #endif
                   4296: 
                   4297: static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *dest, int dest_len, char **error TSRMLS_DC) /* {{{ */
                   4298: {
                   4299:        php_stream_statbuf ssb;
                   4300:        int len;
                   4301:        php_stream *fp;
1.1.1.2 ! misho    4302:        char *fullpath;
        !          4303:        const char *slash;
1.1       misho    4304:        mode_t mode;
                   4305: 
                   4306:        if (entry->is_mounted) {
                   4307:                /* silently ignore mounted entries */
                   4308:                return SUCCESS;
                   4309:        }
                   4310: 
                   4311:        if (entry->filename_len >= sizeof(".phar")-1 && !memcmp(entry->filename, ".phar", sizeof(".phar")-1)) {
                   4312:                return SUCCESS;
                   4313:        }
                   4314: 
                   4315:        len = spprintf(&fullpath, 0, "%s/%s", dest, entry->filename);
                   4316: 
                   4317:        if (len >= MAXPATHLEN) {
                   4318:                char *tmp;
                   4319:                /* truncate for error message */
                   4320:                fullpath[50] = '\0';
                   4321:                if (entry->filename_len > 50) {
                   4322:                        tmp = estrndup(entry->filename, 50);
                   4323:                        spprintf(error, 4096, "Cannot extract \"%s...\" to \"%s...\", extracted filename is too long for filesystem", tmp, fullpath);
                   4324:                        efree(tmp);
                   4325:                } else {
                   4326:                        spprintf(error, 4096, "Cannot extract \"%s\" to \"%s...\", extracted filename is too long for filesystem", entry->filename, fullpath);
                   4327:                }
                   4328:                efree(fullpath);
                   4329:                return FAILURE;
                   4330:        }
                   4331: 
                   4332:        if (!len) {
                   4333:                spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename);
                   4334:                efree(fullpath);
                   4335:                return FAILURE;
                   4336:        }
                   4337: 
                   4338:        if (PHAR_OPENBASEDIR_CHECKPATH(fullpath)) {
                   4339:                spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", openbasedir/safe mode restrictions in effect", entry->filename, fullpath);
                   4340:                efree(fullpath);
                   4341:                return FAILURE;
                   4342:        }
                   4343: 
                   4344:        /* let see if the path already exists */
                   4345:        if (!overwrite && SUCCESS == php_stream_stat_path(fullpath, &ssb)) {
                   4346:                spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", path already exists", entry->filename, fullpath);
                   4347:                efree(fullpath);
                   4348:                return FAILURE;
                   4349:        }
                   4350: 
                   4351:        /* perform dirname */
                   4352:        slash = zend_memrchr(entry->filename, '/', entry->filename_len);
                   4353: 
                   4354:        if (slash) {
                   4355:                fullpath[dest_len + (slash - entry->filename) + 1] = '\0';
                   4356:        } else {
                   4357:                fullpath[dest_len] = '\0';
                   4358:        }
                   4359: 
                   4360:        if (FAILURE == php_stream_stat_path(fullpath, &ssb)) {
                   4361:                if (entry->is_dir) {
                   4362:                        if (!php_stream_mkdir(fullpath, entry->flags & PHAR_ENT_PERM_MASK,  PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
                   4363:                                spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
                   4364:                                efree(fullpath);
                   4365:                                return FAILURE;
                   4366:                        }
                   4367:                } else {
                   4368:                        if (!php_stream_mkdir(fullpath, 0777,  PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
                   4369:                                spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
                   4370:                                efree(fullpath);
                   4371:                                return FAILURE;
                   4372:                        }
                   4373:                }
                   4374:        }
                   4375: 
                   4376:        if (slash) {
                   4377:                fullpath[dest_len + (slash - entry->filename) + 1] = '/';
                   4378:        } else {
                   4379:                fullpath[dest_len] = '/';
                   4380:        }
                   4381: 
                   4382:        /* it is a standalone directory, job done */
                   4383:        if (entry->is_dir) {
                   4384:                efree(fullpath);
                   4385:                return SUCCESS;
                   4386:        }
                   4387: 
                   4388: #if PHP_API_VERSION < 20100412
                   4389:        fp = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
                   4390: #else
                   4391:        fp = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL);
                   4392: #endif
                   4393: 
                   4394:        if (!fp) {
                   4395:                spprintf(error, 4096, "Cannot extract \"%s\", could not open for writing \"%s\"", entry->filename, fullpath);
                   4396:                efree(fullpath);
                   4397:                return FAILURE;
                   4398:        }
                   4399: 
                   4400:        if (!phar_get_efp(entry, 0 TSRMLS_CC)) {
                   4401:                if (FAILURE == phar_open_entry_fp(entry, error, 1 TSRMLS_CC)) {
                   4402:                        if (error) {
                   4403:                                spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer: %s", entry->filename, fullpath, *error);
                   4404:                        } else {
                   4405:                                spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer", entry->filename, fullpath);
                   4406:                        }
                   4407:                        efree(fullpath);
                   4408:                        php_stream_close(fp);
                   4409:                        return FAILURE;
                   4410:                }
                   4411:        }
                   4412: 
                   4413:        if (FAILURE == phar_seek_efp(entry, 0, SEEK_SET, 0, 0 TSRMLS_CC)) {
                   4414:                spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to seek internal file pointer", entry->filename, fullpath);
                   4415:                efree(fullpath);
                   4416:                php_stream_close(fp);
                   4417:                return FAILURE;
                   4418:        }
                   4419: 
                   4420:        if (SUCCESS != phar_stream_copy_to_stream(phar_get_efp(entry, 0 TSRMLS_CC), fp, entry->uncompressed_filesize, NULL)) {
                   4421:                spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", copying contents failed", entry->filename, fullpath);
                   4422:                efree(fullpath);
                   4423:                php_stream_close(fp);
                   4424:                return FAILURE;
                   4425:        }
                   4426: 
                   4427:        php_stream_close(fp);
                   4428:        mode = (mode_t) entry->flags & PHAR_ENT_PERM_MASK;
                   4429: 
                   4430:        if (FAILURE == VCWD_CHMOD(fullpath, mode)) {
                   4431:                spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", setting file permissions failed", entry->filename, fullpath);
                   4432:                efree(fullpath);
                   4433:                return FAILURE;
                   4434:        }
                   4435: 
                   4436:        efree(fullpath);
                   4437:        return SUCCESS;
                   4438: }
                   4439: /* }}} */
                   4440: 
                   4441: /* {{{ proto bool Phar::extractTo(string pathto[[, mixed files], bool overwrite])
                   4442:  * Extract one or more file from a phar archive, optionally overwriting existing files
                   4443:  */
                   4444: PHP_METHOD(Phar, extractTo)
                   4445: {
                   4446:        char *error = NULL;
                   4447:        php_stream *fp;
                   4448:        php_stream_statbuf ssb;
                   4449:        phar_entry_info *entry;
                   4450:        char *pathto, *filename, *actual;
                   4451:        int pathto_len, filename_len;
                   4452:        int ret, i;
                   4453:        int nelems;
                   4454:        zval *zval_files = NULL;
                   4455:        zend_bool overwrite = 0;
                   4456: 
                   4457:        PHAR_ARCHIVE_OBJECT();
                   4458: 
                   4459:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z!b", &pathto, &pathto_len, &zval_files, &overwrite) == FAILURE) {
                   4460:                return;
                   4461:        }
                   4462: 
                   4463:        fp = php_stream_open_wrapper(phar_obj->arc.archive->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, &actual);
                   4464: 
                   4465:        if (!fp) {
                   4466:                zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC,
                   4467:                        "Invalid argument, %s cannot be found", phar_obj->arc.archive->fname);
                   4468:                return;
                   4469:        }
                   4470: 
                   4471:        efree(actual);
                   4472:        php_stream_close(fp);
                   4473: 
                   4474:        if (pathto_len < 1) {
                   4475:                zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC,
                   4476:                        "Invalid argument, extraction path must be non-zero length");
                   4477:                return;
                   4478:        }
                   4479: 
                   4480:        if (pathto_len >= MAXPATHLEN) {
                   4481:                char *tmp = estrndup(pathto, 50);
                   4482:                /* truncate for error message */
                   4483:                zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "Cannot extract to \"%s...\", destination directory is too long for filesystem", tmp);
                   4484:                efree(tmp);
                   4485:                return;
                   4486:        }
                   4487: 
                   4488:        if (php_stream_stat_path(pathto, &ssb) < 0) {
                   4489:                ret = php_stream_mkdir(pathto, 0777,  PHP_STREAM_MKDIR_RECURSIVE, NULL);
                   4490:                if (!ret) {
                   4491:                        zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC,
                   4492:                                "Unable to create path \"%s\" for extraction", pathto);
                   4493:                        return;
                   4494:                }
                   4495:        } else if (!(ssb.sb.st_mode & S_IFDIR)) {
                   4496:                zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC,
                   4497:                        "Unable to use path \"%s\" for extraction, it is a file, must be a directory", pathto);
                   4498:                return;
                   4499:        }
                   4500: 
                   4501:        if (zval_files) {
                   4502:                switch (Z_TYPE_P(zval_files)) {
                   4503:                        case IS_NULL:
                   4504:                                goto all_files;
                   4505: #if PHP_VERSION_ID >= 60000
                   4506:                        case IS_UNICODE:
                   4507:                                zval_unicode_to_string(zval_files TSRMLS_CC);
                   4508:                                /* break intentionally omitted */
                   4509: #endif
                   4510:                        case IS_STRING:
                   4511:                                filename = Z_STRVAL_P(zval_files);
                   4512:                                filename_len = Z_STRLEN_P(zval_files);
                   4513:                                break;
                   4514:                        case IS_ARRAY:
                   4515:                                nelems = zend_hash_num_elements(Z_ARRVAL_P(zval_files));
                   4516:                                if (nelems == 0 ) {
                   4517:                                        RETURN_FALSE;
                   4518:                                }
                   4519:                                for (i = 0; i < nelems; i++) {
                   4520:                                        zval **zval_file;
                   4521:                                        if (zend_hash_index_find(Z_ARRVAL_P(zval_files), i, (void **) &zval_file) == SUCCESS) {
                   4522:                                                switch (Z_TYPE_PP(zval_file)) {
                   4523: #if PHP_VERSION_ID >= 60000
                   4524:                                                        case IS_UNICODE:
                   4525:                                                                zval_unicode_to_string(*(zval_file) TSRMLS_CC);
                   4526:                                                                /* break intentionally omitted */
                   4527: #endif
                   4528:                                                        case IS_STRING:
                   4529:                                                                break;
                   4530:                                                        default:
                   4531:                                                                zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC,
                   4532:                                                                        "Invalid argument, array of filenames to extract contains non-string value");
                   4533:                                                                return;
                   4534:                                                }
                   4535:                                                if (FAILURE == zend_hash_find(&phar_obj->arc.archive->manifest, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file), (void **)&entry)) {
                   4536:                                                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC,
                   4537:                                                                "Phar Error: attempted to extract non-existent file \"%s\" from phar \"%s\"", Z_STRVAL_PP(zval_file), phar_obj->arc.archive->fname);
                   4538:                                                }
                   4539:                                                if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, &error TSRMLS_CC)) {
                   4540:                                                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC,
                   4541:                                                                "Extraction from phar \"%s\" failed: %s", phar_obj->arc.archive->fname, error);
                   4542:                                                        efree(error);
                   4543:                                                        return;
                   4544:                                                }
                   4545:                                        }
                   4546:                                }
                   4547:                                RETURN_TRUE;
                   4548:                        default:
                   4549:                                zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC,
                   4550:                                        "Invalid argument, expected a filename (string) or array of filenames");
                   4551:                                return;
                   4552:                }
                   4553: 
                   4554:                if (FAILURE == zend_hash_find(&phar_obj->arc.archive->manifest, filename, filename_len, (void **)&entry)) {
                   4555:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC,
                   4556:                                "Phar Error: attempted to extract non-existent file \"%s\" from phar \"%s\"", filename, phar_obj->arc.archive->fname);
                   4557:                        return;
                   4558:                }
                   4559: 
                   4560:                if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, &error TSRMLS_CC)) {
                   4561:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC,
                   4562:                                "Extraction from phar \"%s\" failed: %s", phar_obj->arc.archive->fname, error);
                   4563:                        efree(error);
                   4564:                        return;
                   4565:                }
                   4566:        } else {
                   4567:                phar_archive_data *phar;
                   4568: all_files:
                   4569:                phar = phar_obj->arc.archive;
                   4570:                /* Extract all files */
                   4571:                if (!zend_hash_num_elements(&(phar->manifest))) {
                   4572:                        RETURN_TRUE;
                   4573:                }
                   4574: 
                   4575:                for (zend_hash_internal_pointer_reset(&phar->manifest);
                   4576:                zend_hash_has_more_elements(&phar->manifest) == SUCCESS;
                   4577:                zend_hash_move_forward(&phar->manifest)) {
                   4578: 
                   4579:                        if (zend_hash_get_current_data(&phar->manifest, (void **)&entry) == FAILURE) {
                   4580:                                continue;
                   4581:                        }
                   4582: 
                   4583:                        if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, &error TSRMLS_CC)) {
                   4584:                                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC,
                   4585:                                        "Extraction from phar \"%s\" failed: %s", phar->fname, error);
                   4586:                                efree(error);
                   4587:                                return;
                   4588:                        }
                   4589:                }
                   4590:        }
                   4591:        RETURN_TRUE;
                   4592: }
                   4593: /* }}} */
                   4594: 
                   4595: 
                   4596: /* {{{ proto void PharFileInfo::__construct(string entry)
                   4597:  * Construct a Phar entry object
                   4598:  */
                   4599: PHP_METHOD(PharFileInfo, __construct)
                   4600: {
                   4601:        char *fname, *arch, *entry, *error;
                   4602:        int fname_len, arch_len, entry_len;
                   4603:        phar_entry_object *entry_obj;
                   4604:        phar_entry_info *entry_info;
                   4605:        phar_archive_data *phar_data;
                   4606:        zval *zobj = getThis(), arg1;
                   4607: 
                   4608:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, &fname_len) == FAILURE) {
                   4609:                return;
                   4610:        }
                   4611: 
                   4612:        entry_obj = (phar_entry_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
                   4613: 
                   4614:        if (entry_obj->ent.entry) {
                   4615:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot call constructor twice");
                   4616:                return;
                   4617:        }
                   4618: 
                   4619:        if (fname_len < 7 || memcmp(fname, "phar://", 7) || phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC) == FAILURE) {
                   4620:                zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC,
                   4621:                        "'%s' is not a valid phar archive URL (must have at least phar://filename.phar)", fname);
                   4622:                return;
                   4623:        }
                   4624: 
                   4625:        if (phar_open_from_filename(arch, arch_len, NULL, 0, REPORT_ERRORS, &phar_data, &error TSRMLS_CC) == FAILURE) {
                   4626:                efree(arch);
                   4627:                efree(entry);
                   4628:                if (error) {
                   4629:                        zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC,
                   4630:                                "Cannot open phar file '%s': %s", fname, error);
                   4631:                        efree(error);
                   4632:                } else {
                   4633:                        zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC,
                   4634:                                "Cannot open phar file '%s'", fname);
                   4635:                }
                   4636:                return;
                   4637:        }
                   4638: 
                   4639:        if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 1, &error, 1 TSRMLS_CC)) == NULL) {
                   4640:                zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC,
                   4641:                        "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error ? ", " : "", error ? error : "");
                   4642:                efree(arch);
                   4643:                efree(entry);
                   4644:                return;
                   4645:        }
                   4646: 
                   4647:        efree(arch);
                   4648:        efree(entry);
                   4649: 
                   4650:        entry_obj->ent.entry = entry_info;
                   4651: 
                   4652:        INIT_PZVAL(&arg1);
                   4653:        ZVAL_STRINGL(&arg1, fname, fname_len, 0);
                   4654: 
                   4655:        zend_call_method_with_1_params(&zobj, Z_OBJCE_P(zobj), 
                   4656:                &spl_ce_SplFileInfo->constructor, "__construct", NULL, &arg1);
                   4657: }
                   4658: /* }}} */
                   4659: 
                   4660: #define PHAR_ENTRY_OBJECT() \
                   4661:        phar_entry_object *entry_obj = (phar_entry_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
                   4662:        if (!entry_obj->ent.entry) { \
                   4663:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
                   4664:                        "Cannot call method on an uninitialized PharFileInfo object"); \
                   4665:                return; \
                   4666:        }
                   4667: 
                   4668: /* {{{ proto void PharFileInfo::__destruct()
                   4669:  * clean up directory-based entry objects
                   4670:  */
                   4671: PHP_METHOD(PharFileInfo, __destruct)
                   4672: {
                   4673:        phar_entry_object *entry_obj = (phar_entry_object*)zend_object_store_get_object(getThis() TSRMLS_CC); \
                   4674: 
                   4675:        if (entry_obj->ent.entry && entry_obj->ent.entry->is_temp_dir) {
                   4676:                if (entry_obj->ent.entry->filename) {
                   4677:                        efree(entry_obj->ent.entry->filename);
                   4678:                        entry_obj->ent.entry->filename = NULL;
                   4679:                }
                   4680: 
                   4681:                efree(entry_obj->ent.entry);
                   4682:                entry_obj->ent.entry = NULL;
                   4683:        }
                   4684: }
                   4685: /* }}} */
                   4686: 
                   4687: /* {{{ proto int PharFileInfo::getCompressedSize()
                   4688:  * Returns the compressed size
                   4689:  */
                   4690: PHP_METHOD(PharFileInfo, getCompressedSize)
                   4691: {
                   4692:        PHAR_ENTRY_OBJECT();
                   4693:        
                   4694:        if (zend_parse_parameters_none() == FAILURE) {
                   4695:                return;
                   4696:        }
                   4697: 
                   4698:        RETURN_LONG(entry_obj->ent.entry->compressed_filesize);
                   4699: }
                   4700: /* }}} */
                   4701: 
                   4702: /* {{{ proto bool PharFileInfo::isCompressed([int compression_type])
                   4703:  * Returns whether the entry is compressed, and whether it is compressed with Phar::GZ or Phar::BZ2 if specified
                   4704:  */
                   4705: PHP_METHOD(PharFileInfo, isCompressed)
                   4706: {
                   4707:        /* a number that is not Phar::GZ or Phar::BZ2 */
                   4708:        long method = 9021976;
                   4709:        PHAR_ENTRY_OBJECT();
                   4710: 
                   4711:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &method) == FAILURE) {
                   4712:                return;
                   4713:        }
                   4714: 
                   4715:        switch (method) {
                   4716:                case 9021976:
                   4717:                        RETURN_BOOL(entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSION_MASK);
                   4718:                case PHAR_ENT_COMPRESSED_GZ:
                   4719:                        RETURN_BOOL(entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_GZ);
                   4720:                case PHAR_ENT_COMPRESSED_BZ2:
                   4721:                        RETURN_BOOL(entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_BZ2);
                   4722:                default:
                   4723:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
                   4724:                                "Unknown compression type specified"); \
                   4725:        }
                   4726: }
                   4727: /* }}} */
                   4728: 
                   4729: /* {{{ proto int PharFileInfo::getCRC32()
                   4730:  * Returns CRC32 code or throws an exception if not CRC checked
                   4731:  */
                   4732: PHP_METHOD(PharFileInfo, getCRC32)
                   4733: {
                   4734:        PHAR_ENTRY_OBJECT();
                   4735:        
                   4736:        if (zend_parse_parameters_none() == FAILURE) {
                   4737:                return;
                   4738:        }
                   4739: 
                   4740:        if (entry_obj->ent.entry->is_dir) {
                   4741:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
                   4742:                        "Phar entry is a directory, does not have a CRC"); \
                   4743:                return;
                   4744:        }
                   4745: 
                   4746:        if (entry_obj->ent.entry->is_crc_checked) {
                   4747:                RETURN_LONG(entry_obj->ent.entry->crc32);
                   4748:        } else {
                   4749:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
                   4750:                        "Phar entry was not CRC checked"); \
                   4751:        }
                   4752: }
                   4753: /* }}} */
                   4754: 
                   4755: /* {{{ proto int PharFileInfo::isCRCChecked()
                   4756:  * Returns whether file entry is CRC checked
                   4757:  */
                   4758: PHP_METHOD(PharFileInfo, isCRCChecked)
                   4759: {
                   4760:        PHAR_ENTRY_OBJECT();
                   4761:        
                   4762:        if (zend_parse_parameters_none() == FAILURE) {
                   4763:                return;
                   4764:        }
                   4765: 
                   4766:        RETURN_BOOL(entry_obj->ent.entry->is_crc_checked);
                   4767: }
                   4768: /* }}} */
                   4769: 
                   4770: /* {{{ proto int PharFileInfo::getPharFlags()
                   4771:  * Returns the Phar file entry flags
                   4772:  */
                   4773: PHP_METHOD(PharFileInfo, getPharFlags)
                   4774: {
                   4775:        PHAR_ENTRY_OBJECT();
                   4776:        
                   4777:        if (zend_parse_parameters_none() == FAILURE) {
                   4778:                return;
                   4779:        }
                   4780: 
                   4781:        RETURN_LONG(entry_obj->ent.entry->flags & ~(PHAR_ENT_PERM_MASK|PHAR_ENT_COMPRESSION_MASK));
                   4782: }
                   4783: /* }}} */
                   4784: 
                   4785: /* {{{ proto int PharFileInfo::chmod()
                   4786:  * set the file permissions for the Phar.  This only allows setting execution bit, read/write
                   4787:  */
                   4788: PHP_METHOD(PharFileInfo, chmod)
                   4789: {
                   4790:        char *error;
                   4791:        long perms;
                   4792:        PHAR_ENTRY_OBJECT();
                   4793: 
                   4794:        if (entry_obj->ent.entry->is_temp_dir) {
                   4795:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
                   4796:                        "Phar entry \"%s\" is a temporary directory (not an actual entry in the archive), cannot chmod", entry_obj->ent.entry->filename); \
                   4797:                return;
                   4798:        }
                   4799: 
                   4800:        if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
                   4801:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Cannot modify permissions for file \"%s\" in phar \"%s\", write operations are prohibited", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);
                   4802:                return;
                   4803:        }
                   4804: 
                   4805:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &perms) == FAILURE) {
                   4806:                return;
                   4807:        }
                   4808: 
                   4809:        if (entry_obj->ent.entry->is_persistent) {
                   4810:                phar_archive_data *phar = entry_obj->ent.entry->phar;
                   4811: 
                   4812:                if (FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
                   4813:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
                   4814:                        return;
                   4815:                }
                   4816:                /* re-populate after copy-on-write */
                   4817:                zend_hash_find(&phar->manifest, entry_obj->ent.entry->filename, entry_obj->ent.entry->filename_len, (void **)&entry_obj->ent.entry);
                   4818:        }
                   4819:        /* clear permissions */
                   4820:        entry_obj->ent.entry->flags &= ~PHAR_ENT_PERM_MASK;
                   4821:        perms &= 0777;
                   4822:        entry_obj->ent.entry->flags |= perms;
                   4823:        entry_obj->ent.entry->old_flags = entry_obj->ent.entry->flags;
                   4824:        entry_obj->ent.entry->phar->is_modified = 1;
                   4825:        entry_obj->ent.entry->is_modified = 1;
                   4826: 
                   4827:        /* hackish cache in php_stat needs to be cleared */
                   4828:        /* if this code fails to work, check main/streams/streams.c, _php_stream_stat_path */
                   4829:        if (BG(CurrentLStatFile)) {
                   4830:                efree(BG(CurrentLStatFile));
                   4831:        }
                   4832: 
                   4833:        if (BG(CurrentStatFile)) {
                   4834:                efree(BG(CurrentStatFile));
                   4835:        }
                   4836: 
                   4837:        BG(CurrentLStatFile) = NULL;
                   4838:        BG(CurrentStatFile) = NULL;
                   4839:        phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
                   4840: 
                   4841:        if (error) {
                   4842:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   4843:                efree(error);
                   4844:        }
                   4845: }
                   4846: /* }}} */
                   4847: 
                   4848: /* {{{ proto int PharFileInfo::hasMetaData()
                   4849:  * Returns the metadata of the entry
                   4850:  */
                   4851: PHP_METHOD(PharFileInfo, hasMetadata)
                   4852: {
                   4853:        PHAR_ENTRY_OBJECT();
                   4854:        
                   4855:        if (zend_parse_parameters_none() == FAILURE) {
                   4856:                return;
                   4857:        }
                   4858: 
                   4859:        RETURN_BOOL(entry_obj->ent.entry->metadata != NULL);
                   4860: }
                   4861: /* }}} */
                   4862: 
                   4863: /* {{{ proto int PharFileInfo::getMetaData()
                   4864:  * Returns the metadata of the entry
                   4865:  */
                   4866: PHP_METHOD(PharFileInfo, getMetadata)
                   4867: {
                   4868:        PHAR_ENTRY_OBJECT();
                   4869:        
                   4870:        if (zend_parse_parameters_none() == FAILURE) {
                   4871:                return;
                   4872:        }
                   4873: 
                   4874:        if (entry_obj->ent.entry->metadata) {
                   4875:                if (entry_obj->ent.entry->is_persistent) {
                   4876:                        zval *ret;
                   4877:                        char *buf = estrndup((char *) entry_obj->ent.entry->metadata, entry_obj->ent.entry->metadata_len);
                   4878:                        /* assume success, we would have failed before */
                   4879:                        phar_parse_metadata(&buf, &ret, entry_obj->ent.entry->metadata_len TSRMLS_CC);
                   4880:                        efree(buf);
                   4881:                        RETURN_ZVAL(ret, 0, 1);
                   4882:                }
                   4883:                RETURN_ZVAL(entry_obj->ent.entry->metadata, 1, 0);
                   4884:        }
                   4885: }
                   4886: /* }}} */
                   4887: 
                   4888: /* {{{ proto int PharFileInfo::setMetaData(mixed $metadata)
                   4889:  * Sets the metadata of the entry
                   4890:  */
                   4891: PHP_METHOD(PharFileInfo, setMetadata)
                   4892: {
                   4893:        char *error;
                   4894:        zval *metadata;
                   4895: 
                   4896:        PHAR_ENTRY_OBJECT();
                   4897: 
                   4898:        if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
                   4899:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by the php.ini setting phar.readonly");
                   4900:                return;
                   4901:        }
                   4902: 
                   4903:        if (entry_obj->ent.entry->is_temp_dir) {
                   4904:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
                   4905:                        "Phar entry is a temporary directory (not an actual entry in the archive), cannot set metadata"); \
                   4906:                return;
                   4907:        }
                   4908: 
                   4909:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &metadata) == FAILURE) {
                   4910:                return;
                   4911:        }
                   4912: 
                   4913:        if (entry_obj->ent.entry->is_persistent) {
                   4914:                phar_archive_data *phar = entry_obj->ent.entry->phar;
                   4915: 
                   4916:                if (FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
                   4917:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
                   4918:                        return;
                   4919:                }
                   4920:                /* re-populate after copy-on-write */
                   4921:                zend_hash_find(&phar->manifest, entry_obj->ent.entry->filename, entry_obj->ent.entry->filename_len, (void **)&entry_obj->ent.entry);
                   4922:        }
                   4923:        if (entry_obj->ent.entry->metadata) {
                   4924:                zval_ptr_dtor(&entry_obj->ent.entry->metadata);
                   4925:                entry_obj->ent.entry->metadata = NULL;
                   4926:        }
                   4927: 
                   4928:        MAKE_STD_ZVAL(entry_obj->ent.entry->metadata);
                   4929:        ZVAL_ZVAL(entry_obj->ent.entry->metadata, metadata, 1, 0);
                   4930: 
                   4931:        entry_obj->ent.entry->is_modified = 1;
                   4932:        entry_obj->ent.entry->phar->is_modified = 1;
                   4933:        phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
                   4934: 
                   4935:        if (error) {
                   4936:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   4937:                efree(error);
                   4938:        }
                   4939: }
                   4940: /* }}} */
                   4941: 
                   4942: /* {{{ proto bool PharFileInfo::delMetaData()
                   4943:  * Deletes the metadata of the entry
                   4944:  */
                   4945: PHP_METHOD(PharFileInfo, delMetadata)
                   4946: {
                   4947:        char *error;
                   4948: 
                   4949:        PHAR_ENTRY_OBJECT();
                   4950:        
                   4951:        if (zend_parse_parameters_none() == FAILURE) {
                   4952:                return;
                   4953:        }
                   4954: 
                   4955:        if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
                   4956:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Write operations disabled by the php.ini setting phar.readonly");
                   4957:                return;
                   4958:        }
                   4959: 
                   4960:        if (entry_obj->ent.entry->is_temp_dir) {
                   4961:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
                   4962:                        "Phar entry is a temporary directory (not an actual entry in the archive), cannot delete metadata"); \
                   4963:                return;
                   4964:        }
                   4965: 
                   4966:        if (entry_obj->ent.entry->metadata) {
                   4967:                if (entry_obj->ent.entry->is_persistent) {
                   4968:                        phar_archive_data *phar = entry_obj->ent.entry->phar;
                   4969: 
                   4970:                        if (FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
                   4971:                                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
                   4972:                                return;
                   4973:                        }
                   4974:                        /* re-populate after copy-on-write */
                   4975:                        zend_hash_find(&phar->manifest, entry_obj->ent.entry->filename, entry_obj->ent.entry->filename_len, (void **)&entry_obj->ent.entry);
                   4976:                }
                   4977:                zval_ptr_dtor(&entry_obj->ent.entry->metadata);
                   4978:                entry_obj->ent.entry->metadata = NULL;
                   4979:                entry_obj->ent.entry->is_modified = 1;
                   4980:                entry_obj->ent.entry->phar->is_modified = 1;
                   4981: 
                   4982:                phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
                   4983: 
                   4984:                if (error) {
                   4985:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   4986:                        efree(error);
                   4987:                        RETURN_FALSE;
                   4988:                } else {
                   4989:                        RETURN_TRUE;
                   4990:                }
                   4991: 
                   4992:        } else {
                   4993:                RETURN_TRUE;
                   4994:        }
                   4995: }
                   4996: /* }}} */
                   4997: 
                   4998: /* {{{ proto string PharFileInfo::getContent()
                   4999:  * return the complete file contents of the entry (like file_get_contents)
                   5000:  */
                   5001: PHP_METHOD(PharFileInfo, getContent)
                   5002: {
                   5003:        char *error;
                   5004:        php_stream *fp;
                   5005:        phar_entry_info *link;
                   5006: 
                   5007:        PHAR_ENTRY_OBJECT();
                   5008:        
                   5009:        if (zend_parse_parameters_none() == FAILURE) {
                   5010:                return;
                   5011:        }
                   5012: 
                   5013:        if (entry_obj->ent.entry->is_dir) {
                   5014:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5015:                        "Phar error: Cannot retrieve contents, \"%s\" in phar \"%s\" is a directory", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);
                   5016:                return;
                   5017:        }
                   5018: 
                   5019:        link = phar_get_link_source(entry_obj->ent.entry TSRMLS_CC);
                   5020: 
                   5021:        if (!link) {
                   5022:                link = entry_obj->ent.entry;
                   5023:        }
                   5024: 
                   5025:        if (SUCCESS != phar_open_entry_fp(link, &error, 0 TSRMLS_CC)) {
                   5026:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5027:                        "Phar error: Cannot retrieve contents, \"%s\" in phar \"%s\": %s", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname, error);
                   5028:                efree(error);
                   5029:                return;
                   5030:        }
                   5031: 
                   5032:        if (!(fp = phar_get_efp(link, 0 TSRMLS_CC))) {
                   5033:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5034:                        "Phar error: Cannot retrieve contents of \"%s\" in phar \"%s\"", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);
                   5035:                return;
                   5036:        }
                   5037: 
                   5038:        phar_seek_efp(link, 0, SEEK_SET, 0, 0 TSRMLS_CC);
                   5039:        Z_TYPE_P(return_value) = IS_STRING;
                   5040: #if PHP_MAJOR_VERSION >= 6
                   5041:        Z_STRLEN_P(return_value) = php_stream_copy_to_mem(fp, (void **) &(Z_STRVAL_P(return_value)), link->uncompressed_filesize, 0);
                   5042: #else
                   5043:        Z_STRLEN_P(return_value) = php_stream_copy_to_mem(fp, &(Z_STRVAL_P(return_value)), link->uncompressed_filesize, 0);
                   5044: #endif
                   5045: 
                   5046:        if (!Z_STRVAL_P(return_value)) {
                   5047:                Z_STRVAL_P(return_value) = estrndup("", 0);
                   5048:        }
                   5049: }
                   5050: /* }}} */
                   5051: 
                   5052: /* {{{ proto int PharFileInfo::compress(int compression_type)
                   5053:  * Instructs the Phar class to compress the current file using zlib or bzip2 compression
                   5054:  */
                   5055: PHP_METHOD(PharFileInfo, compress)
                   5056: {
                   5057:        long method;
                   5058:        char *error;
                   5059:        PHAR_ENTRY_OBJECT();
                   5060: 
                   5061:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &method) == FAILURE) {
                   5062:                return;
                   5063:        }
                   5064: 
                   5065:        if (entry_obj->ent.entry->is_tar) {
                   5066:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5067:                        "Cannot compress with Gzip compression, not possible with tar-based phar archives");
                   5068:                return;
                   5069:        }
                   5070: 
                   5071:        if (entry_obj->ent.entry->is_dir) {
                   5072:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
                   5073:                        "Phar entry is a directory, cannot set compression"); \
                   5074:                return;
                   5075:        }
                   5076: 
                   5077:        if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
                   5078:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5079:                        "Phar is readonly, cannot change compression");
                   5080:                return;
                   5081:        }
                   5082: 
                   5083:        if (entry_obj->ent.entry->is_deleted) {
                   5084:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5085:                        "Cannot compress deleted file");
                   5086:                return;
                   5087:        }
                   5088: 
                   5089:        if (entry_obj->ent.entry->is_persistent) {
                   5090:                phar_archive_data *phar = entry_obj->ent.entry->phar;
                   5091: 
                   5092:                if (FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
                   5093:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
                   5094:                        return;
                   5095:                }
                   5096:                /* re-populate after copy-on-write */
                   5097:                zend_hash_find(&phar->manifest, entry_obj->ent.entry->filename, entry_obj->ent.entry->filename_len, (void **)&entry_obj->ent.entry);
                   5098:        }
                   5099:        switch (method) {
                   5100:                case PHAR_ENT_COMPRESSED_GZ:
                   5101:                        if (entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_GZ) {
                   5102:                                RETURN_TRUE;
                   5103:                        }
                   5104: 
                   5105:                        if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_BZ2) != 0) {
                   5106:                                if (!PHAR_G(has_bz2)) {
                   5107:                                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5108:                                                "Cannot compress with gzip compression, file is already compressed with bzip2 compression and bz2 extension is not enabled, cannot decompress");
                   5109:                                        return;
                   5110:                                }
                   5111: 
                   5112:                                /* decompress this file indirectly */
                   5113:                                if (SUCCESS != phar_open_entry_fp(entry_obj->ent.entry, &error, 1 TSRMLS_CC)) {
                   5114:                                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5115:                                                "Phar error: Cannot decompress bzip2-compressed file \"%s\" in phar \"%s\" in order to compress with gzip: %s", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname, error);
                   5116:                                        efree(error);
                   5117:                                        return;
                   5118:                                }
                   5119:                        }
                   5120: 
                   5121:                        if (!PHAR_G(has_zlib)) {
                   5122:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5123:                                        "Cannot compress with gzip compression, zlib extension is not enabled");
                   5124:                                return;
                   5125:                        }
                   5126: 
                   5127:                        entry_obj->ent.entry->old_flags = entry_obj->ent.entry->flags;
                   5128:                        entry_obj->ent.entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
                   5129:                        entry_obj->ent.entry->flags |= PHAR_ENT_COMPRESSED_GZ;
                   5130:                        break;
                   5131:                case PHAR_ENT_COMPRESSED_BZ2:
                   5132:                        if (entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_BZ2) {
                   5133:                                RETURN_TRUE;
                   5134:                        }
                   5135: 
                   5136:                        if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_GZ) != 0) {
                   5137:                                if (!PHAR_G(has_zlib)) {
                   5138:                                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5139:                                                "Cannot compress with bzip2 compression, file is already compressed with gzip compression and zlib extension is not enabled, cannot decompress");
                   5140:                                        return;
                   5141:                                }
                   5142: 
                   5143:                                /* decompress this file indirectly */
                   5144:                                if (SUCCESS != phar_open_entry_fp(entry_obj->ent.entry, &error, 1 TSRMLS_CC)) {
                   5145:                                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5146:                                                "Phar error: Cannot decompress gzip-compressed file \"%s\" in phar \"%s\" in order to compress with bzip2: %s", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname, error);
                   5147:                                        efree(error);
                   5148:                                        return;
                   5149:                                }
                   5150:                        }
                   5151: 
                   5152:                        if (!PHAR_G(has_bz2)) {
                   5153:                                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5154:                                        "Cannot compress with bzip2 compression, bz2 extension is not enabled");
                   5155:                                return;
                   5156:                        }
                   5157:                        entry_obj->ent.entry->old_flags = entry_obj->ent.entry->flags;
                   5158:                        entry_obj->ent.entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
                   5159:                        entry_obj->ent.entry->flags |= PHAR_ENT_COMPRESSED_BZ2;
                   5160:                        break;
                   5161:                default:
                   5162:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
                   5163:                                "Unknown compression type specified"); \
                   5164:        }
                   5165: 
                   5166:        entry_obj->ent.entry->phar->is_modified = 1;
                   5167:        entry_obj->ent.entry->is_modified = 1;
                   5168:        phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
                   5169: 
                   5170:        if (error) {
                   5171:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   5172:                efree(error);
                   5173:        }
                   5174: 
                   5175:        RETURN_TRUE;
                   5176: }
                   5177: /* }}} */
                   5178: 
                   5179: /* {{{ proto int PharFileInfo::decompress()
                   5180:  * Instructs the Phar class to decompress the current file
                   5181:  */
                   5182: PHP_METHOD(PharFileInfo, decompress)
                   5183: {
                   5184:        char *error;
                   5185:        PHAR_ENTRY_OBJECT();
                   5186:        
                   5187:        if (zend_parse_parameters_none() == FAILURE) {
                   5188:                return;
                   5189:        }
                   5190: 
                   5191:        if (entry_obj->ent.entry->is_dir) {
                   5192:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, \
                   5193:                        "Phar entry is a directory, cannot set compression"); \
                   5194:                return;
                   5195:        }
                   5196: 
                   5197:        if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSION_MASK) == 0) {
                   5198:                RETURN_TRUE;
                   5199:        }
                   5200: 
                   5201:        if (PHAR_G(readonly) && !entry_obj->ent.entry->phar->is_data) {
                   5202:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5203:                        "Phar is readonly, cannot decompress");
                   5204:                return;
                   5205:        }
                   5206: 
                   5207:        if (entry_obj->ent.entry->is_deleted) {
                   5208:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5209:                        "Cannot compress deleted file");
                   5210:                return;
                   5211:        }
                   5212: 
                   5213:        if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_GZ) != 0 && !PHAR_G(has_zlib)) {
                   5214:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5215:                        "Cannot decompress Gzip-compressed file, zlib extension is not enabled");
                   5216:                return;
                   5217:        }
                   5218: 
                   5219:        if ((entry_obj->ent.entry->flags & PHAR_ENT_COMPRESSED_BZ2) != 0 && !PHAR_G(has_bz2)) {
                   5220:                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC,
                   5221:                        "Cannot decompress Bzip2-compressed file, bz2 extension is not enabled");
                   5222:                return;
                   5223:        }
                   5224: 
                   5225:        if (entry_obj->ent.entry->is_persistent) {
                   5226:                phar_archive_data *phar = entry_obj->ent.entry->phar;
                   5227: 
                   5228:                if (FAILURE == phar_copy_on_write(&phar TSRMLS_CC)) {
                   5229:                        zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
                   5230:                        return;
                   5231:                }
                   5232:                /* re-populate after copy-on-write */
                   5233:                zend_hash_find(&phar->manifest, entry_obj->ent.entry->filename, entry_obj->ent.entry->filename_len, (void **)&entry_obj->ent.entry);
                   5234:        }
                   5235:        if (!entry_obj->ent.entry->fp) {
                   5236:                if (FAILURE == phar_open_archive_fp(entry_obj->ent.entry->phar TSRMLS_CC)) {
                   5237:                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Cannot decompress entry \"%s\", phar error: Cannot open phar archive \"%s\" for reading", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname);
                   5238:                        return;
                   5239:                }
                   5240:                entry_obj->ent.entry->fp_type = PHAR_FP;
                   5241:        }
                   5242: 
                   5243:        entry_obj->ent.entry->old_flags = entry_obj->ent.entry->flags;
                   5244:        entry_obj->ent.entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
                   5245:        entry_obj->ent.entry->phar->is_modified = 1;
                   5246:        entry_obj->ent.entry->is_modified = 1;
                   5247:        phar_flush(entry_obj->ent.entry->phar, 0, 0, 0, &error TSRMLS_CC);
                   5248: 
                   5249:        if (error) {
                   5250:                zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "%s", error);
                   5251:                efree(error);
                   5252:        }
                   5253:        RETURN_TRUE;
                   5254: }
                   5255: /* }}} */
                   5256: 
                   5257: #endif /* HAVE_SPL */
                   5258: 
                   5259: /* {{{ phar methods */
                   5260: PHAR_ARG_INFO
                   5261: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar___construct, 0, 0, 1)
                   5262:        ZEND_ARG_INFO(0, filename)
                   5263:        ZEND_ARG_INFO(0, flags)
                   5264:        ZEND_ARG_INFO(0, alias)
                   5265:        ZEND_ARG_INFO(0, fileformat)
                   5266: ZEND_END_ARG_INFO()
                   5267: 
                   5268: PHAR_ARG_INFO
                   5269: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_createDS, 0, 0, 0)
                   5270:        ZEND_ARG_INFO(0, index)
                   5271:        ZEND_ARG_INFO(0, webindex)
                   5272: ZEND_END_ARG_INFO()
                   5273: 
                   5274: PHAR_ARG_INFO
                   5275: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_cancompress, 0, 0, 0)
                   5276:        ZEND_ARG_INFO(0, method)
                   5277: ZEND_END_ARG_INFO()
                   5278: 
                   5279: PHAR_ARG_INFO
                   5280: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_isvalidpharfilename, 0, 0, 1)
                   5281:        ZEND_ARG_INFO(0, filename)
                   5282:        ZEND_ARG_INFO(0, executable)
                   5283: ZEND_END_ARG_INFO()
                   5284: 
                   5285: PHAR_ARG_INFO
                   5286: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_loadPhar, 0, 0, 1)
                   5287:        ZEND_ARG_INFO(0, filename)
                   5288:        ZEND_ARG_INFO(0, alias)
                   5289: ZEND_END_ARG_INFO()
                   5290: 
                   5291: PHAR_ARG_INFO
                   5292: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mapPhar, 0, 0, 0)
                   5293:        ZEND_ARG_INFO(0, alias)
                   5294:        ZEND_ARG_INFO(0, offset)
                   5295: ZEND_END_ARG_INFO()
                   5296: 
                   5297: PHAR_ARG_INFO
                   5298: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mount, 0, 0, 2)
                   5299:        ZEND_ARG_INFO(0, inphar)
                   5300:        ZEND_ARG_INFO(0, externalfile)
                   5301: ZEND_END_ARG_INFO()
                   5302: 
                   5303: PHAR_ARG_INFO
                   5304: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mungServer, 0, 0, 1)
                   5305:        ZEND_ARG_INFO(0, munglist)
                   5306: ZEND_END_ARG_INFO()
                   5307: 
                   5308: PHAR_ARG_INFO
                   5309: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_webPhar, 0, 0, 0)
                   5310:        ZEND_ARG_INFO(0, alias)
                   5311:        ZEND_ARG_INFO(0, index)
                   5312:        ZEND_ARG_INFO(0, f404)
                   5313:        ZEND_ARG_INFO(0, mimetypes)
                   5314:        ZEND_ARG_INFO(0, rewrites)
                   5315: ZEND_END_ARG_INFO()
                   5316: 
                   5317: PHAR_ARG_INFO
                   5318: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_running, 0, 0, 1)
                   5319:        ZEND_ARG_INFO(0, retphar)
                   5320: ZEND_END_ARG_INFO()
                   5321: 
                   5322: PHAR_ARG_INFO
                   5323: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_ua, 0, 0, 1)
                   5324:        ZEND_ARG_INFO(0, archive)
                   5325: ZEND_END_ARG_INFO()
                   5326: 
                   5327: #if HAVE_SPL
                   5328: PHAR_ARG_INFO
                   5329: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_build, 0, 0, 1)
                   5330:        ZEND_ARG_INFO(0, iterator)
                   5331:        ZEND_ARG_INFO(0, base_directory)
                   5332: ZEND_END_ARG_INFO()
                   5333: 
                   5334: PHAR_ARG_INFO
                   5335: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_conv, 0, 0, 0)
                   5336:        ZEND_ARG_INFO(0, format)
                   5337:        ZEND_ARG_INFO(0, compression_type)
                   5338:        ZEND_ARG_INFO(0, file_ext)
                   5339: ZEND_END_ARG_INFO()
                   5340: 
                   5341: PHAR_ARG_INFO
                   5342: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_comps, 0, 0, 1)
                   5343:        ZEND_ARG_INFO(0, compression_type)
                   5344:        ZEND_ARG_INFO(0, file_ext)
                   5345: ZEND_END_ARG_INFO()
                   5346: 
                   5347: PHAR_ARG_INFO
                   5348: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_decomp, 0, 0, 0)
                   5349:        ZEND_ARG_INFO(0, file_ext)
                   5350: ZEND_END_ARG_INFO()
                   5351: 
                   5352: PHAR_ARG_INFO
                   5353: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_comp, 0, 0, 1)
                   5354:        ZEND_ARG_INFO(0, compression_type)
                   5355: ZEND_END_ARG_INFO()
                   5356: 
                   5357: PHAR_ARG_INFO
                   5358: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_compo, 0, 0, 0)
                   5359:        ZEND_ARG_INFO(0, compression_type)
                   5360: ZEND_END_ARG_INFO()
                   5361: 
                   5362: PHAR_ARG_INFO
                   5363: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_copy, 0, 0, 2)
                   5364:        ZEND_ARG_INFO(0, newfile)
                   5365:        ZEND_ARG_INFO(0, oldfile)
                   5366: ZEND_END_ARG_INFO()
                   5367: 
                   5368: PHAR_ARG_INFO
                   5369: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_delete, 0, 0, 1)
                   5370:        ZEND_ARG_INFO(0, entry)
                   5371: ZEND_END_ARG_INFO()
                   5372: 
                   5373: PHAR_ARG_INFO
                   5374: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_fromdir, 0, 0, 1)
                   5375:        ZEND_ARG_INFO(0, base_dir)
                   5376:        ZEND_ARG_INFO(0, regex)
                   5377: ZEND_END_ARG_INFO()
                   5378: 
                   5379: PHAR_ARG_INFO
                   5380: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_offsetExists, 0, 0, 1)
                   5381:        ZEND_ARG_INFO(0, entry)
                   5382: ZEND_END_ARG_INFO()
                   5383: 
                   5384: PHAR_ARG_INFO
                   5385: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_offsetSet, 0, 0, 2)
                   5386:        ZEND_ARG_INFO(0, entry)
                   5387:        ZEND_ARG_INFO(0, value)
                   5388: ZEND_END_ARG_INFO()
                   5389: 
                   5390: PHAR_ARG_INFO
                   5391: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setAlias, 0, 0, 1)
                   5392:        ZEND_ARG_INFO(0, alias)
                   5393: ZEND_END_ARG_INFO()
                   5394: 
                   5395: PHAR_ARG_INFO
                   5396: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setMetadata, 0, 0, 1)
                   5397:        ZEND_ARG_INFO(0, metadata)
                   5398: ZEND_END_ARG_INFO()
                   5399: 
                   5400: PHAR_ARG_INFO
                   5401: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setSigAlgo, 0, 0, 1)
                   5402:        ZEND_ARG_INFO(0, algorithm)
                   5403:        ZEND_ARG_INFO(0, privatekey)
                   5404: ZEND_END_ARG_INFO()
                   5405: 
                   5406: PHAR_ARG_INFO
                   5407: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setStub, 0, 0, 1)
                   5408:        ZEND_ARG_INFO(0, newstub)
                   5409:        ZEND_ARG_INFO(0, maxlen)
                   5410: ZEND_END_ARG_INFO()
                   5411: 
                   5412: PHAR_ARG_INFO
                   5413: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_emptydir, 0, 0, 0)
                   5414:        ZEND_ARG_INFO(0, dirname)
                   5415: ZEND_END_ARG_INFO()
                   5416: 
                   5417: PHAR_ARG_INFO
                   5418: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_extract, 0, 0, 1)
                   5419:        ZEND_ARG_INFO(0, pathto)
                   5420:        ZEND_ARG_INFO(0, files)
                   5421:        ZEND_ARG_INFO(0, overwrite)
                   5422: ZEND_END_ARG_INFO()
                   5423: 
                   5424: PHAR_ARG_INFO
                   5425: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_addfile, 0, 0, 1)
                   5426:        ZEND_ARG_INFO(0, filename)
                   5427:        ZEND_ARG_INFO(0, localname)
                   5428: ZEND_END_ARG_INFO()
                   5429: 
                   5430: PHAR_ARG_INFO
                   5431: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_fromstring, 0, 0, 1)
                   5432:        ZEND_ARG_INFO(0, localname)
                   5433:        ZEND_ARG_INFO(0, contents)
                   5434: ZEND_END_ARG_INFO()
                   5435: 
                   5436: PHAR_ARG_INFO
                   5437: ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_isff, 0, 0, 1)
                   5438:        ZEND_ARG_INFO(0, fileformat)
                   5439: ZEND_END_ARG_INFO()
                   5440: 
                   5441: PHAR_ARG_INFO
                   5442: ZEND_BEGIN_ARG_INFO(arginfo_phar__void, 0)
                   5443: ZEND_END_ARG_INFO()
                   5444: 
                   5445: 
                   5446: #endif /* HAVE_SPL */
                   5447: 
                   5448: zend_function_entry php_archive_methods[] = {
                   5449: #if !HAVE_SPL
                   5450:        PHP_ME(Phar, __construct,           arginfo_phar___construct,  ZEND_ACC_PRIVATE)
                   5451: #else
                   5452:        PHP_ME(Phar, __construct,           arginfo_phar___construct,  ZEND_ACC_PUBLIC)
                   5453:        PHP_ME(Phar, __destruct,            arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5454:        PHP_ME(Phar, addEmptyDir,           arginfo_phar_emptydir,     ZEND_ACC_PUBLIC)
                   5455:        PHP_ME(Phar, addFile,               arginfo_phar_addfile,      ZEND_ACC_PUBLIC)
                   5456:        PHP_ME(Phar, addFromString,         arginfo_phar_fromstring,   ZEND_ACC_PUBLIC)
                   5457:        PHP_ME(Phar, buildFromDirectory,    arginfo_phar_fromdir,      ZEND_ACC_PUBLIC)
                   5458:        PHP_ME(Phar, buildFromIterator,     arginfo_phar_build,        ZEND_ACC_PUBLIC)
                   5459:        PHP_ME(Phar, compressFiles,         arginfo_phar_comp,         ZEND_ACC_PUBLIC)
                   5460:        PHP_ME(Phar, decompressFiles,       arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5461:        PHP_ME(Phar, compress,              arginfo_phar_comps,        ZEND_ACC_PUBLIC)
                   5462:        PHP_ME(Phar, decompress,            arginfo_phar_decomp,       ZEND_ACC_PUBLIC)
                   5463:        PHP_ME(Phar, convertToExecutable,   arginfo_phar_conv,         ZEND_ACC_PUBLIC)
                   5464:        PHP_ME(Phar, convertToData,         arginfo_phar_conv,         ZEND_ACC_PUBLIC)
                   5465:        PHP_ME(Phar, copy,                  arginfo_phar_copy,         ZEND_ACC_PUBLIC)
                   5466:        PHP_ME(Phar, count,                 arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5467:        PHP_ME(Phar, delete,                arginfo_phar_delete,       ZEND_ACC_PUBLIC)
                   5468:        PHP_ME(Phar, delMetadata,           arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5469:        PHP_ME(Phar, extractTo,             arginfo_phar_extract,      ZEND_ACC_PUBLIC)
                   5470:        PHP_ME(Phar, getAlias,              arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5471:        PHP_ME(Phar, getPath,               arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5472:        PHP_ME(Phar, getMetadata,           arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5473:        PHP_ME(Phar, getModified,           arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5474:        PHP_ME(Phar, getSignature,          arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5475:        PHP_ME(Phar, getStub,               arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5476:        PHP_ME(Phar, getVersion,            arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5477:        PHP_ME(Phar, hasMetadata,           arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5478:        PHP_ME(Phar, isBuffering,           arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5479:        PHP_ME(Phar, isCompressed,          arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5480:        PHP_ME(Phar, isFileFormat,          arginfo_phar_isff,         ZEND_ACC_PUBLIC)
                   5481:        PHP_ME(Phar, isWritable,            arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5482:        PHP_ME(Phar, offsetExists,          arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
                   5483:        PHP_ME(Phar, offsetGet,             arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
                   5484:        PHP_ME(Phar, offsetSet,             arginfo_phar_offsetSet,    ZEND_ACC_PUBLIC)
                   5485:        PHP_ME(Phar, offsetUnset,           arginfo_phar_offsetExists, ZEND_ACC_PUBLIC)
                   5486:        PHP_ME(Phar, setAlias,              arginfo_phar_setAlias,     ZEND_ACC_PUBLIC)
                   5487:        PHP_ME(Phar, setDefaultStub,        arginfo_phar_createDS,     ZEND_ACC_PUBLIC)
                   5488:        PHP_ME(Phar, setMetadata,           arginfo_phar_setMetadata,  ZEND_ACC_PUBLIC)
                   5489:        PHP_ME(Phar, setSignatureAlgorithm, arginfo_phar_setSigAlgo,   ZEND_ACC_PUBLIC)
                   5490:        PHP_ME(Phar, setStub,               arginfo_phar_setStub,      ZEND_ACC_PUBLIC)
                   5491:        PHP_ME(Phar, startBuffering,        arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5492:        PHP_ME(Phar, stopBuffering,         arginfo_phar__void,        ZEND_ACC_PUBLIC)
                   5493: #endif
                   5494:        /* static member functions */
                   5495:        PHP_ME(Phar, apiVersion,            arginfo_phar__void,        ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5496:        PHP_ME(Phar, canCompress,           arginfo_phar_cancompress,  ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5497:        PHP_ME(Phar, canWrite,              arginfo_phar__void,        ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5498:        PHP_ME(Phar, createDefaultStub,     arginfo_phar_createDS,     ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5499:        PHP_ME(Phar, getSupportedCompression,arginfo_phar__void,       ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5500:        PHP_ME(Phar, getSupportedSignatures,arginfo_phar__void,        ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5501:        PHP_ME(Phar, interceptFileFuncs,    arginfo_phar__void,        ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5502:        PHP_ME(Phar, isValidPharFilename,   arginfo_phar_isvalidpharfilename, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5503:        PHP_ME(Phar, loadPhar,              arginfo_phar_loadPhar,     ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5504:        PHP_ME(Phar, mapPhar,               arginfo_phar_mapPhar,      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5505:        PHP_ME(Phar, running,               arginfo_phar_running,      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5506:        PHP_ME(Phar, mount,                 arginfo_phar_mount,        ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5507:        PHP_ME(Phar, mungServer,            arginfo_phar_mungServer,   ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5508:        PHP_ME(Phar, unlinkArchive,         arginfo_phar_ua,           ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5509:        PHP_ME(Phar, webPhar,               arginfo_phar_webPhar,      ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL)
                   5510:        PHP_FE_END
                   5511: };
                   5512: 
                   5513: #if HAVE_SPL
                   5514: PHAR_ARG_INFO
                   5515: ZEND_BEGIN_ARG_INFO_EX(arginfo_entry___construct, 0, 0, 1)
                   5516:        ZEND_ARG_INFO(0, filename)
                   5517: ZEND_END_ARG_INFO()
                   5518: 
                   5519: PHAR_ARG_INFO
                   5520: ZEND_BEGIN_ARG_INFO_EX(arginfo_entry_chmod, 0, 0, 1)
                   5521:        ZEND_ARG_INFO(0, perms)
                   5522: ZEND_END_ARG_INFO()
                   5523: 
                   5524: zend_function_entry php_entry_methods[] = {
                   5525:        PHP_ME(PharFileInfo, __construct,        arginfo_entry___construct,  ZEND_ACC_PUBLIC)
                   5526:        PHP_ME(PharFileInfo, __destruct,         arginfo_phar__void,         ZEND_ACC_PUBLIC)
                   5527:        PHP_ME(PharFileInfo, chmod,              arginfo_entry_chmod,        ZEND_ACC_PUBLIC)
                   5528:        PHP_ME(PharFileInfo, compress,           arginfo_phar_comp,          ZEND_ACC_PUBLIC)
                   5529:        PHP_ME(PharFileInfo, decompress,         arginfo_phar__void,         ZEND_ACC_PUBLIC)
                   5530:        PHP_ME(PharFileInfo, delMetadata,        arginfo_phar__void,         ZEND_ACC_PUBLIC)
                   5531:        PHP_ME(PharFileInfo, getCompressedSize,  arginfo_phar__void,         ZEND_ACC_PUBLIC)
                   5532:        PHP_ME(PharFileInfo, getCRC32,           arginfo_phar__void,         ZEND_ACC_PUBLIC)
                   5533:        PHP_ME(PharFileInfo, getContent,         arginfo_phar__void,         ZEND_ACC_PUBLIC)
                   5534:        PHP_ME(PharFileInfo, getMetadata,        arginfo_phar__void,         ZEND_ACC_PUBLIC)
                   5535:        PHP_ME(PharFileInfo, getPharFlags,       arginfo_phar__void,         ZEND_ACC_PUBLIC)
                   5536:        PHP_ME(PharFileInfo, hasMetadata,        arginfo_phar__void,         ZEND_ACC_PUBLIC)
                   5537:        PHP_ME(PharFileInfo, isCompressed,       arginfo_phar_compo,         ZEND_ACC_PUBLIC)
                   5538:        PHP_ME(PharFileInfo, isCRCChecked,       arginfo_phar__void,         ZEND_ACC_PUBLIC)
                   5539:        PHP_ME(PharFileInfo, setMetadata,        arginfo_phar_setMetadata,   ZEND_ACC_PUBLIC)
                   5540:        PHP_FE_END
                   5541: };
                   5542: #endif /* HAVE_SPL */
                   5543: 
                   5544: zend_function_entry phar_exception_methods[] = {
                   5545:        PHP_FE_END
                   5546: };
                   5547: /* }}} */
                   5548: 
                   5549: #define REGISTER_PHAR_CLASS_CONST_LONG(class_name, const_name, value) \
                   5550:        zend_declare_class_constant_long(class_name, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
                   5551: 
                   5552: #if PHP_VERSION_ID < 50200
                   5553: # define phar_exception_get_default() zend_exception_get_default()
                   5554: #else
                   5555: # define phar_exception_get_default() zend_exception_get_default(TSRMLS_C)
                   5556: #endif
                   5557: 
                   5558: void phar_object_init(TSRMLS_D) /* {{{ */
                   5559: {
                   5560:        zend_class_entry ce;
                   5561: 
                   5562:        INIT_CLASS_ENTRY(ce, "PharException", phar_exception_methods);
                   5563:        phar_ce_PharException = zend_register_internal_class_ex(&ce, phar_exception_get_default(), NULL  TSRMLS_CC);
                   5564: 
                   5565: #if HAVE_SPL
                   5566:        INIT_CLASS_ENTRY(ce, "Phar", php_archive_methods);
                   5567:        phar_ce_archive = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator, NULL  TSRMLS_CC);
                   5568: 
                   5569:        zend_class_implements(phar_ce_archive TSRMLS_CC, 2, spl_ce_Countable, zend_ce_arrayaccess);
                   5570: 
                   5571:        INIT_CLASS_ENTRY(ce, "PharData", php_archive_methods);
                   5572:        phar_ce_data = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator, NULL  TSRMLS_CC);
                   5573: 
                   5574:        zend_class_implements(phar_ce_data TSRMLS_CC, 2, spl_ce_Countable, zend_ce_arrayaccess);
                   5575: 
                   5576:        INIT_CLASS_ENTRY(ce, "PharFileInfo", php_entry_methods);
                   5577:        phar_ce_entry = zend_register_internal_class_ex(&ce, spl_ce_SplFileInfo, NULL  TSRMLS_CC);
                   5578: #else
                   5579:        INIT_CLASS_ENTRY(ce, "Phar", php_archive_methods);
                   5580:        phar_ce_archive = zend_register_internal_class(&ce TSRMLS_CC);
                   5581:        phar_ce_archive->ce_flags |= ZEND_ACC_FINAL_CLASS;
                   5582: 
                   5583:        INIT_CLASS_ENTRY(ce, "PharData", php_archive_methods);
                   5584:        phar_ce_data = zend_register_internal_class(&ce TSRMLS_CC);
                   5585:        phar_ce_data->ce_flags |= ZEND_ACC_FINAL_CLASS;
                   5586: #endif
                   5587: 
                   5588:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "BZ2", PHAR_ENT_COMPRESSED_BZ2)
                   5589:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "GZ", PHAR_ENT_COMPRESSED_GZ)
                   5590:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "NONE", PHAR_ENT_COMPRESSED_NONE)
                   5591:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHAR", PHAR_FORMAT_PHAR)
                   5592:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "TAR", PHAR_FORMAT_TAR)
                   5593:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "ZIP", PHAR_FORMAT_ZIP)
                   5594:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "COMPRESSED", PHAR_ENT_COMPRESSION_MASK)
                   5595:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHP", PHAR_MIME_PHP)
                   5596:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHPS", PHAR_MIME_PHPS)
                   5597:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "MD5", PHAR_SIG_MD5)
                   5598:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "OPENSSL", PHAR_SIG_OPENSSL)
                   5599:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA1", PHAR_SIG_SHA1)
                   5600:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA256", PHAR_SIG_SHA256)
                   5601:        REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA512", PHAR_SIG_SHA512)
                   5602: }
                   5603: /* }}} */
                   5604: 
                   5605: /*
                   5606:  * Local variables:
                   5607:  * tab-width: 4
                   5608:  * c-basic-offset: 4
                   5609:  * End:
                   5610:  * vim600: noet sw=4 ts=4 fdm=marker
                   5611:  * vim<600: noet sw=4 ts=4
                   5612:  */

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