Annotation of embedaddon/php/ext/phar/phar_object.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | phar php single-file executable PHP extension |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 2005-2012 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 of the PHP license, |
! 8: | that is bundled with this package in the file LICENSE, and is |
! 9: | available through the world-wide-web at the following url: |
! 10: | http://www.php.net/license/3_01.txt. |
! 11: | If you did not receive a copy of the PHP license and are unable to |
! 12: | obtain it through the world-wide-web, please send a note to |
! 13: | license@php.net so we can mail you a copy immediately. |
! 14: +----------------------------------------------------------------------+
! 15: | Authors: Gregory Beaver <cellog@php.net> |
! 16: | 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] = ¶ms;
! 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, ®ex, ®ex_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(®exiter, 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(®exiter);
! 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(®exiter);
! 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(®exiter);
! 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>