version: add a feature names array to curl_version_info_data

Field feature_names contains a null-terminated sorted array of feature
names. Bitmask field features is deprecated.

Documentation is updated. Test 1177 and tests/version-scan.pl updated to
match new documentation format and extended to check feature names too.

Closes #9583
This commit is contained in:
Patrick Monnerat 2022-11-09 00:27:32 +01:00 committed by Daniel Stenberg
parent 00ea0aaf46
commit e780aae77a
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
6 changed files with 307 additions and 144 deletions

View file

@ -382,93 +382,145 @@ static const char * const protocols[] = {
NULL
};
/*
* Feature presence run-time check functions.
*
* Warning: the value returned by these should not change between
* curl_global_init() and curl_global_cleanup() calls.
*/
#if defined(USE_LIBIDN2)
static int idn_present(curl_version_info_data *info)
{
return info->libidn != NULL;
}
#else
#define idn_present NULL
#endif
#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY)
static int https_proxy_present(curl_version_info_data *info)
{
(void) info;
return Curl_ssl_supports(NULL, SSLSUPP_HTTPS_PROXY);
}
#endif
/*
* Features table.
*
* Keep the features alphabetically sorted.
* Use FEATURE() macro to define an entry: this allows documentation check.
*/
#define FEATURE(name, present, bitmask) {(name), (present), (bitmask)}
struct feat {
const char *name;
int (*present)(curl_version_info_data *info);
int bitmask;
};
static const struct feat features_table[] = {
#ifndef CURL_DISABLE_ALTSVC
FEATURE("alt-svc", NULL, CURL_VERSION_ALTSVC),
#endif
#ifdef CURLRES_ASYNCH
FEATURE("AsynchDNS", NULL, CURL_VERSION_ASYNCHDNS),
#endif
#ifdef HAVE_BROTLI
FEATURE("brotli", NULL, CURL_VERSION_BROTLI),
#endif
#ifdef DEBUGBUILD
FEATURE("Debug", NULL, CURL_VERSION_DEBUG),
#endif
#ifdef USE_GSASL
FEATURE("gsasl", NULL, CURL_VERSION_GSASL),
#endif
#ifdef HAVE_GSSAPI
FEATURE("GSS-API", NULL, CURL_VERSION_GSSAPI),
#endif
#ifndef CURL_DISABLE_HSTS
FEATURE("HSTS", NULL, CURL_VERSION_HSTS),
#endif
#if defined(USE_NGHTTP2) || defined(USE_HYPER)
FEATURE("HTTP2", NULL, CURL_VERSION_HTTP2),
#endif
#if defined(ENABLE_QUIC)
FEATURE("HTTP3", NULL, CURL_VERSION_HTTP3),
#endif
#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY)
FEATURE("HTTPS-proxy", https_proxy_present, CURL_VERSION_HTTPS_PROXY),
#endif
#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
FEATURE("IDN", idn_present, CURL_VERSION_IDN),
#endif
#ifdef ENABLE_IPV6
FEATURE("IPv6", NULL, CURL_VERSION_IPV6),
#endif
#ifdef USE_KERBEROS5
FEATURE("Kerberos", NULL, CURL_VERSION_KERBEROS5),
#endif
#if (SIZEOF_CURL_OFF_T > 4) && \
( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) )
FEATURE("Largefile", NULL, CURL_VERSION_LARGEFILE),
#endif
#ifdef HAVE_LIBZ
FEATURE("libz", NULL, CURL_VERSION_LIBZ),
#endif
#ifdef CURL_WITH_MULTI_SSL
FEATURE("MultiSSL", NULL, CURL_VERSION_MULTI_SSL),
#endif
#ifdef USE_NTLM
FEATURE("NTLM", NULL, CURL_VERSION_NTLM),
#endif
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
defined(NTLM_WB_ENABLED)
FEATURE("NTLM_WB", NULL, CURL_VERSION_NTLM_WB),
#endif
#if defined(USE_LIBPSL)
FEATURE("PSL", NULL, CURL_VERSION_PSL),
#endif
#ifdef USE_SPNEGO
FEATURE("SPNEGO", NULL, CURL_VERSION_SPNEGO),
#endif
#ifdef USE_SSL
FEATURE("SSL", NULL, CURL_VERSION_SSL),
#endif
#ifdef USE_WINDOWS_SSPI
FEATURE("SSPI", NULL, CURL_VERSION_SSPI),
#endif
#ifdef GLOBAL_INIT_IS_THREADSAFE
FEATURE("threadsafe", NULL, CURL_VERSION_THREADSAFE),
#endif
#ifdef USE_TLS_SRP
FEATURE("TLS-SRP", NULL, CURL_VERSION_TLSAUTH_SRP),
#endif
#ifdef CURLDEBUG
FEATURE("TrackMemory", NULL, CURL_VERSION_CURLDEBUG),
#endif
#if defined(WIN32) && defined(UNICODE) && defined(_UNICODE)
FEATURE("Unicode", NULL, CURL_VERSION_UNICODE),
#endif
#ifdef USE_UNIX_SOCKETS
FEATURE("UnixSockets", NULL, CURL_VERSION_UNIX_SOCKETS),
#endif
#ifdef HAVE_ZSTD
FEATURE("zstd", NULL, CURL_VERSION_ZSTD),
#endif
{NULL, NULL, 0}
};
static const char *feature_names[sizeof(features_table) /
sizeof(features_table[0])] = {NULL};
static curl_version_info_data version_info = {
CURLVERSION_NOW,
LIBCURL_VERSION,
LIBCURL_VERSION_NUM,
OS, /* as found by configure or set by hand at build-time */
0 /* features is 0 by default */
#ifdef ENABLE_IPV6
| CURL_VERSION_IPV6
#endif
#ifdef USE_SSL
| CURL_VERSION_SSL
#endif
#ifdef USE_NTLM
| CURL_VERSION_NTLM
#endif
#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
defined(NTLM_WB_ENABLED)
| CURL_VERSION_NTLM_WB
#endif
#ifdef USE_SPNEGO
| CURL_VERSION_SPNEGO
#endif
#ifdef USE_KERBEROS5
| CURL_VERSION_KERBEROS5
#endif
#ifdef HAVE_GSSAPI
| CURL_VERSION_GSSAPI
#endif
#ifdef USE_WINDOWS_SSPI
| CURL_VERSION_SSPI
#endif
#ifdef HAVE_LIBZ
| CURL_VERSION_LIBZ
#endif
#ifdef DEBUGBUILD
| CURL_VERSION_DEBUG
#endif
#ifdef CURLDEBUG
| CURL_VERSION_CURLDEBUG
#endif
#ifdef CURLRES_ASYNCH
| CURL_VERSION_ASYNCHDNS
#endif
#if (SIZEOF_CURL_OFF_T > 4) && \
( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) )
| CURL_VERSION_LARGEFILE
#endif
#if defined(WIN32) && defined(UNICODE) && defined(_UNICODE)
| CURL_VERSION_UNICODE
#endif
#if defined(USE_TLS_SRP)
| CURL_VERSION_TLSAUTH_SRP
#endif
#if defined(USE_NGHTTP2) || defined(USE_HYPER)
| CURL_VERSION_HTTP2
#endif
#if defined(ENABLE_QUIC)
| CURL_VERSION_HTTP3
#endif
#if defined(USE_UNIX_SOCKETS)
| CURL_VERSION_UNIX_SOCKETS
#endif
#if defined(USE_LIBPSL)
| CURL_VERSION_PSL
#endif
#if defined(CURL_WITH_MULTI_SSL)
| CURL_VERSION_MULTI_SSL
#endif
#if defined(HAVE_BROTLI)
| CURL_VERSION_BROTLI
#endif
#if defined(HAVE_ZSTD)
| CURL_VERSION_ZSTD
#endif
#ifndef CURL_DISABLE_ALTSVC
| CURL_VERSION_ALTSVC
#endif
#ifndef CURL_DISABLE_HSTS
| CURL_VERSION_HSTS
#endif
#if defined(USE_GSASL)
| CURL_VERSION_GSASL
#endif
#if defined(GLOBAL_INIT_IS_THREADSAFE)
| CURL_VERSION_THREADSAFE
#endif
,
OS, /* as found by configure or set by hand at build-time */
0, /* features bitmask is built at run-time */
NULL, /* ssl_version */
0, /* ssl_version_num, this is kept at zero */
NULL, /* zlib_version */
@ -496,11 +548,16 @@ static curl_version_info_data version_info = {
0, /* zstd_ver_num */
NULL, /* zstd version */
NULL, /* Hyper version */
NULL /* gsasl version */
NULL, /* gsasl version */
feature_names
};
curl_version_info_data *curl_version_info(CURLversion stamp)
{
size_t n;
const struct feat *p;
int features = 0;
#if defined(USE_SSH)
static char ssh_buffer[80];
#endif
@ -518,15 +575,11 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
static char zstd_buffer[80];
#endif
(void)stamp; /* avoid compiler warnings, we don't use this */
#ifdef USE_SSL
Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
version_info.ssl_version = ssl_buffer;
#ifndef CURL_DISABLE_PROXY
if(Curl_ssl_supports(NULL, SSLSUPP_HTTPS_PROXY))
version_info.features |= CURL_VERSION_HTTPS_PROXY;
else
version_info.features &= ~CURL_VERSION_HTTPS_PROXY;
#endif
#endif
#ifdef HAVE_LIBZ
@ -544,10 +597,6 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
/* This returns a version string if we use the given version or later,
otherwise it returns NULL */
version_info.libidn = idn2_check_version(IDN2_VERSION);
if(version_info.libidn)
version_info.features |= CURL_VERSION_IDN;
#elif defined(USE_WIN32_IDN)
version_info.features |= CURL_VERSION_IDN;
#endif
#if defined(USE_SSH)
@ -597,6 +646,16 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
}
#endif
(void)stamp; /* avoid compiler warnings, we don't use this */
/* Get available features, build bitmask and names array. */
n = 0;
for(p = features_table; p->name; p++)
if(!p->present || p->present(&version_info)) {
features |= p->bitmask;
feature_names[n++] = p->name;
}
feature_names[n] = NULL; /* Terminate array. */
version_info.features = features;
return &version_info;
}