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