summaryrefslogtreecommitdiff
path: root/ext/zip/php_zip.c
diff options
context:
space:
mode:
authorPierre Joye <pajoye@php.net>2008-10-23 16:13:51 +0000
committerPierre Joye <pajoye@php.net>2008-10-23 16:13:51 +0000
commit047bda3cb82c5b398a610e28433487bd87609383 (patch)
tree1c719997f4a570e2ba10a958d72b7e22468caa51 /ext/zip/php_zip.c
parent8d916b2ec6ec5be8fe68a1461af87d14826a425a (diff)
downloadphp-git-047bda3cb82c5b398a610e28433487bd87609383.tar.gz
- MFH
- Update ziplib - flatten path and make them relative before extraction - remove unnecessary export
Diffstat (limited to 'ext/zip/php_zip.c')
-rw-r--r--ext/zip/php_zip.c357
1 files changed, 261 insertions, 96 deletions
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index 0dcbf2a8a7..e6fb77511e 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -79,81 +79,152 @@ static int le_zip_entry;
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 creating a relative path (to .) */
+static char * php_zip_make_relative_path(char *path, int path_len) /* {{{ */
+{
+ char *path_begin = path;
+ int prev_is_slash = 0;
+ char *e = path + path_len - 1;
+ size_t pos = path_len - 1;
+ 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;
+}
/* }}} */
/* {{{ php_zip_extract_file */
-/* TODO: Simplify it */
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;
- if (file_len >= MAXPATHLEN || zip_stat(za, file, 0, &sb) != 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);
+ path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length);
+ path_cleaned_len = strlen(path_cleaned);
+
+ if (path_cleaned_len >= MAXPATHLEN || zip_stat(za, file, 0, &sb) != 0) {
return 0;
}
- if (file_len > 1 && file[file_len - 1] == '/') {
+ /* 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, file, file_len);
- dir_len = php_dirname(file_dirname, file_len);
+ memcpy(file_dirname, path_cleaned, path_cleaned_len);
+ dir_len = php_dirname(file_dirname, path_cleaned_len);
- if (dir_len > 0) {
- len = spprintf(&file_dirname_fullpath, 0, "%s/%s", dest, file_dirname);
- } else {
+ 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(file, file_len, NULL, 0, &file_basename, (size_t *)&file_basename_len TSRMLS_CC);
+ php_basename(path_cleaned, path_cleaned_len, NULL, 0, &file_basename, (unsigned int *)&file_basename_len TSRMLS_CC);
if (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(file_dirname_fullpath, &ssb) < 0) {
- ret = php_stream_mkdir(file_dirname_fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
+
+#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 (file[file_len - 1] == '/') {
+ if (is_dir_only) {
efree(file_dirname_fullpath);
- if (!is_dir_only) {
- efree(file_basename);
- }
+ free(new_state.cwd);
return 1;
}
- len = spprintf(&fullpath, 0, "%s/%s/%s", dest, file_dirname, file_basename);
+ 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);
}
/* check again the full path, not sure if it
@@ -164,6 +235,7 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
efree(fullpath);
efree(file_dirname_fullpath);
efree(file_basename);
+ free(new_state.cwd);
return 0;
}
@@ -172,10 +244,15 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
efree(fullpath);
efree(file_dirname_fullpath);
efree(file_basename);
+ free(new_state.cwd);
return 0;
}
+#if (PHP_MAJOR_VERSION < 6)
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
n = 0;
if (stream) {
while ((n=zip_fread(zf, b, sizeof(b))) > 0) php_stream_write(stream, b, n);
@@ -186,6 +263,7 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
efree(fullpath);
efree(file_basename);
efree(file_dirname_fullpath);
+ free(new_state.cwd);
if (n<0) {
return 0;
@@ -195,6 +273,111 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
}
/* }}} */
+static int php_zip_add_file(struct zip *za, const char *filename, int filename_len,
+ char *entry_name, int entry_name_len, long offset_start, long offset_len TSRMLS_DC) /* {{{ */
+{
+ struct zip_source *zs;
+ int cur_idx;
+ char resolved_path[MAXPATHLEN];
+
+
+ if (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);
@@ -216,13 +399,13 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, int fil
#define RETURN_SB(sb) \
{ \
array_init(return_value); \
- add_assoc_string(return_value, "name", (char *)(sb)->name, 1); \
- add_assoc_long(return_value, "index", (long) (sb)->index); \
- add_assoc_long(return_value, "crc", (long) (sb)->crc); \
- add_assoc_long(return_value, "size", (long) (sb)->size); \
- add_assoc_long(return_value, "mtime", (long) (sb)->mtime); \
- add_assoc_long(return_value, "comp_size", (long) (sb)->comp_size); \
- add_assoc_long(return_value, "comp_method", (long) (sb)->comp_method); \
+ 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); \
}
/* }}} */
@@ -290,6 +473,7 @@ static zend_function_entry zip_functions[] = {
/* }}} */
/* {{{ ZE2 OO definitions */
+#ifdef ZEND_ENGINE_2_1
static zend_class_entry *zip_class_entry;
static zend_object_handlers zip_object_handlers;
@@ -306,8 +490,10 @@ typedef struct _zip_prop_handler {
int type;
} zip_prop_handler;
+#endif
/* }}} */
+#ifdef ZEND_ENGINE_2_1
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;
@@ -434,7 +620,7 @@ static zval* php_zip_read_property(zval *object, zval *member, int type TSRMLS_D
ret = php_zip_property_reader(obj, hnd, &retval, 1 TSRMLS_CC);
if (ret == SUCCESS) {
/* ensure we're creating a temporary variable */
- retval->refcount = 0;
+ Z_SET_REFCOUNT_P(retval, 0);
} else {
retval = EG(uninitialized_zval_ptr);
}
@@ -478,8 +664,8 @@ static int php_zip_has_property(zval *object, zval *member, int type TSRMLS_DC)
if (type == 2) {
retval = 1;
} else if (php_zip_property_reader(obj, hnd, &tmp, 1 TSRMLS_CC) == SUCCESS) {
- tmp->refcount = 1;
- tmp->is_ref = 0;
+ Z_SET_REFCOUNT_P(tmp, 1);
+ Z_UNSET_ISREF_P(tmp);
if (type == 1) {
retval = zend_is_true(tmp);
} else if (type == 0) {
@@ -580,7 +766,14 @@ static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_
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
+
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,
(void *) &tmp, sizeof(zval *));
@@ -594,6 +787,7 @@ static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_
return retval;
}
/* }}} */
+#endif
/* {{{ Resource dtors */
@@ -636,7 +830,7 @@ static void php_zip_free_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC)
/* }}}*/
/* reset macro */
-#undef zip
+
/* {{{ function prototypes */
static PHP_MINIT_FUNCTION(zip);
static PHP_MSHUTDOWN_FUNCTION(zip);
@@ -654,7 +848,7 @@ zend_module_entry zip_module_entry = {
NULL,
NULL,
PHP_MINFO(zip),
- "2.0.0",
+ PHP_ZIP_VERSION_STRING,
STANDARD_MODULE_PROPERTIES
};
/* }}} */
@@ -663,7 +857,6 @@ zend_module_entry zip_module_entry = {
ZEND_GET_MODULE(zip)
#endif
/* set macro */
-#define zip php_ziplib__zip
/* {{{ proto resource zip_open(string filename)
Create new zip using source uri for output */
@@ -694,7 +887,7 @@ static PHP_NAMED_FUNCTION(zif_zip_open)
rsrc_int = (zip_rsrc *)emalloc(sizeof(zip_rsrc));
- rsrc_int->za = zip_open(filename, 0, &err);
+ rsrc_int->za = zip_open(resolved_path, 0, &err);
if (rsrc_int->za == NULL) {
efree(rsrc_int);
RETURN_LONG((long)err);
@@ -749,7 +942,7 @@ static PHP_NAMED_FUNCTION(zif_zip_read)
if (ret != 0) {
efree(zr_rsrc);
- RETURN_LONG((long)ret);
+ RETURN_FALSE;
}
zr_rsrc->zf = zip_fopen_index(rsrc_int->za, rsrc_int->index_current, 0);
@@ -944,6 +1137,7 @@ static PHP_NAMED_FUNCTION(zif_zip_entry_compressionmethod)
}
/* }}} */
+#ifdef ZEND_ENGINE_2_1
/* {{{ 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)
@@ -991,6 +1185,7 @@ static ZIPARCHIVE_METHOD(open)
efree(ze_obj->filename);
ze_obj->filename = NULL;
}
+
intern = zip_open(resolved_path, flags, &err);
if (!intern || err) {
RETURN_LONG((long)err);
@@ -1031,6 +1226,28 @@ static ZIPARCHIVE_METHOD(close)
}
/* }}} */
+/* {{{ 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)
@@ -1071,17 +1288,10 @@ static ZIPARCHIVE_METHOD(addEmptyDir)
if (idx >= 0) {
RETVAL_FALSE;
} else {
- /* reset the error */
- if (intern->error.str) {
- _zip_error_fini(&intern->error);
- }
- _zip_error_init(&intern->error);
-
if (zip_add_dir(intern, (const char *)s) == -1) {
RETVAL_FALSE;
- } else {
- RETVAL_TRUE;
}
+ RETVAL_TRUE;
}
if (s != dirname) {
@@ -1100,10 +1310,7 @@ static ZIPARCHIVE_METHOD(addFile)
int filename_len;
char *entry_name = NULL;
int entry_name_len = 0;
- struct zip_source *zs;
long offset_start = 0, offset_len = 0;
- int cur_idx;
- char resolved_path[MAXPATHLEN];
if (!this) {
RETURN_FALSE;
@@ -1126,35 +1333,8 @@ static ZIPARCHIVE_METHOD(addFile)
entry_name_len = filename_len;
}
- if (OPENBASEDIR_CHECKPATH(filename)) {
- RETURN_FALSE;
- }
-
- if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
- RETURN_FALSE;
- }
-
- zs = zip_source_file(intern, resolved_path, 0, 0);
- if (!zs) {
- RETURN_FALSE;
- }
-
- cur_idx = zip_name_locate(intern, (const char *)entry_name, 0);
- /* TODO: fix _zip_replace */
- if (cur_idx<0) {
- /* reset the error */
- if (intern->error.str) {
- _zip_error_fini(&intern->error);
- }
- _zip_error_init(&intern->error);
-
- } else {
- if (zip_delete(intern, cur_idx) == -1) {
- RETURN_FALSE;
- }
- }
-
- if (zip_add(intern, entry_name, zs) == -1) {
+ if (php_zip_add_file(intern, filename, filename_len,
+ entry_name, entry_name_len, 0, 0 TSRMLS_CC) < 0) {
RETURN_FALSE;
} else {
RETURN_TRUE;
@@ -1206,14 +1386,7 @@ static ZIPARCHIVE_METHOD(addFromString)
cur_idx = zip_name_locate(intern, (const char *)name, 0);
/* TODO: fix _zip_replace */
- if (cur_idx<0) {
- /* reset the error */
- if (intern->error.str) {
- _zip_error_fini(&intern->error);
- }
- _zip_error_init(&intern->error);
-
- } else {
+ if (cur_idx >= 0) {
if (zip_delete(intern, cur_idx) == -1) {
RETURN_FALSE;
}
@@ -1310,15 +1483,10 @@ static ZIPARCHIVE_METHOD(locateName)
idx = (long)zip_name_locate(intern, (const char *)name, flags);
- if (idx<0) {
- /* reset the error */
- if (intern->error.str) {
- _zip_error_fini(&intern->error);
- }
- _zip_error_init(&intern->error);
- RETURN_FALSE;
- } else {
+ if (idx >= 0) {
RETURN_LONG(idx);
+ } else {
+ RETURN_FALSE;
}
}
/* }}} */
@@ -1979,6 +2147,7 @@ static ZIPARCHIVE_METHOD(getStream)
static zend_function_entry zip_class_functions[] = {
ZIPARCHIVE_ME(open, NULL, ZEND_ACC_PUBLIC)
ZIPARCHIVE_ME(close, NULL, ZEND_ACC_PUBLIC)
+ ZIPARCHIVE_ME(getStatusString, NULL, ZEND_ACC_PUBLIC)
ZIPARCHIVE_ME(addEmptyDir, NULL, ZEND_ACC_PUBLIC)
ZIPARCHIVE_ME(addFromString, NULL, ZEND_ACC_PUBLIC)
ZIPARCHIVE_ME(addFile, NULL, ZEND_ACC_PUBLIC)
@@ -2007,11 +2176,10 @@ static zend_function_entry zip_class_functions[] = {
{NULL, NULL, NULL}
};
/* }}} */
+#endif
/* {{{ PHP_MINIT_FUNCTION */
-#undef zip
static PHP_MINIT_FUNCTION(zip)
-#define zip php_ziplib__zip
{
zend_class_entry ce;
@@ -2092,9 +2260,7 @@ static PHP_MINIT_FUNCTION(zip)
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
-#undef zip
static PHP_MSHUTDOWN_FUNCTION(zip)
-#define zip php_ziplib__zip
{
zend_hash_destroy(&zip_prop_handlers);
php_unregister_url_stream_wrapper("zip" TSRMLS_CC);
@@ -2105,7 +2271,6 @@ static PHP_MSHUTDOWN_FUNCTION(zip)
/* {{{ PHP_MINFO_FUNCTION
*/
-#undef zip
static PHP_MINFO_FUNCTION(zip)
{
php_info_print_table_start();
@@ -2113,7 +2278,7 @@ static PHP_MINFO_FUNCTION(zip)
php_info_print_table_row(2, "Zip", "enabled");
php_info_print_table_row(2, "Extension Version","$Id$");
php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION_STRING);
- php_info_print_table_row(2, "Libzip version", "0.8.0-compatible");
+ php_info_print_table_row(2, "Libzip version", "0.9.0");
php_info_print_table_end();
}