mirror of
https://github.com/curl/curl.git
synced 2025-03-01 15:15:34 +08:00
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.
This commit is contained in:
parent
9d51329047
commit
dd2a024323
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -35,85 +35,167 @@
|
||||
|
||||
/* global variable definitions, for libcurl run-time info */
|
||||
|
||||
curl_version_info_data *curlinfo = NULL;
|
||||
long built_in_protos = 0;
|
||||
#define MAX_PROTOS 64 /* Maximum number of supported protocols. */
|
||||
|
||||
static struct proto_name_pattern {
|
||||
const char *proto_name;
|
||||
long proto_pattern;
|
||||
curl_version_info_data *curlinfo = NULL;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* 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 CURLE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
struct curlx_dynbuf obuf;
|
||||
proto_t proto;
|
||||
CURLcode result;
|
||||
|
||||
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 }
|
||||
};
|
||||
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)) {
|
||||
switch(action) {
|
||||
case deny:
|
||||
val &= ~(pp->bit);
|
||||
break;
|
||||
case allow:
|
||||
val |= pp->bit;
|
||||
break;
|
||||
case set:
|
||||
val = pp->bit;
|
||||
break;
|
||||
}
|
||||
if(curl_strequal(token, "all")) {
|
||||
switch(action) {
|
||||
case deny:
|
||||
val = 0;
|
||||
break;
|
||||
case allow:
|
||||
case set:
|
||||
val = PROTO_ALL;
|
||||
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 {
|
||||
proto = scheme2protocol(token);
|
||||
if(proto != PROTO_NONE) {
|
||||
switch(action) {
|
||||
case deny:
|
||||
val &= ~PROTO_BIT(proto);
|
||||
break;
|
||||
case set:
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user