PageRenderTime 95ms CodeModel.GetById 25ms RepoModel.GetById 2ms app.codeStats 1ms

/ext/zip/php_zip.c

http://github.com/php/php-src
C | 3380 lines | 2542 code | 515 blank | 323 comment | 537 complexity | 16a439257a40511c3f950f39ac4a4335 MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | http://www.php.net/license/3_01.txt. |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Author: Piere-Alain Joye <pierre@php.net> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #ifdef HAVE_CONFIG_H
  17. #include "config.h"
  18. #endif
  19. #include "php.h"
  20. #include "php_ini.h"
  21. #include "ext/standard/info.h"
  22. #include "ext/standard/file.h"
  23. #include "ext/standard/php_string.h"
  24. #include "ext/pcre/php_pcre.h"
  25. #include "ext/standard/php_filestat.h"
  26. #include "zend_interfaces.h"
  27. #include "php_zip.h"
  28. #include "php_zip_arginfo.h"
  29. /* zip_open is a macro for renaming libzip zipopen, so we need to use PHP_NAMED_FUNCTION */
  30. static PHP_NAMED_FUNCTION(zif_zip_open);
  31. static PHP_NAMED_FUNCTION(zif_zip_read);
  32. static PHP_NAMED_FUNCTION(zif_zip_close);
  33. static PHP_NAMED_FUNCTION(zif_zip_entry_read);
  34. static PHP_NAMED_FUNCTION(zif_zip_entry_filesize);
  35. static PHP_NAMED_FUNCTION(zif_zip_entry_name);
  36. static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize);
  37. static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod);
  38. static PHP_NAMED_FUNCTION(zif_zip_entry_open);
  39. static PHP_NAMED_FUNCTION(zif_zip_entry_close);
  40. #ifdef HAVE_GLOB
  41. #ifndef PHP_WIN32
  42. #include <glob.h>
  43. #else
  44. #include "win32/glob.h"
  45. #endif
  46. #endif
  47. /* {{{ Resource le */
  48. static int le_zip_dir;
  49. #define le_zip_dir_name "Zip Directory"
  50. static int le_zip_entry;
  51. #define le_zip_entry_name "Zip Entry"
  52. /* }}} */
  53. /* {{{ PHP_ZIP_STAT_INDEX(za, index, flags, sb) */
  54. #define PHP_ZIP_STAT_INDEX(za, index, flags, sb) \
  55. if (zip_stat_index(za, index, flags, &sb) != 0) { \
  56. RETURN_FALSE; \
  57. }
  58. /* }}} */
  59. /* {{{ PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) */
  60. #define PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) \
  61. if (path_len < 1) { \
  62. php_error_docref(NULL, E_NOTICE, "Empty string as entry name"); \
  63. RETURN_FALSE; \
  64. } \
  65. if (zip_stat(za, path, flags, &sb) != 0) { \
  66. RETURN_FALSE; \
  67. }
  68. /* }}} */
  69. /* {{{ PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) */
  70. #define PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) \
  71. if (comment_len == 0) { \
  72. /* Passing NULL remove the existing comment */ \
  73. if (zip_file_set_comment(za, index, NULL, 0, 0) < 0) { \
  74. RETURN_FALSE; \
  75. } \
  76. } else if (zip_file_set_comment(za, index, comment, comment_len, 0) < 0) { \
  77. RETURN_FALSE; \
  78. } \
  79. RETURN_TRUE;
  80. /* }}} */
  81. # define add_ascii_assoc_string add_assoc_string
  82. # define add_ascii_assoc_long add_assoc_long
  83. /* Flatten a path by making a relative path (to .)*/
  84. static char * php_zip_make_relative_path(char *path, size_t path_len) /* {{{ */
  85. {
  86. char *path_begin = path;
  87. size_t i;
  88. if (path_len < 1 || path == NULL) {
  89. return NULL;
  90. }
  91. if (IS_SLASH(path[0])) {
  92. return path + 1;
  93. }
  94. i = path_len;
  95. while (1) {
  96. while (i > 0 && !IS_SLASH(path[i])) {
  97. i--;
  98. }
  99. if (!i) {
  100. return path;
  101. }
  102. if (i >= 2 && (path[i -1] == '.' || path[i -1] == ':')) {
  103. /* i is the position of . or :, add 1 for / */
  104. path_begin = path + i + 1;
  105. break;
  106. }
  107. i--;
  108. }
  109. return path_begin;
  110. }
  111. /* }}} */
  112. # define CWD_STATE_ALLOC(l) emalloc(l)
  113. # define CWD_STATE_FREE(s) efree(s)
  114. /* {{{ php_zip_extract_file */
  115. static int php_zip_extract_file(struct zip * za, char *dest, char *file, size_t file_len)
  116. {
  117. php_stream_statbuf ssb;
  118. struct zip_file *zf;
  119. struct zip_stat sb;
  120. char b[8192];
  121. int n, ret;
  122. php_stream *stream;
  123. char *fullpath;
  124. char *file_dirname_fullpath;
  125. char file_dirname[MAXPATHLEN];
  126. size_t dir_len, len;
  127. int is_dir_only = 0;
  128. char *path_cleaned;
  129. size_t path_cleaned_len;
  130. cwd_state new_state;
  131. zend_string *file_basename;
  132. new_state.cwd = CWD_STATE_ALLOC(1);
  133. new_state.cwd[0] = '\0';
  134. new_state.cwd_length = 0;
  135. /* Clean/normlize the path and then transform any path (absolute or relative)
  136. to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt)
  137. */
  138. virtual_file_ex(&new_state, file, NULL, CWD_EXPAND);
  139. path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length);
  140. if(!path_cleaned) {
  141. return 0;
  142. }
  143. path_cleaned_len = strlen(path_cleaned);
  144. if (path_cleaned_len >= MAXPATHLEN || zip_stat(za, file, 0, &sb) != 0) {
  145. return 0;
  146. }
  147. /* it is a directory only, see #40228 */
  148. if (path_cleaned_len > 1 && IS_SLASH(path_cleaned[path_cleaned_len - 1])) {
  149. len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, path_cleaned);
  150. is_dir_only = 1;
  151. } else {
  152. memcpy(file_dirname, path_cleaned, path_cleaned_len);
  153. dir_len = php_dirname(file_dirname, path_cleaned_len);
  154. if (!dir_len || (dir_len == 1 && file_dirname[0] == '.')) {
  155. len = spprintf(&file_dirname_fullpath, 0, "%s", dest);
  156. } else {
  157. len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file_dirname);
  158. }
  159. file_basename = php_basename(path_cleaned, path_cleaned_len, NULL, 0);
  160. if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname_fullpath)) {
  161. efree(file_dirname_fullpath);
  162. zend_string_release_ex(file_basename, 0);
  163. CWD_STATE_FREE(new_state.cwd);
  164. return 0;
  165. }
  166. }
  167. /* let see if the path already exists */
  168. if (php_stream_stat_path_ex(file_dirname_fullpath, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
  169. ret = php_stream_mkdir(file_dirname_fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE|REPORT_ERRORS, NULL);
  170. if (!ret) {
  171. efree(file_dirname_fullpath);
  172. if (!is_dir_only) {
  173. zend_string_release_ex(file_basename, 0);
  174. CWD_STATE_FREE(new_state.cwd);
  175. }
  176. return 0;
  177. }
  178. }
  179. /* it is a standalone directory, job done */
  180. if (is_dir_only) {
  181. efree(file_dirname_fullpath);
  182. CWD_STATE_FREE(new_state.cwd);
  183. return 1;
  184. }
  185. len = spprintf(&fullpath, 0, "%s/%s", file_dirname_fullpath, ZSTR_VAL(file_basename));
  186. if (!len) {
  187. efree(file_dirname_fullpath);
  188. zend_string_release_ex(file_basename, 0);
  189. CWD_STATE_FREE(new_state.cwd);
  190. return 0;
  191. } else if (len > MAXPATHLEN) {
  192. php_error_docref(NULL, E_WARNING, "Full extraction path exceed MAXPATHLEN (%i)", MAXPATHLEN);
  193. efree(file_dirname_fullpath);
  194. zend_string_release_ex(file_basename, 0);
  195. CWD_STATE_FREE(new_state.cwd);
  196. return 0;
  197. }
  198. /* check again the full path, not sure if it
  199. * is required, does a file can have a different
  200. * safemode status as its parent folder?
  201. */
  202. if (ZIP_OPENBASEDIR_CHECKPATH(fullpath)) {
  203. efree(fullpath);
  204. efree(file_dirname_fullpath);
  205. zend_string_release_ex(file_basename, 0);
  206. CWD_STATE_FREE(new_state.cwd);
  207. return 0;
  208. }
  209. zf = zip_fopen(za, file, 0);
  210. if (zf == NULL) {
  211. n = -1;
  212. goto done;
  213. }
  214. stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL);
  215. if (stream == NULL) {
  216. n = -1;
  217. zip_fclose(zf);
  218. goto done;
  219. }
  220. n = 0;
  221. while ((n=zip_fread(zf, b, sizeof(b))) > 0) {
  222. php_stream_write(stream, b, n);
  223. }
  224. if (stream->wrapper->wops->stream_metadata) {
  225. struct utimbuf ut;
  226. ut.modtime = ut.actime = sb.mtime;
  227. stream->wrapper->wops->stream_metadata(stream->wrapper, fullpath, PHP_STREAM_META_TOUCH, &ut, NULL);
  228. }
  229. php_stream_close(stream);
  230. n = zip_fclose(zf);
  231. done:
  232. efree(fullpath);
  233. zend_string_release_ex(file_basename, 0);
  234. efree(file_dirname_fullpath);
  235. CWD_STATE_FREE(new_state.cwd);
  236. if (n<0) {
  237. return 0;
  238. } else {
  239. return 1;
  240. }
  241. }
  242. /* }}} */
  243. static int php_zip_add_file(ze_zip_object *obj, const char *filename, size_t filename_len,
  244. char *entry_name, size_t entry_name_len, /* unused if replace >= 0 */
  245. zip_uint64_t offset_start, zip_uint64_t offset_len,
  246. zend_long replace, /* index to replace, add new file if < 0 */
  247. zip_flags_t flags
  248. ) /* {{{ */
  249. {
  250. struct zip_source *zs;
  251. char resolved_path[MAXPATHLEN];
  252. zval exists_flag;
  253. if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
  254. return -1;
  255. }
  256. if (!expand_filepath(filename, resolved_path)) {
  257. return -1;
  258. }
  259. php_stat(resolved_path, strlen(resolved_path), FS_EXISTS, &exists_flag);
  260. if (Z_TYPE(exists_flag) == IS_FALSE) {
  261. return -1;
  262. }
  263. zs = zip_source_file(obj->za, resolved_path, offset_start, offset_len);
  264. if (!zs) {
  265. return -1;
  266. }
  267. /* Replace */
  268. if (replace >= 0) {
  269. if (zip_file_replace(obj->za, replace, zs, flags) < 0) {
  270. zip_source_free(zs);
  271. return -1;
  272. }
  273. zip_error_clear(obj->za);
  274. return 1;
  275. }
  276. /* Add */
  277. obj->last_id = zip_file_add(obj->za, entry_name, zs, flags);
  278. if (obj->last_id < 0) {
  279. zip_source_free(zs);
  280. return -1;
  281. }
  282. zip_error_clear(obj->za);
  283. return 1;
  284. }
  285. /* }}} */
  286. typedef struct {
  287. zend_long remove_all_path;
  288. char *remove_path;
  289. size_t remove_path_len;
  290. char *add_path;
  291. size_t add_path_len;
  292. zip_flags_t flags;
  293. zip_int32_t comp_method;
  294. zip_uint32_t comp_flags;
  295. #ifdef HAVE_ENCRYPTION
  296. zip_int16_t enc_method;
  297. char *enc_password;
  298. #endif
  299. } zip_options;
  300. static int php_zip_parse_options(zval *options, zip_options *opts)
  301. /* {{{ */
  302. {
  303. zval *option;
  304. /* default values */
  305. memset(opts, 0, sizeof(zip_options));
  306. opts->flags = ZIP_FL_OVERWRITE;
  307. opts->comp_method = -1; /* -1 to not change default */
  308. #ifdef HAVE_ENCRYPTION
  309. opts->enc_method = -1; /* -1 to not change default */
  310. #endif
  311. if ((option = zend_hash_str_find(Z_ARRVAL_P(options), "remove_all_path", sizeof("remove_all_path") - 1)) != NULL) {
  312. opts->remove_all_path = zval_get_long(option);
  313. }
  314. if ((option = zend_hash_str_find(Z_ARRVAL_P(options), "comp_method", sizeof("comp_method") - 1)) != NULL) {
  315. opts->comp_method = zval_get_long(option);
  316. if ((option = zend_hash_str_find(Z_ARRVAL_P(options), "comp_flags", sizeof("comp_flags") - 1)) != NULL) {
  317. opts->comp_flags = zval_get_long(option);
  318. }
  319. }
  320. #ifdef HAVE_ENCRYPTION
  321. if ((option = zend_hash_str_find(Z_ARRVAL_P(options), "enc_method", sizeof("enc_method") - 1)) != NULL) {
  322. opts->enc_method = zval_get_long(option);
  323. if ((option = zend_hash_str_find(Z_ARRVAL_P(options), "enc_password", sizeof("enc_password") - 1)) != NULL) {
  324. if (Z_TYPE_P(option) != IS_STRING) {
  325. php_error_docref(NULL, E_WARNING, "enc_password option expected to be a string");
  326. return -1;
  327. }
  328. opts->enc_password = Z_STRVAL_P(option);
  329. }
  330. }
  331. #endif
  332. if ((option = zend_hash_str_find(Z_ARRVAL_P(options), "remove_path", sizeof("remove_path") - 1)) != NULL) {
  333. if (Z_TYPE_P(option) != IS_STRING) {
  334. php_error_docref(NULL, E_WARNING, "remove_path option expected to be a string");
  335. return -1;
  336. }
  337. if (Z_STRLEN_P(option) < 1) {
  338. php_error_docref(NULL, E_NOTICE, "Empty string given as remove_path option");
  339. return -1;
  340. }
  341. if (Z_STRLEN_P(option) >= MAXPATHLEN) {
  342. php_error_docref(NULL, E_WARNING, "remove_path string is too long (max: %d, %zd given)",
  343. MAXPATHLEN - 1, Z_STRLEN_P(option));
  344. return -1;
  345. }
  346. opts->remove_path_len = Z_STRLEN_P(option);
  347. opts->remove_path = Z_STRVAL_P(option);
  348. }
  349. if ((option = zend_hash_str_find(Z_ARRVAL_P(options), "add_path", sizeof("add_path") - 1)) != NULL) {
  350. if (Z_TYPE_P(option) != IS_STRING) {
  351. php_error_docref(NULL, E_WARNING, "add_path option expected to be a string");
  352. return -1;
  353. }
  354. if (Z_STRLEN_P(option) < 1) {
  355. php_error_docref(NULL, E_NOTICE, "Empty string given as the add_path option");
  356. return -1;
  357. }
  358. if (Z_STRLEN_P(option) >= MAXPATHLEN) {
  359. php_error_docref(NULL, E_WARNING, "add_path string too long (max: %d, %zd given)",
  360. MAXPATHLEN - 1, Z_STRLEN_P(option));
  361. return -1;
  362. }
  363. opts->add_path_len = Z_STRLEN_P(option);
  364. opts->add_path = Z_STRVAL_P(option);
  365. }
  366. if ((option = zend_hash_str_find(Z_ARRVAL_P(options), "flags", sizeof("flags") - 1)) != NULL) {
  367. if (Z_TYPE_P(option) != IS_LONG) {
  368. php_error_docref(NULL, E_WARNING, "flags option expected to be a integer");
  369. return -1;
  370. }
  371. opts->flags = Z_LVAL_P(option);
  372. }
  373. return 1;
  374. }
  375. /* }}} */
  376. /* {{{ REGISTER_ZIP_CLASS_CONST_LONG */
  377. #define REGISTER_ZIP_CLASS_CONST_LONG(const_name, value) \
  378. zend_declare_class_constant_long(zip_class_entry, const_name, sizeof(const_name)-1, (zend_long)value);
  379. /* }}} */
  380. /* {{{ ZIP_FROM_OBJECT */
  381. #define ZIP_FROM_OBJECT(intern, object) \
  382. { \
  383. ze_zip_object *obj = Z_ZIP_P(object); \
  384. intern = obj->za; \
  385. if (!intern) { \
  386. zend_value_error("Invalid or uninitialized Zip object"); \
  387. RETURN_THROWS(); \
  388. } \
  389. }
  390. /* }}} */
  391. /* {{{ RETURN_SB(sb) */
  392. #ifdef HAVE_ENCRYPTION
  393. #define RETURN_SB(sb) \
  394. { \
  395. array_init(return_value); \
  396. add_ascii_assoc_string(return_value, "name", (char *)(sb)->name); \
  397. add_ascii_assoc_long(return_value, "index", (zend_long) (sb)->index); \
  398. add_ascii_assoc_long(return_value, "crc", (zend_long) (sb)->crc); \
  399. add_ascii_assoc_long(return_value, "size", (zend_long) (sb)->size); \
  400. add_ascii_assoc_long(return_value, "mtime", (zend_long) (sb)->mtime); \
  401. add_ascii_assoc_long(return_value, "comp_size", (zend_long) (sb)->comp_size); \
  402. add_ascii_assoc_long(return_value, "comp_method", (zend_long) (sb)->comp_method); \
  403. add_ascii_assoc_long(return_value, "encryption_method", (zend_long) (sb)->encryption_method); \
  404. }
  405. #else
  406. #define RETURN_SB(sb) \
  407. { \
  408. array_init(return_value); \
  409. add_ascii_assoc_string(return_value, "name", (char *)(sb)->name); \
  410. add_ascii_assoc_long(return_value, "index", (zend_long) (sb)->index); \
  411. add_ascii_assoc_long(return_value, "crc", (zend_long) (sb)->crc); \
  412. add_ascii_assoc_long(return_value, "size", (zend_long) (sb)->size); \
  413. add_ascii_assoc_long(return_value, "mtime", (zend_long) (sb)->mtime); \
  414. add_ascii_assoc_long(return_value, "comp_size", (zend_long) (sb)->comp_size); \
  415. add_ascii_assoc_long(return_value, "comp_method", (zend_long) (sb)->comp_method); \
  416. }
  417. #endif
  418. /* }}} */
  419. static zend_long php_zip_status(ze_zip_object *obj) /* {{{ */
  420. {
  421. int zep = obj->err_zip; /* saved err if closed */
  422. if (obj->za) {
  423. #if LIBZIP_VERSION_MAJOR < 1
  424. int syp;
  425. zip_error_get(obj->za, &zep, &syp);
  426. #else
  427. zip_error_t *err;
  428. err = zip_get_error(obj->za);
  429. zep = zip_error_code_zip(err);
  430. zip_error_fini(err);
  431. #endif
  432. }
  433. return zep;
  434. }
  435. /* }}} */
  436. static zend_long php_zip_last_id(ze_zip_object *obj) /* {{{ */
  437. {
  438. return obj->last_id;
  439. }
  440. /* }}} */
  441. static zend_long php_zip_status_sys(ze_zip_object *obj) /* {{{ */
  442. {
  443. int syp = obj->err_sys; /* saved err if closed */
  444. if (obj->za) {
  445. #if LIBZIP_VERSION_MAJOR < 1
  446. int zep;
  447. zip_error_get(obj->za, &zep, &syp);
  448. #else
  449. zip_error_t *err;
  450. err = zip_get_error(obj->za);
  451. syp = zip_error_code_system(err);
  452. zip_error_fini(err);
  453. #endif
  454. }
  455. return syp;
  456. }
  457. /* }}} */
  458. static zend_long php_zip_get_num_files(ze_zip_object *obj) /* {{{ */
  459. {
  460. if (obj->za) {
  461. zip_int64_t num = zip_get_num_entries(obj->za, 0);
  462. return MIN(num, ZEND_LONG_MAX);
  463. }
  464. return 0;
  465. }
  466. /* }}} */
  467. static char * php_zipobj_get_filename(ze_zip_object *obj, int *len) /* {{{ */
  468. {
  469. if (obj && obj->filename) {
  470. *len = strlen(obj->filename);
  471. return obj->filename;
  472. }
  473. return NULL;
  474. }
  475. /* }}} */
  476. static char * php_zipobj_get_zip_comment(ze_zip_object *obj, int *len) /* {{{ */
  477. {
  478. if (obj->za) {
  479. return (char *)zip_get_archive_comment(obj->za, len, 0);
  480. }
  481. return NULL;
  482. }
  483. /* }}} */
  484. #ifdef HAVE_GLOB /* {{{ */
  485. #ifndef GLOB_ONLYDIR
  486. #define GLOB_ONLYDIR (1<<30)
  487. #define GLOB_EMULATE_ONLYDIR
  488. #define GLOB_FLAGMASK (~GLOB_ONLYDIR)
  489. #else
  490. #define GLOB_FLAGMASK (~0)
  491. #endif
  492. #ifndef GLOB_BRACE
  493. # define GLOB_BRACE 0
  494. #endif
  495. #ifndef GLOB_MARK
  496. # define GLOB_MARK 0
  497. #endif
  498. #ifndef GLOB_NOSORT
  499. # define GLOB_NOSORT 0
  500. #endif
  501. #ifndef GLOB_NOCHECK
  502. # define GLOB_NOCHECK 0
  503. #endif
  504. #ifndef GLOB_NOESCAPE
  505. # define GLOB_NOESCAPE 0
  506. #endif
  507. #ifndef GLOB_ERR
  508. # define GLOB_ERR 0
  509. #endif
  510. /* This is used for checking validity of passed flags (passing invalid flags causes segfault in glob()!! */
  511. #define GLOB_AVAILABLE_FLAGS (0 | GLOB_BRACE | GLOB_MARK | GLOB_NOSORT | GLOB_NOCHECK | GLOB_NOESCAPE | GLOB_ERR | GLOB_ONLYDIR)
  512. #endif /* }}} */
  513. int php_zip_glob(char *pattern, int pattern_len, zend_long flags, zval *return_value) /* {{{ */
  514. {
  515. #ifdef HAVE_GLOB
  516. int cwd_skip = 0;
  517. #ifdef ZTS
  518. char cwd[MAXPATHLEN];
  519. char work_pattern[MAXPATHLEN];
  520. char *result;
  521. #endif
  522. glob_t globbuf;
  523. size_t n;
  524. int ret;
  525. if (pattern_len >= MAXPATHLEN) {
  526. php_error_docref(NULL, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
  527. return -1;
  528. }
  529. if ((GLOB_AVAILABLE_FLAGS & flags) != flags) {
  530. php_error_docref(NULL, E_WARNING, "At least one of the passed flags is invalid or not supported on this platform");
  531. return -1;
  532. }
  533. #ifdef ZTS
  534. if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) {
  535. result = VCWD_GETCWD(cwd, MAXPATHLEN);
  536. if (!result) {
  537. cwd[0] = '\0';
  538. }
  539. #ifdef PHP_WIN32
  540. if (IS_SLASH(*pattern)) {
  541. cwd[2] = '\0';
  542. }
  543. #endif
  544. cwd_skip = strlen(cwd)+1;
  545. snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
  546. pattern = work_pattern;
  547. }
  548. #endif
  549. globbuf.gl_offs = 0;
  550. if (0 != (ret = glob(pattern, flags & GLOB_FLAGMASK, NULL, &globbuf))) {
  551. #ifdef GLOB_NOMATCH
  552. if (GLOB_NOMATCH == ret) {
  553. /* Some glob implementation simply return no data if no matches
  554. were found, others return the GLOB_NOMATCH error code.
  555. We don't want to treat GLOB_NOMATCH as an error condition
  556. so that PHP glob() behaves the same on both types of
  557. implementations and so that 'foreach (glob() as ...'
  558. can be used for simple glob() calls without further error
  559. checking.
  560. */
  561. array_init(return_value);
  562. return 0;
  563. }
  564. #endif
  565. return 0;
  566. }
  567. /* now catch the FreeBSD style of "no matches" */
  568. if (!globbuf.gl_pathc || !globbuf.gl_pathv) {
  569. array_init(return_value);
  570. return 0;
  571. }
  572. /* we assume that any glob pattern will match files from one directory only
  573. so checking the dirname of the first match should be sufficient */
  574. if (ZIP_OPENBASEDIR_CHECKPATH(globbuf.gl_pathv[0])) {
  575. return -1;
  576. }
  577. array_init(return_value);
  578. for (n = 0; n < globbuf.gl_pathc; n++) {
  579. /* we need to do this every time since GLOB_ONLYDIR does not guarantee that
  580. * all directories will be filtered. GNU libc documentation states the
  581. * following:
  582. * If the information about the type of the file is easily available
  583. * non-directories will be rejected but no extra work will be done to
  584. * determine the information for each file. I.e., the caller must still be
  585. * able to filter directories out.
  586. */
  587. if (flags & GLOB_ONLYDIR) {
  588. zend_stat_t s;
  589. if (0 != VCWD_STAT(globbuf.gl_pathv[n], &s)) {
  590. continue;
  591. }
  592. if (S_IFDIR != (s.st_mode & S_IFMT)) {
  593. continue;
  594. }
  595. }
  596. add_next_index_string(return_value, globbuf.gl_pathv[n]+cwd_skip);
  597. }
  598. ret = globbuf.gl_pathc;
  599. globfree(&globbuf);
  600. return ret;
  601. #else
  602. zend_throw_error(NULL, "Glob support is not available");
  603. return 0;
  604. #endif /* HAVE_GLOB */
  605. }
  606. /* }}} */
  607. int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_value) /* {{{ */
  608. {
  609. #ifdef ZTS
  610. char cwd[MAXPATHLEN];
  611. char work_path[MAXPATHLEN];
  612. char *result;
  613. #endif
  614. int files_cnt;
  615. zend_string **namelist;
  616. pcre2_match_context *mctx = php_pcre_mctx();
  617. #ifdef ZTS
  618. if (!IS_ABSOLUTE_PATH(path, path_len)) {
  619. result = VCWD_GETCWD(cwd, MAXPATHLEN);
  620. if (!result) {
  621. cwd[0] = '\0';
  622. }
  623. #ifdef PHP_WIN32
  624. if (IS_SLASH(*path)) {
  625. cwd[2] = '\0';
  626. }
  627. #endif
  628. snprintf(work_path, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, path);
  629. path = work_path;
  630. }
  631. #endif
  632. if (ZIP_OPENBASEDIR_CHECKPATH(path)) {
  633. return -1;
  634. }
  635. files_cnt = php_stream_scandir(path, &namelist, NULL, (void *) php_stream_dirent_alphasort);
  636. if (files_cnt > 0) {
  637. pcre2_code *re = NULL;
  638. pcre2_match_data *match_data = NULL;
  639. uint32_t i, capture_count;
  640. int rc;
  641. re = pcre_get_compiled_regex(regexp, &capture_count);
  642. if (!re) {
  643. php_error_docref(NULL, E_WARNING, "Invalid expression");
  644. return -1;
  645. }
  646. array_init(return_value);
  647. /* only the files, directories are ignored */
  648. for (i = 0; i < files_cnt; i++) {
  649. zend_stat_t s;
  650. char fullpath[MAXPATHLEN];
  651. size_t namelist_len = ZSTR_LEN(namelist[i]);
  652. if ((namelist_len == 1 && ZSTR_VAL(namelist[i])[0] == '.') ||
  653. (namelist_len == 2 && ZSTR_VAL(namelist[i])[0] == '.' && ZSTR_VAL(namelist[i])[1] == '.')) {
  654. zend_string_release_ex(namelist[i], 0);
  655. continue;
  656. }
  657. if ((path_len + namelist_len + 1) >= MAXPATHLEN) {
  658. php_error_docref(NULL, E_WARNING, "add_path string too long (max: %u, %zu given)",
  659. MAXPATHLEN - 1, (path_len + namelist_len + 1));
  660. zend_string_release_ex(namelist[i], 0);
  661. break;
  662. }
  663. match_data = php_pcre_create_match_data(capture_count, re);
  664. if (!match_data) {
  665. /* Allocation failed, but can proceed to the next pattern. */
  666. zend_string_release_ex(namelist[i], 0);
  667. continue;
  668. }
  669. rc = pcre2_match(re, (PCRE2_SPTR)ZSTR_VAL(namelist[i]), ZSTR_LEN(namelist[i]), 0, 0, match_data, mctx);
  670. php_pcre_free_match_data(match_data);
  671. /* 0 means that the vector is too small to hold all the captured substring offsets */
  672. if (rc < 0) {
  673. zend_string_release_ex(namelist[i], 0);
  674. continue;
  675. }
  676. snprintf(fullpath, MAXPATHLEN, "%s%c%s", path, DEFAULT_SLASH, ZSTR_VAL(namelist[i]));
  677. if (0 != VCWD_STAT(fullpath, &s)) {
  678. php_error_docref(NULL, E_WARNING, "Cannot read <%s>", fullpath);
  679. zend_string_release_ex(namelist[i], 0);
  680. continue;
  681. }
  682. if (S_IFDIR == (s.st_mode & S_IFMT)) {
  683. zend_string_release_ex(namelist[i], 0);
  684. continue;
  685. }
  686. add_next_index_string(return_value, fullpath);
  687. zend_string_release_ex(namelist[i], 0);
  688. }
  689. efree(namelist);
  690. }
  691. return files_cnt;
  692. }
  693. /* }}} */
  694. /* {{{ zend_function_entry */
  695. static const zend_function_entry zip_functions[] = {
  696. ZEND_RAW_FENTRY("zip_open", zif_zip_open, arginfo_zip_open, 0)
  697. ZEND_RAW_FENTRY("zip_close", zif_zip_close, arginfo_zip_close, 0)
  698. ZEND_RAW_FENTRY("zip_read", zif_zip_read, arginfo_zip_read, 0)
  699. PHP_FE(zip_entry_open, arginfo_zip_entry_open)
  700. PHP_FE(zip_entry_close, arginfo_zip_entry_close)
  701. PHP_FE(zip_entry_read, arginfo_zip_entry_read)
  702. PHP_FE(zip_entry_filesize, arginfo_zip_entry_filesize)
  703. PHP_FE(zip_entry_name, arginfo_zip_entry_name)
  704. PHP_FE(zip_entry_compressedsize, arginfo_zip_entry_compressedsize)
  705. PHP_FE(zip_entry_compressionmethod, arginfo_zip_entry_compressionmethod)
  706. #ifdef PHP_FE_END
  707. PHP_FE_END
  708. #else
  709. {NULL,NULL,NULL}
  710. #endif
  711. };
  712. /* }}} */
  713. /* {{{ ZE2 OO definitions */
  714. static zend_class_entry *zip_class_entry;
  715. static zend_object_handlers zip_object_handlers;
  716. static HashTable zip_prop_handlers;
  717. typedef zend_long (*zip_read_int_t)(ze_zip_object *obj);
  718. typedef char *(*zip_read_const_char_t)(ze_zip_object *obj, int *len);
  719. typedef struct _zip_prop_handler {
  720. zip_read_int_t read_int_func;
  721. zip_read_const_char_t read_const_char_func;
  722. int type;
  723. } zip_prop_handler;
  724. /* }}} */
  725. static void php_zip_register_prop_handler(HashTable *prop_handler, char *name, zip_read_int_t read_int_func, zip_read_const_char_t read_char_func, int rettype) /* {{{ */
  726. {
  727. zip_prop_handler hnd;
  728. zend_string *str;
  729. zval tmp;
  730. hnd.read_const_char_func = read_char_func;
  731. hnd.read_int_func = read_int_func;
  732. hnd.type = rettype;
  733. str = zend_string_init_interned(name, strlen(name), 1);
  734. zend_hash_add_mem(prop_handler, str, &hnd, sizeof(zip_prop_handler));
  735. /* Register for reflection */
  736. ZVAL_NULL(&tmp);
  737. zend_declare_property_ex(zip_class_entry, str, &tmp, ZEND_ACC_PUBLIC, NULL);
  738. zend_string_release_ex(str, 1);
  739. }
  740. /* }}} */
  741. static zval *php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, zval *rv) /* {{{ */
  742. {
  743. const char *retchar = NULL;
  744. zend_long retint = 0;
  745. int len = 0;
  746. if (hnd->read_const_char_func) {
  747. retchar = hnd->read_const_char_func(obj, &len);
  748. } else if (hnd->read_int_func) {
  749. retint = hnd->read_int_func(obj);
  750. }
  751. switch (hnd->type) {
  752. case IS_STRING:
  753. if (retchar) {
  754. ZVAL_STRINGL(rv, (char *) retchar, len);
  755. } else {
  756. ZVAL_EMPTY_STRING(rv);
  757. }
  758. break;
  759. /* case IS_TRUE */
  760. case IS_FALSE:
  761. ZVAL_BOOL(rv, retint);
  762. break;
  763. case IS_LONG:
  764. ZVAL_LONG(rv, retint);
  765. break;
  766. default:
  767. ZVAL_NULL(rv);
  768. }
  769. return rv;
  770. }
  771. /* }}} */
  772. static zval *php_zip_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot) /* {{{ */
  773. {
  774. ze_zip_object *obj;
  775. zval *retval = NULL;
  776. zip_prop_handler *hnd = NULL;
  777. obj = php_zip_fetch_object(object);
  778. if (obj->prop_handler != NULL) {
  779. hnd = zend_hash_find_ptr(obj->prop_handler, name);
  780. }
  781. if (hnd == NULL) {
  782. retval = zend_std_get_property_ptr_ptr(object, name, type, cache_slot);
  783. }
  784. return retval;
  785. }
  786. /* }}} */
  787. static zval *php_zip_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv) /* {{{ */
  788. {
  789. ze_zip_object *obj;
  790. zval *retval = NULL;
  791. zip_prop_handler *hnd = NULL;
  792. obj = php_zip_fetch_object(object);
  793. if (obj->prop_handler != NULL) {
  794. hnd = zend_hash_find_ptr(obj->prop_handler, name);
  795. }
  796. if (hnd != NULL) {
  797. retval = php_zip_property_reader(obj, hnd, rv);
  798. if (retval == NULL) {
  799. retval = &EG(uninitialized_zval);
  800. }
  801. } else {
  802. retval = zend_std_read_property(object, name, type, cache_slot, rv);
  803. }
  804. return retval;
  805. }
  806. /* }}} */
  807. static int php_zip_has_property(zend_object *object, zend_string *name, int type, void **cache_slot) /* {{{ */
  808. {
  809. ze_zip_object *obj;
  810. zip_prop_handler *hnd = NULL;
  811. int retval = 0;
  812. obj = php_zip_fetch_object(object);
  813. if (obj->prop_handler != NULL) {
  814. hnd = zend_hash_find_ptr(obj->prop_handler, name);
  815. }
  816. if (hnd != NULL) {
  817. zval tmp, *prop;
  818. if (type == 2) {
  819. retval = 1;
  820. } else if ((prop = php_zip_property_reader(obj, hnd, &tmp)) != NULL) {
  821. if (type == 1) {
  822. retval = zend_is_true(&tmp);
  823. } else if (type == 0) {
  824. retval = (Z_TYPE(tmp) != IS_NULL);
  825. }
  826. }
  827. zval_ptr_dtor(&tmp);
  828. } else {
  829. retval = zend_std_has_property(object, name, type, cache_slot);
  830. }
  831. return retval;
  832. }
  833. /* }}} */
  834. static HashTable *php_zip_get_gc(zend_object *object, zval **gc_data, int *gc_data_count) /* {{{ */
  835. {
  836. *gc_data = NULL;
  837. *gc_data_count = 0;
  838. return zend_std_get_properties(object);
  839. }
  840. /* }}} */
  841. static HashTable *php_zip_get_properties(zend_object *object)/* {{{ */
  842. {
  843. ze_zip_object *obj;
  844. HashTable *props;
  845. zip_prop_handler *hnd;
  846. zend_string *key;
  847. obj = php_zip_fetch_object(object);
  848. props = zend_std_get_properties(object);
  849. if (obj->prop_handler == NULL) {
  850. return NULL;
  851. }
  852. ZEND_HASH_FOREACH_STR_KEY_PTR(obj->prop_handler, key, hnd) {
  853. zval *ret, val;
  854. ret = php_zip_property_reader(obj, hnd, &val);
  855. if (ret == NULL) {
  856. ret = &EG(uninitialized_zval);
  857. }
  858. zend_hash_update(props, key, ret);
  859. } ZEND_HASH_FOREACH_END();
  860. return props;
  861. }
  862. /* }}} */
  863. #ifdef HAVE_PROGRESS_CALLBACK
  864. static void _php_zip_progress_callback_free(void *ptr)
  865. {
  866. ze_zip_object *obj = ptr;
  867. if (!Z_ISUNDEF(obj->progress_callback)) {
  868. zval_ptr_dtor(&obj->progress_callback);
  869. ZVAL_UNDEF(&obj->progress_callback);
  870. }
  871. }
  872. #endif
  873. #ifdef HAVE_CANCEL_CALLBACK
  874. static void _php_zip_cancel_callback_free(void *ptr)
  875. {
  876. ze_zip_object *obj = ptr;
  877. if (!Z_ISUNDEF(obj->cancel_callback)) {
  878. zval_ptr_dtor(&obj->cancel_callback);
  879. ZVAL_UNDEF(&obj->cancel_callback);
  880. }
  881. }
  882. #endif
  883. static void php_zip_object_free_storage(zend_object *object) /* {{{ */
  884. {
  885. ze_zip_object * intern = php_zip_fetch_object(object);
  886. int i;
  887. if (!intern) {
  888. return;
  889. }
  890. if (intern->za) {
  891. if (zip_close(intern->za) != 0) {
  892. php_error_docref(NULL, E_WARNING, "Cannot destroy the zip context: %s", zip_strerror(intern->za));
  893. zip_discard(intern->za);
  894. }
  895. }
  896. if (intern->buffers_cnt>0) {
  897. for (i=0; i<intern->buffers_cnt; i++) {
  898. efree(intern->buffers[i]);
  899. }
  900. efree(intern->buffers);
  901. }
  902. #ifdef HAVE_PROGRESS_CALLBACK
  903. /* if not properly called by libzip */
  904. _php_zip_progress_callback_free(intern);
  905. #endif
  906. #ifdef HAVE_CANCEL_CALLBACK
  907. /* if not properly called by libzip */
  908. _php_zip_cancel_callback_free(intern);
  909. #endif
  910. intern->za = NULL;
  911. zend_object_std_dtor(&intern->zo);
  912. if (intern->filename) {
  913. efree(intern->filename);
  914. }
  915. }
  916. /* }}} */
  917. static zend_object *php_zip_object_new(zend_class_entry *class_type) /* {{{ */
  918. {
  919. ze_zip_object *intern;
  920. intern = zend_object_alloc(sizeof(ze_zip_object), class_type);
  921. intern->prop_handler = &zip_prop_handlers;
  922. zend_object_std_init(&intern->zo, class_type);
  923. object_properties_init(&intern->zo, class_type);
  924. intern->zo.handlers = &zip_object_handlers;
  925. intern->last_id = -1;
  926. return &intern->zo;
  927. }
  928. /* }}} */
  929. /* {{{ Resource dtors */
  930. /* {{{ php_zip_free_dir */
  931. static void php_zip_free_dir(zend_resource *rsrc)
  932. {
  933. zip_rsrc * zip_int = (zip_rsrc *) rsrc->ptr;
  934. if (zip_int) {
  935. if (zip_int->za) {
  936. if (zip_close(zip_int->za) != 0) {
  937. php_error_docref(NULL, E_WARNING, "Cannot destroy the zip context");
  938. }
  939. zip_int->za = NULL;
  940. }
  941. efree(rsrc->ptr);
  942. rsrc->ptr = NULL;
  943. }
  944. }
  945. /* }}} */
  946. /* {{{ php_zip_free_entry */
  947. static void php_zip_free_entry(zend_resource *rsrc)
  948. {
  949. zip_read_rsrc *zr_rsrc = (zip_read_rsrc *) rsrc->ptr;
  950. if (zr_rsrc) {
  951. if (zr_rsrc->zf) {
  952. zip_fclose(zr_rsrc->zf);
  953. zr_rsrc->zf = NULL;
  954. }
  955. efree(zr_rsrc);
  956. rsrc->ptr = NULL;
  957. }
  958. }
  959. /* }}} */
  960. /* }}}*/
  961. /* reset macro */
  962. /* {{{ function prototypes */
  963. static PHP_MINIT_FUNCTION(zip);
  964. static PHP_MSHUTDOWN_FUNCTION(zip);
  965. static PHP_MINFO_FUNCTION(zip);
  966. /* }}} */
  967. /* {{{ zip_module_entry
  968. */
  969. zend_module_entry zip_module_entry = {
  970. STANDARD_MODULE_HEADER,
  971. "zip",
  972. zip_functions,
  973. PHP_MINIT(zip),
  974. PHP_MSHUTDOWN(zip),
  975. NULL,
  976. NULL,
  977. PHP_MINFO(zip),
  978. PHP_ZIP_VERSION,
  979. STANDARD_MODULE_PROPERTIES
  980. };
  981. /* }}} */
  982. #ifdef COMPILE_DL_ZIP
  983. ZEND_GET_MODULE(zip)
  984. #endif
  985. /* set macro */
  986. /* {{{ proto resource zip_open(string filename)
  987. Create new zip using source uri for output */
  988. static PHP_NAMED_FUNCTION(zif_zip_open)
  989. {
  990. char resolved_path[MAXPATHLEN + 1];
  991. zip_rsrc *rsrc_int;
  992. int err = 0;
  993. zend_string *filename;
  994. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &filename) == FAILURE) {
  995. RETURN_THROWS();
  996. }
  997. if (ZSTR_LEN(filename) == 0) {
  998. php_error_docref(NULL, E_WARNING, "Empty string as source");
  999. RETURN_FALSE;
  1000. }
  1001. if (ZIP_OPENBASEDIR_CHECKPATH(ZSTR_VAL(filename))) {
  1002. RETURN_FALSE;
  1003. }
  1004. if(!expand_filepath(ZSTR_VAL(filename), resolved_path)) {
  1005. RETURN_FALSE;
  1006. }
  1007. rsrc_int = (zip_rsrc *)emalloc(sizeof(zip_rsrc));
  1008. rsrc_int->za = zip_open(resolved_path, 0, &err);
  1009. if (rsrc_int->za == NULL) {
  1010. efree(rsrc_int);
  1011. RETURN_LONG((zend_long)err);
  1012. }
  1013. rsrc_int->index_current = 0;
  1014. rsrc_int->num_files = zip_get_num_entries(rsrc_int->za, 0);
  1015. RETURN_RES(zend_register_resource(rsrc_int, le_zip_dir));
  1016. }
  1017. /* }}} */
  1018. /* {{{ proto void zip_close(resource zip)
  1019. Close a Zip archive */
  1020. static PHP_NAMED_FUNCTION(zif_zip_close)
  1021. {
  1022. zval * zip;
  1023. zip_rsrc *z_rsrc = NULL;
  1024. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip) == FAILURE) {
  1025. RETURN_THROWS();
  1026. }
  1027. if ((z_rsrc = (zip_rsrc *)zend_fetch_resource(Z_RES_P(zip), le_zip_dir_name, le_zip_dir)) == NULL) {
  1028. RETURN_THROWS();
  1029. }
  1030. /* really close the zip will break BC :-D */
  1031. zend_list_close(Z_RES_P(zip));
  1032. }
  1033. /* }}} */
  1034. /* {{{ proto resource zip_read(resource zip)
  1035. Returns the next file in the archive */
  1036. static PHP_NAMED_FUNCTION(zif_zip_read)
  1037. {
  1038. zval *zip_dp;
  1039. zip_read_rsrc *zr_rsrc;
  1040. int ret;
  1041. zip_rsrc *rsrc_int;
  1042. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip_dp) == FAILURE) {
  1043. RETURN_THROWS();
  1044. }
  1045. if ((rsrc_int = (zip_rsrc *)zend_fetch_resource(Z_RES_P(zip_dp), le_zip_dir_name, le_zip_dir)) == NULL) {
  1046. RETURN_THROWS();
  1047. }
  1048. if (rsrc_int && rsrc_int->za) {
  1049. if (rsrc_int->index_current >= rsrc_int->num_files) {
  1050. RETURN_FALSE;
  1051. }
  1052. zr_rsrc = emalloc(sizeof(zip_read_rsrc));
  1053. ret = zip_stat_index(rsrc_int->za, rsrc_int->index_current, 0, &zr_rsrc->sb);
  1054. if (ret != 0) {
  1055. efree(zr_rsrc);
  1056. RETURN_FALSE;
  1057. }
  1058. zr_rsrc->zf = zip_fopen_index(rsrc_int->za, rsrc_int->index_current, 0);
  1059. if (zr_rsrc->zf) {
  1060. rsrc_int->index_current++;
  1061. RETURN_RES(zend_register_resource(zr_rsrc, le_zip_entry));
  1062. } else {
  1063. efree(zr_rsrc);
  1064. RETURN_FALSE;
  1065. }
  1066. } else {
  1067. RETURN_FALSE;
  1068. }
  1069. }
  1070. /* }}} */
  1071. /* {{{ proto bool zip_entry_open(resource zip_dp, resource zip_entry [, string mode])
  1072. Open a Zip File, pointed by the resource entry */
  1073. /* Dummy function to follow the old API */
  1074. static PHP_NAMED_FUNCTION(zif_zip_entry_open)
  1075. {
  1076. zval * zip;
  1077. zval * zip_entry;
  1078. char *mode = NULL;
  1079. size_t mode_len = 0;
  1080. zip_read_rsrc * zr_rsrc;
  1081. zip_rsrc *z_rsrc;
  1082. if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr|s", &zip, &zip_entry, &mode, &mode_len) == FAILURE) {
  1083. RETURN_THROWS();
  1084. }
  1085. if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) {
  1086. RETURN_THROWS();
  1087. }
  1088. if ((z_rsrc = (zip_rsrc *)zend_fetch_resource(Z_RES_P(zip), le_zip_dir_name, le_zip_dir)) == NULL) {
  1089. RETURN_THROWS();
  1090. }
  1091. if (zr_rsrc->zf != NULL) {
  1092. RETURN_TRUE;
  1093. } else {
  1094. RETURN_FALSE;
  1095. }
  1096. }
  1097. /* }}} */
  1098. /* {{{ proto bool zip_entry_close(resource zip_ent)
  1099. Close a zip entry */
  1100. static PHP_NAMED_FUNCTION(zif_zip_entry_close)
  1101. {
  1102. zval * zip_entry;
  1103. zip_read_rsrc * zr_rsrc;
  1104. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip_entry) == FAILURE) {
  1105. RETURN_THROWS();
  1106. }
  1107. if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) {
  1108. RETURN_THROWS();
  1109. }
  1110. RETURN_BOOL(SUCCESS == zend_list_close(Z_RES_P(zip_entry)));
  1111. }
  1112. /* }}} */
  1113. /* {{{ proto mixed zip_entry_read(resource zip_entry [, int len])
  1114. Read from an open directory entry */
  1115. static PHP_NAMED_FUNCTION(zif_zip_entry_read)
  1116. {
  1117. zval * zip_entry;
  1118. zend_long len = 0;
  1119. zip_read_rsrc * zr_rsrc;
  1120. zend_string *buffer;
  1121. int n = 0;
  1122. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &zip_entry, &len) == FAILURE) {
  1123. RETURN_THROWS();
  1124. }
  1125. if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) {
  1126. RETURN_THROWS();
  1127. }
  1128. if (len <= 0) {
  1129. len = 1024;
  1130. }
  1131. if (zr_rsrc->zf) {
  1132. buffer = zend_string_safe_alloc(1, len, 0, 0);
  1133. n = zip_fread(zr_rsrc->zf, ZSTR_VAL(buffer), ZSTR_LEN(buffer));
  1134. if (n > 0) {
  1135. ZSTR_VAL(buffer)[n] = '\0';
  1136. ZSTR_LEN(buffer) = n;
  1137. RETURN_NEW_STR(buffer);
  1138. } else {
  1139. zend_string_efree(buffer);
  1140. RETURN_EMPTY_STRING();
  1141. }
  1142. } else {
  1143. RETURN_FALSE;
  1144. }
  1145. }
  1146. /* }}} */
  1147. static void php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS, int opt) /* {{{ */
  1148. {
  1149. zval * zip_entry;
  1150. zip_read_rsrc * zr_rsrc;
  1151. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip_entry) == FAILURE) {
  1152. RETURN_THROWS();
  1153. }
  1154. if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) {
  1155. RETURN_THROWS();
  1156. }
  1157. if (!zr_rsrc->zf) {
  1158. RETURN_FALSE;
  1159. }
  1160. switch (opt) {
  1161. case 0:
  1162. RETURN_STRING((char *)zr_rsrc->sb.name);
  1163. case 1:
  1164. RETURN_LONG((zend_long) (zr_rsrc->sb.comp_size));
  1165. case 2:
  1166. RETURN_LONG((zend_long) (zr_rsrc->sb.size));
  1167. case 3:
  1168. switch (zr_rsrc->sb.comp_method) {
  1169. case 0:
  1170. RETURN_STRING("stored");
  1171. case 1:
  1172. RETURN_STRING("shrunk");
  1173. case 2:
  1174. case 3:
  1175. case 4:
  1176. case 5:
  1177. RETURN_STRING("reduced");
  1178. case 6:
  1179. RETURN_STRING("imploded");
  1180. case 7:
  1181. RETURN_STRING("tokenized");
  1182. break;
  1183. case 8:
  1184. RETURN_STRING("deflated");
  1185. case 9:
  1186. RETURN_STRING("deflatedX");
  1187. break;
  1188. case 10:
  1189. RETURN_STRING("implodedX");
  1190. default:
  1191. RETURN_FALSE;
  1192. }
  1193. }
  1194. }
  1195. /* }}} */
  1196. /* {{{ proto string zip_entry_name(resource zip_entry)
  1197. Return the name given a ZZip entry */
  1198. static PHP_NAMED_FUNCTION(zif_zip_entry_name)
  1199. {
  1200. php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  1201. }
  1202. /* }}} */
  1203. /* {{{ proto int zip_entry_compressedsize(resource zip_entry)
  1204. Return the compressed size of a ZZip entry */
  1205. static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize)
  1206. {
  1207. php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  1208. }
  1209. /* }}} */
  1210. /* {{{ proto int zip_entry_filesize(resource zip_entry)
  1211. Return the actual filesize of a ZZip entry */
  1212. static PHP_NAMED_FUNCTION(zif_zip_entry_filesize)
  1213. {
  1214. php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
  1215. }
  1216. /* }}} */
  1217. /* {{{ proto string zip_entry_compressionmethod(resource zip_entry)
  1218. Return a string containing the compression method used on a particular entry */
  1219. static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod)
  1220. {
  1221. php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
  1222. }
  1223. /* }}} */
  1224. /* {{{ proto mixed ZipArchive::open(string source [, int flags])
  1225. Create new zip using source uri for output, return TRUE on success or the error code */
  1226. static ZIPARCHIVE_METHOD(open)
  1227. {
  1228. struct zip *intern;
  1229. int err = 0;
  1230. zend_long flags = 0;
  1231. char *resolved_path;
  1232. zend_string *filename;
  1233. zval *self = ZEND_THIS;
  1234. ze_zip_object *ze_obj;
  1235. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &filename, &flags) == FAILURE) {
  1236. RETURN_THROWS();
  1237. }
  1238. /* We do not use ZIP_FROM_OBJECT, zip init function here */
  1239. ze_obj = Z_ZIP_P(self);
  1240. if (ZSTR_LEN(filename) == 0) {
  1241. php_error_docref(NULL, E_WARNING, "Empty string as source");
  1242. RETURN_FALSE;
  1243. }
  1244. if (ZIP_OPENBASEDIR_CHECKPATH(ZSTR_VAL(filename))) {
  1245. RETURN_FALSE;
  1246. }
  1247. if (!(resolved_path = expand_filepath(ZSTR_VAL(filename), NULL))) {
  1248. RETURN_FALSE;
  1249. }
  1250. if (ze_obj->za) {
  1251. /* we already have an opened zip, free it */
  1252. if (zip_close(ze_obj->za) != 0) {
  1253. php_error_docref(NULL, E_WARNING, "Empty string as source");
  1254. efree(resolved_path);
  1255. RETURN_FALSE;
  1256. }
  1257. ze_obj->za = NULL;
  1258. }
  1259. if (ze_obj->filename) {
  1260. efree(ze_obj->filename);
  1261. ze_obj->filename = NULL;
  1262. }
  1263. /* reduce BC break introduce in libzip 1.6.0
  1264. "Do not accept empty files as valid zip archives any longer" */
  1265. /* open for write without option to empty the archive */
  1266. if ((flags & (ZIP_TRUNCATE | ZIP_RDONLY)) == 0) {
  1267. zend_stat_t st;
  1268. /* exists and is empty */
  1269. if (VCWD_STAT(resolved_path, &st) == 0 && st.st_size == 0) {
  1270. php_error_docref(NULL, E_DEPRECATED, "Using empty file as ZipArchive is deprecated");
  1271. flags |= ZIP_TRUNCATE;
  1272. }
  1273. }
  1274. intern = zip_open(resolved_path, flags, &err);
  1275. if (!intern || err) {
  1276. efree(resolved_path);
  1277. RETURN_LONG((zend_long)err);
  1278. }
  1279. ze_obj->filename = resolved_path;
  1280. ze_obj->filename_len = strlen(resolved_path);
  1281. ze_obj->za = intern;
  1282. RETURN_TRUE;
  1283. }
  1284. /* }}} */
  1285. /* {{{ proto resource ZipArchive::setPassword(string password)
  1286. Set the password for the active archive */
  1287. static ZIPARCHIVE_METHOD(setPassword)
  1288. {
  1289. struct zip *intern;
  1290. zval *self = ZEND_THIS;
  1291. char *password;
  1292. size_t password_len;
  1293. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &password, &password_len) == FAILURE) {
  1294. RETURN_THROWS();
  1295. }
  1296. ZIP_FROM_OBJECT(intern, self);
  1297. if (password_len < 1) {
  1298. RETURN_FALSE;
  1299. }
  1300. int res = zip_set_default_password(intern, (const char *)password);
  1301. if (res == 0) {
  1302. RETURN_TRUE;
  1303. } else {
  1304. RETURN_FALSE;
  1305. }
  1306. }
  1307. /* }}} */
  1308. /* {{{ proto bool ZipArchive::close()
  1309. close the zip archive */
  1310. static ZIPARCHIVE_METHOD(close)
  1311. {
  1312. struct zip *intern;
  1313. zval *self = ZEND_THIS;
  1314. ze_zip_object *ze_obj;
  1315. int err;
  1316. if (zend_parse_parameters_none() == FAILURE) {
  1317. RETURN_THROWS();
  1318. }
  1319. ZIP_FROM_OBJECT(intern, self);
  1320. ze_obj = Z_ZIP_P(self);
  1321. err = zip_close(intern);
  1322. if (err) {
  1323. php_error_docref(NULL, E_WARNING, "%s", zip_strerror(intern));
  1324. /* Save error for property reader */
  1325. #if LIBZIP_VERSION_MAJOR < 1
  1326. zip_error_get(intern, &ze_obj->err_zip, &ze_obj->err_sys);
  1327. #else
  1328. {
  1329. zip_error_t *ziperr;
  1330. ziperr = zip_get_error(intern);
  1331. ze_obj->err_zip = zip_error_code_zip(ziperr);
  1332. ze_obj->err_sys = zip_error_code_system(ziperr);
  1333. zip_error_fini(ziperr);
  1334. }
  1335. #endif
  1336. zip_discard(intern);
  1337. } else {
  1338. ze_obj->err_zip = 0;
  1339. ze_obj->err_sys = 0;
  1340. }
  1341. efree(ze_obj->filename);
  1342. ze_obj->filename = NULL;
  1343. ze_obj->filename_len = 0;
  1344. ze_obj->za = NULL;
  1345. if (!err) {
  1346. RETURN_TRUE;
  1347. } else {
  1348. RETURN_FALSE;
  1349. }
  1350. }
  1351. /* }}} */
  1352. /* {{{ proto bool ZipArchive::count()
  1353. close the zip archive */
  1354. static ZIPARCHIVE_METHOD(count)
  1355. {
  1356. struct zip *intern;
  1357. zval *self = ZEND_THIS;
  1358. zip_int64_t num;
  1359. if (zend_parse_parameters_none() == FAILURE) {
  1360. RETURN_THROWS();
  1361. }
  1362. ZIP_FROM_OBJECT(intern, self);
  1363. num = zip_get_num_entries(intern, 0);
  1364. RETVAL_LONG(MIN(num, ZEND_LONG_MAX));
  1365. }
  1366. /* }}} */
  1367. /* {{{ proto string ZipArchive::getStatusString()
  1368. * Returns the status error message, system and/or zip messages */
  1369. static ZIPARCHIVE_METHOD(getStatusString)
  1370. {
  1371. zval *self = ZEND_THIS;
  1372. #if LIBZIP_VERSION_MAJOR < 1
  1373. int zep, syp, len;
  1374. char error_string[128];
  1375. #endif
  1376. ze_zip_object *ze_obj;
  1377. if (zend_parse_parameters_none() == FAILURE) {
  1378. RETURN_THROWS();
  1379. }
  1380. ze_obj = Z_ZIP_P(self); /* not ZIP_FROM_OBJECT as we can use saved error after close */
  1381. #if LIBZIP_VERSION_MAJOR < 1
  1382. if (ze_obj->za) {
  1383. zip_error_get(ze_obj->za, &zep, &syp);
  1384. len = zip_error_to_str(error_string, 128, zep, syp);
  1385. } else {
  1386. len = zip_error_to_str(error_string, 128, ze_obj->err_zip, ze_obj->err_sys);
  1387. }
  1388. RETVAL_STRINGL(error_string, len);
  1389. #else
  1390. if (ze_obj->za) {
  1391. zip_error_t *err;
  1392. err = zip_get_error(ze_obj->za);
  1393. RETVAL_STRING(zip_error_strerror(err));
  1394. zip_error_fini(err);
  1395. } else {
  1396. zip_error_t err;
  1397. zip_error_init(&err);
  1398. zip_error_set(&err, ze_obj->err_zip, ze_obj->err_sys);
  1399. RETVAL_STRING(zip_error_strerror(&err));
  1400. zip_error_fini(&err);
  1401. }
  1402. #endif
  1403. }
  1404. /* }}} */
  1405. /* {{{ proto bool ZipArchive::addEmptyDir(string dirname [, bool flags = 0])
  1406. Returns the index of the entry named filename in the archive */
  1407. static ZIPARCHIVE_METHOD(addEmptyDir)
  1408. {
  1409. struct zip *intern;
  1410. zval *self = ZEND_THIS;
  1411. char *dirname;
  1412. size_t dirname_len;
  1413. char *s;
  1414. zend_long flags = 0;
  1415. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l",
  1416. &dirname, &dirname_len, &flags) == FAILURE) {
  1417. RETURN_THROWS();
  1418. }
  1419. ZIP_FROM_OBJECT(intern, self);
  1420. if (dirname_len<1) {
  1421. RETURN_FALSE;
  1422. }
  1423. if (dirname[dirname_len-1] != '/') {
  1424. s=(char *)safe_emalloc(dirname_len, 1, 2);
  1425. strcpy(s, dirname);
  1426. s[dirname_len] = '/';
  1427. s[dirname_len+1] = '\0';
  1428. } else {
  1429. s = dirname;
  1430. }
  1431. if ((Z_ZIP_P(self)->last_id = zip_dir_add(intern, (const char *)s, flags)) == -1) {
  1432. RETVAL_FALSE;
  1433. } else {
  1434. zip_error_clear(intern);
  1435. RETVAL_TRUE;
  1436. }
  1437. if (s != dirname) {
  1438. efree(s);
  1439. }
  1440. }
  1441. /* }}} */
  1442. static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
  1443. {
  1444. zval *self = ZEND_THIS;
  1445. char *path = ".";
  1446. size_t path_len = 1;
  1447. zend_long glob_flags = 0;
  1448. zval *options = NULL;
  1449. zip_options opts;
  1450. int found;
  1451. zend_string *pattern;
  1452. /* 1 == glob, 2 == pcre */
  1453. if (type == 1) {
  1454. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|la",
  1455. &pattern, &glob_flags, &options) == FAILURE) {
  1456. RETURN_THROWS();
  1457. }
  1458. } else {
  1459. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|sa",
  1460. &pattern, &path, &path_len, &options) == FAILURE) {
  1461. RETURN_THROWS();
  1462. }
  1463. }
  1464. if (ZSTR_LEN(pattern) == 0) {
  1465. php_error_docref(NULL, E_NOTICE, "Empty string as pattern");
  1466. RETURN_FALSE;
  1467. }
  1468. if (options && zend_hash_num_elements(Z_ARRVAL_P(options)) > 0 && (php_zip_parse_options(options, &opts) < 0)) {
  1469. RETURN_FALSE;
  1470. }
  1471. if (type == 1) {
  1472. found = php_zip_glob(ZSTR_VAL(pattern), ZSTR_LEN(pattern), glob_flags, return_value);
  1473. } else {
  1474. found = php_zip_pcre(pattern, path, path_len, return_value);
  1475. }
  1476. if (found > 0) {
  1477. int i;
  1478. zval *zval_file;
  1479. ze_zip_object *ze_obj;
  1480. ze_obj = Z_ZIP_P(self);
  1481. for (i = 0; i < found; i++) {
  1482. char *file_stripped, *entry_name;
  1483. size_t entry_name_len, file_stripped_len;
  1484. char entry_name_buf[MAXPATHLEN];
  1485. zend_string *basename = NULL;
  1486. if ((zval_file = zend_hash_index_find(Z_ARRVAL_P(return_value), i)) != NULL) {
  1487. if (opts.remove_all_path) {
  1488. basename = php_basename(Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), NULL, 0);
  1489. file_stripped = ZSTR_VAL(basename);
  1490. file_stripped_len = ZSTR_LEN(basename);
  1491. } else if (opts.remove_path && strstr(Z_STRVAL_P(zval_file), opts.remove_path) != NULL) {
  1492. if (IS_SLASH(Z_STRVAL_P(zval_file)[opts.remove_path_len])) {
  1493. file_stripped = Z_STRVAL_P(zval_file) + opts.remove_path_len + 1;
  1494. file_stripped_len = Z_STRLEN_P(zval_file) - opts.remove_path_len - 1;
  1495. } else {
  1496. file_stripped = Z_STRVAL_P(zval_file) + opts.remove_path_len;
  1497. file_stripped_len = Z_STRLEN_P(zval_file) - opts.remove_path_len;
  1498. }
  1499. } else {
  1500. file_stripped = Z_STRVAL_P(zval_file);
  1501. file_stripped_len = Z_STRLEN_P(zval_file);
  1502. }
  1503. if (opts.add_path) {
  1504. if ((opts.add_path_len + file_stripped_len) > MAXPATHLEN) {
  1505. php_error_docref(NULL, E_WARNING, "Entry name too long (max: %d, %zd given)",
  1506. MAXPATHLEN - 1, (opts.add_path_len + file_stripped_len));
  1507. zend_array_destroy(Z_ARR_P(return_value));
  1508. RETURN_FALSE;
  1509. }
  1510. snprintf(entry_name_buf, MAXPATHLEN, "%s%s", opts.add_path, file_stripped);
  1511. } else {
  1512. snprintf(entry_name_buf, MAXPATHLEN, "%s", file_stripped);
  1513. }
  1514. entry_name = entry_name_buf;
  1515. entry_name_len = strlen(entry_name);
  1516. if (basename) {
  1517. zend_string_release_ex(basename, 0);
  1518. basename = NULL;
  1519. }
  1520. if (php_zip_add_file(ze_obj, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file),
  1521. entry_name, entry_name_len, 0, 0, -1, opts.flags) < 0) {
  1522. zend_array_destroy(Z_ARR_P(return_value));
  1523. RETURN_FALSE;
  1524. }
  1525. if (opts.comp_method >= 0) {
  1526. if (zip_set_file_compression(ze_obj->za, ze_obj->last_id, opts.comp_method, opts.comp_flags)) {
  1527. zend_array_destroy(Z_ARR_P(return_value));
  1528. RETURN_FALSE;
  1529. }
  1530. }
  1531. #ifdef HAVE_ENCRYPTION
  1532. if (opts.enc_method >= 0) {
  1533. if (zip_file_set_encryption(ze_obj->za, ze_obj->last_id, opts.enc_method, opts.enc_password)) {
  1534. zend_array_destroy(Z_ARR_P(return_value));
  1535. RETURN_FALSE;
  1536. }
  1537. }
  1538. #endif
  1539. }
  1540. }
  1541. }
  1542. }
  1543. /* }}} */
  1544. /* {{{ proto bool ZipArchive::addGlob(string pattern[,int flags [, array options]])
  1545. Add files matching the glob pattern. See php's glob for the pattern syntax. */
  1546. static ZIPARCHIVE_METHOD(addGlob)
  1547. {
  1548. php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  1549. }
  1550. /* }}} */
  1551. /* {{{ proto bool ZipArchive::addPattern(string pattern[, string path [, array options]])
  1552. Add files matching the pcre pattern. See php's pcre for the pattern syntax. */
  1553. static ZIPARCHIVE_METHOD(addPattern)
  1554. {
  1555. php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
  1556. }
  1557. /* }}} */
  1558. /* {{{ proto bool ZipArchive::addFile(string filepath[, string entryname[, int start [, int length [, int flags = FL_OVERWRITE]]]])
  1559. Add a file in a Zip archive using its path and the name to use. */
  1560. static ZIPARCHIVE_METHOD(addFile)
  1561. {
  1562. zval *self = ZEND_THIS;
  1563. char *entry_name = NULL;
  1564. size_t entry_name_len = 0;
  1565. zend_long offset_start = 0, offset_len = 0;
  1566. zend_string *filename;
  1567. zend_long flags = ZIP_FL_OVERWRITE;
  1568. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|slll",
  1569. &filename, &entry_name, &entry_name_len, &offset_start, &offset_len, &flags) == FAILURE) {
  1570. RETURN_THROWS();
  1571. }
  1572. if (ZSTR_LEN(filename) == 0) {
  1573. php_error_docref(NULL, E_NOTICE, "Empty string as filename");
  1574. RETURN_FALSE;
  1575. }
  1576. if (entry_name_len == 0) {
  1577. entry_name = ZSTR_VAL(filename);
  1578. entry_name_len = ZSTR_LEN(filename);
  1579. }
  1580. if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename),
  1581. entry_name, entry_name_len, offset_start, offset_len, -1, flags) < 0) {
  1582. RETURN_FALSE;
  1583. } else {
  1584. RETURN_TRUE;
  1585. }
  1586. }
  1587. /* }}} */
  1588. /* {{{ proto bool ZipArchive::replaceFile(string filepath, int index[, int start [, int length [, int flags = 0]]])
  1589. Add a file in a Zip archive using its path and the name to use. */
  1590. static ZIPARCHIVE_METHOD(replaceFile)
  1591. {
  1592. zval *self = ZEND_THIS;
  1593. zend_long index;
  1594. zend_long offset_start = 0, offset_len = 0;
  1595. zend_string *filename;
  1596. zend_long flags = 0;
  1597. if (zend_parse_parameters(ZEND_NUM_ARGS(), "Pl|lll",
  1598. &filename, &index, &offset_start, &offset_len, &flags) == FAILURE) {
  1599. RETURN_THROWS();
  1600. }
  1601. if (ZSTR_LEN(filename) == 0) {
  1602. php_error_docref(NULL, E_NOTICE, "Empty string as filename");
  1603. RETURN_FALSE;
  1604. }
  1605. if (index < 0) {
  1606. php_error_docref(NULL, E_NOTICE, "Invalid negative index");
  1607. RETURN_FALSE;
  1608. }
  1609. if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename),
  1610. NULL, 0, offset_start, offset_len, index, flags) < 0) {
  1611. RETURN_FALSE;
  1612. } else {
  1613. RETURN_TRUE;
  1614. }
  1615. }
  1616. /* }}} */
  1617. /* {{{ proto bool ZipArchive::addFromString(string name, string content [, int flags = FL_OVERWRITE])
  1618. Add a file using content and the entry name */
  1619. static ZIPARCHIVE_METHOD(addFromString)
  1620. {
  1621. struct zip *intern;
  1622. zval *self = ZEND_THIS;
  1623. zend_string *buffer;
  1624. char *name;
  1625. size_t name_len;
  1626. ze_zip_object *ze_obj;
  1627. struct zip_source *zs;
  1628. int pos = 0;
  1629. zend_long flags = ZIP_FL_OVERWRITE;
  1630. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS|l",
  1631. &name, &name_len, &buffer, &flags) == FAILURE) {
  1632. RETURN_THROWS();
  1633. }
  1634. ZIP_FROM_OBJECT(intern, self);
  1635. ze_obj = Z_ZIP_P(self);
  1636. if (ze_obj->buffers_cnt) {
  1637. ze_obj->buffers = (char **)safe_erealloc(ze_obj->buffers, sizeof(char *), (ze_obj->buffers_cnt+1), 0);
  1638. pos = ze_obj->buffers_cnt++;
  1639. } else {
  1640. ze_obj->buffers = (char **)emalloc(sizeof(char *));
  1641. ze_obj->buffers_cnt++;
  1642. pos = 0;
  1643. }
  1644. ze_obj->buffers[pos] = (char *)safe_emalloc(ZSTR_LEN(buffer), 1, 1);
  1645. memcpy(ze_obj->buffers[pos], ZSTR_VAL(buffer), ZSTR_LEN(buffer) + 1);
  1646. zs = zip_source_buffer(intern, ze_obj->buffers[pos], ZSTR_LEN(buffer), 0);
  1647. if (zs == NULL) {
  1648. RETURN_FALSE;
  1649. }
  1650. ze_obj->last_id = zip_file_add(intern, name, zs, flags);
  1651. if (ze_obj->last_id == -1) {
  1652. zip_source_free(zs);
  1653. RETURN_FALSE;
  1654. } else {
  1655. zip_error_clear(intern);
  1656. RETURN_TRUE;
  1657. }
  1658. }
  1659. /* }}} */
  1660. /* {{{ proto array ZipArchive::statName(string filename[, int flags])
  1661. Returns the information about a the zip entry filename */
  1662. static ZIPARCHIVE_METHOD(statName)
  1663. {
  1664. struct zip *intern;
  1665. zval *self = ZEND_THIS;
  1666. zend_long flags = 0;
  1667. struct zip_stat sb;
  1668. zend_string *name;
  1669. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &name, &flags) == FAILURE) {
  1670. RETURN_THROWS();
  1671. }
  1672. ZIP_FROM_OBJECT(intern, self);
  1673. PHP_ZIP_STAT_PATH(intern, ZSTR_VAL(name), ZSTR_LEN(name), flags, sb);
  1674. RETURN_SB(&sb);
  1675. }
  1676. /* }}} */
  1677. /* {{{ proto resource ZipArchive::statIndex(int index[, int flags])
  1678. Returns the zip entry information using its index */
  1679. static ZIPARCHIVE_METHOD(statIndex)
  1680. {
  1681. struct zip *intern;
  1682. zval *self = ZEND_THIS;
  1683. zend_long index, flags = 0;
  1684. struct zip_stat sb;
  1685. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l",
  1686. &index, &flags) == FAILURE) {
  1687. RETURN_THROWS();
  1688. }
  1689. ZIP_FROM_OBJECT(intern, self);
  1690. if (zip_stat_index(intern, index, flags, &sb) != 0) {
  1691. RETURN_FALSE;
  1692. }
  1693. RETURN_SB(&sb);
  1694. }
  1695. /* }}} */
  1696. /* {{{ proto int ZipArchive::locateName(string filename[, int flags])
  1697. Returns the index of the entry named filename in the archive */
  1698. static ZIPARCHIVE_METHOD(locateName)
  1699. {
  1700. struct zip *intern;
  1701. zval *self = ZEND_THIS;
  1702. zend_long flags = 0;
  1703. zend_long idx = -1;
  1704. zend_string *name;
  1705. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &name, &flags) == FAILURE) {
  1706. RETURN_THROWS();
  1707. }
  1708. ZIP_FROM_OBJECT(intern, self);
  1709. if (ZSTR_LEN(name) < 1) {
  1710. RETURN_FALSE;
  1711. }
  1712. idx = (zend_long)zip_name_locate(intern, (const char *)ZSTR_VAL(name), flags);
  1713. if (idx >= 0) {
  1714. RETURN_LONG(idx);
  1715. } else {
  1716. RETURN_FALSE;
  1717. }
  1718. }
  1719. /* }}} */
  1720. /* {{{ proto string ZipArchive::getNameIndex(int index [, int flags])
  1721. Returns the name of the file at position index */
  1722. static ZIPARCHIVE_METHOD(getNameIndex)
  1723. {
  1724. struct zip *intern;
  1725. zval *self = ZEND_THIS;
  1726. const char *name;
  1727. zend_long flags = 0, index = 0;
  1728. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l",
  1729. &index, &flags) == FAILURE) {
  1730. RETURN_THROWS();
  1731. }
  1732. ZIP_FROM_OBJECT(intern, self);
  1733. name = zip_get_name(intern, (int) index, flags);
  1734. if (name) {
  1735. RETVAL_STRING((char *)name);
  1736. } else {
  1737. RETURN_FALSE;
  1738. }
  1739. }
  1740. /* }}} */
  1741. /* {{{ proto bool ZipArchive::setArchiveComment(string comment)
  1742. Set or remove (NULL/'') the comment of the archive */
  1743. static ZIPARCHIVE_METHOD(setArchiveComment)
  1744. {
  1745. struct zip *intern;
  1746. zval *self = ZEND_THIS;
  1747. size_t comment_len;
  1748. char * comment;
  1749. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &comment, &comment_len) == FAILURE) {
  1750. RETURN_THROWS();
  1751. }
  1752. ZIP_FROM_OBJECT(intern, self);
  1753. if (comment_len > 0xffff) {
  1754. php_error_docref(NULL, E_WARNING, "Comment must not exceed 65535 bytes");
  1755. RETURN_FALSE;
  1756. }
  1757. if (zip_set_archive_comment(intern, (const char *)comment, comment_len)) {
  1758. RETURN_FALSE;
  1759. } else {
  1760. RETURN_TRUE;
  1761. }
  1762. }
  1763. /* }}} */
  1764. /* {{{ proto string ZipArchive::getArchiveComment([int flags])
  1765. Returns the comment of an entry using its index */
  1766. static ZIPARCHIVE_METHOD(getArchiveComment)
  1767. {
  1768. struct zip *intern;
  1769. zval *self = ZEND_THIS;
  1770. zend_long flags = 0;
  1771. const char * comment;
  1772. int comment_len = 0;
  1773. if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &flags) == FAILURE) {
  1774. RETURN_THROWS();
  1775. }
  1776. ZIP_FROM_OBJECT(intern, self);
  1777. comment = zip_get_archive_comment(intern, &comment_len, (int)flags);
  1778. if(comment==NULL) {
  1779. RETURN_FALSE;
  1780. }
  1781. RETURN_STRINGL((char *)comment, (zend_long)comment_len);
  1782. }
  1783. /* }}} */
  1784. /* {{{ proto bool ZipArchive::setCommentName(string name, string comment)
  1785. Set or remove (NULL/'') the comment of an entry using its Name */
  1786. static ZIPARCHIVE_METHOD(setCommentName)
  1787. {
  1788. struct zip *intern;
  1789. zval *self = ZEND_THIS;
  1790. size_t comment_len, name_len;
  1791. char * comment, *name;
  1792. int idx;
  1793. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
  1794. &name, &name_len, &comment, &comment_len) == FAILURE) {
  1795. RETURN_THROWS();
  1796. }
  1797. if (name_len < 1) {
  1798. php_error_docref(NULL, E_NOTICE, "Empty string as entry name");
  1799. }
  1800. ZIP_FROM_OBJECT(intern, self);
  1801. if (comment_len > 0xffff) {
  1802. php_error_docref(NULL, E_WARNING, "Comment must not exceed 65535 bytes");
  1803. RETURN_FALSE;
  1804. }
  1805. idx = zip_name_locate(intern, name, 0);
  1806. if (idx < 0) {
  1807. RETURN_FALSE;
  1808. }
  1809. PHP_ZIP_SET_FILE_COMMENT(intern, idx, comment, comment_len);
  1810. }
  1811. /* }}} */
  1812. /* {{{ proto bool ZipArchive::setCommentIndex(int index, string comment)
  1813. Set or remove (NULL/'') the comment of an entry using its index */
  1814. static ZIPARCHIVE_METHOD(setCommentIndex)
  1815. {
  1816. struct zip *intern;
  1817. zval *self = ZEND_THIS;
  1818. zend_long index;
  1819. size_t comment_len;
  1820. char * comment;
  1821. struct zip_stat sb;
  1822. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls",
  1823. &index, &comment, &comment_len) == FAILURE) {
  1824. RETURN_THROWS();
  1825. }
  1826. ZIP_FROM_OBJECT(intern, self);
  1827. if (comment_len > 0xffff) {
  1828. php_error_docref(NULL, E_WARNING, "Comment must not exceed 65535 bytes");
  1829. RETURN_FALSE;
  1830. }
  1831. PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
  1832. PHP_ZIP_SET_FILE_COMMENT(intern, index, comment, comment_len);
  1833. }
  1834. /* }}} */
  1835. /* those constants/functions are only available in libzip since 0.11.2 */
  1836. #ifdef ZIP_OPSYS_DEFAULT
  1837. /* {{{ proto bool ZipArchive::setExternalAttributesName(string name, int opsys, int attr [, int flags])
  1838. Set external attributes for file in zip, using its name */
  1839. static ZIPARCHIVE_METHOD(setExternalAttributesName)
  1840. {
  1841. struct zip *intern;
  1842. zval *self = ZEND_THIS;
  1843. size_t name_len;
  1844. char *name;
  1845. zend_long flags=0, opsys, attr;
  1846. zip_int64_t idx;
  1847. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sll|l",
  1848. &name, &name_len, &opsys, &attr, &flags) == FAILURE) {
  1849. RETURN_THROWS();
  1850. }
  1851. ZIP_FROM_OBJECT(intern, self);
  1852. if (name_len < 1) {
  1853. php_error_docref(NULL, E_NOTICE, "Empty string as entry name");
  1854. }
  1855. idx = zip_name_locate(intern, name, 0);
  1856. if (idx < 0) {
  1857. RETURN_FALSE;
  1858. }
  1859. if (zip_file_set_external_attributes(intern, idx, (zip_flags_t)flags,
  1860. (zip_uint8_t)(opsys&0xff), (zip_uint32_t)attr) < 0) {
  1861. RETURN_FALSE;
  1862. }
  1863. RETURN_TRUE;
  1864. }
  1865. /* }}} */
  1866. /* {{{ proto bool ZipArchive::setExternalAttributesIndex(int index, int opsys, int attr [, int flags])
  1867. Set external attributes for file in zip, using its index */
  1868. static ZIPARCHIVE_METHOD(setExternalAttributesIndex)
  1869. {
  1870. struct zip *intern;
  1871. zval *self = ZEND_THIS;
  1872. zend_long index, flags=0, opsys, attr;
  1873. struct zip_stat sb;
  1874. if (zend_parse_parameters(ZEND_NUM_ARGS(), "lll|l",
  1875. &index, &opsys, &attr, &flags) == FAILURE) {
  1876. RETURN_THROWS();
  1877. }
  1878. ZIP_FROM_OBJECT(intern, self);
  1879. PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
  1880. if (zip_file_set_external_attributes(intern, (zip_uint64_t)index,
  1881. (zip_flags_t)flags, (zip_uint8_t)(opsys&0xff), (zip_uint32_t)attr) < 0) {
  1882. RETURN_FALSE;
  1883. }
  1884. RETURN_TRUE;
  1885. }
  1886. /* }}} */
  1887. /* {{{ proto bool ZipArchive::getExternalAttributesName(string name, int &opsys, int &attr [, int flags])
  1888. Get external attributes for file in zip, using its name */
  1889. static ZIPARCHIVE_METHOD(getExternalAttributesName)
  1890. {
  1891. struct zip *intern;
  1892. zval *self = ZEND_THIS, *z_opsys, *z_attr;
  1893. size_t name_len;
  1894. char *name;
  1895. zend_long flags=0;
  1896. zip_uint8_t opsys;
  1897. zip_uint32_t attr;
  1898. zip_int64_t idx;
  1899. if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l",
  1900. &name, &name_len, &z_opsys, &z_attr, &flags) == FAILURE) {
  1901. RETURN_THROWS();
  1902. }
  1903. ZIP_FROM_OBJECT(intern, self);
  1904. if (name_len < 1) {
  1905. php_error_docref(NULL, E_NOTICE, "Empty string as entry name");
  1906. }
  1907. idx = zip_name_locate(intern, name, 0);
  1908. if (idx < 0) {
  1909. RETURN_FALSE;
  1910. }
  1911. if (zip_file_get_external_attributes(intern, idx,
  1912. (zip_flags_t)flags, &opsys, &attr) < 0) {
  1913. RETURN_FALSE;
  1914. }
  1915. ZEND_TRY_ASSIGN_REF_LONG(z_opsys, opsys);
  1916. ZEND_TRY_ASSIGN_REF_LONG(z_attr, attr);
  1917. RETURN_TRUE;
  1918. }
  1919. /* }}} */
  1920. /* {{{ proto bool ZipArchive::getExternalAttributesIndex(int index, int &opsys, int &attr [, int flags])
  1921. Get external attributes for file in zip, using its index */
  1922. static ZIPARCHIVE_METHOD(getExternalAttributesIndex)
  1923. {
  1924. struct zip *intern;
  1925. zval *self = ZEND_THIS, *z_opsys, *z_attr;
  1926. zend_long index, flags=0;
  1927. zip_uint8_t opsys;
  1928. zip_uint32_t attr;
  1929. struct zip_stat sb;
  1930. if (zend_parse_parameters(ZEND_NUM_ARGS(), "lzz|l",
  1931. &index, &z_opsys, &z_attr, &flags) == FAILURE) {
  1932. RETURN_THROWS();
  1933. }
  1934. ZIP_FROM_OBJECT(intern, self);
  1935. PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
  1936. if (zip_file_get_external_attributes(intern, (zip_uint64_t)index,
  1937. (zip_flags_t)flags, &opsys, &attr) < 0) {
  1938. RETURN_FALSE;
  1939. }
  1940. ZEND_TRY_ASSIGN_REF_LONG(z_opsys, opsys);
  1941. ZEND_TRY_ASSIGN_REF_LONG(z_attr, attr);
  1942. RETURN_TRUE;
  1943. }
  1944. /* }}} */
  1945. #endif /* ifdef ZIP_OPSYS_DEFAULT */
  1946. #ifdef HAVE_ENCRYPTION
  1947. /* {{{ proto bool ZipArchive::setEncryptionName(string name, int method, [string password])
  1948. Set encryption method for file in zip, using its name */
  1949. static ZIPARCHIVE_METHOD(setEncryptionName)
  1950. {
  1951. struct zip *intern;
  1952. zval *self = ZEND_THIS;
  1953. zend_long method;
  1954. zip_int64_t idx;
  1955. char *name, *password = NULL;
  1956. size_t name_len, password_len;
  1957. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|s!",
  1958. &name, &name_len, &method, &password, &password_len) == FAILURE) {
  1959. RETURN_THROWS();
  1960. }
  1961. ZIP_FROM_OBJECT(intern, self);
  1962. if (name_len < 1) {
  1963. php_error_docref(NULL, E_NOTICE, "Empty string as entry name");
  1964. }
  1965. idx = zip_name_locate(intern, name, 0);
  1966. if (idx < 0) {
  1967. RETURN_FALSE;
  1968. }
  1969. if (zip_file_set_encryption(intern, idx, (zip_uint16_t)method, password)) {
  1970. RETURN_FALSE;
  1971. }
  1972. RETURN_TRUE;
  1973. }
  1974. /* }}} */
  1975. /* {{{ proto bool ZipArchive::setEncryptionIndex(int index, int method, [string password])
  1976. Set encryption method for file in zip, using its index */
  1977. static ZIPARCHIVE_METHOD(setEncryptionIndex)
  1978. {
  1979. struct zip *intern;
  1980. zval *self = ZEND_THIS;
  1981. zend_long index, method;
  1982. char *password = NULL;
  1983. size_t password_len;
  1984. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|s!",
  1985. &index, &method, &password, &password_len) == FAILURE) {
  1986. RETURN_THROWS();
  1987. }
  1988. ZIP_FROM_OBJECT(intern, self);
  1989. if (zip_file_set_encryption(intern, index, (zip_uint16_t)method, password)) {
  1990. RETURN_FALSE;
  1991. }
  1992. RETURN_TRUE;
  1993. }
  1994. /* }}} */
  1995. #endif
  1996. /* {{{ proto string ZipArchive::getCommentName(string name[, int flags])
  1997. Returns the comment of an entry using its name */
  1998. static ZIPARCHIVE_METHOD(getCommentName)
  1999. {
  2000. struct zip *intern;
  2001. zval *self = ZEND_THIS;
  2002. size_t name_len;
  2003. int idx;
  2004. zend_long flags = 0;
  2005. zip_uint32_t comment_len = 0;
  2006. const char * comment;
  2007. char *name;
  2008. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l",
  2009. &name, &name_len, &flags) == FAILURE) {
  2010. RETURN_THROWS();
  2011. }
  2012. ZIP_FROM_OBJECT(intern, self);
  2013. if (name_len < 1) {
  2014. php_error_docref(NULL, E_NOTICE, "Empty string as entry name");
  2015. RETURN_FALSE;
  2016. }
  2017. idx = zip_name_locate(intern, name, 0);
  2018. if (idx < 0) {
  2019. RETURN_FALSE;
  2020. }
  2021. comment = zip_file_get_comment(intern, idx, &comment_len, (zip_flags_t)flags);
  2022. RETURN_STRINGL((char *)comment, comment_len);
  2023. }
  2024. /* }}} */
  2025. /* {{{ proto string ZipArchive::getCommentIndex(int index[, int flags])
  2026. Returns the comment of an entry using its index */
  2027. static ZIPARCHIVE_METHOD(getCommentIndex)
  2028. {
  2029. struct zip *intern;
  2030. zval *self = ZEND_THIS;
  2031. zend_long index, flags = 0;
  2032. const char * comment;
  2033. zip_uint32_t comment_len = 0;
  2034. struct zip_stat sb;
  2035. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l",
  2036. &index, &flags) == FAILURE) {
  2037. RETURN_THROWS();
  2038. }
  2039. ZIP_FROM_OBJECT(intern, self);
  2040. PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
  2041. comment = zip_file_get_comment(intern, index, &comment_len, (zip_flags_t)flags);
  2042. RETURN_STRINGL((char *)comment, comment_len);
  2043. }
  2044. /* }}} */
  2045. /* {{{ proto bool ZipArchive::setCompressionName(string name, int comp_method[, int comp_flags])
  2046. Set the compression of a file in zip, using its name */
  2047. static ZIPARCHIVE_METHOD(setCompressionName)
  2048. {
  2049. struct zip *intern;
  2050. zval *this = ZEND_THIS;
  2051. size_t name_len;
  2052. char *name;
  2053. zip_int64_t idx;
  2054. zend_long comp_method, comp_flags = 0;
  2055. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|l",
  2056. &name, &name_len, &comp_method, &comp_flags) == FAILURE) {
  2057. RETURN_THROWS();
  2058. }
  2059. ZIP_FROM_OBJECT(intern, this);
  2060. if (name_len < 1) {
  2061. php_error_docref(NULL, E_NOTICE, "Empty string as entry name");
  2062. }
  2063. idx = zip_name_locate(intern, name, 0);
  2064. if (idx < 0) {
  2065. RETURN_FALSE;
  2066. }
  2067. if (zip_set_file_compression(intern, (zip_uint64_t)idx,
  2068. (zip_int32_t)comp_method, (zip_uint32_t)comp_flags) != 0) {
  2069. RETURN_FALSE;
  2070. }
  2071. RETURN_TRUE;
  2072. }
  2073. /* }}} */
  2074. /* {{{ proto bool ZipArchive::setCompressionIndex(int index, int comp_method[, int comp_flags])
  2075. Set the compression of a file in zip, using its index */
  2076. static ZIPARCHIVE_METHOD(setCompressionIndex)
  2077. {
  2078. struct zip *intern;
  2079. zval *this = ZEND_THIS;
  2080. zend_long index;
  2081. zend_long comp_method, comp_flags = 0;
  2082. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|l",
  2083. &index, &comp_method, &comp_flags) == FAILURE) {
  2084. RETURN_THROWS();
  2085. }
  2086. ZIP_FROM_OBJECT(intern, this);
  2087. if (zip_set_file_compression(intern, (zip_uint64_t)index,
  2088. (zip_int32_t)comp_method, (zip_uint32_t)comp_flags) != 0) {
  2089. RETURN_FALSE;
  2090. }
  2091. RETURN_TRUE;
  2092. }
  2093. /* }}} */
  2094. #ifdef HAVE_SET_MTIME
  2095. /* {{{ proto bool ZipArchive::setMtimeName(string name, int timestamp[, int flags])
  2096. Set the modification time of a file in zip, using its name */
  2097. static ZIPARCHIVE_METHOD(setMtimeName)
  2098. {
  2099. struct zip *intern;
  2100. zval *this = ZEND_THIS;
  2101. size_t name_len;
  2102. char *name;
  2103. zip_int64_t idx;
  2104. zend_long mtime, flags = 0;
  2105. if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|l",
  2106. &name, &name_len, &mtime, &flags) == FAILURE) {
  2107. return;
  2108. }
  2109. ZIP_FROM_OBJECT(intern, this);
  2110. if (name_len < 1) {
  2111. php_error_docref(NULL, E_NOTICE, "Empty string as entry name");
  2112. }
  2113. idx = zip_name_locate(intern, name, 0);
  2114. if (idx < 0) {
  2115. RETURN_FALSE;
  2116. }
  2117. if (zip_file_set_mtime(intern, (zip_uint64_t)idx,
  2118. (time_t)mtime, (zip_uint32_t)flags) != 0) {
  2119. RETURN_FALSE;
  2120. }
  2121. RETURN_TRUE;
  2122. }
  2123. /* }}} */
  2124. /* {{{ proto bool ZipArchive::setMtimeIndex(int index, int timestamp[, int flags])
  2125. Set the modification time of a file in zip, using its index */
  2126. static ZIPARCHIVE_METHOD(setMtimeIndex)
  2127. {
  2128. struct zip *intern;
  2129. zval *this = ZEND_THIS;
  2130. zend_long index;
  2131. zend_long mtime, flags = 0;
  2132. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|l",
  2133. &index, &mtime, &flags) == FAILURE) {
  2134. return;
  2135. }
  2136. ZIP_FROM_OBJECT(intern, this);
  2137. if (zip_file_set_mtime(intern, (zip_uint64_t)index,
  2138. (time_t)mtime, (zip_uint32_t)flags) != 0) {
  2139. RETURN_FALSE;
  2140. }
  2141. RETURN_TRUE;
  2142. }
  2143. /* }}} */
  2144. #endif
  2145. /* {{{ proto bool ZipArchive::deleteIndex(int index)
  2146. Delete a file using its index */
  2147. static ZIPARCHIVE_METHOD(deleteIndex)
  2148. {
  2149. struct zip *intern;
  2150. zval *self = ZEND_THIS;
  2151. zend_long index;
  2152. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
  2153. RETURN_THROWS();
  2154. }
  2155. ZIP_FROM_OBJECT(intern, self);
  2156. if (index < 0) {
  2157. RETURN_FALSE;
  2158. }
  2159. if (zip_delete(intern, index) < 0) {
  2160. RETURN_FALSE;
  2161. }
  2162. RETURN_TRUE;
  2163. }
  2164. /* }}} */
  2165. /* {{{ proto bool ZipArchive::deleteName(string name)
  2166. Delete a file using its index */
  2167. static ZIPARCHIVE_METHOD(deleteName)
  2168. {
  2169. struct zip *intern;
  2170. zval *self = ZEND_THIS;
  2171. size_t name_len;
  2172. char *name;
  2173. struct zip_stat sb;
  2174. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
  2175. RETURN_THROWS();
  2176. }
  2177. ZIP_FROM_OBJECT(intern, self);
  2178. if (name_len < 1) {
  2179. RETURN_FALSE;
  2180. }
  2181. PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
  2182. if (zip_delete(intern, sb.index)) {
  2183. RETURN_FALSE;
  2184. }
  2185. RETURN_TRUE;
  2186. }
  2187. /* }}} */
  2188. /* {{{ proto bool ZipArchive::renameIndex(int index, string new_name)
  2189. Rename an entry selected by its index to new_name */
  2190. static ZIPARCHIVE_METHOD(renameIndex)
  2191. {
  2192. struct zip *intern;
  2193. zval *self = ZEND_THIS;
  2194. char *new_name;
  2195. size_t new_name_len;
  2196. zend_long index;
  2197. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &index, &new_name, &new_name_len) == FAILURE) {
  2198. RETURN_THROWS();
  2199. }
  2200. if (index < 0) {
  2201. RETURN_FALSE;
  2202. }
  2203. ZIP_FROM_OBJECT(intern, self);
  2204. if (new_name_len < 1) {
  2205. php_error_docref(NULL, E_NOTICE, "Empty string as new entry name");
  2206. RETURN_FALSE;
  2207. }
  2208. if (zip_file_rename(intern, index, (const char *)new_name, 0) != 0) {
  2209. RETURN_FALSE;
  2210. }
  2211. RETURN_TRUE;
  2212. }
  2213. /* }}} */
  2214. /* {{{ proto bool ZipArchive::renameName(string name, string new_name)
  2215. Rename an entry selected by its name to new_name */
  2216. static ZIPARCHIVE_METHOD(renameName)
  2217. {
  2218. struct zip *intern;
  2219. zval *self = ZEND_THIS;
  2220. struct zip_stat sb;
  2221. char *name, *new_name;
  2222. size_t name_len, new_name_len;
  2223. if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &name, &name_len, &new_name, &new_name_len) == FAILURE) {
  2224. RETURN_THROWS();
  2225. }
  2226. ZIP_FROM_OBJECT(intern, self);
  2227. if (new_name_len < 1) {
  2228. php_error_docref(NULL, E_NOTICE, "Empty string as new entry name");
  2229. RETURN_FALSE;
  2230. }
  2231. PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
  2232. if (zip_file_rename(intern, sb.index, (const char *)new_name, 0)) {
  2233. RETURN_FALSE;
  2234. }
  2235. RETURN_TRUE;
  2236. }
  2237. /* }}} */
  2238. /* {{{ proto bool ZipArchive::unchangeIndex(int index)
  2239. Changes to the file at position index are reverted */
  2240. static ZIPARCHIVE_METHOD(unchangeIndex)
  2241. {
  2242. struct zip *intern;
  2243. zval *self = ZEND_THIS;
  2244. zend_long index;
  2245. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
  2246. RETURN_THROWS();
  2247. }
  2248. ZIP_FROM_OBJECT(intern, self);
  2249. if (index < 0) {
  2250. RETURN_FALSE;
  2251. }
  2252. if (zip_unchange(intern, index) != 0) {
  2253. RETURN_FALSE;
  2254. } else {
  2255. RETURN_TRUE;
  2256. }
  2257. }
  2258. /* }}} */
  2259. /* {{{ proto bool ZipArchive::unchangeName(string name)
  2260. Changes to the file named 'name' are reverted */
  2261. static ZIPARCHIVE_METHOD(unchangeName)
  2262. {
  2263. struct zip *intern;
  2264. zval *self = ZEND_THIS;
  2265. struct zip_stat sb;
  2266. char *name;
  2267. size_t name_len;
  2268. if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
  2269. RETURN_THROWS();
  2270. }
  2271. ZIP_FROM_OBJECT(intern, self);
  2272. if (name_len < 1) {
  2273. RETURN_FALSE;
  2274. }
  2275. PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
  2276. if (zip_unchange(intern, sb.index) != 0) {
  2277. RETURN_FALSE;
  2278. } else {
  2279. RETURN_TRUE;
  2280. }
  2281. }
  2282. /* }}} */
  2283. /* {{{ proto bool ZipArchive::unchangeAll()
  2284. All changes to files and global information in archive are reverted */
  2285. static ZIPARCHIVE_METHOD(unchangeAll)
  2286. {
  2287. struct zip *intern;
  2288. zval *self = ZEND_THIS;
  2289. if (zend_parse_parameters_none() == FAILURE) {
  2290. RETURN_THROWS();
  2291. }
  2292. ZIP_FROM_OBJECT(intern, self);
  2293. if (zip_unchange_all(intern) != 0) {
  2294. RETURN_FALSE;
  2295. } else {
  2296. RETURN_TRUE;
  2297. }
  2298. }
  2299. /* }}} */
  2300. /* {{{ proto bool ZipArchive::unchangeArchive()
  2301. Revert all global changes to the archive archive. For now, this only reverts archive comment changes. */
  2302. static ZIPARCHIVE_METHOD(unchangeArchive)
  2303. {
  2304. struct zip *intern;
  2305. zval *self = ZEND_THIS;
  2306. if (zend_parse_parameters_none() == FAILURE) {
  2307. RETURN_THROWS();
  2308. }
  2309. ZIP_FROM_OBJECT(intern, self);
  2310. if (zip_unchange_archive(intern) != 0) {
  2311. RETURN_FALSE;
  2312. } else {
  2313. RETURN_TRUE;
  2314. }
  2315. }
  2316. /* }}} */
  2317. /* {{{ proto bool ZipArchive::extractTo(string pathto[, mixed files])
  2318. Extract one or more file from a zip archive */
  2319. /* TODO:
  2320. * - allow index or array of indices
  2321. * - replace path
  2322. * - patterns
  2323. */
  2324. static ZIPARCHIVE_METHOD(extractTo)
  2325. {
  2326. struct zip *intern;
  2327. zval *self = ZEND_THIS;
  2328. zval *zval_files = NULL;
  2329. zval *zval_file = NULL;
  2330. php_stream_statbuf ssb;
  2331. char *pathto;
  2332. size_t pathto_len;
  2333. int ret;
  2334. if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|z", &pathto, &pathto_len, &zval_files) == FAILURE) {
  2335. RETURN_THROWS();
  2336. }
  2337. ZIP_FROM_OBJECT(intern, self);
  2338. if (pathto_len < 1) {
  2339. RETURN_FALSE;
  2340. }
  2341. if (php_stream_stat_path_ex(pathto, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
  2342. ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
  2343. if (!ret) {
  2344. RETURN_FALSE;
  2345. }
  2346. }
  2347. if (zval_files && Z_TYPE_P(zval_files) != IS_NULL) {
  2348. uint32_t nelems, i;
  2349. switch (Z_TYPE_P(zval_files)) {
  2350. case IS_STRING:
  2351. if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_files), Z_STRLEN_P(zval_files))) {
  2352. RETURN_FALSE;
  2353. }
  2354. break;
  2355. case IS_ARRAY:
  2356. nelems = zend_hash_num_elements(Z_ARRVAL_P(zval_files));
  2357. if (nelems == 0 ) {
  2358. RETURN_FALSE;
  2359. }
  2360. for (i = 0; i < nelems; i++) {
  2361. if ((zval_file = zend_hash_index_find(Z_ARRVAL_P(zval_files), i)) != NULL) {
  2362. switch (Z_TYPE_P(zval_file)) {
  2363. case IS_LONG:
  2364. break;
  2365. case IS_STRING:
  2366. if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file))) {
  2367. RETURN_FALSE;
  2368. }
  2369. break;
  2370. }
  2371. }
  2372. }
  2373. break;
  2374. default:
  2375. zend_argument_type_error(2, "must be of type array|string|null, %s given", zend_zval_type_name(zval_files));
  2376. RETURN_THROWS();
  2377. }
  2378. } else {
  2379. /* Extract all files */
  2380. zip_int64_t i, filecount = zip_get_num_entries(intern, 0);
  2381. if (filecount == -1) {
  2382. php_error_docref(NULL, E_WARNING, "Illegal archive");
  2383. RETURN_FALSE;
  2384. }
  2385. for (i = 0; i < filecount; i++) {
  2386. char *file = (char*)zip_get_name(intern, i, ZIP_FL_UNCHANGED);
  2387. if (!file || !php_zip_extract_file(intern, pathto, file, strlen(file))) {
  2388. RETURN_FALSE;
  2389. }
  2390. }
  2391. }
  2392. RETURN_TRUE;
  2393. }
  2394. /* }}} */
  2395. static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
  2396. {
  2397. struct zip *intern;
  2398. zval *self = ZEND_THIS;
  2399. struct zip_stat sb;
  2400. struct zip_file *zf;
  2401. zend_long index = -1;
  2402. zend_long flags = 0;
  2403. zend_long len = 0;
  2404. zend_string *filename;
  2405. zend_string *buffer;
  2406. int n = 0;
  2407. if (type == 1) {
  2408. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|ll", &filename, &len, &flags) == FAILURE) {
  2409. RETURN_THROWS();
  2410. }
  2411. ZIP_FROM_OBJECT(intern, self);
  2412. PHP_ZIP_STAT_PATH(intern, ZSTR_VAL(filename), ZSTR_LEN(filename), flags, sb);
  2413. } else {
  2414. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|ll", &index, &len, &flags) == FAILURE) {
  2415. RETURN_THROWS();
  2416. }
  2417. ZIP_FROM_OBJECT(intern, self);
  2418. PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
  2419. }
  2420. if (sb.size < 1) {
  2421. RETURN_EMPTY_STRING();
  2422. }
  2423. if (len < 1) {
  2424. len = sb.size;
  2425. }
  2426. if (index >= 0) {
  2427. zf = zip_fopen_index(intern, index, flags);
  2428. } else {
  2429. zf = zip_fopen(intern, ZSTR_VAL(filename), flags);
  2430. }
  2431. if (zf == NULL) {
  2432. RETURN_FALSE;
  2433. }
  2434. buffer = zend_string_safe_alloc(1, len, 0, 0);
  2435. n = zip_fread(zf, ZSTR_VAL(buffer), ZSTR_LEN(buffer));
  2436. if (n < 1) {
  2437. zend_string_efree(buffer);
  2438. RETURN_EMPTY_STRING();
  2439. }
  2440. zip_fclose(zf);
  2441. ZSTR_VAL(buffer)[n] = '\0';
  2442. ZSTR_LEN(buffer) = n;
  2443. RETURN_NEW_STR(buffer);
  2444. }
  2445. /* }}} */
  2446. /* {{{ proto string ZipArchive::getFromName(string entryname[, int len [, int flags]])
  2447. get the contents of an entry using its name */
  2448. static ZIPARCHIVE_METHOD(getFromName)
  2449. {
  2450. php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  2451. }
  2452. /* }}} */
  2453. /* {{{ proto string ZipArchive::getFromIndex(int index[, int len [, int flags]])
  2454. get the contents of an entry using its index */
  2455. static ZIPARCHIVE_METHOD(getFromIndex)
  2456. {
  2457. php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2458. }
  2459. /* }}} */
  2460. /* {{{ proto resource ZipArchive::getStream(string entryname)
  2461. get a stream for an entry using its name */
  2462. static ZIPARCHIVE_METHOD(getStream)
  2463. {
  2464. struct zip *intern;
  2465. zval *self = ZEND_THIS;
  2466. struct zip_stat sb;
  2467. char *mode = "rb";
  2468. zend_string *filename;
  2469. php_stream *stream;
  2470. ze_zip_object *obj;
  2471. if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &filename) == FAILURE) {
  2472. RETURN_THROWS();
  2473. }
  2474. ZIP_FROM_OBJECT(intern, self);
  2475. if (zip_stat(intern, ZSTR_VAL(filename), 0, &sb) != 0) {
  2476. RETURN_FALSE;
  2477. }
  2478. obj = Z_ZIP_P(self);
  2479. stream = php_stream_zip_open(obj->filename, ZSTR_VAL(filename), mode STREAMS_CC);
  2480. if (stream) {
  2481. php_stream_to_zval(stream, return_value);
  2482. } else {
  2483. RETURN_FALSE;
  2484. }
  2485. }
  2486. /* }}} */
  2487. #ifdef HAVE_PROGRESS_CALLBACK
  2488. static void _php_zip_progress_callback(zip_t *arch, double state, void *ptr)
  2489. {
  2490. zval cb_args[1];
  2491. zval cb_retval;
  2492. ze_zip_object *obj = ptr;
  2493. ZVAL_DOUBLE(&cb_args[0], state);
  2494. if (call_user_function_ex(EG(function_table), NULL, &obj->progress_callback, &cb_retval, 1, cb_args, 0, NULL) == SUCCESS && !Z_ISUNDEF(cb_retval)) {
  2495. zval_ptr_dtor(&cb_retval);
  2496. }
  2497. }
  2498. /* {{{ proto bool ZipArchive::registerProgressCallback(double rate, callable callback)
  2499. register a progression callback: void callback(double state); */
  2500. static ZIPARCHIVE_METHOD(registerProgressCallback)
  2501. {
  2502. struct zip *intern;
  2503. zval *self = getThis();
  2504. double rate;
  2505. zval *callback;
  2506. ze_zip_object *obj;
  2507. if (!self) {
  2508. RETURN_FALSE;
  2509. }
  2510. if (zend_parse_parameters(ZEND_NUM_ARGS(), "dz", &rate, &callback) == FAILURE) {
  2511. return;
  2512. }
  2513. /* callable? */
  2514. if (!zend_is_callable(callback, 0, NULL)) {
  2515. zend_string *callback_name = zend_get_callable_name(callback);
  2516. php_error_docref(NULL, E_WARNING, "Invalid callback '%s'", ZSTR_VAL(callback_name));
  2517. zend_string_release_ex(callback_name, 0);
  2518. RETURN_FALSE;
  2519. }
  2520. ZIP_FROM_OBJECT(intern, self);
  2521. obj = Z_ZIP_P(self);
  2522. /* free if called twice */
  2523. _php_zip_progress_callback_free(obj);
  2524. /* register */
  2525. ZVAL_COPY(&obj->progress_callback, callback);
  2526. if (zip_register_progress_callback_with_state(intern, rate, _php_zip_progress_callback, _php_zip_progress_callback_free, obj)) {
  2527. RETURN_FALSE;
  2528. }
  2529. RETURN_TRUE;
  2530. }
  2531. /* }}} */
  2532. #endif
  2533. #ifdef HAVE_CANCEL_CALLBACK
  2534. static int _php_zip_cancel_callback(zip_t *arch, void *ptr)
  2535. {
  2536. zval cb_retval;
  2537. int retval = 0;
  2538. ze_zip_object *obj = ptr;
  2539. if (call_user_function_ex(EG(function_table), NULL, &obj->cancel_callback, &cb_retval, 0, NULL, 0, NULL) == SUCCESS && !Z_ISUNDEF(cb_retval)) {
  2540. retval = zval_get_long(&cb_retval);
  2541. zval_ptr_dtor(&cb_retval);
  2542. }
  2543. return retval;
  2544. }
  2545. /* {{{ proto bool ZipArchive::registerCancelCallback(callable callback)
  2546. register a progression callback: int callback(double state); */
  2547. static ZIPARCHIVE_METHOD(registerCancelCallback)
  2548. {
  2549. struct zip *intern;
  2550. zval *self = getThis();
  2551. zval *callback;
  2552. ze_zip_object *obj;
  2553. if (!self) {
  2554. RETURN_FALSE;
  2555. }
  2556. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &callback) == FAILURE) {
  2557. return;
  2558. }
  2559. ZIP_FROM_OBJECT(intern, self);
  2560. /* callable? */
  2561. if (!zend_is_callable(callback, 0, NULL)) {
  2562. zend_string *callback_name = zend_get_callable_name(callback);
  2563. php_error_docref(NULL, E_WARNING, "Invalid callback '%s'", ZSTR_VAL(callback_name));
  2564. zend_string_release_ex(callback_name, 0);
  2565. RETURN_FALSE;
  2566. }
  2567. obj = Z_ZIP_P(self);
  2568. /* free if called twice */
  2569. _php_zip_cancel_callback_free(obj);
  2570. /* register */
  2571. ZVAL_COPY(&obj->cancel_callback, callback);
  2572. if (zip_register_cancel_callback_with_state(intern, _php_zip_cancel_callback, _php_zip_cancel_callback_free, obj)) {
  2573. RETURN_FALSE;
  2574. }
  2575. RETURN_TRUE;
  2576. }
  2577. /* }}} */
  2578. #endif
  2579. #ifdef HAVE_METHOD_SUPPORTED
  2580. /* {{{ proto bool ZipArchive::isCompressionMethodSupported(int method, bool enc)
  2581. check if a compression method is available in used libzip */
  2582. static ZIPARCHIVE_METHOD(isCompressionMethodSupported)
  2583. {
  2584. zend_long method;
  2585. zend_bool enc = 1;
  2586. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|b", &method, &enc) == FAILURE) {
  2587. return;
  2588. }
  2589. RETVAL_BOOL(zip_compression_method_supported((zip_int32_t)method, enc));
  2590. }
  2591. /* }}} */
  2592. /* {{{ proto bool ZipArchive::isEncryptionMethodSupported(int method, bool enc)
  2593. check if a encryption method is available in used libzip */
  2594. static ZIPARCHIVE_METHOD(isEncryptionMethodSupported)
  2595. {
  2596. zend_long method;
  2597. zend_bool enc = 1;
  2598. if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|b", &method, &enc) == FAILURE) {
  2599. return;
  2600. }
  2601. RETVAL_BOOL(zip_encryption_method_supported((zip_uint16_t)method, enc));
  2602. }
  2603. /* }}} */
  2604. #endif
  2605. /* {{{ ze_zip_object_class_functions */
  2606. static const zend_function_entry zip_class_functions[] = {
  2607. ZIPARCHIVE_ME(open, arginfo_class_ZipArchive_open, ZEND_ACC_PUBLIC)
  2608. ZIPARCHIVE_ME(setPassword, arginfo_class_ZipArchive_setPassword, ZEND_ACC_PUBLIC)
  2609. ZIPARCHIVE_ME(close, arginfo_class_ZipArchive_close, ZEND_ACC_PUBLIC)
  2610. ZIPARCHIVE_ME(count, arginfo_class_ZipArchive_count, ZEND_ACC_PUBLIC)
  2611. ZIPARCHIVE_ME(getStatusString, arginfo_class_ZipArchive_getStatusString, ZEND_ACC_PUBLIC)
  2612. ZIPARCHIVE_ME(addEmptyDir, arginfo_class_ZipArchive_addEmptyDir, ZEND_ACC_PUBLIC)
  2613. ZIPARCHIVE_ME(addFromString, arginfo_class_ZipArchive_addFromString, ZEND_ACC_PUBLIC)
  2614. ZIPARCHIVE_ME(addFile, arginfo_class_ZipArchive_addFile, ZEND_ACC_PUBLIC)
  2615. ZIPARCHIVE_ME(addGlob, arginfo_class_ZipArchive_addGlob, ZEND_ACC_PUBLIC)
  2616. ZIPARCHIVE_ME(addPattern, arginfo_class_ZipArchive_addPattern, ZEND_ACC_PUBLIC)
  2617. ZIPARCHIVE_ME(renameIndex, arginfo_class_ZipArchive_renameIndex, ZEND_ACC_PUBLIC)
  2618. ZIPARCHIVE_ME(renameName, arginfo_class_ZipArchive_renameName, ZEND_ACC_PUBLIC)
  2619. ZIPARCHIVE_ME(replaceFile, arginfo_class_ZipArchive_replaceFile, ZEND_ACC_PUBLIC)
  2620. ZIPARCHIVE_ME(setArchiveComment, arginfo_class_ZipArchive_setArchiveComment, ZEND_ACC_PUBLIC)
  2621. ZIPARCHIVE_ME(getArchiveComment, arginfo_class_ZipArchive_getArchiveComment, ZEND_ACC_PUBLIC)
  2622. ZIPARCHIVE_ME(setCommentIndex, arginfo_class_ZipArchive_setCommentIndex, ZEND_ACC_PUBLIC)
  2623. ZIPARCHIVE_ME(setCommentName, arginfo_class_ZipArchive_setCommentName, ZEND_ACC_PUBLIC)
  2624. ZIPARCHIVE_ME(getCommentIndex, arginfo_class_ZipArchive_getCommentIndex, ZEND_ACC_PUBLIC)
  2625. ZIPARCHIVE_ME(getCommentName, arginfo_class_ZipArchive_getCommentName, ZEND_ACC_PUBLIC)
  2626. ZIPARCHIVE_ME(deleteIndex, arginfo_class_ZipArchive_deleteIndex, ZEND_ACC_PUBLIC)
  2627. ZIPARCHIVE_ME(deleteName, arginfo_class_ZipArchive_deleteName, ZEND_ACC_PUBLIC)
  2628. ZIPARCHIVE_ME(statName, arginfo_class_ZipArchive_statName, ZEND_ACC_PUBLIC)
  2629. ZIPARCHIVE_ME(statIndex, arginfo_class_ZipArchive_statIndex, ZEND_ACC_PUBLIC)
  2630. ZIPARCHIVE_ME(locateName, arginfo_class_ZipArchive_locateName, ZEND_ACC_PUBLIC)
  2631. ZIPARCHIVE_ME(getNameIndex, arginfo_class_ZipArchive_getNameIndex, ZEND_ACC_PUBLIC)
  2632. ZIPARCHIVE_ME(unchangeArchive, arginfo_class_ZipArchive_unchangeArchive, ZEND_ACC_PUBLIC)
  2633. ZIPARCHIVE_ME(unchangeAll, arginfo_class_ZipArchive_unchangeAll, ZEND_ACC_PUBLIC)
  2634. ZIPARCHIVE_ME(unchangeIndex, arginfo_class_ZipArchive_unchangeIndex, ZEND_ACC_PUBLIC)
  2635. ZIPARCHIVE_ME(unchangeName, arginfo_class_ZipArchive_unchangeName, ZEND_ACC_PUBLIC)
  2636. ZIPARCHIVE_ME(extractTo, arginfo_class_ZipArchive_extractTo, ZEND_ACC_PUBLIC)
  2637. ZIPARCHIVE_ME(getFromName, arginfo_class_ZipArchive_getFromName, ZEND_ACC_PUBLIC)
  2638. ZIPARCHIVE_ME(getFromIndex, arginfo_class_ZipArchive_getFromIndex, ZEND_ACC_PUBLIC)
  2639. ZIPARCHIVE_ME(getStream, arginfo_class_ZipArchive_getStream, ZEND_ACC_PUBLIC)
  2640. #ifdef ZIP_OPSYS_DEFAULT
  2641. ZIPARCHIVE_ME(setExternalAttributesName, arginfo_class_ZipArchive_setExternalAttributesName, ZEND_ACC_PUBLIC)
  2642. ZIPARCHIVE_ME(setExternalAttributesIndex, arginfo_class_ZipArchive_setExternalAttributesIndex, ZEND_ACC_PUBLIC)
  2643. ZIPARCHIVE_ME(getExternalAttributesName, arginfo_class_ZipArchive_getExternalAttributesName, ZEND_ACC_PUBLIC)
  2644. ZIPARCHIVE_ME(getExternalAttributesIndex, arginfo_class_ZipArchive_getExternalAttributesIndex, ZEND_ACC_PUBLIC)
  2645. #endif
  2646. ZIPARCHIVE_ME(setCompressionName, arginfo_class_ZipArchive_setCompressionName, ZEND_ACC_PUBLIC)
  2647. ZIPARCHIVE_ME(setCompressionIndex, arginfo_class_ZipArchive_setCompressionIndex, ZEND_ACC_PUBLIC)
  2648. #ifdef HAVE_SET_MTIME
  2649. ZIPARCHIVE_ME(setMtimeName, arginfo_class_ZipArchive_setMtimeName, ZEND_ACC_PUBLIC)
  2650. ZIPARCHIVE_ME(setMtimeIndex, arginfo_class_ZipArchive_setMtimeIndex, ZEND_ACC_PUBLIC)
  2651. #endif
  2652. #ifdef HAVE_ENCRYPTION
  2653. ZIPARCHIVE_ME(setEncryptionName, arginfo_class_ZipArchive_setEncryptionName, ZEND_ACC_PUBLIC)
  2654. ZIPARCHIVE_ME(setEncryptionIndex, arginfo_class_ZipArchive_setEncryptionIndex, ZEND_ACC_PUBLIC)
  2655. #endif
  2656. #ifdef HAVE_PROGRESS_CALLBACK
  2657. ZIPARCHIVE_ME(registerProgressCallback, arginfo_class_ZipArchive_registerProgressCallback, ZEND_ACC_PUBLIC)
  2658. #endif
  2659. #ifdef HAVE_CANCEL_CALLBACK
  2660. ZIPARCHIVE_ME(registerCancelCallback, arginfo_class_ZipArchive_registerCancelCallback, ZEND_ACC_PUBLIC)
  2661. #endif
  2662. #ifdef HAVE_METHOD_SUPPORTED
  2663. ZIPARCHIVE_ME(isCompressionMethodSupported, arginfo_class_ZipArchive_isCompressionMethodSupported, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
  2664. ZIPARCHIVE_ME(isEncryptionMethodSupported, arginfo_class_ZipArchive_isEncryptionMethodSupported, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
  2665. #endif
  2666. PHP_FE_END
  2667. };
  2668. /* }}} */
  2669. static void php_zip_free_prop_handler(zval *el) /* {{{ */ {
  2670. pefree(Z_PTR_P(el), 1);
  2671. } /* }}} */
  2672. /* {{{ PHP_MINIT_FUNCTION */
  2673. static PHP_MINIT_FUNCTION(zip)
  2674. {
  2675. zend_class_entry ce;
  2676. memcpy(&zip_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
  2677. zip_object_handlers.offset = XtOffsetOf(ze_zip_object, zo);
  2678. zip_object_handlers.free_obj = php_zip_object_free_storage;
  2679. zip_object_handlers.clone_obj = NULL;
  2680. zip_object_handlers.get_property_ptr_ptr = php_zip_get_property_ptr_ptr;
  2681. zip_object_handlers.get_gc = php_zip_get_gc;
  2682. zip_object_handlers.get_properties = php_zip_get_properties;
  2683. zip_object_handlers.read_property = php_zip_read_property;
  2684. zip_object_handlers.has_property = php_zip_has_property;
  2685. INIT_CLASS_ENTRY(ce, "ZipArchive", zip_class_functions);
  2686. ce.create_object = php_zip_object_new;
  2687. zip_class_entry = zend_register_internal_class(&ce);
  2688. zend_hash_init(&zip_prop_handlers, 0, NULL, php_zip_free_prop_handler, 1);
  2689. php_zip_register_prop_handler(&zip_prop_handlers, "lastId", php_zip_last_id, NULL, IS_LONG);
  2690. php_zip_register_prop_handler(&zip_prop_handlers, "status", php_zip_status, NULL, IS_LONG);
  2691. php_zip_register_prop_handler(&zip_prop_handlers, "statusSys", php_zip_status_sys, NULL, IS_LONG);
  2692. php_zip_register_prop_handler(&zip_prop_handlers, "numFiles", php_zip_get_num_files, NULL, IS_LONG);
  2693. php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, php_zipobj_get_filename, IS_STRING);
  2694. php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, IS_STRING);
  2695. zend_class_implements(zip_class_entry, 1, zend_ce_countable);
  2696. REGISTER_ZIP_CLASS_CONST_LONG("CREATE", ZIP_CREATE);
  2697. REGISTER_ZIP_CLASS_CONST_LONG("EXCL", ZIP_EXCL);
  2698. REGISTER_ZIP_CLASS_CONST_LONG("CHECKCONS", ZIP_CHECKCONS);
  2699. REGISTER_ZIP_CLASS_CONST_LONG("OVERWRITE", ZIP_OVERWRITE);
  2700. #ifdef ZIP_RDONLY
  2701. REGISTER_ZIP_CLASS_CONST_LONG("RDONLY", ZIP_RDONLY);
  2702. #endif
  2703. REGISTER_ZIP_CLASS_CONST_LONG("FL_NOCASE", ZIP_FL_NOCASE);
  2704. REGISTER_ZIP_CLASS_CONST_LONG("FL_NODIR", ZIP_FL_NODIR);
  2705. REGISTER_ZIP_CLASS_CONST_LONG("FL_COMPRESSED", ZIP_FL_COMPRESSED);
  2706. REGISTER_ZIP_CLASS_CONST_LONG("FL_UNCHANGED", ZIP_FL_UNCHANGED);
  2707. REGISTER_ZIP_CLASS_CONST_LONG("FL_RECOMPRESS", ZIP_FL_RECOMPRESS);
  2708. REGISTER_ZIP_CLASS_CONST_LONG("FL_ENCRYPTED", ZIP_FL_ENCRYPTED);
  2709. REGISTER_ZIP_CLASS_CONST_LONG("FL_OVERWRITE", ZIP_FL_OVERWRITE);
  2710. REGISTER_ZIP_CLASS_CONST_LONG("FL_LOCAL", ZIP_FL_LOCAL);
  2711. REGISTER_ZIP_CLASS_CONST_LONG("FL_CENTRAL", ZIP_FL_CENTRAL);
  2712. /* Default filename encoding policy. */
  2713. REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_GUESS", ZIP_FL_ENC_GUESS);
  2714. REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_RAW", ZIP_FL_ENC_RAW);
  2715. REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_STRICT", ZIP_FL_ENC_STRICT);
  2716. REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_UTF_8", ZIP_FL_ENC_UTF_8);
  2717. REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_CP437", ZIP_FL_ENC_CP437);
  2718. REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFAULT", ZIP_CM_DEFAULT);
  2719. REGISTER_ZIP_CLASS_CONST_LONG("CM_STORE", ZIP_CM_STORE);
  2720. REGISTER_ZIP_CLASS_CONST_LONG("CM_SHRINK", ZIP_CM_SHRINK);
  2721. REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_1", ZIP_CM_REDUCE_1);
  2722. REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_2", ZIP_CM_REDUCE_2);
  2723. REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_3", ZIP_CM_REDUCE_3);
  2724. REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_4", ZIP_CM_REDUCE_4);
  2725. REGISTER_ZIP_CLASS_CONST_LONG("CM_IMPLODE", ZIP_CM_IMPLODE);
  2726. REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE", ZIP_CM_DEFLATE);
  2727. REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE64", ZIP_CM_DEFLATE64);
  2728. REGISTER_ZIP_CLASS_CONST_LONG("CM_PKWARE_IMPLODE", ZIP_CM_PKWARE_IMPLODE);
  2729. REGISTER_ZIP_CLASS_CONST_LONG("CM_BZIP2", ZIP_CM_BZIP2);
  2730. REGISTER_ZIP_CLASS_CONST_LONG("CM_LZMA", ZIP_CM_LZMA);
  2731. #ifdef ZIP_CM_LZMA2
  2732. REGISTER_ZIP_CLASS_CONST_LONG("CM_LZMA2", ZIP_CM_LZMA2);
  2733. #endif
  2734. #ifdef ZIP_CM_XZ
  2735. REGISTER_ZIP_CLASS_CONST_LONG("CM_XZ", ZIP_CM_XZ);
  2736. #endif
  2737. REGISTER_ZIP_CLASS_CONST_LONG("CM_TERSE", ZIP_CM_TERSE);
  2738. REGISTER_ZIP_CLASS_CONST_LONG("CM_LZ77", ZIP_CM_LZ77);
  2739. REGISTER_ZIP_CLASS_CONST_LONG("CM_WAVPACK", ZIP_CM_WAVPACK);
  2740. REGISTER_ZIP_CLASS_CONST_LONG("CM_PPMD", ZIP_CM_PPMD);
  2741. /* Error code */
  2742. REGISTER_ZIP_CLASS_CONST_LONG("ER_OK", ZIP_ER_OK); /* N No error */
  2743. REGISTER_ZIP_CLASS_CONST_LONG("ER_MULTIDISK", ZIP_ER_MULTIDISK); /* N Multi-disk zip archives not supported */
  2744. REGISTER_ZIP_CLASS_CONST_LONG("ER_RENAME", ZIP_ER_RENAME); /* S Renaming temporary file failed */
  2745. REGISTER_ZIP_CLASS_CONST_LONG("ER_CLOSE", ZIP_ER_CLOSE); /* S Closing zip archive failed */
  2746. REGISTER_ZIP_CLASS_CONST_LONG("ER_SEEK", ZIP_ER_SEEK); /* S Seek error */
  2747. REGISTER_ZIP_CLASS_CONST_LONG("ER_READ", ZIP_ER_READ); /* S Read error */
  2748. REGISTER_ZIP_CLASS_CONST_LONG("ER_WRITE", ZIP_ER_WRITE); /* S Write error */
  2749. REGISTER_ZIP_CLASS_CONST_LONG("ER_CRC", ZIP_ER_CRC); /* N CRC error */
  2750. REGISTER_ZIP_CLASS_CONST_LONG("ER_ZIPCLOSED", ZIP_ER_ZIPCLOSED); /* N Containing zip archive was closed */
  2751. REGISTER_ZIP_CLASS_CONST_LONG("ER_NOENT", ZIP_ER_NOENT); /* N No such file */
  2752. REGISTER_ZIP_CLASS_CONST_LONG("ER_EXISTS", ZIP_ER_EXISTS); /* N File already exists */
  2753. REGISTER_ZIP_CLASS_CONST_LONG("ER_OPEN", ZIP_ER_OPEN); /* S Can't open file */
  2754. REGISTER_ZIP_CLASS_CONST_LONG("ER_TMPOPEN", ZIP_ER_TMPOPEN); /* S Failure to create temporary file */
  2755. REGISTER_ZIP_CLASS_CONST_LONG("ER_ZLIB", ZIP_ER_ZLIB); /* Z Zlib error */
  2756. REGISTER_ZIP_CLASS_CONST_LONG("ER_MEMORY", ZIP_ER_MEMORY); /* N Malloc failure */
  2757. REGISTER_ZIP_CLASS_CONST_LONG("ER_CHANGED", ZIP_ER_CHANGED); /* N Entry has been changed */
  2758. REGISTER_ZIP_CLASS_CONST_LONG("ER_COMPNOTSUPP", ZIP_ER_COMPNOTSUPP);/* N Compression method not supported */
  2759. REGISTER_ZIP_CLASS_CONST_LONG("ER_EOF", ZIP_ER_EOF); /* N Premature EOF */
  2760. REGISTER_ZIP_CLASS_CONST_LONG("ER_INVAL", ZIP_ER_INVAL); /* N Invalid argument */
  2761. REGISTER_ZIP_CLASS_CONST_LONG("ER_NOZIP", ZIP_ER_NOZIP); /* N Not a zip archive */
  2762. REGISTER_ZIP_CLASS_CONST_LONG("ER_INTERNAL", ZIP_ER_INTERNAL); /* N Internal error */
  2763. REGISTER_ZIP_CLASS_CONST_LONG("ER_INCONS", ZIP_ER_INCONS); /* N Zip archive inconsistent */
  2764. REGISTER_ZIP_CLASS_CONST_LONG("ER_REMOVE", ZIP_ER_REMOVE); /* S Can't remove file */
  2765. REGISTER_ZIP_CLASS_CONST_LONG("ER_DELETED", ZIP_ER_DELETED); /* N Entry has been deleted */
  2766. REGISTER_ZIP_CLASS_CONST_LONG("ER_ENCRNOTSUPP", ZIP_ER_ENCRNOTSUPP);/* N Encryption method not supported */
  2767. REGISTER_ZIP_CLASS_CONST_LONG("ER_RDONLY", ZIP_ER_RDONLY); /* N Read-only archive */
  2768. REGISTER_ZIP_CLASS_CONST_LONG("ER_NOPASSWD", ZIP_ER_NOPASSWD); /* N Entry has been deleted */
  2769. REGISTER_ZIP_CLASS_CONST_LONG("ER_WRONGPASSWD", ZIP_ER_WRONGPASSWD);/* N Wrong password provided */
  2770. /* since 1.0.0 */
  2771. #ifdef ZIP_ER_OPNOTSUPP
  2772. REGISTER_ZIP_CLASS_CONST_LONG("ER_OPNOTSUPP", ZIP_ER_OPNOTSUPP); /* N Operation not supported */
  2773. #endif
  2774. #ifdef ZIP_ER_INUSE
  2775. REGISTER_ZIP_CLASS_CONST_LONG("ER_INUSE", ZIP_ER_INUSE); /* N Resource still in use */
  2776. #endif
  2777. #ifdef ZIP_ER_TELL
  2778. REGISTER_ZIP_CLASS_CONST_LONG("ER_TELL", ZIP_ER_TELL); /* S Tell error */
  2779. #endif
  2780. /* since 1.6.0 */
  2781. #ifdef ZIP_ER_COMPRESSED_DATA
  2782. REGISTER_ZIP_CLASS_CONST_LONG("ER_COMPRESSED_DATA", ZIP_ER_COMPRESSED_DATA);/* N Compressed data invalid */
  2783. #endif
  2784. #ifdef ZIP_ER_CANCELLED
  2785. REGISTER_ZIP_CLASS_CONST_LONG("ER_CANCELLED", ZIP_ER_CANCELLED); /* N Operation cancelled */
  2786. #endif
  2787. #ifdef ZIP_OPSYS_DEFAULT
  2788. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_DOS", ZIP_OPSYS_DOS);
  2789. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_AMIGA", ZIP_OPSYS_AMIGA);
  2790. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OPENVMS", ZIP_OPSYS_OPENVMS);
  2791. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_UNIX", ZIP_OPSYS_UNIX);
  2792. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_VM_CMS", ZIP_OPSYS_VM_CMS);
  2793. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_ATARI_ST", ZIP_OPSYS_ATARI_ST);
  2794. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OS_2", ZIP_OPSYS_OS_2);
  2795. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_MACINTOSH", ZIP_OPSYS_MACINTOSH);
  2796. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_Z_SYSTEM", ZIP_OPSYS_Z_SYSTEM);
  2797. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_CPM", ZIP_OPSYS_CPM);
  2798. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_WINDOWS_NTFS", ZIP_OPSYS_WINDOWS_NTFS);
  2799. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_MVS", ZIP_OPSYS_MVS);
  2800. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_VSE", ZIP_OPSYS_VSE);
  2801. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_ACORN_RISC", ZIP_OPSYS_ACORN_RISC);
  2802. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_VFAT", ZIP_OPSYS_VFAT);
  2803. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_ALTERNATE_MVS", ZIP_OPSYS_ALTERNATE_MVS);
  2804. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_BEOS", ZIP_OPSYS_BEOS);
  2805. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_TANDEM", ZIP_OPSYS_TANDEM);
  2806. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OS_400", ZIP_OPSYS_OS_400);
  2807. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OS_X", ZIP_OPSYS_OS_X);
  2808. REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_DEFAULT", ZIP_OPSYS_DEFAULT);
  2809. #endif /* ifdef ZIP_OPSYS_DEFAULT */
  2810. REGISTER_ZIP_CLASS_CONST_LONG("EM_NONE", ZIP_EM_NONE);
  2811. REGISTER_ZIP_CLASS_CONST_LONG("EM_TRAD_PKWARE", ZIP_EM_TRAD_PKWARE);
  2812. #ifdef HAVE_ENCRYPTION
  2813. REGISTER_ZIP_CLASS_CONST_LONG("EM_AES_128", ZIP_EM_AES_128);
  2814. REGISTER_ZIP_CLASS_CONST_LONG("EM_AES_192", ZIP_EM_AES_192);
  2815. REGISTER_ZIP_CLASS_CONST_LONG("EM_AES_256", ZIP_EM_AES_256);
  2816. #endif
  2817. REGISTER_ZIP_CLASS_CONST_LONG("EM_UNKNOWN", ZIP_EM_UNKNOWN);
  2818. #if HAVE_LIBZIP_VERSION
  2819. zend_declare_class_constant_string(zip_class_entry, "LIBZIP_VERSION", sizeof("LIBZIP_VERSION")-1, zip_libzip_version());
  2820. #else
  2821. zend_declare_class_constant_string(zip_class_entry, "LIBZIP_VERSION", sizeof("LIBZIP_VERSION")-1, LIBZIP_VERSION);
  2822. #endif
  2823. php_register_url_stream_wrapper("zip", &php_stream_zip_wrapper);
  2824. le_zip_dir = zend_register_list_destructors_ex(php_zip_free_dir, NULL, le_zip_dir_name, module_number);
  2825. le_zip_entry = zend_register_list_destructors_ex(php_zip_free_entry, NULL, le_zip_entry_name, module_number);
  2826. return SUCCESS;
  2827. }
  2828. /* }}} */
  2829. /* {{{ PHP_MSHUTDOWN_FUNCTION
  2830. */
  2831. static PHP_MSHUTDOWN_FUNCTION(zip)
  2832. {
  2833. zend_hash_destroy(&zip_prop_handlers);
  2834. php_unregister_url_stream_wrapper("zip");
  2835. return SUCCESS;
  2836. }
  2837. /* }}} */
  2838. /* {{{ PHP_MINFO_FUNCTION
  2839. */
  2840. static PHP_MINFO_FUNCTION(zip)
  2841. {
  2842. php_info_print_table_start();
  2843. php_info_print_table_row(2, "Zip", "enabled");
  2844. php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION);
  2845. #if HAVE_LIBZIP_VERSION
  2846. php_info_print_table_row(2, "Libzip headers version", LIBZIP_VERSION);
  2847. php_info_print_table_row(2, "Libzip library version", zip_libzip_version());
  2848. #else
  2849. php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION);
  2850. #endif
  2851. #ifdef HAVE_METHOD_SUPPORTED
  2852. php_info_print_table_row(2, "BZIP2 compression",
  2853. zip_compression_method_supported(ZIP_CM_BZIP2, 1) ? "Yes" : "No");
  2854. php_info_print_table_row(2, "XZ compression",
  2855. zip_compression_method_supported(ZIP_CM_XZ, 1) ? "Yes" : "No");
  2856. php_info_print_table_row(2, "AES-128 encryption",
  2857. zip_encryption_method_supported(ZIP_EM_AES_128, 1) ? "Yes" : "No");
  2858. php_info_print_table_row(2, "AES-192 encryption",
  2859. zip_encryption_method_supported(ZIP_EM_AES_128, 1) ? "Yes" : "No");
  2860. php_info_print_table_row(2, "AES-256 encryption",
  2861. zip_encryption_method_supported(ZIP_EM_AES_128, 1) ? "Yes" : "No");
  2862. #endif
  2863. php_info_print_table_end();
  2864. }
  2865. /* }}} */