curl: added --proto and --proto-redir

--proto tells curl to use the listed protocols for its initial
retrieval

--proto-redir tells curl to use the listed protocols after a
redirect
This commit is contained in:
Alex Bligh 2010-04-24 12:16:48 +02:00 committed by Daniel Stenberg
parent d487ade72c
commit 36e245658b
2 changed files with 177 additions and 0 deletions

View File

@ -927,6 +927,52 @@ in web browsers, so curl does the conversion by default to maintain
consistency. However, a server may require a POST to remain a POST after such
a redirection. This option is meaningful only when using \fI-L/--location\fP
(Added in 7.19.1)
.IP "--proto <protocols>"
Tells curl to use the listed protocols for its initial retrieval. Protocols
are evaluated left to right, are comma separated, and are each a protocol
name or 'all', optionally prefixed by zero or more modifiers. Available
modifiers are:
.RS
.TP 3
.B +
Permit this protocol in addition to protocols already permitted (this is
the default if no modifier is used).
.TP
.B -
Deny this protocol, removing it from the list of protocols already permitted.
.TP
.B =
Permit only this protocol (ignoring the list already permitted), though
subject to later modification by subsequent entries in the comma separated
list.
.RE
.IP
For example:
.RS
.TP 15
.B --proto -ftps
uses the default protocols, but disables ftps
.TP
.B --proto -all,https,+http
only enables http and https
.TP
.B --proto =http,https
also only enables http and https
.RE
.IP
Unknown protocols produce a warning. This allows scripts to safely rely on
being able to disable potentially dangerous protocols, without relying upon
support for that protocol being built into curl to avoid an error.
This option can be used multiple times, in which case the effect is the same
as concatenating the protocols into one instance of the option.
(Added in 7.20.2)
.IP "--proto-redir <protocols>"
Tells curl to use the listed protocols after a redirect. See --proto for
how protocols are represented.
(Added in 7.20.2)
.IP "--proxy-anyauth"
Tells curl to pick a suitable authentication method when communicating with
the given proxy. This might cause an extra request/response round-trip. (Added

View File

@ -478,6 +478,10 @@ struct Configurable {
bool disable_epsv;
bool disable_eprt;
bool ftp_pret;
long proto;
bool proto_present;
long proto_redir;
bool proto_redir_present;
curl_off_t resume_from;
char *postfields;
curl_off_t postfieldsize;
@ -841,6 +845,8 @@ static void help(void)
" --post301 Do not switch to GET after following a 301 redirect (H)",
" --post302 Do not switch to GET after following a 302 redirect (H)",
" -#/--progress-bar Display transfer progress as a progress bar",
" --proto <protocols> Enable/disable specified protocols",
" --proto-redir <protocols> Enable/disable specified protocols on redirect",
" -x/--proxy <host[:port]> Use HTTP proxy on given port",
" --proxy-anyauth Pick \"any\" proxy authentication method (H)",
" --proxy-basic Use Basic authentication on the proxy (H)",
@ -1492,6 +1498,109 @@ static int str2num(long *val, const char *str)
return retcode;
}
/*
* Parse the string and modify the long in the given address. Return
* non-zero on failure, zero on success.
*
* The string is a list of protocols
*
* Since this function gets called with the 'nextarg' pointer from within the
* getparameter a lot, we must check it for NULL before accessing the str
* data.
*/
static long proto2num(struct Configurable *config, long *val, const char *str)
{
char *buffer;
const char *sep = ",";
char *token;
static struct sprotos {
const char *name;
long bit;
} const protos[] = {
{ "all", 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 },
{ "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 },
{ NULL, 0 }
};
if(!str)
return 1;
buffer = strdup(str); /* because strtok corrupts it */
for (token = strtok(buffer, sep);
token;
token = strtok(NULL, sep)) {
enum e_action { allow, deny, set } action = allow;
struct sprotos const *pp;
/* Process token modifiers */
while (!ISALNUM(*token)) { /* may be NULL if token is all modifiers */
switch (*token++) {
case '=':
action = set;
break;
case '-':
action = deny;
break;
case '+':
action = allow;
break;
default: /* Includes case of terminating NULL */
free(buffer);
return 1;
}
}
for (pp=protos; pp->name; pp++) {
if (curlx_raw_equal(token, pp->name)) {
switch (action) {
case deny:
*val &= ~(pp->bit);
break;
case allow:
*val |= pp->bit;
break;
case set:
*val = pp->bit;
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, "unrecognized protocol '%s'\n", token);
}
}
free(buffer);
return 0;
}
/**
* Parses the given string looking for an offset (which may be
* a larger-than-integer value).
@ -1752,6 +1861,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"$A", "mail-from", TRUE},
{"$B", "mail-rcpt", TRUE},
{"$C", "ftp-pret", FALSE},
{"$D", "proto", TRUE},
{"$E", "proto-redir", TRUE},
{"0", "http1.0", FALSE},
{"1", "tlsv1", FALSE},
{"2", "sslv2", FALSE},
@ -2294,6 +2405,16 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
case 'C': /* --ftp-pret */
config->ftp_pret = toggle;
break;
case 'D': /* --proto */
config->proto_present = 1;
if(proto2num(config, &config->proto, nextarg))
return PARAM_BAD_USE;
break;
case 'E': /* --proto-redir */
config->proto_redir_present = 1;
if(proto2num(config, &config->proto_redir, nextarg))
return PARAM_BAD_USE;
break;
}
break;
case '#': /* --progress-bar */
@ -4362,6 +4483,11 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
config->use_httpget=FALSE;
config->create_dirs=FALSE;
config->maxredirs = DEFAULT_MAXREDIRS;
config->proto = CURLPROTO_ALL; /* FIXME: better to read from library */
config->proto_present = FALSE;
config->proto_redir =
CURLPROTO_ALL & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
config->proto_redir_present = FALSE;
if(argc>1 &&
(!curlx_strnequal("--", argv[1], 2) && (argv[1][0] == '-')) &&
@ -5200,6 +5326,11 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
if(config->ftp_pret)
my_setopt(curl, CURLOPT_FTP_USE_PRET, TRUE);
if (config->proto_present)
my_setopt(curl, CURLOPT_PROTOCOLS, config->proto);
if (config->proto_redir_present)
my_setopt(curl, CURLOPT_REDIR_PROTOCOLS, config->proto_redir);
if ((urlnode->flags & GETOUT_USEREMOTE)
&& config->content_disposition) {
my_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);