Skip to content

Commit b5eb1f8

Browse files
committed
ext/curl: Add feature_info assoc array to curl_version()
The `phpinfo()` section of the Curl extension lists individual features supported by the particular ext-Curl + libcurl build. However, the `curl_version()` function return values do not indicate the same level of details. `curl_version()` has a `protocols` key that returns an array of all protocols supported by the build. But the `features` key is a bitmask of all the features. Checking the availability of certain feature requires knowing the corresponding `CURL_VERSION` constant, and checking the availability of the constant and a bitmask check for it in the `features` value. For example, to determine HTTP2 support, it requires evaluating: ```php defined('CURL_VERSION_HTTP2') && (curl_version()['features'] & CURL_VERSION_HTTP2 === CURL_VERSION_HTTP2) ``` To make feature availability checks more intuitive, this adds a new `feature_list` key to `curl_version()` output array. With it, checking for individual features availability is easier, and does not require inspecting the availability of the `CURL_VERSION` constant and the `features` key. ```php !empty(curl_version()['feature_list']['HTTP2']); ```
1 parent 03f1553 commit b5eb1f8

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ PHP NEWS
1818
- Curl:
1919
. Deprecated the CURLOPT_BINARYTRANSFER constant. (divinity76)
2020
. Bumped required libcurl version to 7.61.0. (Ayesh)
21+
. Added feature_list key to the curl_version() return value (Ayesh)
2122

2223
- Date:
2324
. Added DateTime[Immutable]::createFromTimestamp. (Marc Bennewitz)

UPGRADING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ PHP 8.4 UPGRADE NOTES
252252

253253
- Curl:
254254
. The CURLOPT_BINARYTRANSFER constant is deprecated.
255+
. curl_version() returns an additional feature_list value, which is an
256+
associative array of all known Curl features, and whether they are
257+
supported (true) or not (false).
255258

256259
- Date:
257260
. Calling DatePeriod::__construct(string $isostr, int $options = 0) is

ext/curl/interface.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ PHP_MINFO_FUNCTION(curl)
261261
php_info_print_table_row(2, "Age", str);
262262

263263
/* To update on each new cURL release using src/main.c in cURL sources */
264+
/* make sure to sync this list with curl_version as well */
264265
if (d->features) {
265266
struct feat {
266267
const char *name;
@@ -1000,6 +1001,68 @@ PHP_FUNCTION(curl_version)
10001001
CAAL("version_number", d->version_num);
10011002
CAAL("age", d->age);
10021003
CAAL("features", d->features);
1004+
/* Add an array of features */
1005+
{
1006+
struct feat {
1007+
const char *name;
1008+
int bitmask;
1009+
};
1010+
1011+
unsigned int i;
1012+
zval feature_list;
1013+
array_init(&feature_list);
1014+
1015+
/* Sync this list with PHP_MINFO_FUNCTION(curl) as well */
1016+
static const struct feat feats[] = {
1017+
{"AsynchDNS", CURL_VERSION_ASYNCHDNS},
1018+
{"CharConv", CURL_VERSION_CONV},
1019+
{"Debug", CURL_VERSION_DEBUG},
1020+
{"GSS-Negotiate", CURL_VERSION_GSSNEGOTIATE},
1021+
{"IDN", CURL_VERSION_IDN},
1022+
{"IPv6", CURL_VERSION_IPV6},
1023+
{"krb4", CURL_VERSION_KERBEROS4},
1024+
{"Largefile", CURL_VERSION_LARGEFILE},
1025+
{"libz", CURL_VERSION_LIBZ},
1026+
{"NTLM", CURL_VERSION_NTLM},
1027+
{"NTLMWB", CURL_VERSION_NTLM_WB},
1028+
{"SPNEGO", CURL_VERSION_SPNEGO},
1029+
{"SSL", CURL_VERSION_SSL},
1030+
{"SSPI", CURL_VERSION_SSPI},
1031+
{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
1032+
{"HTTP2", CURL_VERSION_HTTP2},
1033+
{"GSSAPI", CURL_VERSION_GSSAPI},
1034+
{"KERBEROS5", CURL_VERSION_KERBEROS5},
1035+
{"UNIX_SOCKETS", CURL_VERSION_UNIX_SOCKETS},
1036+
{"PSL", CURL_VERSION_PSL},
1037+
{"HTTPS_PROXY", CURL_VERSION_HTTPS_PROXY},
1038+
{"MULTI_SSL", CURL_VERSION_MULTI_SSL},
1039+
{"BROTLI", CURL_VERSION_BROTLI},
1040+
#if LIBCURL_VERSION_NUM >= 0x074001 /* Available since 7.64.1 */
1041+
{"ALTSVC", CURL_VERSION_ALTSVC},
1042+
#endif
1043+
#if LIBCURL_VERSION_NUM >= 0x074200 /* Available since 7.66.0 */
1044+
{"HTTP3", CURL_VERSION_HTTP3},
1045+
#endif
1046+
#if LIBCURL_VERSION_NUM >= 0x074800 /* Available since 7.72.0 */
1047+
{"UNICODE", CURL_VERSION_UNICODE},
1048+
{"ZSTD", CURL_VERSION_ZSTD},
1049+
#endif
1050+
#if LIBCURL_VERSION_NUM >= 0x074a00 /* Available since 7.74.0 */
1051+
{"HSTS", CURL_VERSION_HSTS},
1052+
#endif
1053+
#if LIBCURL_VERSION_NUM >= 0x074c00 /* Available since 7.76.0 */
1054+
{"GSASL", CURL_VERSION_GSASL},
1055+
#endif
1056+
};
1057+
1058+
for(i = 0; i < sizeof(feats) / sizeof(feats[0]); i++) {
1059+
if (feats[i].name) {
1060+
add_assoc_bool(&feature_list, feats[i].name, d->features & feats[i].bitmask ? 1 : 0);
1061+
}
1062+
}
1063+
1064+
CAAZ("feature_list", &feature_list);
1065+
}
10031066
CAAL("ssl_version_number", d->ssl_version_num);
10041067
CAAS("version", d->version);
10051068
CAAS("host", d->host);
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
--TEST--
2+
Test curl_version() - feature_list functionality
3+
--EXTENSIONS--
4+
curl
5+
--FILE--
6+
<?php
7+
$info_curl = curl_version();
8+
var_dump(array_key_exists("feature_list", $info_curl));
9+
var_dump(!array_is_list($info_curl['feature_list']));
10+
11+
print_r(array_map(fn ($v) => get_debug_type($v), $info_curl['feature_list']));
12+
13+
ob_start();
14+
phpinfo();
15+
$phpinfo = ob_get_clean();
16+
17+
foreach ($info_curl['feature_list'] as $key => $value) {
18+
if (!is_bool($value)) {
19+
throw new Exception('Found non-bool value');
20+
}
21+
22+
if (!str_contains($phpinfo, $key .' => ' . $value ? 'Yes' : 'No')) {
23+
throw new Exception($key . ' not found in Curl phpinfo()');
24+
}
25+
}
26+
27+
echo "Complete";
28+
?>
29+
--EXPECTF--
30+
bool(true)
31+
bool(true)
32+
Array
33+
(
34+
[AsynchDNS] => bool
35+
[CharConv] => bool
36+
[Debug] => bool
37+
[GSS-Negotiate] => bool
38+
[IDN] => bool
39+
[IPv6] => bool
40+
[krb4] => bool
41+
[Largefile] => bool
42+
[libz] => bool
43+
[NTLM] => bool
44+
[NTLMWB] => bool
45+
[SPNEGO] => bool
46+
[SSL] => bool
47+
[SSPI] => bool
48+
[TLS-SRP] => bool
49+
[HTTP2] => bool
50+
[GSSAPI] => bool
51+
[KERBEROS5] => bool
52+
[UNIX_SOCKETS] => bool
53+
[PSL] => bool
54+
[HTTPS_PROXY] => bool
55+
[MULTI_SSL] => bool
56+
[BROTLI] => bool
57+
%A
58+
)
59+
Complete

0 commit comments

Comments
 (0)