Return to phar_object.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / phar |
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: */