From 20dd09be679d66cd383a846a6b91c50ba912491d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Wed, 22 Apr 2020 10:37:49 +0200 Subject: [PATCH] Add clone support for Curl object --- ext/curl/interface.c | 54 ++++++++++++++++--- ext/curl/multi.c | 7 +-- ext/curl/php_curl.h | 3 +- ext/curl/tests/curl_handle_clone.phpt | 26 +++++++++ .../posix_ttyname_error_wrongparams.phpt | 7 ++- 5 files changed, 80 insertions(+), 17 deletions(-) create mode 100644 ext/curl/tests/curl_handle_clone.phpt diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 9dbeefb2953c3..c90bb84735931 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -22,6 +22,7 @@ #include "php.h" #include "Zend/zend_interfaces.h" +#include "Zend/zend_exceptions.h" #if HAVE_CURL @@ -239,6 +240,9 @@ static zend_object *curl_create_object(zend_class_entry *class_type); static void curl_free_obj(zend_object *object); static HashTable *curl_get_gc(zend_object *object, zval **table, int *n); static zend_function *curl_get_constructor(zend_object *object); +static zend_object *curl_clone_obj(zend_object *object); +php_curl *alloc_curl_handle_from_zval(zval *curl); +static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields); static const zend_function_entry curl_object_methods[] = { PHP_FE_END @@ -1203,7 +1207,7 @@ PHP_MINIT_FUNCTION(curl) curl_object_handlers.free_obj = curl_free_obj; curl_object_handlers.get_gc = curl_get_gc; curl_object_handlers.get_constructor = curl_get_constructor; - curl_object_handlers.clone_obj = NULL; + curl_object_handlers.clone_obj = curl_clone_obj; curl_multi_register_class(); curl_share_register_class(); @@ -1230,6 +1234,38 @@ static zend_function *curl_get_constructor(zend_object *object) { return NULL; } +static zend_object *curl_clone_obj(zend_object *object) { + php_curl *ch; + CURL *cp; + zval *postfields; + zend_object *clone_object; + php_curl *clone_ch; + + clone_object = curl_create_object(curl_ce); + clone_ch = curl_from_obj(clone_object); + clone_ch = alloc_curl_handle(clone_ch); + + ch = curl_from_obj(object); + cp = curl_easy_duphandle(ch->cp); + if (!cp) { + zend_throw_exception(NULL, "Cannot clone unconstructed Curl object", 0); + return &clone_ch->std; + } + + clone_ch->cp = cp; + _php_setup_easy_copy_handlers(clone_ch, ch); + + postfields = &clone_ch->postfields; + if (Z_TYPE_P(postfields) != IS_UNDEF) { + if (build_mime_structure_from_hash(clone_ch, postfields) != SUCCESS) { + zend_throw_exception(NULL, "Cannot clone unconstructed Curl object", 0); + return &clone_ch->std; + } + } + + return &clone_ch->std; +} + static HashTable *curl_get_gc(zend_object *object, zval **table, int *n) { php_curl *curl = curl_from_obj(object); @@ -1692,15 +1728,18 @@ PHP_FUNCTION(curl_version) } /* }}} */ -/* {{{ alloc_curl_handle - */ -php_curl *alloc_curl_handle(zval *curl) +php_curl *alloc_curl_handle_from_zval(zval *curl) { php_curl *ch; object_init_ex(curl, curl_ce); ch = Z_CURL_P(curl); + return alloc_curl_handle(ch); +} + +php_curl *alloc_curl_handle(php_curl *ch) +{ ch->to_free = ecalloc(1, sizeof(struct _php_curl_free)); ch->handlers = ecalloc(1, sizeof(php_curl_handlers)); ch->handlers->write = ecalloc(1, sizeof(php_curl_write)); @@ -1723,6 +1762,7 @@ php_curl *alloc_curl_handle(zval *curl) return ch; } + /* }}} */ /* {{{ create_certinfo @@ -1813,7 +1853,7 @@ PHP_FUNCTION(curl_init) RETURN_FALSE; } - ch = alloc_curl_handle(return_value); + ch = alloc_curl_handle_from_zval(return_value); ch->cp = cp; @@ -2123,7 +2163,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields Copy a cURL handle along with all of it's preferences */ PHP_FUNCTION(curl_copy_handle) { - php_curl *ch; + php_curl *ch; CURL *cp; zval *zid; php_curl *dupch; @@ -2141,7 +2181,7 @@ PHP_FUNCTION(curl_copy_handle) RETURN_FALSE; } - dupch = alloc_curl_handle(return_value); + dupch = alloc_curl_handle_from_zval(return_value); dupch->cp = cp; _php_setup_easy_copy_handlers(dupch, ch); diff --git a/ext/curl/multi.c b/ext/curl/multi.c index e3603b5eb9fbc..f7534c23fa310 100644 --- a/ext/curl/multi.c +++ b/ext/curl/multi.c @@ -114,11 +114,8 @@ void _php_curl_multi_cleanup_list(void *data) /* {{{ */ if (!z_ch) { return; } - if (!Z_RES_P(z_ch)->ptr) { - return; - } - zend_list_delete(Z_RES_P(z_ch)); + zval_ptr_dtor(z_ch); } /* }}} */ @@ -401,7 +398,7 @@ static int _php_server_push_callback(CURL *parent_ch, CURL *easy, size_t num_hea parent = Z_CURL_P(pz_parent_ch); - ch = alloc_curl_handle(&pz_ch); + ch = alloc_curl_handle_from_zval(&pz_ch); ch->cp = easy; _php_setup_easy_copy_handlers(ch, parent); diff --git a/ext/curl/php_curl.h b/ext/curl/php_curl.h index 624b2d5acf904..d216f9cd8eec3 100644 --- a/ext/curl/php_curl.h +++ b/ext/curl/php_curl.h @@ -151,7 +151,8 @@ typedef struct { zend_object std; } php_curlsh; -php_curl *alloc_curl_handle(zval *curl); +php_curl *alloc_curl_handle_from_zval(zval *curl); +php_curl *alloc_curl_handle(php_curl *ch); void _php_curl_cleanup_handle(php_curl *); void _php_curl_multi_cleanup_list(void *data); void _php_curl_verify_handlers(php_curl *ch, int reporterror); diff --git a/ext/curl/tests/curl_handle_clone.phpt b/ext/curl/tests/curl_handle_clone.phpt new file mode 100644 index 0000000000000..aa1251cbe01a9 --- /dev/null +++ b/ext/curl/tests/curl_handle_clone.phpt @@ -0,0 +1,26 @@ +--TEST-- +Test that cloning of Curl objects is supported +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(true) +Hello World! +Hello World! diff --git a/ext/posix/tests/posix_ttyname_error_wrongparams.phpt b/ext/posix/tests/posix_ttyname_error_wrongparams.phpt index 92cf671c1dd50..8d10ce5497757 100644 --- a/ext/posix/tests/posix_ttyname_error_wrongparams.phpt +++ b/ext/posix/tests/posix_ttyname_error_wrongparams.phpt @@ -12,16 +12,15 @@ PHP Testfest Berlin 2009-05-10 if (!extension_loaded('posix')) { die('SKIP - POSIX extension not available'); } - - if (!function_exists('curl_init')) { - die('SKIP - Function curl_init() not available'); + if (!extension_loaded('sockets')) { + die('SKIP - Sockets extension not available'); } ?> --FILE-- getMessage(), "\n"; }