PageRenderTime 58ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/php_zip.c

https://github.com/weltling/php_zip
C | 3157 lines | 2392 code | 485 blank | 280 comment | 506 complexity | 45360f83b12098f6bb1d2b2514f91f22 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2013 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt. |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Piere-Alain Joye <pierre@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id: 872affeb4da56999accae9cdc682d3f3bb3f3458 $ */
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include "php.h"
  23. #include "php_ini.h"
  24. #include "ext/standard/info.h"
  25. #include "ext/standard/file.h"
  26. #include "ext/standard/php_string.h"
  27. #include "ext/pcre/php_pcre.h"
  28. #include "ext/standard/php_filestat.h"
  29. #include "php_zip.h"
  30. /* zip_open is a macro for renaming libzip zipopen, so we need to use PHP_NAMED_FUNCTION */
  31. static PHP_NAMED_FUNCTION(zif_zip_open);
  32. static PHP_NAMED_FUNCTION(zif_zip_read);
  33. static PHP_NAMED_FUNCTION(zif_zip_close);
  34. static PHP_NAMED_FUNCTION(zif_zip_entry_read);
  35. static PHP_NAMED_FUNCTION(zif_zip_entry_filesize);
  36. static PHP_NAMED_FUNCTION(zif_zip_entry_name);
  37. static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize);
  38. static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod);
  39. static PHP_NAMED_FUNCTION(zif_zip_entry_open);
  40. static PHP_NAMED_FUNCTION(zif_zip_entry_close);
  41. #ifdef HAVE_GLOB
  42. #ifndef PHP_WIN32
  43. #include <glob.h>
  44. #else
  45. #include "win32/glob.h"
  46. #endif
  47. #endif
  48. #if PHP_VERSION_ID < 50400
  49. #define ARG_PATH "s"
  50. #define KEY_ARG_DC
  51. #define KEY_ARG_CC
  52. #else
  53. #define ARG_PATH "p"
  54. #define KEY_ARG_DC , const zend_literal *key
  55. #define KEY_ARG_CC , key
  56. #endif
  57. #if PHP_VERSION_ID < 50500
  58. #define TYPE_ARG_DC
  59. #define TYPE_ARG_CC
  60. #else
  61. #define TYPE_ARG_DC , int type
  62. #define TYPE_ARG_CC , type
  63. #endif
  64. /* {{{ Resource le */
  65. static int le_zip_dir;
  66. #define le_zip_dir_name "Zip Directory"
  67. static int le_zip_entry;
  68. #define le_zip_entry_name "Zip Entry"
  69. /* }}} */
  70. /* {{{ PHP_ZIP_STAT_INDEX(za, index, flags, sb) */
  71. #define PHP_ZIP_STAT_INDEX(za, index, flags, sb) \
  72. if (zip_stat_index(za, index, flags, &sb) != 0) { \
  73. RETURN_FALSE; \
  74. }
  75. /* }}} */
  76. /* {{{ PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) */
  77. #define PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) \
  78. if (path_len < 1) { \
  79. php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name"); \
  80. RETURN_FALSE; \
  81. } \
  82. if (zip_stat(za, path, flags, &sb) != 0) { \
  83. RETURN_FALSE; \
  84. }
  85. /* }}} */
  86. /* {{{ PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) */
  87. #define PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) \
  88. if (comment_len == 0) { \
  89. /* Passing NULL remove the existing comment */ \
  90. if (zip_set_file_comment(intern, index, NULL, 0) < 0) { \
  91. RETURN_FALSE; \
  92. } \
  93. } else if (zip_set_file_comment(intern, index, comment, comment_len) < 0) { \
  94. RETURN_FALSE; \
  95. } \
  96. RETURN_TRUE;
  97. /* }}} */
  98. #if (PHP_MAJOR_VERSION < 6)
  99. # define add_ascii_assoc_string add_assoc_string
  100. # define add_ascii_assoc_long add_assoc_long
  101. #endif
  102. /* Flatten a path by making a relative path (to .)*/
  103. static char * php_zip_make_relative_path(char *path, int path_len) /* {{{ */
  104. {
  105. char *path_begin = path;
  106. size_t i;
  107. if (path_len < 1 || path == NULL) {
  108. return NULL;
  109. }
  110. if (IS_SLASH(path[0])) {
  111. return path + 1;
  112. }
  113. i = path_len;
  114. while (1) {
  115. while (i > 0 && !IS_SLASH(path[i])) {
  116. i--;
  117. }
  118. if (!i) {
  119. return path;
  120. }
  121. if (i >= 2 && (path[i -1] == '.' || path[i -1] == ':')) {
  122. /* i is the position of . or :, add 1 for / */
  123. path_begin = path + i + 1;
  124. break;
  125. }
  126. i--;
  127. }
  128. return path_begin;
  129. }
  130. /* }}} */
  131. #ifdef PHP_ZIP_USE_OO
  132. /* {{{ php_zip_extract_file */
  133. static int php_zip_extract_file(struct zip * za, char *dest, char *file, int file_len TSRMLS_DC)
  134. {
  135. php_stream_statbuf ssb;
  136. struct zip_file *zf;
  137. struct zip_stat sb;
  138. char b[8192];
  139. int n, len, ret;
  140. php_stream *stream;
  141. char *fullpath;
  142. char *file_dirname_fullpath;
  143. char file_dirname[MAXPATHLEN];
  144. size_t dir_len;
  145. char *file_basename;
  146. size_t file_basename_len;
  147. int is_dir_only = 0;
  148. char *path_cleaned;
  149. size_t path_cleaned_len;
  150. cwd_state new_state;
  151. new_state.cwd = (char*)malloc(1);
  152. new_state.cwd[0] = '\0';
  153. new_state.cwd_length = 0;
  154. /* Clean/normlize the path and then transform any path (absolute or relative)
  155. to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt)
  156. */
  157. virtual_file_ex(&new_state, file, NULL, CWD_EXPAND TSRMLS_CC);
  158. path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length);
  159. if(!path_cleaned) {
  160. return 0;
  161. }
  162. path_cleaned_len = strlen(path_cleaned);
  163. if (path_cleaned_len >= MAXPATHLEN || zip_stat(za, file, 0, &sb) != 0) {
  164. return 0;
  165. }
  166. /* it is a directory only, see #40228 */
  167. if (path_cleaned_len > 1 && IS_SLASH(path_cleaned[path_cleaned_len - 1])) {
  168. len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file);
  169. is_dir_only = 1;
  170. } else {
  171. memcpy(file_dirname, path_cleaned, path_cleaned_len);
  172. dir_len = php_dirname(file_dirname, path_cleaned_len);
  173. if (dir_len <= 0 || (dir_len == 1 && file_dirname[0] == '.')) {
  174. len = spprintf(&file_dirname_fullpath, 0, "%s", dest);
  175. } else {
  176. len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file_dirname);
  177. }
  178. php_basename(path_cleaned, path_cleaned_len, NULL, 0, &file_basename, (size_t *)&file_basename_len TSRMLS_CC);
  179. if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname_fullpath)) {
  180. efree(file_dirname_fullpath);
  181. efree(file_basename);
  182. free(new_state.cwd);
  183. return 0;
  184. }
  185. }
  186. /* let see if the path already exists */
  187. if (php_stream_stat_path_ex(file_dirname_fullpath, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
  188. #if defined(PHP_WIN32) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1)
  189. char *e;
  190. e = file_dirname_fullpath;
  191. while (*e) {
  192. if (*e == '/') {
  193. *e = DEFAULT_SLASH;
  194. }
  195. e++;
  196. }
  197. #endif
  198. ret = php_stream_mkdir(file_dirname_fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE|REPORT_ERRORS, NULL);
  199. if (!ret) {
  200. efree(file_dirname_fullpath);
  201. if (!is_dir_only) {
  202. efree(file_basename);
  203. free(new_state.cwd);
  204. }
  205. return 0;
  206. }
  207. }
  208. /* it is a standalone directory, job done */
  209. if (is_dir_only) {
  210. efree(file_dirname_fullpath);
  211. free(new_state.cwd);
  212. return 1;
  213. }
  214. len = spprintf(&fullpath, 0, "%s/%s", file_dirname_fullpath, file_basename);
  215. if (!len) {
  216. efree(file_dirname_fullpath);
  217. efree(file_basename);
  218. free(new_state.cwd);
  219. return 0;
  220. } else if (len > MAXPATHLEN) {
  221. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Full extraction path exceed MAXPATHLEN (%i)", MAXPATHLEN);
  222. efree(file_dirname_fullpath);
  223. efree(file_basename);
  224. free(new_state.cwd);
  225. return 0;
  226. }
  227. /* check again the full path, not sure if it
  228. * is required, does a file can have a different
  229. * safemode status as its parent folder?
  230. */
  231. if (ZIP_OPENBASEDIR_CHECKPATH(fullpath)) {
  232. efree(fullpath);
  233. efree(file_dirname_fullpath);
  234. efree(file_basename);
  235. free(new_state.cwd);
  236. return 0;
  237. }
  238. #if PHP_API_VERSION < 20100412
  239. stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
  240. #else
  241. stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL);
  242. #endif
  243. if (stream == NULL) {
  244. n = -1;
  245. goto done;
  246. }
  247. zf = zip_fopen(za, file, 0);
  248. if (zf == NULL) {
  249. n = -1;
  250. php_stream_close(stream);
  251. goto done;
  252. }
  253. n = 0;
  254. while ((n=zip_fread(zf, b, sizeof(b))) > 0) {
  255. php_stream_write(stream, b, n);
  256. }
  257. php_stream_close(stream);
  258. n = zip_fclose(zf);
  259. done:
  260. efree(fullpath);
  261. efree(file_basename);
  262. efree(file_dirname_fullpath);
  263. free(new_state.cwd);
  264. if (n<0) {
  265. return 0;
  266. } else {
  267. return 1;
  268. }
  269. }
  270. /* }}} */
  271. static int php_zip_add_file(struct zip *za, const char *filename, size_t filename_len,
  272. char *entry_name, size_t entry_name_len, long offset_start, long offset_len TSRMLS_DC) /* {{{ */
  273. {
  274. struct zip_source *zs;
  275. char resolved_path[MAXPATHLEN];
  276. zval exists_flag;
  277. if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
  278. return -1;
  279. }
  280. if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
  281. return -1;
  282. }
  283. php_stat(resolved_path, strlen(resolved_path), FS_EXISTS, &exists_flag TSRMLS_CC);
  284. if (!Z_BVAL(exists_flag)) {
  285. return -1;
  286. }
  287. zs = zip_source_file(za, resolved_path, offset_start, offset_len);
  288. if (!zs) {
  289. return -1;
  290. }
  291. if (zip_file_add(za, entry_name, zs, ZIP_FL_OVERWRITE) < 0) {
  292. zip_source_free(zs);
  293. return -1;
  294. } else {
  295. zip_error_clear(za);
  296. return 1;
  297. }
  298. }
  299. /* }}} */
  300. static int php_zip_parse_options(zval *options, long *remove_all_path,
  301. char **remove_path, int *remove_path_len, char **add_path, int *add_path_len TSRMLS_DC) /* {{{ */
  302. {
  303. zval **option;
  304. if (zend_hash_find(HASH_OF(options), "remove_all_path", sizeof("remove_all_path"), (void **)&option) == SUCCESS) {
  305. long opt;
  306. if (Z_TYPE_PP(option) != IS_LONG) {
  307. zval tmp = **option;
  308. zval_copy_ctor(&tmp);
  309. convert_to_long(&tmp);
  310. opt = Z_LVAL(tmp);
  311. } else {
  312. opt = Z_LVAL_PP(option);
  313. }
  314. *remove_all_path = opt;
  315. }
  316. /* If I add more options, it would make sense to create a nice static struct and loop over it. */
  317. if (zend_hash_find(HASH_OF(options), "remove_path", sizeof("remove_path"), (void **)&option) == SUCCESS) {
  318. if (Z_TYPE_PP(option) != IS_STRING) {
  319. php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path option expected to be a string");
  320. return -1;
  321. }
  322. if (Z_STRLEN_PP(option) < 1) {
  323. php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string given as remove_path option");
  324. return -1;
  325. }
  326. if (Z_STRLEN_PP(option) >= MAXPATHLEN) {
  327. php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path string is too long (max: %i, %i given)",
  328. MAXPATHLEN - 1, Z_STRLEN_PP(option));
  329. return -1;
  330. }
  331. *remove_path_len = Z_STRLEN_PP(option);
  332. *remove_path = Z_STRVAL_PP(option);
  333. }
  334. if (zend_hash_find(HASH_OF(options), "add_path", sizeof("add_path"), (void **)&option) == SUCCESS) {
  335. if (Z_TYPE_PP(option) != IS_STRING) {
  336. php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path option expected to be a string");
  337. return -1;
  338. }
  339. if (Z_STRLEN_PP(option) < 1) {
  340. php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string given as the add_path option");
  341. return -1;
  342. }
  343. if (Z_STRLEN_PP(option) >= MAXPATHLEN) {
  344. php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)",
  345. MAXPATHLEN - 1, Z_STRLEN_PP(option));
  346. return -1;
  347. }
  348. *add_path_len = Z_STRLEN_PP(option);
  349. *add_path = Z_STRVAL_PP(option);
  350. }
  351. return 1;
  352. }
  353. /* }}} */
  354. /* {{{ REGISTER_ZIP_CLASS_CONST_LONG */
  355. #define REGISTER_ZIP_CLASS_CONST_LONG(const_name, value) \
  356. zend_declare_class_constant_long(zip_class_entry, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
  357. /* }}} */
  358. /* {{{ ZIP_FROM_OBJECT */
  359. #define ZIP_FROM_OBJECT(intern, object) \
  360. { \
  361. ze_zip_object *obj = (ze_zip_object*) zend_object_store_get_object(object TSRMLS_CC); \
  362. intern = obj->za; \
  363. if (!intern) { \
  364. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or uninitialized Zip object"); \
  365. RETURN_FALSE; \
  366. } \
  367. }
  368. /* }}} */
  369. /* {{{ RETURN_SB(sb) */
  370. #define RETURN_SB(sb) \
  371. { \
  372. array_init(return_value); \
  373. add_ascii_assoc_string(return_value, "name", (char *)(sb)->name, 1); \
  374. add_ascii_assoc_long(return_value, "index", (long) (sb)->index); \
  375. add_ascii_assoc_long(return_value, "crc", (long) (sb)->crc); \
  376. add_ascii_assoc_long(return_value, "size", (long) (sb)->size); \
  377. add_ascii_assoc_long(return_value, "mtime", (long) (sb)->mtime); \
  378. add_ascii_assoc_long(return_value, "comp_size", (long) (sb)->comp_size); \
  379. add_ascii_assoc_long(return_value, "comp_method", (long) (sb)->comp_method); \
  380. }
  381. /* }}} */
  382. static int php_zip_status(struct zip *za TSRMLS_DC) /* {{{ */
  383. {
  384. int zep, syp;
  385. zip_error_get(za, &zep, &syp);
  386. return zep;
  387. }
  388. /* }}} */
  389. static int php_zip_status_sys(struct zip *za TSRMLS_DC) /* {{{ */
  390. {
  391. int zep, syp;
  392. zip_error_get(za, &zep, &syp);
  393. return syp;
  394. }
  395. /* }}} */
  396. static int php_zip_get_num_files(struct zip *za TSRMLS_DC) /* {{{ */
  397. {
  398. return zip_get_num_files(za);
  399. }
  400. /* }}} */
  401. static char * php_zipobj_get_filename(ze_zip_object *obj TSRMLS_DC) /* {{{ */
  402. {
  403. if (!obj) {
  404. return NULL;
  405. }
  406. if (obj->filename) {
  407. return obj->filename;
  408. }
  409. return NULL;
  410. }
  411. /* }}} */
  412. static char * php_zipobj_get_zip_comment(struct zip *za, int *len TSRMLS_DC) /* {{{ */
  413. {
  414. if (za) {
  415. return (char *)zip_get_archive_comment(za, len, 0);
  416. }
  417. return NULL;
  418. }
  419. /* }}} */
  420. #ifdef HAVE_GLOB /* {{{ */
  421. #ifndef GLOB_ONLYDIR
  422. #define GLOB_ONLYDIR (1<<30)
  423. #define GLOB_EMULATE_ONLYDIR
  424. #define GLOB_FLAGMASK (~GLOB_ONLYDIR)
  425. #else
  426. #define GLOB_FLAGMASK (~0)
  427. #endif
  428. #ifndef GLOB_BRACE
  429. # define GLOB_BRACE 0
  430. #endif
  431. #ifndef GLOB_MARK
  432. # define GLOB_MARK 0
  433. #endif
  434. #ifndef GLOB_NOSORT
  435. # define GLOB_NOSORT 0
  436. #endif
  437. #ifndef GLOB_NOCHECK
  438. # define GLOB_NOCHECK 0
  439. #endif
  440. #ifndef GLOB_NOESCAPE
  441. # define GLOB_NOESCAPE 0
  442. #endif
  443. #ifndef GLOB_ERR
  444. # define GLOB_ERR 0
  445. #endif
  446. /* This is used for checking validity of passed flags (passing invalid flags causes segfault in glob()!! */
  447. #define GLOB_AVAILABLE_FLAGS (0 | GLOB_BRACE | GLOB_MARK | GLOB_NOSORT | GLOB_NOCHECK | GLOB_NOESCAPE | GLOB_ERR | GLOB_ONLYDIR)
  448. #endif /* }}} */
  449. int php_zip_glob(char *pattern, int pattern_len, long flags, zval *return_value TSRMLS_DC) /* {{{ */
  450. {
  451. #ifdef HAVE_GLOB
  452. char cwd[MAXPATHLEN];
  453. int cwd_skip = 0;
  454. #ifdef ZTS
  455. char work_pattern[MAXPATHLEN];
  456. char *result;
  457. #endif
  458. glob_t globbuf;
  459. int n;
  460. int ret;
  461. if (pattern_len >= MAXPATHLEN) {
  462. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
  463. return -1;
  464. }
  465. if ((GLOB_AVAILABLE_FLAGS & flags) != flags) {
  466. php_error_docref(NULL TSRMLS_CC, E_WARNING, "At least one of the passed flags is invalid or not supported on this platform");
  467. return -1;
  468. }
  469. #ifdef ZTS
  470. if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) {
  471. result = VCWD_GETCWD(cwd, MAXPATHLEN);
  472. if (!result) {
  473. cwd[0] = '\0';
  474. }
  475. #ifdef PHP_WIN32
  476. if (IS_SLASH(*pattern)) {
  477. cwd[2] = '\0';
  478. }
  479. #endif
  480. cwd_skip = strlen(cwd)+1;
  481. snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
  482. pattern = work_pattern;
  483. }
  484. #endif
  485. globbuf.gl_offs = 0;
  486. if (0 != (ret = glob(pattern, flags & GLOB_FLAGMASK, NULL, &globbuf))) {
  487. #ifdef GLOB_NOMATCH
  488. if (GLOB_NOMATCH == ret) {
  489. /* Some glob implementation simply return no data if no matches
  490. were found, others return the GLOB_NOMATCH error code.
  491. We don't want to treat GLOB_NOMATCH as an error condition
  492. so that PHP glob() behaves the same on both types of
  493. implementations and so that 'foreach (glob() as ...'
  494. can be used for simple glob() calls without further error
  495. checking.
  496. */
  497. array_init(return_value);
  498. return 0;
  499. }
  500. #endif
  501. return 0;
  502. }
  503. /* now catch the FreeBSD style of "no matches" */
  504. if (!globbuf.gl_pathc || !globbuf.gl_pathv) {
  505. array_init(return_value);
  506. return 0;
  507. }
  508. /* we assume that any glob pattern will match files from one directory only
  509. so checking the dirname of the first match should be sufficient */
  510. strncpy(cwd, globbuf.gl_pathv[0], MAXPATHLEN);
  511. if (ZIP_OPENBASEDIR_CHECKPATH(cwd)) {
  512. return -1;
  513. }
  514. array_init(return_value);
  515. for (n = 0; n < globbuf.gl_pathc; n++) {
  516. /* we need to do this everytime since GLOB_ONLYDIR does not guarantee that
  517. * all directories will be filtered. GNU libc documentation states the
  518. * following:
  519. * If the information about the type of the file is easily available
  520. * non-directories will be rejected but no extra work will be done to
  521. * determine the information for each file. I.e., the caller must still be
  522. * able to filter directories out.
  523. */
  524. if (flags & GLOB_ONLYDIR) {
  525. struct stat s;
  526. if (0 != VCWD_STAT(globbuf.gl_pathv[n], &s)) {
  527. continue;
  528. }
  529. if (S_IFDIR != (s.st_mode & S_IFMT)) {
  530. continue;
  531. }
  532. }
  533. add_next_index_string(return_value, globbuf.gl_pathv[n]+cwd_skip, 1);
  534. }
  535. globfree(&globbuf);
  536. return globbuf.gl_pathc;
  537. #else
  538. php_error_docref(NULL TSRMLS_CC, E_ERROR, "Glob support is not available");
  539. return 0;
  540. #endif /* HAVE_GLOB */
  541. }
  542. /* }}} */
  543. int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *return_value TSRMLS_DC) /* {{{ */
  544. {
  545. #ifdef ZTS
  546. char cwd[MAXPATHLEN];
  547. int cwd_skip = 0;
  548. char work_path[MAXPATHLEN];
  549. char *result;
  550. #endif
  551. int files_cnt;
  552. char **namelist;
  553. #ifdef ZTS
  554. if (!IS_ABSOLUTE_PATH(path, path_len)) {
  555. result = VCWD_GETCWD(cwd, MAXPATHLEN);
  556. if (!result) {
  557. cwd[0] = '\0';
  558. }
  559. #ifdef PHP_WIN32
  560. if (IS_SLASH(*path)) {
  561. cwd[2] = '\0';
  562. }
  563. #endif
  564. cwd_skip = strlen(cwd)+1;
  565. snprintf(work_path, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, path);
  566. path = work_path;
  567. }
  568. #endif
  569. if (ZIP_OPENBASEDIR_CHECKPATH(path)) {
  570. return -1;
  571. }
  572. files_cnt = php_stream_scandir(path, &namelist, NULL, (void *) php_stream_dirent_alphasort);
  573. if (files_cnt > 0) {
  574. pcre *re = NULL;
  575. pcre_extra *pcre_extra = NULL;
  576. int preg_options = 0, i;
  577. re = pcre_get_compiled_regex(regexp, &pcre_extra, &preg_options TSRMLS_CC);
  578. if (!re) {
  579. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid expression");
  580. return -1;
  581. }
  582. array_init(return_value);
  583. /* only the files, directories are ignored */
  584. for (i = 0; i < files_cnt; i++) {
  585. struct stat s;
  586. char fullpath[MAXPATHLEN];
  587. int ovector[3];
  588. int matches;
  589. int namelist_len = strlen(namelist[i]);
  590. if ((namelist_len == 1 && namelist[i][0] == '.') ||
  591. (namelist_len == 2 && namelist[i][0] == '.' && namelist[i][1] == '.')) {
  592. efree(namelist[i]);
  593. continue;
  594. }
  595. if ((path_len + namelist_len + 1) >= MAXPATHLEN) {
  596. php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)",
  597. MAXPATHLEN - 1, (path_len + namelist_len + 1));
  598. efree(namelist[i]);
  599. break;
  600. }
  601. snprintf(fullpath, MAXPATHLEN, "%s%c%s", path, DEFAULT_SLASH, namelist[i]);
  602. if (0 != VCWD_STAT(fullpath, &s)) {
  603. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot read <%s>", fullpath);
  604. efree(namelist[i]);
  605. continue;
  606. }
  607. if (S_IFDIR == (s.st_mode & S_IFMT)) {
  608. efree(namelist[i]);
  609. continue;
  610. }
  611. matches = pcre_exec(re, NULL, namelist[i], strlen(namelist[i]), 0, 0, ovector, 3);
  612. /* 0 means that the vector is too small to hold all the captured substring offsets */
  613. if (matches < 0) {
  614. efree(namelist[i]);
  615. continue;
  616. }
  617. add_next_index_string(return_value, fullpath, 1);
  618. efree(namelist[i]);
  619. }
  620. efree(namelist);
  621. }
  622. return files_cnt;
  623. }
  624. /* }}} */
  625. #endif
  626. /* {{{ arginfo */
  627. ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_open, 0, 0, 1)
  628. ZEND_ARG_INFO(0, filename)
  629. ZEND_END_ARG_INFO()
  630. ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_close, 0, 0, 1)
  631. ZEND_ARG_INFO(0, zip)
  632. ZEND_END_ARG_INFO()
  633. ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_read, 0, 0, 1)
  634. ZEND_ARG_INFO(0, zip)
  635. ZEND_END_ARG_INFO()
  636. ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_open, 0, 0, 2)
  637. ZEND_ARG_INFO(0, zip_dp)
  638. ZEND_ARG_INFO(0, zip_entry)
  639. ZEND_ARG_INFO(0, mode)
  640. ZEND_END_ARG_INFO()
  641. ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_close, 0, 0, 1)
  642. ZEND_ARG_INFO(0, zip_ent)
  643. ZEND_END_ARG_INFO()
  644. ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_read, 0, 0, 1)
  645. ZEND_ARG_INFO(0, zip_entry)
  646. ZEND_ARG_INFO(0, len)
  647. ZEND_END_ARG_INFO()
  648. ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_name, 0, 0, 1)
  649. ZEND_ARG_INFO(0, zip_entry)
  650. ZEND_END_ARG_INFO()
  651. ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressedsize, 0, 0, 1)
  652. ZEND_ARG_INFO(0, zip_entry)
  653. ZEND_END_ARG_INFO()
  654. ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_filesize, 0, 0, 1)
  655. ZEND_ARG_INFO(0, zip_entry)
  656. ZEND_END_ARG_INFO()
  657. ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressionmethod, 0, 0, 1)
  658. ZEND_ARG_INFO(0, zip_entry)
  659. ZEND_END_ARG_INFO()
  660. /* }}} */
  661. /* {{{ zend_function_entry */
  662. static const zend_function_entry zip_functions[] = {
  663. ZEND_RAW_FENTRY("zip_open", zif_zip_open, arginfo_zip_open, 0)
  664. ZEND_RAW_FENTRY("zip_close", zif_zip_close, arginfo_zip_close, 0)
  665. ZEND_RAW_FENTRY("zip_read", zif_zip_read, arginfo_zip_read, 0)
  666. PHP_FE(zip_entry_open, arginfo_zip_entry_open)
  667. PHP_FE(zip_entry_close, arginfo_zip_entry_close)
  668. PHP_FE(zip_entry_read, arginfo_zip_entry_read)
  669. PHP_FE(zip_entry_filesize, arginfo_zip_entry_filesize)
  670. PHP_FE(zip_entry_name, arginfo_zip_entry_name)
  671. PHP_FE(zip_entry_compressedsize, arginfo_zip_entry_compressedsize)
  672. PHP_FE(zip_entry_compressionmethod, arginfo_zip_entry_compressionmethod)
  673. #ifdef PHP_FE_END
  674. PHP_FE_END
  675. #else
  676. {NULL,NULL,NULL}
  677. #endif
  678. };
  679. /* }}} */
  680. /* {{{ ZE2 OO definitions */
  681. #ifdef PHP_ZIP_USE_OO
  682. static zend_class_entry *zip_class_entry;
  683. static zend_object_handlers zip_object_handlers;
  684. static HashTable zip_prop_handlers;
  685. typedef int (*zip_read_int_t)(struct zip *za TSRMLS_DC);
  686. typedef char *(*zip_read_const_char_t)(struct zip *za, int *len TSRMLS_DC);
  687. typedef char *(*zip_read_const_char_from_ze_t)(ze_zip_object *obj TSRMLS_DC);
  688. typedef struct _zip_prop_handler {
  689. zip_read_int_t read_int_func;
  690. zip_read_const_char_t read_const_char_func;
  691. zip_read_const_char_from_ze_t read_const_char_from_obj_func;
  692. int type;
  693. } zip_prop_handler;
  694. #endif
  695. /* }}} */
  696. #ifdef PHP_ZIP_USE_OO
  697. 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, zip_read_const_char_from_ze_t read_char_from_obj_func, int rettype TSRMLS_DC) /* {{{ */
  698. {
  699. zip_prop_handler hnd;
  700. hnd.read_const_char_func = read_char_func;
  701. hnd.read_int_func = read_int_func;
  702. hnd.read_const_char_from_obj_func = read_char_from_obj_func;
  703. hnd.type = rettype;
  704. zend_hash_add(prop_handler, name, strlen(name)+1, &hnd, sizeof(zip_prop_handler), NULL);
  705. }
  706. /* }}} */
  707. static int php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, zval **retval, int newzval TSRMLS_DC) /* {{{ */
  708. {
  709. const char *retchar = NULL;
  710. int retint = 0;
  711. int len = 0;
  712. if (obj && obj->za != NULL) {
  713. if (hnd->read_const_char_func) {
  714. retchar = hnd->read_const_char_func(obj->za, &len TSRMLS_CC);
  715. } else {
  716. if (hnd->read_int_func) {
  717. retint = hnd->read_int_func(obj->za TSRMLS_CC);
  718. if (retint == -1) {
  719. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal zip error returned");
  720. return FAILURE;
  721. }
  722. } else {
  723. if (hnd->read_const_char_from_obj_func) {
  724. retchar = hnd->read_const_char_from_obj_func(obj TSRMLS_CC);
  725. len = strlen(retchar);
  726. }
  727. }
  728. }
  729. }
  730. if (newzval) {
  731. ALLOC_ZVAL(*retval);
  732. }
  733. switch (hnd->type) {
  734. case IS_STRING:
  735. if (retchar) {
  736. ZVAL_STRINGL(*retval, (char *) retchar, len, 1);
  737. } else {
  738. ZVAL_EMPTY_STRING(*retval);
  739. }
  740. break;
  741. case IS_BOOL:
  742. ZVAL_BOOL(*retval, (long)retint);
  743. break;
  744. case IS_LONG:
  745. ZVAL_LONG(*retval, (long)retint);
  746. break;
  747. default:
  748. ZVAL_NULL(*retval);
  749. }
  750. return SUCCESS;
  751. }
  752. /* }}} */
  753. static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member TYPE_ARG_DC KEY_ARG_DC TSRMLS_DC) /* {{{ */
  754. {
  755. ze_zip_object *obj;
  756. zval tmp_member;
  757. zval **retval = NULL;
  758. zip_prop_handler *hnd;
  759. zend_object_handlers *std_hnd;
  760. int ret;
  761. if (member->type != IS_STRING) {
  762. tmp_member = *member;
  763. zval_copy_ctor(&tmp_member);
  764. convert_to_string(&tmp_member);
  765. member = &tmp_member;
  766. #if PHP_VERSION_ID >= 50400
  767. key = NULL;
  768. #endif
  769. }
  770. ret = FAILURE;
  771. obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
  772. if (obj->prop_handler != NULL) {
  773. #if PHP_VERSION_ID >= 50400
  774. if (key) {
  775. ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
  776. } else
  777. #endif
  778. ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
  779. }
  780. if (ret == FAILURE) {
  781. std_hnd = zend_get_std_object_handlers();
  782. retval = std_hnd->get_property_ptr_ptr(object, member TYPE_ARG_CC KEY_ARG_CC TSRMLS_CC);
  783. }
  784. if (member == &tmp_member) {
  785. zval_dtor(member);
  786. }
  787. return retval;
  788. }
  789. /* }}} */
  790. static zval* php_zip_read_property(zval *object, zval *member, int type KEY_ARG_DC TSRMLS_DC) /* {{{ */
  791. {
  792. ze_zip_object *obj;
  793. zval tmp_member;
  794. zval *retval;
  795. zip_prop_handler *hnd;
  796. zend_object_handlers *std_hnd;
  797. int ret;
  798. if (member->type != IS_STRING) {
  799. tmp_member = *member;
  800. zval_copy_ctor(&tmp_member);
  801. convert_to_string(&tmp_member);
  802. member = &tmp_member;
  803. #if PHP_VERSION_ID >= 50400
  804. key = NULL;
  805. #endif
  806. }
  807. ret = FAILURE;
  808. obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
  809. if (obj->prop_handler != NULL) {
  810. #if PHP_VERSION_ID >= 50400
  811. if (key) {
  812. ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
  813. } else
  814. #endif
  815. ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
  816. }
  817. if (ret == SUCCESS) {
  818. ret = php_zip_property_reader(obj, hnd, &retval, 1 TSRMLS_CC);
  819. if (ret == SUCCESS) {
  820. /* ensure we're creating a temporary variable */
  821. Z_SET_REFCOUNT_P(retval, 0);
  822. } else {
  823. retval = EG(uninitialized_zval_ptr);
  824. }
  825. } else {
  826. std_hnd = zend_get_std_object_handlers();
  827. retval = std_hnd->read_property(object, member, type KEY_ARG_CC TSRMLS_CC);
  828. }
  829. if (member == &tmp_member) {
  830. zval_dtor(member);
  831. }
  832. return retval;
  833. }
  834. /* }}} */
  835. static int php_zip_has_property(zval *object, zval *member, int type KEY_ARG_DC TSRMLS_DC) /* {{{ */
  836. {
  837. ze_zip_object *obj;
  838. zval tmp_member;
  839. zip_prop_handler *hnd;
  840. zend_object_handlers *std_hnd;
  841. int ret, retval = 0;
  842. if (member->type != IS_STRING) {
  843. tmp_member = *member;
  844. zval_copy_ctor(&tmp_member);
  845. convert_to_string(&tmp_member);
  846. member = &tmp_member;
  847. #if PHP_VERSION_ID >= 50400
  848. key = NULL;
  849. #endif
  850. }
  851. ret = FAILURE;
  852. obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
  853. if (obj->prop_handler != NULL) {
  854. #if PHP_VERSION_ID >= 50400
  855. if (key) {
  856. ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
  857. } else
  858. #endif
  859. ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
  860. }
  861. if (ret == SUCCESS) {
  862. zval *tmp;
  863. ALLOC_INIT_ZVAL(tmp);
  864. if (type == 2) {
  865. retval = 1;
  866. } else if (php_zip_property_reader(obj, hnd, &tmp, 0 TSRMLS_CC) == SUCCESS) {
  867. Z_SET_REFCOUNT_P(tmp, 1);
  868. Z_UNSET_ISREF_P(tmp);
  869. if (type == 1) {
  870. retval = zend_is_true(tmp);
  871. } else if (type == 0) {
  872. retval = (Z_TYPE_P(tmp) != IS_NULL);
  873. }
  874. }
  875. zval_ptr_dtor(&tmp);
  876. } else {
  877. std_hnd = zend_get_std_object_handlers();
  878. retval = std_hnd->has_property(object, member, type KEY_ARG_CC TSRMLS_CC);
  879. }
  880. if (member == &tmp_member) {
  881. zval_dtor(member);
  882. }
  883. return retval;
  884. }
  885. /* }}} */
  886. static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */
  887. {
  888. ze_zip_object *obj;
  889. zip_prop_handler *hnd;
  890. HashTable *props;
  891. zval *val;
  892. int ret;
  893. char *key;
  894. uint key_len;
  895. HashPosition pos;
  896. ulong num_key;
  897. obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
  898. props = zend_std_get_properties(object TSRMLS_CC);
  899. if (obj->prop_handler == NULL) {
  900. return NULL;
  901. }
  902. zend_hash_internal_pointer_reset_ex(obj->prop_handler, &pos);
  903. while (zend_hash_get_current_data_ex(obj->prop_handler, (void**)&hnd, &pos) == SUCCESS) {
  904. zend_hash_get_current_key_ex(obj->prop_handler, &key, &key_len, &num_key, 0, &pos);
  905. MAKE_STD_ZVAL(val);
  906. ret = php_zip_property_reader(obj, hnd, &val, 0 TSRMLS_CC);
  907. if (ret != SUCCESS) {
  908. val = EG(uninitialized_zval_ptr);
  909. }
  910. zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL);
  911. zend_hash_move_forward_ex(obj->prop_handler, &pos);
  912. }
  913. return props;
  914. }
  915. /* }}} */
  916. static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */
  917. {
  918. ze_zip_object * intern = (ze_zip_object *) object;
  919. int i;
  920. if (!intern) {
  921. return;
  922. }
  923. if (intern->za) {
  924. if (zip_close(intern->za) != 0) {
  925. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot destroy the zip context");
  926. return;
  927. }
  928. intern->za = NULL;
  929. }
  930. if (intern->buffers_cnt>0) {
  931. for (i=0; i<intern->buffers_cnt; i++) {
  932. efree(intern->buffers[i]);
  933. }
  934. efree(intern->buffers);
  935. }
  936. intern->za = NULL;
  937. #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
  938. zend_object_std_dtor(&intern->zo TSRMLS_CC);
  939. #else
  940. if (intern->zo.guards) {
  941. zend_hash_destroy(intern->zo.guards);
  942. FREE_HASHTABLE(intern->zo.guards);
  943. }
  944. if (intern->zo.properties) {
  945. zend_hash_destroy(intern->zo.properties);
  946. FREE_HASHTABLE(intern->zo.properties);
  947. }
  948. #endif
  949. if (intern->filename) {
  950. efree(intern->filename);
  951. }
  952. efree(intern);
  953. }
  954. /* }}} */
  955. static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
  956. {
  957. #if PHP_VERSION_ID < 50400
  958. zval *tmp;
  959. #endif
  960. ze_zip_object *intern;
  961. zend_object_value retval;
  962. intern = emalloc(sizeof(ze_zip_object));
  963. memset(&intern->zo, 0, sizeof(zend_object));
  964. intern->za = NULL;
  965. intern->buffers = NULL;
  966. intern->filename = NULL;
  967. intern->buffers_cnt = 0;
  968. intern->prop_handler = &zip_prop_handlers;
  969. #if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2))
  970. zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
  971. #else
  972. ALLOC_HASHTABLE(intern->zo.properties);
  973. zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
  974. intern->zo.ce = class_type;
  975. #endif
  976. #if PHP_VERSION_ID < 50400
  977. zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,
  978. (void *) &tmp, sizeof(zval *));
  979. #else
  980. object_properties_init(&intern->zo, class_type);
  981. #endif
  982. retval.handle = zend_objects_store_put(intern,
  983. NULL,
  984. (zend_objects_free_object_storage_t) php_zip_object_free_storage,
  985. NULL TSRMLS_CC);
  986. retval.handlers = (zend_object_handlers *) & zip_object_handlers;
  987. return retval;
  988. }
  989. /* }}} */
  990. #endif
  991. /* {{{ Resource dtors */
  992. /* {{{ php_zip_free_dir */
  993. static void php_zip_free_dir(zend_rsrc_list_entry *rsrc TSRMLS_DC)
  994. {
  995. zip_rsrc * zip_int = (zip_rsrc *) rsrc->ptr;
  996. if (zip_int) {
  997. if (zip_int->za) {
  998. if (zip_close(zip_int->za) != 0) {
  999. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot destroy the zip context");
  1000. }
  1001. zip_int->za = NULL;
  1002. }
  1003. efree(rsrc->ptr);
  1004. rsrc->ptr = NULL;
  1005. }
  1006. }
  1007. /* }}} */
  1008. /* {{{ php_zip_free_entry */
  1009. static void php_zip_free_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC)
  1010. {
  1011. zip_read_rsrc *zr_rsrc = (zip_read_rsrc *) rsrc->ptr;
  1012. if (zr_rsrc) {
  1013. if (zr_rsrc->zf) {
  1014. zip_fclose(zr_rsrc->zf);
  1015. zr_rsrc->zf = NULL;
  1016. }
  1017. efree(zr_rsrc);
  1018. rsrc->ptr = NULL;
  1019. }
  1020. }
  1021. /* }}} */
  1022. /* }}}*/
  1023. /* reset macro */
  1024. /* {{{ function prototypes */
  1025. static PHP_MINIT_FUNCTION(zip);
  1026. static PHP_MSHUTDOWN_FUNCTION(zip);
  1027. static PHP_MINFO_FUNCTION(zip);
  1028. /* }}} */
  1029. /* {{{ zip_module_entry
  1030. */
  1031. zend_module_entry zip_module_entry = {
  1032. STANDARD_MODULE_HEADER,
  1033. "zip",
  1034. zip_functions,
  1035. PHP_MINIT(zip),
  1036. PHP_MSHUTDOWN(zip),
  1037. NULL,
  1038. NULL,
  1039. PHP_MINFO(zip),
  1040. PHP_ZIP_VERSION,
  1041. STANDARD_MODULE_PROPERTIES
  1042. };
  1043. /* }}} */
  1044. #ifdef COMPILE_DL_ZIP
  1045. ZEND_GET_MODULE(zip)
  1046. #endif
  1047. /* set macro */
  1048. /* {{{ proto resource zip_open(string filename)
  1049. Create new zip using source uri for output */
  1050. static PHP_NAMED_FUNCTION(zif_zip_open)
  1051. {
  1052. char *filename;
  1053. int filename_len;
  1054. char resolved_path[MAXPATHLEN + 1];
  1055. zip_rsrc *rsrc_int;
  1056. int err = 0;
  1057. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH, &filename, &filename_len) == FAILURE) {
  1058. return;
  1059. }
  1060. if (filename_len == 0) {
  1061. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
  1062. RETURN_FALSE;
  1063. }
  1064. if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
  1065. RETURN_FALSE;
  1066. }
  1067. if(!expand_filepath(filename, resolved_path TSRMLS_CC)) {
  1068. RETURN_FALSE;
  1069. }
  1070. rsrc_int = (zip_rsrc *)emalloc(sizeof(zip_rsrc));
  1071. rsrc_int->za = zip_open(resolved_path, 0, &err);
  1072. if (rsrc_int->za == NULL) {
  1073. efree(rsrc_int);
  1074. RETURN_LONG((long)err);
  1075. }
  1076. rsrc_int->index_current = 0;
  1077. rsrc_int->num_files = zip_get_num_files(rsrc_int->za);
  1078. ZEND_REGISTER_RESOURCE(return_value, rsrc_int, le_zip_dir);
  1079. }
  1080. /* }}} */
  1081. /* {{{ proto void zip_close(resource zip)
  1082. Close a Zip archive */
  1083. static PHP_NAMED_FUNCTION(zif_zip_close)
  1084. {
  1085. zval * zip;
  1086. zip_rsrc *z_rsrc = NULL;
  1087. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip) == FAILURE) {
  1088. return;
  1089. }
  1090. ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir);
  1091. /* really close the zip will break BC :-D */
  1092. zend_list_delete(Z_LVAL_P(zip));
  1093. }
  1094. /* }}} */
  1095. /* {{{ proto resource zip_read(resource zip)
  1096. Returns the next file in the archive */
  1097. static PHP_NAMED_FUNCTION(zif_zip_read)
  1098. {
  1099. zval *zip_dp;
  1100. zip_read_rsrc *zr_rsrc;
  1101. int ret;
  1102. zip_rsrc *rsrc_int;
  1103. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_dp) == FAILURE) {
  1104. return;
  1105. }
  1106. ZEND_FETCH_RESOURCE(rsrc_int, zip_rsrc *, &zip_dp, -1, le_zip_dir_name, le_zip_dir);
  1107. if (rsrc_int && rsrc_int->za) {
  1108. if (rsrc_int->index_current >= rsrc_int->num_files) {
  1109. RETURN_FALSE;
  1110. }
  1111. zr_rsrc = emalloc(sizeof(zip_read_rsrc));
  1112. ret = zip_stat_index(rsrc_int->za, rsrc_int->index_current, 0, &zr_rsrc->sb);
  1113. if (ret != 0) {
  1114. efree(zr_rsrc);
  1115. RETURN_FALSE;
  1116. }
  1117. zr_rsrc->zf = zip_fopen_index(rsrc_int->za, rsrc_int->index_current, 0);
  1118. if (zr_rsrc->zf) {
  1119. rsrc_int->index_current++;
  1120. ZEND_REGISTER_RESOURCE(return_value, zr_rsrc, le_zip_entry);
  1121. } else {
  1122. efree(zr_rsrc);
  1123. RETURN_FALSE;
  1124. }
  1125. } else {
  1126. RETURN_FALSE;
  1127. }
  1128. }
  1129. /* }}} */
  1130. /* {{{ proto bool zip_entry_open(resource zip_dp, resource zip_entry [, string mode])
  1131. Open a Zip File, pointed by the resource entry */
  1132. /* Dummy function to follow the old API */
  1133. static PHP_NAMED_FUNCTION(zif_zip_entry_open)
  1134. {
  1135. zval * zip;
  1136. zval * zip_entry;
  1137. char *mode = NULL;
  1138. int mode_len = 0;
  1139. zip_read_rsrc * zr_rsrc;
  1140. zip_rsrc *z_rsrc;
  1141. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|s", &zip, &zip_entry, &mode, &mode_len) == FAILURE) {
  1142. return;
  1143. }
  1144. ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
  1145. ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir);
  1146. if (zr_rsrc->zf != NULL) {
  1147. RETURN_TRUE;
  1148. } else {
  1149. RETURN_FALSE;
  1150. }
  1151. }
  1152. /* }}} */
  1153. /* {{{ proto bool zip_entry_close(resource zip_ent)
  1154. Close a zip entry */
  1155. static PHP_NAMED_FUNCTION(zif_zip_entry_close)
  1156. {
  1157. zval * zip_entry;
  1158. zip_read_rsrc * zr_rsrc;
  1159. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) {
  1160. return;
  1161. }
  1162. ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
  1163. RETURN_BOOL(SUCCESS == zend_list_delete(Z_LVAL_P(zip_entry)));
  1164. }
  1165. /* }}} */
  1166. /* {{{ proto mixed zip_entry_read(resource zip_entry [, int len])
  1167. Read from an open directory entry */
  1168. static PHP_NAMED_FUNCTION(zif_zip_entry_read)
  1169. {
  1170. zval * zip_entry;
  1171. long len = 0;
  1172. zip_read_rsrc * zr_rsrc;
  1173. char *buffer;
  1174. int n = 0;
  1175. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zip_entry, &len) == FAILURE) {
  1176. return;
  1177. }
  1178. ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
  1179. if (len <= 0) {
  1180. len = 1024;
  1181. }
  1182. if (zr_rsrc->zf) {
  1183. buffer = safe_emalloc(len, 1, 1);
  1184. n = zip_fread(zr_rsrc->zf, buffer, len);
  1185. if (n > 0) {
  1186. buffer[n] = 0;
  1187. RETURN_STRINGL(buffer, n, 0);
  1188. } else {
  1189. efree(buffer);
  1190. RETURN_EMPTY_STRING()
  1191. }
  1192. } else {
  1193. RETURN_FALSE;
  1194. }
  1195. }
  1196. /* }}} */
  1197. static void php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS, int opt) /* {{{ */
  1198. {
  1199. zval * zip_entry;
  1200. zip_read_rsrc * zr_rsrc;
  1201. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) {
  1202. return;
  1203. }
  1204. ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
  1205. if (!zr_rsrc->zf) {
  1206. RETURN_FALSE;
  1207. }
  1208. switch (opt) {
  1209. case 0:
  1210. RETURN_STRING((char *)zr_rsrc->sb.name, 1);
  1211. break;
  1212. case 1:
  1213. RETURN_LONG((long) (zr_rsrc->sb.comp_size));
  1214. break;
  1215. case 2:
  1216. RETURN_LONG((long) (zr_rsrc->sb.size));
  1217. break;
  1218. case 3:
  1219. switch (zr_rsrc->sb.comp_method) {
  1220. case 0:
  1221. RETURN_STRING("stored", 1);
  1222. break;
  1223. case 1:
  1224. RETURN_STRING("shrunk", 1);
  1225. break;
  1226. case 2:
  1227. case 3:
  1228. case 4:
  1229. case 5:
  1230. RETURN_STRING("reduced", 1);
  1231. break;
  1232. case 6:
  1233. RETURN_STRING("imploded", 1);
  1234. break;
  1235. case 7:
  1236. RETURN_STRING("tokenized", 1);
  1237. break;
  1238. case 8:
  1239. RETURN_STRING("deflated", 1);
  1240. break;
  1241. case 9:
  1242. RETURN_STRING("deflatedX", 1);
  1243. break;
  1244. case 10:
  1245. RETURN_STRING("implodedX", 1);
  1246. break;
  1247. default:
  1248. RETURN_FALSE;
  1249. }
  1250. RETURN_LONG((long) (zr_rsrc->sb.comp_method));
  1251. break;
  1252. }
  1253. }
  1254. /* }}} */
  1255. /* {{{ proto string zip_entry_name(resource zip_entry)
  1256. Return the name given a ZZip entry */
  1257. static PHP_NAMED_FUNCTION(zif_zip_entry_name)
  1258. {
  1259. php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  1260. }
  1261. /* }}} */
  1262. /* {{{ proto int zip_entry_compressedsize(resource zip_entry)
  1263. Return the compressed size of a ZZip entry */
  1264. static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize)
  1265. {
  1266. php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  1267. }
  1268. /* }}} */
  1269. /* {{{ proto int zip_entry_filesize(resource zip_entry)
  1270. Return the actual filesize of a ZZip entry */
  1271. static PHP_NAMED_FUNCTION(zif_zip_entry_filesize)
  1272. {
  1273. php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
  1274. }
  1275. /* }}} */
  1276. /* {{{ proto string zip_entry_compressionmethod(resource zip_entry)
  1277. Return a string containing the compression method used on a particular entry */
  1278. static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod)
  1279. {
  1280. php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
  1281. }
  1282. /* }}} */
  1283. #ifdef PHP_ZIP_USE_OO
  1284. /* {{{ proto mixed ZipArchive::open(string source [, int flags])
  1285. Create new zip using source uri for output, return TRUE on success or the error code */
  1286. static ZIPARCHIVE_METHOD(open)
  1287. {
  1288. struct zip *intern;
  1289. char *filename;
  1290. int filename_len;
  1291. int err = 0;
  1292. long flags = 0;
  1293. char *resolved_path;
  1294. zval *this = getThis();
  1295. ze_zip_object *ze_obj = NULL;
  1296. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|l", &filename, &filename_len, &flags) == FAILURE) {
  1297. return;
  1298. }
  1299. if (this) {
  1300. /* We do not use ZIP_FROM_OBJECT, zip init function here */
  1301. ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
  1302. }
  1303. if (filename_len == 0) {
  1304. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
  1305. RETURN_FALSE;
  1306. }
  1307. if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
  1308. RETURN_FALSE;
  1309. }
  1310. if (!(resolved_path = expand_filepath(filename, NULL TSRMLS_CC))) {
  1311. RETURN_FALSE;
  1312. }
  1313. if (ze_obj->za) {
  1314. /* we already have an opened zip, free it */
  1315. if (zip_close(ze_obj->za) != 0) {
  1316. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
  1317. RETURN_FALSE;
  1318. }
  1319. ze_obj->za = NULL;
  1320. }
  1321. if (ze_obj->filename) {
  1322. efree(ze_obj->filename);
  1323. ze_obj->filename = NULL;
  1324. }
  1325. intern = zip_open(resolved_path, flags, &err);
  1326. if (!intern || err) {
  1327. RETURN_LONG((long)err);
  1328. }
  1329. ze_obj->filename = resolved_path;
  1330. ze_obj->filename_len = strlen(resolved_path);
  1331. ze_obj->za = intern;
  1332. RETURN_TRUE;
  1333. }
  1334. /* }}} */
  1335. /* {{{ proto resource ZipArchive::setPassword(string password)
  1336. Set the password for the active archive */
  1337. static ZIPARCHIVE_METHOD(setPassword)
  1338. {
  1339. struct zip *intern;
  1340. zval *this = getThis();
  1341. char *password;
  1342. int password_len;
  1343. if (!this) {
  1344. RETURN_FALSE;
  1345. }
  1346. ZIP_FROM_OBJECT(intern, this);
  1347. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &password, &password_len) == FAILURE) {
  1348. return;
  1349. }
  1350. if (password_len < 1) {
  1351. RETURN_FALSE;
  1352. } else {
  1353. int res = zip_set_default_password(intern, (const char *)password);
  1354. if (res == 0) {
  1355. RETURN_TRUE;
  1356. } else {
  1357. RETURN_FALSE;
  1358. }
  1359. }
  1360. }
  1361. /* }}} */
  1362. /* {{{ proto bool ZipArchive::close()
  1363. close the zip archive */
  1364. static ZIPARCHIVE_METHOD(close)
  1365. {
  1366. struct zip *intern;
  1367. zval *this = getThis();
  1368. ze_zip_object *ze_obj;
  1369. if (!this) {
  1370. RETURN_FALSE;
  1371. }
  1372. ZIP_FROM_OBJECT(intern, this);
  1373. ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
  1374. if (zip_close(intern)) {
  1375. zip_discard(intern);
  1376. }
  1377. efree(ze_obj->filename);
  1378. ze_obj->filename = NULL;
  1379. ze_obj->filename_len = 0;
  1380. ze_obj->za = NULL;
  1381. RETURN_TRUE;
  1382. }
  1383. /* }}} */
  1384. /* {{{ proto string ZipArchive::getStatusString()
  1385. * Returns the status error message, system and/or zip messages */
  1386. static ZIPARCHIVE_METHOD(getStatusString)
  1387. {
  1388. struct zip *intern;
  1389. zval *this = getThis();
  1390. int zep, syp, len;
  1391. char error_string[128];
  1392. if (!this) {
  1393. RETURN_FALSE;
  1394. }
  1395. ZIP_FROM_OBJECT(intern, this);
  1396. zip_error_get(intern, &zep, &syp);
  1397. len = zip_error_to_str(error_string, 128, zep, syp);
  1398. RETVAL_STRINGL(error_string, len, 1);
  1399. }
  1400. /* }}} */
  1401. /* {{{ proto bool ZipArchive::createEmptyDir(string dirname)
  1402. Returns the index of the entry named filename in the archive */
  1403. static ZIPARCHIVE_METHOD(addEmptyDir)
  1404. {
  1405. struct zip *intern;
  1406. zval *this = getThis();
  1407. char *dirname;
  1408. int dirname_len;
  1409. int idx;
  1410. struct zip_stat sb;
  1411. char *s;
  1412. if (!this) {
  1413. RETURN_FALSE;
  1414. }
  1415. ZIP_FROM_OBJECT(intern, this);
  1416. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
  1417. &dirname, &dirname_len) == FAILURE) {
  1418. return;
  1419. }
  1420. if (dirname_len<1) {
  1421. RETURN_FALSE;
  1422. }
  1423. if (dirname[dirname_len-1] != '/') {
  1424. s=(char *)emalloc(dirname_len+2);
  1425. strcpy(s, dirname);
  1426. s[dirname_len] = '/';
  1427. s[dirname_len+1] = '\0';
  1428. } else {
  1429. s = dirname;
  1430. }
  1431. idx = zip_stat(intern, s, 0, &sb);
  1432. if (idx >= 0) {
  1433. RETVAL_FALSE;
  1434. } else {
  1435. if (zip_add_dir(intern, (const char *)s) == -1) {
  1436. RETVAL_FALSE;
  1437. }
  1438. zip_error_clear(intern);
  1439. RETVAL_TRUE;
  1440. }
  1441. if (s != dirname) {
  1442. efree(s);
  1443. }
  1444. }
  1445. /* }}} */
  1446. static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
  1447. {
  1448. struct zip *intern;
  1449. zval *this = getThis();
  1450. char *pattern;
  1451. char *path = NULL;
  1452. char *remove_path = NULL;
  1453. char *add_path = NULL;
  1454. int pattern_len, add_path_len, remove_path_len = 0, path_len = 0;
  1455. long remove_all_path = 0;
  1456. long flags = 0;
  1457. zval *options = NULL;
  1458. int found;
  1459. if (!this) {
  1460. RETURN_FALSE;
  1461. }
  1462. ZIP_FROM_OBJECT(intern, this);
  1463. /* 1 == glob, 2==pcre */
  1464. if (type == 1) {
  1465. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|la",
  1466. &pattern, &pattern_len, &flags, &options) == FAILURE) {
  1467. return;
  1468. }
  1469. } else {
  1470. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|sa",
  1471. &pattern, &pattern_len, &path, &path_len, &options) == FAILURE) {
  1472. return;
  1473. }
  1474. }
  1475. if (pattern_len == 0) {
  1476. php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as pattern");
  1477. RETURN_FALSE;
  1478. }
  1479. if (options && (php_zip_parse_options(options, &remove_all_path, &remove_path, &remove_path_len,
  1480. &add_path, &add_path_len TSRMLS_CC) < 0)) {
  1481. RETURN_FALSE;
  1482. }
  1483. if (remove_path && remove_path_len > 1 && (remove_path[strlen(remove_path) - 1] == '/' ||
  1484. remove_path[strlen(remove_path) - 1] == '\\')) {
  1485. remove_path[strlen(remove_path) - 1] = '\0';
  1486. }
  1487. if (type == 1) {
  1488. found = php_zip_glob(pattern, pattern_len, flags, return_value TSRMLS_CC);
  1489. } else {
  1490. found = php_zip_pcre(pattern, pattern_len, path, path_len, return_value TSRMLS_CC);
  1491. }
  1492. if (found > 0) {
  1493. int i;
  1494. zval **zval_file = NULL;
  1495. for (i = 0; i < found; i++) {
  1496. char *file_stripped, *entry_name;
  1497. size_t entry_name_len, file_stripped_len;
  1498. char entry_name_buf[MAXPATHLEN];
  1499. char *basename = NULL;
  1500. if (zend_hash_index_find(Z_ARRVAL_P(return_value), i, (void **) &zval_file) == SUCCESS) {
  1501. if (remove_all_path) {
  1502. php_basename(Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file), NULL, 0,
  1503. &basename, (size_t *)&file_stripped_len TSRMLS_CC);
  1504. file_stripped = basename;
  1505. } else if (remove_path && strstr(Z_STRVAL_PP(zval_file), remove_path) != NULL) {
  1506. file_stripped = Z_STRVAL_PP(zval_file) + remove_path_len + 1;
  1507. file_stripped_len = Z_STRLEN_PP(zval_file) - remove_path_len - 1;
  1508. } else {
  1509. file_stripped = Z_STRVAL_PP(zval_file);
  1510. file_stripped_len = Z_STRLEN_PP(zval_file);
  1511. }
  1512. if (add_path) {
  1513. if ((add_path_len + file_stripped_len) > MAXPATHLEN) {
  1514. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Entry name too long (max: %d, %ld given)",
  1515. MAXPATHLEN - 1, (add_path_len + file_stripped_len));
  1516. zval_dtor(return_value);
  1517. RETURN_FALSE;
  1518. }
  1519. snprintf(entry_name_buf, MAXPATHLEN, "%s%s", add_path, file_stripped);
  1520. entry_name = entry_name_buf;
  1521. entry_name_len = strlen(entry_name);
  1522. } else {
  1523. entry_name = Z_STRVAL_PP(zval_file);
  1524. entry_name_len = Z_STRLEN_PP(zval_file);
  1525. }
  1526. if (basename) {
  1527. efree(basename);
  1528. basename = NULL;
  1529. }
  1530. if (php_zip_add_file(intern, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file),
  1531. entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
  1532. zval_dtor(return_value);
  1533. RETURN_FALSE;
  1534. }
  1535. }
  1536. }
  1537. }
  1538. }
  1539. /* }}} */
  1540. /* {{{ proto bool ZipArchive::addGlob(string pattern[,int flags [, array options]])
  1541. Add files matching the glob pattern. See php's glob for the pattern syntax. */
  1542. static ZIPARCHIVE_METHOD(addGlob)
  1543. {
  1544. php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  1545. }
  1546. /* }}} */
  1547. /* {{{ proto bool ZipArchive::addPattern(string pattern[, string path [, array options]])
  1548. Add files matching the pcre pattern. See php's pcre for the pattern syntax. */
  1549. static ZIPARCHIVE_METHOD(addPattern)
  1550. {
  1551. php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
  1552. }
  1553. /* }}} */
  1554. /* {{{ proto bool ZipArchive::addFile(string filepath[, string entryname[, int start [, int length]]])
  1555. Add a file in a Zip archive using its path and the name to use. */
  1556. static ZIPARCHIVE_METHOD(addFile)
  1557. {
  1558. struct zip *intern;
  1559. zval *this = getThis();
  1560. char *filename;
  1561. int filename_len;
  1562. char *entry_name = NULL;
  1563. int entry_name_len = 0;
  1564. long offset_start = 0, offset_len = 0;
  1565. if (!this) {
  1566. RETURN_FALSE;
  1567. }
  1568. ZIP_FROM_OBJECT(intern, this);
  1569. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|sll",
  1570. &filename, &filename_len, &entry_name, &entry_name_len, &offset_start, &offset_len) == FAILURE) {
  1571. return;
  1572. }
  1573. if (filename_len == 0) {
  1574. php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as filename");
  1575. RETURN_FALSE;
  1576. }
  1577. if (entry_name_len == 0) {
  1578. entry_name = filename;
  1579. entry_name_len = filename_len;
  1580. }
  1581. if (php_zip_add_file(intern, filename, filename_len,
  1582. entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
  1583. RETURN_FALSE;
  1584. } else {
  1585. RETURN_TRUE;
  1586. }
  1587. }
  1588. /* }}} */
  1589. /* {{{ proto bool ZipArchive::addFromString(string name, string content)
  1590. Add a file using content and the entry name */
  1591. static ZIPARCHIVE_METHOD(addFromString)
  1592. {
  1593. struct zip *intern;
  1594. zval *this = getThis();
  1595. char *buffer, *name;
  1596. int buffer_len, name_len;
  1597. ze_zip_object *ze_obj;
  1598. struct zip_source *zs;
  1599. int pos = 0;
  1600. int cur_idx;
  1601. if (!this) {
  1602. RETURN_FALSE;
  1603. }
  1604. ZIP_FROM_OBJECT(intern, this);
  1605. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
  1606. &name, &name_len, &buffer, &buffer_len) == FAILURE) {
  1607. return;
  1608. }
  1609. ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
  1610. if (ze_obj->buffers_cnt) {
  1611. ze_obj->buffers = (char **)erealloc(ze_obj->buffers, sizeof(char *) * (ze_obj->buffers_cnt+1));
  1612. pos = ze_obj->buffers_cnt++;
  1613. } else {
  1614. ze_obj->buffers = (char **)emalloc(sizeof(char *));
  1615. ze_obj->buffers_cnt++;
  1616. pos = 0;
  1617. }
  1618. ze_obj->buffers[pos] = (char *)emalloc(buffer_len + 1);
  1619. memcpy(ze_obj->buffers[pos], buffer, buffer_len + 1);
  1620. zs = zip_source_buffer(intern, ze_obj->buffers[pos], buffer_len, 0);
  1621. if (zs == NULL) {
  1622. RETURN_FALSE;
  1623. }
  1624. cur_idx = zip_name_locate(intern, (const char *)name, 0);
  1625. /* TODO: fix _zip_replace */
  1626. if (cur_idx >= 0) {
  1627. if (zip_delete(intern, cur_idx) == -1) {
  1628. zip_source_free(zs);
  1629. RETURN_FALSE;
  1630. }
  1631. }
  1632. if (zip_add(intern, name, zs) == -1) {
  1633. zip_source_free(zs);
  1634. RETURN_FALSE;
  1635. } else {
  1636. zip_error_clear(intern);
  1637. RETURN_TRUE;
  1638. }
  1639. }
  1640. /* }}} */
  1641. /* {{{ proto array ZipArchive::statName(string filename[, int flags])
  1642. Returns the information about a the zip entry filename */
  1643. static ZIPARCHIVE_METHOD(statName)
  1644. {
  1645. struct zip *intern;
  1646. zval *this = getThis();
  1647. char *name;
  1648. int name_len;
  1649. long flags = 0;
  1650. struct zip_stat sb;
  1651. if (!this) {
  1652. RETURN_FALSE;
  1653. }
  1654. ZIP_FROM_OBJECT(intern, this);
  1655. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|l",
  1656. &name, &name_len, &flags) == FAILURE) {
  1657. return;
  1658. }
  1659. PHP_ZIP_STAT_PATH(intern, name, name_len, flags, sb);
  1660. RETURN_SB(&sb);
  1661. }
  1662. /* }}} */
  1663. /* {{{ proto resource ZipArchive::statIndex(int index[, int flags])
  1664. Returns the zip entry informations using its index */
  1665. static ZIPARCHIVE_METHOD(statIndex)
  1666. {
  1667. struct zip *intern;
  1668. zval *this = getThis();
  1669. long index, flags = 0;
  1670. struct zip_stat sb;
  1671. if (!this) {
  1672. RETURN_FALSE;
  1673. }
  1674. ZIP_FROM_OBJECT(intern, this);
  1675. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
  1676. &index, &flags) == FAILURE) {
  1677. return;
  1678. }
  1679. if (zip_stat_index(intern, index, flags, &sb) != 0) {
  1680. RETURN_FALSE;
  1681. }
  1682. RETURN_SB(&sb);
  1683. }
  1684. /* }}} */
  1685. /* {{{ proto int ZipArchive::locateName(string filename[, int flags])
  1686. Returns the index of the entry named filename in the archive */
  1687. static ZIPARCHIVE_METHOD(locateName)
  1688. {
  1689. struct zip *intern;
  1690. zval *this = getThis();
  1691. char *name;
  1692. int name_len;
  1693. long flags = 0;
  1694. long idx = -1;
  1695. if (!this) {
  1696. RETURN_FALSE;
  1697. }
  1698. ZIP_FROM_OBJECT(intern, this);
  1699. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|l",
  1700. &name, &name_len, &flags) == FAILURE) {
  1701. return;
  1702. }
  1703. if (name_len<1) {
  1704. RETURN_FALSE;
  1705. }
  1706. idx = (long)zip_name_locate(intern, (const char *)name, flags);
  1707. if (idx >= 0) {
  1708. RETURN_LONG(idx);
  1709. } else {
  1710. RETURN_FALSE;
  1711. }
  1712. }
  1713. /* }}} */
  1714. /* {{{ proto string ZipArchive::getN…

Large files files are truncated, but you can click here to view the full file