* ignored. We allow setting CA location for schannel only when explicitly
* specified by the user via CURLOPT_CAINFO / --cacert.
*/
- if((curlinfo->features & CURL_VERSION_SSL) &&
- backend != CURLSSLBACKEND_SCHANNEL) {
+ if(feature_ssl && backend != CURLSSLBACKEND_SCHANNEL) {
DWORD res_len;
TCHAR buf[PATH_MAX];
break;
case 'j': /* --compressed */
- if(toggle &&
- !(curlinfo->features & (CURL_VERSION_LIBZ |
- CURL_VERSION_BROTLI | CURL_VERSION_ZSTD)))
+ if(toggle && !(feature_libz || feature_brotli || feature_zstd))
return PARAM_LIBCURL_DOESNT_SUPPORT;
config->encoding = toggle;
break;
break;
case 'l': /* --negotiate */
- if(toggle) {
- if(curlinfo->features & CURL_VERSION_SPNEGO)
- config->authtype |= CURLAUTH_NEGOTIATE;
- else
- return PARAM_LIBCURL_DOESNT_SUPPORT;
- }
- else
+ if(!toggle)
config->authtype &= ~CURLAUTH_NEGOTIATE;
+ else if(feature_spnego)
+ config->authtype |= CURLAUTH_NEGOTIATE;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
break;
case 'm': /* --ntlm */
- if(toggle) {
- if(curlinfo->features & CURL_VERSION_NTLM)
- config->authtype |= CURLAUTH_NTLM;
- else
- return PARAM_LIBCURL_DOESNT_SUPPORT;
- }
- else
+ if(!toggle)
config->authtype &= ~CURLAUTH_NTLM;
+ else if(feature_ntlm)
+ config->authtype |= CURLAUTH_NTLM;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
break;
case 'M': /* --ntlm-wb */
- if(toggle) {
- if(curlinfo->features & CURL_VERSION_NTLM_WB)
- config->authtype |= CURLAUTH_NTLM_WB;
- else
- return PARAM_LIBCURL_DOESNT_SUPPORT;
- }
- else
+ if(!toggle)
config->authtype &= ~CURLAUTH_NTLM_WB;
+ else if(feature_ntlm_wb)
+ config->authtype |= CURLAUTH_NTLM_WB;
+ else
+ return PARAM_LIBCURL_DOESNT_SUPPORT;
break;
case 'n': /* --basic for completeness */
break;
case 't': /* --proxy-ntlm */
- if(curlinfo->features & CURL_VERSION_NTLM)
- config->proxyntlm = toggle;
- else
+ if(!feature_ntlm)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->proxyntlm = toggle;
break;
case 'u': /* --crlf */
break;
case 'x': /* --krb */
/* kerberos level string */
- if(curlinfo->features & CURL_VERSION_SPNEGO)
- GetStr(&config->krblevel, nextarg);
- else
+ if(!feature_spnego)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ GetStr(&config->krblevel, nextarg);
break;
case 'X': /* --haproxy-protocol */
config->haproxy_protocol = toggle;
case '$': /* more options without a short option */
switch(subletter) {
case 'a': /* --ssl */
- if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+ if(toggle && !feature_ssl)
return PARAM_LIBCURL_DOESNT_SUPPORT;
config->ftp_ssl = toggle;
if(config->ftp_ssl)
break;
case 'k': /* --proxy-negotiate */
- if(curlinfo->features & CURL_VERSION_SPNEGO)
- config->proxynegotiate = toggle;
- else
+ if(!feature_spnego)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->proxynegotiate = toggle;
break;
case 'l': /* --form-escape */
GetStr(&config->ftp_alternative_to_user, nextarg);
break;
case 'v': /* --ssl-reqd */
- if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+ if(toggle && !feature_ssl)
return PARAM_LIBCURL_DOESNT_SUPPORT;
config->ftp_ssl_reqd = toggle;
break;
config->disable_sessionid = (!toggle)?TRUE:FALSE;
break;
case 'x': /* --ftp-ssl-control */
- if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
+ if(toggle && !feature_ssl)
return PARAM_LIBCURL_DOESNT_SUPPORT;
config->ftp_ssl_control = toggle;
break;
break;
case '4': /* --http3 */
/* HTTP version 3 go over QUIC - at once */
- if(curlinfo->features & CURL_VERSION_HTTP3)
- config->httpversion = CURL_HTTP_VERSION_3;
- else
+ if(!feature_http3)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ config->httpversion = CURL_HTTP_VERSION_3;
break;
case '9':
/* Allow HTTP/0.9 responses! */
case 'b':
switch(subletter) {
case 'a': /* --alt-svc */
- if(curlinfo->features & CURL_VERSION_ALTSVC)
- GetStr(&config->altsvc, nextarg);
- else
+ if(!feature_altsvc)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ GetStr(&config->altsvc, nextarg);
break;
case 'b': /* --hsts */
- if(curlinfo->features & CURL_VERSION_HSTS)
- GetStr(&config->hsts, nextarg);
- else
+ if(!feature_hsts)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ GetStr(&config->hsts, nextarg);
break;
default: /* --cookie string coming up: */
if(nextarg[0] == '@') {
GetStr(&config->crlfile, nextarg);
break;
case 'k': /* TLS username */
- if(!(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)) {
+ if(!feature_tls_srp) {
cleanarg(clearthis);
return PARAM_LIBCURL_DOESNT_SUPPORT;
}
cleanarg(clearthis);
break;
case 'l': /* TLS password */
- if(!(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)) {
+ if(!feature_tls_srp) {
cleanarg(clearthis);
return PARAM_LIBCURL_DOESNT_SUPPORT;
}
cleanarg(clearthis);
break;
case 'm': /* TLS authentication type */
- if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
- GetStr(&config->tls_authtype, nextarg);
- if(!curl_strequal(config->tls_authtype, "SRP"))
- return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
- }
- else
+ if(!feature_tls_srp)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ GetStr(&config->tls_authtype, nextarg);
+ if(!curl_strequal(config->tls_authtype, "SRP"))
+ return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
break;
case 'n': /* no empty SSL fragments, --ssl-allow-beast */
- if(curlinfo->features & CURL_VERSION_SSL)
+ if(feature_ssl)
config->ssl_allow_beast = toggle;
break;
case 'o': /* --ssl-auto-client-cert */
- if(curlinfo->features & CURL_VERSION_SSL)
+ if(feature_ssl)
config->ssl_auto_client_cert = toggle;
break;
case 'O': /* --proxy-ssl-auto-client-cert */
- if(curlinfo->features & CURL_VERSION_SSL)
+ if(feature_ssl)
config->proxy_ssl_auto_client_cert = toggle;
break;
break;
case 's': /* --ssl-no-revoke */
- if(curlinfo->features & CURL_VERSION_SSL)
+ if(feature_ssl)
config->ssl_no_revoke = TRUE;
break;
case 'S': /* --ssl-revoke-best-effort */
- if(curlinfo->features & CURL_VERSION_SSL)
+ if(feature_ssl)
config->ssl_revoke_best_effort = TRUE;
break;
case 'u': /* TLS username for proxy */
cleanarg(clearthis);
- if(!(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)) {
+ if(!feature_tls_srp)
return PARAM_LIBCURL_DOESNT_SUPPORT;
- }
GetStr(&config->proxy_tls_username, nextarg);
break;
case 'v': /* TLS password for proxy */
cleanarg(clearthis);
- if(!(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)) {
+ if(!feature_tls_srp)
return PARAM_LIBCURL_DOESNT_SUPPORT;
- }
GetStr(&config->proxy_tls_password, nextarg);
break;
case 'w': /* TLS authentication type for proxy */
- if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
- GetStr(&config->proxy_tls_authtype, nextarg);
- if(!curl_strequal(config->proxy_tls_authtype, "SRP"))
- return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
- }
- else
+ if(!feature_tls_srp)
return PARAM_LIBCURL_DOESNT_SUPPORT;
+ GetStr(&config->proxy_tls_authtype, nextarg);
+ if(!curl_strequal(config->proxy_tls_authtype, "SRP"))
+ return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
break;
case 'x': /* certificate file for proxy */
break;
case '4': /* no empty SSL fragments for proxy */
- if(curlinfo->features & CURL_VERSION_SSL)
+ if(feature_ssl)
config->proxy_ssl_allow_beast = toggle;
break;
extern const struct helptxt helptext[];
-struct feat {
- const char *name;
- int bitmask;
-};
-
-static const struct feat feats[] = {
- {"AsynchDNS", CURL_VERSION_ASYNCHDNS},
- {"Debug", CURL_VERSION_DEBUG},
- {"TrackMemory", CURL_VERSION_CURLDEBUG},
- {"IDN", CURL_VERSION_IDN},
- {"IPv6", CURL_VERSION_IPV6},
- {"Largefile", CURL_VERSION_LARGEFILE},
- {"Unicode", CURL_VERSION_UNICODE},
- {"SSPI", CURL_VERSION_SSPI},
- {"GSS-API", CURL_VERSION_GSSAPI},
- {"Kerberos", CURL_VERSION_KERBEROS5},
- {"SPNEGO", CURL_VERSION_SPNEGO},
- {"NTLM", CURL_VERSION_NTLM},
- {"NTLM_WB", CURL_VERSION_NTLM_WB},
- {"SSL", CURL_VERSION_SSL},
- {"libz", CURL_VERSION_LIBZ},
- {"brotli", CURL_VERSION_BROTLI},
- {"zstd", CURL_VERSION_ZSTD},
- {"CharConv", CURL_VERSION_CONV},
- {"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
- {"HTTP2", CURL_VERSION_HTTP2},
- {"HTTP3", CURL_VERSION_HTTP3},
- {"UnixSockets", CURL_VERSION_UNIX_SOCKETS},
- {"HTTPS-proxy", CURL_VERSION_HTTPS_PROXY},
- {"MultiSSL", CURL_VERSION_MULTI_SSL},
- {"PSL", CURL_VERSION_PSL},
- {"alt-svc", CURL_VERSION_ALTSVC},
- {"HSTS", CURL_VERSION_HSTS},
- {"gsasl", CURL_VERSION_GSASL},
- {"threadsafe", CURL_VERSION_THREADSAFE},
-};
static void print_category(curlhelp_t category)
{
void tool_version_info(void)
{
- const char *const *proto;
+ const char *const *builtin;
printf(CURL_ID "%s\n", curl_version());
#ifdef CURL_PATCHSTAMP
#else
printf("Release-Date: %s\n", LIBCURL_TIMESTAMP);
#endif
- if(curlinfo->protocols) {
- printf("Protocols: ");
- for(proto = curlinfo->protocols; *proto; ++proto) {
+ if(built_in_protos[0]) {
+ printf("Protocols:");
+ for(builtin = built_in_protos; *builtin; ++builtin) {
/* Special case: do not list rtmp?* protocols.
They may only appear together with "rtmp" */
- if(!curl_strnequal(*proto, "rtmp", 4) || !proto[0][4])
- printf("%s ", *proto);
+ if(!curl_strnequal(*builtin, "rtmp", 4) || !builtin[0][4])
+ printf(" %s", *builtin);
}
puts(""); /* newline */
}
- if(curlinfo->features) {
- char *featp[ sizeof(feats) / sizeof(feats[0]) + 1];
- size_t numfeat = 0;
- unsigned int i;
+ if(feature_names[0]) {
printf("Features:");
- for(i = 0; i < sizeof(feats)/sizeof(feats[0]); i++) {
- if(curlinfo->features & feats[i].bitmask)
- featp[numfeat++] = (char *)feats[i].name;
- }
- qsort(&featp[0], numfeat, sizeof(char *), struplocompare4sort);
- for(i = 0; i< numfeat; i++)
- printf(" %s", featp[i]);
+ for(builtin = feature_names; *builtin; ++builtin)
+ printf(" %s", *builtin);
puts(""); /* newline */
}
if(strcmp(CURL_VERSION, curlinfo->version)) {
{ NULL, NULL }
};
+bool feature_altsvc = FALSE;
+bool feature_brotli = FALSE;
+bool feature_hsts = FALSE;
+bool feature_http2 = FALSE;
+bool feature_http3 = FALSE;
+bool feature_libz = FALSE;
+bool feature_ntlm = FALSE;
+bool feature_ntlm_wb = FALSE;
+bool feature_spnego = FALSE;
+bool feature_ssl = FALSE;
+bool feature_tls_srp = FALSE;
+bool feature_zstd = FALSE;
+
+static struct feature_name_presentp {
+ const char *feature_name;
+ bool *feature_presentp;
+ int feature_bitmask;
+} const maybe_feature[] = {
+ /* Keep alphabetically sorted. */
+ {"alt-svc", &feature_altsvc, CURL_VERSION_ALTSVC},
+ {"AsynchDNS", NULL, CURL_VERSION_ASYNCHDNS},
+ {"brotli", &feature_brotli, CURL_VERSION_BROTLI},
+ {"CharConv", NULL, CURL_VERSION_CONV},
+ {"Debug", NULL, CURL_VERSION_DEBUG},
+ {"gsasl", NULL, CURL_VERSION_GSASL},
+ {"GSS-API", NULL, CURL_VERSION_GSSAPI},
+ {"HSTS", &feature_hsts, CURL_VERSION_HSTS},
+ {"HTTP2", &feature_http2, CURL_VERSION_HTTP2},
+ {"HTTP3", &feature_http3, CURL_VERSION_HTTP3},
+ {"HTTPS-proxy", NULL, CURL_VERSION_HTTPS_PROXY},
+ {"IDN", NULL, CURL_VERSION_IDN},
+ {"IPv6", NULL, CURL_VERSION_IPV6},
+ {"Kerberos", NULL, CURL_VERSION_KERBEROS5},
+ {"Largefile", NULL, CURL_VERSION_LARGEFILE},
+ {"libz", &feature_libz, CURL_VERSION_LIBZ},
+ {"MultiSSL", NULL, CURL_VERSION_MULTI_SSL},
+ {"NTLM", &feature_ntlm, CURL_VERSION_NTLM},
+ {"NTLM_WB", &feature_ntlm_wb, CURL_VERSION_NTLM_WB},
+ {"PSL", NULL, CURL_VERSION_PSL},
+ {"SPNEGO", &feature_spnego, CURL_VERSION_SPNEGO},
+ {"SSL", &feature_ssl, CURL_VERSION_SSL},
+ {"SSPI", NULL, CURL_VERSION_SSPI},
+ {"threadsafe", NULL, CURL_VERSION_THREADSAFE},
+ {"TLS-SRP", &feature_tls_srp, CURL_VERSION_TLSAUTH_SRP},
+ {"TrackMemory", NULL, CURL_VERSION_CURLDEBUG},
+ {"Unicode", NULL, CURL_VERSION_UNICODE},
+ {"UnixSockets", NULL, CURL_VERSION_UNIX_SOCKETS},
+ {"zstd", &feature_zstd, CURL_VERSION_ZSTD},
+ {NULL, NULL, 0}
+};
+
+static const char *fnames[sizeof(maybe_feature) / sizeof(maybe_feature[0])];
+const char * const *feature_names = fnames;
+
/*
* libcurl_info_init: retrieves run-time information about libcurl,
* setting a global pointer 'curlinfo' to libcurl's run-time info
* struct, count protocols and flag those we are interested in.
+ * Global pointer feature_names is set to the feature names array. If
+ * the latter is not returned by curl_version_info(), it is built from
+ * the returned features bit mask.
*/
CURLcode get_libcurl_info(void)
{
CURLcode result = CURLE_OK;
+ const char *const *builtin;
/* Pointer to libcurl's run-time version information */
curlinfo = curl_version_info(CURLVERSION_NOW);
return CURLE_FAILED_INIT;
if(curlinfo->protocols) {
- const char *const *builtin;
const struct proto_name_tokenp *p;
built_in_protos = curlinfo->protocols;
proto_count = builtin - built_in_protos;
}
+ if(curlinfo->age >= CURLVERSION_ELEVENTH && curlinfo->feature_names)
+ feature_names = curlinfo->feature_names;
+ else {
+ const struct feature_name_presentp *p;
+ const char **cpp = fnames;
+
+ for(p = maybe_feature; p->feature_name; p++)
+ if(curlinfo->features & p->feature_bitmask)
+ *cpp++ = p->feature_name;
+ *cpp = NULL;
+ }
+
+ /* Identify features we are interested in. */
+ for(builtin = feature_names; *builtin; builtin++) {
+ const struct feature_name_presentp *p;
+
+ for(p = maybe_feature; p->feature_name; p++)
+ if(curl_strequal(p->feature_name, *builtin)) {
+ if(p->feature_presentp)
+ *p->feature_presentp = TRUE;
+ break;
+ }
+ }
+
return CURLE_OK;
}
extern curl_version_info_data *curlinfo;
+
extern const char * const *built_in_protos;
extern size_t proto_count;
+extern const char * const *feature_names;
+
extern const char *proto_file;
extern const char *proto_ftp;
extern const char *proto_ftps;
extern const char *proto_sftp;
extern const char *proto_tftp;
+extern bool feature_altsvc;
+extern bool feature_brotli;
+extern bool feature_hsts;
+extern bool feature_http2;
+extern bool feature_http3;
+extern bool feature_libz;
+extern bool feature_ntlm;
+extern bool feature_ntlm_wb;
+extern bool feature_spnego;
+extern bool feature_ssl;
+extern bool feature_tls_srp;
+extern bool feature_zstd;
+
CURLcode get_libcurl_info(void);
const char *proto_token(const char *proto);
if(config->httpversion)
my_setopt_enum(curl, CURLOPT_HTTP_VERSION, config->httpversion);
- else if(curlinfo->features & CURL_VERSION_HTTP2) {
+ else if(feature_http2)
my_setopt_enum(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
- }
/* curl 7.19.1 (the 301 version existed in 7.18.2),
303 was added in 7.26.0 */
if(config->ssl_ec_curves)
my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves);
- if(curlinfo->features & CURL_VERSION_SSL) {
+ if(feature_ssl) {
/* Check if config->cert is a PKCS#11 URI and set the
* config->cert_type if necessary */
if(config->cert) {
my_setopt_slist(curl, CURLOPT_CONNECT_TO, config->connect_to);
/* new in 7.21.4 */
- if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
+ if(feature_tls_srp) {
if(config->tls_username)
my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME,
config->tls_username);