setopt: add CURLOPT_PROTOCOLS_STR and CURLOPT_REDIR_PROTOCOLS_STR

... as replacements for deprecated CURLOPT_PROTOCOLS and
CURLOPT_REDIR_PROTOCOLS as these new ones do not risk running into the
32 bit limit the old ones are facing.

CURLINFO_PROTCOOL is now deprecated.

The curl tool is updated to use the new options.

Added test 1597 to verify the libcurl protocol parser.

Closes #8992
This commit is contained in:
Daniel Stenberg 2022-06-13 09:30:45 +02:00
parent 193215db3c
commit e6f8445ede
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
24 changed files with 487 additions and 45 deletions

View file

@ -36,11 +36,7 @@ void config_init(struct OperationConfig *config)
config->use_httpget = FALSE;
config->create_dirs = FALSE;
config->maxredirs = DEFAULT_MAXREDIRS;
config->proto = CURLPROTO_ALL;
config->proto_present = FALSE;
config->proto_redir = CURLPROTO_ALL & /* All except FILE, SCP and SMB */
~(CURLPROTO_FILE | CURLPROTO_SCP | CURLPROTO_SMB |
CURLPROTO_SMBS);
config->proto_redir_present = FALSE;
config->proto_default = NULL;
config->tcp_nodelay = TRUE; /* enabled by default */
@ -172,6 +168,8 @@ static void free_config_fields(struct OperationConfig *config)
Curl_safefree(config->ftp_alternative_to_user);
Curl_safefree(config->aws_sigv4);
Curl_safefree(config->proto_str);
Curl_safefree(config->proto_redir_str);
}
void config_free(struct OperationConfig *config)

View file

@ -67,9 +67,9 @@ struct OperationConfig {
bool disable_epsv;
bool disable_eprt;
bool ftp_pret;
long proto;
char *proto_str;
bool proto_present;
long proto_redir;
char *proto_redir_str;
bool proto_redir_present;
char *proto_default;
curl_off_t resume_from;

View file

@ -1184,12 +1184,16 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
break;
case 'D': /* --proto */
config->proto_present = TRUE;
if(proto2num(config, &config->proto, nextarg))
return PARAM_BAD_USE;
err = proto2num(config, (unsigned int)CURLPROTO_ALL,
&config->proto_str, nextarg);
if(err)
return err;
break;
case 'E': /* --proto-redir */
config->proto_redir_present = TRUE;
if(proto2num(config, &config->proto_redir, nextarg))
if(proto2num(config, CURLPROTO_HTTP|CURLPROTO_HTTPS|
CURLPROTO_FTP|CURLPROTO_FTPS,
&config->proto_redir_str, nextarg))
return PARAM_BAD_USE;
break;
case 'F': /* --resolve */

View file

@ -1989,9 +1989,10 @@ static CURLcode single_transfer(struct GlobalConfig *global,
my_setopt(curl, CURLOPT_NEW_FILE_PERMS, config->create_file_mode);
if(config->proto_present)
my_setopt_flags(curl, CURLOPT_PROTOCOLS, config->proto);
my_setopt_str(curl, CURLOPT_PROTOCOLS_STR, config->proto_str);
if(config->proto_redir_present)
my_setopt_flags(curl, CURLOPT_REDIR_PROTOCOLS, config->proto_redir);
my_setopt_str(curl, CURLOPT_REDIR_PROTOCOLS_STR,
config->proto_redir_str);
if(config->content_disposition
&& (urlnode->flags & GETOUT_USEREMOTE))

View file

@ -275,8 +275,8 @@ ParameterError str2udouble(double *valp, const char *str, long max)
}
/*
* Parse the string and modify the long in the given address. Return
* non-zero on failure, zero on success.
* Parse the string and provide an allocated libcurl compatible protocol
* string output. Return non-zero on failure, zero on success.
*
* The string is a list of protocols
*
@ -285,17 +285,22 @@ ParameterError str2udouble(double *valp, const char *str, long max)
* data.
*/
long proto2num(struct OperationConfig *config, long *val, const char *str)
ParameterError proto2num(struct OperationConfig *config,
unsigned int 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;
long bit;
unsigned int bit;
} const protos[] = {
{ "all", CURLPROTO_ALL },
{ "all", (unsigned int)CURLPROTO_ALL },
{ "http", CURLPROTO_HTTP },
{ "https", CURLPROTO_HTTPS },
{ "ftp", CURLPROTO_FTP },
@ -305,6 +310,7 @@ long proto2num(struct OperationConfig *config, long *val, const char *str)
{ "telnet", CURLPROTO_TELNET },
{ "ldap", CURLPROTO_LDAP },
{ "ldaps", CURLPROTO_LDAPS },
{ "mqtt", CURLPROTO_MQTT },
{ "dict", CURLPROTO_DICT },
{ "file", CURLPROTO_FILE },
{ "tftp", CURLPROTO_TFTP },
@ -316,6 +322,7 @@ long proto2num(struct OperationConfig *config, long *val, const char *str)
{ "smtps", CURLPROTO_SMTPS },
{ "rtsp", CURLPROTO_RTSP },
{ "gopher", CURLPROTO_GOPHER },
{ "gophers", CURLPROTO_GOPHERS },
{ "smb", CURLPROTO_SMB },
{ "smbs", CURLPROTO_SMBS },
{ NULL, 0 }
@ -335,8 +342,6 @@ long proto2num(struct OperationConfig *config, long *val, const char *str)
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++) {
@ -359,13 +364,13 @@ long proto2num(struct OperationConfig *config, long *val, const char *str)
if(curl_strequal(token, pp->name)) {
switch(action) {
case deny:
*val &= ~(pp->bit);
val &= ~(pp->bit);
break;
case allow:
*val |= pp->bit;
val |= pp->bit;
break;
case set:
*val = pp->bit;
val = pp->bit;
break;
}
break;
@ -376,12 +381,25 @@ long proto2num(struct OperationConfig *config, long *val, const char *str)
/* If they have specified only this protocol, we say treat it as
if no protocols are allowed */
if(action == set)
*val = 0;
val = 0;
warnf(config->global, "unrecognized protocol '%s'\n", token);
}
}
Curl_safefree(buffer);
return 0;
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);
return *ostr ? PARAM_OK : PARAM_NO_MEM;
}
/**

View file

@ -39,7 +39,9 @@ ParameterError oct2nummax(long *val, const char *str, long max);
ParameterError str2unummax(long *val, const char *str, long max);
ParameterError str2udouble(double *val, const char *str, long max);
long proto2num(struct OperationConfig *config, long *val, const char *str);
ParameterError proto2num(struct OperationConfig *config,
unsigned int val, char **obuf,
const char *str);
int check_protocol(const char *str);