diff options
Diffstat (limited to 'ext/zip/php_zip.c')
-rw-r--r-- | ext/zip/php_zip.c | 1807 |
1 files changed, 909 insertions, 898 deletions
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 21182068d1..6875850687 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -1,7 +1,5 @@ /* +----------------------------------------------------------------------+ - | PHP Version 7 | - +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | @@ -30,18 +28,7 @@ #include "ext/standard/php_filestat.h" #include "zend_interfaces.h" #include "php_zip.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); +#include "php_zip_arginfo.h" #ifdef HAVE_GLOB #ifndef PHP_WIN32 @@ -65,11 +52,12 @@ static int le_zip_entry; } /* }}} */ -/* {{{ PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) */ +/* {{{ PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) + This is always used for the first argument*/ #define PHP_ZIP_STAT_PATH(za, path, path_len, flags, sb) \ - if (path_len < 1) { \ - php_error_docref(NULL, E_NOTICE, "Empty string as entry name"); \ - RETURN_FALSE; \ + if (path_len == 0) { \ + zend_argument_value_error(1, "cannot be empty"); \ + RETURN_THROWS(); \ } \ if (zip_stat(za, path, flags, &sb) != 0) { \ RETURN_FALSE; \ @@ -259,6 +247,13 @@ static int php_zip_extract_file(struct zip * za, char *dest, char *file, size_t php_stream_write(stream, b, n); } + if (stream->wrapper->wops->stream_metadata) { + struct utimbuf ut; + + ut.modtime = ut.actime = sb.mtime; + stream->wrapper->wops->stream_metadata(stream->wrapper, fullpath, PHP_STREAM_META_TOUCH, &ut, NULL); + } + php_stream_close(stream); n = zip_fclose(zf); @@ -276,8 +271,12 @@ done: } /* }}} */ -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) /* {{{ */ +static int php_zip_add_file(ze_zip_object *obj, const char *filename, size_t filename_len, + char *entry_name, size_t entry_name_len, /* unused if replace >= 0 */ + zip_uint64_t offset_start, zip_uint64_t offset_len, + zend_long replace, /* index to replace, add new file if < 0 */ + zip_flags_t flags +) /* {{{ */ { struct zip_source *zs; char resolved_path[MAXPATHLEN]; @@ -289,75 +288,160 @@ static int php_zip_add_file(struct zip *za, const char *filename, size_t filenam } if (!expand_filepath(filename, resolved_path)) { + php_error_docref(NULL, E_WARNING, "No such file or directory"); return -1; } php_stat(resolved_path, strlen(resolved_path), FS_EXISTS, &exists_flag); if (Z_TYPE(exists_flag) == IS_FALSE) { + php_error_docref(NULL, E_WARNING, "No such file or directory"); return -1; } - zs = zip_source_file(za, resolved_path, offset_start, offset_len); + zs = zip_source_file(obj->za, resolved_path, offset_start, offset_len); if (!zs) { return -1; } - if (zip_file_add(za, entry_name, zs, ZIP_FL_OVERWRITE) < 0) { + /* Replace */ + if (replace >= 0) { + if (zip_file_replace(obj->za, replace, zs, flags) < 0) { + zip_source_free(zs); + return -1; + } + zip_error_clear(obj->za); + return 1; + } + /* Add */ + obj->last_id = zip_file_add(obj->za, entry_name, zs, flags); + if (obj->last_id < 0) { zip_source_free(zs); return -1; - } else { - zip_error_clear(za); - return 1; } + zip_error_clear(obj->za); + return 1; } /* }}} */ -static int php_zip_parse_options(zval *options, zend_long *remove_all_path, char **remove_path, size_t *remove_path_len, char **add_path, size_t *add_path_len) /* {{{ */ +typedef struct { + zend_long remove_all_path; + char *remove_path; + size_t remove_path_len; + char *add_path; + size_t add_path_len; + zip_flags_t flags; + zip_int32_t comp_method; + zip_uint32_t comp_flags; +#ifdef HAVE_ENCRYPTION + zip_int16_t enc_method; + char *enc_password; +#endif +} zip_options; + +static int php_zip_parse_options(HashTable *options, zip_options *opts) +/* {{{ */ { zval *option; - if ((option = zend_hash_str_find(Z_ARRVAL_P(options), "remove_all_path", sizeof("remove_all_path") - 1)) != NULL) { - *remove_all_path = zval_get_long(option); + + /* default values */ + memset(opts, 0, sizeof(zip_options)); + opts->flags = ZIP_FL_OVERWRITE; + opts->comp_method = -1; /* -1 to not change default */ +#ifdef HAVE_ENCRYPTION + opts->enc_method = -1; /* -1 to not change default */ +#endif + + if ((option = zend_hash_str_find(options, "remove_all_path", sizeof("remove_all_path") - 1)) != NULL) { + if (Z_TYPE_P(option) != IS_FALSE && Z_TYPE_P(option) != IS_TRUE) { + php_error_docref(NULL, E_WARNING, "Option \"remove_all_path\" must be of type bool, %s given", + zend_zval_type_name(option)); + } + opts->remove_all_path = zval_get_long(option); + } + + if ((option = zend_hash_str_find(options, "comp_method", sizeof("comp_method") - 1)) != NULL) { + if (Z_TYPE_P(option) != IS_LONG) { + php_error_docref(NULL, E_WARNING, "Option \"comp_method\" must be of type int, %s given", + zend_zval_type_name(option)); + } + opts->comp_method = zval_get_long(option); + + if ((option = zend_hash_str_find(options, "comp_flags", sizeof("comp_flags") - 1)) != NULL) { + if (Z_TYPE_P(option) != IS_LONG) { + php_error_docref(NULL, E_WARNING, "Option \"comp_flags\" must be of type int, %s given", + zend_zval_type_name(option)); + } + opts->comp_flags = zval_get_long(option); + } + } + +#ifdef HAVE_ENCRYPTION + if ((option = zend_hash_str_find(options, "enc_method", sizeof("enc_method") - 1)) != NULL) { + if (Z_TYPE_P(option) != IS_LONG) { + php_error_docref(NULL, E_WARNING, "Option \"enc_method\" must be of type int, %s given", + zend_zval_type_name(option)); + } + opts->enc_method = zval_get_long(option); + + if ((option = zend_hash_str_find(options, "enc_password", sizeof("enc_password") - 1)) != NULL) { + if (Z_TYPE_P(option) != IS_STRING) { + zend_type_error("Option \"enc_password\" must be of type string, %s given", + zend_zval_type_name(option)); + return -1; + } + opts->enc_password = Z_STRVAL_P(option); + } } +#endif - /* If I add more options, it would make sense to create a nice static struct and loop over it. */ - if ((option = zend_hash_str_find(Z_ARRVAL_P(options), "remove_path", sizeof("remove_path") - 1)) != NULL) { + if ((option = zend_hash_str_find(options, "remove_path", sizeof("remove_path") - 1)) != NULL) { if (Z_TYPE_P(option) != IS_STRING) { - php_error_docref(NULL, E_WARNING, "remove_path option expected to be a string"); + zend_type_error("Option \"remove_path\" must be of type string, %s given", + zend_zval_type_name(option)); return -1; } - if (Z_STRLEN_P(option) < 1) { - php_error_docref(NULL, E_NOTICE, "Empty string given as remove_path option"); + if (Z_STRLEN_P(option) == 0) { + zend_value_error("Option \"remove_path\" cannot be empty"); return -1; } if (Z_STRLEN_P(option) >= MAXPATHLEN) { - php_error_docref(NULL, E_WARNING, "remove_path string is too long (max: %d, %zd given)", - MAXPATHLEN - 1, Z_STRLEN_P(option)); + zend_value_error("Option \"remove_path\" must be less than %d bytes", MAXPATHLEN - 1); return -1; } - *remove_path_len = Z_STRLEN_P(option); - *remove_path = Z_STRVAL_P(option); + opts->remove_path_len = Z_STRLEN_P(option); + opts->remove_path = Z_STRVAL_P(option); } - if ((option = zend_hash_str_find(Z_ARRVAL_P(options), "add_path", sizeof("add_path") - 1)) != NULL) { + if ((option = zend_hash_str_find(options, "add_path", sizeof("add_path") - 1)) != NULL) { if (Z_TYPE_P(option) != IS_STRING) { - php_error_docref(NULL, E_WARNING, "add_path option expected to be a string"); + zend_type_error("Option \"add_path\" must be of type string, %s given", + zend_zval_type_name(option)); return -1; } - if (Z_STRLEN_P(option) < 1) { - php_error_docref(NULL, E_NOTICE, "Empty string given as the add_path option"); + if (Z_STRLEN_P(option) == 0) { + zend_value_error("Option \"add_path\" cannot be empty"); return -1; } if (Z_STRLEN_P(option) >= MAXPATHLEN) { - php_error_docref(NULL, E_WARNING, "add_path string too long (max: %d, %zd given)", - MAXPATHLEN - 1, Z_STRLEN_P(option)); + zend_value_error("Option \"add_path\" must be less than %d bytes", MAXPATHLEN - 1); return -1; } - *add_path_len = Z_STRLEN_P(option); - *add_path = Z_STRVAL_P(option); + opts->add_path_len = Z_STRLEN_P(option); + opts->add_path = Z_STRVAL_P(option); } + + if ((option = zend_hash_str_find(options, "flags", sizeof("flags") - 1)) != NULL) { + if (Z_TYPE_P(option) != IS_LONG) { + zend_type_error("Option \"flags\" must be of type int, %s given", + zend_zval_type_name(option)); + return -1; + } + opts->flags = Z_LVAL_P(option); + } + return 1; } /* }}} */ @@ -373,8 +457,8 @@ static int php_zip_parse_options(zval *options, zend_long *remove_all_path, char ze_zip_object *obj = Z_ZIP_P(object); \ intern = obj->za; \ if (!intern) { \ - php_error_docref(NULL, E_WARNING, "Invalid or uninitialized Zip object"); \ - RETURN_FALSE; \ + zend_value_error("Invalid or uninitialized Zip object"); \ + RETURN_THROWS(); \ } \ } /* }}} */ @@ -408,67 +492,78 @@ static int php_zip_parse_options(zval *options, zend_long *remove_all_path, char #endif /* }}} */ -static zend_long php_zip_status(struct zip *za) /* {{{ */ +static zend_long php_zip_status(ze_zip_object *obj) /* {{{ */ { + int zep = obj->err_zip; /* saved err if closed */ + + if (obj->za) { #if LIBZIP_VERSION_MAJOR < 1 - int zep, syp; + int syp; - zip_error_get(za, &zep, &syp); + zip_error_get(obj->za, &zep, &syp); #else - int zep; - zip_error_t *err; + zip_error_t *err; - err = zip_get_error(za); - zep = zip_error_code_zip(err); - zip_error_fini(err); + err = zip_get_error(obj->za); + zep = zip_error_code_zip(err); + zip_error_fini(err); #endif + } return zep; } /* }}} */ -static zend_long php_zip_status_sys(struct zip *za) /* {{{ */ +static zend_long php_zip_last_id(ze_zip_object *obj) /* {{{ */ +{ + return obj->last_id; +} +/* }}} */ + +static zend_long php_zip_status_sys(ze_zip_object *obj) /* {{{ */ { + int syp = obj->err_sys; /* saved err if closed */ + + if (obj->za) { #if LIBZIP_VERSION_MAJOR < 1 - int zep, syp; + int zep; - zip_error_get(za, &zep, &syp); + zip_error_get(obj->za, &zep, &syp); #else - int syp; - zip_error_t *err; + zip_error_t *err; - err = zip_get_error(za); - syp = zip_error_code_system(err); - zip_error_fini(err); + err = zip_get_error(obj->za); + syp = zip_error_code_system(err); + zip_error_fini(err); #endif + } return syp; } /* }}} */ -static zend_long php_zip_get_num_files(struct zip *za) /* {{{ */ +static zend_long php_zip_get_num_files(ze_zip_object *obj) /* {{{ */ { - zip_int64_t num = zip_get_num_entries(za, 0); - return MIN(num, ZEND_LONG_MAX); + if (obj->za) { + zip_int64_t num = zip_get_num_entries(obj->za, 0); + return MIN(num, ZEND_LONG_MAX); + } + return 0; } /* }}} */ -static char * php_zipobj_get_filename(ze_zip_object *obj) /* {{{ */ +static char * php_zipobj_get_filename(ze_zip_object *obj, int *len) /* {{{ */ { - - if (!obj) { - return NULL; - } - - if (obj->filename) { + if (obj && obj->filename) { + *len = strlen(obj->filename); return obj->filename; } return NULL; } /* }}} */ -static char * php_zipobj_get_zip_comment(struct zip *za, int *len) /* {{{ */ +static char * php_zipobj_get_zip_comment(ze_zip_object *obj, int *len) /* {{{ */ { - if (za) { - return (char *)zip_get_archive_comment(za, len, 0); + if (obj->za) { + return (char *)zip_get_archive_comment(obj->za, len, 0); } return NULL; } @@ -525,6 +620,7 @@ int php_zip_glob(char *pattern, int pattern_len, zend_long flags, zval *return_v } if ((GLOB_AVAILABLE_FLAGS & flags) != flags) { + php_error_docref(NULL, E_WARNING, "At least one of the passed flags is invalid or not supported on this platform"); return -1; } @@ -714,91 +810,24 @@ int php_zip_pcre(zend_string *regexp, char *path, int path_len, zval *return_val } /* }}} */ -/* {{{ 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) -#ifdef PHP_FE_END - PHP_FE_END -#else - {NULL,NULL,NULL} -#endif -}; -/* }}} */ - /* {{{ ZE2 OO definitions */ static zend_class_entry *zip_class_entry; static zend_object_handlers zip_object_handlers; static HashTable zip_prop_handlers; -typedef zend_long (*zip_read_int_t)(struct zip *za); -typedef char *(*zip_read_const_char_t)(struct zip *za, int *len); -typedef char *(*zip_read_const_char_from_ze_t)(ze_zip_object *obj); +typedef zend_long (*zip_read_int_t)(ze_zip_object *obj); +typedef char *(*zip_read_const_char_t)(ze_zip_object *obj, int *len); 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; /* }}} */ -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) /* {{{ */ +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, int rettype) /* {{{ */ { zip_prop_handler hnd; zend_string *str; @@ -806,7 +835,6 @@ static void php_zip_register_prop_handler(HashTable *prop_handler, char *name, z 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; str = zend_string_init_interned(name, strlen(name), 1); zend_hash_add_mem(prop_handler, str, &hnd, sizeof(zip_prop_handler)); @@ -824,23 +852,10 @@ static zval *php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, zend_long 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); - } else { - if (hnd->read_int_func) { - retint = hnd->read_int_func(obj->za); - if (retint == -1) { - php_error_docref(NULL, E_WARNING, "Internal zip error returned"); - return NULL; - } - } else { - if (hnd->read_const_char_from_obj_func) { - retchar = hnd->read_const_char_from_obj_func(obj); - len = strlen(retchar); - } - } - } + if (hnd->read_const_char_func) { + retchar = hnd->read_const_char_func(obj, &len); + } else if (hnd->read_int_func) { + retint = hnd->read_int_func(obj); } switch (hnd->type) { @@ -866,62 +881,36 @@ static zval *php_zip_property_reader(ze_zip_object *obj, zip_prop_handler *hnd, } /* }}} */ -static zval *php_zip_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */ +static zval *php_zip_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot) /* {{{ */ { ze_zip_object *obj; - zval tmp_member; zval *retval = NULL; zip_prop_handler *hnd = NULL; - if (Z_TYPE_P(member) != IS_STRING) { - zend_string *str = zval_try_get_string_func(member); - if (UNEXPECTED(!str)) { - return NULL; - } - ZVAL_STR(&tmp_member, str); - member = &tmp_member; - cache_slot = NULL; - } - - obj = Z_ZIP_P(object); + obj = php_zip_fetch_object(object); if (obj->prop_handler != NULL) { - hnd = zend_hash_find_ptr(obj->prop_handler, Z_STR_P(member)); + hnd = zend_hash_find_ptr(obj->prop_handler, name); } if (hnd == NULL) { - retval = zend_std_get_property_ptr_ptr(object, member, type, cache_slot); - } - - if (member == &tmp_member) { - zval_ptr_dtor_str(&tmp_member); + retval = zend_std_get_property_ptr_ptr(object, name, type, cache_slot); } return retval; } /* }}} */ -static zval *php_zip_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */ +static zval *php_zip_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv) /* {{{ */ { ze_zip_object *obj; - zval tmp_member; zval *retval = NULL; zip_prop_handler *hnd = NULL; - if (Z_TYPE_P(member) != IS_STRING) { - zend_string *str = zval_try_get_string_func(member); - if (UNEXPECTED(!str)) { - return &EG(uninitialized_zval); - } - ZVAL_STR(&tmp_member, str); - member = &tmp_member; - cache_slot = NULL; - } - - obj = Z_ZIP_P(object); + obj = php_zip_fetch_object(object); if (obj->prop_handler != NULL) { - hnd = zend_hash_find_ptr(obj->prop_handler, Z_STR_P(member)); + hnd = zend_hash_find_ptr(obj->prop_handler, name); } if (hnd != NULL) { @@ -930,38 +919,23 @@ static zval *php_zip_read_property(zval *object, zval *member, int type, void ** retval = &EG(uninitialized_zval); } } else { - retval = zend_std_read_property(object, member, type, cache_slot, rv); - } - - if (member == &tmp_member) { - zval_ptr_dtor_str(&tmp_member); + retval = zend_std_read_property(object, name, type, cache_slot, rv); } return retval; } /* }}} */ -static int php_zip_has_property(zval *object, zval *member, int type, void **cache_slot) /* {{{ */ +static int php_zip_has_property(zend_object *object, zend_string *name, int type, void **cache_slot) /* {{{ */ { ze_zip_object *obj; - zval tmp_member; zip_prop_handler *hnd = NULL; int retval = 0; - if (Z_TYPE_P(member) != IS_STRING) { - zend_string *str = zval_try_get_string_func(member); - if (UNEXPECTED(!str)) { - return 0; - } - ZVAL_STR(&tmp_member, str); - member = &tmp_member; - cache_slot = NULL; - } - - obj = Z_ZIP_P(object); + obj = php_zip_fetch_object(object); if (obj->prop_handler != NULL) { - hnd = zend_hash_find_ptr(obj->prop_handler, Z_STR_P(member)); + hnd = zend_hash_find_ptr(obj->prop_handler, name); } if (hnd != NULL) { @@ -979,18 +953,14 @@ static int php_zip_has_property(zval *object, zval *member, int type, void **cac zval_ptr_dtor(&tmp); } else { - retval = zend_std_has_property(object, member, type, cache_slot); - } - - if (member == &tmp_member) { - zval_ptr_dtor_str(&tmp_member); + retval = zend_std_has_property(object, name, type, cache_slot); } return retval; } /* }}} */ -static HashTable *php_zip_get_gc(zval *object, zval **gc_data, int *gc_data_count) /* {{{ */ +static HashTable *php_zip_get_gc(zend_object *object, zval **gc_data, int *gc_data_count) /* {{{ */ { *gc_data = NULL; *gc_data_count = 0; @@ -998,14 +968,14 @@ static HashTable *php_zip_get_gc(zval *object, zval **gc_data, int *gc_data_coun } /* }}} */ -static HashTable *php_zip_get_properties(zval *object)/* {{{ */ +static HashTable *php_zip_get_properties(zend_object *object)/* {{{ */ { ze_zip_object *obj; HashTable *props; zip_prop_handler *hnd; zend_string *key; - obj = Z_ZIP_P(object); + obj = php_zip_fetch_object(object); props = zend_std_get_properties(object); if (obj->prop_handler == NULL) { @@ -1025,6 +995,30 @@ static HashTable *php_zip_get_properties(zval *object)/* {{{ */ } /* }}} */ +#ifdef HAVE_PROGRESS_CALLBACK +static void _php_zip_progress_callback_free(void *ptr) +{ + ze_zip_object *obj = ptr; + + if (!Z_ISUNDEF(obj->progress_callback)) { + zval_ptr_dtor(&obj->progress_callback); + ZVAL_UNDEF(&obj->progress_callback); + } +} +#endif + +#ifdef HAVE_CANCEL_CALLBACK +static void _php_zip_cancel_callback_free(void *ptr) +{ + ze_zip_object *obj = ptr; + + if (!Z_ISUNDEF(obj->cancel_callback)) { + zval_ptr_dtor(&obj->cancel_callback); + ZVAL_UNDEF(&obj->cancel_callback); + } +} +#endif + static void php_zip_object_free_storage(zend_object *object) /* {{{ */ { ze_zip_object * intern = php_zip_fetch_object(object); @@ -1035,12 +1029,8 @@ static void php_zip_object_free_storage(zend_object *object) /* {{{ */ } if (intern->za) { if (zip_close(intern->za) != 0) { -#if LIBZIP_VERSION_MAJOR == 1 && LIBZIP_VERSION_MINOR == 3 && LIBZIP_VERSION_MICRO == 1 - php_error_docref(NULL, E_WARNING, "Cannot destroy the zip context: zip_close have failed"); -#else php_error_docref(NULL, E_WARNING, "Cannot destroy the zip context: %s", zip_strerror(intern->za)); zip_discard(intern->za); -#endif } } @@ -1051,6 +1041,16 @@ static void php_zip_object_free_storage(zend_object *object) /* {{{ */ efree(intern->buffers); } +#ifdef HAVE_PROGRESS_CALLBACK + /* if not properly called by libzip */ + _php_zip_progress_callback_free(intern); +#endif + +#ifdef HAVE_CANCEL_CALLBACK + /* if not properly called by libzip */ + _php_zip_cancel_callback_free(intern); +#endif + intern->za = NULL; zend_object_std_dtor(&intern->zo); @@ -1069,6 +1069,7 @@ static zend_object *php_zip_object_new(zend_class_entry *class_type) /* {{{ */ zend_object_std_init(&intern->zo, class_type); object_properties_init(&intern->zo, class_type); intern->zo.handlers = &zip_object_handlers; + intern->last_id = -1; return &intern->zo; } @@ -1122,12 +1123,11 @@ static PHP_MSHUTDOWN_FUNCTION(zip); static PHP_MINFO_FUNCTION(zip); /* }}} */ -/* {{{ zip_module_entry - */ +/* {{{ zip_module_entry */ zend_module_entry zip_module_entry = { STANDARD_MODULE_HEADER, "zip", - zip_functions, + ext_functions, PHP_MINIT(zip), PHP_MSHUTDOWN(zip), NULL, @@ -1143,9 +1143,8 @@ 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) +/* {{{ Create new zip using source uri for output */ +PHP_FUNCTION(zip_open) { char resolved_path[MAXPATHLEN + 1]; zip_rsrc *rsrc_int; @@ -1153,12 +1152,12 @@ static PHP_NAMED_FUNCTION(zif_zip_open) zend_string *filename; if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &filename) == FAILURE) { - return; + RETURN_THROWS(); } if (ZSTR_LEN(filename) == 0) { - php_error_docref(NULL, E_WARNING, "Empty string as source"); - RETURN_FALSE; + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); } if (ZIP_OPENBASEDIR_CHECKPATH(ZSTR_VAL(filename))) { @@ -1166,6 +1165,7 @@ static PHP_NAMED_FUNCTION(zif_zip_open) } if(!expand_filepath(ZSTR_VAL(filename), resolved_path)) { + php_error_docref(NULL, E_WARNING, "No such file or directory"); RETURN_FALSE; } @@ -1184,19 +1184,18 @@ static PHP_NAMED_FUNCTION(zif_zip_open) } /* }}} */ -/* {{{ proto void zip_close(resource zip) - Close a Zip archive */ -static PHP_NAMED_FUNCTION(zif_zip_close) +/* {{{ Close a Zip archive */ +PHP_FUNCTION(zip_close) { zval * zip; zip_rsrc *z_rsrc = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip) == FAILURE) { - return; + RETURN_THROWS(); } if ((z_rsrc = (zip_rsrc *)zend_fetch_resource(Z_RES_P(zip), le_zip_dir_name, le_zip_dir)) == NULL) { - RETURN_FALSE; + RETURN_THROWS(); } /* really close the zip will break BC :-D */ @@ -1204,9 +1203,8 @@ static PHP_NAMED_FUNCTION(zif_zip_close) } /* }}} */ -/* {{{ proto resource zip_read(resource zip) - Returns the next file in the archive */ -static PHP_NAMED_FUNCTION(zif_zip_read) +/* {{{ Returns the next file in the archive */ +PHP_FUNCTION(zip_read) { zval *zip_dp; zip_read_rsrc *zr_rsrc; @@ -1214,11 +1212,11 @@ static PHP_NAMED_FUNCTION(zif_zip_read) zip_rsrc *rsrc_int; if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip_dp) == FAILURE) { - return; + RETURN_THROWS(); } if ((rsrc_int = (zip_rsrc *)zend_fetch_resource(Z_RES_P(zip_dp), le_zip_dir_name, le_zip_dir)) == NULL) { - RETURN_FALSE; + RETURN_THROWS(); } if (rsrc_int && rsrc_int->za) { @@ -1250,10 +1248,9 @@ static PHP_NAMED_FUNCTION(zif_zip_read) } /* }}} */ -/* {{{ proto bool zip_entry_open(resource zip_dp, resource zip_entry [, string mode]) - Open a Zip File, pointed by the resource entry */ +/* {{{ Open a Zip File, pointed by the resource entry */ /* Dummy function to follow the old API */ -static PHP_NAMED_FUNCTION(zif_zip_entry_open) +PHP_FUNCTION(zip_entry_open) { zval * zip; zval * zip_entry; @@ -1263,15 +1260,15 @@ static PHP_NAMED_FUNCTION(zif_zip_entry_open) zip_rsrc *z_rsrc; if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr|s", &zip, &zip_entry, &mode, &mode_len) == FAILURE) { - return; + RETURN_THROWS(); } if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) { - RETURN_FALSE; + RETURN_THROWS(); } if ((z_rsrc = (zip_rsrc *)zend_fetch_resource(Z_RES_P(zip), le_zip_dir_name, le_zip_dir)) == NULL) { - RETURN_FALSE; + RETURN_THROWS(); } if (zr_rsrc->zf != NULL) { @@ -1282,28 +1279,27 @@ static PHP_NAMED_FUNCTION(zif_zip_entry_open) } /* }}} */ -/* {{{ proto bool zip_entry_close(resource zip_ent) - Close a zip entry */ -static PHP_NAMED_FUNCTION(zif_zip_entry_close) +/* {{{ Close a zip entry */ +PHP_FUNCTION(zip_entry_close) { zval * zip_entry; zip_read_rsrc * zr_rsrc; if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip_entry) == FAILURE) { - return; + RETURN_THROWS(); } if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) { - RETURN_FALSE; + RETURN_THROWS(); } - RETURN_BOOL(SUCCESS == zend_list_close(Z_RES_P(zip_entry))); + zend_list_close(Z_RES_P(zip_entry)); + RETURN_TRUE; } /* }}} */ -/* {{{ proto mixed zip_entry_read(resource zip_entry [, int len]) - Read from an open directory entry */ -static PHP_NAMED_FUNCTION(zif_zip_entry_read) +/* {{{ Read from an open directory entry */ +PHP_FUNCTION(zip_entry_read) { zval * zip_entry; zend_long len = 0; @@ -1312,11 +1308,11 @@ static PHP_NAMED_FUNCTION(zif_zip_entry_read) int n = 0; if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &zip_entry, &len) == FAILURE) { - return; + RETURN_THROWS(); } if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) { - RETURN_FALSE; + RETURN_THROWS(); } if (len <= 0) { @@ -1332,7 +1328,7 @@ static PHP_NAMED_FUNCTION(zif_zip_entry_read) RETURN_NEW_STR(buffer); } else { zend_string_efree(buffer); - RETURN_EMPTY_STRING() + RETURN_EMPTY_STRING(); } } else { RETURN_FALSE; @@ -1346,11 +1342,11 @@ static void php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS, int opt) /* {{{ zip_read_rsrc * zr_rsrc; if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zip_entry) == FAILURE) { - return; + RETURN_THROWS(); } if ((zr_rsrc = (zip_read_rsrc *)zend_fetch_resource(Z_RES_P(zip_entry), le_zip_entry_name, le_zip_entry)) == NULL) { - RETURN_FALSE; + RETURN_THROWS(); } if (!zr_rsrc->zf) { @@ -1395,41 +1391,36 @@ static void php_zip_entry_get_info(INTERNAL_FUNCTION_PARAMETERS, int opt) /* {{{ } /* }}} */ -/* {{{ proto string zip_entry_name(resource zip_entry) - Return the name given a ZZip entry */ -static PHP_NAMED_FUNCTION(zif_zip_entry_name) +/* {{{ Return the name given a ZZip entry */ +PHP_FUNCTION(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) +/* {{{ Return the compressed size of a ZZip entry */ +PHP_FUNCTION(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) +/* {{{ Return the actual filesize of a ZZip entry */ +PHP_FUNCTION(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) +/* {{{ Return a string containing the compression method used on a particular entry */ +PHP_FUNCTION(zip_entry_compressionmethod) { php_zip_entry_get_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3); } /* }}} */ -/* {{{ 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) +/* {{{ Create new zip using source uri for output, return TRUE on success or the error code */ +PHP_METHOD(ZipArchive, open) { struct zip *intern; int err = 0; @@ -1440,15 +1431,15 @@ static ZIPARCHIVE_METHOD(open) ze_zip_object *ze_obj; if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &filename, &flags) == FAILURE) { - return; + RETURN_THROWS(); } /* We do not use ZIP_FROM_OBJECT, zip init function here */ ze_obj = Z_ZIP_P(self); if (ZSTR_LEN(filename) == 0) { - php_error_docref(NULL, E_WARNING, "Empty string as source"); - RETURN_FALSE; + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); } if (ZIP_OPENBASEDIR_CHECKPATH(ZSTR_VAL(filename))) { @@ -1456,6 +1447,7 @@ static ZIPARCHIVE_METHOD(open) } if (!(resolved_path = expand_filepath(ZSTR_VAL(filename), NULL))) { + php_error_docref(NULL, E_WARNING, "No such file or directory"); RETURN_FALSE; } @@ -1483,6 +1475,8 @@ static ZIPARCHIVE_METHOD(open) /* exists and is empty */ if (VCWD_STAT(resolved_path, &st) == 0 && st.st_size == 0) { + php_error_docref(NULL, E_DEPRECATED, "Using empty file as ZipArchive is deprecated"); + /* reduce BC break introduced in libzip 1.6.0 "Do not accept empty files as valid zip archives any longer" */ flags |= ZIP_TRUNCATE; @@ -1501,54 +1495,69 @@ static ZIPARCHIVE_METHOD(open) } /* }}} */ -/* {{{ proto resource ZipArchive::setPassword(string password) -Set the password for the active archive */ -static ZIPARCHIVE_METHOD(setPassword) +/* {{{ Set the password for the active archive */ +PHP_METHOD(ZipArchive, setPassword) { struct zip *intern; zval *self = ZEND_THIS; char *password; size_t password_len; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &password, &password_len) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + if (password_len < 1) { RETURN_FALSE; + } + + int res = zip_set_default_password(intern, (const char *)password); + if (res == 0) { + RETURN_TRUE; } else { - int res = zip_set_default_password(intern, (const char *)password); - if (res == 0) { - RETURN_TRUE; - } else { - RETURN_FALSE; - } + RETURN_FALSE; } } /* }}} */ -/* {{{ proto bool ZipArchive::close() -close the zip archive */ -static ZIPARCHIVE_METHOD(close) +/* {{{ close the zip archive */ +PHP_METHOD(ZipArchive, close) { struct zip *intern; zval *self = ZEND_THIS; ze_zip_object *ze_obj; int err; + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + ZIP_FROM_OBJECT(intern, self); ze_obj = Z_ZIP_P(self); - if ((err = zip_close(intern))) { -#if LIBZIP_VERSION_MAJOR == 1 && LIBZIP_VERSION_MINOR == 3 && LIBZIP_VERSION_MICRO == 1 - php_error_docref(NULL, E_WARNING, "zip_close have failed"); -#else + err = zip_close(intern); + if (err) { php_error_docref(NULL, E_WARNING, "%s", zip_strerror(intern)); + /* Save error for property reader */ + #if LIBZIP_VERSION_MAJOR < 1 + zip_error_get(intern, &ze_obj->err_zip, &ze_obj->err_sys); + #else + { + zip_error_t *ziperr; + + ziperr = zip_get_error(intern); + ze_obj->err_zip = zip_error_code_zip(ziperr); + ze_obj->err_sys = zip_error_code_system(ziperr); + zip_error_fini(ziperr); + } + #endif zip_discard(intern); -#endif + } else { + ze_obj->err_zip = 0; + ze_obj->err_sys = 0; } efree(ze_obj->filename); @@ -1564,14 +1573,17 @@ static ZIPARCHIVE_METHOD(close) } /* }}} */ -/* {{{ proto bool ZipArchive::count() -close the zip archive */ -static ZIPARCHIVE_METHOD(count) +/* {{{ close the zip archive */ +PHP_METHOD(ZipArchive, count) { struct zip *intern; zval *self = ZEND_THIS; zip_int64_t num; + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + ZIP_FROM_OBJECT(intern, self); num = zip_get_num_entries(intern, 0); @@ -1579,53 +1591,66 @@ static ZIPARCHIVE_METHOD(count) } /* }}} */ -/* {{{ proto string ZipArchive::getStatusString() - * Returns the status error message, system and/or zip messages */ -static ZIPARCHIVE_METHOD(getStatusString) +/* {{{ Returns the status error message, system and/or zip messages */ +PHP_METHOD(ZipArchive, getStatusString) { - struct zip *intern; zval *self = ZEND_THIS; #if LIBZIP_VERSION_MAJOR < 1 int zep, syp, len; char error_string[128]; -#else - zip_error_t *err; #endif + ze_zip_object *ze_obj; - ZIP_FROM_OBJECT(intern, self); + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } -#if LIBZIP_VERSION_MAJOR < 1 - zip_error_get(intern, &zep, &syp); + ze_obj = Z_ZIP_P(self); /* not ZIP_FROM_OBJECT as we can use saved error after close */ - len = zip_error_to_str(error_string, 128, zep, syp); +#if LIBZIP_VERSION_MAJOR < 1 + if (ze_obj->za) { + zip_error_get(ze_obj->za, &zep, &syp); + len = zip_error_to_str(error_string, 128, zep, syp); + } else { + len = zip_error_to_str(error_string, 128, ze_obj->err_zip, ze_obj->err_sys); + } RETVAL_STRINGL(error_string, len); #else - err = zip_get_error(intern); - RETVAL_STRING(zip_error_strerror(err)); - zip_error_fini(err); + if (ze_obj->za) { + zip_error_t *err; + + err = zip_get_error(ze_obj->za); + RETVAL_STRING(zip_error_strerror(err)); + zip_error_fini(err); + } else { + zip_error_t err; + + zip_error_init(&err); + zip_error_set(&err, ze_obj->err_zip, ze_obj->err_sys); + RETVAL_STRING(zip_error_strerror(&err)); + zip_error_fini(&err); + } #endif } /* }}} */ -/* {{{ proto bool ZipArchive::createEmptyDir(string dirname) -Returns the index of the entry named filename in the archive */ -static ZIPARCHIVE_METHOD(addEmptyDir) +/* {{{ Returns the index of the entry named filename in the archive */ +PHP_METHOD(ZipArchive, addEmptyDir) { struct zip *intern; zval *self = ZEND_THIS; char *dirname; size_t dirname_len; - int idx; - struct zip_stat sb; char *s; + zend_long flags = 0; - ZIP_FROM_OBJECT(intern, self); - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", - &dirname, &dirname_len) == FAILURE) { - return; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", + &dirname, &dirname_len, &flags) == FAILURE) { + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + if (dirname_len<1) { RETURN_FALSE; } @@ -1639,16 +1664,11 @@ static ZIPARCHIVE_METHOD(addEmptyDir) s = dirname; } - idx = zip_stat(intern, s, 0, &sb); - if (idx >= 0) { + if ((Z_ZIP_P(self)->last_id = zip_dir_add(intern, (const char *)s, flags)) == -1) { RETVAL_FALSE; } else { - if (zip_dir_add(intern, (const char *)s, 0) == -1) { - RETVAL_FALSE; - } else { - zip_error_clear(intern); - RETVAL_TRUE; - } + zip_error_clear(intern); + RETVAL_TRUE; } if (s != dirname) { @@ -1659,51 +1679,38 @@ static ZIPARCHIVE_METHOD(addEmptyDir) static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ { - struct zip *intern; zval *self = ZEND_THIS; char *path = "."; - char *remove_path = NULL, *save_remove_path; - char *add_path = NULL; - size_t add_path_len, remove_path_len = 0, path_len = 1; - zend_long remove_all_path = 0; - zend_long flags = 0; - zval *options = NULL; + size_t path_len = 1; + zend_long glob_flags = 0; + HashTable *options = NULL; + zip_options opts; int found; zend_string *pattern; - ZIP_FROM_OBJECT(intern, self); /* 1 == glob, 2 == pcre */ if (type == 1) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|la", - &pattern, &flags, &options) == FAILURE) { - return; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|lh", + &pattern, &glob_flags, &options) == FAILURE) { + RETURN_THROWS(); } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|sa", + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|sh", &pattern, &path, &path_len, &options) == FAILURE) { - return; + RETURN_THROWS(); } } if (ZSTR_LEN(pattern) == 0) { - php_error_docref(NULL, E_NOTICE, "Empty string as pattern"); - RETURN_FALSE; + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); } - if (options && (php_zip_parse_options(options, &remove_all_path, &remove_path, &remove_path_len, - &add_path, &add_path_len) < 0)) { - RETURN_FALSE; - } - - save_remove_path = remove_path; - if (remove_path && remove_path_len > 1) { - size_t real_len = strlen(remove_path); - if ((real_len > 1) && ((remove_path[real_len - 1] == '/') || (remove_path[real_len - 1] == '\\'))) { - remove_path = estrndup(remove_path, real_len - 1); - } + if (options && zend_hash_num_elements(options) > 0 && (php_zip_parse_options(options, &opts) < 0)) { + RETURN_THROWS(); } if (type == 1) { - found = php_zip_glob(ZSTR_VAL(pattern), ZSTR_LEN(pattern), flags, return_value); + found = php_zip_glob(ZSTR_VAL(pattern), ZSTR_LEN(pattern), glob_flags, return_value); } else { found = php_zip_pcre(pattern, path, path_len, return_value); } @@ -1711,6 +1718,9 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* if (found > 0) { int i; zval *zval_file; + ze_zip_object *ze_obj; + + ze_obj = Z_ZIP_P(self); for (i = 0; i < found; i++) { char *file_stripped, *entry_name; @@ -1719,26 +1729,31 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* zend_string *basename = NULL; if ((zval_file = zend_hash_index_find(Z_ARRVAL_P(return_value), i)) != NULL) { - if (remove_all_path) { + if (opts.remove_all_path) { basename = php_basename(Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), NULL, 0); file_stripped = ZSTR_VAL(basename); file_stripped_len = ZSTR_LEN(basename); - } else if (remove_path && strstr(Z_STRVAL_P(zval_file), remove_path) != NULL) { - file_stripped = Z_STRVAL_P(zval_file) + remove_path_len + 1; - file_stripped_len = Z_STRLEN_P(zval_file) - remove_path_len - 1; + } else if (opts.remove_path && strstr(Z_STRVAL_P(zval_file), opts.remove_path) != NULL) { + if (IS_SLASH(Z_STRVAL_P(zval_file)[opts.remove_path_len])) { + file_stripped = Z_STRVAL_P(zval_file) + opts.remove_path_len + 1; + file_stripped_len = Z_STRLEN_P(zval_file) - opts.remove_path_len - 1; + } else { + file_stripped = Z_STRVAL_P(zval_file) + opts.remove_path_len; + file_stripped_len = Z_STRLEN_P(zval_file) - opts.remove_path_len; + } } else { file_stripped = Z_STRVAL_P(zval_file); file_stripped_len = Z_STRLEN_P(zval_file); } - if (add_path) { - if ((add_path_len + file_stripped_len) > MAXPATHLEN) { + if (opts.add_path) { + if ((opts.add_path_len + file_stripped_len) > MAXPATHLEN) { php_error_docref(NULL, E_WARNING, "Entry name too long (max: %d, %zd given)", - MAXPATHLEN - 1, (add_path_len + file_stripped_len)); + MAXPATHLEN - 1, (opts.add_path_len + file_stripped_len)); zend_array_destroy(Z_ARR_P(return_value)); RETURN_FALSE; } - snprintf(entry_name_buf, MAXPATHLEN, "%s%s", add_path, file_stripped); + snprintf(entry_name_buf, MAXPATHLEN, "%s%s", opts.add_path, file_stripped); } else { snprintf(entry_name_buf, MAXPATHLEN, "%s", file_stripped); } @@ -1750,57 +1765,63 @@ static void php_zip_add_from_pattern(INTERNAL_FUNCTION_PARAMETERS, int type) /* basename = NULL; } - if (php_zip_add_file(intern, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), - entry_name, entry_name_len, 0, 0) < 0) { + if (php_zip_add_file(ze_obj, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file), + entry_name, entry_name_len, 0, 0, -1, opts.flags) < 0) { zend_array_destroy(Z_ARR_P(return_value)); RETURN_FALSE; } + if (opts.comp_method >= 0) { + if (zip_set_file_compression(ze_obj->za, ze_obj->last_id, opts.comp_method, opts.comp_flags)) { + zend_array_destroy(Z_ARR_P(return_value)); + RETURN_FALSE; + } + } +#ifdef HAVE_ENCRYPTION + if (opts.enc_method >= 0) { + if (zip_file_set_encryption(ze_obj->za, ze_obj->last_id, opts.enc_method, opts.enc_password)) { + zend_array_destroy(Z_ARR_P(return_value)); + RETURN_FALSE; + } + } +#endif } } } - if (remove_path != save_remove_path) { - efree(remove_path); - } } /* }}} */ -/* {{{ 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) +/* {{{ Add files matching the glob pattern. See php's glob for the pattern syntax. */ +PHP_METHOD(ZipArchive, 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) +/* {{{ Add files matching the pcre pattern. See php's pcre for the pattern syntax. */ +PHP_METHOD(ZipArchive, 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) +/* {{{ Add a file in a Zip archive using its path and the name to use. */ +PHP_METHOD(ZipArchive, addFile) { - struct zip *intern; zval *self = ZEND_THIS; char *entry_name = NULL; size_t entry_name_len = 0; zend_long offset_start = 0, offset_len = 0; zend_string *filename; + zend_long flags = ZIP_FL_OVERWRITE; - ZIP_FROM_OBJECT(intern, self); - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|sll", - &filename, &entry_name, &entry_name_len, &offset_start, &offset_len) == FAILURE) { - return; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|slll", + &filename, &entry_name, &entry_name_len, &offset_start, &offset_len, &flags) == FAILURE) { + RETURN_THROWS(); } if (ZSTR_LEN(filename) == 0) { - php_error_docref(NULL, E_NOTICE, "Empty string as filename"); - RETURN_FALSE; + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); } if (entry_name_len == 0) { @@ -1808,8 +1829,41 @@ static ZIPARCHIVE_METHOD(addFile) entry_name_len = ZSTR_LEN(filename); } - if (php_zip_add_file(intern, ZSTR_VAL(filename), ZSTR_LEN(filename), - entry_name, entry_name_len, offset_start, offset_len) < 0) { + if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename), + entry_name, entry_name_len, offset_start, offset_len, -1, flags) < 0) { + RETURN_FALSE; + } else { + RETURN_TRUE; + } +} +/* }}} */ + +/* {{{ Add a file in a Zip archive using its path and the name to use. */ +PHP_METHOD(ZipArchive, replaceFile) +{ + zval *self = ZEND_THIS; + zend_long index; + zend_long offset_start = 0, offset_len = 0; + zend_string *filename; + zend_long flags = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Pl|lll", + &filename, &index, &offset_start, &offset_len, &flags) == FAILURE) { + RETURN_THROWS(); + } + + if (ZSTR_LEN(filename) == 0) { + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); + } + + if (index < 0) { + zend_argument_value_error(2, "must be greater than or equal to 0"); + RETURN_THROWS(); + } + + if (php_zip_add_file(Z_ZIP_P(self), ZSTR_VAL(filename), ZSTR_LEN(filename), + NULL, 0, offset_start, offset_len, index, flags) < 0) { RETURN_FALSE; } else { RETURN_TRUE; @@ -1817,9 +1871,8 @@ static ZIPARCHIVE_METHOD(addFile) } /* }}} */ -/* {{{ proto bool ZipArchive::addFromString(string name, string content) -Add a file using content and the entry name */ -static ZIPARCHIVE_METHOD(addFromString) +/* {{{ Add a file using content and the entry name */ +PHP_METHOD(ZipArchive, addFromString) { struct zip *intern; zval *self = ZEND_THIS; @@ -1829,15 +1882,15 @@ static ZIPARCHIVE_METHOD(addFromString) ze_zip_object *ze_obj; struct zip_source *zs; int pos = 0; - int cur_idx; - - ZIP_FROM_OBJECT(intern, self); + zend_long flags = ZIP_FL_OVERWRITE; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS", - &name, &name_len, &buffer) == FAILURE) { - return; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS|l", + &name, &name_len, &buffer, &flags) == FAILURE) { + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + ze_obj = Z_ZIP_P(self); if (ze_obj->buffers_cnt) { ze_obj->buffers = (char **)safe_erealloc(ze_obj->buffers, sizeof(char *), (ze_obj->buffers_cnt+1), 0); @@ -1856,16 +1909,8 @@ static ZIPARCHIVE_METHOD(addFromString) 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) { - zip_source_free(zs); - RETURN_FALSE; - } - } - - if (zip_file_add(intern, name, zs, 0) == -1) { + ze_obj->last_id = zip_file_add(intern, name, zs, flags); + if (ze_obj->last_id == -1) { zip_source_free(zs); RETURN_FALSE; } else { @@ -1875,9 +1920,8 @@ static ZIPARCHIVE_METHOD(addFromString) } /* }}} */ -/* {{{ proto array ZipArchive::statName(string filename[, int flags]) -Returns the information about a the zip entry filename */ -static ZIPARCHIVE_METHOD(statName) +/* {{{ Returns the information about a the zip entry filename */ +PHP_METHOD(ZipArchive, statName) { struct zip *intern; zval *self = ZEND_THIS; @@ -1885,21 +1929,20 @@ static ZIPARCHIVE_METHOD(statName) struct zip_stat sb; zend_string *name; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &name, &flags) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + PHP_ZIP_STAT_PATH(intern, ZSTR_VAL(name), ZSTR_LEN(name), flags, sb); RETURN_SB(&sb); } /* }}} */ -/* {{{ proto resource ZipArchive::statIndex(int index[, int flags]) -Returns the zip entry information using its index */ -static ZIPARCHIVE_METHOD(statIndex) +/* {{{ Returns the zip entry information using its index */ +PHP_METHOD(ZipArchive, statIndex) { struct zip *intern; zval *self = ZEND_THIS; @@ -1907,13 +1950,13 @@ static ZIPARCHIVE_METHOD(statIndex) struct zip_stat sb; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &index, &flags) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + if (zip_stat_index(intern, index, flags, &sb) != 0) { RETURN_FALSE; } @@ -1921,9 +1964,8 @@ static ZIPARCHIVE_METHOD(statIndex) } /* }}} */ -/* {{{ proto int ZipArchive::locateName(string filename[, int flags]) -Returns the index of the entry named filename in the archive */ -static ZIPARCHIVE_METHOD(locateName) +/* {{{ Returns the index of the entry named filename in the archive */ +PHP_METHOD(ZipArchive, locateName) { struct zip *intern; zval *self = ZEND_THIS; @@ -1931,12 +1973,12 @@ static ZIPARCHIVE_METHOD(locateName) zend_long idx = -1; zend_string *name; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|l", &name, &flags) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + if (ZSTR_LEN(name) < 1) { RETURN_FALSE; } @@ -1951,22 +1993,21 @@ static ZIPARCHIVE_METHOD(locateName) } /* }}} */ -/* {{{ proto string ZipArchive::getNameIndex(int index [, int flags]) -Returns the name of the file at position index */ -static ZIPARCHIVE_METHOD(getNameIndex) +/* {{{ Returns the name of the file at position index */ +PHP_METHOD(ZipArchive, getNameIndex) { struct zip *intern; zval *self = ZEND_THIS; const char *name; zend_long flags = 0, index = 0; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &index, &flags) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + name = zip_get_name(intern, (int) index, flags); if (name) { @@ -1977,24 +2018,23 @@ static ZIPARCHIVE_METHOD(getNameIndex) } /* }}} */ -/* {{{ proto bool ZipArchive::setArchiveComment(string comment) -Set or remove (NULL/'') the comment of the archive */ -static ZIPARCHIVE_METHOD(setArchiveComment) +/* {{{ Set or remove (NULL/'') the comment of the archive */ +PHP_METHOD(ZipArchive, setArchiveComment) { struct zip *intern; zval *self = ZEND_THIS; size_t comment_len; char * comment; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &comment, &comment_len) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + if (comment_len > 0xffff) { - php_error_docref(NULL, E_WARNING, "Comment must not exceed 65535 bytes"); - RETURN_FALSE; + zend_argument_value_error(1, "must be less than 65535 bytes"); + RETURN_THROWS(); } if (zip_set_archive_comment(intern, (const char *)comment, comment_len)) { @@ -2005,9 +2045,8 @@ static ZIPARCHIVE_METHOD(setArchiveComment) } /* }}} */ -/* {{{ proto string ZipArchive::getArchiveComment([int flags]) -Returns the comment of an entry using its index */ -static ZIPARCHIVE_METHOD(getArchiveComment) +/* {{{ Returns the comment of an entry using its index */ +PHP_METHOD(ZipArchive, getArchiveComment) { struct zip *intern; zval *self = ZEND_THIS; @@ -2015,12 +2054,12 @@ static ZIPARCHIVE_METHOD(getArchiveComment) const char * comment; int comment_len = 0; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &flags) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + comment = zip_get_archive_comment(intern, &comment_len, (int)flags); if(comment==NULL) { RETURN_FALSE; @@ -2029,9 +2068,8 @@ static ZIPARCHIVE_METHOD(getArchiveComment) } /* }}} */ -/* {{{ proto bool ZipArchive::setCommentName(string name, string comment) -Set or remove (NULL/'') the comment of an entry using its Name */ -static ZIPARCHIVE_METHOD(setCommentName) +/* {{{ Set or remove (NULL/'') the comment of an entry using its Name */ +PHP_METHOD(ZipArchive, setCommentName) { struct zip *intern; zval *self = ZEND_THIS; @@ -2039,20 +2077,21 @@ static ZIPARCHIVE_METHOD(setCommentName) char * comment, *name; int idx; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &name, &name_len, &comment, &comment_len) == FAILURE) { - return; + RETURN_THROWS(); } - if (name_len < 1) { - php_error_docref(NULL, E_NOTICE, "Empty string as entry name"); + if (name_len == 0) { + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + if (comment_len > 0xffff) { - php_error_docref(NULL, E_WARNING, "Comment must not exceed 65535 bytes"); - RETURN_FALSE; + zend_argument_value_error(2, "must be less than 65535 bytes"); + RETURN_THROWS(); } idx = zip_name_locate(intern, name, 0); @@ -2063,9 +2102,8 @@ static ZIPARCHIVE_METHOD(setCommentName) } /* }}} */ -/* {{{ proto bool ZipArchive::setCommentIndex(int index, string comment) -Set or remove (NULL/'') the comment of an entry using its index */ -static ZIPARCHIVE_METHOD(setCommentIndex) +/* {{{ Set or remove (NULL/'') the comment of an entry using its index */ +PHP_METHOD(ZipArchive, setCommentIndex) { struct zip *intern; zval *self = ZEND_THIS; @@ -2074,16 +2112,16 @@ static ZIPARCHIVE_METHOD(setCommentIndex) char * comment; struct zip_stat sb; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &index, &comment, &comment_len) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + if (comment_len > 0xffff) { - php_error_docref(NULL, E_WARNING, "Comment must not exceed 65535 bytes"); - RETURN_FALSE; + zend_argument_value_error(2, "must be less than 65535 bytes"); + RETURN_THROWS(); } PHP_ZIP_STAT_INDEX(intern, index, 0, sb); @@ -2094,9 +2132,8 @@ static ZIPARCHIVE_METHOD(setCommentIndex) /* those constants/functions are only available in libzip since 0.11.2 */ #ifdef ZIP_OPSYS_DEFAULT -/* {{{ proto bool ZipArchive::setExternalAttributesName(string name, int opsys, int attr [, int flags]) -Set external attributes for file in zip, using its name */ -static ZIPARCHIVE_METHOD(setExternalAttributesName) +/* {{{ Set external attributes for file in zip, using its name */ +PHP_METHOD(ZipArchive, setExternalAttributesName) { struct zip *intern; zval *self = ZEND_THIS; @@ -2105,18 +2142,20 @@ static ZIPARCHIVE_METHOD(setExternalAttributesName) zend_long flags=0, opsys, attr; zip_int64_t idx; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sll|l", &name, &name_len, &opsys, &attr, &flags) == FAILURE) { - return; + RETURN_THROWS(); } - if (name_len < 1) { - php_error_docref(NULL, E_NOTICE, "Empty string as entry name"); + ZIP_FROM_OBJECT(intern, self); + + if (name_len == 0) { + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); } idx = zip_name_locate(intern, name, 0); + if (idx < 0) { RETURN_FALSE; } @@ -2128,22 +2167,21 @@ static ZIPARCHIVE_METHOD(setExternalAttributesName) } /* }}} */ -/* {{{ proto bool ZipArchive::setExternalAttributesIndex(int index, int opsys, int attr [, int flags]) -Set external attributes for file in zip, using its index */ -static ZIPARCHIVE_METHOD(setExternalAttributesIndex) +/* {{{ Set external attributes for file in zip, using its index */ +PHP_METHOD(ZipArchive, setExternalAttributesIndex) { struct zip *intern; zval *self = ZEND_THIS; zend_long index, flags=0, opsys, attr; struct zip_stat sb; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "lll|l", &index, &opsys, &attr, &flags) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + PHP_ZIP_STAT_INDEX(intern, index, 0, sb); if (zip_file_set_external_attributes(intern, (zip_uint64_t)index, (zip_flags_t)flags, (zip_uint8_t)(opsys&0xff), (zip_uint32_t)attr) < 0) { @@ -2153,9 +2191,8 @@ static ZIPARCHIVE_METHOD(setExternalAttributesIndex) } /* }}} */ -/* {{{ proto bool ZipArchive::getExternalAttributesName(string name, int &opsys, int &attr [, int flags]) -Get external attributes for file in zip, using its name */ -static ZIPARCHIVE_METHOD(getExternalAttributesName) +/* {{{ Get external attributes for file in zip, using its name */ +PHP_METHOD(ZipArchive, getExternalAttributesName) { struct zip *intern; zval *self = ZEND_THIS, *z_opsys, *z_attr; @@ -2166,18 +2203,20 @@ static ZIPARCHIVE_METHOD(getExternalAttributesName) zip_uint32_t attr; zip_int64_t idx; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l", &name, &name_len, &z_opsys, &z_attr, &flags) == FAILURE) { - return; + RETURN_THROWS(); } - if (name_len < 1) { - php_error_docref(NULL, E_NOTICE, "Empty string as entry name"); + ZIP_FROM_OBJECT(intern, self); + + if (name_len == 0) { + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); } idx = zip_name_locate(intern, name, 0); + if (idx < 0) { RETURN_FALSE; } @@ -2191,9 +2230,8 @@ static ZIPARCHIVE_METHOD(getExternalAttributesName) } /* }}} */ -/* {{{ proto bool ZipArchive::getExternalAttributesIndex(int index, int &opsys, int &attr [, int flags]) -Get external attributes for file in zip, using its index */ -static ZIPARCHIVE_METHOD(getExternalAttributesIndex) +/* {{{ Get external attributes for file in zip, using its index */ +PHP_METHOD(ZipArchive, getExternalAttributesIndex) { struct zip *intern; zval *self = ZEND_THIS, *z_opsys, *z_attr; @@ -2202,13 +2240,13 @@ static ZIPARCHIVE_METHOD(getExternalAttributesIndex) zip_uint32_t attr; struct zip_stat sb; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "lzz|l", &index, &z_opsys, &z_attr, &flags) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + PHP_ZIP_STAT_INDEX(intern, index, 0, sb); if (zip_file_get_external_attributes(intern, (zip_uint64_t)index, (zip_flags_t)flags, &opsys, &attr) < 0) { @@ -2222,9 +2260,8 @@ static ZIPARCHIVE_METHOD(getExternalAttributesIndex) #endif /* ifdef ZIP_OPSYS_DEFAULT */ #ifdef HAVE_ENCRYPTION -/* {{{ proto bool ZipArchive::setEncryptionName(string name, int method, [string password]) -Set encryption method for file in zip, using its name */ -static ZIPARCHIVE_METHOD(setEncryptionName) +/* {{{ Set encryption method for file in zip, using its name */ +PHP_METHOD(ZipArchive, setEncryptionName) { struct zip *intern; zval *self = ZEND_THIS; @@ -2233,18 +2270,20 @@ static ZIPARCHIVE_METHOD(setEncryptionName) char *name, *password = NULL; size_t name_len, password_len; - ZIP_FROM_OBJECT(intern, self); - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|s", + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|s!", &name, &name_len, &method, &password, &password_len) == FAILURE) { - return; + RETURN_THROWS(); } - if (name_len < 1) { - php_error_docref(NULL, E_NOTICE, "Empty string as entry name"); + ZIP_FROM_OBJECT(intern, self); + + if (name_len == 0) { + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); } idx = zip_name_locate(intern, name, 0); + if (idx < 0) { RETURN_FALSE; } @@ -2256,9 +2295,8 @@ static ZIPARCHIVE_METHOD(setEncryptionName) } /* }}} */ -/* {{{ proto bool ZipArchive::setEncryptionIndex(int index, int method, [string password]) -Set encryption method for file in zip, using its index */ -static ZIPARCHIVE_METHOD(setEncryptionIndex) +/* {{{ Set encryption method for file in zip, using its index */ +PHP_METHOD(ZipArchive, setEncryptionIndex) { struct zip *intern; zval *self = ZEND_THIS; @@ -2266,13 +2304,13 @@ static ZIPARCHIVE_METHOD(setEncryptionIndex) char *password = NULL; size_t password_len; - ZIP_FROM_OBJECT(intern, self); - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|s", + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|s!", &index, &method, &password, &password_len) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + if (zip_file_set_encryption(intern, index, (zip_uint16_t)method, password)) { RETURN_FALSE; } @@ -2281,9 +2319,8 @@ static ZIPARCHIVE_METHOD(setEncryptionIndex) /* }}} */ #endif -/* {{{ proto string ZipArchive::getCommentName(string name[, int flags]) -Returns the comment of an entry using its name */ -static ZIPARCHIVE_METHOD(getCommentName) +/* {{{ Returns the comment of an entry using its name */ +PHP_METHOD(ZipArchive, getCommentName) { struct zip *intern; zval *self = ZEND_THIS; @@ -2294,18 +2331,20 @@ static ZIPARCHIVE_METHOD(getCommentName) const char * comment; char *name; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &name, &name_len, &flags) == FAILURE) { - return; + RETURN_THROWS(); } - if (name_len < 1) { - php_error_docref(NULL, E_NOTICE, "Empty string as entry name"); - RETURN_FALSE; + + ZIP_FROM_OBJECT(intern, self); + + if (name_len == 0) { + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); } idx = zip_name_locate(intern, name, 0); + if (idx < 0) { RETURN_FALSE; } @@ -2315,9 +2354,8 @@ static ZIPARCHIVE_METHOD(getCommentName) } /* }}} */ -/* {{{ proto string ZipArchive::getCommentIndex(int index[, int flags]) -Returns the comment of an entry using its index */ -static ZIPARCHIVE_METHOD(getCommentIndex) +/* {{{ Returns the comment of an entry using its index */ +PHP_METHOD(ZipArchive, getCommentIndex) { struct zip *intern; zval *self = ZEND_THIS; @@ -2326,23 +2364,22 @@ static ZIPARCHIVE_METHOD(getCommentIndex) zip_uint32_t comment_len = 0; struct zip_stat sb; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &index, &flags) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + PHP_ZIP_STAT_INDEX(intern, index, 0, sb); comment = zip_file_get_comment(intern, index, &comment_len, (zip_flags_t)flags); RETURN_STRINGL((char *)comment, comment_len); } /* }}} */ -/* {{{ proto bool ZipArchive::setCompressionName(string name, int comp_method[, int comp_flags]) -Set the compression of a file in zip, using its name */ -static ZIPARCHIVE_METHOD(setCompressionName) - { +/* {{{ Set the compression of a file in zip, using its name */ +PHP_METHOD(ZipArchive, setCompressionName) +{ struct zip *intern; zval *this = ZEND_THIS; size_t name_len; @@ -2350,18 +2387,20 @@ static ZIPARCHIVE_METHOD(setCompressionName) zip_int64_t idx; zend_long comp_method, comp_flags = 0; - ZIP_FROM_OBJECT(intern, this); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|l", &name, &name_len, &comp_method, &comp_flags) == FAILURE) { - return; + RETURN_THROWS(); } - if (name_len < 1) { - php_error_docref(NULL, E_NOTICE, "Empty string as entry name"); + ZIP_FROM_OBJECT(intern, this); + + if (name_len == 0) { + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); } idx = zip_name_locate(intern, name, 0); + if (idx < 0) { RETURN_FALSE; } @@ -2374,22 +2413,21 @@ static ZIPARCHIVE_METHOD(setCompressionName) } /* }}} */ -/* {{{ proto bool ZipArchive::setCompressionIndex(int index, int comp_method[, int comp_flags]) -Set the compression of a file in zip, using its index */ -static ZIPARCHIVE_METHOD(setCompressionIndex) +/* {{{ Set the compression of a file in zip, using its index */ +PHP_METHOD(ZipArchive, setCompressionIndex) { struct zip *intern; zval *this = ZEND_THIS; zend_long index; zend_long comp_method, comp_flags = 0; - ZIP_FROM_OBJECT(intern, this); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|l", &index, &comp_method, &comp_flags) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, this); + if (zip_set_file_compression(intern, (zip_uint64_t)index, (zip_int32_t)comp_method, (zip_uint32_t)comp_flags) != 0) { RETURN_FALSE; @@ -2398,20 +2436,80 @@ static ZIPARCHIVE_METHOD(setCompressionIndex) } /* }}} */ -/* {{{ proto bool ZipArchive::deleteIndex(int index) -Delete a file using its index */ -static ZIPARCHIVE_METHOD(deleteIndex) +#ifdef HAVE_SET_MTIME +/* {{{ Set the modification time of a file in zip, using its name */ +PHP_METHOD(ZipArchive, setMtimeName) { struct zip *intern; - zval *self = ZEND_THIS; + zval *this = ZEND_THIS; + size_t name_len; + char *name; + zip_int64_t idx; + zend_long mtime, flags = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|l", + &name, &name_len, &mtime, &flags) == FAILURE) { + RETURN_THROWS(); + } + + ZIP_FROM_OBJECT(intern, this); + + if (name_len == 0) { + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); + } + + idx = zip_name_locate(intern, name, 0); + + if (idx < 0) { + RETURN_FALSE; + } + + if (zip_file_set_mtime(intern, (zip_uint64_t)idx, + (time_t)mtime, (zip_uint32_t)flags) != 0) { + RETURN_FALSE; + } + RETURN_TRUE; +} +/* }}} */ + +/* {{{ Set the modification time of a file in zip, using its index */ +PHP_METHOD(ZipArchive, setMtimeIndex) +{ + struct zip *intern; + zval *this = ZEND_THIS; zend_long index; + zend_long mtime, flags = 0; - ZIP_FROM_OBJECT(intern, self); + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|l", + &index, &mtime, &flags) == FAILURE) { + RETURN_THROWS(); + } + + ZIP_FROM_OBJECT(intern, this); + + if (zip_file_set_mtime(intern, (zip_uint64_t)index, + (time_t)mtime, (zip_uint32_t)flags) != 0) { + RETURN_FALSE; + } + RETURN_TRUE; +} +/* }}} */ +#endif + +/* {{{ Delete a file using its index */ +PHP_METHOD(ZipArchive, deleteIndex) +{ + struct zip *intern; + zval *self = ZEND_THIS; + zend_long index; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + if (index < 0) { RETURN_FALSE; } @@ -2424,9 +2522,8 @@ static ZIPARCHIVE_METHOD(deleteIndex) } /* }}} */ -/* {{{ proto bool ZipArchive::deleteName(string name) -Delete a file using its index */ -static ZIPARCHIVE_METHOD(deleteName) +/* {{{ Delete a file using its index */ +PHP_METHOD(ZipArchive, deleteName) { struct zip *intern; zval *self = ZEND_THIS; @@ -2434,11 +2531,12 @@ static ZIPARCHIVE_METHOD(deleteName) char *name; struct zip_stat sb; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) { - return; + RETURN_THROWS(); } + + ZIP_FROM_OBJECT(intern, self); + if (name_len < 1) { RETURN_FALSE; } @@ -2451,9 +2549,8 @@ static ZIPARCHIVE_METHOD(deleteName) } /* }}} */ -/* {{{ proto bool ZipArchive::renameIndex(int index, string new_name) -Rename an entry selected by its index to new_name */ -static ZIPARCHIVE_METHOD(renameIndex) +/* {{{ Rename an entry selected by its index to new_name */ +PHP_METHOD(ZipArchive, renameIndex) { struct zip *intern; zval *self = ZEND_THIS; @@ -2461,31 +2558,31 @@ static ZIPARCHIVE_METHOD(renameIndex) size_t new_name_len; zend_long index; - - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &index, &new_name, &new_name_len) == FAILURE) { - return; + RETURN_THROWS(); } if (index < 0) { RETURN_FALSE; } - if (new_name_len < 1) { - php_error_docref(NULL, E_NOTICE, "Empty string as new entry name"); - RETURN_FALSE; + ZIP_FROM_OBJECT(intern, self); + + if (new_name_len == 0) { + zend_argument_value_error(2, "cannot be empty"); + RETURN_THROWS(); } + if (zip_file_rename(intern, index, (const char *)new_name, 0) != 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) +/* {{{ Rename an entry selected by its name to new_name */ +PHP_METHOD(ZipArchive, renameName) { struct zip *intern; zval *self = ZEND_THIS; @@ -2493,15 +2590,15 @@ static ZIPARCHIVE_METHOD(renameName) char *name, *new_name; size_t name_len, new_name_len; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &name, &name_len, &new_name, &new_name_len) == FAILURE) { - return; + RETURN_THROWS(); } - if (new_name_len < 1) { - php_error_docref(NULL, E_NOTICE, "Empty string as new entry name"); - RETURN_FALSE; + ZIP_FROM_OBJECT(intern, self); + + if (new_name_len == 0) { + zend_argument_value_error(2, "cannot be empty"); + RETURN_THROWS(); } PHP_ZIP_STAT_PATH(intern, name, name_len, 0, sb); @@ -2509,24 +2606,24 @@ static ZIPARCHIVE_METHOD(renameName) if (zip_file_rename(intern, sb.index, (const char *)new_name, 0)) { RETURN_FALSE; } + RETURN_TRUE; } /* }}} */ -/* {{{ proto bool ZipArchive::unchangeIndex(int index) -Changes to the file at position index are reverted */ -static ZIPARCHIVE_METHOD(unchangeIndex) +/* {{{ Changes to the file at position index are reverted */ +PHP_METHOD(ZipArchive, unchangeIndex) { struct zip *intern; zval *self = ZEND_THIS; zend_long index; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &index) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + if (index < 0) { RETURN_FALSE; } @@ -2539,9 +2636,8 @@ static ZIPARCHIVE_METHOD(unchangeIndex) } /* }}} */ -/* {{{ proto bool ZipArchive::unchangeName(string name) -Changes to the file named 'name' are reverted */ -static ZIPARCHIVE_METHOD(unchangeName) +/* {{{ Changes to the file named 'name' are reverted */ +PHP_METHOD(ZipArchive, unchangeName) { struct zip *intern; zval *self = ZEND_THIS; @@ -2549,12 +2645,12 @@ static ZIPARCHIVE_METHOD(unchangeName) char *name; size_t name_len; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + if (name_len < 1) { RETURN_FALSE; } @@ -2569,13 +2665,16 @@ static ZIPARCHIVE_METHOD(unchangeName) } /* }}} */ -/* {{{ proto bool ZipArchive::unchangeAll() -All changes to files and global information in archive are reverted */ -static ZIPARCHIVE_METHOD(unchangeAll) +/* {{{ All changes to files and global information in archive are reverted */ +PHP_METHOD(ZipArchive, unchangeAll) { struct zip *intern; zval *self = ZEND_THIS; + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + ZIP_FROM_OBJECT(intern, self); if (zip_unchange_all(intern) != 0) { @@ -2586,13 +2685,16 @@ static ZIPARCHIVE_METHOD(unchangeAll) } /* }}} */ -/* {{{ proto bool ZipArchive::unchangeArchive() -Revert all global changes to the archive archive. For now, this only reverts archive comment changes. */ -static ZIPARCHIVE_METHOD(unchangeArchive) +/* {{{ Revert all global changes to the archive archive. For now, this only reverts archive comment changes. */ +PHP_METHOD(ZipArchive, unchangeArchive) { struct zip *intern; zval *self = ZEND_THIS; + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + ZIP_FROM_OBJECT(intern, self); if (zip_unchange_archive(intern) != 0) { @@ -2603,73 +2705,68 @@ static ZIPARCHIVE_METHOD(unchangeArchive) } /* }}} */ -/* {{{ proto bool ZipArchive::extractTo(string pathto[, mixed files]) -Extract one or more file from a zip archive */ +/* {{{ Extract one or more file from a zip archive */ /* TODO: * - allow index or array of indices * - replace path * - patterns */ -static ZIPARCHIVE_METHOD(extractTo) +PHP_METHOD(ZipArchive, extractTo) { struct zip *intern; zval *self = ZEND_THIS; - zval *zval_files = NULL; + zend_string *files_str = NULL; + HashTable *files_ht = NULL; + zval *zval_file = NULL; php_stream_statbuf ssb; char *pathto; size_t pathto_len; int ret; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|z", &pathto, &pathto_len, &zval_files) == FAILURE) { - return; - } + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_PATH(pathto, pathto_len) + Z_PARAM_OPTIONAL + Z_PARAM_ARRAY_HT_OR_STR_OR_NULL(files_ht, files_str) + ZEND_PARSE_PARAMETERS_END(); + + ZIP_FROM_OBJECT(intern, self); 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; - } + ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL); + if (!ret) { + RETURN_FALSE; + } } - ZIP_FROM_OBJECT(intern, self); - if (zval_files && (Z_TYPE_P(zval_files) != IS_NULL)) { - uint32_t nelems, i; + uint32_t nelems, i; - 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))) { - 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 ((zval_file = zend_hash_index_find(Z_ARRVAL_P(zval_files), i)) != NULL) { - switch (Z_TYPE_P(zval_file)) { - case IS_LONG: - break; - case IS_STRING: - if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file))) { - RETURN_FALSE; - } - break; + if (files_str) { + if (!php_zip_extract_file(intern, pathto, ZSTR_VAL(files_str), ZSTR_LEN(files_str))) { + RETURN_FALSE; + } + } else if (files_ht) { + nelems = zend_hash_num_elements(files_ht); + if (nelems == 0 ) { + RETURN_FALSE; + } + for (i = 0; i < nelems; i++) { + if ((zval_file = zend_hash_index_find(files_ht, i)) != NULL) { + switch (Z_TYPE_P(zval_file)) { + case IS_LONG: + break; + case IS_STRING: + if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file))) { + RETURN_FALSE; } - } + break; } - break; - case IS_LONG: - default: - php_error_docref(NULL, E_WARNING, "Invalid argument, expect string or array of strings"); - break; + } } } else { /* Extract all files */ @@ -2687,6 +2784,7 @@ static ZIPARCHIVE_METHOD(extractTo) } } } + RETURN_TRUE; } /* }}} */ @@ -2708,17 +2806,21 @@ static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ int n = 0; - ZIP_FROM_OBJECT(intern, self); - if (type == 1) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|ll", &filename, &len, &flags) == FAILURE) { - return; + RETURN_THROWS(); } + + ZIP_FROM_OBJECT(intern, self); + PHP_ZIP_STAT_PATH(intern, ZSTR_VAL(filename), ZSTR_LEN(filename), flags, sb); } else { if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|ll", &index, &len, &flags) == FAILURE) { - return; + RETURN_THROWS(); } + + ZIP_FROM_OBJECT(intern, self); + PHP_ZIP_STAT_INDEX(intern, index, 0, sb); } @@ -2753,25 +2855,22 @@ static void php_zip_get_from(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ } /* }}} */ -/* {{{ proto string ZipArchive::getFromName(string entryname[, int len [, int flags]]) -get the contents of an entry using its name */ -static ZIPARCHIVE_METHOD(getFromName) +/* {{{ get the contents of an entry using its name */ +PHP_METHOD(ZipArchive, 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) +/* {{{ get the contents of an entry using its index */ +PHP_METHOD(ZipArchive, 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) +/* {{{ get a stream for an entry using its name */ +PHP_METHOD(ZipArchive, getStream) { struct zip *intern; zval *self = ZEND_THIS; @@ -2781,12 +2880,12 @@ static ZIPARCHIVE_METHOD(getStream) php_stream *stream; ze_zip_object *obj; - ZIP_FROM_OBJECT(intern, self); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &filename) == FAILURE) { - return; + RETURN_THROWS(); } + ZIP_FROM_OBJECT(intern, self); + if (zip_stat(intern, ZSTR_VAL(filename), 0, &sb) != 0) { RETURN_FALSE; } @@ -2802,231 +2901,124 @@ static ZIPARCHIVE_METHOD(getStream) } /* }}} */ -/* {{{ 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_EX(arginfo_ziparchive_setpassword, 0, 0, 1) - ZEND_ARG_INFO(0, password) -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() +#ifdef HAVE_PROGRESS_CALLBACK +static void _php_zip_progress_callback(zip_t *arch, double state, void *ptr) +{ + zval cb_args[1]; + zval cb_retval; + ze_zip_object *obj = ptr; -#ifdef ZIP_OPSYS_DEFAULT -ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setextattrname, 0, 0, 3) - ZEND_ARG_INFO(0, name) - ZEND_ARG_INFO(0, opsys) - ZEND_ARG_INFO(0, attr) - ZEND_ARG_INFO(0, flags) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setextattrindex, 0, 0, 3) - ZEND_ARG_INFO(0, index) - ZEND_ARG_INFO(0, opsys) - ZEND_ARG_INFO(0, attr) - ZEND_ARG_INFO(0, flags) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getextattrname, 0, 0, 3) - ZEND_ARG_INFO(0, name) - ZEND_ARG_INFO(1, opsys) - ZEND_ARG_INFO(1, attr) - ZEND_ARG_INFO(0, flags) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_getextattrindex, 0, 0, 3) - ZEND_ARG_INFO(0, index) - ZEND_ARG_INFO(1, opsys) - ZEND_ARG_INFO(1, attr) - ZEND_ARG_INFO(0, flags) -ZEND_END_ARG_INFO() -#endif /* ifdef ZIP_OPSYS_DEFAULT */ -/* }}} */ + ZVAL_DOUBLE(&cb_args[0], state); + if (call_user_function(EG(function_table), NULL, &obj->progress_callback, &cb_retval, 1, cb_args) == SUCCESS && !Z_ISUNDEF(cb_retval)) { + zval_ptr_dtor(&cb_retval); + } +} -#ifdef HAVE_ENCRYPTION -ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setencryption_name, 0, 0, 2) - ZEND_ARG_INFO(0, name) - ZEND_ARG_INFO(0, method) - ZEND_ARG_INFO(0, password) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setencryption_index, 0, 0, 2) - ZEND_ARG_INFO(0, index) - ZEND_ARG_INFO(0, method) - ZEND_ARG_INFO(0, password) -ZEND_END_ARG_INFO() -#endif +/* {{{ register a progression callback: void callback(double state); */ +PHP_METHOD(ZipArchive, registerProgressCallback) +{ + struct zip *intern; + zval *self = ZEND_THIS; + double rate; + zend_fcall_info fci; + zend_fcall_info_cache fcc; + ze_zip_object *obj; -ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcompname, 0, 0, 2) - ZEND_ARG_INFO(0, name) - ZEND_ARG_INFO(0, method) - ZEND_ARG_INFO(0, compflags) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_ziparchive_setcompindex, 0, 0, 2) - ZEND_ARG_INFO(0, index) - ZEND_ARG_INFO(0, method) - ZEND_ARG_INFO(0, compflags) -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(setPassword, arginfo_ziparchive_setpassword, ZEND_ACC_PUBLIC) - ZIPARCHIVE_ME(close, arginfo_ziparchive__void, ZEND_ACC_PUBLIC) - ZIPARCHIVE_ME(count, 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) -#ifdef ZIP_OPSYS_DEFAULT - ZIPARCHIVE_ME(setExternalAttributesName, arginfo_ziparchive_setextattrname, ZEND_ACC_PUBLIC) - ZIPARCHIVE_ME(setExternalAttributesIndex, arginfo_ziparchive_setextattrindex, ZEND_ACC_PUBLIC) - ZIPARCHIVE_ME(getExternalAttributesName, arginfo_ziparchive_getextattrname, ZEND_ACC_PUBLIC) - ZIPARCHIVE_ME(getExternalAttributesIndex, arginfo_ziparchive_getextattrindex, ZEND_ACC_PUBLIC) + if (zend_parse_parameters(ZEND_NUM_ARGS(), "df", &rate, &fci, &fcc) == FAILURE) { + RETURN_THROWS(); + } + + ZIP_FROM_OBJECT(intern, self); + + obj = Z_ZIP_P(self); + + /* free if called twice */ + _php_zip_progress_callback_free(obj); + + /* register */ + ZVAL_COPY(&obj->progress_callback, &fci.function_name); + if (zip_register_progress_callback_with_state(intern, rate, _php_zip_progress_callback, _php_zip_progress_callback_free, obj)) { + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ #endif - ZIPARCHIVE_ME(setCompressionName, arginfo_ziparchive_setcompname, ZEND_ACC_PUBLIC) - ZIPARCHIVE_ME(setCompressionIndex, arginfo_ziparchive_setcompindex, ZEND_ACC_PUBLIC) -#ifdef HAVE_ENCRYPTION - ZIPARCHIVE_ME(setEncryptionName, arginfo_ziparchive_setencryption_name, ZEND_ACC_PUBLIC) - ZIPARCHIVE_ME(setEncryptionIndex, arginfo_ziparchive_setencryption_index, ZEND_ACC_PUBLIC) + +#ifdef HAVE_CANCEL_CALLBACK +static int _php_zip_cancel_callback(zip_t *arch, void *ptr) +{ + zval cb_retval; + int retval = 0; + ze_zip_object *obj = ptr; + + if (call_user_function(EG(function_table), NULL, &obj->cancel_callback, &cb_retval, 0, NULL) == SUCCESS && !Z_ISUNDEF(cb_retval)) { + retval = zval_get_long(&cb_retval); + zval_ptr_dtor(&cb_retval); + } + + return retval; +} + +/* {{{ register a progression callback: int callback(double state); */ +PHP_METHOD(ZipArchive, registerCancelCallback) +{ + struct zip *intern; + zval *self = ZEND_THIS; + zend_fcall_info fci; + zend_fcall_info_cache fcc; + ze_zip_object *obj; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "f", &fci, &fcc) == FAILURE) { + RETURN_THROWS(); + } + + ZIP_FROM_OBJECT(intern, self); + + obj = Z_ZIP_P(self); + + /* free if called twice */ + _php_zip_cancel_callback_free(obj); + + /* register */ + ZVAL_COPY(&obj->cancel_callback, &fci.function_name); + if (zip_register_cancel_callback_with_state(intern, _php_zip_cancel_callback, _php_zip_cancel_callback_free, obj)) { + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ #endif - PHP_FE_END -}; + +#ifdef HAVE_METHOD_SUPPORTED +/* {{{ check if a compression method is available in used libzip */ +PHP_METHOD(ZipArchive, isCompressionMethodSupported) +{ + zend_long method; + zend_bool enc = 1; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|b", &method, &enc) == FAILURE) { + return; + } + RETVAL_BOOL(zip_compression_method_supported((zip_int32_t)method, enc)); +} /* }}} */ +/* {{{ check if a encryption method is available in used libzip */ +PHP_METHOD(ZipArchive, isEncryptionMethodSupported) +{ + zend_long method; + zend_bool enc = 1; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|b", &method, &enc) == FAILURE) { + return; + } + RETVAL_BOOL(zip_encryption_method_supported((zip_uint16_t)method, enc)); +} +/* }}} */ +#endif + static void php_zip_free_prop_handler(zval *el) /* {{{ */ { pefree(Z_PTR_P(el), 1); } /* }}} */ @@ -3047,16 +3039,17 @@ static PHP_MINIT_FUNCTION(zip) 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); + INIT_CLASS_ENTRY(ce, "ZipArchive", class_ZipArchive_methods); ce.create_object = php_zip_object_new; zip_class_entry = zend_register_internal_class(&ce); zend_hash_init(&zip_prop_handlers, 0, NULL, php_zip_free_prop_handler, 1); - php_zip_register_prop_handler(&zip_prop_handlers, "status", php_zip_status, NULL, NULL, IS_LONG); - php_zip_register_prop_handler(&zip_prop_handlers, "statusSys", php_zip_status_sys, NULL, NULL, IS_LONG); - php_zip_register_prop_handler(&zip_prop_handlers, "numFiles", php_zip_get_num_files, NULL, NULL, IS_LONG); - php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, NULL, php_zipobj_get_filename, IS_STRING); - php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, NULL, IS_STRING); + php_zip_register_prop_handler(&zip_prop_handlers, "lastId", php_zip_last_id, NULL, IS_LONG); + php_zip_register_prop_handler(&zip_prop_handlers, "status", php_zip_status, NULL, IS_LONG); + php_zip_register_prop_handler(&zip_prop_handlers, "statusSys", php_zip_status_sys, NULL, IS_LONG); + php_zip_register_prop_handler(&zip_prop_handlers, "numFiles", php_zip_get_num_files, NULL, IS_LONG); + php_zip_register_prop_handler(&zip_prop_handlers, "filename", NULL, php_zipobj_get_filename, IS_STRING); + php_zip_register_prop_handler(&zip_prop_handlers, "comment", NULL, php_zipobj_get_zip_comment, IS_STRING); zend_class_implements(zip_class_entry, 1, zend_ce_countable); REGISTER_ZIP_CLASS_CONST_LONG("CREATE", ZIP_CREATE); @@ -3071,23 +3064,18 @@ static PHP_MINIT_FUNCTION(zip) 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("FL_RECOMPRESS", ZIP_FL_RECOMPRESS); + REGISTER_ZIP_CLASS_CONST_LONG("FL_ENCRYPTED", ZIP_FL_ENCRYPTED); + REGISTER_ZIP_CLASS_CONST_LONG("FL_OVERWRITE", ZIP_FL_OVERWRITE); + REGISTER_ZIP_CLASS_CONST_LONG("FL_LOCAL", ZIP_FL_LOCAL); + REGISTER_ZIP_CLASS_CONST_LONG("FL_CENTRAL", ZIP_FL_CENTRAL); -#ifdef ZIP_FL_ENC_GUESS /* Default filename encoding policy. */ REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_GUESS", ZIP_FL_ENC_GUESS); -#endif -#ifdef ZIP_FL_ENC_RAW REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_RAW", ZIP_FL_ENC_RAW); -#endif -#ifdef ZIP_FL_ENC_STRICT REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_STRICT", ZIP_FL_ENC_STRICT); -#endif -#ifdef ZIP_FL_ENC_UTF_8 REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_UTF_8", ZIP_FL_ENC_UTF_8); -#endif -#ifdef ZIP_FL_ENC_CP437 REGISTER_ZIP_CLASS_CONST_LONG("FL_ENC_CP437", ZIP_FL_ENC_CP437); -#endif REGISTER_ZIP_CLASS_CONST_LONG("CM_DEFAULT", ZIP_CM_DEFAULT); REGISTER_ZIP_CLASS_CONST_LONG("CM_STORE", ZIP_CM_STORE); @@ -3105,6 +3093,9 @@ static PHP_MINIT_FUNCTION(zip) #ifdef ZIP_CM_LZMA2 REGISTER_ZIP_CLASS_CONST_LONG("CM_LZMA2", ZIP_CM_LZMA2); #endif +#ifdef ZIP_CM_ZSTD + REGISTER_ZIP_CLASS_CONST_LONG("CM_ZSTD", ZIP_CM_ZSTD); +#endif #ifdef ZIP_CM_XZ REGISTER_ZIP_CLASS_CONST_LONG("CM_XZ", ZIP_CM_XZ); #endif @@ -3170,7 +3161,6 @@ static PHP_MINIT_FUNCTION(zip) REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_OS_2", ZIP_OPSYS_OS_2); REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_MACINTOSH", ZIP_OPSYS_MACINTOSH); REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_Z_SYSTEM", ZIP_OPSYS_Z_SYSTEM); - REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_Z_CPM", ZIP_OPSYS_CPM); // typo kept for BC REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_CPM", ZIP_OPSYS_CPM); REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_WINDOWS_NTFS", ZIP_OPSYS_WINDOWS_NTFS); REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_MVS", ZIP_OPSYS_MVS); @@ -3186,14 +3176,16 @@ static PHP_MINIT_FUNCTION(zip) REGISTER_ZIP_CLASS_CONST_LONG("OPSYS_DEFAULT", ZIP_OPSYS_DEFAULT); #endif /* ifdef ZIP_OPSYS_DEFAULT */ -#ifdef HAVE_ENCRYPTION REGISTER_ZIP_CLASS_CONST_LONG("EM_NONE", ZIP_EM_NONE); + REGISTER_ZIP_CLASS_CONST_LONG("EM_TRAD_PKWARE", ZIP_EM_TRAD_PKWARE); +#ifdef HAVE_ENCRYPTION REGISTER_ZIP_CLASS_CONST_LONG("EM_AES_128", ZIP_EM_AES_128); REGISTER_ZIP_CLASS_CONST_LONG("EM_AES_192", ZIP_EM_AES_192); REGISTER_ZIP_CLASS_CONST_LONG("EM_AES_256", ZIP_EM_AES_256); #endif + REGISTER_ZIP_CLASS_CONST_LONG("EM_UNKNOWN", ZIP_EM_UNKNOWN); -#if HAVE_LIBZIP_VERSION +#ifdef HAVE_LIBZIP_VERSION zend_declare_class_constant_string(zip_class_entry, "LIBZIP_VERSION", sizeof("LIBZIP_VERSION")-1, zip_libzip_version()); #else zend_declare_class_constant_string(zip_class_entry, "LIBZIP_VERSION", sizeof("LIBZIP_VERSION")-1, LIBZIP_VERSION); @@ -3208,8 +3200,7 @@ static PHP_MINIT_FUNCTION(zip) } /* }}} */ -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ +/* {{{ PHP_MSHUTDOWN_FUNCTION */ static PHP_MSHUTDOWN_FUNCTION(zip) { zend_hash_destroy(&zip_prop_handlers); @@ -3218,19 +3209,39 @@ static PHP_MSHUTDOWN_FUNCTION(zip) } /* }}} */ -/* {{{ PHP_MINFO_FUNCTION - */ +/* {{{ 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, "Zip version", PHP_ZIP_VERSION); -#if HAVE_LIBZIP_VERSION - php_info_print_table_row(2, "Libzip headers version", LIBZIP_VERSION); - php_info_print_table_row(2, "Libzip library version", zip_libzip_version()); +#ifdef HAVE_LIBZIP_VERSION + if (strcmp(LIBZIP_VERSION, zip_libzip_version())) { + php_info_print_table_row(2, "Libzip headers version", LIBZIP_VERSION); + php_info_print_table_row(2, "Libzip library version", zip_libzip_version()); + } else +#endif + { + php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION); + } +#ifdef HAVE_METHOD_SUPPORTED + php_info_print_table_row(2, "BZIP2 compression", + zip_compression_method_supported(ZIP_CM_BZIP2, 1) ? "Yes" : "No"); + php_info_print_table_row(2, "XZ compression", + zip_compression_method_supported(ZIP_CM_XZ, 1) ? "Yes" : "No"); +#ifdef ZIP_CM_ZSTD + php_info_print_table_row(2, "ZSTD compression", + zip_compression_method_supported(ZIP_CM_ZSTD, 1) ? "Yes" : "No"); #else - php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION); + php_info_print_table_row(2, "ZSTD compression", "No"); +#endif + php_info_print_table_row(2, "AES-128 encryption", + zip_encryption_method_supported(ZIP_EM_AES_128, 1) ? "Yes" : "No"); + php_info_print_table_row(2, "AES-192 encryption", + zip_encryption_method_supported(ZIP_EM_AES_128, 1) ? "Yes" : "No"); + php_info_print_table_row(2, "AES-256 encryption", + zip_encryption_method_supported(ZIP_EM_AES_128, 1) ? "Yes" : "No"); #endif php_info_print_table_end(); |