* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
# include <locale.h>
#endif
-#ifdef HAVE_NETINET_TCP_H
-# include <netinet/tcp.h>
-#endif
-
#ifdef __VMS
# include <fabdef.h>
#endif
-#include "rawstr.h"
+#include "strcase.h"
#define ENABLE_CURLX_PRINTF
/* use our own printf() functions */
* and CD/DVD images should be either a STREAM_LF format or a fixed format.
*
*/
-static curl_off_t vms_realfilesize(const char * name,
- const struct_stat * stat_buf)
+static curl_off_t vms_realfilesize(const char *name,
+ const struct_stat *stat_buf)
{
char buffer[8192];
curl_off_t count;
int ret_stat;
FILE * file;
+ /* !checksrc! disable FOPENMODE 1 */
file = fopen(name, "r"); /* VMS */
if(file == NULL) {
return 0;
* if not to call a routine to get the correct size.
*
*/
-static curl_off_t VmsSpecialSize(const char * name,
- const struct_stat * stat_buf)
+static curl_off_t VmsSpecialSize(const char *name,
+ const struct_stat *stat_buf)
{
switch(stat_buf->st_fab_rfm) {
case FAB$C_VAR:
CURLcode result = CURLE_OK;
unsigned long li;
+ bool capath_from_env;
/* Save the values of noprogress and isatty to restore them later on */
bool orig_noprogress = global->noprogress;
* We support the environment variable thing for non-Windows platforms
* too. Just for the sake of it.
*/
+ capath_from_env = false;
if(!config->cacert &&
!config->capath &&
!config->insecure_ok) {
result = CURLE_OUT_OF_MEMORY;
goto quit_curl;
}
+ capath_from_env = true;
}
else {
env = curlx_getenv("SSL_CERT_FILE");
/* Single header file for all URLs */
if(config->headerfile) {
/* open file for output: */
- if(!curlx_strequal(config->headerfile, "-")) {
+ if(strcmp(config->headerfile, "-")) {
FILE *newfile = fopen(config->headerfile, "wb");
if(!newfile) {
warnf(config->global, "Failed to open %s\n", config->headerfile);
urlnum = 1; /* without globbing, this is a single URL */
/* if multiple files extracted to stdout, insert separators! */
- separator= ((!outfiles || curlx_strequal(outfiles, "-")) && urlnum > 1);
+ separator= ((!outfiles || !strcmp(outfiles, "-")) && urlnum > 1);
/* Here's looping around each globbed URL */
for(li = 0 ; li < urlnum; li++) {
}
if(((urlnode->flags&GETOUT_USEREMOTE) ||
- (outfile && !curlx_strequal("-", outfile))) &&
+ (outfile && strcmp("-", outfile))) &&
(metalink || !config->use_metalink)) {
/*
infd = -1;
if(stat(uploadfile, &fileinfo) == 0) {
fileinfo.st_size = VmsSpecialSize(uploadfile, &fileinfo);
- switch (fileinfo.st_fab_rfm) {
+ switch(fileinfo.st_fab_rfm) {
case FAB$C_VAR:
case FAB$C_VFC:
case FAB$C_STMCR:
DEBUGASSERT(infd == STDIN_FILENO);
set_binmode(stdin);
- if(curlx_strequal(uploadfile, ".")) {
+ if(!strcmp(uploadfile, ".")) {
if(curlx_nonblock((curl_socket_t)infd, TRUE) < 0)
warnf(config->global,
"fcntl failed on fd=%d: %s\n", infd, strerror(errno));
set_binmode(stdout);
}
- if(config->tcp_nodelay)
- my_setopt(curl, CURLOPT_TCP_NODELAY, 1L);
+ if(!config->tcp_nodelay)
+ my_setopt(curl, CURLOPT_TCP_NODELAY, 0L);
+
+ if(config->tcp_fastopen)
+ my_setopt(curl, CURLOPT_TCP_FASTOPEN, 1L);
/* where to store */
my_setopt(curl, CURLOPT_WRITEDATA, &outs);
+ my_setopt(curl, CURLOPT_INTERLEAVEDATA, &outs);
if(metalink || !config->use_metalink)
/* what call to write */
my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
/* TODO: Make this a run-time check instead of compile-time one. */
my_setopt_str(curl, CURLOPT_PROXY, config->proxy);
+ /* new in libcurl 7.5 */
+ if(config->proxy)
+ my_setopt_enum(curl, CURLOPT_PROXYTYPE, config->proxyver);
+
my_setopt_str(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
/* new in libcurl 7.3 */
my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel?1L:0L);
- /* new in libcurl 7.5 */
- if(config->proxy)
- my_setopt_enum(curl, CURLOPT_PROXYTYPE, (long)config->proxyver);
-
- /* new in libcurl 7.10 */
- if(config->socksproxy) {
- my_setopt_str(curl, CURLOPT_PROXY, config->socksproxy);
- my_setopt_enum(curl, CURLOPT_PROXYTYPE, (long)config->socksver);
- }
+ /* new in libcurl 7.52.0 */
+ if(config->preproxy)
+ my_setopt_str(curl, CURLOPT_PRE_PROXY, config->preproxy);
/* new in libcurl 7.10.6 */
if(config->proxyanyauth)
my_setopt(curl, CURLOPT_RESUME_FROM_LARGE, CURL_OFF_T_C(0));
my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
+ my_setopt_str(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd);
if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
if(config->cacert)
my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
- if(config->capath)
- my_setopt_str(curl, CURLOPT_CAPATH, config->capath);
+ if(config->proxy_cacert)
+ my_setopt_str(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert);
+
+ if(config->capath) {
+ result = res_setopt_str(curl, CURLOPT_CAPATH, config->capath);
+ if(result == CURLE_NOT_BUILT_IN) {
+ warnf(config->global, "ignoring %s, not supported by libcurl\n",
+ capath_from_env?
+ "SSL_CERT_DIR environment variable":"--capath");
+ }
+ else if(result)
+ goto show_error;
+ }
+ /* For the time being if --proxy-capath is not set then we use the
+ --capath value for it, if any. See #1257 */
+ if(config->proxy_capath || config->capath) {
+ result = res_setopt_str(curl, CURLOPT_PROXY_CAPATH,
+ (config->proxy_capath ?
+ config->proxy_capath :
+ config->capath));
+ if(result == CURLE_NOT_BUILT_IN) {
+ if(config->proxy_capath) {
+ warnf(config->global,
+ "ignoring --proxy-capath, not supported by libcurl\n");
+ }
+ }
+ else if(result)
+ goto show_error;
+ }
+
if(config->crlfile)
my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile);
+ if(config->proxy_crlfile)
+ my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->proxy_crlfile);
+ else if(config->crlfile) /* CURLOPT_PROXY_CRLFILE default is crlfile */
+ my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->crlfile);
if(config->pinnedpubkey)
my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY, config->pinnedpubkey);
if(curlinfo->features & CURL_VERSION_SSL) {
my_setopt_str(curl, CURLOPT_SSLCERT, config->cert);
+ my_setopt_str(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert);
my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
+ my_setopt_str(curl, CURLOPT_PROXY_SSLCERTTYPE,
+ config->proxy_cert_type);
my_setopt_str(curl, CURLOPT_SSLKEY, config->key);
+ my_setopt_str(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key);
my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
+ my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE,
+ config->proxy_key_type);
if(config->insecure_ok) {
my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
/* libcurl default is strict verifyhost -> 2L */
/* my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); */
}
+ if(config->proxy_insecure_ok) {
+ my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L);
+ my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
+ }
+ else {
+ my_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
+ }
if(config->verifystatus)
my_setopt(curl, CURLOPT_SSL_VERIFYSTATUS, 1L);
my_setopt(curl, CURLOPT_SSL_FALSESTART, 1L);
my_setopt_enum(curl, CURLOPT_SSLVERSION, config->ssl_version);
+ my_setopt_enum(curl, CURLOPT_PROXY_SSLVERSION,
+ config->proxy_ssl_version);
}
if(config->path_as_is)
my_setopt(curl, CURLOPT_PATH_AS_IS, 1L);
if(config->cipher_list)
my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list);
+ if(config->proxy_cipher_list)
+ my_setopt_str(curl, CURLOPT_PROXY_SSL_CIPHER_LIST,
+ config->proxy_cipher_list);
+
/* new in libcurl 7.9.2: */
if(config->disable_epsv)
/* disable it */
result = res_setopt_str(curl, CURLOPT_SSLENGINE, config->engine);
if(result)
goto show_error;
- my_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L);
}
- /* new in curl 7.10.7, extended in 7.19.4 but this only sets 0 or 1 */
+ /* new in curl 7.10.7, extended in 7.19.4. Modified to use
+ CREATE_DIR_RETRY in 7.49.0 */
my_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
- config->ftp_create_dirs?1L:0L);
+ (long)(config->ftp_create_dirs?
+ CURLFTP_CREATE_DIR_RETRY:
+ CURLFTP_CREATE_DIR_NONE));
/* new in curl 7.10.8 */
if(config->max_filesize)
(long)config->ftp_ssl_ccc_mode);
/* new in curl 7.19.4 */
- if(config->socks5_gssapi_service)
- my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_SERVICE,
- config->socks5_gssapi_service);
-
- /* new in curl 7.19.4 */
if(config->socks5_gssapi_nec)
my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC,
config->socks5_gssapi_nec);
my_setopt_flags(curl, CURLOPT_REDIR_PROTOCOLS, config->proto_redir);
if(config->content_disposition
- && (urlnode->flags & GETOUT_USEREMOTE)
- && (checkprefix("http://", this_url) ||
- checkprefix("https://", this_url)))
+ && (urlnode->flags & GETOUT_USEREMOTE))
hdrcbdata.honor_cd_filename = TRUE;
else
hdrcbdata.honor_cd_filename = FALSE;
/* new in 7.21.3 */
my_setopt_slist(curl, CURLOPT_RESOLVE, config->resolve);
+ if(config->connect_to)
+ /* new in 7.49.0 */
+ my_setopt_slist(curl, CURLOPT_CONNECT_TO, config->connect_to);
+
/* new in 7.21.4 */
if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
if(config->tls_username)
if(config->tls_authtype)
my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE,
config->tls_authtype);
+ if(config->proxy_tls_username)
+ my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_USERNAME,
+ config->proxy_tls_username);
+ if(config->proxy_tls_password)
+ my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD,
+ config->proxy_tls_password);
+ if(config->proxy_tls_authtype)
+ my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_TYPE,
+ config->proxy_tls_authtype);
}
/* new in 7.22.0 */
my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask);
}
+ if(config->proxy_ssl_allow_beast)
+ my_setopt(curl, CURLOPT_PROXY_SSL_OPTIONS,
+ (long)CURLSSLOPT_ALLOW_BEAST);
+
if(config->mail_auth)
my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
my_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L);
}
- /* new in 7.40.0 */
- if(config->unix_socket_path)
- my_setopt_str(curl, CURLOPT_UNIX_SOCKET_PATH,
- config->unix_socket_path);
-
+ /* new in 7.40.0, abstract support added in 7.53.0 */
+ if(config->unix_socket_path) {
+ if(config->abstract_unix_socket) {
+ my_setopt_str(curl, CURLOPT_ABSTRACT_UNIX_SOCKET,
+ config->unix_socket_path);
+ }
+ else {
+ my_setopt_str(curl, CURLOPT_UNIX_SOCKET_PATH,
+ config->unix_socket_path);
+ }
+ }
/* new in 7.45.0 */
if(config->proto_default)
my_setopt_str(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default);
enum {
RETRY_NO,
RETRY_TIMEOUT,
+ RETRY_CONNREFUSED,
RETRY_HTTP,
RETRY_FTP,
RETRY_LAST /* not used */
(CURLE_FTP_ACCEPT_TIMEOUT == result))
/* retry timeout always */
retry = RETRY_TIMEOUT;
+ else if(config->retry_connrefused &&
+ (CURLE_COULDNT_CONNECT == result)) {
+ long oserrno;
+ curl_easy_getinfo(curl, CURLINFO_OS_ERRNO, &oserrno);
+ if(ECONNREFUSED == oserrno)
+ retry = RETRY_CONNREFUSED;
+ }
else if((CURLE_OK == result) ||
(config->failonerror &&
(CURLE_HTTP_RETURNED_ERROR == result))) {
if(retry) {
static const char * const m[]={
- NULL, "timeout", "HTTP error", "FTP error"
+ NULL,
+ "timeout",
+ "connection refused",
+ "HTTP error",
+ "FTP error"
};
warnf(config->global, "Transient problem: %s "
fflush(outs.stream);
/* truncate file at the position where we started appending */
#ifdef HAVE_FTRUNCATE
- if(ftruncate( fileno(outs.stream), outs.init)) {
+ if(ftruncate(fileno(outs.stream), outs.init)) {
/* when truncate fails, we can't just append as then we'll
create something strange, bail out */
if(!global->mute)
char *effective_url = NULL;
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url);
if(effective_url &&
- curlx_strnequal(effective_url, "http", 4)) {
+ curl_strnequal(effective_url, "http", 4)) {
/* This was HTTP(S) */
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
if(response != 200 && response != 206) {
metalink_next_res = 1;
fprintf(global->errors,
"Metalink: fetching (%s) from (%s) FAILED "
- "(HTTP status code %d)\n",
+ "(HTTP status code %ld)\n",
mlfile->filename, this_url, response);
}
}
fprintf(global->errors, "curl: (%d) %s\n", result, (errorbuffer[0]) ?
errorbuffer : curl_easy_strerror(result));
if(result == CURLE_SSL_CACERT)
- fprintf(global->errors, "%s%s",
- CURL_CA_CERT_ERRORMSG1, CURL_CA_CERT_ERRORMSG2);
+ fprintf(global->errors, "%s%s%s",
+ CURL_CA_CERT_ERRORMSG1, CURL_CA_CERT_ERRORMSG2,
+ ((config->proxy &&
+ curl_strnequal(config->proxy, "https://", 8)) ?
+ "HTTPS proxy has similar options --proxy-cacert "
+ "and --proxy-insecure.\n" :
+ ""));
}
/* Fall through comment to 'quit_urls' label */
}
#endif
-#ifdef HAVE_UTIME
+#if defined(HAVE_UTIME) || \
+ (defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8))
/* File time can only be set _after_ the file has been closed */
if(!result && config->remote_time && outs.s_isreg && outs.filename) {
/* Ask libcurl if we got a remote file time */
long filetime = -1;
curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
if(filetime >= 0) {
+/* Windows utime() may attempt to adjust our unix gmt 'filetime' by a daylight
+ saving time offset and since it's GMT that is bad behavior. When we have
+ access to a 64-bit type we can bypass utime and set the times directly. */
+#if defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8)
+ /* 910670515199 is the maximum unix filetime that can be used as a
+ Windows FILETIME without overflow: 30827-12-31T23:59:59. */
+ if(filetime <= CURL_OFF_T_C(910670515199)) {
+ HANDLE hfile = CreateFileA(outs.filename, FILE_WRITE_ATTRIBUTES,
+ (FILE_SHARE_READ | FILE_SHARE_WRITE |
+ FILE_SHARE_DELETE),
+ NULL, OPEN_EXISTING, 0, NULL);
+ if(hfile != INVALID_HANDLE_VALUE) {
+ curl_off_t converted = ((curl_off_t)filetime * 10000000) +
+ CURL_OFF_T_C(116444736000000000);
+ FILETIME ft;
+ ft.dwLowDateTime = (DWORD)(converted & 0xFFFFFFFF);
+ ft.dwHighDateTime = (DWORD)(converted >> 32);
+ if(!SetFileTime(hfile, NULL, &ft, &ft)) {
+ fprintf(config->global->errors,
+ "Failed to set filetime %ld on outfile: "
+ "SetFileTime failed: GetLastError %u\n",
+ filetime, GetLastError());
+ }
+ CloseHandle(hfile);
+ }
+ else {
+ fprintf(config->global->errors,
+ "Failed to set filetime %ld on outfile: "
+ "CreateFile failed: GetLastError %u\n",
+ filetime, GetLastError());
+ }
+ }
+ else {
+ fprintf(config->global->errors,
+ "Failed to set filetime %ld on outfile: overflow\n",
+ filetime);
+ }
+#elif defined(HAVE_UTIME)
struct utimbuf times;
times.actime = (time_t)filetime;
times.modtime = (time_t)filetime;
- utime(outs.filename, ×); /* set the time we got */
+ if(utime(outs.filename, ×)) {
+ fprintf(config->global->errors,
+ "Failed to set filetime %ld on outfile: errno %d\n",
+ filetime, errno);
+ }
+#endif
}
}
-#endif
+#endif /* defined(HAVE_UTIME) || \
+ (defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8)) */
#ifdef USE_METALINK
if(!metalink && config->use_metalink && result == CURLE_OK) {
urlnode->flags = 0;
/*
- ** Bail out upon critical errors
+ ** Bail out upon critical errors or --fail-early
*/
- if(is_fatal_error(result))
+ if(is_fatal_error(result) || (result && global->fail_early))
goto quit_curl;
} /* for-loop through all URLs */
#endif
/* Parse .curlrc if necessary */
- if((argc == 1) || (!curlx_strequal(argv[1], "-q"))) {
+ if((argc == 1) ||
+ (!curl_strequal(argv[1], "-q") &&
+ !curl_strequal(argv[1], "--disable"))) {
parseconfig(NULL, config); /* ignore possible failure */
/* If we had no arguments then make sure a url was specified in .curlrc */
result = operate_do(config, config->current);
config->current = config->current->next;
+
+ if(config->current && config->current->easy)
+ curl_easy_reset(config->current->easy);
}
#ifndef CURL_DISABLE_LIBCURL_OPTION