diff options
author | Patrick Monnerat <patrick@monnerat.net> | 2022-09-15 14:31:36 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2022-09-16 23:29:08 +0200 |
commit | dd2a024323dccd6b813adc4ec7673ab8625f0904 (patch) | |
tree | 6ccf6be761008a4b7a4f273c8312a564d663c5ce /src | |
parent | 9d51329047952ebfc2b944b7448b8f87f9e6ed51 (diff) | |
download | curl-dd2a024323dccd6b813adc4ec7673ab8625f0904.tar.gz |
cli tool: do not use disabled protocols
As they are now rejected by the library, take care of not passing
disabled protocol names to CURLOPT_PROTOCOLS_STR and
CURLOPT_REDIR_PROTOCOLS_STR.
Rather than using the CURLPROTO_* constants, dynamically assign protocol
numbers based on the order they are listed by curl_version_info().
New type proto_set_t implements prototype bit masks: it should therefore
be large enough to accomodate all library-enabled protocols. If not,
protocol numbers beyond the bit count of proto_set_t are recognized but
"inaccessible": when used, a warning is displayed and the value is
ignored. Should proto_set_t overflows, enabled protocols are reordered to
force those having a public CURLPROTO_* representation to be accessible.
Code has been added to subordinate RTMP?* protocols to the presence of
RTMP in the enabled protocol list, being returned by curl_version_info()
or not.
Diffstat (limited to 'src')
-rw-r--r-- | src/tool_cb_hdr.c | 14 | ||||
-rw-r--r-- | src/tool_getparam.c | 7 | ||||
-rw-r--r-- | src/tool_help.c | 5 | ||||
-rw-r--r-- | src/tool_libinfo.c | 198 | ||||
-rw-r--r-- | src/tool_libinfo.h | 32 | ||||
-rw-r--r-- | src/tool_operate.c | 52 | ||||
-rw-r--r-- | src/tool_paramhlp.c | 120 | ||||
-rw-r--r-- | src/tool_paramhlp.h | 3 | ||||
-rw-r--r-- | src/tool_setopt.c | 29 | ||||
-rw-r--r-- | src/tool_setopt.h | 3 |
10 files changed, 270 insertions, 193 deletions
diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c index ec55c6419..f9adb4a2b 100644 --- a/src/tool_cb_hdr.c +++ b/src/tool_cb_hdr.c @@ -35,6 +35,7 @@ #include "tool_cb_hdr.h" #include "tool_cb_wrt.h" #include "tool_operate.h" +#include "tool_libinfo.h" #include "memdebug.h" /* keep this as LAST include */ @@ -74,7 +75,8 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) const char *str = ptr; const size_t cb = size * nmemb; const char *end = (char *)ptr + cb; - long protocol = 0; + char *scheme; + proto_t protocol = proto_last; /* * Once that libcurl has called back tool_header_cb() the returned value @@ -139,10 +141,12 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) * Content-Disposition header specifying a filename property. */ - curl_easy_getinfo(per->curl, CURLINFO_PROTOCOL, &protocol); + curl_easy_getinfo(per->curl, CURLINFO_SCHEME, &scheme); + if(scheme) + protocol = scheme2protocol(scheme); if(hdrcbdata->honor_cd_filename && (cb > 20) && checkprefix("Content-disposition:", str) && - (protocol & (CURLPROTO_HTTPS|CURLPROTO_HTTP))) { + (protocol == proto_https || protocol == proto_http)) { const char *p = str + 20; /* look for the 'filename=' parameter @@ -202,8 +206,8 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) per->was_last_header_empty = TRUE; } if(hdrcbdata->config->show_headers && - (protocol & - (CURLPROTO_HTTP|CURLPROTO_HTTPS|CURLPROTO_RTSP|CURLPROTO_FILE))) { + (protocol == proto_http || protocol == proto_https || + protocol == proto_rtsp || protocol == proto_file)) { /* bold headers only for selected protocols */ char *value = NULL; diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 351b07ad1..f345ed7f7 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -1209,15 +1209,14 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ break; case 'D': /* --proto */ config->proto_present = TRUE; - err = proto2num(config, (unsigned int)CURLPROTO_ALL, - &config->proto_str, nextarg); + err = proto2num(config, PROTO_ALL, &config->proto_str, nextarg); if(err) return err; break; case 'E': /* --proto-redir */ config->proto_redir_present = TRUE; - if(proto2num(config, CURLPROTO_HTTP|CURLPROTO_HTTPS| - CURLPROTO_FTP|CURLPROTO_FTPS, + if(proto2num(config, PROTO_BIT(proto_http) | PROTO_BIT(proto_https) | + PROTO_BIT(proto_ftp) | PROTO_BIT(proto_ftps), &config->proto_redir_str, nextarg)) return PARAM_BAD_USE; break; diff --git a/src/tool_help.c b/src/tool_help.c index 75400d94c..f24a5f2ed 100644 --- a/src/tool_help.c +++ b/src/tool_help.c @@ -221,7 +221,10 @@ void tool_version_info(void) if(curlinfo->protocols) { printf("Protocols: "); for(proto = curlinfo->protocols; *proto; ++proto) { - printf("%s ", *proto); + /* 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); } puts(""); /* newline */ } diff --git a/src/tool_libinfo.c b/src/tool_libinfo.c index 039443e23..5f7bd608f 100644 --- a/src/tool_libinfo.c +++ b/src/tool_libinfo.c @@ -35,85 +35,167 @@ /* global variable definitions, for libcurl run-time info */ +#define MAX_PROTOS 64 /* Maximum number of supported protocols. */ + curl_version_info_data *curlinfo = NULL; -long built_in_protos = 0; -static struct proto_name_pattern { - const char *proto_name; - long proto_pattern; +proto_t proto_last = 0; + +proto_t proto_ftp = PROTO_NONE; +proto_t proto_ftps = PROTO_NONE; +proto_t proto_http = PROTO_NONE; +proto_t proto_https = PROTO_NONE; +proto_t proto_file = PROTO_NONE; +proto_t proto_rtsp = PROTO_NONE; +proto_t proto_scp = PROTO_NONE; +proto_t proto_sftp = PROTO_NONE; +proto_t proto_tftp = PROTO_NONE; + +static struct proto_name_nump { + const char *proto_name; + proto_t *proto_nump; } const possibly_built_in[] = { - { "dict", CURLPROTO_DICT }, - { "file", CURLPROTO_FILE }, - { "ftp", CURLPROTO_FTP }, - { "ftps", CURLPROTO_FTPS }, - { "gopher", CURLPROTO_GOPHER }, - { "gophers",CURLPROTO_GOPHERS}, - { "http", CURLPROTO_HTTP }, - { "https", CURLPROTO_HTTPS }, - { "imap", CURLPROTO_IMAP }, - { "imaps", CURLPROTO_IMAPS }, - { "ldap", CURLPROTO_LDAP }, - { "ldaps", CURLPROTO_LDAPS }, - { "mqtt", CURLPROTO_MQTT }, - { "pop3", CURLPROTO_POP3 }, - { "pop3s", CURLPROTO_POP3S }, - { "rtmp", CURLPROTO_RTMP }, - { "rtmps", CURLPROTO_RTMPS }, - { "rtsp", CURLPROTO_RTSP }, - { "scp", CURLPROTO_SCP }, - { "sftp", CURLPROTO_SFTP }, - { "smb", CURLPROTO_SMB }, - { "smbs", CURLPROTO_SMBS }, - { "smtp", CURLPROTO_SMTP }, - { "smtps", CURLPROTO_SMTPS }, - { "telnet", CURLPROTO_TELNET }, - { "tftp", CURLPROTO_TFTP }, - { NULL, 0 } + /* Keep entries in CURLPROTO_* order for sorting purpose. */ + { "http", &proto_http }, + { "https", &proto_https }, + { "ftp", &proto_ftp }, + { "ftps", &proto_ftps }, + { "scp", &proto_scp }, + { "sftp", &proto_sftp }, + { "telnet", NULL }, + { "ldap", NULL }, + { "ldaps", NULL }, + { "dict", NULL }, + { "file", &proto_file }, + { "tftp", &proto_tftp }, + { "imap", NULL }, + { "imaps", NULL }, + { "pop3", NULL }, + { "pop3s", NULL }, + { "smtp", NULL }, + { "smtps", NULL }, + { "rtsp", &proto_rtsp }, + { "rtmp", NULL }, + { "rtmpt", NULL }, + { "rtmpe", NULL }, + { "rtmpte", NULL }, + { "rtmps", NULL }, + { "rtmpts", NULL }, + { "gopher", NULL }, + { "smb", NULL }, + { "smbs", NULL }, + { "mqtt", NULL }, + { "gophers", NULL }, + { "ws", NULL }, + { "wss", NULL }, + { NULL, NULL } }; +static const char *built_in_protos[MAX_PROTOS + 1] = {NULL}; + +/* + * scheme2protocol() returns the protocol number for the specified URL scheme + */ +proto_t scheme2protocol(const char *scheme) +{ + proto_t p; + + for(p = 0; built_in_protos[p]; p++) + if(curl_strequal(scheme, built_in_protos[p])) + return p; + return PROTO_NONE; +} + +/* + * protocol2scheme() returns the name of the specified protocol. + */ +const char *protocol2scheme(proto_t proto) +{ + return proto < proto_last? built_in_protos[proto]: NULL; +} + +/* Enter a protoype in the built-in prototype table. */ +static CURLcode enter_proto(const char *proto) +{ + if(scheme2protocol(proto) == PROTO_NONE) { + if(proto_last >= MAX_PROTOS) + return CURLE_OUT_OF_MEMORY; + built_in_protos[proto_last] = proto; + built_in_protos[++proto_last] = NULL; + } + + return CURLE_OK; +} + +/* qsort helper functions for prototype array. */ +static int sortkey(const void *arg) +{ + const char *proto = *(const char **) arg; + const struct proto_name_nump *p; + + for(p = possibly_built_in; p->proto_name; p++) + if(curl_strequal(p->proto_name, proto)) + break; + + return (int) (p - possibly_built_in); +} + +static int protocmp(const void *p1, const void *p2) +{ + return sortkey(p1) - sortkey(p2); +} + /* * libcurl_info_init: retrieves run-time information about libcurl, * setting a global pointer 'curlinfo' to libcurl's run-time info - * struct, and a global bit pattern 'built_in_protos' composed of - * CURLPROTO_* bits indicating which protocols are actually built - * into library being used. + * struct, Assigning numbers to specific protocols and identifying protocols + * we are interested in. */ CURLcode get_libcurl_info(void) { - const char *const *proto; + CURLcode result = CURLE_OK; /* Pointer to libcurl's run-time version information */ curlinfo = curl_version_info(CURLVERSION_NOW); if(!curlinfo) return CURLE_FAILED_INIT; - /* Build CURLPROTO_* bit pattern with libcurl's built-in protocols */ - built_in_protos = 0; if(curlinfo->protocols) { - for(proto = curlinfo->protocols; *proto; proto++) { - struct proto_name_pattern const *p; - for(p = possibly_built_in; p->proto_name; p++) { - if(curl_strequal(*proto, p->proto_name)) { - built_in_protos |= p->proto_pattern; - break; - } - } + const char *const *builtin; + const struct proto_name_nump *p; + + /* Copy protocols to local table. */ + for(builtin = curlinfo->protocols; !result && *builtin; builtin++) + result = enter_proto(*builtin); + + /* Special case: if RTMP is present, also include RTMPE, RTMPS, RTMPT, + RTMPTE and RTMPTS. */ + if(scheme2protocol("rtmp") != PROTO_NONE) { + if(!result) + result = enter_proto("rtmpe"); + if(!result) + result = enter_proto("rtmps"); + if(!result) + result = enter_proto("rtmpt"); + if(!result) + result = enter_proto("rtmpte"); + if(!result) + result = enter_proto("rtmpts"); } - } - return CURLE_OK; -} + if(result) + return result; -/* - * scheme2protocol() returns the protocol bit for the specified URL scheme - */ -long scheme2protocol(const char *scheme) -{ - struct proto_name_pattern const *p; - for(p = possibly_built_in; p->proto_name; p++) { - if(curl_strequal(scheme, p->proto_name)) - return p->proto_pattern; + /* Sort the protocols to be sure the primary ones are always accessible and + * to retain their list order for testing purposes. */ + qsort(built_in_protos, proto_last, sizeof(built_in_protos[0]), protocmp); + + /* Identify protocols we are interested in. */ + for(p = possibly_built_in; p->proto_name; p++) + if(p->proto_nump) + *p->proto_nump = scheme2protocol(p->proto_name); } - return 0; + + return CURLE_OK; } diff --git a/src/tool_libinfo.h b/src/tool_libinfo.h index ba6fc0ec1..19c75b1bb 100644 --- a/src/tool_libinfo.h +++ b/src/tool_libinfo.h @@ -27,10 +27,38 @@ /* global variable declarations, for libcurl run-time info */ +typedef unsigned int proto_t; /* A protocol number.*/ + +#define PROTO_NONE ((proto_t) -1) + +/* Protocol numbers set type. This should have enough bits for all + * enabled protocols. + */ +typedef unsigned int proto_set_t; + +#define PROTO_MAX ((proto_t) (8 * sizeof(proto_set_t))) + +#define PROTO_BIT(p) ((p) < PROTO_MAX? (proto_set_t) 1 << (p): \ + (proto_set_t) 0) + +#define PROTO_ALL (PROTO_BIT(proto_last) - (proto_set_t) 1) + + extern curl_version_info_data *curlinfo; -extern long built_in_protos; +extern proto_t proto_last; + +extern proto_t proto_ftp; +extern proto_t proto_ftps; +extern proto_t proto_http; +extern proto_t proto_https; +extern proto_t proto_file; +extern proto_t proto_rtsp; +extern proto_t proto_scp; +extern proto_t proto_sftp; +extern proto_t proto_tftp; CURLcode get_libcurl_info(void); -long scheme2protocol(const char *scheme); +proto_t scheme2protocol(const char *scheme); +const char *protocol2scheme(proto_t proto); #endif /* HEADER_CURL_TOOL_LIBINFO_H */ diff --git a/src/tool_operate.c b/src/tool_operate.c index 7d64c1c4d..b859ab05c 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -465,9 +465,12 @@ static CURLcode post_per_transfer(struct GlobalConfig *global, /* If it returned OK. _or_ failonerror was enabled and it returned due to such an error, check for HTTP transient errors to retry on. */ - long protocol = 0; - curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol); - if((protocol == CURLPROTO_HTTP) || (protocol == CURLPROTO_HTTPS)) { + char *scheme; + proto_t protocol = proto_last; + curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme); + if(scheme) + protocol = scheme2protocol(scheme); + if(protocol == proto_http || protocol == proto_https) { /* This was HTTP(S) */ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); @@ -494,12 +497,16 @@ static CURLcode post_per_transfer(struct GlobalConfig *global, } } /* if CURLE_OK */ else if(result) { - long protocol = 0; + char *scheme; + proto_t protocol = proto_last; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); - curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol); + curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme); - if((protocol == CURLPROTO_FTP || protocol == CURLPROTO_FTPS) && + if(scheme) + protocol = scheme2protocol(scheme); + + if((protocol == proto_ftp || protocol == proto_ftps) && response / 100 == 4) /* * This is typically when the FTP server only allows a certain @@ -688,10 +695,11 @@ static void single_transfer_cleanup(struct OperationConfig *config) /* * Return the proto bit for the scheme used in the given URL */ -static long url_proto(char *url) +static proto_t url_proto(char *url) { CURLU *uh = curl_url(); - long proto = 0; + proto_t proto = PROTO_NONE; + if(uh) { if(url) { if(!curl_url_set(uh, CURLUPART_URL, url, @@ -850,7 +858,7 @@ static CURLcode single_transfer(struct GlobalConfig *global, struct OutStruct *etag_save; struct HdrCbData *hdrcbdata = NULL; struct OutStruct etag_first; - long use_proto; + proto_t use_proto; CURL *curl; /* --etag-save */ @@ -1249,8 +1257,10 @@ static CURLcode single_transfer(struct GlobalConfig *global, /* here */ use_proto = url_proto(per->this_url); + if(use_proto == PROTO_NONE) + use_proto = proto_last; /* Do not match any identified protocol. */ #if 0 - if(!(use_proto & built_in_protos)) { + if(use_proto >= proto_last) { warnf(global, "URL is '%s' but no support for the scheme\n", per->this_url); } @@ -1406,13 +1416,12 @@ static CURLcode single_transfer(struct GlobalConfig *global, my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers); - if(built_in_protos & (CURLPROTO_HTTP | CURLPROTO_RTSP)) { + if(proto_http < proto_last || proto_rtsp < proto_last) { my_setopt_str(curl, CURLOPT_REFERER, config->referer); my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent); } - if(built_in_protos & CURLPROTO_HTTP) { - + if(proto_http < proto_last) { long postRedir = 0; my_setopt(curl, CURLOPT_FOLLOWLOCATION, @@ -1462,9 +1471,10 @@ static CURLcode single_transfer(struct GlobalConfig *global, return result; } - } /* (built_in_protos & CURLPROTO_HTTP) */ + } /* (proto_http < proto_last) */ - my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport); + if(proto_ftp < proto_last) + my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport); my_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, config->low_speed_limit); my_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time); @@ -1481,7 +1491,7 @@ static CURLcode single_transfer(struct GlobalConfig *global, my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd); my_setopt_str(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd); - if(use_proto & (CURLPROTO_SCP|CURLPROTO_SFTP)) { + if(use_proto == proto_scp || use_proto == proto_sftp) { /* SSH and SSL private key uses same command-line option */ /* new in libcurl 7.16.1 */ @@ -1752,7 +1762,7 @@ static CURLcode single_transfer(struct GlobalConfig *global, if(config->path_as_is) my_setopt(curl, CURLOPT_PATH_AS_IS, 1L); - if((use_proto & (CURLPROTO_SCP|CURLPROTO_SFTP)) && + if((use_proto == proto_scp || use_proto == proto_sftp) && !config->insecure_ok) { char *known = findfile(".ssh/known_hosts", FALSE); if(known) { @@ -1962,7 +1972,9 @@ static CURLcode single_transfer(struct GlobalConfig *global, my_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip?1L:0L); /* curl 7.15.1 */ - my_setopt(curl, CURLOPT_FTP_FILEMETHOD, (long)config->ftp_filemethod); + if(proto_ftp < proto_last) + my_setopt(curl, CURLOPT_FTP_FILEMETHOD, + (long)config->ftp_filemethod); /* curl 7.15.2 */ if(config->localport) { @@ -1997,7 +2009,7 @@ static CURLcode single_transfer(struct GlobalConfig *global, my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 0L); /* curl 7.20.0 */ - if(config->tftp_blksize) + if(config->tftp_blksize && proto_tftp < proto_last) my_setopt(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize); if(config->mail_from) @@ -2110,7 +2122,7 @@ static CURLcode single_transfer(struct GlobalConfig *global, (long)(config->expect100timeout*1000)); /* new in 7.48.0 */ - if(config->tftp_no_options) + if(config->tftp_no_options && proto_tftp < proto_last) my_setopt(curl, CURLOPT_TFTP_NO_OPTIONS, 1L); /* new in 7.59.0 */ diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c index 9306498e2..f5745b057 100644 --- a/src/tool_paramhlp.c +++ b/src/tool_paramhlp.c @@ -34,6 +34,7 @@ #include "tool_getpass.h" #include "tool_msgs.h" #include "tool_paramhlp.h" +#include "tool_libinfo.h" #include "tool_version.h" #include "dynbuf.h" @@ -270,48 +271,19 @@ ParameterError str2udouble(double *valp, const char *str, long max) * data. */ +#define MAX_PROTOSTRING (64*11) /* Enough room for 64 10-chars proto names. */ + ParameterError proto2num(struct OperationConfig *config, - unsigned int val, char **ostr, const char *str) + proto_set_t val, char **ostr, const char *str) { char *buffer; const char *sep = ","; char *token; - char obuf[256] = ""; - size_t olen = sizeof(obuf); - char *optr; - struct sprotos const *pp; - - static struct sprotos { - const char *name; - unsigned int bit; - } const protos[] = { - { "all", (unsigned int)CURLPROTO_ALL }, - { "http", CURLPROTO_HTTP }, - { "https", CURLPROTO_HTTPS }, - { "ftp", CURLPROTO_FTP }, - { "ftps", CURLPROTO_FTPS }, - { "scp", CURLPROTO_SCP }, - { "sftp", CURLPROTO_SFTP }, - { "telnet", CURLPROTO_TELNET }, - { "ldap", CURLPROTO_LDAP }, - { "ldaps", CURLPROTO_LDAPS }, - { "mqtt", CURLPROTO_MQTT }, - { "dict", CURLPROTO_DICT }, - { "file", CURLPROTO_FILE }, - { "tftp", CURLPROTO_TFTP }, - { "imap", CURLPROTO_IMAP }, - { "imaps", CURLPROTO_IMAPS }, - { "pop3", CURLPROTO_POP3 }, - { "pop3s", CURLPROTO_POP3S }, - { "smtp", CURLPROTO_SMTP }, - { "smtps", CURLPROTO_SMTPS }, - { "rtsp", CURLPROTO_RTSP }, - { "gopher", CURLPROTO_GOPHER }, - { "gophers", CURLPROTO_GOPHERS }, - { "smb", CURLPROTO_SMB }, - { "smbs", CURLPROTO_SMBS }, - { NULL, 0 } - }; + struct curlx_dynbuf obuf; + proto_t proto; + CURLcode result; + + curlx_dyn_init(&obuf, MAX_PROTOSTRING); if(!str) return PARAM_OPTION_AMBIGUOUS; @@ -345,44 +317,52 @@ ParameterError proto2num(struct OperationConfig *config, } } - for(pp = protos; pp->name; pp++) { - if(curl_strequal(token, pp->name)) { + if(curl_strequal(token, "all")) { + switch(action) { + case deny: + val = 0; + break; + case allow: + case set: + val = PROTO_ALL; + break; + } + } + else { + proto = scheme2protocol(token); + if(proto != PROTO_NONE) { switch(action) { case deny: - val &= ~(pp->bit); - break; - case allow: - val |= pp->bit; + val &= ~PROTO_BIT(proto); break; case set: - val = pp->bit; + val = 0; + /* FALLTHROUGH */ + case allow: + if(proto >= PROTO_MAX) + warnf(config->global, "protocol '%s' enabled but not accessible\n", + token); + val |= PROTO_BIT(proto); break; } - break; } - } - - if(!(pp->name)) { /* unknown protocol */ - /* If they have specified only this protocol, we say treat it as - if no protocols are allowed */ - if(action == set) - val = 0; - warnf(config->global, "unrecognized protocol '%s'\n", token); + else { /* unknown protocol */ + /* If they have specified only this protocol, we say treat it as + if no protocols are allowed */ + if(action == set) + val = 0; + warnf(config->global, "unrecognized protocol '%s'\n", token); + } } } Curl_safefree(buffer); - optr = obuf; - for(pp = &protos[1]; pp->name; pp++) { - if(val & pp->bit) { - size_t n = msnprintf(optr, olen, "%s%s", - olen != sizeof(obuf) ? "," : "", - pp->name); - olen -= n; - optr += n; - } - } - *ostr = strdup(obuf); + result = curlx_dyn_addn(&obuf, "", 0); + for(proto = 0; proto < proto_last && proto < PROTO_MAX && !result; proto++) + if(val & PROTO_BIT(proto)) + result = curlx_dyn_addf(&obuf, "%s,", protocol2scheme(proto)); + curlx_dyn_setlen(&obuf, curlx_dyn_len(&obuf) - 1); + *ostr = curlx_dyn_ptr(&obuf); return *ostr ? PARAM_OK : PARAM_NO_MEM; } @@ -397,14 +377,14 @@ ParameterError proto2num(struct OperationConfig *config, */ ParameterError check_protocol(const char *str) { - const char * const *pp; - const curl_version_info_data *curlinfo = curl_version_info(CURLVERSION_NOW); + proto_t proto; + if(!str) return PARAM_REQUIRES_PARAMETER; - for(pp = curlinfo->protocols; *pp; pp++) { - if(curl_strequal(*pp, str)) - return PARAM_OK; - } + + proto = scheme2protocol(str); + if(proto < proto_last) + return PARAM_OK; return PARAM_LIBCURL_UNSUPPORTED_PROTOCOL; } diff --git a/src/tool_paramhlp.h b/src/tool_paramhlp.h index 6d9451f1d..95338a07e 100644 --- a/src/tool_paramhlp.h +++ b/src/tool_paramhlp.h @@ -24,6 +24,7 @@ * ***************************************************************************/ #include "tool_setup.h" +#include "tool_libinfo.h" struct getout *new_getout(struct OperationConfig *config); @@ -38,7 +39,7 @@ ParameterError str2unummax(long *val, const char *str, long max); ParameterError str2udouble(double *val, const char *str, long max); ParameterError proto2num(struct OperationConfig *config, - unsigned int val, char **obuf, + proto_set_t val, char **obuf, const char *str); ParameterError check_protocol(const char *str); diff --git a/src/tool_setopt.c b/src/tool_setopt.c index 5ea2541e0..b05138889 100644 --- a/src/tool_setopt.c +++ b/src/tool_setopt.c @@ -145,35 +145,6 @@ const struct NameValue setopt_nv_CURL_NETRC[] = { NVEND, }; -/* These mappings essentially triplicated - see - * tool_libinfo.c and tool_paramhlp.c */ -const struct NameValue setopt_nv_CURLPROTO[] = { - NV(CURLPROTO_ALL), /* combination */ - NV(CURLPROTO_DICT), - NV(CURLPROTO_FILE), - NV(CURLPROTO_FTP), - NV(CURLPROTO_FTPS), - NV(CURLPROTO_GOPHER), - NV(CURLPROTO_HTTP), - NV(CURLPROTO_HTTPS), - NV(CURLPROTO_IMAP), - NV(CURLPROTO_IMAPS), - NV(CURLPROTO_LDAP), - NV(CURLPROTO_LDAPS), - NV(CURLPROTO_POP3), - NV(CURLPROTO_POP3S), - NV(CURLPROTO_RTSP), - NV(CURLPROTO_SCP), - NV(CURLPROTO_SFTP), - NV(CURLPROTO_SMB), - NV(CURLPROTO_SMBS), - NV(CURLPROTO_SMTP), - NV(CURLPROTO_SMTPS), - NV(CURLPROTO_TELNET), - NV(CURLPROTO_TFTP), - NVEND, -}; - /* These options have non-zero default values. */ static const struct NameValue setopt_nv_CURLNONZERODEFAULTS[] = { NV1(CURLOPT_SSL_VERIFYPEER, 1), diff --git a/src/tool_setopt.h b/src/tool_setopt.h index 2646edb44..bc5afe9bc 100644 --- a/src/tool_setopt.h +++ b/src/tool_setopt.h @@ -57,7 +57,6 @@ extern const struct NameValue setopt_nv_CURLFTPSSL_CCC[]; extern const struct NameValue setopt_nv_CURLUSESSL[]; extern const struct NameValueUnsigned setopt_nv_CURLSSLOPT[]; extern const struct NameValue setopt_nv_CURL_NETRC[]; -extern const struct NameValue setopt_nv_CURLPROTO[]; extern const struct NameValueUnsigned setopt_nv_CURLAUTH[]; extern const struct NameValueUnsigned setopt_nv_CURLHSTS[]; @@ -73,8 +72,6 @@ extern const struct NameValueUnsigned setopt_nv_CURLHSTS[]; #define setopt_nv_CURLOPT_SSL_OPTIONS setopt_nv_CURLSSLOPT #define setopt_nv_CURLOPT_PROXY_SSL_OPTIONS setopt_nv_CURLSSLOPT #define setopt_nv_CURLOPT_NETRC setopt_nv_CURL_NETRC -#define setopt_nv_CURLOPT_PROTOCOLS setopt_nv_CURLPROTO -#define setopt_nv_CURLOPT_REDIR_PROTOCOLS setopt_nv_CURLPROTO #define setopt_nv_CURLOPT_PROXYTYPE setopt_nv_CURLPROXY #define setopt_nv_CURLOPT_PROXYAUTH setopt_nv_CURLAUTH #define setopt_nv_CURLOPT_SOCKS5_AUTH setopt_nv_CURLAUTH |