diff --git a/ext/curl/curl.stub.php b/ext/curl/curl.stub.php index 58c5a959b25f6..7c1765573939b 100644 --- a/ext/curl/curl.stub.php +++ b/ext/curl/curl.stub.php @@ -7,6 +7,40 @@ * @not-serializable */ final class CurlHandle +{ + public function __construct(?string $url = null) {} + + /** @alias curl_setopt */ + public function setOpt(int $option, mixed $value): CurlHandle {} // CURLCode + + /** @alias curl_getinfo */ + public function getInfo(?int $option = null): mixed {} // CURLCode + + /** @alias curl_exec */ + public function exec(): string|bool {} // CURLCode + + /** @alias curl_escape */ + public function escape(string $string): string {} + + /** @alias curl_unescape */ + public function unescape(string $string): string {} + + /** @alias curl_pause */ + public function pause(int $flags): void {} // CURLCode + + /** @alias curl_reset */ + public function reset(): void; + + /** @alias curl_setopt_array */ + public function setOptArray(array $options): CurlHandle {} // CURLCode + +#if LIBCURL_VERSION_NUM >= 0x073E00 /* Available since 7.62.0 */ + /** @alias curl_upkeep */ + public function upkeep(): void {} // CURLCode +#endif +} + +class CurlException extends Exception { } diff --git a/ext/curl/curl_arginfo.h b/ext/curl/curl_arginfo.h index b8b0b4013ef95..9907c670f67a9 100644 --- a/ext/curl/curl_arginfo.h +++ b/ext/curl/curl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 1bd8a84a4aa80912463ea76d08f64d3c2cf4c0db */ + * Stub hash: 1f19224f819fc1c944937253881b7d371e0b1e09 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_close, 0, 1, IS_VOID, 0) ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) @@ -138,6 +138,44 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_curl_version, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_CurlHandle___construct, 0, 0, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, url, IS_STRING, 1, "null") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_CurlHandle_setOpt, 0, 2, CurlHandle, 0) + ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_CurlHandle_getInfo, 0, 0, IS_MIXED, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, option, IS_LONG, 1, "null") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_CurlHandle_exec, 0, 0, MAY_BE_STRING|MAY_BE_BOOL) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_CurlHandle_escape, 0, 1, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_CurlHandle_unescape arginfo_class_CurlHandle_escape + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_CurlHandle_pause, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_CurlHandle_reset, 0, 0, IS_VOID, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_CurlHandle_setOptArray, 0, 1, CurlHandle, 0) + ZEND_ARG_TYPE_INFO(0, options, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + +#if LIBCURL_VERSION_NUM >= 0x073E00 /* Available since 7.62.0 */ +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_CurlHandle_upkeep, 0, 0, IS_VOID, 0) +ZEND_END_ARG_INFO() +#endif + ZEND_FUNCTION(curl_close); ZEND_FUNCTION(curl_copy_handle); @@ -174,6 +212,7 @@ ZEND_FUNCTION(curl_share_setopt); ZEND_FUNCTION(curl_share_strerror); ZEND_FUNCTION(curl_strerror); ZEND_FUNCTION(curl_version); +ZEND_METHOD(CurlHandle, __construct); static const zend_function_entry ext_functions[] = { @@ -217,6 +256,23 @@ static const zend_function_entry ext_functions[] = { static const zend_function_entry class_CurlHandle_methods[] = { + ZEND_ME(CurlHandle, __construct, arginfo_class_CurlHandle___construct, ZEND_ACC_PUBLIC) + ZEND_ME_MAPPING(setOpt, curl_setopt, arginfo_class_CurlHandle_setOpt, ZEND_ACC_PUBLIC) + ZEND_ME_MAPPING(getInfo, curl_getinfo, arginfo_class_CurlHandle_getInfo, ZEND_ACC_PUBLIC) + ZEND_ME_MAPPING(exec, curl_exec, arginfo_class_CurlHandle_exec, ZEND_ACC_PUBLIC) + ZEND_ME_MAPPING(escape, curl_escape, arginfo_class_CurlHandle_escape, ZEND_ACC_PUBLIC) + ZEND_ME_MAPPING(unescape, curl_unescape, arginfo_class_CurlHandle_unescape, ZEND_ACC_PUBLIC) + ZEND_ME_MAPPING(pause, curl_pause, arginfo_class_CurlHandle_pause, ZEND_ACC_PUBLIC) + ZEND_ME_MAPPING(reset, curl_reset, arginfo_class_CurlHandle_reset, ZEND_ACC_PUBLIC) + ZEND_ME_MAPPING(setOptArray, curl_setopt_array, arginfo_class_CurlHandle_setOptArray, ZEND_ACC_PUBLIC) +#if LIBCURL_VERSION_NUM >= 0x073E00 /* Available since 7.62.0 */ + ZEND_ME_MAPPING(upkeep, curl_upkeep, arginfo_class_CurlHandle_upkeep, ZEND_ACC_PUBLIC) +#endif + ZEND_FE_END +}; + + +static const zend_function_entry class_CurlException_methods[] = { ZEND_FE_END }; @@ -241,6 +297,16 @@ static zend_class_entry *register_class_CurlHandle(void) return class_entry; } +static zend_class_entry *register_class_CurlException(zend_class_entry *class_entry_Exception) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "CurlException", class_CurlException_methods); + class_entry = zend_register_internal_class_ex(&ce, class_entry_Exception); + + return class_entry; +} + static zend_class_entry *register_class_CurlMultiHandle(void) { zend_class_entry ce, *class_entry; diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 0d574a605a6d7..78f65dffd1822 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -218,12 +218,12 @@ ZEND_GET_MODULE (curl) zend_class_entry *curl_ce; zend_class_entry *curl_share_ce; +zend_class_entry *curl_exception_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 zend_result build_mime_structure_from_hash(php_curl *ch, zval *zpostfields); @@ -1330,11 +1330,12 @@ PHP_MINIT_FUNCTION(curl) curl_ce = register_class_CurlHandle(); curl_ce->create_object = curl_create_object; + curl_exception_ce = register_class_CurlException(zend_ce_exception); + 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_object_handlers.cast_object = curl_cast_object; curl_object_handlers.compare = zend_objects_not_comparable; @@ -1362,11 +1363,6 @@ static zend_object *curl_create_object(zend_class_entry *class_type) { 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; @@ -2036,8 +2032,7 @@ static void _php_curl_set_default_options(php_curl *ch) } /* }}} */ -/* {{{ Initialize a cURL session */ -PHP_FUNCTION(curl_init) +static void _php_curl_init(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_procedural) { php_curl *ch; CURL *cp; @@ -2048,17 +2043,19 @@ PHP_FUNCTION(curl_init) Z_PARAM_STR_OR_NULL(url) ZEND_PARSE_PARAMETERS_END(); + ch = Z_CURL_P(return_value); + init_curl_handle(ch); + cp = curl_easy_init(); if (!cp) { php_error_docref(NULL, E_WARNING, "Could not initialize a new cURL handle"); + zval_ptr_dtor(return_value); RETURN_FALSE; } - ch = init_curl_handle_into_zval(return_value); - ch->cp = cp; - ch->handlers.write->method = PHP_CURL_STDOUT; + ch->handlers.write->method = is_procedural ? PHP_CURL_STDOUT : PHP_CURL_RETURN; ch->handlers.read->method = PHP_CURL_DIRECT; ch->handlers.write_header->method = PHP_CURL_IGNORE; @@ -2071,6 +2068,19 @@ PHP_FUNCTION(curl_init) } } } + +/* {{{ Initialize a cURL session */ +PHP_METHOD(CurlHandle, __construct) +{ + return_value = ZEND_THIS; + _php_curl_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, false /* is_procedural */); +} + +PHP_FUNCTION(curl_init) +{ + object_init_ex(return_value, curl_ce); + _php_curl_init(INTERNAL_FUNCTION_PARAM_PASSTHRU, true /* is_procedural */); +} /* }}} */ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) @@ -2518,30 +2528,53 @@ PHP_FUNCTION(curl_copy_handle) } /* }}} */ -static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool is_array_config) /* {{{ */ +static inline void php_curl_setopt_type_failure(zend_long option, zend_uchar exp, zval *arg, zend_bool nullable) { /* {{{ */ + const char *exp_of = "be of type "; + const char *exp_type = ""; + zend_constant *constant; + + if (IS_CALLABLE == exp) { + exp_of = "be callable"; + } else { + exp_type = zend_get_type_by_const(exp); + } + + ZEND_HASH_MAP_FOREACH_PTR(EG(zend_constants), constant) { + if (curl_module_entry.module_number == ZEND_CONSTANT_MODULE_NUMBER(constant) && + Z_TYPE(constant->value) == IS_LONG && + Z_LVAL(constant->value) == option && + 0 == strncmp(ZSTR_VAL(constant->name), "CURLOPT_", sizeof("CURLOPT_")-1) + ) { + break; + } + } ZEND_HASH_FOREACH_END(); + + zend_type_error("Argument 2 passed to CurlHandle::setOpt() for option %s must %s%s%s, %s given", ZSTR_VAL(constant->name), exp_of, (nullable ? "?": ""), exp_type, zend_zval_type_name(arg)); +} +/* }}} */ + +static inline zend_bool php_curl_setopt_callable(zval *arg) { /* {{{ */ + zend_fcall_info fci; + zend_fcall_info_cache fcc; + + return (SUCCESS == zend_fcall_info_init(arg, 0, &fci, &fcc, NULL, NULL)) ? 1 : 0; +} +/* }}} */ + +static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool is_procedural, bool is_array_config) /* {{{ */ { CURLcode error = CURLE_OK; zend_long lval; switch (option) { - /* Long options */ - case CURLOPT_SSL_VERIFYHOST: - lval = zval_get_long(zvalue); - if (lval == 1) { - php_error_docref(NULL, E_NOTICE, "CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used instead"); - error = curl_easy_setopt(ch->cp, option, 2); - break; - } - ZEND_FALLTHROUGH; + /* Boolean options */ case CURLOPT_AUTOREFERER: - case CURLOPT_BUFFERSIZE: - case CURLOPT_CONNECTTIMEOUT: case CURLOPT_COOKIESESSION: case CURLOPT_CRLF: - case CURLOPT_DNS_CACHE_TIMEOUT: - case CURLOPT_DNS_USE_GLOBAL_CACHE: + case CURLOPT_DNS_USE_GLOBAL_CACHE: /* Has no function since 7.62.0. Do not use! */ case CURLOPT_FAILONERROR: case CURLOPT_FILETIME: + case CURLOPT_FOLLOWLOCATION: case CURLOPT_FORBID_REUSE: case CURLOPT_FRESH_CONNECT: case CURLOPT_FTP_USE_EPRT: @@ -2549,86 +2582,38 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue case CURLOPT_HEADER: case CURLOPT_HTTPGET: case CURLOPT_HTTPPROXYTUNNEL: - case CURLOPT_HTTP_VERSION: - case CURLOPT_INFILESIZE: - case CURLOPT_LOW_SPEED_LIMIT: - case CURLOPT_LOW_SPEED_TIME: - case CURLOPT_MAXCONNECTS: - case CURLOPT_MAXREDIRS: - case CURLOPT_NETRC: case CURLOPT_NOBODY: case CURLOPT_NOPROGRESS: case CURLOPT_NOSIGNAL: - case CURLOPT_PORT: case CURLOPT_POST: - case CURLOPT_PROXYPORT: - case CURLOPT_PROXYTYPE: - case CURLOPT_PUT: - case CURLOPT_RESUME_FROM: - case CURLOPT_SSLVERSION: + case CURLOPT_PUT: /* This option is deprecated since version 7.12.1. */ case CURLOPT_SSL_VERIFYPEER: - case CURLOPT_TIMECONDITION: - case CURLOPT_TIMEOUT: - case CURLOPT_TIMEVALUE: case CURLOPT_TRANSFERTEXT: case CURLOPT_UNRESTRICTED_AUTH: case CURLOPT_UPLOAD: case CURLOPT_VERBOSE: - case CURLOPT_HTTPAUTH: - case CURLOPT_FTP_CREATE_MISSING_DIRS: - case CURLOPT_PROXYAUTH: - case CURLOPT_FTP_RESPONSE_TIMEOUT: - case CURLOPT_IPRESOLVE: - case CURLOPT_MAXFILESIZE: case CURLOPT_TCP_NODELAY: - case CURLOPT_FTPSSLAUTH: case CURLOPT_IGNORE_CONTENT_LENGTH: case CURLOPT_FTP_SKIP_PASV_IP: - case CURLOPT_FTP_FILEMETHOD: case CURLOPT_CONNECT_ONLY: - case CURLOPT_LOCALPORT: - case CURLOPT_LOCALPORTRANGE: case CURLOPT_SSL_SESSIONID_CACHE: - case CURLOPT_FTP_SSL_CCC: - case CURLOPT_SSH_AUTH_TYPES: - case CURLOPT_CONNECTTIMEOUT_MS: case CURLOPT_HTTP_CONTENT_DECODING: case CURLOPT_HTTP_TRANSFER_DECODING: - case CURLOPT_TIMEOUT_MS: - case CURLOPT_NEW_DIRECTORY_PERMS: - case CURLOPT_NEW_FILE_PERMS: - case CURLOPT_USE_SSL: case CURLOPT_APPEND: case CURLOPT_DIRLISTONLY: case CURLOPT_PROXY_TRANSFER_MODE: - case CURLOPT_ADDRESS_SCOPE: case CURLOPT_CERTINFO: - case CURLOPT_PROTOCOLS: - case CURLOPT_REDIR_PROTOCOLS: case CURLOPT_SOCKS5_GSSAPI_NEC: - case CURLOPT_TFTP_BLKSIZE: case CURLOPT_FTP_USE_PRET: - case CURLOPT_RTSP_CLIENT_CSEQ: - case CURLOPT_RTSP_REQUEST: - case CURLOPT_RTSP_SERVER_CSEQ: case CURLOPT_WILDCARDMATCH: - case CURLOPT_GSSAPI_DELEGATION: - case CURLOPT_ACCEPTTIMEOUT_MS: - case CURLOPT_SSL_OPTIONS: case CURLOPT_TCP_KEEPALIVE: - case CURLOPT_TCP_KEEPIDLE: - case CURLOPT_TCP_KEEPINTVL: #if LIBCURL_VERSION_NUM >= 0x071f00 /* Available since 7.31.0 */ case CURLOPT_SASL_IR: #endif #if LIBCURL_VERSION_NUM >= 0x072400 /* Available since 7.36.0 */ - case CURLOPT_EXPECT_100_TIMEOUT_MS: case CURLOPT_SSL_ENABLE_ALPN: case CURLOPT_SSL_ENABLE_NPN: #endif -#if LIBCURL_VERSION_NUM >= 0x072500 /* Available since 7.37.0 */ - case CURLOPT_HEADEROPT: -#endif #if LIBCURL_VERSION_NUM >= 0x072900 /* Available since 7.41.0 */ case CURLOPT_SSL_VERIFYSTATUS: #endif @@ -2639,9 +2624,6 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue #if LIBCURL_VERSION_NUM >= 0x072b00 /* Available since 7.43.0 */ case CURLOPT_PIPEWAIT: #endif -#if LIBCURL_VERSION_NUM >= 0x072e00 /* Available since 7.46.0 */ - case CURLOPT_STREAM_WEIGHT: -#endif #if LIBCURL_VERSION_NUM >= 0x073000 /* Available since 7.48.0 */ case CURLOPT_TFTP_NO_OPTIONS: #endif @@ -2652,23 +2634,14 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue case CURLOPT_KEEP_SENDING_ON_ERROR: #endif #if LIBCURL_VERSION_NUM >= 0x073400 /* Available since 7.52.0 */ - case CURLOPT_PROXY_SSL_OPTIONS: - case CURLOPT_PROXY_SSL_VERIFYHOST: case CURLOPT_PROXY_SSL_VERIFYPEER: - case CURLOPT_PROXY_SSLVERSION: #endif #if LIBCURL_VERSION_NUM >= 0x073600 /* Available since 7.54.0 */ case CURLOPT_SUPPRESS_CONNECT_HEADERS: #endif -#if LIBCURL_VERSION_NUM >= 0x073700 /* Available since 7.55.0 */ - case CURLOPT_SOCKS5_AUTH: -#endif #if LIBCURL_VERSION_NUM >= 0x073800 /* Available since 7.56.0 */ case CURLOPT_SSH_COMPRESSION: #endif -#if LIBCURL_VERSION_NUM >= 0x073b00 /* Available since 7.59.0 */ - case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS: -#endif #if LIBCURL_VERSION_NUM >= 0x073c00 /* Available since 7.60.0 */ case CURLOPT_DNS_SHUFFLE_ADDRESSES: case CURLOPT_HAPROXYPROTOCOL: @@ -2676,53 +2649,153 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue #if LIBCURL_VERSION_NUM >= 0x073d00 /* Available since 7.61.0 */ case CURLOPT_DISALLOW_USERNAME_IN_URL: #endif +#if LIBCURL_VERSION_NUM >= 0x074000 /* Available since 7.64.0 */ + case CURLOPT_HTTP09_ALLOWED: +#endif +#if LIBCURL_VERSION_NUM >= 0x074500 /* Available since 7.69.0 */ + case CURLOPT_MAIL_RCPT_ALLLOWFAILS: +#endif +#if LIBCURL_VERSION_NUM >= 0x074c00 /* Available since 7.76.0 */ + case CURLOPT_DOH_SSL_VERIFYPEER: + case CURLOPT_DOH_SSL_VERIFYSTATUS: +#endif + { + if (is_procedural) { + lval = zend_is_true(zvalue); + } else { + zend_bool bval; + if (!zend_parse_arg_bool(zvalue, &bval, 0 /* is_null */, 0 /* check_null */, 2)) { + php_curl_setopt_type_failure(option, _IS_BOOL, zvalue, 0 /* nullable */); + return FAILURE; + } + lval = (zend_long) bval; + } +# if defined(ZTS) + if (option == CURLOPT_DNS_USE_GLOBAL_CACHE && lval) { + php_error_docref(NULL, E_WARNING, "CURLOPT_DNS_USE_GLOBAL_CACHE cannot be activated when thread safety is enabled"); + return FAILURE; + } +# endif + error = curl_easy_setopt(ch->cp, option, lval); + break; + } + + /* Long options */ + case CURLOPT_SSL_VERIFYHOST: + case CURLOPT_BUFFERSIZE: + case CURLOPT_CONNECTTIMEOUT: + case CURLOPT_DNS_CACHE_TIMEOUT: + case CURLOPT_HTTP_VERSION: + case CURLOPT_INFILESIZE: + case CURLOPT_LOW_SPEED_LIMIT: + case CURLOPT_LOW_SPEED_TIME: + case CURLOPT_MAXCONNECTS: + case CURLOPT_MAXREDIRS: + case CURLOPT_NETRC: + case CURLOPT_PORT: + case CURLOPT_PROXYPORT: + case CURLOPT_PROXYTYPE: + case CURLOPT_RESUME_FROM: + case CURLOPT_SSLVERSION: + case CURLOPT_TIMECONDITION: + case CURLOPT_TIMEOUT: + case CURLOPT_TIMEVALUE: + case CURLOPT_HTTPAUTH: + case CURLOPT_FTP_CREATE_MISSING_DIRS: + case CURLOPT_PROXYAUTH: + case CURLOPT_FTP_RESPONSE_TIMEOUT: + case CURLOPT_IPRESOLVE: + case CURLOPT_MAXFILESIZE: + case CURLOPT_FTPSSLAUTH: + case CURLOPT_FTP_FILEMETHOD: + case CURLOPT_LOCALPORT: + case CURLOPT_LOCALPORTRANGE: + case CURLOPT_FTP_SSL_CCC: + case CURLOPT_SSH_AUTH_TYPES: + case CURLOPT_CONNECTTIMEOUT_MS: + case CURLOPT_TIMEOUT_MS: + case CURLOPT_NEW_DIRECTORY_PERMS: + case CURLOPT_NEW_FILE_PERMS: + case CURLOPT_USE_SSL: + case CURLOPT_ADDRESS_SCOPE: + case CURLOPT_PROTOCOLS: + case CURLOPT_REDIR_PROTOCOLS: + case CURLOPT_TFTP_BLKSIZE: + case CURLOPT_RTSP_CLIENT_CSEQ: + case CURLOPT_RTSP_REQUEST: + case CURLOPT_RTSP_SERVER_CSEQ: + case CURLOPT_GSSAPI_DELEGATION: + case CURLOPT_ACCEPTTIMEOUT_MS: + case CURLOPT_SSL_OPTIONS: + case CURLOPT_TCP_KEEPIDLE: + case CURLOPT_TCP_KEEPINTVL: +#if LIBCURL_VERSION_NUM >= 0x072400 /* Available since 7.36.0 */ + case CURLOPT_EXPECT_100_TIMEOUT_MS: +#endif +#if LIBCURL_VERSION_NUM >= 0x072500 /* Available since 7.37.0 */ + case CURLOPT_HEADEROPT: +#endif +#if LIBCURL_VERSION_NUM >= 0x072e00 /* Available since 7.46.0 */ + case CURLOPT_STREAM_WEIGHT: +#endif +#if LIBCURL_VERSION_NUM >= 0x073400 /* Available since 7.52.0 */ + case CURLOPT_PROXY_SSL_OPTIONS: + case CURLOPT_PROXY_SSL_VERIFYHOST: + case CURLOPT_PROXY_SSLVERSION: +#endif +#if LIBCURL_VERSION_NUM >= 0x073700 /* Available since 7.55.0 */ + case CURLOPT_SOCKS5_AUTH: +#endif +#if LIBCURL_VERSION_NUM >= 0x073b00 /* Available since 7.59.0 */ + case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS: +#endif #if LIBCURL_VERSION_NUM >= 0x073E00 /* Available since 7.62.0 */ case CURLOPT_UPKEEP_INTERVAL_MS: case CURLOPT_UPLOAD_BUFFERSIZE: #endif -#if LIBCURL_VERSION_NUM >= 0x074000 /* Available since 7.64.0 */ - case CURLOPT_HTTP09_ALLOWED: -#endif #if LIBCURL_VERSION_NUM >= 0x074001 /* Available since 7.64.1 */ case CURLOPT_ALTSVC_CTRL: #endif #if LIBCURL_VERSION_NUM >= 0x074100 /* Available since 7.65.0 */ case CURLOPT_MAXAGE_CONN: #endif -#if LIBCURL_VERSION_NUM >= 0x074500 /* Available since 7.69.0 */ - case CURLOPT_MAIL_RCPT_ALLLOWFAILS: -#endif #if LIBCURL_VERSION_NUM >= 0x074a00 /* Available since 7.74.0 */ case CURLOPT_HSTS_CTRL: #endif #if LIBCURL_VERSION_NUM >= 0x074c00 /* Available since 7.76.0 */ case CURLOPT_DOH_SSL_VERIFYHOST: - case CURLOPT_DOH_SSL_VERIFYPEER: - case CURLOPT_DOH_SSL_VERIFYSTATUS: #endif #if LIBCURL_VERSION_NUM >= 0x075000 /* Available since 7.80.0 */ case CURLOPT_MAXLIFETIME_CONN: #endif - lval = zval_get_long(zvalue); - if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) && - (PG(open_basedir) && *PG(open_basedir)) && (lval & CURLPROTO_FILE)) { - php_error_docref(NULL, E_WARNING, "CURLPROTO_FILE cannot be activated when an open_basedir is set"); - return FAILURE; + { + if (is_procedural) { + lval = zval_get_long(zvalue); + } else if (!zend_parse_arg_long(zvalue, &lval, 0 /* is_null */, 0 /* check_null */, 0 /* cap */)) { + php_curl_setopt_type_failure(option, IS_LONG, zvalue, 0 /* nullable */); + return FAILURE; } -# if defined(ZTS) - if (option == CURLOPT_DNS_USE_GLOBAL_CACHE && lval) { - php_error_docref(NULL, E_WARNING, "CURLOPT_DNS_USE_GLOBAL_CACHE cannot be activated when thread safety is enabled"); + if (lval == 1 && option == CURLOPT_SSL_VERIFYHOST) { + php_error_docref(NULL, E_NOTICE, "CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used instead"); + lval = 2; + break; + } else if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) && + (PG(open_basedir) && *PG(open_basedir)) && (lval & CURLPROTO_FILE)) { + php_error_docref(NULL, E_WARNING, "CURLPROTO_FILE cannot be activated when an open_basedir is set"); return FAILURE; } -# endif error = curl_easy_setopt(ch->cp, option, lval); break; + } + case CURLOPT_SAFE_UPLOAD: + { if (!zend_is_true(zvalue)) { zend_value_error("%s(): Disabling safe uploads is no longer supported", get_active_function_name()); return FAILURE; } break; + } /* String options */ case CURLOPT_CAINFO: @@ -2820,10 +2893,19 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue #endif { zend_string *tmp_str; - zend_string *str = zval_get_tmp_string(zvalue, &tmp_str); - zend_result ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str)); - zend_tmp_string_release(tmp_str); - return ret; + zend_string *str; + if (is_procedural) { + str = zval_get_tmp_string(zvalue, &tmp_str); + zend_result ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str)); + zend_tmp_string_release(tmp_str); + return ret; + } else { + if (!zend_parse_arg_str(zvalue, &str, 0 /* check_null */, 2)) { + php_curl_setopt_type_failure(option, IS_STRING, zvalue, 0 /* nullable */); + return FAILURE; + } + return php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str)); + } } /* Curl nullable string options */ @@ -2853,10 +2935,19 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue error = curl_easy_setopt(ch->cp, option, NULL); } else { zend_string *tmp_str; - zend_string *str = zval_get_tmp_string(zvalue, &tmp_str); - zend_result ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str)); - zend_tmp_string_release(tmp_str); - return ret; + zend_string *str; + if (is_procedural) { + str = zval_get_tmp_string(zvalue, &tmp_str); + zend_result ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str)); + zend_tmp_string_release(tmp_str); + return ret; + } else { + if (!zend_parse_arg_str(zvalue, &str, 0 /* check_null */, 2)) { + php_curl_setopt_type_failure(option, IS_STRING, zvalue, 1 /* nullable */); + return FAILURE; + } + return php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str)); + } } break; } @@ -2873,17 +2964,27 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue case CURLOPT_URL: { zend_string *tmp_str; - zend_string *str = zval_get_tmp_string(zvalue, &tmp_str); - zend_result ret = php_curl_option_url(ch, ZSTR_VAL(str), ZSTR_LEN(str)); - zend_tmp_string_release(tmp_str); - return ret; + zend_string *str; + if (is_procedural) { + str = zval_get_tmp_string(zvalue, &tmp_str); + zend_result ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str)); + zend_tmp_string_release(tmp_str); + return ret; + } else { + if (!zend_parse_arg_str(zvalue, &str, 0 /* check_null */, 2)) { + php_curl_setopt_type_failure(option, IS_STRING, zvalue, 0 /* nullable */); + return FAILURE; + } + return php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str)); + } } /* Curl file handle options */ case CURLOPT_FILE: case CURLOPT_INFILE: case CURLOPT_STDERR: - case CURLOPT_WRITEHEADER: { + case CURLOPT_WRITEHEADER: + { FILE *fp = NULL; php_stream *what = NULL; @@ -3069,11 +3170,6 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue /* Do nothing, just backward compatibility */ break; - case CURLOPT_FOLLOWLOCATION: - lval = zend_is_true(zvalue); - error = curl_easy_setopt(ch->cp, option, lval); - break; - case CURLOPT_HEADERFUNCTION: if (!Z_ISUNDEF(ch->handlers.write_header->func_name)) { zval_ptr_dtor(&ch->handlers.write_header->func_name); @@ -3271,12 +3367,13 @@ static zend_result _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue } else { zend_argument_value_error(2, "is not a valid cURL option"); } - error = CURLE_UNKNOWN_OPTION; - break; + SAVE_CURL_ERROR(ch, CURLE_UNKNOWN_OPTION); + return FAILURE; } SAVE_CURL_ERROR(ch, error); if (error != CURLE_OK) { + zend_throw_exception_ex(curl_exception_ce, ch->err.no, "Unable to set option: %s", curl_easy_strerror(ch->err.no)); return FAILURE; } else { return SUCCESS; @@ -3290,19 +3387,23 @@ PHP_FUNCTION(curl_setopt) zval *zid, *zvalue; zend_long options; php_curl *ch; + zend_result ret; + zend_bool is_procedural = (NULL == getThis()); - ZEND_PARSE_PARAMETERS_START(3, 3) - Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) - Z_PARAM_LONG(options) - Z_PARAM_ZVAL(zvalue) - ZEND_PARSE_PARAMETERS_END(); + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Olz", &zid, curl_ce, &options, &zvalue) == FAILURE) { + RETURN_THROWS(); + } ch = Z_CURL_P(zid); - if (_php_curl_setopt(ch, options, zvalue, 0) == SUCCESS) { - RETURN_TRUE; - } else { - RETURN_FALSE; + ret = _php_curl_setopt(ch, options, zvalue, is_procedural, 0); + + if (is_procedural) { + RETURN_BOOL(ret == SUCCESS); + } + + if (ret == SUCCESS) { + RETURN_OBJ_COPY(Z_OBJ_P(ZEND_THIS)); } } /* }}} */ @@ -3314,11 +3415,11 @@ PHP_FUNCTION(curl_setopt_array) php_curl *ch; zend_ulong option; zend_string *string_key; + zend_bool is_procedural = (NULL == getThis()); - ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) - Z_PARAM_ARRAY(arr) - ZEND_PARSE_PARAMETERS_END(); + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oa", &zid, curl_ce, &arr) == FAILURE) { + RETURN_THROWS(); + } ch = Z_CURL_P(zid); @@ -3329,12 +3430,20 @@ PHP_FUNCTION(curl_setopt_array) } ZVAL_DEREF(entry); - if (_php_curl_setopt(ch, (zend_long) option, entry, 1) == FAILURE) { - RETURN_FALSE; + if (_php_curl_setopt(ch, (zend_long) option, entry, is_procedural, 1) == FAILURE) { + if (is_procedural) { + RETURN_FALSE; + } else { + zend_throw_exception_ex(curl_exception_ce, ch->err.no, "Unable to set option: %s", curl_easy_strerror(ch->err.no)); + } } } ZEND_HASH_FOREACH_END(); - RETURN_TRUE; + if (NULL == getThis()) { + RETURN_TRUE; + } else { + RETURN_OBJ_COPY(Z_OBJ_P(ZEND_THIS)); + } } /* }}} */ @@ -3360,9 +3469,9 @@ PHP_FUNCTION(curl_exec) zval *zid; php_curl *ch; - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) - ZEND_PARSE_PARAMETERS_END(); + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zid, curl_ce) == FAILURE) { + RETURN_THROWS(); + } ch = Z_CURL_P(zid); @@ -3415,11 +3524,9 @@ PHP_FUNCTION(curl_getinfo) zend_long option; bool option_is_null = 1; - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) - Z_PARAM_OPTIONAL - Z_PARAM_LONG_OR_NULL(option, option_is_null) - ZEND_PARSE_PARAMETERS_END(); + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l!", &zid, curl_ce, &option, &option_is_null) == FAILURE) { + RETURN_THROWS(); + } ch = Z_CURL_P(zid); @@ -3699,9 +3806,9 @@ PHP_FUNCTION(curl_errno) zval *zid; php_curl *ch; - ZEND_PARSE_PARAMETERS_START(1,1) - Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) - ZEND_PARSE_PARAMETERS_END(); + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zid, curl_ce) == FAILURE) { + RETURN_THROWS(); + } ch = Z_CURL_P(zid); @@ -3898,9 +4005,9 @@ PHP_FUNCTION(curl_reset) zval *zid; php_curl *ch; - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) - ZEND_PARSE_PARAMETERS_END(); + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zid, curl_ce) == FAILURE) { + RETURN_THROWS(); + } ch = Z_CURL_P(zid); @@ -3923,10 +4030,9 @@ PHP_FUNCTION(curl_escape) zval *zid; php_curl *ch; - ZEND_PARSE_PARAMETERS_START(2,2) - Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) - Z_PARAM_STR(str) - ZEND_PARSE_PARAMETERS_END(); + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OS", &zid, curl_ce, &str) == FAILURE) { + RETURN_THROWS(); + } ch = Z_CURL_P(zid); @@ -3952,10 +4058,9 @@ PHP_FUNCTION(curl_unescape) zend_string *str; php_curl *ch; - ZEND_PARSE_PARAMETERS_START(2,2) - Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) - Z_PARAM_STR(str) - ZEND_PARSE_PARAMETERS_END(); + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OS", &zid, curl_ce, &str) == FAILURE) { + RETURN_THROWS(); + } ch = Z_CURL_P(zid); @@ -3978,15 +4083,22 @@ PHP_FUNCTION(curl_pause) zend_long bitmask; zval *zid; php_curl *ch; + CURLcode res; - ZEND_PARSE_PARAMETERS_START(2,2) - Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) - Z_PARAM_LONG(bitmask) - ZEND_PARSE_PARAMETERS_END(); + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &zid, curl_ce, &bitmask) == FAILURE) { + RETURN_THROWS(); + } ch = Z_CURL_P(zid); - RETURN_LONG(curl_easy_pause(ch->cp, bitmask)); + res = curl_easy_pause(ch->cp, bitmask); + if (NULL == getThis()) { + RETURN_LONG(res); + } + + if (res != CURLE_OK) { + zend_throw_exception_ex(curl_exception_ce, ch->err.no, "Unable to pause: %s", curl_easy_strerror(ch->err.no)); + } } /* }}} */ @@ -3994,20 +4106,26 @@ PHP_FUNCTION(curl_pause) /* {{{ perform connection upkeep checks */ PHP_FUNCTION(curl_upkeep) { - CURLcode error; + CURLcode res; zval *zid; php_curl *ch; - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_OBJECT_OF_CLASS(zid, curl_ce) - ZEND_PARSE_PARAMETERS_END(); + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &zid, curl_ce) == FAILURE) { + RETURN_THROWS(); + } ch = Z_CURL_P(zid); - error = curl_easy_upkeep(ch->cp); - SAVE_CURL_ERROR(ch, error); + res = curl_easy_upkeep(ch->cp); + SAVE_CURL_ERROR(ch, res); - RETURN_BOOL(error == CURLE_OK); + if (NULL == getThis()) { + RETURN_BOOL(res == CURLE_OK); + } + + if (res != CURLE_OK) { + zend_throw_exception_ex(curl_exception_ce, ch->err.no, "Unable to perform upkeep: %s", curl_easy_strerror(ch->err.no)); + } } /*}}} */ #endif diff --git a/ext/curl/php_curl.h b/ext/curl/php_curl.h index bc92c51121ec8..7f3907ae9ecf9 100644 --- a/ext/curl/php_curl.h +++ b/ext/curl/php_curl.h @@ -38,6 +38,7 @@ extern zend_module_entry curl_module_entry; PHP_CURL_API extern zend_class_entry *curl_ce; PHP_CURL_API extern zend_class_entry *curl_share_ce; PHP_CURL_API extern zend_class_entry *curl_multi_ce; +PHP_CURL_API extern zend_class_entry *curl_exception_ce; PHP_CURL_API extern zend_class_entry *curl_CURLFile_class; PHP_CURL_API extern zend_class_entry *curl_CURLStringFile_class; diff --git a/ext/curl/tests/bug80121.phpt b/ext/curl/tests/bug80121.phpt index a7bf6385367d6..246ac14a1d965 100644 --- a/ext/curl/tests/bug80121.phpt +++ b/ext/curl/tests/bug80121.phpt @@ -5,11 +5,6 @@ curl --FILE-- getMessage(), "\n"; -} try { new CurlMultiHandle; } catch (Error $e) { @@ -23,6 +18,5 @@ try { ?> --EXPECT-- -Cannot directly construct CurlHandle, use curl_init() instead Cannot directly construct CurlMultiHandle, use curl_multi_init() instead Cannot directly construct CurlShareHandle, use curl_share_init() instead diff --git a/ext/curl/tests/curl_object_020.phpt b/ext/curl/tests/curl_object_020.phpt new file mode 100644 index 0000000000000..0205c2095619d --- /dev/null +++ b/ext/curl/tests/curl_object_020.phpt @@ -0,0 +1,20 @@ +--TEST-- +Test curl_getinfo() function with CURLINFO_HTTP_CODE parameter +--CREDITS-- +Jean-Marc Fontaine +--EXTENSIONS-- +curl +--FILE-- +setOpt(CURLOPT_URL, $url); + $ch->exec(); + var_dump($ch->getInfo(CURLINFO_HTTP_CODE)); +?> +--EXPECT-- +Hello World! +Hello World!int(200) diff --git a/ext/curl/tests/curl_object_escape.phpt b/ext/curl/tests/curl_object_escape.phpt new file mode 100644 index 0000000000000..4a6b94d8c6c47 --- /dev/null +++ b/ext/curl/tests/curl_object_escape.phpt @@ -0,0 +1,18 @@ +--TEST-- +Test curl_escape and curl_unescape() functions +--EXTENSIONS-- +curl +--FILE-- +escape($str); +$original = $a->unescape($escaped); +var_dump($escaped, $original); +var_dump($a->unescape('a%00b')); +?> +--EXPECTF-- +string(36) "http%3A%2F%2Fwww.php.net%2F%20%3F%21" +string(22) "http://www.php.net/ ?!" +string(3) "a%0b" diff --git a/ext/curl/tests/curl_reset_002.phpt b/ext/curl/tests/curl_reset_002.phpt new file mode 100644 index 0000000000000..90dcc9359521c --- /dev/null +++ b/ext/curl/tests/curl_reset_002.phpt @@ -0,0 +1,37 @@ +--TEST-- +Test CurlHandle::reset() +--EXTENSIONS-- +curl +--FILE-- +setOpt(CURLOPT_FILE, $testfile_fp); +$ch->setOpt(CURLOPT_URL, 'file://' . $log_file); +$ch->exec(); + +$ch->reset(); +$ch->setOpt(CURLOPT_URL, 'file://' . $log_file); +$ch->exec(); + +unset($ch); + +fclose($testfile_fp); + +echo file_get_contents($test_file); + +// cleanup +unlink($test_file); +unlink($log_file); +?> +--EXPECT-- +testtest diff --git a/ext/curl/tests/curl_setopt_005.phpt b/ext/curl/tests/curl_setopt_005.phpt new file mode 100644 index 0000000000000..85a407104227d --- /dev/null +++ b/ext/curl/tests/curl_setopt_005.phpt @@ -0,0 +1,19 @@ +--TEST-- +curl_setopt() with error +--EXTENSIONS-- +curl +--FILE-- +setOpt(CURLOPT_CONNECTTIMEOUT, -10); +} catch (CurlException $e) { + var_dump($e->getCode(), $e->getMessage()); +} + +?> +==DONE== +--EXPECT-- +int(43) +string(65) "Unable to set option: A libcurl function was given a bad argument" +==DONE== diff --git a/ext/curl/tests/curl_setopt_array_object.phpt b/ext/curl/tests/curl_setopt_array_object.phpt new file mode 100644 index 0000000000000..fdb12371ff7fb --- /dev/null +++ b/ext/curl/tests/curl_setopt_array_object.phpt @@ -0,0 +1,37 @@ +--TEST-- +CurlUrl::setOptArray() - tests setting multiple cURL options +--EXTENSIONS-- +curl +--FILE-- + $url, + CURLOPT_RETURNTRANSFER => 1 +); + +ob_start(); // start output buffering + +$ch->setOptArray($options); +$returnContent = $ch->exec(); +unset($ch); + +var_dump($returnContent); +isset($tempname) and is_file($tempname) and @unlink($tempname); + +?> +--EXPECT-- +string(25) "Hello World! +Hello World!" diff --git a/ext/curl/tests/curl_upkeep_002.phpt b/ext/curl/tests/curl_upkeep_002.phpt new file mode 100644 index 0000000000000..2b0e7f1f93dbc --- /dev/null +++ b/ext/curl/tests/curl_upkeep_002.phpt @@ -0,0 +1,29 @@ +--TEST-- +curl_upkeep() function +--EXTENSIONS-- +curl +--SKIPIF-- += 7.62.0'); +?> +--FILE-- +setOpt(CURLOPT_URL,$url) + ->setOpt(CURLOPT_RETURNTRANSFER,true) + ->setOpt(CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_2_0) + ->setOpt(CURLOPT_SSL_VERIFYPEER,false) + ->setOpt(CURLOPT_UPKEEP_INTERVAL_MS, 200); + +if ($ch->exec()) { + usleep(300); + $ch->upkeep(); + echo '==DONE=='; +} +?> +--EXPECT-- +==DONE== diff --git a/ext/curl/tests/curlhandle_setopt_001.phpt b/ext/curl/tests/curlhandle_setopt_001.phpt new file mode 100644 index 0000000000000..cbc275f1aa560 --- /dev/null +++ b/ext/curl/tests/curlhandle_setopt_001.phpt @@ -0,0 +1,17 @@ +--TEST-- +CurlHandle::setOpt() with invalid bool non strict +--EXTENSIONS-- +curl +--FILE-- +setOpt(CURLOPT_VERBOSE, 1); +} catch (CurlException $e) { + var_dump($e->getCode(), $e->getMessage()); +} + +?> +==DONE== +--EXPECT-- +==DONE== diff --git a/ext/curl/tests/curlhandle_setopt_002.phpt b/ext/curl/tests/curlhandle_setopt_002.phpt new file mode 100644 index 0000000000000..fa89384334151 --- /dev/null +++ b/ext/curl/tests/curlhandle_setopt_002.phpt @@ -0,0 +1,20 @@ +--TEST-- +CurlHandle::setOpt() with invalid bool strict +--EXTENSIONS-- +curl +--FILE-- +setOpt(CURLOPT_VERBOSE, 1); +} catch (TypeError $e) { + var_dump($e->getMessage()); +} + +?> +==DONE== +--EXPECT-- +string(100) "Argument 2 passed to CurlHandle::setOpt() for option CURLOPT_VERBOSE must be of type bool, int given" +==DONE== diff --git a/ext/curl/tests/curlhandle_setopt_003.phpt b/ext/curl/tests/curlhandle_setopt_003.phpt new file mode 100644 index 0000000000000..7a7ac5b095053 --- /dev/null +++ b/ext/curl/tests/curlhandle_setopt_003.phpt @@ -0,0 +1,23 @@ +--TEST-- +CurlHandle::setOpt() with invalid int non strict +--EXTENSIONS-- +curl +--FILE-- +setOpt(CURLOPT_BUFFERSIZE, "2"); +} catch (TypeError $e) { + var_dump($e->getMessage()); +} +try { + (new CurlHandle())->setOpt(CURLOPT_BUFFERSIZE, "OK"); +} catch (TypeError $e) { + var_dump($e->getMessage()); +} + +?> +==DONE== +--EXPECT-- +string(105) "Argument 2 passed to CurlHandle::setOpt() for option CURLOPT_BUFFERSIZE must be of type int, string given" +==DONE== diff --git a/ext/curl/tests/curlhandle_setopt_004.phpt b/ext/curl/tests/curlhandle_setopt_004.phpt new file mode 100644 index 0000000000000..64fd8a1220dda --- /dev/null +++ b/ext/curl/tests/curlhandle_setopt_004.phpt @@ -0,0 +1,26 @@ +--TEST-- +CurlHandle::setOpt() with invalid int strict +--EXTENSIONS-- +curl +--FILE-- +setOpt(CURLOPT_BUFFERSIZE, "2"); +} catch (TypeError $e) { + var_dump($e->getMessage()); +} +try { + (new CurlHandle())->setOpt(CURLOPT_BUFFERSIZE, "OK"); +} catch (TypeError $e) { + var_dump($e->getMessage()); +} + +?> +==DONE== +--EXPECT-- +string(105) "Argument 2 passed to CurlHandle::setOpt() for option CURLOPT_BUFFERSIZE must be of type int, string given" +string(105) "Argument 2 passed to CurlHandle::setOpt() for option CURLOPT_BUFFERSIZE must be of type int, string given" +==DONE== diff --git a/ext/curl/tests/curlhandle_setopt_005.phpt b/ext/curl/tests/curlhandle_setopt_005.phpt new file mode 100644 index 0000000000000..c10951217bc9e --- /dev/null +++ b/ext/curl/tests/curlhandle_setopt_005.phpt @@ -0,0 +1,17 @@ +--TEST-- +CurlHandle::setOpt() with invalid string non strict +--EXTENSIONS-- +curl +--FILE-- +setOpt(CURLOPT_NOPROXY, 20); +} catch (TypeError $e) { + var_dump($e->getMessage()); +} + +?> +==DONE== +--EXPECT-- +==DONE== diff --git a/ext/curl/tests/curlhandle_setopt_006.phpt b/ext/curl/tests/curlhandle_setopt_006.phpt new file mode 100644 index 0000000000000..8a50ce5126b62 --- /dev/null +++ b/ext/curl/tests/curlhandle_setopt_006.phpt @@ -0,0 +1,20 @@ +--TEST-- +CurlHandle::setOpt() with invalid string strict +--EXTENSIONS-- +curl +--FILE-- +setOpt(CURLOPT_NOPROXY, 20); +} catch (TypeError $e) { + var_dump($e->getMessage()); +} + +?> +==DONE== +--EXPECT-- +string(102) "Argument 2 passed to CurlHandle::setOpt() for option CURLOPT_NOPROXY must be of type string, int given" +==DONE== diff --git a/ext/curl/tests/curlhandle_setopt_007.phpt b/ext/curl/tests/curlhandle_setopt_007.phpt new file mode 100644 index 0000000000000..26044692d2838 --- /dev/null +++ b/ext/curl/tests/curlhandle_setopt_007.phpt @@ -0,0 +1,22 @@ +--TEST-- +CurlHandle::setOpt() with invalid nullable string non strict +--EXTENSIONS-- +curl +--FILE-- +setOpt(CURLOPT_CUSTOMREQUEST, 0); +} catch (TypeError $e) { + var_dump($e->getMessage()); +} +try { + (new CurlHandle())->setOpt(CURLOPT_CUSTOMREQUEST, 20); +} catch (TypeError $e) { + var_dump($e->getMessage()); +} + +?> +==DONE== +--EXPECT-- +==DONE== diff --git a/ext/curl/tests/curlhandle_setopt_008.phpt b/ext/curl/tests/curlhandle_setopt_008.phpt new file mode 100644 index 0000000000000..c69b8e0b8b968 --- /dev/null +++ b/ext/curl/tests/curlhandle_setopt_008.phpt @@ -0,0 +1,26 @@ +--TEST-- +CurlHandle::setOpt() with invalid nullable string strict +--EXTENSIONS-- +curl +--FILE-- +setOpt(CURLOPT_CUSTOMREQUEST, 0); +} catch (TypeError $e) { + var_dump($e->getMessage()); +} +try { + (new CurlHandle())->setOpt(CURLOPT_CUSTOMREQUEST, 20); +} catch (TypeError $e) { + var_dump($e->getMessage()); +} + +?> +==DONE== +--EXPECT-- +string(109) "Argument 2 passed to CurlHandle::setOpt() for option CURLOPT_CUSTOMREQUEST must be of type ?string, int given" +string(109) "Argument 2 passed to CurlHandle::setOpt() for option CURLOPT_CUSTOMREQUEST must be of type ?string, int given" +==DONE== diff --git a/ext/curl/tests/curlhandle_setopt_009.phpt b/ext/curl/tests/curlhandle_setopt_009.phpt new file mode 100644 index 0000000000000..17cd435c13b69 --- /dev/null +++ b/ext/curl/tests/curlhandle_setopt_009.phpt @@ -0,0 +1,19 @@ +--TEST-- +CurlHandle::setOpt() with invalid URL non strict +--EXTENSIONS-- +curl +--FILE-- +setOpt(CURLOPT_URL, 10); + var_dump($ch->getInfo(CURLINFO_EFFECTIVE_URL)); +} catch (TypeError $e) { + var_dump($e->getMessage()); +} +?> +==DONE== +--EXPECT-- +string(2) "10" +==DONE== diff --git a/ext/curl/tests/curlhandle_setopt_010.phpt b/ext/curl/tests/curlhandle_setopt_010.phpt new file mode 100644 index 0000000000000..69ec66888ebd9 --- /dev/null +++ b/ext/curl/tests/curlhandle_setopt_010.phpt @@ -0,0 +1,21 @@ +--TEST-- +CurlHandle::setOpt() with invalid URL strict +--EXTENSIONS-- +curl +--FILE-- +setOpt(CURLOPT_URL, 10); + var_dump($ch->getInfo(CURLINFO_EFFECTIVE_URL)); +} catch (TypeError $e) { + var_dump($e->getMessage()); +} +?> +==DONE== +--EXPECT-- +string(98) "Argument 2 passed to CurlHandle::setOpt() for option CURLOPT_URL must be of type string, int given" +==DONE== diff --git a/ext/curl/url.c b/ext/curl/url.c new file mode 100644 index 0000000000000..e69de29bb2d1d