Merge branch 'master' into nuget-fixes

This commit is contained in:
Tom van Dijck 2017-04-24 12:59:41 -07:00 committed by GitHub
commit 88d37b17c6
224 changed files with 9009 additions and 6426 deletions

View File

@ -45,6 +45,9 @@ none:
@echo " osx linux"
mingw: $(SRC)
$(SILENT) rm -rf ./bin
$(SILENT) rm -rf ./build
$(SILENT) rm -rf ./obj
mkdir -p build/bootstrap
$(CC) -o build/bootstrap/premake_bootstrap -DPREMAKE_NO_BUILTIN_SCRIPTS -I"$(LUA_DIR)" $? -lole32
./build/bootstrap/premake_bootstrap embed
@ -52,6 +55,9 @@ mingw: $(SRC)
$(MAKE) -C build/bootstrap
osx: $(SRC)
$(SILENT) rm -rf ./bin
$(SILENT) rm -rf ./build
$(SILENT) rm -rf ./obj
mkdir -p build/bootstrap
$(CC) -o build/bootstrap/premake_bootstrap -DPREMAKE_NO_BUILTIN_SCRIPTS -DLUA_USE_MACOSX -I"$(LUA_DIR)" -framework CoreServices -framework Foundation -framework Security $?
./build/bootstrap/premake_bootstrap embed
@ -59,13 +65,29 @@ osx: $(SRC)
$(MAKE) -C build/bootstrap -j`getconf _NPROCESSORS_ONLN`
linux: $(SRC)
$(SILENT) rm -rf ./bin
$(SILENT) rm -rf ./build
$(SILENT) rm -rf ./obj
mkdir -p build/bootstrap
$(CC) -o build/bootstrap/premake_bootstrap -DPREMAKE_NO_BUILTIN_SCRIPTS -DLUA_USE_POSIX -DLUA_USE_DLOPEN -I"$(LUA_DIR)" $? -lm -ldl -lrt
./build/bootstrap/premake_bootstrap embed
./build/bootstrap/premake_bootstrap --to=build/bootstrap gmake
$(MAKE) -C build/bootstrap -j`getconf _NPROCESSORS_ONLN`
bsd: $(SRC)
$(SILENT) rm -rf ./bin
$(SILENT) rm -rf ./build
$(SILENT) rm -rf ./obj
mkdir -p build/bootstrap
$(CC) -o build/bootstrap/premake_bootstrap -DPREMAKE_NO_BUILTIN_SCRIPTS -DLUA_USE_POSIX -DLUA_USE_DLOPEN -I"$(LUA_DIR)" $? -lm
./build/bootstrap/premake_bootstrap embed
./build/bootstrap/premake_bootstrap --to=build/bootstrap gmake
$(MAKE) -C build/bootstrap -j`getconf _NPROCESSORS_ONLN`
windows-base: $(SRC)
$(SILENT) if exist .\bin rmdir /s /q .\bin
$(SILENT) if exist .\build rmdir /s /q .\build
$(SILENT) if exist .\obj rmdir /s /q .\obj
if not exist build\bootstrap (mkdir build\bootstrap)
cl /Fo.\build\bootstrap\ /Fe.\build\bootstrap\premake_bootstrap.exe /DPREMAKE_NO_BUILTIN_SCRIPTS /I"$(LUA_DIR)" user32.lib ole32.lib advapi32.lib $**
.\build\bootstrap\premake_bootstrap.exe embed

View File

@ -37,7 +37,7 @@ The following notes apply to libcurl version 7.19.0 and later.
also distribute along with it the generated curl/curlbuild.h which has been
used to compile it. Otherwise the library will be of no use for the users of
the library that you have built. It is _your_ responsibility to provide this
file. No one at the cURL project can know how you have built the library.
file. No one at the curl project can know how you have built the library.
* File curl/curlbuild.h includes platform and configuration dependent info,
and must not be modified by anyone. Configure script generates it for you.

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2016, 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
@ -30,6 +30,10 @@
* https://cool.haxx.se/mailman/listinfo/curl-library/
*/
#ifdef CURL_NO_OLDIES
#define CURL_STRICTER
#endif
#include "curlver.h" /* libcurl version defines */
#include "curlbuild.h" /* libcurl build definitions */
#include "curlrules.h" /* libcurl rules enforcement */
@ -91,7 +95,13 @@
extern "C" {
#endif
#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
typedef struct Curl_easy CURL;
typedef struct Curl_share CURLSH;
#else
typedef void CURL;
typedef void CURLSH;
#endif
/*
* libcurl external API function linkage decorations.
@ -183,6 +193,11 @@ typedef int (*curl_xferinfo_callback)(void *clientp,
curl_off_t ultotal,
curl_off_t ulnow);
#ifndef CURL_MAX_READ_SIZE
/* The maximum receive buffer size configurable via CURLOPT_BUFFERSIZE. */
#define CURL_MAX_READ_SIZE 524288
#endif
#ifndef CURL_MAX_WRITE_SIZE
/* Tests have proven that 20K is a very bad buffer size for uploads on
Windows, while 16K for some odd reason performed a lot better.
@ -425,7 +440,7 @@ typedef enum {
CURLE_COULDNT_RESOLVE_PROXY, /* 5 */
CURLE_COULDNT_RESOLVE_HOST, /* 6 */
CURLE_COULDNT_CONNECT, /* 7 */
CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */
CURLE_WEIRD_SERVER_REPLY, /* 8 */
CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server
due to lack of access - when login fails
this is not returned. */
@ -469,7 +484,7 @@ typedef enum {
CURLE_LDAP_CANNOT_BIND, /* 38 */
CURLE_LDAP_SEARCH_FAILED, /* 39 */
CURLE_OBSOLETE40, /* 40 - NOT USED */
CURLE_FUNCTION_NOT_FOUND, /* 41 */
CURLE_FUNCTION_NOT_FOUND, /* 41 - NOT USED starting with 7.53.0 */
CURLE_ABORTED_BY_CALLBACK, /* 42 */
CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */
CURLE_OBSOLETE44, /* 44 - NOT USED */
@ -556,6 +571,7 @@ typedef enum {
/* compatibility with older names */
#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY
/* The following were added in 7.21.5, April 2011 */
#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
@ -629,6 +645,7 @@ typedef enum {
CONNECT HTTP/1.1 */
CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT
HTTP/1.0 */
CURLPROXY_HTTPS = 2, /* added in 7.52.0 */
CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
in 7.10 */
CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
@ -1195,7 +1212,8 @@ typedef enum {
CINIT(SHARE, OBJECTPOINT, 100),
/* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and
CURLPROXY_SOCKS5. */
CINIT(PROXYTYPE, LONG, 101),
/* Set the Accept-Encoding string. Use this to tell a server you would like
@ -1689,6 +1707,77 @@ typedef enum {
/* Set TCP Fast Open */
CINIT(TCP_FASTOPEN, LONG, 244),
/* Continue to send data if the server responds early with an
* HTTP status code >= 300 */
CINIT(KEEP_SENDING_ON_ERROR, LONG, 245),
/* The CApath or CAfile used to validate the proxy certificate
this option is used only if PROXY_SSL_VERIFYPEER is true */
CINIT(PROXY_CAINFO, STRINGPOINT, 246),
/* The CApath directory used to validate the proxy certificate
this option is used only if PROXY_SSL_VERIFYPEER is true */
CINIT(PROXY_CAPATH, STRINGPOINT, 247),
/* Set if we should verify the proxy in ssl handshake,
set 1 to verify. */
CINIT(PROXY_SSL_VERIFYPEER, LONG, 248),
/* Set if we should verify the Common name from the proxy certificate in ssl
* handshake, set 1 to check existence, 2 to ensure that it matches
* the provided hostname. */
CINIT(PROXY_SSL_VERIFYHOST, LONG, 249),
/* What version to specifically try to use for proxy.
See CURL_SSLVERSION defines below. */
CINIT(PROXY_SSLVERSION, LONG, 250),
/* Set a username for authenticated TLS for proxy */
CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251),
/* Set a password for authenticated TLS for proxy */
CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252),
/* Set authentication type for authenticated TLS for proxy */
CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253),
/* name of the file keeping your private SSL-certificate for proxy */
CINIT(PROXY_SSLCERT, STRINGPOINT, 254),
/* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for
proxy */
CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255),
/* name of the file keeping your private SSL-key for proxy */
CINIT(PROXY_SSLKEY, STRINGPOINT, 256),
/* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for
proxy */
CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257),
/* password for the SSL private key for proxy */
CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258),
/* Specify which SSL ciphers to use for proxy */
CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259),
/* CRL file for proxy */
CINIT(PROXY_CRLFILE, STRINGPOINT, 260),
/* Enable/disable specific SSL features with a bitmask for proxy, see
CURLSSLOPT_* */
CINIT(PROXY_SSL_OPTIONS, LONG, 261),
/* Name of pre proxy to use. */
CINIT(PRE_PROXY, STRINGPOINT, 262),
/* The public key in DER form used to validate the proxy public key
this option is used only if PROXY_SSL_VERIFYPEER is true */
CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263),
/* Path to an abstract Unix domain socket */
CINIT(ABSTRACT_UNIX_SOCKET, STRINGPOINT, 264),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@ -1790,6 +1879,7 @@ enum {
CURL_SSLVERSION_TLSv1_0,
CURL_SSLVERSION_TLSv1_1,
CURL_SSLVERSION_TLSv1_2,
CURL_SSLVERSION_TLSv1_3,
CURL_SSLVERSION_LAST /* never use, keep last */
};
@ -1824,7 +1914,10 @@ typedef enum {
/* curl_strequal() and curl_strnequal() are subject for removal in a future
libcurl, see lib/README.curlx for details */
libcurl, see lib/README.curlx for details
!checksrc! disable SPACEBEFOREPAREN 2
*/
CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
@ -2193,9 +2286,13 @@ typedef enum {
CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43,
CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44,
CURLINFO_TLS_SSL_PTR = CURLINFO_SLIST + 45,
CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46,
CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
CURLINFO_PROTOCOL = CURLINFO_LONG + 48,
CURLINFO_SCHEME = CURLINFO_STRING + 49,
/* Fill in new entries below here! */
CURLINFO_LASTONE = 45
CURLINFO_LASTONE = 49
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@ -2257,7 +2354,6 @@ typedef void (*curl_unlock_function)(CURL *handle,
curl_lock_data data,
void *userptr);
typedef void CURLSH;
typedef enum {
CURLSHE_OK, /* all is fine */
@ -2357,6 +2453,7 @@ typedef struct {
#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */
#define CURL_VERSION_PSL (1<<20) /* Mozilla's Public Suffix List, used
for cookie domain verification */
#define CURL_VERSION_HTTPS_PROXY (1<<21) /* HTTPS-proxy support built-in */
/*
* NAME curl_version_info()

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2016, 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
@ -26,16 +26,16 @@
a script at release-time. This was made its own header file in 7.11.2 */
/* This is the global package copyright */
#define LIBCURL_COPYRIGHT "1996 - 2016 Daniel Stenberg, <daniel@haxx.se>."
#define LIBCURL_COPYRIGHT "1996 - 2017 Daniel Stenberg, <daniel@haxx.se>."
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.49.1-DEV"
#define LIBCURL_VERSION "7.53.1-DEV"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 49
#define LIBCURL_VERSION_MINOR 53
#define LIBCURL_VERSION_PATCH 1
/* This is the numeric version of the libcurl version number, meant for easier
@ -57,7 +57,7 @@
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
#define LIBCURL_VERSION_NUM 0x073101
#define LIBCURL_VERSION_NUM 0x073501
/*
* This is the date and time when the full source package was created. The

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -52,7 +52,11 @@
extern "C" {
#endif
#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
typedef struct Curl_multi CURLM;
#else
typedef void CURLM;
#endif
typedef enum {
CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -151,7 +151,7 @@ _CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
"curl_easy_setopt expects a curl_off_t argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_string,
"curl_easy_setopt expects a "
"string (char* or char[]) argument for this option"
"string ('char *' or char[]) argument for this option"
)
_CURL_WARNING(_curl_easy_setopt_err_write_callback,
"curl_easy_setopt expects a curl_write_callback argument for this option")
@ -182,24 +182,25 @@ _CURL_WARNING(_curl_easy_setopt_err_error_buffer,
"curl_easy_setopt expects a "
"char buffer of CURL_ERROR_SIZE as argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_FILE,
"curl_easy_setopt expects a FILE* argument for this option")
"curl_easy_setopt expects a 'FILE *' argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_postfields,
"curl_easy_setopt expects a void* or char* argument for this option")
"curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
"curl_easy_setopt expects a struct curl_httppost* argument for this option")
"curl_easy_setopt expects a 'struct curl_httppost *' "
"argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
"curl_easy_setopt expects a struct curl_slist* argument for this option")
"curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
"curl_easy_setopt expects a CURLSH* argument for this option")
_CURL_WARNING(_curl_easy_getinfo_err_string,
"curl_easy_getinfo expects a pointer to char * for this info")
"curl_easy_getinfo expects a pointer to 'char *' for this info")
_CURL_WARNING(_curl_easy_getinfo_err_long,
"curl_easy_getinfo expects a pointer to long for this info")
_CURL_WARNING(_curl_easy_getinfo_err_double,
"curl_easy_getinfo expects a pointer to double for this info")
_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
"curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
"curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
/* groups of curl_easy_setops options that take the same type of argument */
@ -218,7 +219,8 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
/* evaluates to true if option takes a char* argument */
#define _curl_is_string_option(option) \
((option) == CURLOPT_ACCEPT_ENCODING || \
((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \
(option) == CURLOPT_ACCEPT_ENCODING || \
(option) == CURLOPT_CAINFO || \
(option) == CURLOPT_CAPATH || \
(option) == CURLOPT_COOKIE || \

View File

@ -4,7 +4,6 @@
*.orig
*.rej
*.res
Makefile.vc*.dist
TAGS
curl_config.h
curl_config.h.in

View File

@ -87,6 +87,11 @@ endif()
set_target_properties(${LIB_NAME} PROPERTIES COMPILE_DEFINITIONS BUILDING_LIBCURL)
if(HIDES_CURL_PRIVATE_SYMBOLS)
set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE})
endif()
# Remove the "lib" prefix since the library is already named "libcurl".
set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "")

View File

@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2016, 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
@ -23,7 +23,7 @@ AUTOMAKE_OPTIONS = foreign nostdinc
CMAKE_DIST = CMakeLists.txt curl_config.h.cmake
EXTRA_DIST = Makefile.b32 Makefile.m32 Makefile.vc6 config-win32.h \
EXTRA_DIST = Makefile.b32 Makefile.m32 config-win32.h \
config-win32ce.h config-riscos.h config-mac.h curl_config.h.in \
makefile.dj config-dos.h libcurl.plist libcurl.rc config-amigaos.h \
makefile.amiga Makefile.netware nwlib.c nwos.c config-win32ce.h \

View File

@ -40,31 +40,31 @@ LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h \
LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \
ldap.c version.c getenv.c escape.c mprintf.c telnet.c netrc.c \
getinfo.c transfer.c strequal.c easy.c security.c curl_fnmatch.c \
getinfo.c transfer.c strcase.c easy.c security.c curl_fnmatch.c \
fileinfo.c ftplistparser.c wildcard.c krb5.c memdebug.c http_chunks.c \
strtok.c connect.c llist.c hash.c multi.c content_encoding.c share.c \
http_digest.c md4.c md5.c http_negotiate.c inet_pton.c strtoofft.c \
strerror.c amigaos.c hostasyn.c hostip4.c hostip6.c hostsyn.c \
inet_ntop.c parsedate.c select.c tftp.c splay.c strdup.c socks.c \
ssh.c rawstr.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \
ssh.c curl_addrinfo.c socks_gssapi.c socks_sspi.c \
curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c \
pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c \
openldap.c curl_gethostname.c gopher.c idn_win32.c \
http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c \
http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c \
http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c \
curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c \
x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c
LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h \
speedcheck.h urldata.h curl_ldap.h escape.h telnet.h getinfo.h \
strequal.h curl_sec.h memdebug.h http_chunks.h curl_fnmatch.h \
strcase.h curl_sec.h memdebug.h http_chunks.h curl_fnmatch.h \
wildcard.h fileinfo.h ftplistparser.h strtok.h connect.h llist.h \
hash.h content_encoding.h share.h curl_md4.h curl_md5.h http_digest.h \
http_negotiate.h inet_pton.h amigaos.h strtoofft.h strerror.h \
inet_ntop.h curlx.h curl_memory.h curl_setup.h transfer.h select.h \
easyif.h multiif.h parsedate.h tftp.h sockaddr.h splay.h strdup.h \
socks.h ssh.h curl_base64.h rawstr.h curl_addrinfo.h curl_sspi.h \
socks.h ssh.h curl_base64.h curl_addrinfo.h curl_sspi.h \
slist.h nonblock.h curl_memrchr.h imap.h pop3.h smtp.h pingpong.h \
rtsp.h curl_threads.h warnless.h curl_hmac.h curl_rtmp.h \
curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h \
@ -72,7 +72,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
curl_sasl.h curl_multibyte.h hostcheck.h conncache.h \
curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h \
x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h \
curl_printf.h system_win32.h
curl_printf.h system_win32.h rand.h
LIB_RCFILES = libcurl.rc

View File

@ -258,6 +258,10 @@ ifdef SSL
CFLAGS += -DHAVE_OPENSSL_SRP -DUSE_TLS_SRP
endif
endif
else
ifdef WINSSL
DLL_LIBS += -lcrypt32
endif
endif
ifdef ZLIB
INCLUDES += -I"$(ZLIB_PATH)"

View File

@ -87,7 +87,7 @@ endif
TARGET = libcurl
VERSION = $(LIBCURL_VERSION)
COPYR = Copyright (C) $(LIBCURL_COPYRIGHT_STR)
DESCR = cURL libcurl $(LIBCURL_VERSION_STR) ($(LIBARCH)) - https://curl.haxx.se
DESCR = curl libcurl $(LIBCURL_VERSION_STR) ($(LIBARCH)) - https://curl.haxx.se
MTSAFE = YES
STACK = 64000
SCREEN = none

View File

@ -1,689 +0,0 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 1999 - 2016, 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
# are also available at https://curl.haxx.se/docs/copyright.html.
#
# 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.
#
#***************************************************************************
# All files in the Makefile.vc* series are generated automatically from the
# one made for MSVC version 6. Alas, if you want to do changes to any of the
# files and send back to the project, edit the version six, make your diff and
# mail curl-library.
###########################################################################
#
# Makefile for building libcurl with MSVC6
#
# Usage: see usage message below
# Should be invoked from \lib directory
# Edit the paths and desired library name
# SSL path is only required if you intend compiling
# with SSL.
#
# This make file leaves the result either a .lib or .dll file
# in the \lib directory. It should be called from the \lib
# directory.
#
# An option would have been to allow the source directory to
# be specified, but I saw no requirement.
#
# Another option would have been to leave the .lib and .dll
# files in the "cfg" directory, but then the make file
# in \src would need to be changed.
#
##############################################################
# ----------------------------------------------
# Verify that current subdir is libcurl's 'lib'
# ----------------------------------------------
!IF ! EXIST(.\curl_addrinfo.c)
! MESSAGE Can not process this makefile from outside of libcurl's 'lib' subdirectory.
! MESSAGE Change to libcurl's 'lib' subdirectory, and try again.
! ERROR See previous message.
!ENDIF
# ------------------------------------------------
# Makefile.msvc.names provides libcurl file names
# ------------------------------------------------
!INCLUDE ..\winbuild\Makefile.msvc.names
!IFNDEF OPENSSL_PATH
OPENSSL_PATH = ../../openssl-1.0.2a
!ENDIF
!IFNDEF LIBSSH2_PATH
LIBSSH2_PATH = ../../libssh2-1.5.0
!ENDIF
!IFNDEF ZLIB_PATH
ZLIB_PATH = ../../zlib-1.2.8
!ENDIF
!IFNDEF MACHINE
MACHINE = X86
!ENDIF
# USE_WINDOWS_SSPI uses windows libraries to allow NTLM authentication
# without an openssl installation and offers the ability to authenticate
# using the "current logged in user". Since at least with MSVC6 the sspi.h
# header is broken it is either required to install the Windows SDK,
# or to fix sspi.h with adding this define at the beginning of sspi.h:
# #define FreeCredentialHandle FreeCredentialsHandle
#
# If, for some reason the Windows SDK is installed but not installed
# in the default location, you can specify WINDOWS_SDK_PATH.
# It can be downloaded from:
# https://msdn.microsoft.com/windows/bb980924.aspx
# WINDOWS_SSPI = 1
!IFDEF WINDOWS_SSPI
!IFNDEF WINDOWS_SDK_PATH
WINDOWS_SDK_PATH = "$(PROGRAMFILES)\Microsoft SDK"
!ENDIF
!ENDIF
#############################################################
## Nothing more to do below this line!
CCNODBG = cl.exe /O2 /DNDEBUG
CCDEBUG = cl.exe /Od /Gm /Zi /D_DEBUG /GZ
CFLAGSSSL = /DUSE_OPENSSL /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
CFLAGSWINSSL = /DUSE_SCHANNEL
CFLAGSSSH2 = /DUSE_LIBSSH2 /DCURL_DISABLE_LDAP /DHAVE_LIBSSH2 /DHAVE_LIBSSH2_H /DLIBSSH2_WIN32 /DLIBSSH2_LIBRARY /I "$(LIBSSH2_PATH)/include"
CFLAGSZLIB = /DHAVE_ZLIB_H /DHAVE_ZLIB /DHAVE_LIBZ /I "$(ZLIB_PATH)"
CFLAGS = /I. /I../include /nologo /W3 /GX /DWIN32 /YX /FD /c /DBUILDING_LIBCURL /D_BIND_TO_CURRENT_VCLIBS_VERSION=1
CFLAGSLIB = /DCURL_STATICLIB
LNKDLL = link.exe /DLL
LNKLIB = link.exe /lib
LFLAGS = /nologo /machine:$(MACHINE)
SSLLIBS = libeay32.lib ssleay32.lib
ZLIBLIBSDLL = zdll.lib
ZLIBLIBS = zlib.lib
WINLIBS = ws2_32.lib wldap32.lib advapi32.lib
CFLAGS = $(CFLAGS)
CFGSET = FALSE
!IFDEF WINDOWS_SSPI
CFLAGS = $(CFLAGS) /DUSE_WINDOWS_SSPI /I$(WINDOWS_SDK_PATH)\include
!ENDIF
!IFDEF USE_IPV6
CFLAGS = $(CFLAGS) /DUSE_IPV6
!ENDIF
!IFDEF USE_IDN
CFLAGS = $(CFLAGS) /DUSE_WIN32_IDN /DWANT_IDN_PROTOTYPES
!ENDIF
##############################################################
# Runtime library configuration
RTLIB = /MD
RTLIBD = /MDd
!IF "$(RTLIBCFG)" == "static"
RTLIB = /MT
RTLIBD = /MTd
!ENDIF
######################
# release
!IF "$(CFG)" == "release"
TARGET = $(LIBCURL_STA_LIB_REL)
DIROBJ = $(CFG)
LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# release-ssl
!IF "$(CFG)" == "release-ssl"
TARGET = $(LIBCURL_STA_LIB_REL)
DIROBJ = $(CFG)
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# release-winssl
!IF "$(CFG)" == "release-winssl"
TARGET = $(LIBCURL_STA_LIB_REL)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSWINSSL) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# release-zlib
!IF "$(CFG)" == "release-zlib"
TARGET = $(LIBCURL_STA_LIB_REL)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# release-ssl-zlib
!IF "$(CFG)" == "release-ssl-zlib"
TARGET = $(LIBCURL_STA_LIB_REL)
DIROBJ = $(CFG)
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LNK = $(LNKLIB) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# release-winssl-zlib
!IF "$(CFG)" == "release-winssl-zlib"
TARGET = $(LIBCURL_STA_LIB_REL)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LNK = $(LNKLIB) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSWINSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# release-ssl-ssh2-zlib
!IF "$(CFG)" == "release-ssl-ssh2-zlib"
TARGET = $(LIBCURL_STA_LIB_REL)
DIROBJ = $(CFG)
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
LFLAGSSSH2 = "/LIBPATH:$(LIBSSH2_PATH)"
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LNK = $(LNKLIB) $(LFLAGSSSL) $(LFLAGSSSH2) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSSSH2) $(CFLAGSZLIB) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# release-ssl-dll
!IF "$(CFG)" == "release-ssl-dll"
TARGET = $(LIBCURL_STA_LIB_REL)
DIROBJ = $(CFG)
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# release-zlib-dll
!IF "$(CFG)" == "release-zlib-dll"
TARGET = $(LIBCURL_STA_LIB_REL)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LNK = $(LNKLIB) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# release-ssl-dll-zlib-dll
!IF "$(CFG)" == "release-ssl-dll-zlib-dll"
TARGET = $(LIBCURL_STA_LIB_REL)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# release-dll
!IF "$(CFG)" == "release-dll"
TARGET = $(LIBCURL_DYN_LIB_REL)
DIROBJ = $(CFG)
LNK = $(LNKDLL) $(WINLIBS) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
CC = $(CCNODBG) $(RTLIB)
CFGSET = TRUE
RESOURCE = $(DIROBJ)\libcurl.res
!ENDIF
######################
# release-dll-ssl-dll
!IF "$(CFG)" == "release-dll-ssl-dll"
TARGET = $(LIBCURL_DYN_LIB_REL)
DIROBJ = $(CFG)
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL)
CFGSET = TRUE
RESOURCE = $(DIROBJ)\libcurl.res
!ENDIF
######################
# release-dll-zlib-dll
!IF "$(CFG)" == "release-dll-zlib-dll"
TARGET = $(LIBCURL_DYN_LIB_REL)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LNK = $(LNKDLL) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSZLIB)
CFGSET = TRUE
RESOURCE = $(DIROBJ)\libcurl.res
!ENDIF
######################
# release-dll-ssl-dll-zlib-dll
!IF "$(CFG)" == "release-dll-ssl-dll-zlib-dll"
TARGET = $(LIBCURL_DYN_LIB_REL)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_REL)
CC = $(CCNODBG) $(RTLIB) $(CFLAGSSSL) $(CFLAGSZLIB)
CFGSET = TRUE
RESOURCE = $(DIROBJ)\libcurl.res
!ENDIF
######################
# debug
!IF "$(CFG)" == "debug"
TARGET = $(LIBCURL_STA_LIB_DBG)
DIROBJ = $(CFG)
LNK = $(LNKLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# debug-ssl
!IF "$(CFG)" == "debug-ssl"
TARGET = $(LIBCURL_STA_LIB_DBG)
DIROBJ = $(CFG)
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
LNK = $(LNKLIB) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# debug-zlib
!IF "$(CFG)" == "debug-zlib"
TARGET = $(LIBCURL_STA_LIB_DBG)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# debug-ssl-zlib
!IF "$(CFG)" == "debug-ssl-zlib"
TARGET = $(LIBCURL_STA_LIB_DBG)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# debug-ssl-ssh2-zlib
!IF "$(CFG)" == "debug-ssl-ssh2-zlib"
TARGET = $(LIBCURL_STA_LIB_DBG)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LFLAGSSSH2 = "/LIBPATH:$(LIBSSH2_PATH)"
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32"
LNK = $(LNKLIB) $(ZLIBLIBS) $(LFLAGSSSL) $(LFLAGSSSH2) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSSSH2) $(CFLAGSZLIB) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# debug-ssl-dll
!IF "$(CFG)" == "debug-ssl-dll"
TARGET = $(LIBCURL_STA_LIB_DBG)
DIROBJ = $(CFG)
LFLAGSSSL = /LIBPATH:$(OPENSSL_PATH)\out32dll
LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /out:$(DIROBJ)\$(TARGET)
CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# debug-zlib-dll
!IF "$(CFG)" == "debug-zlib-dll"
TARGET = $(LIBCURL_STA_LIB_DBG)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LNK = $(LNKLIB) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# debug-ssl-dll-zlib-dll
!IF "$(CFG)" == "debug-ssl-dll-zlib-dll"
TARGET = $(LIBCURL_STA_LIB_DBG)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
LNK = $(LNKLIB) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /out:$(DIROBJ)\$(TARGET)
CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB) $(CFLAGSLIB)
CFGSET = TRUE
!ENDIF
######################
# debug-dll
!IF "$(CFG)" == "debug-dll"
TARGET = $(LIBCURL_DYN_LIB_DBG)
DIROBJ = $(CFG)
LNK = $(LNKDLL) $(WINLIBS) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
CC = $(CCDEBUG) $(RTLIBD)
CFGSET = TRUE
RESOURCE = $(DIROBJ)\libcurl.res
!ENDIF
######################
# debug-dll-ssl-dll
!IF "$(CFG)" == "debug-dll-ssl-dll"
TARGET = $(LIBCURL_DYN_LIB_DBG)
DIROBJ = $(CFG)
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(LFLAGSSSL) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL)
CFGSET = TRUE
RESOURCE = $(DIROBJ)\libcurl.res
!ENDIF
######################
# debug-dll-zlib-dll
!IF "$(CFG)" == "debug-dll-zlib-dll"
TARGET = $(LIBCURL_DYN_LIB_DBG)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LNK = $(LNKDLL) $(WINLIBS) $(ZLIBLIBSDLL) $(LFLAGSZLIB) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSZLIB)
CFGSET = TRUE
RESOURCE = $(DIROBJ)\libcurl.res
!ENDIF
######################
# debug-dll-ssl-dll-zlib-dll
!IF "$(CFG)" == "debug-dll-ssl-dll-zlib-dll"
TARGET = $(LIBCURL_DYN_LIB_DBG)
DIROBJ = $(CFG)
LFLAGSZLIB = "/LIBPATH:$(ZLIB_PATH)"
LFLAGSSSL = "/LIBPATH:$(OPENSSL_PATH)\out32dll"
LNK = $(LNKDLL) $(WINLIBS) $(SSLLIBS) $(ZLIBLIBSDLL) $(LFLAGSSSL) $(LFLAGSZLIB) /DEBUG /out:$(DIROBJ)\$(TARGET) /IMPLIB:$(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) /PDB:$(DIROBJ)\$(LIBCURL_DYN_LIB_PDB)
CC = $(CCDEBUG) $(RTLIBD) $(CFLAGSSSL) $(CFLAGSZLIB)
CFGSET = TRUE
RESOURCE = $(DIROBJ)\libcurl.res
!ENDIF
#######################
# Usage
#
!IF "$(CFGSET)" == "FALSE" && "$(CFG)" != ""
!MESSAGE Usage: nmake /f makefile.vc6 CFG=<config> <target>
!MESSAGE where <config> is one of:
!MESSAGE release - release static library
!MESSAGE release-ssl - release static library with ssl
!MESSAGE release-zlib - release static library with zlib
!MESSAGE release-ssl-zlib - release static library with ssl and zlib
!MESSAGE release-ssl-ssh2-zlib - release static library with ssl, ssh2 and zlib
!MESSAGE release-ssl-dll - release static library with dynamic ssl
!MESSAGE release-zlib-dll - release static library with dynamic zlib
!MESSAGE release-ssl-dll-zlib-dll - release static library with dynamic ssl and dynamic zlib
!MESSAGE release-dll - release dynamic library
!MESSAGE release-dll-ssl-dll - release dynamic library with dynamic ssl
!MESSAGE release-dll-zlib-dll - release dynamic library with dynamic zlib
!MESSAGE release-dll-ssl-dll-zlib-dll - release dynamic library with dynamic ssl and dynamic zlib
!MESSAGE debug - debug static library
!MESSAGE debug-ssl - debug static library with ssl
!MESSAGE debug-zlib - debug static library with zlib
!MESSAGE debug-ssl-zlib - debug static library with ssl and zlib
!MESSAGE debug-ssl-ssh2-zlib - debug static library with ssl, ssh2 and zlib
!MESSAGE debug-ssl-dll - debug static library with dynamic ssl
!MESSAGE debug-zlib-dll - debug static library with dynamic zlib
!MESSAGE debug-ssl-dll-zlib-dll - debug static library with dynamic ssl and dynamic zlib
!MESSAGE debug-dll - debug dynamic library
!MESSAGE debug-dll-ssl-dll - debug dynamic library with dynamic ssl
!MESSAGE debug-dll-zlib-dll - debug dynamic library with dynamic zlib1
!MESSAGE debug-dll-ssl-dll-zlib-dll - debug dynamic library with dynamic ssl and dynamic zlib
!MESSAGE <target> can be left blank in which case all is assumed
!ERROR please choose a valid configuration "$(CFG)"
!ENDIF
#######################
# Only the clean target can be used if a config was not provided.
#
!IF "$(CFGSET)" == "FALSE"
clean:
@-erase /s *.dll 2> NUL
@-erase /s *.exp 2> NUL
@-erase /s *.idb 2> NUL
@-erase /s *.lib 2> NUL
@-erase /s *.obj 2> NUL
@-erase /s *.pch 2> NUL
@-erase /s *.pdb 2> NUL
@-erase /s *.res 2> NUL
!ELSE
# A config was provided, so the library can be built.
#
X_OBJS= \
$(DIROBJ)\amigaos.obj \
$(DIROBJ)\asyn-ares.obj \
$(DIROBJ)\asyn-thread.obj \
$(DIROBJ)\axtls.obj \
$(DIROBJ)\base64.obj \
$(DIROBJ)\conncache.obj \
$(DIROBJ)\connect.obj \
$(DIROBJ)\content_encoding.obj \
$(DIROBJ)\cookie.obj \
$(DIROBJ)\curl_addrinfo.obj \
$(DIROBJ)\curl_des.obj \
$(DIROBJ)\curl_endian.obj \
$(DIROBJ)\curl_fnmatch.obj \
$(DIROBJ)\curl_gethostname.obj \
$(DIROBJ)\curl_gssapi.obj \
$(DIROBJ)\curl_memrchr.obj \
$(DIROBJ)\curl_multibyte.obj \
$(DIROBJ)\curl_ntlm_core.obj \
$(DIROBJ)\curl_ntlm_wb.obj \
$(DIROBJ)\curl_rtmp.obj \
$(DIROBJ)\curl_sasl.obj \
$(DIROBJ)\curl_sspi.obj \
$(DIROBJ)\curl_threads.obj \
$(DIROBJ)\cyassl.obj \
$(DIROBJ)\darwinssl.obj \
$(DIROBJ)\dict.obj \
$(DIROBJ)\dotdot.obj \
$(DIROBJ)\easy.obj \
$(DIROBJ)\escape.obj \
$(DIROBJ)\file.obj \
$(DIROBJ)\fileinfo.obj \
$(DIROBJ)\formdata.obj \
$(DIROBJ)\ftp.obj \
$(DIROBJ)\ftplistparser.obj \
$(DIROBJ)\getenv.obj \
$(DIROBJ)\getinfo.obj \
$(DIROBJ)\gopher.obj \
$(DIROBJ)\gtls.obj \
$(DIROBJ)\hash.obj \
$(DIROBJ)\hmac.obj \
$(DIROBJ)\hostasyn.obj \
$(DIROBJ)\hostcheck.obj \
$(DIROBJ)\hostip.obj \
$(DIROBJ)\hostip4.obj \
$(DIROBJ)\hostip6.obj \
$(DIROBJ)\hostsyn.obj \
$(DIROBJ)\http.obj \
$(DIROBJ)\http_chunks.obj \
$(DIROBJ)\http_digest.obj \
$(DIROBJ)\http_negotiate.obj \
$(DIROBJ)\http_ntlm.obj \
$(DIROBJ)\http_proxy.obj \
$(DIROBJ)\idn_win32.obj \
$(DIROBJ)\if2ip.obj \
$(DIROBJ)\imap.obj \
$(DIROBJ)\inet_ntop.obj \
$(DIROBJ)\inet_pton.obj \
$(DIROBJ)\krb5.obj \
$(DIROBJ)\ldap.obj \
$(DIROBJ)\llist.obj \
$(DIROBJ)\md4.obj \
$(DIROBJ)\md5.obj \
$(DIROBJ)\memdebug.obj \
$(DIROBJ)\mprintf.obj \
$(DIROBJ)\multi.obj \
$(DIROBJ)\netrc.obj \
$(DIROBJ)\non-ascii.obj \
$(DIROBJ)\nonblock.obj \
$(DIROBJ)\nss.obj \
$(DIROBJ)\openldap.obj \
$(DIROBJ)\parsedate.obj \
$(DIROBJ)\pingpong.obj \
$(DIROBJ)\pipeline.obj \
$(DIROBJ)\polarssl.obj \
$(DIROBJ)\polarssl_threadlock.obj \
$(DIROBJ)\pop3.obj \
$(DIROBJ)\progress.obj \
$(DIROBJ)\rawstr.obj \
$(DIROBJ)\rtsp.obj \
$(DIROBJ)\schannel.obj \
$(DIROBJ)\security.obj \
$(DIROBJ)\select.obj \
$(DIROBJ)\sendf.obj \
$(DIROBJ)\share.obj \
$(DIROBJ)\slist.obj \
$(DIROBJ)\smb.obj \
$(DIROBJ)\smtp.obj \
$(DIROBJ)\socks.obj \
$(DIROBJ)\socks_gssapi.obj \
$(DIROBJ)\socks_sspi.obj \
$(DIROBJ)\speedcheck.obj \
$(DIROBJ)\splay.obj \
$(DIROBJ)\ssh.obj \
$(DIROBJ)\system_win32.obj \
$(DIROBJ)\vauth.obj \
$(DIROBJ)\cleartext.obj \
$(DIROBJ)\cram.obj \
$(DIROBJ)\digest.obj \
$(DIROBJ)\digest_sspi.obj \
$(DIROBJ)\krb5_gssapi.obj \
$(DIROBJ)\krb5_sspi.obj \
$(DIROBJ)\ntlm.obj \
$(DIROBJ)\ntlm_sspi.obj \
$(DIROBJ)\oauth2.obj \
$(DIROBJ)\spnego_gssapi.obj \
$(DIROBJ)\spnego_sspi.obj \
$(DIROBJ)\vtls.obj \
$(DIROBJ)\openssl.obj \
$(DIROBJ)\strdup.obj \
$(DIROBJ)\strequal.obj \
$(DIROBJ)\strerror.obj \
$(DIROBJ)\strtok.obj \
$(DIROBJ)\strtoofft.obj \
$(DIROBJ)\telnet.obj \
$(DIROBJ)\tftp.obj \
$(DIROBJ)\timeval.obj \
$(DIROBJ)\transfer.obj \
$(DIROBJ)\url.obj \
$(DIROBJ)\version.obj \
$(DIROBJ)\warnless.obj \
$(DIROBJ)\wildcard.obj \
$(RESOURCE)
all : $(TARGET)
$(TARGET): $(X_OBJS)
$(LNK) $(LFLAGS) $(X_OBJS)
-xcopy $(DIROBJ)\$(LIBCURL_STA_LIB_REL) . /y
-xcopy $(DIROBJ)\$(LIBCURL_STA_LIB_DBG) . /y
-xcopy $(DIROBJ)\$(LIBCURL_DYN_LIB_REL) . /y
-xcopy $(DIROBJ)\$(LIBCURL_DYN_LIB_DBG) . /y
-xcopy $(DIROBJ)\$(LIBCURL_IMP_LIB_REL) . /y
-xcopy $(DIROBJ)\$(LIBCURL_IMP_LIB_DBG) . /y
-xcopy $(DIROBJ)\*.exp . /y
-xcopy $(DIROBJ)\*.pdb . /y
$(X_OBJS): $(DIROBJ)
$(DIROBJ):
@if not exist "$(DIROBJ)" mkdir $(DIROBJ)
.SUFFIXES: .c .obj .res
{.\}.c{$(DIROBJ)\}.obj:
$(CC) $(CFLAGS) /Fo"$@" $<
{.\vauth\}.c{$(DIROBJ)\}.obj:
$(CC) $(CFLAGS) /Fo"$@" $<
{.\vtls\}.c{$(DIROBJ)\}.obj:
$(CC) $(CFLAGS) /Fo"$@" $<
debug-dll\libcurl.res \
debug-dll-ssl-dll\libcurl.res \
debug-dll-zlib-dll\libcurl.res \
debug-dll-ssl-dll-zlib-dll\libcurl.res: libcurl.rc
rc /dDEBUGBUILD=1 /Fo $@ libcurl.rc
release-dll\libcurl.res \
release-dll-ssl-dll\libcurl.res \
release-dll-zlib-dll\libcurl.res \
release-dll-ssl-dll-zlib-dll\libcurl.res: libcurl.rc
rc /dDEBUGBUILD=0 /Fo $@ libcurl.rc
!ENDIF # End of case where a config was provided.

View File

@ -57,7 +57,7 @@ bool Curl_amiga_init()
}
if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno,
SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "cURL",
SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "curl",
TAG_DONE)) {
__request("SocketBaseTags ERROR");
return FALSE;

View File

@ -249,7 +249,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
static int waitperform(struct connectdata *conn, int timeout_ms)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
int nfds;
int bitmask;
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
@ -309,7 +309,7 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **dns)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct ResolverResults *res = (struct ResolverResults *)
conn->async.os_specific;
CURLcode result = CURLE_OK;
@ -353,7 +353,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
struct Curl_dns_entry **entry)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
long timeout;
struct timeval now = Curl_tvnow();
struct Curl_dns_entry *temp_entry;
@ -492,7 +492,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
int *waitp)
{
char *bufp;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct in_addr in;
int family = PF_INET;
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
@ -583,7 +583,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
return NULL; /* no struct yet */
}
CURLcode Curl_set_dns_servers(struct SessionHandle *data,
CURLcode Curl_set_dns_servers(struct Curl_easy *data,
char *servers)
{
CURLcode result = CURLE_NOT_BUILT_IN;
@ -621,7 +621,7 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
return result;
}
CURLcode Curl_set_dns_interface(struct SessionHandle *data,
CURLcode Curl_set_dns_interface(struct Curl_easy *data,
const char *interf)
{
#if (ARES_VERSION >= 0x010704)
@ -638,7 +638,7 @@ CURLcode Curl_set_dns_interface(struct SessionHandle *data,
#endif
}
CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
const char *local_ip4)
{
#if (ARES_VERSION >= 0x010704)
@ -663,7 +663,7 @@ CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
#endif
}
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
const char *local_ip6)
{
#if (ARES_VERSION >= 0x010704) && defined(ENABLE_IPV6)

View File

@ -169,7 +169,7 @@ struct thread_sync_data {
struct thread_data {
curl_thread_t thread_hnd;
unsigned int poll_interval;
long interval_end;
time_t interval_end;
struct thread_sync_data tsd;
};
@ -279,6 +279,9 @@ static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
if(tsd->sock_error == 0)
tsd->sock_error = RESOLVER_ENOMEM;
}
else {
Curl_addrinfo_set_port(tsd->res, tsd->port);
}
Curl_mutex_acquire(tsd->mtx);
if(tsd->done) {
@ -494,7 +497,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **entry)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
int done = 0;
@ -522,7 +525,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
}
else {
/* poll for name lookup done with exponential backoff up to 250ms */
long elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
time_t elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
if(elapsed < 0)
elapsed = 0;
@ -602,6 +605,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
*waitp = 0; /* default to synchronous response */
#ifndef USE_RESOLVE_ON_IPS
/* First check if this is an IPv4 address string */
if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
/* This is a dotted IP address 123.123.123.123-style */
@ -612,7 +616,10 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0)
/* This is an IPv6 address literal */
return Curl_ip2addr(AF_INET6, &in6, hostname, port);
#endif /* CURLRES_IPV6 */
#endif /* !USE_RESOLVE_ON_IPS */
#ifdef CURLRES_IPV6
/*
* Check if a limited name resolve has been requested.
*/
@ -631,7 +638,6 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
if((pf != PF_INET) && !Curl_ipv6works())
/* The stack seems to be a non-IPv6 one */
pf = PF_INET;
#endif /* CURLRES_IPV6 */
memset(&hints, 0, sizeof(hints));
@ -656,12 +662,16 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
hostname, port, Curl_strerror(conn, SOCKERRNO));
return NULL;
}
else {
Curl_addrinfo_set_port(res, port);
}
return res;
}
#endif /* !HAVE_GETADDRINFO */
CURLcode Curl_set_dns_servers(struct SessionHandle *data,
CURLcode Curl_set_dns_servers(struct Curl_easy *data,
char *servers)
{
(void)data;
@ -670,7 +680,7 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
}
CURLcode Curl_set_dns_interface(struct SessionHandle *data,
CURLcode Curl_set_dns_interface(struct Curl_easy *data,
const char *interf)
{
(void)data;
@ -678,7 +688,7 @@ CURLcode Curl_set_dns_interface(struct SessionHandle *data,
return CURLE_NOT_BUILT_IN;
}
CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
const char *local_ip4)
{
(void)data;
@ -686,7 +696,7 @@ CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
return CURLE_NOT_BUILT_IN;
}
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
const char *local_ip6)
{
(void)data;

View File

@ -27,7 +27,7 @@
struct addrinfo;
struct hostent;
struct SessionHandle;
struct Curl_easy;
struct connectdata;
struct Curl_dns_entry;

View File

@ -23,7 +23,7 @@
/* Base64 encoding/decoding */
#include "curl_setup.h"
#include "urldata.h" /* for the SessionHandle definition */
#include "urldata.h" /* for the Curl_easy definition */
#include "warnless.h"
#include "curl_base64.h"
#include "non-ascii.h"
@ -169,7 +169,7 @@ CURLcode Curl_base64_decode(const char *src,
}
static CURLcode base64_encode(const char *table64,
struct SessionHandle *data,
struct Curl_easy *data,
const char *inputbuff, size_t insize,
char **outptr, size_t *outlen)
{
@ -190,6 +190,11 @@ static CURLcode base64_encode(const char *table64,
if(!insize)
insize = strlen(indata);
#if SIZEOF_SIZE_T == 4
if(insize > UINT_MAX/4)
return CURLE_OUT_OF_MEMORY;
#endif
base64data = output = malloc(insize * 4 / 3 + 4);
if(!output)
return CURLE_OUT_OF_MEMORY;
@ -283,7 +288,7 @@ static CURLcode base64_encode(const char *table64,
*
* @unittest: 1302
*/
CURLcode Curl_base64_encode(struct SessionHandle *data,
CURLcode Curl_base64_encode(struct Curl_easy *data,
const char *inputbuff, size_t insize,
char **outptr, size_t *outlen)
{
@ -307,7 +312,7 @@ CURLcode Curl_base64_encode(struct SessionHandle *data,
*
* @unittest: 1302
*/
CURLcode Curl_base64url_encode(struct SessionHandle *data,
CURLcode Curl_base64url_encode(struct Curl_easy *data,
const char *inputbuff, size_t insize,
char **outptr, size_t *outlen)
{

View File

@ -55,7 +55,10 @@ my %warnings = (
'COPYRIGHT' => 'file missing a copyright statement',
'BADCOMMAND' => 'bad !checksrc! instruction',
'UNUSEDIGNORE' => 'a warning ignore was not used',
'OPENCOMMENT' => 'file ended with a /* comment still "open"'
'OPENCOMMENT' => 'file ended with a /* comment still "open"',
'ASTERISKSPACE' => 'pointer declared with space after asterisk',
'ASTERISKNOSPACE' => 'pointer declared without space before asterisk',
'ASSIGNWITHINCONDITION' => 'assignment within conditional expression'
);
sub readwhitelist {
@ -241,6 +244,12 @@ sub checksrc {
}
}
sub nostrings {
my ($str) = @_;
$str =~ s/\".*\"//g;
return $str;
}
sub scanfile {
my ($file) = @_;
@ -327,17 +336,35 @@ sub scanfile {
$line, length($1), $file, $l, "\/\/ comment");
}
# check spaces after for/if/while
if($l =~ /^(.*)(for|if|while) \(/) {
my $nostr = nostrings($l);
# check spaces after for/if/while/function call
if($nostr =~ /^(.*)(for|if|while| ([a-zA-Z0-9_]+)) \((.)/) {
if($1 =~ / *\#/) {
# this is a #if, treat it differently
}
elsif($3 eq "return") {
# return must have a space
}
elsif($4 eq "*") {
# (* beginning makes the space OK!
}
elsif($1 =~ / *typedef/) {
# typedefs can use space-paren
}
else {
checkwarn("SPACEBEFOREPAREN", $line, length($1)+length($2), $file, $l,
"$2 with space");
}
}
if($nostr =~ /^((.*)(if) *\()(.*)\)/) {
my $pos = length($1);
if($4 =~ / = /) {
checkwarn("ASSIGNWITHINCONDITION",
$line, $pos+1, $file, $l,
"assignment within conditional expression");
}
}
# check spaces after open parentheses
if($l =~ /^(.*[a-z])\( /i) {
checkwarn("SPACEAFTERPAREN",
@ -421,7 +448,14 @@ sub scanfile {
}
# scan for use of banned functions
if($l =~ /^(.*\W)(sprintf|vsprintf|strcat|strncat|_mbscat|_mbsncat|_tcscat|_tcsncat|wcscat|wcsncat|gets)\s*\(/) {
if($l =~ /^(.*\W)
(gets|
strtok|
v?sprintf|
(str|_mbs|_tcs|_wcs)n?cat|
LoadLibrary(Ex)?(A|W)?)
\s*\(
/x) {
checkwarn("BANNEDFUNC",
$line, length($1), $file, $ol,
"use of $2 is banned");
@ -464,6 +498,31 @@ sub scanfile {
}
}
# check for 'char * name'
if(($l =~ /(^.*(char|int|long|void|curl_slist|CURL|CURLM|CURLMsg|curl_httppost) *(\*+)) (\w+)/) && ($4 ne "const")) {
checkwarn("ASTERISKNOSPACE",
$line, length($1), $file, $ol,
"no space after declarative asterisk");
}
# check for 'char*'
if(($l =~ /(^.*(char|int|long|void|curl_slist|CURL|CURLM|CURLMsg|curl_httppost|sockaddr_in|FILE)\*)/)) {
checkwarn("ASTERISKNOSPACE",
$line, length($1)-1, $file, $ol,
"no space before asterisk");
}
# check for 'void func() {', but avoid false positives by requiring
# both an open and closed parentheses before the open brace
if($l =~ /^((\w).*){\z/) {
my $k = $1;
$k =~ s/const *//;
$k =~ s/static *//;
if($k =~ /\(.*\)/) {
checkwarn("BRACEPOS",
$line, length($l)-1, $file, $ol,
"wrongly placed open brace");
}
}
$line++;
$prevl = $ol;
}

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -98,7 +98,7 @@
#define OS "AmigaOS"
#define PACKAGE "curl"
#define PACKAGE_BUGREPORT "curl-bug@haxx.se"
#define PACKAGE_BUGREPORT "a suitable mailing list: https://curl.haxx.se/mail/"
#define PACKAGE_NAME "curl"
#define PACKAGE_STRING "curl -"
#define PACKAGE_TARNAME "curl"

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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

View File

@ -30,7 +30,6 @@
#include "progress.h"
#include "multiif.h"
#include "sendf.h"
#include "rawstr.h"
#include "conncache.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@ -45,7 +44,7 @@ static void conn_llist_dtor(void *user, void *element)
data->bundle = NULL;
}
static CURLcode bundle_create(struct SessionHandle *data,
static CURLcode bundle_create(struct Curl_easy *data,
struct connectbundle **cb_ptr)
{
(void)data;
@ -133,14 +132,16 @@ static char *hashkey(struct connectdata *conn)
{
const char *hostname;
if(conn->bits.proxy)
hostname = conn->proxy.name;
if(conn->bits.socksproxy)
hostname = conn->socks_proxy.host.name;
else if(conn->bits.httpproxy)
hostname = conn->http_proxy.host.name;
else if(conn->bits.conn_to_host)
hostname = conn->conn_to_host.name;
else
hostname = conn->host.name;
return aprintf("%s:%d", hostname, conn->port);
return aprintf("%s:%ld", hostname, conn->port);
}
/* Look up the bundle with all the connections to the same host this
@ -199,7 +200,7 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
CURLcode result;
struct connectbundle *bundle;
struct connectbundle *new_bundle = NULL;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache);
if(!bundle) {

View File

@ -72,6 +72,7 @@
#include "warnless.h"
#include "conncache.h"
#include "multihandle.h"
#include "system_win32.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@ -103,7 +104,7 @@ struct tcp_keepalive {
#endif
static void
tcpkeepalive(struct SessionHandle *data,
tcpkeepalive(struct Curl_easy *data,
curl_socket_t sockfd)
{
int optval = data->set.tcp_keepalive?1:0;
@ -178,12 +179,12 @@ singleipconnect(struct connectdata *conn,
*
* @unittest: 1303
*/
long Curl_timeleft(struct SessionHandle *data,
time_t Curl_timeleft(struct Curl_easy *data,
struct timeval *nowp,
bool duringconnect)
{
int timeout_set = 0;
long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
time_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
struct timeval now;
/* if a timeout is set, use the most restrictive one */
@ -238,7 +239,7 @@ long Curl_timeleft(struct SessionHandle *data,
static CURLcode bindlocal(struct connectdata *conn,
curl_socket_t sockfd, int af, unsigned int scope)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct Curl_sockaddr_storage sa;
struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
@ -600,6 +601,8 @@ void Curl_persistconninfo(struct connectdata *conn)
{
memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
conn->data->info.conn_scheme = conn->handler->scheme;
conn->data->info.conn_protocol = conn->handler->protocol;
conn->data->info.conn_primary_port = conn->primary_port;
conn->data->info.conn_local_port = conn->local_port;
}
@ -662,7 +665,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
curl_socklen_t len;
struct Curl_sockaddr_storage ssrem;
struct Curl_sockaddr_storage ssloc;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
if(conn->socktype == SOCK_DGRAM)
/* there's no connection! */
@ -719,9 +722,9 @@ CURLcode Curl_is_connected(struct connectdata *conn,
int sockindex,
bool *connected)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
long allow;
time_t allow;
int error = 0;
struct timeval now;
int rc;
@ -761,7 +764,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
#endif
/* check socket for connect */
rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
if(rc == 0) { /* no connection yet */
error = 0;
@ -852,8 +855,10 @@ CURLcode Curl_is_connected(struct connectdata *conn,
return result;
}
if(conn->bits.proxy)
hostname = conn->proxy.name;
if(conn->bits.socksproxy)
hostname = conn->socks_proxy.host.name;
else if(conn->bits.httpproxy)
hostname = conn->http_proxy.host.name;
else if(conn->bits.conn_to_host)
hostname = conn->conn_to_host.name;
else
@ -870,7 +875,7 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
{
#if defined(TCP_NODELAY)
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
#endif
curl_socklen_t onoff = (curl_socklen_t) 1;
int level = IPPROTO_TCP;
@ -912,7 +917,7 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
static void nosigpipe(struct connectdata *conn,
curl_socket_t sockfd)
{
struct SessionHandle *data= conn->data;
struct Curl_easy *data= conn->data;
int onoff = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
sizeof(onoff)) < 0)
@ -945,43 +950,15 @@ void Curl_sndbufset(curl_socket_t sockfd)
int val = CURL_MAX_WRITE_SIZE + 32;
int curval = 0;
int curlen = sizeof(curval);
DWORD majorVersion = 6;
static int detectOsState = DETECT_OS_NONE;
if(detectOsState == DETECT_OS_NONE) {
#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
(_WIN32_WINNT < _WIN32_WINNT_WIN2K)
OSVERSIONINFO osver;
memset(&osver, 0, sizeof(osver));
osver.dwOSVersionInfoSize = sizeof(osver);
detectOsState = DETECT_OS_PREVISTA;
if(GetVersionEx(&osver)) {
if(osver.dwMajorVersion >= majorVersion)
detectOsState = DETECT_OS_VISTA_OR_LATER;
}
#else
ULONGLONG cm;
OSVERSIONINFOEX osver;
memset(&osver, 0, sizeof(osver));
osver.dwOSVersionInfoSize = sizeof(osver);
osver.dwMajorVersion = majorVersion;
cm = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
cm = VerSetConditionMask(cm, VER_MINORVERSION, VER_GREATER_EQUAL);
cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
cm))
if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
VERSION_GREATER_THAN_EQUAL))
detectOsState = DETECT_OS_VISTA_OR_LATER;
else
detectOsState = DETECT_OS_PREVISTA;
#endif
}
if(detectOsState == DETECT_OS_VISTA_OR_LATER)
@ -1012,7 +989,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
int rc = -1;
int error = 0;
bool isconnected = FALSE;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
curl_socket_t sockfd;
CURLcode result;
char ipaddress[MAX_IPADR_LEN];
@ -1111,6 +1088,9 @@ static CURLcode singleipconnect(struct connectdata *conn,
CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
NULL, 0, NULL, NULL);
#elif defined(MSG_FASTOPEN) /* Linux */
if(conn->given->flags & PROTOPT_SSL)
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
else
rc = 0; /* Do nothing */
#endif
}
@ -1173,11 +1153,11 @@ static CURLcode singleipconnect(struct connectdata *conn,
CURLcode Curl_connecthost(struct connectdata *conn, /* context */
const struct Curl_dns_entry *remotehost)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct timeval before = Curl_tvnow();
CURLcode result = CURLE_COULDNT_CONNECT;
long timeout_ms = Curl_timeleft(data, &before, TRUE);
time_t timeout_ms = Curl_timeleft(data, &before, TRUE);
if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */
@ -1232,11 +1212,11 @@ static int conn_is_conn(struct connectdata *conn, void *param)
/*
* Used to extract socket and connectdata struct for the most recent
* transfer on the given SessionHandle.
* transfer on the given Curl_easy.
*
* The returned socket will be CURL_SOCKET_BAD in case of failure!
*/
curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
struct connectdata **connp)
{
curl_socket_t sockfd;
@ -1267,24 +1247,6 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
/* only store this if the caller cares for it */
*connp = c;
sockfd = c->sock[FIRSTSOCKET];
/* we have a socket connected, let's determine if the server shut down */
/* determine if ssl */
if(c->ssl[FIRSTSOCKET].use) {
/* use the SSL context */
if(!Curl_ssl_check_cxn(c))
return CURL_SOCKET_BAD; /* FIN received */
}
/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
#ifdef MSG_PEEK
else if(sockfd != CURL_SOCKET_BAD) {
/* use the socket */
char buf;
if(recv((RECV_TYPE_ARG1)sockfd, (RECV_TYPE_ARG2)&buf,
(RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
return CURL_SOCKET_BAD; /* FIN received */
}
}
#endif
}
else
return CURL_SOCKET_BAD;
@ -1292,6 +1254,33 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
return sockfd;
}
/*
* Check if a connection seems to be alive.
*/
bool Curl_connalive(struct connectdata *conn)
{
/* First determine if ssl */
if(conn->ssl[FIRSTSOCKET].use) {
/* use the SSL context */
if(!Curl_ssl_check_cxn(conn))
return false; /* FIN received */
}
/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
#ifdef MSG_PEEK
else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD)
return false;
else {
/* use the socket */
char buf;
if(recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
(RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
return false; /* FIN received */
}
}
#endif
return true;
}
/*
* Close a socket.
*
@ -1336,7 +1325,7 @@ CURLcode Curl_socket(struct connectdata *conn,
struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct Curl_sockaddr_ex dummy;
if(!addr)
@ -1392,25 +1381,39 @@ CURLcode Curl_socket(struct connectdata *conn,
}
#ifdef CURLDEBUG
/*
* Curl_conncontrol() is used to set the conn->bits.close bit on or off. It
* MUST be called with the connclose() or connkeep() macros with a stated
* reason. The reason is only shown in debug builds but helps to figure out
* decision paths when connections are or aren't re-used as expected.
* Curl_conncontrol() marks streams or connection for closure.
*/
void Curl_conncontrol(struct connectdata *conn, bool closeit,
const char *reason)
{
#if defined(CURL_DISABLE_VERBOSE_STRINGS)
(void) reason;
void Curl_conncontrol(struct connectdata *conn,
int ctrl /* see defines in header */
#ifdef DEBUGBUILD
, const char *reason
#endif
if(closeit != conn->bits.close) {
infof(conn->data, "Marked for [%s]: %s\n", closeit?"closure":"keep alive",
reason);
)
{
/* close if a connection, or a stream that isn't multiplexed */
bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
if((ctrl == CONNCTRL_STREAM) &&
(conn->handler->flags & PROTOPT_STREAM))
DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
else if(closeit != conn->bits.close) {
DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
closeit?"closure":"keep alive", reason));
conn->bits.close = closeit; /* the only place in the source code that
should assign this bit */
}
}
#endif
/* Data received can be cached at various levels, so check them all here. */
bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
{
int readable;
if(Curl_ssl_data_pending(conn, sockindex) ||
Curl_recv_has_postponed_data(conn, sockindex))
return true;
readable = SOCKET_READABLE(conn->sock[sockindex], 0);
return (readable > 0 && (readable & CURL_CSELECT_IN));
}

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -35,7 +35,7 @@ CURLcode Curl_connecthost(struct connectdata *conn,
/* generic function that returns how much time there's left to run, according
to the timeouts set */
long Curl_timeleft(struct SessionHandle *data,
time_t Curl_timeleft(struct Curl_easy *data,
struct timeval *nowp,
bool duringconnect);
@ -45,13 +45,18 @@ long Curl_timeleft(struct SessionHandle *data,
/*
* Used to extract socket and connectdata struct for the most recent
* transfer on the given SessionHandle.
* transfer on the given Curl_easy.
*
* The returned socket will be CURL_SOCKET_BAD in case of failure!
*/
curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
struct connectdata **connp);
/*
* Check if a connection seems to be alive.
*/
bool Curl_connalive(struct connectdata *conn);
#ifdef USE_WINSOCK
/* When you run a program that uses the Windows Sockets API, you may
experience slow performance when you copy data to a TCP server.
@ -104,21 +109,39 @@ CURLcode Curl_socket(struct connectdata *conn,
void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd);
#ifdef CURLDEBUG
/*
* Curl_connclose() sets the bit.close bit to TRUE with an explanation.
* Nothing else.
* Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
* argument specifies if it is the end of a connection or a stream.
*
* For stream-based protocols (such as HTTP/2), a stream close will not cause
* a connection close. Other protocols will close the connection for both
* cases.
*
* It sets the bit.close bit to TRUE (with an explanation for debug builds),
* when the connection will close.
*/
#define CONNCTRL_KEEP 0 /* undo a marked closure */
#define CONNCTRL_CONNECTION 1
#define CONNCTRL_STREAM 2
void Curl_conncontrol(struct connectdata *conn,
bool closeit,
const char *reason);
#define connclose(x,y) Curl_conncontrol(x,TRUE, y)
#define connkeep(x,y) Curl_conncontrol(x, FALSE, y)
int closeit
#ifdef DEBUGBUILD
, const char *reason
#endif
);
#ifdef DEBUGBUILD
#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM, y)
#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION, y)
#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP, y)
#else /* if !CURLDEBUG */
#define connclose(x,y) (x)->bits.close = TRUE
#define connkeep(x,y) (x)->bits.close = FALSE
#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM)
#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION)
#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP)
#endif
bool Curl_conn_data_pending(struct connectdata *conn, int sockindex);
#endif /* HEADER_CURL_CONNECT_H */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -28,8 +28,8 @@
#include <curl/curl.h>
#include "sendf.h"
#include "content_encoding.h"
#include "strdup.h"
#include "curl_memory.h"
#include "memdebug.h"
/* Comment this out if zlib is always going to be at least ver. 1.2.0.4
@ -67,7 +67,7 @@ zfree_cb(voidpf opaque, voidpf ptr)
static CURLcode
process_zlib_error(struct connectdata *conn, z_stream *z)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
if(z->msg)
failf(data, "Error while processing content unencoding: %s",
z->msg);
@ -314,7 +314,7 @@ Curl_unencode_gzip_write(struct connectdata *conn,
#ifndef OLD_ZLIB_SUPPORT
/* Support for old zlib versions is compiled away and we are running with
an old version, so return an error. */
return exit_zlib(z, &k->zlib_init, CURLE_FUNCTION_NOT_FOUND);
return exit_zlib(z, &k->zlib_init, CURLE_WRITE_ERROR);
#else
/* This next mess is to get around the potential case where there isn't
@ -371,12 +371,9 @@ Curl_unencode_gzip_write(struct connectdata *conn,
{
/* Need more gzip header data state */
ssize_t hlen;
unsigned char *oldblock = z->next_in;
z->avail_in += (uInt)nread;
z->next_in = realloc(z->next_in, z->avail_in);
z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
if(z->next_in == NULL) {
free(oldblock);
return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
}
/* Append the new block of data to the previous one */
@ -425,7 +422,7 @@ Curl_unencode_gzip_write(struct connectdata *conn,
void Curl_unencode_cleanup(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
z_stream *z = &k->z;
if(k->zlib_init != ZLIB_UNINIT)

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2016, 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
@ -26,13 +26,13 @@
RECEIVING COOKIE INFORMATION
============================
struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
const char *file, struct CookieInfo *inc, bool newsession);
Inits a cookie struct to store data in a local file. This is always
called before any cookies are set.
struct Cookie *Curl_cookie_add(struct SessionHandle *data,
struct Cookie *Curl_cookie_add(struct Curl_easy *data,
struct CookieInfo *c, bool httpheader, char *lineptr,
const char *domain, const char *path);
@ -90,13 +90,12 @@ Example set of cookies:
#include "urldata.h"
#include "cookie.h"
#include "strequal.h"
#include "strtok.h"
#include "sendf.h"
#include "slist.h"
#include "share.h"
#include "strtoofft.h"
#include "rawstr.h"
#include "strcase.h"
#include "curl_memrchr.h"
#include "inet_pton.h"
@ -126,7 +125,7 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
if(hostname_len < cookie_domain_len)
return FALSE;
if(!Curl_raw_equal(cooke_domain, hostname+hostname_len-cookie_domain_len))
if(!strcasecompare(cooke_domain, hostname+hostname_len-cookie_domain_len))
return FALSE;
/* A lead char of cookie_domain is not '.'.
@ -260,7 +259,7 @@ static char *sanitize_cookie_path(const char *cookie_path)
*
* NOTE: OOM or cookie parsing failures are ignored.
*/
void Curl_cookie_loadfiles(struct SessionHandle *data)
void Curl_cookie_loadfiles(struct Curl_easy *data)
{
struct curl_slist *list = data->change.cookielist;
if(list) {
@ -362,7 +361,7 @@ static bool isip(const char *domain)
***************************************************************************/
struct Cookie *
Curl_cookie_add(struct SessionHandle *data,
Curl_cookie_add(struct Curl_easy *data,
/* The 'data' pointer here may be NULL at times, and thus
must only be used very carefully for things that can deal
with data being NULL. Such as infof() and similar */
@ -469,9 +468,9 @@ Curl_cookie_add(struct SessionHandle *data,
/* this was a "<name>=" with no content, and we must allow
'secure' and 'httponly' specified this weirdly */
done = TRUE;
if(Curl_raw_equal("secure", name))
if(strcasecompare("secure", name))
co->secure = TRUE;
else if(Curl_raw_equal("httponly", name))
else if(strcasecompare("httponly", name))
co->httponly = TRUE;
else if(sep)
/* there was a '=' so we're not done parsing this field */
@ -479,7 +478,7 @@ Curl_cookie_add(struct SessionHandle *data,
}
if(done)
;
else if(Curl_raw_equal("path", name)) {
else if(strcasecompare("path", name)) {
strstore(&co->path, whatptr);
if(!co->path) {
badcookie = TRUE; /* out of memory bad */
@ -491,9 +490,8 @@ Curl_cookie_add(struct SessionHandle *data,
break;
}
}
else if(Curl_raw_equal("domain", name)) {
else if(strcasecompare("domain", name)) {
bool is_ip;
const char *dotp;
/* Now, we make sure that our host is within the given domain,
or the given domain is not valid and thus cannot be set. */
@ -501,12 +499,22 @@ Curl_cookie_add(struct SessionHandle *data,
if('.' == whatptr[0])
whatptr++; /* ignore preceding dot */
is_ip = isip(domain ? domain : whatptr);
#ifndef USE_LIBPSL
/*
* Without PSL we don't know when the incoming cookie is set on a
* TLD or otherwise "protected" suffix. To reduce risk, we require a
* dot OR the exact host name being "localhost".
*/
{
const char *dotp;
/* check for more dots */
dotp = strchr(whatptr, '.');
if(!dotp)
if(!dotp && !strcasecompare("localhost", whatptr))
domain=":";
}
#endif
is_ip = isip(domain ? domain : whatptr);
if(!domain
|| (is_ip && !strcmp(whatptr, domain))
@ -529,14 +537,14 @@ Curl_cookie_add(struct SessionHandle *data,
whatptr);
}
}
else if(Curl_raw_equal("version", name)) {
else if(strcasecompare("version", name)) {
strstore(&co->version, whatptr);
if(!co->version) {
badcookie = TRUE;
break;
}
}
else if(Curl_raw_equal("max-age", name)) {
else if(strcasecompare("max-age", name)) {
/* Defined in RFC2109:
Optional. The Max-Age attribute defines the lifetime of the
@ -552,7 +560,7 @@ Curl_cookie_add(struct SessionHandle *data,
break;
}
}
else if(Curl_raw_equal("expires", name)) {
else if(strcasecompare("expires", name)) {
strstore(&co->expirestr, whatptr);
if(!co->expirestr) {
badcookie = TRUE;
@ -713,7 +721,7 @@ Curl_cookie_add(struct SessionHandle *data,
As far as I can see, it is set to true when the cookie says
.domain.com and to false when the domain is complete www.domain.com
*/
co->tailmatch = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE;
co->tailmatch = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
break;
case 2:
/* It turns out, that sometimes the file format allows the path
@ -742,7 +750,7 @@ Curl_cookie_add(struct SessionHandle *data,
fields++; /* add a field and fall down to secure */
/* FALLTHROUGH */
case 3:
co->secure = Curl_raw_equal(ptr, "TRUE")?TRUE:FALSE;
co->secure = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
break;
case 4:
co->expires = curlx_strtoofft(ptr, NULL, 10);
@ -799,8 +807,8 @@ Curl_cookie_add(struct SessionHandle *data,
/* Check if the domain is a Public Suffix and if yes, ignore the cookie.
This needs a libpsl compiled with builtin data. */
if(domain && co->domain && !isip(co->domain)) {
if(((psl = psl_builtin()) != NULL)
&& !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) {
psl = psl_builtin();
if(psl && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) {
infof(data,
"cookie '%s' dropped, domain '%s' must not set cookies for '%s'\n",
co->name, domain, co->domain);
@ -813,11 +821,12 @@ Curl_cookie_add(struct SessionHandle *data,
clist = c->cookies;
replace_old = FALSE;
while(clist) {
if(Curl_raw_equal(clist->name, co->name)) {
if(strcasecompare(clist->name, co->name)) {
/* the names are identical */
if(clist->domain && co->domain) {
if(Curl_raw_equal(clist->domain, co->domain))
if(strcasecompare(clist->domain, co->domain) &&
(clist->tailmatch == co->tailmatch))
/* The domains are identical */
replace_old=TRUE;
}
@ -828,7 +837,7 @@ Curl_cookie_add(struct SessionHandle *data,
/* the domains were identical */
if(clist->spath && co->spath) {
if(Curl_raw_equal(clist->spath, co->spath)) {
if(strcasecompare(clist->spath, co->spath)) {
replace_old = TRUE;
}
else
@ -902,6 +911,35 @@ Curl_cookie_add(struct SessionHandle *data,
return co;
}
/*
* get_line() makes sure to only return complete whole lines that fit in 'len'
* bytes and end with a newline.
*/
static char *get_line(char *buf, int len, FILE *input)
{
bool partial = FALSE;
while(1) {
char *b = fgets(buf, len, input);
if(b) {
size_t rlen = strlen(b);
if(rlen && (b[rlen-1] == '\n')) {
if(partial) {
partial = FALSE;
continue;
}
return b;
}
else
/* read a partial, discard the next piece that ends with newline */
partial = TRUE;
}
else
break;
}
return NULL;
}
/*****************************************************************************
*
* Curl_cookie_init()
@ -913,7 +951,7 @@ Curl_cookie_add(struct SessionHandle *data,
*
* Returns NULL on out of memory. Invalid cookies are ignored.
****************************************************************************/
struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
const char *file,
struct CookieInfo *inc,
bool newsession)
@ -938,7 +976,7 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
}
c->running = FALSE; /* this is not running, this is init */
if(file && strequal(file, "-")) {
if(file && !strcmp(file, "-")) {
fp = stdin;
fromfile=FALSE;
}
@ -958,7 +996,7 @@ struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
line = malloc(MAX_COOKIE_LINE);
if(!line)
goto fail;
while(fgets(line, MAX_COOKIE_LINE, fp)) {
while(get_line(line, MAX_COOKIE_LINE, fp)) {
if(checkprefix("Set-Cookie:", line)) {
/* This is a cookie line, get it! */
lineptr=&line[11];
@ -1023,6 +1061,40 @@ static int cookie_sort(const void *p1, const void *p2)
return 0;
}
#define CLONE(field) \
do { \
if(src->field) { \
d->field = strdup(src->field); \
if(!d->field) \
goto fail; \
} \
} while(0)
static struct Cookie *dup_cookie(struct Cookie *src)
{
struct Cookie *d = calloc(sizeof(struct Cookie), 1);
if(d) {
CLONE(expirestr);
CLONE(domain);
CLONE(path);
CLONE(spath);
CLONE(name);
CLONE(value);
CLONE(maxage);
CLONE(version);
d->expires = src->expires;
d->tailmatch = src->tailmatch;
d->secure = src->secure;
d->livecookie = src->livecookie;
d->httponly = src->httponly;
}
return d;
fail:
freecookie(d);
return NULL;
}
/*****************************************************************************
*
* Curl_cookie_getlist()
@ -1067,7 +1139,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
/* now check if the domain is correct */
if(!co->domain ||
(co->tailmatch && !is_ip && tailmatch(co->domain, host)) ||
((!co->tailmatch || is_ip) && Curl_raw_equal(host, co->domain)) ) {
((!co->tailmatch || is_ip) && strcasecompare(host, co->domain)) ) {
/* the right part of the host matches the domain stuff in the
cookie data */
@ -1078,11 +1150,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
/* and now, we know this is a match and we should create an
entry for the return-linked-list */
newco = malloc(sizeof(struct Cookie));
newco = dup_cookie(co);
if(newco) {
/* first, copy the whole source cookie: */
memcpy(newco, co, sizeof(struct Cookie));
/* then modify our next */
newco->next = mainco;
@ -1094,12 +1163,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
else {
fail:
/* failure, clear up the allocated chain and return NULL */
while(mainco) {
co = mainco->next;
free(mainco);
mainco = co;
}
Curl_cookie_freelist(mainco);
return NULL;
}
}
@ -1151,7 +1215,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
void Curl_cookie_clearall(struct CookieInfo *cookies)
{
if(cookies) {
Curl_cookie_freelist(cookies->cookies, TRUE);
Curl_cookie_freelist(cookies->cookies);
cookies->cookies = NULL;
cookies->numcookies = 0;
}
@ -1163,21 +1227,14 @@ void Curl_cookie_clearall(struct CookieInfo *cookies)
*
* Free a list of cookies previously returned by Curl_cookie_getlist();
*
* The 'cookiestoo' argument tells this function whether to just free the
* list or actually also free all cookies within the list as well.
*
****************************************************************************/
void Curl_cookie_freelist(struct Cookie *co, bool cookiestoo)
void Curl_cookie_freelist(struct Cookie *co)
{
struct Cookie *next;
while(co) {
next = co->next;
if(cookiestoo)
freecookie(co);
else
free(co); /* we only free the struct since the "members" are all just
pointed out in the main cookie list! */
co = next;
}
}
@ -1232,7 +1289,7 @@ void Curl_cookie_cleanup(struct CookieInfo *c)
{
if(c) {
free(c->filename);
Curl_cookie_freelist(c->cookies, TRUE);
Curl_cookie_freelist(c->cookies);
free(c); /* free the base struct as well */
}
}
@ -1290,7 +1347,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
/* at first, remove expired cookies */
remove_expired(c);
if(strequal("-", dumphere)) {
if(!strcmp("-", dumphere)) {
/* use stdout */
out = stdout;
use_stdout=TRUE;
@ -1326,7 +1383,7 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
return 0;
}
struct curl_slist *Curl_cookie_list(struct SessionHandle *data)
struct curl_slist *Curl_cookie_list(struct Curl_easy *data)
{
struct curl_slist *list = NULL;
struct curl_slist *beg;
@ -1357,7 +1414,7 @@ struct curl_slist *Curl_cookie_list(struct SessionHandle *data)
return list;
}
void Curl_flush_cookies(struct SessionHandle *data, int cleanup)
void Curl_flush_cookies(struct Curl_easy *data, int cleanup)
{
if(data->set.str[STRING_COOKIEJAR]) {
if(data->change.cookielist) {

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -70,19 +70,19 @@ struct CookieInfo {
#define MAX_NAME 1024
#define MAX_NAME_TXT "1023"
struct SessionHandle;
struct Curl_easy;
/*
* Add a cookie to the internal list of cookies. The domain and path arguments
* are only used if the header boolean is TRUE.
*/
struct Cookie *Curl_cookie_add(struct SessionHandle *data,
struct Cookie *Curl_cookie_add(struct Curl_easy *data,
struct CookieInfo *, bool header, char *lineptr,
const char *domain, const char *path);
struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
const char *, bool);
void Curl_cookie_freelist(struct Cookie *cookies, bool cookiestoo);
void Curl_cookie_freelist(struct Cookie *cookies);
void Curl_cookie_clearall(struct CookieInfo *cookies);
void Curl_cookie_clearsess(struct CookieInfo *cookies);
@ -93,12 +93,12 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies);
#define Curl_cookie_cleanup(x) Curl_nop_stmt
#define Curl_flush_cookies(x,y) Curl_nop_stmt
#else
void Curl_flush_cookies(struct SessionHandle *data, int cleanup);
void Curl_flush_cookies(struct Curl_easy *data, int cleanup);
void Curl_cookie_cleanup(struct CookieInfo *);
struct CookieInfo *Curl_cookie_init(struct SessionHandle *data,
struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
const char *, struct CookieInfo *, bool);
struct curl_slist *Curl_cookie_list(struct SessionHandle *data);
void Curl_cookie_loadfiles(struct SessionHandle *data);
struct curl_slist *Curl_cookie_list(struct Curl_easy *data);
void Curl_cookie_loadfiles(struct Curl_easy *data);
#endif
#endif /* HEADER_CURL_COOKIE_H */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2016, 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
@ -47,6 +47,8 @@
# define in_addr_t unsigned long
#endif
#include <stddef.h>
#include "curl_addrinfo.h"
#include "inet_pton.h"
#include "warnless.h"
@ -146,7 +148,8 @@ Curl_getaddrinfo_ex(const char *nodename,
if((size_t)ai->ai_addrlen < ss_size)
continue;
if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) {
ca = malloc(sizeof(Curl_addrinfo));
if(!ca) {
error = EAI_MEMORY;
break;
}
@ -163,7 +166,8 @@ Curl_getaddrinfo_ex(const char *nodename,
ca->ai_canonname = NULL;
ca->ai_next = NULL;
if((ca->ai_addr = malloc(ss_size)) == NULL) {
ca->ai_addr = malloc(ss_size);
if(!ca->ai_addr) {
error = EAI_MEMORY;
free(ca);
break;
@ -171,7 +175,8 @@ Curl_getaddrinfo_ex(const char *nodename,
memcpy(ca->ai_addr, ai->ai_addr, ss_size);
if(ai->ai_canonname != NULL) {
if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) {
ca->ai_canonname = strdup(ai->ai_canonname);
if(!ca->ai_canonname) {
error = EAI_MEMORY;
free(ca->ai_addr);
free(ca);
@ -291,16 +296,19 @@ Curl_he2ai(const struct hostent *he, int port)
#endif
ss_size = sizeof(struct sockaddr_in);
if((ai = calloc(1, sizeof(Curl_addrinfo))) == NULL) {
ai = calloc(1, sizeof(Curl_addrinfo));
if(!ai) {
result = CURLE_OUT_OF_MEMORY;
break;
}
if((ai->ai_canonname = strdup(he->h_name)) == NULL) {
ai->ai_canonname = strdup(he->h_name);
if(!ai->ai_canonname) {
result = CURLE_OUT_OF_MEMORY;
free(ai);
break;
}
if((ai->ai_addr = calloc(1, ss_size)) == NULL) {
ai->ai_addr = calloc(1, ss_size);
if(!ai->ai_addr) {
result = CURLE_OUT_OF_MEMORY;
free(ai->ai_canonname);
free(ai);
@ -475,34 +483,48 @@ Curl_addrinfo *Curl_str2addr(char *address, int port)
/**
* Given a path to a Unix domain socket, return a newly allocated Curl_addrinfo
* struct initialized with this path.
* Set '*longpath' to TRUE if the error is a too long path.
*/
Curl_addrinfo *Curl_unix2addr(const char *path)
Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
{
Curl_addrinfo *ai;
struct sockaddr_un *sa_un;
size_t path_len;
*longpath = FALSE;
ai = calloc(1, sizeof(Curl_addrinfo));
if(!ai)
return NULL;
if((ai->ai_addr = calloc(1, sizeof(struct sockaddr_un))) == NULL) {
ai->ai_addr = calloc(1, sizeof(struct sockaddr_un));
if(!ai->ai_addr) {
free(ai);
return NULL;
}
sa_un = (void *) ai->ai_addr;
sa_un->sun_family = AF_UNIX;
/* sun_path must be able to store the NUL-terminated path */
path_len = strlen(path);
if(path_len >= sizeof(sa_un->sun_path)) {
path_len = strlen(path) + 1;
if(path_len > sizeof(sa_un->sun_path)) {
free(ai->ai_addr);
free(ai);
*longpath = TRUE;
return NULL;
}
ai->ai_family = AF_UNIX;
ai->ai_socktype = SOCK_STREAM; /* assume reliable transport for HTTP */
ai->ai_addrlen = (curl_socklen_t) sizeof(struct sockaddr_un);
sa_un = (void *) ai->ai_addr;
sa_un->sun_family = AF_UNIX;
memcpy(sa_un->sun_path, path, path_len + 1); /* copy NUL byte */
ai->ai_addrlen = (curl_socklen_t)
((offsetof(struct sockaddr_un, sun_path) + path_len) & 0x7FFFFFFF);
/* Abstract Unix domain socket have NULL prefix instead of suffix */
if(abstract)
memcpy(sa_un->sun_path + 1, path, path_len - 1);
else
memcpy(sa_un->sun_path, path, path_len); /* copy NUL byte */
return ai;
}
#endif
@ -563,3 +585,32 @@ curl_dogetaddrinfo(const char *hostname,
}
#endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */
#if defined(HAVE_GETADDRINFO) && defined(USE_RESOLVE_ON_IPS)
/*
* Work-arounds the sin6_port is always zero bug on iOS 9.3.2 and Mac OS X
* 10.11.5.
*/
void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port)
{
Curl_addrinfo *ca;
struct sockaddr_in *addr;
#ifdef ENABLE_IPV6
struct sockaddr_in6 *addr6;
#endif
for(ca = addrinfo; ca != NULL; ca = ca->ai_next) {
switch(ca->ai_family) {
case AF_INET:
addr = (void *)ca->ai_addr; /* storage area for this info */
addr->sin_port = htons((unsigned short)port);
break;
#ifdef ENABLE_IPV6
case AF_INET6:
addr6 = (void *)ca->ai_addr; /* storage area for this info */
addr6->sin6_port = htons((unsigned short)port);
break;
#endif
}
}
}
#endif

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -80,7 +80,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
Curl_addrinfo *Curl_str2addr(char *dotted, int port);
#ifdef USE_UNIX_SOCKETS
Curl_addrinfo *Curl_unix2addr(const char *path);
Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract);
#endif
#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
@ -99,4 +99,12 @@ curl_dogetaddrinfo(const char *hostname,
int line, const char *source);
#endif
#ifdef HAVE_GETADDRINFO
#ifdef USE_RESOLVE_ON_IPS
void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port);
#else
#define Curl_addrinfo_set_port(x,y)
#endif
#endif
#endif /* HEADER_CURL_ADDRINFO_H */

View File

@ -22,10 +22,10 @@
*
***************************************************************************/
CURLcode Curl_base64_encode(struct SessionHandle *data,
CURLcode Curl_base64_encode(struct Curl_easy *data,
const char *inputbuff, size_t insize,
char **outptr, size_t *outlen);
CURLcode Curl_base64url_encode(struct SessionHandle *data,
CURLcode Curl_base64url_encode(struct Curl_easy *data,
const char *inputbuff, size_t insize,
char **outptr, size_t *outlen);

View File

@ -67,7 +67,7 @@
#cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1
/* to make a symbol visible */
#cmakedefine CURL_EXTERN_SYMBOL 1
#cmakedefine CURL_EXTERN_SYMBOL ${CURL_EXTERN_SYMBOL}
/* Ensure using CURL_EXTERN_SYMBOL is possible */
#ifndef CURL_EXTERN_SYMBOL
#define CURL_EXTERN_SYMBOL
@ -518,6 +518,15 @@
/* Define to 1 if you have the send function. */
#cmakedefine HAVE_SEND 1
/* Define to 1 if you have the 'fsetxattr' function. */
#cmakedefine HAVE_FSETXATTR 1
/* fsetxattr() takes 5 args */
#cmakedefine HAVE_FSETXATTR_5 1
/* fsetxattr() takes 6 args */
#cmakedefine HAVE_FSETXATTR_6 1
/* Define to 1 if you have the <setjmp.h> header file. */
#cmakedefine HAVE_SETJMP_H 1
@ -906,6 +915,9 @@
/* Define if you want to enable POSIX threaded DNS lookup */
#cmakedefine USE_THREADS_POSIX 1
/* Define if you want to enable WIN32 threaded DNS lookup */
#cmakedefine USE_THREADS_WIN32 1
/* Define to disable non-blocking sockets. */
#cmakedefine USE_BLOCKING_SOCKETS 1
@ -915,6 +927,9 @@
/* if PolarSSL is enabled */
#cmakedefine USE_POLARSSL 1
/* if mbedTLS is enabled */
#cmakedefine USE_MBEDTLS 1
/* if libSSH2 is in use */
#cmakedefine USE_LIBSSH2 1
@ -930,11 +945,13 @@
/* if OpenSSL is in use */
#cmakedefine USE_OPENSSL 1
/* to enable NGHTTP2 */
#cmakedefine USE_NGHTTP2 1
/* if Unix domain sockets are enabled */
#cmakedefine USE_UNIX_SOCKETS
/* Define to 1 if you are building a Windows target without large file
support. */
/* Define to 1 if you are building a Windows target with large file support. */
#cmakedefine USE_WIN32_LARGE_FILES 1
/* to enable SSPI support */

View File

@ -34,7 +34,7 @@
*
* The function is a port of the Java based oddParity() function over at:
*
* http://davenport.sourceforge.net/ntlm.html
* https://davenport.sourceforge.io/ntlm.html
*
* Parameters:
*

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -37,7 +37,7 @@
*
* Returns the integer.
*/
unsigned short Curl_read16_le(unsigned char *buf)
unsigned short Curl_read16_le(const unsigned char *buf)
{
return (unsigned short)(((unsigned short)buf[0]) |
((unsigned short)buf[1] << 8));
@ -56,7 +56,7 @@ unsigned short Curl_read16_le(unsigned char *buf)
*
* Returns the integer.
*/
unsigned int Curl_read32_le(unsigned char *buf)
unsigned int Curl_read32_le(const unsigned char *buf)
{
return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
@ -77,7 +77,7 @@ unsigned int Curl_read32_le(unsigned char *buf)
* Returns the integer.
*/
#if defined(HAVE_LONGLONG)
unsigned long long Curl_read64_le(unsigned char *buf)
unsigned long long Curl_read64_le(const unsigned char *buf)
{
return ((unsigned long long)buf[0]) |
((unsigned long long)buf[1] << 8) |
@ -89,7 +89,7 @@ unsigned long long Curl_read64_le(unsigned char *buf)
((unsigned long long)buf[7] << 56);
}
#else
unsigned __int64 Curl_read64_le(unsigned char *buf)
unsigned __int64 Curl_read64_le(const unsigned char *buf)
{
return ((unsigned __int64)buf[0]) | ((unsigned __int64)buf[1] << 8) |
((unsigned __int64)buf[2] << 16) | ((unsigned __int64)buf[3] << 24) |
@ -113,7 +113,7 @@ unsigned __int64 Curl_read64_le(unsigned char *buf)
*
* Returns the integer.
*/
unsigned short Curl_read16_be(unsigned char *buf)
unsigned short Curl_read16_be(const unsigned char *buf)
{
return (unsigned short)(((unsigned short)buf[0] << 8) |
((unsigned short)buf[1]));
@ -132,7 +132,7 @@ unsigned short Curl_read16_be(unsigned char *buf)
*
* Returns the integer.
*/
unsigned int Curl_read32_be(unsigned char *buf)
unsigned int Curl_read32_be(const unsigned char *buf)
{
return ((unsigned int)buf[0] << 24) | ((unsigned int)buf[1] << 16) |
((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]);
@ -153,7 +153,7 @@ unsigned int Curl_read32_be(unsigned char *buf)
* Returns the integer.
*/
#if defined(HAVE_LONGLONG)
unsigned long long Curl_read64_be(unsigned char *buf)
unsigned long long Curl_read64_be(const unsigned char *buf)
{
return ((unsigned long long)buf[0] << 56) |
((unsigned long long)buf[1] << 48) |
@ -165,7 +165,7 @@ unsigned long long Curl_read64_be(unsigned char *buf)
((unsigned long long)buf[7]);
}
#else
unsigned __int64 Curl_read64_be(unsigned char *buf)
unsigned __int64 Curl_read64_be(const unsigned char *buf)
{
return ((unsigned __int64)buf[0] << 56) | ((unsigned __int64)buf[1] << 48) |
((unsigned __int64)buf[2] << 40) | ((unsigned __int64)buf[3] << 32) |

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -23,32 +23,32 @@
***************************************************************************/
/* Converts a 16-bit integer from little endian */
unsigned short Curl_read16_le(unsigned char *buf);
unsigned short Curl_read16_le(const unsigned char *buf);
/* Converts a 32-bit integer from little endian */
unsigned int Curl_read32_le(unsigned char *buf);
unsigned int Curl_read32_le(const unsigned char *buf);
#if (CURL_SIZEOF_CURL_OFF_T > 4)
/* Converts a 64-bit integer from little endian */
#if defined(HAVE_LONGLONG)
unsigned long long Curl_read64_le(unsigned char *buf);
unsigned long long Curl_read64_le(const unsigned char *buf);
#else
unsigned __int64 Curl_read64_le(unsigned char *buf);
unsigned __int64 Curl_read64_le(const unsigned char *buf);
#endif
#endif
/* Converts a 16-bit integer from big endian */
unsigned short Curl_read16_be(unsigned char *buf);
unsigned short Curl_read16_be(const unsigned char *buf);
/* Converts a 32-bit integer from big endian */
unsigned int Curl_read32_be(unsigned char *buf);
unsigned int Curl_read32_be(const unsigned char *buf);
#if (CURL_SIZEOF_CURL_OFF_T > 4)
/* Converts a 64-bit integer from big endian */
#if defined(HAVE_LONGLONG)
unsigned long long Curl_read64_be(unsigned char *buf);
unsigned long long Curl_read64_be(const unsigned char *buf);
#else
unsigned __int64 Curl_read64_be(unsigned char *buf);
unsigned __int64 Curl_read64_be(const unsigned char *buf);
#endif
#endif

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -48,8 +48,8 @@
* For libcurl static library release builds no overriding takes place.
*/
int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) {
int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen)
{
#ifndef HAVE_GETHOSTNAME
/* Allow compilation and return failure when unavailable */

View File

@ -33,7 +33,7 @@ static char krb5_oid_bytes[] = "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02";
gss_OID_desc Curl_krb5_mech_oid = { 9, &krb5_oid_bytes };
OM_uint32 Curl_gss_init_sec_context(
struct SessionHandle *data,
struct Curl_easy *data,
OM_uint32 *minor_status,
gss_ctx_id_t *context,
gss_name_t target_name,
@ -114,7 +114,7 @@ static size_t display_gss_error(OM_uint32 status, int type,
* major [in] - The major status code.
* minor [in] - The minor status code.
*/
void Curl_gss_log_error(struct SessionHandle *data, const char *prefix,
void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
OM_uint32 major, OM_uint32 minor)
{
char buf[GSS_LOG_BUFFER_LEN];

View File

@ -44,7 +44,7 @@ extern gss_OID_desc Curl_krb5_mech_oid;
/* Common method for using GSS-API */
OM_uint32 Curl_gss_init_sec_context(
struct SessionHandle *data,
struct Curl_easy *data,
OM_uint32 *minor_status,
gss_ctx_id_t *context,
gss_name_t target_name,
@ -56,7 +56,7 @@ OM_uint32 Curl_gss_init_sec_context(
OM_uint32 *ret_flags);
/* Helper to log a GSS-API error status */
void Curl_gss_log_error(struct SessionHandle *data, const char *prefix,
void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
OM_uint32 major, OM_uint32 minor);
/* Provide some definitions missing in old headers */

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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

View File

@ -27,7 +27,7 @@
/*
* NTLM details:
*
* http://davenport.sourceforge.net/ntlm.html
* https://davenport.sourceforge.io/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
@ -76,6 +76,11 @@
# define MD5_DIGEST_LENGTH 16
# define MD4_DIGEST_LENGTH 16
#elif defined(USE_MBEDTLS)
# include <mbedtls/des.h>
# include <mbedtls/md4.h>
#elif defined(USE_NSS)
# include <nss.h>
@ -100,7 +105,7 @@
#include "urldata.h"
#include "non-ascii.h"
#include "rawstr.h"
#include "strcase.h"
#include "curl_ntlm_core.h"
#include "curl_md5.h"
#include "curl_hmac.h"
@ -188,6 +193,26 @@ static void setup_des_key(const unsigned char *key_56,
gcry_cipher_setkey(*des, key, sizeof(key));
}
#elif defined(USE_MBEDTLS)
static bool encrypt_des(const unsigned char *in, unsigned char *out,
const unsigned char *key_56)
{
mbedtls_des_context ctx;
char key[8];
/* Expand the 56-bit key to 64-bits */
extend_key_56_to_64(key_56, key);
/* Set the key parity to odd */
mbedtls_des_key_set_parity((unsigned char *) key);
/* Perform the encryption */
mbedtls_des_init(&ctx);
mbedtls_des_setkey_enc(&ctx, (unsigned char *) key);
return mbedtls_des_crypt_ecb(&ctx, in, out) == 0;
}
#elif defined(USE_NSS)
/*
@ -400,8 +425,8 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
setup_des_key(keys + 14, &des);
gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
gcry_cipher_close(des);
#elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) \
|| defined(USE_WIN32_CRYPTO)
#elif defined(USE_MBEDTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) \
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(plaintext, results, keys);
encrypt_des(plaintext, results + 8, keys + 7);
encrypt_des(plaintext, results + 16, keys + 14);
@ -411,7 +436,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
/*
* Set up lanmanager hashed password
*/
CURLcode Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data,
CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
const char *password,
unsigned char *lmbuffer /* 21 bytes */)
{
@ -464,8 +489,8 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data,
setup_des_key(pw + 7, &des);
gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
gcry_cipher_close(des);
#elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) \
|| defined(USE_WIN32_CRYPTO)
#elif defined(USE_MBEDTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) \
|| defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
encrypt_des(magic, lmbuffer, pw);
encrypt_des(magic, lmbuffer + 8, pw + 7);
#endif
@ -505,7 +530,7 @@ static void ascii_uppercase_to_unicode_le(unsigned char *dest,
* Set up nt hashed passwords
* @unittest: 1600
*/
CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
const char *password,
unsigned char *ntbuffer /* 21 bytes */)
{
@ -543,6 +568,8 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
gcry_md_write(MD4pw, pw, 2 * len);
memcpy(ntbuffer, gcry_md_read(MD4pw, 0), MD4_DIGEST_LENGTH);
gcry_md_close(MD4pw);
#elif defined(USE_MBEDTLS)
mbedtls_md4(pw, 2 * len, ntbuffer);
#elif defined(USE_NSS) || defined(USE_OS400CRYPTO)
Curl_md4it(ntbuffer, pw, 2 * len);
#elif defined(USE_DARWINSSL)
@ -688,8 +715,10 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
/* Create the BLOB structure */
snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
NTLMv2_BLOB_SIGNATURE
"%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */
"%c%c%c%c", /* Reserved = 0 */
NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
0, 0, 0, 0);
Curl_write64_le(tw, ptr + 24);

View File

@ -64,12 +64,12 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
const unsigned char *plaintext,
unsigned char *results);
CURLcode Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data,
CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
const char *password,
unsigned char *lmbuffer /* 21 bytes */);
#if USE_NTRESPONSES
CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
const char *password,
unsigned char *ntbuffer /* 21 bytes */);

View File

@ -28,7 +28,7 @@
/*
* NTLM details:
*
* http://davenport.sourceforge.net/ntlm.html
* https://davenport.sourceforge.io/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
@ -51,6 +51,7 @@
#include "curl_ntlm_wb.h"
#include "url.h"
#include "strerror.h"
#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@ -156,7 +157,8 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
}
slash = strpbrk(username, "\\/");
if(slash) {
if((domain = strdup(username)) == NULL)
domain = strdup(username);
if(!domain)
return CURLE_OUT_OF_MEMORY;
slash = domain + (slash - username);
*slash = '\0';
@ -293,11 +295,10 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
buf[len_out - 1] = '\0';
break;
}
newbuf = realloc(buf, len_out + NTLM_BUFSIZE);
if(!newbuf) {
free(buf);
newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE);
if(!newbuf)
return CURLE_OUT_OF_MEMORY;
}
buf = newbuf;
}
@ -349,7 +350,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
if(proxy) {
allocuserpwd = &conn->allocptr.proxyuserpwd;
userp = conn->proxyuser;
userp = conn->http_proxy.user;
ntlm = &conn->proxyntlm;
authp = &conn->data->state.authproxy;
}

View File

@ -42,8 +42,6 @@
#include "curl_sasl.h"
#include "warnless.h"
#include "strtok.h"
#include "strequal.h"
#include "rawstr.h"
#include "sendf.h"
#include "non-ascii.h" /* included for Curl_convert_... prototypes */
/* The last 3 #include files should be in this order */
@ -159,7 +157,7 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
sasl->prefmech = SASL_AUTH_NONE;
}
if(strnequal(value, "*", len))
if(!strncmp(value, "*", len))
sasl->prefmech = SASL_AUTH_DEFAULT;
else {
mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
@ -257,13 +255,16 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
bool force_ir, saslprogress *progress)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
unsigned int enabledmechs;
const char *mech = NULL;
char *resp = NULL;
size_t len = 0;
saslstate state1 = SASL_STOP;
saslstate state2 = SASL_FINAL;
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
#if defined(USE_KERBEROS5)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
@ -288,7 +289,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
}
else if(conn->bits.user_passwd) {
#if defined(USE_KERBEROS5)
if(enabledmechs & SASL_MECH_GSSAPI) {
if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() &&
Curl_auth_user_contains_domain(conn->user)) {
sasl->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */
mech = SASL_MECH_STRING_GSSAPI;
state1 = SASL_GSSAPI;
@ -308,7 +310,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
else
#endif
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(enabledmechs & SASL_MECH_DIGEST_MD5) {
if((enabledmechs & SASL_MECH_DIGEST_MD5) &&
Curl_auth_is_digest_supported()) {
mech = SASL_MECH_STRING_DIGEST_MD5;
state1 = SASL_DIGESTMD5;
sasl->authused = SASL_MECH_DIGEST_MD5;
@ -321,7 +324,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
else
#endif
#ifdef USE_NTLM
if(enabledmechs & SASL_MECH_NTLM) {
if((enabledmechs & SASL_MECH_NTLM) && Curl_auth_is_ntlm_supported()) {
mech = SASL_MECH_STRING_NTLM;
state1 = SASL_NTLM;
state2 = SASL_NTLM_TYPE2MSG;
@ -341,8 +344,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
if(force_ir || data->set.sasl_ir)
result = Curl_auth_create_oauth_bearer_message(data, conn->user,
conn->host.name,
conn->port,
hostname,
port,
conn->oauth_bearer,
&resp, &len);
}
@ -405,9 +408,12 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
int code, saslprogress *progress)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
saslstate newstate = SASL_FINAL;
char *resp = NULL;
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
char *serverdata;
char *chlg = NULL;
@ -542,8 +548,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
/* Create the authorisation message */
if(sasl->authused == SASL_MECH_OAUTHBEARER) {
result = Curl_auth_create_oauth_bearer_message(data, conn->user,
conn->host.name,
conn->port,
hostname,
port,
conn->oauth_bearer,
&resp, &len);

View File

@ -24,7 +24,7 @@
#include <curl/curl.h>
struct SessionHandle;
struct Curl_easy;
struct connectdata;
/* Authentication mechanism flags */

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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

View File

@ -82,6 +82,10 @@
# include "config-linux.h"
#endif
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
# include "config-linux.h"
#endif
#ifdef __APPLE__ && __MACH__
# include "config-osx.h"
#endif
@ -229,6 +233,15 @@
# include "setup-vms.h"
#endif
/*
* Use getaddrinfo to resolve the IPv4 address literal. If the current network
* interface doesnt support IPv4, but supports IPv6, NAT64, and DNS64,
* performing this task will result in a synthesized IPv6 address.
*/
#ifdef __APPLE__
#define USE_RESOLVE_ON_IPS 1
#endif
/*
* Include header files for windows builds before redefining anything.
* Use this preprocessor block only to include or exclude windows.h,
@ -598,10 +611,9 @@ int netware_init(void);
#endif
#endif
#if defined(HAVE_LIBIDN) && defined(HAVE_TLD_H)
/* The lib was present and the tld.h header (which is missing in libidn 0.3.X
but we only work with libidn 0.4.1 or later) */
#define USE_LIBIDN
#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H)
/* The lib and header are present */
#define USE_LIBIDN2
#endif
#ifndef SIZEOF_TIME_T
@ -637,6 +649,13 @@ int netware_init(void);
defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
#define USE_NTLM
#elif defined(USE_MBEDTLS)
# include <mbedtls/md4.h>
# if defined(MBEDTLS_MD4_C)
#define USE_NTLM
# endif
#endif
#endif
@ -745,4 +764,14 @@ endings either CRLF or LF so 't' is appropriate.
# endif
#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */
/* Detect Windows App environment which has a restricted access
* to the Win32 APIs. */
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)
# include <winapifamily.h>
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
# define CURL_WINDOWS_APP
# endif
# endif
#endif /* HEADER_CURL_SETUP_H */

View File

@ -64,10 +64,15 @@ PSecurityFunctionTable s_pSecFn = NULL;
*
* Once this function has been executed, Windows SSPI functions can be
* called through the Security Service Provider Interface dispatch table.
*
* Parameters:
*
* None.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_sspi_global_init(void)
{
bool securityDll = FALSE;
INITSECURITYINTERFACE_FN pInitSecurityInterface;
/* If security interface is not yet initialized try to do this */
@ -75,49 +80,9 @@ CURLcode Curl_sspi_global_init(void)
/* Security Service Provider Interface (SSPI) functions are located in
* security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP
* have both these DLLs (security.dll forwards calls to secur32.dll) */
DWORD majorVersion = 4;
DWORD platformId = VER_PLATFORM_WIN32_NT;
#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
(_WIN32_WINNT < _WIN32_WINNT_WIN2K)
OSVERSIONINFO osver;
memset(&osver, 0, sizeof(osver));
osver.dwOSVersionInfoSize = sizeof(osver);
/* Find out Windows version */
if(!GetVersionEx(&osver))
return CURLE_FAILED_INIT;
/* Verify the major version number == 4 and platform id == WIN_NT */
if(osver.dwMajorVersion == majorVersion &&
osver.dwPlatformId == platformId)
securityDll = TRUE;
#else
ULONGLONG cm;
OSVERSIONINFOEX osver;
memset(&osver, 0, sizeof(osver));
osver.dwOSVersionInfoSize = sizeof(osver);
osver.dwMajorVersion = majorVersion;
osver.dwPlatformId = platformId;
cm = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
cm = VerSetConditionMask(cm, VER_MINORVERSION, VER_GREATER_EQUAL);
cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL);
cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL);
/* Verify the major version number == 4 and platform id == WIN_NT */
if(VerifyVersionInfo(&osver, (VER_MAJORVERSION | VER_MINORVERSION |
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR |
VER_PLATFORMID),
cm))
securityDll = TRUE;
#endif
/* Load SSPI dll into the address space of the calling process */
if(securityDll)
if(Curl_verify_windows_version(4, 0, PLATFORM_WINNT, VERSION_EQUAL))
s_hSecDll = Curl_load_library(TEXT("security.dll"));
else
s_hSecDll = Curl_load_library(TEXT("secur32.dll"));
@ -143,8 +108,11 @@ CURLcode Curl_sspi_global_init(void)
* Curl_sspi_global_cleanup()
*
* This deinitializes the Security Service Provider Interface from libcurl.
*
* Parameters:
*
* None.
*/
void Curl_sspi_global_cleanup(void)
{
if(s_hSecDll) {
@ -246,6 +214,15 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
return CURLE_OK;
}
/*
* Curl_sspi_free_identity()
*
* This is used to free the contents of a SSPI identifier structure.
*
* Parameters:
*
* identity [in/out] - The identity structure.
*/
void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity)
{
if(identity) {

View File

@ -100,6 +100,7 @@ int Curl_thread_join(curl_thread_t *hnd)
#elif defined(USE_THREADS_WIN32)
/* !checksrc! disable SPACEBEFOREPAREN 1 */
curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
void *arg)
{

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -50,6 +50,7 @@
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
/* !checksrc! disable SPACEBEFOREPAREN 1 */
curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
void *arg);

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -34,8 +34,8 @@
functions while they still are offered publicly. They will be made library-
private one day */
#include "strequal.h"
/* "strequal.h" provides the strequal protos */
#include "strcase.h"
/* "strcase.h" provides the strcasecompare protos */
#include "strtoofft.h"
/* "strtoofft.h" provides this function: curlx_strtoofft(), returns a
@ -67,15 +67,12 @@
be removed from a future libcurl official API:
curlx_getenv
curlx_mprintf (and its variations)
curlx_strequal
curlx_strnequal
curlx_strcasecompare
curlx_strncasecompare
*/
#define curlx_getenv curl_getenv
#define curlx_strequal curl_strequal
#define curlx_strnequal curl_strnequal
#define curlx_raw_equal Curl_raw_equal
#define curlx_mvsnprintf curl_mvsnprintf
#define curlx_msnprintf curl_msnprintf
#define curlx_maprintf curl_maprintf

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -52,11 +52,10 @@
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
#include "escape.h"
#include "progress.h"
#include "strequal.h"
#include "dict.h"
#include "rawstr.h"
#include "strcase.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
@ -91,17 +90,17 @@ const struct Curl_handler Curl_handler_dict = {
PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
};
static char *unescape_word(struct SessionHandle *data, const char *inputbuff)
static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
{
char *newp;
char *dictp;
char *ptr;
int len;
size_t len;
char ch;
int olen=0;
newp = curl_easy_unescape(data, inputbuff, 0, &len);
if(!newp)
CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
if(!newp || result)
return NULL;
dictp = malloc(((size_t)len)*2 + 1); /* add one for terminating zero */
@ -133,7 +132,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
char *nthdef = NULL; /* This is not part of the protocol, but required
by RFC 2229 */
CURLcode result=CURLE_OK;
struct SessionHandle *data=conn->data;
struct Curl_easy *data=conn->data;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
char *path = data->state.path;
@ -145,9 +144,9 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
/* AUTH is missing */
}
if(Curl_raw_nequal(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
Curl_raw_nequal(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
Curl_raw_nequal(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {
if(strncasecompare(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
strncasecompare(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
strncasecompare(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {
word = strchr(path, ':');
if(word) {
@ -203,9 +202,9 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL); /* no upload */
}
else if(Curl_raw_nequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
Curl_raw_nequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
Curl_raw_nequal(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) {
else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
strncasecompare(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) {
word = strchr(path, ':');
if(word) {

View File

@ -50,7 +50,6 @@
#include <sys/param.h>
#endif
#include "strequal.h"
#include "urldata.h"
#include <curl/curl.h>
#include "transfer.h"
@ -144,28 +143,6 @@ static CURLcode win32_init(void)
return CURLE_OK;
}
#ifdef USE_LIBIDN
/*
* Initialise use of IDNA library.
* It falls back to ASCII if $CHARSET isn't defined. This doesn't work for
* idna_to_ascii_lz().
*/
static void idna_init (void)
{
#ifdef WIN32
char buf[60];
UINT cp = GetACP();
if(!getenv("CHARSET") && cp > 0) {
snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp);
putenv(buf);
}
#else
/* to do? */
#endif
}
#endif /* USE_LIBIDN */
/* true globals -- for curl_global_init() and curl_global_cleanup() */
static unsigned int initialized;
static long init_flags;
@ -217,7 +194,7 @@ curl_calloc_callback Curl_ccalloc;
#endif
/**
* curl_global_init() globally initializes cURL given a bitwise set of the
* curl_global_init() globally initializes curl given a bitwise set of the
* different features of what to initialize.
*/
static CURLcode global_init(long flags, bool memoryfuncs)
@ -262,15 +239,13 @@ static CURLcode global_init(long flags, bool memoryfuncs)
}
#endif
#ifdef USE_LIBIDN
idna_init();
#endif
if(Curl_resolver_global_init()) {
DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
return CURLE_FAILED_INIT;
}
(void)Curl_ipv6works();
#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT)
if(libssh2_init(0)) {
DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
@ -290,7 +265,7 @@ static CURLcode global_init(long flags, bool memoryfuncs)
/**
* curl_global_init() globally initializes cURL given a bitwise set of the
* curl_global_init() globally initializes curl given a bitwise set of the
* different features of what to initialize.
*/
CURLcode curl_global_init(long flags)
@ -299,7 +274,7 @@ CURLcode curl_global_init(long flags)
}
/*
* curl_global_init_mem() globally initializes cURL and also registers the
* curl_global_init_mem() globally initializes curl and also registers the
* user provided callback routines.
*/
CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
@ -331,7 +306,7 @@ CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
}
/**
* curl_global_cleanup() globally cleanups cURL, uses the value of
* curl_global_cleanup() globally cleanups curl, uses the value of
* "init_flags" to determine what needs to be cleaned up and what doesn't.
*/
void curl_global_cleanup(void)
@ -365,10 +340,10 @@ void curl_global_cleanup(void)
* curl_easy_init() is the external interface to alloc, setup and init an
* easy handle that is returned. If anything goes wrong, NULL is returned.
*/
CURL *curl_easy_init(void)
struct Curl_easy *curl_easy_init(void)
{
CURLcode result;
struct SessionHandle *data;
struct Curl_easy *data;
/* Make sure we inited the global SSL stuff */
if(!initialized) {
@ -396,13 +371,12 @@ CURL *curl_easy_init(void)
*/
#undef curl_easy_setopt
CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
{
va_list arg;
struct SessionHandle *data = curl;
CURLcode result;
if(!curl)
if(!data)
return CURLE_BAD_FUNCTION_ARGUMENT;
va_start(arg, tag);
@ -434,7 +408,7 @@ struct events {
* updated.
*/
static int events_timer(CURLM *multi, /* multi handle */
static int events_timer(struct Curl_multi *multi, /* multi handle */
long timeout_ms, /* see above */
void *userp) /* private callback pointer */
{
@ -489,7 +463,7 @@ static short socketcb2poll(int pollmask)
* Callback that gets called with information about socket activity to
* monitor.
*/
static int events_socket(CURL *easy, /* easy handle */
static int events_socket(struct Curl_easy *easy, /* easy handle */
curl_socket_t s, /* socket */
int what, /* see above */
void *userp, /* private callback
@ -567,7 +541,7 @@ static int events_socket(CURL *easy, /* easy handle */
*
* Do the multi handle setups that only event-based transfers need.
*/
static void events_setup(CURLM *multi, struct events *ev)
static void events_setup(struct Curl_multi *multi, struct events *ev)
{
/* timer callback */
curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer);
@ -671,7 +645,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
*
* Runs a transfer in a blocking manner using the events-based API
*/
static CURLcode easy_events(CURLM *multi)
static CURLcode easy_events(struct Curl_multi *multi)
{
struct events evs= {2, FALSE, 0, NULL, 0};
@ -685,7 +659,7 @@ static CURLcode easy_events(CURLM *multi)
#define easy_events(x) CURLE_NOT_BUILT_IN
#endif
static CURLcode easy_transfer(CURLM *multi)
static CURLcode easy_transfer(struct Curl_multi *multi)
{
bool done = FALSE;
CURLMcode mcode = CURLM_OK;
@ -765,9 +739,9 @@ static CURLcode easy_transfer(CURLM *multi)
* DEBUG: if 'events' is set TRUE, this function will use a replacement engine
* instead of curl_multi_perform() and use curl_multi_socket_action().
*/
static CURLcode easy_perform(struct SessionHandle *data, bool events)
static CURLcode easy_perform(struct Curl_easy *data, bool events)
{
CURLM *multi;
struct Curl_multi *multi;
CURLMcode mcode;
CURLcode result = CURLE_OK;
SIGPIPE_VARIABLE(pipe_st);
@ -827,9 +801,9 @@ static CURLcode easy_perform(struct SessionHandle *data, bool events)
* curl_easy_perform() is the external interface that performs a blocking
* transfer as previously setup.
*/
CURLcode curl_easy_perform(CURL *easy)
CURLcode curl_easy_perform(struct Curl_easy *data)
{
return easy_perform(easy, FALSE);
return easy_perform(data, FALSE);
}
#ifdef CURLDEBUG
@ -837,9 +811,9 @@ CURLcode curl_easy_perform(CURL *easy)
* curl_easy_perform_ev() is the external interface that performs a blocking
* transfer using the event-based API internally.
*/
CURLcode curl_easy_perform_ev(CURL *easy)
CURLcode curl_easy_perform_ev(struct Curl_easy *data)
{
return easy_perform(easy, TRUE);
return easy_perform(data, TRUE);
}
#endif
@ -848,9 +822,8 @@ CURLcode curl_easy_perform_ev(CURL *easy)
* curl_easy_cleanup() is the external interface to cleaning/freeing the given
* easy handle.
*/
void curl_easy_cleanup(CURL *curl)
void curl_easy_cleanup(struct Curl_easy *data)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
SIGPIPE_VARIABLE(pipe_st);
if(!data)
@ -866,12 +839,11 @@ void curl_easy_cleanup(CURL *curl)
* information from a performed transfer and similar.
*/
#undef curl_easy_getinfo
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
CURLcode curl_easy_getinfo(struct Curl_easy *data, CURLINFO info, ...)
{
va_list arg;
void *paramp;
CURLcode result;
struct SessionHandle *data = (struct SessionHandle *)curl;
va_start(arg, info);
paramp = va_arg(arg, void *);
@ -887,11 +859,9 @@ CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
* given input easy handle. The returned handle will be a new working handle
* with all options set exactly as the input source handle.
*/
CURL *curl_easy_duphandle(CURL *incurl)
struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
{
struct SessionHandle *data=(struct SessionHandle *)incurl;
struct SessionHandle *outcurl = calloc(1, sizeof(struct SessionHandle));
struct Curl_easy *outcurl = calloc(1, sizeof(struct Curl_easy));
if(NULL == outcurl)
goto fail;
@ -900,6 +870,11 @@ CURL *curl_easy_duphandle(CURL *incurl)
* get setup on-demand in the code, as that would probably decrease
* the likeliness of us forgetting to init a buffer here in the future.
*/
outcurl->set.buffer_size = data->set.buffer_size;
outcurl->state.buffer = malloc(CURL_BUFSIZE(outcurl->set.buffer_size) + 1);
if(!outcurl->state.buffer)
goto fail;
outcurl->state.headerbuff = malloc(HEADERSIZE);
if(!outcurl->state.headerbuff)
goto fail;
@ -957,6 +932,8 @@ CURL *curl_easy_duphandle(CURL *incurl)
Curl_convert_setup(outcurl);
Curl_initinfo(outcurl);
outcurl->magic = CURLEASY_MAGIC_NUMBER;
/* we reach this point and thus we are OK */
@ -968,6 +945,7 @@ CURL *curl_easy_duphandle(CURL *incurl)
if(outcurl) {
curl_slist_free_all(outcurl->change.cookielist);
outcurl->change.cookielist = NULL;
Curl_safefree(outcurl->state.buffer);
Curl_safefree(outcurl->state.headerbuff);
Curl_safefree(outcurl->change.url);
Curl_safefree(outcurl->change.referer);
@ -982,10 +960,8 @@ CURL *curl_easy_duphandle(CURL *incurl)
* curl_easy_reset() is an external interface that allows an app to re-
* initialize a session handle to the default values.
*/
void curl_easy_reset(CURL *curl)
void curl_easy_reset(struct Curl_easy *data)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
Curl_safefree(data->state.pathbuffer);
data->state.path = NULL;
@ -1000,6 +976,9 @@ void curl_easy_reset(CURL *curl)
/* zero out Progress data: */
memset(&data->progress, 0, sizeof(struct Progress));
/* zero out PureInfo data: */
Curl_initinfo(data);
data->progress.flags |= PGRS_HIDE;
data->state.current_speed = -1; /* init to negative == impossible */
}
@ -1014,9 +993,8 @@ void curl_easy_reset(CURL *curl)
*
* Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
*/
CURLcode curl_easy_pause(CURL *curl, int action)
CURLcode curl_easy_pause(struct Curl_easy *data, int action)
{
struct SessionHandle *data = (struct SessionHandle *)curl;
struct SingleRequest *k = &data->req;
CURLcode result = CURLE_OK;
@ -1050,13 +1028,13 @@ CURLcode curl_easy_pause(CURL *curl, int action)
if(!result &&
((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
Curl_expire(data, 1); /* get this handle going again */
Curl_expire(data, 0); /* get this handle going again */
return result;
}
static CURLcode easy_connection(struct SessionHandle *data,
static CURLcode easy_connection(struct Curl_easy *data,
curl_socket_t *sfd,
struct connectdata **connp)
{
@ -1084,13 +1062,13 @@ static CURLcode easy_connection(struct SessionHandle *data,
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
* Returns CURLE_OK on success, error code on error.
*/
CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n)
CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen,
size_t *n)
{
curl_socket_t sfd;
CURLcode result;
ssize_t n1;
struct connectdata *c;
struct SessionHandle *data = (struct SessionHandle *)curl;
result = easy_connection(data, &sfd, &c);
if(result)
@ -1111,14 +1089,13 @@ CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n)
* Sends data over the connected socket. Use after successful
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
*/
CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen,
size_t *n)
CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,
size_t buflen, size_t *n)
{
curl_socket_t sfd;
CURLcode result;
ssize_t n1;
struct connectdata *c = NULL;
struct SessionHandle *data = (struct SessionHandle *)curl;
result = easy_connection(data, &sfd, &c);
if(result)

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -26,7 +26,7 @@
* Prototypes for library-wide functions provided by easy.c
*/
#ifdef CURLDEBUG
CURL_EXTERN CURLcode curl_easy_perform_ev(CURL *easy);
CURL_EXTERN CURLcode curl_easy_perform_ev(struct Curl_easy *easy);
#endif
#endif /* HEADER_CURL_EASYIF_H */

View File

@ -31,6 +31,7 @@
#include "warnless.h"
#include "non-ascii.h"
#include "escape.h"
#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@ -75,17 +76,24 @@ char *curl_unescape(const char *string, int length)
return curl_easy_unescape(NULL, string, length, NULL);
}
char *curl_easy_escape(CURL *handle, const char *string, int inlength)
char *curl_easy_escape(struct Curl_easy *data, const char *string,
int inlength)
{
size_t alloc = (inlength?(size_t)inlength:strlen(string))+1;
size_t alloc;
char *ns;
char *testing_ptr = NULL;
unsigned char in; /* we need to treat the characters unsigned */
size_t newlen = alloc;
size_t newlen;
size_t strindex=0;
size_t length;
CURLcode result;
if(inlength < 0)
return NULL;
alloc = (inlength?(size_t)inlength:strlen(string))+1;
newlen = alloc;
ns = malloc(alloc);
if(!ns)
return NULL;
@ -102,17 +110,15 @@ char *curl_easy_escape(CURL *handle, const char *string, int inlength)
newlen += 2; /* the size grows with two, since this'll become a %XX */
if(newlen > alloc) {
alloc *= 2;
testing_ptr = realloc(ns, alloc);
if(!testing_ptr) {
free(ns);
testing_ptr = Curl_saferealloc(ns, alloc);
if(!testing_ptr)
return NULL;
}
else {
ns = testing_ptr;
}
}
result = Curl_convert_to_network(handle, &in, 1);
result = Curl_convert_to_network(data, &in, 1);
if(result) {
/* Curl_convert_to_network calls failf if unsuccessful */
free(ns);
@ -139,7 +145,7 @@ char *curl_easy_escape(CURL *handle, const char *string, int inlength)
* *olen. If length == 0, the length is assumed to be strlen(string).
*
*/
CURLcode Curl_urldecode(struct SessionHandle *data,
CURLcode Curl_urldecode(struct Curl_easy *data,
const char *string, size_t length,
char **ostring, size_t *olen,
bool reject_ctrl)
@ -206,18 +212,26 @@ CURLcode Curl_urldecode(struct SessionHandle *data,
* If length == 0, the length is assumed to be strlen(string).
* If olen == NULL, no output length is stored.
*/
char *curl_easy_unescape(CURL *handle, const char *string, int length,
int *olen)
char *curl_easy_unescape(struct Curl_easy *data, const char *string,
int length, int *olen)
{
char *str = NULL;
if(length >= 0) {
size_t inputlen = length;
size_t outputlen;
CURLcode res = Curl_urldecode(handle, string, inputlen, &str, &outputlen,
CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen,
FALSE);
if(res)
return NULL;
if(olen)
if(olen) {
if(outputlen <= (size_t) INT_MAX)
*olen = curlx_uztosi(outputlen);
else
/* too large to return in an int, fail! */
Curl_safefree(str);
}
}
return str;
}

View File

@ -24,7 +24,7 @@
/* Escape and unescape URL encoding in strings. The functions return a new
* allocated string or NULL if an error occurred. */
CURLcode Curl_urldecode(struct SessionHandle *data,
CURLcode Curl_urldecode(struct Curl_easy *data,
const char *string, size_t length,
char **ostring, size_t *olen,
bool reject_crlf);

View File

@ -135,7 +135,7 @@ static CURLcode file_range(struct connectdata *conn)
curl_off_t totalsize=-1;
char *ptr;
char *ptr2;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
if(data->state.use_range && data->state.range) {
from=curlx_strtoofft(data->state.range, &ptr, 0);
@ -185,19 +185,20 @@ static CURLcode file_range(struct connectdata *conn)
*/
static CURLcode file_connect(struct connectdata *conn, bool *done)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
char *real_path;
struct FILEPROTO *file = data->req.protop;
int fd;
#ifdef DOS_FILESYSTEM
int i;
size_t i;
char *actual_path;
#endif
int real_path_len;
size_t real_path_len;
real_path = curl_easy_unescape(data, data->state.path, 0, &real_path_len);
if(!real_path)
return CURLE_OUT_OF_MEMORY;
CURLcode result = Curl_urldecode(data, data->state.path, 0, &real_path,
&real_path_len, FALSE);
if(result)
return result;
#ifdef DOS_FILESYSTEM
/* If the first character is a slash, and there's
@ -227,15 +228,19 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
for(i=0; i < real_path_len; ++i)
if(actual_path[i] == '/')
actual_path[i] = '\\';
else if(!actual_path[i]) /* binary zero */
else if(!actual_path[i]) { /* binary zero */
Curl_safefree(real_path);
return CURLE_URL_MALFORMAT;
}
fd = open_readonly(actual_path, O_RDONLY|O_BINARY);
file->path = actual_path;
#else
if(memchr(real_path, 0, real_path_len))
if(memchr(real_path, 0, real_path_len)) {
/* binary zeroes indicate foul play */
Curl_safefree(real_path);
return CURLE_URL_MALFORMAT;
}
fd = open_readonly(real_path, O_RDONLY);
file->path = real_path;
@ -301,7 +306,7 @@ static CURLcode file_upload(struct connectdata *conn)
int fd;
int mode;
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
char *buf = data->state.buffer;
size_t nread;
size_t nwrite;
@ -428,7 +433,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
bool size_known;
bool fstated=FALSE;
ssize_t nread;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
char *buf = data->state.buffer;
curl_off_t bytecount = 0;
int fd;
@ -471,7 +476,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
time_t filetime;
struct tm buffer;
const struct tm *tm = &buffer;
snprintf(buf, sizeof(data->state.buffer),
snprintf(buf, CURL_BUFSIZE(data->set.buffer_size),
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size);
result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
if(result)

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2016, 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
@ -30,12 +30,13 @@
#include <libgen.h>
#endif
#include "urldata.h" /* for struct SessionHandle */
#include "urldata.h" /* for struct Curl_easy */
#include "formdata.h"
#include "vtls/vtls.h"
#include "strequal.h"
#include "strcase.h"
#include "sendf.h"
#include "strdup.h"
#include "rand.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@ -47,7 +48,7 @@ static char *Curl_basename(char *path);
#endif
static size_t readfromfile(struct Form *form, char *buffer, size_t size);
static char *formboundary(struct SessionHandle *data);
static char *formboundary(struct Curl_easy *data);
/* What kind of Content-Type to use on un-specified files with unrecognized
extensions. */
@ -201,7 +202,7 @@ static const char *ContentTypeForFilename(const char *filename,
if(filename) { /* in case a NULL was passed in */
for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
if(strlen(filename) >= strlen(ctts[i].extension)) {
if(strequal(filename +
if(strcasecompare(filename +
strlen(filename) - strlen(ctts[i].extension),
ctts[i].extension)) {
contenttype = ctts[i].type;
@ -845,7 +846,7 @@ static CURLcode AddFormData(struct FormData **formp,
goto error;
}
#endif
if(type != FORM_DATAMEM) {
newform->line = malloc((size_t)length+1);
if(!newform->line) {
result = CURLE_OUT_OF_MEMORY;
@ -853,8 +854,15 @@ static CURLcode AddFormData(struct FormData **formp,
}
alloc2 = newform->line;
memcpy(newform->line, line, (size_t)length);
/* zero terminate for easier debugging */
newform->line[(size_t)length]=0;
}
else {
newform->line = (char *)line;
type = FORM_DATA; /* in all other aspects this is just FORM_DATA */
}
newform->length = (size_t)length;
newform->line[(size_t)length]=0; /* zero terminate for easier debugging */
}
else
/* For callbacks and files we don't have any actual data so we just keep a
@ -863,13 +871,6 @@ static CURLcode AddFormData(struct FormData **formp,
newform->type = type;
if(*formp) {
(*formp)->next = newform;
*formp = newform;
}
else
*formp = newform;
if(size) {
if(type != FORM_FILE)
/* for static content as well as callback data we add the size given
@ -878,7 +879,7 @@ static CURLcode AddFormData(struct FormData **formp,
else {
/* Since this is a file to be uploaded here, add the size of the actual
file */
if(!strequal("-", newform->line)) {
if(strcmp("-", newform->line)) {
struct_stat file;
if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
*size += filesize(newform->line, file);
@ -889,6 +890,14 @@ static CURLcode AddFormData(struct FormData **formp,
}
}
}
if(*formp) {
(*formp)->next = newform;
*formp = newform;
}
else
*formp = newform;
return CURLE_OK;
error:
if(newform)
@ -906,13 +915,21 @@ static CURLcode AddFormDataf(struct FormData **formp,
curl_off_t *size,
const char *fmt, ...)
{
char s[4096];
char *s;
CURLcode result;
va_list ap;
va_start(ap, fmt);
vsnprintf(s, sizeof(s), fmt, ap);
s = curl_mvaprintf(fmt, ap);
va_end(ap);
return AddFormData(formp, FORM_DATA, s, 0, size);
if(!s)
return CURLE_OUT_OF_MEMORY;
result = AddFormData(formp, FORM_DATAMEM, s, 0, size);
if(result)
free(s);
return result;
}
/*
@ -932,8 +949,8 @@ void Curl_formclean(struct FormData **form_ptr)
if(form->type <= FORM_CONTENT)
free(form->line); /* free the line */
free(form); /* free the struct */
} while((form = next) != NULL); /* continue */
form = next;
} while(form); /* continue */
*form_ptr = NULL;
}
@ -1014,8 +1031,8 @@ void curl_formfree(struct curl_httppost *form)
free(form->contenttype); /* free the content type */
free(form->showfilename); /* free the faked file name */
free(form); /* free the struct */
} while((form = next) != NULL); /* continue */
form = next;
} while(form); /* continue */
}
#ifndef HAVE_BASENAME
@ -1136,7 +1153,7 @@ static CURLcode formdata_add_filename(const struct curl_httppost *file,
* a NULL pointer in the 'data' argument.
*/
CURLcode Curl_getformdata(struct SessionHandle *data,
CURLcode Curl_getformdata(struct Curl_easy *data,
struct FormData **finalform,
struct curl_httppost *post,
const char *custom_content_type,
@ -1289,7 +1306,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data,
/* we should include the contents from the specified file */
FILE *fileread;
fileread = strequal("-", file->contents)?
fileread = !strcmp("-", file->contents)?
stdin:fopen(file->contents, "rb"); /* binary read for win32 */
/*
@ -1315,7 +1332,7 @@ CURLcode Curl_getformdata(struct SessionHandle *data,
char buffer[512];
while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
if(result)
if(result || feof(fileread) || ferror(fileread))
break;
}
}
@ -1357,8 +1374,8 @@ CURLcode Curl_getformdata(struct SessionHandle *data,
if(result)
break;
}
} while((post = post->next) != NULL); /* for each field */
post = post->next;
} while(post); /* for each field */
/* end-boundary for everything */
if(!result)
@ -1410,7 +1427,8 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata)
*
*/
# define fopen_read vmsfopenread
static FILE * vmsfopenread(const char *file, const char *mode) {
static FILE * vmsfopenread(const char *file, const char *mode)
{
struct_stat statbuf;
int result;
@ -1535,7 +1553,7 @@ char *Curl_formpostheader(void *formp, size_t *len)
struct Form *form=(struct Form *)formp;
if(!form->data)
return 0; /* nothing, ERROR! */
return NULL; /* nothing, ERROR! */
header = form->data->line;
*len = form->data->length;
@ -1549,12 +1567,16 @@ char *Curl_formpostheader(void *formp, size_t *len)
* formboundary() creates a suitable boundary string and returns an allocated
* one.
*/
static char *formboundary(struct SessionHandle *data)
static char *formboundary(struct Curl_easy *data)
{
/* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
combinations */
return aprintf("------------------------%08x%08x",
Curl_rand(data), Curl_rand(data));
unsigned int rnd[2];
CURLcode result = Curl_rand(data, &rnd[0], 2);
if(result)
return NULL;
return aprintf("------------------------%08x%08x", rnd[0], rnd[1]);
}
#else /* CURL_DISABLE_HTTP */

View File

@ -23,6 +23,7 @@
***************************************************************************/
enum formtype {
FORM_DATAMEM, /* already allocated FORM_DATA memory */
FORM_DATA, /* form metadata (convert to network encoding if necessary) */
FORM_CONTENT, /* form content (never convert) */
FORM_CALLBACK, /* 'line' points to the custom pointer we pass to the callback
@ -70,7 +71,7 @@ typedef struct FormInfo {
int Curl_FormInit(struct Form *form, struct FormData *formdata);
CURLcode Curl_getformdata(struct SessionHandle *data,
CURLcode Curl_getformdata(struct Curl_easy *data,
struct FormData **,
struct curl_httppost *post,
const char *custom_contenttype,
@ -93,6 +94,6 @@ char *Curl_FormBoundary(void);
void Curl_formclean(struct FormData **);
CURLcode Curl_formconvert(struct SessionHandle *, struct FormData *);
CURLcode Curl_formconvert(struct Curl_easy *, struct FormData *);
#endif /* HEADER_CURL_FORMDATA_H */

View File

@ -61,7 +61,7 @@
#include "ftplistparser.h"
#include "curl_sec.h"
#include "strtoofft.h"
#include "strequal.h"
#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
#include "strerror.h"
@ -72,7 +72,7 @@
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h"
#include "url.h"
#include "rawstr.h"
#include "strcase.h"
#include "speedcheck.h"
#include "warnless.h"
#include "http_proxy.h"
@ -327,7 +327,7 @@ static bool isBadFtpString(const char *string)
*/
static CURLcode AcceptServerConnect(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
curl_socket_t sock = conn->sock[SECONDARYSOCKET];
curl_socket_t s = CURL_SOCKET_BAD;
#ifdef ENABLE_IPV6
@ -384,10 +384,10 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
* Curl_pgrsTime(..., TIMER_STARTACCEPT);
*
*/
static long ftp_timeleft_accept(struct SessionHandle *data)
static time_t ftp_timeleft_accept(struct Curl_easy *data)
{
long timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
long other;
time_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
time_t other;
struct timeval now;
if(data->set.accepttimeout > 0)
@ -424,13 +424,13 @@ static long ftp_timeleft_accept(struct SessionHandle *data)
*/
static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
curl_socket_t data_sock = conn->sock[SECONDARYSOCKET];
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
int result;
long timeout_ms;
time_t timeout_ms;
ssize_t nread;
int ftpcode;
@ -475,7 +475,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
if(ftpcode/100 > 3)
return CURLE_FTP_ACCEPT_FAILED;
return CURLE_FTP_WEIRD_SERVER_REPLY;
return CURLE_WEIRD_SERVER_REPLY;
}
break;
@ -495,11 +495,11 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
*/
static CURLcode InitiateTransfer(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct FTP *ftp = data->req.protop;
CURLcode result = CURLE_OK;
if(conn->ssl[SECONDARYSOCKET].use) {
if(conn->bits.ftp_use_data_ssl) {
/* since we only have a plaintext TCP connection here, we must now
* do the TLS stuff */
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
@ -546,8 +546,8 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
*/
static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
{
struct SessionHandle *data = conn->data;
long timeout_ms;
struct Curl_easy *data = conn->data;
time_t timeout_ms;
CURLcode result = CURLE_OK;
*connected = FALSE;
@ -617,7 +617,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
size_t *size) /* size of the response */
{
struct connectdata *conn = pp->conn;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
#ifdef HAVE_GSSAPI
char * const buf = data->state.buffer;
#endif
@ -687,9 +687,9 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
* line in a response or continue reading. */
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
long timeout; /* timeout in milliseconds */
long interval_ms;
struct SessionHandle *data = conn->data;
time_t timeout; /* timeout in milliseconds */
time_t interval_ms;
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
@ -740,8 +740,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
* wait for more data anyway.
*/
}
else {
switch (Curl_socket_ready(sockfd, CURL_SOCKET_BAD, interval_ms)) {
else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) {
switch(SOCKET_READABLE(sockfd, interval_ms)) {
case -1: /* select() error, stop reading */
failf(data, "FTP response aborted due to select/poll error: %d",
SOCKERRNO);
@ -911,7 +911,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
}
else {
socks[1] = conn->sock[SECONDARYSOCKET];
bits |= GETSOCK_WRITESOCK(1);
bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1);
}
return bits;
@ -980,7 +980,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct SessionHandle *data=conn->data;
struct Curl_easy *data=conn->data;
curl_socket_t portsock= CURL_SOCKET_BAD;
char myhost[256] = "";
@ -1035,7 +1035,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
if(*string_ftpport == '[') {
/* [ipv6]:port(-range) */
ip_start = string_ftpport + 1;
if((ip_end = strchr(string_ftpport, ']')) != NULL)
ip_end = strchr(string_ftpport, ']');
if(ip_end)
strncpy(addr, ip_start, ip_end - ip_start);
}
else
@ -1044,7 +1045,9 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
/* :port */
ip_end = string_ftpport;
}
else if((ip_end = strchr(string_ftpport, ':')) != NULL) {
else {
ip_end = strchr(string_ftpport, ':');
if(ip_end) {
/* either ipv6 or (ipv4|domain|interface):port(-range) */
#ifdef ENABLE_IPV6
if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
@ -1061,12 +1064,15 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
else
/* ipv4|interface */
strcpy(addr, string_ftpport);
}
/* parse the port */
if(ip_end != NULL) {
if((port_start = strchr(ip_end, ':')) != NULL) {
port_start = strchr(ip_end, ':');
if(port_start) {
port_min = curlx_ultous(strtoul(port_start+1, NULL, 10));
if((port_sep = strchr(port_start, '-')) != NULL) {
port_sep = strchr(port_start, '-');
if(port_sep) {
port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10));
}
else
@ -1403,7 +1409,7 @@ static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct FTP *ftp = conn->data->req.protop;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
if(ftp->transfer != FTPTRANSFER_BODY) {
/* doesn't transfer any data */
@ -1486,7 +1492,7 @@ static CURLcode ftp_state_size(struct connectdata *conn)
static CURLcode ftp_state_list(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
/* If this output is to be machine-parsed, the NLST command might be better
to use, since the LIST command output is not specified or standard in any
@ -1575,7 +1581,7 @@ static CURLcode ftp_state_type(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct FTP *ftp = conn->data->req.protop;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
/* If we have selected NOBODY and HEADER, it means that we only want file
@ -1607,7 +1613,7 @@ static CURLcode ftp_state_type(struct connectdata *conn)
static CURLcode ftp_state_mdtm(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
/* Requested time of file or time-depended transfer? */
@ -1632,7 +1638,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
struct FTP *ftp = conn->data->req.protop;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
int seekerr = CURL_SEEKFUNC_OK;
@ -1728,7 +1734,7 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
ftpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
bool quote=FALSE;
@ -1835,7 +1841,7 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
if(conn->bits.ipv6) {
/* We can't disable EPSV when doing IPv6, so this is instead a fail */
failf(conn->data, "Failed EPSV attempt, exiting\n");
return CURLE_FTP_WEIRD_SERVER_REPLY;
return CURLE_WEIRD_SERVER_REPLY;
}
infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n");
@ -1850,84 +1856,6 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
return result;
}
/*
* Perform the necessary magic that needs to be done once the TCP connection
* to the proxy has completed.
*/
static CURLcode proxy_magic(struct connectdata *conn,
char *newhost, unsigned short newport,
bool *magicdone)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
#if defined(CURL_DISABLE_PROXY)
(void) newhost;
(void) newport;
#endif
*magicdone = FALSE;
switch(conn->proxytype) {
case CURLPROXY_SOCKS5:
case CURLPROXY_SOCKS5_HOSTNAME:
result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost,
newport, SECONDARYSOCKET, conn);
*magicdone = TRUE;
break;
case CURLPROXY_SOCKS4:
result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
SECONDARYSOCKET, conn, FALSE);
*magicdone = TRUE;
break;
case CURLPROXY_SOCKS4A:
result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
SECONDARYSOCKET, conn, TRUE);
*magicdone = TRUE;
break;
case CURLPROXY_HTTP:
case CURLPROXY_HTTP_1_0:
/* do nothing here. handled later. */
break;
default:
failf(data, "unknown proxytype option given");
result = CURLE_COULDNT_CONNECT;
break;
}
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
/* BLOCKING */
/* We want "seamless" FTP operations through HTTP proxy tunnel */
/* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
* member conn->proto.http; we want FTP through HTTP and we have to
* change the member temporarily for connecting to the HTTP proxy. After
* Curl_proxyCONNECT we have to set back the member to the original
* struct FTP pointer
*/
struct HTTP http_proxy;
struct FTP *ftp_save = data->req.protop;
memset(&http_proxy, 0, sizeof(http_proxy));
data->req.protop = &http_proxy;
result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE);
data->req.protop = ftp_save;
if(result)
return result;
if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
/* the CONNECT procedure is not complete, the tunnel is not yet up */
state(conn, FTP_STOP); /* this phase is completed */
return result;
}
else
*magicdone = TRUE;
}
return result;
}
static char *control_address(struct connectdata *conn)
{
@ -1935,11 +1863,7 @@ static char *control_address(struct connectdata *conn)
If a proxy tunnel is used, returns the original host name instead, because
the effective control connection address is the proxy address,
not the ftp host. */
if(conn->bits.tunnel_proxy ||
conn->proxytype == CURLPROXY_SOCKS5 ||
conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
conn->proxytype == CURLPROXY_SOCKS4 ||
conn->proxytype == CURLPROXY_SOCKS4A)
if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
return conn->host.name;
return conn->ip_addr_str;
@ -1950,7 +1874,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
{
struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result;
struct SessionHandle *data=conn->data;
struct Curl_easy *data=conn->data;
struct Curl_dns_entry *addr=NULL;
int rc;
unsigned short connectport; /* the local port connect() should use! */
@ -2063,7 +1987,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
* here. We don't want to rely on a former host lookup that might've
* expired now, instead we remake the lookup here and now!
*/
rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr);
const char * const host_name = conn->bits.socksproxy ?
conn->socks_proxy.host.name : conn->http_proxy.host.name;
rc = Curl_resolv(conn, host_name, (int)conn->port, &addr);
if(rc == CURLRESOLV_PENDING)
/* BLOCKING, ignores the return code but 'addr' will be NULL in
case of failure */
@ -2073,9 +1999,8 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
(unsigned short)conn->port; /* we connect to the proxy's port */
if(!addr) {
failf(data, "Can't resolve proxy host %s:%hu",
conn->proxy.name, connectport);
return CURLE_FTP_CANT_GET_HOST;
failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport);
return CURLE_COULDNT_RESOLVE_PROXY;
}
}
else {
@ -2115,6 +2040,10 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
/* this just dumps information about this second connection */
ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport);
Curl_safefree(conn->secondaryhostname);
conn->secondaryhostname = strdup(ftpc->newhost);
conn->secondary_port = ftpc->newport;
Curl_resolv_unlock(data, addr); /* we're done using this address */
conn->bits.do_more = TRUE;
state(conn, FTP_STOP); /* this phase is completed */
@ -2125,7 +2054,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
static CURLcode ftp_state_port_resp(struct connectdata *conn,
int ftpcode)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
ftpport fcmd = (ftpport)ftpc->count1;
CURLcode result = CURLE_OK;
@ -2162,7 +2091,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
int ftpcode)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data=conn->data;
struct Curl_easy *data=conn->data;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
@ -2178,7 +2107,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
/* we have a time, reformat it */
time_t secs=time(NULL);
/* using the good old yacc/bison yuck */
snprintf(buf, sizeof(conn->data->state.buffer),
snprintf(buf, CURL_BUFSIZE(conn->data->set.buffer_size),
"%04d%02d%02d %02d:%02d:%02d GMT",
year, month, day, hour, minute, second);
/* now, convert this into a time() value: */
@ -2267,7 +2196,7 @@ static CURLcode ftp_state_type_resp(struct connectdata *conn,
ftpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data=conn->data;
struct Curl_easy *data=conn->data;
if(ftpcode/100 != 2) {
/* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a
@ -2296,7 +2225,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
curl_off_t filesize)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data=conn->data;
struct Curl_easy *data=conn->data;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
@ -2379,7 +2308,7 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
ftpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data=conn->data;
struct Curl_easy *data=conn->data;
curl_off_t filesize;
char *buf = data->state.buffer;
@ -2389,7 +2318,7 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
if(instate == FTP_SIZE) {
#ifdef CURL_FTP_HTTPSTYLE_HEAD
if(-1 != filesize) {
snprintf(buf, sizeof(data->state.buffer),
snprintf(buf, CURL_BUFSIZE(data->set.buffer_size),
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
if(result)
@ -2451,7 +2380,7 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
int ftpcode, ftpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
if(ftpcode>=400) {
failf(data, "Failed FTP upload: %0d", ftpcode);
@ -2490,7 +2419,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
ftpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct FTP *ftp = data->req.protop;
char *buf = data->state.buffer;
@ -2647,7 +2576,7 @@ static CURLcode ftp_state_user_resp(struct connectdata *conn,
ftpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
(void)instate; /* no use for this yet */
@ -2702,7 +2631,7 @@ static CURLcode ftp_state_acct_resp(struct connectdata *conn,
int ftpcode)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
if(ftpcode != 230) {
failf(data, "ACCT rejected by server: %03d", ftpcode);
result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */
@ -2718,7 +2647,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
{
CURLcode result;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
struct SessionHandle *data=conn->data;
struct Curl_easy *data=conn->data;
int ftpcode;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
@ -2742,7 +2671,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
else if(ftpcode != 220) {
failf(data, "Got a %03d ftp-server response when 220 was expected",
ftpcode);
return CURLE_FTP_WEIRD_SERVER_REPLY;
return CURLE_WEIRD_SERVER_REPLY;
}
/* We have received a 220 response fine, now we proceed. */
@ -2763,7 +2692,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
}
#endif
if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
if(data->set.use_ssl &&
(!conn->ssl[FIRSTSOCKET].use ||
(conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
!conn->proxy_ssl[FIRSTSOCKET].use))) {
/* We don't have a SSL/TLS connection yet, but FTPS is
requested. Try a FTPS connection now */
@ -2808,7 +2740,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* Curl_ssl_connect is BLOCKING */
result = Curl_ssl_connect(conn, FIRSTSOCKET);
if(!result) {
conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */
conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
result = ftp_state_user(conn);
}
}
@ -2850,7 +2782,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
case FTP_PROT:
if(ftpcode/100 == 2)
/* We have enabled SSL for the data connection! */
conn->ssl[SECONDARYSOCKET].use =
conn->bits.ftp_use_data_ssl =
(data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
/* FTP servers typically responds with 500 if they decide to reject
our 'P' request */
@ -2891,6 +2823,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
case FTP_PWD:
if(ftpcode == 257) {
char *ptr=&data->state.buffer[4]; /* start on the first letter */
const size_t buf_size = CURL_BUFSIZE(data->set.buffer_size);
char *dir;
char *store;
@ -2908,7 +2841,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
*/
/* scan for the first double-quote for non-standard responses */
while(ptr < &data->state.buffer[sizeof(data->state.buffer)]
while(ptr < &data->state.buffer[buf_size]
&& *ptr != '\n' && *ptr != '\0' && *ptr != '"')
ptr++;
@ -2999,7 +2932,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
/* Check for special servers here. */
if(strequal(os, "OS/400")) {
if(strcasecompare(os, "OS/400")) {
/* Force OS400 name format 1. */
result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1");
if(result) {
@ -3165,7 +3098,7 @@ static CURLcode ftp_multi_statemach(struct connectdata *conn,
struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE);
/* Check for the state outside of the Curl_socket_ready() return code checks
/* Check for the state outside of the Curl_socket_check() return code checks
since at times we are in fact already in this state when this function
gets called. */
*done = (ftpc->state == FTP_STOP) ? TRUE : FALSE;
@ -3243,15 +3176,14 @@ static CURLcode ftp_connect(struct connectdata *conn,
static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
bool premature)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct pingpong *pp = &ftpc->pp;
ssize_t nread;
int ftpcode;
CURLcode result = CURLE_OK;
bool was_ctl_valid = ftpc->ctl_valid;
char *path;
char *path = NULL;
const char *path_to_use = data->state.path;
if(!ftp)
@ -3274,10 +3206,9 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
/* the connection stays alive fine even though this happened */
/* fall-through */
case CURLE_OK: /* doesn't affect the control connection's status */
if(!premature) {
ftpc->ctl_valid = was_ctl_valid;
if(!premature)
break;
}
/* until we cope better with prematurely ended requests, let them
* fallback as if in complete failure */
default: /* by default, an error means the control connection is
@ -3300,13 +3231,12 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
ftpc->known_filesize = -1;
}
/* get the "raw" path */
path = curl_easy_unescape(data, path_to_use, 0, NULL);
if(!path) {
/* out of memory, but we can limp along anyway (and should try to
* since we may already be in the out of memory cleanup path) */
if(!result)
result = CURLE_OUT_OF_MEMORY;
/* get the "raw" path */
result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE);
if(result) {
/* We can limp along anyway (and should try to since we may already be in
* the error path) */
ftpc->ctl_valid = FALSE; /* mark control connection as bad */
connclose(conn, "FTP: out of memory!"); /* mark for connection closure */
ftpc->prevpath = NULL; /* no path remembering */
@ -3587,7 +3517,7 @@ static CURLcode ftp_range(struct connectdata *conn)
curl_off_t from, to;
char *ptr;
char *ptr2;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
if(data->state.use_range && data->state.range) {
@ -3645,7 +3575,7 @@ static CURLcode ftp_range(struct connectdata *conn)
static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
{
struct SessionHandle *data=conn->data;
struct Curl_easy *data=conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result = CURLE_OK;
bool connected = FALSE;
@ -3669,10 +3599,6 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
/* Ready to do more? */
if(connected) {
DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
if(conn->bits.proxy) {
infof(data, "Connection to proxy confirmed\n");
result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected);
}
}
else {
if(result && (ftpc->count1 == 0)) {
@ -3684,6 +3610,18 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
}
}
result = Curl_proxy_connect(conn, SECONDARYSOCKET);
if(result)
return result;
if(CONNECT_SECONDARYSOCKET_PROXY_SSL())
return result;
if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE)
return result;
if(ftpc->state) {
/* already in a state so skip the intial commands.
They are only done to kickstart the do_more state */
@ -4093,8 +4031,7 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done)
}
CURLcode Curl_ftpsendf(struct connectdata *conn,
const char *fmt, ...)
CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
{
ssize_t bytes_written;
#define SBUF_SIZE 1024
@ -4106,10 +4043,9 @@ CURLcode Curl_ftpsendf(struct connectdata *conn,
enum protection_level data_sec = conn->data_prot;
#endif
va_list ap;
va_start(ap, fmt);
write_len = vsnprintf(s, SBUF_SIZE-3, fmt, ap);
va_end(ap);
write_len = strlen(cmd);
if(write_len > (sizeof(s) -3))
return CURLE_BAD_FUNCTION_ARGUMENT;
strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
write_len +=2;
@ -4209,7 +4145,7 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
(void)ftp_quit(conn); /* ignore errors on the QUIT */
if(ftpc->entrypath) {
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) {
data->state.most_recent_ftp_entrypath = NULL;
}
@ -4242,7 +4178,7 @@ static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
static
CURLcode ftp_parse_url_path(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
/* the ftp struct is already inited in ftp_connect() */
struct FTP *ftp = data->req.protop;
struct ftp_conn *ftpc = &conn->proto.ftpc;
@ -4251,8 +4187,8 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
const char *cur_pos;
const char *filename = NULL;
cur_pos = path_to_use; /* current position in path. point at the begin
of next path component */
cur_pos = path_to_use; /* current position in path. point at the begin of
next path component */
ftpc->ctl_valid = FALSE;
ftpc->cwdfail = FALSE;
@ -4291,6 +4227,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
slash_pos=strrchr(cur_pos, '/');
if(slash_pos || !*cur_pos) {
size_t dirlen = slash_pos-cur_pos;
CURLcode result;
ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
if(!ftpc->dirs)
@ -4299,12 +4236,13 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
if(!dirlen)
dirlen++;
ftpc->dirs[0] = curl_easy_unescape(conn->data, slash_pos ? cur_pos : "/",
slash_pos ? curlx_uztosi(dirlen) : 1,
NULL);
if(!ftpc->dirs[0]) {
result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/",
slash_pos ? dirlen : 1,
&ftpc->dirs[0], NULL,
FALSE);
if(result) {
freedirs(ftpc);
return CURLE_OUT_OF_MEMORY;
return result;
}
ftpc->dirdepth = 1; /* we consider it to be a single dir */
filename = slash_pos ? slash_pos+1 : cur_pos; /* rest is file name */
@ -4322,7 +4260,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY;
/* we have a special case for listing the root dir only */
if(strequal(path_to_use, "/")) {
if(!strcmp(path_to_use, "/")) {
cur_pos++; /* make it point to the zero byte */
ftpc->dirs[0] = strdup("/");
ftpc->dirdepth++;
@ -4339,18 +4277,15 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
/* we skip empty path components, like "x//y" since the FTP command
CWD requires a parameter and a non-existent parameter a) doesn't
work on many servers and b) has no effect on the others. */
int len = curlx_sztosi(slash_pos - cur_pos + absolute_dir);
ftpc->dirs[ftpc->dirdepth] =
curl_easy_unescape(conn->data, cur_pos - absolute_dir, len, NULL);
if(!ftpc->dirs[ftpc->dirdepth]) { /* run out of memory ... */
failf(data, "no memory");
freedirs(ftpc);
return CURLE_OUT_OF_MEMORY;
}
if(isBadFtpString(ftpc->dirs[ftpc->dirdepth])) {
size_t len = slash_pos - cur_pos + absolute_dir;
CURLcode result =
Curl_urldecode(conn->data, cur_pos - absolute_dir, len,
&ftpc->dirs[ftpc->dirdepth], NULL,
TRUE);
if(result) {
free(ftpc->dirs[ftpc->dirdepth]);
freedirs(ftpc);
return CURLE_URL_MALFORMAT;
return result;
}
}
else {
@ -4386,15 +4321,12 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
} /* switch */
if(filename && *filename) {
ftpc->file = curl_easy_unescape(conn->data, filename, 0, NULL);
if(NULL == ftpc->file) {
CURLcode result =
Curl_urldecode(conn->data, filename, 0, &ftpc->file, NULL, TRUE);
if(result) {
freedirs(ftpc);
failf(data, "no memory");
return CURLE_OUT_OF_MEMORY;
}
if(isBadFtpString(ftpc->file)) {
freedirs(ftpc);
return CURLE_URL_MALFORMAT;
return result;
}
}
else
@ -4412,16 +4344,18 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
if(ftpc->prevpath) {
/* prevpath is "raw" so we convert the input path before we compare the
strings */
int dlen;
char *path = curl_easy_unescape(conn->data, data->state.path, 0, &dlen);
if(!path) {
size_t dlen;
char *path;
CURLcode result =
Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, FALSE);
if(result) {
freedirs(ftpc);
return CURLE_OUT_OF_MEMORY;
return result;
}
dlen -= ftpc->file?curlx_uztosi(strlen(ftpc->file)):0;
if((dlen == curlx_uztosi(strlen(ftpc->prevpath))) &&
strnequal(path, ftpc->prevpath, dlen)) {
dlen -= ftpc->file?strlen(ftpc->file):0;
if((dlen == strlen(ftpc->prevpath)) &&
!strncmp(path, ftpc->prevpath, dlen)) {
infof(data, "Request has same path as previous transfer\n");
ftpc->cwddone = TRUE;
}
@ -4494,7 +4428,7 @@ CURLcode ftp_regular_transfer(struct connectdata *conn,
{
CURLcode result=CURLE_OK;
bool connected=FALSE;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct ftp_conn *ftpc = &conn->proto.ftpc;
data->req.size = -1; /* make sure this is unknown at this point */
@ -4528,7 +4462,7 @@ CURLcode ftp_regular_transfer(struct connectdata *conn,
static CURLcode ftp_setup_connection(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
char *type;
char command;
struct FTP *ftp;

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -31,7 +31,7 @@ extern const struct Curl_handler Curl_handler_ftp;
extern const struct Curl_handler Curl_handler_ftps;
#endif
CURLcode Curl_ftpsendf(struct connectdata *, const char *fmt, ...);
CURLcode Curl_ftpsend(struct connectdata *, const char *cmd);
CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
int *ftpcode);
#endif /* CURL_DISABLE_FTP */
@ -97,9 +97,9 @@ typedef enum {
file */
} curl_ftpfile;
/* This FTP struct is used in the SessionHandle. All FTP data that is
/* This FTP struct is used in the Curl_easy. All FTP data that is
connection-oriented must be in FTP_conn to properly deal with the fact that
perhaps the SessionHandle is changed between the times the connection is
perhaps the Curl_easy is changed between the times the connection is
used. */
struct FTP {
curl_off_t *bytecountp;

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -45,7 +45,6 @@
#include "fileinfo.h"
#include "llist.h"
#include "strtoofft.h"
#include "rawstr.h"
#include "ftp.h"
#include "ftplistparser.h"
#include "curl_fnmatch.h"

View File

@ -30,7 +30,8 @@
static
char *GetEnv(const char *variable)
{
#ifdef _WIN32_WCE
#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
(void)variable;
return NULL;
#else
#ifdef WIN32

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -36,10 +36,13 @@
#include "memdebug.h"
/*
* This is supposed to be called in the beginning of a perform() session
* and should reset all session-info variables
* Initialize statistical and informational data.
*
* This function is called in curl_easy_reset, curl_easy_duphandle and at the
* beginning of a perform session. It must reset the session-info variables,
* in particular all variables in struct PureInfo.
*/
CURLcode Curl_initinfo(struct SessionHandle *data)
CURLcode Curl_initinfo(struct Curl_easy *data)
{
struct Progress *pro = &data->progress;
struct PureInfo *info = &data->info;
@ -58,23 +61,35 @@ CURLcode Curl_initinfo(struct SessionHandle *data)
info->filetime = -1; /* -1 is an illegal time and thus means unknown */
info->timecond = FALSE;
info->header_size = 0;
info->request_size = 0;
info->proxyauthavail = 0;
info->httpauthavail = 0;
info->numconnects = 0;
free(info->contenttype);
info->contenttype = NULL;
info->header_size = 0;
info->request_size = 0;
info->numconnects = 0;
free(info->wouldredirect);
info->wouldredirect = NULL;
info->conn_primary_ip[0] = '\0';
info->conn_local_ip[0] = '\0';
info->conn_primary_port = 0;
info->conn_local_port = 0;
info->conn_scheme = 0;
info->conn_protocol = 0;
#ifdef USE_SSL
Curl_ssl_free_certinfo(data);
#endif
return CURLE_OK;
}
static CURLcode getinfo_char(struct SessionHandle *data, CURLINFO info,
char **param_charp)
static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
const char **param_charp)
{
switch(info) {
case CURLINFO_EFFECTIVE_URL:
@ -111,6 +126,9 @@ static CURLcode getinfo_char(struct SessionHandle *data, CURLINFO info,
case CURLINFO_RTSP_SESSION_ID:
*param_charp = data->set.str[STRING_RTSP_SESSION_ID];
break;
case CURLINFO_SCHEME:
*param_charp = data->info.conn_scheme;
break;
default:
return CURLE_UNKNOWN_OPTION;
@ -119,7 +137,7 @@ static CURLcode getinfo_char(struct SessionHandle *data, CURLINFO info,
return CURLE_OK;
}
static CURLcode getinfo_long(struct SessionHandle *data, CURLINFO info,
static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
long *param_longp)
{
curl_socket_t sockfd;
@ -148,6 +166,9 @@ static CURLcode getinfo_long(struct SessionHandle *data, CURLINFO info,
case CURLINFO_SSL_VERIFYRESULT:
*param_longp = data->set.ssl.certverifyresult;
break;
case CURLINFO_PROXY_SSL_VERIFYRESULT:
*param_longp = data->set.proxy_ssl.certverifyresult;
break;
case CURLINFO_REDIRECT_COUNT:
*param_longp = data->set.followlocation;
break;
@ -198,6 +219,25 @@ static CURLcode getinfo_long(struct SessionHandle *data, CURLINFO info,
case CURLINFO_RTSP_CSEQ_RECV:
*param_longp = data->state.rtsp_CSeq_recv;
break;
case CURLINFO_HTTP_VERSION:
switch(data->info.httpversion) {
case 10:
*param_longp = CURL_HTTP_VERSION_1_0;
break;
case 11:
*param_longp = CURL_HTTP_VERSION_1_1;
break;
case 20:
*param_longp = CURL_HTTP_VERSION_2_0;
break;
default:
*param_longp = CURL_HTTP_VERSION_NONE;
break;
}
break;
case CURLINFO_PROTOCOL:
*param_longp = data->info.conn_protocol;
break;
default:
return CURLE_UNKNOWN_OPTION;
@ -206,7 +246,7 @@ static CURLcode getinfo_long(struct SessionHandle *data, CURLINFO info,
return CURLE_OK;
}
static CURLcode getinfo_double(struct SessionHandle *data, CURLINFO info,
static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
double *param_doublep)
{
switch(info) {
@ -259,7 +299,7 @@ static CURLcode getinfo_double(struct SessionHandle *data, CURLINFO info,
return CURLE_OK;
}
static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info,
static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
struct curl_slist **param_slistp)
{
union {
@ -335,7 +375,7 @@ static CURLcode getinfo_slist(struct SessionHandle *data, CURLINFO info,
return CURLE_OK;
}
static CURLcode getinfo_socket(struct SessionHandle *data, CURLINFO info,
static CURLcode getinfo_socket(struct Curl_easy *data, CURLINFO info,
curl_socket_t *param_socketp)
{
switch(info) {
@ -349,12 +389,12 @@ static CURLcode getinfo_socket(struct SessionHandle *data, CURLINFO info,
return CURLE_OK;
}
CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
{
va_list arg;
long *param_longp = NULL;
double *param_doublep = NULL;
char **param_charp = NULL;
const char **param_charp = NULL;
struct curl_slist **param_slistp = NULL;
curl_socket_t *param_socketp = NULL;
int type;
@ -368,7 +408,7 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
type = CURLINFO_TYPEMASK & (int)info;
switch(type) {
case CURLINFO_STRING:
param_charp = va_arg(arg, char **);
param_charp = va_arg(arg, const char **);
if(param_charp)
result = getinfo_char(data, info, param_charp);
break;

View File

@ -21,7 +21,7 @@
* KIND, either express or implied.
*
***************************************************************************/
CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...);
CURLcode Curl_initinfo(struct SessionHandle *data);
CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...);
CURLcode Curl_initinfo(struct Curl_easy *data);
#endif /* HEADER_CURL_GETINFO_H */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -28,13 +28,11 @@
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
#include "progress.h"
#include "strequal.h"
#include "gopher.h"
#include "rawstr.h"
#include "select.h"
#include "url.h"
#include "escape.h"
#include "warnless.h"
#include "curl_memory.h"
/* The last #include file should be: */
@ -75,7 +73,7 @@ const struct Curl_handler Curl_handler_gopher = {
static CURLcode gopher_do(struct connectdata *conn, bool *done)
{
CURLcode result=CURLE_OK;
struct SessionHandle *data=conn->data;
struct Curl_easy *data=conn->data;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
curl_off_t *bytecount = &data->req.bytecount;
@ -83,7 +81,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
char *sel;
char *sel_org = NULL;
ssize_t amount, k;
int len;
size_t len;
*done = TRUE; /* unconditionally */
@ -107,7 +105,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
newp[i] = '\x09';
/* ... and finally unescape */
sel = curl_easy_unescape(data, newp, 0, &len);
result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
if(!sel)
return CURLE_OUT_OF_MEMORY;
sel_org = sel;
@ -121,20 +119,17 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
result = Curl_write(conn, sockfd, sel, k, &amount);
if(!result) { /* Which may not have written it all! */
result = Curl_client_write(conn, CLIENTWRITE_HEADER, sel, amount);
if(result) {
free(sel_org);
return result;
}
if(result)
break;
k -= amount;
sel += amount;
if(k < 1)
break; /* but it did write it all */
}
else {
failf(data, "Failed sending Gopher request");
free(sel_org);
return result;
}
else
break;
/* Don't busyloop. The entire loop thing is a work-around as it causes a
BLOCKING behavior which is a NO-NO. This function should rather be
split up in a do and a doing piece where the pieces that aren't
@ -144,11 +139,15 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
Wait a while for the socket to be writable. Note that this doesn't
acknowledge the timeout.
*/
Curl_socket_ready(CURL_SOCKET_BAD, sockfd, 100);
if(SOCKET_WRITABLE(sockfd, 100) < 0) {
result = CURLE_SEND_ERROR;
break;
}
}
free(sel_org);
if(!result)
/* We can use Curl_sendf to send the terminal \r\n relatively safely and
save allocing another string/doing another _write loop. */
result = Curl_sendf(sockfd, conn, "\r\n");

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -87,7 +87,6 @@ void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num);
size_t Curl_str_key_compare(void *k1, size_t key1_len, void *k2,
size_t key2_len);
void Curl_hash_start_iterate(struct curl_hash *hash,
struct curl_hash_iterator *iter);
struct curl_hash_element *

View File

@ -77,7 +77,7 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
if(CURL_ASYNC_SUCCESS == status) {
if(ai) {
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -22,7 +22,10 @@
#include "curl_setup.h"
#if defined(USE_OPENSSL) || defined(USE_AXTLS) || defined(USE_GSKIT)
#if defined(USE_OPENSSL) \
|| defined(USE_AXTLS) \
|| defined(USE_GSKIT) \
|| (defined(USE_SCHANNEL) && defined(_WIN32_WCE))
/* these backends use functions from this file */
#ifdef HAVE_NETINET_IN_H
@ -30,7 +33,7 @@
#endif
#include "hostcheck.h"
#include "rawstr.h"
#include "strcase.h"
#include "inet_pton.h"
#include "curl_memory.h"
@ -77,7 +80,7 @@ static int hostmatch(char *hostname, char *pattern)
pattern_wildcard = strchr(pattern, '*');
if(pattern_wildcard == NULL)
return Curl_raw_equal(pattern, hostname) ?
return strcasecompare(pattern, hostname) ?
CURL_HOST_MATCH : CURL_HOST_NOMATCH;
/* detect IP address as hostname and fail the match if so */
@ -94,16 +97,16 @@ static int hostmatch(char *hostname, char *pattern)
pattern_label_end = strchr(pattern, '.');
if(pattern_label_end == NULL || strchr(pattern_label_end+1, '.') == NULL ||
pattern_wildcard > pattern_label_end ||
Curl_raw_nequal(pattern, "xn--", 4)) {
strncasecompare(pattern, "xn--", 4)) {
wildcard_enabled = 0;
}
if(!wildcard_enabled)
return Curl_raw_equal(pattern, hostname) ?
return strcasecompare(pattern, hostname) ?
CURL_HOST_MATCH : CURL_HOST_NOMATCH;
hostname_label_end = strchr(hostname, '.');
if(hostname_label_end == NULL ||
!Curl_raw_equal(pattern_label_end, hostname_label_end))
!strcasecompare(pattern_label_end, hostname_label_end))
return CURL_HOST_NOMATCH;
/* The wildcard must match at least one character, so the left-most
@ -114,8 +117,8 @@ static int hostmatch(char *hostname, char *pattern)
prefixlen = pattern_wildcard - pattern;
suffixlen = pattern_label_end - (pattern_wildcard+1);
return Curl_raw_nequal(pattern, hostname, prefixlen) &&
Curl_raw_nequal(pattern_wildcard+1, hostname_label_end - suffixlen,
return strncasecompare(pattern, hostname, prefixlen) &&
strncasecompare(pattern_wildcard+1, hostname_label_end - suffixlen,
suffixlen) ?
CURL_HOST_MATCH : CURL_HOST_NOMATCH;
}
@ -144,4 +147,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
return res;
}
#endif /* OPENSSL or AXTLS or GSKIT */
#endif /* OPENSSL, AXTLS, GSKIT or schannel+wince */

View File

@ -254,7 +254,7 @@ hostcache_prune(struct curl_hash *hostcache, long cache_timeout, time_t now)
* Library-wide function for pruning the DNS cache. This function takes and
* returns the appropriate locks.
*/
void Curl_hostcache_prune(struct SessionHandle *data)
void Curl_hostcache_prune(struct Curl_easy *data)
{
time_t now;
@ -293,7 +293,7 @@ fetch_addr(struct connectdata *conn,
char *entry_id = NULL;
struct Curl_dns_entry *dns = NULL;
size_t entry_len;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
/* Create an entry id, based upon the hostname and port */
entry_id = create_hostcache_id(hostname, port);
@ -345,7 +345,7 @@ Curl_fetch_addr(struct connectdata *conn,
const char *hostname,
int port)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct Curl_dns_entry *dns = NULL;
if(data->share)
@ -372,7 +372,7 @@ Curl_fetch_addr(struct connectdata *conn,
* Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
*/
struct Curl_dns_entry *
Curl_cache_addr(struct SessionHandle *data,
Curl_cache_addr(struct Curl_easy *data,
Curl_addrinfo *addr,
const char *hostname,
int port)
@ -447,7 +447,7 @@ int Curl_resolv(struct connectdata *conn,
struct Curl_dns_entry **entry)
{
struct Curl_dns_entry *dns = NULL;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
CURLcode result;
int rc = CURLRESOLV_ERROR; /* default to failure */
@ -568,7 +568,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
const char *hostname,
int port,
struct Curl_dns_entry **entry,
long timeoutms)
time_t timeoutms)
{
#ifdef USE_ALARM_TIMEOUT
#ifdef HAVE_SIGACTION
@ -582,7 +582,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
#endif /* HAVE_SIGACTION */
volatile long timeout;
volatile unsigned int prev_alarm = 0;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
#endif /* USE_ALARM_TIMEOUT */
int rc;
@ -603,11 +603,14 @@ int Curl_resolv_timeout(struct connectdata *conn,
/* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
return Curl_resolv(conn, hostname, port, entry);
if(timeout < 1000)
if(timeout < 1000) {
/* The alarm() function only provides integer second resolution, so if
we want to wait less than one second we must bail out already now. */
failf(data,
"remaining timeout of %ld too small to resolve via SIGALRM method",
timeout);
return CURLRESOLV_TIMEDOUT;
}
/* This allows us to time-out from the name resolver, as the timeout
will generate a signal and we will siglongjmp() from that here.
This technique has problems (see alarmfunc).
@ -716,7 +719,7 @@ clean_up:
*
* May be called with 'data' == NULL for global cache.
*/
void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns)
void Curl_resolv_unlock(struct Curl_easy *data, struct Curl_dns_entry *dns)
{
if(data && data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
@ -758,7 +761,7 @@ int Curl_mk_dnscache(struct curl_hash *hash)
* can be done!
*/
void Curl_hostcache_clean(struct SessionHandle *data,
void Curl_hostcache_clean(struct Curl_easy *data,
struct curl_hash *hash)
{
if(data && data->share)
@ -771,7 +774,7 @@ void Curl_hostcache_clean(struct SessionHandle *data,
}
CURLcode Curl_loadhostpairs(struct SessionHandle *data)
CURLcode Curl_loadhostpairs(struct Curl_easy *data)
{
struct curl_slist *hostp;
char hostname[256];

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -50,7 +50,7 @@
struct addrinfo;
struct hostent;
struct SessionHandle;
struct Curl_easy;
struct connectdata;
/*
@ -87,7 +87,7 @@ int Curl_resolv(struct connectdata *conn, const char *hostname,
int port, struct Curl_dns_entry **dnsentry);
int Curl_resolv_timeout(struct connectdata *conn, const char *hostname,
int port, struct Curl_dns_entry **dnsentry,
long timeoutms);
time_t timeoutms);
#ifdef CURLRES_IPV6
/*
@ -118,7 +118,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
/* unlock a previously resolved dns entry */
void Curl_resolv_unlock(struct SessionHandle *data,
void Curl_resolv_unlock(struct Curl_easy *data,
struct Curl_dns_entry *dns);
/* for debugging purposes only: */
@ -128,7 +128,7 @@ void Curl_scan_cache_used(void *user, void *ptr);
int Curl_mk_dnscache(struct curl_hash *hash);
/* prune old entries from the DNS cache */
void Curl_hostcache_prune(struct SessionHandle *data);
void Curl_hostcache_prune(struct Curl_easy *data);
/* Return # of adresses in a Curl_addrinfo struct */
int Curl_num_addresses(const Curl_addrinfo *addr);
@ -188,7 +188,7 @@ Curl_fetch_addr(struct connectdata *conn,
* Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
*/
struct Curl_dns_entry *
Curl_cache_addr(struct SessionHandle *data, Curl_addrinfo *addr,
Curl_cache_addr(struct Curl_easy *data, Curl_addrinfo *addr,
const char *hostname, int port);
#ifndef INADDR_NONE
@ -209,42 +209,42 @@ extern sigjmp_buf curl_jmpenv;
/*
* Function provided by the resolver backend to set DNS servers to use.
*/
CURLcode Curl_set_dns_servers(struct SessionHandle *data, char *servers);
CURLcode Curl_set_dns_servers(struct Curl_easy *data, char *servers);
/*
* Function provided by the resolver backend to set
* outgoing interface to use for DNS requests
*/
CURLcode Curl_set_dns_interface(struct SessionHandle *data,
CURLcode Curl_set_dns_interface(struct Curl_easy *data,
const char *interf);
/*
* Function provided by the resolver backend to set
* local IPv4 address to use as source address for DNS requests
*/
CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
const char *local_ip4);
/*
* Function provided by the resolver backend to set
* local IPv6 address to use as source address for DNS requests
*/
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
const char *local_ip6);
/*
* Clean off entries from the cache
*/
void Curl_hostcache_clean(struct SessionHandle *data, struct curl_hash *hash);
void Curl_hostcache_clean(struct Curl_easy *data, struct curl_hash *hash);
/*
* Destroy the hostcache of this handle.
*/
void Curl_hostcache_destroy(struct SessionHandle *data);
void Curl_hostcache_destroy(struct Curl_easy *data);
/*
* Populate the cache with specified entries from CURLOPT_RESOLVE.
*/
CURLcode Curl_loadhostpairs(struct SessionHandle *data);
CURLcode Curl_loadhostpairs(struct Curl_easy *data);
#endif /* HEADER_CURL_HOSTIP_H */

View File

@ -167,10 +167,12 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
int error;
char sbuf[12];
char *sbufptr = NULL;
#ifndef USE_RESOLVE_ON_IPS
char addrbuf[128];
#endif
int pf;
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
#endif
*waitp = 0; /* synchronous response only */
@ -196,11 +198,17 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
hints.ai_family = pf;
hints.ai_socktype = conn->socktype;
#ifndef USE_RESOLVE_ON_IPS
/*
* The AI_NUMERICHOST must not be set to get synthesized IPv6 address from
* an IPv4 address on iOS and Mac OS X.
*/
if((1 == Curl_inet_pton(AF_INET, hostname, addrbuf)) ||
(1 == Curl_inet_pton(AF_INET6, hostname, addrbuf))) {
/* the given address is numerical only, prevent a reverse lookup */
hints.ai_flags = AI_NUMERICHOST;
}
#endif
if(port) {
snprintf(sbuf, sizeof(sbuf), "%d", port);
@ -213,6 +221,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
return NULL;
}
if(port) {
Curl_addrinfo_set_port(res, port);
}
dump_addrinfo(conn, res);
return res;

View File

@ -59,7 +59,7 @@
/*
* Function provided by the resolver backend to set DNS servers to use.
*/
CURLcode Curl_set_dns_servers(struct SessionHandle *data,
CURLcode Curl_set_dns_servers(struct Curl_easy *data,
char *servers)
{
(void)data;
@ -72,7 +72,7 @@ CURLcode Curl_set_dns_servers(struct SessionHandle *data,
* Function provided by the resolver backend to set
* outgoing interface to use for DNS requests
*/
CURLcode Curl_set_dns_interface(struct SessionHandle *data,
CURLcode Curl_set_dns_interface(struct Curl_easy *data,
const char *interf)
{
(void)data;
@ -84,7 +84,7 @@ CURLcode Curl_set_dns_interface(struct SessionHandle *data,
* Function provided by the resolver backend to set
* local IPv4 address to use as source address for DNS requests
*/
CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data,
const char *local_ip4)
{
(void)data;
@ -96,7 +96,7 @@ CURLcode Curl_set_dns_local_ip4(struct SessionHandle *data,
* Function provided by the resolver backend to set
* local IPv6 address to use as source address for DNS requests
*/
CURLcode Curl_set_dns_local_ip6(struct SessionHandle *data,
CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data,
const char *local_ip6)
{
(void)data;

View File

@ -53,7 +53,6 @@
#include "progress.h"
#include "curl_base64.h"
#include "cookie.h"
#include "strequal.h"
#include "vauth/vauth.h"
#include "vtls/vtls.h"
#include "http_digest.h"
@ -68,7 +67,7 @@
#include "parsedate.h" /* for the week day and month names */
#include "strtoofft.h"
#include "multiif.h"
#include "rawstr.h"
#include "strcase.h"
#include "content_encoding.h"
#include "http_proxy.h"
#include "warnless.h"
@ -77,6 +76,7 @@
#include "pipeline.h"
#include "http2.h"
#include "connect.h"
#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@ -151,7 +151,7 @@ const struct Curl_handler Curl_handler_https = {
CURLcode Curl_http_setup_conn(struct connectdata *conn)
{
/* allocate the HTTP-specific struct for the SessionHandle, only to survive
/* allocate the HTTP-specific struct for the Curl_easy, only to survive
during this request */
struct HTTP *http;
DEBUGASSERT(conn->data->req.protop == NULL);
@ -179,10 +179,10 @@ char *Curl_checkheaders(const struct connectdata *conn,
{
struct curl_slist *head;
size_t thislen = strlen(thisheader);
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
for(head = data->set.headers;head; head=head->next) {
if(Curl_raw_nequal(head->data, thisheader, thislen))
if(strncasecompare(head->data, thisheader, thislen))
return head->data;
}
@ -194,7 +194,7 @@ char *Curl_checkheaders(const struct connectdata *conn,
* if proxy headers are not available, then it will lookup into http header
* link list
*
* It takes a connectdata struct as input instead of the SessionHandle simply
* It takes a connectdata struct as input instead of the Curl_easy simply
* to know if this is a proxy request or not, as it then might check a
* different header list.
*/
@ -203,12 +203,12 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
{
struct curl_slist *head;
size_t thislen = strlen(thisheader);
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
for(head = (conn->bits.proxy && data->set.sep_headers) ?
data->set.proxyheaders : data->set.headers;
head; head=head->next) {
if(Curl_raw_nequal(head->data, thisheader, thislen))
if(strncasecompare(head->data, thisheader, thislen))
return head->data;
}
@ -280,7 +280,7 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
{
size_t size = 0;
char *authorization = NULL;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
char **userp;
const char *user;
const char *pwd;
@ -288,8 +288,8 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
if(proxy) {
userp = &conn->allocptr.proxyuserpwd;
user = conn->proxyuser;
pwd = conn->proxypasswd;
user = conn->http_proxy.user;
pwd = conn->http_proxy.passwd;
}
else {
userp = &conn->allocptr.userpwd;
@ -297,7 +297,8 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
pwd = conn->passwd;
}
snprintf(data->state.buffer, sizeof(data->state.buffer), "%s:%s", user, pwd);
snprintf(data->state.buffer, CURL_BUFSIZE(data->set.buffer_size),
"%s:%s", user, pwd);
result = Curl_base64_encode(data,
data->state.buffer, strlen(data->state.buffer),
@ -377,7 +378,7 @@ static bool pickoneauth(struct auth *pick)
*/
static CURLcode http_perhapsrewind(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct HTTP *http = data->req.protop;
curl_off_t bytessent;
curl_off_t expectsend = -1; /* default is unknown */
@ -462,7 +463,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
#endif
/* This is not NTLM or many bytes left to send: close */
connclose(conn, "Mid-auth HTTP and much data left to send");
streamclose(conn, "Mid-auth HTTP and much data left to send");
data->req.size = 0; /* don't download any more than 0 bytes */
/* There still is data left to send, but this connection is marked for
@ -485,7 +486,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
CURLcode Curl_http_auth_act(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
bool pickhost = FALSE;
bool pickproxy = FALSE;
CURLcode result = CURLE_OK;
@ -567,7 +568,7 @@ output_auth_headers(struct connectdata *conn,
const char *auth = NULL;
CURLcode result = CURLE_OK;
#if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO)
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
#endif
#ifdef USE_SPNEGO
struct negotiatedata *negdata = proxy ?
@ -642,7 +643,7 @@ output_auth_headers(struct connectdata *conn,
if(auth) {
infof(data, "%s auth using %s with user '%s'\n",
proxy ? "Proxy" : "Server", auth,
proxy ? (conn->proxyuser ? conn->proxyuser : "") :
proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") :
(conn->user ? conn->user : ""));
authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
}
@ -674,7 +675,7 @@ Curl_http_output_auth(struct connectdata *conn,
up the proxy tunnel */
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct auth *authhost;
struct auth *authproxy;
@ -726,7 +727,7 @@ Curl_http_output_auth(struct connectdata *conn,
conn->bits.netrc ||
!data->state.first_host ||
data->set.http_disable_hostname_check_before_authentication ||
Curl_raw_equal(data->state.first_host, conn->host.name)) {
strcasecompare(data->state.first_host, conn->host.name)) {
result = output_auth_headers(conn, authhost, request, path, FALSE);
}
else
@ -747,7 +748,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
/*
* This resource requires authentication
*/
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
#ifdef USE_SPNEGO
struct negotiatedata *negdata = proxy?
@ -784,11 +785,14 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
while(*auth) {
#ifdef USE_SPNEGO
if(checkprefix("Negotiate", auth)) {
if((authp->avail & CURLAUTH_NEGOTIATE) ||
Curl_auth_is_spnego_supported()) {
*availp |= CURLAUTH_NEGOTIATE;
authp->avail |= CURLAUTH_NEGOTIATE;
if(authp->picked == CURLAUTH_NEGOTIATE) {
if(negdata->state == GSS_AUTHSENT || negdata->state == GSS_AUTHNONE) {
if(negdata->state == GSS_AUTHSENT ||
negdata->state == GSS_AUTHNONE) {
CURLcode result = Curl_input_negotiate(conn, proxy, auth);
if(!result) {
DEBUGASSERT(!data->req.newurl);
@ -804,13 +808,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
}
}
}
}
else
#endif
#ifdef USE_NTLM
/* NTLM support requires the SSL crypto libs */
if(checkprefix("NTLM", auth)) {
if((authp->avail & CURLAUTH_NTLM) ||
(authp->avail & CURLAUTH_NTLM_WB) ||
Curl_auth_is_ntlm_supported()) {
*availp |= CURLAUTH_NTLM;
authp->avail |= CURLAUTH_NTLM;
if(authp->picked == CURLAUTH_NTLM ||
authp->picked == CURLAUTH_NTLM_WB) {
/* NTLM authentication is picked and activated */
@ -832,11 +841,13 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
auth += strlen("NTLM");
while(*auth && ISSPACE(*auth))
auth++;
if(*auth)
if((conn->challenge_header = strdup(auth)) == NULL)
if(*auth) {
conn->challenge_header = strdup(auth);
if(!conn->challenge_header)
return CURLE_OUT_OF_MEMORY;
}
}
}
#endif
}
else {
@ -845,22 +856,23 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
}
}
}
}
else
#endif
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(checkprefix("Digest", auth)) {
if((authp->avail & CURLAUTH_DIGEST) != 0) {
if((authp->avail & CURLAUTH_DIGEST) != 0)
infof(data, "Ignoring duplicate digest auth header.\n");
}
else {
else if(Curl_auth_is_digest_supported()) {
CURLcode result;
*availp |= CURLAUTH_DIGEST;
authp->avail |= CURLAUTH_DIGEST;
/* We call this function on input Digest headers even if Digest
* authentication isn't activated yet, as we need to store the
* incoming data from this header in case we are gonna use
* Digest. */
* incoming data from this header in case we are going to use
* Digest */
result = Curl_input_digest(conn, proxy, auth);
if(result) {
infof(data, "Authentication problem. Ignoring this.\n");
@ -907,7 +919,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
*/
static int http_should_fail(struct connectdata *conn)
{
struct SessionHandle *data;
struct Curl_easy *data;
int httpcode;
DEBUGASSERT(conn);
@ -1090,7 +1102,9 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
return result;
}
if((conn->handler->flags & PROTOPT_SSL) && conn->httpversion != 20) {
if((conn->handler->flags & PROTOPT_SSL ||
conn->http_proxy.proxytype == CURLPROXY_HTTPS)
&& conn->httpversion != 20) {
/* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
when we speak HTTPS, as if only a fraction of it is sent now, this data
needs to fit into the normal read-callback buffer later on and that
@ -1247,14 +1261,13 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
if(in->buffer)
/* we have a buffer, enlarge the existing one */
new_rb = realloc(in->buffer, new_size);
new_rb = Curl_saferealloc(in->buffer, new_size);
else
/* create a new buffer */
new_rb = malloc(new_size);
if(!new_rb) {
/* If we failed, we cleanup the whole buffer and return error */
Curl_safefree(in->buffer);
free(in);
return CURLE_OUT_OF_MEMORY;
}
@ -1296,7 +1309,7 @@ Curl_compareheader(const char *headerline, /* line to check */
const char *start;
const char *end;
if(!Curl_raw_nequal(headerline, header, hlen))
if(!strncasecompare(headerline, header, hlen))
return FALSE; /* doesn't start with header */
/* pass the header */
@ -1322,7 +1335,7 @@ Curl_compareheader(const char *headerline, /* line to check */
/* find the content string in the rest of the line */
for(;len>=clen;len--, start++) {
if(Curl_raw_nequal(start, content, clen))
if(strncasecompare(start, content, clen))
return TRUE; /* match! */
}
@ -1342,10 +1355,13 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
connkeep(conn, "HTTP default");
/* the CONNECT procedure might not have been completed */
result = Curl_proxy_connect(conn);
result = Curl_proxy_connect(conn, FIRSTSOCKET);
if(result)
return result;
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */
if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
/* nothing else to do except wait right now - we're not done here. */
return CURLE_OK;
@ -1388,50 +1404,16 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
return result;
}
#endif
#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \
defined(USE_MBEDTLS)
/* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only.
It should be made to query the generic SSL layer instead. */
static int https_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
{
if(conn->handler->flags & PROTOPT_SSL) {
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
if(!numsocks)
return GETSOCK_BLANK;
if(connssl->connecting_state == ssl_connect_2_writing) {
/* write mode */
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_WRITESOCK(0);
}
else if(connssl->connecting_state == ssl_connect_2_reading) {
/* read mode */
socks[0] = conn->sock[FIRSTSOCKET];
return GETSOCK_READSOCK(0);
}
}
return CURLE_OK;
}
#else
#ifdef USE_SSL
static int https_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
{
(void)conn;
(void)socks;
(void)numsocks;
if(conn->handler->flags & PROTOPT_SSL)
return Curl_ssl_getsock(conn, socks, numsocks);
return GETSOCK_BLANK;
}
#endif /* USE_SSL */
#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */
/*
* Curl_http_done() gets called after a single HTTP request has been
@ -1441,11 +1423,8 @@ static int https_getsock(struct connectdata *conn,
CURLcode Curl_http_done(struct connectdata *conn,
CURLcode status, bool premature)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct HTTP *http = data->req.protop;
#ifdef USE_NGHTTP2
struct http_conn *httpc = &conn->proto.httpc;
#endif
Curl_unencode_cleanup(conn);
@ -1458,7 +1437,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
* Do not close CONNECT_ONLY connections. */
if((data->req.httpcode != 401) && (data->req.httpcode != 407) &&
!data->set.connect_only)
connclose(conn, "Negotiate transfer completed");
streamclose(conn, "Negotiate transfer completed");
Curl_cleanup_negotiate(data);
}
#endif
@ -1475,27 +1454,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
http->send_buffer = NULL; /* clear the pointer */
}
#ifdef USE_NGHTTP2
if(http->header_recvbuf) {
DEBUGF(infof(data, "free header_recvbuf!!\n"));
Curl_add_buffer_free(http->header_recvbuf);
http->header_recvbuf = NULL; /* clear the pointer */
Curl_add_buffer_free(http->trailer_recvbuf);
http->trailer_recvbuf = NULL; /* clear the pointer */
if(http->push_headers) {
/* if they weren't used and then freed before */
for(; http->push_headers_used > 0; --http->push_headers_used) {
free(http->push_headers[http->push_headers_used - 1]);
}
free(http->push_headers);
http->push_headers = NULL;
}
}
if(http->stream_id) {
nghttp2_session_set_stream_user_data(httpc->h2, http->stream_id, 0);
http->stream_id = 0;
}
#endif
Curl_http2_done(conn, premature);
if(HTTPREQ_POST_FORM == data->set.httpreq) {
data->req.bytecount = http->readbytecount + http->writebytecount;
@ -1539,7 +1498,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
* - if any server previously contacted to handle this request only supports
* 1.0.
*/
static bool use_http_1_1plus(const struct SessionHandle *data,
static bool use_http_1_1plus(const struct Curl_easy *data,
const struct connectdata *conn)
{
if((data->state.httpversion == 10) || (conn->httpversion == 10))
@ -1551,8 +1510,22 @@ static bool use_http_1_1plus(const struct SessionHandle *data,
(data->set.httpversion >= CURL_HTTP_VERSION_1_1));
}
static const char *get_http_string(const struct Curl_easy *data,
const struct connectdata *conn)
{
#ifdef USE_NGHTTP2
if(conn->proto.httpc.h2)
return "2";
#endif
if(use_http_1_1plus(data, conn))
return "1.1";
return "1.0";
}
/* check and possibly add an Expect: header */
static CURLcode expect100(struct SessionHandle *data,
static CURLcode expect100(struct Curl_easy *data,
struct connectdata *conn,
Curl_send_buffer *req_buffer)
{
@ -1595,7 +1568,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
struct curl_slist *h[2];
struct curl_slist *headers;
int numlists=1; /* by default */
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
int i;
enum proxy_use proxy;
@ -1660,6 +1633,10 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
Connection: */
checkprefix("Connection", headers->data))
;
else if((conn->httpversion == 20) &&
checkprefix("Transfer-Encoding:", headers->data))
/* HTTP/2 doesn't support chunked requests */
;
else {
CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n",
headers->data);
@ -1700,7 +1677,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
return CURLE_OK;
}
CURLcode Curl_add_timecondition(struct SessionHandle *data,
CURLcode Curl_add_timecondition(struct Curl_easy *data,
Curl_send_buffer *req_buffer)
{
const struct tm *tm;
@ -1758,13 +1735,13 @@ CURLcode Curl_add_timecondition(struct SessionHandle *data,
}
/*
* Curl_http() gets called from the generic Curl_do() function when a HTTP
* Curl_http() gets called from the generic multi_do() function when a HTTP
* request is to be performed. This creates and sends a properly constructed
* HTTP request.
*/
CURLcode Curl_http(struct connectdata *conn, bool *done)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
struct HTTP *http;
const char *ppath = data->state.path;
@ -1946,10 +1923,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
#endif
if(conn->httpversion == 20)
/* In HTTP2 forbids Transfer-Encoding: chunked */
ptr = NULL;
else {
ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
if(ptr) {
/* Some kind of TE is requested, check if 'chunked' is chosen */
@ -1980,13 +1953,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(data->req.upload_chunky)
te = "Transfer-Encoding: chunked\r\n";
}
}
Curl_safefree(conn->allocptr.host);
ptr = Curl_checkheaders(conn, "Host:");
if(ptr && (!data->state.this_is_a_follow ||
Curl_raw_equal(data->state.first_host, conn->host.name))) {
strcasecompare(data->state.first_host, conn->host.name))) {
#if !defined(CURL_DISABLE_COOKIES)
/* If we have a given custom Host: header, we extract the host name in
order to possibly use it for cookie reasons later on. We only allow the
@ -2266,9 +2238,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
}
/* Use 1.1 unless the user specifically asked for 1.0 or the server only
supports 1.0 */
httpstring= use_http_1_1plus(data, conn)?"1.1":"1.0";
httpstring = get_http_string(data, conn);
/* initialize a dynamic send-buffer */
req_buffer = Curl_add_buffer_init();
@ -2305,6 +2275,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
"%s" /* TE: */
"%s" /* accept-encoding */
"%s" /* referer */
"%s" /* Proxy-Connection */
"%s",/* transfer-encoding */
ftp_typecode,
@ -2327,6 +2298,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.accept_encoding:"",
(data->change.referer && conn->allocptr.ref)?
conn->allocptr.ref:"" /* Referer: <data> */,
(conn->bits.httpproxy &&
!conn->bits.tunnel_proxy &&
!Curl_checkProxyheaders(conn, "Proxy-Connection:"))?
"Proxy-Connection: Keep-Alive\r\n":"",
te
);
@ -2392,7 +2367,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
co = co->next; /* next cookie please */
}
Curl_cookie_freelist(store, FALSE); /* free the cookie list */
Curl_cookie_freelist(store);
}
if(addcookies && !result) {
if(!count)
@ -2537,7 +2512,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
postsize = data->state.infilesize;
if((postsize != -1) && !data->req.upload_chunky &&
!Curl_checkheaders(conn, "Content-Length:")) {
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
/* only add Content-Length if not uploading chunked */
result = Curl_add_bufferf(req_buffer,
"Content-Length: %" CURL_FORMAT_CURL_OFF_T
@ -2589,7 +2564,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
we don't upload data chunked, as RFC2616 forbids us to set both
kinds of headers (Transfer-Encoding: chunked and Content-Length) */
if((postsize != -1) && !data->req.upload_chunky &&
!Curl_checkheaders(conn, "Content-Length:")) {
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
/* we allow replacing this header if not during auth negotiation,
although it isn't very wise to actually set your own */
result = Curl_add_bufferf(req_buffer,
@ -2768,6 +2743,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
}
if((conn->httpversion == 20) && data->req.upload_chunky)
/* upload_chunky was set above to set up the request in a chunky fashion,
but is disabled here again to avoid that the chunked encoded version is
actually used when sending the request body over h2 */
data->req.upload_chunky = FALSE;
return result;
}
@ -2777,7 +2757,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
* Returns TRUE if member of the list matches prefix of string
*/
static bool
checkhttpprefix(struct SessionHandle *data,
checkhttpprefix(struct Curl_easy *data,
const char *s)
{
struct curl_slist *head = data->set.http200aliases;
@ -2816,7 +2796,7 @@ checkhttpprefix(struct SessionHandle *data,
#ifndef CURL_DISABLE_RTSP
static bool
checkrtspprefix(struct SessionHandle *data,
checkrtspprefix(struct Curl_easy *data,
const char *s)
{
@ -2844,7 +2824,7 @@ checkrtspprefix(struct SessionHandle *data,
#endif /* CURL_DISABLE_RTSP */
static bool
checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
const char *s)
{
#ifndef CURL_DISABLE_RTSP
@ -2862,7 +2842,7 @@ checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
* header. We make sure that the full string fit in the allocated header
* buffer, or else we enlarge it.
*/
static CURLcode header_append(struct SessionHandle *data,
static CURLcode header_append(struct Curl_easy *data,
struct SingleRequest *k,
size_t length)
{
@ -2900,7 +2880,7 @@ static CURLcode header_append(struct SessionHandle *data,
return CURLE_OK;
}
static void print_http_error(struct SessionHandle *data)
static void print_http_error(struct Curl_easy *data)
{
struct SingleRequest *k = &data->req;
char *beg = k->p;
@ -2940,7 +2920,7 @@ static void print_http_error(struct SessionHandle *data)
/*
* Read any HTTP header lines from the server and pass them to the client app.
*/
CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
struct connectdata *conn,
ssize_t *nread,
bool *stop_reading)
@ -3040,6 +3020,9 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
#endif /* CURL_DOES_CONVERSIONS */
if(100 <= k->httpcode && 199 >= k->httpcode) {
/* "A user agent MAY ignore unexpected 1xx status responses." */
switch(k->httpcode) {
case 100:
/*
* We have made a HTTP PUT or POST and this is 1.1-lingo
* that tells us that the server is OK with this and ready
@ -3050,11 +3033,8 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
k->header = TRUE;
k->headerline = 0; /* restart the header line counter */
/* "A user agent MAY ignore unexpected 1xx status responses." */
switch(k->httpcode) {
case 100:
/* if we did wait for this do enable write now! */
if(k->exp100) {
if(k->exp100 > EXP100_SEND_DATA) {
k->exp100 = EXP100_SEND_DATA;
k->keepon |= KEEP_SEND;
}
@ -3062,9 +3042,14 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
case 101:
/* Switching Protocols */
if(k->upgr101 == UPGR101_REQUESTED) {
/* Switching to HTTP/2 */
infof(data, "Received 101\n");
k->upgr101 = UPGR101_RECEIVED;
/* we'll get more headers (HTTP/2 response) */
k->header = TRUE;
k->headerline = 0; /* restart the header line counter */
/* switch to http2 now. The bytes after response headers
are also processed here, otherwise they are lost. */
result = Curl_http2_switched(conn, k->str, *nread);
@ -3072,8 +3057,16 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
return result;
*nread = 0;
}
else {
/* Switching to another protocol (e.g. WebSocket) */
k->header = FALSE; /* no more header to parse! */
}
break;
default:
/* the status code 1xx indicates a provisional response, so
we'll get another set of headers */
k->header = TRUE;
k->headerline = 0; /* restart the header line counter */
break;
}
}
@ -3091,7 +3084,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
signal the end of the document. */
infof(data, "no chunk, no close, no size. Assume close to "
"signal end\n");
connclose(conn, "HTTP: No end-of-message indicator");
streamclose(conn, "HTTP: No end-of-message indicator");
}
}
@ -3138,7 +3131,6 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
data->req.deductheadercount =
(100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
if(!*stop_reading) {
/* Curl_http_auth_act() checks what authentication methods
* that are available and decides which one (if any) to
* use. It will set 'newurl' if an auth method was picked. */
@ -3172,20 +3164,28 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
* connection for closure after we've read the entire response.
*/
if(!k->upload_done) {
if(data->set.http_keep_sending_on_error) {
infof(data, "HTTP error before end of send, keep sending\n");
if(k->exp100 > EXP100_SEND_DATA) {
k->exp100 = EXP100_SEND_DATA;
k->keepon |= KEEP_SEND;
}
}
else {
infof(data, "HTTP error before end of send, stop sending\n");
connclose(conn, "Stop sending data before everything sent");
streamclose(conn, "Stop sending data before everything sent");
k->upload_done = TRUE;
k->keepon &= ~KEEP_SEND; /* don't send */
if(data->state.expect100header)
k->exp100 = EXP100_FAILED;
}
}
break;
default: /* default label present to avoid compiler warnings */
break;
}
}
}
if(conn->bits.rewindaftersend) {
/* We rewind after a complete send, so thus we continue
@ -3210,7 +3210,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
(k->size <= -1))
/* Respect section 4.4 of rfc2326: If the Content-Length header is
absent, a length 0 must be assumed. It will prevent libcurl from
hanging on DECRIBE request that got refused for whatever
hanging on DESCRIBE request that got refused for whatever
reason */
*stop_reading = TRUE;
#endif
@ -3308,6 +3308,13 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
&httpversion_major,
&conn->httpversion,
&k->httpcode);
if(nc == 1 && httpversion_major == 2 &&
1 == sscanf(HEADER1, " HTTP/2 %d", &k->httpcode)) {
conn->httpversion = 0;
nc = 3;
}
if(nc==3) {
conn->httpversion += 10 * httpversion_major;
@ -3471,7 +3478,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
/* Negative Content-Length is really odd, and we know it
happens for example when older Apache servers send large
files */
connclose(conn, "negative content-length");
streamclose(conn, "negative content-length");
infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
", closing after transfer\n", contentlength);
}
@ -3544,7 +3551,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
* the connection will close when this request has been
* served.
*/
connclose(conn, "Connection: close used");
streamclose(conn, "Connection: close used");
}
else if(checkprefix("Transfer-Encoding:", k->p)) {
/* One or more encodings. We check for chunked and/or a compression
@ -3754,7 +3761,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
k->hbufp = data->state.headerbuff;
k->hbuflen = 0;
}
while(!*stop_reading && *k->str); /* header line within buffer */
while(*k->str); /* header line within buffer */
/* We might have reached the end of the header part here, but
there might be a non-header part left in the end of the read

View File

@ -69,7 +69,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
size_t included_body_bytes,
int socketindex);
CURLcode Curl_add_timecondition(struct SessionHandle *data,
CURLcode Curl_add_timecondition(struct Curl_easy *data,
Curl_send_buffer *buf);
CURLcode Curl_add_custom_headers(struct connectdata *conn,
bool is_connect,
@ -87,7 +87,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,
ssize_t length, ssize_t *wrote);
/* These functions are in http.c */
void Curl_http_auth_stage(struct SessionHandle *data, int stage);
void Curl_http_auth_stage(struct Curl_easy *data, int stage);
CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
const char *auth);
CURLcode Curl_http_auth_act(struct connectdata *conn);
@ -168,6 +168,7 @@ struct HTTP {
const uint8_t *pausedata; /* pointer to data received in on_data_chunk */
size_t pauselen; /* the number of bytes left in data */
bool closed; /* TRUE on HTTP2 stream close */
bool close_handled; /* TRUE if stream closure is handled by libcurl */
uint32_t error_code; /* HTTP/2 error code */
char *mem; /* points to a buffer in memory to store received data */
@ -216,14 +217,18 @@ struct http_conn {
nghttp2_session_mem_recv */
size_t drain_total; /* sum of all stream's UrlState.drain */
/* this is a hash of all individual streams (SessionHandle structs) */
/* this is a hash of all individual streams (Curl_easy structs) */
struct h2settings settings;
/* list of settings that will be sent */
nghttp2_settings_entry local_settings[3];
size_t local_settings_num;
#else
int unused; /* prevent a compiler warning */
#endif
};
CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
struct connectdata *conn,
ssize_t *nread,
bool *stop_reading);

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2016, 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
@ -29,13 +29,13 @@
#include "http.h"
#include "sendf.h"
#include "curl_base64.h"
#include "rawstr.h"
#include "strcase.h"
#include "multiif.h"
#include "conncache.h"
#include "url.h"
#include "connect.h"
#include "strtoofft.h"
#include "strdup.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@ -59,6 +59,12 @@
#define nghttp2_session_callbacks_set_error_callback(x,y)
#endif
#if (NGHTTP2_VERSION_NUM >= 0x010c00)
#define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1
#endif
#define HTTP2_HUGE_WINDOW_SIZE (1 << 30)
/*
* Curl_http2_init_state() is called when the easy handle is created and
* allows for HTTP/2 specific init of state.
@ -92,7 +98,8 @@ static int http2_perform_getsock(const struct connectdata *conn,
because of renegotiation. */
sock[0] = conn->sock[FIRSTSOCKET];
if(nghttp2_session_want_read(c->h2))
/* in a HTTP/2 connection we can basically always get a frame so we should
always be ready for one */
bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
if(nghttp2_session_want_write(c->h2))
@ -109,18 +116,11 @@ static int http2_getsock(struct connectdata *conn,
return http2_perform_getsock(conn, sock, numsocks);
}
static CURLcode http2_disconnect(struct connectdata *conn,
bool dead_connection)
/*
* http2_stream_free() free HTTP2 stream related data
*/
static void http2_stream_free(struct HTTP *http)
{
struct HTTP *http = conn->data->req.protop;
struct http_conn *c = &conn->proto.httpc;
(void)dead_connection;
DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
nghttp2_session_del(c->h2);
Curl_safefree(c->inbuf);
if(http) {
Curl_add_buffer_free(http->header_recvbuf);
http->header_recvbuf = NULL; /* clear the pointer */
@ -132,6 +132,19 @@ static CURLcode http2_disconnect(struct connectdata *conn,
free(http->push_headers);
http->push_headers = NULL;
}
}
static CURLcode http2_disconnect(struct connectdata *conn,
bool dead_connection)
{
struct http_conn *c = &conn->proto.httpc;
(void)dead_connection;
DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT starts now\n"));
nghttp2_session_del(c->h2);
Curl_safefree(c->inbuf);
http2_stream_free(conn->data->req.protop);
DEBUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
@ -139,7 +152,7 @@ static CURLcode http2_disconnect(struct connectdata *conn,
}
/* called from Curl_http_setup_conn */
void Curl_http2_setup_req(struct SessionHandle *data)
void Curl_http2_setup_req(struct Curl_easy *data)
{
struct HTTP *http = data->req.protop;
@ -150,6 +163,7 @@ void Curl_http2_setup_req(struct SessionHandle *data)
http->pauselen = 0;
http->error_code = NGHTTP2_NO_ERROR;
http->closed = FALSE;
http->close_handled = FALSE;
http->mem = data->state.buffer;
http->len = BUFSIZE;
http->memlen = 0;
@ -184,7 +198,7 @@ const struct Curl_handler Curl_handler_http2 = {
ZERO_NULL, /* readwrite */
PORT_HTTP, /* defport */
CURLPROTO_HTTP, /* protocol */
PROTOPT_NONE /* flags */
PROTOPT_STREAM /* flags */
};
const struct Curl_handler Curl_handler_http2_ssl = {
@ -204,7 +218,7 @@ const struct Curl_handler Curl_handler_http2_ssl = {
ZERO_NULL, /* readwrite */
PORT_HTTP, /* defport */
CURLPROTO_HTTPS, /* protocol */
PROTOPT_SSL /* flags */
PROTOPT_SSL | PROTOPT_STREAM /* flags */
};
/*
@ -221,7 +235,8 @@ int Curl_http2_ver(char *p, size_t len)
https://tools.ietf.org/html/rfc7540#page-77
nghttp2_error_code enums are identical.
*/
const char *Curl_http2_strerror(uint32_t err) {
const char *Curl_http2_strerror(uint32_t err)
{
#ifndef NGHTTP2_HAS_HTTP2_STRERROR
const char *str[] = {
"NO_ERROR", /* 0x0 */
@ -284,7 +299,7 @@ static ssize_t send_callback(nghttp2_session *h2,
/* We pass a pointer to this struct in the push callback, but the contents of
the struct are hidden from the user. */
struct curl_pushheaders {
struct SessionHandle *data;
struct Curl_easy *data;
const nghttp2_push_promise *frame;
};
@ -317,7 +332,7 @@ char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
the middle of header, it could be matched in middle of the value,
this is because we do prefix match.*/
if(!h || !GOOD_EASY_HANDLE(h->data) || !header || !header[0] ||
Curl_raw_equal(header, ":") || strchr(header + 1, ':'))
!strcmp(header, ":") || strchr(header + 1, ':'))
return NULL;
else {
struct HTTP *stream = h->data->req.protop;
@ -335,9 +350,9 @@ char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
return NULL;
}
static CURL *duphandle(struct SessionHandle *data)
static struct Curl_easy *duphandle(struct Curl_easy *data)
{
struct SessionHandle *second = curl_easy_duphandle(data);
struct Curl_easy *second = curl_easy_duphandle(data);
if(second) {
/* setup the request struct */
struct HTTP *http = calloc(1, sizeof(struct HTTP));
@ -363,7 +378,7 @@ static CURL *duphandle(struct SessionHandle *data)
}
static int push_promise(struct SessionHandle *data,
static int push_promise(struct Curl_easy *data,
struct connectdata *conn,
const nghttp2_push_promise *frame)
{
@ -378,7 +393,7 @@ static int push_promise(struct SessionHandle *data,
struct http_conn *httpc;
size_t i;
/* clone the parent */
struct SessionHandle *newhandle = duphandle(data);
struct Curl_easy *newhandle = duphandle(data);
if(!newhandle) {
infof(data, "failed to duplicate handle\n");
rv = 1; /* FAIL HARD */
@ -406,9 +421,11 @@ static int push_promise(struct SessionHandle *data,
free(stream->push_headers[i]);
free(stream->push_headers);
stream->push_headers = NULL;
stream->push_headers_used = 0;
if(rv) {
/* denied, kill off the new handle again */
http2_stream_free(newhandle->req.protop);
(void)Curl_close(newhandle);
goto fail;
}
@ -423,6 +440,7 @@ static int push_promise(struct SessionHandle *data,
rc = Curl_multi_add_perform(data->multi, newhandle, conn);
if(rc) {
infof(data, "failed to add handle to multi\n");
http2_stream_free(newhandle->req.protop);
Curl_close(newhandle);
rv = 1;
goto fail;
@ -445,7 +463,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
{
struct connectdata *conn = (struct connectdata *)userp;
struct http_conn *httpc = &conn->proto.httpc;
struct SessionHandle *data_s = NULL;
struct Curl_easy *data_s = NULL;
struct HTTP *stream = NULL;
static int lastStream = -1;
int rv;
@ -482,14 +500,17 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
}
if(!data_s) {
DEBUGF(infof(conn->data,
"No SessionHandle associated with stream: %x\n",
"No Curl_easy associated with stream: %x\n",
stream_id));
return 0;
}
stream = data_s->req.protop;
if(!stream)
if(!stream) {
DEBUGF(infof(conn->data, "No proto pointer for stream: %x\n",
stream_id));
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
DEBUGF(infof(data_s, "on_frame_recv() header %x stream %x\n",
frame->hd.type, stream_id));
@ -547,7 +568,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
/* if we receive data for another handle, wake that up */
if(conn_s->data != data_s)
Curl_expire(data_s, 1);
Curl_expire(data_s, 0);
}
break;
case NGHTTP2_PUSH_PROMISE:
@ -573,7 +594,7 @@ static int on_invalid_frame_recv(nghttp2_session *session,
const nghttp2_frame *frame,
int lib_error_code, void *userp)
{
struct SessionHandle *data_s = NULL;
struct Curl_easy *data_s = NULL;
(void)userp;
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
@ -590,7 +611,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
const uint8_t *data, size_t len, void *userp)
{
struct HTTP *stream;
struct SessionHandle *data_s;
struct Curl_easy *data_s;
size_t nread;
struct connectdata *conn = (struct connectdata *)userp;
(void)session;
@ -621,8 +642,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
Curl_expire(data_s, 1); /* TODO: fix so that this can be set to 0 for
immediately? */
Curl_expire(data_s, 0);
DEBUGF(infof(data_s, "%zu data received for stream %u "
"(%zu left in buffer %p, total %zu)\n",
@ -656,7 +676,7 @@ static int before_frame_send(nghttp2_session *session,
const nghttp2_frame *frame,
void *userp)
{
struct SessionHandle *data_s;
struct Curl_easy *data_s;
(void)userp;
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
@ -670,7 +690,7 @@ static int on_frame_send(nghttp2_session *session,
const nghttp2_frame *frame,
void *userp)
{
struct SessionHandle *data_s;
struct Curl_easy *data_s;
(void)userp;
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
@ -684,7 +704,7 @@ static int on_frame_not_send(nghttp2_session *session,
const nghttp2_frame *frame,
int lib_error_code, void *userp)
{
struct SessionHandle *data_s;
struct Curl_easy *data_s;
(void)userp;
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
@ -698,7 +718,7 @@ static int on_frame_not_send(nghttp2_session *session,
static int on_stream_close(nghttp2_session *session, int32_t stream_id,
uint32_t error_code, void *userp)
{
struct SessionHandle *data_s;
struct Curl_easy *data_s;
struct HTTP *stream;
struct connectdata *conn = (struct connectdata *)userp;
(void)session;
@ -735,7 +755,7 @@ static int on_begin_headers(nghttp2_session *session,
const nghttp2_frame *frame, void *userp)
{
struct HTTP *stream;
struct SessionHandle *data_s = NULL;
struct Curl_easy *data_s = NULL;
(void)userp;
data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
@ -802,7 +822,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
void *userp)
{
struct HTTP *stream;
struct SessionHandle *data_s;
struct Curl_easy *data_s;
int32_t stream_id = frame->hd.stream_id;
struct connectdata *conn = (struct connectdata *)userp;
(void)flags;
@ -837,10 +857,9 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
stream->push_headers_alloc) {
char **headp;
stream->push_headers_alloc *= 2;
headp = realloc(stream->push_headers,
headp = Curl_saferealloc(stream->push_headers,
stream->push_headers_alloc * sizeof(char *));
if(!headp) {
free(stream->push_headers);
stream->push_headers = NULL;
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
@ -883,7 +902,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
Curl_add_buffer(stream->header_recvbuf, " \r\n", 3);
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
Curl_expire(data_s, 1);
Curl_expire(data_s, 0);
DEBUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
stream->status_code, data_s));
@ -899,7 +918,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
Curl_expire(data_s, 1);
Curl_expire(data_s, 0);
DEBUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
value));
@ -914,7 +933,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
nghttp2_data_source *source,
void *userp)
{
struct SessionHandle *data_s;
struct Curl_easy *data_s;
struct HTTP *stream = NULL;
size_t nread;
(void)source;
@ -941,11 +960,12 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
memcpy(buf, stream->upload_mem, nread);
stream->upload_mem += nread;
stream->upload_len -= nread;
if(data_s->state.infilesize != -1)
stream->upload_left -= nread;
}
if(stream->upload_left == 0)
*data_flags = 1;
*data_flags = NGHTTP2_DATA_FLAG_EOF;
else if(nread == 0)
return NGHTTP2_ERR_DEFERRED;
@ -956,14 +976,6 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
return nread;
}
/*
* The HTTP2 settings we send in the Upgrade request
*/
static nghttp2_settings_entry settings[] = {
{ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 },
{ NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE },
};
#define H2_BUFSIZE 32768
#ifdef NGHTTP2_HAS_ERROR_CALLBACK
@ -979,6 +991,60 @@ static int error_callback(nghttp2_session *session,
}
#endif
static void populate_settings(struct connectdata *conn,
struct http_conn *httpc)
{
nghttp2_settings_entry *iv = httpc->local_settings;
iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
iv[0].value = 100;
iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
iv[1].value = HTTP2_HUGE_WINDOW_SIZE;
iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
iv[2].value = conn->data->multi->push_cb != NULL;
httpc->local_settings_num = 3;
}
void Curl_http2_done(struct connectdata *conn, bool premature)
{
struct Curl_easy *data = conn->data;
struct HTTP *http = data->req.protop;
struct http_conn *httpc = &conn->proto.httpc;
if(http->header_recvbuf) {
DEBUGF(infof(data, "free header_recvbuf!!\n"));
Curl_add_buffer_free(http->header_recvbuf);
http->header_recvbuf = NULL; /* clear the pointer */
Curl_add_buffer_free(http->trailer_recvbuf);
http->trailer_recvbuf = NULL; /* clear the pointer */
if(http->push_headers) {
/* if they weren't used and then freed before */
for(; http->push_headers_used > 0; --http->push_headers_used) {
free(http->push_headers[http->push_headers_used - 1]);
}
free(http->push_headers);
http->push_headers = NULL;
}
}
if(premature) {
/* RST_STREAM */
nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE, http->stream_id,
NGHTTP2_STREAM_CLOSED);
if(http->stream_id == httpc->pause_stream_id) {
infof(data, "stopped the pause stream!\n");
httpc->pause_stream_id = 0;
}
}
if(http->stream_id) {
nghttp2_session_set_stream_user_data(httpc->h2, http->stream_id, 0);
http->stream_id = 0;
}
}
/*
* Initialize nghttp2 for a Curl connection
*/
@ -1055,16 +1121,14 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
size_t blen;
struct SingleRequest *k = &conn->data->req;
uint8_t *binsettings = conn->proto.httpc.binsettings;
struct http_conn *httpc = &conn->proto.httpc;
/* As long as we have a fixed set of settings, we don't have to dynamically
* figure out the base64 strings since it'll always be the same. However,
* the settings will likely not be fixed every time in the future.
*/
populate_settings(conn, httpc);
/* this returns number of bytes it wrote */
binlen = nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN,
settings,
sizeof(settings)/sizeof(settings[0]));
httpc->local_settings,
httpc->local_settings_num);
if(!binlen) {
failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
return CURLE_FAILED_INIT;
@ -1091,12 +1155,13 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
/*
* Returns nonzero if current HTTP/2 session should be closed.
*/
static int should_close_session(struct http_conn *httpc) {
static int should_close_session(struct http_conn *httpc)
{
return httpc->drain_total == 0 && !nghttp2_session_want_read(httpc->h2) &&
!nghttp2_session_want_write(httpc->h2);
}
static int h2_session_send(struct SessionHandle *data,
static int h2_session_send(struct Curl_easy *data,
nghttp2_session *h2);
/*
@ -1105,9 +1170,10 @@ static int h2_session_send(struct SessionHandle *data,
* This function returns 0 if it succeeds, or -1 and error code will
* be assigned to *err.
*/
static int h2_process_pending_input(struct SessionHandle *data,
static int h2_process_pending_input(struct Curl_easy *data,
struct http_conn *httpc,
CURLcode *err) {
CURLcode *err)
{
ssize_t nread;
char *inbuf;
ssize_t rv;
@ -1155,9 +1221,41 @@ static int h2_process_pending_input(struct SessionHandle *data,
return 0;
}
/*
* Called from transfer.c:done_sending when we stop uploading.
*/
CURLcode Curl_http2_done_sending(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
if((conn->handler == &Curl_handler_http2_ssl) ||
(conn->handler == &Curl_handler_http2)) {
/* make sure this is only attempted for HTTP/2 transfers */
struct HTTP *stream = conn->data->req.protop;
if(stream->upload_left) {
/* If the stream still thinks there's data left to upload. */
struct http_conn *httpc = &conn->proto.httpc;
nghttp2_session *h2 = httpc->h2;
stream->upload_left = 0; /* DONE! */
/* resume sending here to trigger the callback to get called again so
that it can signal EOF to nghttp2 */
(void)nghttp2_session_resume_data(h2, stream->stream_id);
(void)h2_process_pending_input(conn->data, httpc, &result);
}
}
return result;
}
static ssize_t http2_handle_stream_close(struct connectdata *conn,
struct SessionHandle *data,
struct HTTP *stream, CURLcode *err) {
struct Curl_easy *data,
struct HTTP *stream, CURLcode *err)
{
char *trailer_pos, *trailer_end;
CURLcode result;
struct http_conn *httpc = &conn->proto.httpc;
@ -1178,8 +1276,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
DEBUGASSERT(data->state.drain == 0);
/* Reset to FALSE to prevent infinite loop in readwrite_data
function. */
/* Reset to FALSE to prevent infinite loop in readwrite_data function. */
stream->closed = FALSE;
if(stream->error_code != NGHTTP2_NO_ERROR) {
failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)",
@ -1216,6 +1313,8 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
}
}
stream->close_handled = TRUE;
DEBUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
return 0;
}
@ -1226,7 +1325,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
* struct.
*/
static void h2_pri_spec(struct SessionHandle *data,
static void h2_pri_spec(struct Curl_easy *data,
nghttp2_priority_spec *pri_spec)
{
struct HTTP *depstream = (data->set.stream_depends_on?
@ -1244,7 +1343,7 @@ static void h2_pri_spec(struct SessionHandle *data,
* dependency settings and if so it submits a PRIORITY frame with the updated
* info.
*/
static int h2_session_send(struct SessionHandle *data,
static int h2_session_send(struct Curl_easy *data,
nghttp2_session *h2)
{
struct HTTP *stream = data->req.protop;
@ -1268,10 +1367,6 @@ static int h2_session_send(struct SessionHandle *data,
return nghttp2_session_send(h2);
}
/*
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
* a regular CURLcode value.
*/
static ssize_t http2_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len, CURLcode *err)
{
@ -1279,7 +1374,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
ssize_t rv;
ssize_t nread;
struct http_conn *httpc = &conn->proto.httpc;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct HTTP *stream = data->req.protop;
(void)sockindex; /* we always do HTTP2 on sockindex 0 */
@ -1297,7 +1392,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
stream->upload_len = 0;
/*
* At this point 'stream' is just in the SessionHandle the connection
* At this point 'stream' is just in the Curl_easy the connection
* identifies as its owner at this time.
*/
@ -1382,6 +1477,8 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
socket is not read. But it seems that usually streams are
notified with its drain property, and socket is read again
quickly. */
DEBUGF(infof(data, "stream %x is paused, pause id: %x\n",
stream->stream_id, httpc->pause_stream_id));
*err = CURLE_AGAIN;
return -1;
}
@ -1497,7 +1594,72 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
#define HEADER_OVERFLOW(x) \
(x.namelen > (uint16_t)-1 || x.valuelen > (uint16_t)-1 - x.namelen)
/* return number of received (decrypted) bytes */
/*
* Check header memory for the token "trailers".
* Parse the tokens as separated by comma and surrounded by whitespace.
* Returns TRUE if found or FALSE if not.
*/
static bool contains_trailers(const char *p, size_t len)
{
const char *end = p + len;
for(;;) {
for(; p != end && (*p == ' ' || *p == '\t'); ++p)
;
if(p == end || (size_t)(end - p) < sizeof("trailers") - 1)
return FALSE;
if(strncasecompare("trailers", p, sizeof("trailers") - 1)) {
p += sizeof("trailers") - 1;
for(; p != end && (*p == ' ' || *p == '\t'); ++p)
;
if(p == end || *p == ',')
return TRUE;
}
/* skip to next token */
for(; p != end && *p != ','; ++p)
;
if(p == end)
return FALSE;
++p;
}
}
typedef enum {
/* Send header to server */
HEADERINST_FORWARD,
/* Don't send header to server */
HEADERINST_IGNORE,
/* Discard header, and replace it with "te: trailers" */
HEADERINST_TE_TRAILERS
} header_instruction;
/* Decides how to treat given header field. */
static header_instruction inspect_header(const char *name, size_t namelen,
const char *value, size_t valuelen) {
switch(namelen) {
case 2:
if(!strncasecompare("te", name, namelen))
return HEADERINST_FORWARD;
return contains_trailers(value, valuelen) ?
HEADERINST_TE_TRAILERS : HEADERINST_IGNORE;
case 7:
return strncasecompare("upgrade", name, namelen) ?
HEADERINST_IGNORE : HEADERINST_FORWARD;
case 10:
return (strncasecompare("connection", name, namelen) ||
strncasecompare("keep-alive", name, namelen)) ?
HEADERINST_IGNORE : HEADERINST_FORWARD;
case 16:
return strncasecompare("proxy-connection", name, namelen) ?
HEADERINST_IGNORE : HEADERINST_FORWARD;
case 17:
return strncasecompare("transfer-encoding", name, namelen) ?
HEADERINST_IGNORE : HEADERINST_FORWARD;
default:
return HEADERINST_FORWARD;
}
}
static ssize_t http2_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
@ -1525,6 +1687,14 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
DEBUGF(infof(conn->data, "http2_send len=%zu\n", len));
if(stream->stream_id != -1) {
if(stream->close_handled) {
infof(conn->data, "stream %d closed\n", stream->stream_id);
*err = CURLE_HTTP2_STREAM;
return -1;
}
else if(stream->closed) {
return http2_handle_stream_close(conn, conn->data, stream, err);
}
/* If stream_id != -1, we have dispatched request HEADERS, and now
are going to send or sending request body in DATA frame */
stream->upload_mem = mem;
@ -1643,7 +1813,6 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
i = 3;
while(i < nheader) {
size_t hlen;
int skip = 0;
hdbuf = line_end + 2;
@ -1661,12 +1830,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
goto fail;
hlen = end - hdbuf;
if(hlen == 10 && Curl_raw_nequal("connection", hdbuf, 10)) {
/* skip Connection: headers! */
skip = 1;
--nheader;
}
else if(hlen == 4 && Curl_raw_nequal("host", hdbuf, 4)) {
if(hlen == 4 && strncasecompare("host", hdbuf, 4)) {
authority_idx = i;
nva[i].name = (unsigned char *)":authority";
nva[i].namelen = strlen((char *)nva[i].name);
@ -1679,39 +1843,29 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
while(*hdbuf == ' ' || *hdbuf == '\t')
++hdbuf;
end = line_end;
if(!skip) {
switch(inspect_header((const char *)nva[i].name, nva[i].namelen, hdbuf,
end - hdbuf)) {
case HEADERINST_IGNORE:
/* skip header fields prohibited by HTTP/2 specification. */
--nheader;
continue;
case HEADERINST_TE_TRAILERS:
nva[i].value = (uint8_t*)"trailers";
nva[i].valuelen = sizeof("trailers") - 1;
break;
default:
nva[i].value = (unsigned char *)hdbuf;
nva[i].valuelen = (size_t)(end - hdbuf);
}
nva[i].flags = NGHTTP2_NV_FLAG_NONE;
if(HEADER_OVERFLOW(nva[i])) {
failf(conn->data, "Failed sending HTTP request: Header overflow");
goto fail;
}
/* Inspect Content-Length header field and retrieve the request
entity length so that we can set END_STREAM to the last DATA
frame. */
if(nva[i].namelen == 14 &&
Curl_raw_nequal("content-length", (char*)nva[i].name, 14)) {
size_t j;
stream->upload_left = 0;
if(!nva[i].valuelen)
goto fail;
for(j = 0; j < nva[i].valuelen; ++j) {
if(nva[i].value[j] < '0' || nva[i].value[j] > '9')
goto fail;
if(stream->upload_left >= CURL_OFF_T_MAX / 10)
goto fail;
stream->upload_left *= 10;
stream->upload_left += nva[i].value[j] - '0';
}
DEBUGF(infof(conn->data,
"request content-length=%"
CURL_FORMAT_CURL_OFF_T
"\n", stream->upload_left));
}
++i;
}
}
/* :authority must come before non-pseudo header fields */
if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) {
@ -1724,24 +1878,22 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
/* Warn stream may be rejected if cumulative length of headers is too large.
It appears nghttp2 will not send a header frame larger than 64KB. */
#define MAX_ACC 60000 /* <64KB to account for some overhead */
{
size_t acc = 0;
const size_t max_acc = 60000; /* <64KB to account for some overhead */
for(i = 0; i < nheader; ++i) {
if(nva[i].namelen > max_acc - acc)
break;
acc += nva[i].namelen;
acc += nva[i].namelen + nva[i].valuelen;
if(nva[i].valuelen > max_acc - acc)
break;
acc += nva[i].valuelen;
DEBUGF(infof(conn->data, "h2 header: %.*s:%.*s\n",
nva[i].namelen, nva[i].name,
nva[i].valuelen, nva[i].value));
}
if(i != nheader) {
if(acc > MAX_ACC) {
infof(conn->data, "http2_send: Warning: The cumulative length of all "
"headers exceeds %zu bytes and that could cause the "
"stream to be rejected.\n", max_acc);
"stream to be rejected.\n", MAX_ACC);
}
}
@ -1751,6 +1903,12 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
case HTTPREQ_PUT:
if(conn->data->state.infilesize != -1)
stream->upload_left = conn->data->state.infilesize;
else
/* data sending without specifying the data amount up front */
stream->upload_left = -1; /* unknown, but not zero */
data_prd.read_callback = data_source_read_callback;
data_prd.source.ptr = NULL;
stream_id = nghttp2_submit_request(h2, &pri_spec, nva, nheader,
@ -1850,10 +2008,6 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n");
Curl_multi_connchanged(conn->data->multi);
/* switch on TCP_NODELAY as we need to send off packets without delay for
maximum throughput */
Curl_tcpnodelay(conn, conn->sock[FIRSTSOCKET]);
return CURLE_OK;
}
@ -1864,7 +2018,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
struct http_conn *httpc = &conn->proto.httpc;
int rv;
ssize_t nproc;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct HTTP *stream = conn->data->req.protop;
result = Curl_http2_setup(conn);
@ -1893,9 +2047,13 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
conn->data);
}
else {
populate_settings(conn, httpc);
/* stream ID is unknown at this point */
stream->stream_id = -1;
rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0);
rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE,
httpc->local_settings,
httpc->local_settings_num);
if(rv != 0) {
failf(data, "nghttp2_submit_settings() failed: %s(%d)",
nghttp2_strerror(rv), rv);
@ -1903,6 +2061,16 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
}
}
#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0,
HTTP2_HUGE_WINDOW_SIZE);
if(rv != 0) {
failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
nghttp2_strerror(rv), rv);
return CURLE_HTTP2;
}
#endif
/* we are going to copy mem to httpc->inbuf. This is required since
mem is part of buffer pointed by stream->mem, and callbacks
called by nghttp2_session_mem_recv() will write stream specific
@ -1918,6 +2086,7 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
" after upgrade: len=%zu\n",
nread);
if(nread)
memcpy(httpc->inbuf, mem, nread);
httpc->inbuflen = nread;
@ -1958,6 +2127,82 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
return CURLE_OK;
}
void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child,
bool exclusive)
{
struct Curl_http2_dep **tail;
struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep));
dep->data = child;
if(parent->set.stream_dependents && exclusive) {
struct Curl_http2_dep *node = parent->set.stream_dependents;
while(node) {
node->data->set.stream_depends_on = child;
node = node->next;
}
tail = &child->set.stream_dependents;
while(*tail)
tail = &(*tail)->next;
DEBUGASSERT(!*tail);
*tail = parent->set.stream_dependents;
parent->set.stream_dependents = 0;
}
tail = &parent->set.stream_dependents;
while(*tail) {
(*tail)->data->set.stream_depends_e = FALSE;
tail = &(*tail)->next;
}
DEBUGASSERT(!*tail);
*tail = dep;
child->set.stream_depends_on = parent;
child->set.stream_depends_e = exclusive;
}
void Curl_http2_remove_child(struct Curl_easy *parent, struct Curl_easy *child)
{
struct Curl_http2_dep *last = 0;
struct Curl_http2_dep *data = parent->set.stream_dependents;
DEBUGASSERT(child->set.stream_depends_on == parent);
while(data && data->data != child) {
last = data;
data = data->next;
}
DEBUGASSERT(data);
if(data) {
if(last) {
last->next = data->next;
}
else {
parent->set.stream_dependents = data->next;
}
free(data);
}
child->set.stream_depends_on = 0;
child->set.stream_depends_e = FALSE;
}
void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
{
while(data->set.stream_dependents) {
struct Curl_easy *tmp = data->set.stream_dependents->data;
Curl_http2_remove_child(data, tmp);
if(data->set.stream_depends_on)
Curl_http2_add_child(data->set.stream_depends_on, tmp, FALSE);
}
if(data->set.stream_depends_on)
Curl_http2_remove_child(data->set.stream_depends_on, data);
}
#else /* !USE_NGHTTP2 */
/* Satisfy external references even if http2 is not compiled in. */

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2016, 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
@ -50,7 +50,14 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
const char *data, size_t nread);
/* called from Curl_http_setup_conn */
void Curl_http2_setup_conn(struct connectdata *conn);
void Curl_http2_setup_req(struct SessionHandle *data);
void Curl_http2_setup_req(struct Curl_easy *data);
void Curl_http2_done(struct connectdata *conn, bool premature);
CURLcode Curl_http2_done_sending(struct connectdata *conn);
void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child,
bool exclusive);
void Curl_http2_remove_child(struct Curl_easy *parent,
struct Curl_easy *child);
void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
#else /* USE_NGHTTP2 */
#define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
@ -61,6 +68,11 @@ void Curl_http2_setup_req(struct SessionHandle *data);
#define Curl_http2_setup_req(x)
#define Curl_http2_init_state(x)
#define Curl_http2_init_userset(x)
#define Curl_http2_done(x,y)
#define Curl_http2_done_sending(x)
#define Curl_http2_add_child(x, y, z)
#define Curl_http2_remove_child(x, y)
#define Curl_http2_cleanup_dependencies(x)
#endif
#endif /* HEADER_CURL_HTTP2_H */

View File

@ -108,7 +108,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
ssize_t *wrotep)
{
CURLcode result=CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct Curl_chunker *ch = &conn->chunk;
struct SingleRequest *k = &data->req;
size_t piece;

View File

@ -25,7 +25,7 @@
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
#include "urldata.h"
#include "rawstr.h"
#include "strcase.h"
#include "vauth/vauth.h"
#include "http_digest.h"
/* The last 3 #include files should be in this order */
@ -45,7 +45,7 @@ CURLcode Curl_input_digest(struct connectdata *conn,
const char *header) /* rest of the *-authenticate:
header */
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
/* Point to the correct struct with this */
struct digestdata *digest;
@ -73,9 +73,9 @@ CURLcode Curl_output_digest(struct connectdata *conn,
const unsigned char *uripath)
{
CURLcode result;
struct SessionHandle *data = conn->data;
unsigned char *path;
char *tmp;
struct Curl_easy *data = conn->data;
unsigned char *path = NULL;
char *tmp = NULL;
char *response;
size_t len;
bool have_chlg;
@ -95,8 +95,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
if(proxy) {
digest = &data->state.proxydigest;
allocuserpwd = &conn->allocptr.proxyuserpwd;
userp = conn->proxyuser;
passwdp = conn->proxypasswd;
userp = conn->http_proxy.user;
passwdp = conn->http_proxy.passwd;
authp = &data->state.authproxy;
}
else {
@ -140,12 +140,14 @@ CURLcode Curl_output_digest(struct connectdata *conn,
http://www.fngtps.com/2006/09/http-authentication
*/
if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) {
if(authp->iestyle) {
tmp = strchr((char *)uripath, '?');
if(tmp) {
size_t urilen = tmp - (char *)uripath;
path = (unsigned char *) aprintf("%.*s", urilen, uripath);
}
else
}
if(!tmp)
path = (unsigned char *) strdup((char *) uripath);
if(!path)
@ -169,7 +171,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
return CURLE_OK;
}
void Curl_digest_cleanup(struct SessionHandle *data)
void Curl_digest_cleanup(struct Curl_easy *data)
{
Curl_auth_digest_cleanup(&data->state.digest);
Curl_auth_digest_cleanup(&data->state.proxydigest);

View File

@ -34,7 +34,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
const unsigned char *uripath);
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
void Curl_digest_cleanup(struct SessionHandle *data);
void Curl_digest_cleanup(struct Curl_easy *data);
#else
#define Curl_digest_cleanup(x) Curl_nop_stmt
#endif

View File

@ -26,7 +26,6 @@
#include "urldata.h"
#include "sendf.h"
#include "rawstr.h"
#include "http_negotiate.h"
#include "vauth/vauth.h"
@ -38,7 +37,8 @@
CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
const char *header)
{
struct SessionHandle *data = conn->data;
CURLcode result;
struct Curl_easy *data = conn->data;
size_t len;
/* Point to the username, password, service and host */
@ -51,11 +51,11 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
struct negotiatedata *neg_ctx;
if(proxy) {
userp = conn->proxyuser;
passwdp = conn->proxypasswd;
userp = conn->http_proxy.user;
passwdp = conn->http_proxy.passwd;
service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
host = conn->proxy.name;
host = conn->http_proxy.host.name;
neg_ctx = &data->state.proxyneg;
}
else {
@ -90,8 +90,13 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
}
/* Initilise the security context and decode our challenge */
return Curl_auth_decode_spnego_message(data, userp, passwdp, service, host,
header, neg_ctx);
result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
host, header, neg_ctx);
if(result)
Curl_auth_spnego_cleanup(neg_ctx);
return result;
}
CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
@ -124,7 +129,7 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
}
void Curl_cleanup_negotiate(struct SessionHandle *data)
void Curl_cleanup_negotiate(struct Curl_easy *data)
{
Curl_auth_spnego_cleanup(&data->state.negotiate);
Curl_auth_spnego_cleanup(&data->state.proxyneg);

View File

@ -31,7 +31,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
/* this is for creating Negotiate header output */
CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
void Curl_cleanup_negotiate(struct SessionHandle *data);
void Curl_cleanup_negotiate(struct Curl_easy *data);
#endif /* USE_SPNEGO */

View File

@ -27,7 +27,7 @@
/*
* NTLM details:
*
* http://davenport.sourceforge.net/ntlm.html
* https://davenport.sourceforge.io/ntlm.html
* https://www.innovation.ch/java/ntlm.html
*/
@ -35,7 +35,7 @@
#include "urldata.h"
#include "sendf.h"
#include "rawstr.h"
#include "strcase.h"
#include "http_ntlm.h"
#include "curl_ntlm_wb.h"
#include "vauth/vauth.h"
@ -136,8 +136,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
if(proxy) {
allocuserpwd = &conn->allocptr.proxyuserpwd;
userp = conn->proxyuser;
passwdp = conn->proxypasswd;
userp = conn->http_proxy.user;
passwdp = conn->http_proxy.passwd;
ntlm = &conn->proxyntlm;
authp = &conn->data->state.authproxy;
}

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2016, 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
@ -31,19 +31,54 @@
#include "http.h"
#include "url.h"
#include "select.h"
#include "rawstr.h"
#include "progress.h"
#include "non-ascii.h"
#include "connect.h"
#include "curlx.h"
#include "vtls/vtls.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
CURLcode Curl_proxy_connect(struct connectdata *conn)
/*
* Perform SSL initialization for HTTPS proxy. Sets
* proxy_ssl_connected connection bit when complete. Can be
* called multiple times.
*/
static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex)
{
#ifdef USE_SSL
CURLcode result = CURLE_OK;
DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS);
if(!conn->bits.proxy_ssl_connected[sockindex]) {
/* perform SSL initialization for this socket */
result =
Curl_ssl_connect_nonblocking(conn, sockindex,
&conn->bits.proxy_ssl_connected[sockindex]);
if(result)
conn->bits.close = TRUE; /* a failed connection is marked for closure to
prevent (bad) re-use or similar */
}
return result;
#else
(void) conn;
(void) sockindex;
return CURLE_NOT_BUILT_IN;
#endif
}
CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
{
if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
const CURLcode result = https_proxy_connect(conn, sockindex);
if(result)
return result;
if(!conn->bits.proxy_ssl_connected[sockindex])
return result; /* wait for HTTPS proxy SSL initialization to complete */
}
if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
#ifndef CURL_DISABLE_PROXY
/* for [protocol] tunneled through HTTP proxy */
@ -63,21 +98,31 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
* original pointer
*
* This function might be called several times in the multi interface case
* if the proxy's CONNTECT response is not instant.
* if the proxy's CONNECT response is not instant.
*/
prot_save = conn->data->req.protop;
memset(&http_proxy, 0, sizeof(http_proxy));
conn->data->req.protop = &http_proxy;
connkeep(conn, "HTTP proxy CONNECT");
/* for the secondary socket (FTP), use the "connect to host"
* but ignore the "connect to port" (use the secondary port)
*/
if(conn->bits.conn_to_host)
hostname = conn->conn_to_host.name;
else if(sockindex == SECONDARYSOCKET)
hostname = conn->secondaryhostname;
else
hostname = conn->host.name;
if(conn->bits.conn_to_port)
if(sockindex == SECONDARYSOCKET)
remote_port = conn->secondary_port;
else if(conn->bits.conn_to_port)
remote_port = conn->conn_to_port;
else
remote_port = conn->remote_port;
result = Curl_proxyCONNECT(conn, FIRSTSOCKET, hostname,
result = Curl_proxyCONNECT(conn, sockindex, hostname,
remote_port, FALSE);
conn->data->req.protop = prot_save;
if(CURLE_OK != result)
@ -107,14 +152,14 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
bool blocking)
{
int subversion=0;
struct SessionHandle *data=conn->data;
struct Curl_easy *data=conn->data;
struct SingleRequest *k = &data->req;
CURLcode result;
curl_socket_t tunnelsocket = conn->sock[sockindex];
curl_off_t cl=0;
bool closeConnection = FALSE;
bool chunked_encoding = FALSE;
long check;
time_t check;
#define SELECT_OK 0
#define SELECT_ERROR 1
@ -159,9 +204,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
free(host_port);
if(!result) {
char *host=(char *)"";
char *host = NULL;
const char *proxyconn="";
const char *useragent="";
const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ?
const char *http = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ?
"1.0" : "1.1";
bool ipv6_ip = conn->bits.ipv6_ip;
char *hostheader;
@ -185,6 +231,9 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
return CURLE_OUT_OF_MEMORY;
}
}
if(!Curl_checkProxyheaders(conn, "Proxy-Connection:"))
proxyconn = "Proxy-Connection: Keep-Alive\r\n";
if(!Curl_checkProxyheaders(conn, "User-Agent:") &&
data->set.str[STRING_USERAGENT])
useragent = conn->allocptr.uagent;
@ -194,15 +243,17 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
"CONNECT %s HTTP/%s\r\n"
"%s" /* Host: */
"%s" /* Proxy-Authorization */
"%s", /* User-Agent */
"%s" /* User-Agent */
"%s", /* Proxy-Connection */
hostheader,
http,
host,
host?host:"",
conn->allocptr.proxyuserpwd?
conn->allocptr.proxyuserpwd:"",
useragent);
useragent,
proxyconn);
if(host && *host)
if(host)
free(host);
free(hostheader);
@ -239,7 +290,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
}
if(!blocking) {
if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
if(!Curl_conn_data_pending(conn, sockindex))
/* return so we'll be called again polling-style */
return CURLE_OK;
else {
@ -264,7 +315,16 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
nread = 0;
perline = 0;
while((nread<BUFSIZE) && (keepon && !error)) {
while(nread < BUFSIZE && keepon && !error) {
int writetype;
if(Curl_pgrsUpdate(conn))
return CURLE_ABORTED_BY_CALLBACK;
if(ptr >= &data->state.buffer[BUFSIZE]) {
failf(data, "CONNECT response too large!");
return CURLE_RECV_ERROR;
}
check = Curl_timeleft(data, NULL, TRUE);
if(check <= 0) {
@ -273,25 +333,22 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
break;
}
/* loop every second at least, less if the timeout is near */
switch (Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD,
check<1000L?check:1000)) {
case -1: /* select() error, stop reading */
/* Read one byte at a time to avoid a race condition. Wait at most one
second before looping to ensure continuous pgrsUpdates. */
result = Curl_read(conn, tunnelsocket, ptr, 1, &gotbytes);
if(result == CURLE_AGAIN) {
if(SOCKET_READABLE(tunnelsocket, check<1000L?check:1000) == -1) {
error = SELECT_ERROR;
failf(data, "Proxy CONNECT aborted due to select/poll error");
break;
case 0: /* timeout */
}
continue;
}
else if(result) {
keepon = FALSE;
break;
default:
DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1);
result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread,
&gotbytes);
if(result==CURLE_AGAIN)
continue; /* go loop yourself */
else if(result)
keepon = FALSE;
}
else if(gotbytes <= 0) {
keepon = FALSE;
if(data->set.proxyauth && data->state.authproxy.avail) {
/* proxy auth was requested and there was proxy auth available,
then deem this as "mere" proxy disconnect */
@ -302,16 +359,12 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
error = SELECT_ERROR;
failf(data, "Proxy CONNECT aborted");
}
keepon = FALSE;
break;
}
else {
/*
* We got a whole chunk of data, which can be anything from one
* byte to a set of lines and possibly just a piece of the last
* line.
*/
int i;
nread += gotbytes;
/* We got a byte of data */
nread++;
if(keepon > TRUE) {
/* This means we are currently ignoring a response-body */
@ -321,7 +374,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
if(cl) {
/* A Content-Length based body: simply count down the counter
and make sure to break out of the loop when we're done! */
cl -= gotbytes;
cl--;
if(cl <= 0) {
keepon = FALSE;
break;
@ -335,7 +388,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
/* now parse the chunked piece of data so that we can
properly tell when the stream ends */
r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof);
r = Curl_httpchunk_read(conn, ptr, 1, &tookcareof);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
infof(data, "chunk reading DONE\n");
@ -343,21 +396,20 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
/* we did the full CONNECT treatment, go COMPLETE */
conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
}
else
infof(data, "Read %zd bytes of chunk, continue\n",
tookcareof);
}
continue;
}
else
for(i = 0; i < gotbytes; ptr++, i++) {
perline++; /* amount of bytes in this line so far */
if(*ptr == 0x0a) {
char letter;
int writetype;
/* if this is not the end of a header line then continue */
if(*ptr != 0x0a) {
ptr++;
continue;
}
/* convert from the network encoding */
result = Curl_convert_from_network(data, line_start,
perline);
result = Curl_convert_from_network(data, line_start, perline);
/* Curl_convert_from_network calls failf if unsuccessful */
if(result)
return result;
@ -372,8 +424,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
if(data->set.include_header)
writetype |= CLIENTWRITE_BODY;
result = Curl_client_write(conn, writetype, line_start,
perline);
result = Curl_client_write(conn, writetype, line_start, perline);
data->info.header_size += (long)perline;
data->req.headerbytecount += (long)perline;
@ -400,36 +451,27 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
if(cl) {
infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
" bytes of response-body\n", cl);
/* remove the remaining chunk of what we already
read */
cl -= (gotbytes - i);
if(cl<=0)
/* if the whole thing was already read, we are done!
*/
keepon=FALSE;
}
else if(chunked_encoding) {
CHUNKcode r;
infof(data, "Ignore chunked response-body\n");
/* We set ignorebody true here since the chunked
decoder function will acknowledge that. Pay
attention so that this is cleared again when this
function returns! */
k->ignorebody = TRUE;
infof(data, "%zd bytes of chunk left\n", gotbytes-i);
if(line_start[1] == '\n') {
/* this can only be a LF if the letter at index 0
was a CR */
line_start++;
i++;
}
/* now parse the chunked piece of data so that we can
properly tell when the stream ends */
r = Curl_httpchunk_read(conn, line_start+1,
gotbytes -i, &gotbytes);
r = Curl_httpchunk_read(conn, line_start + 1, 1, &gotbytes);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
infof(data, "chunk reading DONE\n");
@ -438,9 +480,6 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
COMPLETE */
conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
}
else
infof(data, "Read %zd bytes of chunk, continue\n",
gotbytes);
}
else {
/* without content-length or chunked encoding, we
@ -449,22 +488,13 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
keepon = FALSE;
}
}
else {
else
keepon = FALSE;
if(200 == data->info.httpproxycode) {
if(gotbytes - (i+1))
failf(data, "Proxy CONNECT followed by %zd bytes "
"of opaque data. Data ignored (known bug #39)",
gotbytes - (i+1));
}
}
/* we did the full CONNECT treatment, go to COMPLETE */
conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
break; /* breaks out of for-loop, not switch() */
continue;
}
/* keep a backup of the position we are about to blank */
letter = line_start[perline];
line_start[perline] = 0; /* zero terminate the buffer */
if((checkprefix("WWW-Authenticate:", line_start) &&
(401 == k->httpcode)) ||
@ -484,22 +514,36 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
return result;
}
else if(checkprefix("Content-Length:", line_start)) {
if(k->httpcode/100 == 2) {
/* A server MUST NOT send any Transfer-Encoding or
Content-Length header fields in a 2xx (Successful)
response to CONNECT. (RFC 7231 section 4.3.6) */
failf(data, "Content-Length: in %03d response",
k->httpcode);
return CURLE_RECV_ERROR;
}
cl = curlx_strtoofft(line_start +
strlen("Content-Length:"), NULL, 10);
}
else if(Curl_compareheader(line_start,
"Connection:", "close"))
else if(Curl_compareheader(line_start, "Connection:", "close"))
closeConnection = TRUE;
else if(Curl_compareheader(line_start,
"Transfer-Encoding:",
"chunked")) {
if(k->httpcode/100 == 2) {
/* A server MUST NOT send any Transfer-Encoding or
Content-Length header fields in a 2xx (Successful)
response to CONNECT. (RFC 7231 section 4.3.6) */
failf(data, "Transfer-Encoding: in %03d response", k->httpcode);
return CURLE_RECV_ERROR;
}
infof(data, "CONNECT responded chunked\n");
chunked_encoding = TRUE;
/* init our chunky engine */
Curl_httpchunk_init(conn);
}
else if(Curl_compareheader(line_start,
"Proxy-Connection:", "close"))
else if(Curl_compareheader(line_start, "Proxy-Connection:", "close"))
closeConnection = TRUE;
else if(2 == sscanf(line_start, "HTTP/1.%d %d",
&subversion,
@ -507,19 +551,14 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
/* store the HTTP code from the proxy */
data->info.httpproxycode = k->httpcode;
}
/* put back the letter we blanked out before */
line_start[perline]= letter;
perline = 0; /* line starts over here */
line_start = ptr+1; /* this skips the zero byte we wrote */
}
}
}
break;
} /* switch */
ptr = data->state.buffer;
line_start = ptr;
} /* while there's buffer left and loop is requested */
if(Curl_pgrsUpdate(conn))
return CURLE_ABORTED_BY_CALLBACK;
} /* while there's buffer left and loop is requested */
if(error)
return CURLE_RECV_ERROR;
@ -534,8 +573,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
if(conn->bits.close)
/* the connection has been marked for closure, most likely in the
Curl_http_auth_act() function and thus we can kill it at once
below
*/
below */
closeConnection = TRUE;
}
@ -568,7 +606,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
free(data->req.newurl);
data->req.newurl = NULL;
/* failure, close this connection to avoid re-use */
connclose(conn, "proxy CONNECT failure");
streamclose(conn, "proxy CONNECT failure");
Curl_closesocket(conn, conn->sock[sockindex]);
conn->sock[sockindex] = CURL_SOCKET_BAD;
}

View File

@ -32,11 +32,11 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
/* Default proxy timeout in milliseconds */
#define PROXY_TIMEOUT (3600*1000)
CURLcode Curl_proxy_connect(struct connectdata *conn);
CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex);
#else
#define Curl_proxyCONNECT(x,y,z,w,v) CURLE_NOT_BUILT_IN
#define Curl_proxy_connect(x) CURLE_OK
#define Curl_proxy_connect(x,y) CURLE_OK
#endif
#endif /* HEADER_CURL_HTTP_PROXY_H */

View File

@ -51,7 +51,7 @@
#endif
#include "inet_ntop.h"
#include "strequal.h"
#include "strcase.h"
#include "if2ip.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@ -102,7 +102,7 @@ bool Curl_if_is_interface_name(const char *interf)
if(getifaddrs(&head) >= 0) {
for(iface=head; iface != NULL; iface=iface->ifa_next) {
if(curl_strequal(iface->ifa_name, interf)) {
if(strcasecompare(iface->ifa_name, interf)) {
result = TRUE;
break;
}
@ -132,7 +132,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
for(iface = head; iface != NULL; iface=iface->ifa_next) {
if(iface->ifa_addr != NULL) {
if(iface->ifa_addr->sa_family == af) {
if(curl_strequal(iface->ifa_name, interf)) {
if(strcasecompare(iface->ifa_name, interf)) {
void *addr;
char *ip;
char scope[12] = "";
@ -180,7 +180,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
}
}
else if((res == IF2IP_NOT_FOUND) &&
curl_strequal(iface->ifa_name, interf)) {
strcasecompare(iface->ifa_name, interf)) {
res = IF2IP_AF_NOT_SUPPORTED;
}
}

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2016, 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
@ -68,16 +68,15 @@
#include "http.h" /* for HTTP proxy tunnel stuff */
#include "socks.h"
#include "imap.h"
#include "strtoofft.h"
#include "strequal.h"
#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
#include "strerror.h"
#include "select.h"
#include "multiif.h"
#include "url.h"
#include "rawstr.h"
#include "strcase.h"
#include "curl_sasl.h"
#include "warnless.h"
@ -131,7 +130,8 @@ const struct Curl_handler Curl_handler_imap = {
ZERO_NULL, /* readwrite */
PORT_IMAP, /* defport */
CURLPROTO_IMAP, /* protocol */
PROTOPT_CLOSEACTION /* flags */
PROTOPT_CLOSEACTION| /* flags */
PROTOPT_URLOPTIONS
};
#ifdef USE_SSL
@ -271,7 +271,7 @@ static bool imap_matchresp(const char *line, size_t len, const char *cmd)
/* Does the command name match and is it followed by a space character or at
the end of line? */
if(line + cmd_len <= end && Curl_raw_nequal(line, cmd, cmd_len) &&
if(line + cmd_len <= end && strncasecompare(line, cmd, cmd_len) &&
(line[cmd_len] == ' ' || line + cmd_len + 2 == end))
return TRUE;
@ -648,7 +648,7 @@ static CURLcode imap_perform_authentication(struct connectdata *conn)
static CURLcode imap_perform_list(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct IMAP *imap = data->req.protop;
char *mailbox;
@ -683,7 +683,7 @@ static CURLcode imap_perform_list(struct connectdata *conn)
static CURLcode imap_perform_select(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct IMAP *imap = data->req.protop;
struct imap_conn *imapc = &conn->proto.imapc;
char *mailbox;
@ -840,13 +840,13 @@ static CURLcode imap_state_servergreet_resp(struct connectdata *conn,
imapstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
(void)instate; /* no use for this yet */
if(imapcode != 'O') {
failf(data, "Got unexpected imap-server response");
result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: fix this code */
result = CURLE_WEIRD_SERVER_REPLY;
}
else
result = imap_perform_capability(conn);
@ -860,7 +860,7 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
imapstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer;
size_t wordlen;
@ -947,13 +947,13 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn,
imapstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
(void)instate; /* no use for this yet */
if(imapcode != 'O') {
if(data->set.use_ssl != CURLUSESSL_TRY) {
failf(data, "STARTTLS denied. %c", imapcode);
failf(data, "STARTTLS denied");
result = CURLE_USE_SSL_FAILED;
}
else
@ -971,7 +971,7 @@ static CURLcode imap_state_auth_resp(struct connectdata *conn,
imapstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct imap_conn *imapc = &conn->proto.imapc;
saslprogress progress;
@ -1005,7 +1005,7 @@ static CURLcode imap_state_login_resp(struct connectdata *conn,
imapstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
(void)instate; /* no use for this yet */
@ -1051,7 +1051,7 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct IMAP *imap = conn->data->req.protop;
struct imap_conn *imapc = &conn->proto.imapc;
const char *line = data->state.buffer;
@ -1098,7 +1098,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct imap_conn *imapc = &conn->proto.imapc;
struct pingpong *pp = &imapc->pp;
const char *ptr = data->state.buffer;
@ -1179,7 +1179,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
else {
/* We don't know how to parse this line */
failf(pp->conn->data, "Failed to parse FETCH response.");
result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: fix this code */
result = CURLE_WEIRD_SERVER_REPLY;
}
/* End of DO phase */
@ -1198,7 +1198,7 @@ static CURLcode imap_state_fetch_final_resp(struct connectdata *conn,
(void)instate; /* No use for this yet */
if(imapcode != 'O')
result = CURLE_FTP_WEIRD_SERVER_REPLY; /* TODO: Fix error code */
result = CURLE_WEIRD_SERVER_REPLY;
else
/* End of DONE phase */
state(conn, IMAP_STOP);
@ -1211,7 +1211,7 @@ static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode,
imapstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
(void)instate; /* No use for this yet */
@ -1275,7 +1275,7 @@ static CURLcode imap_statemach_act(struct connectdata *conn)
/* Was there an error parsing the response line? */
if(imapcode == -1)
return CURLE_FTP_WEIRD_SERVER_REPLY;
return CURLE_WEIRD_SERVER_REPLY;
if(!imapcode)
break;
@ -1371,12 +1371,12 @@ static CURLcode imap_block_statemach(struct connectdata *conn)
return result;
}
/* Allocate and initialize the struct IMAP for the current SessionHandle if
/* Allocate and initialize the struct IMAP for the current Curl_easy if
required */
static CURLcode imap_init(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct IMAP *imap;
imap = data->req.protop = calloc(sizeof(struct IMAP), 1);
@ -1456,7 +1456,7 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
bool premature)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct IMAP *imap = data->req.protop;
(void)premature;
@ -1518,7 +1518,7 @@ static CURLcode imap_perform(struct connectdata *conn, bool *connected,
{
/* This is IMAP and no proxy */
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct IMAP *imap = data->req.protop;
struct imap_conn *imapc = &conn->proto.imapc;
bool selected = FALSE;
@ -1683,7 +1683,7 @@ static CURLcode imap_regular_transfer(struct connectdata *conn,
{
CURLcode result = CURLE_OK;
bool connected = FALSE;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
/* Make sure size is unknown at this point */
data->req.size = -1;
@ -1706,7 +1706,7 @@ static CURLcode imap_regular_transfer(struct connectdata *conn,
static CURLcode imap_setup_connection(struct connectdata *conn)
{
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
/* Initialise the IMAP layer */
CURLcode result = imap_init(conn);
@ -1935,7 +1935,7 @@ static CURLcode imap_parse_url_options(struct connectdata *conn)
while(*ptr && *ptr != ';')
ptr++;
if(strnequal(key, "AUTH=", 5))
if(strncasecompare(key, "AUTH=", 5))
result = Curl_sasl_parse_url_auth_option(&imapc->sasl,
value, ptr - value);
else
@ -1971,7 +1971,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
{
/* The imap struct is already initialised in imap_connect() */
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct IMAP *imap = data->req.protop;
const char *begin = data->state.path;
const char *ptr = begin;
@ -2031,28 +2031,28 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
PARTIAL) stripping of the trailing slash character if it is present.
Note: Unknown parameters trigger a URL_MALFORMAT error. */
if(Curl_raw_equal(name, "UIDVALIDITY") && !imap->uidvalidity) {
if(strcasecompare(name, "UIDVALIDITY") && !imap->uidvalidity) {
if(valuelen > 0 && value[valuelen - 1] == '/')
value[valuelen - 1] = '\0';
imap->uidvalidity = value;
value = NULL;
}
else if(Curl_raw_equal(name, "UID") && !imap->uid) {
else if(strcasecompare(name, "UID") && !imap->uid) {
if(valuelen > 0 && value[valuelen - 1] == '/')
value[valuelen - 1] = '\0';
imap->uid = value;
value = NULL;
}
else if(Curl_raw_equal(name, "SECTION") && !imap->section) {
else if(strcasecompare(name, "SECTION") && !imap->section) {
if(valuelen > 0 && value[valuelen - 1] == '/')
value[valuelen - 1] = '\0';
imap->section = value;
value = NULL;
}
else if(Curl_raw_equal(name, "PARTIAL") && !imap->partial) {
else if(strcasecompare(name, "PARTIAL") && !imap->partial) {
if(valuelen > 0 && value[valuelen - 1] == '/')
value[valuelen - 1] = '\0';
@ -2101,7 +2101,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
static CURLcode imap_parse_custom_request(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
struct IMAP *imap = data->req.protop;
const char *custom = data->set.str[STRING_CUSTOMREQUEST];

View File

@ -49,9 +49,9 @@ typedef enum {
IMAP_LAST /* never used */
} imapstate;
/* This IMAP struct is used in the SessionHandle. All IMAP data that is
/* This IMAP struct is used in the Curl_easy. All IMAP data that is
connection-oriented must be in imap_conn to properly deal with the fact that
perhaps the SessionHandle is changed between the times the connection is
perhaps the Curl_easy is changed between the times the connection is
used. */
struct IMAP {
curl_pp_transfer transfer;

View File

@ -103,7 +103,8 @@ inet_pton4(const char *src, unsigned char *dst)
while((ch = *src++) != '\0') {
const char *pch;
if((pch = strchr(digits, ch)) != NULL) {
pch = strchr(digits, ch);
if(pch) {
unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
if(saw_digit && *tp == 0)
@ -169,7 +170,8 @@ inet_pton6(const char *src, unsigned char *dst)
while((ch = *src++) != '\0') {
const char *pch;
if((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
pch = strchr((xdigits = xdigits_l), ch);
if(!pch)
pch = strchr((xdigits = xdigits_u), ch);
if(pch != NULL) {
val <<= 4;

View File

@ -150,7 +150,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
const char *host = conn->host.name;
ssize_t nread;
curl_socklen_t l = sizeof(conn->local_addr);
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
CURLcode result;
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
@ -182,7 +182,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
for(;;) {
/* this really shouldn't be repeated here, but can't help it */
if(service == srv_host) {
result = Curl_ftpsendf(conn, "AUTH GSSAPI");
result = Curl_ftpsend(conn, "AUTH GSSAPI");
if(result)
return -2;
@ -243,16 +243,22 @@ krb5_auth(void *app_data, struct connectdata *conn)
}
if(output_buffer.length != 0) {
char *cmd;
result = Curl_base64_encode(data, (char *)output_buffer.value,
output_buffer.length, &p, &base64_sz);
if(result) {
Curl_infof(data, "base64-encoding: %s\n",
curl_easy_strerror(result));
ret = AUTH_CONTINUE;
ret = AUTH_ERROR;
break;
}
result = Curl_ftpsendf(conn, "ADAT %s", p);
cmd = aprintf("ADAT %s", p);
if(cmd)
result = Curl_ftpsend(conn, cmd);
else
result = CURLE_OUT_OF_MEMORY;
free(p);

View File

@ -69,12 +69,11 @@
#include "escape.h"
#include "progress.h"
#include "transfer.h"
#include "strequal.h"
#include "strcase.h"
#include "strtok.h"
#include "curl_ldap.h"
#include "curl_multibyte.h"
#include "curl_base64.h"
#include "rawstr.h"
#include "connect.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@ -192,7 +191,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
LDAPMessage *ldapmsg = NULL;
LDAPMessage *entryIterator;
int num = 0;
struct SessionHandle *data=conn->data;
struct Curl_easy *data=conn->data;
int ldap_proto = LDAP_VERSION3;
int ldap_ssl = 0;
char *val_b64 = NULL;
@ -272,7 +271,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
#else
int ldap_option;
char* ldap_ca = data->set.str[STRING_SSL_CAFILE];
char *ldap_ca = conn->ssl_config.CAfile;
#if defined(CURL_HAS_NOVELL_LDAPSDK)
rc = ldapssl_client_init(NULL, NULL);
if(rc != LDAP_SUCCESS) {
@ -280,11 +279,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
result = CURLE_SSL_CERTPROBLEM;
goto quit;
}
if(data->set.ssl.verifypeer) {
if(conn->ssl_config.verifypeer) {
/* Novell SDK supports DER or BASE64 files. */
int cert_type = LDAPSSL_CERT_FILETYPE_B64;
if((data->set.str[STRING_CERT_TYPE]) &&
(Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "DER")))
if((data->set.ssl.cert_type) &&
(strcasecompare(data->set.ssl.cert_type, "DER")))
cert_type = LDAPSSL_CERT_FILETYPE_DER;
if(!ldap_ca) {
failf(data, "LDAP local: ERROR %s CA cert not set!",
@ -322,10 +321,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
goto quit;
}
#elif defined(LDAP_OPT_X_TLS)
if(data->set.ssl.verifypeer) {
if(conn->ssl_config.verifypeer) {
/* OpenLDAP SDK supports BASE64 files. */
if((data->set.str[STRING_CERT_TYPE]) &&
(!Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "PEM"))) {
if((data->set.ssl.cert_type) &&
(!strcasecompare(data->set.ssl.cert_type, "PEM"))) {
failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!");
result = CURLE_SSL_CERTPROBLEM;
goto quit;
@ -708,15 +707,15 @@ static void _ldap_trace (const char *fmt, ...)
*/
static int str2scope(const char *p)
{
if(strequal(p, "one"))
if(strcasecompare(p, "one"))
return LDAP_SCOPE_ONELEVEL;
if(strequal(p, "onetree"))
if(strcasecompare(p, "onetree"))
return LDAP_SCOPE_ONELEVEL;
if(strequal(p, "base"))
if(strcasecompare(p, "base"))
return LDAP_SCOPE_BASE;
if(strequal(p, "sub"))
if(strcasecompare(p, "sub"))
return LDAP_SCOPE_SUBTREE;
if(strequal(p, "subtree"))
if(strcasecompare(p, "subtree"))
return LDAP_SCOPE_SUBTREE;
return (-1);
}
@ -798,12 +797,13 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
if(*p) {
char *dn = p;
char *unescaped;
CURLcode result;
LDAP_TRACE(("DN '%s'\n", dn));
/* Unescape the DN */
unescaped = curl_easy_unescape(conn->data, dn, 0, NULL);
if(!unescaped) {
result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE);
if(result) {
rc = LDAP_NO_MEMORY;
goto quit;
@ -862,12 +862,14 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
for(i = 0; i < count; i++) {
char *unescaped;
CURLcode result;
LDAP_TRACE(("attr[%d] '%s'\n", i, attributes[i]));
/* Unescape the attribute */
unescaped = curl_easy_unescape(conn->data, attributes[i], 0, NULL);
if(!unescaped) {
result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
FALSE);
if(result) {
free(attributes);
rc = LDAP_NO_MEMORY;
@ -930,12 +932,13 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
if(*p) {
char *filter = p;
char *unescaped;
CURLcode result;
LDAP_TRACE(("filter '%s'\n", filter));
/* Unescape the filter */
unescaped = curl_easy_unescape(conn->data, filter, 0, NULL);
if(!unescaped) {
result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE);
if(result) {
rc = LDAP_NO_MEMORY;
goto quit;

View File

@ -1,53 +0,0 @@
;
; Definition file for the DLL version of the LIBCURL library from curl
;
LIBRARY LIBCURL
;DESCRIPTION 'curl libcurl - https://curl.haxx.se'
EXPORTS
curl_easy_cleanup @ 1 ;
curl_easy_getinfo @ 2 ;
curl_easy_init @ 3 ;
curl_easy_perform @ 4 ;
curl_easy_setopt @ 5 ;
curl_escape @ 6 ;
curl_unescape @ 7;
curl_formfree @ 9 ;
curl_getdate @ 10 ;
curl_getenv @ 11 ;
curl_global_cleanup @ 12 ;
curl_global_init @ 13 ;
curl_slist_append @ 14 ;
curl_slist_free_all @ 15 ;
curl_version @ 16 ;
curl_maprintf @ 17 ;
curl_mfprintf @ 18 ;
curl_mprintf @ 19 ;
curl_msprintf @ 20 ;
curl_msnprintf @ 21 ;
curl_mvfprintf @ 22 ;
curl_strequal @ 23 ;
curl_strnequal @ 24 ;
curl_easy_duphandle @ 25 ;
curl_formadd @ 26 ;
curl_multi_init @ 27;
curl_multi_add_handle @ 28;
curl_multi_remove_handle @ 29;
curl_multi_fdset @ 30;
curl_multi_perform @ 31;
curl_multi_cleanup @ 32;
curl_multi_info_read @ 33;
curl_free @ 34;
curl_version_info @ 35;
curl_share_init @ 36;
curl_share_setopt @ 37;
curl_share_cleanup @ 38;
curl_global_init_mem @ 39;
curl_easy_strerror @ 40;
curl_multi_strerror @ 41;
curl_share_strerror @ 42;
curl_easy_reset @ 43;
curl_mvsnprintf @ 44 ;

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, 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
@ -44,14 +44,14 @@ BEGIN
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "The cURL library, https://curl.haxx.se/\0"
VALUE "CompanyName", "The curl library, https://curl.haxx.se/\0"
VALUE "FileDescription", "libcurl Shared Library\0"
VALUE "FileVersion", LIBCURL_VERSION "\0"
VALUE "InternalName", "libcurl\0"
VALUE "OriginalFilename", "libcurl.dll\0"
VALUE "ProductName", "The cURL library\0"
VALUE "ProductName", "The curl library\0"
VALUE "ProductVersion", LIBCURL_VERSION "\0"
VALUE "LegalCopyright", "© " LIBCURL_COPYRIGHT "\0"
VALUE "LegalCopyright", "\xa9 " LIBCURL_COPYRIGHT "\0" /* a9: Copyright symbol */
VALUE "License", "https://curl.haxx.se/docs/copyright.html\0"
END
END

View File

@ -213,7 +213,8 @@ static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
unsigned long used, available;
saved_lo = ctx->lo;
if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
ctx->lo = (saved_lo + size) & 0x1fffffff;
if(ctx->lo < saved_lo)
ctx->hi++;
ctx->hi += (MD4_u32plus)size >> 29;

View File

@ -124,7 +124,7 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
CC_MD5_Final(digest, ctx);
}
#elif defined(_WIN32)
#elif defined(_WIN32) && !defined(CURL_WINDOWS_APP)
#include <wincrypt.h>
#include "curl_memory.h"
@ -402,7 +402,8 @@ static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
unsigned long used, available;
saved_lo = ctx->lo;
if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
ctx->lo = (saved_lo + size) & 0x1fffffff;
if(ctx->lo < saved_lo)
ctx->hi++;
ctx->hi += (MD5_u32plus)size >> 29;

View File

@ -119,7 +119,7 @@ void curl_memdebug(const char *logname)
logfile = stderr;
#ifdef MEMDEBUG_LOG_SYNC
/* Flush the log file after every line so the log isn't lost in a crash */
setvbuf(logfile, (char *)NULL, _IOLBF, 0);
setbuf(logfile, (char *)NULL);
#endif
}
}

View File

@ -6,7 +6,7 @@
# * | (__| |_| | _ <| |___
# * \___|\___/|_| \_\_____|
# *
# * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
# * Copyright (C) 1998 - 2016, 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
@ -30,11 +30,11 @@
# dependency is the OpenSSL commandline tool for optional text listing.
# Hacked by Guenter Knauf.
#
use Encode;
use Getopt::Std;
use MIME::Base64;
use LWP::UserAgent;
use strict;
use vars qw($opt_b $opt_d $opt_f $opt_h $opt_i $opt_l $opt_n $opt_p $opt_q $opt_s $opt_t $opt_u $opt_v $opt_w);
use vars qw($opt_b $opt_d $opt_f $opt_h $opt_i $opt_k $opt_l $opt_m $opt_n $opt_p $opt_q $opt_s $opt_t $opt_u $opt_v $opt_w);
use List::Util;
use Text::Wrap;
my $MOD_SHA = "Digest::SHA";
@ -43,18 +43,19 @@ if ($@) {
$MOD_SHA = "Digest::SHA::PurePerl";
eval "require $MOD_SHA";
}
eval "require LWP::UserAgent";
my %urls = (
'nss' =>
'http://hg.mozilla.org/projects/nss/raw-file/tip/lib/ckfw/builtins/certdata.txt',
'https://hg.mozilla.org/projects/nss/raw-file/tip/lib/ckfw/builtins/certdata.txt',
'central' =>
'http://hg.mozilla.org/mozilla-central/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
'https://hg.mozilla.org/mozilla-central/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
'aurora' =>
'http://hg.mozilla.org/releases/mozilla-aurora/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
'https://hg.mozilla.org/releases/mozilla-aurora/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
'beta' =>
'http://hg.mozilla.org/releases/mozilla-beta/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
'https://hg.mozilla.org/releases/mozilla-beta/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
'release' =>
'http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
'https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt',
);
$opt_d = 'release';
@ -62,7 +63,7 @@ $opt_d = 'release';
# If the OpenSSL commandline is not in search path you can configure it here!
my $openssl = 'openssl';
my $version = '1.25';
my $version = '1.27';
$opt_w = 76; # default base64 encoded lines length
@ -109,7 +110,7 @@ my @valid_signature_algorithms = (
$0 =~ s@.*(/|\\)@@;
$Getopt::Std::STANDARD_HELP_VERSION = 1;
getopts('bd:fhilnp:qs:tuvw:');
getopts('bd:fhiklmnp:qs:tuvw:');
if(!defined($opt_d)) {
# to make plain "-d" use not cause warnings, and actually still work
@ -117,7 +118,16 @@ if(!defined($opt_d)) {
}
# Use predefined URL or else custom URL specified on command line.
my $url = ( defined( $urls{$opt_d} ) ) ? $urls{$opt_d} : $opt_d;
my $url;
if(defined($urls{$opt_d})) {
$url = $urls{$opt_d};
if(!$opt_k && $url !~ /^https:\/\//i) {
die "The URL for '$opt_d' is not HTTPS. Use -k to override (insecure).\n";
}
}
else {
$url = $opt_d;
}
my $curl = `curl -V`;
@ -128,8 +138,8 @@ if ($opt_i) {
print "Operating System Name : $^O\n";
print "Getopt::Std.pm Version : ${Getopt::Std::VERSION}\n";
print "MIME::Base64.pm Version : ${MIME::Base64::VERSION}\n";
print "LWP::UserAgent.pm Version : ${LWP::UserAgent::VERSION}\n";
print "LWP.pm Version : ${LWP::VERSION}\n";
print "LWP::UserAgent.pm Version : ${LWP::UserAgent::VERSION}\n" if($LWP::UserAgent::VERSION);
print "LWP.pm Version : ${LWP::VERSION}\n" if($LWP::VERSION);
print "Digest::SHA.pm Version : ${Digest::SHA::VERSION}\n" if ($Digest::SHA::VERSION);
print "Digest::SHA::PurePerl.pm Version : ${Digest::SHA::PurePerl::VERSION}\n" if ($Digest::SHA::PurePerl::VERSION);
print ("=" x 78 . "\n");
@ -139,7 +149,7 @@ sub warning_message() {
if ( $opt_d =~ m/^risk$/i ) { # Long Form Warning and Exit
print "Warning: Use of this script may pose some risk:\n";
print "\n";
print " 1) Using http is subject to man in the middle attack of certdata content\n";
print " 1) If you use HTTP URLs they are subject to a man in the middle attack\n";
print " 2) Default to 'release', but more recent updates may be found in other trees\n";
print " 3) certdata.txt file format may change, lag time to update this script\n";
print " 4) Generally unwise to blindly trust CAs without manual review & verification\n";
@ -153,14 +163,16 @@ sub warning_message() {
}
sub HELP_MESSAGE() {
print "Usage:\t${0} [-b] [-d<certdata>] [-f] [-i] [-l] [-n] [-p<purposes:levels>] [-q] [-s<algorithms>] [-t] [-u] [-v] [-w<l>] [<outputfile>]\n";
print "Usage:\t${0} [-b] [-d<certdata>] [-f] [-i] [-k] [-l] [-n] [-p<purposes:levels>] [-q] [-s<algorithms>] [-t] [-u] [-v] [-w<l>] [<outputfile>]\n";
print "\t-b\tbackup an existing version of ca-bundle.crt\n";
print "\t-d\tspecify Mozilla tree to pull certdata.txt or custom URL\n";
print "\t\t Valid names are:\n";
print "\t\t ", join( ", ", map { ( $_ =~ m/$opt_d/ ) ? "$_ (default)" : "$_" } sort keys %urls ), "\n";
print "\t-f\tforce rebuild even if certdata.txt is current\n";
print "\t-i\tprint version info about used modules\n";
print "\t-k\tallow URLs other than HTTPS, enable HTTP fallback (insecure)\n";
print "\t-l\tprint license info about certdata.txt\n";
print "\t-m\tinclude meta data in output\n";
print "\t-n\tno download of certdata.txt (to use existing)\n";
print wrap("\t","\t\t", "-p\tlist of Mozilla trust purposes and levels for certificates to include in output. Takes the form of a comma separated list of purposes, a colon, and a comma separated list of levels. (default: $default_mozilla_trust_purposes:$default_mozilla_trust_levels)"), "\n";
print "\t\t Valid purposes are:\n";
@ -224,33 +236,34 @@ sub parse_csv_param($$@) {
return @values;
}
sub sha1 {
sub sha256 {
my $result;
if ($Digest::SHA::VERSION || $Digest::SHA::PurePerl::VERSION) {
open(FILE, $_[0]) or die "Can't open '$_[0]': $!";
binmode(FILE);
$result = $MOD_SHA->new(1)->addfile(*FILE)->hexdigest;
$result = $MOD_SHA->new(256)->addfile(*FILE)->hexdigest;
close(FILE);
} else {
# Use OpenSSL command if Perl Digest::SHA modules not available
$result = (split(/ |\r|\n/,`$openssl dgst -sha1 $_[0]`))[1];
$result = `"$openssl" dgst -r -sha256 "$_[0]"`;
$result =~ s/^([0-9a-f]{64}) .+/$1/is;
}
return $result;
}
sub oldsha1 {
my $sha1 = "";
sub oldhash {
my $hash = "";
open(C, "<$_[0]") || return 0;
while(<C>) {
chomp;
if($_ =~ /^\#\# SHA1: (.*)/) {
$sha1 = $1;
if($_ =~ /^\#\# SHA256: (.*)/) {
$hash = $1;
last;
}
}
close(C);
return $sha1;
return $hash;
}
if ( $opt_p !~ m/:/ ) {
@ -282,34 +295,66 @@ my $stdout = $crt eq '-';
my $resp;
my $fetched;
my $oldsha1 = oldsha1($crt);
my $oldhash = oldhash($crt);
report "SHA1 of old file: $oldsha1";
report "SHA256 of old file: $oldhash";
report "Downloading '$txt' ...";
if(!$opt_n) {
report "Downloading $txt ...";
if($curl && !$opt_n) {
my $https = $url;
$https =~ s/^http:/https:/;
report "Get certdata over HTTPS with curl!";
# If we have an HTTPS URL then use curl
if($url =~ /^https:\/\//i) {
if($curl) {
if($curl =~ /^Protocols:.* https( |$)/m) {
report "Get certdata with curl!";
my $proto = !$opt_k ? "--proto =https" : "";
my $quiet = $opt_q ? "-s" : "";
my @out = `curl -w %{response_code} $quiet -O $https`;
my @out = `curl -w %{response_code} $proto $quiet -o "$txt" "$url"`;
if(@out && $out[0] == 200) {
$fetched = 1;
} else {
report "Failed downloading HTTPS with curl, trying HTTP with LWP";
report "Downloaded $txt";
}
else {
report "Failed downloading via HTTPS with curl";
if(-e $txt && !unlink($txt)) {
report "Failed to remove '$txt': $!";
}
}
}
else {
report "curl lacks https support";
}
}
else {
report "curl not found";
}
}
unless ($fetched || ($opt_n and -e $txt)) {
# If nothing was fetched then use LWP
if(!$fetched) {
if($url =~ /^https:\/\//i) {
report "Falling back to HTTP";
$url =~ s/^https:\/\//http:\/\//i;
}
if(!$opt_k) {
report "URLs other than HTTPS are disabled by default, to enable use -k";
exit 1;
}
report "Get certdata with LWP!";
if(!defined(${LWP::UserAgent::VERSION})) {
report "LWP is not available (LWP::UserAgent not found)";
exit 1;
}
my $ua = new LWP::UserAgent(agent => "$0/$version");
$ua->env_proxy();
$resp = $ua->mirror($url, $txt);
if($resp && $resp->code eq '304') {
report "Not modified";
exit 0 if -e $crt && !$opt_f;
} else {
}
else {
$fetched = 1;
report "Downloaded $txt";
}
if(!$resp || $resp->code !~ /^(?:200|304)$/) {
report "Unable to download latest data: "
@ -317,6 +362,7 @@ unless ($fetched || ($opt_n and -e $txt)) {
exit 1 if -e $crt || ! -r $txt;
}
}
}
my $filedate = $resp ? $resp->last_modified : (stat($txt))[9];
my $datesrc = "as of";
@ -327,14 +373,14 @@ if(!$filedate) {
}
# get the hash from the download file
my $newsha1= sha1($txt);
my $newhash= sha256($txt);
if(!$opt_f && $oldsha1 eq $newsha1) {
if(!$opt_f && $oldhash eq $newhash) {
report "Downloaded file identical to previous run\'s source file. Exiting";
exit;
}
report "SHA1 of new file: $newsha1";
report "SHA256 of new file: $newhash";
my $currentdate = scalar gmtime($filedate);
@ -348,7 +394,7 @@ print CRT <<EOT;
##
## Bundle of CA Root Certificates
##
## Certificate data from Mozilla ${datesrc}: ${currentdate}
## Certificate data from Mozilla ${datesrc}: ${currentdate} GMT
##
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla's root certificates
@ -361,7 +407,7 @@ print CRT <<EOT;
## Just configure this file as the SSLCACertificateFile.
##
## Conversion done with mk-ca-bundle.pl version $version.
## SHA1: $newsha1
## SHA256: $newhash
##
EOT
@ -371,6 +417,7 @@ my $caname;
my $certnum = 0;
my $skipnum = 0;
my $start_of_cert = 0;
my @precert;
open(TXT,"$txt") or die "Couldn't open $txt: $!\n";
while (<TXT>) {
@ -383,11 +430,15 @@ while (<TXT>) {
last if (/\*\*\*\*\* END LICENSE BLOCK \*\*\*\*\*/);
}
}
next if /^#|^\s*$/;
chomp;
if (/^CVS_ID\s+\"(.*)\"/) {
print CRT "# $1\n";
elsif(/^# (Issuer|Serial Number|Subject|Not Valid Before|Not Valid After |Fingerprint \(MD5\)|Fingerprint \(SHA1\)):/) {
push @precert, $_;
next;
}
elsif(/^#|^\s*$/) {
undef @precert;
next;
}
chomp;
# this is a match for the start of a certificate
if (/^CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE/) {
@ -436,8 +487,8 @@ while (<TXT>) {
. $encoded
. "-----END CERTIFICATE-----\n";
print CRT "\n$caname\n";
my $maxStringLength = length($caname);
print CRT @precert if($opt_m);
my $maxStringLength = length(decode('UTF-8', $caname, Encode::FB_CROAK));
if ($opt_t) {
foreach my $key (keys %trust_purposes_by_level) {
my $string = $key . ": " . join(", ", @{$trust_purposes_by_level{$key}});
@ -479,7 +530,9 @@ while (<TXT>) {
$certnum ++;
$start_of_cert = 0;
}
undef @precert;
}
}
close(TXT) or die "Couldn't close $txt: $!\n";
close(CRT) or die "Couldn't close $crt.~: $!\n";
@ -495,5 +548,7 @@ unless( $stdout ) {
}
rename "$crt.~", $crt or die "Failed to rename $crt.~ to $crt: $!\n";
}
unlink $txt if ($opt_u);
if($opt_u && -e $txt && !unlink($txt)) {
report "Failed to remove $txt: $!\n";
}
report "Done ($certnum CA certs processed, $skipnum skipped).";

View File

@ -26,20 +26,36 @@
'* Hacked by Guenter Knauf
'***************************************************************************
Option Explicit
Const myVersion = "0.3.9"
Const myVersion = "0.4.0"
Const myUrl = "http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt"
Const myOpenssl = "openssl.exe"
Const myUrl = "https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt"
Const myCdSavF = FALSE ' Flag: save downloaded data to file certdata.txt
Const myOpenSSL = "openssl.exe"
Dim myUseOpenSSL
myUseOpenSSL = TRUE ' Flag: TRUE to use OpenSSL. If TRUE and is not
' found then a warning is shown before continuing.
Const myCdSavF = TRUE ' Flag: save downloaded data to file certdata.txt
Const myCaBakF = TRUE ' Flag: backup existing ca-bundle certificate
Const myAskLiF = TRUE ' Flag: display certdata.txt license agreement
Const myAskTiF = TRUE ' Flag: ask to include certificate text info
Const myWrapLe = 76 ' Default length of base64 output lines
' cert info code doesn't work properly with any recent openssl, leave disabled.
' Also: we want our certificate output by default to be as similar as possible
' to mk-ca-bundle.pl and setting this TRUE changes the base64 width to
' OpenSSL's built-in default width, which is not the same as mk-ca-bundle.pl.
Const myAskTiF = FALSE ' Flag: ask to include certificate text info
'
'******************* Nothing to configure below! *******************
'
Const adTypeBinary = 1
Const adTypeText = 2
Const adSaveCreateNotExist = 1
Const adSaveCreateOverWrite = 2
Dim objShell, objNetwork, objFSO, objHttp
Dim myBase, mySelf, myFh, myTmpFh, myCdData, myCdFile, myCaFile, myTmpName, myBakNum, myOptTxt, i
Dim myBase, mySelf, myStream, myTmpFh, myCdData, myCdFile
Dim myCaFile, myTmpName, myBakNum, myOptTxt, i
Set objNetwork = WScript.CreateObject("WScript.Network")
Set objShell = WScript.CreateObject("WScript.Shell")
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
@ -47,14 +63,60 @@ Set objHttp = WScript.CreateObject("WinHttp.WinHttpRequest.5.1")
If objHttp Is Nothing Then Set objHttp = WScript.CreateObject("WinHttp.WinHttpRequest")
myBase = Left(WScript.ScriptFullName, InstrRev(WScript.ScriptFullName, "\"))
mySelf = Left(WScript.ScriptName, InstrRev(WScript.ScriptName, ".") - 1) & " " & myVersion
myCdFile = Mid(myUrl, InstrRev(myUrl, "/") + 1)
myCaFile = "ca-bundle.crt"
myTmpName = InputBox("Enter output filename:", mySelf, myCaFile)
If Not (myTmpName = "") Then
myCaFile = myTmpName
myTmpName = InputBox("It will take a minute to download and parse the " & _
"certificate data." & _
vbLf & vbLf & _
"Please enter the output filename:", mySelf, myCaFile)
If (myTmpName = "") Then
WScript.Quit 1
End If
' Lets ignore SSL invalid cert errors
objHttp.Option(4) = 256 + 512 + 4096 + 8192
myCaFile = myTmpName
If (myCdFile = "") Then
MsgBox("URL does not contain filename!"), vbCritical, mySelf
WScript.Quit 1
End If
' Don't use OpenSSL if it's not present.
If (myUseOpenSSL = TRUE) Then
Dim errnum
On Error Resume Next
Call objShell.Run("""" & myOpenSSL & """ version", 0, TRUE)
errnum = Err.Number
On Error GoTo 0
If Not (errnum = 0) Then
myUseOpenSSL = FALSE
MsgBox("OpenSSL was not found so the certificate bundle will not " & _
"include the SHA256 hash of the raw certificate data file " & _
"that was used to generate the certificates in the bundle. " & _
vbLf & vbLf & _
"This does not have any effect on the certificate output, " & _
"so this script will continue." & _
vbLf & vbLf & _
"If you want to set a custom location for OpenSSL or disable " & _
"this message then edit the variables at the start of the " & _
"script."), vbInformation, mySelf
End If
End If
If (myAskTiF = TRUE) And (myUseOpenSSL = TRUE) Then
If (6 = objShell.PopUp("Do you want to include text information about " & _
"each certificate?" & vbLf & _
"(Requires OpenSSL.exe in the current directory " & _
"or search path)",, _
mySelf, vbQuestion + vbYesNo + vbDefaultButton2)) Then
myOptTxt = TRUE
Else
myOptTxt = FALSE
End If
End If
' Uncomment the line below to ignore SSL invalid cert errors
' objHttp.Option(4) = 256 + 512 + 4096 + 8192
objHttp.SetTimeouts 0, 5000, 10000, 10000
objHttp.Open "GET", myUrl, FALSE
objHttp.setRequestHeader "User-Agent", WScript.ScriptName & "/" & myVersion
@ -63,15 +125,13 @@ If Not (objHttp.Status = 200) Then
MsgBox("Failed to download '" & myCdFile & "': " & objHttp.Status & " - " & objHttp.StatusText), vbCritical, mySelf
WScript.Quit 1
End If
' Convert data from ResponseBody instead of using ResponseText because of UTF-8
myCdData = ConvertBinaryData(objHttp.ResponseBody)
Set objHttp = Nothing
' Write received data to file if enabled
If (myCdSavF = TRUE) Then
Set myFh = objFSO.OpenTextFile(myCdFile, 2, TRUE)
myFh.Write myCdData
myFh.Close
Call SaveBinaryData(myCdFile, objHttp.ResponseBody)
End If
' Convert data from ResponseBody instead of using ResponseText because of UTF-8
myCdData = ConvertBinaryToUTF8(objHttp.ResponseBody)
Set objHttp = Nothing
' Backup exitsing ca-bundle certificate file
If (myCaBakF = TRUE) Then
If objFSO.FileExists(myCaFile) Then
@ -86,15 +146,7 @@ If (myCaBakF = TRUE) Then
myTmpFh.Move myBakFile
End If
End If
If (myAskTiF = TRUE) Then
If (6 = objShell.PopUp("Do you want to include text information about each certificate?" & vbLf & _
"(requires OpenSSL commandline in current directory or in search path)",, _
mySelf, vbQuestion + vbYesNo + vbDefaultButton2)) Then
myOptTxt = TRUE
Else
myOptTxt = FALSE
End If
End If
' Process the received data
Dim myLines, myPattern, myInsideCert, myInsideLicense, myLicenseText, myNumCerts, myNumSkipped
Dim myLabel, myOctets, myData, myPem, myRev, myUntrusted, j
@ -102,23 +154,33 @@ myNumSkipped = 0
myNumCerts = 0
myData = ""
myLines = Split(myCdData, vbLf, -1)
Set myFh = objFSO.OpenTextFile(myCaFile, 2, TRUE)
myFh.Write "##" & vbLf
myFh.Write "## " & myCaFile & " -- Bundle of CA Root Certificates" & vbLf
myFh.Write "##" & vbLf
myFh.Write "## Converted at: " & Now & vbLf
myFh.Write "##" & vbLf
myFh.Write "## This is a bundle of X.509 certificates of public Certificate Authorities" & vbLf
myFh.Write "## (CA). These were automatically extracted from Mozilla's root certificates" & vbLf
myFh.Write "## file (certdata.txt). This file can be found in the mozilla source tree:" & vbLf
myFh.Write "## '/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt'" & vbLf
myFh.Write "##" & vbLf
myFh.Write "## It contains the certificates in PEM format and therefore" & vbLf
myFh.Write "## can be directly used with curl / libcurl / php_curl, or with" & vbLf
myFh.Write "## an Apache+mod_ssl webserver for SSL client authentication." & vbLf
myFh.Write "## Just configure this file as the SSLCACertificateFile." & vbLf
myFh.Write "##" & vbLf
myFh.Write vbLf
Set myStream = CreateObject("ADODB.Stream")
myStream.Open
myStream.Type = adTypeText
myStream.Charset = "utf-8"
myStream.WriteText "##" & vbLf & _
"## Bundle of CA Root Certificates" & vbLf & _
"##" & vbLf & _
"## Certificate data from Mozilla as of: " & _
ConvertDateToString(LocalDateToUTC(Now)) & " GMT" & vbLf & _
"##" & vbLf & _
"## This is a bundle of X.509 certificates of public Certificate Authorities" & vbLf & _
"## (CA). These were automatically extracted from Mozilla's root certificates" & vbLf & _
"## file (certdata.txt). This file can be found in the mozilla source tree:" & vbLf & _
"## " & myUrl & vbLf & _
"##" & vbLf & _
"## It contains the certificates in PEM format and therefore" & vbLf & _
"## can be directly used with curl / libcurl / php_curl, or with" & vbLf & _
"## an Apache+mod_ssl webserver for SSL client authentication." & vbLf & _
"## Just configure this file as the SSLCACertificateFile." & vbLf & _
"##" & vbLf & _
"## Conversion done with mk-ca-bundle.vbs version " & myVersion & "." & vbLf
If (myCdSavF = TRUE) And (myUseOpenSSL = TRUE) Then
myStream.WriteText "## SHA256: " & FileSHA256(myCdFile) & vbLf
End If
myStream.WriteText "##" & vbLf & vbLf
myStream.WriteText vbLf
For i = 0 To UBound(myLines)
If InstrRev(myLines(i), "CKA_LABEL ") Then
myPattern = "^CKA_LABEL\s+[A-Z0-9]+\s+""(.+?)"""
@ -136,13 +198,13 @@ For i = 0 To UBound(myLines)
If (myUntrusted = TRUE) Then
myNumSkipped = myNumSkipped + 1
Else
myFh.Write myLabel & vbLf
myFh.Write String(Len(myLabel), "=") & vbLf
myStream.WriteText myLabel & vbLf
myStream.WriteText String(Len(myLabel), "=") & vbLf
myPem = "-----BEGIN CERTIFICATE-----" & vbLf & _
Base64Encode(myData) & vbLf & _
"-----END CERTIFICATE-----" & vbLf
If (myOptTxt = FALSE) Then
myFh.Write myPem & vbLf
myStream.WriteText myPem & vbLf
Else
Dim myCmd, myRval, myTmpIn, myTmpOut
myTmpIn = objFSO.GetSpecialFolder(2).Path & "\" & objFSO.GetTempName
@ -150,8 +212,8 @@ For i = 0 To UBound(myLines)
Set myTmpFh = objFSO.OpenTextFile(myTmpIn, 2, TRUE)
myTmpFh.Write myPem
myTmpFh.Close
myCmd = myOpenssl & " x509 -md5 -fingerprint -text -inform PEM" & _
" -in " & myTmpIn & " -out " & myTmpOut
myCmd = """" & myOpenSSL & """ x509 -md5 -fingerprint -text " & _
"-inform PEM -in " & myTmpIn & " -out " & myTmpOut
myRval = objShell.Run (myCmd, 0, TRUE)
objFSO.DeleteFile myTmpIn, TRUE
If Not (myRval = 0) Then
@ -160,7 +222,7 @@ For i = 0 To UBound(myLines)
WScript.Quit 3
End If
Set myTmpFh = objFSO.OpenTextFile(myTmpOut, 1)
myFh.Write myTmpFh.ReadAll & vbLf
myStream.WriteText myTmpFh.ReadAll & vbLf
myTmpFh.Close
objFSO.DeleteFile myTmpOut, TRUE
End If
@ -176,7 +238,7 @@ For i = 0 To UBound(myLines)
If InstrRev(myLines(i), "CVS_ID ") Then
myPattern = "^CVS_ID\s+""(.+?)"""
myRev = RegExprFirst(myPattern, myLines(i))
myFh.Write "# " & myRev & vbLf & vbLf
myStream.WriteText "# " & myRev & vbLf & vbLf
End If
If InstrRev(myLines(i), "CKA_VALUE MULTILINE_OCTAL") Then
myInsideCert = TRUE
@ -187,7 +249,7 @@ For i = 0 To UBound(myLines)
myInsideLicense = TRUE
End If
If (myInsideLicense = TRUE) Then
myFh.Write myLines(i) & vbLf
myStream.WriteText myLines(i) & vbLf
myLicenseText = myLicenseText & Mid(myLines(i), 2) & vbLf
End If
If InstrRev(myLines(i), "***** END LICENSE BLOCK *****") Then
@ -196,28 +258,54 @@ For i = 0 To UBound(myLines)
If Not (6 = objShell.PopUp(myLicenseText & vbLf & _
"Do you agree to the license shown above (required to proceed) ?",, _
mySelf, vbQuestion + vbYesNo + vbDefaultButton1)) Then
myFh.Close
myStream.Close
objFSO.DeleteFile myCaFile, TRUE
WScript.Quit 2
End If
End If
End If
Next
myFh.Close
' To stop the UTF-8 BOM from being written the stream has to be copied and
' then saved as binary.
Dim myCopy
Set myCopy = CreateObject("ADODB.Stream")
myCopy.Type = adTypeBinary
myCopy.Open
myStream.Position = 3 ' Skip UTF-8 BOM
myStream.CopyTo myCopy
myCopy.SaveToFile myCaFile, adSaveCreateOverWrite
myCopy.Close
myStream.Close
Set myCopy = Nothing
Set myStream = Nothing
' Done
objShell.PopUp "Done (" & myNumCerts & " CA certs processed, " & myNumSkipped & _
" untrusted skipped).", 20, mySelf, vbInformation
WScript.Quit 0
Function ConvertBinaryData(arrBytes)
Function ConvertBinaryToUTF8(arrBytes)
Dim objStream
Set objStream = CreateObject("ADODB.Stream")
objStream.Open
objStream.Type = 1
objStream.Type = adTypeBinary
objStream.Write arrBytes
objStream.Position = 0
objStream.Type = 2
objStream.Charset = "ascii"
ConvertBinaryData = objStream.ReadText
objStream.Type = adTypeText
objStream.Charset = "utf-8"
ConvertBinaryToUTF8 = objStream.ReadText
Set objStream = Nothing
End Function
Function SaveBinaryData(filename, data)
Dim objStream
Set objStream = CreateObject("ADODB.Stream")
objStream.Type = adTypeBinary
objStream.Open
objStream.Write data
objStream.SaveToFile filename, adSaveCreateOverWrite
objStream.Close
Set objStream = Nothing
End Function
@ -283,4 +371,61 @@ Function MyASC(OneChar)
If OneChar = "" Then MyASC = 0 Else MyASC = Asc(OneChar)
End Function
' Return the date in the same format as perl to match mk-ca-bundle.pl output:
' Wed Sep 7 03:12:05 2016
Function ConvertDateToString(input)
Dim output
output = WeekDayName(WeekDay(input), TRUE) & " " & _
MonthName(Month(input), TRUE) & " "
If (Len(Day(input)) = 1) Then
output = output & " "
End If
output = output & _
Day(input) & " " & _
FormatDateTime(input, vbShortTime) & ":"
If (Len(Second(input)) = 1) Then
output = output & "0"
End If
output = output & _
Second(input) & " " & _
Year(input)
ConvertDateToString = output
End Function
' Convert local Date to UTC. Microsoft says:
' Use Win32_ComputerSystem CurrentTimeZone property, because it automatically
' adjusts the Time Zone bias for daylight saving time; Win32_Time Zone Bias
' property does not.
' https://msdn.microsoft.com/en-us/library/windows/desktop/ms696015.aspx
Function LocalDateToUTC(localdate)
Dim item, offset
For Each item In GetObject("winmgmts:").InstancesOf("Win32_ComputerSystem")
offset = item.CurrentTimeZone ' the offset in minutes
Next
If (offset < 0) Then
LocalDateToUTC = DateAdd("n", ABS(offset), localdate)
Else
LocalDateToUTC = DateAdd("n", -ABS(offset), localdate)
End If
'objShell.PopUp LocalDateToUTC
End Function
Function FileSHA256(filename)
Dim cmd, rval, tmpOut, tmpFh
if (myUseOpenSSL = TRUE) Then
tmpOut = objFSO.GetSpecialFolder(2).Path & "\" & objFSO.GetTempName
cmd = """" & myOpenSSL & """ dgst -r -sha256 -out """ & tmpOut & """ """ & filename & """"
rval = objShell.Run(cmd, 0, TRUE)
If Not (rval = 0) Then
MsgBox("Failed to get sha256 of """ & filename & """ with OpenSSL commandline!"), vbCritical, mySelf
objFSO.DeleteFile tmpOut, TRUE
WScript.Quit 3
End If
Set tmpFh = objFSO.OpenTextFile(tmpOut, 1)
FileSHA256 = RegExprFirst("^([0-9a-f]{64}) .+", tmpFh.ReadAll)
tmpFh.Close
objFSO.DeleteFile tmpOut, TRUE
Else
FileSHA256 = ""
End If
End Function

View File

@ -92,7 +92,8 @@
# define mp_uintmax_t unsigned long
#endif
#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should
fit negative DBL_MAX (317 letters) */
#define MAX_PARAMETERS 128 /* lame static limit */
#ifdef __AMIGA__
@ -227,9 +228,11 @@ static bool dprintf_IsQualifierNoDollar(const char *fmt)
* Create an index with the type of each parameter entry and its
* value (may vary in size)
*
* Returns zero on success.
*
******************************************************************/
static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
va_list arglist)
{
char *fmt = (char *)format;
@ -301,7 +304,6 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
flags |= FLAGS_ALT;
break;
case '.':
flags |= FLAGS_PREC;
if('*' == *fmt) {
/* The precision is picked from a specified parameter */
@ -393,6 +395,10 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
i = this_param - 1;
if((i < 0) || (i >= MAX_PARAMETERS))
/* out of allowed range */
return 1;
switch (*fmt) {
case 'S':
flags |= FLAGS_ALT;
@ -549,7 +555,7 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
}
}
return max_param;
return 0;
}
@ -587,7 +593,8 @@ static int dprintf_formatf(
char *workend = &work[sizeof(work) - 2];
/* Do the actual %-code parsing */
dprintf_Pass1(format, vto, endpos, ap_save);
if(dprintf_Pass1(format, vto, endpos, ap_save))
return -1;
end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()
created for us */
@ -910,12 +917,25 @@ static int dprintf_formatf(
*fptr = 0;
if(width >= 0) {
if(width >= (long)sizeof(work))
width = sizeof(work)-1;
/* RECURSIVE USAGE */
len = curl_msnprintf(fptr, left, "%ld", width);
fptr += len;
left -= len;
}
if(prec >= 0) {
/* for each digit in the integer part, we can have one less
precision */
size_t maxprec = sizeof(work) - 2;
double val = p->data.dnum;
while(val >= 10.0) {
val /= 10;
maxprec--;
}
if(prec > (long)maxprec)
prec = (long)maxprec-1;
/* RECURSIVE USAGE */
len = curl_msnprintf(fptr, left, ".%ld", prec);
fptr += len;
@ -935,7 +955,9 @@ static int dprintf_formatf(
/* NOTE NOTE NOTE!! Not all sprintf implementations return number of
output characters */
(sprintf)(work, formatbuf, p->data.dnum);
#ifdef CURLDEBUG
assert(strlen(work) <= sizeof(work));
#endif
for(fptr=work; *fptr; fptr++)
OUTCHAR(*fptr);
}
@ -992,7 +1014,7 @@ int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
info.max = maxlength;
retcode = dprintf_formatf(&info, addbyter, format, ap_save);
if(info.max) {
if((retcode != -1) && info.max) {
/* we terminate this with a zero byte */
if(info.max == info.length)
/* we're at maximum, scrap the last letter */
@ -1029,16 +1051,19 @@ static int alloc_addbyter(int output, FILE *data)
infop->len =0;
}
else if(infop->len+1 >= infop->alloc) {
char *newptr;
char *newptr = NULL;
size_t newsize = infop->alloc*2;
newptr = realloc(infop->buffer, infop->alloc*2);
/* detect wrap-around or other overflow problems */
if(newsize > infop->alloc)
newptr = realloc(infop->buffer, newsize);
if(!newptr) {
infop->fail = 1;
return -1; /* fail */
}
infop->buffer = newptr;
infop->alloc *= 2;
infop->alloc = newsize;
}
infop->buffer[ infop->len ] = outc;

View File

@ -42,6 +42,8 @@
#include "multihandle.h"
#include "pipeline.h"
#include "sigpipe.h"
#include "vtls/vtls.h"
#include "connect.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@ -61,15 +63,15 @@
#define CURL_MULTI_HANDLE 0x000bab1e
#define GOOD_MULTI_HANDLE(x) \
((x) && (((struct Curl_multi *)(x))->type == CURL_MULTI_HANDLE))
((x) && (x)->type == CURL_MULTI_HANDLE)
static void singlesocket(struct Curl_multi *multi,
struct SessionHandle *data);
struct Curl_easy *data);
static int update_timer(struct Curl_multi *multi);
static CURLMcode add_next_timeout(struct timeval now,
struct Curl_multi *multi,
struct SessionHandle *d);
struct Curl_easy *d);
static CURLMcode multi_timeout(struct Curl_multi *multi,
long *timeout_ms);
@ -100,10 +102,10 @@ static const char * const statename[]={
static void multi_freetimeout(void *a, void *b);
/* function pointer called once when switching TO a state */
typedef void (*init_multistate_func)(struct SessionHandle *data);
typedef void (*init_multistate_func)(struct Curl_easy *data);
/* always use this function to change state, to make debugging easier */
static void mstate(struct SessionHandle *data, CURLMstate state
static void mstate(struct Curl_easy *data, CURLMstate state
#ifdef DEBUGBUILD
, int lineno
#endif
@ -162,7 +164,7 @@ static void mstate(struct SessionHandle *data, CURLMstate state
*/
struct Curl_sh_entry {
struct SessionHandle *easy;
struct Curl_easy *easy;
int action; /* what action READ/WRITE this socket waits for */
curl_socket_t socket; /* mainly to ease debugging */
void *socketp; /* settable by users with curl_multi_assign() */
@ -185,7 +187,7 @@ static struct Curl_sh_entry *sh_getentry(struct curl_hash *sh,
/* make sure this socket is present in the hash for this handle */
static struct Curl_sh_entry *sh_addentry(struct curl_hash *sh,
curl_socket_t s,
struct SessionHandle *data)
struct Curl_easy *data)
{
struct Curl_sh_entry *there = sh_getentry(sh, s);
struct Curl_sh_entry *check;
@ -334,7 +336,7 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
/* -1 means it not set by user, use the default value */
multi->maxconnects = -1;
return (CURLM *) multi;
return multi;
error:
@ -350,25 +352,23 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
return NULL;
}
CURLM *curl_multi_init(void)
struct Curl_multi *curl_multi_init(void)
{
return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
CURL_CONNECTION_HASH_SIZE);
}
CURLMcode curl_multi_add_handle(CURLM *multi_handle,
CURL *easy_handle)
CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
struct Curl_easy *data)
{
struct curl_llist *timeoutlist;
struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
struct SessionHandle *data = (struct SessionHandle *)easy_handle;
/* First, make some basic checks that the CURLM handle is a good handle */
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
/* Verify that we got a somewhat good easy handle too */
if(!GOOD_EASY_HANDLE(easy_handle))
if(!GOOD_EASY_HANDLE(data))
return CURLM_BAD_EASY_HANDLE;
/* Prevent users from adding same easy handle more than once and prevent
@ -417,14 +417,14 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
data->state.conn_cache = &multi->conn_cache;
/* This adds the new entry at the 'end' of the doubly-linked circular
list of SessionHandle structs to try and maintain a FIFO queue so
list of Curl_easy structs to try and maintain a FIFO queue so
the pipelined requests are in order. */
/* We add this new entry last in the list. */
data->next = NULL; /* end of the line */
if(multi->easyp) {
struct SessionHandle *last = multi->easylp;
struct Curl_easy *last = multi->easylp;
last->next = data;
data->prev = last;
multi->easylp = data; /* the new last node */
@ -435,8 +435,8 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
multi->easylp = multi->easyp = data; /* both first and last */
}
/* make the SessionHandle refer back to this multi handle */
data->multi = multi_handle;
/* make the Curl_easy refer back to this multi handle */
data->multi = multi;
/* Set the timeout for this handle to expire really soon so that it will
be taken care of even when this handle is added in the midst of operation
@ -444,7 +444,7 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
sockets that time-out or have actions will be dealt with. Since this
handle has no action yet, we make sure it times out to get things to
happen. */
Curl_expire(data, 1);
Curl_expire(data, 0);
/* increase the node-counter */
multi->num_easy++;
@ -464,6 +464,14 @@ CURLMcode curl_multi_add_handle(CURLM *multi_handle,
handle is added */
memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
/* The closure handle only ever has default timeouts set. To improve the
state somewhat we clone the timeouts from each added handle so that the
closure handle always has the same timeouts as the most recently added
easy handle. */
multi->closure_handle->set.timeout = data->set.timeout;
multi->closure_handle->set.server_response_timeout =
data->set.server_response_timeout;
update_timer(multi);
return CURLM_OK;
}
@ -487,7 +495,7 @@ static void debug_print_sock_hash(void *p)
/* Mark the connection as 'idle', or close it if the cache is full.
Returns TRUE if the connection is kept, or FALSE if it was closed. */
static bool
ConnectionDone(struct SessionHandle *data, struct connectdata *conn)
ConnectionDone(struct Curl_easy *data, struct connectdata *conn)
{
/* data->multi->maxconnects can be negative, deal with it. */
size_t maxconnects =
@ -523,7 +531,7 @@ static CURLcode multi_done(struct connectdata **connp,
{
CURLcode result;
struct connectdata *conn;
struct SessionHandle *data;
struct Curl_easy *data;
DEBUGASSERT(*connp);
@ -571,12 +579,12 @@ static CURLcode multi_done(struct connectdata **connp,
result = CURLE_ABORTED_BY_CALLBACK;
}
if((!premature &&
conn->send_pipe->size + conn->recv_pipe->size != 0 &&
if(conn->send_pipe->size + conn->recv_pipe->size != 0 &&
!data->set.reuse_forbid &&
!conn->bits.close)) {
!conn->bits.close) {
/* Stop if pipeline is not empty and we do not have to close
connection. */
data->easy_conn = NULL;
DEBUGF(infof(data, "Connection still in use, no more multi_done now!\n"));
return CURLE_OK;
}
@ -630,7 +638,10 @@ static CURLcode multi_done(struct connectdata **connp,
infof(data, "Connection #%ld to host %s left intact\n",
conn->connection_id,
conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname);
conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
conn->bits.httpproxy ? conn->http_proxy.host.dispname :
conn->bits.conn_to_host ? conn->conn_to_host.dispname :
conn->host.dispname);
}
else
data->state.lastconnect = NULL;
@ -645,12 +656,10 @@ static CURLcode multi_done(struct connectdata **connp,
return result;
}
CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
CURL *curl_handle)
CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
struct Curl_easy *data)
{
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
struct SessionHandle *easy = curl_handle;
struct SessionHandle *data = easy;
struct Curl_easy *easy = data;
bool premature;
bool easy_owns_conn;
struct curl_llist_element *e;
@ -660,7 +669,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
return CURLM_BAD_HANDLE;
/* Verify that we got a somewhat good easy handle too */
if(!GOOD_EASY_HANDLE(curl_handle))
if(!GOOD_EASY_HANDLE(data))
return CURLM_BAD_EASY_HANDLE;
/* Prevent users from trying to remove same easy handle more than once */
@ -689,7 +698,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
/* If the handle is in a pipeline and has started sending off its
request but not received its response yet, we need to close
connection. */
connclose(data->easy_conn, "Removed with partial response");
streamclose(data->easy_conn, "Removed with partial response");
/* Set connection owner so that the DONE function closes it. We can
safely do this here since connection is killed. */
data->easy_conn->data = easy;
@ -699,7 +708,7 @@ CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
/* The timer must be shut down before data->multi is set to NULL,
else the timenode will remain in the splay tree after
curl_easy_cleanup is called. */
Curl_expire(data, 0);
Curl_expire_clear(data);
if(data->dns.hostcachetype == HCACHE_MULTI) {
/* stop using the multi handle's DNS cache */
@ -791,7 +800,7 @@ bool Curl_pipeline_wanted(const struct Curl_multi *multi, int bits)
return (multi && (multi->pipelining & bits)) ? TRUE : FALSE;
}
void Curl_multi_handlePipeBreak(struct SessionHandle *data)
void Curl_multi_handlePipeBreak(struct Curl_easy *data)
{
data->easy_conn = NULL;
}
@ -807,6 +816,11 @@ static int waitconnect_getsock(struct connectdata *conn,
if(!numsocks)
return GETSOCK_BLANK;
#ifdef USE_SSL
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
return Curl_ssl_getsock(conn, sock, numsocks);
#endif
for(i=0; i<2; i++) {
if(conn->tempsock[i] != CURL_SOCKET_BAD) {
sock[s] = conn->tempsock[i];
@ -844,7 +858,7 @@ static int domore_getsock(struct connectdata *conn,
}
/* returns bitmapped flags for this handle and its sockets */
static int multi_getsock(struct SessionHandle *data,
static int multi_getsock(struct Curl_easy *data,
curl_socket_t *socks, /* points to numsocks number
of sockets */
int numsocks)
@ -910,15 +924,14 @@ static int multi_getsock(struct SessionHandle *data,
}
CURLMcode curl_multi_fdset(CURLM *multi_handle,
CURLMcode curl_multi_fdset(struct Curl_multi *multi,
fd_set *read_fd_set, fd_set *write_fd_set,
fd_set *exc_fd_set, int *max_fd)
{
/* Scan through all the easy handles to get the file descriptors set.
Some easy handles may not have connected to the remote host yet,
and then we must make sure that is done. */
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
struct SessionHandle *data;
struct Curl_easy *data;
int this_max_fd=-1;
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
int bitmap;
@ -960,14 +973,13 @@ CURLMcode curl_multi_fdset(CURLM *multi_handle,
return CURLM_OK;
}
CURLMcode curl_multi_wait(CURLM *multi_handle,
CURLMcode curl_multi_wait(struct Curl_multi *multi,
struct curl_waitfd extra_fds[],
unsigned int extra_nfds,
int timeout_ms,
int *ret)
{
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
struct SessionHandle *data;
struct Curl_easy *data;
curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
int bitmap;
unsigned int i;
@ -1130,7 +1142,7 @@ static bool multi_ischanged(struct Curl_multi *multi, bool clear)
}
CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
struct SessionHandle *data,
struct Curl_easy *data,
struct connectdata *conn)
{
CURLMcode rc;
@ -1155,7 +1167,7 @@ static CURLcode multi_reconnect_request(struct connectdata **connp)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = *connp;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
/* This was a re-use of a connection and we got a write error in the
* DO-phase. Then we DISCONNECT this connection and have another attempt to
@ -1223,7 +1235,7 @@ static CURLcode multi_do(struct connectdata **connp, bool *done)
{
CURLcode result=CURLE_OK;
struct connectdata *conn = *connp;
struct SessionHandle *data = conn->data;
struct Curl_easy *data = conn->data;
if(conn->handler->do_it) {
/* generic protocol-specific function pointer set in curl_connect() */
@ -1286,7 +1298,7 @@ static CURLcode multi_do_more(struct connectdata *conn, int *complete)
static CURLMcode multi_runsingle(struct Curl_multi *multi,
struct timeval now,
struct SessionHandle *data)
struct Curl_easy *data)
{
struct Curl_message *msg = NULL;
bool connected;
@ -1297,14 +1309,18 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
CURLMcode rc;
CURLcode result = CURLE_OK;
struct SingleRequest *k;
long timeout_ms;
time_t timeout_ms;
time_t recv_timeout_ms;
time_t send_timeout_ms;
int control;
if(!GOOD_EASY_HANDLE(data))
return CURLM_BAD_EASY_HANDLE;
do {
bool disconnect_conn = FALSE;
/* A "stream" here is a logical stream if the protocol can handle that
(HTTP/2), or the full connection for older protocols */
bool stream_error = FALSE;
rc = CURLM_OK;
/* Handle the case when the pipe breaks, i.e., the connection
@ -1382,8 +1398,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* Force connection closed if the connection has indeed been used */
if(data->mstate > CURLM_STATE_DO) {
connclose(data->easy_conn, "Disconnected with pending data");
disconnect_conn = TRUE;
streamclose(data->easy_conn, "Disconnected with pending data");
stream_error = TRUE;
}
result = CURLE_OPERATION_TIMEDOUT;
(void)multi_done(&data->easy_conn, result, TRUE);
@ -1432,7 +1448,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* Add this handle to the send or pend pipeline */
result = Curl_add_handle_to_pipeline(data, data->easy_conn);
if(result)
disconnect_conn = TRUE;
stream_error = TRUE;
else {
if(async)
/* We're now waiting for an asynchronous name lookup */
@ -1466,8 +1482,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
struct connectdata *conn = data->easy_conn;
const char *hostname;
if(conn->bits.proxy)
hostname = conn->proxy.name;
if(conn->bits.httpproxy)
hostname = conn->http_proxy.host.name;
else if(conn->bits.conn_to_host)
hostname = conn->conn_to_host.name;
else
@ -1524,7 +1540,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(result) {
/* failure detected */
disconnect_conn = TRUE;
stream_error = TRUE;
break;
}
}
@ -1543,7 +1559,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multistate(data, CURLM_STATE_CONNECT);
}
else if(!result) {
if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE) {
if((data->easy_conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
(data->easy_conn->tunnel_state[FIRSTSOCKET] != TUNNEL_CONNECT)) {
rc = CURLM_CALL_MULTI_PERFORM;
/* initiate protocol connect phase */
multistate(data, CURLM_STATE_SENDPROTOCONNECT);
@ -1556,6 +1574,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* awaiting a completion of an asynch TCP connect */
result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected);
if(connected && !result) {
#ifndef CURL_DISABLE_HTTP
if((data->easy_conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
!data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)) {
multistate(data, CURLM_STATE_WAITPROXYCONNECT);
break;
}
#endif
rc = CURLM_CALL_MULTI_PERFORM;
multistate(data, data->easy_conn->bits.tunnel_proxy?
CURLM_STATE_WAITPROXYCONNECT:
@ -1564,7 +1590,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
else if(result) {
/* failure detected */
/* Just break, the cleaning up is handled all in one place */
disconnect_conn = TRUE;
stream_error = TRUE;
break;
}
break;
@ -1584,7 +1610,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* failure detected */
Curl_posttransfer(data);
multi_done(&data->easy_conn, result, TRUE);
disconnect_conn = TRUE;
stream_error = TRUE;
}
break;
@ -1601,7 +1627,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* failure detected */
Curl_posttransfer(data);
multi_done(&data->easy_conn, result, TRUE);
disconnect_conn = TRUE;
stream_error = TRUE;
}
break;
@ -1676,7 +1702,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(drc) {
/* a failure here pretty much implies an out of memory */
result = drc;
disconnect_conn = TRUE;
stream_error = TRUE;
}
else
retry = (newurl)?TRUE:FALSE;
@ -1709,7 +1735,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
else {
/* Have error handler disconnect conn if we can't retry */
disconnect_conn = TRUE;
stream_error = TRUE;
free(newurl);
}
}
@ -1718,7 +1744,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
Curl_posttransfer(data);
if(data->easy_conn)
multi_done(&data->easy_conn, result, FALSE);
disconnect_conn = TRUE;
stream_error = TRUE;
}
}
break;
@ -1740,7 +1766,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* failure detected */
Curl_posttransfer(data);
multi_done(&data->easy_conn, result, FALSE);
disconnect_conn = TRUE;
stream_error = TRUE;
}
break;
@ -1769,7 +1795,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* failure detected */
Curl_posttransfer(data);
multi_done(&data->easy_conn, result, FALSE);
disconnect_conn = TRUE;
stream_error = TRUE;
}
break;
@ -1805,52 +1831,67 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
else
result = Curl_speedcheck(data, now);
if(( (data->set.max_send_speed == 0) ||
(data->progress.ulspeed < data->set.max_send_speed)) &&
( (data->set.max_recv_speed == 0) ||
(data->progress.dlspeed < data->set.max_recv_speed)))
if(!result) {
send_timeout_ms = 0;
if(data->set.max_send_speed > 0)
send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
data->progress.ul_limit_size,
data->set.max_send_speed,
data->progress.ul_limit_start,
now);
recv_timeout_ms = 0;
if(data->set.max_recv_speed > 0)
recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
data->progress.dl_limit_size,
data->set.max_recv_speed,
data->progress.dl_limit_start,
now);
if(send_timeout_ms <= 0 && recv_timeout_ms <= 0)
multistate(data, CURLM_STATE_PERFORM);
else if(send_timeout_ms >= recv_timeout_ms)
Curl_expire_latest(data, send_timeout_ms);
else
Curl_expire_latest(data, recv_timeout_ms);
}
break;
case CURLM_STATE_PERFORM:
{
char *newurl = NULL;
bool retry = FALSE;
bool comeback = FALSE;
/* check if over send speed */
if((data->set.max_send_speed > 0) &&
(data->progress.ulspeed > data->set.max_send_speed)) {
int buffersize;
multistate(data, CURLM_STATE_TOOFAST);
/* calculate upload rate-limitation timeout. */
buffersize = (int)(data->set.buffer_size ?
data->set.buffer_size : BUFSIZE);
timeout_ms = Curl_sleep_time(data->set.max_send_speed,
data->progress.ulspeed, buffersize);
Curl_expire_latest(data, timeout_ms);
break;
}
send_timeout_ms = 0;
if(data->set.max_send_speed > 0)
send_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
data->progress.ul_limit_size,
data->set.max_send_speed,
data->progress.ul_limit_start,
now);
/* check if over recv speed */
if((data->set.max_recv_speed > 0) &&
(data->progress.dlspeed > data->set.max_recv_speed)) {
int buffersize;
recv_timeout_ms = 0;
if(data->set.max_recv_speed > 0)
recv_timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
data->progress.dl_limit_size,
data->set.max_recv_speed,
data->progress.dl_limit_start,
now);
if(send_timeout_ms > 0 || recv_timeout_ms > 0) {
multistate(data, CURLM_STATE_TOOFAST);
/* Calculate download rate-limitation timeout. */
buffersize = (int)(data->set.buffer_size ?
data->set.buffer_size : BUFSIZE);
timeout_ms = Curl_sleep_time(data->set.max_recv_speed,
data->progress.dlspeed, buffersize);
Curl_expire_latest(data, timeout_ms);
if(send_timeout_ms >= recv_timeout_ms)
Curl_expire_latest(data, send_timeout_ms);
else
Curl_expire_latest(data, recv_timeout_ms);
break;
}
/* read/write data if it is ready to do so */
result = Curl_readwrite(data->easy_conn, data, &done);
result = Curl_readwrite(data->easy_conn, data, &done, &comeback);
k = &data->req;
@ -1890,10 +1931,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(!(data->easy_conn->handler->flags & PROTOPT_DUAL) &&
result != CURLE_HTTP2_STREAM)
connclose(data->easy_conn, "Transfer returned error");
streamclose(data->easy_conn, "Transfer returned error");
Curl_posttransfer(data);
multi_done(&data->easy_conn, result, FALSE);
multi_done(&data->easy_conn, result, TRUE);
}
else if(done) {
followtype follow=FOLLOW_NONE;
@ -1906,7 +1947,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* expire the new receiving pipeline head */
if(data->easy_conn->recv_pipe->head)
Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 1);
Curl_expire_latest(data->easy_conn->recv_pipe->head->ptr, 0);
/* Check if we can move pending requests to send pipe */
Curl_multi_process_pending_handles(multi);
@ -1949,13 +1990,15 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(!result)
newurl = NULL; /* allocation was handed over Curl_follow() */
else
disconnect_conn = TRUE;
stream_error = TRUE;
}
multistate(data, CURLM_STATE_DONE);
rc = CURLM_CALL_MULTI_PERFORM;
}
}
else if(comeback)
rc = CURLM_CALL_MULTI_PERFORM;
free(newurl);
break;
@ -2014,7 +2057,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
that could be freed anytime */
data->easy_conn = NULL;
Curl_expire(data, 0); /* stop all timers */
Curl_expire_clear(data); /* stop all timers */
break;
case CURLM_STATE_MSGSENT:
@ -2048,7 +2091,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
Curl_removeHandleFromPipeline(data, data->easy_conn->send_pipe);
Curl_removeHandleFromPipeline(data, data->easy_conn->recv_pipe);
if(disconnect_conn) {
if(stream_error) {
/* Don't attempt to send data over a connection that timed out */
bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
/* disconnect properly */
@ -2072,7 +2115,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* aborted due to progress callback return code must close the
connection */
result = CURLE_ABORTED_BY_CALLBACK;
connclose(data->easy_conn, "Aborted by callback");
streamclose(data->easy_conn, "Aborted by callback");
/* if not yet in DONE state, go there, otherwise COMPLETED */
multistate(data, (data->mstate < CURLM_STATE_DONE)?
@ -2102,10 +2145,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
}
CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
{
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
struct SessionHandle *data;
struct Curl_easy *data;
CURLMcode returncode=CURLM_OK;
struct Curl_tree *t;
struct timeval now = Curl_tvnow();
@ -2164,7 +2206,10 @@ static void close_all_connections(struct Curl_multi *multi)
conn->data = multi->closure_handle;
sigpipe_ignore(conn->data, &pipe_st);
conn->data->easy_conn = NULL; /* clear the easy handle's connection
pointer */
/* This will remove the connection from the cache */
connclose(conn, "kill all");
(void)Curl_disconnect(conn, FALSE);
sigpipe_restore(&pipe_st);
@ -2172,11 +2217,10 @@ static void close_all_connections(struct Curl_multi *multi)
}
}
CURLMcode curl_multi_cleanup(CURLM *multi_handle)
CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
{
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
struct SessionHandle *data;
struct SessionHandle *nextdata;
struct Curl_easy *data;
struct Curl_easy *nextdata;
if(GOOD_MULTI_HANDLE(multi)) {
bool restore_pipe = FALSE;
@ -2247,9 +2291,8 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle)
* beyond. The current design is fully O(1).
*/
CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
{
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
struct Curl_message *msg;
*msgs_in_queue = 0; /* default to none */
@ -2280,7 +2323,7 @@ CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
* call the callback accordingly.
*/
static void singlesocket(struct Curl_multi *multi,
struct SessionHandle *data)
struct Curl_easy *data)
{
curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
int i;
@ -2452,7 +2495,7 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
/*
* add_next_timeout()
*
* Each SessionHandle has a list of timeouts. The add_next_timeout() is called
* Each Curl_easy has a list of timeouts. The add_next_timeout() is called
* when it has just been removed from the splay tree because the timeout has
* expired. This function is then to advance in the list to pick the next
* timeout to use (skip the already expired ones) and add this node back to
@ -2463,7 +2506,7 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
*/
static CURLMcode add_next_timeout(struct timeval now,
struct Curl_multi *multi,
struct SessionHandle *d)
struct Curl_easy *d)
{
struct timeval *tv = &d->state.expiretime;
struct curl_llist *list = d->state.timeoutlist;
@ -2474,7 +2517,7 @@ static CURLMcode add_next_timeout(struct timeval now,
timeout in *tv */
for(e = list->head; e;) {
struct curl_llist_element *n = e->next;
long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
time_t diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
if(diff <= 0)
/* remove outdated entry */
Curl_llist_remove(list, e, NULL);
@ -2511,7 +2554,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
int *running_handles)
{
CURLMcode result = CURLM_OK;
struct SessionHandle *data = NULL;
struct Curl_easy *data = NULL;
struct Curl_tree *t;
struct timeval now = Curl_tvnow();
@ -2639,10 +2682,9 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
}
#undef curl_multi_setopt
CURLMcode curl_multi_setopt(CURLM *multi_handle,
CURLMcode curl_multi_setopt(struct Curl_multi *multi,
CURLMoption option, ...)
{
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
CURLMcode res = CURLM_OK;
va_list param;
@ -2710,33 +2752,32 @@ CURLMcode curl_multi_setopt(CURLM *multi_handle,
/* we define curl_multi_socket() in the public multi.h header */
#undef curl_multi_socket
CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
CURLMcode curl_multi_socket(struct Curl_multi *multi, curl_socket_t s,
int *running_handles)
{
CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
0, running_handles);
CURLMcode result = multi_socket(multi, FALSE, s, 0, running_handles);
if(CURLM_OK >= result)
update_timer((struct Curl_multi *)multi_handle);
update_timer(multi);
return result;
}
CURLMcode curl_multi_socket_action(CURLM *multi_handle, curl_socket_t s,
CURLMcode curl_multi_socket_action(struct Curl_multi *multi, curl_socket_t s,
int ev_bitmask, int *running_handles)
{
CURLMcode result = multi_socket((struct Curl_multi *)multi_handle, FALSE, s,
CURLMcode result = multi_socket(multi, FALSE, s,
ev_bitmask, running_handles);
if(CURLM_OK >= result)
update_timer((struct Curl_multi *)multi_handle);
update_timer(multi);
return result;
}
CURLMcode curl_multi_socket_all(CURLM *multi_handle, int *running_handles)
CURLMcode curl_multi_socket_all(struct Curl_multi *multi, int *running_handles)
{
CURLMcode result = multi_socket((struct Curl_multi *)multi_handle,
TRUE, CURL_SOCKET_BAD, 0, running_handles);
CURLMcode result = multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0,
running_handles);
if(CURLM_OK >= result)
update_timer((struct Curl_multi *)multi_handle);
update_timer(multi);
return result;
}
@ -2754,7 +2795,7 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
/* some time left before expiration */
*timeout_ms = curlx_tvdiff(multi->timetree->key, now);
*timeout_ms = (long)curlx_tvdiff(multi->timetree->key, now);
if(!*timeout_ms)
/*
* Since we only provide millisecond resolution on the returned value
@ -2775,11 +2816,9 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
return CURLM_OK;
}
CURLMcode curl_multi_timeout(CURLM *multi_handle,
CURLMcode curl_multi_timeout(struct Curl_multi *multi,
long *timeout_ms)
{
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
/* First, make some basic checks that the CURLM handle is a good handle */
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
@ -2806,7 +2845,7 @@ static int update_timer(struct Curl_multi *multi)
multi->timer_lastcall = none;
/* there's no timeout now but there was one previously, tell the app to
disable it */
return multi->timer_cb((CURLM*)multi, -1, multi->timer_userp);
return multi->timer_cb(multi, -1, multi->timer_userp);
}
return 0;
}
@ -2820,7 +2859,7 @@ static int update_timer(struct Curl_multi *multi)
multi->timer_lastcall = multi->timetree->key;
return multi->timer_cb((CURLM*)multi, timeout_ms, multi->timer_userp);
return multi->timer_cb(multi, timeout_ms, multi->timer_userp);
}
/*
@ -2863,7 +2902,7 @@ multi_addtimeout(struct curl_llist *timeoutlist,
/* find the correct spot in the list */
for(e = timeoutlist->head; e; e = e->next) {
struct timeval *checktime = e->ptr;
long diff = curlx_tvdiff(*checktime, *timedup);
time_t diff = curlx_tvdiff(*checktime, *timedup);
if(diff > 0)
break;
prev = e;
@ -2887,51 +2926,23 @@ multi_addtimeout(struct curl_llist *timeoutlist,
* given a number of milliseconds from now to use to set the 'act before
* this'-time for the transfer, to be extracted by curl_multi_timeout()
*
* Note that the timeout will be added to a queue of timeouts if it defines a
* moment in time that is later than the current head of queue.
*
* Pass zero to clear all timeout values for this handle.
* The timeout will be added to a queue of timeouts if it defines a moment in
* time that is later than the current head of queue.
*/
void Curl_expire(struct SessionHandle *data, long milli)
void Curl_expire(struct Curl_easy *data, time_t milli)
{
struct Curl_multi *multi = data->multi;
struct timeval *nowp = &data->state.expiretime;
int rc;
struct timeval set;
/* this is only interesting while there is still an associated multi struct
remaining! */
if(!multi)
return;
if(!milli) {
/* No timeout, clear the time data. */
if(nowp->tv_sec || nowp->tv_usec) {
/* Since this is an cleared time, we must remove the previous entry from
the splay tree */
struct curl_llist *list = data->state.timeoutlist;
rc = Curl_splayremovebyaddr(multi->timetree,
&data->state.timenode,
&multi->timetree);
if(rc)
infof(data, "Internal error clearing splay node = %d\n", rc);
/* flush the timeout list too */
while(list->size > 0)
Curl_llist_remove(list, list->tail, NULL);
#ifdef DEBUGBUILD
infof(data, "Expire cleared\n");
#endif
nowp->tv_sec = 0;
nowp->tv_usec = 0;
}
}
else {
struct timeval set;
set = Curl_tvnow();
set.tv_sec += milli/1000;
set.tv_sec += (long)(milli/1000);
set.tv_usec += (milli%1000)*1000;
if(set.tv_usec >= 1000000) {
@ -2943,7 +2954,7 @@ void Curl_expire(struct SessionHandle *data, long milli)
/* This means that the struct is added as a node in the splay tree.
Compare if the new time is earlier, and only remove-old/add-new if it
is. */
long diff = curlx_tvdiff(set, *nowp);
time_t diff = curlx_tvdiff(set, *nowp);
if(diff > 0) {
/* the new expire time was later so just add it to the queue
and get out */
@ -2966,14 +2977,9 @@ void Curl_expire(struct SessionHandle *data, long milli)
*nowp = set;
data->state.timenode.payload = data;
multi->timetree = Curl_splayinsert(*nowp,
multi->timetree,
multi->timetree = Curl_splayinsert(*nowp, multi->timetree,
&data->state.timenode);
}
#if 0
Curl_splayprint(multi->timetree, 0, TRUE);
#endif
}
/*
* Curl_expire_latest()
@ -2986,14 +2992,14 @@ void Curl_expire(struct SessionHandle *data, long milli)
* time-out period to expire.
*
*/
void Curl_expire_latest(struct SessionHandle *data, long milli)
void Curl_expire_latest(struct Curl_easy *data, time_t milli)
{
struct timeval *expire = &data->state.expiretime;
struct timeval set;
set = Curl_tvnow();
set.tv_sec += milli / 1000;
set.tv_sec += (long)(milli / 1000);
set.tv_usec += (milli % 1000) * 1000;
if(set.tv_usec >= 1000000) {
@ -3005,7 +3011,7 @@ void Curl_expire_latest(struct SessionHandle *data, long milli)
/* This means that the struct is added as a node in the splay tree.
Compare if the new time is earlier, and only remove-old/add-new if it
is. */
long diff = curlx_tvdiff(set, *expire);
time_t diff = curlx_tvdiff(set, *expire);
if(diff > 0)
/* the new expire time was later than the top time, so just skip this */
return;
@ -3015,11 +3021,53 @@ void Curl_expire_latest(struct SessionHandle *data, long milli)
Curl_expire(data, milli);
}
CURLMcode curl_multi_assign(CURLM *multi_handle,
curl_socket_t s, void *hashp)
/*
* Curl_expire_clear()
*
* Clear ALL timeout values for this handle.
*/
void Curl_expire_clear(struct Curl_easy *data)
{
struct Curl_multi *multi = data->multi;
struct timeval *nowp = &data->state.expiretime;
int rc;
/* this is only interesting while there is still an associated multi struct
remaining! */
if(!multi)
return;
if(nowp->tv_sec || nowp->tv_usec) {
/* Since this is an cleared time, we must remove the previous entry from
the splay tree */
struct curl_llist *list = data->state.timeoutlist;
rc = Curl_splayremovebyaddr(multi->timetree,
&data->state.timenode,
&multi->timetree);
if(rc)
infof(data, "Internal error clearing splay node = %d\n", rc);
/* flush the timeout list too */
while(list->size > 0)
Curl_llist_remove(list, list->tail, NULL);
#ifdef DEBUGBUILD
infof(data, "Expire cleared\n");
#endif
nowp->tv_sec = 0;
nowp->tv_usec = 0;
}
}
CURLMcode curl_multi_assign(struct Curl_multi *multi, curl_socket_t s,
void *hashp)
{
struct Curl_sh_entry *there = NULL;
struct Curl_multi *multi = (struct Curl_multi *)multi_handle;
there = sh_getentry(&multi->sockhash, s);
@ -3066,7 +3114,7 @@ void Curl_multi_process_pending_handles(struct Curl_multi *multi)
struct curl_llist_element *e = multi->pending->head;
while(e) {
struct SessionHandle *data = e->ptr;
struct Curl_easy *data = e->ptr;
struct curl_llist_element *next = e->next;
if(data->mstate == CURLM_STATE_CONNECT_PEND) {
@ -3076,7 +3124,7 @@ void Curl_multi_process_pending_handles(struct Curl_multi *multi)
Curl_llist_remove(multi->pending, e, NULL);
/* Make sure that the handle will be processed soonish. */
Curl_expire_latest(data, 1);
Curl_expire_latest(data, 0);
}
e = next; /* operate on next handle */
@ -3084,10 +3132,9 @@ void Curl_multi_process_pending_handles(struct Curl_multi *multi)
}
#ifdef DEBUGBUILD
void Curl_multi_dump(const struct Curl_multi *multi_handle)
void Curl_multi_dump(struct Curl_multi *multi)
{
struct Curl_multi *multi=(struct Curl_multi *)multi_handle;
struct SessionHandle *data;
struct Curl_easy *data;
int i;
fprintf(stderr, "* Multi status: %d handles, %d alive\n",
multi->num_easy, multi->num_alive);

Some files were not shown because too many files have changed in this diff Show More