From e780aae77a10d95b1e2bfe80b6a4a9d67b772c50 Mon Sep 17 00:00:00 2001 From: Patrick Monnerat Date: Wed, 9 Nov 2022 00:27:32 +0100 Subject: 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 --- lib/version.c | 199 +++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 129 insertions(+), 70 deletions(-) (limited to 'lib/version.c') diff --git a/lib/version.c b/lib/version.c index 44adbf8ee..b43a8bc71 100644 --- a/lib/version.c +++ b/lib/version.c @@ -382,93 +382,145 @@ static const char * const protocols[] = { 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 +/* + * 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 -#ifdef USE_SSL - | CURL_VERSION_SSL + +#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 -#ifdef USE_NTLM - | CURL_VERSION_NTLM + +/* + * 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 -#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ - defined(NTLM_WB_ENABLED) - | CURL_VERSION_NTLM_WB +#ifdef CURLRES_ASYNCH + FEATURE("AsynchDNS", NULL, CURL_VERSION_ASYNCHDNS), #endif -#ifdef USE_SPNEGO - | CURL_VERSION_SPNEGO +#ifdef HAVE_BROTLI + FEATURE("brotli", NULL, CURL_VERSION_BROTLI), #endif -#ifdef USE_KERBEROS5 - | CURL_VERSION_KERBEROS5 +#ifdef DEBUGBUILD + FEATURE("Debug", NULL, CURL_VERSION_DEBUG), +#endif +#ifdef USE_GSASL + FEATURE("gsasl", NULL, CURL_VERSION_GSASL), #endif #ifdef HAVE_GSSAPI - | CURL_VERSION_GSSAPI + FEATURE("GSS-API", NULL, CURL_VERSION_GSSAPI), #endif -#ifdef USE_WINDOWS_SSPI - | CURL_VERSION_SSPI +#ifndef CURL_DISABLE_HSTS + FEATURE("HSTS", NULL, CURL_VERSION_HSTS), #endif -#ifdef HAVE_LIBZ - | CURL_VERSION_LIBZ +#if defined(USE_NGHTTP2) || defined(USE_HYPER) + FEATURE("HTTP2", NULL, CURL_VERSION_HTTP2), #endif -#ifdef DEBUGBUILD - | CURL_VERSION_DEBUG +#if defined(ENABLE_QUIC) + FEATURE("HTTP3", NULL, CURL_VERSION_HTTP3), #endif -#ifdef CURLDEBUG - | CURL_VERSION_CURLDEBUG +#if defined(USE_SSL) && !defined(CURL_DISABLE_PROXY) + FEATURE("HTTPS-proxy", https_proxy_present, CURL_VERSION_HTTPS_PROXY), #endif -#ifdef CURLRES_ASYNCH - | CURL_VERSION_ASYNCHDNS +#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) ) - | CURL_VERSION_LARGEFILE + FEATURE("Largefile", NULL, CURL_VERSION_LARGEFILE), #endif -#if defined(WIN32) && defined(UNICODE) && defined(_UNICODE) - | CURL_VERSION_UNICODE -#endif -#if defined(USE_TLS_SRP) - | CURL_VERSION_TLSAUTH_SRP +#ifdef HAVE_LIBZ + FEATURE("libz", NULL, CURL_VERSION_LIBZ), #endif -#if defined(USE_NGHTTP2) || defined(USE_HYPER) - | CURL_VERSION_HTTP2 +#ifdef CURL_WITH_MULTI_SSL + FEATURE("MultiSSL", NULL, CURL_VERSION_MULTI_SSL), #endif -#if defined(ENABLE_QUIC) - | CURL_VERSION_HTTP3 +#ifdef USE_NTLM + FEATURE("NTLM", NULL, CURL_VERSION_NTLM), #endif -#if defined(USE_UNIX_SOCKETS) - | CURL_VERSION_UNIX_SOCKETS +#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) - | CURL_VERSION_PSL + FEATURE("PSL", NULL, CURL_VERSION_PSL), +#endif +#ifdef USE_SPNEGO + FEATURE("SPNEGO", NULL, CURL_VERSION_SPNEGO), #endif -#if defined(CURL_WITH_MULTI_SSL) - | CURL_VERSION_MULTI_SSL +#ifdef USE_SSL + FEATURE("SSL", NULL, CURL_VERSION_SSL), #endif -#if defined(HAVE_BROTLI) - | CURL_VERSION_BROTLI +#ifdef USE_WINDOWS_SSPI + FEATURE("SSPI", NULL, CURL_VERSION_SSPI), #endif -#if defined(HAVE_ZSTD) - | CURL_VERSION_ZSTD +#ifdef GLOBAL_INIT_IS_THREADSAFE + FEATURE("threadsafe", NULL, CURL_VERSION_THREADSAFE), #endif -#ifndef CURL_DISABLE_ALTSVC - | CURL_VERSION_ALTSVC +#ifdef USE_TLS_SRP + FEATURE("TLS-SRP", NULL, CURL_VERSION_TLSAUTH_SRP), #endif -#ifndef CURL_DISABLE_HSTS - | CURL_VERSION_HSTS +#ifdef CURLDEBUG + FEATURE("TrackMemory", NULL, CURL_VERSION_CURLDEBUG), +#endif +#if defined(WIN32) && defined(UNICODE) && defined(_UNICODE) + FEATURE("Unicode", NULL, CURL_VERSION_UNICODE), #endif -#if defined(USE_GSASL) - | CURL_VERSION_GSASL +#ifdef USE_UNIX_SOCKETS + FEATURE("UnixSockets", NULL, CURL_VERSION_UNIX_SOCKETS), #endif -#if defined(GLOBAL_INIT_IS_THREADSAFE) - | CURL_VERSION_THREADSAFE +#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 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; } -- cgit v1.2.1