mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
add ZipArchive::registerProgressCallback and ZipArchive::registerCancelCallback methods
This commit is contained in:
parent
7e7a85e881
commit
3af1cee884
7 changed files with 286 additions and 0 deletions
|
@ -35,6 +35,22 @@ if test "$PHP_ZIP" != "no"; then
|
|||
$LIBZIP_LIBS
|
||||
])
|
||||
|
||||
PHP_CHECK_LIBRARY(zip, zip_register_progress_callback_with_state,
|
||||
[
|
||||
AC_DEFINE(HAVE_PROGRESS_CALLBACK, 1, [Libzip >= 1.3.0 with zip_register_progress_callback_with_state function])
|
||||
], [
|
||||
], [
|
||||
$LIBZIP_LIBS
|
||||
])
|
||||
|
||||
PHP_CHECK_LIBRARY(zip, zip_register_cancel_callback_with_state,
|
||||
[
|
||||
AC_DEFINE(HAVE_CANCEL_CALLBACK, 1, [Libzip >= 1.6.0 with zip_register_cancel_callback_with_state function])
|
||||
], [
|
||||
], [
|
||||
$LIBZIP_LIBS
|
||||
])
|
||||
|
||||
AC_DEFINE(HAVE_ZIP,1,[ ])
|
||||
|
||||
PHP_ZIP_SOURCES="php_zip.c zip_stream.c"
|
||||
|
|
|
@ -933,6 +933,30 @@ static HashTable *php_zip_get_properties(zend_object *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);
|
||||
|
@ -959,6 +983,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);
|
||||
|
||||
|
@ -2774,6 +2808,121 @@ static ZIPARCHIVE_METHOD(getStream)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
#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;
|
||||
|
||||
ZVAL_DOUBLE(&cb_args[0], state);
|
||||
if (call_user_function_ex(EG(function_table), NULL, &obj->progress_callback, &cb_retval, 1, cb_args, 0, NULL) == SUCCESS && !Z_ISUNDEF(cb_retval)) {
|
||||
zval_ptr_dtor(&cb_retval);
|
||||
}
|
||||
}
|
||||
|
||||
/* {{{ proto bool ZipArchive::registerProgressCallback(double rate, callable callback)
|
||||
register a progression callback: void callback(double state); */
|
||||
static ZIPARCHIVE_METHOD(registerProgressCallback)
|
||||
{
|
||||
struct zip *intern;
|
||||
zval *self = getThis();
|
||||
double rate;
|
||||
zval *callback;
|
||||
ze_zip_object *obj;
|
||||
|
||||
if (!self) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
ZIP_FROM_OBJECT(intern, self);
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "dz", &rate, &callback) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* callable? */
|
||||
if (!zend_is_callable(callback, 0, NULL)) {
|
||||
zend_string *callback_name = zend_get_callable_name(callback);
|
||||
php_error_docref(NULL, E_WARNING, "Invalid callback '%s'", ZSTR_VAL(callback_name));
|
||||
zend_string_release_ex(callback_name, 0);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
obj = Z_ZIP_P(self);
|
||||
|
||||
/* free if called twice */
|
||||
_php_zip_progress_callback_free(obj);
|
||||
|
||||
/* register */
|
||||
ZVAL_COPY(&obj->progress_callback, callback);
|
||||
if (zip_register_progress_callback_with_state(intern, rate, _php_zip_progress_callback, _php_zip_progress_callback_free, obj)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
#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_ex(EG(function_table), NULL, &obj->cancel_callback, &cb_retval, 0, NULL, 0, NULL) == SUCCESS && !Z_ISUNDEF(cb_retval)) {
|
||||
retval = zval_get_long(&cb_retval);
|
||||
zval_ptr_dtor(&cb_retval);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* {{{ proto bool ZipArchive::registerCancelCallback(callable callback)
|
||||
register a progression callback: int callback(double state); */
|
||||
static ZIPARCHIVE_METHOD(registerCancelCallback)
|
||||
{
|
||||
struct zip *intern;
|
||||
zval *self = getThis();
|
||||
zval *callback;
|
||||
ze_zip_object *obj;
|
||||
|
||||
if (!self) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
ZIP_FROM_OBJECT(intern, self);
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &callback) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* callable? */
|
||||
if (!zend_is_callable(callback, 0, NULL)) {
|
||||
zend_string *callback_name = zend_get_callable_name(callback);
|
||||
php_error_docref(NULL, E_WARNING, "Invalid callback '%s'", ZSTR_VAL(callback_name));
|
||||
zend_string_release_ex(callback_name, 0);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
obj = Z_ZIP_P(self);
|
||||
|
||||
/* free if called twice */
|
||||
_php_zip_cancel_callback_free(obj);
|
||||
|
||||
/* register */
|
||||
ZVAL_COPY(&obj->cancel_callback, callback);
|
||||
if (zip_register_cancel_callback_with_state(intern, _php_zip_cancel_callback, _php_zip_cancel_callback_free, obj)) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
/* {{{ ze_zip_object_class_functions */
|
||||
static const zend_function_entry zip_class_functions[] = {
|
||||
ZIPARCHIVE_ME(open, arginfo_class_ZipArchive_open, ZEND_ACC_PUBLIC)
|
||||
|
@ -2824,6 +2973,13 @@ static const zend_function_entry zip_class_functions[] = {
|
|||
ZIPARCHIVE_ME(setEncryptionName, arginfo_class_ZipArchive_setEncryptionName, ZEND_ACC_PUBLIC)
|
||||
ZIPARCHIVE_ME(setEncryptionIndex, arginfo_class_ZipArchive_setEncryptionIndex, ZEND_ACC_PUBLIC)
|
||||
#endif
|
||||
#ifdef HAVE_PROGRESS_CALLBACK
|
||||
ZIPARCHIVE_ME(registerProgressCallback, arginfo_class_ZipArchive_registerProgressCallback, ZEND_ACC_PUBLIC)
|
||||
#endif
|
||||
#ifdef HAVE_CANCEL_CALLBACK
|
||||
ZIPARCHIVE_ME(registerCancelCallback, arginfo_class_ZipArchive_registerCancelCallback, ZEND_ACC_PUBLIC)
|
||||
#endif
|
||||
|
||||
PHP_FE_END
|
||||
};
|
||||
/* }}} */
|
||||
|
|
|
@ -60,6 +60,12 @@ typedef struct _ze_zip_object {
|
|||
int filename_len;
|
||||
int buffers_cnt;
|
||||
zend_object zo;
|
||||
#ifdef HAVE_PROGRESS_CALLBACK
|
||||
zval progress_callback;
|
||||
#endif
|
||||
#ifdef HAVE_CANCEL_CALLBACK
|
||||
zval cancel_callback;
|
||||
#endif
|
||||
} ze_zip_object;
|
||||
|
||||
static inline ze_zip_object *php_zip_fetch_object(zend_object *obj) {
|
||||
|
|
|
@ -90,11 +90,13 @@ class ZipArchive
|
|||
/** @return null|false */
|
||||
public function setCommentName(string $name, string $comment) {}
|
||||
|
||||
#ifdef HAVE_SET_MTIME
|
||||
/** @return null|false */
|
||||
public function setMtimeIndex(int $index, int $timestamp, int $flags = 0) {}
|
||||
|
||||
/** @return null|false */
|
||||
public function setMtimeName(string $name, int $timestamp, int $flags = 0) {}
|
||||
#endif
|
||||
|
||||
/** @return string|false */
|
||||
public function getCommentIndex(int $index, int $flags = 0) {}
|
||||
|
@ -171,4 +173,14 @@ class ZipArchive
|
|||
/** @return bool */
|
||||
public function setEncryptionIndex(int $index, int $method, string $password = UNKNOWN) {}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PROGRESS_CALLBACK
|
||||
/** @return bool */
|
||||
public function registerProgressCallback(float $rate, callable $callback) {}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CANCEL_CALLBACK
|
||||
/** @return bool */
|
||||
public function registerCancelCallback(callable $callback) {}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -111,17 +111,21 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_setCommentName, 0, 0, 2)
|
|||
ZEND_ARG_TYPE_INFO(0, comment, IS_STRING, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#if defined(HAVE_SET_MTIME)
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_setMtimeIndex, 0, 0, 2)
|
||||
ZEND_ARG_TYPE_INFO(0, index, IS_LONG, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, timestamp, IS_LONG, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SET_MTIME)
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_setMtimeName, 0, 0, 2)
|
||||
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, timestamp, IS_LONG, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
#endif
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_getCommentIndex, 0, 0, 1)
|
||||
ZEND_ARG_TYPE_INFO(0, index, IS_LONG, 0)
|
||||
|
@ -241,3 +245,16 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_setEncryptionIndex, 0, 0, 2)
|
|||
ZEND_ARG_TYPE_INFO(0, password, IS_STRING, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PROGRESS_CALLBACK)
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_registerProgressCallback, 0, 0, 2)
|
||||
ZEND_ARG_TYPE_INFO(0, rate, IS_DOUBLE, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CANCEL_CALLBACK)
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_registerCancelCallback, 0, 0, 1)
|
||||
ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
#endif
|
||||
|
|
39
ext/zip/tests/oo_cancel.phpt
Normal file
39
ext/zip/tests/oo_cancel.phpt
Normal file
|
@ -0,0 +1,39 @@
|
|||
--TEST--
|
||||
registerCancelCallback
|
||||
--SKIPIF--
|
||||
<?php
|
||||
/* $Id$ */
|
||||
if(!extension_loaded('zip')) die('skip');
|
||||
if (!method_exists('ZipArchive', 'registerCancelCallback')) die('skip libzip too old');
|
||||
?>
|
||||
--INI--
|
||||
date.timezone=UTC
|
||||
--FILE--
|
||||
<?php
|
||||
$dirname = dirname(__FILE__) . '/';
|
||||
$file = $dirname . '__tmp_oo_progress.zip';
|
||||
|
||||
@unlink($file);
|
||||
|
||||
$zip = new ZipArchive;
|
||||
if (!$zip->open($file, ZIPARCHIVE::CREATE)) {
|
||||
exit('failed');
|
||||
}
|
||||
|
||||
var_dump($zip->registerCancelCallback(function () {
|
||||
// Always cancel
|
||||
return -1;
|
||||
}));
|
||||
var_dump($zip->addFromString(PHP_BINARY, 'entry #1'));
|
||||
|
||||
var_dump($zip->close());
|
||||
@unlink($file);
|
||||
?>
|
||||
Done
|
||||
--EXPECTF--
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
||||
Warning: ZipArchive::close(): Operation cancelled in %s
|
||||
bool(false)
|
||||
Done
|
40
ext/zip/tests/oo_progress.phpt
Normal file
40
ext/zip/tests/oo_progress.phpt
Normal file
|
@ -0,0 +1,40 @@
|
|||
--TEST--
|
||||
registerProgressCallback
|
||||
--SKIPIF--
|
||||
<?php
|
||||
/* $Id$ */
|
||||
if(!extension_loaded('zip')) die('skip');
|
||||
if (!method_exists('ZipArchive', 'registerProgressCallback')) die('skip libzip too old');
|
||||
?>
|
||||
--INI--
|
||||
date.timezone=UTC
|
||||
--FILE--
|
||||
<?php
|
||||
$dirname = dirname(__FILE__) . '/';
|
||||
$file = $dirname . '__tmp_oo_progress.zip';
|
||||
|
||||
@unlink($file);
|
||||
|
||||
$zip = new ZipArchive;
|
||||
if (!$zip->open($file, ZIPARCHIVE::CREATE)) {
|
||||
exit('failed');
|
||||
}
|
||||
|
||||
var_dump($zip->registerProgressCallback(0.5, function ($r) {
|
||||
// Only check start/end as intermediate is not reliable
|
||||
if ($r == 0.0) echo "start\n";
|
||||
if ($r == 1.0) echo "end\n";
|
||||
}));
|
||||
var_dump($zip->addFromString('foo', 'entry #1'));
|
||||
|
||||
var_dump($zip->close());
|
||||
unlink($file);
|
||||
?>
|
||||
Done
|
||||
--EXPECTF--
|
||||
bool(true)
|
||||
bool(true)
|
||||
start
|
||||
end
|
||||
bool(true)
|
||||
Done
|
Loading…
Add table
Add a link
Reference in a new issue