PageRenderTime 53ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/php-5.4.5/ext/zip/php_zip.c

#
C | 3120 lines | 2351 code | 492 blank | 277 comment | 506 complexity | 7f0482418a0a32be742181d5dae9b266 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.1

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

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