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