From b9495a6d2e3d791e5489ac536615ed6303d95ba5 Mon Sep 17 00:00:00 2001 From: Soner Sayakci Date: Mon, 29 Apr 2024 19:48:00 +0200 Subject: [PATCH 1/2] ext/zip: add ZipArchive::openBuffer method Signed-off-by: Soner Sayakci --- ext/zip/php_zip.c | 61 ++++++++++++++++++++++-- ext/zip/php_zip.h | 1 + ext/zip/php_zip.stub.php | 3 ++ ext/zip/php_zip_arginfo.h | 8 +++- ext/zip/tests/ziparchive_openbuffer.phpt | 28 +++++++++++ 5 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 ext/zip/tests/ziparchive_openbuffer.phpt diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 0c1dfaf5dd131..e236be7784016 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -1517,6 +1517,47 @@ PHP_METHOD(ZipArchive, open) } /* }}} */ +/* {{{ Create new read-only zip using given buffer */ +PHP_METHOD(ZipArchive, openBuffer) +{ + struct zip *intern; + zend_string *buffer; + zval *self = ZEND_THIS; + ze_zip_object *ze_obj; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &buffer) == FAILURE) { + RETURN_THROWS(); + } + + zip_error_t err; + zip_error_init(&err); + + zip_source_t * zip_source = zip_source_buffer_create(ZSTR_VAL(buffer), ZSTR_LEN(buffer), 0, &err); + + if (!zip_source) { + zend_throw_error(NULL, "Cannot open zip: %s", zip_error_strerror(&err)); + zip_error_fini(&err); + RETURN_THROWS(); + } + + ze_obj = Z_ZIP_P(self); + + intern = zip_open_from_source(zip_source, ZIP_RDONLY, &err); + if (!intern) { + zip_source_free(zip_source); + zend_throw_error(NULL, "Cannot open zip: %s", zip_error_strerror(&err)); + zip_error_fini(&err); + RETURN_THROWS(); + } + + zip_source_keep(zip_source); + zip_error_fini(&err); + + ze_obj->za = intern; + ze_obj->source = zip_source; +} +/* }}} */ + /* {{{ Set the password for the active archive */ PHP_METHOD(ZipArchive, setPassword) { @@ -1582,12 +1623,22 @@ PHP_METHOD(ZipArchive, close) ze_obj->err_sys = 0; } - /* clear cache as empty zip are not created but deleted */ - php_clear_stat_cache(1, ze_obj->filename, ze_obj->filename_len); + // if we have a filename, we need to free it + if (ze_obj->filename) { + /* clear cache as empty zip are not created but deleted */ + php_clear_stat_cache(1, ze_obj->filename, ze_obj->filename_len); + + efree(ze_obj->filename); + ze_obj->filename = NULL; + ze_obj->filename_len = 0; + } + + if (ze_obj->source) { + zip_source_close(ze_obj->source); + zip_source_free(ze_obj->source); + ze_obj->source = NULL; + } - efree(ze_obj->filename); - ze_obj->filename = NULL; - ze_obj->filename_len = 0; ze_obj->za = NULL; if (!err) { diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h index 41392d1967d74..fa265ba83117d 100644 --- a/ext/zip/php_zip.h +++ b/ext/zip/php_zip.h @@ -65,6 +65,7 @@ typedef struct _ze_zip_read_rsrc { /* Extends zend object */ typedef struct _ze_zip_object { struct zip *za; + zip_source_t *source; char **buffers; HashTable *prop_handler; char *filename; diff --git a/ext/zip/php_zip.stub.php b/ext/zip/php_zip.stub.php index bdd236faaa1a6..0c0236fe845c5 100644 --- a/ext/zip/php_zip.stub.php +++ b/ext/zip/php_zip.stub.php @@ -641,6 +641,9 @@ class ZipArchive implements Countable /** @tentative-return-type */ public function open(string $filename, int $flags = 0): bool|int {} + /** @tentative-return-type */ + public function openBuffer(string $data): void {} + /** * @tentative-return-type */ diff --git a/ext/zip/php_zip_arginfo.h b/ext/zip/php_zip_arginfo.h index fc0621ea19b3c..0d7e91303eb0d 100644 --- a/ext/zip/php_zip_arginfo.h +++ b/ext/zip/php_zip_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 95564c667a51a548f5d43025c90546b991970ddd */ + * Stub hash: 4aae5b13ccac47ac028567125b31206c9a5365ad */ ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_open, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) @@ -45,6 +45,10 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_MASK_EX(arginfo_class_ZipArchive_open, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ZipArchive_openBuffer, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ZipArchive_setPassword, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, password, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -327,6 +331,7 @@ ZEND_FUNCTION(zip_entry_compressedsize); ZEND_FUNCTION(zip_entry_filesize); ZEND_FUNCTION(zip_entry_compressionmethod); ZEND_METHOD(ZipArchive, open); +ZEND_METHOD(ZipArchive, openBuffer); ZEND_METHOD(ZipArchive, setPassword); ZEND_METHOD(ZipArchive, close); ZEND_METHOD(ZipArchive, count); @@ -419,6 +424,7 @@ static const zend_function_entry ext_functions[] = { static const zend_function_entry class_ZipArchive_methods[] = { ZEND_ME(ZipArchive, open, arginfo_class_ZipArchive_open, ZEND_ACC_PUBLIC) + ZEND_ME(ZipArchive, openBuffer, arginfo_class_ZipArchive_openBuffer, ZEND_ACC_PUBLIC) ZEND_ME(ZipArchive, setPassword, arginfo_class_ZipArchive_setPassword, ZEND_ACC_PUBLIC) ZEND_ME(ZipArchive, close, arginfo_class_ZipArchive_close, ZEND_ACC_PUBLIC) ZEND_ME(ZipArchive, count, arginfo_class_ZipArchive_count, ZEND_ACC_PUBLIC) diff --git a/ext/zip/tests/ziparchive_openbuffer.phpt b/ext/zip/tests/ziparchive_openbuffer.phpt new file mode 100644 index 0000000000000..87b471d3bc5f2 --- /dev/null +++ b/ext/zip/tests/ziparchive_openbuffer.phpt @@ -0,0 +1,28 @@ +--TEST-- +ZipArchive::openBuffer() method +--EXTENSIONS-- +zip +--FILE-- +openBuffer(file_get_contents(__DIR__."/test_procedural.zip")); + +for ($i = 0; $i < $zip->numFiles; $i++) { + $stat = $zip->statIndex($i); + echo $stat['name'] . "\n"; +} + +// Zip is read-only, not allowed +var_dump($zip->addFromString("foobar/baz", "baz")); +var_dump($zip->addEmptyDir("blub")); + +var_dump($zip->close()); +?> +--EXPECTF-- +foo +bar +foobar/ +foobar/baz +bool(false) +bool(false) +bool(true) From ccd3914be91d05dc74a587d214dc3af647c47938 Mon Sep 17 00:00:00 2001 From: Shyim Date: Sat, 22 Jun 2024 13:45:45 +0700 Subject: [PATCH 2/2] remove tentative return annotation --- ext/zip/php_zip.stub.php | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/zip/php_zip.stub.php b/ext/zip/php_zip.stub.php index 0c0236fe845c5..7ffbf699e5dda 100644 --- a/ext/zip/php_zip.stub.php +++ b/ext/zip/php_zip.stub.php @@ -641,7 +641,6 @@ class ZipArchive implements Countable /** @tentative-return-type */ public function open(string $filename, int $flags = 0): bool|int {} - /** @tentative-return-type */ public function openBuffer(string $data): void {} /**