Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / php / ext / zip / php_zip.c
blob727cc853ca1ae15d995c3520c5719784ddc1e292
1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2013 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 +----------------------------------------------------------------------+
19 /* $Id$ */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "ext/standard/file.h"
29 #include "ext/standard/php_string.h"
30 #include "ext/pcre/php_pcre.h"
31 #include "php_zip.h"
32 #include "lib/zip.h"
33 #include "lib/zipint.h"
35 /* zip_open is a macro for renaming libzip zipopen, so we need to use PHP_NAMED_FUNCTION */
36 static PHP_NAMED_FUNCTION(zif_zip_open);
37 static PHP_NAMED_FUNCTION(zif_zip_read);
38 static PHP_NAMED_FUNCTION(zif_zip_close);
39 static PHP_NAMED_FUNCTION(zif_zip_entry_read);
40 static PHP_NAMED_FUNCTION(zif_zip_entry_filesize);
41 static PHP_NAMED_FUNCTION(zif_zip_entry_name);
42 static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize);
43 static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod);
44 static PHP_NAMED_FUNCTION(zif_zip_entry_open);
45 static PHP_NAMED_FUNCTION(zif_zip_entry_close);
47 #ifdef HAVE_GLOB
48 #ifndef PHP_WIN32
49 #include <glob.h>
50 #else
51 #include "win32/glob.h"
52 #endif
53 #endif
55 /* {{{ Resource le */
56 static int le_zip_dir;
57 #define le_zip_dir_name "Zip Directory"
58 static int le_zip_entry;
59 #define le_zip_entry_name "Zip Entry"
60 /* }}} */
62 /* {{{ PHP_ZIP_STAT_INDEX(za, index, flags, sb) */
63 #define PHP_ZIP_STAT_INDEX(za, index, flags, sb) \
64 if (zip_stat_index(za, index, flags, &sb) != 0) { \
65 RETURN_FALSE; \
67 /* }}} */
69 /* {{{ PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) */
70 #define PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) \
71 if (path_len < 1) { \
72 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name"); \
73 RETURN_FALSE; \
74 } \
75 if (zip_stat(za, path, flags, &sb) != 0) { \
76 RETURN_FALSE; \
78 /* }}} */
80 /* {{{ PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) */
81 #define PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) \
82 if (comment_len == 0) { \
83 /* Passing NULL remove the existing comment */ \
84 if (zip_set_file_comment(intern, index, NULL, 0) < 0) { \
85 RETURN_FALSE; \
86 } \
87 } else if (zip_set_file_comment(intern, index, comment, comment_len) < 0) { \
88 RETURN_FALSE; \
89 } \
90 RETURN_TRUE;
91 /* }}} */
93 #if (PHP_MAJOR_VERSION < 6)
94 # define add_ascii_assoc_string add_assoc_string
95 # define add_ascii_assoc_long add_assoc_long
96 #endif
98 /* Flatten a path by making a relative path (to .)*/
99 static char * php_zip_make_relative_path(char *path, int path_len) /* {{{ */
101 char *path_begin = path;
102 size_t i;
104 if (IS_SLASH(path[0])) {
105 return path + 1;
108 if (path_len < 1 || path == NULL) {
109 return NULL;
112 i = path_len;
114 while (1) {
115 while (i > 0 && !IS_SLASH(path[i])) {
116 i--;
119 if (!i) {
120 return path;
123 if (i >= 2 && (path[i -1] == '.' || path[i -1] == ':')) {
124 /* i is the position of . or :, add 1 for / */
125 path_begin = path + i + 1;
126 break;
128 i--;
131 return path_begin;
133 /* }}} */
135 #ifdef PHP_ZIP_USE_OO
136 /* {{{ php_zip_extract_file */
137 static int php_zip_extract_file(struct zip * za, char *dest, char *file, int file_len TSRMLS_DC)
139 php_stream_statbuf ssb;
140 struct zip_file *zf;
141 struct zip_stat sb;
142 char b[8192];
143 int n, len, ret;
144 php_stream *stream;
145 char *fullpath;
146 char *file_dirname_fullpath;
147 char file_dirname[MAXPATHLEN];
148 size_t dir_len;
149 char *file_basename;
150 size_t file_basename_len;
151 int is_dir_only = 0;
152 char *path_cleaned;
153 size_t path_cleaned_len;
154 cwd_state new_state;
156 new_state.cwd = (char*)malloc(1);
157 new_state.cwd[0] = '\0';
158 new_state.cwd_length = 0;
160 /* Clean/normlize the path and then transform any path (absolute or relative)
161 to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt)
163 virtual_file_ex(&new_state, file, NULL, CWD_EXPAND TSRMLS_CC);
164 path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length);
165 if(!path_cleaned) {
166 return 0;
168 path_cleaned_len = strlen(path_cleaned);
170 if (path_cleaned_len >= MAXPATHLEN || zip_stat(za, file, 0, &sb) != 0) {
171 return 0;
174 /* it is a directory only, see #40228 */
175 if (path_cleaned_len > 1 && IS_SLASH(path_cleaned[path_cleaned_len - 1])) {
176 len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file);
177 is_dir_only = 1;
178 } else {
179 memcpy(file_dirname, path_cleaned, path_cleaned_len);
180 dir_len = php_dirname(file_dirname, path_cleaned_len);
182 if (dir_len <= 0 || (dir_len == 1 && file_dirname[0] == '.')) {
183 len = spprintf(&file_dirname_fullpath, 0, "%s", dest);
184 } else {
185 len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file_dirname);
188 php_basename(path_cleaned, path_cleaned_len, NULL, 0, &file_basename, (size_t *)&file_basename_len TSRMLS_CC);
190 if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname_fullpath)) {
191 efree(file_dirname_fullpath);
192 efree(file_basename);
193 free(new_state.cwd);
194 return 0;
198 /* let see if the path already exists */
199 if (php_stream_stat_path_ex(file_dirname_fullpath, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
201 #if defined(PHP_WIN32) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1)
202 char *e;
203 e = file_dirname_fullpath;
204 while (*e) {
205 if (*e == '/') {
206 *e = DEFAULT_SLASH;
208 e++;
210 #endif
212 ret = php_stream_mkdir(file_dirname_fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE|REPORT_ERRORS, NULL);
213 if (!ret) {
214 efree(file_dirname_fullpath);
215 if (!is_dir_only) {
216 efree(file_basename);
217 free(new_state.cwd);
219 return 0;
223 /* it is a standalone directory, job done */
224 if (is_dir_only) {
225 efree(file_dirname_fullpath);
226 free(new_state.cwd);
227 return 1;
230 len = spprintf(&fullpath, 0, "%s/%s", file_dirname_fullpath, file_basename);
231 if (!len) {
232 efree(file_dirname_fullpath);
233 efree(file_basename);
234 free(new_state.cwd);
235 return 0;
236 } else if (len > MAXPATHLEN) {
237 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Full extraction path exceed MAXPATHLEN (%i)", MAXPATHLEN);
238 efree(file_dirname_fullpath);
239 efree(file_basename);
240 free(new_state.cwd);
241 return 0;
244 /* check again the full path, not sure if it
245 * is required, does a file can have a different
246 * safemode status as its parent folder?
248 if (ZIP_OPENBASEDIR_CHECKPATH(fullpath)) {
249 efree(fullpath);
250 efree(file_dirname_fullpath);
251 efree(file_basename);
252 free(new_state.cwd);
253 return 0;
256 #if PHP_API_VERSION < 20100412
257 stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
258 #else
259 stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL);
260 #endif
262 if (stream == NULL) {
263 n = -1;
264 goto done;
267 zf = zip_fopen(za, file, 0);
268 if (zf == NULL) {
269 n = -1;
270 php_stream_close(stream);
271 goto done;
274 n = 0;
276 while ((n=zip_fread(zf, b, sizeof(b))) > 0) {
277 php_stream_write(stream, b, n);
280 php_stream_close(stream);
281 n = zip_fclose(zf);
283 done:
284 efree(fullpath);
285 efree(file_basename);
286 efree(file_dirname_fullpath);
287 free(new_state.cwd);
289 if (n<0) {
290 return 0;
291 } else {
292 return 1;
295 /* }}} */
297 static int php_zip_add_file(struct zip *za, const char *filename, size_t filename_len,
298 char *entry_name, size_t entry_name_len, long offset_start, long offset_len TSRMLS_DC) /* {{{ */
300 struct zip_source *zs;
301 int cur_idx;
302 char resolved_path[MAXPATHLEN];
305 if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
306 return -1;
309 if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
310 return -1;
313 zs = zip_source_file(za, resolved_path, offset_start, offset_len);
314 if (!zs) {
315 return -1;
318 cur_idx = zip_name_locate(za, (const char *)entry_name, 0);
319 /* TODO: fix _zip_replace */
320 if (cur_idx<0) {
321 /* reset the error */
322 if (za->error.str) {
323 _zip_error_fini(&za->error);
325 _zip_error_init(&za->error);
326 } else {
327 if (zip_delete(za, cur_idx) == -1) {
328 zip_source_free(zs);
329 return -1;
333 if (zip_add(za, entry_name, zs) == -1) {
334 return -1;
335 } else {
336 return 1;
339 /* }}} */
341 static int php_zip_parse_options(zval *options, long *remove_all_path,
342 char **remove_path, int *remove_path_len, char **add_path, int *add_path_len TSRMLS_DC) /* {{{ */
344 zval **option;
345 if (zend_hash_find(HASH_OF(options), "remove_all_path", sizeof("remove_all_path"), (void **)&option) == SUCCESS) {
346 long opt;
347 if (Z_TYPE_PP(option) != IS_LONG) {
348 zval tmp = **option;
349 zval_copy_ctor(&tmp);
350 convert_to_long(&tmp);
351 opt = Z_LVAL(tmp);
352 } else {
353 opt = Z_LVAL_PP(option);
355 *remove_all_path = opt;
358 /* If I add more options, it would make sense to create a nice static struct and loop over it. */
359 if (zend_hash_find(HASH_OF(options), "remove_path", sizeof("remove_path"), (void **)&option) == SUCCESS) {
360 if (Z_TYPE_PP(option) != IS_STRING) {
361 php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path option expected to be a string");
362 return -1;
365 if (Z_STRLEN_PP(option) < 1) {
366 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string given as remove_path option");
367 return -1;
370 if (Z_STRLEN_PP(option) >= MAXPATHLEN) {
371 php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path string is too long (max: %i, %i given)",
372 MAXPATHLEN - 1, Z_STRLEN_PP(option));
373 return -1;
375 *remove_path_len = Z_STRLEN_PP(option);
376 *remove_path = Z_STRVAL_PP(option);
379 if (zend_hash_find(HASH_OF(options), "add_path", sizeof("add_path"), (void **)&option) == SUCCESS) {
380 if (Z_TYPE_PP(option) != IS_STRING) {
381 php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path option expected to be a string");
382 return -1;
385 if (Z_STRLEN_PP(option) < 1) {
386 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string given as the add_path option");
387 return -1;
390 if (Z_STRLEN_PP(option) >= MAXPATHLEN) {
391 php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)",
392 MAXPATHLEN - 1, Z_STRLEN_PP(option));
393 return -1;
395 *add_path_len = Z_STRLEN_PP(option);
396 *add_path = Z_STRVAL_PP(option);
398 return 1;
400 /* }}} */
402 /* {{{ REGISTER_ZIP_CLASS_CONST_LONG */
403 #define REGISTER_ZIP_CLASS_CONST_LONG(const_name, value) \
404 zend_declare_class_constant_long(zip_class_entry, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
405 /* }}} */
407 /* {{{ ZIP_FROM_OBJECT */
408 #define ZIP_FROM_OBJECT(intern, object) \
410 ze_zip_object *obj = (ze_zip_object*) zend_object_store_get_object(object TSRMLS_CC); \
411 intern = obj->za; \
412 if (!intern) { \
413 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or unitialized Zip object"); \
414 RETURN_FALSE; \
417 /* }}} */
419 /* {{{ RETURN_SB(sb) */
420 #define RETURN_SB(sb) \
422 array_init(return_value); \
423 add_ascii_assoc_string(return_value, "name", (char *)(sb)->name, 1); \
424 add_ascii_assoc_long(return_value, "index", (long) (sb)->index); \
425 add_ascii_assoc_long(return_value, "crc", (long) (sb)->crc); \
426 add_ascii_assoc_long(return_value, "size", (long) (sb)->size); \
427 add_ascii_assoc_long(return_value, "mtime", (long) (sb)->mtime); \
428 add_ascii_assoc_long(return_value, "comp_size", (long) (sb)->comp_size); \
429 add_ascii_assoc_long(return_value, "comp_method", (long) (sb)->comp_method); \
431 /* }}} */
433 static int php_zip_status(struct zip *za TSRMLS_DC) /* {{{ */
435 int zep, syp;
437 zip_error_get(za, &zep, &syp);
438 return zep;
440 /* }}} */
442 static int php_zip_status_sys(struct zip *za TSRMLS_DC) /* {{{ */
444 int zep, syp;
446 zip_error_get(za, &zep, &syp);
447 return syp;
449 /* }}} */
451 static int php_zip_get_num_files(struct zip *za TSRMLS_DC) /* {{{ */
453 return zip_get_num_files(za);
455 /* }}} */
457 static char * php_zipobj_get_filename(ze_zip_object *obj TSRMLS_DC) /* {{{ */
460 if (!obj) {
461 return NULL;
464 if (obj->filename) {
465 return obj->filename;
467 return NULL;
469 /* }}} */
471 static char * php_zipobj_get_zip_comment(struct zip *za, int *len TSRMLS_DC) /* {{{ */
473 if (za) {
474 return (char *)zip_get_archive_comment(za, len, 0);
476 return NULL;
478 /* }}} */
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
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)
510 #endif /* }}} */
512 int php_zip_glob(char *pattern, int pattern_len, long flags, zval *return_value TSRMLS_DC) /* {{{ */
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 int n;
523 int ret;
525 if (pattern_len >= MAXPATHLEN) {
526 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
527 return -1;
530 if ((GLOB_AVAILABLE_FLAGS & flags) != flags) {
531 php_error_docref(NULL TSRMLS_CC, E_WARNING, "At least one of the passed flags is invalid or not supported on this platform");
532 return -1;
535 #ifdef ZTS
536 if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) {
537 result = VCWD_GETCWD(cwd, MAXPATHLEN);
538 if (!result) {
539 cwd[0] = '\0';
541 #ifdef PHP_WIN32
542 if (IS_SLASH(*pattern)) {
543 cwd[2] = '\0';
545 #endif
546 cwd_skip = strlen(cwd)+1;
548 snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
549 pattern = work_pattern;
551 #endif
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.
565 array_init(return_value);
566 return 0;
568 #endif
569 return 0;
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;
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;
585 array_init(return_value);
586 for (n = 0; n < globbuf.gl_pathc; n++) {
587 /* we need to do this everytime 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.
595 if (flags & GLOB_ONLYDIR) {
596 struct stat s;
598 if (0 != VCWD_STAT(globbuf.gl_pathv[n], &s)) {
599 continue;
602 if (S_IFDIR != (s.st_mode & S_IFMT)) {
603 continue;
606 add_next_index_string(return_value, globbuf.gl_pathv[n]+cwd_skip, 1);
609 globfree(&globbuf);
610 return globbuf.gl_pathc;
611 #else
612 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Glob support is not available");
613 return 0;
614 #endif /* HAVE_GLOB */
616 /* }}} */
618 int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *return_value TSRMLS_DC) /* {{{ */
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 char **namelist;
629 #ifdef ZTS
630 if (!IS_ABSOLUTE_PATH(path, path_len)) {
631 result = VCWD_GETCWD(cwd, MAXPATHLEN);
632 if (!result) {
633 cwd[0] = '\0';
635 #ifdef PHP_WIN32
636 if (IS_SLASH(*path)) {
637 cwd[2] = '\0';
639 #endif
640 cwd_skip = strlen(cwd)+1;
642 snprintf(work_path, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, path);
643 path = work_path;
645 #endif
647 if (ZIP_OPENBASEDIR_CHECKPATH(path)) {
648 return -1;
651 files_cnt = php_stream_scandir(path, &namelist, NULL, (void *) php_stream_dirent_alphasort);
653 if (files_cnt > 0) {
654 pcre *re = NULL;
655 pcre_extra *pcre_extra = NULL;
656 int preg_options = 0, i;
658 re = pcre_get_compiled_regex(regexp, &pcre_extra, &preg_options TSRMLS_CC);
659 if (!re) {
660 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid expression");
661 return -1;
664 array_init(return_value);
666 /* only the files, directories are ignored */
667 for (i = 0; i < files_cnt; i++) {
668 struct stat s;
669 char fullpath[MAXPATHLEN];
670 int ovector[3];
671 int matches;
672 int namelist_len = strlen(namelist[i]);
675 if ((namelist_len == 1 && namelist[i][0] == '.') ||
676 (namelist_len == 2 && namelist[i][0] == '.' && namelist[i][1] == '.')) {
677 efree(namelist[i]);
678 continue;
681 if ((path_len + namelist_len + 1) >= MAXPATHLEN) {
682 php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)",
683 MAXPATHLEN - 1, (path_len + namelist_len + 1));
684 efree(namelist[i]);
685 break;
688 snprintf(fullpath, MAXPATHLEN, "%s%c%s", path, DEFAULT_SLASH, namelist[i]);
690 if (0 != VCWD_STAT(fullpath, &s)) {
691 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot read <%s>", fullpath);
692 efree(namelist[i]);
693 continue;
696 if (S_IFDIR == (s.st_mode & S_IFMT)) {
697 efree(namelist[i]);
698 continue;
701 matches = pcre_exec(re, NULL, namelist[i], strlen(namelist[i]), 0, 0, ovector, 3);
702 /* 0 means that the vector is too small to hold all the captured substring offsets */
703 if (matches < 0) {
704 efree(namelist[i]);
705 continue;
708 add_next_index_string(return_value, fullpath, 1);
709 efree(namelist[i]);
711 efree(namelist);
713 return files_cnt;
715 /* }}} */
717 #endif
719 /* {{{ arginfo */
720 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_open, 0, 0, 1)
721 ZEND_ARG_INFO(0, filename)
722 ZEND_END_ARG_INFO()
724 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_close, 0, 0, 1)
725 ZEND_ARG_INFO(0, zip)
726 ZEND_END_ARG_INFO()
728 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_read, 0, 0, 1)
729 ZEND_ARG_INFO(0, zip)
730 ZEND_END_ARG_INFO()
732 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_open, 0, 0, 2)
733 ZEND_ARG_INFO(0, zip_dp)
734 ZEND_ARG_INFO(0, zip_entry)
735 ZEND_ARG_INFO(0, mode)
736 ZEND_END_ARG_INFO()
738 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_close, 0, 0, 1)
739 ZEND_ARG_INFO(0, zip_ent)
740 ZEND_END_ARG_INFO()
742 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_read, 0, 0, 1)
743 ZEND_ARG_INFO(0, zip_entry)
744 ZEND_ARG_INFO(0, len)
745 ZEND_END_ARG_INFO()
747 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_name, 0, 0, 1)
748 ZEND_ARG_INFO(0, zip_entry)
749 ZEND_END_ARG_INFO()
751 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressedsize, 0, 0, 1)
752 ZEND_ARG_INFO(0, zip_entry)
753 ZEND_END_ARG_INFO()
755 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_filesize, 0, 0, 1)
756 ZEND_ARG_INFO(0, zip_entry)
757 ZEND_END_ARG_INFO()
759 ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressionmethod, 0, 0, 1)
760 ZEND_ARG_INFO(0, zip_entry)
761 ZEND_END_ARG_INFO()
762 /* }}} */
764 /* {{{ zend_function_entry */
765 static const zend_function_entry zip_functions[] = {
766 ZEND_RAW_FENTRY("zip_open", zif_zip_open, arginfo_zip_open, 0)
767 ZEND_RAW_FENTRY("zip_close", zif_zip_close, arginfo_zip_close, 0)
768 ZEND_RAW_FENTRY("zip_read", zif_zip_read, arginfo_zip_read, 0)
769 PHP_FE(zip_entry_open, arginfo_zip_entry_open)
770 PHP_FE(zip_entry_close, arginfo_zip_entry_close)
771 PHP_FE(zip_entry_read, arginfo_zip_entry_read)
772 PHP_FE(zip_entry_filesize, arginfo_zip_entry_filesize)
773 PHP_FE(zip_entry_name, arginfo_zip_entry_name)
774 PHP_FE(zip_entry_compressedsize, arginfo_zip_entry_compressedsize)
775 PHP_FE(zip_entry_compressionmethod, arginfo_zip_entry_compressionmethod)
776 PHP_FE_END
778 /* }}} */
780 /* {{{ ZE2 OO definitions */
781 #ifdef PHP_ZIP_USE_OO
782 static zend_class_entry *zip_class_entry;
783 static zend_object_handlers zip_object_handlers;
785 static HashTable zip_prop_handlers;
787 typedef int (*zip_read_int_t)(struct zip *za TSRMLS_DC);
788 typedef char *(*zip_read_const_char_t)(struct zip *za, int *len TSRMLS_DC);
789 typedef char *(*zip_read_const_char_from_ze_t)(ze_zip_object *obj TSRMLS_DC);
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;
796 int type;
797 } zip_prop_handler;
798 #endif
799 /* }}} */
801 #ifdef PHP_ZIP_USE_OO
802 static void php_zip_register_prop_handler(HashTable *prop_handler, char *name, zip_read_int_t read_int_func, zip_read_const_char_t read_char_func, zip_read_const_char_from_ze_t read_char_from_obj_func, int rettype TSRMLS_DC) /* {{{ */
804 zip_prop_handler hnd;
806 hnd.read_const_char_func = read_char_func;
807 hnd.read_int_func = read_int_func;
808 hnd.read_const_char_from_obj_func = read_char_from_obj_func;
809 hnd.type = rettype;
810 zend_hash_add(prop_handler, name, strlen(name)+1, &hnd, sizeof(zip_prop_handler), NULL);
812 /* }}} */
814 static int php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, zval **retval, int newzval TSRMLS_DC) /* {{{ */
816 const char *retchar = NULL;
817 int retint = 0;
818 int len = 0;
820 if (obj && obj->za != NULL) {
821 if (hnd->read_const_char_func) {
822 retchar = hnd->read_const_char_func(obj->za, &len TSRMLS_CC);
823 } else {
824 if (hnd->read_int_func) {
825 retint = hnd->read_int_func(obj->za TSRMLS_CC);
826 if (retint == -1) {
827 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal zip error returned");
828 return FAILURE;
830 } else {
831 if (hnd->read_const_char_from_obj_func) {
832 retchar = hnd->read_const_char_from_obj_func(obj TSRMLS_CC);
833 len = strlen(retchar);
839 if (newzval) {
840 ALLOC_ZVAL(*retval);
843 switch (hnd->type) {
844 case IS_STRING:
845 if (retchar) {
846 ZVAL_STRINGL(*retval, (char *) retchar, len, 1);
847 } else {
848 ZVAL_EMPTY_STRING(*retval);
850 break;
851 case IS_BOOL:
852 ZVAL_BOOL(*retval, (long)retint);
853 break;
854 case IS_LONG:
855 ZVAL_LONG(*retval, (long)retint);
856 break;
857 default:
858 ZVAL_NULL(*retval);
861 return SUCCESS;
863 /* }}} */
865 static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
867 ze_zip_object *obj;
868 zval tmp_member;
869 zval **retval = NULL;
871 zip_prop_handler *hnd;
872 zend_object_handlers *std_hnd;
873 int ret;
875 if (member->type != IS_STRING) {
876 tmp_member = *member;
877 zval_copy_ctor(&tmp_member);
878 convert_to_string(&tmp_member);
879 member = &tmp_member;
880 key = NULL;
883 ret = FAILURE;
884 obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
886 if (obj->prop_handler != NULL) {
887 if (key) {
888 ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
889 } else {
890 ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
895 if (ret == FAILURE) {
896 std_hnd = zend_get_std_object_handlers();
897 retval = std_hnd->get_property_ptr_ptr(object, member, key TSRMLS_CC);
900 if (member == &tmp_member) {
901 zval_dtor(member);
903 return retval;
905 /* }}} */
907 static zval* php_zip_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
909 ze_zip_object *obj;
910 zval tmp_member;
911 zval *retval;
912 zip_prop_handler *hnd;
913 zend_object_handlers *std_hnd;
914 int ret;
916 if (member->type != IS_STRING) {
917 tmp_member = *member;
918 zval_copy_ctor(&tmp_member);
919 convert_to_string(&tmp_member);
920 member = &tmp_member;
921 key = NULL;
924 ret = FAILURE;
925 obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
927 if (obj->prop_handler != NULL) {
928 if (key) {
929 ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
930 } else {
931 ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
935 if (ret == SUCCESS) {
936 ret = php_zip_property_reader(obj, hnd, &retval, 1 TSRMLS_CC);
937 if (ret == SUCCESS) {
938 /* ensure we're creating a temporary variable */
939 Z_SET_REFCOUNT_P(retval, 0);
940 } else {
941 retval = EG(uninitialized_zval_ptr);
943 } else {
944 std_hnd = zend_get_std_object_handlers();
945 retval = std_hnd->read_property(object, member, type, key TSRMLS_CC);
948 if (member == &tmp_member) {
949 zval_dtor(member);
951 return retval;
953 /* }}} */
955 static int php_zip_has_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
957 ze_zip_object *obj;
958 zval tmp_member;
959 zip_prop_handler *hnd;
960 zend_object_handlers *std_hnd;
961 int ret, retval = 0;
963 if (member->type != IS_STRING) {
964 tmp_member = *member;
965 zval_copy_ctor(&tmp_member);
966 convert_to_string(&tmp_member);
967 member = &tmp_member;
968 key = NULL;
971 ret = FAILURE;
972 obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
974 if (obj->prop_handler != NULL) {
975 if (key) {
976 ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
977 } else {
978 ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
982 if (ret == SUCCESS) {
983 zval *tmp;
984 ALLOC_INIT_ZVAL(tmp);
986 if (type == 2) {
987 retval = 1;
988 } else if (php_zip_property_reader(obj, hnd, &tmp, 0 TSRMLS_CC) == SUCCESS) {
989 Z_SET_REFCOUNT_P(tmp, 1);
990 Z_UNSET_ISREF_P(tmp);
991 if (type == 1) {
992 retval = zend_is_true(tmp);
993 } else if (type == 0) {
994 retval = (Z_TYPE_P(tmp) != IS_NULL);
998 zval_ptr_dtor(&tmp);
999 } else {
1000 std_hnd = zend_get_std_object_handlers();
1001 retval = std_hnd->has_property(object, member, type, key TSRMLS_CC);
1004 if (member == &tmp_member) {
1005 zval_dtor(member);
1007 return retval;
1009 /* }}} */
1011 static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */
1013 ze_zip_object *obj;
1014 zip_prop_handler *hnd;
1015 HashTable *props;
1016 zval *val;
1017 int ret;
1018 char *key;
1019 uint key_len;
1020 HashPosition pos;
1021 ulong num_key;
1023 obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
1024 props = zend_std_get_properties(object TSRMLS_CC);
1026 if (obj->prop_handler == NULL) {
1027 return NULL;
1029 zend_hash_internal_pointer_reset_ex(obj->prop_handler, &pos);
1031 while (zend_hash_get_current_data_ex(obj->prop_handler, (void**)&hnd, &pos) == SUCCESS) {
1032 zend_hash_get_current_key_ex(obj->prop_handler, &key, &key_len, &num_key, 0, &pos);
1033 MAKE_STD_ZVAL(val);
1034 ret = php_zip_property_reader(obj, hnd, &val, 0 TSRMLS_CC);
1035 if (ret != SUCCESS) {
1036 val = EG(uninitialized_zval_ptr);
1038 zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL);
1039 zend_hash_move_forward_ex(obj->prop_handler, &pos);
1041 return props;
1043 /* }}} */
1045 static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */
1047 ze_zip_object * intern = (ze_zip_object *) object;
1048 int i;
1050 if (!intern) {
1051 return;
1053 if (intern->za) {
1054 if (zip_close(intern->za) != 0) {
1055 _zip_free(intern->za);
1057 intern->za = NULL;
1060 if (intern->buffers_cnt>0) {
1061 for (i=0; i<intern->buffers_cnt; i++) {
1062 efree(intern->buffers[i]);
1064 efree(intern->buffers);
1067 intern->za = NULL;
1069 #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
1070 zend_object_std_dtor(&intern->zo TSRMLS_CC);
1071 #else
1072 if (intern->zo.guards) {
1073 zend_hash_destroy(intern->zo.guards);
1074 FREE_HASHTABLE(intern->zo.guards);
1077 if (intern->zo.properties) {
1078 zend_hash_destroy(intern->zo.properties);
1079 FREE_HASHTABLE(intern->zo.properties);
1081 #endif
1083 if (intern->filename) {
1084 efree(intern->filename);
1086 efree(intern);
1088 /* }}} */
1090 static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
1092 ze_zip_object *intern;
1093 zend_object_value retval;
1095 intern = emalloc(sizeof(ze_zip_object));
1096 memset(&intern->zo, 0, sizeof(zend_object));
1098 intern->za = NULL;
1099 intern->buffers = NULL;
1100 intern->filename = NULL;
1101 intern->buffers_cnt = 0;
1102 intern->prop_handler = &zip_prop_handlers;
1104 #if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2))
1105 zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
1106 #else
1107 ALLOC_HASHTABLE(intern->zo.properties);
1108 zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
1109 intern->zo.ce = class_type;
1110 #endif
1112 object_properties_init(&intern->zo, class_type);
1114 retval.handle = zend_objects_store_put(intern,
1115 NULL,
1116 (zend_objects_free_object_storage_t) php_zip_object_free_storage,
1117 NULL TSRMLS_CC);
1119 retval.handlers = (zend_object_handlers *) & zip_object_handlers;
1121 return retval;
1123 /* }}} */
1124 #endif
1126 /* {{{ Resource dtors */
1128 /* {{{ php_zip_free_dir */
1129 static void php_zip_free_dir(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1131 zip_rsrc * zip_int = (zip_rsrc *) rsrc->ptr;
1133 if (zip_int) {
1134 if (zip_int->za) {
1135 if (zip_close(zip_int->za) != 0) {
1136 _zip_free(zip_int->za);
1138 zip_int->za = NULL;
1141 efree(rsrc->ptr);
1143 rsrc->ptr = NULL;
1146 /* }}} */
1148 /* {{{ php_zip_free_entry */
1149 static void php_zip_free_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1151 zip_read_rsrc *zr_rsrc = (zip_read_rsrc *) rsrc->ptr;
1153 if (zr_rsrc) {
1154 if (zr_rsrc->zf) {
1155 if (zr_rsrc->zf->za) {
1156 zip_fclose(zr_rsrc->zf);
1157 } else {
1158 if (zr_rsrc->zf->src)
1159 zip_source_free(zr_rsrc->zf->src);
1160 free(zr_rsrc->zf);
1162 zr_rsrc->zf = NULL;
1164 efree(zr_rsrc);
1165 rsrc->ptr = NULL;
1168 /* }}} */
1170 /* }}}*/
1172 /* reset macro */
1174 /* {{{ function prototypes */
1175 static PHP_MINIT_FUNCTION(zip);
1176 static PHP_MSHUTDOWN_FUNCTION(zip);
1177 static PHP_MINFO_FUNCTION(zip);
1178 /* }}} */
1180 /* {{{ zip_module_entry
1182 zend_module_entry zip_module_entry = {
1183 STANDARD_MODULE_HEADER,
1184 "zip",
1185 zip_functions,
1186 PHP_MINIT(zip),
1187 PHP_MSHUTDOWN(zip),
1188 NULL,
1189 NULL,
1190 PHP_MINFO(zip),
1191 PHP_ZIP_VERSION_STRING,
1192 STANDARD_MODULE_PROPERTIES
1194 /* }}} */
1196 #ifdef COMPILE_DL_ZIP
1197 ZEND_GET_MODULE(zip)
1198 #endif
1199 /* set macro */
1201 /* {{{ proto resource zip_open(string filename)
1202 Create new zip using source uri for output */
1203 static PHP_NAMED_FUNCTION(zif_zip_open)
1205 char *filename;
1206 int filename_len;
1207 char resolved_path[MAXPATHLEN + 1];
1208 zip_rsrc *rsrc_int;
1209 int err = 0;
1211 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
1212 return;
1215 if (filename_len == 0) {
1216 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
1217 RETURN_FALSE;
1220 if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
1221 RETURN_FALSE;
1224 if(!expand_filepath(filename, resolved_path TSRMLS_CC)) {
1225 RETURN_FALSE;
1228 rsrc_int = (zip_rsrc *)emalloc(sizeof(zip_rsrc));
1230 rsrc_int->za = zip_open(resolved_path, 0, &err);
1231 if (rsrc_int->za == NULL) {
1232 efree(rsrc_int);
1233 RETURN_LONG((long)err);
1236 rsrc_int->index_current = 0;
1237 rsrc_int->num_files = zip_get_num_files(rsrc_int->za);
1239 ZEND_REGISTER_RESOURCE(return_value, rsrc_int, le_zip_dir);
1241 /* }}} */
1243 /* {{{ proto void zip_close(resource zip)
1244 Close a Zip archive */
1245 static PHP_NAMED_FUNCTION(zif_zip_close)
1247 zval * zip;
1248 zip_rsrc *z_rsrc = NULL;
1250 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip) == FAILURE) {
1251 return;
1253 ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir);
1255 /* really close the zip will break BC :-D */
1256 zend_list_delete(Z_LVAL_P(zip));
1258 /* }}} */
1260 /* {{{ proto resource zip_read(resource zip)
1261 Returns the next file in the archive */
1262 static PHP_NAMED_FUNCTION(zif_zip_read)
1264 zval *zip_dp;
1265 zip_read_rsrc *zr_rsrc;
1266 int ret;
1267 zip_rsrc *rsrc_int;
1269 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_dp) == FAILURE) {
1270 return;
1272 ZEND_FETCH_RESOURCE(rsrc_int, zip_rsrc *, &zip_dp, -1, le_zip_dir_name, le_zip_dir);
1274 if (rsrc_int && rsrc_int->za) {
1275 if (rsrc_int->index_current >= rsrc_int->num_files) {
1276 RETURN_FALSE;
1279 zr_rsrc = emalloc(sizeof(zip_read_rsrc));
1281 ret = zip_stat_index(rsrc_int->za, rsrc_int->index_current, 0, &zr_rsrc->sb);
1283 if (ret != 0) {
1284 efree(zr_rsrc);
1285 RETURN_FALSE;
1288 zr_rsrc->zf = zip_fopen_index(rsrc_int->za, rsrc_int->index_current, 0);
1289 if (zr_rsrc->zf) {
1290 rsrc_int->index_current++;
1291 ZEND_REGISTER_RESOURCE(return_value, zr_rsrc, le_zip_entry);
1292 } else {
1293 efree(zr_rsrc);
1294 RETURN_FALSE;
1297 } else {
1298 RETURN_FALSE;
1301 /* }}} */
1303 /* {{{ proto bool zip_entry_open(resource zip_dp, resource zip_entry [, string mode])
1304 Open a Zip File, pointed by the resource entry */
1305 /* Dummy function to follow the old API */
1306 static PHP_NAMED_FUNCTION(zif_zip_entry_open)
1308 zval * zip;
1309 zval * zip_entry;
1310 char *mode = NULL;
1311 int mode_len = 0;
1312 zip_read_rsrc * zr_rsrc;
1313 zip_rsrc *z_rsrc;
1315 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|s", &zip, &zip_entry, &mode, &mode_len) == FAILURE) {
1316 return;
1319 ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
1320 ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir);
1322 if (zr_rsrc->zf != NULL) {
1323 RETURN_TRUE;
1324 } else {
1325 RETURN_FALSE;
1328 /* }}} */
1330 /* {{{ proto bool zip_entry_close(resource zip_ent)
1331 Close a zip entry */
1332 static PHP_NAMED_FUNCTION(zif_zip_entry_close)
1334 zval * zip_entry;
1335 zip_read_rsrc * zr_rsrc;
1337 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) {
1338 return;
1341 ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
1343 RETURN_BOOL(SUCCESS == zend_list_delete(Z_LVAL_P(zip_entry)));
1345 /* }}} */
1347 /* {{{ proto mixed zip_entry_read(resource zip_entry [, int len])
1348 Read from an open directory entry */
1349 static PHP_NAMED_FUNCTION(zif_zip_entry_read)
1351 zval * zip_entry;
1352 long len = 0;
1353 zip_read_rsrc * zr_rsrc;
1354 char *buffer;
1355 int n = 0;
1357 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zip_entry, &len) == FAILURE) {
1358 return;
1361 ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
1363 if (len <= 0) {
1364 len = 1024;
1367 if (zr_rsrc->zf) {
1368 buffer = safe_emalloc(len, 1, 1);
1369 n = zip_fread(zr_rsrc->zf, buffer, len);
1370 if (n > 0) {
1371 buffer[n] = 0;
1372 RETURN_STRINGL(buffer, n, 0);
1373 } else {
1374 efree(buffer);
1375 RETURN_EMPTY_STRING()
1377 } else {
1378 RETURN_FALSE;
1381 /* }}} */
1383 static void php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS, int opt) /* {{{ */
1385 zval * zip_entry;
1386 zip_read_rsrc * zr_rsrc;
1388 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) {
1389 return;
1392 ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
1394 if (!zr_rsrc->zf) {
1395 RETURN_FALSE;
1398 switch (opt) {
1399 case 0:
1400 RETURN_STRING((char *)zr_rsrc->sb.name, 1);
1401 break;
1402 case 1:
1403 RETURN_LONG((long) (zr_rsrc->sb.comp_size));
1404 break;
1405 case 2:
1406 RETURN_LONG((long) (zr_rsrc->sb.size));
1407 break;
1408 case 3:
1409 switch (zr_rsrc->sb.comp_method) {
1410 case 0:
1411 RETURN_STRING("stored", 1);
1412 break;
1413 case 1:
1414 RETURN_STRING("shrunk", 1);
1415 break;
1416 case 2:
1417 case 3:
1418 case 4:
1419 case 5:
1420 RETURN_STRING("reduced", 1);
1421 break;
1422 case 6:
1423 RETURN_STRING("imploded", 1);
1424 break;
1425 case 7:
1426 RETURN_STRING("tokenized", 1);
1427 break;
1428 case 8:
1429 RETURN_STRING("deflated", 1);
1430 break;
1431 case 9:
1432 RETURN_STRING("deflatedX", 1);
1433 break;
1434 case 10:
1435 RETURN_STRING("implodedX", 1);
1436 break;
1437 default:
1438 RETURN_FALSE;
1440 RETURN_LONG((long) (zr_rsrc->sb.comp_method));
1441 break;
1445 /* }}} */
1447 /* {{{ proto string zip_entry_name(resource zip_entry)
1448 Return the name given a ZZip entry */
1449 static PHP_NAMED_FUNCTION(zif_zip_entry_name)
1451 php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1453 /* }}} */
1455 /* {{{ proto int zip_entry_compressedsize(resource zip_entry)
1456 Return the compressed size of a ZZip entry */
1457 static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize)
1459 php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1461 /* }}} */
1463 /* {{{ proto int zip_entry_filesize(resource zip_entry)
1464 Return the actual filesize of a ZZip entry */
1465 static PHP_NAMED_FUNCTION(zif_zip_entry_filesize)
1467 php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
1469 /* }}} */
1471 /* {{{ proto string zip_entry_compressionmethod(resource zip_entry)
1472 Return a string containing the compression method used on a particular entry */
1473 static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod)
1475 php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
1477 /* }}} */
1479 #ifdef PHP_ZIP_USE_OO
1480 /* {{{ proto mixed ZipArchive::open(string source [, int flags])
1481 Create new zip using source uri for output, return TRUE on success or the error code */
1482 static ZIPARCHIVE_METHOD(open)
1484 struct zip *intern;
1485 char *filename;
1486 int filename_len;
1487 int err = 0;
1488 long flags = 0;
1489 char resolved_path[MAXPATHLEN];
1491 zval *this = getThis();
1492 ze_zip_object *ze_obj = NULL;
1494 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &flags) == FAILURE) {
1495 return;
1498 if (this) {
1499 /* We do not use ZIP_FROM_OBJECT, zip init function here */
1500 ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
1503 if (filename_len == 0) {
1504 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
1505 RETURN_FALSE;
1508 if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
1509 RETURN_FALSE;
1512 if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
1513 RETURN_FALSE;
1516 if (ze_obj->za) {
1517 /* we already have an opened zip, free it */
1518 if (zip_close(ze_obj->za) != 0) {
1519 _zip_free(ze_obj->za);
1521 ze_obj->za = NULL;
1523 if (ze_obj->filename) {
1524 efree(ze_obj->filename);
1525 ze_obj->filename = NULL;
1528 intern = zip_open(resolved_path, flags, &err);
1529 if (!intern || err) {
1530 RETURN_LONG((long)err);
1532 ze_obj->filename = estrdup(resolved_path);
1533 ze_obj->filename_len = filename_len;
1534 ze_obj->za = intern;
1535 RETURN_TRUE;
1537 /* }}} */
1539 /* {{{ proto bool ZipArchive::close()
1540 close the zip archive */
1541 static ZIPARCHIVE_METHOD(close)
1543 struct zip *intern;
1544 zval *this = getThis();
1545 ze_zip_object *ze_obj;
1547 if (!this) {
1548 RETURN_FALSE;
1551 ZIP_FROM_OBJECT(intern, this);
1553 ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
1555 if (zip_close(intern)) {
1556 RETURN_FALSE;
1559 efree(ze_obj->filename);
1560 ze_obj->filename = NULL;
1561 ze_obj->filename_len = 0;
1562 ze_obj->za = NULL;
1564 RETURN_TRUE;
1566 /* }}} */
1568 /* {{{ proto string ZipArchive::getStatusString()
1569 * Returns the status error message, system and/or zip messages */
1570 static ZIPARCHIVE_METHOD(getStatusString)
1572 struct zip *intern;
1573 zval *this = getThis();
1574 int zep, syp, len;
1575 char error_string[128];
1577 if (!this) {
1578 RETURN_FALSE;
1581 ZIP_FROM_OBJECT(intern, this);
1583 zip_error_get(intern, &zep, &syp);
1585 len = zip_error_to_str(error_string, 128, zep, syp);
1586 RETVAL_STRINGL(error_string, len, 1);
1588 /* }}} */
1590 /* {{{ proto bool ZipArchive::createEmptyDir(string dirname)
1591 Returns the index of the entry named filename in the archive */
1592 static ZIPARCHIVE_METHOD(addEmptyDir)
1594 struct zip *intern;
1595 zval *this = getThis();
1596 char *dirname;
1597 int dirname_len;
1598 int idx;
1599 struct zip_stat sb;
1600 char *s;
1602 if (!this) {
1603 RETURN_FALSE;
1606 ZIP_FROM_OBJECT(intern, this);
1608 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
1609 &dirname, &dirname_len) == FAILURE) {
1610 return;
1613 if (dirname_len<1) {
1614 RETURN_FALSE;
1617 if (dirname[dirname_len-1] != '/') {
1618 s=(char *)emalloc(dirname_len+2);
1619 strcpy(s, dirname);
1620 s[dirname_len] = '/';
1621 s[dirname_len+1] = '\0';
1622 } else {
1623 s = dirname;
1626 idx = zip_stat(intern, s, 0, &sb);
1627 if (idx >= 0) {
1628 RETVAL_FALSE;
1629 } else {
1630 if (zip_add_dir(intern, (const char *)s) == -1) {
1631 RETVAL_FALSE;
1633 RETVAL_TRUE;
1636 if (s != dirname) {
1637 efree(s);
1640 /* }}} */
1642 static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
1644 struct zip *intern;
1645 zval *this = getThis();
1646 char *pattern;
1647 char *path = NULL;
1648 char *remove_path = NULL;
1649 char *add_path = NULL;
1650 int pattern_len, add_path_len, remove_path_len, path_len = 0;
1651 long remove_all_path = 0;
1652 long flags = 0;
1653 zval *options = NULL;
1654 int found;
1656 if (!this) {
1657 RETURN_FALSE;
1660 ZIP_FROM_OBJECT(intern, this);
1661 /* 1 == glob, 2==pcre */
1662 if (type == 1) {
1663 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|la",
1664 &pattern, &pattern_len, &flags, &options) == FAILURE) {
1665 return;
1667 } else {
1668 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sa",
1669 &pattern, &pattern_len, &path, &path_len, &options) == FAILURE) {
1670 return;
1674 if (pattern_len == 0) {
1675 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as pattern");
1676 RETURN_FALSE;
1678 if (options && (php_zip_parse_options(options, &remove_all_path, &remove_path, &remove_path_len,
1679 &add_path, &add_path_len TSRMLS_CC) < 0)) {
1680 RETURN_FALSE;
1683 if (remove_path && remove_path_len > 1 && (remove_path[strlen(remove_path) - 1] == '/' ||
1684 remove_path[strlen(remove_path) - 1] == '\\')) {
1685 remove_path[strlen(remove_path) - 1] = '\0';
1688 if (type == 1) {
1689 found = php_zip_glob(pattern, pattern_len, flags, return_value TSRMLS_CC);
1690 } else {
1691 found = php_zip_pcre(pattern, pattern_len, path, path_len, return_value TSRMLS_CC);
1694 if (found > 0) {
1695 int i;
1696 zval **zval_file = NULL;
1698 for (i = 0; i < found; i++) {
1699 char *file, *file_stripped, *entry_name;
1700 size_t entry_name_len, file_stripped_len;
1701 char entry_name_buf[MAXPATHLEN];
1702 char *basename = NULL;
1704 if (zend_hash_index_find(Z_ARRVAL_P(return_value), i, (void **) &zval_file) == SUCCESS) {
1705 file = Z_STRVAL_PP(zval_file);
1706 if (remove_all_path) {
1707 php_basename(Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file), NULL, 0,
1708 &basename, (size_t *)&file_stripped_len TSRMLS_CC);
1709 file_stripped = basename;
1710 } else if (remove_path && strstr(Z_STRVAL_PP(zval_file), remove_path) != NULL) {
1711 file_stripped = Z_STRVAL_PP(zval_file) + remove_path_len + 1;
1712 file_stripped_len = Z_STRLEN_PP(zval_file) - remove_path_len - 1;
1713 } else {
1714 file_stripped = Z_STRVAL_PP(zval_file);
1715 file_stripped_len = Z_STRLEN_PP(zval_file);
1718 if (add_path) {
1719 if ((add_path_len + file_stripped_len) > MAXPATHLEN) {
1720 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Entry name too long (max: %d, %ld given)",
1721 MAXPATHLEN - 1, (add_path_len + file_stripped_len));
1722 zval_dtor(return_value);
1723 RETURN_FALSE;
1726 snprintf(entry_name_buf, MAXPATHLEN, "%s%s", add_path, file_stripped);
1727 entry_name = entry_name_buf;
1728 entry_name_len = strlen(entry_name);
1729 } else {
1730 entry_name = Z_STRVAL_PP(zval_file);
1731 entry_name_len = Z_STRLEN_PP(zval_file);
1733 if (basename) {
1734 efree(basename);
1735 basename = NULL;
1737 if (php_zip_add_file(intern, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file),
1738 entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
1739 zval_dtor(return_value);
1740 RETURN_FALSE;
1746 /* }}} */
1748 /* {{{ proto bool ZipArchive::addGlob(string pattern[,int flags [, array options]])
1749 Add files matching the glob pattern. See php's glob for the pattern syntax. */
1750 static ZIPARCHIVE_METHOD(addGlob)
1752 php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1754 /* }}} */
1756 /* {{{ proto bool ZipArchive::addPattern(string pattern[, string path [, array options]])
1757 Add files matching the pcre pattern. See php's pcre for the pattern syntax. */
1758 static ZIPARCHIVE_METHOD(addPattern)
1760 php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
1762 /* }}} */
1764 /* {{{ proto bool ZipArchive::addFile(string filepath[, string entryname[, int start [, int length]]])
1765 Add a file in a Zip archive using its path and the name to use. */
1766 static ZIPARCHIVE_METHOD(addFile)
1768 struct zip *intern;
1769 zval *this = getThis();
1770 char *filename;
1771 int filename_len;
1772 char *entry_name = NULL;
1773 int entry_name_len = 0;
1774 long offset_start = 0, offset_len = 0;
1776 if (!this) {
1777 RETURN_FALSE;
1780 ZIP_FROM_OBJECT(intern, this);
1782 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sll",
1783 &filename, &filename_len, &entry_name, &entry_name_len, &offset_start, &offset_len) == FAILURE) {
1784 return;
1787 if (filename_len == 0) {
1788 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as filename");
1789 RETURN_FALSE;
1792 if (entry_name_len == 0) {
1793 entry_name = filename;
1794 entry_name_len = filename_len;
1797 if (php_zip_add_file(intern, filename, filename_len,
1798 entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
1799 RETURN_FALSE;
1800 } else {
1801 RETURN_TRUE;
1804 /* }}} */
1806 /* {{{ proto bool ZipArchive::addFromString(string name, string content)
1807 Add a file using content and the entry name */
1808 static ZIPARCHIVE_METHOD(addFromString)
1810 struct zip *intern;
1811 zval *this = getThis();
1812 char *buffer, *name;
1813 int buffer_len, name_len;
1814 ze_zip_object *ze_obj;
1815 struct zip_source *zs;
1816 int pos = 0;
1817 int cur_idx;
1819 if (!this) {
1820 RETURN_FALSE;
1823 ZIP_FROM_OBJECT(intern, this);
1825 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
1826 &name, &name_len, &buffer, &buffer_len) == FAILURE) {
1827 return;
1830 ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
1831 if (ze_obj->buffers_cnt) {
1832 ze_obj->buffers = (char **)erealloc(ze_obj->buffers, sizeof(char *) * (ze_obj->buffers_cnt+1));
1833 pos = ze_obj->buffers_cnt++;
1834 } else {
1835 ze_obj->buffers = (char **)emalloc(sizeof(char *));
1836 ze_obj->buffers_cnt++;
1837 pos = 0;
1839 ze_obj->buffers[pos] = (char *)emalloc(buffer_len + 1);
1840 memcpy(ze_obj->buffers[pos], buffer, buffer_len + 1);
1842 zs = zip_source_buffer(intern, ze_obj->buffers[pos], buffer_len, 0);
1844 if (zs == NULL) {
1845 RETURN_FALSE;
1848 cur_idx = zip_name_locate(intern, (const char *)name, 0);
1849 /* TODO: fix _zip_replace */
1850 if (cur_idx >= 0) {
1851 if (zip_delete(intern, cur_idx) == -1) {
1852 RETURN_FALSE;
1856 if (zip_add(intern, name, zs) == -1) {
1857 RETURN_FALSE;
1858 } else {
1859 RETURN_TRUE;
1862 /* }}} */
1864 /* {{{ proto array ZipArchive::statName(string filename[, int flags])
1865 Returns the information about a the zip entry filename */
1866 static ZIPARCHIVE_METHOD(statName)
1868 struct zip *intern;
1869 zval *this = getThis();
1870 char *name;
1871 int name_len;
1872 long flags = 0;
1873 struct zip_stat sb;
1875 if (!this) {
1876 RETURN_FALSE;
1879 ZIP_FROM_OBJECT(intern, this);
1881 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l",
1882 &name, &name_len, &flags) == FAILURE) {
1883 return;
1886 PHP_ZIP_STAT_PATH(intern, name, name_len, flags, sb);
1888 RETURN_SB(&sb);
1890 /* }}} */
1892 /* {{{ proto resource ZipArchive::statIndex(int index[, int flags])
1893 Returns the zip entry informations using its index */
1894 static ZIPARCHIVE_METHOD(statIndex)
1896 struct zip *intern;
1897 zval *this = getThis();
1898 long index, flags = 0;
1900 struct zip_stat sb;
1902 if (!this) {
1903 RETURN_FALSE;
1906 ZIP_FROM_OBJECT(intern, this);
1908 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
1909 &index, &flags) == FAILURE) {
1910 return;
1913 if (zip_stat_index(intern, index, flags, &sb) != 0) {
1914 RETURN_FALSE;
1916 RETURN_SB(&sb);
1918 /* }}} */
1920 /* {{{ proto int ZipArchive::locateName(string filename[, int flags])
1921 Returns the index of the entry named filename in the archive */
1922 static ZIPARCHIVE_METHOD(locateName)
1924 struct zip *intern;
1925 zval *this = getThis();
1926 char *name;
1927 int name_len;
1928 long flags = 0;
1929 long idx = -1;
1931 if (!this) {
1932 RETURN_FALSE;
1935 ZIP_FROM_OBJECT(intern, this);
1937 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l",
1938 &name, &name_len, &flags) == FAILURE) {
1939 return;
1941 if (name_len<1) {
1942 RETURN_FALSE;
1945 idx = (long)zip_name_locate(intern, (const char *)name, flags);
1947 if (idx >= 0) {
1948 RETURN_LONG(idx);
1949 } else {
1950 RETURN_FALSE;
1953 /* }}} */
1955 /* {{{ proto string ZipArchive::getNameIndex(int index [, int flags])
1956 Returns the name of the file at position index */
1957 static ZIPARCHIVE_METHOD(getNameIndex)
1959 struct zip *intern;
1960 zval *this = getThis();
1961 const char *name;
1962 long flags = 0, index = 0;
1964 if (!this) {
1965 RETURN_FALSE;
1968 ZIP_FROM_OBJECT(intern, this);
1970 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
1971 &index, &flags) == FAILURE) {
1972 return;
1975 name = zip_get_name(intern, (int) index, flags);
1977 if (name) {
1978 RETVAL_STRING((char *)name, 1);
1979 } else {
1980 RETURN_FALSE;
1983 /* }}} */
1985 /* {{{ proto bool ZipArchive::setArchiveComment(string comment)
1986 Set or remove (NULL/'') the comment of the archive */
1987 static ZIPARCHIVE_METHOD(setArchiveComment)
1989 struct zip *intern;
1990 zval *this = getThis();
1991 int comment_len;
1992 char * comment;
1994 if (!this) {
1995 RETURN_FALSE;
1998 ZIP_FROM_OBJECT(intern, this);
2000 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &comment, &comment_len) == FAILURE) {
2001 return;
2003 if (zip_set_archive_comment(intern, (const char *)comment, (int)comment_len)) {
2004 RETURN_FALSE;
2005 } else {
2006 RETURN_TRUE;
2009 /* }}} */
2011 /* {{{ proto string ZipArchive::getArchiveComment([int flags])
2012 Returns the comment of an entry using its index */
2013 static ZIPARCHIVE_METHOD(getArchiveComment)
2015 struct zip *intern;
2016 zval *this = getThis();
2017 long flags = 0;
2018 const char * comment;
2019 int comment_len = 0;
2021 if (!this) {
2022 RETURN_FALSE;
2025 ZIP_FROM_OBJECT(intern, this);
2027 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE) {
2028 return;
2031 comment = zip_get_archive_comment(intern, &comment_len, (int)flags);
2032 if(comment==NULL) {
2033 RETURN_FALSE;
2035 RETURN_STRINGL((char *)comment, (long)comment_len, 1);
2037 /* }}} */
2039 /* {{{ proto bool ZipArchive::setCommentName(string name, string comment)
2040 Set or remove (NULL/'') the comment of an entry using its Name */
2041 static ZIPARCHIVE_METHOD(setCommentName)
2043 struct zip *intern;
2044 zval *this = getThis();
2045 int comment_len, name_len;
2046 char * comment, *name;
2047 int idx;
2049 if (!this) {
2050 RETURN_FALSE;
2053 ZIP_FROM_OBJECT(intern, this);
2055 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
2056 &name, &name_len, &comment, &comment_len) == FAILURE) {
2057 return;
2060 if (name_len < 1) {
2061 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name");
2064 idx = zip_name_locate(intern, name, 0);
2065 if (idx < 0) {
2066 RETURN_FALSE;
2068 PHP_ZIP_SET_FILE_COMMENT(intern, idx, comment, comment_len);
2070 /* }}} */
2072 /* {{{ proto bool ZipArchive::setCommentIndex(int index, string comment)
2073 Set or remove (NULL/'') the comment of an entry using its index */
2074 static ZIPARCHIVE_METHOD(setCommentIndex)
2076 struct zip *intern;
2077 zval *this = getThis();
2078 long index;
2079 int comment_len;
2080 char * comment;
2081 struct zip_stat sb;
2083 if (!this) {
2084 RETURN_FALSE;
2087 ZIP_FROM_OBJECT(intern, this);
2089 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls",
2090 &index, &comment, &comment_len) == FAILURE) {
2091 return;
2094 PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2095 PHP_ZIP_SET_FILE_COMMENT(intern, index, comment, comment_len);
2097 /* }}} */
2099 /* {{{ proto string ZipArchive::getCommentName(string name[, int flags])
2100 Returns the comment of an entry using its name */
2101 static ZIPARCHIVE_METHOD(getCommentName)
2103 struct zip *intern;
2104 zval *this = getThis();
2105 int name_len, idx;
2106 long flags = 0;
2107 int comment_len = 0;
2108 const char * comment;
2109 char *name;
2111 if (!this) {
2112 RETURN_FALSE;
2115 ZIP_FROM_OBJECT(intern, this);
2117 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
2118 &name, &name_len, &flags) == FAILURE) {
2119 return;
2121 if (name_len < 1) {
2122 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name");
2123 RETURN_FALSE;
2126 idx = zip_name_locate(intern, name, 0);
2127 if (idx < 0) {
2128 RETURN_FALSE;
2131 comment = zip_get_file_comment(intern, idx, &comment_len, (int)flags);
2132 RETURN_STRINGL((char *)comment, (long)comment_len, 1);
2134 /* }}} */
2136 /* {{{ proto string ZipArchive::getCommentIndex(int index[, int flags])
2137 Returns the comment of an entry using its index */
2138 static ZIPARCHIVE_METHOD(getCommentIndex)
2140 struct zip *intern;
2141 zval *this = getThis();
2142 long index, flags = 0;
2143 const char * comment;
2144 int comment_len = 0;
2145 struct zip_stat sb;
2147 if (!this) {
2148 RETURN_FALSE;
2151 ZIP_FROM_OBJECT(intern, this);
2153 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
2154 &index, &flags) == FAILURE) {
2155 return;
2158 PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2159 comment = zip_get_file_comment(intern, index, &comment_len, (int)flags);
2160 RETURN_STRINGL((char *)comment, (long)comment_len, 1);
2162 /* }}} */
2164 /* {{{ proto bool ZipArchive::deleteIndex(int index)
2165 Delete a file using its index */
2166 static ZIPARCHIVE_METHOD(deleteIndex)
2168 struct zip *intern;
2169 zval *this = getThis();
2170 long index;
2172 if (!this) {
2173 RETURN_FALSE;
2176 ZIP_FROM_OBJECT(intern, this);
2178 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
2179 return;
2182 if (index < 0) {
2183 RETURN_FALSE;
2186 if (zip_delete(intern, index) < 0) {
2187 RETURN_FALSE;
2190 RETURN_TRUE;
2192 /* }}} */
2194 /* {{{ proto bool ZipArchive::deleteName(string name)
2195 Delete a file using its index */
2196 static ZIPARCHIVE_METHOD(deleteName)
2198 struct zip *intern;
2199 zval *this = getThis();
2200 int name_len;
2201 char *name;
2202 struct zip_stat sb;
2204 if (!this) {
2205 RETURN_FALSE;
2208 ZIP_FROM_OBJECT(intern, this);
2210 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
2211 return;
2213 if (name_len < 1) {
2214 RETURN_FALSE;
2217 PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
2218 if (zip_delete(intern, sb.index)) {
2219 RETURN_FALSE;
2221 RETURN_TRUE;
2223 /* }}} */
2225 /* {{{ proto bool ZipArchive::renameIndex(int index, string new_name)
2226 Rename an entry selected by its index to new_name */
2227 static ZIPARCHIVE_METHOD(renameIndex)
2229 struct zip *intern;
2230 zval *this = getThis();
2232 char *new_name;
2233 int new_name_len;
2234 long index;
2236 if (!this) {
2237 RETURN_FALSE;
2240 ZIP_FROM_OBJECT(intern, this);
2242 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &index, &new_name, &new_name_len) == FAILURE) {
2243 return;
2246 if (index < 0) {
2247 RETURN_FALSE;
2250 if (new_name_len < 1) {
2251 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as new entry name");
2252 RETURN_FALSE;
2254 if (zip_rename(intern, index, (const char *)new_name) != 0) {
2255 RETURN_FALSE;
2257 RETURN_TRUE;
2259 /* }}} */
2261 /* {{{ proto bool ZipArchive::renameName(string name, string new_name)
2262 Rename an entry selected by its name to new_name */
2263 static ZIPARCHIVE_METHOD(renameName)
2265 struct zip *intern;
2266 zval *this = getThis();
2267 struct zip_stat sb;
2268 char *name, *new_name;
2269 int name_len, new_name_len;
2271 if (!this) {
2272 RETURN_FALSE;
2275 ZIP_FROM_OBJECT(intern, this);
2277 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &new_name, &new_name_len) == FAILURE) {
2278 return;
2281 if (new_name_len < 1) {
2282 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as new entry name");
2283 RETURN_FALSE;
2286 PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
2288 if (zip_rename(intern, sb.index, (const char *)new_name)) {
2289 RETURN_FALSE;
2291 RETURN_TRUE;
2293 /* }}} */
2295 /* {{{ proto bool ZipArchive::unchangeIndex(int index)
2296 Changes to the file at position index are reverted */
2297 static ZIPARCHIVE_METHOD(unchangeIndex)
2299 struct zip *intern;
2300 zval *this = getThis();
2301 long index;
2303 if (!this) {
2304 RETURN_FALSE;
2307 ZIP_FROM_OBJECT(intern, this);
2309 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
2310 return;
2313 if (index < 0) {
2314 RETURN_FALSE;
2317 if (zip_unchange(intern, index) != 0) {
2318 RETURN_FALSE;
2319 } else {
2320 RETURN_TRUE;
2323 /* }}} */
2325 /* {{{ proto bool ZipArchive::unchangeName(string name)
2326 Changes to the file named 'name' are reverted */
2327 static ZIPARCHIVE_METHOD(unchangeName)
2329 struct zip *intern;
2330 zval *this = getThis();
2331 struct zip_stat sb;
2332 char *name;
2333 int name_len;
2335 if (!this) {
2336 RETURN_FALSE;
2339 ZIP_FROM_OBJECT(intern, this);
2341 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
2342 return;
2345 if (name_len < 1) {
2346 RETURN_FALSE;
2349 PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
2351 if (zip_unchange(intern, sb.index) != 0) {
2352 RETURN_FALSE;
2353 } else {
2354 RETURN_TRUE;
2357 /* }}} */
2359 /* {{{ proto bool ZipArchive::unchangeAll()
2360 All changes to files and global information in archive are reverted */
2361 static ZIPARCHIVE_METHOD(unchangeAll)
2363 struct zip *intern;
2364 zval *this = getThis();
2366 if (!this) {
2367 RETURN_FALSE;
2370 ZIP_FROM_OBJECT(intern, this);
2372 if (zip_unchange_all(intern) != 0) {
2373 RETURN_FALSE;
2374 } else {
2375 RETURN_TRUE;
2378 /* }}} */
2380 /* {{{ proto bool ZipArchive::unchangeArchive()
2381 Revert all global changes to the archive archive. For now, this only reverts archive comment changes. */
2382 static ZIPARCHIVE_METHOD(unchangeArchive)
2384 struct zip *intern;
2385 zval *this = getThis();
2387 if (!this) {
2388 RETURN_FALSE;
2391 ZIP_FROM_OBJECT(intern, this);
2393 if (zip_unchange_archive(intern) != 0) {
2394 RETURN_FALSE;
2395 } else {
2396 RETURN_TRUE;
2399 /* }}} */
2401 /* {{{ proto bool ZipArchive::extractTo(string pathto[, mixed files])
2402 Extract one or more file from a zip archive */
2403 /* TODO:
2404 * - allow index or array of indeces
2405 * - replace path
2406 * - patterns
2408 static ZIPARCHIVE_METHOD(extractTo)
2410 struct zip *intern;
2412 zval *this = getThis();
2413 zval *zval_files = NULL;
2414 zval **zval_file = NULL;
2415 php_stream_statbuf ssb;
2416 char *pathto;
2417 int pathto_len;
2418 int ret, i;
2420 int nelems;
2422 if (!this) {
2423 RETURN_FALSE;
2426 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &pathto, &pathto_len, &zval_files) == FAILURE) {
2427 return;
2430 if (pathto_len < 1) {
2431 RETURN_FALSE;
2434 if (php_stream_stat_path_ex(pathto, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
2435 ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
2436 if (!ret) {
2437 RETURN_FALSE;
2441 ZIP_FROM_OBJECT(intern, this);
2442 if (zval_files && (Z_TYPE_P(zval_files) != IS_NULL)) {
2443 switch (Z_TYPE_P(zval_files)) {
2444 case IS_STRING:
2445 if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_files), Z_STRLEN_P(zval_files) TSRMLS_CC)) {
2446 RETURN_FALSE;
2448 break;
2449 case IS_ARRAY:
2450 nelems = zend_hash_num_elements(Z_ARRVAL_P(zval_files));
2451 if (nelems == 0 ) {
2452 RETURN_FALSE;
2454 for (i = 0; i < nelems; i++) {
2455 if (zend_hash_index_find(Z_ARRVAL_P(zval_files), i, (void **) &zval_file) == SUCCESS) {
2456 switch (Z_TYPE_PP(zval_file)) {
2457 case IS_LONG:
2458 break;
2459 case IS_STRING:
2460 if (!php_zip_extract_file(intern, pathto, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file) TSRMLS_CC)) {
2461 RETURN_FALSE;
2463 break;
2467 break;
2468 case IS_LONG:
2469 default:
2470 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid argument, expect string or array of strings");
2471 break;
2473 } else {
2474 /* Extract all files */
2475 int filecount = zip_get_num_files(intern);
2477 if (filecount == -1) {
2478 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal archive");
2479 RETURN_FALSE;
2482 for (i = 0; i < filecount; i++) {
2483 char *file = (char*)zip_get_name(intern, i, ZIP_FL_UNCHANGED);
2484 if (!php_zip_extract_file(intern, pathto, file, strlen(file) TSRMLS_CC)) {
2485 RETURN_FALSE;
2489 RETURN_TRUE;
2491 /* }}} */
2493 static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
2495 struct zip *intern;
2496 zval *this = getThis();
2498 struct zip_stat sb;
2499 struct zip_file *zf;
2501 char *filename;
2502 int filename_len;
2503 long index = -1;
2504 long flags = 0;
2505 long len = 0;
2507 char *buffer;
2508 int n = 0;
2510 if (!this) {
2511 RETURN_FALSE;
2514 ZIP_FROM_OBJECT(intern, this);
2516 if (type == 1) {
2517 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|ll", &filename, &filename_len, &len, &flags) == FAILURE) {
2518 return;
2520 PHP_ZIP_STAT_PATH(intern, filename, filename_len, flags, sb);
2521 } else {
2522 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ll", &index, &len, &flags) == FAILURE) {
2523 return;
2525 PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
2528 if (sb.size < 1) {
2529 RETURN_EMPTY_STRING();
2532 if (len < 1) {
2533 len = sb.size;
2535 if (index >= 0) {
2536 zf = zip_fopen_index(intern, index, flags);
2537 } else {
2538 zf = zip_fopen(intern, filename, flags);
2541 if (zf == NULL) {
2542 RETURN_FALSE;
2545 buffer = safe_emalloc(len, 1, 2);
2546 n = zip_fread(zf, buffer, len);
2547 if (n < 1) {
2548 efree(buffer);
2549 RETURN_EMPTY_STRING();
2552 zip_fclose(zf);
2553 buffer[n] = 0;
2554 RETURN_STRINGL(buffer, n, 0);
2556 /* }}} */
2558 /* {{{ proto string ZipArchive::getFromName(string entryname[, int len [, int flags]])
2559 get the contents of an entry using its name */
2560 static ZIPARCHIVE_METHOD(getFromName)
2562 php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2564 /* }}} */
2566 /* {{{ proto string ZipArchive::getFromIndex(int index[, int len [, int flags]])
2567 get the contents of an entry using its index */
2568 static ZIPARCHIVE_METHOD(getFromIndex)
2570 php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2572 /* }}} */
2574 /* {{{ proto resource ZipArchive::getStream(string entryname)
2575 get a stream for an entry using its name */
2576 static ZIPARCHIVE_METHOD(getStream)
2578 struct zip *intern;
2579 zval *this = getThis();
2580 struct zip_stat sb;
2581 char *filename;
2582 int filename_len;
2583 char *mode = "rb";
2584 php_stream *stream;
2585 ze_zip_object *obj;
2587 if (!this) {
2588 RETURN_FALSE;
2591 ZIP_FROM_OBJECT(intern, this);
2593 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
2594 return;
2597 if (zip_stat(intern, filename, 0, &sb) != 0) {
2598 RETURN_FALSE;
2601 obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
2603 stream = php_stream_zip_open(obj->filename, filename, mode STREAMS_CC TSRMLS_CC);
2604 if (stream) {
2605 php_stream_to_zval(stream, return_value);
2608 /* }}} */
2610 /* {{{ arginfo */
2611 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_open, 0, 0, 1)
2612 ZEND_ARG_INFO(0, filename)
2613 ZEND_ARG_INFO(0, flags)
2614 ZEND_END_ARG_INFO()
2616 ZEND_BEGIN_ARG_INFO(arginfo_ziparchive__void, 0)
2617 ZEND_END_ARG_INFO()
2619 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addemptydir, 0, 0, 1)
2620 ZEND_ARG_INFO(0, dirname)
2621 ZEND_END_ARG_INFO()
2623 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addglob, 0, 0, 1)
2624 ZEND_ARG_INFO(0, pattern)
2625 ZEND_ARG_INFO(0, flags)
2626 ZEND_ARG_INFO(0, options)
2627 ZEND_END_ARG_INFO()
2629 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addpattern, 0, 0, 1)
2630 ZEND_ARG_INFO(0, pattern)
2631 ZEND_ARG_INFO(0, path)
2632 ZEND_ARG_INFO(0, options)
2633 ZEND_END_ARG_INFO()
2635 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addfile, 0, 0, 1)
2636 ZEND_ARG_INFO(0, filepath)
2637 ZEND_ARG_INFO(0, entryname)
2638 ZEND_ARG_INFO(0, start)
2639 ZEND_ARG_INFO(0, length)
2640 ZEND_END_ARG_INFO()
2642 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addfromstring, 0, 0, 2)
2643 ZEND_ARG_INFO(0, name)
2644 ZEND_ARG_INFO(0, content)
2645 ZEND_END_ARG_INFO()
2647 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_statname, 0, 0, 1)
2648 ZEND_ARG_INFO(0, filename)
2649 ZEND_ARG_INFO(0, flags)
2650 ZEND_END_ARG_INFO()
2652 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_statindex, 0, 0, 1)
2653 ZEND_ARG_INFO(0, index)
2654 ZEND_ARG_INFO(0, flags)
2655 ZEND_END_ARG_INFO()
2657 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setarchivecomment, 0, 0, 1)
2658 ZEND_ARG_INFO(0, comment)
2659 ZEND_END_ARG_INFO()
2661 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcommentindex, 0, 0, 2)
2662 ZEND_ARG_INFO(0, index)
2663 ZEND_ARG_INFO(0, comment)
2664 ZEND_END_ARG_INFO()
2666 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getcommentname, 0, 0, 1)
2667 ZEND_ARG_INFO(0, name)
2668 ZEND_ARG_INFO(0, flags)
2669 ZEND_END_ARG_INFO()
2671 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getcommentindex, 0, 0, 1)
2672 ZEND_ARG_INFO(0, index)
2673 ZEND_ARG_INFO(0, flags)
2674 ZEND_END_ARG_INFO()
2676 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_renameindex, 0, 0, 2)
2677 ZEND_ARG_INFO(0, index)
2678 ZEND_ARG_INFO(0, new_name)
2679 ZEND_END_ARG_INFO()
2681 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_renamename, 0, 0, 2)
2682 ZEND_ARG_INFO(0, name)
2683 ZEND_ARG_INFO(0, new_name)
2684 ZEND_END_ARG_INFO()
2686 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_unchangeindex, 0, 0, 1)
2687 ZEND_ARG_INFO(0, index)
2688 ZEND_END_ARG_INFO()
2690 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_unchangename, 0, 0, 1)
2691 ZEND_ARG_INFO(0, name)
2692 ZEND_END_ARG_INFO()
2694 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_extractto, 0, 0, 1)
2695 ZEND_ARG_INFO(0, pathto)
2696 ZEND_ARG_INFO(0, files)
2697 ZEND_END_ARG_INFO()
2699 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getfromname, 0, 0, 1)
2700 ZEND_ARG_INFO(0, entryname)
2701 ZEND_ARG_INFO(0, len)
2702 ZEND_ARG_INFO(0, flags)
2703 ZEND_END_ARG_INFO()
2705 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getfromindex, 0, 0, 1)
2706 ZEND_ARG_INFO(0, index)
2707 ZEND_ARG_INFO(0, len)
2708 ZEND_ARG_INFO(0, flags)
2709 ZEND_END_ARG_INFO()
2711 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getarchivecomment, 0, 0, 0)
2712 ZEND_ARG_INFO(0, flags)
2713 ZEND_END_ARG_INFO()
2715 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcommentname, 0, 0, 2)
2716 ZEND_ARG_INFO(0, name)
2717 ZEND_ARG_INFO(0, comment)
2718 ZEND_END_ARG_INFO()
2720 ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getstream, 0, 0, 1)
2721 ZEND_ARG_INFO(0, entryname)
2722 ZEND_END_ARG_INFO()
2723 /* }}} */
2725 /* {{{ ze_zip_object_class_functions */
2726 static const zend_function_entry zip_class_functions[] = {
2727 ZIPARCHIVE_ME(open, arginfo_ziparchive_open, ZEND_ACC_PUBLIC)
2728 ZIPARCHIVE_ME(close, arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
2729 ZIPARCHIVE_ME(getStatusString, arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
2730 ZIPARCHIVE_ME(addEmptyDir, arginfo_ziparchive_addemptydir, ZEND_ACC_PUBLIC)
2731 ZIPARCHIVE_ME(addFromString, arginfo_ziparchive_addfromstring, ZEND_ACC_PUBLIC)
2732 ZIPARCHIVE_ME(addFile, arginfo_ziparchive_addfile, ZEND_ACC_PUBLIC)
2733 ZIPARCHIVE_ME(addGlob, arginfo_ziparchive_addglob, ZEND_ACC_PUBLIC)
2734 ZIPARCHIVE_ME(addPattern, arginfo_ziparchive_addpattern, ZEND_ACC_PUBLIC)
2735 ZIPARCHIVE_ME(renameIndex, arginfo_ziparchive_renameindex, ZEND_ACC_PUBLIC)
2736 ZIPARCHIVE_ME(renameName, arginfo_ziparchive_renamename, ZEND_ACC_PUBLIC)
2737 ZIPARCHIVE_ME(setArchiveComment, arginfo_ziparchive_setarchivecomment, ZEND_ACC_PUBLIC)
2738 ZIPARCHIVE_ME(getArchiveComment, arginfo_ziparchive_getarchivecomment, ZEND_ACC_PUBLIC)
2739 ZIPARCHIVE_ME(setCommentIndex, arginfo_ziparchive_setcommentindex, ZEND_ACC_PUBLIC)
2740 ZIPARCHIVE_ME(setCommentName, arginfo_ziparchive_setcommentname, ZEND_ACC_PUBLIC)
2741 ZIPARCHIVE_ME(getCommentIndex, arginfo_ziparchive_getcommentindex, ZEND_ACC_PUBLIC)
2742 ZIPARCHIVE_ME(getCommentName, arginfo_ziparchive_getcommentname, ZEND_ACC_PUBLIC)
2743 ZIPARCHIVE_ME(deleteIndex, arginfo_ziparchive_unchangeindex, ZEND_ACC_PUBLIC)
2744 ZIPARCHIVE_ME(deleteName, arginfo_ziparchive_unchangename, ZEND_ACC_PUBLIC)
2745 ZIPARCHIVE_ME(statName, arginfo_ziparchive_statname, ZEND_ACC_PUBLIC)
2746 ZIPARCHIVE_ME(statIndex, arginfo_ziparchive_statindex, ZEND_ACC_PUBLIC)
2747 ZIPARCHIVE_ME(locateName, arginfo_ziparchive_statname, ZEND_ACC_PUBLIC)
2748 ZIPARCHIVE_ME(getNameIndex, arginfo_ziparchive_statindex, ZEND_ACC_PUBLIC)
2749 ZIPARCHIVE_ME(unchangeArchive, arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
2750 ZIPARCHIVE_ME(unchangeAll, arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
2751 ZIPARCHIVE_ME(unchangeIndex, arginfo_ziparchive_unchangeindex, ZEND_ACC_PUBLIC)
2752 ZIPARCHIVE_ME(unchangeName, arginfo_ziparchive_unchangename, ZEND_ACC_PUBLIC)
2753 ZIPARCHIVE_ME(extractTo, arginfo_ziparchive_extractto, ZEND_ACC_PUBLIC)
2754 ZIPARCHIVE_ME(getFromName, arginfo_ziparchive_getfromname, ZEND_ACC_PUBLIC)
2755 ZIPARCHIVE_ME(getFromIndex, arginfo_ziparchive_getfromindex, ZEND_ACC_PUBLIC)
2756 ZIPARCHIVE_ME(getStream, arginfo_ziparchive_getstream, ZEND_ACC_PUBLIC)
2757 {NULL, NULL, NULL}
2759 /* }}} */
2760 #endif
2762 /* {{{ PHP_MINIT_FUNCTION */
2763 static PHP_MINIT_FUNCTION(zip)
2765 #ifdef PHP_ZIP_USE_OO
2766 zend_class_entry ce;
2768 memcpy(&zip_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
2769 zip_object_handlers.clone_obj = NULL;
2770 zip_object_handlers.get_property_ptr_ptr = php_zip_get_property_ptr_ptr;
2772 zip_object_handlers.get_properties = php_zip_get_properties;
2773 zip_object_handlers.read_property = php_zip_read_property;
2774 zip_object_handlers.has_property = php_zip_has_property;
2776 INIT_CLASS_ENTRY(ce, "ZipArchive", zip_class_functions);
2777 ce.create_object = php_zip_object_new;
2778 zip_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
2780 zend_hash_init(&zip_prop_handlers, 0, NULL, NULL, 1);
2781 php_zip_register_prop_handler(&zip_prop_handlers, "status", php_zip_status, NULL, NULL, IS_LONG TSRMLS_CC);
2782 php_zip_register_prop_handler(&zip_prop_handlers, "statusSys", php_zip_status_sys, NULL, NULL, IS_LONG TSRMLS_CC);
2783 php_zip_register_prop_handler(&zip_prop_handlers, "numFiles", php_zip_get_num_files, NULL, NULL, IS_LONG TSRMLS_CC);
2784 php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, NULL, php_zipobj_get_filename, IS_STRING TSRMLS_CC);
2785 php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, NULL, IS_STRING TSRMLS_CC);
2787 REGISTER_ZIP_CLASS_CONST_LONG("CREATE", ZIP_CREATE);
2788 REGISTER_ZIP_CLASS_CONST_LONG("EXCL", ZIP_EXCL);
2789 REGISTER_ZIP_CLASS_CONST_LONG("CHECKCONS", ZIP_CHECKCONS);
2790 REGISTER_ZIP_CLASS_CONST_LONG("OVERWRITE", ZIP_OVERWRITE);
2792 REGISTER_ZIP_CLASS_CONST_LONG("FL_NOCASE", ZIP_FL_NOCASE);
2793 REGISTER_ZIP_CLASS_CONST_LONG("FL_NODIR", ZIP_FL_NODIR);
2794 REGISTER_ZIP_CLASS_CONST_LONG("FL_COMPRESSED", ZIP_FL_COMPRESSED);
2795 REGISTER_ZIP_CLASS_CONST_LONG("FL_UNCHANGED", ZIP_FL_UNCHANGED);
2796 REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFAULT", ZIP_CM_DEFAULT);
2797 REGISTER_ZIP_CLASS_CONST_LONG("CM_STORE", ZIP_CM_STORE);
2798 REGISTER_ZIP_CLASS_CONST_LONG("CM_SHRINK", ZIP_CM_SHRINK);
2799 REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_1", ZIP_CM_REDUCE_1);
2800 REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_2", ZIP_CM_REDUCE_2);
2801 REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_3", ZIP_CM_REDUCE_3);
2802 REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_4", ZIP_CM_REDUCE_4);
2803 REGISTER_ZIP_CLASS_CONST_LONG("CM_IMPLODE", ZIP_CM_IMPLODE);
2804 REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE", ZIP_CM_DEFLATE);
2805 REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE64", ZIP_CM_DEFLATE64);
2806 REGISTER_ZIP_CLASS_CONST_LONG("CM_PKWARE_IMPLODE", ZIP_CM_PKWARE_IMPLODE);
2807 REGISTER_ZIP_CLASS_CONST_LONG("CM_BZIP2", ZIP_CM_BZIP2);
2808 REGISTER_ZIP_CLASS_CONST_LONG("CM_LZMA", ZIP_CM_LZMA);
2809 REGISTER_ZIP_CLASS_CONST_LONG("CM_TERSE", ZIP_CM_TERSE);
2810 REGISTER_ZIP_CLASS_CONST_LONG("CM_LZ77", ZIP_CM_LZ77);
2811 REGISTER_ZIP_CLASS_CONST_LONG("CM_WAVPACK", ZIP_CM_WAVPACK);
2812 REGISTER_ZIP_CLASS_CONST_LONG("CM_PPMD", ZIP_CM_PPMD);
2814 /* Error code */
2815 REGISTER_ZIP_CLASS_CONST_LONG("ER_OK", ZIP_ER_OK); /* N No error */
2816 REGISTER_ZIP_CLASS_CONST_LONG("ER_MULTIDISK", ZIP_ER_MULTIDISK); /* N Multi-disk zip archives not supported */
2817 REGISTER_ZIP_CLASS_CONST_LONG("ER_RENAME", ZIP_ER_RENAME); /* S Renaming temporary file failed */
2818 REGISTER_ZIP_CLASS_CONST_LONG("ER_CLOSE", ZIP_ER_CLOSE); /* S Closing zip archive failed */
2819 REGISTER_ZIP_CLASS_CONST_LONG("ER_SEEK", ZIP_ER_SEEK); /* S Seek error */
2820 REGISTER_ZIP_CLASS_CONST_LONG("ER_READ", ZIP_ER_READ); /* S Read error */
2821 REGISTER_ZIP_CLASS_CONST_LONG("ER_WRITE", ZIP_ER_WRITE); /* S Write error */
2822 REGISTER_ZIP_CLASS_CONST_LONG("ER_CRC", ZIP_ER_CRC); /* N CRC error */
2823 REGISTER_ZIP_CLASS_CONST_LONG("ER_ZIPCLOSED", ZIP_ER_ZIPCLOSED); /* N Containing zip archive was closed */
2824 REGISTER_ZIP_CLASS_CONST_LONG("ER_NOENT", ZIP_ER_NOENT); /* N No such file */
2825 REGISTER_ZIP_CLASS_CONST_LONG("ER_EXISTS", ZIP_ER_EXISTS); /* N File already exists */
2826 REGISTER_ZIP_CLASS_CONST_LONG("ER_OPEN", ZIP_ER_OPEN); /* S Can't open file */
2827 REGISTER_ZIP_CLASS_CONST_LONG("ER_TMPOPEN", ZIP_ER_TMPOPEN); /* S Failure to create temporary file */
2828 REGISTER_ZIP_CLASS_CONST_LONG("ER_ZLIB", ZIP_ER_ZLIB); /* Z Zlib error */
2829 REGISTER_ZIP_CLASS_CONST_LONG("ER_MEMORY", ZIP_ER_MEMORY); /* N Malloc failure */
2830 REGISTER_ZIP_CLASS_CONST_LONG("ER_CHANGED", ZIP_ER_CHANGED); /* N Entry has been changed */
2831 REGISTER_ZIP_CLASS_CONST_LONG("ER_COMPNOTSUPP", ZIP_ER_COMPNOTSUPP);/* N Compression method not supported */
2832 REGISTER_ZIP_CLASS_CONST_LONG("ER_EOF", ZIP_ER_EOF); /* N Premature EOF */
2833 REGISTER_ZIP_CLASS_CONST_LONG("ER_INVAL", ZIP_ER_INVAL); /* N Invalid argument */
2834 REGISTER_ZIP_CLASS_CONST_LONG("ER_NOZIP", ZIP_ER_NOZIP); /* N Not a zip archive */
2835 REGISTER_ZIP_CLASS_CONST_LONG("ER_INTERNAL", ZIP_ER_INTERNAL); /* N Internal error */
2836 REGISTER_ZIP_CLASS_CONST_LONG("ER_INCONS", ZIP_ER_INCONS); /* N Zip archive inconsistent */
2837 REGISTER_ZIP_CLASS_CONST_LONG("ER_REMOVE", ZIP_ER_REMOVE); /* S Can't remove file */
2838 REGISTER_ZIP_CLASS_CONST_LONG("ER_DELETED", ZIP_ER_DELETED); /* N Entry has been deleted */
2840 php_register_url_stream_wrapper("zip", &php_stream_zip_wrapper TSRMLS_CC);
2841 #endif
2843 le_zip_dir = zend_register_list_destructors_ex(php_zip_free_dir, NULL, le_zip_dir_name, module_number);
2844 le_zip_entry = zend_register_list_destructors_ex(php_zip_free_entry, NULL, le_zip_entry_name, module_number);
2846 return SUCCESS;
2848 /* }}} */
2850 /* {{{ PHP_MSHUTDOWN_FUNCTION
2852 static PHP_MSHUTDOWN_FUNCTION(zip)
2854 #ifdef PHP_ZIP_USE_OO
2855 zend_hash_destroy(&zip_prop_handlers);
2856 php_unregister_url_stream_wrapper("zip" TSRMLS_CC);
2857 #endif
2858 return SUCCESS;
2860 /* }}} */
2862 /* {{{ PHP_MINFO_FUNCTION
2864 static PHP_MINFO_FUNCTION(zip)
2866 php_info_print_table_start();
2868 php_info_print_table_row(2, "Zip", "enabled");
2869 php_info_print_table_row(2, "Extension Version","$Id$");
2870 php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION_STRING);
2871 php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION);
2873 php_info_print_table_end();
2875 /* }}} */
2878 * Local variables:
2879 * tab-width: 4
2880 * c-basic-offset: 4
2881 * End:
2882 * vim600: noet sw=4 ts=4 fdm=marker
2883 * vim<600: noet sw=4 ts=4