summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPatrick Monnerat <patrick@monnerat.net>2022-09-15 14:31:36 +0200
committerDaniel Stenberg <daniel@haxx.se>2022-09-16 23:29:08 +0200
commitdd2a024323dccd6b813adc4ec7673ab8625f0904 (patch)
tree6ccf6be761008a4b7a4f273c8312a564d663c5ce /src
parent9d51329047952ebfc2b944b7448b8f87f9e6ed51 (diff)
downloadcurl-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.c14
-rw-r--r--src/tool_getparam.c7
-rw-r--r--src/tool_help.c5
-rw-r--r--src/tool_libinfo.c198
-rw-r--r--src/tool_libinfo.h32
-rw-r--r--src/tool_operate.c52
-rw-r--r--src/tool_paramhlp.c120
-rw-r--r--src/tool_paramhlp.h3
-rw-r--r--src/tool_setopt.c29
-rw-r--r--src/tool_setopt.h3
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