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