php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
php_zip.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Piere-Alain Joye <pierre@php.net> |
14 +----------------------------------------------------------------------+
15*/
16
17
18#ifdef HAVE_CONFIG_H
19#include <config.h>
20#endif
21
22#include "php.h"
23#include "ext/standard/info.h"
24#include "ext/standard/file.h"
25#include "ext/standard/php_string.h" /* For php_basename() */
26#include "ext/pcre/php_pcre.h"
28#include "zend_attributes.h"
29#include "zend_interfaces.h"
30#include "php_zip.h"
31#include "php_zip_arginfo.h"
32
33#ifdef HAVE_GLOB
34#ifndef PHP_WIN32
35#include <glob.h>
36#else
37#include "win32/glob.h"
38#endif
39#endif
40
41/* {{{ Resource le */
42static int le_zip_dir;
43#define le_zip_dir_name "Zip Directory"
44static int le_zip_entry;
45#define le_zip_entry_name "Zip Entry"
46/* }}} */
47
48/* {{{ PHP_ZIP_STAT_INDEX(za, index, flags, sb) */
49#define PHP_ZIP_STAT_INDEX(za, index, flags, sb) \
50 if (zip_stat_index(za, index, flags, &sb) != 0) { \
51 RETURN_FALSE; \
52 }
53/* }}} */
54
55/* {{{ PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb)
56 This is always used for the first argument*/
57#define PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) \
58 if (path_len == 0) { \
59 zend_argument_must_not_be_empty_error(1); \
60 RETURN_THROWS(); \
61 } \
62 if (zip_stat(za, path, flags, &sb) != 0) { \
63 RETURN_FALSE; \
64 }
65/* }}} */
66
67/* {{{ PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) */
68#define PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) \
69 if (comment_len == 0) { \
70 /* Passing NULL remove the existing comment */ \
71 if (zip_file_set_comment(za, index, NULL, 0, 0) < 0) { \
72 RETURN_FALSE; \
73 } \
74 } else if (zip_file_set_comment(za, index, comment, comment_len, 0) < 0) { \
75 RETURN_FALSE; \
76 } \
77 RETURN_TRUE;
78/* }}} */
79
80# define add_ascii_assoc_string add_assoc_string
81# define add_ascii_assoc_long add_assoc_long
82
83/* Flatten a path by making a relative path (to .)*/
84static char * php_zip_make_relative_path(char *path, size_t path_len) /* {{{ */
85{
86 char *path_begin = path;
87 size_t i;
88
89 if (path_len < 1 || path == NULL) {
90 return NULL;
91 }
92
93 if (IS_ABSOLUTE_PATH(path, path_len)) {
94 return path + COPY_WHEN_ABSOLUTE(path) + 1;
95 }
96
97 i = path_len;
98
99 while (1) {
100 while (i > 0 && !IS_SLASH(path[i])) {
101 i--;
102 }
103
104 if (!i) {
105 return path;
106 }
107
108 if (i >= 2 && path[i -1] == '.') {
109 /* i is the position of ., add 1 for / */
110 path_begin = path + i + 1;
111 break;
112 }
113 i--;
114 }
115
116 return path_begin;
117}
118/* }}} */
119
120# define CWD_STATE_ALLOC(l) emalloc(l)
121# define CWD_STATE_FREE(s) efree(s)
122
123/* {{{ php_zip_extract_file */
124static int php_zip_extract_file(struct zip * za, char *dest, const char *file, size_t file_len, zip_int64_t idx)
125{
127 struct zip_file *zf;
128 struct zip_stat sb;
129 char b[8192];
130 int n, ret;
131 php_stream *stream;
132 char *fullpath;
133 char *file_dirname_fullpath;
134 char file_dirname[MAXPATHLEN];
135 size_t dir_len, len;
136 int is_dir_only = 0;
137 char *path_cleaned;
138 size_t path_cleaned_len;
139 cwd_state new_state;
140 zend_string *file_basename;
141
142 if (idx < 0) {
143 idx = zip_name_locate(za, file, 0);
144 if (idx < 0) {
145 return 0;
146 }
147 }
148 new_state.cwd = CWD_STATE_ALLOC(1);
149 new_state.cwd[0] = '\0';
150 new_state.cwd_length = 0;
151
152 /* Clean/normlize the path and then transform any path (absolute or relative)
153 to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt)
154 */
155 virtual_file_ex(&new_state, file, NULL, CWD_EXPAND);
156 path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length);
157 if(!path_cleaned) {
158 CWD_STATE_FREE(new_state.cwd);
159 return 0;
160 }
161 path_cleaned_len = strlen(path_cleaned);
162
163 if (path_cleaned_len >= MAXPATHLEN || zip_stat_index(za, idx, 0, &sb) != 0) {
164 CWD_STATE_FREE(new_state.cwd);
165 return 0;
166 }
167
168 /* it is a directory only, see #40228 */
169 if (path_cleaned_len > 1 && IS_SLASH(path_cleaned[path_cleaned_len - 1])) {
170 len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, path_cleaned);
171 is_dir_only = 1;
172 } else {
173 memcpy(file_dirname, path_cleaned, path_cleaned_len);
174 dir_len = zend_dirname(file_dirname, path_cleaned_len);
175
176 if (!dir_len || (dir_len == 1 && file_dirname[0] == '.')) {
177 len = spprintf(&file_dirname_fullpath, 0, "%s", dest);
178 } else {
179 len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file_dirname);
180 }
181
182 file_basename = php_basename(path_cleaned, path_cleaned_len, NULL, 0);
183
184 if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname_fullpath)) {
185 efree(file_dirname_fullpath);
186 zend_string_release_ex(file_basename, 0);
187 CWD_STATE_FREE(new_state.cwd);
188 return 0;
189 }
190 }
191
192 /* let see if the path already exists */
193 if (php_stream_stat_path_ex(file_dirname_fullpath, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
194 ret = php_stream_mkdir(file_dirname_fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE|REPORT_ERRORS, NULL);
195 if (!ret) {
196 efree(file_dirname_fullpath);
197 if (!is_dir_only) {
198 zend_string_release_ex(file_basename, 0);
199 }
200 CWD_STATE_FREE(new_state.cwd);
201 return 0;
202 }
203 }
204
205 /* it is a standalone directory, job done */
206 if (is_dir_only) {
207 efree(file_dirname_fullpath);
208 CWD_STATE_FREE(new_state.cwd);
209 return 1;
210 }
211
212 len = spprintf(&fullpath, 0, "%s/%s", file_dirname_fullpath, ZSTR_VAL(file_basename));
213 if (!len) {
214 efree(file_dirname_fullpath);
215 zend_string_release_ex(file_basename, 0);
216 CWD_STATE_FREE(new_state.cwd);
217 return 0;
218 } else if (len > MAXPATHLEN) {
219 php_error_docref(NULL, E_WARNING, "Full extraction path exceed MAXPATHLEN (%i)", MAXPATHLEN);
220 efree(file_dirname_fullpath);
221 zend_string_release_ex(file_basename, 0);
222 CWD_STATE_FREE(new_state.cwd);
223 return 0;
224 }
225
226 /* check again the full path, not sure if it
227 * is required, does a file can have a different
228 * safemode status as its parent folder?
229 */
230 if (ZIP_OPENBASEDIR_CHECKPATH(fullpath)) {
231 efree(fullpath);
232 efree(file_dirname_fullpath);
233 zend_string_release_ex(file_basename, 0);
234 CWD_STATE_FREE(new_state.cwd);
235 return 0;
236 }
237
238 zf = zip_fopen_index(za, idx, 0);
239 if (zf == NULL) {
240 n = -1;
241 goto done;
242 }
243
244 stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL);
245
246 if (stream == NULL) {
247 n = -1;
248 zip_fclose(zf);
249 goto done;
250 }
251
252 n = 0;
253
254 while ((n=zip_fread(zf, b, sizeof(b))) > 0) {
255 php_stream_write(stream, b, n);
256 }
257
258 if (stream->wrapper->wops->stream_metadata) {
259 struct utimbuf ut;
260
261 ut.modtime = ut.actime = sb.mtime;
262 stream->wrapper->wops->stream_metadata(stream->wrapper, fullpath, PHP_STREAM_META_TOUCH, &ut, NULL);
263 }
264
265 php_stream_close(stream);
266 n = zip_fclose(zf);
267
268done:
269 efree(fullpath);
270 zend_string_release_ex(file_basename, 0);
271 efree(file_dirname_fullpath);
272 CWD_STATE_FREE(new_state.cwd);
273
274 if (n<0) {
275 return 0;
276 } else {
277 return 1;
278 }
279}
280/* }}} */
281
282static int php_zip_add_file(ze_zip_object *obj, const char *filename, size_t filename_len,
283 char *entry_name, size_t entry_name_len, /* unused if replace >= 0 */
284 zip_uint64_t offset_start, zip_uint64_t offset_len,
285 zend_long replace, /* index to replace, add new file if < 0 */
286 zip_flags_t flags
287) /* {{{ */
288{
289 struct zip_source *zs;
290 char resolved_path[MAXPATHLEN];
292
293 if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
294 return -1;
295 }
296
297 if (!expand_filepath(filename, resolved_path)) {
298 php_error_docref(NULL, E_WARNING, "No such file or directory");
299 return -1;
300 }
301
302 if (php_stream_stat_path_ex(resolved_path, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL)) {
303 php_error_docref(NULL, E_WARNING, "No such file or directory");
304 return -1;
305 }
306
308 FILE *fd;
309 fd = fopen(resolved_path, "rb");
310 if (!fd) {
311 return -1;
312 }
314 zs = zip_source_filep(obj->za, fd, offset_start, offset_len);
315 } else {
316 zs = zip_source_file(obj->za, resolved_path, offset_start, offset_len);
317 }
318 if (!zs) {
319 return -1;
320 }
321 /* Replace */
322 if (replace >= 0) {
323 if (zip_file_replace(obj->za, replace, zs, flags) < 0) {
324 zip_source_free(zs);
325 return -1;
326 }
327 zip_error_clear(obj->za);
328 return 1;
329 }
330 /* Add */
331 obj->last_id = zip_file_add(obj->za, entry_name, zs, flags);
332 if (obj->last_id < 0) {
333 zip_source_free(zs);
334 return -1;
335 }
336 zip_error_clear(obj->za);
337 return 1;
338}
339/* }}} */
340
341typedef struct {
345 char *add_path;
347 zip_flags_t flags;
348 zip_int32_t comp_method;
349 zip_uint32_t comp_flags;
350#ifdef HAVE_ENCRYPTION
351 zip_int16_t enc_method;
352 char *enc_password;
353#endif
355
356/* Expects opts to be zero-initialized. */
357static int php_zip_parse_options(HashTable *options, zip_options *opts)
358/* {{{ */
359{
360 zval *option;
361
362 /* default values */
363 opts->flags = ZIP_FL_OVERWRITE;
364 opts->comp_method = -1; /* -1 to not change default */
365#ifdef HAVE_ENCRYPTION
366 opts->enc_method = -1; /* -1 to not change default */
367#endif
368
369 if ((option = zend_hash_str_find(options, "remove_all_path", sizeof("remove_all_path") - 1)) != NULL) {
370 if (Z_TYPE_P(option) != IS_FALSE && Z_TYPE_P(option) != IS_TRUE) {
371 php_error_docref(NULL, E_WARNING, "Option \"remove_all_path\" must be of type bool, %s given",
372 zend_zval_value_name(option));
373 }
374 opts->remove_all_path = zval_get_long(option);
375 }
376
377 if ((option = zend_hash_str_find(options, "comp_method", sizeof("comp_method") - 1)) != NULL) {
378 if (Z_TYPE_P(option) != IS_LONG) {
379 php_error_docref(NULL, E_WARNING, "Option \"comp_method\" must be of type int, %s given",
380 zend_zval_value_name(option));
381 }
382 opts->comp_method = zval_get_long(option);
383
384 if ((option = zend_hash_str_find(options, "comp_flags", sizeof("comp_flags") - 1)) != NULL) {
385 if (Z_TYPE_P(option) != IS_LONG) {
386 php_error_docref(NULL, E_WARNING, "Option \"comp_flags\" must be of type int, %s given",
387 zend_zval_value_name(option));
388 }
389 opts->comp_flags = zval_get_long(option);
390 }
391 }
392
393#ifdef HAVE_ENCRYPTION
394 if ((option = zend_hash_str_find(options, "enc_method", sizeof("enc_method") - 1)) != NULL) {
395 if (Z_TYPE_P(option) != IS_LONG) {
396 php_error_docref(NULL, E_WARNING, "Option \"enc_method\" must be of type int, %s given",
397 zend_zval_value_name(option));
398 }
399 opts->enc_method = zval_get_long(option);
400
401 if ((option = zend_hash_str_find(options, "enc_password", sizeof("enc_password") - 1)) != NULL) {
402 if (Z_TYPE_P(option) != IS_STRING) {
403 zend_type_error("Option \"enc_password\" must be of type string, %s given",
404 zend_zval_value_name(option));
405 return -1;
406 }
407 opts->enc_password = Z_STRVAL_P(option);
408 }
409 }
410#endif
411
412 if ((option = zend_hash_str_find(options, "remove_path", sizeof("remove_path") - 1)) != NULL) {
413 if (Z_TYPE_P(option) != IS_STRING) {
414 zend_type_error("Option \"remove_path\" must be of type string, %s given",
415 zend_zval_value_name(option));
416 return -1;
417 }
418
419 if (Z_STRLEN_P(option) == 0) {
420 zend_value_error("Option \"remove_path\" must not be empty");
421 return -1;
422 }
423
424 if (Z_STRLEN_P(option) >= MAXPATHLEN) {
425 zend_value_error("Option \"remove_path\" must be less than %d bytes", MAXPATHLEN - 1);
426 return -1;
427 }
428 opts->remove_path_len = Z_STRLEN_P(option);
429 opts->remove_path = Z_STRVAL_P(option);
430 }
431
432 if ((option = zend_hash_str_find(options, "add_path", sizeof("add_path") - 1)) != NULL) {
433 if (Z_TYPE_P(option) != IS_STRING) {
434 zend_type_error("Option \"add_path\" must be of type string, %s given",
435 zend_zval_value_name(option));
436 return -1;
437 }
438
439 if (Z_STRLEN_P(option) == 0) {
440 zend_value_error("Option \"add_path\" must not be empty");
441 return -1;
442 }
443
444 if (Z_STRLEN_P(option) >= MAXPATHLEN) {
445 zend_value_error("Option \"add_path\" must be less than %d bytes", MAXPATHLEN - 1);
446 return -1;
447 }
448 opts->add_path_len = Z_STRLEN_P(option);
449 opts->add_path = Z_STRVAL_P(option);
450 }
451
452 if ((option = zend_hash_str_find(options, "flags", sizeof("flags") - 1)) != NULL) {
453 if (Z_TYPE_P(option) != IS_LONG) {
454 zend_type_error("Option \"flags\" must be of type int, %s given",
455 zend_zval_value_name(option));
456 return -1;
457 }
458 opts->flags = Z_LVAL_P(option);
459 }
460
461 return 1;
462}
463/* }}} */
464
465/* {{{ ZIP_FROM_OBJECT */
466#define ZIP_FROM_OBJECT(intern, object) \
467 { \
468 ze_zip_object *obj = Z_ZIP_P(object); \
469 intern = obj->za; \
470 if (!intern) { \
471 zend_value_error("Invalid or uninitialized Zip object"); \
472 RETURN_THROWS(); \
473 } \
474 }
475/* }}} */
476
477/* {{{ RETURN_SB(sb) */
478#ifdef HAVE_ENCRYPTION
479#define RETURN_SB(sb) \
480 { \
481 array_init(return_value); \
482 add_ascii_assoc_string(return_value, "name", (char *)(sb)->name); \
483 add_ascii_assoc_long(return_value, "index", (zend_long) (sb)->index); \
484 add_ascii_assoc_long(return_value, "crc", (zend_long) (sb)->crc); \
485 add_ascii_assoc_long(return_value, "size", (zend_long) (sb)->size); \
486 add_ascii_assoc_long(return_value, "mtime", (zend_long) (sb)->mtime); \
487 add_ascii_assoc_long(return_value, "comp_size", (zend_long) (sb)->comp_size); \
488 add_ascii_assoc_long(return_value, "comp_method", (zend_long) (sb)->comp_method); \
489 add_ascii_assoc_long(return_value, "encryption_method", (zend_long) (sb)->encryption_method); \
490 }
491#else
492#define RETURN_SB(sb) \
493 { \
494 array_init(return_value); \
495 add_ascii_assoc_string(return_value, "name", (char *)(sb)->name); \
496 add_ascii_assoc_long(return_value, "index", (zend_long) (sb)->index); \
497 add_ascii_assoc_long(return_value, "crc", (zend_long) (sb)->crc); \
498 add_ascii_assoc_long(return_value, "size", (zend_long) (sb)->size); \
499 add_ascii_assoc_long(return_value, "mtime", (zend_long) (sb)->mtime); \
500 add_ascii_assoc_long(return_value, "comp_size", (zend_long) (sb)->comp_size); \
501 add_ascii_assoc_long(return_value, "comp_method", (zend_long) (sb)->comp_method); \
502 }
503#endif
504/* }}} */
505
506static zend_long php_zip_status(ze_zip_object *obj) /* {{{ */
507{
508 int zep = obj->err_zip; /* saved err if closed */
509
510 if (obj->za) {
511#if LIBZIP_VERSION_MAJOR < 1
512 int syp;
513
514 zip_error_get(obj->za, &zep, &syp);
515#else
516 zip_error_t *err;
517
518 err = zip_get_error(obj->za);
519 zep = zip_error_code_zip(err);
520 zip_error_fini(err);
521#endif
522 }
523 return zep;
524}
525/* }}} */
526
527static zend_long php_zip_last_id(ze_zip_object *obj) /* {{{ */
528{
529 return obj->last_id;
530}
531/* }}} */
532
533static zend_long php_zip_status_sys(ze_zip_object *obj) /* {{{ */
534{
535 int syp = obj->err_sys; /* saved err if closed */
536
537 if (obj->za) {
538#if LIBZIP_VERSION_MAJOR < 1
539 int zep;
540
541 zip_error_get(obj->za, &zep, &syp);
542#else
543 zip_error_t *err;
544
545 err = zip_get_error(obj->za);
546 syp = zip_error_code_system(err);
547 zip_error_fini(err);
548#endif
549 }
550 return syp;
551}
552/* }}} */
553
554static zend_long php_zip_get_num_files(ze_zip_object *obj) /* {{{ */
555{
556 if (obj->za) {
557 zip_int64_t num = zip_get_num_entries(obj->za, 0);
558 return MIN(num, ZEND_LONG_MAX);
559 }
560 return 0;
561}
562/* }}} */
563
564static char * php_zipobj_get_filename(ze_zip_object *obj, int *len) /* {{{ */
565{
566 if (obj && obj->filename) {
567 *len = strlen(obj->filename);
568 return obj->filename;
569 }
570 return NULL;
571}
572/* }}} */
573
574static char * php_zipobj_get_zip_comment(ze_zip_object *obj, int *len) /* {{{ */
575{
576 if (obj->za) {
577 return (char *)zip_get_archive_comment(obj->za, len, 0);
578 }
579 return NULL;
580}
581/* }}} */
582
583#ifdef HAVE_GLOB /* {{{ */
584#ifndef GLOB_ONLYDIR
585#define GLOB_ONLYDIR (1<<30)
586#define GLOB_EMULATE_ONLYDIR
587#define GLOB_FLAGMASK (~GLOB_ONLYDIR)
588#else
589#define GLOB_FLAGMASK (~0)
590#endif
591#ifndef GLOB_BRACE
592# define GLOB_BRACE 0
593#endif
594#ifndef GLOB_MARK
595# define GLOB_MARK 0
596#endif
597#ifndef GLOB_NOSORT
598# define GLOB_NOSORT 0
599#endif
600#ifndef GLOB_NOCHECK
601# define GLOB_NOCHECK 0
602#endif
603#ifndef GLOB_NOESCAPE
604# define GLOB_NOESCAPE 0
605#endif
606#ifndef GLOB_ERR
607# define GLOB_ERR 0
608#endif
609
610/* This is used for checking validity of passed flags (passing invalid flags causes segfault in glob()!! */
611#define GLOB_AVAILABLE_FLAGS (0 | GLOB_BRACE | GLOB_MARK | GLOB_NOSORT | GLOB_NOCHECK | GLOB_NOESCAPE | GLOB_ERR | GLOB_ONLYDIR)
612
613#endif /* }}} */
614
615int php_zip_glob(char *pattern, int pattern_len, zend_long flags, zval *return_value) /* {{{ */
616{
617#ifdef HAVE_GLOB
618 int cwd_skip = 0;
619#ifdef ZTS
620 char cwd[MAXPATHLEN];
621 char work_pattern[MAXPATHLEN];
622 char *result;
623#endif
624 glob_t globbuf;
625 size_t n;
626 int ret;
627
628 if (pattern_len >= MAXPATHLEN) {
629 php_error_docref(NULL, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
630 return -1;
631 }
632
633 if ((GLOB_AVAILABLE_FLAGS & flags) != flags) {
634
635 php_error_docref(NULL, E_WARNING, "At least one of the passed flags is invalid or not supported on this platform");
636 return -1;
637 }
638
639#ifdef ZTS
640 if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) {
642 if (!result) {
643 cwd[0] = '\0';
644 }
645#ifdef PHP_WIN32
646 if (IS_SLASH(*pattern)) {
647 cwd[2] = '\0';
648 }
649#endif
650 cwd_skip = strlen(cwd)+1;
651
652 snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
653 pattern = work_pattern;
654 }
655#endif
656
657 globbuf.gl_offs = 0;
658 if (0 != (ret = glob(pattern, flags & GLOB_FLAGMASK, NULL, &globbuf))) {
659#ifdef GLOB_NOMATCH
660 if (GLOB_NOMATCH == ret) {
661 /* Some glob implementation simply return no data if no matches
662 were found, others return the GLOB_NOMATCH error code.
663 We don't want to treat GLOB_NOMATCH as an error condition
664 so that PHP glob() behaves the same on both types of
665 implementations and so that 'foreach (glob() as ...'
666 can be used for simple glob() calls without further error
667 checking.
668 */
670 return 0;
671 }
672#endif
673 return 0;
674 }
675
676 /* now catch the FreeBSD style of "no matches" */
677 if (!globbuf.gl_pathc || !globbuf.gl_pathv) {
679 return 0;
680 }
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 if (ZIP_OPENBASEDIR_CHECKPATH(globbuf.gl_pathv[0])) {
685 return -1;
686 }
687
689 for (n = 0; n < globbuf.gl_pathc; n++) {
690 /* we need to do this every time 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 zend_stat_t s = {0};
700
701 if (0 != VCWD_STAT(globbuf.gl_pathv[n], &s)) {
702 continue;
703 }
704
705 if (S_IFDIR != (s.st_mode & S_IFMT)) {
706 continue;
707 }
708 }
709 add_next_index_string(return_value, globbuf.gl_pathv[n]+cwd_skip);
710 }
711
712 ret = globbuf.gl_pathc;
713 globfree(&globbuf);
714 return ret;
715#else
716 zend_throw_error(NULL, "Glob support is not available");
717 return 0;
718#endif /* HAVE_GLOB */
719}
720/* }}} */
721
722int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_value) /* {{{ */
723{
724#ifdef ZTS
725 char cwd[MAXPATHLEN];
726 char work_path[MAXPATHLEN];
727 char *result;
728#endif
729 int files_cnt;
730 zend_string **namelist;
732
733#ifdef ZTS
734 if (!IS_ABSOLUTE_PATH(path, path_len)) {
736 if (!result) {
737 cwd[0] = '\0';
738 }
739#ifdef PHP_WIN32
740 if (IS_SLASH(*path)) {
741 cwd[2] = '\0';
742 }
743#endif
744 snprintf(work_path, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, path);
745 path = work_path;
746 }
747#endif
748
749 if (ZIP_OPENBASEDIR_CHECKPATH(path)) {
750 return -1;
751 }
752
753 files_cnt = php_stream_scandir(path, &namelist, NULL, (void *) php_stream_dirent_alphasort);
754
755 if (files_cnt > 0) {
756 pcre2_code *re = NULL;
757 pcre2_match_data *match_data = NULL;
758 uint32_t i, capture_count;
759 int rc;
760
761 re = pcre_get_compiled_regex(regexp, &capture_count);
762 if (!re) {
763 for (i = 0; i < files_cnt; i++) {
764 zend_string_release_ex(namelist[i], 0);
765 }
766 efree(namelist);
767 php_error_docref(NULL, E_WARNING, "Invalid expression");
768 return -1;
769 }
770
772
773 /* only the files, directories are ignored */
774 for (i = 0; i < files_cnt; i++) {
775 zend_stat_t s = {0};
776 char fullpath[MAXPATHLEN];
777 size_t namelist_len = ZSTR_LEN(namelist[i]);
778
779 if ((namelist_len == 1 && ZSTR_VAL(namelist[i])[0] == '.') ||
780 (namelist_len == 2 && ZSTR_VAL(namelist[i])[0] == '.' && ZSTR_VAL(namelist[i])[1] == '.')) {
781 zend_string_release_ex(namelist[i], 0);
782 continue;
783 }
784
785 if ((path_len + namelist_len + 1) >= MAXPATHLEN) {
786 php_error_docref(NULL, E_WARNING, "add_path string too long (max: %u, %zu given)",
787 MAXPATHLEN - 1, (path_len + namelist_len + 1));
788 zend_string_release_ex(namelist[i], 0);
789 break;
790 }
791
792 match_data = php_pcre_create_match_data(capture_count, re);
793 if (!match_data) {
794 /* Allocation failed, but can proceed to the next pattern. */
795 zend_string_release_ex(namelist[i], 0);
796 continue;
797 }
798 rc = pcre2_match(re, (PCRE2_SPTR)ZSTR_VAL(namelist[i]), ZSTR_LEN(namelist[i]), 0, 0, match_data, mctx);
799 php_pcre_free_match_data(match_data);
800 /* 0 means that the vector is too small to hold all the captured substring offsets */
801 if (rc < 0) {
802 zend_string_release_ex(namelist[i], 0);
803 continue;
804 }
805
806 snprintf(fullpath, MAXPATHLEN, "%s%c%s", path, DEFAULT_SLASH, ZSTR_VAL(namelist[i]));
807
808 if (0 != VCWD_STAT(fullpath, &s)) {
809 php_error_docref(NULL, E_WARNING, "Cannot read <%s>", fullpath);
810 zend_string_release_ex(namelist[i], 0);
811 continue;
812 }
813
814 if (S_IFDIR == (s.st_mode & S_IFMT)) {
815 zend_string_release_ex(namelist[i], 0);
816 continue;
817 }
818
820 zend_string_release_ex(namelist[i], 0);
821 }
822 efree(namelist);
823 }
824 return files_cnt;
825}
826/* }}} */
827
828/* {{{ ZE2 OO definitions */
829static zend_class_entry *zip_class_entry;
830static zend_object_handlers zip_object_handlers;
831
832static HashTable zip_prop_handlers;
833
835typedef char *(*zip_read_const_char_t)(ze_zip_object *obj, int *len);
836
843/* }}} */
844
845static void php_zip_register_prop_handler(HashTable *prop_handler, char *name, zip_read_int_t read_int_func, zip_read_const_char_t read_char_func, int rettype) /* {{{ */
846{
848 zend_string *str;
849
850 hnd.read_const_char_func = read_char_func;
851 hnd.read_int_func = read_int_func;
852 hnd.type = rettype;
854 zend_hash_add_mem(prop_handler, str, &hnd, sizeof(zip_prop_handler));
856}
857/* }}} */
858
859static zval *php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, zval *rv) /* {{{ */
860{
861 const char *retchar = NULL;
862 zend_long retint = 0;
863 int len = 0;
864
865 if (hnd->read_const_char_func) {
866 retchar = hnd->read_const_char_func(obj, &len);
867 } else if (hnd->read_int_func) {
868 retint = hnd->read_int_func(obj);
869 }
870
871 switch (hnd->type) {
872 case IS_STRING:
873 if (retchar) {
874 ZVAL_STRINGL(rv, (char *) retchar, len);
875 } else {
877 }
878 break;
879 case IS_LONG:
880 ZVAL_LONG(rv, retint);
881 break;
882 default:
883 ZVAL_NULL(rv);
884 }
885
886 return rv;
887}
888/* }}} */
889
890static zval *php_zip_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot) /* {{{ */
891{
892 ze_zip_object *obj;
893 zval *retval = NULL;
894 zip_prop_handler *hnd = NULL;
895
896 obj = php_zip_fetch_object(object);
897
898 if (obj->prop_handler != NULL) {
899 hnd = zend_hash_find_ptr(obj->prop_handler, name);
900 }
901
902 if (hnd == NULL) {
903 retval = zend_std_get_property_ptr_ptr(object, name, type, cache_slot);
904 } else if (cache_slot) {
905 cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
906 }
907
908 return retval;
909}
910/* }}} */
911
912
913static zval *php_zip_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot)
914{
915 ze_zip_object *obj;
916 zip_prop_handler *hnd = NULL;
917
918 obj = php_zip_fetch_object(object);
919
920 if (obj->prop_handler != NULL) {
921 hnd = zend_hash_find_ptr(obj->prop_handler, name);
922 }
923
924 if (hnd != NULL) {
925 zend_throw_error(NULL, "Cannot write read-only property %s::$%s", ZSTR_VAL(object->ce->name), ZSTR_VAL(name));
926 return &EG(error_zval);
927 }
928
929 return zend_std_write_property(object, name, value, cache_slot);
930}
931
932static zval *php_zip_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv) /* {{{ */
933{
934 ze_zip_object *obj;
935 zval *retval = NULL;
936 zip_prop_handler *hnd = NULL;
937
938 obj = php_zip_fetch_object(object);
939
940 if (obj->prop_handler != NULL) {
941 hnd = zend_hash_find_ptr(obj->prop_handler, name);
942 }
943
944 if (hnd != NULL) {
945 retval = php_zip_property_reader(obj, hnd, rv);
946 if (retval == NULL) {
947 retval = &EG(uninitialized_zval);
948 }
949 } else {
950 retval = zend_std_read_property(object, name, type, cache_slot, rv);
951 }
952
953 return retval;
954}
955/* }}} */
956
957// todo: make php_zip_has_property return bool as well
958static int php_zip_has_property(zend_object *object, zend_string *name, int type, void **cache_slot) /* {{{ */
959{
960 ze_zip_object *obj;
961 zip_prop_handler *hnd = NULL;
962 bool retval = false;
963
964 obj = php_zip_fetch_object(object);
965
966 if (obj->prop_handler != NULL) {
967 hnd = zend_hash_find_ptr(obj->prop_handler, name);
968 }
969
970 if (hnd != NULL) {
971 zval tmp, *prop;
972
973 if (type == 2) {
974 retval = true;
975 } else if ((prop = php_zip_property_reader(obj, hnd, &tmp)) != NULL) {
976 if (type == 1) {
977 retval = zend_is_true(&tmp);
978 } else if (type == 0) {
979 retval = (Z_TYPE(tmp) != IS_NULL);
980 }
981 }
982
983 zval_ptr_dtor(&tmp);
984 } else {
985 retval = zend_std_has_property(object, name, type, cache_slot);
986 }
987
988 return retval;
989}
990/* }}} */
991
992static HashTable *php_zip_get_gc(zend_object *object, zval **gc_data, int *gc_data_count) /* {{{ */
993{
994 *gc_data = NULL;
995 *gc_data_count = 0;
996 return zend_std_get_properties(object);
997}
998/* }}} */
999
1000static HashTable *php_zip_get_properties(zend_object *object)/* {{{ */
1001{
1002 ze_zip_object *obj;
1003 HashTable *props;
1004 zip_prop_handler *hnd;
1006
1007 obj = php_zip_fetch_object(object);
1008 props = zend_std_get_properties(object);
1009
1010 if (obj->prop_handler == NULL) {
1011 return NULL;
1012 }
1013
1015 zval *ret, val;
1016 ret = php_zip_property_reader(obj, hnd, &val);
1017 if (ret == NULL) {
1018 ret = &EG(uninitialized_zval);
1019 }
1020 zend_hash_update(props, key, ret);
1022
1023 return props;
1024}
1025/* }}} */
1026
1027#ifdef HAVE_PROGRESS_CALLBACK
1028static void _php_zip_progress_callback_free(void *ptr)
1029{
1030 ze_zip_object *obj = ptr;
1031
1032 if (!Z_ISUNDEF(obj->progress_callback)) {
1033 zval_ptr_dtor(&obj->progress_callback);
1034 ZVAL_UNDEF(&obj->progress_callback);
1035 }
1036}
1037#endif
1038
1039#ifdef HAVE_CANCEL_CALLBACK
1040static void _php_zip_cancel_callback_free(void *ptr)
1041{
1042 ze_zip_object *obj = ptr;
1043
1044 if (!Z_ISUNDEF(obj->cancel_callback)) {
1045 zval_ptr_dtor(&obj->cancel_callback);
1046 ZVAL_UNDEF(&obj->cancel_callback);
1047 }
1048}
1049#endif
1050
1051static void php_zip_object_free_storage(zend_object *object) /* {{{ */
1052{
1053 ze_zip_object * intern = php_zip_fetch_object(object);
1054 int i;
1055
1056 if (!intern) {
1057 return;
1058 }
1059 if (intern->za) {
1060 if (zip_close(intern->za) != 0) {
1061 php_error_docref(NULL, E_WARNING, "Cannot destroy the zip context: %s", zip_strerror(intern->za));
1062 zip_discard(intern->za);
1063 }
1064 }
1065
1066 if (intern->buffers_cnt>0) {
1067 for (i=0; i<intern->buffers_cnt; i++) {
1068 efree(intern->buffers[i]);
1069 }
1070 efree(intern->buffers);
1071 }
1072
1073#ifdef HAVE_PROGRESS_CALLBACK
1074 /* if not properly called by libzip */
1075 _php_zip_progress_callback_free(intern);
1076#endif
1077
1078#ifdef HAVE_CANCEL_CALLBACK
1079 /* if not properly called by libzip */
1080 _php_zip_cancel_callback_free(intern);
1081#endif
1082
1083 intern->za = NULL;
1084 zend_object_std_dtor(&intern->zo);
1085
1086 if (intern->filename) {
1087 efree(intern->filename);
1088 }
1089}
1090/* }}} */
1091
1092static zend_object *php_zip_object_new(zend_class_entry *class_type) /* {{{ */
1093{
1094 ze_zip_object *intern;
1095
1096 intern = zend_object_alloc(sizeof(ze_zip_object), class_type);
1097 intern->prop_handler = &zip_prop_handlers;
1098 zend_object_std_init(&intern->zo, class_type);
1099 object_properties_init(&intern->zo, class_type);
1100 intern->last_id = -1;
1101
1102 return &intern->zo;
1103}
1104/* }}} */
1105
1106/* {{{ Resource dtors */
1107
1108/* {{{ php_zip_free_dir */
1109static void php_zip_free_dir(zend_resource *rsrc)
1110{
1111 zip_rsrc * zip_int = (zip_rsrc *) rsrc->ptr;
1112
1113 if (zip_int) {
1114 if (zip_int->za) {
1115 if (zip_close(zip_int->za) != 0) {
1116 php_error_docref(NULL, E_WARNING, "Cannot destroy the zip context");
1117 }
1118 zip_int->za = NULL;
1119 }
1120
1121 efree(rsrc->ptr);
1122
1123 rsrc->ptr = NULL;
1124 }
1125}
1126/* }}} */
1127
1128/* {{{ php_zip_free_entry */
1129static void php_zip_free_entry(zend_resource *rsrc)
1130{
1131 zip_read_rsrc *zr_rsrc = (zip_read_rsrc *) rsrc->ptr;
1132
1133 if (zr_rsrc) {
1134 if (zr_rsrc->zf) {
1135 zip_fclose(zr_rsrc->zf);
1136 zr_rsrc->zf = NULL;
1137 }
1138 efree(zr_rsrc);
1139 rsrc->ptr = NULL;
1140 }
1141}
1142/* }}} */
1143
1144/* }}}*/
1145
1146/* reset macro */
1147
1148/* {{{ function prototypes */
1149static PHP_MINIT_FUNCTION(zip);
1150static PHP_MSHUTDOWN_FUNCTION(zip);
1151static PHP_MINFO_FUNCTION(zip);
1152/* }}} */
1153
1154static const zend_module_dep zip_deps[] = {
1155 ZEND_MOD_REQUIRED("pcre")
1157};
1158
1159/* {{{ zip_module_entry */
1162 zip_deps,
1163 "zip",
1164 ext_functions,
1165 PHP_MINIT(zip),
1166 PHP_MSHUTDOWN(zip),
1167 NULL,
1168 NULL,
1169 PHP_MINFO(zip),
1172};
1173/* }}} */
1174
1175#ifdef COMPILE_DL_ZIP
1176ZEND_GET_MODULE(zip)
1177#endif
1178/* set macro */
1179
1180/* {{{ Create new zip using source uri for output */
1182{
1183 char resolved_path[MAXPATHLEN + 1];
1184 zip_rsrc *rsrc_int;
1185 int err = 0;
1186 zend_string *filename;
1187
1188 if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &filename) == FAILURE) {
1189 RETURN_THROWS();
1190 }
1191
1192 if (ZSTR_LEN(filename) == 0) {
1194 RETURN_THROWS();
1195 }
1196
1197 if (ZIP_OPENBASEDIR_CHECKPATH(ZSTR_VAL(filename))) {
1199 }
1200
1201 if(!expand_filepath(ZSTR_VAL(filename), resolved_path)) {
1202 php_error_docref(NULL, E_WARNING, "No such file or directory");
1204 }
1205
1206 rsrc_int = (zip_rsrc *)emalloc(sizeof(zip_rsrc));
1207
1208 rsrc_int->za = zip_open(resolved_path, 0, &err);
1209 if (rsrc_int->za == NULL) {
1210 efree(rsrc_int);
1212 }
1213
1214 rsrc_int->index_current = 0;
1215 rsrc_int->num_files = zip_get_num_entries(rsrc_int->za, 0);
1216
1217 RETURN_RES(zend_register_resource(rsrc_int, le_zip_dir));
1218}
1219/* }}} */
1220
1221/* {{{ Close a Zip archive */
1223{
1224 zval * zip;
1225 zip_rsrc *z_rsrc = NULL;
1226
1227 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip) == FAILURE) {
1228 RETURN_THROWS();
1229 }
1230
1231 if ((z_rsrc = (zip_rsrc *)zend_fetch_resource(Z_RES_P(zip), le_zip_dir_name, le_zip_dir)) == NULL) {
1232 RETURN_THROWS();
1233 }
1234
1235 /* really close the zip will break BC :-D */
1237}
1238/* }}} */
1239
1240/* {{{ Returns the next file in the archive */
1242{
1243 zval *zip_dp;
1244 zip_read_rsrc *zr_rsrc;
1245 int ret;
1246 zip_rsrc *rsrc_int;
1247
1248 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip_dp) == FAILURE) {
1249 RETURN_THROWS();
1250 }
1251
1252 if ((rsrc_int = (zip_rsrc *)zend_fetch_resource(Z_RES_P(zip_dp), le_zip_dir_name, le_zip_dir)) == NULL) {
1253 RETURN_THROWS();
1254 }
1255
1256 if (rsrc_int && rsrc_int->za) {
1257 if (rsrc_int->index_current >= rsrc_int->num_files) {
1259 }
1260
1261 zr_rsrc = emalloc(sizeof(zip_read_rsrc));
1262
1263 ret = zip_stat_index(rsrc_int->za, rsrc_int->index_current, 0, &zr_rsrc->sb);
1264
1265 if (ret != 0) {
1266 efree(zr_rsrc);
1268 }
1269
1270 zr_rsrc->zip_rsrc_handle = Z_RES_P(zip_dp)->handle;
1271 zr_rsrc->zf = zip_fopen_index(rsrc_int->za, rsrc_int->index_current, 0);
1272 if (zr_rsrc->zf) {
1273 rsrc_int->index_current++;
1274 RETURN_RES(zend_register_resource(zr_rsrc, le_zip_entry));
1275 } else {
1276 efree(zr_rsrc);
1278 }
1279
1280 } else {
1282 }
1283}
1284/* }}} */
1285
1286/* {{{ Open a Zip File, pointed by the resource entry */
1287/* Dummy function to follow the old API */
1289{
1290 zval * zip;
1291 zval * zip_entry;
1292 char *mode = NULL;
1293 size_t mode_len = 0;
1294 zip_read_rsrc * zr_rsrc;
1295 zip_rsrc *z_rsrc;
1296
1297 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr|s", &zip, &zip_entry, &mode, &mode_len) == FAILURE) {
1298 RETURN_THROWS();
1299 }
1300
1301 if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) {
1302 RETURN_THROWS();
1303 }
1304
1305 if ((z_rsrc = (zip_rsrc *)zend_fetch_resource(Z_RES_P(zip), le_zip_dir_name, le_zip_dir)) == NULL) {
1306 RETURN_THROWS();
1307 }
1308
1309 if (zr_rsrc->zf != NULL) {
1311 } else {
1313 }
1314}
1315/* }}} */
1316
1317/* {{{ Close a zip entry */
1319{
1320 zval * zip_entry;
1321 zip_read_rsrc * zr_rsrc;
1322
1323 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip_entry) == FAILURE) {
1324 RETURN_THROWS();
1325 }
1326
1327 if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) {
1328 RETURN_THROWS();
1329 }
1330
1331 zend_list_close(Z_RES_P(zip_entry));
1333}
1334/* }}} */
1335
1336/* {{{ Read from an open directory entry */
1338{
1339 zval * zip_entry;
1340 zend_long len = 0;
1341 zip_read_rsrc * zr_rsrc;
1343 int n = 0;
1344
1345 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &zip_entry, &len) == FAILURE) {
1346 RETURN_THROWS();
1347 }
1348
1349 if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) {
1350 RETURN_THROWS();
1351 }
1352
1353 if (len <= 0) {
1354 len = 1024;
1355 }
1356
1357 if (zr_rsrc->zf) {
1358 buffer = zend_string_safe_alloc(1, len, 0, 0);
1359 n = zip_fread(zr_rsrc->zf, ZSTR_VAL(buffer), ZSTR_LEN(buffer));
1360 if (n > 0) {
1361 ZSTR_VAL(buffer)[n] = '\0';
1362 ZSTR_LEN(buffer) = n;
1364 } else {
1365 zend_string_efree(buffer);
1367 }
1368 } else {
1370 }
1371}
1372/* }}} */
1373
1374static void php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS, int opt) /* {{{ */
1375{
1376 zval * zip_entry;
1377 zip_read_rsrc * zr_rsrc;
1378
1379 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip_entry) == FAILURE) {
1380 RETURN_THROWS();
1381 }
1382
1383 if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) {
1384 RETURN_THROWS();
1385 }
1386
1387 if (!zr_rsrc->zf || !zend_hash_index_exists(&EG(regular_list), zr_rsrc->zip_rsrc_handle)) {
1389 }
1390
1391 switch (opt) {
1392 case 0:
1393 RETURN_STRING((char *)zr_rsrc->sb.name);
1394 case 1:
1395 RETURN_LONG((zend_long) (zr_rsrc->sb.comp_size));
1396 case 2:
1397 RETURN_LONG((zend_long) (zr_rsrc->sb.size));
1398 case 3:
1399 switch (zr_rsrc->sb.comp_method) {
1400 case 0:
1401 RETURN_STRING("stored");
1402 case 1:
1403 RETURN_STRING("shrunk");
1404 case 2:
1405 case 3:
1406 case 4:
1407 case 5:
1408 RETURN_STRING("reduced");
1409 case 6:
1410 RETURN_STRING("imploded");
1411 case 7:
1412 RETURN_STRING("tokenized");
1413 break;
1414 case 8:
1415 RETURN_STRING("deflated");
1416 case 9:
1417 RETURN_STRING("deflatedX");
1418 break;
1419 case 10:
1420 RETURN_STRING("implodedX");
1421 default:
1423 }
1424 }
1425
1426}
1427/* }}} */
1428
1429/* {{{ Return the name given a ZZip entry */
1431{
1432 php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1433}
1434/* }}} */
1435
1436/* {{{ Return the compressed size of a ZZip entry */
1438{
1439 php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1440}
1441/* }}} */
1442
1443/* {{{ Return the actual filesize of a ZZip entry */
1445{
1446 php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
1447}
1448/* }}} */
1449
1450/* {{{ Return a string containing the compression method used on a particular entry */
1455/* }}} */
1456
1457/* {{{ Create new zip using source uri for output, return TRUE on success or the error code */
1459{
1460 struct zip *intern;
1461 int err = 0;
1462 zend_long flags = 0;
1463 char *resolved_path;
1464 zend_string *filename;
1465 zval *self = ZEND_THIS;
1466 ze_zip_object *ze_obj;
1467
1468 if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &filename, &flags) == FAILURE) {
1469 RETURN_THROWS();
1470 }
1471
1472 /* We do not use ZIP_FROM_OBJECT, zip init function here */
1473 ze_obj = Z_ZIP_P(self);
1474
1475 if (ZSTR_LEN(filename) == 0) {
1477 RETURN_THROWS();
1478 }
1479
1480 if (ZIP_OPENBASEDIR_CHECKPATH(ZSTR_VAL(filename))) {
1482 }
1483
1484 if (!(resolved_path = expand_filepath(ZSTR_VAL(filename), NULL))) {
1485 php_error_docref(NULL, E_WARNING, "No such file or directory");
1487 }
1488
1489 if (ze_obj->za) {
1490 /* we already have an opened zip, free it */
1491 if (zip_close(ze_obj->za) != 0) {
1492 php_error_docref(NULL, E_WARNING, "Empty string as source");
1493 efree(resolved_path);
1495 }
1496 ze_obj->za = NULL;
1497 }
1498 if (ze_obj->filename) {
1499 efree(ze_obj->filename);
1500 ze_obj->filename = NULL;
1501 }
1502
1503 /* open for write without option to empty the archive */
1504#ifdef ZIP_RDONLY
1505 if ((flags & (ZIP_TRUNCATE | ZIP_RDONLY)) == 0) {
1506#else
1507 if ((flags & ZIP_TRUNCATE) == 0) {
1508#endif
1509 zend_stat_t st = {0};
1510
1511 /* exists and is empty */
1512 if (VCWD_STAT(resolved_path, &st) == 0 && st.st_size == 0) {
1513 php_error_docref(NULL, E_DEPRECATED, "Using empty file as ZipArchive is deprecated");
1514
1515 /* reduce BC break introduced in libzip 1.6.0
1516 "Do not accept empty files as valid zip archives any longer" */
1517 flags |= ZIP_TRUNCATE;
1518 }
1519 }
1520
1521 intern = zip_open(resolved_path, flags, &err);
1522 if (!intern || err) {
1523 efree(resolved_path);
1525 }
1526 ze_obj->filename = resolved_path;
1527 ze_obj->filename_len = strlen(resolved_path);
1528 ze_obj->za = intern;
1530}
1531/* }}} */
1532
1533/* {{{ Set the password for the active archive */
1535{
1536 struct zip *intern;
1537 zval *self = ZEND_THIS;
1538 char *password;
1539 size_t password_len;
1540
1541 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &password, &password_len) == FAILURE) {
1542 RETURN_THROWS();
1543 }
1544
1545 ZIP_FROM_OBJECT(intern, self);
1546
1547 if (password_len < 1) {
1549 }
1550
1551 int res = zip_set_default_password(intern, (const char *)password);
1552 if (res == 0) {
1554 } else {
1556 }
1557}
1558/* }}} */
1559
1560/* {{{ close the zip archive */
1562{
1563 struct zip *intern;
1564 zval *self = ZEND_THIS;
1565 ze_zip_object *ze_obj;
1566 int err;
1567
1569 RETURN_THROWS();
1570 }
1571
1572 ZIP_FROM_OBJECT(intern, self);
1573
1574 ze_obj = Z_ZIP_P(self);
1575
1576 err = zip_close(intern);
1577 if (err) {
1578 php_error_docref(NULL, E_WARNING, "%s", zip_strerror(intern));
1579 /* Save error for property reader */
1580 #if LIBZIP_VERSION_MAJOR < 1
1581 zip_error_get(intern, &ze_obj->err_zip, &ze_obj->err_sys);
1582 #else
1583 {
1584 zip_error_t *ziperr;
1585
1586 ziperr = zip_get_error(intern);
1587 ze_obj->err_zip = zip_error_code_zip(ziperr);
1588 ze_obj->err_sys = zip_error_code_system(ziperr);
1589 zip_error_fini(ziperr);
1590 }
1591 #endif
1592 zip_discard(intern);
1593 } else {
1594 ze_obj->err_zip = 0;
1595 ze_obj->err_sys = 0;
1596 }
1597
1598 /* clear cache as empty zip are not created but deleted */
1599 php_clear_stat_cache(1, ze_obj->filename, ze_obj->filename_len);
1600
1601 efree(ze_obj->filename);
1602 ze_obj->filename = NULL;
1603 ze_obj->filename_len = 0;
1604 ze_obj->za = NULL;
1605
1606 if (!err) {
1608 } else {
1610 }
1611}
1612/* }}} */
1613
1614/* {{{ close the zip archive */
1616{
1617 struct zip *intern;
1618 zval *self = ZEND_THIS;
1619 zip_int64_t num;
1620
1622 RETURN_THROWS();
1623 }
1624
1625 ZIP_FROM_OBJECT(intern, self);
1626
1627 num = zip_get_num_entries(intern, 0);
1629}
1630/* }}} */
1631
1632/* {{{ clear the internal status */
1634{
1635 zval *self = ZEND_THIS;
1636 ze_zip_object *ze_obj;
1637
1639 RETURN_THROWS();
1640 }
1641
1642 ze_obj = Z_ZIP_P(self); /* not ZIP_FROM_OBJECT as we can use saved error after close */
1643 if (ze_obj->za) {
1644 zip_error_clear(ze_obj->za);
1645 } else {
1646 ze_obj->err_zip = 0;
1647 ze_obj->err_sys = 0;
1648 }
1649}
1650/* }}} */
1651
1652/* {{{ Returns the status error message, system and/or zip messages */
1653PHP_METHOD(ZipArchive, getStatusString)
1654{
1655 zval *self = ZEND_THIS;
1656#if LIBZIP_VERSION_MAJOR < 1
1657 int zep, syp, len;
1658 char error_string[128];
1659#endif
1660 ze_zip_object *ze_obj;
1661
1663 RETURN_THROWS();
1664 }
1665
1666 ze_obj = Z_ZIP_P(self); /* not ZIP_FROM_OBJECT as we can use saved error after close */
1667
1668#if LIBZIP_VERSION_MAJOR < 1
1669 if (ze_obj->za) {
1670 zip_error_get(ze_obj->za, &zep, &syp);
1671 len = zip_error_to_str(error_string, 128, zep, syp);
1672 } else {
1673 len = zip_error_to_str(error_string, 128, ze_obj->err_zip, ze_obj->err_sys);
1674 }
1675 RETVAL_STRINGL(error_string, len);
1676#else
1677 if (ze_obj->za) {
1678 zip_error_t *err;
1679
1680 err = zip_get_error(ze_obj->za);
1681 RETVAL_STRING(zip_error_strerror(err));
1682 zip_error_fini(err);
1683 } else {
1684 zip_error_t err;
1685
1686 zip_error_init(&err);
1687 zip_error_set(&err, ze_obj->err_zip, ze_obj->err_sys);
1688 RETVAL_STRING(zip_error_strerror(&err));
1689 zip_error_fini(&err);
1690 }
1691#endif
1692}
1693/* }}} */
1694
1695/* {{{ Returns the index of the entry named filename in the archive */
1697{
1698 struct zip *intern;
1699 zval *self = ZEND_THIS;
1700 char *dirname;
1701 size_t dirname_len;
1702 char *s;
1703 zend_long flags = 0;
1704
1706 &dirname, &dirname_len, &flags) == FAILURE) {
1707 RETURN_THROWS();
1708 }
1709
1710 ZIP_FROM_OBJECT(intern, self);
1711
1712 if (dirname_len<1) {
1714 }
1715
1716 if (dirname[dirname_len-1] != '/') {
1717 s=(char *)safe_emalloc(dirname_len, 1, 2);
1718 strcpy(s, dirname);
1719 s[dirname_len] = '/';
1720 s[dirname_len+1] = '\0';
1721 } else {
1722 s = dirname;
1723 }
1724
1725 if ((Z_ZIP_P(self)->last_id = zip_dir_add(intern, (const char *)s, flags)) == -1) {
1727 } else {
1728 zip_error_clear(intern);
1730 }
1731
1732 if (s != dirname) {
1733 efree(s);
1734 }
1735}
1736/* }}} */
1737
1738static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
1739{
1740 zval *self = ZEND_THIS;
1741 char *path = ".";
1742 size_t path_len = 1;
1743 zend_long glob_flags = 0;
1745 zip_options opts = {0};
1746 int found;
1747 zend_string *pattern;
1748
1749 /* 1 == glob, 2 == pcre */
1750 if (type == 1) {
1752 &pattern, &glob_flags, &options) == FAILURE) {
1753 RETURN_THROWS();
1754 }
1755 } else {
1757 &pattern, &path, &path_len, &options) == FAILURE) {
1758 RETURN_THROWS();
1759 }
1760 }
1761
1762 if (ZSTR_LEN(pattern) == 0) {
1764 RETURN_THROWS();
1765 }
1766 if (options && zend_hash_num_elements(options) > 0 && (php_zip_parse_options(options, &opts) < 0)) {
1767 RETURN_THROWS();
1768 }
1769
1770 if (type == 1) {
1771 found = php_zip_glob(ZSTR_VAL(pattern), ZSTR_LEN(pattern), glob_flags, return_value);
1772 } else {
1773 found = php_zip_pcre(pattern, path, path_len, return_value);
1774 }
1775
1776 if (found > 0) {
1777 int i;
1778 zval *zval_file;
1779 ze_zip_object *ze_obj;
1780
1781 ze_obj = Z_ZIP_P(self);
1782
1783 for (i = 0; i < found; i++) {
1784 char *file_stripped, *entry_name;
1785 size_t entry_name_len, file_stripped_len;
1786 char entry_name_buf[MAXPATHLEN];
1788
1789 if ((zval_file = zend_hash_index_find(Z_ARRVAL_P(return_value), i)) != NULL) {
1790 if (opts.remove_all_path) {
1791 basename = php_basename(Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), NULL, 0);
1792 file_stripped = ZSTR_VAL(basename);
1793 file_stripped_len = ZSTR_LEN(basename);
1794 } else if (opts.remove_path && !memcmp(Z_STRVAL_P(zval_file), opts.remove_path, opts.remove_path_len)) {
1795 if (IS_SLASH(Z_STRVAL_P(zval_file)[opts.remove_path_len])) {
1796 file_stripped = Z_STRVAL_P(zval_file) + opts.remove_path_len + 1;
1797 file_stripped_len = Z_STRLEN_P(zval_file) - opts.remove_path_len - 1;
1798 } else {
1799 file_stripped = Z_STRVAL_P(zval_file) + opts.remove_path_len;
1800 file_stripped_len = Z_STRLEN_P(zval_file) - opts.remove_path_len;
1801 }
1802 } else {
1803 file_stripped = Z_STRVAL_P(zval_file);
1804 file_stripped_len = Z_STRLEN_P(zval_file);
1805 }
1806
1807 if (opts.add_path) {
1808 if ((opts.add_path_len + file_stripped_len) > MAXPATHLEN) {
1809 if (basename) {
1811 }
1812 php_error_docref(NULL, E_WARNING, "Entry name too long (max: %d, %zd given)",
1813 MAXPATHLEN - 1, (opts.add_path_len + file_stripped_len));
1816 }
1817 snprintf(entry_name_buf, MAXPATHLEN, "%s%s", opts.add_path, file_stripped);
1818 } else {
1819 snprintf(entry_name_buf, MAXPATHLEN, "%s", file_stripped);
1820 }
1821
1822 entry_name = entry_name_buf;
1823 entry_name_len = strlen(entry_name);
1824 if (basename) {
1826 basename = NULL;
1827 }
1828
1829 if (php_zip_add_file(ze_obj, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file),
1830 entry_name, entry_name_len, 0, 0, -1, opts.flags) < 0) {
1833 }
1834 if (opts.comp_method >= 0) {
1835 if (zip_set_file_compression(ze_obj->za, ze_obj->last_id, opts.comp_method, opts.comp_flags)) {
1838 }
1839 }
1840#ifdef HAVE_ENCRYPTION
1841 if (opts.enc_method >= 0) {
1842 if (zip_file_set_encryption(ze_obj->za, ze_obj->last_id, opts.enc_method, opts.enc_password)) {
1845 }
1846 }
1847#endif
1848 }
1849 }
1850 } else if (found == 0) {
1852 } else {
1854 }
1855}
1856/* }}} */
1857
1858/* {{{ Add files matching the glob pattern. See php's glob for the pattern syntax. */
1860{
1861 php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1862}
1863/* }}} */
1864
1865/* {{{ Add files matching the pcre pattern. See php's pcre for the pattern syntax. */
1867{
1868 php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
1869}
1870/* }}} */
1871
1872/* {{{ Add a file in a Zip archive using its path and the name to use. */
1874{
1875 zval *self = ZEND_THIS;
1876 char *entry_name = NULL;
1877 size_t entry_name_len = 0;
1878 zend_long offset_start = 0, offset_len = 0;
1879 zend_string *filename;
1880 zend_long flags = ZIP_FL_OVERWRITE;
1881
1882 if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|slll",
1883 &filename, &entry_name, &entry_name_len, &offset_start, &offset_len, &flags) == FAILURE) {
1884 RETURN_THROWS();
1885 }
1886
1887 if (ZSTR_LEN(filename) == 0) {
1889 RETURN_THROWS();
1890 }
1891
1892 if (entry_name_len == 0) {
1893 entry_name = ZSTR_VAL(filename);
1894 entry_name_len = ZSTR_LEN(filename);
1895 }
1896
1897 if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename),
1898 entry_name, entry_name_len, offset_start, offset_len, -1, flags) < 0) {
1900 } else {
1902 }
1903}
1904/* }}} */
1905
1906/* {{{ Add a file in a Zip archive using its path and the name to use. */
1908{
1909 zval *self = ZEND_THIS;
1910 zend_long index;
1911 zend_long offset_start = 0, offset_len = 0;
1912 zend_string *filename;
1913 zend_long flags = 0;
1914
1915 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Pl|lll",
1916 &filename, &index, &offset_start, &offset_len, &flags) == FAILURE) {
1917 RETURN_THROWS();
1918 }
1919
1920 if (ZSTR_LEN(filename) == 0) {
1922 RETURN_THROWS();
1923 }
1924
1925 if (index < 0) {
1926 zend_argument_value_error(2, "must be greater than or equal to 0");
1927 RETURN_THROWS();
1928 }
1929
1930 if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename),
1931 NULL, 0, offset_start, offset_len, index, flags) < 0) {
1933 } else {
1935 }
1936}
1937/* }}} */
1938
1939/* {{{ Add a file using content and the entry name */
1940PHP_METHOD(ZipArchive, addFromString)
1941{
1942 struct zip *intern;
1943 zval *self = ZEND_THIS;
1945 char *name;
1946 size_t name_len;
1947 ze_zip_object *ze_obj;
1948 struct zip_source *zs;
1949 int pos = 0;
1950 zend_long flags = ZIP_FL_OVERWRITE;
1951
1953 &name, &name_len, &buffer, &flags) == FAILURE) {
1954 RETURN_THROWS();
1955 }
1956
1957 ZIP_FROM_OBJECT(intern, self);
1958
1959 ze_obj = Z_ZIP_P(self);
1960 if (ze_obj->buffers_cnt) {
1961 ze_obj->buffers = (char **)safe_erealloc(ze_obj->buffers, sizeof(char *), (ze_obj->buffers_cnt+1), 0);
1962 pos = ze_obj->buffers_cnt++;
1963 } else {
1964 ze_obj->buffers = (char **)emalloc(sizeof(char *));
1965 ze_obj->buffers_cnt++;
1966 pos = 0;
1967 }
1968 ze_obj->buffers[pos] = (char *)safe_emalloc(ZSTR_LEN(buffer), 1, 1);
1969 memcpy(ze_obj->buffers[pos], ZSTR_VAL(buffer), ZSTR_LEN(buffer) + 1);
1970
1971 zs = zip_source_buffer(intern, ze_obj->buffers[pos], ZSTR_LEN(buffer), 0);
1972
1973 if (zs == NULL) {
1975 }
1976
1977 ze_obj->last_id = zip_file_add(intern, name, zs, flags);
1978 if (ze_obj->last_id == -1) {
1979 zip_source_free(zs);
1981 } else {
1982 zip_error_clear(intern);
1984 }
1985}
1986/* }}} */
1987
1988/* {{{ Returns the information about a the zip entry filename */
1990{
1991 struct zip *intern;
1992 zval *self = ZEND_THIS;
1993 zend_long flags = 0;
1994 struct zip_stat sb;
1996
1997 if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &name, &flags) == FAILURE) {
1998 RETURN_THROWS();
1999 }
2000
2001 ZIP_FROM_OBJECT(intern, self);
2002
2004
2005 RETURN_SB(&sb);
2006}
2007/* }}} */
2008
2009/* {{{ Returns the zip entry information using its index */
2011{
2012 struct zip *intern;
2013 zval *self = ZEND_THIS;
2014 zend_long index, flags = 0;
2015
2016 struct zip_stat sb;
2017
2019 &index, &flags) == FAILURE) {
2020 RETURN_THROWS();
2021 }
2022
2023 ZIP_FROM_OBJECT(intern, self);
2024
2025 if (zip_stat_index(intern, index, flags, &sb) != 0) {
2027 }
2028 RETURN_SB(&sb);
2029}
2030/* }}} */
2031
2032/* {{{ Returns the index of the entry named filename in the archive */
2034{
2035 struct zip *intern;
2036 zval *self = ZEND_THIS;
2037 zend_long flags = 0;
2038 zend_long idx = -1;
2040
2041 if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &name, &flags) == FAILURE) {
2042 RETURN_THROWS();
2043 }
2044
2045 ZIP_FROM_OBJECT(intern, self);
2046
2047 if (ZSTR_LEN(name) < 1) {
2049 }
2050
2051 idx = (zend_long)zip_name_locate(intern, (const char *)ZSTR_VAL(name), flags);
2052
2053 if (idx >= 0) {
2054 RETURN_LONG(idx);
2055 } else {
2057 }
2058}
2059/* }}} */
2060
2061/* {{{ Returns the name of the file at position index */
2063{
2064 struct zip *intern;
2065 zval *self = ZEND_THIS;
2066 const char *name;
2067 zend_long flags = 0, index = 0;
2068
2070 &index, &flags) == FAILURE) {
2071 RETURN_THROWS();
2072 }
2073
2074 ZIP_FROM_OBJECT(intern, self);
2075
2076 name = zip_get_name(intern, (int) index, flags);
2077
2078 if (name) {
2079 RETVAL_STRING((char *)name);
2080 } else {
2082 }
2083}
2084/* }}} */
2085
2086/* {{{ Set or remove (NULL/'') the comment of the archive */
2087PHP_METHOD(ZipArchive, setArchiveComment)
2088{
2089 struct zip *intern;
2090 zval *self = ZEND_THIS;
2091 size_t comment_len;
2092 char * comment;
2093
2094 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &comment, &comment_len) == FAILURE) {
2095 RETURN_THROWS();
2096 }
2097
2098 ZIP_FROM_OBJECT(intern, self);
2099
2100 if (comment_len > 0xffff) {
2101 zend_argument_value_error(1, "must be less than 65535 bytes");
2102 RETURN_THROWS();
2103 }
2104
2105 if (zip_set_archive_comment(intern, (const char *)comment, comment_len)) {
2107 } else {
2109 }
2110}
2111/* }}} */
2112
2113/* {{{ Returns the comment of an entry using its index */
2114PHP_METHOD(ZipArchive, getArchiveComment)
2115{
2116 struct zip *intern;
2117 zval *self = ZEND_THIS;
2118 zend_long flags = 0;
2119 const char * comment;
2120 int comment_len = 0;
2121
2123 RETURN_THROWS();
2124 }
2125
2126 ZIP_FROM_OBJECT(intern, self);
2127
2128 comment = zip_get_archive_comment(intern, &comment_len, (int)flags);
2129 if(comment==NULL) {
2131 }
2132 RETURN_STRINGL((char *)comment, (zend_long)comment_len);
2133}
2134/* }}} */
2135
2136PHP_METHOD(ZipArchive, setArchiveFlag)
2137{
2138 struct zip *intern;
2139 zval *self = ZEND_THIS;
2140 zend_long flag, value;
2141
2142 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &flag, &value) == FAILURE) {
2143 RETURN_THROWS();
2144 }
2145
2146 ZIP_FROM_OBJECT(intern, self);
2147
2148 if (zip_set_archive_flag(intern, flag, (int)value)) {
2150 } else {
2152 }
2153}
2154
2155PHP_METHOD(ZipArchive, getArchiveFlag)
2156{
2157 struct zip *intern;
2158 zval *self = ZEND_THIS;
2159 zend_long flag, flags = 0;
2160
2161 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &flag, &flags) == FAILURE) {
2162 RETURN_THROWS();
2163 }
2164
2165 ZIP_FROM_OBJECT(intern, self);
2166
2167 RETURN_LONG(zip_get_archive_flag(intern, flag, flags));
2168}
2169
2170/* {{{ Set or remove (NULL/'') the comment of an entry using its Name */
2171PHP_METHOD(ZipArchive, setCommentName)
2172{
2173 struct zip *intern;
2174 zval *self = ZEND_THIS;
2175 size_t comment_len, name_len;
2176 char * comment, *name;
2177 int idx;
2178
2180 &name, &name_len, &comment, &comment_len) == FAILURE) {
2181 RETURN_THROWS();
2182 }
2183
2184 if (name_len == 0) {
2186 RETURN_THROWS();
2187 }
2188
2189 ZIP_FROM_OBJECT(intern, self);
2190
2191 if (comment_len > 0xffff) {
2192 zend_argument_value_error(2, "must be less than 65535 bytes");
2193 RETURN_THROWS();
2194 }
2195
2196 idx = zip_name_locate(intern, name, 0);
2197 if (idx < 0) {
2199 }
2200 PHP_ZIP_SET_FILE_COMMENT(intern, idx, comment, comment_len);
2201}
2202/* }}} */
2203
2204/* {{{ Set or remove (NULL/'') the comment of an entry using its index */
2205PHP_METHOD(ZipArchive, setCommentIndex)
2206{
2207 struct zip *intern;
2208 zval *self = ZEND_THIS;
2209 zend_long index;
2210 size_t comment_len;
2211 char * comment;
2212 struct zip_stat sb;
2213
2215 &index, &comment, &comment_len) == FAILURE) {
2216 RETURN_THROWS();
2217 }
2218
2219 ZIP_FROM_OBJECT(intern, self);
2220
2221 if (comment_len > 0xffff) {
2222 zend_argument_value_error(2, "must be less than 65535 bytes");
2223 RETURN_THROWS();
2224 }
2225
2226 PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2227 PHP_ZIP_SET_FILE_COMMENT(intern, index, comment, comment_len);
2228}
2229/* }}} */
2230
2231/* those constants/functions are only available in libzip since 0.11.2 */
2232#ifdef ZIP_OPSYS_DEFAULT
2233
2234/* {{{ Set external attributes for file in zip, using its name */
2235PHP_METHOD(ZipArchive, setExternalAttributesName)
2236{
2237 struct zip *intern;
2238 zval *self = ZEND_THIS;
2239 size_t name_len;
2240 char *name;
2241 zend_long flags=0, opsys, attr;
2242 zip_int64_t idx;
2243
2244 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sll|l",
2245 &name, &name_len, &opsys, &attr, &flags) == FAILURE) {
2246 RETURN_THROWS();
2247 }
2248
2249 ZIP_FROM_OBJECT(intern, self);
2250
2251 if (name_len == 0) {
2253 RETURN_THROWS();
2254 }
2255
2256 idx = zip_name_locate(intern, name, 0);
2257
2258 if (idx < 0) {
2260 }
2261 if (zip_file_set_external_attributes(intern, idx, (zip_flags_t)flags,
2262 (zip_uint8_t)(opsys&0xff), (zip_uint32_t)attr) < 0) {
2264 }
2266}
2267/* }}} */
2268
2269/* {{{ Set external attributes for file in zip, using its index */
2270PHP_METHOD(ZipArchive, setExternalAttributesIndex)
2271{
2272 struct zip *intern;
2273 zval *self = ZEND_THIS;
2274 zend_long index, flags=0, opsys, attr;
2275 struct zip_stat sb;
2276
2277 if (zend_parse_parameters(ZEND_NUM_ARGS(), "lll|l",
2278 &index, &opsys, &attr, &flags) == FAILURE) {
2279 RETURN_THROWS();
2280 }
2281
2282 ZIP_FROM_OBJECT(intern, self);
2283
2284 PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2285 if (zip_file_set_external_attributes(intern, (zip_uint64_t)index,
2286 (zip_flags_t)flags, (zip_uint8_t)(opsys&0xff), (zip_uint32_t)attr) < 0) {
2288 }
2290}
2291/* }}} */
2292
2293/* {{{ Get external attributes for file in zip, using its name */
2294PHP_METHOD(ZipArchive, getExternalAttributesName)
2295{
2296 struct zip *intern;
2297 zval *self = ZEND_THIS, *z_opsys, *z_attr;
2298 size_t name_len;
2299 char *name;
2300 zend_long flags=0;
2301 zip_uint8_t opsys;
2302 zip_uint32_t attr;
2303 zip_int64_t idx;
2304
2305 if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l",
2306 &name, &name_len, &z_opsys, &z_attr, &flags) == FAILURE) {
2307 RETURN_THROWS();
2308 }
2309
2310 ZIP_FROM_OBJECT(intern, self);
2311
2312 if (name_len == 0) {
2314 RETURN_THROWS();
2315 }
2316
2317 idx = zip_name_locate(intern, name, 0);
2318
2319 if (idx < 0) {
2321 }
2322 if (zip_file_get_external_attributes(intern, idx,
2323 (zip_flags_t)flags, &opsys, &attr) < 0) {
2325 }
2326 ZEND_TRY_ASSIGN_REF_LONG(z_opsys, opsys);
2329}
2330/* }}} */
2331
2332/* {{{ Get external attributes for file in zip, using its index */
2333PHP_METHOD(ZipArchive, getExternalAttributesIndex)
2334{
2335 struct zip *intern;
2336 zval *self = ZEND_THIS, *z_opsys, *z_attr;
2337 zend_long index, flags=0;
2338 zip_uint8_t opsys;
2339 zip_uint32_t attr;
2340 struct zip_stat sb;
2341
2342 if (zend_parse_parameters(ZEND_NUM_ARGS(), "lzz|l",
2343 &index, &z_opsys, &z_attr, &flags) == FAILURE) {
2344 RETURN_THROWS();
2345 }
2346
2347 ZIP_FROM_OBJECT(intern, self);
2348
2349 PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2350 if (zip_file_get_external_attributes(intern, (zip_uint64_t)index,
2351 (zip_flags_t)flags, &opsys, &attr) < 0) {
2353 }
2354 ZEND_TRY_ASSIGN_REF_LONG(z_opsys, opsys);
2357}
2358/* }}} */
2359#endif /* ifdef ZIP_OPSYS_DEFAULT */
2360
2361#ifdef HAVE_ENCRYPTION
2362/* {{{ Set encryption method for file in zip, using its name */
2363PHP_METHOD(ZipArchive, setEncryptionName)
2364{
2365 struct zip *intern;
2366 zval *self = ZEND_THIS;
2367 zend_long method;
2368 zip_int64_t idx;
2369 char *name, *password = NULL;
2370 size_t name_len, password_len;
2371
2372 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|s!",
2373 &name, &name_len, &method, &password, &password_len) == FAILURE) {
2374 RETURN_THROWS();
2375 }
2376
2377 ZIP_FROM_OBJECT(intern, self);
2378
2379 if (name_len == 0) {
2381 RETURN_THROWS();
2382 }
2383
2384 idx = zip_name_locate(intern, name, 0);
2385
2386 if (idx < 0) {
2388 }
2389
2390 if (zip_file_set_encryption(intern, idx, (zip_uint16_t)method, password)) {
2392 }
2394}
2395/* }}} */
2396
2397/* {{{ Set encryption method for file in zip, using its index */
2398PHP_METHOD(ZipArchive, setEncryptionIndex)
2399{
2400 struct zip *intern;
2401 zval *self = ZEND_THIS;
2402 zend_long index, method;
2403 char *password = NULL;
2404 size_t password_len;
2405
2406 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|s!",
2407 &index, &method, &password, &password_len) == FAILURE) {
2408 RETURN_THROWS();
2409 }
2410
2411 ZIP_FROM_OBJECT(intern, self);
2412
2413 if (zip_file_set_encryption(intern, index, (zip_uint16_t)method, password)) {
2415 }
2417}
2418/* }}} */
2419#endif
2420
2421/* {{{ Returns the comment of an entry using its name */
2422PHP_METHOD(ZipArchive, getCommentName)
2423{
2424 struct zip *intern;
2425 zval *self = ZEND_THIS;
2426 size_t name_len;
2427 int idx;
2428 zend_long flags = 0;
2429 zip_uint32_t comment_len = 0;
2430 const char * comment;
2431 char *name;
2432
2434 &name, &name_len, &flags) == FAILURE) {
2435 RETURN_THROWS();
2436 }
2437
2438 ZIP_FROM_OBJECT(intern, self);
2439
2440 if (name_len == 0) {
2442 RETURN_THROWS();
2443 }
2444
2445 idx = zip_name_locate(intern, name, 0);
2446
2447 if (idx < 0) {
2449 }
2450
2451 comment = zip_file_get_comment(intern, idx, &comment_len, (zip_flags_t)flags);
2452 RETURN_STRINGL((char *)comment, comment_len);
2453}
2454/* }}} */
2455
2456/* {{{ Returns the comment of an entry using its index */
2457PHP_METHOD(ZipArchive, getCommentIndex)
2458{
2459 struct zip *intern;
2460 zval *self = ZEND_THIS;
2461 zend_long index, flags = 0;
2462 const char * comment;
2463 zip_uint32_t comment_len = 0;
2464 struct zip_stat sb;
2465
2467 &index, &flags) == FAILURE) {
2468 RETURN_THROWS();
2469 }
2470
2471 ZIP_FROM_OBJECT(intern, self);
2472
2473 PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2474 comment = zip_file_get_comment(intern, index, &comment_len, (zip_flags_t)flags);
2475 RETURN_STRINGL((char *)comment, comment_len);
2476}
2477/* }}} */
2478
2479/* {{{ Set the compression of a file in zip, using its name */
2480PHP_METHOD(ZipArchive, setCompressionName)
2481{
2482 struct zip *intern;
2483 zval *this = ZEND_THIS;
2484 size_t name_len;
2485 char *name;
2486 zip_int64_t idx;
2487 zend_long comp_method, comp_flags = 0;
2488
2490 &name, &name_len, &comp_method, &comp_flags) == FAILURE) {
2491 RETURN_THROWS();
2492 }
2493
2494 ZIP_FROM_OBJECT(intern, this);
2495
2496 if (name_len == 0) {
2498 RETURN_THROWS();
2499 }
2500
2501 idx = zip_name_locate(intern, name, 0);
2502
2503 if (idx < 0) {
2505 }
2506
2507 if (zip_set_file_compression(intern, (zip_uint64_t)idx,
2508 (zip_int32_t)comp_method, (zip_uint32_t)comp_flags) != 0) {
2510 }
2512}
2513/* }}} */
2514
2515/* {{{ Set the compression of a file in zip, using its index */
2516PHP_METHOD(ZipArchive, setCompressionIndex)
2517{
2518 struct zip *intern;
2519 zval *this = ZEND_THIS;
2520 zend_long index;
2521 zend_long comp_method, comp_flags = 0;
2522
2524 &index, &comp_method, &comp_flags) == FAILURE) {
2525 RETURN_THROWS();
2526 }
2527
2528 ZIP_FROM_OBJECT(intern, this);
2529
2530 if (zip_set_file_compression(intern, (zip_uint64_t)index,
2531 (zip_int32_t)comp_method, (zip_uint32_t)comp_flags) != 0) {
2533 }
2535}
2536/* }}} */
2537
2538#ifdef HAVE_SET_MTIME
2539/* {{{ Set the modification time of a file in zip, using its name */
2540PHP_METHOD(ZipArchive, setMtimeName)
2541{
2542 struct zip *intern;
2543 zval *this = ZEND_THIS;
2544 size_t name_len;
2545 char *name;
2546 zip_int64_t idx;
2547 zend_long mtime, flags = 0;
2548
2550 &name, &name_len, &mtime, &flags) == FAILURE) {
2551 RETURN_THROWS();
2552 }
2553
2554 ZIP_FROM_OBJECT(intern, this);
2555
2556 if (name_len == 0) {
2558 RETURN_THROWS();
2559 }
2560
2561 idx = zip_name_locate(intern, name, 0);
2562
2563 if (idx < 0) {
2565 }
2566
2567 if (zip_file_set_mtime(intern, (zip_uint64_t)idx,
2568 (time_t)mtime, (zip_uint32_t)flags) != 0) {
2570 }
2572}
2573/* }}} */
2574
2575/* {{{ Set the modification time of a file in zip, using its index */
2576PHP_METHOD(ZipArchive, setMtimeIndex)
2577{
2578 struct zip *intern;
2579 zval *this = ZEND_THIS;
2580 zend_long index;
2581 zend_long mtime, flags = 0;
2582
2584 &index, &mtime, &flags) == FAILURE) {
2585 RETURN_THROWS();
2586 }
2587
2588 ZIP_FROM_OBJECT(intern, this);
2589
2590 if (zip_file_set_mtime(intern, (zip_uint64_t)index,
2591 (time_t)mtime, (zip_uint32_t)flags) != 0) {
2593 }
2595}
2596/* }}} */
2597#endif
2598
2599/* {{{ Delete a file using its index */
2601{
2602 struct zip *intern;
2603 zval *self = ZEND_THIS;
2604 zend_long index;
2605
2606 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
2607 RETURN_THROWS();
2608 }
2609
2610 ZIP_FROM_OBJECT(intern, self);
2611
2612 if (index < 0) {
2614 }
2615
2616 if (zip_delete(intern, index) < 0) {
2618 }
2619
2621}
2622/* }}} */
2623
2624/* {{{ Delete a file using its index */
2626{
2627 struct zip *intern;
2628 zval *self = ZEND_THIS;
2629 size_t name_len;
2630 char *name;
2631 struct zip_stat sb;
2632
2633 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
2634 RETURN_THROWS();
2635 }
2636
2637 ZIP_FROM_OBJECT(intern, self);
2638
2639 if (name_len < 1) {
2641 }
2642
2643 PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
2644 if (zip_delete(intern, sb.index)) {
2646 }
2648}
2649/* }}} */
2650
2651/* {{{ Rename an entry selected by its index to new_name */
2653{
2654 struct zip *intern;
2655 zval *self = ZEND_THIS;
2656 char *new_name;
2657 size_t new_name_len;
2658 zend_long index;
2659
2660 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &index, &new_name, &new_name_len) == FAILURE) {
2661 RETURN_THROWS();
2662 }
2663
2664 if (index < 0) {
2666 }
2667
2668 ZIP_FROM_OBJECT(intern, self);
2669
2670 if (new_name_len == 0) {
2672 RETURN_THROWS();
2673 }
2674
2675 if (zip_file_rename(intern, index, (const char *)new_name, 0) != 0) {
2677 }
2678
2680}
2681/* }}} */
2682
2683/* {{{ Rename an entry selected by its name to new_name */
2685{
2686 struct zip *intern;
2687 zval *self = ZEND_THIS;
2688 struct zip_stat sb;
2689 char *name, *new_name;
2690 size_t name_len, new_name_len;
2691
2692 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &name, &name_len, &new_name, &new_name_len) == FAILURE) {
2693 RETURN_THROWS();
2694 }
2695
2696 ZIP_FROM_OBJECT(intern, self);
2697
2698 if (new_name_len == 0) {
2700 RETURN_THROWS();
2701 }
2702
2703 PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
2704
2705 if (zip_file_rename(intern, sb.index, (const char *)new_name, 0)) {
2707 }
2708
2710}
2711/* }}} */
2712
2713/* {{{ Changes to the file at position index are reverted */
2714PHP_METHOD(ZipArchive, unchangeIndex)
2715{
2716 struct zip *intern;
2717 zval *self = ZEND_THIS;
2718 zend_long index;
2719
2720 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) {
2721 RETURN_THROWS();
2722 }
2723
2724 ZIP_FROM_OBJECT(intern, self);
2725
2726 if (index < 0) {
2728 }
2729
2730 if (zip_unchange(intern, index) != 0) {
2732 } else {
2734 }
2735}
2736/* }}} */
2737
2738/* {{{ Changes to the file named 'name' are reverted */
2740{
2741 struct zip *intern;
2742 zval *self = ZEND_THIS;
2743 struct zip_stat sb;
2744 char *name;
2745 size_t name_len;
2746
2747 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
2748 RETURN_THROWS();
2749 }
2750
2751 ZIP_FROM_OBJECT(intern, self);
2752
2753 if (name_len < 1) {
2755 }
2756
2757 PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
2758
2759 if (zip_unchange(intern, sb.index) != 0) {
2761 } else {
2763 }
2764}
2765/* }}} */
2766
2767/* {{{ All changes to files and global information in archive are reverted */
2769{
2770 struct zip *intern;
2771 zval *self = ZEND_THIS;
2772
2774 RETURN_THROWS();
2775 }
2776
2777 ZIP_FROM_OBJECT(intern, self);
2778
2779 if (zip_unchange_all(intern) != 0) {
2781 } else {
2783 }
2784}
2785/* }}} */
2786
2787/* {{{ Revert all global changes to the archive archive. For now, this only reverts archive comment changes. */
2788PHP_METHOD(ZipArchive, unchangeArchive)
2789{
2790 struct zip *intern;
2791 zval *self = ZEND_THIS;
2792
2794 RETURN_THROWS();
2795 }
2796
2797 ZIP_FROM_OBJECT(intern, self);
2798
2799 if (zip_unchange_archive(intern) != 0) {
2801 } else {
2803 }
2804}
2805/* }}} */
2806
2807/* {{{ Extract one or more file from a zip archive */
2808/* TODO:
2809 * - allow index or array of indices
2810 * - replace path
2811 * - patterns
2812 */
2814{
2815 struct zip *intern;
2816
2817 zval *self = ZEND_THIS;
2818 zend_string *files_str = NULL;
2819 HashTable *files_ht = NULL;
2820
2822 char *pathto;
2823 size_t pathto_len;
2824 int ret;
2825
2827 Z_PARAM_PATH(pathto, pathto_len)
2829 Z_PARAM_ARRAY_HT_OR_STR_OR_NULL(files_ht, files_str)
2831
2832 ZIP_FROM_OBJECT(intern, self);
2833
2834 if (pathto_len < 1) {
2836 }
2837
2838 if (php_stream_stat_path_ex(pathto, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
2840 if (!ret) {
2842 }
2843 }
2844
2845 uint32_t nelems, i;
2846
2847 if (files_str) {
2848 if (!php_zip_extract_file(intern, pathto, ZSTR_VAL(files_str), ZSTR_LEN(files_str), -1)) {
2850 }
2851 } else if (files_ht) {
2852 nelems = zend_hash_num_elements(files_ht);
2853 if (nelems == 0 ) {
2855 }
2856 for (i = 0; i < nelems; i++) {
2857 zval *zval_file;
2858 if ((zval_file = zend_hash_index_find_deref(files_ht, i)) != NULL) {
2859 switch (Z_TYPE_P(zval_file)) {
2860 case IS_LONG:
2861 break;
2862 case IS_STRING:
2863 if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), -1)) {
2865 }
2866 break;
2867 }
2868 }
2869 }
2870 } else {
2871 /* Extract all files */
2872 zip_int64_t i, filecount = zip_get_num_entries(intern, 0);
2873
2874 if (filecount == -1) {
2875 php_error_docref(NULL, E_WARNING, "Illegal archive");
2877 }
2878
2879 for (i = 0; i < filecount; i++) {
2880 const char *file = zip_get_name(intern, i, ZIP_FL_UNCHANGED);
2881 if (!file || !php_zip_extract_file(intern, pathto, file, strlen(file), i)) {
2883 }
2884 }
2885 }
2886
2888}
2889/* }}} */
2890
2891static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
2892{
2893 struct zip *intern;
2894 zval *self = ZEND_THIS;
2895
2896 struct zip_stat sb;
2897 struct zip_file *zf;
2898
2899 zend_long index = -1;
2900 zend_long flags = 0;
2901 zend_long len = 0;
2902
2903 zend_string *filename;
2905
2906 int n = 0;
2907
2908 if (type == 1) {
2909 if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|ll", &filename, &len, &flags) == FAILURE) {
2910 RETURN_THROWS();
2911 }
2912
2913 ZIP_FROM_OBJECT(intern, self);
2914
2915 PHP_ZIP_STAT_PATH(intern, ZSTR_VAL(filename), ZSTR_LEN(filename), flags, sb);
2916 } else {
2917 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|ll", &index, &len, &flags) == FAILURE) {
2918 RETURN_THROWS();
2919 }
2920
2921 ZIP_FROM_OBJECT(intern, self);
2922
2923 PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2924 }
2925
2926 if (sb.size < 1) {
2928 }
2929
2930 if (len < 1) {
2931 len = sb.size;
2932 }
2933 if (index >= 0) {
2934 zf = zip_fopen_index(intern, index, flags);
2935 } else {
2936 zf = zip_fopen(intern, ZSTR_VAL(filename), flags);
2937 }
2938
2939 if (zf == NULL) {
2941 }
2942
2943 buffer = zend_string_safe_alloc(1, len, 0, 0);
2944 n = zip_fread(zf, ZSTR_VAL(buffer), ZSTR_LEN(buffer));
2945 if (n < 1) {
2946 zend_string_efree(buffer);
2948 }
2949
2950 zip_fclose(zf);
2951 ZSTR_VAL(buffer)[n] = '\0';
2952 ZSTR_LEN(buffer) = n;
2954}
2955/* }}} */
2956
2957/* {{{ get the contents of an entry using its name */
2959{
2960 php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2961}
2962/* }}} */
2963
2964/* {{{ get the contents of an entry using its index */
2966{
2967 php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2968}
2969/* }}} */
2970
2971static void php_zip_get_stream(INTERNAL_FUNCTION_PARAMETERS, int type, bool accept_flags) /* {{{ */
2972{
2973 struct zip *intern;
2974 zval *self = ZEND_THIS;
2975 zend_long index;
2976 zend_long flags = 0;
2977 struct zip_stat sb;
2978 char *mode = "rb";
2979 zend_string *filename;
2980 php_stream *stream;
2981
2982 if (type) {
2983 if (accept_flags) {
2984 if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &filename, &flags) == FAILURE) {
2985 RETURN_THROWS();
2986 }
2987 } else {
2988 if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &filename) == FAILURE) {
2989 RETURN_THROWS();
2990 }
2991 }
2992 } else {
2993 ZEND_ASSERT(accept_flags);
2994 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &index, &flags) == FAILURE) {
2995 RETURN_THROWS();
2996 }
2997 }
2998
2999 ZIP_FROM_OBJECT(intern, self);
3000
3001 if (type) {
3002 PHP_ZIP_STAT_PATH(intern, ZSTR_VAL(filename), ZSTR_LEN(filename), flags, sb);
3003 } else {
3004 PHP_ZIP_STAT_INDEX(intern, index, flags, sb);
3005 }
3006
3007 stream = php_stream_zip_open(intern, &sb, mode, flags STREAMS_CC);
3008 if (stream) {
3010 } else {
3012 }
3013}
3014
3015/* {{{ get a stream for an entry using its name */
3016PHP_METHOD(ZipArchive, getStreamName)
3017{
3018 php_zip_get_stream(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, /* accept_flags */ true);
3019}
3020/* }}} */
3021
3022/* {{{ get a stream for an entry using its index */
3023PHP_METHOD(ZipArchive, getStreamIndex)
3024{
3025 php_zip_get_stream(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, /* accept_flags */ true);
3026}
3027/* }}} */
3028
3030{
3031 php_zip_get_stream(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, /* accept_flags */ false);
3032}
3033
3034#ifdef HAVE_PROGRESS_CALLBACK
3035static void _php_zip_progress_callback(zip_t *arch, double state, void *ptr)
3036{
3037 zval cb_args[1];
3038 zval cb_retval;
3039 ze_zip_object *obj = ptr;
3040
3041 ZVAL_DOUBLE(&cb_args[0], state);
3042 if (call_user_function(EG(function_table), NULL, &obj->progress_callback, &cb_retval, 1, cb_args) == SUCCESS && !Z_ISUNDEF(cb_retval)) {
3043 zval_ptr_dtor(&cb_retval);
3044 }
3045}
3046
3047/* {{{ register a progression callback: void callback(double state); */
3048PHP_METHOD(ZipArchive, registerProgressCallback)
3049{
3050 struct zip *intern;
3051 zval *self = ZEND_THIS;
3052 double rate;
3053 zend_fcall_info fci;
3055 ze_zip_object *obj;
3056
3057 if (zend_parse_parameters(ZEND_NUM_ARGS(), "df", &rate, &fci, &fcc) == FAILURE) {
3058 RETURN_THROWS();
3059 }
3060
3061 ZIP_FROM_OBJECT(intern, self);
3062
3063 obj = Z_ZIP_P(self);
3064
3065 /* register */
3066 if (zip_register_progress_callback_with_state(intern, rate, _php_zip_progress_callback, _php_zip_progress_callback_free, obj)) {
3068 }
3069 ZVAL_COPY(&obj->progress_callback, &fci.function_name);
3070
3072}
3073/* }}} */
3074#endif
3075
3076#ifdef HAVE_CANCEL_CALLBACK
3077static int _php_zip_cancel_callback(zip_t *arch, void *ptr)
3078{
3079 zval cb_retval;
3080 int retval = 0;
3081 ze_zip_object *obj = ptr;
3082
3083 if (call_user_function(EG(function_table), NULL, &obj->cancel_callback, &cb_retval, 0, NULL) == SUCCESS && !Z_ISUNDEF(cb_retval)) {
3084 retval = zval_get_long(&cb_retval);
3085 zval_ptr_dtor(&cb_retval);
3086 }
3087
3088 return retval;
3089}
3090
3091/* {{{ register a progression callback: int callback(double state); */
3092PHP_METHOD(ZipArchive, registerCancelCallback)
3093{
3094 struct zip *intern;
3095 zval *self = ZEND_THIS;
3096 zend_fcall_info fci;
3098 ze_zip_object *obj;
3099 if (zend_parse_parameters(ZEND_NUM_ARGS(), "f", &fci, &fcc) == FAILURE) {
3100 RETURN_THROWS();
3101 }
3102
3103 ZIP_FROM_OBJECT(intern, self);
3104
3105 obj = Z_ZIP_P(self);
3106
3107 /* register */
3108 if (zip_register_cancel_callback_with_state(intern, _php_zip_cancel_callback, _php_zip_cancel_callback_free, obj)) {
3110 }
3111 ZVAL_COPY(&obj->cancel_callback, &fci.function_name);
3112
3114}
3115/* }}} */
3116#endif
3117
3118#ifdef HAVE_METHOD_SUPPORTED
3119/* {{{ check if a compression method is available in used libzip */
3120PHP_METHOD(ZipArchive, isCompressionMethodSupported)
3121{
3122 zend_long method;
3123 bool enc = 1;
3124
3125 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|b", &method, &enc) == FAILURE) {
3126 return;
3127 }
3128 RETVAL_BOOL(zip_compression_method_supported((zip_int32_t)method, enc));
3129}
3130/* }}} */
3131
3132/* {{{ check if a encryption method is available in used libzip */
3133PHP_METHOD(ZipArchive, isEncryptionMethodSupported)
3134{
3135 zend_long method;
3136 bool enc = 1;
3137
3138 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|b", &method, &enc) == FAILURE) {
3139 return;
3140 }
3141 RETVAL_BOOL(zip_encryption_method_supported((zip_uint16_t)method, enc));
3142}
3143/* }}} */
3144#endif
3145
3146static void php_zip_free_prop_handler(zval *el) /* {{{ */ {
3147 pefree(Z_PTR_P(el), 1);
3148} /* }}} */
3149
3150/* {{{ PHP_MINIT_FUNCTION */
3151static PHP_MINIT_FUNCTION(zip)
3152{
3153 memcpy(&zip_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
3154 zip_object_handlers.offset = XtOffsetOf(ze_zip_object, zo);
3155 zip_object_handlers.free_obj = php_zip_object_free_storage;
3156 zip_object_handlers.clone_obj = NULL;
3157 zip_object_handlers.get_property_ptr_ptr = php_zip_get_property_ptr_ptr;
3158
3159 zip_object_handlers.get_gc = php_zip_get_gc;
3160 zip_object_handlers.get_properties = php_zip_get_properties;
3161 zip_object_handlers.read_property = php_zip_read_property;
3162 zip_object_handlers.has_property = php_zip_has_property;
3163 zip_object_handlers.write_property = php_zip_write_property;
3164
3165 zip_class_entry = register_class_ZipArchive(zend_ce_countable);
3166 zip_class_entry->create_object = php_zip_object_new;
3167 zip_class_entry->default_object_handlers = &zip_object_handlers;
3168
3169 zend_hash_init(&zip_prop_handlers, 0, NULL, php_zip_free_prop_handler, 1);
3170 php_zip_register_prop_handler(&zip_prop_handlers, "lastId", php_zip_last_id, NULL, IS_LONG);
3171 php_zip_register_prop_handler(&zip_prop_handlers, "status", php_zip_status, NULL, IS_LONG);
3172 php_zip_register_prop_handler(&zip_prop_handlers, "statusSys", php_zip_status_sys, NULL, IS_LONG);
3173 php_zip_register_prop_handler(&zip_prop_handlers, "numFiles", php_zip_get_num_files, NULL, IS_LONG);
3174 php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, php_zipobj_get_filename, IS_STRING);
3175 php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, IS_STRING);
3176
3178
3179 register_php_zip_symbols(module_number);
3180
3181 le_zip_dir = zend_register_list_destructors_ex(php_zip_free_dir, NULL, le_zip_dir_name, module_number);
3182 le_zip_entry = zend_register_list_destructors_ex(php_zip_free_entry, NULL, le_zip_entry_name, module_number);
3183
3184 return SUCCESS;
3185}
3186/* }}} */
3187
3188/* {{{ PHP_MSHUTDOWN_FUNCTION */
3189static PHP_MSHUTDOWN_FUNCTION(zip)
3190{
3191 zend_hash_destroy(&zip_prop_handlers);
3193 return SUCCESS;
3194}
3195/* }}} */
3196
3197/* {{{ PHP_MINFO_FUNCTION */
3198static PHP_MINFO_FUNCTION(zip)
3199{
3201
3202 php_info_print_table_row(2, "Zip", "enabled");
3203 php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION);
3204#ifdef HAVE_LIBZIP_VERSION
3205 if (strcmp(LIBZIP_VERSION, zip_libzip_version())) {
3206 php_info_print_table_row(2, "Libzip headers version", LIBZIP_VERSION);
3207 php_info_print_table_row(2, "Libzip library version", zip_libzip_version());
3208 } else
3209#endif
3210 {
3211 php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION);
3212 }
3213#ifdef HAVE_METHOD_SUPPORTED
3214 php_info_print_table_row(2, "BZIP2 compression",
3215 zip_compression_method_supported(ZIP_CM_BZIP2, 1) ? "Yes" : "No");
3216 php_info_print_table_row(2, "XZ compression",
3217 zip_compression_method_supported(ZIP_CM_XZ, 1) ? "Yes" : "No");
3218#ifdef ZIP_CM_ZSTD
3219 php_info_print_table_row(2, "ZSTD compression",
3220 zip_compression_method_supported(ZIP_CM_ZSTD, 1) ? "Yes" : "No");
3221#else
3222 php_info_print_table_row(2, "ZSTD compression", "No");
3223#endif
3224 php_info_print_table_row(2, "AES-128 encryption",
3225 zip_encryption_method_supported(ZIP_EM_AES_128, 1) ? "Yes" : "No");
3226 php_info_print_table_row(2, "AES-192 encryption",
3227 zip_encryption_method_supported(ZIP_EM_AES_128, 1) ? "Yes" : "No");
3228 php_info_print_table_row(2, "AES-256 encryption",
3229 zip_encryption_method_supported(ZIP_EM_AES_128, 1) ? "Yes" : "No");
3230#endif
3231
3233}
3234/* }}} */
size_t len
Definition apprentice.c:174
file(string $filename, int $flags=0, $context=null)
dirname(string $path, int $levels=1)
fopen(string $filename, string $mode, bool $use_include_path=false, $context=null)
count(Countable|array $value, int $mode=COUNT_NORMAL)
glob(string $pattern, int $flags=0)
basename(string $path, string $suffix="")
char s[4]
Definition cdf.c:77
const GLOB_AVAILABLE_FLAGS
Definition dir.stub.php:71
const GLOB_ONLYDIR
Definition dir.stub.php:64
zend_ffi_type * type
Definition ffi.c:3812
zend_long n
Definition ffi.c:4979
zend_string * res
Definition ffi.c:4692
void * ptr
Definition ffi.c:3814
memcpy(ptr1, ptr2, size)
char * err
Definition ffi.c:3029
new_type attr
Definition ffi.c:4364
zval * val
Definition ffi.c:4262
PHPAPI void php_clear_stat_cache(bool clear_realpath_cache, const char *filename, size_t filename_len)
Definition filestat.c:697
PHPAPI char * expand_filepath(const char *filepath, char *real_path)
size_t mode_len
char * mode
size_t filename_len
#define NULL
Definition gdcache.h:45
PHPAPI void globfree(glob_t *pglob)
Definition glob.c:777
#define GLOB_NOMATCH
Definition glob.h:94
#define SUCCESS
Definition hash_sha3.c:261
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
#define pcre2_code
Definition pcre2.h:822
#define pcre2_match
Definition pcre2.h:881
#define PCRE2_SPTR
Definition pcre2.h:820
#define pcre2_match_data
Definition pcre2.h:844
#define pcre2_match_context
Definition pcre2.h:843
php_info_print_table_start()
Definition info.c:1064
php_info_print_table_row(2, "PDO Driver for Firebird", "enabled")
php_info_print_table_end()
Definition info.c:1074
char * cwd
#define PHP_FUNCTION
Definition php.h:364
#define PHP_MSHUTDOWN_FUNCTION
Definition php.h:401
#define PHP_MINFO
Definition php.h:396
#define PHP_MINIT_FUNCTION
Definition php.h:400
#define PHP_MSHUTDOWN
Definition php.h:393
#define PHP_MINFO_FUNCTION
Definition php.h:404
#define PHP_MINIT
Definition php.h:392
#define PHP_METHOD
Definition php.h:365
unsigned const char * pos
Definition php_ffi.h:52
PHP_JSON_API size_t int options
Definition php_json.h:102
PHPAPI pcre2_match_context * php_pcre_mctx(void)
Definition php_pcre.c:3054
PHPAPI pcre2_match_data * php_pcre_create_match_data(uint32_t capture_count, pcre2_code *re)
Definition php_pcre.c:906
PHPAPI pcre2_code * pcre_get_compiled_regex(zend_string *regex, uint32_t *capture_count)
Definition php_pcre.c:892
PHPAPI void php_pcre_free_match_data(pcre2_match_data *match_data)
Definition php_pcre.c:928
unsigned char key[REFLECTION_KEY_LEN]
struct _php_stream php_stream
Definition php_streams.h:96
#define php_stream_stat_path_ex(path, flags, ssb, context)
#define REPORT_ERRORS
#define STREAMS_CC
Definition php_streams.h:54
#define php_stream_mkdir(path, mode, options, context)
#define PHP_STREAM_MKDIR_RECURSIVE
#define php_stream_to_zval(stream, zval)
PHPAPI int php_stream_dirent_alphasort(const zend_string **a, const zend_string **b)
Definition streams.c:2438
#define php_stream_close(stream)
#define php_stream_scandir(dirname, namelist, context, compare)
PHPAPI zend_result php_register_url_stream_wrapper(const char *protocol, const php_stream_wrapper *wrapper)
Definition streams.c:1911
#define PHP_STREAM_META_TOUCH
#define php_stream_open_wrapper(path, mode, options, opened)
PHPAPI zend_result php_unregister_url_stream_wrapper(const char *protocol)
Definition streams.c:1927
#define PHP_STREAM_URL_STAT_QUIET
struct _php_stream_statbuf php_stream_statbuf
#define php_stream_write(stream, buf, count)
PHPAPI zend_string * php_basename(const char *s, size_t len, const char *suffix, size_t sufflen)
Definition string.c:1372
int php_zip_glob(char *pattern, int pattern_len, zend_long flags, zval *return_value)
Definition php_zip.c:615
int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_value)
Definition php_zip.c:722
#define CWD_STATE_FREE(s)
Definition php_zip.c:121
#define PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb)
Definition php_zip.c:57
#define ZIP_FROM_OBJECT(intern, object)
Definition php_zip.c:466
#define le_zip_entry_name
Definition php_zip.c:45
#define PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len)
Definition php_zip.c:68
zend_long(* zip_read_int_t)(ze_zip_object *obj)
Definition php_zip.c:834
#define le_zip_dir_name
Definition php_zip.c:43
char *(* zip_read_const_char_t)(ze_zip_object *obj, int *len)
Definition php_zip.c:835
zend_module_entry zip_module_entry
Definition php_zip.c:1160
#define RETURN_SB(sb)
Definition php_zip.c:492
#define PHP_ZIP_STAT_INDEX(za, index, flags, sb)
Definition php_zip.c:49
#define CWD_STATE_ALLOC(l)
Definition php_zip.c:120
struct _zip_prop_handler zip_prop_handler
#define ZIP_OPENBASEDIR_CHECKPATH(filename)
Definition php_zip.h:50
struct _ze_zip_object ze_zip_object
#define Z_ZIP_P(zv)
Definition php_zip.h:92
#define ZIP_FL_OPEN_FILE_NOW
Definition php_zip.h:40
php_stream * php_stream_zip_open(struct zip *arch, struct zip_stat *sb, const char *mode, zip_flags_t flags STREAMS_DC)
#define PHP_ZIP_VERSION
Definition php_zip.h:42
struct _ze_zip_rsrc zip_rsrc
struct _ze_zip_read_rsrc zip_read_rsrc
const php_stream_wrapper php_stream_zip_wrapper
zip_read($zip)
zip_open(string $filename)
zip_close($zip)
zip_entry_filesize($zip_entry)
zip_entry_compressedsize($zip_entry)
zip_entry_compressionmethod($zip_entry)
zip_entry_open($zip_dp, $zip_entry, string $mode="rb")
zip_entry_name($zip_entry)
zip_entry_close($zip_entry)
zip_entry_read($zip_entry, int $len=1024)
int fd
Definition phpdbg.h:282
zval rv
Definition session.c:1024
#define spprintf
Definition spprintf.h:29
int(* stream_metadata)(php_stream_wrapper *wrapper, const char *url, int options, void *value, php_stream_context *context)
const php_stream_wrapper_ops * wops
php_stream_wrapper * wrapper
zip_int64_t last_id
Definition php_zip.h:76
int buffers_cnt
Definition php_zip.h:75
struct zip * za
Definition php_zip.h:70
char ** buffers
Definition php_zip.h:71
zend_object zo
Definition php_zip.h:85
int filename_len
Definition php_zip.h:74
char * filename
Definition php_zip.h:73
HashTable * prop_handler
Definition php_zip.h:72
struct zip_stat sb
Definition php_zip.h:62
zend_long zip_rsrc_handle
Definition php_zip.h:65
struct zip_file * zf
Definition php_zip.h:61
struct zip * za
Definition php_zip.h:53
zip_int64_t num_files
Definition php_zip.h:55
zip_uint64_t index_current
Definition php_zip.h:54
zip_read_const_char_t read_const_char_func
Definition php_zip.c:839
zip_read_int_t read_int_func
Definition php_zip.c:838
Definition file.h:177
Definition glob.h:51
int gl_offs
Definition glob.h:54
int gl_pathc
Definition glob.h:52
char ** gl_pathv
Definition glob.h:56
size_t add_path_len
Definition php_zip.c:346
zip_int32_t comp_method
Definition php_zip.c:348
zip_flags_t flags
Definition php_zip.c:347
char * remove_path
Definition php_zip.c:343
zend_long remove_all_path
Definition php_zip.c:342
char * add_path
Definition php_zip.c:345
size_t remove_path_len
Definition php_zip.c:344
zip_uint32_t comp_flags
Definition php_zip.c:349
#define close(a)
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API ZEND_COLD void zend_type_error(const char *format,...)
Definition zend.c:1824
ZEND_API ZEND_COLD void zend_value_error(const char *format,...)
Definition zend.c:1849
#define INTERNAL_FUNCTION_PARAMETERS
Definition zend.h:49
#define INTERNAL_FUNCTION_PARAM_PASSTHRU
Definition zend.h:50
ZEND_API const char * zend_zval_value_name(const zval *arg)
Definition zend_API.c:148
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type)
Definition zend_API.c:1688
ZEND_API ZEND_COLD void zend_argument_must_not_be_empty_error(uint32_t arg_num)
Definition zend_API.c:443
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
ZEND_API zend_result add_next_index_string(zval *arg, const char *str)
Definition zend_API.c:2186
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
struct _zend_fcall_info_cache zend_fcall_info_cache
#define Z_PARAM_ARRAY_HT_OR_STR_OR_NULL(dest_ht, dest_str)
Definition zend_API.h:2154
#define RETURN_STRING(s)
Definition zend_API.h:1043
#define RETURN_STRINGL(s, l)
Definition zend_API.h:1044
#define ZEND_PARSE_PARAMETERS_END()
Definition zend_API.h:1641
#define RETURN_FALSE
Definition zend_API.h:1058
#define RETVAL_STRING(s)
Definition zend_API.h:1017
#define Z_PARAM_OPTIONAL
Definition zend_API.h:1667
#define ZEND_GET_MODULE(name)
Definition zend_API.h:241
#define zend_parse_parameters_none()
Definition zend_API.h:353
#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args)
Definition zend_API.h:1620
#define ZEND_TRY_ASSIGN_REF_LONG(zv, lval)
Definition zend_API.h:1205
#define RETURN_LONG(l)
Definition zend_API.h:1037
#define RETURN_NEW_STR(s)
Definition zend_API.h:1041
struct _zend_fcall_info zend_fcall_info
#define RETURN_THROWS()
Definition zend_API.h:1060
#define RETVAL_TRUE
Definition zend_API.h:1033
#define ZEND_THIS
Definition zend_API.h:523
#define RETVAL_BOOL(b)
Definition zend_API.h:1009
#define RETURN_RES(r)
Definition zend_API.h:1049
#define call_user_function(function_table, object, function_name, retval_ptr, param_count, params)
Definition zend_API.h:687
#define RETVAL_LONG(l)
Definition zend_API.h:1011
#define RETURN_EMPTY_ARRAY()
Definition zend_API.h:1051
#define RETURN_EMPTY_STRING()
Definition zend_API.h:1047
#define Z_PARAM_PATH(dest, dest_len)
Definition zend_API.h:2026
#define ZVAL_STRINGL(z, s, l)
Definition zend_API.h:952
#define RETVAL_FALSE
Definition zend_API.h:1032
#define RETURN_TRUE
Definition zend_API.h:1059
#define RETVAL_STRINGL(s, l)
Definition zend_API.h:1018
#define array_init(arg)
Definition zend_API.h:537
#define ZVAL_EMPTY_STRING(z)
Definition zend_API.h:961
#define safe_erealloc(ptr, nmemb, size, offset)
Definition zend_alloc.h:161
#define efree(ptr)
Definition zend_alloc.h:155
#define pefree(ptr, persistent)
Definition zend_alloc.h:191
#define safe_emalloc(nmemb, size, offset)
Definition zend_alloc.h:154
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
strlen(string $string)
strcmp(string $string1, string $string2)
zend_string_release_ex(func->internal_function.function_name, 0)
ZEND_API size_t zend_dirname(char *path, size_t len)
#define snprintf
#define E_WARNING
Definition zend_errors.h:24
#define E_DEPRECATED
Definition zend_errors.h:37
#define EG(v)
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
Definition zend_hash.c:1727
ZEND_API zval *ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
Definition zend_hash.c:2689
ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
Definition zend_hash.c:1808
ZEND_API zval *ZEND_FASTCALL zend_hash_update(HashTable *ht, zend_string *key, zval *pData)
Definition zend_hash.c:997
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
Definition zend_hash.c:2701
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
Definition zend_hash.h:108
#define ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(ht, _key, _ptr)
Definition zend_hash.h:1433
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
ZEND_API zend_class_entry * zend_ce_countable
ZEND_API void * zend_fetch_resource(zend_resource *res, const char *resource_type_name, int resource_type)
Definition zend_list.c:117
ZEND_API zend_resource * zend_register_resource(void *rsrc_pointer, int rsrc_type)
Definition zend_list.c:87
ZEND_API void ZEND_FASTCALL zend_list_close(zend_resource *res)
Definition zend_list.c:78
ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, const char *type_name, int module_number)
Definition zend_list.c:265
int32_t zend_long
Definition zend_long.h:42
#define ZEND_LONG_MAX
Definition zend_long.h:45
struct _zend_string zend_string
#define ZEND_MOD_END
struct _zend_module_dep zend_module_dep
struct _zend_module_entry zend_module_entry
#define STANDARD_MODULE_PROPERTIES
#define ZEND_MOD_REQUIRED(name)
#define STANDARD_MODULE_HEADER_EX
ZEND_API zval * zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *name, int type, void **cache_slot)
ZEND_API HashTable * zend_std_get_properties(zend_object *zobj)
ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has_set_exists, void **cache_slot)
ZEND_API const zend_object_handlers std_object_handlers
ZEND_API zval * zend_std_write_property(zend_object *zobj, zend_string *name, zval *value, void **cache_slot)
ZEND_API zval * zend_std_read_property(zend_object *zobj, zend_string *name, int type, void **cache_slot, zval *rv)
ZEND_API void ZEND_FASTCALL zend_object_std_init(zend_object *object, zend_class_entry *ce)
ZEND_API void zend_object_std_dtor(zend_object *object)
ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op)
#define MIN(a, b)
#define XtOffsetOf(s_type, field)
#define ZEND_ASSERT(c)
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
struct stat zend_stat_t
Definition zend_stream.h:94
ZEND_API zend_string_init_interned_func_t zend_string_init_interned
Definition zend_string.c:31
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define IS_TRUE
Definition zend_types.h:603
#define ZVAL_UNDEF(z)
#define IS_FALSE
Definition zend_types.h:602
#define Z_STRVAL_P(zval_p)
Definition zend_types.h:975
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define ZVAL_NULL(z)
#define ZVAL_LONG(z, l)
#define IS_STRING
Definition zend_types.h:606
struct _zend_resource zend_resource
Definition zend_types.h:99
struct _zend_array HashTable
Definition zend_types.h:386
#define Z_ISUNDEF(zval)
Definition zend_types.h:956
#define Z_PTR_P(zval_p)
#define Z_STRLEN_P(zval_p)
Definition zend_types.h:978
#define IS_NULL
Definition zend_types.h:601
@ FAILURE
Definition zend_types.h:61
#define IS_LONG
Definition zend_types.h:604
#define ZVAL_COPY(z, v)
#define ZVAL_DOUBLE(z, d)
#define Z_RES_P(zval_p)
struct _zend_object_handlers zend_object_handlers
Definition zend_types.h:88
#define Z_TYPE(zval)
Definition zend_types.h:659
#define Z_ARR_P(zval_p)
Definition zend_types.h:984
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath)
#define IS_SLASH(c)
#define DEFAULT_SLASH
#define COPY_WHEN_ABSOLUTE(path)
#define IS_ABSOLUTE_PATH(path, len)
#define CWD_EXPAND
#define VCWD_GETCWD(buff, size)
#define MAXPATHLEN
struct _cwd_state cwd_state
#define VCWD_STAT(path, buff)
zval retval
zval * return_value
zend_string * name
bool result
object
zval * ret
value