diff --git a/UPGRADING b/UPGRADING index 7e8b5971bac..794b91f9432 100644 --- a/UPGRADING +++ b/UPGRADING @@ -739,6 +739,21 @@ PHP 8.0 UPGRADE NOTES - CURL: . The CURL extension now requires at least libcurl 7.29.0. + . curl_init() will now return a CurlHandle object rather than a resource. + Return value checks using is_resource() should be replaced with + checks for `false`. The curl_close() function no longer has an effect, + instead the CurlHandle instance is automatically destroyed if it is no + longer referenced. + . curl_multi_init() will now return a CurlMultiHandle object rather than a + resource. Return value checks using is_resource() should be replaced with + checks for `false`. The curl_multi_close() function no longer has an effect, + instead the CurlMultiHandle instance is automatically destroyed if it is no + longer referenced. + . curl_share_init() will now return a CurlShareHandle object rather than a + resource. Return value checks using is_resource() should be replaced with + checks for `false`. The curl_share_close() function no longer has an effect, + instead the CurlShareHandle instance is automatically destroyed if it is no + longer referenced. - Enchant: . The enchant extension now uses libenchant-2 by default when available. diff --git a/ext/curl/curl.stub.php b/ext/curl/curl.stub.php index ac998c45650..f7e20e30f6e 100644 --- a/ext/curl/curl.stub.php +++ b/ext/curl/curl.stub.php @@ -2,120 +2,82 @@ /** @generate-function-entries */ -/** @param resource $handle */ -function curl_close($handle): void {} +final class CurlHandle +{ +} -/** - * @param resource $handle - * @return resource|false - */ -function curl_copy_handle($handle) {} +final class CurlMultiHandle +{ +} -/** @param resource $handle */ -function curl_errno($handle): int {} +final class CurlShareHandle +{ +} -/** @param resource $handle */ -function curl_error($handle): string {} +function curl_close(CurlHandle $handle): void {} + +function curl_copy_handle(CurlHandle $handle): CurlHandle|false {} + +function curl_errno(CurlHandle $handle): int {} + +function curl_error(CurlHandle $handle): string {} #if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */ -/** @param resource $handle */ -function curl_escape($handle, string $string): string|false {} +function curl_escape(CurlHandle $handle, string $string): string|false {} -/** @param resource $handle */ -function curl_unescape($handle, string $string): string|false {} +function curl_unescape(CurlHandle $handle, string $string): string|false {} -/** - * @param resource $multi_handle - * @param mixed $value - */ -function curl_multi_setopt($multi_handle, int $option, $value): bool {} +function curl_multi_setopt(CurlMultiHandle $multi_handle, int $option, mixed $value): bool {} #endif -/** @param resource $handle */ -function curl_exec($handle): string|bool {} +function curl_exec(CurlHandle $handle): string|bool {} -function curl_file_create( - string $filename, - string $mimetype = UNKNOWN, - string $postname = UNKNOWN -): CURLFile {} +function curl_file_create(string $filename, string $mimetype = UNKNOWN, string $postname = UNKNOWN): CURLFile {} -/** - * @param resource $handle - * @return mixed - */ -function curl_getinfo($handle, int $option = UNKNOWN) {} +function curl_getinfo(CurlHandle $handle, int $option = UNKNOWN): mixed {} -/** - * @param resource $handle - * @return resource|false - */ -function curl_init(string $url = UNKNOWN) {} +function curl_init(string $url = UNKNOWN): CurlHandle|false {} -/** - * @param resource $multi_handle - * @param resource $handle - */ -function curl_multi_add_handle($multi_handle, $handle): int {} +function curl_multi_add_handle(CurlMultiHandle $multi_handle, CurlHandle $handle): int {} -/** @param resource $multi_handle */ -function curl_multi_close($multi_handle): void {} +function curl_multi_close(CurlMultiHandle $multi_handle): void {} -/** @param resource $multi_handle */ -function curl_multi_errno($multi_handle): int {} +function curl_multi_errno(CurlMultiHandle $multi_handle): int {} -/** @param resource $multi_handle */ -function curl_multi_exec($multi_handle, &$still_running): int {} +/** @param int $still_running */ +function curl_multi_exec(CurlMultiHandle $multi_handle, &$still_running): int {} -/** @param resource $multi_handle */ -function curl_multi_getcontent($multi_handle): ?string {} +function curl_multi_getcontent(CurlHandle $multi_handle): ?string {} -/** @param resource $multi_handle */ -function curl_multi_info_read($multi_handle, &$msgs_in_queue = null): array|false {} +/** @param int|null $msgs_in_queue */ +function curl_multi_info_read(CurlMultiHandle $multi_handle, &$msgs_in_queue = null): array|false {} -/** @return resource */ -function curl_multi_init() {} +function curl_multi_init(): CurlMultiHandle {} -/** - * @param resource $multi_handle - * @param resource $handle - */ -function curl_multi_remove_handle($multi_handle, $handle): int {} +function curl_multi_remove_handle(CurlMultiHandle $multi_handle, CurlHandle $handle): int {} -/** @param resource $multi_handle */ -function curl_multi_select($multi_handle, float $timeout = 1.0): int {} +function curl_multi_select(CurlMultiHandle $multi_handle, float $timeout = 1.0): int {} function curl_multi_strerror(int $error_number): ?string {} #if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */ -/** @param resource $handle */ -function curl_pause($handle, int $bitmask): int {} +function curl_pause(CurlHandle $handle, int $bitmask): int {} #endif -/** @param resource $handle */ -function curl_reset($handle): void {} +function curl_reset(CurlHandle $handle): void {} -/** @param resource $handle */ -function curl_setopt_array($handle, array $options): bool {} +function curl_setopt_array(CurlHandle $handle, array $options): bool {} -/** - * @param resource $handle - * @param mixed $value - */ -function curl_setopt($handle, int $option, $value): bool {} +function curl_setopt(CurlHandle $handle, int $option, mixed $value): bool {} -/** @param resource $share_handle */ -function curl_share_close($share_handle): void {} +function curl_share_close(CurlShareHandle $share_handle): void {} -/** @param resource $share_handle */ -function curl_share_errno($share_handle): int {} +function curl_share_errno(CurlShareHandle $share_handle): int {} -/** @return resource */ -function curl_share_init() {} +function curl_share_init(): CurlShareHandle {} -/** @param resource $share_handle */ -function curl_share_setopt($share_handle, int $option, $value): bool {} +function curl_share_setopt(CurlShareHandle $share_handle, int $option, mixed $value): bool {} function curl_share_strerror(int $error_number): ?string {} diff --git a/ext/curl/curl_arginfo.h b/ext/curl/curl_arginfo.h index efc57e91487..72f68a63079 100644 --- a/ext/curl/curl_arginfo.h +++ b/ext/curl/curl_arginfo.h @@ -1,24 +1,24 @@ /* This is a generated file, edit the .stub.php file instead. */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_close, 0, 1, IS_VOID, 0) - ZEND_ARG_INFO(0, handle) + ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_copy_handle, 0, 0, 1) - ZEND_ARG_INFO(0, handle) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_curl_copy_handle, 0, 1, CurlHandle, MAY_BE_FALSE) + ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_errno, 0, 1, IS_LONG, 0) - ZEND_ARG_INFO(0, handle) + ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_error, 0, 1, IS_STRING, 0) - ZEND_ARG_INFO(0, handle) + ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) ZEND_END_ARG_INFO() #if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_curl_escape, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) - ZEND_ARG_INFO(0, handle) + ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0) ZEND_END_ARG_INFO() #endif @@ -29,14 +29,14 @@ ZEND_END_ARG_INFO() #if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_multi_setopt, 0, 3, _IS_BOOL, 0) - ZEND_ARG_INFO(0, multi_handle) + ZEND_ARG_OBJ_INFO(0, multi_handle, CurlMultiHandle, 0) ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0) - ZEND_ARG_INFO(0, value) + ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) ZEND_END_ARG_INFO() #endif ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_curl_exec, 0, 1, MAY_BE_STRING|MAY_BE_BOOL) - ZEND_ARG_INFO(0, handle) + ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_curl_file_create, 0, 1, CURLFile, 0) @@ -45,49 +45,49 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_curl_file_create, 0, 1, CURLFile, ZEND_ARG_TYPE_INFO(0, postname, IS_STRING, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_getinfo, 0, 0, 1) - ZEND_ARG_INFO(0, handle) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_getinfo, 0, 1, IS_MIXED, 0) + ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_init, 0, 0, 0) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_curl_init, 0, 0, CurlHandle, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, url, IS_STRING, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_multi_add_handle, 0, 2, IS_LONG, 0) - ZEND_ARG_INFO(0, multi_handle) - ZEND_ARG_INFO(0, handle) + ZEND_ARG_OBJ_INFO(0, multi_handle, CurlMultiHandle, 0) + ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_multi_close, 0, 1, IS_VOID, 0) - ZEND_ARG_INFO(0, multi_handle) + ZEND_ARG_OBJ_INFO(0, multi_handle, CurlMultiHandle, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_multi_errno, 0, 1, IS_LONG, 0) - ZEND_ARG_INFO(0, multi_handle) + ZEND_ARG_OBJ_INFO(0, multi_handle, CurlMultiHandle, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_multi_exec, 0, 2, IS_LONG, 0) - ZEND_ARG_INFO(0, multi_handle) + ZEND_ARG_OBJ_INFO(0, multi_handle, CurlMultiHandle, 0) ZEND_ARG_INFO(1, still_running) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_multi_getcontent, 0, 1, IS_STRING, 1) - ZEND_ARG_INFO(0, multi_handle) + ZEND_ARG_OBJ_INFO(0, multi_handle, CurlHandle, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_curl_multi_info_read, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) - ZEND_ARG_INFO(0, multi_handle) + ZEND_ARG_OBJ_INFO(0, multi_handle, CurlMultiHandle, 0) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, msgs_in_queue, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_init, 0, 0, 0) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_curl_multi_init, 0, 0, CurlMultiHandle, 0) ZEND_END_ARG_INFO() #define arginfo_curl_multi_remove_handle arginfo_curl_multi_add_handle ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_multi_select, 0, 1, IS_LONG, 0) - ZEND_ARG_INFO(0, multi_handle) + ZEND_ARG_OBJ_INFO(0, multi_handle, CurlMultiHandle, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeout, IS_DOUBLE, 0, "1.0") ZEND_END_ARG_INFO() @@ -97,7 +97,7 @@ ZEND_END_ARG_INFO() #if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_pause, 0, 2, IS_LONG, 0) - ZEND_ARG_INFO(0, handle) + ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) ZEND_ARG_TYPE_INFO(0, bitmask, IS_LONG, 0) ZEND_END_ARG_INFO() #endif @@ -105,30 +105,31 @@ ZEND_END_ARG_INFO() #define arginfo_curl_reset arginfo_curl_close ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_setopt_array, 0, 2, _IS_BOOL, 0) - ZEND_ARG_INFO(0, handle) + ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) ZEND_ARG_TYPE_INFO(0, options, IS_ARRAY, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_setopt, 0, 3, _IS_BOOL, 0) - ZEND_ARG_INFO(0, handle) + ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0) - ZEND_ARG_INFO(0, value) + ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_share_close, 0, 1, IS_VOID, 0) - ZEND_ARG_INFO(0, share_handle) + ZEND_ARG_OBJ_INFO(0, share_handle, CurlShareHandle, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_share_errno, 0, 1, IS_LONG, 0) - ZEND_ARG_INFO(0, share_handle) + ZEND_ARG_OBJ_INFO(0, share_handle, CurlShareHandle, 0) ZEND_END_ARG_INFO() -#define arginfo_curl_share_init arginfo_curl_multi_init +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_curl_share_init, 0, 0, CurlShareHandle, 0) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_share_setopt, 0, 3, _IS_BOOL, 0) - ZEND_ARG_INFO(0, share_handle) + ZEND_ARG_OBJ_INFO(0, share_handle, CurlShareHandle, 0) ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0) - ZEND_ARG_INFO(0, value) + ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) ZEND_END_ARG_INFO() #define arginfo_curl_share_strerror arginfo_curl_multi_strerror @@ -225,3 +226,18 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(curl_version, arginfo_curl_version) ZEND_FE_END }; + + +static const zend_function_entry class_CurlHandle_methods[] = { + ZEND_FE_END +}; + + +static const zend_function_entry class_CurlMultiHandle_methods[] = { + ZEND_FE_END +}; + + +static const zend_function_entry class_CurlShareHandle_methods[] = { + ZEND_FE_END +}; diff --git a/ext/curl/interface.c b/ext/curl/interface.c index dc79a9e2d7c..bdc284b4abb 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -21,6 +21,8 @@ #endif #include "php.h" +#include "Zend/zend_interfaces.h" +#include "Zend/zend_exceptions.h" #ifdef HAVE_CURL @@ -63,10 +65,6 @@ #include "php_curl.h" #include "curl_arginfo.h" -int le_curl; -int le_curl_multi_handle; -int le_curl_share_handle; - #ifdef PHP_CURL_NEED_OPENSSL_TSL /* {{{ */ static MUTEX_T *php_curl_openssl_tsl = NULL; @@ -88,9 +86,6 @@ static ZEND_ATTRIBUTE_UNUSED unsigned long php_curl_ssl_id(void) #endif /* }}} */ -static void _php_curl_close_ex(php_curl *ch); -static void _php_curl_close(zend_resource *rsrc); - #define CAAL(s, v) add_assoc_long_ex(return_value, s, sizeof(s) - 1, (zend_long) v); #define CAAD(s, v) add_assoc_double_ex(return_value, s, sizeof(s) - 1, (double) v); #define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s) - 1, (char *) (v ? v : "")); @@ -235,6 +230,20 @@ zend_module_entry curl_module_entry = { ZEND_GET_MODULE (curl) #endif +/* CurlHandle class */ + +zend_class_entry *curl_ce; +zend_class_entry *curl_share_ce; +static zend_object_handlers curl_object_handlers; + +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 *init_curl_handle_into_zval(zval *curl); +static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields); + /* {{{ PHP_INI_BEGIN */ PHP_INI_BEGIN() PHP_INI_ENTRY("curl.cainfo", "", PHP_INI_SYSTEM, NULL) @@ -365,10 +374,6 @@ PHP_MINFO_FUNCTION(curl) */ PHP_MINIT_FUNCTION(curl) { - le_curl = zend_register_list_destructors_ex(_php_curl_close, NULL, "curl", module_number); - le_curl_multi_handle = zend_register_list_destructors_ex(_php_curl_multi_close, NULL, "curl_multi", module_number); - le_curl_share_handle = zend_register_list_destructors_ex(_php_curl_share_close, NULL, "curl_share", module_number); - REGISTER_INI_ENTRIES(); /* See http://curl.haxx.se/lxr/source/docs/libcurl/symbols-in-versions @@ -1185,12 +1190,119 @@ PHP_MINIT_FUNCTION(curl) return FAILURE; } + zend_class_entry ce; + INIT_CLASS_ENTRY(ce, "CurlHandle", class_CurlHandle_methods); + curl_ce = zend_register_internal_class(&ce); + curl_ce->ce_flags |= ZEND_ACC_FINAL; + curl_ce->create_object = curl_create_object; + curl_ce->serialize = zend_class_serialize_deny; + curl_ce->unserialize = zend_class_unserialize_deny; + + memcpy(&curl_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + curl_object_handlers.offset = XtOffsetOf(php_curl, std); + 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 = curl_clone_obj; + + curl_multi_register_class(class_CurlMultiHandle_methods); + curl_share_register_class(class_CurlShareHandle_methods); curlfile_register_class(); return SUCCESS; } /* }}} */ +/* CurlHandle class */ + +static zend_object *curl_create_object(zend_class_entry *class_type) { + php_curl *intern = zend_object_alloc(sizeof(php_curl), class_type); + + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &curl_object_handlers; + + return &intern->std; +} + +static zend_function *curl_get_constructor(zend_object *object) { + zend_throw_error(NULL, "Cannot directly construct CurlHandle, use curl_init() instead"); + 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); + init_curl_handle(clone_ch); + + ch = curl_from_obj(object); + cp = curl_easy_duphandle(ch->cp); + if (!cp) { + zend_throw_exception(NULL, "Failed to clone CurlHandle", 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, "Failed to clone CurlHandle", 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); + + zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); + + zend_get_gc_buffer_add_zval(gc_buffer, &curl->postfields); + if (curl->handlers) { + if (curl->handlers->read) { + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->read->func_name); + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->read->stream); + } + + if (curl->handlers->write) { + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->write->func_name); + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->write->stream); + } + + if (curl->handlers->write_header) { + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->write_header->func_name); + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->write_header->stream); + } + + if (curl->handlers->progress) { + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->progress->func_name); + } + +#if LIBCURL_VERSION_NUM >= 0x071500 + if (curl->handlers->fnmatch) { + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->fnmatch->func_name); + } +#endif + + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->std_err); + } + + zend_get_gc_buffer_use(gc_buffer, table, n); + + return zend_std_get_properties(object); +} + /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(curl) @@ -1255,8 +1367,8 @@ static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx) int error; zend_fcall_info fci; - GC_ADDREF(ch->res); - ZVAL_RES(&argv[0], ch->res); + GC_ADDREF(&ch->std); + ZVAL_OBJ(&argv[0], &ch->std); ZVAL_STRINGL(&argv[1], data, length); fci.size = sizeof(fci); @@ -1302,8 +1414,8 @@ static int curl_fnmatch(void *ctx, const char *pattern, const char *string) int error; zend_fcall_info fci; - GC_ADDREF(ch->res); - ZVAL_RES(&argv[0], ch->res); + GC_ADDREF(&ch->std); + ZVAL_OBJ(&argv[0], &ch->std); ZVAL_STRING(&argv[1], pattern); ZVAL_STRING(&argv[2], string); @@ -1354,8 +1466,8 @@ static size_t curl_progress(void *clientp, double dltotal, double dlnow, double int error; zend_fcall_info fci; - GC_ADDREF(ch->res); - ZVAL_RES(&argv[0], ch->res); + GC_ADDREF(&ch->std); + ZVAL_OBJ(&argv[0], &ch->std); ZVAL_LONG(&argv[1], (zend_long)dltotal); ZVAL_LONG(&argv[2], (zend_long)dlnow); ZVAL_LONG(&argv[3], (zend_long)ultotal); @@ -1408,8 +1520,8 @@ static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx) int error; zend_fcall_info fci; - GC_ADDREF(ch->res); - ZVAL_RES(&argv[0], ch->res); + GC_ADDREF(&ch->std); + ZVAL_OBJ(&argv[0], &ch->std); if (t->res) { GC_ADDREF(t->res); ZVAL_RES(&argv[1], t->res); @@ -1477,8 +1589,8 @@ static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx int error; zend_fcall_info fci; - GC_ADDREF(ch->res); - ZVAL_RES(&argv[0], ch->res); + GC_ADDREF(&ch->std); + ZVAL_OBJ(&argv[0], &ch->std); ZVAL_STRINGL(&argv[1], data, length); fci.size = sizeof(fci); @@ -1643,11 +1755,20 @@ PHP_FUNCTION(curl_version) } /* }}} */ -/* {{{ alloc_curl_handle - */ -php_curl *alloc_curl_handle() +php_curl *init_curl_handle_into_zval(zval *curl) +{ + php_curl *ch; + + object_init_ex(curl, curl_ce); + ch = Z_CURL_P(curl); + + init_curl_handle(ch); + + return ch; +} + +void init_curl_handle(php_curl *ch) { - php_curl *ch = ecalloc(1, sizeof(php_curl)); 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)); @@ -1666,11 +1787,9 @@ php_curl *alloc_curl_handle() ch->to_free->slist = emalloc(sizeof(HashTable)); zend_hash_init(ch->to_free->slist, 4, NULL, curl_free_slist, 0); -#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ ZVAL_UNDEF(&ch->postfields); -#endif - return ch; } + /* }}} */ /* {{{ create_certinfo @@ -1742,7 +1861,7 @@ static void _php_curl_set_default_options(php_curl *ch) } /* }}} */ -/* {{{ proto resource curl_init([string url]) +/* {{{ proto CurlHandle curl_init([string url]) Initialize a cURL session */ PHP_FUNCTION(curl_init) { @@ -1761,7 +1880,7 @@ PHP_FUNCTION(curl_init) RETURN_FALSE; } - ch = alloc_curl_handle(); + ch = init_curl_handle_into_zval(return_value); ch->cp = cp; @@ -1773,13 +1892,10 @@ PHP_FUNCTION(curl_init) if (url) { if (php_curl_option_url(ch, ZSTR_VAL(url), ZSTR_LEN(url)) == FAILURE) { - _php_curl_close_ex(ch); + zval_ptr_dtor(return_value); RETURN_FALSE; } } - - ZVAL_RES(return_value, zend_register_resource(ch, le_curl)); - ch->res = Z_RES_P(return_value); } /* }}} */ @@ -2070,24 +2186,21 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields } /* }}} */ -/* {{{ proto resource curl_copy_handle(resource ch) +/* {{{ proto CurlHandle curl_copy_handle(CurlHandle ch) Copy a cURL handle along with all of it's preferences */ PHP_FUNCTION(curl_copy_handle) { + php_curl *ch; CURL *cp; zval *zid; - php_curl *ch, *dupch; -#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ + php_curl *dupch; zval *postfields; -#endif ZEND_PARSE_PARAMETERS_START(1,1) - Z_PARAM_RESOURCE(zid) + Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) ZEND_PARSE_PARAMETERS_END(); - if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - RETURN_FALSE; - } + ch = Z_CURL_P(zid); cp = curl_easy_duphandle(ch->cp); if (!cp) { @@ -2095,24 +2208,19 @@ PHP_FUNCTION(curl_copy_handle) RETURN_FALSE; } - dupch = alloc_curl_handle(); + dupch = init_curl_handle_into_zval(return_value); dupch->cp = cp; _php_setup_easy_copy_handlers(dupch, ch); -#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ postfields = &ch->postfields; if (Z_TYPE_P(postfields) != IS_UNDEF) { if (build_mime_structure_from_hash(dupch, postfields) != SUCCESS) { - _php_curl_close_ex(dupch); + zval_ptr_dtor(return_value); php_error_docref(NULL, E_WARNING, "Cannot rebuild mime structure"); RETURN_FALSE; } } -#endif - - ZVAL_RES(return_value, zend_register_resource(dupch, le_curl)); - dupch->res = Z_RES_P(return_value); } /* }}} */ @@ -2742,8 +2850,8 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ case CURLOPT_SHARE: { - php_curlsh *sh; - if ((sh = (php_curlsh *)zend_fetch_resource_ex(zvalue, le_curl_share_handle_name, le_curl_share_handle))) { + if (Z_TYPE_P(zvalue) == IS_OBJECT && Z_OBJCE_P(zvalue) == curl_share_ce) { + php_curlsh *sh = Z_CURL_SHARE_P(zvalue); curl_easy_setopt(ch->cp, CURLOPT_SHARE, sh->share); } } @@ -2773,7 +2881,7 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ } /* }}} */ -/* {{{ proto bool curl_setopt(resource ch, int option, mixed value) +/* {{{ proto bool curl_setopt(CurlHandle ch, int option, mixed value) Set an option for a cURL transfer */ PHP_FUNCTION(curl_setopt) { @@ -2782,14 +2890,12 @@ PHP_FUNCTION(curl_setopt) php_curl *ch; ZEND_PARSE_PARAMETERS_START(3, 3) - Z_PARAM_RESOURCE(zid) + Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) Z_PARAM_LONG(options) Z_PARAM_ZVAL(zvalue) ZEND_PARSE_PARAMETERS_END(); - if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + ch = Z_CURL_P(zid); if (options <= 0 && options != CURLOPT_SAFE_UPLOAD) { php_error_docref(NULL, E_WARNING, "Invalid curl configuration option"); @@ -2804,7 +2910,7 @@ PHP_FUNCTION(curl_setopt) } /* }}} */ -/* {{{ proto bool curl_setopt_array(resource ch, array options) +/* {{{ proto bool curl_setopt_array(CurlHandle ch, array options) Set an array of option for a cURL transfer */ PHP_FUNCTION(curl_setopt_array) { @@ -2814,13 +2920,11 @@ PHP_FUNCTION(curl_setopt_array) zend_string *string_key; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(zid) + Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) Z_PARAM_ARRAY(arr) ZEND_PARSE_PARAMETERS_END(); - if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + ch = Z_CURL_P(zid); ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(arr), option, string_key, entry) { if (string_key) { @@ -2853,7 +2957,7 @@ void _php_curl_cleanup_handle(php_curl *ch) } /* }}} */ -/* {{{ proto bool curl_exec(resource ch) +/* {{{ proto bool curl_exec(CurlHandle ch) Perform a cURL session */ PHP_FUNCTION(curl_exec) { @@ -2862,12 +2966,10 @@ PHP_FUNCTION(curl_exec) php_curl *ch; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(zid) + Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) ZEND_PARSE_PARAMETERS_END(); - if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + ch = Z_CURL_P(zid); _php_curl_verify_handlers(ch, 1); @@ -2910,7 +3012,7 @@ PHP_FUNCTION(curl_exec) } /* }}} */ -/* {{{ proto mixed curl_getinfo(resource ch [, int option]) +/* {{{ proto mixed curl_getinfo(CurlHandle ch [, int option]) Get information regarding a specific transfer */ PHP_FUNCTION(curl_getinfo) { @@ -2919,14 +3021,12 @@ PHP_FUNCTION(curl_getinfo) zend_long option = 0; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_RESOURCE(zid) + Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) Z_PARAM_OPTIONAL Z_PARAM_LONG(option) ZEND_PARSE_PARAMETERS_END(); - if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + ch = Z_CURL_P(zid); if (ZEND_NUM_ARGS() < 2) { char *s_code; @@ -3165,7 +3265,7 @@ PHP_FUNCTION(curl_getinfo) } /* }}} */ -/* {{{ proto string curl_error(resource ch) +/* {{{ proto string curl_error(CurlHandle ch) Return a string contain the last error for the current session */ PHP_FUNCTION(curl_error) { @@ -3173,12 +3273,10 @@ PHP_FUNCTION(curl_error) php_curl *ch; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(zid) + Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) ZEND_PARSE_PARAMETERS_END(); - if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + ch = Z_CURL_P(zid); if (ch->err.no) { ch->err.str[CURL_ERROR_SIZE] = 0; @@ -3189,7 +3287,7 @@ PHP_FUNCTION(curl_error) } /* }}} */ -/* {{{ proto int curl_errno(resource ch) +/* {{{ proto int curl_errno(CurlHandle ch) Return an integer containing the last error number */ PHP_FUNCTION(curl_errno) { @@ -3197,18 +3295,16 @@ PHP_FUNCTION(curl_errno) php_curl *ch; ZEND_PARSE_PARAMETERS_START(1,1) - Z_PARAM_RESOURCE(zid) + Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) ZEND_PARSE_PARAMETERS_END(); - if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + ch = Z_CURL_P(zid); RETURN_LONG(ch->err.no); } /* }}} */ -/* {{{ proto void curl_close(resource ch) +/* {{{ proto void curl_close(CurlHandle ch) Close a cURL session */ PHP_FUNCTION(curl_close) { @@ -3216,26 +3312,22 @@ PHP_FUNCTION(curl_close) php_curl *ch; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(zid) + Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) ZEND_PARSE_PARAMETERS_END(); - if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + ch = Z_CURL_P(zid); if (ch->in_callback) { php_error_docref(NULL, E_WARNING, "Attempt to close cURL handle from a callback"); return; } - - zend_list_close(Z_RES_P(zid)); } /* }}} */ -/* {{{ _php_curl_close_ex() - List destructor for curl handles */ -static void _php_curl_close_ex(php_curl *ch) +static void curl_free_obj(zend_object *object) { + php_curl *ch = curl_from_obj(object); + #if PHP_CURL_DEBUG fprintf(stderr, "DTOR CALLED, ch = %x\n", ch); #endif @@ -3299,19 +3391,9 @@ static void _php_curl_close_ex(php_curl *ch) } efree(ch->handlers); -#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ zval_ptr_dtor(&ch->postfields); -#endif - efree(ch); -} -/* }}} */ -/* {{{ _php_curl_close() - List destructor for curl handles */ -static void _php_curl_close(zend_resource *rsrc) -{ - php_curl *ch = (php_curl *) rsrc->ptr; - _php_curl_close_ex(ch); + zend_object_std_dtor(&ch->std); } /* }}} */ @@ -3381,7 +3463,7 @@ static void _php_curl_reset_handlers(php_curl *ch) } /* }}} */ -/* {{{ proto void curl_reset(resource ch) +/* {{{ proto void curl_reset(CurlHandle ch) Reset all options of a libcurl session handle */ PHP_FUNCTION(curl_reset) { @@ -3389,12 +3471,10 @@ PHP_FUNCTION(curl_reset) php_curl *ch; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(zid) + Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) ZEND_PARSE_PARAMETERS_END(); - if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + ch = Z_CURL_P(zid); if (ch->in_callback) { php_error_docref(NULL, E_WARNING, "Attempt to reset cURL handle from a callback"); @@ -3407,7 +3487,7 @@ PHP_FUNCTION(curl_reset) } /* }}} */ -/* {{{ proto void curl_escape(resource ch, string str) +/* {{{ proto void curl_escape(CurlHandle ch, string str) URL encodes the given string */ PHP_FUNCTION(curl_escape) { @@ -3417,13 +3497,11 @@ PHP_FUNCTION(curl_escape) php_curl *ch; ZEND_PARSE_PARAMETERS_START(2,2) - Z_PARAM_RESOURCE(zid) + Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) Z_PARAM_STR(str) ZEND_PARSE_PARAMETERS_END(); - if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + ch = Z_CURL_P(zid); if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(str))) { RETURN_FALSE; @@ -3438,7 +3516,7 @@ PHP_FUNCTION(curl_escape) } /* }}} */ -/* {{{ proto void curl_unescape(resource ch, string str) +/* {{{ proto void curl_unescape(CurlHandle ch, string str) URL decodes the given string */ PHP_FUNCTION(curl_unescape) { @@ -3449,13 +3527,11 @@ PHP_FUNCTION(curl_unescape) php_curl *ch; ZEND_PARSE_PARAMETERS_START(2,2) - Z_PARAM_RESOURCE(zid) + Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) Z_PARAM_STR(str) ZEND_PARSE_PARAMETERS_END(); - if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + ch = Z_CURL_P(zid); if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(str))) { RETURN_FALSE; @@ -3470,7 +3546,7 @@ PHP_FUNCTION(curl_unescape) } /* }}} */ -/* {{{ proto void curl_pause(resource ch, int bitmask) +/* {{{ proto void curl_pause(CurlHandle ch, int bitmask) pause and unpause a connection */ PHP_FUNCTION(curl_pause) { @@ -3479,13 +3555,11 @@ PHP_FUNCTION(curl_pause) php_curl *ch; ZEND_PARSE_PARAMETERS_START(2,2) - Z_PARAM_RESOURCE(zid) + Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) Z_PARAM_LONG(bitmask) ZEND_PARSE_PARAMETERS_END(); - if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + ch = Z_CURL_P(zid); RETURN_LONG(curl_easy_pause(ch->cp, bitmask)); } diff --git a/ext/curl/multi.c b/ext/curl/multi.c index d8c1caac3c6..6a4c48ee185 100644 --- a/ext/curl/multi.c +++ b/ext/curl/multi.c @@ -21,6 +21,7 @@ #endif #include "php.h" +#include "Zend/zend_interfaces.h" #ifdef HAVE_CURL @@ -47,7 +48,17 @@ #define SAVE_CURLM_ERROR(__handle, __err) (__handle)->err.no = (int) __err; -/* {{{ proto resource curl_multi_init(void) +/* CurlMultiHandle class */ + +static zend_class_entry *curl_multi_ce; + +static inline php_curlm *curl_multi_from_obj(zend_object *obj) { + return (php_curlm *)((char *)(obj) - XtOffsetOf(php_curlm, std)); +} + +#define Z_CURL_MULTI_P(zv) curl_multi_from_obj(Z_OBJ_P(zv)) + +/* {{{ proto CurlMultiHandle curl_multi_init(void) Returns a new cURL multi handle */ PHP_FUNCTION(curl_multi_init) { @@ -55,17 +66,16 @@ PHP_FUNCTION(curl_multi_init) ZEND_PARSE_PARAMETERS_NONE(); - mh = ecalloc(1, sizeof(php_curlm)); + object_init_ex(return_value, curl_multi_ce); + mh = Z_CURL_MULTI_P(return_value); mh->multi = curl_multi_init(); mh->handlers = ecalloc(1, sizeof(php_curlm_handlers)); zend_llist_init(&mh->easyh, sizeof(zval), _php_curl_multi_cleanup_list, 0); - - RETURN_RES(zend_register_resource(mh, le_curl_multi_handle)); } /* }}} */ -/* {{{ proto int curl_multi_add_handle(resource mh, resource ch) +/* {{{ proto int curl_multi_add_handle(CurlMultiHandle mh, Curl ch) Add a normal cURL handle to a cURL multi handle */ PHP_FUNCTION(curl_multi_add_handle) { @@ -76,23 +86,18 @@ PHP_FUNCTION(curl_multi_add_handle) CURLMcode error = CURLM_OK; ZEND_PARSE_PARAMETERS_START(2,2) - Z_PARAM_RESOURCE(z_mh) - Z_PARAM_RESOURCE(z_ch) + Z_PARAM_OBJECT_OF_CLASS(z_mh, curl_multi_ce) + Z_PARAM_OBJECT_OF_CLASS(z_ch, curl_ce) ZEND_PARSE_PARAMETERS_END(); - if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) { - RETURN_THROWS(); - } - - if ((ch = (php_curl *)zend_fetch_resource(Z_RES_P(z_ch), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + mh = Z_CURL_MULTI_P(z_mh); + ch = Z_CURL_P(z_ch); _php_curl_verify_handlers(ch, 1); _php_curl_cleanup_handle(ch); - GC_ADDREF(Z_RES_P(z_ch)); + Z_ADDREF_P(z_ch); zend_llist_add_element(&mh->easyh, z_ch); error = curl_multi_add_handle(mh->multi, ch->cp); @@ -105,28 +110,17 @@ PHP_FUNCTION(curl_multi_add_handle) void _php_curl_multi_cleanup_list(void *data) /* {{{ */ { zval *z_ch = (zval *)data; - php_curl *ch; - if (!z_ch) { - return; - } - if (!Z_RES_P(z_ch)->ptr) { - return; - } - if ((ch = (php_curl *)zend_fetch_resource(Z_RES_P(z_ch), le_curl_name, le_curl)) == NULL) { - return; - } - - zend_list_delete(Z_RES_P(z_ch)); + zval_ptr_dtor(z_ch); } /* }}} */ /* Used internally as comparison routine passed to zend_list_del_element */ -static int curl_compare_resources( zval *z1, zval *z2 ) /* {{{ */ +static int curl_compare_objects( zval *z1, zval *z2 ) /* {{{ */ { return (Z_TYPE_P(z1) == Z_TYPE_P(z2) && - Z_TYPE_P(z1) == IS_RESOURCE && - Z_RES_P(z1) == Z_RES_P(z2)); + Z_TYPE_P(z1) == IS_OBJECT && + Z_OBJ_P(z1) == Z_OBJ_P(z2)); } /* }}} */ @@ -139,10 +133,7 @@ static zval *_php_curl_multi_find_easy_handle(php_curlm *mh, CURL *easy) /* {{{ for(pz_ch_temp = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch_temp; pz_ch_temp = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) { - - if ((tmp_ch = (php_curl *)zend_fetch_resource(Z_RES_P(pz_ch_temp), le_curl_name, le_curl)) == NULL) { - return NULL; - } + tmp_ch = Z_CURL_P(pz_ch_temp); if (tmp_ch->cp == easy) { return pz_ch_temp; @@ -153,7 +144,7 @@ static zval *_php_curl_multi_find_easy_handle(php_curlm *mh, CURL *easy) /* {{{ } /* }}} */ -/* {{{ proto int curl_multi_remove_handle(resource mh, resource ch) +/* {{{ proto int curl_multi_remove_handle(CurlMultiHandle mh, Curl ch) Remove a multi handle from a set of cURL handles */ PHP_FUNCTION(curl_multi_remove_handle) { @@ -164,28 +155,23 @@ PHP_FUNCTION(curl_multi_remove_handle) CURLMcode error = CURLM_OK; ZEND_PARSE_PARAMETERS_START(2,2) - Z_PARAM_RESOURCE(z_mh) - Z_PARAM_RESOURCE(z_ch) + Z_PARAM_OBJECT_OF_CLASS(z_mh, curl_multi_ce) + Z_PARAM_OBJECT_OF_CLASS(z_ch, curl_ce) ZEND_PARSE_PARAMETERS_END(); - if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) { - RETURN_THROWS(); - } - - if ((ch = (php_curl *)zend_fetch_resource(Z_RES_P(z_ch), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + mh = Z_CURL_MULTI_P(z_mh); + ch = Z_CURL_P(z_ch); error = curl_multi_remove_handle(mh->multi, ch->cp); SAVE_CURLM_ERROR(mh, error); RETVAL_LONG((zend_long) error); - zend_llist_del_element(&mh->easyh, z_ch, (int (*)(void *, void *))curl_compare_resources); + zend_llist_del_element(&mh->easyh, z_ch, (int (*)(void *, void *))curl_compare_objects); } /* }}} */ -/* {{{ proto int curl_multi_select(resource mh[, double timeout]) +/* {{{ proto int curl_multi_select(CurlMultiHandle mh[, double timeout]) Get all the sockets associated with the cURL extension, which can then be "selected" */ PHP_FUNCTION(curl_multi_select) { @@ -196,14 +182,12 @@ PHP_FUNCTION(curl_multi_select) CURLMcode error = CURLM_OK; ZEND_PARSE_PARAMETERS_START(1,2) - Z_PARAM_RESOURCE(z_mh) + Z_PARAM_OBJECT_OF_CLASS(z_mh, curl_multi_ce) Z_PARAM_OPTIONAL Z_PARAM_DOUBLE(timeout) ZEND_PARSE_PARAMETERS_END(); - if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) { - RETURN_THROWS(); - } + mh = Z_CURL_MULTI_P(z_mh); error = curl_multi_wait(mh->multi, NULL, 0, (unsigned long) (timeout * 1000.0), &numfds); if (CURLM_OK != error) { @@ -215,7 +199,7 @@ PHP_FUNCTION(curl_multi_select) } /* }}} */ -/* {{{ proto int curl_multi_exec(resource mh, int &still_running) +/* {{{ proto int curl_multi_exec(CurlMultiHandle mh, int &still_running) Run the sub-connections of the current cURL handle */ PHP_FUNCTION(curl_multi_exec) { @@ -226,13 +210,11 @@ PHP_FUNCTION(curl_multi_exec) CURLMcode error = CURLM_OK; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(z_mh) + Z_PARAM_OBJECT_OF_CLASS(z_mh, curl_multi_ce) Z_PARAM_ZVAL(z_still_running) ZEND_PARSE_PARAMETERS_END(); - if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) { - RETURN_THROWS(); - } + mh = Z_CURL_MULTI_P(z_mh); { zend_llist_position pos; @@ -241,10 +223,7 @@ PHP_FUNCTION(curl_multi_exec) for (pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch; pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) { - - if ((ch = (php_curl *)zend_fetch_resource(Z_RES_P(pz_ch), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + ch = Z_CURL_P(pz_ch); _php_curl_verify_handlers(ch, 1); } @@ -259,20 +238,18 @@ PHP_FUNCTION(curl_multi_exec) } /* }}} */ -/* {{{ proto string curl_multi_getcontent(resource ch) +/* {{{ proto string curl_multi_getcontent(CurlHandle ch) Return the content of a cURL handle if CURLOPT_RETURNTRANSFER is set */ PHP_FUNCTION(curl_multi_getcontent) { zval *z_ch; php_curl *ch; - ZEND_PARSE_PARAMETERS_START(1,1) - Z_PARAM_RESOURCE(z_ch) + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_OBJECT_OF_CLASS(z_ch, curl_ce) ZEND_PARSE_PARAMETERS_END(); - if ((ch = (php_curl *)zend_fetch_resource(Z_RES_P(z_ch), le_curl_name, le_curl)) == NULL) { - RETURN_THROWS(); - } + ch = Z_CURL_P(z_ch); if (ch->handlers->write->method == PHP_CURL_RETURN) { if (!ch->handlers->write->buf.s) { @@ -286,7 +263,7 @@ PHP_FUNCTION(curl_multi_getcontent) } /* }}} */ -/* {{{ proto array curl_multi_info_read(resource mh [, int &msgs_in_queue]) +/* {{{ proto array curl_multi_info_read(CurlMultiHandle mh [, int &msgs_in_queue]) Get information about the current transfers */ PHP_FUNCTION(curl_multi_info_read) { @@ -298,14 +275,12 @@ PHP_FUNCTION(curl_multi_info_read) php_curl *ch; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_RESOURCE(z_mh) + Z_PARAM_OBJECT_OF_CLASS(z_mh, curl_multi_ce) Z_PARAM_OPTIONAL Z_PARAM_ZVAL(zmsgs_in_queue) ZEND_PARSE_PARAMETERS_END(); - if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) { - RETURN_THROWS(); - } + mh = Z_CURL_MULTI_P(z_mh); tmp_msg = curl_multi_info_read(mh->multi, &queued_msgs); if (tmp_msg == NULL) { @@ -322,83 +297,46 @@ PHP_FUNCTION(curl_multi_info_read) /* find the original easy curl handle */ { - zval *pz_ch = _php_curl_multi_find_easy_handle(mh, tmp_msg->easy_handle); + zval *pz_ch = _php_curl_multi_find_easy_handle(mh, tmp_msg->easy_handle); if (pz_ch != NULL) { - /* we are adding a reference to the underlying php_curl - resource, so we need to add one to the resource's refcount - in order to ensure it doesn't get destroyed when the - underlying curl easy handle goes out of scope. - Normally you would call zval_copy_ctor( pz_ch ), or - SEPARATE_ZVAL, but those create new zvals, which is already - being done in add_assoc_resource */ - Z_ADDREF_P(pz_ch); - /* we must save result to be able to read error message */ - ch = (php_curl*)zend_fetch_resource(Z_RES_P(pz_ch), le_curl_name, le_curl); + ch = Z_CURL_P(pz_ch); SAVE_CURL_ERROR(ch, tmp_msg->data.result); - /* add_assoc_resource automatically creates a new zval to - wrap the "resource" represented by the current pz_ch */ - + Z_ADDREF_P(pz_ch); add_assoc_zval(return_value, "handle", pz_ch); } } } /* }}} */ -/* {{{ proto void curl_multi_close(resource mh) +/* {{{ proto void curl_multi_close(CurlMultiHandle mh) Close a set of cURL handles */ PHP_FUNCTION(curl_multi_close) { - zval *z_mh; php_curlm *mh; + zval *z_mh; + + zend_llist_position pos; + zval *pz_ch; ZEND_PARSE_PARAMETERS_START(1,1) - Z_PARAM_RESOURCE(z_mh) + Z_PARAM_OBJECT_OF_CLASS(z_mh, curl_multi_ce) ZEND_PARSE_PARAMETERS_END(); - if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) { - RETURN_THROWS(); - } + mh = Z_CURL_MULTI_P(z_mh); - zend_list_close(Z_RES_P(z_mh)); + for (pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch; + pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) { + php_curl *ch = Z_CURL_P(pz_ch); + _php_curl_verify_handlers(ch, 1); + curl_multi_remove_handle(mh->multi, ch->cp); + } + zend_llist_clean(&mh->easyh); } /* }}} */ -void _php_curl_multi_close(zend_resource *rsrc) /* {{{ */ -{ - php_curlm *mh = (php_curlm *)rsrc->ptr; - if (mh) { - zend_llist_position pos; - php_curl *ch; - zval *pz_ch; - - for (pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch; - pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) { - /* ptr is NULL means it already be freed */ - if (Z_RES_P(pz_ch)->ptr) { - if ((ch = (php_curl *) zend_fetch_resource(Z_RES_P(pz_ch), le_curl_name, le_curl))) { - _php_curl_verify_handlers(ch, 0); - } - } - } - - curl_multi_cleanup(mh->multi); - zend_llist_clean(&mh->easyh); - if (mh->handlers->server_push) { - zval_ptr_dtor(&mh->handlers->server_push->func_name); - efree(mh->handlers->server_push); - } - if (mh->handlers) { - efree(mh->handlers); - } - efree(mh); - rsrc->ptr = NULL; - } -} -/* }}} */ - -/* {{{ proto int curl_multi_errno(resource mh) +/* {{{ proto int curl_multi_errno(CurlMultiHandle mh) Return an integer containing the last multi curl error number */ PHP_FUNCTION(curl_multi_errno) { @@ -406,12 +344,10 @@ PHP_FUNCTION(curl_multi_errno) php_curlm *mh; ZEND_PARSE_PARAMETERS_START(1,1) - Z_PARAM_RESOURCE(z_mh) + Z_PARAM_OBJECT_OF_CLASS(z_mh, curl_multi_ce) ZEND_PARSE_PARAMETERS_END(); - if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) { - RETURN_THROWS(); - } + mh = Z_CURL_MULTI_P(z_mh); RETURN_LONG(mh->err.no); } @@ -450,7 +386,6 @@ static int _php_server_push_callback(CURL *parent_ch, CURL *easy, size_t num_hea zval pz_ch; zval headers; zval retval; - zend_resource *res; char *header; int error; zend_fcall_info fci = empty_fcall_info; @@ -460,18 +395,12 @@ static int _php_server_push_callback(CURL *parent_ch, CURL *easy, size_t num_hea return rval; } - parent = (php_curl*)zend_fetch_resource(Z_RES_P(pz_parent_ch), le_curl_name, le_curl); + parent = Z_CURL_P(pz_parent_ch); - ch = alloc_curl_handle(); + ch = init_curl_handle_into_zval(&pz_ch); ch->cp = easy; _php_setup_easy_copy_handlers(ch, parent); - Z_ADDREF_P(pz_parent_ch); - - res = zend_register_resource(ch, le_curl); - ch->res = res; - ZVAL_RES(&pz_ch, res); - size_t i; array_init(&headers); for(i=0; ieasyh, &pz_ch); } else { /* libcurl will free this easy handle, avoid double free */ @@ -570,7 +498,7 @@ static int _php_curl_multi_setopt(php_curlm *mh, zend_long option, zval *zvalue, } /* }}} */ -/* {{{ proto int curl_multi_setopt(resource mh, int option, mixed value) +/* {{{ proto int curl_multi_setopt(CurlMultiHandle mh, int option, mixed value) Set an option for the curl multi handle */ PHP_FUNCTION(curl_multi_setopt) { @@ -579,14 +507,12 @@ PHP_FUNCTION(curl_multi_setopt) php_curlm *mh; ZEND_PARSE_PARAMETERS_START(3,3) - Z_PARAM_RESOURCE(z_mh) + Z_PARAM_OBJECT_OF_CLASS(z_mh, curl_multi_ce) Z_PARAM_LONG(options) Z_PARAM_ZVAL(zvalue) ZEND_PARSE_PARAMETERS_END(); - if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) { - RETURN_THROWS(); - } + mh = Z_CURL_MULTI_P(z_mh); if (!_php_curl_multi_setopt(mh, options, zvalue, return_value)) { RETURN_TRUE; @@ -596,4 +522,92 @@ PHP_FUNCTION(curl_multi_setopt) } /* }}} */ +/* CurlMultiHandle class */ + +static zend_object_handlers curl_multi_handlers; + +static zend_object *curl_multi_create_object(zend_class_entry *class_type) { + php_curlm *intern = zend_object_alloc(sizeof(php_curlm), class_type); + + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &curl_multi_handlers; + + return &intern->std; +} + +static zend_function *curl_multi_get_constructor(zend_object *object) { + zend_throw_error(NULL, "Cannot directly construct CurlMultiHandle, use curl_multi_init() instead"); + return NULL; +} + +void curl_multi_free_obj(zend_object *object) +{ + php_curlm *mh = curl_multi_from_obj(object); + + zend_llist_position pos; + php_curl *ch; + zval *pz_ch; + + for (pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch; + pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) { + if (!(OBJ_FLAGS(Z_OBJ_P(pz_ch)) & IS_OBJ_FREE_CALLED)) { + ch = Z_CURL_P(pz_ch); + _php_curl_verify_handlers(ch, 0); + } + } + + curl_multi_cleanup(mh->multi); + zend_llist_clean(&mh->easyh); + if (mh->handlers->server_push) { + zval_ptr_dtor(&mh->handlers->server_push->func_name); + efree(mh->handlers->server_push); + } + if (mh->handlers) { + efree(mh->handlers); + } + + zend_object_std_dtor(&mh->std); +} + +static HashTable *curl_multi_get_gc(zend_object *object, zval **table, int *n) +{ + php_curlm *curl_multi = curl_multi_from_obj(object); + + zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); + + if (curl_multi->handlers) { + if (curl_multi->handlers->server_push) { + zend_get_gc_buffer_add_zval(gc_buffer, &curl_multi->handlers->server_push->func_name); + } + } + + zend_llist_position pos; + for (zval *pz_ch = (zval *) zend_llist_get_first_ex(&curl_multi->easyh, &pos); pz_ch; + pz_ch = (zval *) zend_llist_get_next_ex(&curl_multi->easyh, &pos)) { + zend_get_gc_buffer_add_zval(gc_buffer, pz_ch); + } + + zend_get_gc_buffer_use(gc_buffer, table, n); + + return zend_std_get_properties(object); +} + +void curl_multi_register_class(const zend_function_entry *method_entries) { + zend_class_entry ce_multi; + INIT_CLASS_ENTRY(ce_multi, "CurlMultiHandle", method_entries); + curl_multi_ce = zend_register_internal_class(&ce_multi); + curl_multi_ce->ce_flags |= ZEND_ACC_FINAL; + curl_multi_ce->create_object = curl_multi_create_object; + curl_multi_ce->serialize = zend_class_serialize_deny; + curl_multi_ce->unserialize = zend_class_unserialize_deny; + + memcpy(&curl_multi_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + curl_multi_handlers.offset = XtOffsetOf(php_curlm, std); + curl_multi_handlers.free_obj = curl_multi_free_obj; + curl_multi_handlers.get_gc = curl_multi_get_gc; + curl_multi_handlers.get_constructor = curl_multi_get_constructor; + curl_multi_handlers.clone_obj = NULL; +} + #endif diff --git a/ext/curl/php_curl.h b/ext/curl/php_curl.h index 2013e1cef2f..a469d5e41cf 100644 --- a/ext/curl/php_curl.h +++ b/ext/curl/php_curl.h @@ -59,22 +59,10 @@ extern zend_module_entry curl_module_entry; #define SAVE_CURL_ERROR(__handle, __err) \ do { (__handle)->err.no = (int) __err; } while (0) -extern int le_curl; -#define le_curl_name "cURL handle" -extern int le_curl_multi_handle; -#define le_curl_multi_handle_name "cURL Multi Handle" -extern int le_curl_share_handle; -#define le_curl_share_handle_name "cURL Share Handle" -//extern int le_curl_pushheaders; -//#define le_curl_pushheaders "cURL Push Headers" - PHP_MINIT_FUNCTION(curl); PHP_MSHUTDOWN_FUNCTION(curl); PHP_MINFO_FUNCTION(curl); -void _php_curl_multi_close(zend_resource *); -void _php_curl_share_close(zend_resource *); - typedef struct { zval func_name; zend_fcall_info_cache fci_cache; @@ -129,15 +117,13 @@ struct _php_curl_free { typedef struct { CURL *cp; php_curl_handlers *handlers; - zend_resource *res; struct _php_curl_free *to_free; struct _php_curl_send_headers header; struct _php_curl_error err; zend_bool in_callback; uint32_t* clone; -#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ zval postfields; -#endif + zend_object std; } php_curl; #define CURLOPT_SAFE_UPLOAD -1 @@ -154,6 +140,7 @@ typedef struct { struct { int no; } err; + zend_object std; } php_curlm; typedef struct { @@ -161,15 +148,35 @@ typedef struct { struct { int no; } err; + zend_object std; } php_curlsh; -php_curl *alloc_curl_handle(); +php_curl *init_curl_handle_into_zval(zval *curl); +void init_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); void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source); +static inline php_curl *curl_from_obj(zend_object *obj) { + return (php_curl *)((char *)(obj) - XtOffsetOf(php_curl, std)); +} + +#define Z_CURL_P(zv) curl_from_obj(Z_OBJ_P(zv)) + +static inline php_curlsh *curl_share_from_obj(zend_object *obj) { + return (php_curlsh *)((char *)(obj) - XtOffsetOf(php_curlsh, std)); +} + +#define Z_CURL_SHARE_P(zv) curl_share_from_obj(Z_OBJ_P(zv)) + +PHP_CURL_API extern zend_class_entry *curl_ce; +PHP_CURL_API extern zend_class_entry *curl_share_ce; + +void curl_multi_register_class(const zend_function_entry *method_entries); +void curl_share_register_class(const zend_function_entry *method_entries); void curlfile_register_class(void); + PHP_CURL_API extern zend_class_entry *curl_CURLFile_class; #else diff --git a/ext/curl/share.c b/ext/curl/share.c index 78532f4d37f..c8ba8e3270b 100644 --- a/ext/curl/share.c +++ b/ext/curl/share.c @@ -21,6 +21,7 @@ #endif #include "php.h" +#include "Zend/zend_interfaces.h" #ifdef HAVE_CURL @@ -30,7 +31,9 @@ #define SAVE_CURLSH_ERROR(__handle, __err) (__handle)->err.no = (int) __err; -/* {{{ proto void curl_share_init() +zend_class_entry *curl_share_ce; + +/* {{{ proto CurlShareHandle curl_share_init() Initialize a share curl handle */ PHP_FUNCTION(curl_share_init) { @@ -38,30 +41,22 @@ PHP_FUNCTION(curl_share_init) ZEND_PARSE_PARAMETERS_NONE(); - sh = ecalloc(1, sizeof(php_curlsh)); + object_init_ex(return_value, curl_share_ce); + sh = Z_CURL_SHARE_P(return_value); sh->share = curl_share_init(); - - RETURN_RES(zend_register_resource(sh, le_curl_share_handle)); } /* }}} */ -/* {{{ proto void curl_share_close(resource sh) +/* {{{ proto void curl_share_close(CurlShareHandle sh) Close a set of cURL handles */ PHP_FUNCTION(curl_share_close) { zval *z_sh; - php_curlsh *sh; ZEND_PARSE_PARAMETERS_START(1,1) - Z_PARAM_RESOURCE(z_sh) + Z_PARAM_OBJECT_OF_CLASS(z_sh, curl_share_ce) ZEND_PARSE_PARAMETERS_END(); - - if ((sh = (php_curlsh *)zend_fetch_resource(Z_RES_P(z_sh), le_curl_share_handle_name, le_curl_share_handle)) == NULL) { - RETURN_THROWS(); - } - - zend_list_close(Z_RES_P(z_sh)); } /* }}} */ @@ -87,23 +82,21 @@ static int _php_curl_share_setopt(php_curlsh *sh, zend_long option, zval *zvalue } /* }}} */ -/* {{{ proto bool curl_share_setopt(resource sh, int option, mixed value) +/* {{{ proto bool curl_share_setopt(CurlShareHandle sh, int option, mixed value) Set an option for a cURL transfer */ PHP_FUNCTION(curl_share_setopt) { - zval *zid, *zvalue; + zval *z_sh, *zvalue; zend_long options; php_curlsh *sh; ZEND_PARSE_PARAMETERS_START(3,3) - Z_PARAM_RESOURCE(zid) + Z_PARAM_OBJECT_OF_CLASS(z_sh, curl_share_ce) Z_PARAM_LONG(options) Z_PARAM_ZVAL(zvalue) ZEND_PARSE_PARAMETERS_END(); - if ((sh = (php_curlsh *)zend_fetch_resource(Z_RES_P(zid), le_curl_share_handle_name, le_curl_share_handle)) == NULL) { - RETURN_THROWS(); - } + sh = Z_CURL_SHARE_P(z_sh); if (!_php_curl_share_setopt(sh, options, zvalue, return_value)) { RETURN_TRUE; @@ -113,18 +106,7 @@ PHP_FUNCTION(curl_share_setopt) } /* }}} */ -void _php_curl_share_close(zend_resource *rsrc) /* {{{ */ -{ - php_curlsh *sh = (php_curlsh *)rsrc->ptr; - if (sh) { - curl_share_cleanup(sh->share); - efree(sh); - rsrc->ptr = NULL; - } -} -/* }}} */ - -/* {{{ proto int curl_share_errno(resource mh) +/* {{{ proto int curl_share_errno(CurlShareHandle sh) Return an integer containing the last share curl error number */ PHP_FUNCTION(curl_share_errno) { @@ -132,12 +114,10 @@ PHP_FUNCTION(curl_share_errno) php_curlsh *sh; ZEND_PARSE_PARAMETERS_START(1,1) - Z_PARAM_RESOURCE(z_sh) + Z_PARAM_OBJECT_OF_CLASS(z_sh, curl_share_ce) ZEND_PARSE_PARAMETERS_END(); - if ((sh = (php_curlsh *)zend_fetch_resource(Z_RES_P(z_sh), le_curl_share_handle_name, le_curl_share_handle)) == NULL) { - RETURN_THROWS(); - } + sh = Z_CURL_SHARE_P(z_sh); RETURN_LONG(sh->err.no); } @@ -164,4 +144,47 @@ PHP_FUNCTION(curl_share_strerror) } /* }}} */ +/* CurlShareHandle class */ + +static zend_object_handlers curl_share_handlers; + +static zend_object *curl_share_create_object(zend_class_entry *class_type) { + php_curlsh *intern = zend_object_alloc(sizeof(php_curlsh), class_type); + + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &curl_share_handlers; + + return &intern->std; +} + +static zend_function *curl_share_get_constructor(zend_object *object) { + zend_throw_error(NULL, "Cannot directly construct CurlShareHandle, use curl_share_init() instead"); + return NULL; +} + +void curl_share_free_obj(zend_object *object) +{ + php_curlsh *sh = curl_share_from_obj(object); + + curl_share_cleanup(sh->share); + zend_object_std_dtor(&sh->std); +} + +void curl_share_register_class(const zend_function_entry *method_entries) { + zend_class_entry ce_share; + INIT_CLASS_ENTRY(ce_share, "CurlShareHandle", method_entries); + curl_share_ce = zend_register_internal_class(&ce_share); + curl_share_ce->ce_flags |= ZEND_ACC_FINAL; + curl_share_ce->create_object = curl_share_create_object; + curl_share_ce->serialize = &zend_class_serialize_deny; + curl_share_ce->unserialize = &zend_class_unserialize_deny; + + memcpy(&curl_share_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + curl_share_handlers.offset = XtOffsetOf(php_curlsh, std); + curl_share_handlers.free_obj = curl_share_free_obj; + curl_share_handlers.get_constructor = curl_share_get_constructor; + curl_share_handlers.clone_obj = NULL; +} + #endif diff --git a/ext/curl/tests/bug48514.phpt b/ext/curl/tests/bug48514.phpt index 66b81097ea2..759e4bc1be1 100644 --- a/ext/curl/tests/bug48514.phpt +++ b/ext/curl/tests/bug48514.phpt @@ -13,15 +13,17 @@ if (!extension_loaded('curl')) { $ch1 = curl_init(); var_dump($ch1); -var_dump(get_resource_type($ch1)); +var_dump($ch1::class); $ch2 = curl_multi_init(); var_dump($ch2); -var_dump(get_resource_type($ch2)); +var_dump($ch2::class); ?> ---EXPECTF-- -resource(%d) of type (curl) -string(4) "curl" -resource(%d) of type (curl_multi) -string(10) "curl_multi" +--EXPECT-- +object(CurlHandle)#1 (0) { +} +string(10) "CurlHandle" +object(CurlMultiHandle)#2 (0) { +} +string(15) "CurlMultiHandle" diff --git a/ext/curl/tests/bug72202.phpt b/ext/curl/tests/bug72202.phpt index 01564c0a585..bf04d9faea5 100644 --- a/ext/curl/tests/bug72202.phpt +++ b/ext/curl/tests/bug72202.phpt @@ -27,7 +27,11 @@ resource(%d) of type (stream) resource(%d) of type (stream) resource(%d) of type (Unknown) resource(%d) of type (Unknown) -resource(%d) of type (curl) -resource(%d) of type (curl) -resource(%d) of type (Unknown) -resource(%d) of type (Unknown) +object(CurlHandle)#1 (0) { +} +object(CurlHandle)#1 (0) { +} +object(CurlHandle)#1 (0) { +} +object(CurlHandle)#1 (0) { +} diff --git a/ext/curl/tests/bug77535.phpt b/ext/curl/tests/bug77535.phpt index 4505352ca8e..95eec344a89 100644 --- a/ext/curl/tests/bug77535.phpt +++ b/ext/curl/tests/bug77535.phpt @@ -53,7 +53,8 @@ class MyHttpClient if (CURLMSG_DONE !== $info['msg']) { continue; } - die("Start handle request."); + echo "Start handle request.\n"; + return; } } } @@ -72,6 +73,7 @@ class MyHttpClient $buzz = new MyHttpClient(); $buzz->sendRequest(); +?> --EXPECT-- Start handle request. diff --git a/ext/curl/tests/curl_basic_014.phpt b/ext/curl/tests/curl_basic_014.phpt index 88605e648f6..88d65d316cb 100644 --- a/ext/curl/tests/curl_basic_014.phpt +++ b/ext/curl/tests/curl_basic_014.phpt @@ -9,5 +9,6 @@ Jean-Marc Fontaine $ch = curl_init(); var_dump($ch); ?> ---EXPECTF-- -resource(%d) of type (curl) +--EXPECT-- +object(CurlHandle)#1 (0) { +} diff --git a/ext/curl/tests/curl_close_basic.phpt b/ext/curl/tests/curl_close_basic.phpt index 5824fdddb80..af7d9ea88ed 100644 --- a/ext/curl/tests/curl_close_basic.phpt +++ b/ext/curl/tests/curl_close_basic.phpt @@ -13,5 +13,6 @@ $ch = curl_init(); curl_close($ch); var_dump($ch); ?> ---EXPECTF-- -resource(%d) of type (Unknown) +--EXPECT-- +object(CurlHandle)#1 (0) { +} diff --git a/ext/curl/tests/curl_handle_clone.phpt b/ext/curl/tests/curl_handle_clone.phpt new file mode 100644 index 00000000000..aa1251cbe01 --- /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/curl/tests/curl_multi_close_basic.phpt b/ext/curl/tests/curl_multi_close_basic.phpt index a9712dcf150..76dcb588265 100644 --- a/ext/curl/tests/curl_multi_close_basic.phpt +++ b/ext/curl/tests/curl_multi_close_basic.phpt @@ -13,5 +13,6 @@ $ch = curl_multi_init(); curl_multi_close($ch); var_dump($ch); ?> ---EXPECTF-- -resource(%d) of type (Unknown) +--EXPECT-- +object(CurlMultiHandle)#1 (0) { +} diff --git a/ext/curl/tests/curl_multi_close_basic001.phpt b/ext/curl/tests/curl_multi_close_basic001.phpt index 42deaf78be1..f47028e8733 100644 --- a/ext/curl/tests/curl_multi_close_basic001.phpt +++ b/ext/curl/tests/curl_multi_close_basic001.phpt @@ -11,15 +11,11 @@ var_dump($cmh); $multi_close_result = curl_multi_close($cmh); var_dump($multi_close_result); var_dump($cmh); -try { - $bad_mh_close_result = curl_multi_close($cmh); - var_dump($bad_mh_close_result); -} catch (TypeError $e) { - echo $e->getMessage(), "\n"; -} +curl_multi_close($cmh); ?> --EXPECTF-- -resource(%d) of type (curl_multi) +object(CurlMultiHandle)#1 (0) { +} NULL -resource(%d) of type (Unknown) -curl_multi_close(): supplied resource is not a valid cURL Multi Handle resource +object(CurlMultiHandle)#1 (0) { +} diff --git a/ext/curl/tests/curl_multi_info_read.phpt b/ext/curl/tests/curl_multi_info_read.phpt index 9f54e10b128..bbaa1cec252 100644 --- a/ext/curl/tests/curl_multi_info_read.phpt +++ b/ext/curl/tests/curl_multi_info_read.phpt @@ -39,7 +39,8 @@ array(3) { ["result"]=> int(%d) ["handle"]=> - resource(%d) of type (curl) + object(CurlHandle)#%d (0) { + } } array(3) { ["msg"]=> @@ -47,5 +48,6 @@ array(3) { ["result"]=> int(%d) ["handle"]=> - resource(%d) of type (curl) + object(CurlHandle)#%d (0) { + } } diff --git a/ext/curl/tests/curl_multi_init_basic.phpt b/ext/curl/tests/curl_multi_init_basic.phpt index 452bc42837c..808a8c4814d 100644 --- a/ext/curl/tests/curl_multi_init_basic.phpt +++ b/ext/curl/tests/curl_multi_init_basic.phpt @@ -25,5 +25,7 @@ var_dump($mh); ?> --EXPECTF-- *** Testing curl_multi_init(void); *** -resource(%d) of type (curl_multi) -resource(%d) of type (Unknown) +object(CurlMultiHandle)#1 (0) { +} +object(CurlMultiHandle)#1 (0) { +} diff --git a/ext/curl/tests/curl_share_close_basic001.phpt b/ext/curl/tests/curl_share_close_basic001.phpt index eec1bde0996..4c2c07d73da 100644 --- a/ext/curl/tests/curl_share_close_basic001.phpt +++ b/ext/curl/tests/curl_share_close_basic001.phpt @@ -6,14 +6,15 @@ curl_share_close basic test ---EXPECTF-- -resource(%d) of type (curl_share) -resource(%d) of type (Unknown) +--EXPECT-- +object(CurlShareHandle)#1 (0) { +} +object(CurlShareHandle)#1 (0) { +} diff --git a/ext/opcache/Optimizer/zend_func_info.c b/ext/opcache/Optimizer/zend_func_info.c index 3b9ebf75ab5..ff985fc63fa 100644 --- a/ext/opcache/Optimizer/zend_func_info.c +++ b/ext/opcache/Optimizer/zend_func_info.c @@ -510,8 +510,8 @@ static const func_info_t func_infos[] = { F1("mysqli_use_result", MAY_BE_FALSE | MAY_BE_OBJECT), /* ext/curl */ - F1("curl_init", MAY_BE_FALSE | MAY_BE_RESOURCE), - F1("curl_copy_handle", MAY_BE_FALSE | MAY_BE_RESOURCE), + F1("curl_init", MAY_BE_FALSE | MAY_BE_OBJECT), + F1("curl_copy_handle", MAY_BE_FALSE | MAY_BE_OBJECT), F1("curl_version", MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_STRING | MAY_BE_ARRAY_OF_LONG | MAY_BE_ARRAY_OF_STRING | MAY_BE_ARRAY_OF_ARRAY), F1("curl_getinfo", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING | MAY_BE_LONG | MAY_BE_DOUBLE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY), F1("curl_error", MAY_BE_STRING), @@ -519,9 +519,9 @@ static const func_info_t func_infos[] = { F1("curl_multi_strerror", MAY_BE_NULL | MAY_BE_STRING), F1("curl_escape", MAY_BE_FALSE | MAY_BE_STRING), F1("curl_unescape", MAY_BE_FALSE | MAY_BE_STRING), - F1("curl_multi_init", MAY_BE_RESOURCE), - F1("curl_multi_info_read", MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_STRING | MAY_BE_ARRAY_OF_LONG | MAY_BE_ARRAY_OF_RESOURCE), - F1("curl_share_init", MAY_BE_RESOURCE), + F1("curl_multi_init", MAY_BE_OBJECT), + F1("curl_multi_info_read", MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_STRING | MAY_BE_ARRAY_OF_LONG | MAY_BE_ARRAY_OF_OBJECT), + F1("curl_share_init", MAY_BE_OBJECT), F1("curl_file_create", MAY_BE_OBJECT), /* ext/mbstring */ diff --git a/ext/posix/tests/posix_ttyname_error_wrongparams.phpt b/ext/posix/tests/posix_ttyname_error_wrongparams.phpt index 92cf671c1dd..8d10ce54977 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"; }