2011-10-04 18:03:20 -04:00
|
|
|
/***************************************************************************
|
|
|
|
* _ _ ____ _
|
|
|
|
* Project ___| | | | _ \| |
|
|
|
|
* / __| | | | |_) | |
|
|
|
|
* | (__| |_| | _ <| |___
|
|
|
|
* \___|\___/|_| \_\_____|
|
|
|
|
*
|
2020-01-05 11:12:03 -05:00
|
|
|
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
2011-10-04 18:03:20 -04:00
|
|
|
*
|
|
|
|
* This software is licensed as described in the file COPYING, which
|
|
|
|
* you should have received as part of this distribution. The terms
|
2016-02-02 18:19:02 -05:00
|
|
|
* are also available at https://curl.haxx.se/docs/copyright.html.
|
2011-10-04 18:03:20 -04:00
|
|
|
*
|
|
|
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
|
|
* copies of the Software, and permit persons to whom the Software is
|
|
|
|
* furnished to do so, under the terms of the COPYING file.
|
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
***************************************************************************/
|
2012-04-06 17:35:15 -04:00
|
|
|
#include "tool_setup.h"
|
2011-10-04 18:03:20 -04:00
|
|
|
|
2016-09-30 12:54:02 -04:00
|
|
|
#include "strcase.h"
|
2011-10-04 18:03:20 -04:00
|
|
|
|
|
|
|
#define ENABLE_CURLX_PRINTF
|
|
|
|
/* use our own printf() functions */
|
|
|
|
#include "curlx.h"
|
|
|
|
|
|
|
|
#include "tool_binmode.h"
|
|
|
|
#include "tool_cfgable.h"
|
|
|
|
#include "tool_cb_prg.h"
|
2017-05-01 14:10:43 -04:00
|
|
|
#include "tool_convert.h"
|
2018-02-05 15:57:39 -05:00
|
|
|
#include "tool_filetime.h"
|
2011-10-04 18:03:20 -04:00
|
|
|
#include "tool_formparse.h"
|
|
|
|
#include "tool_getparam.h"
|
|
|
|
#include "tool_helpers.h"
|
|
|
|
#include "tool_libinfo.h"
|
2012-06-08 08:21:29 -04:00
|
|
|
#include "tool_metalink.h"
|
2011-10-04 18:03:20 -04:00
|
|
|
#include "tool_msgs.h"
|
|
|
|
#include "tool_paramhlp.h"
|
|
|
|
#include "tool_parsecfg.h"
|
2019-07-20 13:14:00 -04:00
|
|
|
#include "tool_main.h"
|
2012-04-26 09:59:52 -04:00
|
|
|
|
2013-01-03 20:50:28 -05:00
|
|
|
#include "memdebug.h" /* keep this as LAST include */
|
2011-10-04 18:03:20 -04:00
|
|
|
|
|
|
|
#ifdef MSDOS
|
|
|
|
# define USE_WATT32
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define GetStr(str,val) do { \
|
|
|
|
if(*(str)) { \
|
|
|
|
free(*(str)); \
|
|
|
|
*(str) = NULL; \
|
|
|
|
} \
|
2012-07-13 17:39:25 -04:00
|
|
|
if((val)) { \
|
2011-10-04 18:03:20 -04:00
|
|
|
*(str) = strdup((val)); \
|
2012-07-13 17:39:25 -04:00
|
|
|
if(!(*(str))) \
|
|
|
|
return PARAM_NO_MEM; \
|
|
|
|
} \
|
2019-11-30 03:29:36 -05:00
|
|
|
} while(0)
|
2011-10-04 18:03:20 -04:00
|
|
|
|
|
|
|
struct LongShort {
|
|
|
|
const char *letter; /* short name option */
|
|
|
|
const char *lname; /* long name option */
|
2017-04-30 19:23:53 -04:00
|
|
|
enum {
|
|
|
|
ARG_NONE, /* stand-alone but not a boolean */
|
|
|
|
ARG_BOOL, /* accepts a --no-[name] prefix */
|
2018-08-15 03:17:43 -04:00
|
|
|
ARG_STRING, /* requires an argument */
|
|
|
|
ARG_FILENAME /* requires an argument, usually a file name */
|
2017-04-30 19:23:53 -04:00
|
|
|
} desc;
|
2011-10-04 18:03:20 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct LongShort aliases[]= {
|
2016-04-28 16:24:10 -04:00
|
|
|
/* 'letter' strings with more than one character have *no* short option to
|
|
|
|
mention. */
|
2017-04-30 19:23:53 -04:00
|
|
|
{"*@", "url", ARG_STRING},
|
|
|
|
{"*4", "dns-ipv4-addr", ARG_STRING},
|
|
|
|
{"*6", "dns-ipv6-addr", ARG_STRING},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"*a", "random-file", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"*b", "egd-file", ARG_STRING},
|
|
|
|
{"*B", "oauth2-bearer", ARG_STRING},
|
|
|
|
{"*c", "connect-timeout", ARG_STRING},
|
2018-09-06 03:16:02 -04:00
|
|
|
{"*C", "doh-url" , ARG_STRING},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"*d", "ciphers", ARG_STRING},
|
|
|
|
{"*D", "dns-interface", ARG_STRING},
|
|
|
|
{"*e", "disable-epsv", ARG_BOOL},
|
2018-02-25 14:17:25 -05:00
|
|
|
{"*f", "disallow-username-in-url", ARG_BOOL},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"*E", "epsv", ARG_BOOL},
|
2011-10-04 18:03:20 -04:00
|
|
|
/* 'epsv' made like this to make --no-epsv and --epsv to work
|
|
|
|
although --disable-epsv is the documented option */
|
2017-04-30 19:23:53 -04:00
|
|
|
{"*F", "dns-servers", ARG_STRING},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"*g", "trace", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"*G", "npn", ARG_BOOL},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"*h", "trace-ascii", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"*H", "alpn", ARG_BOOL},
|
|
|
|
{"*i", "limit-rate", ARG_STRING},
|
|
|
|
{"*j", "compressed", ARG_BOOL},
|
|
|
|
{"*J", "tr-encoding", ARG_BOOL},
|
|
|
|
{"*k", "digest", ARG_BOOL},
|
|
|
|
{"*l", "negotiate", ARG_BOOL},
|
|
|
|
{"*m", "ntlm", ARG_BOOL},
|
|
|
|
{"*M", "ntlm-wb", ARG_BOOL},
|
|
|
|
{"*n", "basic", ARG_BOOL},
|
|
|
|
{"*o", "anyauth", ARG_BOOL},
|
2011-10-04 18:03:20 -04:00
|
|
|
#ifdef USE_WATT32
|
2017-04-30 19:23:53 -04:00
|
|
|
{"*p", "wdebug", ARG_BOOL},
|
2011-10-04 18:03:20 -04:00
|
|
|
#endif
|
2017-04-30 19:23:53 -04:00
|
|
|
{"*q", "ftp-create-dirs", ARG_BOOL},
|
|
|
|
{"*r", "create-dirs", ARG_BOOL},
|
|
|
|
{"*s", "max-redirs", ARG_STRING},
|
|
|
|
{"*t", "proxy-ntlm", ARG_BOOL},
|
|
|
|
{"*u", "crlf", ARG_BOOL},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"*v", "stderr", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"*w", "interface", ARG_STRING},
|
|
|
|
{"*x", "krb", ARG_STRING},
|
|
|
|
{"*x", "krb4", ARG_STRING},
|
2011-10-04 18:03:20 -04:00
|
|
|
/* 'krb4' is the previous name */
|
2016-12-01 07:05:04 -05:00
|
|
|
{"*X", "haproxy-protocol", ARG_BOOL},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"*y", "max-filesize", ARG_STRING},
|
|
|
|
{"*z", "disable-eprt", ARG_BOOL},
|
|
|
|
{"*Z", "eprt", ARG_BOOL},
|
2011-10-04 18:03:20 -04:00
|
|
|
/* 'eprt' made like this to make --no-eprt and --eprt to work
|
|
|
|
although --disable-eprt is the documented option */
|
2017-04-30 19:23:53 -04:00
|
|
|
{"*~", "xattr", ARG_BOOL},
|
|
|
|
{"$a", "ftp-ssl", ARG_BOOL},
|
2011-10-04 18:03:20 -04:00
|
|
|
/* 'ftp-ssl' deprecated name since 7.20.0 */
|
2017-04-30 19:23:53 -04:00
|
|
|
{"$a", "ssl", ARG_BOOL},
|
2011-10-04 18:03:20 -04:00
|
|
|
/* 'ssl' new option name in 7.20.0, previously this was ftp-ssl */
|
2017-04-30 19:23:53 -04:00
|
|
|
{"$b", "ftp-pasv", ARG_BOOL},
|
|
|
|
{"$c", "socks5", ARG_STRING},
|
|
|
|
{"$d", "tcp-nodelay", ARG_BOOL},
|
|
|
|
{"$e", "proxy-digest", ARG_BOOL},
|
|
|
|
{"$f", "proxy-basic", ARG_BOOL},
|
|
|
|
{"$g", "retry", ARG_STRING},
|
|
|
|
{"$V", "retry-connrefused", ARG_BOOL},
|
|
|
|
{"$h", "retry-delay", ARG_STRING},
|
|
|
|
{"$i", "retry-max-time", ARG_STRING},
|
|
|
|
{"$k", "proxy-negotiate", ARG_BOOL},
|
|
|
|
{"$m", "ftp-account", ARG_STRING},
|
|
|
|
{"$n", "proxy-anyauth", ARG_BOOL},
|
|
|
|
{"$o", "trace-time", ARG_BOOL},
|
|
|
|
{"$p", "ignore-content-length", ARG_BOOL},
|
|
|
|
{"$q", "ftp-skip-pasv-ip", ARG_BOOL},
|
|
|
|
{"$r", "ftp-method", ARG_STRING},
|
|
|
|
{"$s", "local-port", ARG_STRING},
|
|
|
|
{"$t", "socks4", ARG_STRING},
|
|
|
|
{"$T", "socks4a", ARG_STRING},
|
|
|
|
{"$u", "ftp-alternative-to-user", ARG_STRING},
|
|
|
|
{"$v", "ftp-ssl-reqd", ARG_BOOL},
|
2011-10-04 18:03:20 -04:00
|
|
|
/* 'ftp-ssl-reqd' deprecated name since 7.20.0 */
|
2017-04-30 19:23:53 -04:00
|
|
|
{"$v", "ssl-reqd", ARG_BOOL},
|
2011-10-04 18:03:20 -04:00
|
|
|
/* 'ssl-reqd' new in 7.20.0, previously this was ftp-ssl-reqd */
|
2017-04-30 19:23:53 -04:00
|
|
|
{"$w", "sessionid", ARG_BOOL},
|
2015-04-22 18:09:49 -04:00
|
|
|
/* 'sessionid' listed as --no-sessionid in the help */
|
2017-04-30 19:23:53 -04:00
|
|
|
{"$x", "ftp-ssl-control", ARG_BOOL},
|
|
|
|
{"$y", "ftp-ssl-ccc", ARG_BOOL},
|
|
|
|
{"$j", "ftp-ssl-ccc-mode", ARG_STRING},
|
|
|
|
{"$z", "libcurl", ARG_STRING},
|
|
|
|
{"$#", "raw", ARG_BOOL},
|
|
|
|
{"$0", "post301", ARG_BOOL},
|
|
|
|
{"$1", "keepalive", ARG_BOOL},
|
2011-10-04 18:03:20 -04:00
|
|
|
/* 'keepalive' listed as --no-keepalive in the help */
|
2017-04-30 19:23:53 -04:00
|
|
|
{"$2", "socks5-hostname", ARG_STRING},
|
|
|
|
{"$3", "keepalive-time", ARG_STRING},
|
|
|
|
{"$4", "post302", ARG_BOOL},
|
|
|
|
{"$5", "noproxy", ARG_STRING},
|
|
|
|
{"$7", "socks5-gssapi-nec", ARG_BOOL},
|
|
|
|
{"$8", "proxy1.0", ARG_STRING},
|
|
|
|
{"$9", "tftp-blksize", ARG_STRING},
|
|
|
|
{"$A", "mail-from", ARG_STRING},
|
|
|
|
{"$B", "mail-rcpt", ARG_STRING},
|
|
|
|
{"$C", "ftp-pret", ARG_BOOL},
|
|
|
|
{"$D", "proto", ARG_STRING},
|
|
|
|
{"$E", "proto-redir", ARG_STRING},
|
|
|
|
{"$F", "resolve", ARG_STRING},
|
|
|
|
{"$G", "delegation", ARG_STRING},
|
|
|
|
{"$H", "mail-auth", ARG_STRING},
|
|
|
|
{"$I", "post303", ARG_BOOL},
|
|
|
|
{"$J", "metalink", ARG_BOOL},
|
2019-04-19 09:26:47 -04:00
|
|
|
{"$6", "sasl-authzid", ARG_STRING},
|
|
|
|
{"$K", "sasl-ir", ARG_BOOL },
|
2017-04-30 19:23:53 -04:00
|
|
|
{"$L", "test-event", ARG_BOOL},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"$M", "unix-socket", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"$N", "path-as-is", ARG_BOOL},
|
|
|
|
{"$O", "socks5-gssapi-service", ARG_STRING},
|
2016-04-09 15:47:05 -04:00
|
|
|
/* 'socks5-gssapi-service' merged with'proxy-service-name' and
|
|
|
|
deprecated since 7.49.0 */
|
2017-04-30 19:23:53 -04:00
|
|
|
{"$O", "proxy-service-name", ARG_STRING},
|
|
|
|
{"$P", "service-name", ARG_STRING},
|
|
|
|
{"$Q", "proto-default", ARG_STRING},
|
|
|
|
{"$R", "expect100-timeout", ARG_STRING},
|
|
|
|
{"$S", "tftp-no-options", ARG_BOOL},
|
|
|
|
{"$U", "connect-to", ARG_STRING},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"$W", "abstract-unix-socket", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"$X", "tls-max", ARG_STRING},
|
|
|
|
{"$Y", "suppress-connect-headers", ARG_BOOL},
|
2017-08-05 05:26:04 -04:00
|
|
|
{"$Z", "compressed-ssh", ARG_BOOL},
|
2018-01-30 19:33:51 -05:00
|
|
|
{"$~", "happy-eyeballs-timeout-ms", ARG_STRING},
|
2020-04-04 16:16:18 -04:00
|
|
|
{"$!", "retry-all-errors", ARG_BOOL},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"0", "http1.0", ARG_NONE},
|
|
|
|
{"01", "http1.1", ARG_NONE},
|
|
|
|
{"02", "http2", ARG_NONE},
|
|
|
|
{"03", "http2-prior-knowledge", ARG_NONE},
|
2019-08-07 08:17:48 -04:00
|
|
|
{"04", "http3", ARG_NONE},
|
2018-12-17 09:46:56 -05:00
|
|
|
{"09", "http0.9", ARG_BOOL},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"1", "tlsv1", ARG_NONE},
|
|
|
|
{"10", "tlsv1.0", ARG_NONE},
|
|
|
|
{"11", "tlsv1.1", ARG_NONE},
|
|
|
|
{"12", "tlsv1.2", ARG_NONE},
|
|
|
|
{"13", "tlsv1.3", ARG_NONE},
|
2018-05-29 10:12:52 -04:00
|
|
|
{"1A", "tls13-ciphers", ARG_STRING},
|
|
|
|
{"1B", "proxy-tls13-ciphers", ARG_STRING},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"2", "sslv2", ARG_NONE},
|
|
|
|
{"3", "sslv3", ARG_NONE},
|
|
|
|
{"4", "ipv4", ARG_NONE},
|
|
|
|
{"6", "ipv6", ARG_NONE},
|
|
|
|
{"a", "append", ARG_BOOL},
|
|
|
|
{"A", "user-agent", ARG_STRING},
|
|
|
|
{"b", "cookie", ARG_STRING},
|
2019-03-03 05:17:52 -05:00
|
|
|
{"ba", "alt-svc", ARG_STRING},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"B", "use-ascii", ARG_BOOL},
|
|
|
|
{"c", "cookie-jar", ARG_STRING},
|
|
|
|
{"C", "continue-at", ARG_STRING},
|
|
|
|
{"d", "data", ARG_STRING},
|
|
|
|
{"dr", "data-raw", ARG_STRING},
|
|
|
|
{"da", "data-ascii", ARG_STRING},
|
|
|
|
{"db", "data-binary", ARG_STRING},
|
|
|
|
{"de", "data-urlencode", ARG_STRING},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"D", "dump-header", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"e", "referer", ARG_STRING},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"E", "cert", ARG_FILENAME},
|
|
|
|
{"Ea", "cacert", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"Eb", "cert-type", ARG_STRING},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"Ec", "key", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"Ed", "key-type", ARG_STRING},
|
|
|
|
{"Ee", "pass", ARG_STRING},
|
|
|
|
{"Ef", "engine", ARG_STRING},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"Eg", "capath", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"Eh", "pubkey", ARG_STRING},
|
|
|
|
{"Ei", "hostpubmd5", ARG_STRING},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"Ej", "crlfile", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"Ek", "tlsuser", ARG_STRING},
|
|
|
|
{"El", "tlspassword", ARG_STRING},
|
|
|
|
{"Em", "tlsauthtype", ARG_STRING},
|
|
|
|
{"En", "ssl-allow-beast", ARG_BOOL},
|
2019-09-19 04:28:05 -04:00
|
|
|
/* Eo */
|
2017-04-30 19:23:53 -04:00
|
|
|
{"Ep", "pinnedpubkey", ARG_STRING},
|
2018-01-28 08:15:56 -05:00
|
|
|
{"EP", "proxy-pinnedpubkey", ARG_STRING},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"Eq", "cert-status", ARG_BOOL},
|
|
|
|
{"Er", "false-start", ARG_BOOL},
|
|
|
|
{"Es", "ssl-no-revoke", ARG_BOOL},
|
schannel: add "best effort" revocation check option
- Implement new option CURLSSLOPT_REVOKE_BEST_EFFORT and
--ssl-revoke-best-effort to allow a "best effort" revocation check.
A best effort revocation check ignores errors that the revocation check
was unable to take place. The reasoning is described in detail below and
discussed further in the PR.
---
When running e.g. with Fiddler, the schannel backend fails with an
unhelpful error message:
Unknown error (0x80092012) - The revocation function was unable
to check revocation for the certificate.
Sadly, many enterprise users who are stuck behind MITM proxies suffer
the very same problem.
This has been discussed in plenty of issues:
https://github.com/curl/curl/issues/3727,
https://github.com/curl/curl/issues/264, for example.
In the latter, a Microsoft Edge developer even made the case that the
common behavior is to ignore issues when a certificate has no recorded
distribution point for revocation lists, or when the server is offline.
This is also known as "best effort" strategy and addresses the Fiddler
issue.
Unfortunately, this strategy was not chosen as the default for schannel
(and is therefore a backend-specific behavior: OpenSSL seems to happily
ignore the offline servers and missing distribution points).
To maintain backward-compatibility, we therefore add a new flag
(`CURLSSLOPT_REVOKE_BEST_EFFORT`) and a new option
(`--ssl-revoke-best-effort`) to select the new behavior.
Due to the many related issues Git for Windows and GitHub Desktop, the
plan is to make this behavior the default in these software packages.
The test 2070 was added to verify this behavior, adapted from 310.
Based-on-work-by: georgeok <giorgos.n.oikonomou@gmail.com>
Co-authored-by: Markus Olsson <j.markus.olsson@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Closes https://github.com/curl/curl/pull/4981
2020-02-26 05:24:26 -05:00
|
|
|
{"ES", "ssl-revoke-best-effort", ARG_BOOL},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"Et", "tcp-fastopen", ARG_BOOL},
|
|
|
|
{"Eu", "proxy-tlsuser", ARG_STRING},
|
|
|
|
{"Ev", "proxy-tlspassword", ARG_STRING},
|
|
|
|
{"Ew", "proxy-tlsauthtype", ARG_STRING},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"Ex", "proxy-cert", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"Ey", "proxy-cert-type", ARG_STRING},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"Ez", "proxy-key", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"E0", "proxy-key-type", ARG_STRING},
|
|
|
|
{"E1", "proxy-pass", ARG_STRING},
|
|
|
|
{"E2", "proxy-ciphers", ARG_STRING},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"E3", "proxy-crlfile", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"E4", "proxy-ssl-allow-beast", ARG_BOOL},
|
|
|
|
{"E5", "login-options", ARG_STRING},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"E6", "proxy-cacert", ARG_FILENAME},
|
|
|
|
{"E7", "proxy-capath", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"E8", "proxy-insecure", ARG_BOOL},
|
|
|
|
{"E9", "proxy-tlsv1", ARG_NONE},
|
2017-05-19 12:11:47 -04:00
|
|
|
{"EA", "socks5-basic", ARG_BOOL},
|
|
|
|
{"EB", "socks5-gssapi", ARG_BOOL},
|
2019-10-30 04:43:14 -04:00
|
|
|
{"EC", "etag-save", ARG_FILENAME},
|
|
|
|
{"ED", "etag-compare", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"f", "fail", ARG_BOOL},
|
|
|
|
{"fa", "fail-early", ARG_BOOL},
|
2018-05-17 08:09:17 -04:00
|
|
|
{"fb", "styled-output", ARG_BOOL},
|
2020-01-14 17:22:38 -05:00
|
|
|
{"fc", "mail-rcpt-allowfails", ARG_BOOL},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"F", "form", ARG_STRING},
|
|
|
|
{"Fs", "form-string", ARG_STRING},
|
|
|
|
{"g", "globoff", ARG_BOOL},
|
|
|
|
{"G", "get", ARG_NONE},
|
2017-06-21 17:35:08 -04:00
|
|
|
{"Ga", "request-target", ARG_STRING},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"h", "help", ARG_BOOL},
|
|
|
|
{"H", "header", ARG_STRING},
|
|
|
|
{"Hp", "proxy-header", ARG_STRING},
|
|
|
|
{"i", "include", ARG_BOOL},
|
|
|
|
{"I", "head", ARG_BOOL},
|
|
|
|
{"j", "junk-session-cookies", ARG_BOOL},
|
|
|
|
{"J", "remote-header-name", ARG_BOOL},
|
|
|
|
{"k", "insecure", ARG_BOOL},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"K", "config", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"l", "list-only", ARG_BOOL},
|
|
|
|
{"L", "location", ARG_BOOL},
|
|
|
|
{"Lt", "location-trusted", ARG_BOOL},
|
|
|
|
{"m", "max-time", ARG_STRING},
|
|
|
|
{"M", "manual", ARG_BOOL},
|
|
|
|
{"n", "netrc", ARG_BOOL},
|
|
|
|
{"no", "netrc-optional", ARG_BOOL},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"ne", "netrc-file", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"N", "buffer", ARG_BOOL},
|
2011-10-04 18:03:20 -04:00
|
|
|
/* 'buffer' listed as --no-buffer in the help */
|
2018-08-15 03:17:43 -04:00
|
|
|
{"o", "output", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"O", "remote-name", ARG_NONE},
|
|
|
|
{"Oa", "remote-name-all", ARG_BOOL},
|
|
|
|
{"p", "proxytunnel", ARG_BOOL},
|
|
|
|
{"P", "ftp-port", ARG_STRING},
|
|
|
|
{"q", "disable", ARG_BOOL},
|
|
|
|
{"Q", "quote", ARG_STRING},
|
|
|
|
{"r", "range", ARG_STRING},
|
|
|
|
{"R", "remote-time", ARG_BOOL},
|
|
|
|
{"s", "silent", ARG_BOOL},
|
|
|
|
{"S", "show-error", ARG_BOOL},
|
|
|
|
{"t", "telnet-option", ARG_STRING},
|
2018-08-15 03:17:43 -04:00
|
|
|
{"T", "upload-file", ARG_FILENAME},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"u", "user", ARG_STRING},
|
|
|
|
{"U", "proxy-user", ARG_STRING},
|
|
|
|
{"v", "verbose", ARG_BOOL},
|
|
|
|
{"V", "version", ARG_BOOL},
|
|
|
|
{"w", "write-out", ARG_STRING},
|
|
|
|
{"x", "proxy", ARG_STRING},
|
|
|
|
{"xa", "preproxy", ARG_STRING},
|
|
|
|
{"X", "request", ARG_STRING},
|
|
|
|
{"Y", "speed-limit", ARG_STRING},
|
|
|
|
{"y", "speed-time", ARG_STRING},
|
|
|
|
{"z", "time-cond", ARG_STRING},
|
2019-07-20 13:14:00 -04:00
|
|
|
{"Z", "parallel", ARG_BOOL},
|
|
|
|
{"Zb", "parallel-max", ARG_STRING},
|
2019-10-17 04:05:53 -04:00
|
|
|
{"Zc", "parallel-immediate", ARG_BOOL},
|
2017-04-30 19:23:53 -04:00
|
|
|
{"#", "progress-bar", ARG_BOOL},
|
2019-10-07 08:54:35 -04:00
|
|
|
{"#m", "progress-meter", ARG_BOOL},
|
2017-04-30 19:23:53 -04:00
|
|
|
{":", "next", ARG_NONE},
|
2011-10-04 18:03:20 -04:00
|
|
|
};
|
|
|
|
|
2013-04-05 10:10:46 -04:00
|
|
|
/* Split the argument of -E to 'certname' and 'passphrase' separated by colon.
|
|
|
|
* We allow ':' and '\' to be escaped by '\' so that we can use certificate
|
|
|
|
* nicknames containing ':'. See <https://sourceforge.net/p/curl/bugs/1196/>
|
|
|
|
* for details. */
|
2013-05-03 07:26:25 -04:00
|
|
|
#ifndef UNITTESTS
|
|
|
|
static
|
|
|
|
#endif
|
|
|
|
void parse_cert_parameter(const char *cert_parameter,
|
|
|
|
char **certname,
|
|
|
|
char **passphrase)
|
2013-04-05 10:01:31 -04:00
|
|
|
{
|
|
|
|
size_t param_length = strlen(cert_parameter);
|
|
|
|
size_t span;
|
|
|
|
const char *param_place = NULL;
|
|
|
|
char *certname_place = NULL;
|
2013-05-03 16:57:18 -04:00
|
|
|
*certname = NULL;
|
2013-04-05 10:10:46 -04:00
|
|
|
*passphrase = NULL;
|
|
|
|
|
2013-04-05 10:01:31 -04:00
|
|
|
/* most trivial assumption: cert_parameter is empty */
|
2013-05-03 16:57:18 -04:00
|
|
|
if(param_length == 0)
|
2013-04-05 10:01:31 -04:00
|
|
|
return;
|
2013-05-03 16:57:18 -04:00
|
|
|
|
curl: allow "pkcs11:" prefix for client certificates
RFC7512 provides a standard method to reference certificates in PKCS#11
tokens, by means of a URI starting 'pkcs11:'.
We're working on fixing various applications so that whenever they would
have been able to use certificates from a file, users can simply insert
a PKCS#11 URI instead and expect it to work. This expectation is now a
part of the Fedora packaging guidelines, for example.
This doesn't work with cURL because of the way that the colon is used
to separate the certificate argument from the passphrase. So instead of
curl -E 'pkcs11:manufacturer=piv_II;id=%01' …
I instead need to invoke cURL with the colon escaped, like this:
curl -E 'pkcs11\:manufacturer=piv_II;id=%01' …
This is suboptimal because we want *consistency* — the URI should be
usable in place of a filename anywhere, without having strange
differences for different applications.
This patch therefore disables the processing in parse_cert_parameter()
when the string starts with 'pkcs11:'. It means you can't pass a
passphrase with an unescaped PKCS#11 URI, but there's no need to do so
because RFC7512 allows a PIN to be given as a 'pin-value' attribute in
the URI itself.
Also, if users are already using RFC7512 URIs with the colon escaped as
in the above example — even providing a passphrase for cURL to handling
instead of using a pin-value attribute, that will continue to work
because their string will start 'pkcs11\:' and won't match the check.
What *does* break with this patch is the extremely unlikely case that a
user has a file which is in the local directory and literally named
just "pkcs11", and they have a passphrase on it. If that ever happened,
the user would need to refer to it as './pkcs11:<passphrase>' instead.
2016-08-17 05:30:21 -04:00
|
|
|
/* next less trivial: cert_parameter starts 'pkcs11:' and thus
|
|
|
|
* looks like a RFC7512 PKCS#11 URI which can be used as-is.
|
|
|
|
* Also if cert_parameter contains no colon nor backslash, this
|
2013-04-05 10:01:31 -04:00
|
|
|
* means no passphrase was given and no characters escaped */
|
2018-02-19 08:31:06 -05:00
|
|
|
if(curl_strnequal(cert_parameter, "pkcs11:", 7) ||
|
curl: allow "pkcs11:" prefix for client certificates
RFC7512 provides a standard method to reference certificates in PKCS#11
tokens, by means of a URI starting 'pkcs11:'.
We're working on fixing various applications so that whenever they would
have been able to use certificates from a file, users can simply insert
a PKCS#11 URI instead and expect it to work. This expectation is now a
part of the Fedora packaging guidelines, for example.
This doesn't work with cURL because of the way that the colon is used
to separate the certificate argument from the passphrase. So instead of
curl -E 'pkcs11:manufacturer=piv_II;id=%01' …
I instead need to invoke cURL with the colon escaped, like this:
curl -E 'pkcs11\:manufacturer=piv_II;id=%01' …
This is suboptimal because we want *consistency* — the URI should be
usable in place of a filename anywhere, without having strange
differences for different applications.
This patch therefore disables the processing in parse_cert_parameter()
when the string starts with 'pkcs11:'. It means you can't pass a
passphrase with an unescaped PKCS#11 URI, but there's no need to do so
because RFC7512 allows a PIN to be given as a 'pin-value' attribute in
the URI itself.
Also, if users are already using RFC7512 URIs with the colon escaped as
in the above example — even providing a passphrase for cURL to handling
instead of using a pin-value attribute, that will continue to work
because their string will start 'pkcs11\:' and won't match the check.
What *does* break with this patch is the extremely unlikely case that a
user has a file which is in the local directory and literally named
just "pkcs11", and they have a passphrase on it. If that ever happened,
the user would need to refer to it as './pkcs11:<passphrase>' instead.
2016-08-17 05:30:21 -04:00
|
|
|
!strpbrk(cert_parameter, ":\\")) {
|
2013-04-05 10:01:31 -04:00
|
|
|
*certname = strdup(cert_parameter);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* deal with escaped chars; find unescaped colon if it exists */
|
2013-05-03 16:57:18 -04:00
|
|
|
certname_place = malloc(param_length + 1);
|
|
|
|
if(!certname_place)
|
|
|
|
return;
|
|
|
|
|
|
|
|
*certname = certname_place;
|
2013-04-05 10:01:31 -04:00
|
|
|
param_place = cert_parameter;
|
|
|
|
while(*param_place) {
|
|
|
|
span = strcspn(param_place, ":\\");
|
|
|
|
strncpy(certname_place, param_place, span);
|
|
|
|
param_place += span;
|
|
|
|
certname_place += span;
|
|
|
|
/* we just ate all the non-special chars. now we're on either a special
|
|
|
|
* char or the end of the string. */
|
|
|
|
switch(*param_place) {
|
|
|
|
case '\0':
|
|
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
param_place++;
|
|
|
|
switch(*param_place) {
|
|
|
|
case '\0':
|
|
|
|
*certname_place++ = '\\';
|
|
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
*certname_place++ = '\\';
|
|
|
|
param_place++;
|
|
|
|
break;
|
|
|
|
case ':':
|
|
|
|
*certname_place++ = ':';
|
|
|
|
param_place++;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*certname_place++ = '\\';
|
|
|
|
*certname_place++ = *param_place;
|
|
|
|
param_place++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ':':
|
|
|
|
/* Since we live in a world of weirdness and confusion, the win32
|
|
|
|
dudes can use : when using drive letters and thus c:\file:password
|
|
|
|
needs to work. In order not to break compatibility, we still use : as
|
|
|
|
separator, but we try to detect when it is used for a file name! On
|
|
|
|
windows. */
|
|
|
|
#ifdef WIN32
|
|
|
|
if(param_place &&
|
|
|
|
(param_place == &cert_parameter[1]) &&
|
|
|
|
(cert_parameter[2] == '\\' || cert_parameter[2] == '/') &&
|
|
|
|
(ISALPHA(cert_parameter[0])) ) {
|
|
|
|
/* colon in the second column, followed by a backslash, and the
|
|
|
|
first character is an alphabetic letter:
|
|
|
|
|
|
|
|
this is a drive letter colon */
|
|
|
|
*certname_place++ = ':';
|
|
|
|
param_place++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/* escaped colons and Windows drive letter colons were handled
|
|
|
|
* above; if we're still here, this is a separating colon */
|
|
|
|
param_place++;
|
2020-02-03 04:42:46 -05:00
|
|
|
if(*param_place) {
|
2013-04-05 10:01:31 -04:00
|
|
|
*passphrase = strdup(param_place);
|
|
|
|
}
|
2013-05-03 16:57:18 -04:00
|
|
|
goto done;
|
2013-04-05 10:01:31 -04:00
|
|
|
}
|
|
|
|
}
|
2013-05-03 16:57:18 -04:00
|
|
|
done:
|
|
|
|
*certname_place = '\0';
|
2013-04-05 10:01:31 -04:00
|
|
|
}
|
|
|
|
|
2016-11-16 12:49:15 -05:00
|
|
|
static void
|
|
|
|
GetFileAndPassword(char *nextarg, char **file, char **password)
|
|
|
|
{
|
|
|
|
char *certname, *passphrase;
|
|
|
|
parse_cert_parameter(nextarg, &certname, &passphrase);
|
|
|
|
Curl_safefree(*file);
|
|
|
|
*file = certname;
|
|
|
|
if(passphrase) {
|
|
|
|
Curl_safefree(*password);
|
|
|
|
*password = passphrase;
|
|
|
|
}
|
|
|
|
cleanarg(nextarg);
|
|
|
|
}
|
|
|
|
|
2017-12-17 17:26:10 -05:00
|
|
|
/* Get a size parameter for '--limit-rate' or '--max-filesize'.
|
|
|
|
* We support a 'G', 'M' or 'K' suffix too.
|
|
|
|
*/
|
|
|
|
static ParameterError GetSizeParameter(struct GlobalConfig *global,
|
|
|
|
const char *arg,
|
|
|
|
const char *which,
|
|
|
|
curl_off_t *value_out)
|
|
|
|
{
|
|
|
|
char *unit;
|
|
|
|
curl_off_t value;
|
|
|
|
|
|
|
|
if(curlx_strtoofft(arg, &unit, 0, &value)) {
|
|
|
|
warnf(global, "invalid number specified for %s\n", which);
|
|
|
|
return PARAM_BAD_USE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!*unit)
|
|
|
|
unit = (char *)"b";
|
|
|
|
else if(strlen(unit) > 1)
|
|
|
|
unit = (char *)"w"; /* unsupported */
|
|
|
|
|
|
|
|
switch(*unit) {
|
|
|
|
case 'G':
|
|
|
|
case 'g':
|
|
|
|
if(value > (CURL_OFF_T_MAX / (1024*1024*1024)))
|
|
|
|
return PARAM_NUMBER_TOO_LARGE;
|
|
|
|
value *= 1024*1024*1024;
|
|
|
|
break;
|
|
|
|
case 'M':
|
|
|
|
case 'm':
|
|
|
|
if(value > (CURL_OFF_T_MAX / (1024*1024)))
|
|
|
|
return PARAM_NUMBER_TOO_LARGE;
|
|
|
|
value *= 1024*1024;
|
|
|
|
break;
|
|
|
|
case 'K':
|
|
|
|
case 'k':
|
|
|
|
if(value > (CURL_OFF_T_MAX / 1024))
|
|
|
|
return PARAM_NUMBER_TOO_LARGE;
|
|
|
|
value *= 1024;
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
case 'B':
|
|
|
|
/* for plain bytes, leave as-is */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
warnf(global, "unsupported %s unit. Use G, M, K or B!\n", which);
|
|
|
|
return PARAM_BAD_USE;
|
|
|
|
}
|
|
|
|
*value_out = value;
|
|
|
|
return PARAM_OK;
|
|
|
|
}
|
|
|
|
|
2017-05-09 13:20:28 -04:00
|
|
|
ParameterError getparameter(const char *flag, /* f or -long-flag */
|
|
|
|
char *nextarg, /* NULL if unset */
|
|
|
|
bool *usedarg, /* set to TRUE if the arg
|
|
|
|
has been used */
|
2014-02-23 11:04:39 -05:00
|
|
|
struct GlobalConfig *global,
|
2014-02-23 07:59:59 -05:00
|
|
|
struct OperationConfig *config)
|
2011-10-04 18:03:20 -04:00
|
|
|
{
|
|
|
|
char letter;
|
|
|
|
char subletter = '\0'; /* subletters can only occur on long options */
|
|
|
|
int rc;
|
|
|
|
const char *parse = NULL;
|
|
|
|
unsigned int j;
|
|
|
|
time_t now;
|
|
|
|
int hit = -1;
|
|
|
|
bool longopt = FALSE;
|
|
|
|
bool singleopt = FALSE; /* when true means '-o foo' used '-ofoo' */
|
|
|
|
ParameterError err;
|
|
|
|
bool toggle = TRUE; /* how to switch boolean options, on or off. Controlled
|
|
|
|
by using --OPTION or --no-OPTION */
|
|
|
|
|
2017-08-04 05:49:27 -04:00
|
|
|
*usedarg = FALSE; /* default is that we don't use the arg */
|
2011-10-04 18:03:20 -04:00
|
|
|
|
2018-06-02 16:52:56 -04:00
|
|
|
if(('-' != flag[0]) || ('-' == flag[1])) {
|
2011-10-04 18:03:20 -04:00
|
|
|
/* this should be a long name */
|
2017-09-09 17:55:08 -04:00
|
|
|
const char *word = ('-' == flag[0]) ? flag + 2 : flag;
|
2011-10-04 18:03:20 -04:00
|
|
|
size_t fnam = strlen(word);
|
|
|
|
int numhits = 0;
|
2019-05-20 04:51:53 -04:00
|
|
|
bool noflagged = FALSE;
|
2011-10-04 18:03:20 -04:00
|
|
|
|
|
|
|
if(!strncmp(word, "no-", 3)) {
|
|
|
|
/* disable this option but ignore the "no-" part when looking for it */
|
|
|
|
word += 3;
|
|
|
|
toggle = FALSE;
|
2019-05-20 04:51:53 -04:00
|
|
|
noflagged = TRUE;
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
|
2016-10-31 16:49:38 -04:00
|
|
|
if(curl_strnequal(aliases[j].lname, word, fnam)) {
|
2011-10-04 18:03:20 -04:00
|
|
|
longopt = TRUE;
|
|
|
|
numhits++;
|
2016-10-31 16:49:38 -04:00
|
|
|
if(curl_strequal(aliases[j].lname, word)) {
|
2011-10-04 18:03:20 -04:00
|
|
|
parse = aliases[j].letter;
|
|
|
|
hit = j;
|
|
|
|
numhits = 1; /* a single unique hit */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
parse = aliases[j].letter;
|
|
|
|
hit = j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(numhits > 1) {
|
|
|
|
/* this is at least the second match! */
|
|
|
|
return PARAM_OPTION_AMBIGUOUS;
|
|
|
|
}
|
|
|
|
if(hit < 0) {
|
|
|
|
return PARAM_OPTION_UNKNOWN;
|
|
|
|
}
|
2019-05-20 04:51:53 -04:00
|
|
|
if(noflagged && (aliases[hit].desc != ARG_BOOL))
|
|
|
|
/* --no- prefixed an option that isn't boolean! */
|
|
|
|
return PARAM_NO_NOT_BOOLEAN;
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
flag++; /* prefixed with one dash, pass it */
|
|
|
|
hit = -1;
|
|
|
|
parse = flag;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
/* we can loop here if we have multiple single-letters */
|
|
|
|
|
|
|
|
if(!longopt) {
|
2014-10-04 10:14:39 -04:00
|
|
|
letter = (char)*parse;
|
2017-09-09 17:09:06 -04:00
|
|
|
subletter = '\0';
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
letter = parse[0];
|
|
|
|
subletter = parse[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
if(hit < 0) {
|
|
|
|
for(j = 0; j < sizeof(aliases)/sizeof(aliases[0]); j++) {
|
|
|
|
if(letter == aliases[j].letter[0]) {
|
|
|
|
hit = j;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(hit < 0) {
|
|
|
|
return PARAM_OPTION_UNKNOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-15 03:17:43 -04:00
|
|
|
if(aliases[hit].desc >= ARG_STRING) {
|
2011-10-04 18:03:20 -04:00
|
|
|
/* this option requires an extra parameter */
|
|
|
|
if(!longopt && parse[1]) {
|
|
|
|
nextarg = (char *)&parse[1]; /* this is the actual extra parameter */
|
|
|
|
singleopt = TRUE; /* don't loop anymore after this */
|
|
|
|
}
|
|
|
|
else if(!nextarg)
|
|
|
|
return PARAM_REQUIRES_PARAMETER;
|
|
|
|
else
|
|
|
|
*usedarg = TRUE; /* mark it as used */
|
2018-08-15 03:17:43 -04:00
|
|
|
|
|
|
|
if((aliases[hit].desc == ARG_FILENAME) &&
|
|
|
|
(nextarg[0] == '-') && nextarg[1]) {
|
|
|
|
/* if the file name looks like a command line option */
|
|
|
|
warnf(global, "The file name argument '%s' looks like a flag.\n",
|
|
|
|
nextarg);
|
|
|
|
}
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
2017-04-30 19:23:53 -04:00
|
|
|
else if((aliases[hit].desc == ARG_NONE) && !toggle)
|
|
|
|
return PARAM_NO_PREFIX;
|
2011-10-04 18:03:20 -04:00
|
|
|
|
|
|
|
switch(letter) {
|
|
|
|
case '*': /* options without a short option */
|
|
|
|
switch(subletter) {
|
2013-02-09 16:18:02 -05:00
|
|
|
case '4': /* --dns-ipv4-addr */
|
|
|
|
/* addr in dot notation */
|
|
|
|
GetStr(&config->dns_ipv4_addr, nextarg);
|
|
|
|
break;
|
|
|
|
case '6': /* --dns-ipv6-addr */
|
|
|
|
/* addr in dot notation */
|
|
|
|
GetStr(&config->dns_ipv6_addr, nextarg);
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'a': /* random-file */
|
|
|
|
GetStr(&config->random_file, nextarg);
|
|
|
|
break;
|
|
|
|
case 'b': /* egd-file */
|
|
|
|
GetStr(&config->egd_file, nextarg);
|
|
|
|
break;
|
2015-09-04 01:56:26 -04:00
|
|
|
case 'B': /* OAuth 2.0 bearer token */
|
2015-09-04 02:11:09 -04:00
|
|
|
GetStr(&config->oauth_bearer, nextarg);
|
2018-05-22 06:28:41 -04:00
|
|
|
config->authtype |= CURLAUTH_BEARER;
|
2013-08-25 13:18:59 -04:00
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'c': /* connect-timeout */
|
2017-08-06 14:10:40 -04:00
|
|
|
err = str2udouble(&config->connecttimeout, nextarg,
|
|
|
|
LONG_MAX/1000);
|
2012-11-26 10:23:02 -05:00
|
|
|
if(err)
|
|
|
|
return err;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
2018-09-06 03:16:02 -04:00
|
|
|
case 'C': /* doh-url */
|
|
|
|
GetStr(&config->doh_url, nextarg);
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'd': /* ciphers */
|
|
|
|
GetStr(&config->cipher_list, nextarg);
|
|
|
|
break;
|
2013-02-09 16:18:02 -05:00
|
|
|
case 'D': /* --dns-interface */
|
|
|
|
/* interface name */
|
|
|
|
GetStr(&config->dns_interface, nextarg);
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'e': /* --disable-epsv */
|
|
|
|
config->disable_epsv = toggle;
|
|
|
|
break;
|
2018-02-25 14:17:25 -05:00
|
|
|
case 'f': /* --disallow-username-in-url */
|
|
|
|
config->disallow_username_in_url = toggle;
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'E': /* --epsv */
|
|
|
|
config->disable_epsv = (!toggle)?TRUE:FALSE;
|
|
|
|
break;
|
2013-02-09 16:18:02 -05:00
|
|
|
case 'F': /* --dns-servers */
|
|
|
|
/* IP addrs of DNS servers */
|
|
|
|
GetStr(&config->dns_servers, nextarg);
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'g': /* --trace */
|
2014-02-27 15:51:49 -05:00
|
|
|
GetStr(&global->trace_dump, nextarg);
|
|
|
|
if(global->tracetype && (global->tracetype != TRACE_BIN))
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global, "--trace overrides an earlier trace/verbose option\n");
|
2014-02-27 15:51:49 -05:00
|
|
|
global->tracetype = TRACE_BIN;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
2014-02-10 02:38:55 -05:00
|
|
|
case 'G': /* --npn */
|
|
|
|
config->nonpn = (!toggle)?TRUE:FALSE;
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'h': /* --trace-ascii */
|
2014-02-27 15:51:49 -05:00
|
|
|
GetStr(&global->trace_dump, nextarg);
|
|
|
|
if(global->tracetype && (global->tracetype != TRACE_ASCII))
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global,
|
2011-10-04 18:03:20 -04:00
|
|
|
"--trace-ascii overrides an earlier trace/verbose option\n");
|
2014-02-27 15:51:49 -05:00
|
|
|
global->tracetype = TRACE_ASCII;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
2014-02-10 02:38:55 -05:00
|
|
|
case 'H': /* --alpn */
|
|
|
|
config->noalpn = (!toggle)?TRUE:FALSE;
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'i': /* --limit-rate */
|
|
|
|
{
|
2017-08-14 17:33:23 -04:00
|
|
|
curl_off_t value;
|
2017-12-17 17:26:10 -05:00
|
|
|
ParameterError pe = GetSizeParameter(global, nextarg, "rate", &value);
|
2011-10-04 18:03:20 -04:00
|
|
|
|
2017-12-17 17:26:10 -05:00
|
|
|
if(pe != PARAM_OK)
|
|
|
|
return pe;
|
2011-10-04 18:03:20 -04:00
|
|
|
config->recvpersecond = value;
|
|
|
|
config->sendpersecond = value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'j': /* --compressed */
|
2018-03-07 19:39:29 -05:00
|
|
|
if(toggle &&
|
|
|
|
!(curlinfo->features & (CURL_VERSION_LIBZ | CURL_VERSION_BROTLI)))
|
2011-10-04 18:03:20 -04:00
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
config->encoding = toggle;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'J': /* --tr-encoding */
|
|
|
|
config->tr_encoding = toggle;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'k': /* --digest */
|
|
|
|
if(toggle)
|
|
|
|
config->authtype |= CURLAUTH_DIGEST;
|
|
|
|
else
|
|
|
|
config->authtype &= ~CURLAUTH_DIGEST;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'l': /* --negotiate */
|
|
|
|
if(toggle) {
|
2014-07-21 03:53:46 -04:00
|
|
|
if(curlinfo->features & CURL_VERSION_SPNEGO)
|
|
|
|
config->authtype |= CURLAUTH_NEGOTIATE;
|
2011-10-04 18:03:20 -04:00
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
}
|
|
|
|
else
|
2014-07-21 03:53:46 -04:00
|
|
|
config->authtype &= ~CURLAUTH_NEGOTIATE;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'm': /* --ntlm */
|
|
|
|
if(toggle) {
|
|
|
|
if(curlinfo->features & CURL_VERSION_NTLM)
|
|
|
|
config->authtype |= CURLAUTH_NTLM;
|
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
config->authtype &= ~CURLAUTH_NTLM;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'M': /* --ntlm-wb */
|
|
|
|
if(toggle) {
|
|
|
|
if(curlinfo->features & CURL_VERSION_NTLM_WB)
|
|
|
|
config->authtype |= CURLAUTH_NTLM_WB;
|
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
config->authtype &= ~CURLAUTH_NTLM_WB;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n': /* --basic for completeness */
|
|
|
|
if(toggle)
|
|
|
|
config->authtype |= CURLAUTH_BASIC;
|
|
|
|
else
|
|
|
|
config->authtype &= ~CURLAUTH_BASIC;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'o': /* --anyauth, let libcurl pick it */
|
|
|
|
if(toggle)
|
|
|
|
config->authtype = CURLAUTH_ANY;
|
|
|
|
/* --no-anyauth simply doesn't touch it */
|
|
|
|
break;
|
|
|
|
|
|
|
|
#ifdef USE_WATT32
|
|
|
|
case 'p': /* --wdebug */
|
|
|
|
dbug_init();
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case 'q': /* --ftp-create-dirs */
|
|
|
|
config->ftp_create_dirs = toggle;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'r': /* --create-dirs */
|
2013-08-14 05:35:42 -04:00
|
|
|
config->create_dirs = toggle;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 's': /* --max-redirs */
|
2012-07-10 17:11:30 -04:00
|
|
|
/* specified max no of redirects (http(s)), this accepts -1 as a
|
|
|
|
special condition */
|
2012-11-26 10:23:02 -05:00
|
|
|
err = str2num(&config->maxredirs, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
2012-07-10 17:11:30 -04:00
|
|
|
if(config->maxredirs < -1)
|
2011-10-04 18:03:20 -04:00
|
|
|
return PARAM_BAD_NUMERIC;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 't': /* --proxy-ntlm */
|
|
|
|
if(curlinfo->features & CURL_VERSION_NTLM)
|
|
|
|
config->proxyntlm = toggle;
|
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'u': /* --crlf */
|
|
|
|
/* LF -> CRLF conversion? */
|
2013-08-14 05:35:42 -04:00
|
|
|
config->crlf = toggle;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'v': /* --stderr */
|
|
|
|
if(strcmp(nextarg, "-")) {
|
2015-06-01 03:20:18 -04:00
|
|
|
FILE *newfile = fopen(nextarg, FOPEN_WRITETEXT);
|
2011-10-04 18:03:20 -04:00
|
|
|
if(!newfile)
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global, "Failed to open %s!\n", nextarg);
|
2011-10-04 18:03:20 -04:00
|
|
|
else {
|
2014-03-01 08:00:31 -05:00
|
|
|
if(global->errors_fopened)
|
|
|
|
fclose(global->errors);
|
|
|
|
global->errors = newfile;
|
|
|
|
global->errors_fopened = TRUE;
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2014-03-01 08:00:31 -05:00
|
|
|
global->errors = stdout;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'w': /* --interface */
|
|
|
|
/* interface */
|
|
|
|
GetStr(&config->iface, nextarg);
|
|
|
|
break;
|
|
|
|
case 'x': /* --krb */
|
|
|
|
/* kerberos level string */
|
2014-07-21 03:53:46 -04:00
|
|
|
if(curlinfo->features & CURL_VERSION_KERBEROS4)
|
2011-10-04 18:03:20 -04:00
|
|
|
GetStr(&config->krblevel, nextarg);
|
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
break;
|
2016-12-01 07:05:04 -05:00
|
|
|
case 'X': /* --haproxy-protocol */
|
|
|
|
config->haproxy_protocol = toggle;
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'y': /* --max-filesize */
|
2017-12-17 17:26:10 -05:00
|
|
|
{
|
|
|
|
curl_off_t value;
|
|
|
|
ParameterError pe =
|
|
|
|
GetSizeParameter(global, nextarg, "max-filesize", &value);
|
|
|
|
|
|
|
|
if(pe != PARAM_OK)
|
|
|
|
return pe;
|
|
|
|
config->max_filesize = value;
|
|
|
|
}
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'z': /* --disable-eprt */
|
|
|
|
config->disable_eprt = toggle;
|
|
|
|
break;
|
|
|
|
case 'Z': /* --eprt */
|
|
|
|
config->disable_eprt = (!toggle)?TRUE:FALSE;
|
|
|
|
break;
|
2016-04-28 16:24:10 -04:00
|
|
|
case '~': /* --xattr */
|
|
|
|
config->xattr = toggle;
|
|
|
|
break;
|
|
|
|
case '@': /* the URL! */
|
2011-10-04 18:03:20 -04:00
|
|
|
{
|
|
|
|
struct getout *url;
|
2016-12-13 19:29:44 -05:00
|
|
|
|
|
|
|
if(!config->url_get)
|
|
|
|
config->url_get = config->url_list;
|
|
|
|
|
|
|
|
if(config->url_get) {
|
2011-10-04 18:03:20 -04:00
|
|
|
/* there's a node here, if it already is filled-in continue to find
|
|
|
|
an "empty" node */
|
2011-10-05 09:06:26 -04:00
|
|
|
while(config->url_get && (config->url_get->flags & GETOUT_URL))
|
2011-10-04 18:03:20 -04:00
|
|
|
config->url_get = config->url_get->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now there might or might not be an available node to fill in! */
|
|
|
|
|
|
|
|
if(config->url_get)
|
|
|
|
/* existing node */
|
|
|
|
url = config->url_get;
|
|
|
|
else
|
|
|
|
/* there was no free node, create one! */
|
2017-11-04 07:56:30 -04:00
|
|
|
config->url_get = url = new_getout(config);
|
2011-10-04 18:03:20 -04:00
|
|
|
|
2011-10-05 09:06:26 -04:00
|
|
|
if(!url)
|
|
|
|
return PARAM_NO_MEM;
|
2017-03-10 08:28:37 -05:00
|
|
|
|
|
|
|
/* fill in the URL */
|
|
|
|
GetStr(&url->url, nextarg);
|
|
|
|
url->flags |= GETOUT_URL;
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '$': /* more options without a short option */
|
|
|
|
switch(subletter) {
|
2016-12-17 17:49:11 -05:00
|
|
|
case 'a': /* --ssl */
|
2011-10-04 18:03:20 -04:00
|
|
|
if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
config->ftp_ssl = toggle;
|
|
|
|
break;
|
|
|
|
case 'b': /* --ftp-pasv */
|
|
|
|
Curl_safefree(config->ftpport);
|
|
|
|
break;
|
|
|
|
case 'c': /* --socks5 specifies a socks5 proxy to use, and resolves
|
|
|
|
the name locally and passes on the resolved address */
|
2016-12-16 09:34:14 -05:00
|
|
|
GetStr(&config->proxy, nextarg);
|
|
|
|
config->proxyver = CURLPROXY_SOCKS5;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 't': /* --socks4 specifies a socks4 proxy to use */
|
2016-12-16 09:34:14 -05:00
|
|
|
GetStr(&config->proxy, nextarg);
|
|
|
|
config->proxyver = CURLPROXY_SOCKS4;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'T': /* --socks4a specifies a socks4a proxy to use */
|
2016-12-16 09:34:14 -05:00
|
|
|
GetStr(&config->proxy, nextarg);
|
|
|
|
config->proxyver = CURLPROXY_SOCKS4A;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case '2': /* --socks5-hostname specifies a socks5 proxy and enables name
|
|
|
|
resolving with the proxy */
|
2016-12-16 09:34:14 -05:00
|
|
|
GetStr(&config->proxy, nextarg);
|
|
|
|
config->proxyver = CURLPROXY_SOCKS5_HOSTNAME;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'd': /* --tcp-nodelay option */
|
|
|
|
config->tcp_nodelay = toggle;
|
|
|
|
break;
|
|
|
|
case 'e': /* --proxy-digest */
|
|
|
|
config->proxydigest = toggle;
|
|
|
|
break;
|
|
|
|
case 'f': /* --proxy-basic */
|
|
|
|
config->proxybasic = toggle;
|
|
|
|
break;
|
|
|
|
case 'g': /* --retry */
|
2012-11-26 10:23:02 -05:00
|
|
|
err = str2unum(&config->req_retry, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
2016-10-09 19:00:25 -04:00
|
|
|
case 'V': /* --retry-connrefused */
|
|
|
|
config->retry_connrefused = toggle;
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'h': /* --retry-delay */
|
2019-07-29 16:10:13 -04:00
|
|
|
err = str2unummax(&config->retry_delay, nextarg, LONG_MAX/1000);
|
2012-11-26 10:23:02 -05:00
|
|
|
if(err)
|
|
|
|
return err;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'i': /* --retry-max-time */
|
2019-07-29 16:10:13 -04:00
|
|
|
err = str2unummax(&config->retry_maxtime, nextarg, LONG_MAX/1000);
|
2012-11-26 10:23:02 -05:00
|
|
|
if(err)
|
|
|
|
return err;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
2020-04-04 16:16:18 -04:00
|
|
|
case '!': /* --retry-all-errors */
|
|
|
|
config->retry_all_errors = toggle;
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
|
|
|
|
case 'k': /* --proxy-negotiate */
|
2014-07-21 03:53:46 -04:00
|
|
|
if(curlinfo->features & CURL_VERSION_SPNEGO)
|
2011-10-04 18:03:20 -04:00
|
|
|
config->proxynegotiate = toggle;
|
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
break;
|
2014-07-21 03:53:46 -04:00
|
|
|
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'm': /* --ftp-account */
|
|
|
|
GetStr(&config->ftp_account, nextarg);
|
|
|
|
break;
|
|
|
|
case 'n': /* --proxy-anyauth */
|
|
|
|
config->proxyanyauth = toggle;
|
|
|
|
break;
|
|
|
|
case 'o': /* --trace-time */
|
2014-02-27 15:51:49 -05:00
|
|
|
global->tracetime = toggle;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'p': /* --ignore-content-length */
|
|
|
|
config->ignorecl = toggle;
|
|
|
|
break;
|
|
|
|
case 'q': /* --ftp-skip-pasv-ip */
|
|
|
|
config->ftp_skip_ip = toggle;
|
|
|
|
break;
|
|
|
|
case 'r': /* --ftp-method (undocumented at this point) */
|
|
|
|
config->ftp_filemethod = ftpfilemethod(config, nextarg);
|
|
|
|
break;
|
2018-11-05 05:57:29 -05:00
|
|
|
case 's': { /* --local-port */
|
|
|
|
char lrange[7]; /* 16bit base 10 is 5 digits, but we allow 6 so that
|
|
|
|
this catches overflows, not just truncates */
|
|
|
|
char *p = nextarg;
|
|
|
|
while(ISDIGIT(*p))
|
|
|
|
p++;
|
|
|
|
if(*p) {
|
|
|
|
/* if there's anything more than a plain decimal number */
|
|
|
|
rc = sscanf(p, " - %6s", lrange);
|
2018-11-07 17:26:55 -05:00
|
|
|
*p = 0; /* zero terminate to make str2unum() work below */
|
2018-11-05 05:57:29 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = 0;
|
|
|
|
|
|
|
|
err = str2unum(&config->localport, nextarg);
|
|
|
|
if(err || (config->localport > 65535))
|
2011-10-04 18:03:20 -04:00
|
|
|
return PARAM_BAD_USE;
|
2018-11-05 05:57:29 -05:00
|
|
|
if(!rc)
|
2011-10-04 18:03:20 -04:00
|
|
|
config->localportrange = 1; /* default number of ports to try */
|
|
|
|
else {
|
2018-11-05 05:57:29 -05:00
|
|
|
err = str2unum(&config->localportrange, lrange);
|
|
|
|
if(err || (config->localportrange > 65535))
|
|
|
|
return PARAM_BAD_USE;
|
2018-11-09 04:49:14 -05:00
|
|
|
config->localportrange -= (config->localport-1);
|
2018-11-05 05:57:29 -05:00
|
|
|
if(config->localportrange < 1)
|
2011-10-04 18:03:20 -04:00
|
|
|
return PARAM_BAD_USE;
|
|
|
|
}
|
|
|
|
break;
|
2018-11-05 05:57:29 -05:00
|
|
|
}
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'u': /* --ftp-alternative-to-user */
|
|
|
|
GetStr(&config->ftp_alternative_to_user, nextarg);
|
|
|
|
break;
|
2016-12-17 17:49:11 -05:00
|
|
|
case 'v': /* --ssl-reqd */
|
2011-10-04 18:03:20 -04:00
|
|
|
if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
config->ftp_ssl_reqd = toggle;
|
|
|
|
break;
|
|
|
|
case 'w': /* --no-sessionid */
|
|
|
|
config->disable_sessionid = (!toggle)?TRUE:FALSE;
|
|
|
|
break;
|
|
|
|
case 'x': /* --ftp-ssl-control */
|
|
|
|
if(toggle && !(curlinfo->features & CURL_VERSION_SSL))
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
config->ftp_ssl_control = toggle;
|
|
|
|
break;
|
|
|
|
case 'y': /* --ftp-ssl-ccc */
|
|
|
|
config->ftp_ssl_ccc = toggle;
|
|
|
|
if(!config->ftp_ssl_ccc_mode)
|
|
|
|
config->ftp_ssl_ccc_mode = CURLFTPSSL_CCC_PASSIVE;
|
|
|
|
break;
|
|
|
|
case 'j': /* --ftp-ssl-ccc-mode */
|
|
|
|
config->ftp_ssl_ccc = TRUE;
|
|
|
|
config->ftp_ssl_ccc_mode = ftpcccmethod(config, nextarg);
|
|
|
|
break;
|
|
|
|
case 'z': /* --libcurl */
|
2012-02-05 12:44:22 -05:00
|
|
|
#ifdef CURL_DISABLE_LIBCURL_OPTION
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global,
|
2012-02-05 12:44:22 -05:00
|
|
|
"--libcurl option was disabled at build-time!\n");
|
|
|
|
return PARAM_OPTION_UNKNOWN;
|
|
|
|
#else
|
2014-03-01 08:38:00 -05:00
|
|
|
GetStr(&global->libcurl, nextarg);
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
2012-02-05 12:44:22 -05:00
|
|
|
#endif
|
2011-10-04 18:03:20 -04:00
|
|
|
case '#': /* --raw */
|
|
|
|
config->raw = toggle;
|
|
|
|
break;
|
|
|
|
case '0': /* --post301 */
|
|
|
|
config->post301 = toggle;
|
|
|
|
break;
|
|
|
|
case '1': /* --no-keepalive */
|
|
|
|
config->nokeepalive = (!toggle)?TRUE:FALSE;
|
|
|
|
break;
|
|
|
|
case '3': /* --keepalive-time */
|
2012-11-26 10:23:02 -05:00
|
|
|
err = str2unum(&config->alivetime, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case '4': /* --post302 */
|
|
|
|
config->post302 = toggle;
|
|
|
|
break;
|
2012-04-05 17:34:12 -04:00
|
|
|
case 'I': /* --post303 */
|
|
|
|
config->post303 = toggle;
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
case '5': /* --noproxy */
|
|
|
|
/* This specifies the noproxy list */
|
|
|
|
GetStr(&config->noproxy, nextarg);
|
|
|
|
break;
|
2016-04-09 15:47:05 -04:00
|
|
|
case '7': /* --socks5-gssapi-nec*/
|
2013-08-14 05:35:42 -04:00
|
|
|
config->socks5_gssapi_nec = toggle;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case '8': /* --proxy1.0 */
|
|
|
|
/* http 1.0 proxy */
|
|
|
|
GetStr(&config->proxy, nextarg);
|
|
|
|
config->proxyver = CURLPROXY_HTTP_1_0;
|
|
|
|
break;
|
|
|
|
case '9': /* --tftp-blksize */
|
2012-11-26 10:23:02 -05:00
|
|
|
err = str2unum(&config->tftp_blksize, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'A': /* --mail-from */
|
|
|
|
GetStr(&config->mail_from, nextarg);
|
|
|
|
break;
|
|
|
|
case 'B': /* --mail-rcpt */
|
|
|
|
/* append receiver to a list */
|
|
|
|
err = add2list(&config->mail_rcpt, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
break;
|
|
|
|
case 'C': /* --ftp-pret */
|
|
|
|
config->ftp_pret = toggle;
|
|
|
|
break;
|
|
|
|
case 'D': /* --proto */
|
|
|
|
config->proto_present = TRUE;
|
|
|
|
if(proto2num(config, &config->proto, nextarg))
|
|
|
|
return PARAM_BAD_USE;
|
|
|
|
break;
|
|
|
|
case 'E': /* --proto-redir */
|
|
|
|
config->proto_redir_present = TRUE;
|
|
|
|
if(proto2num(config, &config->proto_redir, nextarg))
|
|
|
|
return PARAM_BAD_USE;
|
|
|
|
break;
|
|
|
|
case 'F': /* --resolve */
|
|
|
|
err = add2list(&config->resolve, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
break;
|
|
|
|
case 'G': /* --delegation LEVEL */
|
|
|
|
config->gssapi_delegation = delegation(config, nextarg);
|
|
|
|
break;
|
2012-02-16 07:19:47 -05:00
|
|
|
case 'H': /* --mail-auth */
|
|
|
|
GetStr(&config->mail_auth, nextarg);
|
|
|
|
break;
|
2012-04-26 09:59:52 -04:00
|
|
|
case 'J': /* --metalink */
|
|
|
|
{
|
2012-06-07 17:49:27 -04:00
|
|
|
#ifdef USE_METALINK
|
2012-07-04 06:54:21 -04:00
|
|
|
int mlmaj, mlmin, mlpatch;
|
|
|
|
metalink_get_version(&mlmaj, &mlmin, &mlpatch);
|
2017-09-09 17:55:08 -04:00
|
|
|
if((mlmaj*10000)+(mlmin*100) + mlpatch < CURL_REQ_LIBMETALINK_VERS) {
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global,
|
2012-06-30 08:17:44 -04:00
|
|
|
"--metalink option cannot be used because the version of "
|
|
|
|
"the linked libmetalink library is too old. "
|
|
|
|
"Required: %d.%d.%d, found %d.%d.%d\n",
|
|
|
|
CURL_REQ_LIBMETALINK_MAJOR,
|
|
|
|
CURL_REQ_LIBMETALINK_MINOR,
|
|
|
|
CURL_REQ_LIBMETALINK_PATCH,
|
2012-07-04 06:54:21 -04:00
|
|
|
mlmaj, mlmin, mlpatch);
|
2012-06-30 08:17:44 -04:00
|
|
|
return PARAM_BAD_USE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
config->use_metalink = toggle;
|
2012-04-28 08:48:56 -04:00
|
|
|
#else
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global, "--metalink option is ignored because the binary is "
|
2012-04-28 08:48:56 -04:00
|
|
|
"built without the Metalink support.\n");
|
|
|
|
#endif
|
2012-04-26 09:59:52 -04:00
|
|
|
break;
|
|
|
|
}
|
2019-04-19 09:26:47 -04:00
|
|
|
case '6': /* --sasl-authzid */
|
|
|
|
GetStr(&config->sasl_authzid, nextarg);
|
|
|
|
break;
|
2013-04-27 04:54:14 -04:00
|
|
|
case 'K': /* --sasl-ir */
|
2013-08-14 05:35:42 -04:00
|
|
|
config->sasl_ir = toggle;
|
2013-04-27 04:54:14 -04:00
|
|
|
break;
|
2013-08-10 16:55:59 -04:00
|
|
|
case 'L': /* --test-event */
|
|
|
|
#ifdef CURLDEBUG
|
2019-07-20 13:14:00 -04:00
|
|
|
global->test_event_based = toggle;
|
2013-08-10 16:55:59 -04:00
|
|
|
#else
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global, "--test-event is ignored unless a debug build!\n");
|
2013-08-10 16:55:59 -04:00
|
|
|
#endif
|
|
|
|
break;
|
2014-11-27 17:59:26 -05:00
|
|
|
case 'M': /* --unix-socket */
|
2017-01-08 17:51:08 -05:00
|
|
|
config->abstract_unix_socket = FALSE;
|
2014-11-27 17:59:26 -05:00
|
|
|
GetStr(&config->unix_socket_path, nextarg);
|
|
|
|
break;
|
2015-03-23 05:51:49 -04:00
|
|
|
case 'N': /* --path-as-is */
|
|
|
|
config->path_as_is = toggle;
|
|
|
|
break;
|
2015-08-22 21:49:26 -04:00
|
|
|
case 'O': /* --proxy-service-name */
|
|
|
|
GetStr(&config->proxy_service_name, nextarg);
|
|
|
|
break;
|
|
|
|
case 'P': /* --service-name */
|
|
|
|
GetStr(&config->service_name, nextarg);
|
|
|
|
break;
|
|
|
|
case 'Q': /* --proto-default */
|
|
|
|
GetStr(&config->proto_default, nextarg);
|
|
|
|
err = check_protocol(config->proto_default);
|
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
break;
|
2015-12-14 07:29:13 -05:00
|
|
|
case 'R': /* --expect100-timeout */
|
2017-08-06 14:10:40 -04:00
|
|
|
err = str2udouble(&config->expect100timeout, nextarg, LONG_MAX/1000);
|
2015-12-14 07:29:13 -05:00
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
break;
|
2015-08-24 00:15:01 -04:00
|
|
|
case 'S': /* --tftp-no-options */
|
|
|
|
config->tftp_no_options = toggle;
|
|
|
|
break;
|
2016-01-25 08:37:24 -05:00
|
|
|
case 'U': /* --connect-to */
|
|
|
|
err = add2list(&config->connect_to, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
break;
|
2017-01-08 17:51:08 -05:00
|
|
|
case 'W': /* --abstract-unix-socket */
|
|
|
|
config->abstract_unix_socket = TRUE;
|
|
|
|
GetStr(&config->unix_socket_path, nextarg);
|
|
|
|
break;
|
2016-12-13 15:10:00 -05:00
|
|
|
case 'X': /* --tls-max */
|
|
|
|
err = str2tls_max(&config->ssl_version_max, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
break;
|
2016-04-28 05:33:25 -04:00
|
|
|
case 'Y': /* --suppress-connect-headers */
|
|
|
|
config->suppress_connect_headers = toggle;
|
|
|
|
break;
|
2017-08-05 05:26:04 -04:00
|
|
|
case 'Z': /* --compressed-ssh */
|
|
|
|
config->ssh_compression = toggle;
|
|
|
|
break;
|
2018-01-30 19:33:51 -05:00
|
|
|
case '~': /* --happy-eyeballs-timeout-ms */
|
|
|
|
err = str2unum(&config->happy_eyeballs_timeout_ms, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
/* 0 is a valid value for this timeout */
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
break;
|
2019-10-07 08:54:35 -04:00
|
|
|
case '#':
|
|
|
|
switch(subletter) {
|
|
|
|
case 'm': /* --progress-meter */
|
|
|
|
global->noprogress = !toggle;
|
|
|
|
break;
|
|
|
|
default: /* --progress-bar */
|
|
|
|
global->progressmode =
|
|
|
|
toggle ? CURL_PROGRESS_BAR : CURL_PROGRESS_STATS;
|
|
|
|
break;
|
|
|
|
}
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
2014-02-23 12:19:45 -05:00
|
|
|
case ':': /* --next */
|
|
|
|
return PARAM_NEXT_OPERATION;
|
2013-09-04 16:28:16 -04:00
|
|
|
case '0': /* --http* options */
|
|
|
|
switch(subletter) {
|
2013-09-05 03:56:05 -04:00
|
|
|
case '\0':
|
2013-09-04 16:28:16 -04:00
|
|
|
/* HTTP version 1.0 */
|
|
|
|
config->httpversion = CURL_HTTP_VERSION_1_0;
|
|
|
|
break;
|
|
|
|
case '1':
|
|
|
|
/* HTTP version 1.1 */
|
|
|
|
config->httpversion = CURL_HTTP_VERSION_1_1;
|
|
|
|
break;
|
|
|
|
case '2':
|
|
|
|
/* HTTP version 2.0 */
|
|
|
|
config->httpversion = CURL_HTTP_VERSION_2_0;
|
|
|
|
break;
|
2019-07-21 17:48:58 -04:00
|
|
|
case '3': /* --http2-prior-knowledge */
|
2016-03-18 18:25:56 -04:00
|
|
|
/* HTTP version 2.0 over clean TCP*/
|
|
|
|
config->httpversion = CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE;
|
|
|
|
break;
|
2019-08-07 08:17:48 -04:00
|
|
|
case '4': /* --http3 */
|
|
|
|
/* HTTP version 3 go over QUIC - at once */
|
2020-01-05 11:12:03 -05:00
|
|
|
if(curlinfo->features & CURL_VERSION_HTTP3)
|
|
|
|
config->httpversion = CURL_HTTP_VERSION_3;
|
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
2019-07-21 17:48:58 -04:00
|
|
|
break;
|
2018-12-17 09:46:56 -05:00
|
|
|
case '9':
|
|
|
|
/* Allow HTTP/0.9 responses! */
|
|
|
|
config->http09_allowed = toggle;
|
|
|
|
break;
|
2013-09-04 16:28:16 -04:00
|
|
|
}
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
2013-09-19 09:17:13 -04:00
|
|
|
case '1': /* --tlsv1* options */
|
|
|
|
switch(subletter) {
|
|
|
|
case '\0':
|
|
|
|
/* TLS version 1.x */
|
|
|
|
config->ssl_version = CURL_SSLVERSION_TLSv1;
|
|
|
|
break;
|
|
|
|
case '0':
|
|
|
|
/* TLS version 1.0 */
|
|
|
|
config->ssl_version = CURL_SSLVERSION_TLSv1_0;
|
|
|
|
break;
|
|
|
|
case '1':
|
|
|
|
/* TLS version 1.1 */
|
|
|
|
config->ssl_version = CURL_SSLVERSION_TLSv1_1;
|
|
|
|
break;
|
|
|
|
case '2':
|
|
|
|
/* TLS version 1.2 */
|
|
|
|
config->ssl_version = CURL_SSLVERSION_TLSv1_2;
|
|
|
|
break;
|
2016-10-27 08:58:43 -04:00
|
|
|
case '3':
|
|
|
|
/* TLS version 1.3 */
|
|
|
|
config->ssl_version = CURL_SSLVERSION_TLSv1_3;
|
|
|
|
break;
|
2018-05-29 10:12:52 -04:00
|
|
|
case 'A': /* --tls13-ciphers */
|
|
|
|
GetStr(&config->cipher13_list, nextarg);
|
|
|
|
break;
|
|
|
|
case 'B': /* --proxy-tls13-ciphers */
|
|
|
|
GetStr(&config->proxy_cipher13_list, nextarg);
|
|
|
|
break;
|
2013-09-19 09:17:13 -04:00
|
|
|
}
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case '2':
|
|
|
|
/* SSL version 2 */
|
|
|
|
config->ssl_version = CURL_SSLVERSION_SSLv2;
|
|
|
|
break;
|
|
|
|
case '3':
|
|
|
|
/* SSL version 3 */
|
|
|
|
config->ssl_version = CURL_SSLVERSION_SSLv3;
|
|
|
|
break;
|
|
|
|
case '4':
|
|
|
|
/* IPv4 */
|
|
|
|
config->ip_version = 4;
|
|
|
|
break;
|
|
|
|
case '6':
|
|
|
|
/* IPv6 */
|
|
|
|
config->ip_version = 6;
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
/* This makes the FTP sessions use APPE instead of STOR */
|
|
|
|
config->ftp_append = toggle;
|
|
|
|
break;
|
|
|
|
case 'A':
|
|
|
|
/* This specifies the User-Agent name */
|
|
|
|
GetStr(&config->useragent, nextarg);
|
|
|
|
break;
|
2019-03-03 05:17:52 -05:00
|
|
|
case 'b':
|
|
|
|
switch(subletter) {
|
|
|
|
case 'a': /* --alt-svc */
|
2020-02-04 11:32:55 -05:00
|
|
|
if(curlinfo->features & CURL_VERSION_ALTSVC)
|
|
|
|
GetStr(&config->altsvc, nextarg);
|
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
2019-03-03 05:17:52 -05:00
|
|
|
default: /* --cookie string coming up: */
|
|
|
|
if(nextarg[0] == '@') {
|
|
|
|
nextarg++;
|
|
|
|
}
|
|
|
|
else if(strchr(nextarg, '=')) {
|
|
|
|
/* A cookie string must have a =-letter */
|
|
|
|
GetStr(&config->cookie, nextarg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* We have a cookie file to read from! */
|
|
|
|
GetStr(&config->cookiefile, nextarg);
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'B':
|
|
|
|
/* use ASCII/text when transferring */
|
|
|
|
config->use_ascii = toggle;
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
/* get the file name to dump all cookies in */
|
|
|
|
GetStr(&config->cookiejar, nextarg);
|
|
|
|
break;
|
|
|
|
case 'C':
|
|
|
|
/* This makes us continue an ftp transfer at given position */
|
2016-09-30 11:15:05 -04:00
|
|
|
if(strcmp(nextarg, "-")) {
|
2012-11-26 10:23:02 -05:00
|
|
|
err = str2offset(&config->resume_from, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
2011-10-04 18:03:20 -04:00
|
|
|
config->resume_from_current = FALSE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
config->resume_from_current = TRUE;
|
|
|
|
config->resume_from = 0;
|
|
|
|
}
|
2017-09-09 17:09:06 -04:00
|
|
|
config->use_resume = TRUE;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
/* postfield data */
|
|
|
|
{
|
|
|
|
char *postdata = NULL;
|
|
|
|
FILE *file;
|
|
|
|
size_t size = 0;
|
2015-04-25 14:49:39 -04:00
|
|
|
bool raw_mode = (subletter == 'r');
|
2011-10-04 18:03:20 -04:00
|
|
|
|
|
|
|
if(subletter == 'e') { /* --data-urlencode*/
|
|
|
|
/* [name]=[content], we encode the content part only
|
|
|
|
* [name]@[file name]
|
|
|
|
*
|
|
|
|
* Case 2: we first load the file using that name and then encode
|
|
|
|
* the content.
|
|
|
|
*/
|
|
|
|
const char *p = strchr(nextarg, '=');
|
|
|
|
size_t nlen;
|
|
|
|
char is_file;
|
|
|
|
if(!p)
|
|
|
|
/* there was no '=' letter, check for a '@' instead */
|
|
|
|
p = strchr(nextarg, '@');
|
|
|
|
if(p) {
|
|
|
|
nlen = p - nextarg; /* length of the name part */
|
|
|
|
is_file = *p++; /* pass the separator */
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* neither @ nor =, so no name and it isn't a file */
|
|
|
|
nlen = is_file = 0;
|
|
|
|
p = nextarg;
|
|
|
|
}
|
|
|
|
if('@' == is_file) {
|
|
|
|
/* a '@' letter, it means that a file name or - (stdin) follows */
|
2016-09-30 11:15:05 -04:00
|
|
|
if(!strcmp("-", p)) {
|
2011-10-04 18:03:20 -04:00
|
|
|
file = stdin;
|
|
|
|
set_binmode(stdin);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
file = fopen(p, "rb");
|
|
|
|
if(!file)
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global,
|
2011-10-04 18:03:20 -04:00
|
|
|
"Couldn't read data from file \"%s\", this makes "
|
|
|
|
"an empty POST.\n", nextarg);
|
|
|
|
}
|
|
|
|
|
|
|
|
err = file2memory(&postdata, &size, file);
|
|
|
|
|
|
|
|
if(file && (file != stdin))
|
|
|
|
fclose(file);
|
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
GetStr(&postdata, p);
|
2011-10-05 10:41:04 -04:00
|
|
|
if(postdata)
|
|
|
|
size = strlen(postdata);
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if(!postdata) {
|
|
|
|
/* no data from the file, point to a zero byte string to make this
|
|
|
|
get sent as a POST anyway */
|
|
|
|
postdata = strdup("");
|
2011-10-05 09:06:26 -04:00
|
|
|
if(!postdata)
|
|
|
|
return PARAM_NO_MEM;
|
2011-10-04 18:03:20 -04:00
|
|
|
size = 0;
|
|
|
|
}
|
|
|
|
else {
|
2019-07-20 13:14:00 -04:00
|
|
|
char *enc = curl_easy_escape(NULL, postdata, (int)size);
|
2011-10-04 18:03:20 -04:00
|
|
|
Curl_safefree(postdata); /* no matter if it worked or not */
|
|
|
|
if(enc) {
|
|
|
|
/* now make a string with the name from above and append the
|
|
|
|
encoded string */
|
|
|
|
size_t outlen = nlen + strlen(enc) + 2;
|
|
|
|
char *n = malloc(outlen);
|
|
|
|
if(!n) {
|
|
|
|
curl_free(enc);
|
|
|
|
return PARAM_NO_MEM;
|
|
|
|
}
|
|
|
|
if(nlen > 0) { /* only append '=' if we have a name */
|
2018-11-22 03:01:24 -05:00
|
|
|
msnprintf(n, outlen, "%.*s=%s", nlen, nextarg, enc);
|
2011-10-04 18:03:20 -04:00
|
|
|
size = outlen-1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
strcpy(n, enc);
|
|
|
|
size = outlen-2; /* since no '=' was inserted */
|
|
|
|
}
|
|
|
|
curl_free(enc);
|
|
|
|
postdata = n;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return PARAM_NO_MEM;
|
|
|
|
}
|
|
|
|
}
|
2015-04-25 14:49:39 -04:00
|
|
|
else if('@' == *nextarg && !raw_mode) {
|
2011-10-04 18:03:20 -04:00
|
|
|
/* the data begins with a '@' letter, it means that a file name
|
|
|
|
or - (stdin) follows */
|
|
|
|
nextarg++; /* pass the @ */
|
|
|
|
|
2016-09-30 11:15:05 -04:00
|
|
|
if(!strcmp("-", nextarg)) {
|
2011-10-04 18:03:20 -04:00
|
|
|
file = stdin;
|
|
|
|
if(subletter == 'b') /* forced data-binary */
|
|
|
|
set_binmode(stdin);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
file = fopen(nextarg, "rb");
|
|
|
|
if(!file)
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global, "Couldn't read data from file \"%s\", this makes "
|
2011-10-04 18:03:20 -04:00
|
|
|
"an empty POST.\n", nextarg);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(subletter == 'b')
|
|
|
|
/* forced binary */
|
|
|
|
err = file2memory(&postdata, &size, file);
|
|
|
|
else {
|
|
|
|
err = file2string(&postdata, file);
|
|
|
|
if(postdata)
|
|
|
|
size = strlen(postdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(file && (file != stdin))
|
|
|
|
fclose(file);
|
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if(!postdata) {
|
|
|
|
/* no data from the file, point to a zero byte string to make this
|
|
|
|
get sent as a POST anyway */
|
2011-10-05 09:06:26 -04:00
|
|
|
postdata = strdup("");
|
|
|
|
if(!postdata)
|
|
|
|
return PARAM_NO_MEM;
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
GetStr(&postdata, nextarg);
|
2011-10-05 13:33:46 -04:00
|
|
|
if(postdata)
|
|
|
|
size = strlen(postdata);
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CURL_DOES_CONVERSIONS
|
2011-10-05 10:41:04 -04:00
|
|
|
if(subletter != 'b') {
|
|
|
|
/* NOT forced binary, convert to ASCII */
|
|
|
|
if(convert_to_network(postdata, strlen(postdata))) {
|
|
|
|
Curl_safefree(postdata);
|
|
|
|
return PARAM_NO_MEM;
|
|
|
|
}
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if(config->postfields) {
|
|
|
|
/* we already have a string, we append this one with a separating
|
|
|
|
&-letter */
|
|
|
|
char *oldpost = config->postfields;
|
|
|
|
curl_off_t oldlen = config->postfieldsize;
|
2014-03-23 08:46:54 -04:00
|
|
|
curl_off_t newlen = oldlen + curlx_uztoso(size) + 2;
|
2011-10-04 18:03:20 -04:00
|
|
|
config->postfields = malloc((size_t)newlen);
|
|
|
|
if(!config->postfields) {
|
2011-10-05 10:41:04 -04:00
|
|
|
Curl_safefree(oldpost);
|
2011-10-04 18:03:20 -04:00
|
|
|
Curl_safefree(postdata);
|
|
|
|
return PARAM_NO_MEM;
|
|
|
|
}
|
|
|
|
memcpy(config->postfields, oldpost, (size_t)oldlen);
|
|
|
|
/* use byte value 0x26 for '&' to accommodate non-ASCII platforms */
|
|
|
|
config->postfields[oldlen] = '\x26';
|
2017-09-09 17:55:08 -04:00
|
|
|
memcpy(&config->postfields[oldlen + 1], postdata, size);
|
|
|
|
config->postfields[oldlen + 1 + size] = '\0';
|
2011-10-04 18:03:20 -04:00
|
|
|
Curl_safefree(oldpost);
|
|
|
|
Curl_safefree(postdata);
|
2017-09-09 17:55:08 -04:00
|
|
|
config->postfieldsize += size + 1;
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
config->postfields = postdata;
|
2014-03-23 08:46:54 -04:00
|
|
|
config->postfieldsize = curlx_uztoso(size);
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
We can't set the request type here, as this data might be used in
|
|
|
|
a simple GET if -G is used. Already or soon.
|
|
|
|
|
2011-10-05 10:41:04 -04:00
|
|
|
if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq)) {
|
|
|
|
Curl_safefree(postdata);
|
|
|
|
return PARAM_BAD_USE;
|
|
|
|
}
|
2011-10-04 18:03:20 -04:00
|
|
|
*/
|
|
|
|
break;
|
|
|
|
case 'D':
|
|
|
|
/* dump-header to given file name */
|
|
|
|
GetStr(&config->headerfile, nextarg);
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
{
|
|
|
|
char *ptr = strstr(nextarg, ";auto");
|
|
|
|
if(ptr) {
|
|
|
|
/* Automatic referer requested, this may be combined with a
|
|
|
|
set initial one */
|
|
|
|
config->autoreferer = TRUE;
|
|
|
|
*ptr = 0; /* zero terminate here */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
config->autoreferer = FALSE;
|
|
|
|
GetStr(&config->referer, nextarg);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'E':
|
|
|
|
switch(subletter) {
|
2016-11-16 12:49:15 -05:00
|
|
|
case '\0': /* certificate file */
|
|
|
|
GetFileAndPassword(nextarg, &config->cert, &config->key_passwd);
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'a': /* CA info PEM file */
|
|
|
|
GetStr(&config->cacert, nextarg);
|
|
|
|
break;
|
|
|
|
case 'b': /* cert file type */
|
|
|
|
GetStr(&config->cert_type, nextarg);
|
|
|
|
break;
|
|
|
|
case 'c': /* private key file */
|
|
|
|
GetStr(&config->key, nextarg);
|
|
|
|
break;
|
|
|
|
case 'd': /* private key file type */
|
|
|
|
GetStr(&config->key_type, nextarg);
|
|
|
|
break;
|
|
|
|
case 'e': /* private key passphrase */
|
|
|
|
GetStr(&config->key_passwd, nextarg);
|
|
|
|
cleanarg(nextarg);
|
|
|
|
break;
|
|
|
|
case 'f': /* crypto engine */
|
|
|
|
GetStr(&config->engine, nextarg);
|
2016-10-31 16:49:38 -04:00
|
|
|
if(config->engine && curl_strequal(config->engine, "list"))
|
2014-02-22 15:58:43 -05:00
|
|
|
return PARAM_ENGINES_REQUESTED;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
2018-11-03 12:24:31 -04:00
|
|
|
case 'g': /* CA cert directory */
|
2011-10-04 18:03:20 -04:00
|
|
|
GetStr(&config->capath, nextarg);
|
|
|
|
break;
|
|
|
|
case 'h': /* --pubkey public key file */
|
|
|
|
GetStr(&config->pubkey, nextarg);
|
|
|
|
break;
|
|
|
|
case 'i': /* --hostpubmd5 md5 of the host public key */
|
|
|
|
GetStr(&config->hostpubmd5, nextarg);
|
|
|
|
if(!config->hostpubmd5 || strlen(config->hostpubmd5) != 32)
|
|
|
|
return PARAM_BAD_USE;
|
|
|
|
break;
|
2018-11-03 12:24:31 -04:00
|
|
|
case 'j': /* CRL file */
|
2011-10-04 18:03:20 -04:00
|
|
|
GetStr(&config->crlfile, nextarg);
|
|
|
|
break;
|
|
|
|
case 'k': /* TLS username */
|
|
|
|
if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
|
|
|
|
GetStr(&config->tls_username, nextarg);
|
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
break;
|
|
|
|
case 'l': /* TLS password */
|
|
|
|
if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
|
|
|
|
GetStr(&config->tls_password, nextarg);
|
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
break;
|
|
|
|
case 'm': /* TLS authentication type */
|
|
|
|
if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
|
|
|
|
GetStr(&config->tls_authtype, nextarg);
|
2016-10-31 16:49:38 -04:00
|
|
|
if(!curl_strequal(config->tls_authtype, "SRP"))
|
2011-10-04 18:03:20 -04:00
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
break;
|
2013-12-14 16:39:27 -05:00
|
|
|
case 'n': /* no empty SSL fragments, --ssl-allow-beast */
|
2012-02-06 16:25:04 -05:00
|
|
|
if(curlinfo->features & CURL_VERSION_SSL)
|
|
|
|
config->ssl_allow_beast = toggle;
|
|
|
|
break;
|
2013-12-14 16:39:27 -05:00
|
|
|
|
2014-09-30 22:31:17 -04:00
|
|
|
case 'p': /* Pinned public key DER file */
|
|
|
|
GetStr(&config->pinnedpubkey, nextarg);
|
|
|
|
break;
|
|
|
|
|
2018-01-28 08:15:56 -05:00
|
|
|
case 'P': /* proxy pinned public key */
|
|
|
|
GetStr(&config->proxy_pinnedpubkey, nextarg);
|
|
|
|
break;
|
|
|
|
|
2014-06-16 14:47:26 -04:00
|
|
|
case 'q': /* --cert-status */
|
|
|
|
config->verifystatus = TRUE;
|
|
|
|
break;
|
|
|
|
|
2015-02-14 12:17:04 -05:00
|
|
|
case 'r': /* --false-start */
|
|
|
|
config->falsestart = TRUE;
|
|
|
|
break;
|
|
|
|
|
2015-07-17 02:40:16 -04:00
|
|
|
case 's': /* --ssl-no-revoke */
|
|
|
|
if(curlinfo->features & CURL_VERSION_SSL)
|
|
|
|
config->ssl_no_revoke = TRUE;
|
|
|
|
break;
|
|
|
|
|
schannel: add "best effort" revocation check option
- Implement new option CURLSSLOPT_REVOKE_BEST_EFFORT and
--ssl-revoke-best-effort to allow a "best effort" revocation check.
A best effort revocation check ignores errors that the revocation check
was unable to take place. The reasoning is described in detail below and
discussed further in the PR.
---
When running e.g. with Fiddler, the schannel backend fails with an
unhelpful error message:
Unknown error (0x80092012) - The revocation function was unable
to check revocation for the certificate.
Sadly, many enterprise users who are stuck behind MITM proxies suffer
the very same problem.
This has been discussed in plenty of issues:
https://github.com/curl/curl/issues/3727,
https://github.com/curl/curl/issues/264, for example.
In the latter, a Microsoft Edge developer even made the case that the
common behavior is to ignore issues when a certificate has no recorded
distribution point for revocation lists, or when the server is offline.
This is also known as "best effort" strategy and addresses the Fiddler
issue.
Unfortunately, this strategy was not chosen as the default for schannel
(and is therefore a backend-specific behavior: OpenSSL seems to happily
ignore the offline servers and missing distribution points).
To maintain backward-compatibility, we therefore add a new flag
(`CURLSSLOPT_REVOKE_BEST_EFFORT`) and a new option
(`--ssl-revoke-best-effort`) to select the new behavior.
Due to the many related issues Git for Windows and GitHub Desktop, the
plan is to make this behavior the default in these software packages.
The test 2070 was added to verify this behavior, adapted from 310.
Based-on-work-by: georgeok <giorgos.n.oikonomou@gmail.com>
Co-authored-by: Markus Olsson <j.markus.olsson@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Closes https://github.com/curl/curl/pull/4981
2020-02-26 05:24:26 -05:00
|
|
|
case 'S': /* --ssl-revoke-best-effort */
|
|
|
|
if(curlinfo->features & CURL_VERSION_SSL)
|
|
|
|
config->ssl_revoke_best_effort = TRUE;
|
|
|
|
break;
|
|
|
|
|
2016-02-16 07:21:34 -05:00
|
|
|
case 't': /* --tcp-fastopen */
|
|
|
|
config->tcp_fastopen = TRUE;
|
|
|
|
break;
|
|
|
|
|
2016-11-16 12:49:15 -05:00
|
|
|
case 'u': /* TLS username for proxy */
|
|
|
|
if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
|
|
|
|
GetStr(&config->proxy_tls_username, nextarg);
|
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'v': /* TLS password for proxy */
|
|
|
|
if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP)
|
|
|
|
GetStr(&config->proxy_tls_password, nextarg);
|
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'w': /* TLS authentication type for proxy */
|
|
|
|
if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
|
|
|
|
GetStr(&config->proxy_tls_authtype, nextarg);
|
|
|
|
if(!curl_strequal(config->proxy_tls_authtype, "SRP"))
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT; /* only support TLS-SRP */
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
2016-11-16 12:49:15 -05:00
|
|
|
else
|
|
|
|
return PARAM_LIBCURL_DOESNT_SUPPORT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'x': /* certificate file for proxy */
|
|
|
|
GetFileAndPassword(nextarg, &config->proxy_cert,
|
|
|
|
&config->proxy_key_passwd);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'y': /* cert file type for proxy */
|
|
|
|
GetStr(&config->proxy_cert_type, nextarg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'z': /* private key file for proxy */
|
|
|
|
GetStr(&config->proxy_key, nextarg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '0': /* private key file type for proxy */
|
|
|
|
GetStr(&config->proxy_key_type, nextarg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '1': /* private key passphrase for proxy */
|
|
|
|
GetStr(&config->proxy_key_passwd, nextarg);
|
2011-10-04 18:03:20 -04:00
|
|
|
cleanarg(nextarg);
|
2016-11-16 12:49:15 -05:00
|
|
|
break;
|
|
|
|
|
|
|
|
case '2': /* ciphers for proxy */
|
|
|
|
GetStr(&config->proxy_cipher_list, nextarg);
|
|
|
|
break;
|
|
|
|
|
2018-11-03 12:24:31 -04:00
|
|
|
case '3': /* CRL file for proxy */
|
2016-11-16 12:49:15 -05:00
|
|
|
GetStr(&config->proxy_crlfile, nextarg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '4': /* no empty SSL fragments for proxy */
|
|
|
|
if(curlinfo->features & CURL_VERSION_SSL)
|
|
|
|
config->proxy_ssl_allow_beast = toggle;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '5': /* --login-options */
|
|
|
|
GetStr(&config->login_options, nextarg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '6': /* CA info PEM file for proxy */
|
|
|
|
GetStr(&config->proxy_cacert, nextarg);
|
|
|
|
break;
|
|
|
|
|
2018-11-03 12:24:31 -04:00
|
|
|
case '7': /* CA cert directory for proxy */
|
2016-11-16 12:49:15 -05:00
|
|
|
GetStr(&config->proxy_capath, nextarg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '8': /* allow insecure SSL connects for proxy */
|
|
|
|
config->proxy_insecure_ok = toggle;
|
|
|
|
break;
|
|
|
|
|
2017-06-16 05:30:36 -04:00
|
|
|
case '9': /* --proxy-tlsv1 */
|
2016-11-16 12:49:15 -05:00
|
|
|
/* TLS version 1 for proxy */
|
|
|
|
config->proxy_ssl_version = CURL_SSLVERSION_TLSv1;
|
|
|
|
break;
|
|
|
|
|
2017-05-19 12:11:47 -04:00
|
|
|
case 'A':
|
|
|
|
/* --socks5-basic */
|
|
|
|
if(toggle)
|
|
|
|
config->socks5_auth |= CURLAUTH_BASIC;
|
|
|
|
else
|
|
|
|
config->socks5_auth &= ~CURLAUTH_BASIC;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'B':
|
|
|
|
/* --socks5-gssapi */
|
|
|
|
if(toggle)
|
|
|
|
config->socks5_auth |= CURLAUTH_GSSAPI;
|
|
|
|
else
|
|
|
|
config->socks5_auth &= ~CURLAUTH_GSSAPI;
|
|
|
|
break;
|
|
|
|
|
2019-10-30 04:43:14 -04:00
|
|
|
case 'C':
|
|
|
|
GetStr(&config->etag_save_file, nextarg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'D':
|
|
|
|
GetStr(&config->etag_compare_file, nextarg);
|
|
|
|
break;
|
|
|
|
|
2016-11-16 12:49:15 -05:00
|
|
|
default: /* unknown flag */
|
|
|
|
return PARAM_OPTION_UNKNOWN;
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'f':
|
2016-11-12 08:19:29 -05:00
|
|
|
switch(subletter) {
|
|
|
|
case 'a': /* --fail-early */
|
|
|
|
global->fail_early = toggle;
|
|
|
|
break;
|
2018-05-17 08:09:17 -04:00
|
|
|
case 'b': /* --styled-output */
|
|
|
|
global->styled_output = toggle;
|
|
|
|
break;
|
2020-01-14 17:22:38 -05:00
|
|
|
case 'c': /* --mail-rcpt-allowfails */
|
|
|
|
config->mail_rcpt_allowfails = toggle;
|
|
|
|
break;
|
2018-05-17 08:09:17 -04:00
|
|
|
default: /* --fail (hard on errors) */
|
2016-11-12 08:19:29 -05:00
|
|
|
config->failonerror = toggle;
|
|
|
|
}
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'F':
|
|
|
|
/* "form data" simulation, this is a little advanced so lets do our best
|
|
|
|
to sort this out slowly and carefully */
|
|
|
|
if(formparse(config,
|
|
|
|
nextarg,
|
2019-02-19 11:08:58 -05:00
|
|
|
&config->mimeroot,
|
2017-09-02 13:17:33 -04:00
|
|
|
&config->mimecurrent,
|
2017-09-09 17:09:06 -04:00
|
|
|
(subletter == 's')?TRUE:FALSE)) /* 's' is literal string */
|
2011-10-04 18:03:20 -04:00
|
|
|
return PARAM_BAD_USE;
|
2017-09-02 13:17:33 -04:00
|
|
|
if(SetHTTPrequest(config, HTTPREQ_MIMEPOST, &config->httpreq))
|
2011-10-04 18:03:20 -04:00
|
|
|
return PARAM_BAD_USE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'g': /* g disables URLglobbing */
|
|
|
|
config->globoff = toggle;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'G': /* HTTP GET */
|
2017-06-21 17:35:08 -04:00
|
|
|
if(subletter == 'a') { /* --request-target */
|
|
|
|
GetStr(&config->request_target, nextarg);
|
2017-06-19 08:10:33 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
config->use_httpget = TRUE;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'h': /* h for help */
|
|
|
|
if(toggle) {
|
|
|
|
return PARAM_HELP_REQUESTED;
|
|
|
|
}
|
|
|
|
/* we now actually support --no-help too! */
|
|
|
|
break;
|
|
|
|
case 'H':
|
|
|
|
/* A custom header to append to a list */
|
2017-06-15 05:08:31 -04:00
|
|
|
if(nextarg[0] == '@') {
|
|
|
|
/* read many headers from a file or stdin */
|
|
|
|
char *string;
|
|
|
|
size_t len;
|
|
|
|
bool use_stdin = !strcmp(&nextarg[1], "-");
|
|
|
|
FILE *file = use_stdin?stdin:fopen(&nextarg[1], FOPEN_READTEXT);
|
|
|
|
if(!file)
|
|
|
|
warnf(global, "Failed to open %s!\n", &nextarg[1]);
|
|
|
|
else {
|
2017-07-09 12:04:42 -04:00
|
|
|
err = file2memory(&string, &len, file);
|
2018-07-26 17:22:49 -04:00
|
|
|
if(!err && string) {
|
2017-06-15 05:08:31 -04:00
|
|
|
/* Allow strtok() here since this isn't used threaded */
|
|
|
|
/* !checksrc! disable BANNEDFUNC 2 */
|
|
|
|
char *h = strtok(string, "\r\n");
|
|
|
|
while(h) {
|
|
|
|
if(subletter == 'p') /* --proxy-header */
|
|
|
|
err = add2list(&config->proxyheaders, h);
|
|
|
|
else
|
|
|
|
err = add2list(&config->headers, h);
|
|
|
|
if(err)
|
2017-06-26 01:03:12 -04:00
|
|
|
break;
|
2017-06-15 05:08:31 -04:00
|
|
|
h = strtok(NULL, "\r\n");
|
|
|
|
}
|
|
|
|
free(string);
|
|
|
|
}
|
|
|
|
if(!use_stdin)
|
|
|
|
fclose(file);
|
2017-06-26 01:03:12 -04:00
|
|
|
if(err)
|
|
|
|
return err;
|
2017-06-15 05:08:31 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(subletter == 'p') /* --proxy-header */
|
|
|
|
err = add2list(&config->proxyheaders, nextarg);
|
|
|
|
else
|
|
|
|
err = add2list(&config->headers, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
}
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'i':
|
2018-05-17 07:56:35 -04:00
|
|
|
config->show_headers = toggle; /* show the headers as well in the
|
|
|
|
general output stream */
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'j':
|
|
|
|
config->cookiesession = toggle;
|
|
|
|
break;
|
2018-05-17 07:56:35 -04:00
|
|
|
case 'I': /* --head */
|
2011-10-04 18:03:20 -04:00
|
|
|
config->no_body = toggle;
|
2018-05-17 07:56:35 -04:00
|
|
|
config->show_headers = toggle;
|
2011-10-04 18:03:20 -04:00
|
|
|
if(SetHTTPrequest(config,
|
|
|
|
(config->no_body)?HTTPREQ_HEAD:HTTPREQ_GET,
|
|
|
|
&config->httpreq))
|
|
|
|
return PARAM_BAD_USE;
|
|
|
|
break;
|
|
|
|
case 'J': /* --remote-header-name */
|
2018-05-17 07:56:35 -04:00
|
|
|
if(config->show_headers) {
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global,
|
2011-10-04 18:03:20 -04:00
|
|
|
"--include and --remote-header-name cannot be combined.\n");
|
|
|
|
return PARAM_BAD_USE;
|
|
|
|
}
|
|
|
|
config->content_disposition = toggle;
|
|
|
|
break;
|
|
|
|
case 'k': /* allow insecure SSL connects */
|
|
|
|
config->insecure_ok = toggle;
|
|
|
|
break;
|
|
|
|
case 'K': /* parse config file */
|
2014-02-23 11:04:39 -05:00
|
|
|
if(parseconfig(nextarg, global))
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global, "error trying read config from the '%s' file\n",
|
2011-10-04 18:03:20 -04:00
|
|
|
nextarg);
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
config->dirlistonly = toggle; /* only list the names of the FTP dir */
|
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
config->followlocation = toggle; /* Follow Location: HTTP headers */
|
2016-12-13 17:34:59 -05:00
|
|
|
switch(subletter) {
|
2011-10-04 18:03:20 -04:00
|
|
|
case 't':
|
|
|
|
/* Continue to send authentication (user+password) when following
|
|
|
|
* locations, even when hostname changed */
|
|
|
|
config->unrestricted_auth = toggle;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
/* specified max time */
|
2017-08-06 14:10:40 -04:00
|
|
|
err = str2udouble(&config->timeout, nextarg, LONG_MAX/1000);
|
2012-11-26 10:23:02 -05:00
|
|
|
if(err)
|
|
|
|
return err;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'M': /* M for manual, huge help */
|
|
|
|
if(toggle) { /* --no-manual shows no manual... */
|
|
|
|
#ifdef USE_MANUAL
|
2014-02-23 05:37:44 -05:00
|
|
|
return PARAM_MANUAL_REQUESTED;
|
2011-10-04 18:03:20 -04:00
|
|
|
#else
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global,
|
2011-10-04 18:03:20 -04:00
|
|
|
"built-in manual was disabled at build-time!\n");
|
|
|
|
return PARAM_OPTION_UNKNOWN;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
switch(subletter) {
|
2018-11-03 12:24:31 -04:00
|
|
|
case 'o': /* use .netrc or URL */
|
2011-10-04 18:03:20 -04:00
|
|
|
config->netrc_opt = toggle;
|
|
|
|
break;
|
|
|
|
case 'e': /* netrc-file */
|
|
|
|
GetStr(&config->netrc_file, nextarg);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* pick info from .netrc, if this is used for http, curl will
|
|
|
|
automatically enfore user+password with the request */
|
|
|
|
config->netrc = toggle;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'N':
|
|
|
|
/* disable the output I/O buffering. note that the option is called
|
|
|
|
--buffer but is mostly used in the negative form: --no-buffer */
|
|
|
|
if(longopt)
|
|
|
|
config->nobuffer = (!toggle)?TRUE:FALSE;
|
|
|
|
else
|
|
|
|
config->nobuffer = toggle;
|
|
|
|
break;
|
|
|
|
case 'O': /* --remote-name */
|
|
|
|
if(subletter == 'a') { /* --remote-name-all */
|
|
|
|
config->default_node_flags = toggle?GETOUT_USEREMOTE:0;
|
|
|
|
break;
|
|
|
|
}
|
2018-07-09 12:52:05 -04:00
|
|
|
/* FALLTHROUGH */
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'o': /* --output */
|
|
|
|
/* output file */
|
|
|
|
{
|
|
|
|
struct getout *url;
|
2016-12-13 19:29:44 -05:00
|
|
|
if(!config->url_out)
|
|
|
|
config->url_out = config->url_list;
|
|
|
|
if(config->url_out) {
|
2011-10-04 18:03:20 -04:00
|
|
|
/* there's a node here, if it already is filled-in continue to find
|
|
|
|
an "empty" node */
|
2011-10-05 09:06:26 -04:00
|
|
|
while(config->url_out && (config->url_out->flags & GETOUT_OUTFILE))
|
2011-10-04 18:03:20 -04:00
|
|
|
config->url_out = config->url_out->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now there might or might not be an available node to fill in! */
|
|
|
|
|
|
|
|
if(config->url_out)
|
|
|
|
/* existing node */
|
|
|
|
url = config->url_out;
|
|
|
|
else
|
|
|
|
/* there was no free node, create one! */
|
2017-11-04 07:56:30 -04:00
|
|
|
config->url_out = url = new_getout(config);
|
2011-10-04 18:03:20 -04:00
|
|
|
|
2011-10-05 09:06:26 -04:00
|
|
|
if(!url)
|
|
|
|
return PARAM_NO_MEM;
|
2017-03-10 08:28:37 -05:00
|
|
|
|
|
|
|
/* fill in the outfile */
|
|
|
|
if('o' == letter) {
|
|
|
|
GetStr(&url->outfile, nextarg);
|
|
|
|
url->flags &= ~GETOUT_USEREMOTE; /* switch off */
|
|
|
|
}
|
2011-10-05 09:06:26 -04:00
|
|
|
else {
|
2017-03-10 08:28:37 -05:00
|
|
|
url->outfile = NULL; /* leave it */
|
|
|
|
if(toggle)
|
|
|
|
url->flags |= GETOUT_USEREMOTE; /* switch on */
|
|
|
|
else
|
2011-10-04 18:03:20 -04:00
|
|
|
url->flags &= ~GETOUT_USEREMOTE; /* switch off */
|
|
|
|
}
|
2017-03-10 08:28:37 -05:00
|
|
|
url->flags |= GETOUT_OUTFILE;
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'P':
|
|
|
|
/* This makes the FTP sessions use PORT instead of PASV */
|
|
|
|
/* use <eth0> or <192.168.10.10> style addresses. Anything except
|
|
|
|
this will make us try to get the "default" address.
|
|
|
|
NOTE: this is a changed behaviour since the released 4.1!
|
|
|
|
*/
|
|
|
|
GetStr(&config->ftpport, nextarg);
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
/* proxy tunnel for non-http protocols */
|
|
|
|
config->proxytunnel = toggle;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'q': /* if used first, already taken care of, we do it like
|
|
|
|
this so we don't cause an error! */
|
|
|
|
break;
|
|
|
|
case 'Q':
|
|
|
|
/* QUOTE command to send to FTP server */
|
|
|
|
switch(nextarg[0]) {
|
|
|
|
case '-':
|
|
|
|
/* prefixed with a dash makes it a POST TRANSFER one */
|
|
|
|
nextarg++;
|
|
|
|
err = add2list(&config->postquote, nextarg);
|
|
|
|
break;
|
|
|
|
case '+':
|
|
|
|
/* prefixed with a plus makes it a just-before-transfer one */
|
|
|
|
nextarg++;
|
|
|
|
err = add2list(&config->prequote, nextarg);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
err = add2list(&config->quote, nextarg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
/* Specifying a range WITHOUT A DASH will create an illegal HTTP range
|
|
|
|
(and won't actually be range by definition). The man page previously
|
|
|
|
claimed that to be a good way, why this code is added to work-around
|
|
|
|
it. */
|
|
|
|
if(ISDIGIT(*nextarg) && !strchr(nextarg, '-')) {
|
|
|
|
char buffer[32];
|
|
|
|
curl_off_t off;
|
2017-08-14 17:33:23 -04:00
|
|
|
if(curlx_strtoofft(nextarg, NULL, 10, &off)) {
|
|
|
|
warnf(global, "unsupported range point\n");
|
|
|
|
return PARAM_BAD_USE;
|
|
|
|
}
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global,
|
2011-10-04 18:03:20 -04:00
|
|
|
"A specified range MUST include at least one dash (-). "
|
|
|
|
"Appending one for you!\n");
|
2018-11-22 03:01:24 -05:00
|
|
|
msnprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-", off);
|
2011-10-04 18:03:20 -04:00
|
|
|
Curl_safefree(config->range);
|
|
|
|
config->range = strdup(buffer);
|
2011-10-05 09:06:26 -04:00
|
|
|
if(!config->range)
|
|
|
|
return PARAM_NO_MEM;
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
{
|
|
|
|
/* byte range requested */
|
2019-04-13 17:00:45 -04:00
|
|
|
const char *tmp_range = nextarg;
|
2011-10-04 18:03:20 -04:00
|
|
|
while(*tmp_range != '\0') {
|
|
|
|
if(!ISDIGIT(*tmp_range) && *tmp_range != '-' && *tmp_range != ',') {
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global, "Invalid character is found in given range. "
|
2011-10-04 18:03:20 -04:00
|
|
|
"A specified range MUST have only digits in "
|
|
|
|
"\'start\'-\'stop\'. The server's response to this "
|
|
|
|
"request is uncertain.\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tmp_range++;
|
|
|
|
}
|
|
|
|
/* byte range requested */
|
|
|
|
GetStr(&config->range, nextarg);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'R':
|
|
|
|
/* use remote file's time */
|
|
|
|
config->remote_time = toggle;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
/* don't show progress meter, don't show errors : */
|
|
|
|
if(toggle)
|
2014-03-01 08:20:20 -05:00
|
|
|
global->mute = global->noprogress = TRUE;
|
2011-10-04 18:03:20 -04:00
|
|
|
else
|
2014-03-01 08:20:20 -05:00
|
|
|
global->mute = global->noprogress = FALSE;
|
2014-02-23 11:37:28 -05:00
|
|
|
if(global->showerror < 0)
|
2011-10-16 17:39:59 -04:00
|
|
|
/* if still on the default value, set showerror to the reverse of
|
|
|
|
toggle. This is to allow -S and -s to be used in an independent
|
|
|
|
order but still have the same effect. */
|
2014-02-23 11:37:28 -05:00
|
|
|
global->showerror = (!toggle)?TRUE:FALSE; /* toggle off */
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'S':
|
|
|
|
/* show errors */
|
2014-02-23 11:37:28 -05:00
|
|
|
global->showerror = toggle?1:0; /* toggle on if used with -s */
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
/* Telnet options */
|
|
|
|
err = add2list(&config->telnet_options, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
break;
|
|
|
|
case 'T':
|
|
|
|
/* we are uploading */
|
|
|
|
{
|
|
|
|
struct getout *url;
|
2017-11-04 07:56:30 -04:00
|
|
|
if(!config->url_ul)
|
|
|
|
config->url_ul = config->url_list;
|
|
|
|
if(config->url_ul) {
|
2011-10-04 18:03:20 -04:00
|
|
|
/* there's a node here, if it already is filled-in continue to find
|
|
|
|
an "empty" node */
|
2017-11-04 07:56:30 -04:00
|
|
|
while(config->url_ul && (config->url_ul->flags & GETOUT_UPLOAD))
|
|
|
|
config->url_ul = config->url_ul->next;
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* now there might or might not be an available node to fill in! */
|
|
|
|
|
2017-11-04 07:56:30 -04:00
|
|
|
if(config->url_ul)
|
2011-10-04 18:03:20 -04:00
|
|
|
/* existing node */
|
2017-11-04 07:56:30 -04:00
|
|
|
url = config->url_ul;
|
2011-10-04 18:03:20 -04:00
|
|
|
else
|
|
|
|
/* there was no free node, create one! */
|
2017-11-04 07:56:30 -04:00
|
|
|
config->url_ul = url = new_getout(config);
|
2011-10-04 18:03:20 -04:00
|
|
|
|
2011-10-05 09:06:26 -04:00
|
|
|
if(!url)
|
|
|
|
return PARAM_NO_MEM;
|
2017-03-10 08:28:37 -05:00
|
|
|
|
|
|
|
url->flags |= GETOUT_UPLOAD; /* mark -T used */
|
|
|
|
if(!*nextarg)
|
|
|
|
url->flags |= GETOUT_NOUPLOAD;
|
2011-10-05 09:06:26 -04:00
|
|
|
else {
|
2017-03-10 08:28:37 -05:00
|
|
|
/* "-" equals stdin, but keep the string around for now */
|
|
|
|
GetStr(&url->infile, nextarg);
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'u':
|
2013-12-14 16:39:27 -05:00
|
|
|
/* user:password */
|
2011-10-04 18:03:20 -04:00
|
|
|
GetStr(&config->userpwd, nextarg);
|
|
|
|
cleanarg(nextarg);
|
|
|
|
break;
|
|
|
|
case 'U':
|
|
|
|
/* Proxy user:password */
|
|
|
|
GetStr(&config->proxyuserpwd, nextarg);
|
|
|
|
cleanarg(nextarg);
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
if(toggle) {
|
|
|
|
/* the '%' thing here will cause the trace get sent to stderr */
|
2014-02-27 15:51:49 -05:00
|
|
|
Curl_safefree(global->trace_dump);
|
|
|
|
global->trace_dump = strdup("%");
|
|
|
|
if(!global->trace_dump)
|
2011-10-05 09:06:26 -04:00
|
|
|
return PARAM_NO_MEM;
|
2014-02-27 15:51:49 -05:00
|
|
|
if(global->tracetype && (global->tracetype != TRACE_PLAIN))
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global,
|
2011-10-04 18:03:20 -04:00
|
|
|
"-v, --verbose overrides an earlier trace/verbose option\n");
|
2014-02-27 15:51:49 -05:00
|
|
|
global->tracetype = TRACE_PLAIN;
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
/* verbose is disabled here */
|
2014-02-27 15:51:49 -05:00
|
|
|
global->tracetype = TRACE_NONE;
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'V':
|
2014-02-23 05:16:36 -05:00
|
|
|
if(toggle) /* --no-version yields no output! */
|
|
|
|
return PARAM_VERSION_INFO_REQUESTED;
|
2014-02-22 12:45:38 -05:00
|
|
|
break;
|
|
|
|
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'w':
|
|
|
|
/* get the output string */
|
|
|
|
if('@' == *nextarg) {
|
|
|
|
/* the data begins with a '@' letter, it means that a file name
|
|
|
|
or - (stdin) follows */
|
|
|
|
FILE *file;
|
|
|
|
const char *fname;
|
|
|
|
nextarg++; /* pass the @ */
|
2016-09-30 11:15:05 -04:00
|
|
|
if(!strcmp("-", nextarg)) {
|
2011-10-04 18:03:20 -04:00
|
|
|
fname = "<stdin>";
|
|
|
|
file = stdin;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fname = nextarg;
|
2015-06-01 03:20:18 -04:00
|
|
|
file = fopen(nextarg, FOPEN_READTEXT);
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
2018-11-30 05:59:04 -05:00
|
|
|
Curl_safefree(config->writeout);
|
2011-10-04 18:03:20 -04:00
|
|
|
err = file2string(&config->writeout, file);
|
|
|
|
if(file && (file != stdin))
|
|
|
|
fclose(file);
|
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
if(!config->writeout)
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global, "Failed to read %s", fname);
|
2011-10-04 18:03:20 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
GetStr(&config->writeout, nextarg);
|
|
|
|
break;
|
|
|
|
case 'x':
|
2016-12-16 10:02:08 -05:00
|
|
|
switch(subletter) {
|
|
|
|
case 'a': /* --preproxy */
|
|
|
|
GetStr(&config->preproxy, nextarg);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* --proxy */
|
|
|
|
GetStr(&config->proxy, nextarg);
|
|
|
|
config->proxyver = CURLPROXY_HTTP;
|
|
|
|
break;
|
|
|
|
}
|
2011-10-04 18:03:20 -04:00
|
|
|
break;
|
|
|
|
case 'X':
|
|
|
|
/* set custom request */
|
|
|
|
GetStr(&config->customrequest, nextarg);
|
|
|
|
break;
|
|
|
|
case 'y':
|
|
|
|
/* low speed time */
|
2012-11-26 10:23:02 -05:00
|
|
|
err = str2unum(&config->low_speed_time, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
2011-10-04 18:03:20 -04:00
|
|
|
if(!config->low_speed_limit)
|
|
|
|
config->low_speed_limit = 1;
|
|
|
|
break;
|
|
|
|
case 'Y':
|
|
|
|
/* low speed limit */
|
2012-11-26 10:23:02 -05:00
|
|
|
err = str2unum(&config->low_speed_limit, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
2011-10-04 18:03:20 -04:00
|
|
|
if(!config->low_speed_time)
|
|
|
|
config->low_speed_time = 30;
|
|
|
|
break;
|
2019-07-20 13:14:00 -04:00
|
|
|
case 'Z':
|
|
|
|
switch(subletter) {
|
|
|
|
case '\0': /* --parallel */
|
|
|
|
global->parallel = toggle;
|
|
|
|
break;
|
|
|
|
case 'b': /* --parallel-max */
|
|
|
|
err = str2unum(&global->parallel_max, nextarg);
|
|
|
|
if(err)
|
|
|
|
return err;
|
|
|
|
if((global->parallel_max > MAX_PARALLEL) ||
|
|
|
|
(global->parallel_max < 1))
|
|
|
|
global->parallel_max = PARALLEL_DEFAULT;
|
|
|
|
break;
|
2019-10-17 04:05:53 -04:00
|
|
|
case 'c': /* --parallel-connect */
|
|
|
|
global->parallel_connect = toggle;
|
|
|
|
break;
|
2019-07-20 13:14:00 -04:00
|
|
|
}
|
|
|
|
break;
|
2011-10-04 18:03:20 -04:00
|
|
|
case 'z': /* time condition coming up */
|
|
|
|
switch(*nextarg) {
|
|
|
|
case '+':
|
|
|
|
nextarg++;
|
2014-10-04 10:12:06 -04:00
|
|
|
/* FALLTHROUGH */
|
2011-10-04 18:03:20 -04:00
|
|
|
default:
|
|
|
|
/* If-Modified-Since: (section 14.28 in RFC2068) */
|
|
|
|
config->timecond = CURL_TIMECOND_IFMODSINCE;
|
|
|
|
break;
|
|
|
|
case '-':
|
|
|
|
/* If-Unmodified-Since: (section 14.24 in RFC2068) */
|
|
|
|
config->timecond = CURL_TIMECOND_IFUNMODSINCE;
|
|
|
|
nextarg++;
|
|
|
|
break;
|
|
|
|
case '=':
|
|
|
|
/* Last-Modified: (section 14.29 in RFC2068) */
|
|
|
|
config->timecond = CURL_TIMECOND_LASTMOD;
|
|
|
|
nextarg++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
now = time(NULL);
|
2018-02-05 15:57:39 -05:00
|
|
|
config->condtime = (curl_off_t)curl_getdate(nextarg, &now);
|
|
|
|
if(-1 == config->condtime) {
|
2011-10-04 18:03:20 -04:00
|
|
|
/* now let's see if it is a file name to get the time from instead! */
|
2018-02-05 15:57:39 -05:00
|
|
|
curl_off_t filetime = getfiletime(nextarg, config->global->errors);
|
|
|
|
if(filetime >= 0) {
|
|
|
|
/* pull the time out from the file */
|
|
|
|
config->condtime = filetime;
|
|
|
|
}
|
|
|
|
else {
|
2011-10-04 18:03:20 -04:00
|
|
|
/* failed, remove time condition */
|
|
|
|
config->timecond = CURL_TIMECOND_NONE;
|
2015-02-27 15:48:38 -05:00
|
|
|
warnf(global,
|
2017-02-14 16:20:51 -05:00
|
|
|
"Illegal date format for -z, --time-cond (and not "
|
2011-10-04 18:03:20 -04:00
|
|
|
"a file name). Disabling time condition. "
|
|
|
|
"See curl_getdate(3) for valid date syntax.\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default: /* unknown flag */
|
|
|
|
return PARAM_OPTION_UNKNOWN;
|
|
|
|
}
|
|
|
|
hit = -1;
|
|
|
|
|
|
|
|
} while(!longopt && !singleopt && *++parse && !*usedarg);
|
|
|
|
|
|
|
|
return PARAM_OK;
|
|
|
|
}
|
2014-02-02 09:58:25 -05:00
|
|
|
|
2019-07-20 13:14:00 -04:00
|
|
|
ParameterError parse_args(struct GlobalConfig *global, int argc,
|
2014-02-02 09:58:25 -05:00
|
|
|
argv_item_t argv[])
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
bool stillflags;
|
2014-08-08 07:03:34 -04:00
|
|
|
char *orig_opt = NULL;
|
2014-02-02 09:58:25 -05:00
|
|
|
ParameterError result = PARAM_OK;
|
2019-07-20 13:14:00 -04:00
|
|
|
struct OperationConfig *config = global->first;
|
2014-02-02 09:58:25 -05:00
|
|
|
|
|
|
|
for(i = 1, stillflags = TRUE; i < argc && !result; i++) {
|
2019-04-12 16:59:40 -04:00
|
|
|
orig_opt = curlx_convert_tchar_to_UTF8(argv[i]);
|
2014-02-02 09:58:25 -05:00
|
|
|
|
2019-04-12 16:59:40 -04:00
|
|
|
if(stillflags && ('-' == orig_opt[0])) {
|
2014-02-02 09:58:25 -05:00
|
|
|
bool passarg;
|
|
|
|
|
2019-04-12 16:59:40 -04:00
|
|
|
if(!strcmp("--", orig_opt))
|
2014-02-02 09:58:25 -05:00
|
|
|
/* This indicates the end of the flags and thus enables the
|
|
|
|
following (URL) argument to start with -. */
|
|
|
|
stillflags = FALSE;
|
|
|
|
else {
|
2019-04-12 16:59:40 -04:00
|
|
|
char *nextarg = (i < (argc - 1))
|
|
|
|
? curlx_convert_tchar_to_UTF8(argv[i + 1])
|
|
|
|
: NULL;
|
2014-02-02 09:58:25 -05:00
|
|
|
|
2019-04-12 16:59:40 -04:00
|
|
|
result = getparameter(orig_opt, nextarg, &passarg, global, config);
|
|
|
|
curlx_unicodefree(nextarg);
|
2020-03-18 19:28:19 -04:00
|
|
|
config = global->last;
|
2014-02-23 12:32:19 -05:00
|
|
|
if(result == PARAM_NEXT_OPERATION) {
|
2014-03-22 12:31:13 -04:00
|
|
|
/* Reset result as PARAM_NEXT_OPERATION is only used here and not
|
|
|
|
returned from this function */
|
|
|
|
result = PARAM_OK;
|
|
|
|
|
2019-07-20 13:14:00 -04:00
|
|
|
if(config->url_list && config->url_list->url) {
|
2014-02-23 12:32:19 -05:00
|
|
|
/* Allocate the next config */
|
2019-07-20 13:14:00 -04:00
|
|
|
config->next = malloc(sizeof(struct OperationConfig));
|
|
|
|
if(config->next) {
|
2014-02-23 12:32:19 -05:00
|
|
|
/* Initialise the newly created config */
|
2019-07-20 13:14:00 -04:00
|
|
|
config_init(config->next);
|
2014-02-23 12:32:19 -05:00
|
|
|
|
2014-02-26 16:02:53 -05:00
|
|
|
/* Set the global config pointer */
|
2019-07-20 13:14:00 -04:00
|
|
|
config->next->global = global;
|
2014-02-26 16:02:53 -05:00
|
|
|
|
2019-07-20 13:14:00 -04:00
|
|
|
/* Update the last config pointer */
|
|
|
|
global->last = config->next;
|
2014-02-23 12:32:19 -05:00
|
|
|
|
|
|
|
/* Move onto the new config */
|
2019-07-20 13:14:00 -04:00
|
|
|
config->next->prev = config;
|
|
|
|
config = config->next;
|
2014-02-23 12:32:19 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
result = PARAM_NO_MEM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(!result && passarg)
|
2014-02-02 09:58:25 -05:00
|
|
|
i++; /* we're supposed to skip this */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bool used;
|
|
|
|
|
|
|
|
/* Just add the URL please */
|
2019-04-12 16:59:40 -04:00
|
|
|
result = getparameter("--url", orig_opt, &used, global,
|
2019-07-20 13:14:00 -04:00
|
|
|
config);
|
2014-02-02 09:58:25 -05:00
|
|
|
}
|
2020-06-09 11:49:44 -04:00
|
|
|
|
2020-06-17 18:51:37 -04:00
|
|
|
if(!result)
|
|
|
|
curlx_unicodefree(orig_opt);
|
2014-02-02 09:58:25 -05:00
|
|
|
}
|
|
|
|
|
2014-02-22 15:58:43 -05:00
|
|
|
if(result && result != PARAM_HELP_REQUESTED &&
|
2014-02-23 05:37:44 -05:00
|
|
|
result != PARAM_MANUAL_REQUESTED &&
|
2014-02-23 05:16:36 -05:00
|
|
|
result != PARAM_VERSION_INFO_REQUESTED &&
|
2014-02-22 15:58:43 -05:00
|
|
|
result != PARAM_ENGINES_REQUESTED) {
|
2014-02-02 09:58:25 -05:00
|
|
|
const char *reason = param2text(result);
|
2014-02-07 16:14:43 -05:00
|
|
|
|
2016-09-30 11:15:05 -04:00
|
|
|
if(orig_opt && strcmp(":", orig_opt))
|
2019-07-20 13:14:00 -04:00
|
|
|
helpf(global->errors, "option %s: %s\n", orig_opt, reason);
|
2014-02-07 16:14:43 -05:00
|
|
|
else
|
2019-07-20 13:14:00 -04:00
|
|
|
helpf(global->errors, "%s\n", reason);
|
2014-02-02 09:58:25 -05:00
|
|
|
}
|
|
|
|
|
2019-04-12 16:59:40 -04:00
|
|
|
curlx_unicodefree(orig_opt);
|
2014-02-02 09:58:25 -05:00
|
|
|
return result;
|
|
|
|
}
|