Convert CURL resources to objects

Closes GH-5402

Co-authored-by: Nikita Popov <nikita.ppv@gmail.com>
This commit is contained in:
Máté Kocsis 2020-06-17 16:05:55 +02:00
parent 1e095e3412
commit b516566b84
No known key found for this signature in database
GPG Key ID: FD055E41728BF310
20 changed files with 620 additions and 472 deletions

View File

@ -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.

View File

@ -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 {}

View File

@ -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
};

View File

@ -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));
}

View File

@ -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; 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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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) {
}

View File

@ -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.

View File

@ -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) {
}

View File

@ -13,5 +13,6 @@ $ch = curl_init();
curl_close($ch);
var_dump($ch);
?>
--EXPECTF--
resource(%d) of type (Unknown)
--EXPECT--
object(CurlHandle)#1 (0) {
}

View File

@ -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!

View File

@ -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) {
}

View File

@ -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) {
}

View File

@ -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) {
}
}

View File

@ -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) {
}

View File

@ -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) {
}

View File

@ -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 */

View File

@ -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";
}