summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMáté Kocsis <kocsismate@woohoolabs.com>2020-06-17 16:05:55 +0200
committerMáté Kocsis <kocsismate@woohoolabs.com>2020-06-17 16:11:57 +0200
commitb516566b84c210ce6ceddeb238e45d4b1bcb32ce (patch)
tree353ab0f357eee9583aadf196688c382059568871
parent1e095e3412f0d8be5b245326b72e7ab82c553985 (diff)
downloadphp-git-b516566b84c210ce6ceddeb238e45d4b1bcb32ce.tar.gz
Convert CURL resources to objects
Closes GH-5402 Co-authored-by: Nikita Popov <nikita.ppv@gmail.com>
-rw-r--r--UPGRADING15
-rw-r--r--ext/curl/curl.stub.php122
-rw-r--r--ext/curl/curl_arginfo.h76
-rw-r--r--ext/curl/interface.c318
-rw-r--r--ext/curl/multi.c300
-rw-r--r--ext/curl/php_curl.h39
-rw-r--r--ext/curl/share.c93
-rw-r--r--ext/curl/tests/bug48514.phpt16
-rw-r--r--ext/curl/tests/bug72202.phpt12
-rw-r--r--ext/curl/tests/bug77535.phpt4
-rw-r--r--ext/curl/tests/curl_basic_014.phpt5
-rw-r--r--ext/curl/tests/curl_close_basic.phpt5
-rw-r--r--ext/curl/tests/curl_handle_clone.phpt26
-rw-r--r--ext/curl/tests/curl_multi_close_basic.phpt5
-rw-r--r--ext/curl/tests/curl_multi_close_basic001.phpt14
-rw-r--r--ext/curl/tests/curl_multi_info_read.phpt6
-rw-r--r--ext/curl/tests/curl_multi_init_basic.phpt6
-rw-r--r--ext/curl/tests/curl_share_close_basic001.phpt11
-rw-r--r--ext/opcache/Optimizer/zend_func_info.c10
-rw-r--r--ext/posix/tests/posix_ttyname_error_wrongparams.phpt7
20 files changed, 619 insertions, 471 deletions
diff --git a/UPGRADING b/UPGRADING
index 7e8b5971ba..794b91f943 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 ac998c4565..f7e20e30f6 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 efc57e9148..72f68a6307 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 dc79a9e2d7..bdc284b4ab 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 d8c1caac3c..6a4c48ee18 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();
- }
-
- zend_list_close(Z_RES_P(z_mh));
-}
-/* }}} */
+ mh = Z_CURL_MULTI_P(z_mh);
-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;
+ 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);
}
/* }}} */
-/* {{{ 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; i<num_headers; i++) {
@@ -499,7 +428,6 @@ static int _php_server_push_callback(CURL *parent_ch, CURL *easy, size_t num_hea
} else if (!Z_ISUNDEF(retval)) {
if (CURL_PUSH_DENY != zval_get_long(&retval)) {
rval = CURL_PUSH_OK;
- GC_ADDREF(Z_RES(pz_ch));
zend_llist_add_element(&mh->easyh, &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 2013e1cef2..a469d5e41c 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 78532f4d37..c8ba8e3270 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 66b81097ea..759e4bc1be 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 01564c0a58..bf04d9faea 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 4505352ca8..95eec344a8 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 88605e648f..88d65d316c 100644
--- a/ext/curl/tests/curl_basic_014.phpt
+++ b/ext/curl/tests/curl_basic_014.phpt
@@ -9,5 +9,6 @@ Jean-Marc Fontaine <jmf@durcommefaire.net>
$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 5824fdddb8..af7d9ea88e 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 0000000000..aa1251cbe0
--- /dev/null
+++ b/ext/curl/tests/curl_handle_clone.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Test that cloning of Curl objects is supported
+--SKIPIF--
+<?php include 'skipif.inc'; ?>
+--FILE--
+<?php
+
+include 'server.inc';
+$host = curl_cli_server_start();
+
+$ch1 = curl_init();
+curl_setopt($ch1, CURLOPT_URL, $host);
+curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
+curl_exec($ch1);
+
+$ch2 = clone $ch1;
+curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 0);
+
+var_dump(curl_getinfo($ch1, CURLINFO_EFFECTIVE_URL) === curl_getinfo($ch2, CURLINFO_EFFECTIVE_URL));
+curl_exec($ch2);
+
+?>
+--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 a9712dcf15..76dcb58826 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 42deaf78be..f47028e873 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 9f54e10b12..bbaa1cec25 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 452bc42837..808a8c4814 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 eec1bde099..4c2c07d73d 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
<?php
$sh = curl_share_init();
-//Show that there's a curl_share resource
+//Show that there's a curl_share object
var_dump($sh);
curl_share_close($sh);
-//Show that resource is no longer a curl_share, and is therefore unusable and "closed"
var_dump($sh);
?>
---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 3b9ebf75ab..ff985fc63f 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 92cf671c1d..8d10ce5497 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--
<?php
var_dump(posix_ttyname(0)); // param not a resource
try {
- var_dump(posix_ttyname(curl_init())); // wrong resource type
+ var_dump(posix_ttyname(socket_create(AF_INET, SOCK_DGRAM, SOL_UDP))); // wrong resource type
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}