summaryrefslogtreecommitdiff
path: root/ext/zip/php_zip.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2013-03-14 05:42:27 +0000
committer <>2013-04-03 16:25:08 +0000
commitc4dd7a1a684490673e25aaf4fabec5df138854c4 (patch)
tree4d57c44caae4480efff02b90b9be86f44bf25409 /ext/zip/php_zip.c
downloadphp2-master.tar.gz
Imported from /home/lorry/working-area/delta_php2/php-5.4.13.tar.bz2.HEADphp-5.4.13master
Diffstat (limited to 'ext/zip/php_zip.c')
-rw-r--r--ext/zip/php_zip.c2884
1 files changed, 2884 insertions, 0 deletions
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
new file mode 100644
index 0000000..5683b32
--- /dev/null
+++ b/ext/zip/php_zip.c
@@ -0,0 +1,2884 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Piere-Alain Joye <pierre@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: 727cc853ca1ae15d995c3520c5719784ddc1e292 $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "ext/standard/file.h"
+#include "ext/standard/php_string.h"
+#include "ext/pcre/php_pcre.h"
+#include "php_zip.h"
+#include "lib/zip.h"
+#include "lib/zipint.h"
+
+/* zip_open is a macro for renaming libzip zipopen, so we need to use PHP_NAMED_FUNCTION */
+static PHP_NAMED_FUNCTION(zif_zip_open);
+static PHP_NAMED_FUNCTION(zif_zip_read);
+static PHP_NAMED_FUNCTION(zif_zip_close);
+static PHP_NAMED_FUNCTION(zif_zip_entry_read);
+static PHP_NAMED_FUNCTION(zif_zip_entry_filesize);
+static PHP_NAMED_FUNCTION(zif_zip_entry_name);
+static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize);
+static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod);
+static PHP_NAMED_FUNCTION(zif_zip_entry_open);
+static PHP_NAMED_FUNCTION(zif_zip_entry_close);
+
+#ifdef HAVE_GLOB
+#ifndef PHP_WIN32
+#include <glob.h>
+#else
+#include "win32/glob.h"
+#endif
+#endif
+
+/* {{{ Resource le */
+static int le_zip_dir;
+#define le_zip_dir_name "Zip Directory"
+static int le_zip_entry;
+#define le_zip_entry_name "Zip Entry"
+/* }}} */
+
+/* {{{ PHP_ZIP_STAT_INDEX(za, index, flags, sb) */
+#define PHP_ZIP_STAT_INDEX(za, index, flags, sb) \
+ if (zip_stat_index(za, index, flags, &sb) != 0) { \
+ RETURN_FALSE; \
+ }
+/* }}} */
+
+/* {{{ PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) */
+#define PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) \
+ if (path_len < 1) { \
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name"); \
+ RETURN_FALSE; \
+ } \
+ if (zip_stat(za, path, flags, &sb) != 0) { \
+ RETURN_FALSE; \
+ }
+/* }}} */
+
+/* {{{ PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) */
+#define PHP_ZIP_SET_FILE_COMMENT(za, index, comment, comment_len) \
+ if (comment_len == 0) { \
+ /* Passing NULL remove the existing comment */ \
+ if (zip_set_file_comment(intern, index, NULL, 0) < 0) { \
+ RETURN_FALSE; \
+ } \
+ } else if (zip_set_file_comment(intern, index, comment, comment_len) < 0) { \
+ RETURN_FALSE; \
+ } \
+ RETURN_TRUE;
+/* }}} */
+
+#if (PHP_MAJOR_VERSION < 6)
+# define add_ascii_assoc_string add_assoc_string
+# define add_ascii_assoc_long add_assoc_long
+#endif
+
+/* Flatten a path by making a relative path (to .)*/
+static char * php_zip_make_relative_path(char *path, int path_len) /* {{{ */
+{
+ char *path_begin = path;
+ size_t i;
+
+ if (IS_SLASH(path[0])) {
+ return path + 1;
+ }
+
+ if (path_len < 1 || path == NULL) {
+ return NULL;
+ }
+
+ i = path_len;
+
+ while (1) {
+ while (i > 0 && !IS_SLASH(path[i])) {
+ i--;
+ }
+
+ if (!i) {
+ return path;
+ }
+
+ if (i >= 2 && (path[i -1] == '.' || path[i -1] == ':')) {
+ /* i is the position of . or :, add 1 for / */
+ path_begin = path + i + 1;
+ break;
+ }
+ i--;
+ }
+
+ return path_begin;
+}
+/* }}} */
+
+#ifdef PHP_ZIP_USE_OO
+/* {{{ php_zip_extract_file */
+static int php_zip_extract_file(struct zip * za, char *dest, char *file, int file_len TSRMLS_DC)
+{
+ php_stream_statbuf ssb;
+ struct zip_file *zf;
+ struct zip_stat sb;
+ char b[8192];
+ int n, len, ret;
+ php_stream *stream;
+ char *fullpath;
+ char *file_dirname_fullpath;
+ char file_dirname[MAXPATHLEN];
+ size_t dir_len;
+ char *file_basename;
+ size_t file_basename_len;
+ int is_dir_only = 0;
+ char *path_cleaned;
+ size_t path_cleaned_len;
+ cwd_state new_state;
+
+ new_state.cwd = (char*)malloc(1);
+ new_state.cwd[0] = '\0';
+ new_state.cwd_length = 0;
+
+ /* Clean/normlize the path and then transform any path (absolute or relative)
+ to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt)
+ */
+ virtual_file_ex(&new_state, file, NULL, CWD_EXPAND TSRMLS_CC);
+ path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length);
+ if(!path_cleaned) {
+ return 0;
+ }
+ path_cleaned_len = strlen(path_cleaned);
+
+ if (path_cleaned_len >= MAXPATHLEN || zip_stat(za, file, 0, &sb) != 0) {
+ return 0;
+ }
+
+ /* it is a directory only, see #40228 */
+ if (path_cleaned_len > 1 && IS_SLASH(path_cleaned[path_cleaned_len - 1])) {
+ len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file);
+ is_dir_only = 1;
+ } else {
+ memcpy(file_dirname, path_cleaned, path_cleaned_len);
+ dir_len = php_dirname(file_dirname, path_cleaned_len);
+
+ if (dir_len <= 0 || (dir_len == 1 && file_dirname[0] == '.')) {
+ len = spprintf(&file_dirname_fullpath, 0, "%s", dest);
+ } else {
+ len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file_dirname);
+ }
+
+ php_basename(path_cleaned, path_cleaned_len, NULL, 0, &file_basename, (size_t *)&file_basename_len TSRMLS_CC);
+
+ if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname_fullpath)) {
+ efree(file_dirname_fullpath);
+ efree(file_basename);
+ free(new_state.cwd);
+ return 0;
+ }
+ }
+
+ /* let see if the path already exists */
+ if (php_stream_stat_path_ex(file_dirname_fullpath, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
+
+#if defined(PHP_WIN32) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1)
+ char *e;
+ e = file_dirname_fullpath;
+ while (*e) {
+ if (*e == '/') {
+ *e = DEFAULT_SLASH;
+ }
+ e++;
+ }
+#endif
+
+ ret = php_stream_mkdir(file_dirname_fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE|REPORT_ERRORS, NULL);
+ if (!ret) {
+ efree(file_dirname_fullpath);
+ if (!is_dir_only) {
+ efree(file_basename);
+ free(new_state.cwd);
+ }
+ return 0;
+ }
+ }
+
+ /* it is a standalone directory, job done */
+ if (is_dir_only) {
+ efree(file_dirname_fullpath);
+ free(new_state.cwd);
+ return 1;
+ }
+
+ len = spprintf(&fullpath, 0, "%s/%s", file_dirname_fullpath, file_basename);
+ if (!len) {
+ efree(file_dirname_fullpath);
+ efree(file_basename);
+ free(new_state.cwd);
+ return 0;
+ } else if (len > MAXPATHLEN) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Full extraction path exceed MAXPATHLEN (%i)", MAXPATHLEN);
+ efree(file_dirname_fullpath);
+ efree(file_basename);
+ free(new_state.cwd);
+ return 0;
+ }
+
+ /* check again the full path, not sure if it
+ * is required, does a file can have a different
+ * safemode status as its parent folder?
+ */
+ if (ZIP_OPENBASEDIR_CHECKPATH(fullpath)) {
+ efree(fullpath);
+ efree(file_dirname_fullpath);
+ efree(file_basename);
+ free(new_state.cwd);
+ return 0;
+ }
+
+#if PHP_API_VERSION < 20100412
+ stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
+#else
+ stream = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL);
+#endif
+
+ if (stream == NULL) {
+ n = -1;
+ goto done;
+ }
+
+ zf = zip_fopen(za, file, 0);
+ if (zf == NULL) {
+ n = -1;
+ php_stream_close(stream);
+ goto done;
+ }
+
+ n = 0;
+
+ while ((n=zip_fread(zf, b, sizeof(b))) > 0) {
+ php_stream_write(stream, b, n);
+ }
+
+ php_stream_close(stream);
+ n = zip_fclose(zf);
+
+done:
+ efree(fullpath);
+ efree(file_basename);
+ efree(file_dirname_fullpath);
+ free(new_state.cwd);
+
+ if (n<0) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+/* }}} */
+
+static int 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 TSRMLS_DC) /* {{{ */
+{
+ struct zip_source *zs;
+ int cur_idx;
+ char resolved_path[MAXPATHLEN];
+
+
+ if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
+ return -1;
+ }
+
+ if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
+ return -1;
+ }
+
+ zs = zip_source_file(za, resolved_path, offset_start, offset_len);
+ if (!zs) {
+ return -1;
+ }
+
+ cur_idx = zip_name_locate(za, (const char *)entry_name, 0);
+ /* TODO: fix _zip_replace */
+ if (cur_idx<0) {
+ /* reset the error */
+ if (za->error.str) {
+ _zip_error_fini(&za->error);
+ }
+ _zip_error_init(&za->error);
+ } else {
+ if (zip_delete(za, cur_idx) == -1) {
+ zip_source_free(zs);
+ return -1;
+ }
+ }
+
+ if (zip_add(za, entry_name, zs) == -1) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+/* }}} */
+
+static int php_zip_parse_options(zval *options, long *remove_all_path,
+ char **remove_path, int *remove_path_len, char **add_path, int *add_path_len TSRMLS_DC) /* {{{ */
+{
+ zval **option;
+ if (zend_hash_find(HASH_OF(options), "remove_all_path", sizeof("remove_all_path"), (void **)&option) == SUCCESS) {
+ long opt;
+ if (Z_TYPE_PP(option) != IS_LONG) {
+ zval tmp = **option;
+ zval_copy_ctor(&tmp);
+ convert_to_long(&tmp);
+ opt = Z_LVAL(tmp);
+ } else {
+ opt = Z_LVAL_PP(option);
+ }
+ *remove_all_path = opt;
+ }
+
+ /* If I add more options, it would make sense to create a nice static struct and loop over it. */
+ if (zend_hash_find(HASH_OF(options), "remove_path", sizeof("remove_path"), (void **)&option) == SUCCESS) {
+ if (Z_TYPE_PP(option) != IS_STRING) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path option expected to be a string");
+ return -1;
+ }
+
+ if (Z_STRLEN_PP(option) < 1) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string given as remove_path option");
+ return -1;
+ }
+
+ if (Z_STRLEN_PP(option) >= MAXPATHLEN) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "remove_path string is too long (max: %i, %i given)",
+ MAXPATHLEN - 1, Z_STRLEN_PP(option));
+ return -1;
+ }
+ *remove_path_len = Z_STRLEN_PP(option);
+ *remove_path = Z_STRVAL_PP(option);
+ }
+
+ if (zend_hash_find(HASH_OF(options), "add_path", sizeof("add_path"), (void **)&option) == SUCCESS) {
+ if (Z_TYPE_PP(option) != IS_STRING) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path option expected to be a string");
+ return -1;
+ }
+
+ if (Z_STRLEN_PP(option) < 1) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string given as the add_path option");
+ return -1;
+ }
+
+ if (Z_STRLEN_PP(option) >= MAXPATHLEN) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)",
+ MAXPATHLEN - 1, Z_STRLEN_PP(option));
+ return -1;
+ }
+ *add_path_len = Z_STRLEN_PP(option);
+ *add_path = Z_STRVAL_PP(option);
+ }
+ return 1;
+}
+/* }}} */
+
+/* {{{ REGISTER_ZIP_CLASS_CONST_LONG */
+#define REGISTER_ZIP_CLASS_CONST_LONG(const_name, value) \
+ zend_declare_class_constant_long(zip_class_entry, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
+/* }}} */
+
+/* {{{ ZIP_FROM_OBJECT */
+#define ZIP_FROM_OBJECT(intern, object) \
+ { \
+ ze_zip_object *obj = (ze_zip_object*) zend_object_store_get_object(object TSRMLS_CC); \
+ intern = obj->za; \
+ if (!intern) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid or unitialized Zip object"); \
+ RETURN_FALSE; \
+ } \
+ }
+/* }}} */
+
+/* {{{ RETURN_SB(sb) */
+#define RETURN_SB(sb) \
+ { \
+ array_init(return_value); \
+ add_ascii_assoc_string(return_value, "name", (char *)(sb)->name, 1); \
+ add_ascii_assoc_long(return_value, "index", (long) (sb)->index); \
+ add_ascii_assoc_long(return_value, "crc", (long) (sb)->crc); \
+ add_ascii_assoc_long(return_value, "size", (long) (sb)->size); \
+ add_ascii_assoc_long(return_value, "mtime", (long) (sb)->mtime); \
+ add_ascii_assoc_long(return_value, "comp_size", (long) (sb)->comp_size); \
+ add_ascii_assoc_long(return_value, "comp_method", (long) (sb)->comp_method); \
+ }
+/* }}} */
+
+static int php_zip_status(struct zip *za TSRMLS_DC) /* {{{ */
+{
+ int zep, syp;
+
+ zip_error_get(za, &zep, &syp);
+ return zep;
+}
+/* }}} */
+
+static int php_zip_status_sys(struct zip *za TSRMLS_DC) /* {{{ */
+{
+ int zep, syp;
+
+ zip_error_get(za, &zep, &syp);
+ return syp;
+}
+/* }}} */
+
+static int php_zip_get_num_files(struct zip *za TSRMLS_DC) /* {{{ */
+{
+ return zip_get_num_files(za);
+}
+/* }}} */
+
+static char * php_zipobj_get_filename(ze_zip_object *obj TSRMLS_DC) /* {{{ */
+{
+
+ if (!obj) {
+ return NULL;
+ }
+
+ if (obj->filename) {
+ return obj->filename;
+ }
+ return NULL;
+}
+/* }}} */
+
+static char * php_zipobj_get_zip_comment(struct zip *za, int *len TSRMLS_DC) /* {{{ */
+{
+ if (za) {
+ return (char *)zip_get_archive_comment(za, len, 0);
+ }
+ return NULL;
+}
+/* }}} */
+
+#ifdef HAVE_GLOB /* {{{ */
+#ifndef GLOB_ONLYDIR
+#define GLOB_ONLYDIR (1<<30)
+#define GLOB_EMULATE_ONLYDIR
+#define GLOB_FLAGMASK (~GLOB_ONLYDIR)
+#else
+#define GLOB_FLAGMASK (~0)
+#endif
+#ifndef GLOB_BRACE
+# define GLOB_BRACE 0
+#endif
+#ifndef GLOB_MARK
+# define GLOB_MARK 0
+#endif
+#ifndef GLOB_NOSORT
+# define GLOB_NOSORT 0
+#endif
+#ifndef GLOB_NOCHECK
+# define GLOB_NOCHECK 0
+#endif
+#ifndef GLOB_NOESCAPE
+# define GLOB_NOESCAPE 0
+#endif
+#ifndef GLOB_ERR
+# define GLOB_ERR 0
+#endif
+
+/* This is used for checking validity of passed flags (passing invalid flags causes segfault in glob()!! */
+#define GLOB_AVAILABLE_FLAGS (0 | GLOB_BRACE | GLOB_MARK | GLOB_NOSORT | GLOB_NOCHECK | GLOB_NOESCAPE | GLOB_ERR | GLOB_ONLYDIR)
+
+#endif /* }}} */
+
+int php_zip_glob(char *pattern, int pattern_len, long flags, zval *return_value TSRMLS_DC) /* {{{ */
+{
+#ifdef HAVE_GLOB
+ char cwd[MAXPATHLEN];
+ int cwd_skip = 0;
+#ifdef ZTS
+ char work_pattern[MAXPATHLEN];
+ char *result;
+#endif
+ glob_t globbuf;
+ int n;
+ int ret;
+
+ if (pattern_len >= MAXPATHLEN) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pattern exceeds the maximum allowed length of %d characters", MAXPATHLEN);
+ return -1;
+ }
+
+ if ((GLOB_AVAILABLE_FLAGS & flags) != flags) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "At least one of the passed flags is invalid or not supported on this platform");
+ return -1;
+ }
+
+#ifdef ZTS
+ if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) {
+ result = VCWD_GETCWD(cwd, MAXPATHLEN);
+ if (!result) {
+ cwd[0] = '\0';
+ }
+#ifdef PHP_WIN32
+ if (IS_SLASH(*pattern)) {
+ cwd[2] = '\0';
+ }
+#endif
+ cwd_skip = strlen(cwd)+1;
+
+ snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
+ pattern = work_pattern;
+ }
+#endif
+
+ globbuf.gl_offs = 0;
+ if (0 != (ret = glob(pattern, flags & GLOB_FLAGMASK, NULL, &globbuf))) {
+#ifdef GLOB_NOMATCH
+ if (GLOB_NOMATCH == ret) {
+ /* Some glob implementation simply return no data if no matches
+ were found, others return the GLOB_NOMATCH error code.
+ We don't want to treat GLOB_NOMATCH as an error condition
+ so that PHP glob() behaves the same on both types of
+ implementations and so that 'foreach (glob() as ...'
+ can be used for simple glob() calls without further error
+ checking.
+ */
+ array_init(return_value);
+ return 0;
+ }
+#endif
+ return 0;
+ }
+
+ /* now catch the FreeBSD style of "no matches" */
+ if (!globbuf.gl_pathc || !globbuf.gl_pathv) {
+ array_init(return_value);
+ return 0;
+ }
+
+ /* we assume that any glob pattern will match files from one directory only
+ so checking the dirname of the first match should be sufficient */
+ strncpy(cwd, globbuf.gl_pathv[0], MAXPATHLEN);
+ if (ZIP_OPENBASEDIR_CHECKPATH(cwd)) {
+ return -1;
+ }
+
+ array_init(return_value);
+ for (n = 0; n < globbuf.gl_pathc; n++) {
+ /* we need to do this everytime since GLOB_ONLYDIR does not guarantee that
+ * all directories will be filtered. GNU libc documentation states the
+ * following:
+ * If the information about the type of the file is easily available
+ * non-directories will be rejected but no extra work will be done to
+ * determine the information for each file. I.e., the caller must still be
+ * able to filter directories out.
+ */
+ if (flags & GLOB_ONLYDIR) {
+ struct stat s;
+
+ if (0 != VCWD_STAT(globbuf.gl_pathv[n], &s)) {
+ continue;
+ }
+
+ if (S_IFDIR != (s.st_mode & S_IFMT)) {
+ continue;
+ }
+ }
+ add_next_index_string(return_value, globbuf.gl_pathv[n]+cwd_skip, 1);
+ }
+
+ globfree(&globbuf);
+ return globbuf.gl_pathc;
+#else
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Glob support is not available");
+ return 0;
+#endif /* HAVE_GLOB */
+}
+/* }}} */
+
+int php_zip_pcre(char *regexp, int regexp_len, char *path, int path_len, zval *return_value TSRMLS_DC) /* {{{ */
+{
+#ifdef ZTS
+ char cwd[MAXPATHLEN];
+ int cwd_skip = 0;
+ char work_path[MAXPATHLEN];
+ char *result;
+#endif
+ int files_cnt;
+ char **namelist;
+
+#ifdef ZTS
+ if (!IS_ABSOLUTE_PATH(path, path_len)) {
+ result = VCWD_GETCWD(cwd, MAXPATHLEN);
+ if (!result) {
+ cwd[0] = '\0';
+ }
+#ifdef PHP_WIN32
+ if (IS_SLASH(*path)) {
+ cwd[2] = '\0';
+ }
+#endif
+ cwd_skip = strlen(cwd)+1;
+
+ snprintf(work_path, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, path);
+ path = work_path;
+ }
+#endif
+
+ if (ZIP_OPENBASEDIR_CHECKPATH(path)) {
+ return -1;
+ }
+
+ files_cnt = php_stream_scandir(path, &namelist, NULL, (void *) php_stream_dirent_alphasort);
+
+ if (files_cnt > 0) {
+ pcre *re = NULL;
+ pcre_extra *pcre_extra = NULL;
+ int preg_options = 0, i;
+
+ re = pcre_get_compiled_regex(regexp, &pcre_extra, &preg_options TSRMLS_CC);
+ if (!re) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid expression");
+ return -1;
+ }
+
+ array_init(return_value);
+
+ /* only the files, directories are ignored */
+ for (i = 0; i < files_cnt; i++) {
+ struct stat s;
+ char fullpath[MAXPATHLEN];
+ int ovector[3];
+ int matches;
+ int namelist_len = strlen(namelist[i]);
+
+
+ if ((namelist_len == 1 && namelist[i][0] == '.') ||
+ (namelist_len == 2 && namelist[i][0] == '.' && namelist[i][1] == '.')) {
+ efree(namelist[i]);
+ continue;
+ }
+
+ if ((path_len + namelist_len + 1) >= MAXPATHLEN) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "add_path string too long (max: %i, %i given)",
+ MAXPATHLEN - 1, (path_len + namelist_len + 1));
+ efree(namelist[i]);
+ break;
+ }
+
+ snprintf(fullpath, MAXPATHLEN, "%s%c%s", path, DEFAULT_SLASH, namelist[i]);
+
+ if (0 != VCWD_STAT(fullpath, &s)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot read <%s>", fullpath);
+ efree(namelist[i]);
+ continue;
+ }
+
+ if (S_IFDIR == (s.st_mode & S_IFMT)) {
+ efree(namelist[i]);
+ continue;
+ }
+
+ matches = pcre_exec(re, NULL, namelist[i], strlen(namelist[i]), 0, 0, ovector, 3);
+ /* 0 means that the vector is too small to hold all the captured substring offsets */
+ if (matches < 0) {
+ efree(namelist[i]);
+ continue;
+ }
+
+ add_next_index_string(return_value, fullpath, 1);
+ efree(namelist[i]);
+ }
+ efree(namelist);
+ }
+ return files_cnt;
+}
+/* }}} */
+
+#endif
+
+/* {{{ arginfo */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_open, 0, 0, 1)
+ ZEND_ARG_INFO(0, filename)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_close, 0, 0, 1)
+ ZEND_ARG_INFO(0, zip)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_read, 0, 0, 1)
+ ZEND_ARG_INFO(0, zip)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_open, 0, 0, 2)
+ ZEND_ARG_INFO(0, zip_dp)
+ ZEND_ARG_INFO(0, zip_entry)
+ ZEND_ARG_INFO(0, mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_close, 0, 0, 1)
+ ZEND_ARG_INFO(0, zip_ent)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_read, 0, 0, 1)
+ ZEND_ARG_INFO(0, zip_entry)
+ ZEND_ARG_INFO(0, len)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_name, 0, 0, 1)
+ ZEND_ARG_INFO(0, zip_entry)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressedsize, 0, 0, 1)
+ ZEND_ARG_INFO(0, zip_entry)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_filesize, 0, 0, 1)
+ ZEND_ARG_INFO(0, zip_entry)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_entry_compressionmethod, 0, 0, 1)
+ ZEND_ARG_INFO(0, zip_entry)
+ZEND_END_ARG_INFO()
+/* }}} */
+
+/* {{{ zend_function_entry */
+static const zend_function_entry zip_functions[] = {
+ ZEND_RAW_FENTRY("zip_open", zif_zip_open, arginfo_zip_open, 0)
+ ZEND_RAW_FENTRY("zip_close", zif_zip_close, arginfo_zip_close, 0)
+ ZEND_RAW_FENTRY("zip_read", zif_zip_read, arginfo_zip_read, 0)
+ PHP_FE(zip_entry_open, arginfo_zip_entry_open)
+ PHP_FE(zip_entry_close, arginfo_zip_entry_close)
+ PHP_FE(zip_entry_read, arginfo_zip_entry_read)
+ PHP_FE(zip_entry_filesize, arginfo_zip_entry_filesize)
+ PHP_FE(zip_entry_name, arginfo_zip_entry_name)
+ PHP_FE(zip_entry_compressedsize, arginfo_zip_entry_compressedsize)
+ PHP_FE(zip_entry_compressionmethod, arginfo_zip_entry_compressionmethod)
+ PHP_FE_END
+};
+/* }}} */
+
+/* {{{ ZE2 OO definitions */
+#ifdef PHP_ZIP_USE_OO
+static zend_class_entry *zip_class_entry;
+static zend_object_handlers zip_object_handlers;
+
+static HashTable zip_prop_handlers;
+
+typedef int (*zip_read_int_t)(struct zip *za TSRMLS_DC);
+typedef char *(*zip_read_const_char_t)(struct zip *za, int *len TSRMLS_DC);
+typedef char *(*zip_read_const_char_from_ze_t)(ze_zip_object *obj TSRMLS_DC);
+
+typedef struct _zip_prop_handler {
+ zip_read_int_t read_int_func;
+ zip_read_const_char_t read_const_char_func;
+ zip_read_const_char_from_ze_t read_const_char_from_obj_func;
+
+ int type;
+} zip_prop_handler;
+#endif
+/* }}} */
+
+#ifdef PHP_ZIP_USE_OO
+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) /* {{{ */
+{
+ zip_prop_handler hnd;
+
+ hnd.read_const_char_func = read_char_func;
+ hnd.read_int_func = read_int_func;
+ hnd.read_const_char_from_obj_func = read_char_from_obj_func;
+ hnd.type = rettype;
+ zend_hash_add(prop_handler, name, strlen(name)+1, &hnd, sizeof(zip_prop_handler), NULL);
+}
+/* }}} */
+
+static int php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, zval **retval, int newzval TSRMLS_DC) /* {{{ */
+{
+ const char *retchar = NULL;
+ int retint = 0;
+ int len = 0;
+
+ if (obj && obj->za != NULL) {
+ if (hnd->read_const_char_func) {
+ retchar = hnd->read_const_char_func(obj->za, &len TSRMLS_CC);
+ } else {
+ if (hnd->read_int_func) {
+ retint = hnd->read_int_func(obj->za TSRMLS_CC);
+ if (retint == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal zip error returned");
+ return FAILURE;
+ }
+ } else {
+ if (hnd->read_const_char_from_obj_func) {
+ retchar = hnd->read_const_char_from_obj_func(obj TSRMLS_CC);
+ len = strlen(retchar);
+ }
+ }
+ }
+ }
+
+ if (newzval) {
+ ALLOC_ZVAL(*retval);
+ }
+
+ switch (hnd->type) {
+ case IS_STRING:
+ if (retchar) {
+ ZVAL_STRINGL(*retval, (char *) retchar, len, 1);
+ } else {
+ ZVAL_EMPTY_STRING(*retval);
+ }
+ break;
+ case IS_BOOL:
+ ZVAL_BOOL(*retval, (long)retint);
+ break;
+ case IS_LONG:
+ ZVAL_LONG(*retval, (long)retint);
+ break;
+ default:
+ ZVAL_NULL(*retval);
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+static zval **php_zip_get_property_ptr_ptr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
+{
+ ze_zip_object *obj;
+ zval tmp_member;
+ zval **retval = NULL;
+
+ zip_prop_handler *hnd;
+ zend_object_handlers *std_hnd;
+ int ret;
+
+ if (member->type != IS_STRING) {
+ tmp_member = *member;
+ zval_copy_ctor(&tmp_member);
+ convert_to_string(&tmp_member);
+ member = &tmp_member;
+ key = NULL;
+ }
+
+ ret = FAILURE;
+ obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
+
+ if (obj->prop_handler != NULL) {
+ if (key) {
+ ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
+ } else {
+ ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
+ }
+ }
+
+
+ if (ret == FAILURE) {
+ std_hnd = zend_get_std_object_handlers();
+ retval = std_hnd->get_property_ptr_ptr(object, member, key TSRMLS_CC);
+ }
+
+ if (member == &tmp_member) {
+ zval_dtor(member);
+ }
+ return retval;
+}
+/* }}} */
+
+static zval* php_zip_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
+{
+ ze_zip_object *obj;
+ zval tmp_member;
+ zval *retval;
+ zip_prop_handler *hnd;
+ zend_object_handlers *std_hnd;
+ int ret;
+
+ if (member->type != IS_STRING) {
+ tmp_member = *member;
+ zval_copy_ctor(&tmp_member);
+ convert_to_string(&tmp_member);
+ member = &tmp_member;
+ key = NULL;
+ }
+
+ ret = FAILURE;
+ obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
+
+ if (obj->prop_handler != NULL) {
+ if (key) {
+ ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
+ } else {
+ ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
+ }
+ }
+
+ if (ret == SUCCESS) {
+ ret = php_zip_property_reader(obj, hnd, &retval, 1 TSRMLS_CC);
+ if (ret == SUCCESS) {
+ /* ensure we're creating a temporary variable */
+ Z_SET_REFCOUNT_P(retval, 0);
+ } else {
+ retval = EG(uninitialized_zval_ptr);
+ }
+ } else {
+ std_hnd = zend_get_std_object_handlers();
+ retval = std_hnd->read_property(object, member, type, key TSRMLS_CC);
+ }
+
+ if (member == &tmp_member) {
+ zval_dtor(member);
+ }
+ return retval;
+}
+/* }}} */
+
+static int php_zip_has_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
+{
+ ze_zip_object *obj;
+ zval tmp_member;
+ zip_prop_handler *hnd;
+ zend_object_handlers *std_hnd;
+ int ret, retval = 0;
+
+ if (member->type != IS_STRING) {
+ tmp_member = *member;
+ zval_copy_ctor(&tmp_member);
+ convert_to_string(&tmp_member);
+ member = &tmp_member;
+ key = NULL;
+ }
+
+ ret = FAILURE;
+ obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
+
+ if (obj->prop_handler != NULL) {
+ if (key) {
+ ret = zend_hash_quick_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, key->hash_value, (void **) &hnd);
+ } else {
+ ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
+ }
+ }
+
+ if (ret == SUCCESS) {
+ zval *tmp;
+ ALLOC_INIT_ZVAL(tmp);
+
+ if (type == 2) {
+ retval = 1;
+ } else if (php_zip_property_reader(obj, hnd, &tmp, 0 TSRMLS_CC) == SUCCESS) {
+ Z_SET_REFCOUNT_P(tmp, 1);
+ Z_UNSET_ISREF_P(tmp);
+ if (type == 1) {
+ retval = zend_is_true(tmp);
+ } else if (type == 0) {
+ retval = (Z_TYPE_P(tmp) != IS_NULL);
+ }
+ }
+
+ zval_ptr_dtor(&tmp);
+ } else {
+ std_hnd = zend_get_std_object_handlers();
+ retval = std_hnd->has_property(object, member, type, key TSRMLS_CC);
+ }
+
+ if (member == &tmp_member) {
+ zval_dtor(member);
+ }
+ return retval;
+}
+/* }}} */
+
+static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */
+{
+ ze_zip_object *obj;
+ zip_prop_handler *hnd;
+ HashTable *props;
+ zval *val;
+ int ret;
+ char *key;
+ uint key_len;
+ HashPosition pos;
+ ulong num_key;
+
+ obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
+ props = zend_std_get_properties(object TSRMLS_CC);
+
+ if (obj->prop_handler == NULL) {
+ return NULL;
+ }
+ zend_hash_internal_pointer_reset_ex(obj->prop_handler, &pos);
+
+ while (zend_hash_get_current_data_ex(obj->prop_handler, (void**)&hnd, &pos) == SUCCESS) {
+ zend_hash_get_current_key_ex(obj->prop_handler, &key, &key_len, &num_key, 0, &pos);
+ MAKE_STD_ZVAL(val);
+ ret = php_zip_property_reader(obj, hnd, &val, 0 TSRMLS_CC);
+ if (ret != SUCCESS) {
+ val = EG(uninitialized_zval_ptr);
+ }
+ zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL);
+ zend_hash_move_forward_ex(obj->prop_handler, &pos);
+ }
+ return props;
+}
+/* }}} */
+
+static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */
+{
+ ze_zip_object * intern = (ze_zip_object *) object;
+ int i;
+
+ if (!intern) {
+ return;
+ }
+ if (intern->za) {
+ if (zip_close(intern->za) != 0) {
+ _zip_free(intern->za);
+ }
+ intern->za = NULL;
+ }
+
+ if (intern->buffers_cnt>0) {
+ for (i=0; i<intern->buffers_cnt; i++) {
+ efree(intern->buffers[i]);
+ }
+ efree(intern->buffers);
+ }
+
+ intern->za = NULL;
+
+#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)
+ zend_object_std_dtor(&intern->zo TSRMLS_CC);
+#else
+ if (intern->zo.guards) {
+ zend_hash_destroy(intern->zo.guards);
+ FREE_HASHTABLE(intern->zo.guards);
+ }
+
+ if (intern->zo.properties) {
+ zend_hash_destroy(intern->zo.properties);
+ FREE_HASHTABLE(intern->zo.properties);
+ }
+#endif
+
+ if (intern->filename) {
+ efree(intern->filename);
+ }
+ efree(intern);
+}
+/* }}} */
+
+static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
+{
+ ze_zip_object *intern;
+ zend_object_value retval;
+
+ intern = emalloc(sizeof(ze_zip_object));
+ memset(&intern->zo, 0, sizeof(zend_object));
+
+ intern->za = NULL;
+ intern->buffers = NULL;
+ intern->filename = NULL;
+ intern->buffers_cnt = 0;
+ intern->prop_handler = &zip_prop_handlers;
+
+#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2))
+ zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
+#else
+ ALLOC_HASHTABLE(intern->zo.properties);
+ zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+ intern->zo.ce = class_type;
+#endif
+
+ object_properties_init(&intern->zo, class_type);
+
+ retval.handle = zend_objects_store_put(intern,
+ NULL,
+ (zend_objects_free_object_storage_t) php_zip_object_free_storage,
+ NULL TSRMLS_CC);
+
+ retval.handlers = (zend_object_handlers *) & zip_object_handlers;
+
+ return retval;
+}
+/* }}} */
+#endif
+
+/* {{{ Resource dtors */
+
+/* {{{ php_zip_free_dir */
+static void php_zip_free_dir(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ zip_rsrc * zip_int = (zip_rsrc *) rsrc->ptr;
+
+ if (zip_int) {
+ if (zip_int->za) {
+ if (zip_close(zip_int->za) != 0) {
+ _zip_free(zip_int->za);
+ }
+ zip_int->za = NULL;
+ }
+
+ efree(rsrc->ptr);
+
+ rsrc->ptr = NULL;
+ }
+}
+/* }}} */
+
+/* {{{ php_zip_free_entry */
+static void php_zip_free_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ zip_read_rsrc *zr_rsrc = (zip_read_rsrc *) rsrc->ptr;
+
+ if (zr_rsrc) {
+ if (zr_rsrc->zf) {
+ if (zr_rsrc->zf->za) {
+ zip_fclose(zr_rsrc->zf);
+ } else {
+ if (zr_rsrc->zf->src)
+ zip_source_free(zr_rsrc->zf->src);
+ free(zr_rsrc->zf);
+ }
+ zr_rsrc->zf = NULL;
+ }
+ efree(zr_rsrc);
+ rsrc->ptr = NULL;
+ }
+}
+/* }}} */
+
+/* }}}*/
+
+/* reset macro */
+
+/* {{{ function prototypes */
+static PHP_MINIT_FUNCTION(zip);
+static PHP_MSHUTDOWN_FUNCTION(zip);
+static PHP_MINFO_FUNCTION(zip);
+/* }}} */
+
+/* {{{ zip_module_entry
+ */
+zend_module_entry zip_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "zip",
+ zip_functions,
+ PHP_MINIT(zip),
+ PHP_MSHUTDOWN(zip),
+ NULL,
+ NULL,
+ PHP_MINFO(zip),
+ PHP_ZIP_VERSION_STRING,
+ STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+#ifdef COMPILE_DL_ZIP
+ZEND_GET_MODULE(zip)
+#endif
+/* set macro */
+
+/* {{{ proto resource zip_open(string filename)
+Create new zip using source uri for output */
+static PHP_NAMED_FUNCTION(zif_zip_open)
+{
+ char *filename;
+ int filename_len;
+ char resolved_path[MAXPATHLEN + 1];
+ zip_rsrc *rsrc_int;
+ int err = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
+ return;
+ }
+
+ if (filename_len == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
+ RETURN_FALSE;
+ }
+
+ if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
+ RETURN_FALSE;
+ }
+
+ if(!expand_filepath(filename, resolved_path TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ rsrc_int = (zip_rsrc *)emalloc(sizeof(zip_rsrc));
+
+ rsrc_int->za = zip_open(resolved_path, 0, &err);
+ if (rsrc_int->za == NULL) {
+ efree(rsrc_int);
+ RETURN_LONG((long)err);
+ }
+
+ rsrc_int->index_current = 0;
+ rsrc_int->num_files = zip_get_num_files(rsrc_int->za);
+
+ ZEND_REGISTER_RESOURCE(return_value, rsrc_int, le_zip_dir);
+}
+/* }}} */
+
+/* {{{ proto void zip_close(resource zip)
+ Close a Zip archive */
+static PHP_NAMED_FUNCTION(zif_zip_close)
+{
+ zval * zip;
+ zip_rsrc *z_rsrc = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip) == FAILURE) {
+ return;
+ }
+ ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir);
+
+ /* really close the zip will break BC :-D */
+ zend_list_delete(Z_LVAL_P(zip));
+}
+/* }}} */
+
+/* {{{ proto resource zip_read(resource zip)
+ Returns the next file in the archive */
+static PHP_NAMED_FUNCTION(zif_zip_read)
+{
+ zval *zip_dp;
+ zip_read_rsrc *zr_rsrc;
+ int ret;
+ zip_rsrc *rsrc_int;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_dp) == FAILURE) {
+ return;
+ }
+ ZEND_FETCH_RESOURCE(rsrc_int, zip_rsrc *, &zip_dp, -1, le_zip_dir_name, le_zip_dir);
+
+ if (rsrc_int && rsrc_int->za) {
+ if (rsrc_int->index_current >= rsrc_int->num_files) {
+ RETURN_FALSE;
+ }
+
+ zr_rsrc = emalloc(sizeof(zip_read_rsrc));
+
+ ret = zip_stat_index(rsrc_int->za, rsrc_int->index_current, 0, &zr_rsrc->sb);
+
+ if (ret != 0) {
+ efree(zr_rsrc);
+ RETURN_FALSE;
+ }
+
+ zr_rsrc->zf = zip_fopen_index(rsrc_int->za, rsrc_int->index_current, 0);
+ if (zr_rsrc->zf) {
+ rsrc_int->index_current++;
+ ZEND_REGISTER_RESOURCE(return_value, zr_rsrc, le_zip_entry);
+ } else {
+ efree(zr_rsrc);
+ RETURN_FALSE;
+ }
+
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto bool zip_entry_open(resource zip_dp, resource zip_entry [, string mode])
+ Open a Zip File, pointed by the resource entry */
+/* Dummy function to follow the old API */
+static PHP_NAMED_FUNCTION(zif_zip_entry_open)
+{
+ zval * zip;
+ zval * zip_entry;
+ char *mode = NULL;
+ int mode_len = 0;
+ zip_read_rsrc * zr_rsrc;
+ zip_rsrc *z_rsrc;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|s", &zip, &zip_entry, &mode, &mode_len) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
+ ZEND_FETCH_RESOURCE(z_rsrc, zip_rsrc *, &zip, -1, le_zip_dir_name, le_zip_dir);
+
+ if (zr_rsrc->zf != NULL) {
+ RETURN_TRUE;
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto bool zip_entry_close(resource zip_ent)
+ Close a zip entry */
+static PHP_NAMED_FUNCTION(zif_zip_entry_close)
+{
+ zval * zip_entry;
+ zip_read_rsrc * zr_rsrc;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
+
+ RETURN_BOOL(SUCCESS == zend_list_delete(Z_LVAL_P(zip_entry)));
+}
+/* }}} */
+
+/* {{{ proto mixed zip_entry_read(resource zip_entry [, int len])
+ Read from an open directory entry */
+static PHP_NAMED_FUNCTION(zif_zip_entry_read)
+{
+ zval * zip_entry;
+ long len = 0;
+ zip_read_rsrc * zr_rsrc;
+ char *buffer;
+ int n = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zip_entry, &len) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
+
+ if (len <= 0) {
+ len = 1024;
+ }
+
+ if (zr_rsrc->zf) {
+ buffer = safe_emalloc(len, 1, 1);
+ n = zip_fread(zr_rsrc->zf, buffer, len);
+ if (n > 0) {
+ buffer[n] = 0;
+ RETURN_STRINGL(buffer, n, 0);
+ } else {
+ efree(buffer);
+ RETURN_EMPTY_STRING()
+ }
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+static void php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS, int opt) /* {{{ */
+{
+ zval * zip_entry;
+ zip_read_rsrc * zr_rsrc;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zip_entry) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(zr_rsrc, zip_read_rsrc *, &zip_entry, -1, le_zip_entry_name, le_zip_entry);
+
+ if (!zr_rsrc->zf) {
+ RETURN_FALSE;
+ }
+
+ switch (opt) {
+ case 0:
+ RETURN_STRING((char *)zr_rsrc->sb.name, 1);
+ break;
+ case 1:
+ RETURN_LONG((long) (zr_rsrc->sb.comp_size));
+ break;
+ case 2:
+ RETURN_LONG((long) (zr_rsrc->sb.size));
+ break;
+ case 3:
+ switch (zr_rsrc->sb.comp_method) {
+ case 0:
+ RETURN_STRING("stored", 1);
+ break;
+ case 1:
+ RETURN_STRING("shrunk", 1);
+ break;
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ RETURN_STRING("reduced", 1);
+ break;
+ case 6:
+ RETURN_STRING("imploded", 1);
+ break;
+ case 7:
+ RETURN_STRING("tokenized", 1);
+ break;
+ case 8:
+ RETURN_STRING("deflated", 1);
+ break;
+ case 9:
+ RETURN_STRING("deflatedX", 1);
+ break;
+ case 10:
+ RETURN_STRING("implodedX", 1);
+ break;
+ default:
+ RETURN_FALSE;
+ }
+ RETURN_LONG((long) (zr_rsrc->sb.comp_method));
+ break;
+ }
+
+}
+/* }}} */
+
+/* {{{ proto string zip_entry_name(resource zip_entry)
+ Return the name given a ZZip entry */
+static PHP_NAMED_FUNCTION(zif_zip_entry_name)
+{
+ php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ proto int zip_entry_compressedsize(resource zip_entry)
+ Return the compressed size of a ZZip entry */
+static PHP_NAMED_FUNCTION(zif_zip_entry_compressedsize)
+{
+ php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ proto int zip_entry_filesize(resource zip_entry)
+ Return the actual filesize of a ZZip entry */
+static PHP_NAMED_FUNCTION(zif_zip_entry_filesize)
+{
+ php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
+}
+/* }}} */
+
+/* {{{ proto string zip_entry_compressionmethod(resource zip_entry)
+ Return a string containing the compression method used on a particular entry */
+static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod)
+{
+ php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
+}
+/* }}} */
+
+#ifdef PHP_ZIP_USE_OO
+/* {{{ proto mixed ZipArchive::open(string source [, int flags])
+Create new zip using source uri for output, return TRUE on success or the error code */
+static ZIPARCHIVE_METHOD(open)
+{
+ struct zip *intern;
+ char *filename;
+ int filename_len;
+ int err = 0;
+ long flags = 0;
+ char resolved_path[MAXPATHLEN];
+
+ zval *this = getThis();
+ ze_zip_object *ze_obj = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l", &filename, &filename_len, &flags) == FAILURE) {
+ return;
+ }
+
+ if (this) {
+ /* We do not use ZIP_FROM_OBJECT, zip init function here */
+ ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
+ }
+
+ if (filename_len == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string as source");
+ RETURN_FALSE;
+ }
+
+ if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
+ RETURN_FALSE;
+ }
+
+ if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+
+ if (ze_obj->za) {
+ /* we already have an opened zip, free it */
+ if (zip_close(ze_obj->za) != 0) {
+ _zip_free(ze_obj->za);
+ }
+ ze_obj->za = NULL;
+ }
+ if (ze_obj->filename) {
+ efree(ze_obj->filename);
+ ze_obj->filename = NULL;
+ }
+
+ intern = zip_open(resolved_path, flags, &err);
+ if (!intern || err) {
+ RETURN_LONG((long)err);
+ }
+ ze_obj->filename = estrdup(resolved_path);
+ ze_obj->filename_len = filename_len;
+ ze_obj->za = intern;
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::close()
+close the zip archive */
+static ZIPARCHIVE_METHOD(close)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ ze_zip_object *ze_obj;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
+
+ if (zip_close(intern)) {
+ RETURN_FALSE;
+ }
+
+ efree(ze_obj->filename);
+ ze_obj->filename = NULL;
+ ze_obj->filename_len = 0;
+ ze_obj->za = NULL;
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string ZipArchive::getStatusString()
+ * Returns the status error message, system and/or zip messages */
+static ZIPARCHIVE_METHOD(getStatusString)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ int zep, syp, len;
+ char error_string[128];
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ zip_error_get(intern, &zep, &syp);
+
+ len = zip_error_to_str(error_string, 128, zep, syp);
+ RETVAL_STRINGL(error_string, len, 1);
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::createEmptyDir(string dirname)
+Returns the index of the entry named filename in the archive */
+static ZIPARCHIVE_METHOD(addEmptyDir)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ char *dirname;
+ int dirname_len;
+ int idx;
+ struct zip_stat sb;
+ char *s;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
+ &dirname, &dirname_len) == FAILURE) {
+ return;
+ }
+
+ if (dirname_len<1) {
+ RETURN_FALSE;
+ }
+
+ if (dirname[dirname_len-1] != '/') {
+ s=(char *)emalloc(dirname_len+2);
+ strcpy(s, dirname);
+ s[dirname_len] = '/';
+ s[dirname_len+1] = '\0';
+ } else {
+ s = dirname;
+ }
+
+ idx = zip_stat(intern, s, 0, &sb);
+ if (idx >= 0) {
+ RETVAL_FALSE;
+ } else {
+ if (zip_add_dir(intern, (const char *)s) == -1) {
+ RETVAL_FALSE;
+ }
+ RETVAL_TRUE;
+ }
+
+ if (s != dirname) {
+ efree(s);
+ }
+}
+/* }}} */
+
+static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
+{
+ struct zip *intern;
+ zval *this = getThis();
+ char *pattern;
+ char *path = NULL;
+ char *remove_path = NULL;
+ char *add_path = NULL;
+ int pattern_len, add_path_len, remove_path_len, path_len = 0;
+ long remove_all_path = 0;
+ long flags = 0;
+ zval *options = NULL;
+ int found;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+ /* 1 == glob, 2==pcre */
+ if (type == 1) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|la",
+ &pattern, &pattern_len, &flags, &options) == FAILURE) {
+ return;
+ }
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sa",
+ &pattern, &pattern_len, &path, &path_len, &options) == FAILURE) {
+ return;
+ }
+ }
+
+ if (pattern_len == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as pattern");
+ RETURN_FALSE;
+ }
+ if (options && (php_zip_parse_options(options, &remove_all_path, &remove_path, &remove_path_len,
+ &add_path, &add_path_len TSRMLS_CC) < 0)) {
+ RETURN_FALSE;
+ }
+
+ if (remove_path && remove_path_len > 1 && (remove_path[strlen(remove_path) - 1] == '/' ||
+ remove_path[strlen(remove_path) - 1] == '\\')) {
+ remove_path[strlen(remove_path) - 1] = '\0';
+ }
+
+ if (type == 1) {
+ found = php_zip_glob(pattern, pattern_len, flags, return_value TSRMLS_CC);
+ } else {
+ found = php_zip_pcre(pattern, pattern_len, path, path_len, return_value TSRMLS_CC);
+ }
+
+ if (found > 0) {
+ int i;
+ zval **zval_file = NULL;
+
+ for (i = 0; i < found; i++) {
+ char *file, *file_stripped, *entry_name;
+ size_t entry_name_len, file_stripped_len;
+ char entry_name_buf[MAXPATHLEN];
+ char *basename = NULL;
+
+ if (zend_hash_index_find(Z_ARRVAL_P(return_value), i, (void **) &zval_file) == SUCCESS) {
+ file = Z_STRVAL_PP(zval_file);
+ if (remove_all_path) {
+ php_basename(Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file), NULL, 0,
+ &basename, (size_t *)&file_stripped_len TSRMLS_CC);
+ file_stripped = basename;
+ } else if (remove_path && strstr(Z_STRVAL_PP(zval_file), remove_path) != NULL) {
+ file_stripped = Z_STRVAL_PP(zval_file) + remove_path_len + 1;
+ file_stripped_len = Z_STRLEN_PP(zval_file) - remove_path_len - 1;
+ } else {
+ file_stripped = Z_STRVAL_PP(zval_file);
+ file_stripped_len = Z_STRLEN_PP(zval_file);
+ }
+
+ if (add_path) {
+ if ((add_path_len + file_stripped_len) > MAXPATHLEN) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Entry name too long (max: %d, %ld given)",
+ MAXPATHLEN - 1, (add_path_len + file_stripped_len));
+ zval_dtor(return_value);
+ RETURN_FALSE;
+ }
+
+ snprintf(entry_name_buf, MAXPATHLEN, "%s%s", add_path, file_stripped);
+ entry_name = entry_name_buf;
+ entry_name_len = strlen(entry_name);
+ } else {
+ entry_name = Z_STRVAL_PP(zval_file);
+ entry_name_len = Z_STRLEN_PP(zval_file);
+ }
+ if (basename) {
+ efree(basename);
+ basename = NULL;
+ }
+ if (php_zip_add_file(intern, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file),
+ entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
+ zval_dtor(return_value);
+ RETURN_FALSE;
+ }
+ }
+ }
+ }
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::addGlob(string pattern[,int flags [, array options]])
+Add files matching the glob pattern. See php's glob for the pattern syntax. */
+static ZIPARCHIVE_METHOD(addGlob)
+{
+ php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::addPattern(string pattern[, string path [, array options]])
+Add files matching the pcre pattern. See php's pcre for the pattern syntax. */
+static ZIPARCHIVE_METHOD(addPattern)
+{
+ php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::addFile(string filepath[, string entryname[, int start [, int length]]])
+Add a file in a Zip archive using its path and the name to use. */
+static ZIPARCHIVE_METHOD(addFile)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ char *filename;
+ int filename_len;
+ char *entry_name = NULL;
+ int entry_name_len = 0;
+ long offset_start = 0, offset_len = 0;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|sll",
+ &filename, &filename_len, &entry_name, &entry_name_len, &offset_start, &offset_len) == FAILURE) {
+ return;
+ }
+
+ if (filename_len == 0) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as filename");
+ RETURN_FALSE;
+ }
+
+ if (entry_name_len == 0) {
+ entry_name = filename;
+ entry_name_len = filename_len;
+ }
+
+ if (php_zip_add_file(intern, filename, filename_len,
+ entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
+ RETURN_FALSE;
+ } else {
+ RETURN_TRUE;
+ }
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::addFromString(string name, string content)
+Add a file using content and the entry name */
+static ZIPARCHIVE_METHOD(addFromString)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ char *buffer, *name;
+ int buffer_len, name_len;
+ ze_zip_object *ze_obj;
+ struct zip_source *zs;
+ int pos = 0;
+ int cur_idx;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
+ &name, &name_len, &buffer, &buffer_len) == FAILURE) {
+ return;
+ }
+
+ ze_obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
+ if (ze_obj->buffers_cnt) {
+ ze_obj->buffers = (char **)erealloc(ze_obj->buffers, sizeof(char *) * (ze_obj->buffers_cnt+1));
+ pos = ze_obj->buffers_cnt++;
+ } else {
+ ze_obj->buffers = (char **)emalloc(sizeof(char *));
+ ze_obj->buffers_cnt++;
+ pos = 0;
+ }
+ ze_obj->buffers[pos] = (char *)emalloc(buffer_len + 1);
+ memcpy(ze_obj->buffers[pos], buffer, buffer_len + 1);
+
+ zs = zip_source_buffer(intern, ze_obj->buffers[pos], buffer_len, 0);
+
+ if (zs == NULL) {
+ RETURN_FALSE;
+ }
+
+ cur_idx = zip_name_locate(intern, (const char *)name, 0);
+ /* TODO: fix _zip_replace */
+ if (cur_idx >= 0) {
+ if (zip_delete(intern, cur_idx) == -1) {
+ RETURN_FALSE;
+ }
+ }
+
+ if (zip_add(intern, name, zs) == -1) {
+ RETURN_FALSE;
+ } else {
+ RETURN_TRUE;
+ }
+}
+/* }}} */
+
+/* {{{ proto array ZipArchive::statName(string filename[, int flags])
+Returns the information about a the zip entry filename */
+static ZIPARCHIVE_METHOD(statName)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ char *name;
+ int name_len;
+ long flags = 0;
+ struct zip_stat sb;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l",
+ &name, &name_len, &flags) == FAILURE) {
+ return;
+ }
+
+ PHP_ZIP_STAT_PATH(intern, name, name_len, flags, sb);
+
+ RETURN_SB(&sb);
+}
+/* }}} */
+
+/* {{{ proto resource ZipArchive::statIndex(int index[, int flags])
+Returns the zip entry informations using its index */
+static ZIPARCHIVE_METHOD(statIndex)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ long index, flags = 0;
+
+ struct zip_stat sb;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
+ &index, &flags) == FAILURE) {
+ return;
+ }
+
+ if (zip_stat_index(intern, index, flags, &sb) != 0) {
+ RETURN_FALSE;
+ }
+ RETURN_SB(&sb);
+}
+/* }}} */
+
+/* {{{ proto int ZipArchive::locateName(string filename[, int flags])
+Returns the index of the entry named filename in the archive */
+static ZIPARCHIVE_METHOD(locateName)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ char *name;
+ int name_len;
+ long flags = 0;
+ long idx = -1;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|l",
+ &name, &name_len, &flags) == FAILURE) {
+ return;
+ }
+ if (name_len<1) {
+ RETURN_FALSE;
+ }
+
+ idx = (long)zip_name_locate(intern, (const char *)name, flags);
+
+ if (idx >= 0) {
+ RETURN_LONG(idx);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto string ZipArchive::getNameIndex(int index [, int flags])
+Returns the name of the file at position index */
+static ZIPARCHIVE_METHOD(getNameIndex)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ const char *name;
+ long flags = 0, index = 0;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
+ &index, &flags) == FAILURE) {
+ return;
+ }
+
+ name = zip_get_name(intern, (int) index, flags);
+
+ if (name) {
+ RETVAL_STRING((char *)name, 1);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::setArchiveComment(string comment)
+Set or remove (NULL/'') the comment of the archive */
+static ZIPARCHIVE_METHOD(setArchiveComment)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ int comment_len;
+ char * comment;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &comment, &comment_len) == FAILURE) {
+ return;
+ }
+ if (zip_set_archive_comment(intern, (const char *)comment, (int)comment_len)) {
+ RETURN_FALSE;
+ } else {
+ RETURN_TRUE;
+ }
+}
+/* }}} */
+
+/* {{{ proto string ZipArchive::getArchiveComment([int flags])
+Returns the comment of an entry using its index */
+static ZIPARCHIVE_METHOD(getArchiveComment)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ long flags = 0;
+ const char * comment;
+ int comment_len = 0;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) == FAILURE) {
+ return;
+ }
+
+ comment = zip_get_archive_comment(intern, &comment_len, (int)flags);
+ if(comment==NULL) {
+ RETURN_FALSE;
+ }
+ RETURN_STRINGL((char *)comment, (long)comment_len, 1);
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::setCommentName(string name, string comment)
+Set or remove (NULL/'') the comment of an entry using its Name */
+static ZIPARCHIVE_METHOD(setCommentName)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ int comment_len, name_len;
+ char * comment, *name;
+ int idx;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
+ &name, &name_len, &comment, &comment_len) == FAILURE) {
+ return;
+ }
+
+ if (name_len < 1) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name");
+ }
+
+ idx = zip_name_locate(intern, name, 0);
+ if (idx < 0) {
+ RETURN_FALSE;
+ }
+ PHP_ZIP_SET_FILE_COMMENT(intern, idx, comment, comment_len);
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::setCommentIndex(int index, string comment)
+Set or remove (NULL/'') the comment of an entry using its index */
+static ZIPARCHIVE_METHOD(setCommentIndex)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ long index;
+ int comment_len;
+ char * comment;
+ struct zip_stat sb;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls",
+ &index, &comment, &comment_len) == FAILURE) {
+ return;
+ }
+
+ PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
+ PHP_ZIP_SET_FILE_COMMENT(intern, index, comment, comment_len);
+}
+/* }}} */
+
+/* {{{ proto string ZipArchive::getCommentName(string name[, int flags])
+Returns the comment of an entry using its name */
+static ZIPARCHIVE_METHOD(getCommentName)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ int name_len, idx;
+ long flags = 0;
+ int comment_len = 0;
+ const char * comment;
+ char *name;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
+ &name, &name_len, &flags) == FAILURE) {
+ return;
+ }
+ if (name_len < 1) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as entry name");
+ RETURN_FALSE;
+ }
+
+ idx = zip_name_locate(intern, name, 0);
+ if (idx < 0) {
+ RETURN_FALSE;
+ }
+
+ comment = zip_get_file_comment(intern, idx, &comment_len, (int)flags);
+ RETURN_STRINGL((char *)comment, (long)comment_len, 1);
+}
+/* }}} */
+
+/* {{{ proto string ZipArchive::getCommentIndex(int index[, int flags])
+Returns the comment of an entry using its index */
+static ZIPARCHIVE_METHOD(getCommentIndex)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ long index, flags = 0;
+ const char * comment;
+ int comment_len = 0;
+ struct zip_stat sb;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l",
+ &index, &flags) == FAILURE) {
+ return;
+ }
+
+ PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
+ comment = zip_get_file_comment(intern, index, &comment_len, (int)flags);
+ RETURN_STRINGL((char *)comment, (long)comment_len, 1);
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::deleteIndex(int index)
+Delete a file using its index */
+static ZIPARCHIVE_METHOD(deleteIndex)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ long index;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
+ return;
+ }
+
+ if (index < 0) {
+ RETURN_FALSE;
+ }
+
+ if (zip_delete(intern, index) < 0) {
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::deleteName(string name)
+Delete a file using its index */
+static ZIPARCHIVE_METHOD(deleteName)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ int name_len;
+ char *name;
+ struct zip_stat sb;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
+ return;
+ }
+ if (name_len < 1) {
+ RETURN_FALSE;
+ }
+
+ PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
+ if (zip_delete(intern, sb.index)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::renameIndex(int index, string new_name)
+Rename an entry selected by its index to new_name */
+static ZIPARCHIVE_METHOD(renameIndex)
+{
+ struct zip *intern;
+ zval *this = getThis();
+
+ char *new_name;
+ int new_name_len;
+ long index;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &index, &new_name, &new_name_len) == FAILURE) {
+ return;
+ }
+
+ if (index < 0) {
+ RETURN_FALSE;
+ }
+
+ if (new_name_len < 1) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as new entry name");
+ RETURN_FALSE;
+ }
+ if (zip_rename(intern, index, (const char *)new_name) != 0) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::renameName(string name, string new_name)
+Rename an entry selected by its name to new_name */
+static ZIPARCHIVE_METHOD(renameName)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ struct zip_stat sb;
+ char *name, *new_name;
+ int name_len, new_name_len;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &new_name, &new_name_len) == FAILURE) {
+ return;
+ }
+
+ if (new_name_len < 1) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Empty string as new entry name");
+ RETURN_FALSE;
+ }
+
+ PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
+
+ if (zip_rename(intern, sb.index, (const char *)new_name)) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::unchangeIndex(int index)
+Changes to the file at position index are reverted */
+static ZIPARCHIVE_METHOD(unchangeIndex)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ long index;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) {
+ return;
+ }
+
+ if (index < 0) {
+ RETURN_FALSE;
+ }
+
+ if (zip_unchange(intern, index) != 0) {
+ RETURN_FALSE;
+ } else {
+ RETURN_TRUE;
+ }
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::unchangeName(string name)
+Changes to the file named 'name' are reverted */
+static ZIPARCHIVE_METHOD(unchangeName)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ struct zip_stat sb;
+ char *name;
+ int name_len;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
+ return;
+ }
+
+ if (name_len < 1) {
+ RETURN_FALSE;
+ }
+
+ PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb);
+
+ if (zip_unchange(intern, sb.index) != 0) {
+ RETURN_FALSE;
+ } else {
+ RETURN_TRUE;
+ }
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::unchangeAll()
+All changes to files and global information in archive are reverted */
+static ZIPARCHIVE_METHOD(unchangeAll)
+{
+ struct zip *intern;
+ zval *this = getThis();
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zip_unchange_all(intern) != 0) {
+ RETURN_FALSE;
+ } else {
+ RETURN_TRUE;
+ }
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::unchangeArchive()
+Revert all global changes to the archive archive. For now, this only reverts archive comment changes. */
+static ZIPARCHIVE_METHOD(unchangeArchive)
+{
+ struct zip *intern;
+ zval *this = getThis();
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zip_unchange_archive(intern) != 0) {
+ RETURN_FALSE;
+ } else {
+ RETURN_TRUE;
+ }
+}
+/* }}} */
+
+/* {{{ proto bool ZipArchive::extractTo(string pathto[, mixed files])
+Extract one or more file from a zip archive */
+/* TODO:
+ * - allow index or array of indeces
+ * - replace path
+ * - patterns
+ */
+static ZIPARCHIVE_METHOD(extractTo)
+{
+ struct zip *intern;
+
+ zval *this = getThis();
+ zval *zval_files = NULL;
+ zval **zval_file = NULL;
+ php_stream_statbuf ssb;
+ char *pathto;
+ int pathto_len;
+ int ret, i;
+
+ int nelems;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &pathto, &pathto_len, &zval_files) == FAILURE) {
+ return;
+ }
+
+ if (pathto_len < 1) {
+ RETURN_FALSE;
+ }
+
+ if (php_stream_stat_path_ex(pathto, PHP_STREAM_URL_STAT_QUIET, &ssb, NULL) < 0) {
+ ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
+ if (!ret) {
+ RETURN_FALSE;
+ }
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+ if (zval_files && (Z_TYPE_P(zval_files) != IS_NULL)) {
+ switch (Z_TYPE_P(zval_files)) {
+ case IS_STRING:
+ if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_files), Z_STRLEN_P(zval_files) TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ break;
+ case IS_ARRAY:
+ nelems = zend_hash_num_elements(Z_ARRVAL_P(zval_files));
+ if (nelems == 0 ) {
+ RETURN_FALSE;
+ }
+ for (i = 0; i < nelems; i++) {
+ if (zend_hash_index_find(Z_ARRVAL_P(zval_files), i, (void **) &zval_file) == SUCCESS) {
+ switch (Z_TYPE_PP(zval_file)) {
+ case IS_LONG:
+ break;
+ case IS_STRING:
+ if (!php_zip_extract_file(intern, pathto, Z_STRVAL_PP(zval_file), Z_STRLEN_PP(zval_file) TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ break;
+ }
+ }
+ }
+ break;
+ case IS_LONG:
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid argument, expect string or array of strings");
+ break;
+ }
+ } else {
+ /* Extract all files */
+ int filecount = zip_get_num_files(intern);
+
+ if (filecount == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal archive");
+ RETURN_FALSE;
+ }
+
+ for (i = 0; i < filecount; i++) {
+ char *file = (char*)zip_get_name(intern, i, ZIP_FL_UNCHANGED);
+ if (!php_zip_extract_file(intern, pathto, file, strlen(file) TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ }
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
+{
+ struct zip *intern;
+ zval *this = getThis();
+
+ struct zip_stat sb;
+ struct zip_file *zf;
+
+ char *filename;
+ int filename_len;
+ long index = -1;
+ long flags = 0;
+ long len = 0;
+
+ char *buffer;
+ int n = 0;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (type == 1) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|ll", &filename, &filename_len, &len, &flags) == FAILURE) {
+ return;
+ }
+ PHP_ZIP_STAT_PATH(intern, filename, filename_len, flags, sb);
+ } else {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ll", &index, &len, &flags) == FAILURE) {
+ return;
+ }
+ PHP_ZIP_STAT_INDEX(intern, index, 0, sb);
+ }
+
+ if (sb.size < 1) {
+ RETURN_EMPTY_STRING();
+ }
+
+ if (len < 1) {
+ len = sb.size;
+ }
+ if (index >= 0) {
+ zf = zip_fopen_index(intern, index, flags);
+ } else {
+ zf = zip_fopen(intern, filename, flags);
+ }
+
+ if (zf == NULL) {
+ RETURN_FALSE;
+ }
+
+ buffer = safe_emalloc(len, 1, 2);
+ n = zip_fread(zf, buffer, len);
+ if (n < 1) {
+ efree(buffer);
+ RETURN_EMPTY_STRING();
+ }
+
+ zip_fclose(zf);
+ buffer[n] = 0;
+ RETURN_STRINGL(buffer, n, 0);
+}
+/* }}} */
+
+/* {{{ proto string ZipArchive::getFromName(string entryname[, int len [, int flags]])
+get the contents of an entry using its name */
+static ZIPARCHIVE_METHOD(getFromName)
+{
+ php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ proto string ZipArchive::getFromIndex(int index[, int len [, int flags]])
+get the contents of an entry using its index */
+static ZIPARCHIVE_METHOD(getFromIndex)
+{
+ php_zip_get_from(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ proto resource ZipArchive::getStream(string entryname)
+get a stream for an entry using its name */
+static ZIPARCHIVE_METHOD(getStream)
+{
+ struct zip *intern;
+ zval *this = getThis();
+ struct zip_stat sb;
+ char *filename;
+ int filename_len;
+ char *mode = "rb";
+ php_stream *stream;
+ ze_zip_object *obj;
+
+ if (!this) {
+ RETURN_FALSE;
+ }
+
+ ZIP_FROM_OBJECT(intern, this);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
+ return;
+ }
+
+ if (zip_stat(intern, filename, 0, &sb) != 0) {
+ RETURN_FALSE;
+ }
+
+ obj = (ze_zip_object*) zend_object_store_get_object(this TSRMLS_CC);
+
+ stream = php_stream_zip_open(obj->filename, filename, mode STREAMS_CC TSRMLS_CC);
+ if (stream) {
+ php_stream_to_zval(stream, return_value);
+ }
+}
+/* }}} */
+
+/* {{{ arginfo */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_open, 0, 0, 1)
+ ZEND_ARG_INFO(0, filename)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_ziparchive__void, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addemptydir, 0, 0, 1)
+ ZEND_ARG_INFO(0, dirname)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addglob, 0, 0, 1)
+ ZEND_ARG_INFO(0, pattern)
+ ZEND_ARG_INFO(0, flags)
+ ZEND_ARG_INFO(0, options)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addpattern, 0, 0, 1)
+ ZEND_ARG_INFO(0, pattern)
+ ZEND_ARG_INFO(0, path)
+ ZEND_ARG_INFO(0, options)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addfile, 0, 0, 1)
+ ZEND_ARG_INFO(0, filepath)
+ ZEND_ARG_INFO(0, entryname)
+ ZEND_ARG_INFO(0, start)
+ ZEND_ARG_INFO(0, length)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_addfromstring, 0, 0, 2)
+ ZEND_ARG_INFO(0, name)
+ ZEND_ARG_INFO(0, content)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_statname, 0, 0, 1)
+ ZEND_ARG_INFO(0, filename)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_statindex, 0, 0, 1)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setarchivecomment, 0, 0, 1)
+ ZEND_ARG_INFO(0, comment)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcommentindex, 0, 0, 2)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, comment)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getcommentname, 0, 0, 1)
+ ZEND_ARG_INFO(0, name)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getcommentindex, 0, 0, 1)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_renameindex, 0, 0, 2)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, new_name)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_renamename, 0, 0, 2)
+ ZEND_ARG_INFO(0, name)
+ ZEND_ARG_INFO(0, new_name)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_unchangeindex, 0, 0, 1)
+ ZEND_ARG_INFO(0, index)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_unchangename, 0, 0, 1)
+ ZEND_ARG_INFO(0, name)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_extractto, 0, 0, 1)
+ ZEND_ARG_INFO(0, pathto)
+ ZEND_ARG_INFO(0, files)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getfromname, 0, 0, 1)
+ ZEND_ARG_INFO(0, entryname)
+ ZEND_ARG_INFO(0, len)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getfromindex, 0, 0, 1)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, len)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getarchivecomment, 0, 0, 0)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcommentname, 0, 0, 2)
+ ZEND_ARG_INFO(0, name)
+ ZEND_ARG_INFO(0, comment)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getstream, 0, 0, 1)
+ ZEND_ARG_INFO(0, entryname)
+ZEND_END_ARG_INFO()
+/* }}} */
+
+/* {{{ ze_zip_object_class_functions */
+static const zend_function_entry zip_class_functions[] = {
+ ZIPARCHIVE_ME(open, arginfo_ziparchive_open, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(close, arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(getStatusString, arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(addEmptyDir, arginfo_ziparchive_addemptydir, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(addFromString, arginfo_ziparchive_addfromstring, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(addFile, arginfo_ziparchive_addfile, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(addGlob, arginfo_ziparchive_addglob, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(addPattern, arginfo_ziparchive_addpattern, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(renameIndex, arginfo_ziparchive_renameindex, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(renameName, arginfo_ziparchive_renamename, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(setArchiveComment, arginfo_ziparchive_setarchivecomment, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(getArchiveComment, arginfo_ziparchive_getarchivecomment, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(setCommentIndex, arginfo_ziparchive_setcommentindex, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(setCommentName, arginfo_ziparchive_setcommentname, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(getCommentIndex, arginfo_ziparchive_getcommentindex, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(getCommentName, arginfo_ziparchive_getcommentname, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(deleteIndex, arginfo_ziparchive_unchangeindex, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(deleteName, arginfo_ziparchive_unchangename, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(statName, arginfo_ziparchive_statname, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(statIndex, arginfo_ziparchive_statindex, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(locateName, arginfo_ziparchive_statname, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(getNameIndex, arginfo_ziparchive_statindex, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(unchangeArchive, arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(unchangeAll, arginfo_ziparchive__void, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(unchangeIndex, arginfo_ziparchive_unchangeindex, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(unchangeName, arginfo_ziparchive_unchangename, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(extractTo, arginfo_ziparchive_extractto, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(getFromName, arginfo_ziparchive_getfromname, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(getFromIndex, arginfo_ziparchive_getfromindex, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(getStream, arginfo_ziparchive_getstream, ZEND_ACC_PUBLIC)
+ {NULL, NULL, NULL}
+};
+/* }}} */
+#endif
+
+/* {{{ PHP_MINIT_FUNCTION */
+static PHP_MINIT_FUNCTION(zip)
+{
+#ifdef PHP_ZIP_USE_OO
+ zend_class_entry ce;
+
+ memcpy(&zip_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ zip_object_handlers.clone_obj = NULL;
+ zip_object_handlers.get_property_ptr_ptr = php_zip_get_property_ptr_ptr;
+
+ zip_object_handlers.get_properties = php_zip_get_properties;
+ zip_object_handlers.read_property = php_zip_read_property;
+ zip_object_handlers.has_property = php_zip_has_property;
+
+ INIT_CLASS_ENTRY(ce, "ZipArchive", zip_class_functions);
+ ce.create_object = php_zip_object_new;
+ zip_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
+
+ zend_hash_init(&zip_prop_handlers, 0, NULL, NULL, 1);
+ php_zip_register_prop_handler(&zip_prop_handlers, "status", php_zip_status, NULL, NULL, IS_LONG TSRMLS_CC);
+ php_zip_register_prop_handler(&zip_prop_handlers, "statusSys", php_zip_status_sys, NULL, NULL, IS_LONG TSRMLS_CC);
+ php_zip_register_prop_handler(&zip_prop_handlers, "numFiles", php_zip_get_num_files, NULL, NULL, IS_LONG TSRMLS_CC);
+ php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, NULL, php_zipobj_get_filename, IS_STRING TSRMLS_CC);
+ php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, NULL, IS_STRING TSRMLS_CC);
+
+ REGISTER_ZIP_CLASS_CONST_LONG("CREATE", ZIP_CREATE);
+ REGISTER_ZIP_CLASS_CONST_LONG("EXCL", ZIP_EXCL);
+ REGISTER_ZIP_CLASS_CONST_LONG("CHECKCONS", ZIP_CHECKCONS);
+ REGISTER_ZIP_CLASS_CONST_LONG("OVERWRITE", ZIP_OVERWRITE);
+
+ REGISTER_ZIP_CLASS_CONST_LONG("FL_NOCASE", ZIP_FL_NOCASE);
+ REGISTER_ZIP_CLASS_CONST_LONG("FL_NODIR", ZIP_FL_NODIR);
+ REGISTER_ZIP_CLASS_CONST_LONG("FL_COMPRESSED", ZIP_FL_COMPRESSED);
+ REGISTER_ZIP_CLASS_CONST_LONG("FL_UNCHANGED", ZIP_FL_UNCHANGED);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFAULT", ZIP_CM_DEFAULT);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_STORE", ZIP_CM_STORE);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_SHRINK", ZIP_CM_SHRINK);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_1", ZIP_CM_REDUCE_1);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_2", ZIP_CM_REDUCE_2);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_3", ZIP_CM_REDUCE_3);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_REDUCE_4", ZIP_CM_REDUCE_4);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_IMPLODE", ZIP_CM_IMPLODE);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE", ZIP_CM_DEFLATE);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFLATE64", ZIP_CM_DEFLATE64);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_PKWARE_IMPLODE", ZIP_CM_PKWARE_IMPLODE);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_BZIP2", ZIP_CM_BZIP2);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_LZMA", ZIP_CM_LZMA);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_TERSE", ZIP_CM_TERSE);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_LZ77", ZIP_CM_LZ77);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_WAVPACK", ZIP_CM_WAVPACK);
+ REGISTER_ZIP_CLASS_CONST_LONG("CM_PPMD", ZIP_CM_PPMD);
+
+ /* Error code */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_OK", ZIP_ER_OK); /* N No error */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_MULTIDISK", ZIP_ER_MULTIDISK); /* N Multi-disk zip archives not supported */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_RENAME", ZIP_ER_RENAME); /* S Renaming temporary file failed */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_CLOSE", ZIP_ER_CLOSE); /* S Closing zip archive failed */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_SEEK", ZIP_ER_SEEK); /* S Seek error */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_READ", ZIP_ER_READ); /* S Read error */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_WRITE", ZIP_ER_WRITE); /* S Write error */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_CRC", ZIP_ER_CRC); /* N CRC error */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_ZIPCLOSED", ZIP_ER_ZIPCLOSED); /* N Containing zip archive was closed */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_NOENT", ZIP_ER_NOENT); /* N No such file */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_EXISTS", ZIP_ER_EXISTS); /* N File already exists */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_OPEN", ZIP_ER_OPEN); /* S Can't open file */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_TMPOPEN", ZIP_ER_TMPOPEN); /* S Failure to create temporary file */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_ZLIB", ZIP_ER_ZLIB); /* Z Zlib error */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_MEMORY", ZIP_ER_MEMORY); /* N Malloc failure */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_CHANGED", ZIP_ER_CHANGED); /* N Entry has been changed */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_COMPNOTSUPP", ZIP_ER_COMPNOTSUPP);/* N Compression method not supported */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_EOF", ZIP_ER_EOF); /* N Premature EOF */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_INVAL", ZIP_ER_INVAL); /* N Invalid argument */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_NOZIP", ZIP_ER_NOZIP); /* N Not a zip archive */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_INTERNAL", ZIP_ER_INTERNAL); /* N Internal error */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_INCONS", ZIP_ER_INCONS); /* N Zip archive inconsistent */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_REMOVE", ZIP_ER_REMOVE); /* S Can't remove file */
+ REGISTER_ZIP_CLASS_CONST_LONG("ER_DELETED", ZIP_ER_DELETED); /* N Entry has been deleted */
+
+ php_register_url_stream_wrapper("zip", &php_stream_zip_wrapper TSRMLS_CC);
+#endif
+
+ le_zip_dir = zend_register_list_destructors_ex(php_zip_free_dir, NULL, le_zip_dir_name, module_number);
+ le_zip_entry = zend_register_list_destructors_ex(php_zip_free_entry, NULL, le_zip_entry_name, module_number);
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+static PHP_MSHUTDOWN_FUNCTION(zip)
+{
+#ifdef PHP_ZIP_USE_OO
+ zend_hash_destroy(&zip_prop_handlers);
+ php_unregister_url_stream_wrapper("zip" TSRMLS_CC);
+#endif
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+static PHP_MINFO_FUNCTION(zip)
+{
+ php_info_print_table_start();
+
+ php_info_print_table_row(2, "Zip", "enabled");
+ php_info_print_table_row(2, "Extension Version","$Id: 727cc853ca1ae15d995c3520c5719784ddc1e292 $");
+ php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION_STRING);
+ php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION);
+
+ php_info_print_table_end();
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */