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