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