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

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

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