diff --git a/UPGRADING b/UPGRADING index 2a82975517178..1d878a44e2a10 100644 --- a/UPGRADING +++ b/UPGRADING @@ -188,6 +188,11 @@ PHP 8.5 UPGRADE NOTES first redirect thus if there is any follow up redirect, it won't go any further. CURLFOLLOW_ALL is equivalent to setting CURLOPT_FOLLOWLOCATION to true. + . Added support for CURLINFO_CONN_ID (libcurl >= 8.2.0) to the curl_getinfo() + function. This constant allows retrieving the unique ID of the connection + used by a cURL transfer. It is primarily useful when connection reuse or + connection pooling logic is needed in PHP-level applications. When + curl_getinfo() returns an array, this value is available as the "conn_id" key. - DOM: . Added Dom\Element::$outerHTML. @@ -517,6 +522,7 @@ PHP 8.5 UPGRADE NOTES . CURLINFO_USED_PROXY. . CURLINFO_HTTPAUTH_USED. . CURLINFO_PROXYAUTH_USED. + . CURLINFO_CONN_ID. . CURLOPT_INFILESIZE_LARGE. . CURLFOLLOW_ALL. . CURLFOLLOW_OBEYCODE. diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c index 8c42b2494ea08..28a275e6fce74 100644 --- a/Zend/zend_llist.c +++ b/Zend/zend_llist.c @@ -121,7 +121,6 @@ ZEND_API void zend_llist_destroy(zend_llist *l) ZEND_API void zend_llist_clean(zend_llist *l) { zend_llist_destroy(l); - l->head = l->tail = NULL; } diff --git a/ext/curl/config.m4 b/ext/curl/config.m4 index f3c39b4c5179d..bbb41fdde3223 100644 --- a/ext/curl/config.m4 +++ b/ext/curl/config.m4 @@ -15,8 +15,8 @@ if test "$PHP_CURL" != "no"; then AC_MSG_RESULT([$CURL_SSL]) AS_IF([test "x$PHP_THREAD_SAFETY" = xyes && test "x$CURL_SSL" = xyes], - [AC_CACHE_CHECK([whether libcurl is linked against old OpenSSL < 1.1], - [php_cv_lib_curl_ssl], [ + [AC_CACHE_CHECK([whether libcurl is linked against a supported OpenSSL version], + [php_cv_lib_curl_ssl_supported], [ save_LIBS=$LIBS save_CFLAGS=$CFLAGS LIBS="$LIBS $CURL_SHARED_LIBADD" @@ -34,17 +34,14 @@ if test "$PHP_CURL" != "no"; then while(*ptr == ' ') ++ptr; int major, minor; - if (sscanf(ptr, "OpenSSL/%d", &major) == 1) { - if (major >= 3) { - /* OpenSSL version 3 or later */ - return 4; - } - } if (sscanf(ptr, "OpenSSL/%d.%d", &major, &minor) == 2) { - if (major > 1 || (major == 1 && minor >= 1)) { - /* OpenSSL version 1.1 or later */ + /* Check for 1.1.1+ (including 1.1.1a, 1.1.1b, etc.) */ + if ((major > 1) || (major == 1 && minor == 1 && strncmp(ptr + 12, "1", 1) == 0)) { + /* OpenSSL 1.1.1+ - supported */ return 3; } + /* OpenSSL 1.1.0 and earlier - unsupported */ + return 0; } if (strncasecmp(ptr, "OpenSSL", sizeof("OpenSSL")-1) == 0) { /* Old OpenSSL version */ @@ -56,18 +53,15 @@ if test "$PHP_CURL" != "no"; then /* No SSL support */ return 1; ])], - [php_cv_lib_curl_ssl=yes], - [php_cv_lib_curl_ssl=no], - [php_cv_lib_curl_ssl=no]) + [php_cv_lib_curl_ssl_supported=no], + [php_cv_lib_curl_ssl_supported=yes], + [php_cv_lib_curl_ssl_supported=yes]) LIBS=$save_LIBS CFLAGS=$save_CFLAGS ]) - AS_VAR_IF([php_cv_lib_curl_ssl], [yes], [ - AC_DEFINE([HAVE_CURL_OLD_OPENSSL], [1], - [Define to 1 if libcurl is linked against old OpenSSL < 1.1.]) - PHP_SETUP_OPENSSL([CURL_SHARED_LIBADD], - [AC_CHECK_HEADERS([openssl/crypto.h])]) + AS_VAR_IF([php_cv_lib_curl_ssl_supported], [no], [ + AC_MSG_ERROR([libcurl is linked against an unsupported OpenSSL version. OpenSSL 1.1.1 or later is required.]) ]) ]) diff --git a/ext/curl/curl.stub.php b/ext/curl/curl.stub.php index 00532f45793f5..5dac22ae7952c 100644 --- a/ext/curl/curl.stub.php +++ b/ext/curl/curl.stub.php @@ -3103,6 +3103,13 @@ */ const CURLINFO_POSTTRANSFER_TIME_T = UNKNOWN; #endif +#if LIBCURL_VERSION_NUM >= 0x080200 /* Available since 8.2.0 */ +/** + * @var int + * @cvalue CURLINFO_CONN_ID + */ +const CURLINFO_CONN_ID = UNKNOWN; +#endif /** * @var int * @cvalue CURLOPT_DISALLOW_USERNAME_IN_URL diff --git a/ext/curl/curl_arginfo.h b/ext/curl/curl_arginfo.h index 1defefdab2d00..75be3b75c4983 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: c087ac501d0abe14ed87968023d837f358e6fee8 */ + * Stub hash: 533884c442ca1146a61c0824a4f8c9628c31aae3 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_curl_close, 0, 1, IS_VOID, 0) ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) @@ -824,6 +824,9 @@ static void register_curl_symbols(int module_number) #endif #if LIBCURL_VERSION_NUM >= 0x080a00 /* Available since 8.10.0 */ REGISTER_LONG_CONSTANT("CURLINFO_POSTTRANSFER_TIME_T", CURLINFO_POSTTRANSFER_TIME_T, CONST_PERSISTENT); +#endif +#if LIBCURL_VERSION_NUM >= 0x080200 /* Available since 8.2.0 */ + REGISTER_LONG_CONSTANT("CURLINFO_CONN_ID", CURLINFO_CONN_ID, CONST_PERSISTENT); #endif REGISTER_LONG_CONSTANT("CURLOPT_DISALLOW_USERNAME_IN_URL", CURLOPT_DISALLOW_USERNAME_IN_URL, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CURLOPT_PROXY_TLS13_CIPHERS", CURLOPT_PROXY_TLS13_CIPHERS, CONST_PERSISTENT); diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 4cba1e4d32891..ffb7889c748b2 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -39,20 +39,6 @@ #define HttpPost curl_httppost #endif -/* {{{ cruft for thread safe SSL crypto locks */ -#if defined(ZTS) && defined(HAVE_CURL_OLD_OPENSSL) -# if defined(HAVE_OPENSSL_CRYPTO_H) -# define PHP_CURL_NEED_OPENSSL_TSL -# include -# else -# warning \ - "libcurl was compiled with OpenSSL support, but configure could not find " \ - "openssl/crypto.h; thus no SSL crypto locking callbacks will be set, which may " \ - "cause random crashes on SSL requests" -# endif -#endif /* ZTS && HAVE_CURL_OLD_OPENSSL */ -/* }}} */ - #include "zend_smart_str.h" #include "ext/standard/info.h" #include "ext/standard/file.h" @@ -70,27 +56,6 @@ ZEND_DECLARE_MODULE_GLOBALS(curl) -#ifdef PHP_CURL_NEED_OPENSSL_TSL /* {{{ */ -static MUTEX_T *php_curl_openssl_tsl = NULL; - -/* Locking callbacks are no longer used since OpenSSL 1.1. Mark the functions as unused to - * avoid warnings due to this. */ -static ZEND_ATTRIBUTE_UNUSED void php_curl_ssl_lock(int mode, int n, const char * file, int line) -{ - if (mode & CRYPTO_LOCK) { - tsrm_mutex_lock(php_curl_openssl_tsl[n]); - } else { - tsrm_mutex_unlock(php_curl_openssl_tsl[n]); - } -} - -static ZEND_ATTRIBUTE_UNUSED unsigned long php_curl_ssl_id(void) -{ - return (unsigned long) tsrm_thread_id(); -} -#endif -/* }}} */ - #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 : "")); @@ -389,24 +354,6 @@ PHP_MINIT_FUNCTION(curl) register_curl_symbols(module_number); -#ifdef PHP_CURL_NEED_OPENSSL_TSL - if (!CRYPTO_get_id_callback()) { - int i, c = CRYPTO_num_locks(); - - php_curl_openssl_tsl = malloc(c * sizeof(MUTEX_T)); - if (!php_curl_openssl_tsl) { - return FAILURE; - } - - for (i = 0; i < c; ++i) { - php_curl_openssl_tsl[i] = tsrm_mutex_alloc(); - } - - CRYPTO_set_id_callback(php_curl_ssl_id); - CRYPTO_set_locking_callback(php_curl_ssl_lock); - } -#endif - if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) { return FAILURE; } @@ -568,21 +515,6 @@ zend_result curl_cast_object(zend_object *obj, zval *result, int type) PHP_MSHUTDOWN_FUNCTION(curl) { curl_global_cleanup(); -#ifdef PHP_CURL_NEED_OPENSSL_TSL - if (php_curl_openssl_tsl) { - int i, c = CRYPTO_num_locks(); - - CRYPTO_set_id_callback(NULL); - CRYPTO_set_locking_callback(NULL); - - for (i = 0; i < c; ++i) { - tsrm_mutex_free(php_curl_openssl_tsl[i]); - } - - free(php_curl_openssl_tsl); - php_curl_openssl_tsl = NULL; - } -#endif UNREGISTER_INI_ENTRIES(); return SUCCESS; } @@ -2690,6 +2622,11 @@ PHP_FUNCTION(curl_getinfo) if (curl_easy_getinfo(ch->cp, CURLINFO_PROXYAUTH_USED, &l_code) == CURLE_OK) { CAAL("proxyauth_used", l_code); } +#endif +#if LIBCURL_VERSION_NUM >= 0x080200 /* Available since 8.2.0 */ + if (curl_easy_getinfo(ch->cp, CURLINFO_CONN_ID , &co) == CURLE_OK) { + CAAL("conn_id", co); + } #endif } else { switch (option) { diff --git a/ext/curl/tests/curl_getinfo_CURLINFO_CONN_ID.phpt b/ext/curl/tests/curl_getinfo_CURLINFO_CONN_ID.phpt new file mode 100644 index 0000000000000..4a90b0a3c52e3 --- /dev/null +++ b/ext/curl/tests/curl_getinfo_CURLINFO_CONN_ID.phpt @@ -0,0 +1,146 @@ +--TEST-- +Curlinfo CURLINFO_CONN_ID +--EXTENSIONS-- +curl +--SKIPIF-- += 8.2.0"); +?> +--FILE-- +0); + +foreach([$ch1, $ch2] as $key => $ch) { + $result = curl_multi_getcontent($ch); + $info = curl_getinfo($ch); + var_dump(isset($info['conn_id'])); + var_dump(is_int($info['conn_id'])); + var_dump(curl_getinfo($ch, CURLINFO_CONN_ID) === $info['conn_id']); + var_dump(curl_getinfo($ch, CURLINFO_CONN_ID) === $key); +} + +$csh = curl_share_init(); + +curl_share_setopt($csh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); +curl_share_setopt($csh, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); +curl_share_setopt($csh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); +curl_share_setopt($csh, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); + + +$ch1=curl_init(); +$ch2=curl_init(); + +foreach([$ch1, $ch2] as $ch) { + curl_setopt($ch, CURLOPT_URL, "{$host}/get.inc?test=getpost&get_param=Curl%20Handle"); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $info = curl_getinfo($ch); + var_dump(isset($info['conn_id'])); + var_dump($info['conn_id'] === -1); +} + + +curl_setopt($ch1, CURLOPT_SHARE, $csh); + +$result = curl_exec($ch1); + +$info = curl_getinfo($ch1); +var_dump(isset($info['conn_id'])); +var_dump(is_int($info['conn_id'])); +var_dump(curl_getinfo($ch1, CURLINFO_CONN_ID) === $info['conn_id']); +var_dump(curl_getinfo($ch1, CURLINFO_CONN_ID) === 0); + +curl_setopt($ch2, CURLOPT_SHARE, $csh); + +$result = curl_exec($ch2); + +$info = curl_getinfo($ch2); +var_dump(isset($info['conn_id'])); +var_dump(is_int($info['conn_id'])); +var_dump(curl_getinfo($ch2, CURLINFO_CONN_ID) === $info['conn_id']); +var_dump(curl_getinfo($ch2, CURLINFO_CONN_ID) === 1); + +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +