PageRenderTime 239ms CodeModel.GetById 41ms RepoModel.GetById 0ms app.codeStats 2ms

/ext/phar/phar_object.c

http://github.com/php/php-src
C | 5199 lines | 3957 code | 772 blank | 470 comment | 1140 complexity | d61464bec3a114a57f5b0e28525667ba MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1
  1. /*
  2. +----------------------------------------------------------------------+
  3. | phar php single-file executable PHP extension |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 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. #include "phar_internal.h"
  20. #include "func_interceptors.h"
  21. #include "phar_object_arginfo.h"
  22. static zend_class_entry *phar_ce_archive;
  23. static zend_class_entry *phar_ce_data;
  24. static zend_class_entry *phar_ce_PharException;
  25. static zend_class_entry *phar_ce_entry;
  26. static int phar_file_type(HashTable *mimes, char *file, char **mime_type) /* {{{ */
  27. {
  28. char *ext;
  29. phar_mime_type *mime;
  30. ext = strrchr(file, '.');
  31. if (!ext) {
  32. *mime_type = "text/plain";
  33. /* no file extension = assume text/plain */
  34. return PHAR_MIME_OTHER;
  35. }
  36. ++ext;
  37. if (NULL == (mime = zend_hash_str_find_ptr(mimes, ext, strlen(ext)))) {
  38. *mime_type = "application/octet-stream";
  39. return PHAR_MIME_OTHER;
  40. }
  41. *mime_type = mime->mime;
  42. return mime->type;
  43. }
  44. /* }}} */
  45. static void phar_mung_server_vars(char *fname, char *entry, size_t entry_len, char *basename, size_t request_uri_len) /* {{{ */
  46. {
  47. HashTable *_SERVER;
  48. zval *stuff;
  49. char *path_info;
  50. size_t basename_len = strlen(basename);
  51. size_t code;
  52. zval temp;
  53. /* "tweak" $_SERVER variables requested in earlier call to Phar::mungServer() */
  54. if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_UNDEF) {
  55. return;
  56. }
  57. _SERVER = Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]);
  58. /* PATH_INFO and PATH_TRANSLATED should always be munged */
  59. if (NULL != (stuff = zend_hash_str_find(_SERVER, "PATH_INFO", sizeof("PATH_INFO")-1))) {
  60. path_info = Z_STRVAL_P(stuff);
  61. code = Z_STRLEN_P(stuff);
  62. if (code > (size_t)entry_len && !memcmp(path_info, entry, entry_len)) {
  63. ZVAL_STR(&temp, Z_STR_P(stuff));
  64. ZVAL_STRINGL(stuff, path_info + entry_len, request_uri_len);
  65. zend_hash_str_update(_SERVER, "PHAR_PATH_INFO", sizeof("PHAR_PATH_INFO")-1, &temp);
  66. }
  67. }
  68. if (NULL != (stuff = zend_hash_str_find(_SERVER, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED")-1))) {
  69. zend_string *str = strpprintf(4096, "phar://%s%s", fname, entry);
  70. ZVAL_STR(&temp, Z_STR_P(stuff));
  71. ZVAL_NEW_STR(stuff, str);
  72. zend_hash_str_update(_SERVER, "PHAR_PATH_TRANSLATED", sizeof("PHAR_PATH_TRANSLATED")-1, &temp);
  73. }
  74. if (!PHAR_G(phar_SERVER_mung_list)) {
  75. return;
  76. }
  77. if (PHAR_G(phar_SERVER_mung_list) & PHAR_MUNG_REQUEST_URI) {
  78. if (NULL != (stuff = zend_hash_str_find(_SERVER, "REQUEST_URI", sizeof("REQUEST_URI")-1))) {
  79. path_info = Z_STRVAL_P(stuff);
  80. code = Z_STRLEN_P(stuff);
  81. if (code > basename_len && !memcmp(path_info, basename, basename_len)) {
  82. ZVAL_STR(&temp, Z_STR_P(stuff));
  83. ZVAL_STRINGL(stuff, path_info + basename_len, code - basename_len);
  84. zend_hash_str_update(_SERVER, "PHAR_REQUEST_URI", sizeof("PHAR_REQUEST_URI")-1, &temp);
  85. }
  86. }
  87. }
  88. if (PHAR_G(phar_SERVER_mung_list) & PHAR_MUNG_PHP_SELF) {
  89. if (NULL != (stuff = zend_hash_str_find(_SERVER, "PHP_SELF", sizeof("PHP_SELF")-1))) {
  90. path_info = Z_STRVAL_P(stuff);
  91. code = Z_STRLEN_P(stuff);
  92. if (code > basename_len && !memcmp(path_info, basename, basename_len)) {
  93. ZVAL_STR(&temp, Z_STR_P(stuff));
  94. ZVAL_STRINGL(stuff, path_info + basename_len, code - basename_len);
  95. zend_hash_str_update(_SERVER, "PHAR_PHP_SELF", sizeof("PHAR_PHP_SELF")-1, &temp);
  96. }
  97. }
  98. }
  99. if (PHAR_G(phar_SERVER_mung_list) & PHAR_MUNG_SCRIPT_NAME) {
  100. if (NULL != (stuff = zend_hash_str_find(_SERVER, "SCRIPT_NAME", sizeof("SCRIPT_NAME")-1))) {
  101. ZVAL_STR(&temp, Z_STR_P(stuff));
  102. ZVAL_STRINGL(stuff, entry, entry_len);
  103. zend_hash_str_update(_SERVER, "PHAR_SCRIPT_NAME", sizeof("PHAR_SCRIPT_NAME")-1, &temp);
  104. }
  105. }
  106. if (PHAR_G(phar_SERVER_mung_list) & PHAR_MUNG_SCRIPT_FILENAME) {
  107. if (NULL != (stuff = zend_hash_str_find(_SERVER, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1))) {
  108. zend_string *str = strpprintf(4096, "phar://%s%s", fname, entry);
  109. ZVAL_STR(&temp, Z_STR_P(stuff));
  110. ZVAL_NEW_STR(stuff, str);
  111. zend_hash_str_update(_SERVER, "PHAR_SCRIPT_FILENAME", sizeof("PHAR_SCRIPT_FILENAME")-1, &temp);
  112. }
  113. }
  114. }
  115. /* }}} */
  116. static int phar_file_action(phar_archive_data *phar, phar_entry_info *info, char *mime_type, int code, char *entry, size_t entry_len, char *arch, char *basename, char *ru, size_t ru_len) /* {{{ */
  117. {
  118. char *name = NULL, buf[8192];
  119. const char *cwd;
  120. zend_syntax_highlighter_ini syntax_highlighter_ini;
  121. sapi_header_line ctr = {0};
  122. size_t got;
  123. zval dummy;
  124. size_t name_len;
  125. zend_file_handle file_handle;
  126. zend_op_array *new_op_array;
  127. zval result;
  128. php_stream *fp;
  129. zend_off_t position;
  130. switch (code) {
  131. case PHAR_MIME_PHPS:
  132. efree(basename);
  133. /* highlight source */
  134. if (entry[0] == '/') {
  135. spprintf(&name, 4096, "phar://%s%s", arch, entry);
  136. } else {
  137. spprintf(&name, 4096, "phar://%s/%s", arch, entry);
  138. }
  139. php_get_highlight_struct(&syntax_highlighter_ini);
  140. highlight_file(name, &syntax_highlighter_ini);
  141. efree(name);
  142. #ifdef PHP_WIN32
  143. efree(arch);
  144. #endif
  145. zend_bailout();
  146. case PHAR_MIME_OTHER:
  147. /* send headers, output file contents */
  148. efree(basename);
  149. ctr.line_len = spprintf(&(ctr.line), 0, "Content-type: %s", mime_type);
  150. sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
  151. efree(ctr.line);
  152. ctr.line_len = spprintf(&(ctr.line), 0, "Content-length: %u", info->uncompressed_filesize);
  153. sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
  154. efree(ctr.line);
  155. if (FAILURE == sapi_send_headers()) {
  156. zend_bailout();
  157. }
  158. /* prepare to output */
  159. fp = phar_get_efp(info, 1);
  160. if (!fp) {
  161. char *error;
  162. if (!phar_open_jit(phar, info, &error)) {
  163. if (error) {
  164. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  165. efree(error);
  166. }
  167. return -1;
  168. }
  169. fp = phar_get_efp(info, 1);
  170. }
  171. position = 0;
  172. phar_seek_efp(info, 0, SEEK_SET, 0, 1);
  173. do {
  174. got = php_stream_read(fp, buf, MIN(8192, info->uncompressed_filesize - position));
  175. if (got > 0) {
  176. PHPWRITE(buf, got);
  177. position += got;
  178. if (position == (zend_off_t) info->uncompressed_filesize) {
  179. break;
  180. }
  181. }
  182. } while (1);
  183. zend_bailout();
  184. case PHAR_MIME_PHP:
  185. if (basename) {
  186. phar_mung_server_vars(arch, entry, entry_len, basename, ru_len);
  187. efree(basename);
  188. }
  189. if (entry[0] == '/') {
  190. name_len = spprintf(&name, 4096, "phar://%s%s", arch, entry);
  191. } else {
  192. name_len = spprintf(&name, 4096, "phar://%s/%s", arch, entry);
  193. }
  194. zend_stream_init_filename(&file_handle, name);
  195. PHAR_G(cwd) = NULL;
  196. PHAR_G(cwd_len) = 0;
  197. ZVAL_NULL(&dummy);
  198. if (zend_hash_str_add(&EG(included_files), name, name_len, &dummy) != NULL) {
  199. if ((cwd = zend_memrchr(entry, '/', entry_len))) {
  200. PHAR_G(cwd_init) = 1;
  201. if (entry == cwd) {
  202. /* root directory */
  203. PHAR_G(cwd_len) = 0;
  204. PHAR_G(cwd) = NULL;
  205. } else if (entry[0] == '/') {
  206. PHAR_G(cwd_len) = (cwd - (entry + 1));
  207. PHAR_G(cwd) = estrndup(entry + 1, PHAR_G(cwd_len));
  208. } else {
  209. PHAR_G(cwd_len) = (cwd - entry);
  210. PHAR_G(cwd) = estrndup(entry, PHAR_G(cwd_len));
  211. }
  212. }
  213. new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE);
  214. if (!new_op_array) {
  215. zend_hash_str_del(&EG(included_files), name, name_len);
  216. }
  217. zend_destroy_file_handle(&file_handle);
  218. } else {
  219. efree(name);
  220. new_op_array = NULL;
  221. }
  222. #ifdef PHP_WIN32
  223. efree(arch);
  224. #endif
  225. if (new_op_array) {
  226. ZVAL_UNDEF(&result);
  227. zend_try {
  228. zend_execute(new_op_array, &result);
  229. if (PHAR_G(cwd)) {
  230. efree(PHAR_G(cwd));
  231. PHAR_G(cwd) = NULL;
  232. PHAR_G(cwd_len) = 0;
  233. }
  234. PHAR_G(cwd_init) = 0;
  235. efree(name);
  236. destroy_op_array(new_op_array);
  237. efree(new_op_array);
  238. zval_ptr_dtor(&result);
  239. } zend_catch {
  240. if (PHAR_G(cwd)) {
  241. efree(PHAR_G(cwd));
  242. PHAR_G(cwd) = NULL;
  243. PHAR_G(cwd_len) = 0;
  244. }
  245. PHAR_G(cwd_init) = 0;
  246. efree(name);
  247. } zend_end_try();
  248. zend_bailout();
  249. }
  250. return PHAR_MIME_PHP;
  251. }
  252. return -1;
  253. }
  254. /* }}} */
  255. static void phar_do_403(char *entry, size_t entry_len) /* {{{ */
  256. {
  257. sapi_header_line ctr = {0};
  258. ctr.response_code = 403;
  259. ctr.line_len = sizeof("HTTP/1.0 403 Access Denied")-1;
  260. ctr.line = "HTTP/1.0 403 Access Denied";
  261. sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
  262. sapi_send_headers();
  263. 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);
  264. PHPWRITE("Access Denied</h1>\n </body>\n</html>", sizeof("Access Denied</h1>\n </body>\n</html>") - 1);
  265. }
  266. /* }}} */
  267. static void phar_do_404(phar_archive_data *phar, char *fname, size_t fname_len, char *f404, size_t f404_len, char *entry, size_t entry_len) /* {{{ */
  268. {
  269. sapi_header_line ctr = {0};
  270. phar_entry_info *info;
  271. if (phar && f404_len) {
  272. info = phar_get_entry_info(phar, f404, f404_len, NULL, 1);
  273. if (info) {
  274. phar_file_action(phar, info, "text/html", PHAR_MIME_PHP, f404, f404_len, fname, NULL, NULL, 0);
  275. return;
  276. }
  277. }
  278. ctr.response_code = 404;
  279. ctr.line_len = sizeof("HTTP/1.0 404 Not Found")-1;
  280. ctr.line = "HTTP/1.0 404 Not Found";
  281. sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
  282. sapi_send_headers();
  283. 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);
  284. PHPWRITE("Not Found</h1>\n </body>\n</html>", sizeof("Not Found</h1>\n </body>\n</html>") - 1);
  285. }
  286. /* }}} */
  287. /* post-process REQUEST_URI and retrieve the actual request URI. This is for
  288. cases like http://localhost/blah.phar/path/to/file.php/extra/stuff
  289. which calls "blah.phar" file "path/to/file.php" with PATH_INFO "/extra/stuff" */
  290. static void phar_postprocess_ru_web(char *fname, size_t fname_len, char **entry, size_t *entry_len, char **ru, size_t *ru_len) /* {{{ */
  291. {
  292. char *e = *entry + 1, *u = NULL, *u1 = NULL, *saveu = NULL;
  293. size_t e_len = *entry_len - 1, u_len = 0;
  294. phar_archive_data *pphar;
  295. /* we already know we can retrieve the phar if we reach here */
  296. pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), fname, fname_len);
  297. if (!pphar && PHAR_G(manifest_cached)) {
  298. pphar = zend_hash_str_find_ptr(&cached_phars, fname, fname_len);
  299. }
  300. do {
  301. if (zend_hash_str_exists(&(pphar->manifest), e, e_len)) {
  302. if (u) {
  303. u[0] = '/';
  304. *ru = estrndup(u, u_len+1);
  305. ++u_len;
  306. u[0] = '\0';
  307. } else {
  308. *ru = NULL;
  309. }
  310. *ru_len = u_len;
  311. *entry_len = e_len + 1;
  312. return;
  313. }
  314. if (u) {
  315. u1 = strrchr(e, '/');
  316. u[0] = '/';
  317. saveu = u;
  318. e_len += u_len + 1;
  319. u = u1;
  320. if (!u) {
  321. return;
  322. }
  323. } else {
  324. u = strrchr(e, '/');
  325. if (!u) {
  326. if (saveu) {
  327. saveu[0] = '/';
  328. }
  329. return;
  330. }
  331. }
  332. u[0] = '\0';
  333. u_len = strlen(u + 1);
  334. e_len -= u_len + 1;
  335. } while (1);
  336. }
  337. /* }}} */
  338. /* {{{ proto void Phar::running([bool retphar = true])
  339. * return the name of the currently running phar archive. If the optional parameter
  340. * is set to true, return the phar:// URL to the currently running phar
  341. */
  342. PHP_METHOD(Phar, running)
  343. {
  344. char *fname, *arch, *entry;
  345. size_t fname_len, arch_len, entry_len;
  346. zend_bool retphar = 1;
  347. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &retphar) == FAILURE) {
  348. RETURN_THROWS();
  349. }
  350. fname = (char*)zend_get_executed_filename();
  351. fname_len = strlen(fname);
  352. if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  353. efree(entry);
  354. if (retphar) {
  355. RETVAL_STRINGL(fname, arch_len + 7);
  356. efree(arch);
  357. return;
  358. } else {
  359. // TODO: avoid reallocation ???
  360. RETVAL_STRINGL(arch, arch_len);
  361. efree(arch);
  362. return;
  363. }
  364. }
  365. RETURN_EMPTY_STRING();
  366. }
  367. /* }}} */
  368. /* {{{ proto void Phar::mount(string pharpath, string externalfile)
  369. * mount an external file or path to a location within the phar. This maps
  370. * an external file or directory to a location within the phar archive, allowing
  371. * reference to an external location as if it were within the phar archive. This
  372. * is useful for writable temp files like databases
  373. */
  374. PHP_METHOD(Phar, mount)
  375. {
  376. char *fname, *arch = NULL, *entry = NULL, *path, *actual;
  377. size_t fname_len, arch_len, entry_len;
  378. size_t path_len, actual_len;
  379. phar_archive_data *pphar;
  380. #ifdef PHP_WIN32
  381. char *save_fname;
  382. ALLOCA_FLAG(fname_use_heap)
  383. #endif
  384. if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &path, &path_len, &actual, &actual_len) == FAILURE) {
  385. RETURN_THROWS();
  386. }
  387. fname = (char*)zend_get_executed_filename();
  388. fname_len = strlen(fname);
  389. #ifdef PHP_WIN32
  390. save_fname = fname;
  391. if (memchr(fname, '\\', fname_len)) {
  392. fname = do_alloca(fname_len + 1, fname_use_heap);
  393. memcpy(fname, save_fname, fname_len);
  394. fname[fname_len] = '\0';
  395. phar_unixify_path_separators(fname, fname_len);
  396. }
  397. #endif
  398. if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  399. efree(entry);
  400. entry = NULL;
  401. if (path_len > 7 && !memcmp(path, "phar://", 7)) {
  402. zend_throw_exception_ex(phar_ce_PharException, 0, "Can only mount internal paths within a phar archive, use a relative path instead of \"%s\"", path);
  403. efree(arch);
  404. goto finish;
  405. }
  406. carry_on2:
  407. if (NULL == (pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), arch, arch_len))) {
  408. if (PHAR_G(manifest_cached) && NULL != (pphar = zend_hash_str_find_ptr(&cached_phars, arch, arch_len))) {
  409. if (SUCCESS == phar_copy_on_write(&pphar)) {
  410. goto carry_on;
  411. }
  412. }
  413. zend_throw_exception_ex(phar_ce_PharException, 0, "%s is not a phar archive, cannot mount", arch);
  414. if (arch) {
  415. efree(arch);
  416. }
  417. goto finish;
  418. }
  419. carry_on:
  420. if (SUCCESS != phar_mount_entry(pphar, actual, actual_len, path, path_len)) {
  421. zend_throw_exception_ex(phar_ce_PharException, 0, "Mounting of %s to %s within phar %s failed", path, actual, arch);
  422. if (path && path == entry) {
  423. efree(entry);
  424. }
  425. if (arch) {
  426. efree(arch);
  427. }
  428. goto finish;
  429. }
  430. if (entry && path && path == entry) {
  431. efree(entry);
  432. }
  433. if (arch) {
  434. efree(arch);
  435. }
  436. goto finish;
  437. } else if (HT_IS_INITIALIZED(&PHAR_G(phar_fname_map)) && NULL != (pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), fname, fname_len))) {
  438. goto carry_on;
  439. } else if (PHAR_G(manifest_cached) && NULL != (pphar = zend_hash_str_find_ptr(&cached_phars, fname, fname_len))) {
  440. if (SUCCESS == phar_copy_on_write(&pphar)) {
  441. goto carry_on;
  442. }
  443. goto carry_on;
  444. } else if (SUCCESS == phar_split_fname(path, path_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  445. path = entry;
  446. path_len = entry_len;
  447. goto carry_on2;
  448. }
  449. zend_throw_exception_ex(phar_ce_PharException, 0, "Mounting of %s to %s failed", path, actual);
  450. finish: ;
  451. #ifdef PHP_WIN32
  452. if (fname != save_fname) {
  453. free_alloca(fname, fname_use_heap);
  454. fname = save_fname;
  455. }
  456. #endif
  457. }
  458. /* }}} */
  459. /* {{{ proto void Phar::webPhar([string alias, [string index, [string f404, [array mimetypes, [callback rewrites]]]]])
  460. * mapPhar for web-based phars. Reads the currently executed file (a phar)
  461. * and registers its manifest. When executed in the CLI or CGI command-line sapi,
  462. * this works exactly like mapPhar(). When executed by a web-based sapi, this
  463. * reads $_SERVER['REQUEST_URI'] (the actual original value) and parses out the
  464. * intended internal file.
  465. */
  466. PHP_METHOD(Phar, webPhar)
  467. {
  468. zval *mimeoverride = NULL, *rewrite = NULL;
  469. char *alias = NULL, *error, *index_php = NULL, *f404 = NULL, *ru = NULL;
  470. size_t alias_len = 0, f404_len = 0, free_pathinfo = 0;
  471. size_t ru_len = 0;
  472. char *fname, *path_info, *mime_type = NULL, *entry, *pt;
  473. const char *basename;
  474. size_t fname_len, index_php_len = 0;
  475. size_t entry_len;
  476. int code, not_cgi;
  477. phar_archive_data *phar = NULL;
  478. phar_entry_info *info = NULL;
  479. size_t sapi_mod_name_len = strlen(sapi_module.name);
  480. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!s!saz", &alias, &alias_len, &index_php, &index_php_len, &f404, &f404_len, &mimeoverride, &rewrite) == FAILURE) {
  481. RETURN_THROWS();
  482. }
  483. phar_request_initialize();
  484. fname = (char*)zend_get_executed_filename();
  485. fname_len = strlen(fname);
  486. if (phar_open_executed_filename(alias, alias_len, &error) != SUCCESS) {
  487. if (error) {
  488. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  489. efree(error);
  490. }
  491. return;
  492. }
  493. /* retrieve requested file within phar */
  494. if (!(SG(request_info).request_method
  495. && SG(request_info).request_uri
  496. && (!strcmp(SG(request_info).request_method, "GET")
  497. || !strcmp(SG(request_info).request_method, "POST")
  498. || !strcmp(SG(request_info).request_method, "DELETE")
  499. || !strcmp(SG(request_info).request_method, "HEAD")
  500. || !strcmp(SG(request_info).request_method, "OPTIONS")
  501. || !strcmp(SG(request_info).request_method, "PATCH")
  502. || !strcmp(SG(request_info).request_method, "PUT")
  503. )
  504. )
  505. ) {
  506. return;
  507. }
  508. #ifdef PHP_WIN32
  509. if (memchr(fname, '\\', fname_len)) {
  510. fname = estrndup(fname, fname_len);
  511. phar_unixify_path_separators(fname, fname_len);
  512. }
  513. #endif
  514. basename = zend_memrchr(fname, '/', fname_len);
  515. if (!basename) {
  516. basename = fname;
  517. } else {
  518. ++basename;
  519. }
  520. if ((sapi_mod_name_len == sizeof("cgi-fcgi") - 1 && !strncmp(sapi_module.name, "cgi-fcgi", sizeof("cgi-fcgi") - 1))
  521. || (sapi_mod_name_len == sizeof("fpm-fcgi") - 1 && !strncmp(sapi_module.name, "fpm-fcgi", sizeof("fpm-fcgi") - 1))
  522. || (sapi_mod_name_len == sizeof("cgi") - 1 && !strncmp(sapi_module.name, "cgi", sizeof("cgi") - 1))) {
  523. if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) != IS_UNDEF) {
  524. HashTable *_server = Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]);
  525. zval *z_script_name, *z_path_info;
  526. if (NULL == (z_script_name = zend_hash_str_find(_server, "SCRIPT_NAME", sizeof("SCRIPT_NAME")-1)) ||
  527. IS_STRING != Z_TYPE_P(z_script_name) ||
  528. !strstr(Z_STRVAL_P(z_script_name), basename)) {
  529. return;
  530. }
  531. if (NULL != (z_path_info = zend_hash_str_find(_server, "PATH_INFO", sizeof("PATH_INFO")-1)) &&
  532. IS_STRING == Z_TYPE_P(z_path_info)) {
  533. entry_len = Z_STRLEN_P(z_path_info);
  534. entry = estrndup(Z_STRVAL_P(z_path_info), entry_len);
  535. path_info = emalloc(Z_STRLEN_P(z_script_name) + entry_len + 1);
  536. memcpy(path_info, Z_STRVAL_P(z_script_name), Z_STRLEN_P(z_script_name));
  537. memcpy(path_info + Z_STRLEN_P(z_script_name), entry, entry_len + 1);
  538. free_pathinfo = 1;
  539. } else {
  540. entry_len = 0;
  541. entry = estrndup("", 0);
  542. path_info = Z_STRVAL_P(z_script_name);
  543. }
  544. pt = estrndup(Z_STRVAL_P(z_script_name), Z_STRLEN_P(z_script_name));
  545. } else {
  546. char *testit;
  547. testit = sapi_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1);
  548. if (!(pt = strstr(testit, basename))) {
  549. efree(testit);
  550. return;
  551. }
  552. path_info = sapi_getenv("PATH_INFO", sizeof("PATH_INFO")-1);
  553. if (path_info) {
  554. entry = path_info;
  555. entry_len = strlen(entry);
  556. spprintf(&path_info, 0, "%s%s", testit, path_info);
  557. free_pathinfo = 1;
  558. } else {
  559. path_info = testit;
  560. free_pathinfo = 1;
  561. entry = estrndup("", 0);
  562. entry_len = 0;
  563. }
  564. pt = estrndup(testit, (pt - testit) + (fname_len - (basename - fname)));
  565. }
  566. not_cgi = 0;
  567. } else {
  568. path_info = SG(request_info).request_uri;
  569. if (!(pt = strstr(path_info, basename))) {
  570. /* this can happen with rewrite rules - and we have no idea what to do then, so return */
  571. return;
  572. }
  573. entry_len = strlen(path_info);
  574. entry_len -= (pt - path_info) + (fname_len - (basename - fname));
  575. entry = estrndup(pt + (fname_len - (basename - fname)), entry_len);
  576. pt = estrndup(path_info, (pt - path_info) + (fname_len - (basename - fname)));
  577. not_cgi = 1;
  578. }
  579. if (rewrite) {
  580. zend_fcall_info fci;
  581. zend_fcall_info_cache fcc;
  582. zval params, retval;
  583. ZVAL_STRINGL(&params, entry, entry_len);
  584. if (FAILURE == zend_fcall_info_init(rewrite, 0, &fci, &fcc, NULL, NULL)) {
  585. zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: invalid rewrite callback");
  586. if (free_pathinfo) {
  587. efree(path_info);
  588. }
  589. efree(pt);
  590. RETURN_THROWS();
  591. }
  592. fci.param_count = 1;
  593. fci.params = &params;
  594. Z_ADDREF(params);
  595. fci.retval = &retval;
  596. if (FAILURE == zend_call_function(&fci, &fcc)) {
  597. if (!EG(exception)) {
  598. zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: failed to call rewrite callback");
  599. }
  600. if (free_pathinfo) {
  601. efree(path_info);
  602. }
  603. efree(pt);
  604. RETURN_THROWS();
  605. }
  606. if (Z_TYPE_P(fci.retval) == IS_UNDEF || Z_TYPE(retval) == IS_UNDEF) {
  607. if (free_pathinfo) {
  608. efree(path_info);
  609. }
  610. zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: rewrite callback must return a string or false");
  611. efree(pt);
  612. RETURN_THROWS();
  613. }
  614. switch (Z_TYPE(retval)) {
  615. case IS_STRING:
  616. efree(entry);
  617. entry = estrndup(Z_STRVAL_P(fci.retval), Z_STRLEN_P(fci.retval));
  618. entry_len = Z_STRLEN_P(fci.retval);
  619. break;
  620. case IS_TRUE:
  621. case IS_FALSE:
  622. phar_do_403(entry, entry_len);
  623. if (free_pathinfo) {
  624. efree(path_info);
  625. }
  626. efree(pt);
  627. zend_bailout();
  628. return;
  629. default:
  630. if (free_pathinfo) {
  631. efree(path_info);
  632. }
  633. efree(pt);
  634. zend_throw_exception_ex(phar_ce_PharException, 0, "phar error: rewrite callback must return a string or false");
  635. RETURN_THROWS();
  636. }
  637. }
  638. if (entry_len) {
  639. phar_postprocess_ru_web(fname, fname_len, &entry, &entry_len, &ru, &ru_len);
  640. }
  641. if (!entry_len || (entry_len == 1 && entry[0] == '/')) {
  642. efree(entry);
  643. /* direct request */
  644. if (index_php_len) {
  645. entry = index_php;
  646. entry_len = index_php_len;
  647. if (entry[0] != '/') {
  648. spprintf(&entry, 0, "/%s", index_php);
  649. ++entry_len;
  650. }
  651. } else {
  652. /* assume "index.php" is starting point */
  653. entry = estrndup("/index.php", sizeof("/index.php"));
  654. entry_len = sizeof("/index.php")-1;
  655. }
  656. if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL) ||
  657. (info = phar_get_entry_info(phar, entry, entry_len, NULL, 0)) == NULL) {
  658. phar_do_404(phar, fname, fname_len, f404, f404_len, entry, entry_len);
  659. if (free_pathinfo) {
  660. efree(path_info);
  661. }
  662. zend_bailout();
  663. } else {
  664. char *tmp = NULL, sa = '\0';
  665. sapi_header_line ctr = {0};
  666. ctr.response_code = 301;
  667. ctr.line_len = sizeof("HTTP/1.1 301 Moved Permanently")-1;
  668. ctr.line = "HTTP/1.1 301 Moved Permanently";
  669. sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
  670. if (not_cgi) {
  671. tmp = strstr(path_info, basename) + fname_len;
  672. sa = *tmp;
  673. *tmp = '\0';
  674. }
  675. ctr.response_code = 0;
  676. if (path_info[strlen(path_info)-1] == '/') {
  677. ctr.line_len = spprintf(&(ctr.line), 4096, "Location: %s%s", path_info, entry + 1);
  678. } else {
  679. ctr.line_len = spprintf(&(ctr.line), 4096, "Location: %s%s", path_info, entry);
  680. }
  681. if (not_cgi) {
  682. *tmp = sa;
  683. }
  684. if (free_pathinfo) {
  685. efree(path_info);
  686. }
  687. sapi_header_op(SAPI_HEADER_REPLACE, &ctr);
  688. sapi_send_headers();
  689. efree(ctr.line);
  690. zend_bailout();
  691. }
  692. }
  693. if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL) ||
  694. (info = phar_get_entry_info(phar, entry, entry_len, NULL, 0)) == NULL) {
  695. phar_do_404(phar, fname, fname_len, f404, f404_len, entry, entry_len);
  696. #ifdef PHP_WIN32
  697. efree(fname);
  698. #endif
  699. zend_bailout();
  700. }
  701. if (mimeoverride && zend_hash_num_elements(Z_ARRVAL_P(mimeoverride))) {
  702. const char *ext = zend_memrchr(entry, '.', entry_len);
  703. zval *val;
  704. if (ext) {
  705. ++ext;
  706. if (NULL != (val = zend_hash_str_find(Z_ARRVAL_P(mimeoverride), ext, strlen(ext)))) {
  707. switch (Z_TYPE_P(val)) {
  708. case IS_LONG:
  709. if (Z_LVAL_P(val) == PHAR_MIME_PHP || Z_LVAL_P(val) == PHAR_MIME_PHPS) {
  710. mime_type = "";
  711. code = Z_LVAL_P(val);
  712. } else {
  713. zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown mime type specifier used, only Phar::PHP, Phar::PHPS and a mime type string are allowed");
  714. if (free_pathinfo) {
  715. efree(path_info);
  716. }
  717. efree(pt);
  718. efree(entry);
  719. #ifdef PHP_WIN32
  720. efree(fname);
  721. #endif
  722. RETURN_THROWS();
  723. }
  724. break;
  725. case IS_STRING:
  726. mime_type = Z_STRVAL_P(val);
  727. code = PHAR_MIME_OTHER;
  728. break;
  729. default:
  730. zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown mime type specifier used (not a string or int), only Phar::PHP, Phar::PHPS and a mime type string are allowed");
  731. if (free_pathinfo) {
  732. efree(path_info);
  733. }
  734. efree(pt);
  735. efree(entry);
  736. #ifdef PHP_WIN32
  737. efree(fname);
  738. #endif
  739. RETURN_THROWS();
  740. }
  741. }
  742. }
  743. }
  744. if (!mime_type) {
  745. code = phar_file_type(&PHAR_G(mime_types), entry, &mime_type);
  746. }
  747. phar_file_action(phar, info, mime_type, code, entry, entry_len, fname, pt, ru, ru_len);
  748. }
  749. /* }}} */
  750. /* {{{ proto void Phar::mungServer(array munglist)
  751. * Defines a list of up to 4 $_SERVER variables that should be modified for execution
  752. * to mask the presence of the phar archive. This should be used in conjunction with
  753. * Phar::webPhar(), and has no effect otherwise
  754. * SCRIPT_NAME, PHP_SELF, REQUEST_URI and SCRIPT_FILENAME
  755. */
  756. PHP_METHOD(Phar, mungServer)
  757. {
  758. zval *mungvalues, *data;
  759. if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &mungvalues) == FAILURE) {
  760. RETURN_THROWS();
  761. }
  762. if (!zend_hash_num_elements(Z_ARRVAL_P(mungvalues))) {
  763. zend_throw_exception_ex(phar_ce_PharException, 0, "No values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
  764. RETURN_THROWS();
  765. }
  766. if (zend_hash_num_elements(Z_ARRVAL_P(mungvalues)) > 4) {
  767. zend_throw_exception_ex(phar_ce_PharException, 0, "Too many values passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
  768. RETURN_THROWS();
  769. }
  770. phar_request_initialize();
  771. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(mungvalues), data) {
  772. if (Z_TYPE_P(data) != IS_STRING) {
  773. zend_throw_exception_ex(phar_ce_PharException, 0, "Non-string value passed to Phar::mungServer(), expecting an array of any of these strings: PHP_SELF, REQUEST_URI, SCRIPT_FILENAME, SCRIPT_NAME");
  774. RETURN_THROWS();
  775. }
  776. if (Z_STRLEN_P(data) == sizeof("PHP_SELF")-1 && !strncmp(Z_STRVAL_P(data), "PHP_SELF", sizeof("PHP_SELF")-1)) {
  777. PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_PHP_SELF;
  778. }
  779. if (Z_STRLEN_P(data) == sizeof("REQUEST_URI")-1) {
  780. if (!strncmp(Z_STRVAL_P(data), "REQUEST_URI", sizeof("REQUEST_URI")-1)) {
  781. PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_REQUEST_URI;
  782. }
  783. if (!strncmp(Z_STRVAL_P(data), "SCRIPT_NAME", sizeof("SCRIPT_NAME")-1)) {
  784. PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_SCRIPT_NAME;
  785. }
  786. }
  787. if (Z_STRLEN_P(data) == sizeof("SCRIPT_FILENAME")-1 && !strncmp(Z_STRVAL_P(data), "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1)) {
  788. PHAR_G(phar_SERVER_mung_list) |= PHAR_MUNG_SCRIPT_FILENAME;
  789. }
  790. } ZEND_HASH_FOREACH_END();
  791. }
  792. /* }}} */
  793. /* {{{ proto void Phar::interceptFileFuncs()
  794. * instructs phar to intercept fopen, file_get_contents, opendir, and all of the stat-related functions
  795. * and return stat on files within the phar for relative paths
  796. *
  797. * Once called, this cannot be reversed, and continue until the end of the request.
  798. *
  799. * This allows legacy scripts to be pharred unmodified
  800. */
  801. PHP_METHOD(Phar, interceptFileFuncs)
  802. {
  803. if (zend_parse_parameters_none() == FAILURE) {
  804. RETURN_THROWS();
  805. }
  806. phar_intercept_functions();
  807. }
  808. /* }}} */
  809. /* {{{ proto array Phar::createDefaultStub([string indexfile[, string webindexfile]])
  810. * Return a stub that can be used to run a phar-based archive without the phar extension
  811. * indexfile is the CLI startup filename, which defaults to "index.php", webindexfile
  812. * is the web startup filename, and also defaults to "index.php"
  813. */
  814. PHP_METHOD(Phar, createDefaultStub)
  815. {
  816. char *index = NULL, *webindex = NULL, *error;
  817. zend_string *stub;
  818. size_t index_len = 0, webindex_len = 0;
  819. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|pp", &index, &index_len, &webindex, &webindex_len) == FAILURE) {
  820. RETURN_THROWS();
  821. }
  822. stub = phar_create_default_stub(index, webindex, &error);
  823. if (error) {
  824. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  825. efree(error);
  826. RETURN_THROWS();
  827. }
  828. RETURN_NEW_STR(stub);
  829. }
  830. /* }}} */
  831. /* {{{ proto mixed Phar::mapPhar([string alias, [int dataoffset]])
  832. * Reads the currently executed file (a phar) and registers its manifest */
  833. PHP_METHOD(Phar, mapPhar)
  834. {
  835. char *alias = NULL, *error;
  836. size_t alias_len = 0;
  837. zend_long dataoffset = 0;
  838. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!l", &alias, &alias_len, &dataoffset) == FAILURE) {
  839. RETURN_THROWS();
  840. }
  841. phar_request_initialize();
  842. RETVAL_BOOL(phar_open_executed_filename(alias, alias_len, &error) == SUCCESS);
  843. if (error) {
  844. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  845. efree(error);
  846. }
  847. } /* }}} */
  848. /* {{{ proto mixed Phar::loadPhar(string filename [, string alias])
  849. * Loads any phar archive with an alias */
  850. PHP_METHOD(Phar, loadPhar)
  851. {
  852. char *fname, *alias = NULL, *error;
  853. size_t fname_len, alias_len = 0;
  854. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s!", &fname, &fname_len, &alias, &alias_len) == FAILURE) {
  855. RETURN_THROWS();
  856. }
  857. phar_request_initialize();
  858. RETVAL_BOOL(phar_open_from_filename(fname, fname_len, alias, alias_len, REPORT_ERRORS, NULL, &error) == SUCCESS);
  859. if (error) {
  860. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  861. efree(error);
  862. }
  863. } /* }}} */
  864. /* {{{ proto string Phar::apiVersion()
  865. * Returns the api version */
  866. PHP_METHOD(Phar, apiVersion)
  867. {
  868. if (zend_parse_parameters_none() == FAILURE) {
  869. RETURN_THROWS();
  870. }
  871. RETURN_STRINGL(PHP_PHAR_API_VERSION, sizeof(PHP_PHAR_API_VERSION)-1);
  872. }
  873. /* }}}*/
  874. /* {{{ proto bool Phar::canCompress([int method])
  875. * Returns whether phar extension supports compression using zlib/bzip2 */
  876. PHP_METHOD(Phar, canCompress)
  877. {
  878. zend_long method = 0;
  879. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &method) == FAILURE) {
  880. RETURN_THROWS();
  881. }
  882. phar_request_initialize();
  883. switch (method) {
  884. case PHAR_ENT_COMPRESSED_GZ:
  885. if (PHAR_G(has_zlib)) {
  886. RETURN_TRUE;
  887. } else {
  888. RETURN_FALSE;
  889. }
  890. case PHAR_ENT_COMPRESSED_BZ2:
  891. if (PHAR_G(has_bz2)) {
  892. RETURN_TRUE;
  893. } else {
  894. RETURN_FALSE;
  895. }
  896. default:
  897. if (PHAR_G(has_zlib) || PHAR_G(has_bz2)) {
  898. RETURN_TRUE;
  899. } else {
  900. RETURN_FALSE;
  901. }
  902. }
  903. }
  904. /* }}} */
  905. /* {{{ proto bool Phar::canWrite()
  906. * Returns whether phar extension supports writing and creating phars */
  907. PHP_METHOD(Phar, canWrite)
  908. {
  909. if (zend_parse_parameters_none() == FAILURE) {
  910. RETURN_THROWS();
  911. }
  912. RETURN_BOOL(!PHAR_G(readonly));
  913. }
  914. /* }}} */
  915. /* {{{ proto bool Phar::isValidPharFilename(string filename[, bool executable = true])
  916. * Returns whether the given filename is a valid phar filename */
  917. PHP_METHOD(Phar, isValidPharFilename)
  918. {
  919. char *fname;
  920. const char *ext_str;
  921. size_t fname_len;
  922. size_t ext_len;
  923. int is_executable;
  924. zend_bool executable = 1;
  925. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|b", &fname, &fname_len, &executable) == FAILURE) {
  926. RETURN_THROWS();
  927. }
  928. is_executable = executable;
  929. RETVAL_BOOL(phar_detect_phar_fname_ext(fname, fname_len, &ext_str, &ext_len, is_executable, 2, 1) == SUCCESS);
  930. }
  931. /* }}} */
  932. /**
  933. * from spl_directory
  934. */
  935. static void phar_spl_foreign_dtor(spl_filesystem_object *object) /* {{{ */
  936. {
  937. phar_archive_data *phar = (phar_archive_data *) object->oth;
  938. if (!phar->is_persistent) {
  939. phar_archive_delref(phar);
  940. }
  941. object->oth = NULL;
  942. }
  943. /* }}} */
  944. /**
  945. * from spl_directory
  946. */
  947. static void phar_spl_foreign_clone(spl_filesystem_object *src, spl_filesystem_object *dst) /* {{{ */
  948. {
  949. phar_archive_data *phar_data = (phar_archive_data *) dst->oth;
  950. if (!phar_data->is_persistent) {
  951. ++(phar_data->refcount);
  952. }
  953. }
  954. /* }}} */
  955. static const spl_other_handler phar_spl_foreign_handler = {
  956. phar_spl_foreign_dtor,
  957. phar_spl_foreign_clone
  958. };
  959. /* {{{ proto Phar::__construct(string fname [, int flags [, string alias]])
  960. * Construct a Phar archive object
  961. *
  962. * proto PharData::__construct(string fname [[, int flags [, string alias]], int file format = Phar::TAR])
  963. * Construct a PharData archive object
  964. *
  965. * This function is used as the constructor for both the Phar and PharData
  966. * classes, hence the two prototypes above.
  967. */
  968. PHP_METHOD(Phar, __construct)
  969. {
  970. char *fname, *alias = NULL, *error, *arch = NULL, *entry = NULL, *save_fname;
  971. size_t fname_len, alias_len = 0;
  972. size_t arch_len, entry_len;
  973. zend_bool is_data;
  974. zend_long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS;
  975. zend_long format = 0;
  976. phar_archive_object *phar_obj;
  977. phar_archive_data *phar_data;
  978. zval *zobj = ZEND_THIS, arg1, arg2;
  979. phar_obj = (phar_archive_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset);
  980. is_data = instanceof_function(Z_OBJCE_P(zobj), phar_ce_data);
  981. if (is_data) {
  982. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|ls!l", &fname, &fname_len, &flags, &alias, &alias_len, &format) == FAILURE) {
  983. RETURN_THROWS();
  984. }
  985. } else {
  986. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|ls!", &fname, &fname_len, &flags, &alias, &alias_len) == FAILURE) {
  987. RETURN_THROWS();
  988. }
  989. }
  990. if (phar_obj->archive) {
  991. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot call constructor twice");
  992. RETURN_THROWS();
  993. }
  994. save_fname = fname;
  995. if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, !is_data, 2)) {
  996. /* use arch (the basename for the archive) for fname instead of fname */
  997. /* this allows support for RecursiveDirectoryIterator of subdirectories */
  998. #ifdef PHP_WIN32
  999. phar_unixify_path_separators(arch, arch_len);
  1000. #endif
  1001. fname = arch;
  1002. fname_len = arch_len;
  1003. #ifdef PHP_WIN32
  1004. } else {
  1005. arch = estrndup(fname, fname_len);
  1006. arch_len = fname_len;
  1007. fname = arch;
  1008. phar_unixify_path_separators(arch, arch_len);
  1009. #endif
  1010. }
  1011. if (phar_open_or_create_filename(fname, fname_len, alias, alias_len, is_data, REPORT_ERRORS, &phar_data, &error) == FAILURE) {
  1012. if (fname == arch && fname != save_fname) {
  1013. efree(arch);
  1014. fname = save_fname;
  1015. }
  1016. if (entry) {
  1017. efree(entry);
  1018. }
  1019. if (error) {
  1020. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1021. "%s", error);
  1022. efree(error);
  1023. } else {
  1024. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1025. "Phar creation or opening failed");
  1026. }
  1027. RETURN_THROWS();
  1028. }
  1029. if (is_data && phar_data->is_tar && phar_data->is_brandnew && format == PHAR_FORMAT_ZIP) {
  1030. phar_data->is_zip = 1;
  1031. phar_data->is_tar = 0;
  1032. }
  1033. if (fname == arch) {
  1034. efree(arch);
  1035. fname = save_fname;
  1036. }
  1037. if ((is_data && !phar_data->is_data) || (!is_data && phar_data->is_data)) {
  1038. if (is_data) {
  1039. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1040. "PharData class can only be used for non-executable tar and zip archives");
  1041. } else {
  1042. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1043. "Phar class can only be used for executable tar and zip archives");
  1044. }
  1045. efree(entry);
  1046. RETURN_THROWS();
  1047. }
  1048. is_data = phar_data->is_data;
  1049. if (!phar_data->is_persistent) {
  1050. ++(phar_data->refcount);
  1051. }
  1052. phar_obj->archive = phar_data;
  1053. phar_obj->spl.oth_handler = &phar_spl_foreign_handler;
  1054. if (entry) {
  1055. fname_len = spprintf(&fname, 0, "phar://%s%s", phar_data->fname, entry);
  1056. efree(entry);
  1057. } else {
  1058. fname_len = spprintf(&fname, 0, "phar://%s", phar_data->fname);
  1059. }
  1060. ZVAL_STRINGL(&arg1, fname, fname_len);
  1061. ZVAL_LONG(&arg2, flags);
  1062. zend_call_method_with_2_params(Z_OBJ_P(zobj), Z_OBJCE_P(zobj),
  1063. &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg1, &arg2);
  1064. zval_ptr_dtor(&arg1);
  1065. if (!phar_data->is_persistent) {
  1066. phar_obj->archive->is_data = is_data;
  1067. } else if (!EG(exception)) {
  1068. /* register this guy so we can modify if necessary */
  1069. zend_hash_str_add_ptr(&PHAR_G(phar_persist_map), (const char *) phar_obj->archive, sizeof(phar_obj->archive), phar_obj);
  1070. }
  1071. phar_obj->spl.info_class = phar_ce_entry;
  1072. efree(fname);
  1073. }
  1074. /* }}} */
  1075. /* {{{ proto array Phar::getSupportedSignatures()
  1076. * Return array of supported signature types
  1077. */
  1078. PHP_METHOD(Phar, getSupportedSignatures)
  1079. {
  1080. if (zend_parse_parameters_none() == FAILURE) {
  1081. RETURN_THROWS();
  1082. }
  1083. array_init(return_value);
  1084. add_next_index_stringl(return_value, "MD5", 3);
  1085. add_next_index_stringl(return_value, "SHA-1", 5);
  1086. add_next_index_stringl(return_value, "SHA-256", 7);
  1087. add_next_index_stringl(return_value, "SHA-512", 7);
  1088. #if PHAR_HAVE_OPENSSL
  1089. add_next_index_stringl(return_value, "OpenSSL", 7);
  1090. #else
  1091. if (zend_hash_str_exists(&module_registry, "openssl", sizeof("openssl")-1)) {
  1092. add_next_index_stringl(return_value, "OpenSSL", 7);
  1093. }
  1094. #endif
  1095. }
  1096. /* }}} */
  1097. /* {{{ proto array Phar::getSupportedCompression()
  1098. * Return array of supported comparession algorithms
  1099. */
  1100. PHP_METHOD(Phar, getSupportedCompression)
  1101. {
  1102. if (zend_parse_parameters_none() == FAILURE) {
  1103. RETURN_THROWS();
  1104. }
  1105. array_init(return_value);
  1106. phar_request_initialize();
  1107. if (PHAR_G(has_zlib)) {
  1108. add_next_index_stringl(return_value, "GZ", 2);
  1109. }
  1110. if (PHAR_G(has_bz2)) {
  1111. add_next_index_stringl(return_value, "BZIP2", 5);
  1112. }
  1113. }
  1114. /* }}} */
  1115. /* {{{ proto array Phar::unlinkArchive(string archive)
  1116. * Completely remove a phar archive from memory and disk
  1117. */
  1118. PHP_METHOD(Phar, unlinkArchive)
  1119. {
  1120. char *fname, *error, *zname, *arch, *entry;
  1121. size_t fname_len;
  1122. size_t zname_len, arch_len, entry_len;
  1123. phar_archive_data *phar;
  1124. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
  1125. RETURN_THROWS();
  1126. }
  1127. if (!fname_len) {
  1128. zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown phar archive \"\"");
  1129. RETURN_THROWS();
  1130. }
  1131. if (FAILURE == phar_open_from_filename(fname, fname_len, NULL, 0, REPORT_ERRORS, &phar, &error)) {
  1132. if (error) {
  1133. zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown phar archive \"%s\": %s", fname, error);
  1134. efree(error);
  1135. } else {
  1136. zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown phar archive \"%s\"", fname);
  1137. }
  1138. RETURN_THROWS();
  1139. }
  1140. zname = (char*)zend_get_executed_filename();
  1141. zname_len = strlen(zname);
  1142. if (zname_len > 7 && !memcmp(zname, "phar://", 7) && SUCCESS == phar_split_fname(zname, zname_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
  1143. if ((size_t)arch_len == fname_len && !memcmp(arch, fname, arch_len)) {
  1144. zend_throw_exception_ex(phar_ce_PharException, 0, "phar archive \"%s\" cannot be unlinked from within itself", fname);
  1145. efree(arch);
  1146. efree(entry);
  1147. RETURN_THROWS();
  1148. }
  1149. efree(arch);
  1150. efree(entry);
  1151. }
  1152. if (phar->is_persistent) {
  1153. zend_throw_exception_ex(phar_ce_PharException, 0, "phar archive \"%s\" is in phar.cache_list, cannot unlinkArchive()", fname);
  1154. RETURN_THROWS();
  1155. }
  1156. if (phar->refcount) {
  1157. zend_throw_exception_ex(phar_ce_PharException, 0, "phar archive \"%s\" has open file handles or objects. fclose() all file handles, and unset() all objects prior to calling unlinkArchive()", fname);
  1158. RETURN_THROWS();
  1159. }
  1160. fname = estrndup(phar->fname, phar->fname_len);
  1161. /* invalidate phar cache */
  1162. PHAR_G(last_phar) = NULL;
  1163. PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
  1164. phar_archive_delref(phar);
  1165. unlink(fname);
  1166. efree(fname);
  1167. RETURN_TRUE;
  1168. }
  1169. /* }}} */
  1170. #define PHAR_ARCHIVE_OBJECT() \
  1171. zval *zobj = ZEND_THIS; \
  1172. phar_archive_object *phar_obj = (phar_archive_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); \
  1173. if (!phar_obj->archive) { \
  1174. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  1175. "Cannot call method on an uninitialized Phar object"); \
  1176. RETURN_THROWS(); \
  1177. }
  1178. /* {{{ proto Phar::__destruct()
  1179. * if persistent, remove from the cache
  1180. */
  1181. PHP_METHOD(Phar, __destruct)
  1182. {
  1183. zval *zobj = ZEND_THIS;
  1184. phar_archive_object *phar_obj = (phar_archive_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset);
  1185. if (zend_parse_parameters_none() == FAILURE) {
  1186. RETURN_THROWS();
  1187. }
  1188. if (phar_obj->archive && phar_obj->archive->is_persistent) {
  1189. zend_hash_str_del(&PHAR_G(phar_persist_map), (const char *) phar_obj->archive, sizeof(phar_obj->archive));
  1190. }
  1191. }
  1192. /* }}} */
  1193. struct _phar_t {
  1194. phar_archive_object *p;
  1195. zend_class_entry *c;
  1196. char *b;
  1197. zval *ret;
  1198. php_stream *fp;
  1199. uint32_t l;
  1200. int count;
  1201. };
  1202. static int phar_build(zend_object_iterator *iter, void *puser) /* {{{ */
  1203. {
  1204. zval *value;
  1205. zend_bool close_fp = 1;
  1206. struct _phar_t *p_obj = (struct _phar_t*) puser;
  1207. size_t str_key_len, base_len = p_obj->l;
  1208. phar_entry_data *data;
  1209. php_stream *fp;
  1210. size_t fname_len;
  1211. size_t contents_len;
  1212. char *fname, *error = NULL, *base = p_obj->b, *save = NULL, *temp = NULL;
  1213. zend_string *opened;
  1214. char *str_key;
  1215. zend_class_entry *ce = p_obj->c;
  1216. phar_archive_object *phar_obj = p_obj->p;
  1217. php_stream_statbuf ssb;
  1218. value = iter->funcs->get_current_data(iter);
  1219. if (EG(exception)) {
  1220. return ZEND_HASH_APPLY_STOP;
  1221. }
  1222. if (!value) {
  1223. /* failure in get_current_data */
  1224. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned no value", ZSTR_VAL(ce->name));
  1225. return ZEND_HASH_APPLY_STOP;
  1226. }
  1227. switch (Z_TYPE_P(value)) {
  1228. case IS_STRING:
  1229. break;
  1230. case IS_RESOURCE:
  1231. php_stream_from_zval_no_verify(fp, value);
  1232. if (!fp) {
  1233. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Iterator %s returned an invalid stream handle", ZSTR_VAL(ce->name));
  1234. return ZEND_HASH_APPLY_STOP;
  1235. }
  1236. if (iter->funcs->get_current_key) {
  1237. zval key;
  1238. iter->funcs->get_current_key(iter, &key);
  1239. if (EG(exception)) {
  1240. return ZEND_HASH_APPLY_STOP;
  1241. }
  1242. if (Z_TYPE(key) != IS_STRING) {
  1243. zval_ptr_dtor(&key);
  1244. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned an invalid key (must return a string)", ZSTR_VAL(ce->name));
  1245. return ZEND_HASH_APPLY_STOP;
  1246. }
  1247. str_key_len = Z_STRLEN(key);
  1248. str_key = estrndup(Z_STRVAL(key), str_key_len);
  1249. save = str_key;
  1250. zval_ptr_dtor_str(&key);
  1251. } else {
  1252. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned an invalid key (must return a string)", ZSTR_VAL(ce->name));
  1253. return ZEND_HASH_APPLY_STOP;
  1254. }
  1255. close_fp = 0;
  1256. opened = zend_string_init("[stream]", sizeof("[stream]") - 1, 0);
  1257. goto after_open_fp;
  1258. case IS_OBJECT:
  1259. if (instanceof_function(Z_OBJCE_P(value), spl_ce_SplFileInfo)) {
  1260. char *test = NULL;
  1261. zval dummy;
  1262. spl_filesystem_object *intern = (spl_filesystem_object*)((char*)Z_OBJ_P(value) - Z_OBJ_P(value)->handlers->offset);
  1263. if (!base_len) {
  1264. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Iterator %s returns an SplFileInfo object, so base directory must be specified", ZSTR_VAL(ce->name));
  1265. return ZEND_HASH_APPLY_STOP;
  1266. }
  1267. switch (intern->type) {
  1268. case SPL_FS_DIR:
  1269. test = spl_filesystem_object_get_path(intern, NULL);
  1270. fname_len = spprintf(&fname, 0, "%s%c%s", test, DEFAULT_SLASH, intern->u.dir.entry.d_name);
  1271. php_stat(fname, fname_len, FS_IS_DIR, &dummy);
  1272. if (Z_TYPE(dummy) == IS_TRUE) {
  1273. /* ignore directories */
  1274. efree(fname);
  1275. return ZEND_HASH_APPLY_KEEP;
  1276. }
  1277. test = expand_filepath(fname, NULL);
  1278. efree(fname);
  1279. if (test) {
  1280. fname = test;
  1281. fname_len = strlen(fname);
  1282. } else {
  1283. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path");
  1284. return ZEND_HASH_APPLY_STOP;
  1285. }
  1286. save = fname;
  1287. goto phar_spl_fileinfo;
  1288. case SPL_FS_INFO:
  1289. case SPL_FS_FILE:
  1290. fname = expand_filepath(intern->file_name, NULL);
  1291. if (!fname) {
  1292. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path");
  1293. return ZEND_HASH_APPLY_STOP;
  1294. }
  1295. fname_len = strlen(fname);
  1296. save = fname;
  1297. goto phar_spl_fileinfo;
  1298. }
  1299. }
  1300. /* fall-through */
  1301. default:
  1302. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned an invalid value (must return a string)", ZSTR_VAL(ce->name));
  1303. return ZEND_HASH_APPLY_STOP;
  1304. }
  1305. fname = Z_STRVAL_P(value);
  1306. fname_len = Z_STRLEN_P(value);
  1307. phar_spl_fileinfo:
  1308. if (base_len) {
  1309. temp = expand_filepath(base, NULL);
  1310. if (!temp) {
  1311. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Could not resolve file path");
  1312. if (save) {
  1313. efree(save);
  1314. }
  1315. return ZEND_HASH_APPLY_STOP;
  1316. }
  1317. base = temp;
  1318. base_len = strlen(base);
  1319. if (strstr(fname, base)) {
  1320. str_key_len = fname_len - base_len;
  1321. if (str_key_len <= 0) {
  1322. if (save) {
  1323. efree(save);
  1324. efree(temp);
  1325. }
  1326. return ZEND_HASH_APPLY_KEEP;
  1327. }
  1328. str_key = fname + base_len;
  1329. if (*str_key == '/' || *str_key == '\\') {
  1330. str_key++;
  1331. str_key_len--;
  1332. }
  1333. } else {
  1334. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned a path \"%s\" that is not in the base directory \"%s\"", ZSTR_VAL(ce->name), fname, base);
  1335. if (save) {
  1336. efree(save);
  1337. efree(temp);
  1338. }
  1339. return ZEND_HASH_APPLY_STOP;
  1340. }
  1341. } else {
  1342. if (iter->funcs->get_current_key) {
  1343. zval key;
  1344. iter->funcs->get_current_key(iter, &key);
  1345. if (EG(exception)) {
  1346. return ZEND_HASH_APPLY_STOP;
  1347. }
  1348. if (Z_TYPE(key) != IS_STRING) {
  1349. zval_ptr_dtor(&key);
  1350. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned an invalid key (must return a string)", ZSTR_VAL(ce->name));
  1351. return ZEND_HASH_APPLY_STOP;
  1352. }
  1353. str_key_len = Z_STRLEN(key);
  1354. str_key = estrndup(Z_STRVAL(key), str_key_len);
  1355. save = str_key;
  1356. zval_ptr_dtor_str(&key);
  1357. } else {
  1358. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned an invalid key (must return a string)", ZSTR_VAL(ce->name));
  1359. return ZEND_HASH_APPLY_STOP;
  1360. }
  1361. }
  1362. if (php_check_open_basedir(fname)) {
  1363. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned a path \"%s\" that open_basedir prevents opening", ZSTR_VAL(ce->name), fname);
  1364. if (save) {
  1365. efree(save);
  1366. }
  1367. if (temp) {
  1368. efree(temp);
  1369. }
  1370. return ZEND_HASH_APPLY_STOP;
  1371. }
  1372. /* try to open source file, then create internal phar file and copy contents */
  1373. fp = php_stream_open_wrapper(fname, "rb", STREAM_MUST_SEEK|0, &opened);
  1374. if (!fp) {
  1375. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %s returned a file that could not be opened \"%s\"", ZSTR_VAL(ce->name), fname);
  1376. if (save) {
  1377. efree(save);
  1378. }
  1379. if (temp) {
  1380. efree(temp);
  1381. }
  1382. return ZEND_HASH_APPLY_STOP;
  1383. }
  1384. after_open_fp:
  1385. if (str_key_len >= sizeof(".phar")-1 && !memcmp(str_key, ".phar", sizeof(".phar")-1)) {
  1386. /* silently skip any files that would be added to the magic .phar directory */
  1387. if (save) {
  1388. efree(save);
  1389. }
  1390. if (temp) {
  1391. efree(temp);
  1392. }
  1393. if (opened) {
  1394. zend_string_release_ex(opened, 0);
  1395. }
  1396. if (close_fp) {
  1397. php_stream_close(fp);
  1398. }
  1399. return ZEND_HASH_APPLY_KEEP;
  1400. }
  1401. if (!(data = phar_get_or_create_entry_data(phar_obj->archive->fname, phar_obj->archive->fname_len, str_key, str_key_len, "w+b", 0, &error, 1))) {
  1402. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s cannot be created: %s", str_key, error);
  1403. efree(error);
  1404. if (save) {
  1405. efree(save);
  1406. }
  1407. if (opened) {
  1408. zend_string_release_ex(opened, 0);
  1409. }
  1410. if (temp) {
  1411. efree(temp);
  1412. }
  1413. if (close_fp) {
  1414. php_stream_close(fp);
  1415. }
  1416. return ZEND_HASH_APPLY_STOP;
  1417. } else {
  1418. if (error) {
  1419. efree(error);
  1420. }
  1421. /* convert to PHAR_UFP */
  1422. if (data->internal_file->fp_type == PHAR_MOD) {
  1423. php_stream_close(data->internal_file->fp);
  1424. }
  1425. data->internal_file->fp = NULL;
  1426. data->internal_file->fp_type = PHAR_UFP;
  1427. data->internal_file->offset_abs = data->internal_file->offset = php_stream_tell(p_obj->fp);
  1428. data->fp = NULL;
  1429. php_stream_copy_to_stream_ex(fp, p_obj->fp, PHP_STREAM_COPY_ALL, &contents_len);
  1430. data->internal_file->uncompressed_filesize = data->internal_file->compressed_filesize =
  1431. php_stream_tell(p_obj->fp) - data->internal_file->offset;
  1432. if (php_stream_stat(fp, &ssb) != -1) {
  1433. data->internal_file->flags = ssb.sb.st_mode & PHAR_ENT_PERM_MASK ;
  1434. } else {
  1435. #ifndef _WIN32
  1436. mode_t mask;
  1437. mask = umask(0);
  1438. umask(mask);
  1439. data->internal_file->flags &= ~mask;
  1440. #endif
  1441. }
  1442. }
  1443. if (close_fp) {
  1444. php_stream_close(fp);
  1445. }
  1446. add_assoc_str(p_obj->ret, str_key, opened);
  1447. if (save) {
  1448. efree(save);
  1449. }
  1450. if (temp) {
  1451. efree(temp);
  1452. }
  1453. data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len;
  1454. phar_entry_delref(data);
  1455. return ZEND_HASH_APPLY_KEEP;
  1456. }
  1457. /* }}} */
  1458. /* {{{ proto array Phar::buildFromDirectory(string base_dir[, string regex])
  1459. * Construct a phar archive from an existing directory, recursively.
  1460. * Optional second parameter is a regular expression for filtering directory contents.
  1461. *
  1462. * Return value is an array mapping phar index to actual files added.
  1463. */
  1464. PHP_METHOD(Phar, buildFromDirectory)
  1465. {
  1466. char *dir, *error, *regex = NULL;
  1467. size_t dir_len, regex_len = 0;
  1468. zend_bool apply_reg = 0;
  1469. zval arg, arg2, iter, iteriter, regexiter;
  1470. struct _phar_t pass;
  1471. PHAR_ARCHIVE_OBJECT();
  1472. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  1473. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1474. "Cannot write to archive - write operations restricted by INI setting");
  1475. RETURN_THROWS();
  1476. }
  1477. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s", &dir, &dir_len, &regex, &regex_len) == FAILURE) {
  1478. RETURN_THROWS();
  1479. }
  1480. if (ZEND_SIZE_T_UINT_OVFL(dir_len)) {
  1481. RETURN_FALSE;
  1482. }
  1483. if (SUCCESS != object_init_ex(&iter, spl_ce_RecursiveDirectoryIterator)) {
  1484. zval_ptr_dtor(&iter);
  1485. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate directory iterator for %s", phar_obj->archive->fname);
  1486. RETURN_THROWS();
  1487. }
  1488. ZVAL_STRINGL(&arg, dir, dir_len);
  1489. ZVAL_LONG(&arg2, SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS);
  1490. zend_call_method_with_2_params(Z_OBJ(iter), spl_ce_RecursiveDirectoryIterator,
  1491. &spl_ce_RecursiveDirectoryIterator->constructor, "__construct", NULL, &arg, &arg2);
  1492. zval_ptr_dtor(&arg);
  1493. if (EG(exception)) {
  1494. zval_ptr_dtor(&iter);
  1495. RETURN_THROWS();
  1496. }
  1497. if (SUCCESS != object_init_ex(&iteriter, spl_ce_RecursiveIteratorIterator)) {
  1498. zval_ptr_dtor(&iter);
  1499. zval_ptr_dtor(&iteriter);
  1500. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate directory iterator for %s", phar_obj->archive->fname);
  1501. RETURN_THROWS();
  1502. }
  1503. zend_call_method_with_1_params(Z_OBJ(iteriter), spl_ce_RecursiveIteratorIterator,
  1504. &spl_ce_RecursiveIteratorIterator->constructor, "__construct", NULL, &iter);
  1505. if (EG(exception)) {
  1506. zval_ptr_dtor(&iter);
  1507. zval_ptr_dtor(&iteriter);
  1508. RETURN_THROWS();
  1509. }
  1510. zval_ptr_dtor(&iter);
  1511. if (regex_len > 0) {
  1512. apply_reg = 1;
  1513. if (SUCCESS != object_init_ex(&regexiter, spl_ce_RegexIterator)) {
  1514. zval_ptr_dtor(&iteriter);
  1515. zval_ptr_dtor(&regexiter);
  1516. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate regex iterator for %s", phar_obj->archive->fname);
  1517. RETURN_THROWS();
  1518. }
  1519. ZVAL_STRINGL(&arg2, regex, regex_len);
  1520. zend_call_method_with_2_params(Z_OBJ(regexiter), spl_ce_RegexIterator,
  1521. &spl_ce_RegexIterator->constructor, "__construct", NULL, &iteriter, &arg2);
  1522. zval_ptr_dtor(&arg2);
  1523. }
  1524. array_init(return_value);
  1525. pass.c = apply_reg ? Z_OBJCE(regexiter) : Z_OBJCE(iteriter);
  1526. pass.p = phar_obj;
  1527. pass.b = dir;
  1528. pass.l = (uint32_t)dir_len;
  1529. pass.count = 0;
  1530. pass.ret = return_value;
  1531. pass.fp = php_stream_fopen_tmpfile();
  1532. if (pass.fp == NULL) {
  1533. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" unable to create temporary file", phar_obj->archive->fname);
  1534. RETURN_THROWS();
  1535. }
  1536. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  1537. zval_ptr_dtor(&iteriter);
  1538. if (apply_reg) {
  1539. zval_ptr_dtor(&regexiter);
  1540. }
  1541. php_stream_close(pass.fp);
  1542. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  1543. RETURN_THROWS();
  1544. }
  1545. if (SUCCESS == spl_iterator_apply((apply_reg ? &regexiter : &iteriter), (spl_iterator_apply_func_t) phar_build, (void *) &pass)) {
  1546. zval_ptr_dtor(&iteriter);
  1547. if (apply_reg) {
  1548. zval_ptr_dtor(&regexiter);
  1549. }
  1550. phar_obj->archive->ufp = pass.fp;
  1551. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  1552. if (error) {
  1553. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  1554. efree(error);
  1555. }
  1556. } else {
  1557. zval_ptr_dtor(&iteriter);
  1558. if (apply_reg) {
  1559. zval_ptr_dtor(&regexiter);
  1560. }
  1561. php_stream_close(pass.fp);
  1562. }
  1563. }
  1564. /* }}} */
  1565. /* {{{ proto array Phar::buildFromIterator(Iterator iter[, string base_directory])
  1566. * Construct a phar archive from an iterator. The iterator must return a series of strings
  1567. * that are full paths to files that should be added to the phar. The iterator key should
  1568. * be the path that the file will have within the phar archive.
  1569. *
  1570. * If base directory is specified, then the key will be ignored, and instead the portion of
  1571. * the current value minus the base directory will be used
  1572. *
  1573. * Returned is an array mapping phar index to actual file added
  1574. */
  1575. PHP_METHOD(Phar, buildFromIterator)
  1576. {
  1577. zval *obj;
  1578. char *error;
  1579. size_t base_len = 0;
  1580. char *base = NULL;
  1581. struct _phar_t pass;
  1582. PHAR_ARCHIVE_OBJECT();
  1583. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  1584. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1585. "Cannot write out phar archive, phar is read-only");
  1586. RETURN_THROWS();
  1587. }
  1588. if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|s", &obj, zend_ce_traversable, &base, &base_len) == FAILURE) {
  1589. RETURN_THROWS();
  1590. }
  1591. if (ZEND_SIZE_T_UINT_OVFL(base_len)) {
  1592. RETURN_FALSE;
  1593. }
  1594. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  1595. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  1596. RETURN_THROWS();
  1597. }
  1598. array_init(return_value);
  1599. pass.c = Z_OBJCE_P(obj);
  1600. pass.p = phar_obj;
  1601. pass.b = base;
  1602. pass.l = (uint32_t)base_len;
  1603. pass.ret = return_value;
  1604. pass.count = 0;
  1605. pass.fp = php_stream_fopen_tmpfile();
  1606. if (pass.fp == NULL) {
  1607. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\": unable to create temporary file", phar_obj->archive->fname);
  1608. RETURN_THROWS();
  1609. }
  1610. if (SUCCESS == spl_iterator_apply(obj, (spl_iterator_apply_func_t) phar_build, (void *) &pass)) {
  1611. phar_obj->archive->ufp = pass.fp;
  1612. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  1613. if (error) {
  1614. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  1615. efree(error);
  1616. }
  1617. } else {
  1618. php_stream_close(pass.fp);
  1619. }
  1620. }
  1621. /* }}} */
  1622. /* {{{ proto int Phar::count()
  1623. * Returns the number of entries in the Phar archive
  1624. */
  1625. PHP_METHOD(Phar, count)
  1626. {
  1627. /* mode can be ignored, maximum depth is 1 */
  1628. zend_long mode;
  1629. PHAR_ARCHIVE_OBJECT();
  1630. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &mode) == FAILURE) {
  1631. RETURN_THROWS();
  1632. }
  1633. RETURN_LONG(zend_hash_num_elements(&phar_obj->archive->manifest));
  1634. }
  1635. /* }}} */
  1636. /* {{{ proto bool Phar::isFileFormat(int format)
  1637. * Returns true if the phar archive is based on the tar/zip/phar file format depending
  1638. * on whether Phar::TAR, Phar::ZIP or Phar::PHAR was passed in
  1639. */
  1640. PHP_METHOD(Phar, isFileFormat)
  1641. {
  1642. zend_long type;
  1643. PHAR_ARCHIVE_OBJECT();
  1644. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &type) == FAILURE) {
  1645. RETURN_THROWS();
  1646. }
  1647. switch (type) {
  1648. case PHAR_FORMAT_TAR:
  1649. RETURN_BOOL(phar_obj->archive->is_tar);
  1650. case PHAR_FORMAT_ZIP:
  1651. RETURN_BOOL(phar_obj->archive->is_zip);
  1652. case PHAR_FORMAT_PHAR:
  1653. RETURN_BOOL(!phar_obj->archive->is_tar && !phar_obj->archive->is_zip);
  1654. default:
  1655. zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown file format specified");
  1656. }
  1657. }
  1658. /* }}} */
  1659. static int phar_copy_file_contents(phar_entry_info *entry, php_stream *fp) /* {{{ */
  1660. {
  1661. char *error;
  1662. zend_off_t offset;
  1663. phar_entry_info *link;
  1664. if (FAILURE == phar_open_entry_fp(entry, &error, 1)) {
  1665. if (error) {
  1666. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1667. "Cannot convert phar archive \"%s\", unable to open entry \"%s\" contents: %s", entry->phar->fname, entry->filename, error);
  1668. efree(error);
  1669. } else {
  1670. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1671. "Cannot convert phar archive \"%s\", unable to open entry \"%s\" contents", entry->phar->fname, entry->filename);
  1672. }
  1673. return FAILURE;
  1674. }
  1675. /* copy old contents in entirety */
  1676. phar_seek_efp(entry, 0, SEEK_SET, 0, 1);
  1677. offset = php_stream_tell(fp);
  1678. link = phar_get_link_source(entry);
  1679. if (!link) {
  1680. link = entry;
  1681. }
  1682. if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(link, 0), fp, link->uncompressed_filesize, NULL)) {
  1683. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  1684. "Cannot convert phar archive \"%s\", unable to copy entry \"%s\" contents", entry->phar->fname, entry->filename);
  1685. return FAILURE;
  1686. }
  1687. if (entry->fp_type == PHAR_MOD) {
  1688. /* save for potential restore on error */
  1689. entry->cfp = entry->fp;
  1690. entry->fp = NULL;
  1691. }
  1692. /* set new location of file contents */
  1693. entry->fp_type = PHAR_FP;
  1694. entry->offset = offset;
  1695. return SUCCESS;
  1696. }
  1697. /* }}} */
  1698. static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext) /* {{{ */
  1699. {
  1700. const char *oldname = NULL;
  1701. phar_archive_data *phar = *sphar;
  1702. char *oldpath = NULL;
  1703. char *basename = NULL, *basepath = NULL;
  1704. char *newname = NULL, *newpath = NULL;
  1705. zval ret, arg1;
  1706. zend_class_entry *ce;
  1707. char *error = NULL;
  1708. const char *pcr_error;
  1709. size_t ext_len = ext ? strlen(ext) : 0;
  1710. size_t new_len, oldname_len, phar_ext_len;
  1711. phar_archive_data *pphar = NULL;
  1712. php_stream_statbuf ssb;
  1713. int phar_ext_list_len, i = 0;
  1714. char *ext_pos = NULL;
  1715. /* Array of PHAR extensions, Must be in order, starting with longest
  1716. * ending with the shortest. */
  1717. char *phar_ext_list[] = {
  1718. ".phar.tar.bz2",
  1719. ".phar.tar.gz",
  1720. ".phar.php",
  1721. ".phar.bz2",
  1722. ".phar.zip",
  1723. ".phar.tar",
  1724. ".phar.gz",
  1725. ".tar.bz2",
  1726. ".tar.gz",
  1727. ".phar",
  1728. ".tar",
  1729. ".zip"
  1730. };
  1731. if (!ext) {
  1732. if (phar->is_zip) {
  1733. if (phar->is_data) {
  1734. ext = "zip";
  1735. } else {
  1736. ext = "phar.zip";
  1737. }
  1738. } else if (phar->is_tar) {
  1739. switch (phar->flags) {
  1740. case PHAR_FILE_COMPRESSED_GZ:
  1741. if (phar->is_data) {
  1742. ext = "tar.gz";
  1743. } else {
  1744. ext = "phar.tar.gz";
  1745. }
  1746. break;
  1747. case PHAR_FILE_COMPRESSED_BZ2:
  1748. if (phar->is_data) {
  1749. ext = "tar.bz2";
  1750. } else {
  1751. ext = "phar.tar.bz2";
  1752. }
  1753. break;
  1754. default:
  1755. if (phar->is_data) {
  1756. ext = "tar";
  1757. } else {
  1758. ext = "phar.tar";
  1759. }
  1760. }
  1761. } else {
  1762. switch (phar->flags) {
  1763. case PHAR_FILE_COMPRESSED_GZ:
  1764. ext = "phar.gz";
  1765. break;
  1766. case PHAR_FILE_COMPRESSED_BZ2:
  1767. ext = "phar.bz2";
  1768. break;
  1769. default:
  1770. ext = "phar";
  1771. }
  1772. }
  1773. } else if (phar_path_check(&ext, &ext_len, &pcr_error) > pcr_is_ok) {
  1774. if (phar->is_data) {
  1775. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "data phar converted from \"%s\" has invalid extension %s", phar->fname, ext);
  1776. } else {
  1777. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar converted from \"%s\" has invalid extension %s", phar->fname, ext);
  1778. }
  1779. return NULL;
  1780. }
  1781. oldpath = estrndup(phar->fname, phar->fname_len);
  1782. if ((oldname = zend_memrchr(phar->fname, '/', phar->fname_len))) {
  1783. ++oldname;
  1784. } else {
  1785. oldname = phar->fname;
  1786. }
  1787. oldname_len = strlen(oldname);
  1788. /* Copy the old name to create base for the new name */
  1789. basename = estrndup(oldname, oldname_len);
  1790. phar_ext_list_len = sizeof(phar_ext_list)/sizeof(phar_ext_list[0]);
  1791. /* Remove possible PHAR extensions */
  1792. /* phar_ext_list must be in order of longest extension to shortest */
  1793. for (i=0; i < phar_ext_list_len; i++) {
  1794. phar_ext_len = strlen(phar_ext_list[i]);
  1795. if (phar_ext_len && oldname_len > phar_ext_len) {
  1796. /* Check if the basename strings ends with the extension */
  1797. if (memcmp(phar_ext_list[i], basename + (oldname_len - phar_ext_len), phar_ext_len) == 0) {
  1798. ext_pos = basename + (oldname_len - phar_ext_len);
  1799. ext_pos[0] = '\0';
  1800. break;
  1801. }
  1802. }
  1803. ext_pos = NULL;
  1804. }
  1805. /* If no default PHAR extension found remove the last extension */
  1806. if (!ext_pos) {
  1807. ext_pos = strrchr(basename, '.');
  1808. if (ext_pos) {
  1809. ext_pos[0] = '\0';
  1810. }
  1811. }
  1812. ext_pos = NULL;
  1813. if (ext[0] == '.') {
  1814. ++ext;
  1815. }
  1816. /* Append extension to the basename */
  1817. spprintf(&newname, 0, "%s.%s", basename, ext);
  1818. efree(basename);
  1819. basepath = estrndup(oldpath, (strlen(oldpath) - oldname_len));
  1820. new_len = spprintf(&newpath, 0, "%s%s", basepath, newname);
  1821. phar->fname_len = new_len;
  1822. phar->fname = newpath;
  1823. phar->ext = newpath + phar->fname_len - strlen(ext) - 1;
  1824. efree(basepath);
  1825. efree(newname);
  1826. if (PHAR_G(manifest_cached) && NULL != (pphar = zend_hash_str_find_ptr(&cached_phars, newpath, phar->fname_len))) {
  1827. efree(oldpath);
  1828. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to add newly converted phar \"%s\" to the list of phars, new phar name is in phar.cache_list", phar->fname);
  1829. return NULL;
  1830. }
  1831. if (NULL != (pphar = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), newpath, phar->fname_len))) {
  1832. if (pphar->fname_len == phar->fname_len && !memcmp(pphar->fname, phar->fname, phar->fname_len)) {
  1833. if (!zend_hash_num_elements(&phar->manifest)) {
  1834. pphar->is_tar = phar->is_tar;
  1835. pphar->is_zip = phar->is_zip;
  1836. pphar->is_data = phar->is_data;
  1837. pphar->flags = phar->flags;
  1838. pphar->fp = phar->fp;
  1839. phar->fp = NULL;
  1840. phar_destroy_phar_data(phar);
  1841. *sphar = NULL;
  1842. phar = pphar;
  1843. phar->refcount++;
  1844. newpath = oldpath;
  1845. goto its_ok;
  1846. }
  1847. }
  1848. efree(oldpath);
  1849. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to add newly converted phar \"%s\" to the list of phars, a phar with that name already exists", phar->fname);
  1850. return NULL;
  1851. }
  1852. its_ok:
  1853. if (SUCCESS == php_stream_stat_path(newpath, &ssb)) {
  1854. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar \"%s\" exists and must be unlinked prior to conversion", newpath);
  1855. efree(oldpath);
  1856. return NULL;
  1857. }
  1858. if (!phar->is_data) {
  1859. if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &ext_len, 1, 1, 1)) {
  1860. efree(oldpath);
  1861. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "phar \"%s\" has invalid extension %s", phar->fname, ext);
  1862. return NULL;
  1863. }
  1864. phar->ext_len = ext_len;
  1865. if (phar->alias) {
  1866. if (phar->is_temporary_alias) {
  1867. phar->alias = NULL;
  1868. phar->alias_len = 0;
  1869. } else {
  1870. phar->alias = estrndup(newpath, strlen(newpath));
  1871. phar->alias_len = strlen(newpath);
  1872. phar->is_temporary_alias = 1;
  1873. zend_hash_str_update_ptr(&(PHAR_G(phar_alias_map)), newpath, phar->fname_len, phar);
  1874. }
  1875. }
  1876. } else {
  1877. if (SUCCESS != phar_detect_phar_fname_ext(newpath, phar->fname_len, (const char **) &(phar->ext), &ext_len, 0, 1, 1)) {
  1878. efree(oldpath);
  1879. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "data phar \"%s\" has invalid extension %s", phar->fname, ext);
  1880. return NULL;
  1881. }
  1882. phar->ext_len = ext_len;
  1883. phar->alias = NULL;
  1884. phar->alias_len = 0;
  1885. }
  1886. if ((!pphar || phar == pphar) && NULL == zend_hash_str_update_ptr(&(PHAR_G(phar_fname_map)), newpath, phar->fname_len, phar)) {
  1887. efree(oldpath);
  1888. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to add newly converted phar \"%s\" to the list of phars", phar->fname);
  1889. return NULL;
  1890. }
  1891. phar_flush(phar, 0, 0, 1, &error);
  1892. if (error) {
  1893. zend_hash_str_del(&(PHAR_G(phar_fname_map)), newpath, phar->fname_len);
  1894. *sphar = NULL;
  1895. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s", error);
  1896. efree(error);
  1897. efree(oldpath);
  1898. return NULL;
  1899. }
  1900. efree(oldpath);
  1901. if (phar->is_data) {
  1902. ce = phar_ce_data;
  1903. } else {
  1904. ce = phar_ce_archive;
  1905. }
  1906. ZVAL_NULL(&ret);
  1907. if (SUCCESS != object_init_ex(&ret, ce)) {
  1908. zval_ptr_dtor(&ret);
  1909. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate phar object when converting archive \"%s\"", phar->fname);
  1910. return NULL;
  1911. }
  1912. ZVAL_STRINGL(&arg1, phar->fname, phar->fname_len);
  1913. zend_call_method_with_1_params(Z_OBJ(ret), ce, &ce->constructor, "__construct", NULL, &arg1);
  1914. zval_ptr_dtor(&arg1);
  1915. return Z_OBJ(ret);
  1916. }
  1917. /* }}} */
  1918. static zend_object *phar_convert_to_other(phar_archive_data *source, int convert, char *ext, uint32_t flags) /* {{{ */
  1919. {
  1920. phar_archive_data *phar;
  1921. phar_entry_info *entry, newentry;
  1922. zend_object *ret;
  1923. /* invalidate phar cache */
  1924. PHAR_G(last_phar) = NULL;
  1925. PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
  1926. phar = (phar_archive_data *) ecalloc(1, sizeof(phar_archive_data));
  1927. /* set whole-archive compression and type from parameter */
  1928. phar->flags = flags;
  1929. phar->is_data = source->is_data;
  1930. switch (convert) {
  1931. case PHAR_FORMAT_TAR:
  1932. phar->is_tar = 1;
  1933. break;
  1934. case PHAR_FORMAT_ZIP:
  1935. phar->is_zip = 1;
  1936. break;
  1937. default:
  1938. phar->is_data = 0;
  1939. break;
  1940. }
  1941. zend_hash_init(&(phar->manifest), sizeof(phar_entry_info),
  1942. zend_get_hash_value, destroy_phar_manifest_entry, 0);
  1943. zend_hash_init(&phar->mounted_dirs, sizeof(char *),
  1944. zend_get_hash_value, NULL, 0);
  1945. zend_hash_init(&phar->virtual_dirs, sizeof(char *),
  1946. zend_get_hash_value, NULL, 0);
  1947. phar->fp = php_stream_fopen_tmpfile();
  1948. if (phar->fp == NULL) {
  1949. zend_throw_exception_ex(phar_ce_PharException, 0, "unable to create temporary file");
  1950. return NULL;
  1951. }
  1952. phar->fname = source->fname;
  1953. phar->fname_len = source->fname_len;
  1954. phar->is_temporary_alias = source->is_temporary_alias;
  1955. phar->alias = source->alias;
  1956. if (Z_TYPE(source->metadata) != IS_UNDEF) {
  1957. ZVAL_DUP(&phar->metadata, &source->metadata);
  1958. phar->metadata_len = 0;
  1959. }
  1960. /* first copy each file's uncompressed contents to a temporary file and set per-file flags */
  1961. ZEND_HASH_FOREACH_PTR(&source->manifest, entry) {
  1962. newentry = *entry;
  1963. if (newentry.link) {
  1964. newentry.link = estrdup(newentry.link);
  1965. goto no_copy;
  1966. }
  1967. if (newentry.tmp) {
  1968. newentry.tmp = estrdup(newentry.tmp);
  1969. goto no_copy;
  1970. }
  1971. newentry.metadata_str.s = NULL;
  1972. if (FAILURE == phar_copy_file_contents(&newentry, phar->fp)) {
  1973. zend_hash_destroy(&(phar->manifest));
  1974. php_stream_close(phar->fp);
  1975. efree(phar);
  1976. /* exception already thrown */
  1977. return NULL;
  1978. }
  1979. no_copy:
  1980. newentry.filename = estrndup(newentry.filename, newentry.filename_len);
  1981. if (Z_TYPE(newentry.metadata) != IS_UNDEF) {
  1982. zval_copy_ctor(&newentry.metadata);
  1983. newentry.metadata_str.s = NULL;
  1984. }
  1985. newentry.is_zip = phar->is_zip;
  1986. newentry.is_tar = phar->is_tar;
  1987. if (newentry.is_tar) {
  1988. newentry.tar_type = (entry->is_dir ? TAR_DIR : TAR_FILE);
  1989. }
  1990. newentry.is_modified = 1;
  1991. newentry.phar = phar;
  1992. newentry.old_flags = newentry.flags & ~PHAR_ENT_COMPRESSION_MASK; /* remove compression from old_flags */
  1993. phar_set_inode(&newentry);
  1994. zend_hash_str_add_mem(&(phar->manifest), newentry.filename, newentry.filename_len, (void*)&newentry, sizeof(phar_entry_info));
  1995. phar_add_virtual_dirs(phar, newentry.filename, newentry.filename_len);
  1996. } ZEND_HASH_FOREACH_END();
  1997. if ((ret = phar_rename_archive(&phar, ext))) {
  1998. return ret;
  1999. } else {
  2000. if(phar != NULL) {
  2001. zend_hash_destroy(&(phar->manifest));
  2002. zend_hash_destroy(&(phar->mounted_dirs));
  2003. zend_hash_destroy(&(phar->virtual_dirs));
  2004. if (phar->fp) {
  2005. php_stream_close(phar->fp);
  2006. }
  2007. efree(phar->fname);
  2008. efree(phar);
  2009. }
  2010. return NULL;
  2011. }
  2012. }
  2013. /* }}} */
  2014. /* {{{ proto object Phar::convertToExecutable([int format[, int compression [, string file_ext]]])
  2015. * Convert a phar.tar or phar.zip archive to the phar file format. The
  2016. * optional parameter allows the user to determine the new
  2017. * filename extension (default is phar).
  2018. */
  2019. PHP_METHOD(Phar, convertToExecutable)
  2020. {
  2021. char *ext = NULL;
  2022. int is_data;
  2023. size_t ext_len = 0;
  2024. uint32_t flags;
  2025. zend_object *ret;
  2026. /* a number that is not 0, 1 or 2 (Which is also Greg's birthday, so there) */
  2027. zend_long format = 9021976, method = 9021976;
  2028. PHAR_ARCHIVE_OBJECT();
  2029. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|lls", &format, &method, &ext, &ext_len) == FAILURE) {
  2030. RETURN_THROWS();
  2031. }
  2032. if (PHAR_G(readonly)) {
  2033. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2034. "Cannot write out executable phar archive, phar is read-only");
  2035. RETURN_THROWS();
  2036. }
  2037. switch (format) {
  2038. case 9021976:
  2039. case PHAR_FORMAT_SAME: /* null is converted to 0 */
  2040. /* by default, use the existing format */
  2041. if (phar_obj->archive->is_tar) {
  2042. format = PHAR_FORMAT_TAR;
  2043. } else if (phar_obj->archive->is_zip) {
  2044. format = PHAR_FORMAT_ZIP;
  2045. } else {
  2046. format = PHAR_FORMAT_PHAR;
  2047. }
  2048. break;
  2049. case PHAR_FORMAT_PHAR:
  2050. case PHAR_FORMAT_TAR:
  2051. case PHAR_FORMAT_ZIP:
  2052. break;
  2053. default:
  2054. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2055. "Unknown file format specified, please pass one of Phar::PHAR, Phar::TAR or Phar::ZIP");
  2056. RETURN_THROWS();
  2057. }
  2058. switch (method) {
  2059. case 9021976:
  2060. flags = phar_obj->archive->flags & PHAR_FILE_COMPRESSION_MASK;
  2061. break;
  2062. case 0:
  2063. flags = PHAR_FILE_COMPRESSED_NONE;
  2064. break;
  2065. case PHAR_ENT_COMPRESSED_GZ:
  2066. if (format == PHAR_FORMAT_ZIP) {
  2067. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2068. "Cannot compress entire archive with gzip, zip archives do not support whole-archive compression");
  2069. RETURN_THROWS();
  2070. }
  2071. if (!PHAR_G(has_zlib)) {
  2072. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2073. "Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
  2074. RETURN_THROWS();
  2075. }
  2076. flags = PHAR_FILE_COMPRESSED_GZ;
  2077. break;
  2078. case PHAR_ENT_COMPRESSED_BZ2:
  2079. if (format == PHAR_FORMAT_ZIP) {
  2080. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2081. "Cannot compress entire archive with bz2, zip archives do not support whole-archive compression");
  2082. RETURN_THROWS();
  2083. }
  2084. if (!PHAR_G(has_bz2)) {
  2085. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2086. "Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
  2087. RETURN_THROWS();
  2088. }
  2089. flags = PHAR_FILE_COMPRESSED_BZ2;
  2090. break;
  2091. default:
  2092. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2093. "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
  2094. RETURN_THROWS();
  2095. }
  2096. is_data = phar_obj->archive->is_data;
  2097. phar_obj->archive->is_data = 0;
  2098. ret = phar_convert_to_other(phar_obj->archive, format, ext, flags);
  2099. phar_obj->archive->is_data = is_data;
  2100. if (ret) {
  2101. ZVAL_OBJ(return_value, ret);
  2102. } else {
  2103. RETURN_NULL();
  2104. }
  2105. }
  2106. /* }}} */
  2107. /* {{{ proto object Phar::convertToData([int format[, int compression [, string file_ext]]])
  2108. * Convert an archive to a non-executable .tar or .zip.
  2109. * The optional parameter allows the user to determine the new
  2110. * filename extension (default is .zip or .tar).
  2111. */
  2112. PHP_METHOD(Phar, convertToData)
  2113. {
  2114. char *ext = NULL;
  2115. int is_data;
  2116. size_t ext_len = 0;
  2117. uint32_t flags;
  2118. zend_object *ret;
  2119. /* a number that is not 0, 1 or 2 (Which is also Greg's birthday so there) */
  2120. zend_long format = 9021976, method = 9021976;
  2121. PHAR_ARCHIVE_OBJECT();
  2122. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|lls", &format, &method, &ext, &ext_len) == FAILURE) {
  2123. RETURN_THROWS();
  2124. }
  2125. switch (format) {
  2126. case 9021976:
  2127. case PHAR_FORMAT_SAME: /* null is converted to 0 */
  2128. /* by default, use the existing format */
  2129. if (phar_obj->archive->is_tar) {
  2130. format = PHAR_FORMAT_TAR;
  2131. } else if (phar_obj->archive->is_zip) {
  2132. format = PHAR_FORMAT_ZIP;
  2133. } else {
  2134. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2135. "Cannot write out data phar archive, use Phar::TAR or Phar::ZIP");
  2136. RETURN_THROWS();
  2137. }
  2138. break;
  2139. case PHAR_FORMAT_PHAR:
  2140. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2141. "Cannot write out data phar archive, use Phar::TAR or Phar::ZIP");
  2142. RETURN_THROWS();
  2143. case PHAR_FORMAT_TAR:
  2144. case PHAR_FORMAT_ZIP:
  2145. break;
  2146. default:
  2147. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2148. "Unknown file format specified, please pass one of Phar::TAR or Phar::ZIP");
  2149. RETURN_THROWS();
  2150. }
  2151. switch (method) {
  2152. case 9021976:
  2153. flags = phar_obj->archive->flags & PHAR_FILE_COMPRESSION_MASK;
  2154. break;
  2155. case 0:
  2156. flags = PHAR_FILE_COMPRESSED_NONE;
  2157. break;
  2158. case PHAR_ENT_COMPRESSED_GZ:
  2159. if (format == PHAR_FORMAT_ZIP) {
  2160. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2161. "Cannot compress entire archive with gzip, zip archives do not support whole-archive compression");
  2162. RETURN_THROWS();
  2163. }
  2164. if (!PHAR_G(has_zlib)) {
  2165. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2166. "Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
  2167. RETURN_THROWS();
  2168. }
  2169. flags = PHAR_FILE_COMPRESSED_GZ;
  2170. break;
  2171. case PHAR_ENT_COMPRESSED_BZ2:
  2172. if (format == PHAR_FORMAT_ZIP) {
  2173. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2174. "Cannot compress entire archive with bz2, zip archives do not support whole-archive compression");
  2175. RETURN_THROWS();
  2176. }
  2177. if (!PHAR_G(has_bz2)) {
  2178. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2179. "Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
  2180. RETURN_THROWS();
  2181. }
  2182. flags = PHAR_FILE_COMPRESSED_BZ2;
  2183. break;
  2184. default:
  2185. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2186. "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
  2187. RETURN_THROWS();
  2188. }
  2189. is_data = phar_obj->archive->is_data;
  2190. phar_obj->archive->is_data = 1;
  2191. ret = phar_convert_to_other(phar_obj->archive, (int)format, ext, flags);
  2192. phar_obj->archive->is_data = is_data;
  2193. if (ret) {
  2194. ZVAL_OBJ(return_value, ret);
  2195. } else {
  2196. RETURN_NULL();
  2197. }
  2198. }
  2199. /* }}} */
  2200. /* {{{ proto int|false Phar::isCompressed()
  2201. * Returns Phar::GZ or PHAR::BZ2 if the entire archive is compressed
  2202. * (.tar.gz/tar.bz2 and so on), or FALSE otherwise.
  2203. */
  2204. PHP_METHOD(Phar, isCompressed)
  2205. {
  2206. PHAR_ARCHIVE_OBJECT();
  2207. if (zend_parse_parameters_none() == FAILURE) {
  2208. RETURN_THROWS();
  2209. }
  2210. if (phar_obj->archive->flags & PHAR_FILE_COMPRESSED_GZ) {
  2211. RETURN_LONG(PHAR_ENT_COMPRESSED_GZ);
  2212. }
  2213. if (phar_obj->archive->flags & PHAR_FILE_COMPRESSED_BZ2) {
  2214. RETURN_LONG(PHAR_ENT_COMPRESSED_BZ2);
  2215. }
  2216. RETURN_FALSE;
  2217. }
  2218. /* }}} */
  2219. /* {{{ proto bool Phar::isWritable()
  2220. * Returns true if phar.readonly=0 or phar is a PharData AND the actual file is writable.
  2221. */
  2222. PHP_METHOD(Phar, isWritable)
  2223. {
  2224. php_stream_statbuf ssb;
  2225. PHAR_ARCHIVE_OBJECT();
  2226. if (zend_parse_parameters_none() == FAILURE) {
  2227. RETURN_THROWS();
  2228. }
  2229. if (!phar_obj->archive->is_writeable) {
  2230. RETURN_FALSE;
  2231. }
  2232. if (SUCCESS != php_stream_stat_path(phar_obj->archive->fname, &ssb)) {
  2233. if (phar_obj->archive->is_brandnew) {
  2234. /* assume it works if the file doesn't exist yet */
  2235. RETURN_TRUE;
  2236. }
  2237. RETURN_FALSE;
  2238. }
  2239. RETURN_BOOL((ssb.sb.st_mode & (S_IWOTH | S_IWGRP | S_IWUSR)) != 0);
  2240. }
  2241. /* }}} */
  2242. /* {{{ proto bool Phar::delete(string entry)
  2243. * Deletes a named file within the archive.
  2244. */
  2245. PHP_METHOD(Phar, delete)
  2246. {
  2247. char *fname;
  2248. size_t fname_len;
  2249. char *error;
  2250. phar_entry_info *entry;
  2251. PHAR_ARCHIVE_OBJECT();
  2252. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2253. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2254. "Cannot write out phar archive, phar is read-only");
  2255. RETURN_THROWS();
  2256. }
  2257. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
  2258. RETURN_THROWS();
  2259. }
  2260. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2261. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2262. RETURN_THROWS();
  2263. }
  2264. if (zend_hash_str_exists(&phar_obj->archive->manifest, fname, (uint32_t) fname_len)) {
  2265. if (NULL != (entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint32_t) fname_len))) {
  2266. if (entry->is_deleted) {
  2267. /* entry is deleted, but has not been flushed to disk yet */
  2268. RETURN_TRUE;
  2269. } else {
  2270. entry->is_deleted = 1;
  2271. entry->is_modified = 1;
  2272. phar_obj->archive->is_modified = 1;
  2273. }
  2274. }
  2275. } else {
  2276. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist and cannot be deleted", fname);
  2277. RETURN_THROWS();
  2278. }
  2279. phar_flush(phar_obj->archive, NULL, 0, 0, &error);
  2280. if (error) {
  2281. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2282. efree(error);
  2283. RETURN_THROWS();
  2284. }
  2285. RETURN_TRUE;
  2286. }
  2287. /* }}} */
  2288. /* {{{ proto int Phar::getAlias()
  2289. * Returns the alias for the Phar or NULL.
  2290. */
  2291. PHP_METHOD(Phar, getAlias)
  2292. {
  2293. PHAR_ARCHIVE_OBJECT();
  2294. if (zend_parse_parameters_none() == FAILURE) {
  2295. RETURN_THROWS();
  2296. }
  2297. if (phar_obj->archive->alias && phar_obj->archive->alias != phar_obj->archive->fname) {
  2298. RETURN_STRINGL(phar_obj->archive->alias, phar_obj->archive->alias_len);
  2299. }
  2300. }
  2301. /* }}} */
  2302. /* {{{ proto int Phar::getPath()
  2303. * Returns the real path to the phar archive on disk
  2304. */
  2305. PHP_METHOD(Phar, getPath)
  2306. {
  2307. PHAR_ARCHIVE_OBJECT();
  2308. if (zend_parse_parameters_none() == FAILURE) {
  2309. RETURN_THROWS();
  2310. }
  2311. RETURN_STRINGL(phar_obj->archive->fname, phar_obj->archive->fname_len);
  2312. }
  2313. /* }}} */
  2314. /* {{{ proto bool Phar::setAlias(string alias)
  2315. * Sets the alias for a Phar archive. The default value is the full path
  2316. * to the archive.
  2317. */
  2318. PHP_METHOD(Phar, setAlias)
  2319. {
  2320. char *alias, *error, *oldalias;
  2321. phar_archive_data *fd_ptr;
  2322. size_t alias_len, oldalias_len;
  2323. int old_temp, readd = 0;
  2324. PHAR_ARCHIVE_OBJECT();
  2325. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2326. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2327. "Cannot write out phar archive, phar is read-only");
  2328. RETURN_THROWS();
  2329. }
  2330. /* invalidate phar cache */
  2331. PHAR_G(last_phar) = NULL;
  2332. PHAR_G(last_phar_name) = PHAR_G(last_alias) = NULL;
  2333. if (phar_obj->archive->is_data) {
  2334. if (phar_obj->archive->is_tar) {
  2335. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2336. "A Phar alias cannot be set in a plain tar archive");
  2337. } else {
  2338. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2339. "A Phar alias cannot be set in a plain zip archive");
  2340. }
  2341. RETURN_THROWS();
  2342. }
  2343. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &alias, &alias_len) == SUCCESS) {
  2344. if (alias_len == phar_obj->archive->alias_len && memcmp(phar_obj->archive->alias, alias, alias_len) == 0) {
  2345. RETURN_TRUE;
  2346. }
  2347. if (alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len))) {
  2348. spprintf(&error, 0, "alias \"%s\" is already used for archive \"%s\" and cannot be used for other archives", alias, fd_ptr->fname);
  2349. if (SUCCESS == phar_free_alias(fd_ptr, alias, alias_len)) {
  2350. efree(error);
  2351. goto valid_alias;
  2352. }
  2353. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2354. efree(error);
  2355. RETURN_THROWS();
  2356. }
  2357. if (!phar_validate_alias(alias, alias_len)) {
  2358. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2359. "Invalid alias \"%s\" specified for phar \"%s\"", alias, phar_obj->archive->fname);
  2360. RETURN_THROWS();
  2361. }
  2362. valid_alias:
  2363. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2364. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2365. RETURN_THROWS();
  2366. }
  2367. if (phar_obj->archive->alias_len && NULL != (fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), phar_obj->archive->alias, phar_obj->archive->alias_len))) {
  2368. zend_hash_str_del(&(PHAR_G(phar_alias_map)), phar_obj->archive->alias, phar_obj->archive->alias_len);
  2369. readd = 1;
  2370. }
  2371. oldalias = phar_obj->archive->alias;
  2372. oldalias_len = phar_obj->archive->alias_len;
  2373. old_temp = phar_obj->archive->is_temporary_alias;
  2374. if (alias_len) {
  2375. phar_obj->archive->alias = estrndup(alias, alias_len);
  2376. } else {
  2377. phar_obj->archive->alias = NULL;
  2378. }
  2379. phar_obj->archive->alias_len = alias_len;
  2380. phar_obj->archive->is_temporary_alias = 0;
  2381. phar_flush(phar_obj->archive, NULL, 0, 0, &error);
  2382. if (error) {
  2383. phar_obj->archive->alias = oldalias;
  2384. phar_obj->archive->alias_len = oldalias_len;
  2385. phar_obj->archive->is_temporary_alias = old_temp;
  2386. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2387. if (readd) {
  2388. zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), oldalias, oldalias_len, phar_obj->archive);
  2389. }
  2390. efree(error);
  2391. RETURN_THROWS();
  2392. }
  2393. zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, phar_obj->archive);
  2394. if (oldalias) {
  2395. efree(oldalias);
  2396. }
  2397. RETURN_TRUE;
  2398. }
  2399. RETURN_FALSE;
  2400. }
  2401. /* }}} */
  2402. /* {{{ proto string Phar::getVersion()
  2403. * Return version info of Phar archive
  2404. */
  2405. PHP_METHOD(Phar, getVersion)
  2406. {
  2407. PHAR_ARCHIVE_OBJECT();
  2408. if (zend_parse_parameters_none() == FAILURE) {
  2409. RETURN_THROWS();
  2410. }
  2411. RETURN_STRING(phar_obj->archive->version);
  2412. }
  2413. /* }}} */
  2414. /* {{{ proto void Phar::startBuffering()
  2415. * Do not flush a writeable phar (save its contents) until explicitly requested
  2416. */
  2417. PHP_METHOD(Phar, startBuffering)
  2418. {
  2419. PHAR_ARCHIVE_OBJECT();
  2420. if (zend_parse_parameters_none() == FAILURE) {
  2421. RETURN_THROWS();
  2422. }
  2423. phar_obj->archive->donotflush = 1;
  2424. }
  2425. /* }}} */
  2426. /* {{{ proto bool Phar::isBuffering()
  2427. * Returns whether write operations are flushing to disk immediately.
  2428. */
  2429. PHP_METHOD(Phar, isBuffering)
  2430. {
  2431. PHAR_ARCHIVE_OBJECT();
  2432. if (zend_parse_parameters_none() == FAILURE) {
  2433. RETURN_THROWS();
  2434. }
  2435. RETURN_BOOL(phar_obj->archive->donotflush);
  2436. }
  2437. /* }}} */
  2438. /* {{{ proto bool Phar::stopBuffering()
  2439. * Saves the contents of a modified archive to disk.
  2440. */
  2441. PHP_METHOD(Phar, stopBuffering)
  2442. {
  2443. char *error;
  2444. PHAR_ARCHIVE_OBJECT();
  2445. if (zend_parse_parameters_none() == FAILURE) {
  2446. RETURN_THROWS();
  2447. }
  2448. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2449. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2450. "Cannot write out phar archive, phar is read-only");
  2451. RETURN_THROWS();
  2452. }
  2453. phar_obj->archive->donotflush = 0;
  2454. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  2455. if (error) {
  2456. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2457. efree(error);
  2458. }
  2459. }
  2460. /* }}} */
  2461. /* {{{ proto bool Phar::setStub(string|stream stub [, int len])
  2462. * Change the stub in a phar, phar.tar or phar.zip archive to something other
  2463. * than the default. The stub *must* end with a call to __HALT_COMPILER().
  2464. */
  2465. PHP_METHOD(Phar, setStub)
  2466. {
  2467. zval *zstub;
  2468. char *stub, *error;
  2469. size_t stub_len;
  2470. zend_long len = -1;
  2471. php_stream *stream;
  2472. PHAR_ARCHIVE_OBJECT();
  2473. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2474. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2475. "Cannot change stub, phar is read-only");
  2476. RETURN_THROWS();
  2477. }
  2478. if (phar_obj->archive->is_data) {
  2479. if (phar_obj->archive->is_tar) {
  2480. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2481. "A Phar stub cannot be set in a plain tar archive");
  2482. } else {
  2483. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2484. "A Phar stub cannot be set in a plain zip archive");
  2485. }
  2486. RETURN_THROWS();
  2487. }
  2488. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "r|l", &zstub, &len) == SUCCESS) {
  2489. if ((php_stream_from_zval_no_verify(stream, zstub)) != NULL) {
  2490. if (len > 0) {
  2491. len = -len;
  2492. } else {
  2493. len = -1;
  2494. }
  2495. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2496. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2497. RETURN_THROWS();
  2498. }
  2499. phar_flush(phar_obj->archive, (char *) zstub, len, 0, &error);
  2500. if (error) {
  2501. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2502. efree(error);
  2503. }
  2504. RETURN_TRUE;
  2505. } else {
  2506. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2507. "Cannot change stub, unable to read from input stream");
  2508. }
  2509. } else if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &stub, &stub_len) == SUCCESS) {
  2510. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2511. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2512. RETURN_THROWS();
  2513. }
  2514. phar_flush(phar_obj->archive, stub, stub_len, 0, &error);
  2515. if (error) {
  2516. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2517. efree(error);
  2518. RETURN_THROWS();
  2519. }
  2520. RETURN_TRUE;
  2521. }
  2522. RETURN_FALSE;
  2523. }
  2524. /* }}} */
  2525. /* {{{ proto bool Phar::setDefaultStub([string index[, string webindex]])
  2526. * In a pure phar archive, sets a stub that can be used to run the archive
  2527. * regardless of whether the phar extension is available. The first parameter
  2528. * is the CLI startup filename, which defaults to "index.php". The second
  2529. * parameter is the web startup filename and also defaults to "index.php"
  2530. * (falling back to CLI behaviour).
  2531. * Both parameters are optional.
  2532. * In a phar.zip or phar.tar archive, the default stub is used only to
  2533. * identify the archive to the extension as a Phar object. This allows the
  2534. * extension to treat phar.zip and phar.tar types as honorary phars. Since
  2535. * files cannot be loaded via this kind of stub, no parameters are accepted
  2536. * when the Phar object is zip- or tar-based.
  2537. */
  2538. PHP_METHOD(Phar, setDefaultStub)
  2539. {
  2540. char *index = NULL, *webindex = NULL, *error = NULL;
  2541. zend_string *stub = NULL;
  2542. size_t index_len = 0, webindex_len = 0;
  2543. int created_stub = 0;
  2544. PHAR_ARCHIVE_OBJECT();
  2545. if (phar_obj->archive->is_data) {
  2546. if (phar_obj->archive->is_tar) {
  2547. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2548. "A Phar stub cannot be set in a plain tar archive");
  2549. } else {
  2550. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2551. "A Phar stub cannot be set in a plain zip archive");
  2552. }
  2553. RETURN_THROWS();
  2554. }
  2555. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!s", &index, &index_len, &webindex, &webindex_len) == FAILURE) {
  2556. RETURN_THROWS();
  2557. }
  2558. if (ZEND_NUM_ARGS() > 0 && (phar_obj->archive->is_tar || phar_obj->archive->is_zip)) {
  2559. php_error_docref(NULL, E_WARNING, "Method accepts no arguments for a tar- or zip-based phar stub, %d given", ZEND_NUM_ARGS());
  2560. RETURN_FALSE;
  2561. }
  2562. if (PHAR_G(readonly)) {
  2563. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2564. "Cannot change stub: phar.readonly=1");
  2565. RETURN_THROWS();
  2566. }
  2567. if (!phar_obj->archive->is_tar && !phar_obj->archive->is_zip) {
  2568. stub = phar_create_default_stub(index, webindex, &error);
  2569. if (error) {
  2570. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "%s", error);
  2571. efree(error);
  2572. if (stub) {
  2573. zend_string_free(stub);
  2574. }
  2575. RETURN_THROWS();
  2576. }
  2577. created_stub = 1;
  2578. }
  2579. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2580. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2581. RETURN_THROWS();
  2582. }
  2583. phar_flush(phar_obj->archive, stub ? ZSTR_VAL(stub) : 0, stub ? ZSTR_LEN(stub) : 0, 1, &error);
  2584. if (created_stub) {
  2585. zend_string_free(stub);
  2586. }
  2587. if (error) {
  2588. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2589. efree(error);
  2590. RETURN_THROWS();
  2591. }
  2592. RETURN_TRUE;
  2593. }
  2594. /* }}} */
  2595. /* {{{ proto array Phar::setSignatureAlgorithm(int sigtype[, string privatekey])
  2596. * Sets the signature algorithm for a phar and applies it. The signature
  2597. * algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256,
  2598. * Phar::SHA512, or Phar::OPENSSL. Note that zip- based phar archives
  2599. * cannot support signatures.
  2600. */
  2601. PHP_METHOD(Phar, setSignatureAlgorithm)
  2602. {
  2603. zend_long algo;
  2604. char *error, *key = NULL;
  2605. size_t key_len = 0;
  2606. PHAR_ARCHIVE_OBJECT();
  2607. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2608. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2609. "Cannot set signature algorithm, phar is read-only");
  2610. RETURN_THROWS();
  2611. }
  2612. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "l|s", &algo, &key, &key_len) != SUCCESS) {
  2613. return;
  2614. }
  2615. switch (algo) {
  2616. case PHAR_SIG_SHA256:
  2617. case PHAR_SIG_SHA512:
  2618. case PHAR_SIG_MD5:
  2619. case PHAR_SIG_SHA1:
  2620. case PHAR_SIG_OPENSSL:
  2621. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2622. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2623. RETURN_THROWS();
  2624. }
  2625. phar_obj->archive->sig_flags = (php_uint32)algo;
  2626. phar_obj->archive->is_modified = 1;
  2627. PHAR_G(openssl_privatekey) = key;
  2628. PHAR_G(openssl_privatekey_len) = key_len;
  2629. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  2630. if (error) {
  2631. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  2632. efree(error);
  2633. }
  2634. break;
  2635. default:
  2636. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2637. "Unknown signature algorithm specified");
  2638. }
  2639. }
  2640. /* }}} */
  2641. /* {{{ proto array|false Phar::getSignature()
  2642. * Returns a hash signature, or FALSE if the archive is unsigned.
  2643. */
  2644. PHP_METHOD(Phar, getSignature)
  2645. {
  2646. PHAR_ARCHIVE_OBJECT();
  2647. if (zend_parse_parameters_none() == FAILURE) {
  2648. RETURN_THROWS();
  2649. }
  2650. if (phar_obj->archive->signature) {
  2651. zend_string *unknown;
  2652. array_init(return_value);
  2653. add_assoc_stringl(return_value, "hash", phar_obj->archive->signature, phar_obj->archive->sig_len);
  2654. switch(phar_obj->archive->sig_flags) {
  2655. case PHAR_SIG_MD5:
  2656. add_assoc_stringl(return_value, "hash_type", "MD5", 3);
  2657. break;
  2658. case PHAR_SIG_SHA1:
  2659. add_assoc_stringl(return_value, "hash_type", "SHA-1", 5);
  2660. break;
  2661. case PHAR_SIG_SHA256:
  2662. add_assoc_stringl(return_value, "hash_type", "SHA-256", 7);
  2663. break;
  2664. case PHAR_SIG_SHA512:
  2665. add_assoc_stringl(return_value, "hash_type", "SHA-512", 7);
  2666. break;
  2667. case PHAR_SIG_OPENSSL:
  2668. add_assoc_stringl(return_value, "hash_type", "OpenSSL", 7);
  2669. break;
  2670. default:
  2671. unknown = strpprintf(0, "Unknown (%u)", phar_obj->archive->sig_flags);
  2672. add_assoc_str(return_value, "hash_type", unknown);
  2673. break;
  2674. }
  2675. } else {
  2676. RETURN_FALSE;
  2677. }
  2678. }
  2679. /* }}} */
  2680. /* {{{ proto bool Phar::getModified()
  2681. * Return whether phar was modified
  2682. */
  2683. PHP_METHOD(Phar, getModified)
  2684. {
  2685. PHAR_ARCHIVE_OBJECT();
  2686. if (zend_parse_parameters_none() == FAILURE) {
  2687. RETURN_THROWS();
  2688. }
  2689. RETURN_BOOL(phar_obj->archive->is_modified);
  2690. }
  2691. /* }}} */
  2692. static int phar_set_compression(zval *zv, void *argument) /* {{{ */
  2693. {
  2694. phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv);
  2695. uint32_t compress = *(uint32_t *)argument;
  2696. if (entry->is_deleted) {
  2697. return ZEND_HASH_APPLY_KEEP;
  2698. }
  2699. entry->old_flags = entry->flags;
  2700. entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
  2701. entry->flags |= compress;
  2702. entry->is_modified = 1;
  2703. return ZEND_HASH_APPLY_KEEP;
  2704. }
  2705. /* }}} */
  2706. static int phar_test_compression(zval *zv, void *argument) /* {{{ */
  2707. {
  2708. phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv);
  2709. if (entry->is_deleted) {
  2710. return ZEND_HASH_APPLY_KEEP;
  2711. }
  2712. if (!PHAR_G(has_bz2)) {
  2713. if (entry->flags & PHAR_ENT_COMPRESSED_BZ2) {
  2714. *(int *) argument = 0;
  2715. }
  2716. }
  2717. if (!PHAR_G(has_zlib)) {
  2718. if (entry->flags & PHAR_ENT_COMPRESSED_GZ) {
  2719. *(int *) argument = 0;
  2720. }
  2721. }
  2722. return ZEND_HASH_APPLY_KEEP;
  2723. }
  2724. /* }}} */
  2725. static void pharobj_set_compression(HashTable *manifest, uint32_t compress) /* {{{ */
  2726. {
  2727. zend_hash_apply_with_argument(manifest, phar_set_compression, &compress);
  2728. }
  2729. /* }}} */
  2730. static int pharobj_cancompress(HashTable *manifest) /* {{{ */
  2731. {
  2732. int test;
  2733. test = 1;
  2734. zend_hash_apply_with_argument(manifest, phar_test_compression, &test);
  2735. return test;
  2736. }
  2737. /* }}} */
  2738. /* {{{ proto object Phar::compress(int method[, string extension])
  2739. * Compress a .tar, or .phar.tar with whole-file compression
  2740. * The parameter can be one of Phar::GZ or Phar::BZ2 to specify
  2741. * the kind of compression desired
  2742. */
  2743. PHP_METHOD(Phar, compress)
  2744. {
  2745. zend_long method;
  2746. char *ext = NULL;
  2747. size_t ext_len = 0;
  2748. uint32_t flags;
  2749. zend_object *ret;
  2750. PHAR_ARCHIVE_OBJECT();
  2751. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|s", &method, &ext, &ext_len) == FAILURE) {
  2752. RETURN_THROWS();
  2753. }
  2754. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2755. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2756. "Cannot compress phar archive, phar is read-only");
  2757. RETURN_THROWS();
  2758. }
  2759. if (phar_obj->archive->is_zip) {
  2760. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2761. "Cannot compress zip-based archives with whole-archive compression");
  2762. RETURN_THROWS();
  2763. }
  2764. switch (method) {
  2765. case 0:
  2766. flags = PHAR_FILE_COMPRESSED_NONE;
  2767. break;
  2768. case PHAR_ENT_COMPRESSED_GZ:
  2769. if (!PHAR_G(has_zlib)) {
  2770. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2771. "Cannot compress entire archive with gzip, enable ext/zlib in php.ini");
  2772. RETURN_THROWS();
  2773. }
  2774. flags = PHAR_FILE_COMPRESSED_GZ;
  2775. break;
  2776. case PHAR_ENT_COMPRESSED_BZ2:
  2777. if (!PHAR_G(has_bz2)) {
  2778. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2779. "Cannot compress entire archive with bz2, enable ext/bz2 in php.ini");
  2780. return;
  2781. }
  2782. flags = PHAR_FILE_COMPRESSED_BZ2;
  2783. break;
  2784. default:
  2785. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2786. "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
  2787. RETURN_THROWS();
  2788. }
  2789. if (phar_obj->archive->is_tar) {
  2790. ret = phar_convert_to_other(phar_obj->archive, PHAR_FORMAT_TAR, ext, flags);
  2791. } else {
  2792. ret = phar_convert_to_other(phar_obj->archive, PHAR_FORMAT_PHAR, ext, flags);
  2793. }
  2794. if (ret) {
  2795. ZVAL_OBJ(return_value, ret);
  2796. } else {
  2797. RETURN_NULL();
  2798. }
  2799. }
  2800. /* }}} */
  2801. /* {{{ proto object Phar::decompress([string extension])
  2802. * Decompress a .tar, or .phar.tar with whole-file compression
  2803. */
  2804. PHP_METHOD(Phar, decompress)
  2805. {
  2806. char *ext = NULL;
  2807. size_t ext_len = 0;
  2808. zend_object *ret;
  2809. PHAR_ARCHIVE_OBJECT();
  2810. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &ext, &ext_len) == FAILURE) {
  2811. RETURN_THROWS();
  2812. }
  2813. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2814. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2815. "Cannot decompress phar archive, phar is read-only");
  2816. RETURN_THROWS();
  2817. }
  2818. if (phar_obj->archive->is_zip) {
  2819. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2820. "Cannot decompress zip-based archives with whole-archive compression");
  2821. RETURN_THROWS();
  2822. }
  2823. if (phar_obj->archive->is_tar) {
  2824. ret = phar_convert_to_other(phar_obj->archive, PHAR_FORMAT_TAR, ext, PHAR_FILE_COMPRESSED_NONE);
  2825. } else {
  2826. ret = phar_convert_to_other(phar_obj->archive, PHAR_FORMAT_PHAR, ext, PHAR_FILE_COMPRESSED_NONE);
  2827. }
  2828. if (ret) {
  2829. ZVAL_OBJ(return_value, ret);
  2830. } else {
  2831. RETURN_NULL();
  2832. }
  2833. }
  2834. /* }}} */
  2835. /* {{{ proto object Phar::compressFiles(int method)
  2836. * Compress all files within a phar or zip archive using the specified compression
  2837. * The parameter can be one of Phar::GZ or Phar::BZ2 to specify
  2838. * the kind of compression desired
  2839. */
  2840. PHP_METHOD(Phar, compressFiles)
  2841. {
  2842. char *error;
  2843. uint32_t flags;
  2844. zend_long method;
  2845. PHAR_ARCHIVE_OBJECT();
  2846. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &method) == FAILURE) {
  2847. RETURN_THROWS();
  2848. }
  2849. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2850. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2851. "Phar is readonly, cannot change compression");
  2852. RETURN_THROWS();
  2853. }
  2854. switch (method) {
  2855. case PHAR_ENT_COMPRESSED_GZ:
  2856. if (!PHAR_G(has_zlib)) {
  2857. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2858. "Cannot compress files within archive with gzip, enable ext/zlib in php.ini");
  2859. RETURN_THROWS();
  2860. }
  2861. flags = PHAR_ENT_COMPRESSED_GZ;
  2862. break;
  2863. case PHAR_ENT_COMPRESSED_BZ2:
  2864. if (!PHAR_G(has_bz2)) {
  2865. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2866. "Cannot compress files within archive with bz2, enable ext/bz2 in php.ini");
  2867. RETURN_THROWS();
  2868. }
  2869. flags = PHAR_ENT_COMPRESSED_BZ2;
  2870. break;
  2871. default:
  2872. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2873. "Unknown compression specified, please pass one of Phar::GZ or Phar::BZ2");
  2874. RETURN_THROWS();
  2875. }
  2876. if (phar_obj->archive->is_tar) {
  2877. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2878. "Cannot compress with Gzip compression, tar archives cannot compress individual files, use compress() to compress the whole archive");
  2879. RETURN_THROWS();
  2880. }
  2881. if (!pharobj_cancompress(&phar_obj->archive->manifest)) {
  2882. if (flags == PHAR_FILE_COMPRESSED_GZ) {
  2883. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2884. "Cannot compress all files as Gzip, some are compressed as bzip2 and cannot be decompressed");
  2885. } else {
  2886. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2887. "Cannot compress all files as Bzip2, some are compressed as gzip and cannot be decompressed");
  2888. }
  2889. RETURN_THROWS();
  2890. }
  2891. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2892. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2893. RETURN_THROWS();
  2894. }
  2895. pharobj_set_compression(&phar_obj->archive->manifest, flags);
  2896. phar_obj->archive->is_modified = 1;
  2897. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  2898. if (error) {
  2899. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s", error);
  2900. efree(error);
  2901. }
  2902. }
  2903. /* }}} */
  2904. /* {{{ proto bool Phar::decompressFiles()
  2905. * decompress every file
  2906. */
  2907. PHP_METHOD(Phar, decompressFiles)
  2908. {
  2909. char *error;
  2910. PHAR_ARCHIVE_OBJECT();
  2911. if (zend_parse_parameters_none() == FAILURE) {
  2912. RETURN_THROWS();
  2913. }
  2914. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2915. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2916. "Phar is readonly, cannot change compression");
  2917. RETURN_THROWS();
  2918. }
  2919. if (!pharobj_cancompress(&phar_obj->archive->manifest)) {
  2920. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  2921. "Cannot decompress all files, some are compressed as bzip2 or gzip and cannot be decompressed");
  2922. RETURN_THROWS();
  2923. }
  2924. if (phar_obj->archive->is_tar) {
  2925. RETURN_TRUE;
  2926. } else {
  2927. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2928. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2929. RETURN_THROWS();
  2930. }
  2931. pharobj_set_compression(&phar_obj->archive->manifest, PHAR_ENT_COMPRESSED_NONE);
  2932. }
  2933. phar_obj->archive->is_modified = 1;
  2934. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  2935. if (error) {
  2936. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s", error);
  2937. efree(error);
  2938. }
  2939. RETURN_TRUE;
  2940. }
  2941. /* }}} */
  2942. /* {{{ proto bool Phar::copy(string oldfile, string newfile)
  2943. * copy a file internal to the phar archive to another new file within the phar
  2944. */
  2945. PHP_METHOD(Phar, copy)
  2946. {
  2947. char *oldfile, *newfile, *error;
  2948. const char *pcr_error;
  2949. size_t oldfile_len, newfile_len;
  2950. phar_entry_info *oldentry, newentry = {0}, *temp;
  2951. size_t tmp_len = 0;
  2952. PHAR_ARCHIVE_OBJECT();
  2953. if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &oldfile, &oldfile_len, &newfile, &newfile_len) == FAILURE) {
  2954. RETURN_THROWS();
  2955. }
  2956. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  2957. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2958. "Cannot copy \"%s\" to \"%s\", phar is read-only", oldfile, newfile);
  2959. RETURN_THROWS();
  2960. }
  2961. if (oldfile_len >= sizeof(".phar")-1 && !memcmp(oldfile, ".phar", sizeof(".phar")-1)) {
  2962. /* can't copy a meta file */
  2963. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2964. "file \"%s\" cannot be copied to file \"%s\", cannot copy Phar meta-file in %s", oldfile, newfile, phar_obj->archive->fname);
  2965. RETURN_THROWS();
  2966. }
  2967. if (newfile_len >= sizeof(".phar")-1 && !memcmp(newfile, ".phar", sizeof(".phar")-1)) {
  2968. /* can't copy a meta file */
  2969. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2970. "file \"%s\" cannot be copied to file \"%s\", cannot copy to Phar meta-file in %s", oldfile, newfile, phar_obj->archive->fname);
  2971. RETURN_THROWS();
  2972. }
  2973. if (!zend_hash_str_exists(&phar_obj->archive->manifest, oldfile, (uint32_t) oldfile_len) || NULL == (oldentry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, oldfile, (uint32_t) oldfile_len)) || oldentry->is_deleted) {
  2974. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2975. "file \"%s\" cannot be copied to file \"%s\", file does not exist in %s", oldfile, newfile, phar_obj->archive->fname);
  2976. RETURN_THROWS();
  2977. }
  2978. if (zend_hash_str_exists(&phar_obj->archive->manifest, newfile, (uint32_t) newfile_len)) {
  2979. if (NULL != (temp = zend_hash_str_find_ptr(&phar_obj->archive->manifest, newfile, (uint32_t) newfile_len)) || !temp->is_deleted) {
  2980. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2981. "file \"%s\" cannot be copied to file \"%s\", file must not already exist in phar %s", oldfile, newfile, phar_obj->archive->fname);
  2982. RETURN_THROWS();
  2983. }
  2984. }
  2985. tmp_len = newfile_len;
  2986. if (phar_path_check(&newfile, &tmp_len, &pcr_error) > pcr_is_ok) {
  2987. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
  2988. "file \"%s\" contains invalid characters %s, cannot be copied from \"%s\" in phar %s", newfile, pcr_error, oldfile, phar_obj->archive->fname);
  2989. RETURN_THROWS();
  2990. }
  2991. newfile_len = tmp_len;
  2992. if (phar_obj->archive->is_persistent) {
  2993. if (FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  2994. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  2995. RETURN_THROWS();
  2996. }
  2997. /* re-populate with copied-on-write entry */
  2998. oldentry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, oldfile, (uint32_t) oldfile_len);
  2999. }
  3000. memcpy((void *) &newentry, oldentry, sizeof(phar_entry_info));
  3001. if (Z_TYPE(newentry.metadata) != IS_UNDEF) {
  3002. zval_copy_ctor(&newentry.metadata);
  3003. newentry.metadata_str.s = NULL;
  3004. }
  3005. newentry.filename = estrndup(newfile, newfile_len);
  3006. newentry.filename_len = newfile_len;
  3007. newentry.fp_refcount = 0;
  3008. if (oldentry->fp_type != PHAR_FP) {
  3009. if (FAILURE == phar_copy_entry_fp(oldentry, &newentry, &error)) {
  3010. efree(newentry.filename);
  3011. php_stream_close(newentry.fp);
  3012. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3013. efree(error);
  3014. RETURN_THROWS();
  3015. }
  3016. }
  3017. zend_hash_str_add_mem(&oldentry->phar->manifest, newfile, newfile_len, &newentry, sizeof(phar_entry_info));
  3018. phar_obj->archive->is_modified = 1;
  3019. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  3020. if (error) {
  3021. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3022. efree(error);
  3023. }
  3024. RETURN_TRUE;
  3025. }
  3026. /* }}} */
  3027. /* {{{ proto bool Phar::offsetExists(string entry)
  3028. * determines whether a file exists in the phar
  3029. */
  3030. PHP_METHOD(Phar, offsetExists)
  3031. {
  3032. char *fname;
  3033. size_t fname_len;
  3034. phar_entry_info *entry;
  3035. PHAR_ARCHIVE_OBJECT();
  3036. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
  3037. RETURN_THROWS();
  3038. }
  3039. if (zend_hash_str_exists(&phar_obj->archive->manifest, fname, (uint32_t) fname_len)) {
  3040. if (NULL != (entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint32_t) fname_len))) {
  3041. if (entry->is_deleted) {
  3042. /* entry is deleted, but has not been flushed to disk yet */
  3043. RETURN_FALSE;
  3044. }
  3045. }
  3046. if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
  3047. /* none of these are real files, so they don't exist */
  3048. RETURN_FALSE;
  3049. }
  3050. RETURN_TRUE;
  3051. } else {
  3052. if (zend_hash_str_exists(&phar_obj->archive->virtual_dirs, fname, (uint32_t) fname_len)) {
  3053. RETURN_TRUE;
  3054. }
  3055. RETURN_FALSE;
  3056. }
  3057. }
  3058. /* }}} */
  3059. /* {{{ proto PharFileInfo Phar::offsetGet(string entry)
  3060. * get a PharFileInfo object for a specific file
  3061. */
  3062. PHP_METHOD(Phar, offsetGet)
  3063. {
  3064. char *fname, *error;
  3065. size_t fname_len;
  3066. zval zfname;
  3067. phar_entry_info *entry;
  3068. zend_string *sfname;
  3069. PHAR_ARCHIVE_OBJECT();
  3070. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
  3071. RETURN_THROWS();
  3072. }
  3073. /* security is 0 here so that we can get a better error message than "entry doesn't exist" */
  3074. if (!(entry = phar_get_entry_info_dir(phar_obj->archive, fname, fname_len, 1, &error, 0))) {
  3075. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist%s%s", fname, error?", ":"", error?error:"");
  3076. } else {
  3077. if (fname_len == sizeof(".phar/stub.php")-1 && !memcmp(fname, ".phar/stub.php", sizeof(".phar/stub.php")-1)) {
  3078. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot get stub \".phar/stub.php\" directly in phar \"%s\", use getStub", phar_obj->archive->fname);
  3079. RETURN_THROWS();
  3080. }
  3081. if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
  3082. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot get alias \".phar/alias.txt\" directly in phar \"%s\", use getAlias", phar_obj->archive->fname);
  3083. RETURN_THROWS();
  3084. }
  3085. if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
  3086. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot directly get any files or directories in magic \".phar\" directory");
  3087. RETURN_THROWS();
  3088. }
  3089. if (entry->is_temp_dir) {
  3090. efree(entry->filename);
  3091. efree(entry);
  3092. }
  3093. sfname = strpprintf(0, "phar://%s/%s", phar_obj->archive->fname, fname);
  3094. ZVAL_NEW_STR(&zfname, sfname);
  3095. spl_instantiate_arg_ex1(phar_obj->spl.info_class, return_value, &zfname);
  3096. zval_ptr_dtor(&zfname);
  3097. }
  3098. }
  3099. /* }}} */
  3100. /* {{{ add a file within the phar archive from a string or resource
  3101. */
  3102. static void phar_add_file(phar_archive_data **pphar, char *filename, size_t filename_len, char *cont_str, size_t cont_len, zval *zresource)
  3103. {
  3104. size_t start_pos=0;
  3105. char *error;
  3106. size_t contents_len;
  3107. phar_entry_data *data;
  3108. php_stream *contents_file = NULL;
  3109. php_stream_statbuf ssb;
  3110. #ifdef PHP_WIN32
  3111. char *save_filename;
  3112. ALLOCA_FLAG(filename_use_heap)
  3113. #endif
  3114. if (filename_len >= sizeof(".phar")-1) {
  3115. start_pos = '/' == filename[0]; /* account for any leading slash: multiple-leads handled elsewhere */
  3116. if (!memcmp(&filename[start_pos], ".phar", sizeof(".phar")-1) && (filename[start_pos+5] == '/' || filename[start_pos+5] == '\\' || filename[start_pos+5] == '\0')) {
  3117. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot create any files in magic \".phar\" directory");
  3118. return;
  3119. }
  3120. }
  3121. #ifdef PHP_WIN32
  3122. save_filename = filename;
  3123. if (memchr(filename, '\\', filename_len)) {
  3124. filename = do_alloca(filename_len + 1, filename_use_heap);
  3125. memcpy(filename, save_filename, filename_len);
  3126. filename[filename_len] = '\0';
  3127. }
  3128. #endif
  3129. if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, filename, filename_len, "w+b", 0, &error, 1))) {
  3130. if (error) {
  3131. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist and cannot be created: %s", filename, error);
  3132. efree(error);
  3133. } else {
  3134. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s does not exist and cannot be created", filename);
  3135. }
  3136. goto finish;
  3137. } else {
  3138. if (error) {
  3139. efree(error);
  3140. }
  3141. if (!data->internal_file->is_dir) {
  3142. if (cont_str) {
  3143. contents_len = php_stream_write(data->fp, cont_str, cont_len);
  3144. if (contents_len != cont_len) {
  3145. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s could not be written to", filename);
  3146. goto finish;
  3147. }
  3148. } else {
  3149. if (!(php_stream_from_zval_no_verify(contents_file, zresource))) {
  3150. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Entry %s could not be written to", filename);
  3151. goto finish;
  3152. }
  3153. php_stream_copy_to_stream_ex(contents_file, data->fp, PHP_STREAM_COPY_ALL, &contents_len);
  3154. }
  3155. data->internal_file->compressed_filesize = data->internal_file->uncompressed_filesize = contents_len;
  3156. }
  3157. if (contents_file != NULL && php_stream_stat(contents_file, &ssb) != -1) {
  3158. data->internal_file->flags = ssb.sb.st_mode & PHAR_ENT_PERM_MASK ;
  3159. } else {
  3160. #ifndef _WIN32
  3161. mode_t mask;
  3162. mask = umask(0);
  3163. umask(mask);
  3164. data->internal_file->flags &= ~mask;
  3165. #endif
  3166. }
  3167. /* check for copy-on-write */
  3168. if (pphar[0] != data->phar) {
  3169. *pphar = data->phar;
  3170. }
  3171. phar_entry_delref(data);
  3172. phar_flush(*pphar, 0, 0, 0, &error);
  3173. if (error) {
  3174. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3175. efree(error);
  3176. }
  3177. }
  3178. finish: ;
  3179. #ifdef PHP_WIN32
  3180. if (filename != save_filename) {
  3181. free_alloca(filename, filename_use_heap);
  3182. filename = save_filename;
  3183. }
  3184. #endif
  3185. }
  3186. /* }}} */
  3187. /* {{{ create a directory within the phar archive
  3188. */
  3189. static void phar_mkdir(phar_archive_data **pphar, char *dirname, size_t dirname_len)
  3190. {
  3191. char *error;
  3192. phar_entry_data *data;
  3193. if (!(data = phar_get_or_create_entry_data((*pphar)->fname, (*pphar)->fname_len, dirname, dirname_len, "w+b", 2, &error, 1))) {
  3194. if (error) {
  3195. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Directory %s does not exist and cannot be created: %s", dirname, error);
  3196. efree(error);
  3197. } else {
  3198. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Directory %s does not exist and cannot be created", dirname);
  3199. }
  3200. return;
  3201. } else {
  3202. if (error) {
  3203. efree(error);
  3204. }
  3205. /* check for copy on write */
  3206. if (data->phar != *pphar) {
  3207. *pphar = data->phar;
  3208. }
  3209. phar_entry_delref(data);
  3210. phar_flush(*pphar, 0, 0, 0, &error);
  3211. if (error) {
  3212. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3213. efree(error);
  3214. }
  3215. }
  3216. }
  3217. /* }}} */
  3218. /* {{{ proto void Phar::offsetSet(string entry, string value)
  3219. * set the contents of an internal file to those of an external file
  3220. */
  3221. PHP_METHOD(Phar, offsetSet)
  3222. {
  3223. char *fname, *cont_str = NULL;
  3224. size_t fname_len, cont_len;
  3225. zval *zresource;
  3226. PHAR_ARCHIVE_OBJECT();
  3227. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  3228. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
  3229. RETURN_THROWS();
  3230. }
  3231. if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "pr", &fname, &fname_len, &zresource) == FAILURE
  3232. && zend_parse_parameters(ZEND_NUM_ARGS(), "ps", &fname, &fname_len, &cont_str, &cont_len) == FAILURE) {
  3233. RETURN_THROWS();
  3234. }
  3235. if (fname_len == sizeof(".phar/stub.php")-1 && !memcmp(fname, ".phar/stub.php", sizeof(".phar/stub.php")-1)) {
  3236. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot set stub \".phar/stub.php\" directly in phar \"%s\", use setStub", phar_obj->archive->fname);
  3237. RETURN_THROWS();
  3238. }
  3239. if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, ".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
  3240. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot set alias \".phar/alias.txt\" directly in phar \"%s\", use setAlias", phar_obj->archive->fname);
  3241. RETURN_THROWS();
  3242. }
  3243. if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", sizeof(".phar")-1)) {
  3244. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot set any files or directories in magic \".phar\" directory");
  3245. RETURN_THROWS();
  3246. }
  3247. phar_add_file(&(phar_obj->archive), fname, fname_len, cont_str, cont_len, zresource);
  3248. }
  3249. /* }}} */
  3250. /* {{{ proto bool Phar::offsetUnset(string entry)
  3251. * remove a file from a phar
  3252. */
  3253. PHP_METHOD(Phar, offsetUnset)
  3254. {
  3255. char *fname, *error;
  3256. size_t fname_len;
  3257. phar_entry_info *entry;
  3258. PHAR_ARCHIVE_OBJECT();
  3259. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  3260. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
  3261. RETURN_THROWS();
  3262. }
  3263. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
  3264. RETURN_THROWS();
  3265. }
  3266. if (zend_hash_str_exists(&phar_obj->archive->manifest, fname, (uint32_t) fname_len)) {
  3267. if (NULL != (entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint32_t) fname_len))) {
  3268. if (entry->is_deleted) {
  3269. /* entry is deleted, but has not been flushed to disk yet */
  3270. return;
  3271. }
  3272. if (phar_obj->archive->is_persistent) {
  3273. if (FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  3274. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  3275. RETURN_THROWS();
  3276. }
  3277. /* re-populate entry after copy on write */
  3278. entry = zend_hash_str_find_ptr(&phar_obj->archive->manifest, fname, (uint32_t) fname_len);
  3279. }
  3280. entry->is_modified = 0;
  3281. entry->is_deleted = 1;
  3282. /* we need to "flush" the stream to save the newly deleted file on disk */
  3283. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  3284. if (error) {
  3285. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3286. efree(error);
  3287. }
  3288. RETURN_TRUE;
  3289. }
  3290. } else {
  3291. RETURN_FALSE;
  3292. }
  3293. }
  3294. /* }}} */
  3295. /* {{{ proto string Phar::addEmptyDir(string dirname)
  3296. * Adds an empty directory to the phar archive
  3297. */
  3298. PHP_METHOD(Phar, addEmptyDir)
  3299. {
  3300. char *dirname;
  3301. size_t dirname_len;
  3302. PHAR_ARCHIVE_OBJECT();
  3303. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &dirname, &dirname_len) == FAILURE) {
  3304. RETURN_THROWS();
  3305. }
  3306. if (dirname_len >= sizeof(".phar")-1 && !memcmp(dirname, ".phar", sizeof(".phar")-1)) {
  3307. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot create a directory in magic \".phar\" directory");
  3308. RETURN_THROWS();
  3309. }
  3310. phar_mkdir(&phar_obj->archive, dirname, dirname_len);
  3311. }
  3312. /* }}} */
  3313. /* {{{ proto string Phar::addFile(string filename[, string localname])
  3314. * Adds a file to the archive using the filename, or the second parameter as the name within the archive
  3315. */
  3316. PHP_METHOD(Phar, addFile)
  3317. {
  3318. char *fname, *localname = NULL;
  3319. size_t fname_len, localname_len = 0;
  3320. php_stream *resource;
  3321. zval zresource;
  3322. PHAR_ARCHIVE_OBJECT();
  3323. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s", &fname, &fname_len, &localname, &localname_len) == FAILURE) {
  3324. RETURN_THROWS();
  3325. }
  3326. if (!strstr(fname, "://") && php_check_open_basedir(fname)) {
  3327. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "phar error: unable to open file \"%s\" to add to phar archive, open_basedir restrictions prevent this", fname);
  3328. RETURN_THROWS();
  3329. }
  3330. if (!(resource = php_stream_open_wrapper(fname, "rb", 0, NULL))) {
  3331. zend_throw_exception_ex(spl_ce_RuntimeException, 0, "phar error: unable to open file \"%s\" to add to phar archive", fname);
  3332. RETURN_THROWS();
  3333. }
  3334. if (localname) {
  3335. fname = localname;
  3336. fname_len = localname_len;
  3337. }
  3338. php_stream_to_zval(resource, &zresource);
  3339. phar_add_file(&(phar_obj->archive), fname, fname_len, NULL, 0, &zresource);
  3340. zval_ptr_dtor(&zresource);
  3341. }
  3342. /* }}} */
  3343. /* {{{ proto string Phar::addFromString(string localname, string contents)
  3344. * Adds a file to the archive using its contents as a string
  3345. */
  3346. PHP_METHOD(Phar, addFromString)
  3347. {
  3348. char *localname, *cont_str;
  3349. size_t localname_len, cont_len;
  3350. PHAR_ARCHIVE_OBJECT();
  3351. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ps", &localname, &localname_len, &cont_str, &cont_len) == FAILURE) {
  3352. RETURN_THROWS();
  3353. }
  3354. phar_add_file(&(phar_obj->archive), localname, localname_len, cont_str, cont_len, NULL);
  3355. }
  3356. /* }}} */
  3357. /* {{{ proto string Phar::getStub()
  3358. * Returns the stub at the head of a phar archive as a string.
  3359. */
  3360. PHP_METHOD(Phar, getStub)
  3361. {
  3362. size_t len;
  3363. zend_string *buf;
  3364. php_stream *fp;
  3365. php_stream_filter *filter = NULL;
  3366. phar_entry_info *stub;
  3367. PHAR_ARCHIVE_OBJECT();
  3368. if (zend_parse_parameters_none() == FAILURE) {
  3369. RETURN_THROWS();
  3370. }
  3371. if (phar_obj->archive->is_tar || phar_obj->archive->is_zip) {
  3372. if (NULL != (stub = zend_hash_str_find_ptr(&(phar_obj->archive->manifest), ".phar/stub.php", sizeof(".phar/stub.php")-1))) {
  3373. if (phar_obj->archive->fp && !phar_obj->archive->is_brandnew && !(stub->flags & PHAR_ENT_COMPRESSION_MASK)) {
  3374. fp = phar_obj->archive->fp;
  3375. } else {
  3376. if (!(fp = php_stream_open_wrapper(phar_obj->archive->fname, "rb", 0, NULL))) {
  3377. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "phar error: unable to open phar \"%s\"", phar_obj->archive->fname);
  3378. RETURN_THROWS();
  3379. }
  3380. if (stub->flags & PHAR_ENT_COMPRESSION_MASK) {
  3381. char *filter_name;
  3382. if ((filter_name = phar_decompress_filter(stub, 0)) != NULL) {
  3383. filter = php_stream_filter_create(filter_name, NULL, php_stream_is_persistent(fp));
  3384. } else {
  3385. filter = NULL;
  3386. }
  3387. if (!filter) {
  3388. zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "phar error: unable to read stub of phar \"%s\" (cannot create %s filter)", phar_obj->archive->fname, phar_decompress_filter(stub, 1));
  3389. RETURN_THROWS();
  3390. }
  3391. php_stream_filter_append(&fp->readfilters, filter);
  3392. }
  3393. }
  3394. if (!fp) {
  3395. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3396. "Unable to read stub");
  3397. RETURN_THROWS();
  3398. }
  3399. php_stream_seek(fp, stub->offset_abs, SEEK_SET);
  3400. len = stub->uncompressed_filesize;
  3401. goto carry_on;
  3402. } else {
  3403. RETURN_EMPTY_STRING();
  3404. }
  3405. }
  3406. len = phar_obj->archive->halt_offset;
  3407. if (phar_obj->archive->fp && !phar_obj->archive->is_brandnew) {
  3408. fp = phar_obj->archive->fp;
  3409. } else {
  3410. fp = php_stream_open_wrapper(phar_obj->archive->fname, "rb", 0, NULL);
  3411. }
  3412. if (!fp) {
  3413. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3414. "Unable to read stub");
  3415. RETURN_THROWS();
  3416. }
  3417. php_stream_rewind(fp);
  3418. carry_on:
  3419. buf = zend_string_alloc(len, 0);
  3420. if (len != php_stream_read(fp, ZSTR_VAL(buf), len)) {
  3421. if (fp != phar_obj->archive->fp) {
  3422. php_stream_close(fp);
  3423. }
  3424. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3425. "Unable to read stub");
  3426. zend_string_release_ex(buf, 0);
  3427. RETURN_THROWS();
  3428. }
  3429. if (filter) {
  3430. php_stream_filter_flush(filter, 1);
  3431. php_stream_filter_remove(filter, 1);
  3432. }
  3433. if (fp != phar_obj->archive->fp) {
  3434. php_stream_close(fp);
  3435. }
  3436. ZSTR_VAL(buf)[len] = '\0';
  3437. ZSTR_LEN(buf) = len;
  3438. RETVAL_STR(buf);
  3439. }
  3440. /* }}}*/
  3441. /* {{{ proto int Phar::hasMetaData()
  3442. * Returns TRUE if the phar has global metadata, FALSE otherwise.
  3443. */
  3444. PHP_METHOD(Phar, hasMetadata)
  3445. {
  3446. PHAR_ARCHIVE_OBJECT();
  3447. if (zend_parse_parameters_none() == FAILURE) {
  3448. RETURN_THROWS();
  3449. }
  3450. RETURN_BOOL(Z_TYPE(phar_obj->archive->metadata) != IS_UNDEF);
  3451. }
  3452. /* }}} */
  3453. /* {{{ proto int Phar::getMetaData()
  3454. * Returns the global metadata of the phar
  3455. */
  3456. PHP_METHOD(Phar, getMetadata)
  3457. {
  3458. PHAR_ARCHIVE_OBJECT();
  3459. if (zend_parse_parameters_none() == FAILURE) {
  3460. RETURN_THROWS();
  3461. }
  3462. if (Z_TYPE(phar_obj->archive->metadata) != IS_UNDEF) {
  3463. if (phar_obj->archive->is_persistent) {
  3464. char *buf = estrndup((char *) Z_PTR(phar_obj->archive->metadata), phar_obj->archive->metadata_len);
  3465. /* assume success, we would have failed before */
  3466. phar_parse_metadata(&buf, return_value, phar_obj->archive->metadata_len);
  3467. efree(buf);
  3468. } else {
  3469. ZVAL_COPY(return_value, &phar_obj->archive->metadata);
  3470. }
  3471. }
  3472. }
  3473. /* }}} */
  3474. /* {{{ proto int Phar::setMetaData(mixed $metadata)
  3475. * Sets the global metadata of the phar
  3476. */
  3477. PHP_METHOD(Phar, setMetadata)
  3478. {
  3479. char *error;
  3480. zval *metadata;
  3481. PHAR_ARCHIVE_OBJECT();
  3482. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  3483. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
  3484. RETURN_THROWS();
  3485. }
  3486. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &metadata) == FAILURE) {
  3487. RETURN_THROWS();
  3488. }
  3489. if (phar_obj->archive->is_persistent && FAILURE == phar_copy_on_write(&(phar_obj->archive))) {
  3490. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar_obj->archive->fname);
  3491. RETURN_THROWS();
  3492. }
  3493. if (Z_TYPE(phar_obj->archive->metadata) != IS_UNDEF) {
  3494. zval_ptr_dtor(&phar_obj->archive->metadata);
  3495. ZVAL_UNDEF(&phar_obj->archive->metadata);
  3496. }
  3497. ZVAL_COPY(&phar_obj->archive->metadata, metadata);
  3498. phar_obj->archive->is_modified = 1;
  3499. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  3500. if (error) {
  3501. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3502. efree(error);
  3503. }
  3504. }
  3505. /* }}} */
  3506. /* {{{ proto int Phar::delMetadata()
  3507. * Deletes the global metadata of the phar
  3508. */
  3509. PHP_METHOD(Phar, delMetadata)
  3510. {
  3511. char *error;
  3512. PHAR_ARCHIVE_OBJECT();
  3513. if (PHAR_G(readonly) && !phar_obj->archive->is_data) {
  3514. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
  3515. RETURN_THROWS();
  3516. }
  3517. if (zend_parse_parameters_none() == FAILURE) {
  3518. RETURN_THROWS();
  3519. }
  3520. if (Z_TYPE(phar_obj->archive->metadata) != IS_UNDEF) {
  3521. zval_ptr_dtor(&phar_obj->archive->metadata);
  3522. ZVAL_UNDEF(&phar_obj->archive->metadata);
  3523. phar_obj->archive->is_modified = 1;
  3524. phar_flush(phar_obj->archive, 0, 0, 0, &error);
  3525. if (error) {
  3526. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  3527. efree(error);
  3528. RETURN_THROWS();
  3529. } else {
  3530. RETURN_TRUE;
  3531. }
  3532. } else {
  3533. RETURN_TRUE;
  3534. }
  3535. }
  3536. /* }}} */
  3537. static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *dest, size_t dest_len, char **error) /* {{{ */
  3538. {
  3539. php_stream_statbuf ssb;
  3540. size_t len;
  3541. php_stream *fp;
  3542. char *fullpath;
  3543. const char *slash;
  3544. mode_t mode;
  3545. cwd_state new_state;
  3546. char *filename;
  3547. size_t filename_len;
  3548. if (entry->is_mounted) {
  3549. /* silently ignore mounted entries */
  3550. return SUCCESS;
  3551. }
  3552. if (entry->filename_len >= sizeof(".phar")-1 && !memcmp(entry->filename, ".phar", sizeof(".phar")-1)) {
  3553. return SUCCESS;
  3554. }
  3555. /* strip .. from path and restrict it to be under dest directory */
  3556. new_state.cwd = (char*)emalloc(2);
  3557. new_state.cwd[0] = DEFAULT_SLASH;
  3558. new_state.cwd[1] = '\0';
  3559. new_state.cwd_length = 1;
  3560. if (virtual_file_ex(&new_state, entry->filename, NULL, CWD_EXPAND) != 0 ||
  3561. new_state.cwd_length <= 1) {
  3562. if (EINVAL == errno && entry->filename_len > 50) {
  3563. char *tmp = estrndup(entry->filename, 50);
  3564. spprintf(error, 4096, "Cannot extract \"%s...\" to \"%s...\", extracted filename is too long for filesystem", tmp, dest);
  3565. efree(tmp);
  3566. } else {
  3567. spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename);
  3568. }
  3569. efree(new_state.cwd);
  3570. return FAILURE;
  3571. }
  3572. filename = new_state.cwd + 1;
  3573. filename_len = new_state.cwd_length - 1;
  3574. #ifdef PHP_WIN32
  3575. /* unixify the path back, otherwise non zip formats might be broken */
  3576. {
  3577. size_t cnt = 0;
  3578. do {
  3579. if ('\\' == filename[cnt]) {
  3580. filename[cnt] = '/';
  3581. }
  3582. } while (cnt++ < filename_len);
  3583. }
  3584. #endif
  3585. len = spprintf(&fullpath, 0, "%s/%s", dest, filename);
  3586. if (len >= MAXPATHLEN) {
  3587. char *tmp;
  3588. /* truncate for error message */
  3589. fullpath[50] = '\0';
  3590. if (entry->filename_len > 50) {
  3591. tmp = estrndup(entry->filename, 50);
  3592. spprintf(error, 4096, "Cannot extract \"%s...\" to \"%s...\", extracted filename is too long for filesystem", tmp, fullpath);
  3593. efree(tmp);
  3594. } else {
  3595. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s...\", extracted filename is too long for filesystem", entry->filename, fullpath);
  3596. }
  3597. efree(fullpath);
  3598. efree(new_state.cwd);
  3599. return FAILURE;
  3600. }
  3601. if (!len) {
  3602. spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename);
  3603. efree(fullpath);
  3604. efree(new_state.cwd);
  3605. return FAILURE;
  3606. }
  3607. if (php_check_open_basedir(fullpath)) {
  3608. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", openbasedir/safe mode restrictions in effect", entry->filename, fullpath);
  3609. efree(fullpath);
  3610. efree(new_state.cwd);
  3611. return FAILURE;
  3612. }
  3613. /* let see if the path already exists */
  3614. if (!overwrite && SUCCESS == php_stream_stat_path(fullpath, &ssb)) {
  3615. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", path already exists", entry->filename, fullpath);
  3616. efree(fullpath);
  3617. efree(new_state.cwd);
  3618. return FAILURE;
  3619. }
  3620. /* perform dirname */
  3621. slash = zend_memrchr(filename, '/', filename_len);
  3622. if (slash) {
  3623. fullpath[dest_len + (slash - filename) + 1] = '\0';
  3624. } else {
  3625. fullpath[dest_len] = '\0';
  3626. }
  3627. if (FAILURE == php_stream_stat_path(fullpath, &ssb)) {
  3628. if (entry->is_dir) {
  3629. if (!php_stream_mkdir(fullpath, entry->flags & PHAR_ENT_PERM_MASK, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
  3630. spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
  3631. efree(fullpath);
  3632. efree(new_state.cwd);
  3633. return FAILURE;
  3634. }
  3635. } else {
  3636. if (!php_stream_mkdir(fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
  3637. spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
  3638. efree(fullpath);
  3639. efree(new_state.cwd);
  3640. return FAILURE;
  3641. }
  3642. }
  3643. }
  3644. if (slash) {
  3645. fullpath[dest_len + (slash - filename) + 1] = '/';
  3646. } else {
  3647. fullpath[dest_len] = '/';
  3648. }
  3649. filename = NULL;
  3650. efree(new_state.cwd);
  3651. /* it is a standalone directory, job done */
  3652. if (entry->is_dir) {
  3653. efree(fullpath);
  3654. return SUCCESS;
  3655. }
  3656. fp = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL);
  3657. if (!fp) {
  3658. spprintf(error, 4096, "Cannot extract \"%s\", could not open for writing \"%s\"", entry->filename, fullpath);
  3659. efree(fullpath);
  3660. return FAILURE;
  3661. }
  3662. if (!phar_get_efp(entry, 0)) {
  3663. if (FAILURE == phar_open_entry_fp(entry, error, 1)) {
  3664. if (error) {
  3665. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer: %s", entry->filename, fullpath, *error);
  3666. } else {
  3667. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to open internal file pointer", entry->filename, fullpath);
  3668. }
  3669. efree(fullpath);
  3670. php_stream_close(fp);
  3671. return FAILURE;
  3672. }
  3673. }
  3674. if (FAILURE == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) {
  3675. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", unable to seek internal file pointer", entry->filename, fullpath);
  3676. efree(fullpath);
  3677. php_stream_close(fp);
  3678. return FAILURE;
  3679. }
  3680. if (SUCCESS != php_stream_copy_to_stream_ex(phar_get_efp(entry, 0), fp, entry->uncompressed_filesize, NULL)) {
  3681. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", copying contents failed", entry->filename, fullpath);
  3682. efree(fullpath);
  3683. php_stream_close(fp);
  3684. return FAILURE;
  3685. }
  3686. php_stream_close(fp);
  3687. mode = (mode_t) entry->flags & PHAR_ENT_PERM_MASK;
  3688. if (FAILURE == VCWD_CHMOD(fullpath, mode)) {
  3689. spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", setting file permissions failed", entry->filename, fullpath);
  3690. efree(fullpath);
  3691. return FAILURE;
  3692. }
  3693. efree(fullpath);
  3694. return SUCCESS;
  3695. }
  3696. /* }}} */
  3697. static int extract_helper(phar_archive_data *archive, zend_string *search, char *pathto, size_t pathto_len, zend_bool overwrite, char **error) { /* {{{ */
  3698. int extracted = 0;
  3699. phar_entry_info *entry;
  3700. if (!search) {
  3701. /* nothing to match -- extract all files */
  3702. ZEND_HASH_FOREACH_PTR(&archive->manifest, entry) {
  3703. if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1;
  3704. extracted++;
  3705. } ZEND_HASH_FOREACH_END();
  3706. } else if ('/' == ZSTR_VAL(search)[ZSTR_LEN(search) - 1]) {
  3707. /* ends in "/" -- extract all entries having that prefix */
  3708. ZEND_HASH_FOREACH_PTR(&archive->manifest, entry) {
  3709. if (0 != strncmp(ZSTR_VAL(search), entry->filename, ZSTR_LEN(search))) continue;
  3710. if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1;
  3711. extracted++;
  3712. } ZEND_HASH_FOREACH_END();
  3713. } else {
  3714. /* otherwise, looking for an exact match */
  3715. entry = zend_hash_find_ptr(&archive->manifest, search);
  3716. if (NULL == entry) return 0;
  3717. if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1;
  3718. return 1;
  3719. }
  3720. return extracted;
  3721. }
  3722. /* }}} */
  3723. /* {{{ proto bool Phar::extractTo(string pathto[[, mixed files], bool overwrite])
  3724. * Extract one or more file from a phar archive, optionally overwriting existing files
  3725. */
  3726. PHP_METHOD(Phar, extractTo)
  3727. {
  3728. php_stream *fp;
  3729. php_stream_statbuf ssb;
  3730. char *pathto;
  3731. zend_string *filename;
  3732. size_t pathto_len;
  3733. int ret;
  3734. zval *zval_file;
  3735. zval *zval_files = NULL;
  3736. zend_bool overwrite = 0;
  3737. char *error = NULL;
  3738. PHAR_ARCHIVE_OBJECT();
  3739. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|z!b", &pathto, &pathto_len, &zval_files, &overwrite) == FAILURE) {
  3740. RETURN_THROWS();
  3741. }
  3742. fp = php_stream_open_wrapper(phar_obj->archive->fname, "rb", IGNORE_URL|STREAM_MUST_SEEK, NULL);
  3743. if (!fp) {
  3744. zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
  3745. "Invalid argument, %s cannot be found", phar_obj->archive->fname);
  3746. RETURN_THROWS();
  3747. }
  3748. php_stream_close(fp);
  3749. if (pathto_len < 1) {
  3750. zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
  3751. "Invalid argument, extraction path must be non-zero length");
  3752. RETURN_THROWS();
  3753. }
  3754. if (pathto_len >= MAXPATHLEN) {
  3755. char *tmp = estrndup(pathto, 50);
  3756. /* truncate for error message */
  3757. zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Cannot extract to \"%s...\", destination directory is too long for filesystem", tmp);
  3758. efree(tmp);
  3759. RETURN_THROWS();
  3760. }
  3761. if (php_stream_stat_path(pathto, &ssb) < 0) {
  3762. ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
  3763. if (!ret) {
  3764. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3765. "Unable to create path \"%s\" for extraction", pathto);
  3766. RETURN_THROWS();
  3767. }
  3768. } else if (!(ssb.sb.st_mode & S_IFDIR)) {
  3769. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3770. "Unable to use path \"%s\" for extraction, it is a file, must be a directory", pathto);
  3771. RETURN_THROWS();
  3772. }
  3773. if (zval_files) {
  3774. switch (Z_TYPE_P(zval_files)) {
  3775. case IS_NULL:
  3776. filename = NULL;
  3777. break;
  3778. case IS_STRING:
  3779. filename = Z_STR_P(zval_files);
  3780. break;
  3781. case IS_ARRAY:
  3782. if (zend_hash_num_elements(Z_ARRVAL_P(zval_files)) == 0) {
  3783. RETURN_FALSE;
  3784. }
  3785. ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zval_files), zval_file) {
  3786. ZVAL_DEREF(zval_file);
  3787. if (IS_STRING != Z_TYPE_P(zval_file)) {
  3788. zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
  3789. "Invalid argument, array of filenames to extract contains non-string value");
  3790. RETURN_THROWS();
  3791. }
  3792. switch (extract_helper(phar_obj->archive, Z_STR_P(zval_file), pathto, pathto_len, overwrite, &error)) {
  3793. case -1:
  3794. zend_throw_exception_ex(phar_ce_PharException, 0, "Extraction from phar \"%s\" failed: %s",
  3795. phar_obj->archive->fname, error);
  3796. efree(error);
  3797. RETURN_THROWS();
  3798. case 0:
  3799. zend_throw_exception_ex(phar_ce_PharException, 0,
  3800. "phar error: attempted to extract non-existent file or directory \"%s\" from phar \"%s\"",
  3801. ZSTR_VAL(Z_STR_P(zval_file)), phar_obj->archive->fname);
  3802. RETURN_THROWS();
  3803. }
  3804. } ZEND_HASH_FOREACH_END();
  3805. RETURN_TRUE;
  3806. default:
  3807. zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
  3808. "Invalid argument, expected a filename (string) or array of filenames");
  3809. RETURN_THROWS();
  3810. }
  3811. } else {
  3812. filename = NULL;
  3813. }
  3814. ret = extract_helper(phar_obj->archive, filename, pathto, pathto_len, overwrite, &error);
  3815. if (-1 == ret) {
  3816. zend_throw_exception_ex(phar_ce_PharException, 0, "Extraction from phar \"%s\" failed: %s",
  3817. phar_obj->archive->fname, error);
  3818. efree(error);
  3819. } else if (0 == ret && NULL != filename) {
  3820. zend_throw_exception_ex(phar_ce_PharException, 0,
  3821. "phar error: attempted to extract non-existent file or directory \"%s\" from phar \"%s\"",
  3822. ZSTR_VAL(filename), phar_obj->archive->fname);
  3823. } else {
  3824. RETURN_TRUE;
  3825. }
  3826. }
  3827. /* }}} */
  3828. /* {{{ proto PharFileInfo::__construct(string entry)
  3829. * Construct a Phar entry object
  3830. */
  3831. PHP_METHOD(PharFileInfo, __construct)
  3832. {
  3833. char *fname, *arch, *entry, *error;
  3834. size_t fname_len;
  3835. size_t arch_len, entry_len;
  3836. phar_entry_object *entry_obj;
  3837. phar_entry_info *entry_info;
  3838. phar_archive_data *phar_data;
  3839. zval *zobj = ZEND_THIS, arg1;
  3840. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &fname, &fname_len) == FAILURE) {
  3841. RETURN_THROWS();
  3842. }
  3843. entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset);
  3844. if (entry_obj->entry) {
  3845. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Cannot call constructor twice");
  3846. RETURN_THROWS();
  3847. }
  3848. if (fname_len < 7 || memcmp(fname, "phar://", 7) || phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0) == FAILURE) {
  3849. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3850. "'%s' is not a valid phar archive URL (must have at least phar://filename.phar)", fname);
  3851. RETURN_THROWS();
  3852. }
  3853. if (phar_open_from_filename(arch, arch_len, NULL, 0, REPORT_ERRORS, &phar_data, &error) == FAILURE) {
  3854. efree(arch);
  3855. efree(entry);
  3856. if (error) {
  3857. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3858. "Cannot open phar file '%s': %s", fname, error);
  3859. efree(error);
  3860. } else {
  3861. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3862. "Cannot open phar file '%s'", fname);
  3863. }
  3864. RETURN_THROWS();
  3865. }
  3866. if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 1, &error, 1)) == NULL) {
  3867. zend_throw_exception_ex(spl_ce_RuntimeException, 0,
  3868. "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error ? ", " : "", error ? error : "");
  3869. efree(arch);
  3870. efree(entry);
  3871. RETURN_THROWS();
  3872. }
  3873. efree(arch);
  3874. efree(entry);
  3875. entry_obj->entry = entry_info;
  3876. ZVAL_STRINGL(&arg1, fname, fname_len);
  3877. zend_call_method_with_1_params(Z_OBJ_P(zobj), Z_OBJCE_P(zobj),
  3878. &spl_ce_SplFileInfo->constructor, "__construct", NULL, &arg1);
  3879. zval_ptr_dtor(&arg1);
  3880. }
  3881. /* }}} */
  3882. #define PHAR_ENTRY_OBJECT() \
  3883. zval *zobj = ZEND_THIS; \
  3884. phar_entry_object *entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); \
  3885. if (!entry_obj->entry) { \
  3886. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  3887. "Cannot call method on an uninitialized PharFileInfo object"); \
  3888. RETURN_THROWS(); \
  3889. }
  3890. /* {{{ proto PharFileInfo::__destruct()
  3891. * clean up directory-based entry objects
  3892. */
  3893. PHP_METHOD(PharFileInfo, __destruct)
  3894. {
  3895. zval *zobj = ZEND_THIS;
  3896. phar_entry_object *entry_obj = (phar_entry_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset);
  3897. if (entry_obj->entry && entry_obj->entry->is_temp_dir) {
  3898. if (entry_obj->entry->filename) {
  3899. efree(entry_obj->entry->filename);
  3900. entry_obj->entry->filename = NULL;
  3901. }
  3902. efree(entry_obj->entry);
  3903. entry_obj->entry = NULL;
  3904. }
  3905. }
  3906. /* }}} */
  3907. /* {{{ proto int PharFileInfo::getCompressedSize()
  3908. * Returns the compressed size
  3909. */
  3910. PHP_METHOD(PharFileInfo, getCompressedSize)
  3911. {
  3912. PHAR_ENTRY_OBJECT();
  3913. if (zend_parse_parameters_none() == FAILURE) {
  3914. RETURN_THROWS();
  3915. }
  3916. RETURN_LONG(entry_obj->entry->compressed_filesize);
  3917. }
  3918. /* }}} */
  3919. /* {{{ proto bool PharFileInfo::isCompressed([int compression_type])
  3920. * Returns whether the entry is compressed, and whether it is compressed with Phar::GZ or Phar::BZ2 if specified
  3921. */
  3922. PHP_METHOD(PharFileInfo, isCompressed)
  3923. {
  3924. /* a number that is not Phar::GZ or Phar::BZ2 */
  3925. zend_long method = 9021976;
  3926. PHAR_ENTRY_OBJECT();
  3927. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &method) == FAILURE) {
  3928. RETURN_THROWS();
  3929. }
  3930. switch (method) {
  3931. case 9021976:
  3932. RETURN_BOOL(entry_obj->entry->flags & PHAR_ENT_COMPRESSION_MASK);
  3933. case PHAR_ENT_COMPRESSED_GZ:
  3934. RETURN_BOOL(entry_obj->entry->flags & PHAR_ENT_COMPRESSED_GZ);
  3935. case PHAR_ENT_COMPRESSED_BZ2:
  3936. RETURN_BOOL(entry_obj->entry->flags & PHAR_ENT_COMPRESSED_BZ2);
  3937. default:
  3938. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  3939. "Unknown compression type specified"); \
  3940. }
  3941. }
  3942. /* }}} */
  3943. /* {{{ proto int PharFileInfo::getCRC32()
  3944. * Returns CRC32 code or throws an exception if not CRC checked
  3945. */
  3946. PHP_METHOD(PharFileInfo, getCRC32)
  3947. {
  3948. PHAR_ENTRY_OBJECT();
  3949. if (zend_parse_parameters_none() == FAILURE) {
  3950. RETURN_THROWS();
  3951. }
  3952. if (entry_obj->entry->is_dir) {
  3953. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  3954. "Phar entry is a directory, does not have a CRC"); \
  3955. RETURN_THROWS();
  3956. }
  3957. if (entry_obj->entry->is_crc_checked) {
  3958. RETURN_LONG(entry_obj->entry->crc32);
  3959. } else {
  3960. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  3961. "Phar entry was not CRC checked"); \
  3962. }
  3963. }
  3964. /* }}} */
  3965. /* {{{ proto int PharFileInfo::isCRCChecked()
  3966. * Returns whether file entry is CRC checked
  3967. */
  3968. PHP_METHOD(PharFileInfo, isCRCChecked)
  3969. {
  3970. PHAR_ENTRY_OBJECT();
  3971. if (zend_parse_parameters_none() == FAILURE) {
  3972. RETURN_THROWS();
  3973. }
  3974. RETURN_BOOL(entry_obj->entry->is_crc_checked);
  3975. }
  3976. /* }}} */
  3977. /* {{{ proto int PharFileInfo::getPharFlags()
  3978. * Returns the Phar file entry flags
  3979. */
  3980. PHP_METHOD(PharFileInfo, getPharFlags)
  3981. {
  3982. PHAR_ENTRY_OBJECT();
  3983. if (zend_parse_parameters_none() == FAILURE) {
  3984. RETURN_THROWS();
  3985. }
  3986. RETURN_LONG(entry_obj->entry->flags & ~(PHAR_ENT_PERM_MASK|PHAR_ENT_COMPRESSION_MASK));
  3987. }
  3988. /* }}} */
  3989. /* {{{ proto int PharFileInfo::chmod()
  3990. * set the file permissions for the Phar. This only allows setting execution bit, read/write
  3991. */
  3992. PHP_METHOD(PharFileInfo, chmod)
  3993. {
  3994. char *error;
  3995. zend_long perms;
  3996. PHAR_ENTRY_OBJECT();
  3997. if (entry_obj->entry->is_temp_dir) {
  3998. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  3999. "Phar entry \"%s\" is a temporary directory (not an actual entry in the archive), cannot chmod", entry_obj->entry->filename); \
  4000. RETURN_THROWS();
  4001. }
  4002. if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
  4003. zend_throw_exception_ex(phar_ce_PharException, 0, "Cannot modify permissions for file \"%s\" in phar \"%s\", write operations are prohibited", entry_obj->entry->filename, entry_obj->entry->phar->fname);
  4004. RETURN_THROWS();
  4005. }
  4006. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &perms) == FAILURE) {
  4007. RETURN_THROWS();
  4008. }
  4009. if (entry_obj->entry->is_persistent) {
  4010. phar_archive_data *phar = entry_obj->entry->phar;
  4011. if (FAILURE == phar_copy_on_write(&phar)) {
  4012. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
  4013. RETURN_THROWS();
  4014. }
  4015. /* re-populate after copy-on-write */
  4016. entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
  4017. }
  4018. /* clear permissions */
  4019. entry_obj->entry->flags &= ~PHAR_ENT_PERM_MASK;
  4020. perms &= 0777;
  4021. entry_obj->entry->flags |= perms;
  4022. entry_obj->entry->old_flags = entry_obj->entry->flags;
  4023. entry_obj->entry->phar->is_modified = 1;
  4024. entry_obj->entry->is_modified = 1;
  4025. /* hackish cache in php_stat needs to be cleared */
  4026. /* if this code fails to work, check main/streams/streams.c, _php_stream_stat_path */
  4027. if (BG(CurrentLStatFile)) {
  4028. efree(BG(CurrentLStatFile));
  4029. }
  4030. if (BG(CurrentStatFile)) {
  4031. efree(BG(CurrentStatFile));
  4032. }
  4033. BG(CurrentLStatFile) = NULL;
  4034. BG(CurrentStatFile) = NULL;
  4035. phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
  4036. if (error) {
  4037. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  4038. efree(error);
  4039. }
  4040. }
  4041. /* }}} */
  4042. /* {{{ proto int PharFileInfo::hasMetaData()
  4043. * Returns the metadata of the entry
  4044. */
  4045. PHP_METHOD(PharFileInfo, hasMetadata)
  4046. {
  4047. PHAR_ENTRY_OBJECT();
  4048. if (zend_parse_parameters_none() == FAILURE) {
  4049. RETURN_THROWS();
  4050. }
  4051. RETURN_BOOL(Z_TYPE(entry_obj->entry->metadata) != IS_UNDEF);
  4052. }
  4053. /* }}} */
  4054. /* {{{ proto int PharFileInfo::getMetaData()
  4055. * Returns the metadata of the entry
  4056. */
  4057. PHP_METHOD(PharFileInfo, getMetadata)
  4058. {
  4059. PHAR_ENTRY_OBJECT();
  4060. if (zend_parse_parameters_none() == FAILURE) {
  4061. RETURN_THROWS();
  4062. }
  4063. if (Z_TYPE(entry_obj->entry->metadata) != IS_UNDEF) {
  4064. if (entry_obj->entry->is_persistent) {
  4065. char *buf = estrndup((char *) Z_PTR(entry_obj->entry->metadata), entry_obj->entry->metadata_len);
  4066. /* assume success, we would have failed before */
  4067. phar_parse_metadata(&buf, return_value, entry_obj->entry->metadata_len);
  4068. efree(buf);
  4069. } else {
  4070. ZVAL_COPY(return_value, &entry_obj->entry->metadata);
  4071. }
  4072. }
  4073. }
  4074. /* }}} */
  4075. /* {{{ proto int PharFileInfo::setMetaData(mixed $metadata)
  4076. * Sets the metadata of the entry
  4077. */
  4078. PHP_METHOD(PharFileInfo, setMetadata)
  4079. {
  4080. char *error;
  4081. zval *metadata;
  4082. PHAR_ENTRY_OBJECT();
  4083. if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
  4084. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
  4085. RETURN_THROWS();
  4086. }
  4087. if (entry_obj->entry->is_temp_dir) {
  4088. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  4089. "Phar entry is a temporary directory (not an actual entry in the archive), cannot set metadata"); \
  4090. RETURN_THROWS();
  4091. }
  4092. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &metadata) == FAILURE) {
  4093. RETURN_THROWS();
  4094. }
  4095. if (entry_obj->entry->is_persistent) {
  4096. phar_archive_data *phar = entry_obj->entry->phar;
  4097. if (FAILURE == phar_copy_on_write(&phar)) {
  4098. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
  4099. RETURN_THROWS();
  4100. }
  4101. /* re-populate after copy-on-write */
  4102. entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
  4103. }
  4104. if (Z_TYPE(entry_obj->entry->metadata) != IS_UNDEF) {
  4105. zval_ptr_dtor(&entry_obj->entry->metadata);
  4106. ZVAL_UNDEF(&entry_obj->entry->metadata);
  4107. }
  4108. ZVAL_COPY(&entry_obj->entry->metadata, metadata);
  4109. entry_obj->entry->is_modified = 1;
  4110. entry_obj->entry->phar->is_modified = 1;
  4111. phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
  4112. if (error) {
  4113. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  4114. efree(error);
  4115. }
  4116. }
  4117. /* }}} */
  4118. /* {{{ proto bool PharFileInfo::delMetaData()
  4119. * Deletes the metadata of the entry
  4120. */
  4121. PHP_METHOD(PharFileInfo, delMetadata)
  4122. {
  4123. char *error;
  4124. PHAR_ENTRY_OBJECT();
  4125. if (zend_parse_parameters_none() == FAILURE) {
  4126. RETURN_THROWS();
  4127. }
  4128. if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
  4129. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Write operations disabled by the php.ini setting phar.readonly");
  4130. RETURN_THROWS();
  4131. }
  4132. if (entry_obj->entry->is_temp_dir) {
  4133. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  4134. "Phar entry is a temporary directory (not an actual entry in the archive), cannot delete metadata"); \
  4135. RETURN_THROWS();
  4136. }
  4137. if (Z_TYPE(entry_obj->entry->metadata) != IS_UNDEF) {
  4138. if (entry_obj->entry->is_persistent) {
  4139. phar_archive_data *phar = entry_obj->entry->phar;
  4140. if (FAILURE == phar_copy_on_write(&phar)) {
  4141. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
  4142. RETURN_THROWS();
  4143. }
  4144. /* re-populate after copy-on-write */
  4145. entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
  4146. }
  4147. zval_ptr_dtor(&entry_obj->entry->metadata);
  4148. ZVAL_UNDEF(&entry_obj->entry->metadata);
  4149. entry_obj->entry->is_modified = 1;
  4150. entry_obj->entry->phar->is_modified = 1;
  4151. phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
  4152. if (error) {
  4153. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  4154. efree(error);
  4155. RETURN_THROWS();
  4156. } else {
  4157. RETURN_TRUE;
  4158. }
  4159. } else {
  4160. RETURN_TRUE;
  4161. }
  4162. }
  4163. /* }}} */
  4164. /* {{{ proto string PharFileInfo::getContent()
  4165. * return the complete file contents of the entry (like file_get_contents)
  4166. */
  4167. PHP_METHOD(PharFileInfo, getContent)
  4168. {
  4169. char *error;
  4170. php_stream *fp;
  4171. phar_entry_info *link;
  4172. zend_string *str;
  4173. PHAR_ENTRY_OBJECT();
  4174. if (zend_parse_parameters_none() == FAILURE) {
  4175. RETURN_THROWS();
  4176. }
  4177. if (entry_obj->entry->is_dir) {
  4178. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4179. "phar error: Cannot retrieve contents, \"%s\" in phar \"%s\" is a directory", entry_obj->entry->filename, entry_obj->entry->phar->fname);
  4180. RETURN_THROWS();
  4181. }
  4182. link = phar_get_link_source(entry_obj->entry);
  4183. if (!link) {
  4184. link = entry_obj->entry;
  4185. }
  4186. if (SUCCESS != phar_open_entry_fp(link, &error, 0)) {
  4187. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4188. "phar error: Cannot retrieve contents, \"%s\" in phar \"%s\": %s", entry_obj->entry->filename, entry_obj->entry->phar->fname, error);
  4189. efree(error);
  4190. RETURN_THROWS();
  4191. }
  4192. if (!(fp = phar_get_efp(link, 0))) {
  4193. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4194. "phar error: Cannot retrieve contents of \"%s\" in phar \"%s\"", entry_obj->entry->filename, entry_obj->entry->phar->fname);
  4195. RETURN_THROWS();
  4196. }
  4197. phar_seek_efp(link, 0, SEEK_SET, 0, 0);
  4198. str = php_stream_copy_to_mem(fp, link->uncompressed_filesize, 0);
  4199. if (str) {
  4200. RETURN_STR(str);
  4201. } else {
  4202. RETURN_EMPTY_STRING();
  4203. }
  4204. }
  4205. /* }}} */
  4206. /* {{{ proto int PharFileInfo::compress(int compression_type)
  4207. * Instructs the Phar class to compress the current file using zlib or bzip2 compression
  4208. */
  4209. PHP_METHOD(PharFileInfo, compress)
  4210. {
  4211. zend_long method;
  4212. char *error;
  4213. PHAR_ENTRY_OBJECT();
  4214. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &method) == FAILURE) {
  4215. RETURN_THROWS();
  4216. }
  4217. if (entry_obj->entry->is_tar) {
  4218. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4219. "Cannot compress with Gzip compression, not possible with tar-based phar archives");
  4220. RETURN_THROWS();
  4221. }
  4222. if (entry_obj->entry->is_dir) {
  4223. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  4224. "Phar entry is a directory, cannot set compression"); \
  4225. RETURN_THROWS();
  4226. }
  4227. if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
  4228. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4229. "Phar is readonly, cannot change compression");
  4230. RETURN_THROWS();
  4231. }
  4232. if (entry_obj->entry->is_deleted) {
  4233. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4234. "Cannot compress deleted file");
  4235. RETURN_THROWS();
  4236. }
  4237. if (entry_obj->entry->is_persistent) {
  4238. phar_archive_data *phar = entry_obj->entry->phar;
  4239. if (FAILURE == phar_copy_on_write(&phar)) {
  4240. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
  4241. RETURN_THROWS();
  4242. }
  4243. /* re-populate after copy-on-write */
  4244. entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
  4245. }
  4246. switch (method) {
  4247. case PHAR_ENT_COMPRESSED_GZ:
  4248. if (entry_obj->entry->flags & PHAR_ENT_COMPRESSED_GZ) {
  4249. RETURN_TRUE;
  4250. }
  4251. if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSED_BZ2) != 0) {
  4252. if (!PHAR_G(has_bz2)) {
  4253. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4254. "Cannot compress with gzip compression, file is already compressed with bzip2 compression and bz2 extension is not enabled, cannot decompress");
  4255. RETURN_THROWS();
  4256. }
  4257. /* decompress this file indirectly */
  4258. if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) {
  4259. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4260. "phar error: Cannot decompress bzip2-compressed file \"%s\" in phar \"%s\" in order to compress with gzip: %s", entry_obj->entry->filename, entry_obj->entry->phar->fname, error);
  4261. efree(error);
  4262. RETURN_THROWS();
  4263. }
  4264. }
  4265. if (!PHAR_G(has_zlib)) {
  4266. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4267. "Cannot compress with gzip compression, zlib extension is not enabled");
  4268. RETURN_THROWS();
  4269. }
  4270. entry_obj->entry->old_flags = entry_obj->entry->flags;
  4271. entry_obj->entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
  4272. entry_obj->entry->flags |= PHAR_ENT_COMPRESSED_GZ;
  4273. break;
  4274. case PHAR_ENT_COMPRESSED_BZ2:
  4275. if (entry_obj->entry->flags & PHAR_ENT_COMPRESSED_BZ2) {
  4276. RETURN_TRUE;
  4277. }
  4278. if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSED_GZ) != 0) {
  4279. if (!PHAR_G(has_zlib)) {
  4280. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4281. "Cannot compress with bzip2 compression, file is already compressed with gzip compression and zlib extension is not enabled, cannot decompress");
  4282. RETURN_THROWS();
  4283. }
  4284. /* decompress this file indirectly */
  4285. if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) {
  4286. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4287. "phar error: Cannot decompress gzip-compressed file \"%s\" in phar \"%s\" in order to compress with bzip2: %s", entry_obj->entry->filename, entry_obj->entry->phar->fname, error);
  4288. efree(error);
  4289. RETURN_THROWS();
  4290. }
  4291. }
  4292. if (!PHAR_G(has_bz2)) {
  4293. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4294. "Cannot compress with bzip2 compression, bz2 extension is not enabled");
  4295. RETURN_THROWS();
  4296. }
  4297. entry_obj->entry->old_flags = entry_obj->entry->flags;
  4298. entry_obj->entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
  4299. entry_obj->entry->flags |= PHAR_ENT_COMPRESSED_BZ2;
  4300. break;
  4301. default:
  4302. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  4303. "Unknown compression type specified"); \
  4304. }
  4305. entry_obj->entry->phar->is_modified = 1;
  4306. entry_obj->entry->is_modified = 1;
  4307. phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
  4308. if (error) {
  4309. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  4310. efree(error);
  4311. RETURN_THROWS();
  4312. }
  4313. RETURN_TRUE;
  4314. }
  4315. /* }}} */
  4316. /* {{{ proto int PharFileInfo::decompress()
  4317. * Instructs the Phar class to decompress the current file
  4318. */
  4319. PHP_METHOD(PharFileInfo, decompress)
  4320. {
  4321. char *error;
  4322. char *compression_type;
  4323. PHAR_ENTRY_OBJECT();
  4324. if (zend_parse_parameters_none() == FAILURE) {
  4325. RETURN_THROWS();
  4326. }
  4327. if (entry_obj->entry->is_dir) {
  4328. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, \
  4329. "Phar entry is a directory, cannot set compression"); \
  4330. RETURN_THROWS();
  4331. }
  4332. if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSION_MASK) == 0) {
  4333. RETURN_TRUE;
  4334. }
  4335. if (PHAR_G(readonly) && !entry_obj->entry->phar->is_data) {
  4336. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4337. "Phar is readonly, cannot decompress");
  4338. RETURN_THROWS();
  4339. }
  4340. if (entry_obj->entry->is_deleted) {
  4341. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4342. "Cannot compress deleted file");
  4343. RETURN_THROWS();
  4344. }
  4345. if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSED_GZ) != 0 && !PHAR_G(has_zlib)) {
  4346. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4347. "Cannot decompress Gzip-compressed file, zlib extension is not enabled");
  4348. RETURN_THROWS();
  4349. }
  4350. if ((entry_obj->entry->flags & PHAR_ENT_COMPRESSED_BZ2) != 0 && !PHAR_G(has_bz2)) {
  4351. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4352. "Cannot decompress Bzip2-compressed file, bz2 extension is not enabled");
  4353. RETURN_THROWS();
  4354. }
  4355. if (entry_obj->entry->is_persistent) {
  4356. phar_archive_data *phar = entry_obj->entry->phar;
  4357. if (FAILURE == phar_copy_on_write(&phar)) {
  4358. zend_throw_exception_ex(phar_ce_PharException, 0, "phar \"%s\" is persistent, unable to copy on write", phar->fname);
  4359. RETURN_THROWS();
  4360. }
  4361. /* re-populate after copy-on-write */
  4362. entry_obj->entry = zend_hash_str_find_ptr(&phar->manifest, entry_obj->entry->filename, entry_obj->entry->filename_len);
  4363. }
  4364. switch (entry_obj->entry->flags & PHAR_ENT_COMPRESSION_MASK) {
  4365. case PHAR_ENT_COMPRESSED_GZ:
  4366. compression_type = "gzip";
  4367. break;
  4368. case PHAR_ENT_COMPRESSED_BZ2:
  4369. compression_type = "bz2";
  4370. break;
  4371. default:
  4372. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4373. "Cannot decompress file compressed with unknown compression type");
  4374. RETURN_THROWS();
  4375. }
  4376. /* decompress this file indirectly */
  4377. if (SUCCESS != phar_open_entry_fp(entry_obj->entry, &error, 1)) {
  4378. zend_throw_exception_ex(spl_ce_BadMethodCallException, 0,
  4379. "Phar error: Cannot decompress %s-compressed file \"%s\" in phar \"%s\": %s", compression_type, entry_obj->entry->filename, entry_obj->entry->phar->fname, error);
  4380. efree(error);
  4381. return;
  4382. }
  4383. entry_obj->entry->old_flags = entry_obj->entry->flags;
  4384. entry_obj->entry->flags &= ~PHAR_ENT_COMPRESSION_MASK;
  4385. entry_obj->entry->phar->is_modified = 1;
  4386. entry_obj->entry->is_modified = 1;
  4387. phar_flush(entry_obj->entry->phar, 0, 0, 0, &error);
  4388. if (error) {
  4389. zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error);
  4390. efree(error);
  4391. RETURN_THROWS();
  4392. }
  4393. RETURN_TRUE;
  4394. }
  4395. /* }}} */
  4396. /* {{{ phar methods */
  4397. #define REGISTER_PHAR_CLASS_CONST_LONG(class_name, const_name, value) \
  4398. zend_declare_class_constant_long(class_name, const_name, sizeof(const_name)-1, (zend_long)value);
  4399. void phar_object_init(void) /* {{{ */
  4400. {
  4401. zend_class_entry ce;
  4402. INIT_CLASS_ENTRY(ce, "PharException", class_PharException_methods);
  4403. phar_ce_PharException = zend_register_internal_class_ex(&ce, zend_ce_exception);
  4404. INIT_CLASS_ENTRY(ce, "Phar", class_Phar_methods);
  4405. phar_ce_archive = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator);
  4406. zend_class_implements(phar_ce_archive, 2, zend_ce_countable, zend_ce_arrayaccess);
  4407. INIT_CLASS_ENTRY(ce, "PharData", class_PharData_methods);
  4408. phar_ce_data = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator);
  4409. zend_class_implements(phar_ce_data, 2, zend_ce_countable, zend_ce_arrayaccess);
  4410. INIT_CLASS_ENTRY(ce, "PharFileInfo", class_PharFileInfo_methods);
  4411. phar_ce_entry = zend_register_internal_class_ex(&ce, spl_ce_SplFileInfo);
  4412. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "BZ2", PHAR_ENT_COMPRESSED_BZ2)
  4413. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "GZ", PHAR_ENT_COMPRESSED_GZ)
  4414. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "NONE", PHAR_ENT_COMPRESSED_NONE)
  4415. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHAR", PHAR_FORMAT_PHAR)
  4416. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "TAR", PHAR_FORMAT_TAR)
  4417. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "ZIP", PHAR_FORMAT_ZIP)
  4418. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "COMPRESSED", PHAR_ENT_COMPRESSION_MASK)
  4419. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHP", PHAR_MIME_PHP)
  4420. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "PHPS", PHAR_MIME_PHPS)
  4421. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "MD5", PHAR_SIG_MD5)
  4422. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "OPENSSL", PHAR_SIG_OPENSSL)
  4423. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA1", PHAR_SIG_SHA1)
  4424. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA256", PHAR_SIG_SHA256)
  4425. REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "SHA512", PHAR_SIG_SHA512)
  4426. }
  4427. /* }}} */