Merge branch 'upstream-curl' into update-curl

* upstream-curl:
  curl 2016-11-02 (3c561c65)
This commit is contained in:
Brad King
2016-12-05 11:50:43 -05:00
106 changed files with 2086 additions and 1517 deletions
@@ -0,0 +1,61 @@
include(CheckCSourceCompiles)
option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON)
mark_as_advanced(CURL_HIDDEN_SYMBOLS)
if(CURL_HIDDEN_SYMBOLS)
set(SUPPORTS_SYMBOL_HIDING FALSE)
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(SUPPORTS_SYMBOL_HIDING TRUE)
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
elseif(CMAKE_COMPILER_IS_GNUCC)
if(NOT CMAKE_VERSION VERSION_LESS 2.8.10)
set(GCC_VERSION ${CMAKE_C_COMPILER_VERSION})
else()
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION)
endif()
if(NOT GCC_VERSION VERSION_LESS 3.4)
# note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact
set(SUPPORTS_SYMBOL_HIDING TRUE)
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
endif()
elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0)
set(SUPPORTS_SYMBOL_HIDING TRUE)
set(_SYMBOL_EXTERN "__global")
set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden")
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0)
# note: this should probably just check for version 9.1.045 but I'm not 100% sure
# so let's to it the same way autotools do.
set(SUPPORTS_SYMBOL_HIDING TRUE)
set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
check_c_source_compiles("#include <stdio.h>
int main (void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug)
if(NOT _no_bug)
set(SUPPORTS_SYMBOL_HIDING FALSE)
set(_SYMBOL_EXTERN "")
set(_CFLAG_SYMBOLS_HIDE "")
endif()
elseif(MSVC)
set(SUPPORTS_SYMBOL_HIDING TRUE)
endif()
set(HIDES_CURL_PRIVATE_SYMBOLS ${SUPPORTS_SYMBOL_HIDING})
elseif(MSVC)
if(NOT CMAKE_VERSION VERSION_LESS 3.7)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) #present since 3.4.3 but broken
set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
else()
message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.")
set(HIDES_CURL_PRIVATE_SYMBOLS TRUE)
endif()
elseif()
set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
endif()
set(CURL_CFLAG_SYMBOLS_HIDE ${_CFLAG_SYMBOLS_HIDE})
set(CURL_EXTERN_SYMBOL ${_SYMBOL_EXTERN})
+18
View File
@@ -0,0 +1,18 @@
include(FindPackageHandleStandardArgs)
find_path(NGHTTP2_INCLUDE_DIR "nghttp2/nghttp2.h")
find_library(NGHTTP2_LIBRARY NAMES nghttp2)
find_package_handle_standard_args(NGHTTP2
FOUND_VAR
NGHTTP2_FOUND
REQUIRED_VARS
NGHTTP2_LIBRARY
NGHTTP2_INCLUDE_DIR
FAIL_MESSAGE
"Could NOT find NGHTTP2"
)
set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR} )
set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY})
+54 -44
View File
@@ -65,7 +65,7 @@ endif()
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# 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
@@ -79,7 +79,7 @@ endif()
# KIND, either express or implied.
#
###########################################################################
# cURL/libcurl CMake script
# curl/libcurl CMake script
# by Tetetest and Sukender (Benoit Neil)
# TODO:
@@ -102,6 +102,7 @@ cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
include(Utilities)
include(Macros)
include(CMakeDependentOption)
project( CURL C )
@@ -135,11 +136,17 @@ set(OS "\"${CMAKE_SYSTEM_NAME}\"")
include_directories(${PROJECT_BINARY_DIR}/include/curl)
include_directories( ${CURL_SOURCE_DIR}/include )
option(BUILD_CURL_EXE "Set to ON to build cURL executable." ON)
option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
option(CURL_STATICLIB "Set to ON to build libcurl with static linking." OFF)
option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
option(ENABLE_THREADED_RESOLVER "Set to ON to enable POSIX threaded DNS lookup" OFF)
if(WIN32)
CMAKE_DEPENDENT_OPTION(ENABLE_THREADED_RESOLVER
"Set to ON to enable threaded DNS lookup"
ON "NOT ENABLE_ARES"
OFF)
else()
option(ENABLE_THREADED_RESOLVER "Set to ON to enable POSIX threaded DNS lookup" OFF)
endif()
option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF)
option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OFF)
@@ -176,8 +183,7 @@ if(MSVC)
mark_as_advanced(BUILD_RELEASE_DEBUG_DIRS)
endif()
option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON)
mark_as_advanced(CURL_HIDDEN_SYMBOLS)
include(CurlSymbolHiding)
option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" OFF)
mark_as_advanced(HTTP_ONLY)
@@ -313,13 +319,17 @@ if(WIN32)
endif(WIN32)
if(ENABLE_THREADED_RESOLVER)
check_include_file_concat("pthread.h" HAVE_PTHREAD_H)
if(HAVE_PTHREAD_H)
set(CMAKE_THREAD_PREFER_PTHREAD 1)
find_package(Threads)
if(CMAKE_USE_PTHREADS_INIT)
set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
set(USE_THREADS_POSIX 1)
if(WIN32)
set(USE_THREADS_WIN32 ON)
else()
check_include_file_concat("pthread.h" HAVE_PTHREAD_H)
if(HAVE_PTHREAD_H)
set(CMAKE_THREAD_PREFER_PTHREAD 1)
find_package(Threads)
if(CMAKE_USE_PTHREADS_INIT)
set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
set(USE_THREADS_POSIX 1)
endif()
endif()
endif()
endif()
@@ -411,6 +421,13 @@ elseif(APPLE)
endif()
endif()
option(USE_NGHTTP2 "Use Nghttp2 library" OFF)
if(USE_NGHTTP2)
find_package(NGHTTP2 REQUIRED)
include_directories(${NGHTTP2_INCLUDE_DIRS})
list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES})
endif()
if(NOT CURL_DISABLE_LDAP)
if(WIN32)
option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON)
@@ -521,13 +538,13 @@ if(NOT CURL_DISABLE_LDAPS)
endif()
# Check for idn
check_library_exists_concat("idn" idna_to_ascii_lz HAVE_LIBIDN)
check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
# Check for symbol dlopen (same as HAVE_LIBDL)
check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)
if(0) # This code not needed for building within CMake.
option(CURL_ZLIB "Set to ON to enable building cURL with zlib support." ON)
option(CURL_ZLIB "Set to ON to enable building curl with zlib support." ON)
set(HAVE_LIBZ OFF)
set(HAVE_ZLIB_H OFF)
set(HAVE_ZLIB OFF)
@@ -707,7 +724,7 @@ check_include_file_concat("des.h" HAVE_DES_H)
check_include_file_concat("err.h" HAVE_ERR_H)
check_include_file_concat("errno.h" HAVE_ERRNO_H)
check_include_file_concat("fcntl.h" HAVE_FCNTL_H)
check_include_file_concat("idn-free.h" HAVE_IDN_FREE_H)
check_include_file_concat("idn2.h" HAVE_IDN2_H)
check_include_file_concat("ifaddrs.h" HAVE_IFADDRS_H)
check_include_file_concat("io.h" HAVE_IO_H)
check_include_file_concat("krb.h" HAVE_KRB_H)
@@ -737,7 +754,6 @@ check_include_file_concat("stropts.h" HAVE_STROPTS_H)
check_include_file_concat("termio.h" HAVE_TERMIO_H)
check_include_file_concat("termios.h" HAVE_TERMIOS_H)
check_include_file_concat("time.h" HAVE_TIME_H)
check_include_file_concat("tld.h" HAVE_TLD_H)
check_include_file_concat("unistd.h" HAVE_UNISTD_H)
check_include_file_concat("utime.h" HAVE_UTIME_H)
check_include_file_concat("x509.h" HAVE_X509_H)
@@ -751,9 +767,6 @@ check_include_file_concat("netinet/if_ether.h" HAVE_NETINET_IF_ETHER_H)
check_include_file_concat("stdint.h" HAVE_STDINT_H)
check_include_file_concat("sockio.h" HAVE_SOCKIO_H)
check_include_file_concat("sys/utsname.h" HAVE_SYS_UTSNAME_H)
check_include_file_concat("idna.h" HAVE_IDNA_H)
check_type_size(size_t SIZEOF_SIZE_T)
check_type_size(ssize_t SIZEOF_SSIZE_T)
@@ -763,7 +776,6 @@ check_type_size("short" SIZEOF_SHORT)
check_type_size("int" SIZEOF_INT)
check_type_size("__int64" SIZEOF___INT64)
check_type_size("time_t" SIZEOF_TIME_T)
check_type_size("off_t" SIZEOF_OFF_T)
# Make public versions of some type sizes for curlbuild.h.
foreach(t INT LONG LONG_LONG SSIZE_T)
@@ -823,8 +835,6 @@ if(CMAKE_USE_OPENSSL)
check_symbol_exists(RAND_status "${CURL_INCLUDES}" HAVE_RAND_STATUS)
check_symbol_exists(RAND_screen "${CURL_INCLUDES}" HAVE_RAND_SCREEN)
check_symbol_exists(RAND_egd "${CURL_INCLUDES}" HAVE_RAND_EGD)
check_symbol_exists(CRYPTO_cleanup_all_ex_data "${CURL_INCLUDES}"
HAVE_CRYPTO_CLEANUP_ALL_EX_DATA)
if(HAVE_LIBCRYPTO AND HAVE_LIBSSL)
set(USE_OPENSSL 1)
endif(HAVE_LIBCRYPTO AND HAVE_LIBSSL)
@@ -854,9 +864,6 @@ check_symbol_exists(pipe "${CURL_INCLUDES}" HAVE_PIPE)
check_symbol_exists(ftruncate "${CURL_INCLUDES}" HAVE_FTRUNCATE)
check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
check_symbol_exists(getrlimit "${CURL_INCLUDES}" HAVE_GETRLIMIT)
check_symbol_exists(idn_free "${CURL_INCLUDES}" HAVE_IDN_FREE)
check_symbol_exists(idna_strerror "${CURL_INCLUDES}" HAVE_IDNA_STRERROR)
check_symbol_exists(tld_strerror "${CURL_INCLUDES}" HAVE_TLD_STRERROR)
check_symbol_exists(setlocale "${CURL_INCLUDES}" HAVE_SETLOCALE)
check_symbol_exists(setrlimit "${CURL_INCLUDES}" HAVE_SETRLIMIT)
check_symbol_exists(fcntl "${CURL_INCLUDES}" HAVE_FCNTL)
@@ -923,9 +930,14 @@ foreach(CURL_TEST
)
curl_internal_test(${CURL_TEST})
endforeach(CURL_TEST)
if(HAVE_FILE_OFFSET_BITS)
set(_FILE_OFFSET_BITS 64)
set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
endif(HAVE_FILE_OFFSET_BITS)
check_type_size("off_t" SIZEOF_OFF_T)
set(CMAKE_REQUIRED_FLAGS)
foreach(CURL_TEST
HAVE_GLIBC_STRERROR_R
HAVE_POSIX_STRERROR_R
@@ -987,16 +999,6 @@ if(NOT CURL_SPECIAL_LIBZ)
endif(NOT HAVE_ZLIB_H)
endif(NOT CURL_SPECIAL_LIBZ)
if(_FILE_OFFSET_BITS)
set(_FILE_OFFSET_BITS 64)
endif(_FILE_OFFSET_BITS)
set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
set(CMAKE_EXTRA_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/curl/curl.h")
check_type_size("curl_off_t" SIZEOF_CURL_OFF_T)
set(CMAKE_EXTRA_INCLUDE_FILES)
set(CMAKE_REQUIRED_FLAGS)
# Check for nonblocking
set(HAVE_DISABLED_NONBLOCKING 1)
if(HAVE_FIONBIO OR
@@ -1069,6 +1071,11 @@ if(WIN32)
add_definitions(-D_WIN32_WINNT=0x0501)
endif(WIN32)
# For windows, all compilers used by cmake should support large files
if(WIN32)
set(USE_WIN32_LARGE_FILES ON)
endif(WIN32)
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
endif(MSVC)
@@ -1133,8 +1140,10 @@ _add_if("OpenSSL" SSL_ENABLED AND USE_OPENSSL)
_add_if("IPv6" ENABLE_IPV6)
_add_if("unix-sockets" USE_UNIX_SOCKETS)
_add_if("libz" HAVE_LIBZ)
_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX)
_add_if("IDN" HAVE_LIBIDN)
_add_if("AsynchDNS" USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
_add_if("IDN" HAVE_LIBIDN2)
_add_if("Largefile" (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND
((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES))
# TODO SSP1 (WinSSL) check is missing
_add_if("SSPI" USE_WINDOWS_SSPI)
_add_if("GSS-API" HAVE_GSSAPI)
@@ -1200,9 +1209,7 @@ set(CURL_CA_BUNDLE "")
set(CURLVERSION "${CURL_VERSION}")
set(ENABLE_SHARED "yes")
if(CURL_STATICLIB)
# Broken: LIBCURL_LIBS below; .a lib is not built
message(WARNING "Static linking is broken!")
set(ENABLE_STATIC "no")
set(ENABLE_STATIC "yes")
else()
set(ENABLE_STATIC "no")
endif()
@@ -1211,9 +1218,12 @@ set(includedir "\${prefix}/include")
set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
set(LIBCURL_LIBS "")
set(libdir "${CMAKE_INSTALL_PREFIX}/lib")
# TODO CURL_LIBS also contains absolute paths which don't work with static -l...
foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS})
set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}")
if(_lib MATCHES ".*/.*")
set(LIBCURL_LIBS "${LIBCURL_LIBS} ${_lib}")
else()
set(LIBCURL_LIBS "${LIBCURL_LIBS} -l${_lib}")
endif()
endforeach()
# "a" (Linux) or "lib" (Windows)
string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
+10 -1
View File
@@ -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 "cmcurl/include/curl/curlbuild.h" /* libcurl build definitions */
#include "curlrules.h" /* libcurl rules enforcement */
@@ -431,7 +435,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. */
@@ -562,6 +566,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
@@ -1695,6 +1700,10 @@ 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),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
+4 -4
View File
@@ -30,13 +30,13 @@
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.50.1"
#define LIBCURL_VERSION "7.51.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 50
#define LIBCURL_VERSION_PATCH 1
#define LIBCURL_VERSION_MINOR 51
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
@@ -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 0x073201
#define LIBCURL_VERSION_NUM 0x073300
/*
* This is the date and time when the full source package was created. The
+5
View File
@@ -111,6 +111,11 @@ endif()
set_target_properties(${LIB_NAME} PROPERTIES COMPILE_DEFINITIONS BUILDING_LIBCURL)
if(0) # This code not needed for building within CMake.
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 "")
+4 -4
View File
@@ -40,13 +40,13 @@ 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 \
@@ -58,13 +58,13 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.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 \
+1 -1
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;
+5
View File
@@ -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;
-1
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"
+17 -16
View File
@@ -762,7 +762,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;
@@ -1368,25 +1368,26 @@ 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
+28 -12
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
@@ -104,21 +104,37 @@ 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
#endif /* HEADER_CURL_CONNECT_H */
+88 -40
View File
@@ -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 '.'.
@@ -469,9 +468,9 @@ Curl_cookie_add(struct Curl_easy *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 Curl_easy *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,7 +490,7 @@ Curl_cookie_add(struct Curl_easy *data,
break;
}
}
else if(Curl_raw_equal("domain", name)) {
else if(strcasecompare("domain", name)) {
bool is_ip;
const char *dotp;
@@ -529,14 +528,14 @@ Curl_cookie_add(struct Curl_easy *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 +551,7 @@ Curl_cookie_add(struct Curl_easy *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 +712,7 @@ Curl_cookie_add(struct Curl_easy *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 +741,7 @@ Curl_cookie_add(struct Curl_easy *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);
@@ -813,11 +812,12 @@ Curl_cookie_add(struct Curl_easy *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 +828,7 @@ Curl_cookie_add(struct Curl_easy *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 +902,35 @@ Curl_cookie_add(struct Curl_easy *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()
@@ -938,7 +967,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *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 +987,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *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 +1052,40 @@ static int cookie_sort(const void *p1, const void *p2)
return 0;
}
#define CLONE(field) \
do { \
if(src->field) { \
dup->field = strdup(src->field); \
if(!dup->field) \
goto fail; \
} \
} while(0)
static struct Cookie *dup_cookie(struct Cookie *src)
{
struct Cookie *dup = calloc(sizeof(struct Cookie), 1);
if(dup) {
CLONE(expirestr);
CLONE(domain);
CLONE(path);
CLONE(spath);
CLONE(name);
CLONE(value);
CLONE(maxage);
CLONE(version);
dup->expires = src->expires;
dup->tailmatch = src->tailmatch;
dup->secure = src->secure;
dup->livecookie = src->livecookie;
dup->httponly = src->httponly;
}
return dup;
fail:
freecookie(dup);
return NULL;
}
/*****************************************************************************
*
* Curl_cookie_getlist()
@@ -1067,7 +1130,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 +1141,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 +1154,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 +1206,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 +1218,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! */
freecookie(co);
co = next;
}
}
@@ -1232,7 +1280,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 +1338,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;
+2 -2
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
@@ -82,7 +82,7 @@ struct Cookie *Curl_cookie_add(struct Curl_easy *data,
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);
+7 -1
View File
@@ -61,7 +61,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
@@ -900,6 +900,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
@@ -927,6 +930,9 @@
/* 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
+32 -5
View File
@@ -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);
@@ -464,8 +489,8 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *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
@@ -543,6 +568,8 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *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)
+6 -6
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);
@@ -288,7 +286,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 +307,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 +321,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;
+20 -4
View File
@@ -614,10 +614,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
@@ -653,6 +652,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
@@ -761,4 +767,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 */
+19 -1
View File
@@ -64,6 +64,12 @@ 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)
{
@@ -102,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) {
@@ -205,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) {
+5 -8
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
+12 -13
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"
@@ -96,12 +95,12 @@ 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 */
@@ -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) {
+8 -32
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,10 +239,6 @@ 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;
@@ -292,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)
@@ -301,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,
@@ -333,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)
@@ -995,6 +968,9 @@ void curl_easy_reset(struct Curl_easy *data)
/* 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 */
}
@@ -1044,7 +1020,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, 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;
}
+24 -10
View File
@@ -78,15 +78,21 @@ char *curl_unescape(const char *string, int length)
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;
@@ -211,14 +217,22 @@ char *curl_easy_unescape(struct Curl_easy *data, const char *string,
int length, int *olen)
{
char *str = NULL;
size_t inputlen = length;
size_t outputlen;
CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen,
FALSE);
if(res)
return NULL;
if(olen)
*olen = curlx_uztosi(outputlen);
if(length >= 0) {
size_t inputlen = length;
size_t outputlen;
CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen,
FALSE);
if(res)
return NULL;
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;
}
+6 -5
View File
@@ -190,14 +190,15 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
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
+39 -23
View File
@@ -33,7 +33,7 @@
#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"
/* The last 3 #include files should be in this order */
@@ -201,9 +201,9 @@ 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 +
strlen(filename) - strlen(ctts[i].extension),
ctts[i].extension)) {
if(strcasecompare(filename +
strlen(filename) - strlen(ctts[i].extension),
ctts[i].extension)) {
contenttype = ctts[i].type;
break;
}
@@ -845,16 +845,23 @@ 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;
goto error;
}
alloc2 = newform->line;
memcpy(newform->line, line, (size_t)length);
newform->line = malloc((size_t)length+1);
if(!newform->line) {
result = CURLE_OUT_OF_MEMORY;
goto error;
/* 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 */
}
alloc2 = newform->line;
memcpy(newform->line, line, (size_t)length);
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 +870,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 +878,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 +889,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 +914,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;
}
/*
@@ -1289,7 +1305,7 @@ CURLcode Curl_getformdata(struct Curl_easy *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 */
/*
+1
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
+50 -57
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"
@@ -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;
@@ -741,7 +741,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
*/
}
else {
switch (Curl_socket_ready(sockfd, CURL_SOCKET_BAD, interval_ms)) {
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;
@@ -1835,7 +1835,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");
@@ -2742,7 +2742,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. */
@@ -2999,7 +2999,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 +3165,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;
@@ -3250,7 +3250,6 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
ssize_t nread;
int ftpcode;
CURLcode result = CURLE_OK;
bool was_ctl_valid = ftpc->ctl_valid;
char *path;
const char *path_to_use = data->state.path;
@@ -3274,10 +3273,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 +3298,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;
if(!result)
/* 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 */
@@ -4094,8 +4091,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
@@ -4107,10 +4103,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;
@@ -4292,6 +4287,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)
@@ -4300,12 +4296,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 */
@@ -4323,7 +4320,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++;
@@ -4340,18 +4337,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 {
@@ -4387,15 +4381,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
@@ -4413,16 +4404,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;
}
+2 -2
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 */
+1 -2
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"
+2 -1
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
+14 -5
View File
@@ -36,8 +36,8 @@
#include "memdebug.h"
/*
* This is supposed to be called in the beginning of a perform() session
* and should reset all session-info variables
* This is supposed to be called in the beginning of a perform() session and
* in curl_easy_reset() and should reset all session-info variables.
*/
CURLcode Curl_initinfo(struct Curl_easy *data)
{
@@ -58,18 +58,27 @@ CURLcode Curl_initinfo(struct Curl_easy *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;
#ifdef USE_SSL
Curl_ssl_free_certinfo(data);
#endif
return CURLE_OK;
}
+18 -19
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: */
@@ -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,14 +139,18 @@ 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);
/* 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");
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");
if(result) {
failf(data, "Failed sending Gopher request");
return result;
+7 -7
View File
@@ -30,7 +30,7 @@
#endif
#include "hostcheck.h"
#include "rawstr.h"
#include "strcase.h"
#include "inet_pton.h"
#include "curl_memory.h"
@@ -77,7 +77,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 +94,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 +114,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;
}
+5 -2
View File
@@ -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).
+149 -131
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"
@@ -182,7 +181,7 @@ char *Curl_checkheaders(const struct connectdata *conn,
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;
}
@@ -208,7 +207,7 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
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;
}
@@ -462,7 +461,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
@@ -726,7 +725,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
@@ -784,23 +783,27 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
while(*auth) {
#ifdef USE_SPNEGO
if(checkprefix("Negotiate", auth)) {
*availp |= CURLAUTH_NEGOTIATE;
authp->avail |= CURLAUTH_NEGOTIATE;
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) {
CURLcode result = Curl_input_negotiate(conn, proxy, auth);
if(!result) {
DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->change.url);
if(!data->req.newurl)
return CURLE_OUT_OF_MEMORY;
data->state.authproblem = FALSE;
/* we received a GSS auth token and we dealt with it fine */
negdata->state = GSS_AUTHRECV;
if(authp->picked == CURLAUTH_NEGOTIATE) {
if(negdata->state == GSS_AUTHSENT ||
negdata->state == GSS_AUTHNONE) {
CURLcode result = Curl_input_negotiate(conn, proxy, auth);
if(!result) {
DEBUGASSERT(!data->req.newurl);
data->req.newurl = strdup(data->change.url);
if(!data->req.newurl)
return CURLE_OUT_OF_MEMORY;
data->state.authproblem = FALSE;
/* we received a GSS auth token and we dealt with it fine */
negdata->state = GSS_AUTHRECV;
}
else
data->state.authproblem = TRUE;
}
else
data->state.authproblem = TRUE;
}
}
}
@@ -809,39 +812,44 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
#ifdef USE_NTLM
/* NTLM support requires the SSL crypto libs */
if(checkprefix("NTLM", auth)) {
*availp |= CURLAUTH_NTLM;
authp->avail |= CURLAUTH_NTLM;
if(authp->picked == CURLAUTH_NTLM ||
authp->picked == CURLAUTH_NTLM_WB) {
/* NTLM authentication is picked and activated */
CURLcode result = Curl_input_ntlm(conn, proxy, auth);
if(!result) {
data->state.authproblem = FALSE;
#ifdef NTLM_WB_ENABLED
if(authp->picked == CURLAUTH_NTLM_WB) {
*availp &= ~CURLAUTH_NTLM;
authp->avail &= ~CURLAUTH_NTLM;
*availp |= CURLAUTH_NTLM_WB;
authp->avail |= CURLAUTH_NTLM_WB;
if((authp->avail & CURLAUTH_NTLM) ||
(authp->avail & CURLAUTH_NTLM_WB) ||
Curl_auth_is_ntlm_supported()) {
*availp |= CURLAUTH_NTLM;
authp->avail |= CURLAUTH_NTLM;
/* Get the challenge-message which will be passed to
* ntlm_auth for generating the type 3 message later */
while(*auth && ISSPACE(*auth))
auth++;
if(checkprefix("NTLM", auth)) {
auth += strlen("NTLM");
if(authp->picked == CURLAUTH_NTLM ||
authp->picked == CURLAUTH_NTLM_WB) {
/* NTLM authentication is picked and activated */
CURLcode result = Curl_input_ntlm(conn, proxy, auth);
if(!result) {
data->state.authproblem = FALSE;
#ifdef NTLM_WB_ENABLED
if(authp->picked == CURLAUTH_NTLM_WB) {
*availp &= ~CURLAUTH_NTLM;
authp->avail &= ~CURLAUTH_NTLM;
*availp |= CURLAUTH_NTLM_WB;
authp->avail |= CURLAUTH_NTLM_WB;
/* Get the challenge-message which will be passed to
* ntlm_auth for generating the type 3 message later */
while(*auth && ISSPACE(*auth))
auth++;
if(*auth)
if((conn->challenge_header = strdup(auth)) == NULL)
return CURLE_OUT_OF_MEMORY;
if(checkprefix("NTLM", auth)) {
auth += strlen("NTLM");
while(*auth && ISSPACE(*auth))
auth++;
if(*auth)
if((conn->challenge_header = strdup(auth)) == NULL)
return CURLE_OUT_OF_MEMORY;
}
}
}
#endif
}
else {
infof(data, "Authentication problem. Ignoring this.\n");
data->state.authproblem = TRUE;
}
else {
infof(data, "Authentication problem. Ignoring this.\n");
data->state.authproblem = TRUE;
}
}
}
}
@@ -849,18 +857,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
#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");
@@ -1296,7 +1304,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 +1330,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! */
}
@@ -1443,9 +1451,8 @@ CURLcode Curl_http_done(struct connectdata *conn,
{
struct Curl_easy *data = conn->data;
struct HTTP *http = data->req.protop;
#ifdef USE_NGHTTP2
struct http_conn *httpc = &conn->proto.httpc;
#endif
infof(data, "Curl_http_done: called premature == %d\n", premature);
Curl_unencode_cleanup(conn);
@@ -1458,7 +1465,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 +1482,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;
@@ -1660,6 +1647,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);
@@ -1946,47 +1937,42 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
#endif
if(conn->httpversion == 20)
/* In HTTP2 forbids Transfer-Encoding: chunked */
ptr = NULL;
ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
if(ptr) {
/* Some kind of TE is requested, check if 'chunked' is chosen */
data->req.upload_chunky =
Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
}
else {
ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
if(ptr) {
/* Some kind of TE is requested, check if 'chunked' is chosen */
data->req.upload_chunky =
Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
}
else {
if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
data->set.upload &&
(data->state.infilesize == -1)) {
if(conn->bits.authneg)
/* don't enable chunked during auth neg */
;
else if(use_http_1_1plus(data, conn)) {
/* HTTP, upload, unknown file size and not HTTP 1.0 */
data->req.upload_chunky = TRUE;
}
else {
failf(data, "Chunky upload is not supported by HTTP 1.0");
return CURLE_UPLOAD_FAILED;
}
if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
data->set.upload &&
(data->state.infilesize == -1)) {
if(conn->bits.authneg)
/* don't enable chunked during auth neg */
;
else if(use_http_1_1plus(data, conn)) {
/* HTTP, upload, unknown file size and not HTTP 1.0 */
data->req.upload_chunky = TRUE;
}
else {
/* else, no chunky upload */
data->req.upload_chunky = FALSE;
failf(data, "Chunky upload is not supported by HTTP 1.0");
return CURLE_UPLOAD_FAILED;
}
if(data->req.upload_chunky)
te = "Transfer-Encoding: chunked\r\n";
}
else {
/* else, no chunky upload */
data->req.upload_chunky = FALSE;
}
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
@@ -2305,6 +2291,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 +2314,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 +2383,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)
@@ -2768,6 +2759,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;
}
@@ -3040,19 +3036,19 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
#endif /* CURL_DOES_CONVERSIONS */
if(100 <= k->httpcode && 199 >= k->httpcode) {
/*
* 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
* to receive the data.
* However, we'll get more headers now so we must get
* back into the header-parsing state!
*/
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:
/*
* 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
* to receive the data.
* However, we'll get more headers now so we must get
* back into the header-parsing state!
*/
k->header = TRUE;
k->headerline = 0; /* restart the header line counter */
/* if we did wait for this do enable write now! */
if(k->exp100 > EXP100_SEND_DATA) {
k->exp100 = EXP100_SEND_DATA;
@@ -3062,9 +3058,14 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *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 +3073,16 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *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 +3100,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *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");
}
}
@@ -3171,12 +3180,21 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* connection for closure after we've read the entire response.
*/
if(!k->upload_done) {
infof(data, "HTTP error before end of send, stop sending\n");
connclose(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;
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");
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;
@@ -3476,7 +3494,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *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);
}
@@ -3549,7 +3567,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *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
+1
View File
@@ -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 */
+119 -53
View File
@@ -29,7 +29,7 @@
#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"
@@ -92,8 +92,9 @@ static int http2_perform_getsock(const struct connectdata *conn,
because of renegotiation. */
sock[0] = conn->sock[FIRSTSOCKET];
if(nghttp2_session_want_read(c->h2))
bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
/* 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))
bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
@@ -150,6 +151,7 @@ void Curl_http2_setup_req(struct Curl_easy *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 +186,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 +206,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 */
};
/*
@@ -317,7 +319,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;
@@ -488,8 +490,11 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
}
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 +552,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:
@@ -621,8 +626,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",
@@ -883,7 +887,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 +903,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));
@@ -941,11 +945,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;
stream->upload_left -= 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;
@@ -979,6 +984,43 @@ static int error_callback(nghttp2_session *session,
}
#endif
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
*/
@@ -1091,9 +1133,10 @@ 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);
!nghttp2_session_want_write(httpc->h2);
}
static int h2_session_send(struct Curl_easy *data,
@@ -1107,7 +1150,8 @@ static int h2_session_send(struct Curl_easy *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 +1199,41 @@ static int h2_process_pending_input(struct Curl_easy *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 Curl_easy *data,
struct HTTP *stream, CURLcode *err) {
struct HTTP *stream, CURLcode *err)
{
char *trailer_pos, *trailer_end;
CURLcode result;
struct http_conn *httpc = &conn->proto.httpc;
@@ -1178,8 +1254,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 +1291,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;
}
@@ -1268,10 +1345,6 @@ static int h2_session_send(struct Curl_easy *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)
{
@@ -1382,6 +1455,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 +1572,6 @@ 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 */
static ssize_t http2_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
@@ -1525,6 +1599,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;
@@ -1661,12 +1743,12 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
goto fail;
hlen = end - hdbuf;
if(hlen == 10 && Curl_raw_nequal("connection", hdbuf, 10)) {
if(hlen == 10 && strncasecompare("connection", hdbuf, 10)) {
/* skip Connection: headers! */
skip = 1;
--nheader;
}
else if(hlen == 4 && Curl_raw_nequal("host", hdbuf, 4)) {
else if(hlen == 4 && strncasecompare("host", hdbuf, 4)) {
authority_idx = i;
nva[i].name = (unsigned char *)":authority";
nva[i].namelen = strlen((char *)nva[i].name);
@@ -1687,28 +1769,6 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
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;
}
}
@@ -1736,6 +1796,10 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
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) {
@@ -1751,6 +1815,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 +1920,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;
}
+5 -1
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
@@ -51,6 +51,8 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
/* called from Curl_http_setup_conn */
void Curl_http2_setup_conn(struct connectdata *conn);
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);
#else /* USE_NGHTTP2 */
#define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
#define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
@@ -61,6 +63,8 @@ void Curl_http2_setup_req(struct Curl_easy *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)
#endif
#endif /* HEADER_CURL_HTTP2_H */
+1 -1
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 */
-1
View File
@@ -26,7 +26,6 @@
#include "urldata.h"
#include "sendf.h"
#include "rawstr.h"
#include "http_negotiate.h"
#include "vauth/vauth.h"
+1 -1
View File
@@ -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"
+11 -7
View File
@@ -31,7 +31,6 @@
#include "http.h"
#include "url.h"
#include "select.h"
#include "rawstr.h"
#include "progress.h"
#include "non-ascii.h"
#include "connect.h"
@@ -160,6 +159,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
if(!result) {
char *host=(char *)"";
const char *proxyconn="";
const char *useragent="";
const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ?
"1.0" : "1.1";
@@ -185,6 +185,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,13 +197,15 @@ 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,
conn->allocptr.proxyuserpwd?
conn->allocptr.proxyuserpwd:"",
useragent);
useragent,
proxyconn);
if(host && *host)
free(host);
@@ -239,7 +244,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
}
if(!blocking) {
if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0))
if(0 == SOCKET_READABLE(tunnelsocket, 0))
/* return so we'll be called again polling-style */
return CURLE_OK;
else {
@@ -274,8 +279,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
}
/* loop every second at least, less if the timeout is near */
switch (Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD,
check<1000L?check:1000)) {
switch (SOCKET_READABLE(tunnelsocket, check<1000L?check:1000)) {
case -1: /* select() error, stop reading */
error = SELECT_ERROR;
failf(data, "Proxy CONNECT aborted due to select/poll error");
@@ -568,7 +572,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;
}
+4 -4
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;
}
}
+12 -13
View File
@@ -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"
@@ -271,7 +270,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;
@@ -846,7 +845,7 @@ static CURLcode imap_state_servergreet_resp(struct connectdata *conn,
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);
@@ -1179,7 +1178,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 +1197,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);
@@ -1275,7 +1274,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;
@@ -1935,7 +1934,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
@@ -2031,28 +2030,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';
+9 -3
View File
@@ -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);
+31 -28
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"
@@ -284,7 +283,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
/* 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")))
(strcasecompare(data->set.str[STRING_CERT_TYPE], "DER")))
cert_type = LDAPSSL_CERT_FILETYPE_DER;
if(!ldap_ca) {
failf(data, "LDAP local: ERROR %s CA cert not set!",
@@ -325,7 +324,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(data->set.ssl.verifypeer) {
/* OpenLDAP SDK supports BASE64 files. */
if((data->set.str[STRING_CERT_TYPE]) &&
(!Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "PEM"))) {
(!strcasecompare(data->set.str[STRING_CERT_TYPE], "PEM"))) {
failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!");
result = CURLE_SSL_CERTPROBLEM;
goto quit;
@@ -708,16 +707,16 @@ static void _ldap_trace (const char *fmt, ...)
*/
static int str2scope (const char *p)
{
if(strequal(p, "one"))
return LDAP_SCOPE_ONELEVEL;
if(strequal(p, "onetree"))
return LDAP_SCOPE_ONELEVEL;
if(strequal(p, "base"))
return LDAP_SCOPE_BASE;
if(strequal(p, "sub"))
return LDAP_SCOPE_SUBTREE;
if(strequal(p, "subtree"))
return LDAP_SCOPE_SUBTREE;
if(strcasecompare(p, "one"))
return LDAP_SCOPE_ONELEVEL;
if(strcasecompare(p, "onetree"))
return LDAP_SCOPE_ONELEVEL;
if(strcasecompare(p, "base"))
return LDAP_SCOPE_BASE;
if(strcasecompare(p, "sub"))
return LDAP_SCOPE_SUBTREE;
if(strcasecompare(p, "subtree"))
return LDAP_SCOPE_SUBTREE;
return (-1);
}
@@ -767,7 +766,7 @@ static bool split_str(char *str, char ***out, size_t *count)
*
* Defined in RFC4516 section 2.
*/
static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
{
int rc = LDAP_SUCCESS;
char *path;
@@ -776,9 +775,9 @@ static int _ldap_url_parse2 (const struct connectdata *conn, LDAPURLDesc *ludp)
size_t i;
if(!conn->data ||
!conn->data->state.path ||
conn->data->state.path[0] != '/' ||
!checkprefix("LDAP", conn->data->change.url))
!conn->data->state.path ||
conn->data->state.path[0] != '/' ||
!checkprefix("LDAP", conn->data->change.url))
return LDAP_INVALID_SYNTAX;
ludp->lud_scope = LDAP_SCOPE_BASE;
@@ -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;
@@ -971,8 +974,8 @@ quit:
return rc;
}
static int _ldap_url_parse (const struct connectdata *conn,
LDAPURLDesc **ludpp)
static int _ldap_url_parse(const struct connectdata *conn,
LDAPURLDesc **ludpp)
{
LDAPURLDesc *ludp = calloc(1, sizeof(*ludp));
int rc;
@@ -981,7 +984,7 @@ static int _ldap_url_parse (const struct connectdata *conn,
if(!ludp)
return LDAP_NO_MEMORY;
rc = _ldap_url_parse2 (conn, ludp);
rc = _ldap_url_parse2(conn, ludp);
if(rc != LDAP_SUCCESS) {
_ldap_free_urldesc(ludp);
ludp = NULL;
@@ -990,7 +993,7 @@ static int _ldap_url_parse (const struct connectdata *conn,
return (rc);
}
static void _ldap_free_urldesc (LDAPURLDesc *ludp)
static void _ldap_free_urldesc(LDAPURLDesc *ludp)
{
size_t i;
+3 -3
View File
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, 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
@@ -44,12 +44,12 @@ 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 "License", "https://curl.haxx.se/docs/copyright.html\0"
+1 -1
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"
+18 -8
View File
@@ -223,10 +223,12 @@ 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,
va_list arglist)
static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
va_list arglist)
{
char *fmt = (char *)format;
int param_num = 0;
@@ -389,6 +391,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;
@@ -545,7 +551,7 @@ static long dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
}
}
return max_param;
return 0;
}
@@ -583,7 +589,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 */
@@ -988,7 +995,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 */
@@ -1025,16 +1032,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;
+154 -125
View File
@@ -42,6 +42,7 @@
#include "multihandle.h"
#include "pipeline.h"
#include "sigpipe.h"
#include "connect.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -442,7 +443,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
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++;
@@ -462,6 +463,14 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
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;
}
@@ -569,12 +578,12 @@ static CURLcode multi_done(struct connectdata **connp,
result = CURLE_ABORTED_BY_CALLBACK;
}
if((!premature &&
conn->send_pipe->size + conn->recv_pipe->size != 0 &&
!data->set.reuse_forbid &&
!conn->bits.close)) {
if(conn->send_pipe->size + conn->recv_pipe->size != 0 &&
!data->set.reuse_forbid &&
!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;
}
@@ -685,7 +694,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
/* 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;
@@ -695,7 +704,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
/* 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 */
@@ -1298,7 +1307,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
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
@@ -1376,8 +1387,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);
@@ -1426,7 +1437,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 */
@@ -1518,7 +1529,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(result) {
/* failure detected */
disconnect_conn = TRUE;
stream_error = TRUE;
break;
}
}
@@ -1558,7 +1569,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;
@@ -1578,7 +1589,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;
@@ -1595,7 +1606,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;
@@ -1670,7 +1681,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;
@@ -1703,7 +1714,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);
}
}
@@ -1712,7 +1723,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;
@@ -1734,7 +1745,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;
@@ -1763,7 +1774,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;
@@ -1800,9 +1811,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
result = Curl_speedcheck(data, now);
if(( (data->set.max_send_speed == 0) ||
(data->progress.ulspeed < data->set.max_send_speed)) &&
(Curl_pgrsLimitWaitTime(data->progress.uploaded,
data->progress.ul_limit_size,
data->set.max_send_speed,
data->progress.ul_limit_start,
now) <= 0)) &&
( (data->set.max_recv_speed == 0) ||
(data->progress.dlspeed < data->set.max_recv_speed)))
(Curl_pgrsLimitWaitTime(data->progress.downloaded,
data->progress.dl_limit_size,
data->set.max_recv_speed,
data->progress.dl_limit_start,
now) <= 0)))
multistate(data, CURLM_STATE_PERFORM);
break;
@@ -1810,41 +1829,38 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
{
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;
if(data->set.max_send_speed > 0) {
timeout_ms = Curl_pgrsLimitWaitTime(data->progress.uploaded,
data->progress.ul_limit_size,
data->set.max_send_speed,
data->progress.ul_limit_start,
now);
if(timeout_ms > 0) {
multistate(data, CURLM_STATE_TOOFAST);
Curl_expire_latest(data, timeout_ms);
break;
}
}
/* check if over recv speed */
if((data->set.max_recv_speed > 0) &&
(data->progress.dlspeed > data->set.max_recv_speed)) {
int buffersize;
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);
break;
if(data->set.max_recv_speed > 0) {
timeout_ms = Curl_pgrsLimitWaitTime(data->progress.downloaded,
data->progress.dl_limit_size,
data->set.max_recv_speed,
data->progress.dl_limit_start,
now);
if(timeout_ms > 0) {
multistate(data, CURLM_STATE_TOOFAST);
Curl_expire_latest(data, 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;
@@ -1884,10 +1900,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;
@@ -1900,7 +1916,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);
@@ -1943,13 +1959,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;
@@ -2008,7 +2026,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:
@@ -2042,7 +2060,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 */
@@ -2066,7 +2084,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)?
@@ -2160,6 +2178,7 @@ static void close_all_connections(struct Curl_multi *multi)
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);
@@ -2876,92 +2895,59 @@ 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 Curl_easy *data, long 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;
set = Curl_tvnow();
set.tv_sec += milli/1000;
set.tv_usec += (milli%1000)*1000;
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;
}
if(set.tv_usec >= 1000000) {
set.tv_sec++;
set.tv_usec -= 1000000;
}
else {
struct timeval set;
set = Curl_tvnow();
set.tv_sec += milli/1000;
set.tv_usec += (milli%1000)*1000;
if(set.tv_usec >= 1000000) {
set.tv_sec++;
set.tv_usec -= 1000000;
if(nowp->tv_sec || nowp->tv_usec) {
/* 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);
if(diff > 0) {
/* the new expire time was later so just add it to the queue
and get out */
multi_addtimeout(data->state.timeoutlist, &set);
return;
}
if(nowp->tv_sec || nowp->tv_usec) {
/* 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);
if(diff > 0) {
/* the new expire time was later so just add it to the queue
and get out */
multi_addtimeout(data->state.timeoutlist, &set);
return;
}
/* the new time is newer than the presently set one, so add the current
to the queue and update the head */
multi_addtimeout(data->state.timeoutlist, nowp);
/* the new time is newer than the presently set one, so add the current
to the queue and update the head */
multi_addtimeout(data->state.timeoutlist, nowp);
/* Since this is an updated time, we must remove the previous entry from
the splay tree first and then re-add the new value */
rc = Curl_splayremovebyaddr(multi->timetree,
&data->state.timenode,
&multi->timetree);
if(rc)
infof(data, "Internal error removing splay node = %d\n", rc);
}
*nowp = set;
data->state.timenode.payload = data;
multi->timetree = Curl_splayinsert(*nowp,
multi->timetree,
&data->state.timenode);
/* Since this is an updated time, we must remove the previous entry from
the splay tree first and then re-add the new value */
rc = Curl_splayremovebyaddr(multi->timetree,
&data->state.timenode,
&multi->timetree);
if(rc)
infof(data, "Internal error removing splay node = %d\n", rc);
}
#if 0
Curl_splayprint(multi->timetree, 0, TRUE);
#endif
*nowp = set;
data->state.timenode.payload = data;
multi->timetree = Curl_splayinsert(*nowp, multi->timetree,
&data->state.timenode);
}
/*
@@ -3004,6 +2990,49 @@ void Curl_expire_latest(struct Curl_easy *data, long milli)
Curl_expire(data, milli);
}
/*
* 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)
{
@@ -3064,7 +3093,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 */
+1
View File
@@ -26,6 +26,7 @@
* Prototypes for library-wide functions provided by multi.c
*/
void Curl_expire(struct Curl_easy *data, long milli);
void Curl_expire_clear(struct Curl_easy *data);
void Curl_expire_latest(struct Curl_easy *data, long milli);
bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
void Curl_multi_handlePipeBreak(struct Curl_easy *data);
+8 -10
View File
@@ -28,10 +28,8 @@
#include <curl/curl.h>
#include "netrc.h"
#include "strequal.h"
#include "strtok.h"
#include "rawstr.h"
#include "strcase.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -130,20 +128,20 @@ int Curl_parsenetrc(const char *host,
switch(state) {
case NOTHING:
if(Curl_raw_equal("machine", tok)) {
if(strcasecompare("machine", tok)) {
/* the next tok is the machine name, this is in itself the
delimiter that starts the stuff entered for this machine,
after this we need to search for 'login' and
'password'. */
state=HOSTFOUND;
}
else if(Curl_raw_equal("default", tok)) {
else if(strcasecompare("default", tok)) {
state=HOSTVALID;
retcode=0; /* we did find our host */
}
break;
case HOSTFOUND:
if(Curl_raw_equal(host, tok)) {
if(strcasecompare(host, tok)) {
/* and yes, this is our host! */
state=HOSTVALID;
retcode=0; /* we did find our host */
@@ -156,7 +154,7 @@ int Curl_parsenetrc(const char *host,
/* we are now parsing sub-keywords concerning "our" host */
if(state_login) {
if(specific_login) {
state_our_login = Curl_raw_equal(*loginp, tok);
state_our_login = strcasecompare(*loginp, tok);
}
else {
free(*loginp);
@@ -179,11 +177,11 @@ int Curl_parsenetrc(const char *host,
}
state_password=0;
}
else if(Curl_raw_equal("login", tok))
else if(strcasecompare("login", tok))
state_login=1;
else if(Curl_raw_equal("password", tok))
else if(strcasecompare("password", tok))
state_password=1;
else if(Curl_raw_equal("machine", tok)) {
else if(strcasecompare("machine", tok)) {
/* ok, there's machine here go => */
state = HOSTFOUND;
state_our_login = FALSE;
+11 -9
View File
@@ -5,7 +5,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
@@ -80,7 +80,7 @@
#endif
#include <curl/curl.h>
#include "rawstr.h"
#include "strcase.h"
#include "warnless.h"
#include "parsedate.h"
@@ -211,7 +211,7 @@ static int checkday(const char *check, size_t len)
else
what = &Curl_wkday[0];
for(i=0; i<7; i++) {
if(Curl_raw_equal(check, what[0])) {
if(strcasecompare(check, what[0])) {
found=TRUE;
break;
}
@@ -228,7 +228,7 @@ static int checkmonth(const char *check)
what = &Curl_month[0];
for(i=0; i<12; i++) {
if(Curl_raw_equal(check, what[0])) {
if(strcasecompare(check, what[0])) {
found=TRUE;
break;
}
@@ -248,7 +248,7 @@ static int checktz(const char *check)
what = tz;
for(i=0; i< sizeof(tz)/sizeof(tz[0]); i++) {
if(Curl_raw_equal(check, what->name)) {
if(strcasecompare(check, what->name)) {
found=TRUE;
break;
}
@@ -386,15 +386,17 @@ static int parsedate(const char *date, time_t *output)
/* a digit */
int val;
char *end;
int len=0;
if((secnum == -1) &&
(3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) {
(3 == sscanf(date, "%02d:%02d:%02d%n",
&hournum, &minnum, &secnum, &len))) {
/* time stamp! */
date += 8;
date += len;
}
else if((secnum == -1) &&
(2 == sscanf(date, "%02d:%02d", &hournum, &minnum))) {
(2 == sscanf(date, "%02d:%02d%n", &hournum, &minnum, &len))) {
/* time stamp without seconds */
date += 5;
date += len;
secnum = 0;
}
else {
+2 -1
View File
@@ -108,7 +108,8 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
/* We are receiving and there is data ready in the SSL library */
rc = 1;
else
rc = Curl_socket_ready(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */
rc = Curl_socket_check(pp->sendleft?CURL_SOCKET_BAD:sock, /* reading */
CURL_SOCKET_BAD,
pp->sendleft?sock:CURL_SOCKET_BAD, /* writing */
interval_ms);
+6 -6
View File
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2013, Linus Nielsen Feltzing, <linus@haxx.se>
* Copyright (C) 2013-2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2013-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 @@
#include "multiif.h"
#include "pipeline.h"
#include "sendf.h"
#include "rawstr.h"
#include "strcase.h"
#include "curl_memory.h"
/* The last #include file should be: */
@@ -114,7 +114,7 @@ CURLcode Curl_add_handle_to_pipeline(struct Curl_easy *handle,
if(pipeline == conn->send_pipe && sendhead != conn->send_pipe->head) {
/* this is a new one as head, expire it */
Curl_pipeline_leave_write(conn); /* not in use yet */
Curl_expire(conn->send_pipe->head->ptr, 1);
Curl_expire(conn->send_pipe->head->ptr, 0);
}
#if 0 /* enable for pipeline debugging */
@@ -149,7 +149,7 @@ void Curl_move_handle_from_send_to_recv_pipe(struct Curl_easy *handle,
infof(conn->data, "%p is at send pipe head B!\n",
(void *)conn->send_pipe->head->ptr);
#endif
Curl_expire(conn->send_pipe->head->ptr, 1);
Curl_expire(conn->send_pipe->head->ptr, 0);
}
/* The receiver's list is not really interesting here since either this
@@ -177,7 +177,7 @@ bool Curl_pipeline_site_blacklisted(struct Curl_easy *handle,
struct site_blacklist_entry *site;
site = curr->ptr;
if(Curl_raw_equal(site->hostname, conn->host.name) &&
if(strcasecompare(site->hostname, conn->host.name) &&
site->port == conn->remote_port) {
infof(handle, "Site %s:%d is pipeline blacklisted\n",
conn->host.name, conn->remote_port);
@@ -269,7 +269,7 @@ bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle,
char *bl_server_name;
bl_server_name = curr->ptr;
if(Curl_raw_nequal(bl_server_name, server_name,
if(strncasecompare(bl_server_name, server_name,
strlen(bl_server_name))) {
infof(handle, "Server %s is blacklisted\n", server_name);
return TRUE;
+4 -6
View File
@@ -70,16 +70,14 @@
#include "http.h" /* for HTTP proxy tunnel stuff */
#include "socks.h"
#include "pop3.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 "curl_sasl.h"
#include "curl_md5.h"
#include "warnless.h"
@@ -663,7 +661,7 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
if(pop3code != '+') {
failf(data, "Got unexpected pop3-server response");
result = CURLE_FTP_WEIRD_SERVER_REPLY;
result = CURLE_WEIRD_SERVER_REPLY;
}
else {
/* Does the server support APOP authentication? */
@@ -1412,11 +1410,11 @@ static CURLcode pop3_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(&pop3c->sasl,
value, ptr - value);
if(result && strnequal(value, "+APOP", ptr - value)) {
if(result && strncasecompare(value, "+APOP", ptr - value)) {
pop3c->preftype = POP3_TYPE_APOP;
pop3c->sasl.prefmech = SASL_AUTH_NONE;
result = CURLE_OK;
+75
View File
@@ -216,18 +216,93 @@ void Curl_pgrsStartNow(struct Curl_easy *data)
{
data->progress.speeder_c = 0; /* reset the progress meter display */
data->progress.start = Curl_tvnow();
data->progress.ul_limit_start.tv_sec = 0;
data->progress.ul_limit_start.tv_usec = 0;
data->progress.dl_limit_start.tv_sec = 0;
data->progress.dl_limit_start.tv_usec = 0;
/* clear all bits except HIDE and HEADERS_OUT */
data->progress.flags &= PGRS_HIDE|PGRS_HEADERS_OUT;
}
/*
* This is used to handle speed limits, calculating how much milliseconds we
* need to wait until we're back under the speed limit, if needed.
*
* The way it works is by having a "starting point" (time & amount of data
* transfered by then) used in the speed computation, to be used instead of the
* start of the transfer.
* This starting point is regularly moved as transfer goes on, to keep getting
* accurate values (instead of average over the entire tranfer).
*
* This function takes the current amount of data transfered, the amount at the
* starting point, the limit (in bytes/s), the time of the starting point and
* the current time.
*
* Returns -1 if no waiting is needed (not enough data transfered since
* starting point yet), 0 when no waiting is needed but the starting point
* should be reset (to current), or the number of milliseconds to wait to get
* back under the speed limit.
*/
long Curl_pgrsLimitWaitTime(curl_off_t cursize,
curl_off_t startsize,
curl_off_t limit,
struct timeval start,
struct timeval now)
{
curl_off_t size = cursize - startsize;
long minimum, actual;
/* we don't have a starting point yet -- return 0 so it gets (re)set */
if(start.tv_sec == 0 && start.tv_usec == 0)
return 0;
/* not enough data yet */
if(size < limit)
return -1;
minimum = (long) (CURL_OFF_T_C(1000) * size / limit);
actual = Curl_tvdiff(now, start);
if(actual < minimum)
return minimum - actual;
else
return 0;
}
void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
{
struct timeval now = Curl_tvnow();
data->progress.downloaded = size;
/* download speed limit */
if((data->set.max_recv_speed > 0) &&
(Curl_pgrsLimitWaitTime(data->progress.downloaded,
data->progress.dl_limit_size,
data->set.max_recv_speed,
data->progress.dl_limit_start,
now) == 0)) {
data->progress.dl_limit_start = now;
data->progress.dl_limit_size = size;
}
}
void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size)
{
struct timeval now = Curl_tvnow();
data->progress.uploaded = size;
/* upload speed limit */
if((data->set.max_send_speed > 0) &&
(Curl_pgrsLimitWaitTime(data->progress.uploaded,
data->progress.ul_limit_size,
data->set.max_send_speed,
data->progress.ul_limit_start,
now) == 0)) {
data->progress.ul_limit_start = now;
data->progress.ul_limit_size = size;
}
}
void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size)
+5 -1
View File
@@ -49,7 +49,11 @@ void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
int Curl_pgrsUpdate(struct connectdata *);
void Curl_pgrsResetTimesSizes(struct Curl_easy *data);
void Curl_pgrsTime(struct Curl_easy *data, timerid timer);
long Curl_pgrsLimitWaitTime(curl_off_t cursize,
curl_off_t startsize,
curl_off_t limit,
struct timeval start,
struct timeval now);
/* Don't show progress for sizes smaller than: */
#define LEAST_SIZE_PROGRESS BUFSIZE
+9 -13
View File
@@ -33,7 +33,7 @@
#include "url.h"
#include "progress.h"
#include "rtsp.h"
#include "rawstr.h"
#include "strcase.h"
#include "select.h"
#include "connect.h"
/* The last 3 #include files should be in this order */
@@ -147,7 +147,7 @@ bool Curl_rtsp_connisdead(struct connectdata *check)
int sval;
bool ret_val = TRUE;
sval = Curl_socket_ready(check->sock[FIRSTSOCKET], CURL_SOCKET_BAD, 0);
sval = SOCKET_READABLE(check->sock[FIRSTSOCKET], 0);
if(sval == 0) {
/* timeout */
ret_val = FALSE;
@@ -796,19 +796,15 @@ CURLcode Curl_rtsp_parseheader(struct connectdata *conn,
}
}
else {
/* If the Session ID is not set, and we find it in a response, then
set it */
/* The session ID can be an alphanumeric or a 'safe' character
/* If the Session ID is not set, and we find it in a response, then set
* it.
*
* RFC 2326 15.1 Base Syntax:
* safe = "\$" | "-" | "_" | "." | "+"
* */
* Allow any non whitespace content, up to the field seperator or end of
* line. RFC 2326 isn't 100% clear on the session ID and for example
* gstreamer does url-encoded session ID's not covered by the standard.
*/
char *end = start;
while(*end &&
(ISALNUM(*end) || *end == '-' || *end == '_' || *end == '.' ||
*end == '+' ||
(*end == '\\' && *(end + 1) && *(end + 1) == '$' && (++end, 1))))
while(*end && *end != ';' && !ISSPACE(*end))
end++;
/* Copy the id substring into a new buffer */
+8 -5
View File
@@ -60,7 +60,7 @@
#include "curl_sec.h"
#include "ftp.h"
#include "sendf.h"
#include "rawstr.h"
#include "strcase.h"
#include "warnless.h"
/* The last #include file should be: */
@@ -122,7 +122,7 @@ static int ftp_send_command(struct connectdata *conn, const char *message, ...)
vsnprintf(print_buffer, sizeof(print_buffer), message, args);
va_end(args);
if(Curl_ftpsendf(conn, print_buffer)) {
if(Curl_ftpsend(conn, print_buffer)) {
ftp_code = -1;
}
else {
@@ -192,15 +192,18 @@ static CURLcode read_data(struct connectdata *conn,
struct krb5buffer *buf)
{
int len;
void* tmp;
void *tmp = NULL;
CURLcode result;
result = socket_read(fd, &len, sizeof(len));
if(result)
return result;
len = ntohl(len);
tmp = realloc(buf->data, len);
if(len) {
/* only realloc if there was a length */
len = ntohl(len);
tmp = realloc(buf->data, len);
}
if(tmp == NULL)
return CURLE_OUT_OF_MEMORY;
+20 -15
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
@@ -51,15 +51,14 @@
#include "warnless.h"
/* Convenience local macros */
#define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
#define ELAPSED_MS() (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
int Curl_ack_eintr = 0;
#define error_not_EINTR (Curl_ack_eintr || error != EINTR)
#define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR)
/*
* Internal function used for waiting a specific amount of ms
* in Curl_socket_ready() and Curl_poll() when no file descriptor
* in Curl_socket_check() and Curl_poll() when no file descriptor
* is provided to wait on, just being used to delay execution.
* WinSock select() and poll() timeout mechanisms need a valid
* socket descriptor in a not null file descriptor set to work.
@@ -109,9 +108,9 @@ int Curl_wait_ms(int timeout_ms)
if(r != -1)
break;
error = SOCKERRNO;
if(error && error_not_EINTR)
if(error && ERROR_NOT_EINTR(error))
break;
pending_ms = timeout_ms - elapsed_ms;
pending_ms = timeout_ms - ELAPSED_MS();
if(pending_ms <= 0) {
r = 0; /* Simulate a "call timed out" case */
break;
@@ -165,6 +164,12 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
int r;
int ret;
#if SIZEOF_LONG != SIZEOF_INT
/* wrap-around precaution */
if(timeout_ms >= INT_MAX)
timeout_ms = INT_MAX;
#endif
if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
(writefd == CURL_SOCKET_BAD)) {
/* no sockets, just wait */
@@ -213,10 +218,10 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
if(r != -1)
break;
error = SOCKERRNO;
if(error && error_not_EINTR)
if(error && ERROR_NOT_EINTR(error))
break;
if(timeout_ms > 0) {
pending_ms = (int)(timeout_ms - elapsed_ms);
pending_ms = (int)(timeout_ms - ELAPSED_MS());
if(pending_ms <= 0) {
r = 0; /* Simulate a "call timed out" case */
break;
@@ -328,10 +333,10 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
if(r != -1)
break;
error = SOCKERRNO;
if(error && error_not_EINTR)
if(error && ERROR_NOT_EINTR(error))
break;
if(timeout_ms > 0) {
pending_ms = timeout_ms - elapsed_ms;
pending_ms = (int)(timeout_ms - ELAPSED_MS());
if(pending_ms <= 0) {
r = 0; /* Simulate a "call timed out" case */
break;
@@ -434,10 +439,10 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
if(r != -1)
break;
error = SOCKERRNO;
if(error && error_not_EINTR)
if(error && ERROR_NOT_EINTR(error))
break;
if(timeout_ms > 0) {
pending_ms = timeout_ms - elapsed_ms;
pending_ms = (int)(timeout_ms - ELAPSED_MS());
if(pending_ms <= 0) {
r = 0; /* Simulate a "call timed out" case */
break;
@@ -521,10 +526,10 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
if(r != -1)
break;
error = SOCKERRNO;
if(error && error_not_EINTR)
if(error && ERROR_NOT_EINTR(error))
break;
if(timeout_ms > 0) {
pending_ms = timeout_ms - elapsed_ms;
pending_ms = timeout_ms - ELAPSED_MS();
if(pending_ms <= 0) {
r = 0; /* Simulate a "call timed out" case */
break;
+5 -4
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
@@ -75,9 +75,10 @@ int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
curl_socket_t writefd,
long timeout_ms);
/* provide the former API internally */
#define Curl_socket_ready(x,y,z) \
Curl_socket_check(x, CURL_SOCKET_BAD, y, z)
#define SOCKET_READABLE(x,z) \
Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, z)
#define SOCKET_WRITABLE(x,z) \
Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, x, z)
int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);
+5 -5
View File
@@ -673,7 +673,7 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
switch(smbc->state) {
case SMB_NEGOTIATE:
if(h->status) {
if(h->status || smbc->got < sizeof(*nrsp) + sizeof(smbc->challenge) - 1) {
connclose(conn, "SMB: negotiation failed");
return CURLE_COULDNT_CONNECT;
}
@@ -712,6 +712,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
{
struct smb_request *req = conn->data->req.protop;
struct smb_header *h;
struct smb_conn *smbc = &conn->proto.smbc;
enum smb_req_state next_state = SMB_DONE;
unsigned short len;
unsigned short off;
@@ -754,7 +755,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
break;
case SMB_OPEN:
if(h->status) {
if(h->status || smbc->got < sizeof(struct smb_nt_create_response)) {
req->result = CURLE_REMOTE_FILE_NOT_FOUND;
next_state = SMB_TREE_DISCONNECT;
break;
@@ -775,7 +776,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
break;
case SMB_DOWNLOAD:
if(h->status) {
if(h->status || smbc->got < sizeof(struct smb_header) + 14) {
req->result = CURLE_RECV_ERROR;
next_state = SMB_CLOSE;
break;
@@ -785,7 +786,6 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
off = Curl_read16_le(((unsigned char *) msg) +
sizeof(struct smb_header) + 13);
if(len > 0) {
struct smb_conn *smbc = &conn->proto.smbc;
if(off + sizeof(unsigned int) + len > smbc->got) {
failf(conn->data, "Invalid input packet");
result = CURLE_RECV_ERROR;
@@ -807,7 +807,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
break;
case SMB_UPLOAD:
if(h->status) {
if(h->status || smbc->got < sizeof(struct smb_header) + 6) {
req->result = CURLE_UPLOAD_FAILED;
next_state = SMB_CLOSE;
break;
+3 -5
View File
@@ -69,16 +69,14 @@
#include "http.h" /* for HTTP proxy tunnel stuff */
#include "socks.h"
#include "smtp.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 "curl_gethostname.h"
#include "curl_sasl.h"
#include "warnless.h"
@@ -674,7 +672,7 @@ static CURLcode smtp_state_servergreet_resp(struct connectdata *conn,
if(smtpcode/100 != 2) {
failf(data, "Got unexpected smtp-server response: %d", smtpcode);
result = CURLE_FTP_WEIRD_SERVER_REPLY;
result = CURLE_WEIRD_SERVER_REPLY;
}
else
result = smtp_perform_ehlo(conn);
@@ -1512,7 +1510,7 @@ static CURLcode smtp_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(&smtpc->sasl,
value, ptr - value);
else
+75 -57
View File
@@ -33,7 +33,6 @@
#include "urldata.h"
#include "sendf.h"
#include "strequal.h"
#include "select.h"
#include "connect.h"
#include "timeval.h"
@@ -67,7 +66,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
result = CURLE_OPERATION_TIMEDOUT;
break;
}
if(Curl_socket_ready(sockfd, CURL_SOCKET_BAD, timeleft) <= 0) {
if(SOCKET_READABLE(sockfd, timeleft) <= 0) {
result = ~CURLE_OK;
break;
}
@@ -170,24 +169,26 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
hp=dns->addr;
if(hp) {
char buf[64];
unsigned short ip[4];
Curl_printable_address(hp, buf, sizeof(buf));
if(4 == sscanf(buf, "%hu.%hu.%hu.%hu",
&ip[0], &ip[1], &ip[2], &ip[3])) {
/* Set DSTIP */
socksreq[4] = (unsigned char)ip[0];
socksreq[5] = (unsigned char)ip[1];
socksreq[6] = (unsigned char)ip[2];
socksreq[7] = (unsigned char)ip[3];
if(hp->ai_family == AF_INET) {
struct sockaddr_in *saddr_in;
saddr_in = (struct sockaddr_in*)(void*)hp->ai_addr;
socksreq[4] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[0];
socksreq[5] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[1];
socksreq[6] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[2];
socksreq[7] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[3];
infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)\n", buf);
}
else
else {
hp = NULL; /* fail! */
infof(data, "SOCKS4 connect to %s (locally resolved)\n", buf);
failf(data, "SOCKS4 connection to %s not supported\n", buf);
}
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
}
if(!hp) {
failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
@@ -399,7 +400,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
(void)curlx_nonblock(sock, TRUE);
/* wait until socket gets connected */
result = Curl_socket_ready(CURL_SOCKET_BAD, sock, timeout);
result = SOCKET_WRITABLE(sock, timeout);
if(-1 == result) {
failf(conn->data, "SOCKS5: no connection here");
@@ -429,6 +430,8 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
(void)curlx_nonblock(sock, FALSE);
infof(data, "SOCKS5 communication to %s:%d\n", hostname, remote_port);
code = Curl_write_plain(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]),
&written);
if(code || (written != (2 + (int)socksreq[1]))) {
@@ -438,7 +441,7 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
(void)curlx_nonblock(sock, TRUE);
result = Curl_socket_ready(sock, CURL_SOCKET_BAD, timeout);
result = SOCKET_READABLE(sock, timeout);
if(-1 == result) {
failf(conn->data, "SOCKS5 nothing to read");
@@ -594,34 +597,40 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
if(dns)
hp=dns->addr;
if(hp) {
struct sockaddr_in *saddr_in;
#ifdef ENABLE_IPV6
struct sockaddr_in6 *saddr_in6;
#endif
int i;
char buf[64];
Curl_printable_address(hp, buf, sizeof(buf));
if(hp->ai_family == AF_INET) {
struct sockaddr_in *saddr_in;
socksreq[len++] = 1; /* ATYP: IPv4 = 1 */
saddr_in = (struct sockaddr_in*)(void*)hp->ai_addr;
for(i = 0; i < 4; i++) {
socksreq[len++] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[i];
infof(data, "%d\n", socksreq[len-1]);
}
infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", buf);
}
#ifdef ENABLE_IPV6
else if(hp->ai_family == AF_INET6) {
struct sockaddr_in6 *saddr_in6;
socksreq[len++] = 4; /* ATYP: IPv6 = 4 */
saddr_in6 = (struct sockaddr_in6*)(void*)hp->ai_addr;
for(i = 0; i < 16; i++) {
socksreq[len++] = ((unsigned char*)&saddr_in6->sin6_addr.s6_addr)[i];
}
infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", buf);
}
#endif
else
else {
hp = NULL; /* fail! */
failf(data, "SOCKS5 connection to %s not supported\n", buf);
}
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
}
if(!hp) {
@@ -668,39 +677,6 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
"SOCKS5 reply has wrong version, version should be 5.");
return CURLE_COULDNT_CONNECT;
}
if(socksreq[1] != 0) { /* Anything besides 0 is an error */
if(socksreq[3] == 1) {
failf(data,
"Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
(((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
(unsigned char)socksreq[1]);
}
else if(socksreq[3] == 3) {
failf(data,
"Can't complete SOCKS5 connection to %s:%d. (%d)",
hostname,
(((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
(unsigned char)socksreq[1]);
}
else if(socksreq[3] == 4) {
failf(data,
"Can't complete SOCKS5 connection to %02x%02x:%02x%02x:"
"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
(unsigned char)socksreq[8], (unsigned char)socksreq[9],
(unsigned char)socksreq[10], (unsigned char)socksreq[11],
(unsigned char)socksreq[12], (unsigned char)socksreq[13],
(unsigned char)socksreq[14], (unsigned char)socksreq[15],
(unsigned char)socksreq[16], (unsigned char)socksreq[17],
(unsigned char)socksreq[18], (unsigned char)socksreq[19],
(((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
(unsigned char)socksreq[1]);
}
return CURLE_COULDNT_CONNECT;
}
/* Fix: in general, returned BND.ADDR is variable length parameter by RFC
1928, so the reply packet should be read until the end to avoid errors at
@@ -735,10 +711,9 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
/* decrypt_gssapi_blockread already read the whole packet */
#endif
if(len > 10) {
len -= 10;
result = Curl_blockread_all(conn, sock, (char *)&socksreq[10],
len, &actualread);
if(result || (len != actualread)) {
len - 10, &actualread);
if(result || ((len - 10) != actualread)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
return CURLE_COULDNT_CONNECT;
}
@@ -747,6 +722,49 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
}
#endif
if(socksreq[1] != 0) { /* Anything besides 0 is an error */
if(socksreq[3] == 1) {
failf(data,
"Can't complete SOCKS5 connection to %d.%d.%d.%d:%d. (%d)",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
(((unsigned char)socksreq[8] << 8) |
(unsigned char)socksreq[9]),
(unsigned char)socksreq[1]);
}
else if(socksreq[3] == 3) {
unsigned char port_upper = (unsigned char)socksreq[len - 2];
socksreq[len - 2] = 0;
failf(data,
"Can't complete SOCKS5 connection to %s:%d. (%d)",
(char *)&socksreq[5],
((port_upper << 8) |
(unsigned char)socksreq[len - 1]),
(unsigned char)socksreq[1]);
socksreq[len - 2] = port_upper;
}
else if(socksreq[3] == 4) {
failf(data,
"Can't complete SOCKS5 connection to %02x%02x:%02x%02x:"
"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%d. (%d)",
(unsigned char)socksreq[4], (unsigned char)socksreq[5],
(unsigned char)socksreq[6], (unsigned char)socksreq[7],
(unsigned char)socksreq[8], (unsigned char)socksreq[9],
(unsigned char)socksreq[10], (unsigned char)socksreq[11],
(unsigned char)socksreq[12], (unsigned char)socksreq[13],
(unsigned char)socksreq[14], (unsigned char)socksreq[15],
(unsigned char)socksreq[16], (unsigned char)socksreq[17],
(unsigned char)socksreq[18], (unsigned char)socksreq[19],
(((unsigned char)socksreq[20] << 8) |
(unsigned char)socksreq[21]),
(unsigned char)socksreq[1]);
}
return CURLE_COULDNT_CONNECT;
}
else {
infof(data, "SOCKS5 request granted.\n");
}
(void)curlx_nonblock(sock, TRUE);
return CURLE_OK; /* Proxy was successful! */
}
+25 -30
View File
@@ -72,7 +72,7 @@
#include "speedcheck.h"
#include "getinfo.h"
#include "strequal.h"
#include "strcase.h"
#include "vtls/vtls.h"
#include "connect.h"
#include "strerror.h"
@@ -416,12 +416,12 @@ static CURLcode ssh_getworkingpath(struct connectdata *conn,
struct Curl_easy *data = conn->data;
char *real_path = NULL;
char *working_path;
int working_path_len;
working_path = curl_easy_unescape(data, data->state.path, 0,
&working_path_len);
if(!working_path)
return CURLE_OUT_OF_MEMORY;
size_t working_path_len;
CURLcode result =
Curl_urldecode(data, data->state.path, 0, &working_path,
&working_path_len, FALSE);
if(result)
return result;
/* Check for /~/, indicating relative to the user's home directory */
if(conn->handler->protocol & CURLPROTO_SCP) {
@@ -676,7 +676,7 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn)
* against a known fingerprint, if available.
*/
if(pubkey_md5 && strlen(pubkey_md5) == 32) {
if(!fingerprint || !strequal(md5buffer, pubkey_md5)) {
if(!fingerprint || strcmp(md5buffer, pubkey_md5)) {
if(fingerprint)
failf(data,
"Denied establishing ssh session: mismatch md5 fingerprint. "
@@ -1233,7 +1233,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->acceptfail = TRUE;
}
if(curl_strequal("pwd", cmd)) {
if(strcasecompare("pwd", cmd)) {
/* output debug output if that is requested */
char *tmp = aprintf("257 \"%s\" is current directory.\n",
sftp_scp->path);
@@ -1297,9 +1297,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* OpenSSH's sftp program and call the appropriate libssh2
* functions.
*/
if(curl_strnequal(cmd, "chgrp ", 6) ||
curl_strnequal(cmd, "chmod ", 6) ||
curl_strnequal(cmd, "chown ", 6) ) {
if(strncasecompare(cmd, "chgrp ", 6) ||
strncasecompare(cmd, "chmod ", 6) ||
strncasecompare(cmd, "chown ", 6) ) {
/* attribute change */
/* sshc->quote_path1 contains the mode to set */
@@ -1321,8 +1321,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_SFTP_QUOTE_STAT);
break;
}
else if(curl_strnequal(cmd, "ln ", 3) ||
curl_strnequal(cmd, "symlink ", 8)) {
else if(strncasecompare(cmd, "ln ", 3) ||
strncasecompare(cmd, "symlink ", 8)) {
/* symbolic linking */
/* sshc->quote_path1 is the source */
/* get the destination */
@@ -1342,12 +1342,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_SFTP_QUOTE_SYMLINK);
break;
}
else if(curl_strnequal(cmd, "mkdir ", 6)) {
else if(strncasecompare(cmd, "mkdir ", 6)) {
/* create dir */
state(conn, SSH_SFTP_QUOTE_MKDIR);
break;
}
else if(curl_strnequal(cmd, "rename ", 7)) {
else if(strncasecompare(cmd, "rename ", 7)) {
/* rename file */
/* first param is the source path */
/* second param is the dest. path */
@@ -1366,17 +1366,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_SFTP_QUOTE_RENAME);
break;
}
else if(curl_strnequal(cmd, "rmdir ", 6)) {
else if(strncasecompare(cmd, "rmdir ", 6)) {
/* delete dir */
state(conn, SSH_SFTP_QUOTE_RMDIR);
break;
}
else if(curl_strnequal(cmd, "rm ", 3)) {
else if(strncasecompare(cmd, "rm ", 3)) {
state(conn, SSH_SFTP_QUOTE_UNLINK);
break;
}
#ifdef HAS_STATVFS_SUPPORT
else if(curl_strnequal(cmd, "statvfs ", 8)) {
else if(strncasecompare(cmd, "statvfs ", 8)) {
state(conn, SSH_SFTP_QUOTE_STATVFS);
break;
}
@@ -1431,7 +1431,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->acceptfail = TRUE;
}
if(!curl_strnequal(cmd, "chmod", 5)) {
if(!strncasecompare(cmd, "chmod", 5)) {
/* Since chown and chgrp only set owner OR group but libssh2 wants to
* set them both at once, we need to obtain the current ownership
* first. This takes an extra protocol round trip.
@@ -1457,7 +1457,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
/* Now set the new attributes... */
if(curl_strnequal(cmd, "chgrp", 5)) {
if(strncasecompare(cmd, "chgrp", 5)) {
sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
@@ -1471,7 +1471,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
}
else if(curl_strnequal(cmd, "chmod", 5)) {
else if(strncasecompare(cmd, "chmod", 5)) {
sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
/* permissions are octal */
@@ -1486,7 +1486,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
}
else if(curl_strnequal(cmd, "chown", 5)) {
else if(strncasecompare(cmd, "chown", 5)) {
sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
@@ -1895,7 +1895,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* since we don't really wait for anything at this point, we want the
state machine to move on as soon as possible so we set a very short
timeout here */
Curl_expire(data, 1);
Curl_expire(data, 0);
state(conn, SSH_STOP);
}
@@ -2860,7 +2860,7 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
fd_write = sock;
/* wait for the socket to become ready */
Curl_socket_ready(fd_read, fd_write,
Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
left>1000?1000:left); /* ignore result */
}
#endif
@@ -3109,7 +3109,6 @@ static CURLcode scp_done(struct connectdata *conn, CURLcode status,
}
/* return number of received (decrypted) bytes */
static ssize_t scp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
@@ -3134,10 +3133,6 @@ static ssize_t scp_send(struct connectdata *conn, int sockindex,
return nwrite;
}
/*
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
* a regular CURLcode value.
*/
static ssize_t scp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len, CURLcode *err)
{
@@ -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,9 @@
#include "curl_setup.h"
#include "rawstr.h"
#include <curl/curl.h>
#include "strcase.h"
/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
its behavior is altered by the current locale. */
@@ -99,9 +101,11 @@ char Curl_raw_toupper(char in)
*
* The function is capable of comparing a-z case insensitively even for
* non-ascii.
*
* @unittest: 1301
*/
int Curl_raw_equal(const char *first, const char *second)
int Curl_strcasecompare(const char *first, const char *second)
{
while(*first && *second) {
if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
@@ -116,7 +120,10 @@ int Curl_raw_equal(const char *first, const char *second)
return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
}
int Curl_raw_nequal(const char *first, const char *second, size_t max)
/*
* @unittest: 1301
*/
int Curl_strncasecompare(const char *first, const char *second, size_t max)
{
while(*first && *second && max) {
if(Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) {
@@ -146,3 +153,14 @@ void Curl_strntoupper(char *dest, const char *src, size_t n)
*dest++ = Curl_raw_toupper(*src);
} while(*src++ && --n);
}
/* --- public functions --- */
int curl_strequal(const char *first, const char *second)
{
return Curl_strcasecompare(first, second);
}
int curl_strnequal(const char *first, const char *second, size_t max)
{
return Curl_strncasecompare(first, second, max);
}
@@ -1,5 +1,5 @@
#ifndef HEADER_CURL_RAWSTR_H
#define HEADER_CURL_RAWSTR_H
#ifndef HEADER_CURL_STRCASE_H
#define HEADER_CURL_STRCASE_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
@@ -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
@@ -25,23 +25,26 @@
#include <curl/curl.h>
/*
* Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant
* to be locale independent and only compare strings we know are safe for
* this.
* Only "raw" case insensitive strings. This is meant to be locale independent
* and only compare strings we know are safe for this.
*
* The function is capable of comparing a-z case insensitively even for
* non-ascii.
*/
int Curl_raw_equal(const char *first, const char *second);
int Curl_raw_nequal(const char *first, const char *second, size_t max);
#define strcasecompare(a,b) Curl_strcasecompare(a,b)
#define strncasecompare(a,b,c) Curl_strncasecompare(a,b,c)
int Curl_strcasecompare(const char *first, const char *second);
int Curl_strncasecompare(const char *first, const char *second, size_t max);
char Curl_raw_toupper(char in);
/* checkprefix() is a shorter version of the above, used when the first
argument is zero-byte terminated */
#define checkprefix(a,b) Curl_raw_nequal(a,b,strlen(a))
#define checkprefix(a,b) curl_strnequal(a,b,strlen(a))
void Curl_strntoupper(char *dest, const char *src, size_t n);
char Curl_raw_toupper(char in);
#endif /* HEADER_CURL_RAWSTR_H */
#endif /* HEADER_CURL_STRCASE_H */
+2 -2
View File
@@ -65,9 +65,9 @@ char *curlx_strdup(const char *str)
* Returns the new pointer or NULL on failure.
*
***************************************************************************/
char *Curl_memdup(const char *src, size_t length)
void *Curl_memdup(const void *src, size_t length)
{
char *buffer = malloc(length);
void *buffer = malloc(length);
if(!buffer)
return NULL; /* fail */
+2 -2
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
@@ -26,6 +26,6 @@
#ifndef HAVE_STRDUP
extern char *curlx_strdup(const char *str);
#endif
char *Curl_memdup(const char *src, size_t buffer_length);
void *Curl_memdup(const void *src, size_t buffer_length);
#endif /* HEADER_CURL_STRDUP_H */
-79
View File
@@ -1,79 +0,0 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2013, 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.
*
***************************************************************************/
#include "curl_setup.h"
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include "strequal.h"
/*
* @unittest: 1301
*/
int curl_strequal(const char *first, const char *second)
{
#if defined(HAVE_STRCASECMP)
return !(strcasecmp)(first, second);
#elif defined(HAVE_STRCMPI)
return !(strcmpi)(first, second);
#elif defined(HAVE_STRICMP)
return !(stricmp)(first, second);
#else
while(*first && *second) {
if(toupper(*first) != toupper(*second)) {
break;
}
first++;
second++;
}
return toupper(*first) == toupper(*second);
#endif
}
/*
* @unittest: 1301
*/
int curl_strnequal(const char *first, const char *second, size_t max)
{
#if defined(HAVE_STRNCASECMP)
return !strncasecmp(first, second, max);
#elif defined(HAVE_STRNCMPI)
return !strncmpi(first, second, max);
#elif defined(HAVE_STRNICMP)
return !strnicmp(first, second, max);
#else
while(*first && *second && max) {
if(toupper(*first) != toupper(*second)) {
break;
}
max--;
first++;
second++;
}
if(0 == max)
return 1; /* they are equal this far */
return toupper(*first) == toupper(*second);
#endif
}
-31
View File
@@ -1,31 +0,0 @@
#ifndef HEADER_CURL_STREQUAL_H
#define HEADER_CURL_STREQUAL_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2013, 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.
*
***************************************************************************/
#include <curl/curl.h>
#define strequal(a,b) curl_strequal(a,b)
#define strnequal(a,b,c) curl_strnequal(a,b,c)
#endif /* HEADER_CURL_STREQUAL_H */
+5 -82
View File
@@ -35,8 +35,8 @@
#include <curl/curl.h>
#ifdef USE_LIBIDN
#include <idna.h>
#ifdef USE_LIBIDN2
#include <idn2.h>
#endif
#ifdef USE_WINDOWS_SSPI
@@ -79,8 +79,8 @@ curl_easy_strerror(CURLcode error)
case CURLE_COULDNT_CONNECT:
return "Couldn't connect to server";
case CURLE_FTP_WEIRD_SERVER_REPLY:
return "FTP: weird server reply";
case CURLE_WEIRD_SERVER_REPLY:
return "Weird server reply";
case CURLE_REMOTE_ACCESS_DENIED:
return "Access denied to remote resource";
@@ -427,7 +427,7 @@ curl_share_strerror(CURLSHcode error)
#ifdef USE_WINSOCK
/* This function handles most / all (?) Winsock errors cURL is able to produce.
/* This function handles most / all (?) Winsock errors curl is able to produce.
*/
static const char *
get_winsock_error (int err, char *buf, size_t len)
@@ -726,83 +726,6 @@ const char *Curl_strerror(struct connectdata *conn, int err)
return buf;
}
#ifdef USE_LIBIDN
/*
* Return error-string for libidn status as returned from idna_to_ascii_lz().
*/
const char *Curl_idn_strerror (struct connectdata *conn, int err)
{
#ifdef HAVE_IDNA_STRERROR
(void)conn;
return idna_strerror((Idna_rc) err);
#else
const char *str;
char *buf;
size_t max;
DEBUGASSERT(conn);
buf = conn->syserr_buf;
max = sizeof(conn->syserr_buf)-1;
*buf = '\0';
#ifndef CURL_DISABLE_VERBOSE_STRINGS
switch ((Idna_rc)err) {
case IDNA_SUCCESS:
str = "No error";
break;
case IDNA_STRINGPREP_ERROR:
str = "Error in string preparation";
break;
case IDNA_PUNYCODE_ERROR:
str = "Error in Punycode operation";
break;
case IDNA_CONTAINS_NON_LDH:
str = "Illegal ASCII characters";
break;
case IDNA_CONTAINS_MINUS:
str = "Contains minus";
break;
case IDNA_INVALID_LENGTH:
str = "Invalid output length";
break;
case IDNA_NO_ACE_PREFIX:
str = "No ACE prefix (\"xn--\")";
break;
case IDNA_ROUNDTRIP_VERIFY_ERROR:
str = "Round trip verify error";
break;
case IDNA_CONTAINS_ACE_PREFIX:
str = "Already have ACE prefix (\"xn--\")";
break;
case IDNA_ICONV_ERROR:
str = "Locale conversion failed";
break;
case IDNA_MALLOC_ERROR:
str = "Allocation failed";
break;
case IDNA_DLOPEN_ERROR:
str = "dlopen() error";
break;
default:
snprintf(buf, max, "error %d", err);
str = NULL;
break;
}
#else
if((Idna_rc)err == IDNA_SUCCESS)
str = "No error";
else
str = "Error";
#endif
if(str)
strncpy(buf, str, max);
buf[max] = '\0';
return (buf);
#endif
}
#endif /* USE_LIBIDN */
#ifdef USE_WINDOWS_SSPI
const char *Curl_sspi_strerror (struct connectdata *conn, int err)
{
+2 -2
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
@@ -26,7 +26,7 @@
const char *Curl_strerror (struct connectdata *conn, int err);
#ifdef USE_LIBIDN
#ifdef USE_LIBIDN2
const char *Curl_idn_strerror (struct connectdata *conn, int err);
#endif
+37 -2
View File
@@ -83,7 +83,39 @@ bool Curl_verify_windows_version(const unsigned int majorVersion,
{
bool matched = FALSE;
#if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
#if defined(CURL_WINDOWS_APP)
/* We have no way to determine the Windows version from Windows apps,
so let's assume we're running on the target Windows version. */
const WORD fullVersion = MAKEWORD(minorVersion, majorVersion);
const WORD targetVersion = (WORD)_WIN32_WINNT;
switch(condition) {
case VERSION_LESS_THAN:
matched = targetVersion < fullVersion;
break;
case VERSION_LESS_THAN_EQUAL:
matched = targetVersion <= fullVersion;
break;
case VERSION_EQUAL:
matched = targetVersion == fullVersion;
break;
case VERSION_GREATER_THAN_EQUAL:
matched = targetVersion >= fullVersion;
break;
case VERSION_GREATER_THAN:
matched = targetVersion > fullVersion;
break;
}
if(matched && (platform == PLATFORM_WINDOWS)) {
/* we're always running on PLATFORM_WINNT */
matched = FALSE;
}
#elif !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_WIN2K) || \
(_WIN32_WINNT < _WIN32_WINNT_WIN2K)
OSVERSIONINFO osver;
@@ -128,7 +160,7 @@ bool Curl_verify_windows_version(const unsigned int majorVersion,
}
/* Verify the platform identifier (if necessary) */
if(matched && platform != PLATFORM_DONT_CARE) {
if(matched) {
switch(platform) {
case PLATFORM_WINDOWS:
if(osver.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)
@@ -138,6 +170,9 @@ bool Curl_verify_windows_version(const unsigned int majorVersion,
case PLATFORM_WINNT:
if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
matched = FALSE;
default: /* like platform == PLATFORM_DONT_CARE */
break;
}
}
}
+6 -7
View File
@@ -58,8 +58,7 @@
#include "arpa_telnet.h"
#include "select.h"
#include "strequal.h"
#include "rawstr.h"
#include "strcase.h"
#include "warnless.h"
/* The last 3 #include files should be in this order */
@@ -846,7 +845,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
option_keyword, option_arg) == 2) {
/* Terminal type */
if(Curl_raw_equal(option_keyword, "TTYPE")) {
if(strcasecompare(option_keyword, "TTYPE")) {
strncpy(tn->subopt_ttype, option_arg, 31);
tn->subopt_ttype[31] = 0; /* String termination */
tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
@@ -854,7 +853,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
}
/* Display variable */
if(Curl_raw_equal(option_keyword, "XDISPLOC")) {
if(strcasecompare(option_keyword, "XDISPLOC")) {
strncpy(tn->subopt_xdisploc, option_arg, 127);
tn->subopt_xdisploc[127] = 0; /* String termination */
tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
@@ -862,7 +861,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
}
/* Environment variable */
if(Curl_raw_equal(option_keyword, "NEW_ENV")) {
if(strcasecompare(option_keyword, "NEW_ENV")) {
beg = curl_slist_append(tn->telnet_vars, option_arg);
if(!beg) {
result = CURLE_OUT_OF_MEMORY;
@@ -874,7 +873,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
}
/* Window Size */
if(Curl_raw_equal(option_keyword, "WS")) {
if(strcasecompare(option_keyword, "WS")) {
if(sscanf(option_arg, "%hu%*[xX]%hu",
&tn->subopt_wsx, &tn->subopt_wsy) == 2)
tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES;
@@ -887,7 +886,7 @@ static CURLcode check_telnet_options(struct connectdata *conn)
}
/* To take care or not of the 8th bit in data exchange */
if(Curl_raw_equal(option_keyword, "BINARY")) {
if(strcasecompare(option_keyword, "BINARY")) {
binary_option=atoi(option_arg);
if(binary_option!=1) {
tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO;
+22 -9
View File
@@ -55,9 +55,10 @@
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h"
#include "url.h"
#include "rawstr.h"
#include "strcase.h"
#include "speedcheck.h"
#include "select.h"
#include "escape.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -484,10 +485,10 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
/* As RFC3617 describes the separator slash is not actually part of the
file name so we skip the always-present first letter of the path
string. */
filename = curl_easy_unescape(data, &state->conn->data->state.path[1], 0,
NULL);
if(!filename)
return CURLE_OUT_OF_MEMORY;
result = Curl_urldecode(data, &state->conn->data->state.path[1], 0,
&filename, NULL, FALSE);
if(result)
return result;
snprintf((char *)state->spacket.data+2,
state->blksize,
@@ -705,6 +706,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
int rblock;
CURLcode result = CURLE_OK;
struct SingleRequest *k = &data->req;
int cb; /* Bytes currently read */
switch(event) {
@@ -762,9 +764,20 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
return CURLE_OK;
}
result = Curl_fillreadbuffer(state->conn, state->blksize, &state->sbytes);
if(result)
return result;
/* TFTP considers data block size < 512 bytes as an end of session. So
* in some cases we must wait for additional data to build full (512 bytes)
* data block.
* */
state->sbytes = 0;
state->conn->data->req.upload_fromhere = (char *)state->spacket.data+4;
do {
result = Curl_fillreadbuffer(state->conn, state->blksize - state->sbytes,
&cb);
if(result)
return result;
state->sbytes += cb;
state->conn->data->req.upload_fromhere += cb;
} while(state->sbytes < state->blksize && cb != 0);
sbytes = sendto(state->sockfd, (void *) state->spacket.data,
4 + state->sbytes, SEND_4TH_ARG,
@@ -1221,7 +1234,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
}
else {
/* no timeouts to handle, check our socket */
rc = Curl_socket_ready(state->sockfd, CURL_SOCKET_BAD, 0);
rc = SOCKET_READABLE(state->sockfd, 0);
if(rc == -1) {
/* bail out */
+35 -68
View File
@@ -21,10 +21,7 @@
***************************************************************************/
#include "curl_setup.h"
#include "strtoofft.h"
#include "strequal.h"
#include "rawstr.h"
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
@@ -75,6 +72,7 @@
#include "multiif.h"
#include "connect.h"
#include "non-ascii.h"
#include "http2.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -384,11 +382,15 @@ bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc)
* Go ahead and do a read if we have a readable socket or if
* the stream was rewound (in which case we have data in a
* buffer)
*
* return '*comeback' TRUE if we didn't properly drain the socket so this
* function should get called again without select() or similar in between!
*/
static CURLcode readwrite_data(struct Curl_easy *data,
struct connectdata *conn,
struct SingleRequest *k,
int *didwhat, bool *done)
int *didwhat, bool *done,
bool *comeback)
{
CURLcode result = CURLE_OK;
ssize_t nread; /* number of bytes read */
@@ -398,6 +400,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
int maxloops = 100;
*done = FALSE;
*comeback = FALSE;
/* This is where we loop until we have read everything there is to
read or we get a CURLE_AGAIN */
@@ -529,6 +532,13 @@ static CURLcode readwrite_data(struct Curl_easy *data,
is non-headers. */
if(k->str && !k->header && (nread > 0 || is_empty_data)) {
if(data->set.opt_no_body) {
/* data arrives although we want none, bail out */
streamclose(conn, "ignoring body");
*done = TRUE;
return CURLE_WEIRD_SERVER_REPLY;
}
#ifndef CURL_DISABLE_HTTP
if(0 == k->bodywrites && !is_empty_data) {
/* These checks are only made the first time we are about to
@@ -804,6 +814,12 @@ static CURLcode readwrite_data(struct Curl_easy *data,
} while(data_pending(conn) && maxloops--);
if(maxloops <= 0) {
/* we mark it as read-again-please */
conn->cselect_bits = CURL_CSELECT_IN;
*comeback = TRUE;
}
if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) &&
conn->bits.close) {
/* When we've read the entire thing and the close bit is set, the server
@@ -821,6 +837,8 @@ static CURLcode done_sending(struct connectdata *conn,
{
k->keepon &= ~KEEP_SEND; /* we're done writing */
Curl_http2_done_sending(conn);
if(conn->bits.rewindaftersend) {
CURLcode result = Curl_readrewind(conn);
if(result)
@@ -1029,10 +1047,14 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
/*
* Curl_readwrite() is the low-level function to be called when data is to
* be read and written to/from the connection.
*
* return '*comeback' TRUE if we didn't properly drain the socket so this
* function should get called again without select() or similar in between!
*/
CURLcode Curl_readwrite(struct connectdata *conn,
struct Curl_easy *data,
bool *done)
bool *done,
bool *comeback)
{
struct SingleRequest *k = &data->req;
CURLcode result;
@@ -1064,7 +1086,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if(!select_res) /* Call for select()/poll() only, if read/write/error
status is not known. */
select_res = Curl_socket_ready(fd_read, fd_write, 0);
select_res = Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, 0);
if(select_res == CURL_CSELECT_ERR) {
failf(data, "select/poll returned error");
@@ -1077,7 +1099,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if((k->keepon & KEEP_RECV) &&
((select_res & CURL_CSELECT_IN) || conn->bits.stream_was_rewound)) {
result = readwrite_data(data, conn, k, &didwhat, done);
result = readwrite_data(data, conn, k, &didwhat, done, comeback);
if(result || *done)
return result;
}
@@ -1249,60 +1271,6 @@ int Curl_single_getsock(const struct connectdata *conn,
return bitmap;
}
/*
* Determine optimum sleep time based on configured rate, current rate,
* and packet size.
* Returns value in milliseconds.
*
* The basic idea is to adjust the desired rate up/down in this method
* based on whether we are running too slow or too fast. Then, calculate
* how many milliseconds to wait for the next packet to achieve this new
* rate.
*/
long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
int pkt_size)
{
curl_off_t min_sleep = 0;
curl_off_t rv = 0;
if(rate_bps == 0)
return 0;
/* If running faster than about .1% of the desired speed, slow
* us down a bit. Use shift instead of division as the 0.1%
* cutoff is arbitrary anyway.
*/
if(cur_rate_bps > (rate_bps + (rate_bps >> 10))) {
/* running too fast, decrease target rate by 1/64th of rate */
rate_bps -= rate_bps >> 6;
min_sleep = 1;
}
else if(cur_rate_bps < (rate_bps - (rate_bps >> 10))) {
/* running too slow, increase target rate by 1/64th of rate */
rate_bps += rate_bps >> 6;
}
/* Determine number of milliseconds to wait until we do
* the next packet at the adjusted rate. We should wait
* longer when using larger packets, for instance.
*/
rv = ((curl_off_t)(pkt_size * 1000) / rate_bps);
/* Catch rounding errors and always slow down at least 1ms if
* we are running too fast.
*/
if(rv < min_sleep)
rv = min_sleep;
/* Bound value to fit in 'long' on 32-bit platform. That's
* plenty long enough anyway!
*/
if(rv > 0x7fffffff)
rv = 0x7fffffff;
return (long)rv;
}
/* Curl_init_CONNECT() gets called each time the handle switches to CONNECT
which means this gets called once for each subsequent redirect etc */
void Curl_init_CONNECT(struct Curl_easy *data)
@@ -1875,13 +1843,12 @@ CURLcode Curl_retry_request(struct connectdata *conn,
return CURLE_OK;
if((data->req.bytecount + data->req.headerbytecount == 0) &&
conn->bits.reuse &&
!data->set.opt_no_body &&
(data->set.rtspreq != RTSPREQ_RECEIVE)) {
/* We got no data, we attempted to re-use a connection and yet we want a
"body". This might happen if the connection was left alive when we were
done using it before, but that was closed when we wanted to read from
it again. Bad luck. Retry the same request on a fresh connect! */
conn->bits.reuse &&
(data->set.rtspreq != RTSPREQ_RECEIVE)) {
/* We didn't get a single byte when we attempted to re-use a
connection. This might happen if the connection was left alive when we
were done using it before, but that was closed when we wanted to use it
again. Bad luck. Retry the same request on a fresh connect! */
infof(conn->data, "Connection died, retrying a fresh connect\n");
*url = strdup(conn->data->change.url);
if(!*url)
+2 -6
View File
@@ -40,10 +40,9 @@ typedef enum {
CURLcode Curl_follow(struct Curl_easy *data, char *newurl,
followtype type);
CURLcode Curl_readwrite(struct connectdata *conn,
struct Curl_easy *data, bool *done);
struct Curl_easy *data, bool *done,
bool *comeback);
int Curl_single_getsock(const struct connectdata *conn,
curl_socket_t *socks,
int numsocks);
@@ -65,8 +64,5 @@ Curl_setup_transfer (struct connectdata *data,
curl_off_t *writecountp /* return number of bytes written */
);
long Curl_sleep_time(curl_off_t rate_bps, curl_off_t cur_rate_bps,
int pkt_size);
#endif /* HEADER_CURL_TRANSFER_H */
+104 -141
View File
@@ -59,24 +59,13 @@
#include <limits.h>
#endif
#ifdef USE_LIBIDN
#include <idna.h>
#include <tld.h>
#include <stringprep.h>
#ifdef HAVE_IDN_FREE_H
#include <idn-free.h>
#else
/* prototype from idn-free.h, not provided by libidn 0.4.5's make install! */
void idn_free (void *ptr);
#endif
#ifndef HAVE_IDN_FREE
/* if idn_free() was not found in this version of libidn use free() instead */
#define idn_free(x) (free)(x)
#endif
#ifdef USE_LIBIDN2
#include <idn2.h>
#elif defined(USE_WIN32_IDN)
/* prototype for curl_win32_idn_to_ascii() */
bool curl_win32_idn_to_ascii(const char *in, char **out);
#endif /* USE_LIBIDN */
#endif /* USE_LIBIDN2 */
#include "urldata.h"
#include "netrc.h"
@@ -88,7 +77,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "sendf.h"
#include "progress.h"
#include "cookie.h"
#include "strequal.h"
#include "strcase.h"
#include "strerror.h"
#include "escape.h"
#include "strtok.h"
@@ -100,7 +89,6 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "multiif.h"
#include "easyif.h"
#include "speedcheck.h"
#include "rawstr.h"
#include "warnless.h"
#include "non-ascii.h"
#include "inet_pton.h"
@@ -405,7 +393,7 @@ CURLcode Curl_close(struct Curl_easy *data)
if(!data)
return CURLE_OK;
Curl_expire(data, 0); /* shut off timers */
Curl_expire_clear(data); /* shut off timers */
m = data->multi;
@@ -602,6 +590,7 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
set->tcp_keepintvl = 60;
set->tcp_keepidle = 60;
set->tcp_fastopen = FALSE;
set->tcp_nodelay = TRUE;
set->ssl_enable_npn = TRUE;
set->ssl_enable_alpn = TRUE;
@@ -781,6 +770,10 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
*/
data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
case CURLOPT_KEEP_SENDING_ON_ERROR:
data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
TRUE : FALSE;
break;
case CURLOPT_UPLOAD:
case CURLOPT_PUT:
/*
@@ -1225,23 +1218,23 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
if(argptr == NULL)
break;
if(Curl_raw_equal(argptr, "ALL")) {
if(strcasecompare(argptr, "ALL")) {
/* clear all cookies */
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
Curl_cookie_clearall(data->cookies);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
else if(Curl_raw_equal(argptr, "SESS")) {
else if(strcasecompare(argptr, "SESS")) {
/* clear session cookies */
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
Curl_cookie_clearsess(data->cookies);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
else if(Curl_raw_equal(argptr, "FLUSH")) {
else if(strcasecompare(argptr, "FLUSH")) {
/* flush cookies to file, takes care of the locking */
Curl_flush_cookies(data, 0);
}
else if(Curl_raw_equal(argptr, "RELOAD")) {
else if(strcasecompare(argptr, "RELOAD")) {
/* reload cookies from file */
Curl_cookie_loadfiles(data);
break;
@@ -2614,7 +2607,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
case CURLOPT_TLSAUTH_TYPE:
if(strnequal((char *)va_arg(param, char *), "SRP", strlen("SRP")))
if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
data->set.ssl.authtype = CURL_TLSAUTH_SRP;
else
data->set.ssl.authtype = CURL_TLSAUTH_NONE;
@@ -2829,6 +2822,17 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
return CURLE_OK;
}
/*
* If this connection isn't marked to force-close, leave it open if there
* are other users of it
*/
if(!conn->bits.close &&
(conn->send_pipe->size + conn->recv_pipe->size)) {
DEBUGF(infof(data, "Curl_disconnect, usecounter: %d\n",
conn->send_pipe->size + conn->recv_pipe->size));
return CURLE_OK;
}
if(conn->dns_entry != NULL) {
Curl_resolv_unlock(data, conn->dns_entry);
conn->dns_entry = NULL;
@@ -2876,7 +2880,7 @@ static bool SocketIsDead(curl_socket_t sock)
int sval;
bool ret_val = TRUE;
sval = Curl_socket_ready(sock, CURL_SOCKET_BAD, 0);
sval = SOCKET_READABLE(sock, 0);
if(sval == 0)
/* timeout */
ret_val = FALSE;
@@ -2892,7 +2896,8 @@ static bool IsPipeliningPossible(const struct Curl_easy *handle,
const struct connectdata *conn)
{
/* If a HTTP protocol and pipelining is enabled */
if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
(!conn->bits.protoconnstart || !conn->bits.close)) {
if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
(handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
@@ -3267,6 +3272,8 @@ ConnectionExists(struct Curl_easy *data,
pipeLen = check->send_pipe->size + check->recv_pipe->size;
if(canPipeline) {
if(check->bits.protoconnstart && check->bits.close)
continue;
if(!check->bits.multiplex) {
/* If not multiplexing, make sure the pipe has only GET requests */
@@ -3341,7 +3348,7 @@ ConnectionExists(struct Curl_easy *data,
(needle->proxytype != check->proxytype ||
needle->bits.httpproxy != check->bits.httpproxy ||
needle->bits.tunnel_proxy != check->bits.tunnel_proxy ||
!Curl_raw_equal(needle->proxy.name, check->proxy.name) ||
!strcasecompare(needle->proxy.name, check->proxy.name) ||
needle->port != check->port))
/* don't mix connections that use different proxies */
continue;
@@ -3384,8 +3391,8 @@ ConnectionExists(struct Curl_easy *data,
if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
/* This protocol requires credentials per connection,
so verify that we're using the same name and password as well */
if(!strequal(needle->user, check->user) ||
!strequal(needle->passwd, check->passwd)) {
if(strcmp(needle->user, check->user) ||
strcmp(needle->passwd, check->passwd)) {
/* one of them was different */
continue;
}
@@ -3396,14 +3403,14 @@ ConnectionExists(struct Curl_easy *data,
/* The requested connection does not use a HTTP proxy or it uses SSL or
it is a non-SSL protocol tunneled over the same HTTP proxy name and
port number */
if((Curl_raw_equal(needle->handler->scheme, check->handler->scheme) ||
if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
(get_protocol_family(check->handler->protocol) ==
needle->handler->protocol && check->tls_upgraded)) &&
(!needle->bits.conn_to_host || Curl_raw_equal(
(!needle->bits.conn_to_host || strcasecompare(
needle->conn_to_host.name, check->conn_to_host.name)) &&
(!needle->bits.conn_to_port ||
needle->conn_to_port == check->conn_to_port) &&
Curl_raw_equal(needle->host.name, check->host.name) &&
strcasecompare(needle->host.name, check->host.name) &&
needle->remote_port == check->remote_port) {
/* The schemes match or the the protocol family is the same and the
previous connection was TLS upgraded, and the hostname and host
@@ -3445,8 +3452,8 @@ ConnectionExists(struct Curl_easy *data,
possible. (Especially we must not reuse the same connection if
partway through a handshake!) */
if(wantNTLMhttp) {
if(!strequal(needle->user, check->user) ||
!strequal(needle->passwd, check->passwd))
if(strcmp(needle->user, check->user) ||
strcmp(needle->passwd, check->passwd))
continue;
}
else if(check->ntlm.state != NTLMSTATE_NONE) {
@@ -3460,8 +3467,8 @@ ConnectionExists(struct Curl_easy *data,
if(!check->proxyuser || !check->proxypasswd)
continue;
if(!strequal(needle->proxyuser, check->proxyuser) ||
!strequal(needle->proxypasswd, check->proxypasswd))
if(strcmp(needle->proxyuser, check->proxyuser) ||
strcmp(needle->proxypasswd, check->proxypasswd))
continue;
}
else if(check->proxyntlm.state != NTLMSTATE_NONE) {
@@ -3752,58 +3759,15 @@ static bool is_ASCII_name(const char *hostname)
return TRUE;
}
#ifdef USE_LIBIDN
/*
* Check if characters in hostname is allowed in Top Level Domain.
*/
static bool tld_check_name(struct Curl_easy *data,
const char *ace_hostname)
{
size_t err_pos;
char *uc_name = NULL;
int rc;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
const char *tld_errmsg = "<no msg>";
#else
(void)data;
#endif
/* Convert (and downcase) ACE-name back into locale's character set */
rc = idna_to_unicode_lzlz(ace_hostname, &uc_name, 0);
if(rc != IDNA_SUCCESS)
return FALSE;
/* Warning: err_pos receives "the decoded character offset rather than the
byte position in the string." And as of libidn 1.32 that character offset
is for UTF-8, even if the passed in string is another locale. */
rc = tld_check_lz(uc_name, &err_pos, NULL);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
#ifdef HAVE_TLD_STRERROR
if(rc != TLD_SUCCESS)
tld_errmsg = tld_strerror((Tld_rc)rc);
#endif
if(rc != TLD_SUCCESS)
infof(data, "WARNING: TLD check for %s failed; %s\n",
uc_name, tld_errmsg);
#endif /* CURL_DISABLE_VERBOSE_STRINGS */
if(uc_name)
idn_free(uc_name);
if(rc != TLD_SUCCESS)
return FALSE;
return TRUE;
}
#endif
/*
* Perform any necessary IDN conversion of hostname
*/
static void fix_hostname(struct Curl_easy *data,
struct connectdata *conn, struct hostname *host)
static void fix_hostname(struct connectdata *conn, struct hostname *host)
{
size_t len;
struct Curl_easy *data = conn->data;
#ifndef USE_LIBIDN
#ifndef USE_LIBIDN2
(void)data;
(void)conn;
#elif defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -3821,25 +3785,18 @@ static void fix_hostname(struct Curl_easy *data,
/* Check name for non-ASCII and convert hostname to ACE form if we can */
if(!is_ASCII_name(host->name)) {
#ifdef USE_LIBIDN
if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
#ifdef USE_LIBIDN2
if(idn2_check_version(IDN2_VERSION)) {
char *ace_hostname = NULL;
int rc = idna_to_ascii_lz(host->name, &ace_hostname, 0);
infof(data, "Input domain encoded as `%s'\n",
stringprep_locale_charset());
if(rc == IDNA_SUCCESS) {
/* tld_check_name() displays a warning if the host name contains
"illegal" characters for this TLD */
(void)tld_check_name(data, ace_hostname);
host->encalloc = ace_hostname;
int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, 0);
if(rc == IDN2_OK) {
host->encalloc = (char *)ace_hostname;
/* change the name pointer to point to the encoded hostname */
host->name = host->encalloc;
}
else
infof(data, "Failed to convert %s to ACE; %s\n", host->name,
Curl_idn_strerror(conn, rc));
idn2_strerror(rc));
}
#elif defined(USE_WIN32_IDN)
char *ace_hostname = NULL;
@@ -3862,9 +3819,9 @@ static void fix_hostname(struct Curl_easy *data,
*/
static void free_fixed_hostname(struct hostname *host)
{
#if defined(USE_LIBIDN)
#if defined(USE_LIBIDN2)
if(host->encalloc) {
idn_free(host->encalloc); /* must be freed with idn_free() since this was
idn2_free(host->encalloc); /* must be freed with idn2_free() since this was
allocated by libidn */
host->encalloc = NULL;
}
@@ -4022,7 +3979,7 @@ static CURLcode findprotocol(struct Curl_easy *data,
variables based on the URL. Now that the handler may be changed later
when the protocol specific setup function is called. */
for(pp = protocols; (p = *pp) != NULL; pp++) {
if(Curl_raw_equal(p->scheme, protostr)) {
if(strcasecompare(p->scheme, protostr)) {
/* Protocol found in table. Check if allowed */
if(!(data->set.allowed_protocols & p->protocol))
/* nope, get out */
@@ -4091,7 +4048,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
************************************************************/
if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]",
protobuf, path)) &&
Curl_raw_equal(protobuf, "file")) {
strcasecompare(protobuf, "file")) {
if(path[0] == '/' && path[1] == '/') {
/* Allow omitted hostname (e.g. file:/<path>). This is not strictly
* speaking a valid file: URL by RFC 1738, but treating file:/<path> as
@@ -4145,7 +4102,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
path[0]=0;
rc = sscanf(data->change.url,
"%15[^\n:]:%3[/]%[^\n/?]%[^\n]",
"%15[^\n:]:%3[/]%[^\n/?#]%[^\n]",
protobuf, slashbuf, conn->host.name, path);
if(2 == rc) {
failf(data, "Bad URL");
@@ -4157,7 +4114,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
* The URL was badly formatted, let's try the browser-style _without_
* protocol specified like 'http://'.
*/
rc = sscanf(data->change.url, "%[^\n/?]%[^\n]", conn->host.name, path);
rc = sscanf(data->change.url, "%[^\n/?#]%[^\n]", conn->host.name, path);
if(1 > rc) {
/*
* We couldn't even get this format.
@@ -4262,10 +4219,10 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
}
/* If the URL is malformatted (missing a '/' after hostname before path) we
* insert a slash here. The only letter except '/' we accept to start a path
* is '?'.
* insert a slash here. The only letters except '/' that can start a path is
* '?' and '#' - as controlled by the two sscanf() patterns above.
*/
if(path[0] == '?') {
if(path[0] != '/') {
/* We need this function to deal with overlapping memory areas. We know
that the memory area 'path' points to is 'urllen' bytes big and that
is bigger than the path. Use +1 to move the zero byte too. */
@@ -4531,7 +4488,7 @@ static bool check_noproxy(const char* name, const char* no_proxy)
char *endptr;
if(no_proxy && no_proxy[0]) {
if(Curl_raw_equal("*", no_proxy)) {
if(strcasecompare("*", no_proxy)) {
return TRUE;
}
@@ -4569,7 +4526,7 @@ static bool check_noproxy(const char* name, const char* no_proxy)
if((tok_end - tok_start) <= namelen) {
/* Match the last part of the name to the domain we are checking. */
const char *checkn = name + namelen - (tok_end - tok_start);
if(Curl_raw_nequal(no_proxy + tok_start, checkn,
if(strncasecompare(no_proxy + tok_start, checkn,
tok_end - tok_start)) {
if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
/* We either have an exact match, or the previous character is a .
@@ -4648,7 +4605,7 @@ static char *detect_proxy(struct connectdata *conn)
* This can cause 'internal' http/ftp requests to be
* arbitrarily redirected by any external attacker.
*/
if(!prox && !Curl_raw_equal("http_proxy", proxy_env)) {
if(!prox && !strcasecompare("http_proxy", proxy_env)) {
/* There was no lowercase variable, try the uppercase version: */
Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
prox=curl_getenv(proxy_env);
@@ -4705,7 +4662,13 @@ static CURLcode parse_proxy(struct Curl_easy *data,
conn->proxytype = CURLPROXY_SOCKS4A;
else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
conn->proxytype = CURLPROXY_SOCKS4;
/* Any other xxx:// : change to http proxy */
else if(checkprefix("http:", proxy))
; /* leave it as HTTP or HTTP/1.0 */
else {
/* Any other xxx:// reject! */
failf(data, "Unsupported proxy scheme for \'%s\'", proxy);
return CURLE_COULDNT_CONNECT;
}
}
else
proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
@@ -4725,21 +4688,24 @@ static CURLcode parse_proxy(struct Curl_easy *data,
them. */
Curl_safefree(conn->proxyuser);
if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH)
conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
else
conn->proxyuser = strdup("");
if(!conn->proxyuser)
result = CURLE_OUT_OF_MEMORY;
result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL,
FALSE);
else {
conn->proxyuser = strdup("");
if(!conn->proxyuser)
result = CURLE_OUT_OF_MEMORY;
}
if(!result) {
Curl_safefree(conn->proxypasswd);
if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
else
result = Curl_urldecode(data, proxypasswd, 0,
&conn->proxypasswd, NULL, FALSE);
else {
conn->proxypasswd = strdup("");
if(!conn->proxypasswd)
result = CURLE_OUT_OF_MEMORY;
if(!conn->proxypasswd)
result = CURLE_OUT_OF_MEMORY;
}
}
if(!result) {
@@ -4846,6 +4812,7 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
{
char proxyuser[MAX_CURL_USER_LENGTH]="";
char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
CURLcode result;
if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
@@ -4858,15 +4825,11 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
}
conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL);
if(!conn->proxyuser)
return CURLE_OUT_OF_MEMORY;
conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL);
if(!conn->proxypasswd)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL, FALSE);
if(!result)
result = Curl_urldecode(data, proxypasswd, 0, &conn->proxypasswd, NULL,
FALSE);
return result;
}
#endif /* CURL_DISABLE_PROXY */
@@ -4940,9 +4903,8 @@ static CURLcode parse_url_login(struct Curl_easy *data,
conn->bits.user_passwd = TRUE; /* enable user+password */
/* Decode the user */
newname = curl_easy_unescape(data, userp, 0, NULL);
if(!newname) {
result = CURLE_OUT_OF_MEMORY;
result = Curl_urldecode(data, userp, 0, &newname, NULL, FALSE);
if(result) {
goto out;
}
@@ -4952,9 +4914,9 @@ static CURLcode parse_url_login(struct Curl_easy *data,
if(passwdp) {
/* We have a password in the URL so decode it */
char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
if(!newpasswd) {
result = CURLE_OUT_OF_MEMORY;
char *newpasswd;
result = Curl_urldecode(data, passwdp, 0, &newpasswd, NULL, FALSE);
if(result) {
goto out;
}
@@ -4964,9 +4926,9 @@ static CURLcode parse_url_login(struct Curl_easy *data,
if(optionsp) {
/* We have an options list in the URL so decode it */
char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
if(!newoptions) {
result = CURLE_OUT_OF_MEMORY;
char *newoptions;
result = Curl_urldecode(data, optionsp, 0, &newoptions, NULL, FALSE);
if(result) {
goto out;
}
@@ -5457,7 +5419,8 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data,
if(!hostname_to_match)
return CURLE_OUT_OF_MEMORY;
hostname_to_match_len = strlen(hostname_to_match);
host_match = curl_strnequal(ptr, hostname_to_match, hostname_to_match_len);
host_match = strncasecompare(ptr, hostname_to_match,
hostname_to_match_len);
free(hostname_to_match);
ptr += hostname_to_match_len;
@@ -6021,18 +5984,18 @@ static CURLcode create_conn(struct Curl_easy *data,
/*************************************************************
* IDN-fix the hostnames
*************************************************************/
fix_hostname(data, conn, &conn->host);
fix_hostname(conn, &conn->host);
if(conn->bits.conn_to_host)
fix_hostname(data, conn, &conn->conn_to_host);
fix_hostname(conn, &conn->conn_to_host);
if(conn->proxy.name && *conn->proxy.name)
fix_hostname(data, conn, &conn->proxy);
fix_hostname(conn, &conn->proxy);
/*************************************************************
* Check whether the host and the "connect to host" are equal.
* Do this after the hostnames have been IDN-fixed .
*************************************************************/
if(conn->bits.conn_to_host &&
Curl_raw_equal(conn->conn_to_host.name, conn->host.name)) {
strcasecompare(conn->conn_to_host.name, conn->host.name)) {
conn->bits.conn_to_host = FALSE;
}
+14 -1
View File
@@ -330,6 +330,7 @@ struct ssl_connect_data {
CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
bool recv_sspi_close_notify; /* true if connection closed by close_notify */
bool recv_connection_closed; /* true if connection closed, regardless how */
bool use_alpn; /* true if ALPN is used for this connection */
#elif defined(USE_DARWINSSL)
SSLContextRef ssl_ctx;
curl_socket_t ssl_sockfd;
@@ -373,6 +374,7 @@ struct ssl_config_data {
struct curl_ssl_session {
char *name; /* host name for which this ID was used */
char *conn_to_host; /* host name for the connection (may be NULL) */
const char *scheme; /* protocol scheme used */
void *sessionid; /* as returned from the SSL layer */
size_t idsize; /* if known, otherwise 0 */
long age; /* just a number, the higher the more recent */
@@ -817,6 +819,7 @@ struct Curl_handler {
#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login credentials per
request instead of per connection */
#define PROTOPT_ALPN_NPN (1<<8) /* set ALPN and/or NPN for this */
#define PROTOPT_STREAM (1<<9) /* a protocol with individual logical streams */
/* return the count of bytes sent, or -1 on error */
typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
@@ -1102,9 +1105,10 @@ struct connectdata {
/*
* Struct to keep statistical and informational data.
* All variables in this struct must be reset in Curl_initinfo().
*/
struct PureInfo {
int httpcode; /* Recent HTTP, FTP, or RTSP response code */
int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */
int httpproxycode; /* response code from proxy when received separate */
int httpversion; /* the http version number X.Y = X*10+Y */
long filetime; /* If requested, this is might get set. Set to -1 if the time
@@ -1171,6 +1175,14 @@ struct Progress {
struct timeval t_startsingle;
struct timeval t_startop;
struct timeval t_acceptdata;
/* upload speed limit */
struct timeval ul_limit_start;
curl_off_t ul_limit_size;
/* download speed limit */
struct timeval dl_limit_start;
curl_off_t dl_limit_size;
#define CURR_TIME (5+1) /* 6 entries for 5 seconds */
curl_off_t speeder[ CURR_TIME ];
@@ -1600,6 +1612,7 @@ struct UserDefined {
bool ftp_use_port; /* use the FTP PORT command */
bool hide_progress; /* don't use the progress meter */
bool http_fail_on_error; /* fail on HTTP error codes >= 400 */
bool http_keep_sending_on_error; /* for HTTP status codes >= 300 */
bool http_follow_location; /* follow HTTP redirects */
bool http_transfer_encoding; /* request compressed HTTP transfer-encoding */
bool http_disable_hostname_check_before_authentication;
-2
View File
@@ -33,8 +33,6 @@
#include "curl_md5.h"
#include "warnless.h"
#include "strtok.h"
#include "strequal.h"
#include "rawstr.h"
#include "sendf.h"
#include "curl_printf.h"
+31 -17
View File
@@ -37,7 +37,7 @@
#include "vtls/vtls.h"
#include "warnless.h"
#include "strtok.h"
#include "rawstr.h"
#include "strcase.h"
#include "non-ascii.h" /* included for Curl_convert_... prototypes */
#include "curl_printf.h"
@@ -217,11 +217,11 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value)
token = strtok_r(tmp, ",", &tok_buf);
while(token != NULL) {
if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH))
if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH))
*value |= DIGEST_QOP_VALUE_AUTH;
else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_INT))
else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_INT))
*value |= DIGEST_QOP_VALUE_AUTH_INT;
else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_CONF))
else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_CONF))
*value |= DIGEST_QOP_VALUE_AUTH_CONF;
token = strtok_r(NULL, ",", &tok_buf);
@@ -305,6 +305,20 @@ static CURLcode auth_decode_digest_md5_message(const char *chlg64,
return CURLE_OK;
}
/*
* Curl_auth_is_digest_supported()
*
* This is used to evaluate if DIGEST is supported.
*
* Parameters: None
*
* Returns TRUE as DIGEST as handled by libcurl.
*/
bool Curl_auth_is_digest_supported(void)
{
return TRUE;
}
/*
* Curl_auth_create_digest_md5_message()
*
@@ -524,31 +538,31 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
/* Extract a value=content pair */
if(Curl_auth_digest_get_pair(chlg, value, content, &chlg)) {
if(Curl_raw_equal(value, "nonce")) {
if(strcasecompare(value, "nonce")) {
free(digest->nonce);
digest->nonce = strdup(content);
if(!digest->nonce)
return CURLE_OUT_OF_MEMORY;
}
else if(Curl_raw_equal(value, "stale")) {
if(Curl_raw_equal(content, "true")) {
else if(strcasecompare(value, "stale")) {
if(strcasecompare(content, "true")) {
digest->stale = TRUE;
digest->nc = 1; /* we make a new nonce now */
}
}
else if(Curl_raw_equal(value, "realm")) {
else if(strcasecompare(value, "realm")) {
free(digest->realm);
digest->realm = strdup(content);
if(!digest->realm)
return CURLE_OUT_OF_MEMORY;
}
else if(Curl_raw_equal(value, "opaque")) {
else if(strcasecompare(value, "opaque")) {
free(digest->opaque);
digest->opaque = strdup(content);
if(!digest->opaque)
return CURLE_OUT_OF_MEMORY;
}
else if(Curl_raw_equal(value, "qop")) {
else if(strcasecompare(value, "qop")) {
char *tok_buf;
/* Tokenize the list and choose auth if possible, use a temporary
clone of the buffer since strtok_r() ruins it */
@@ -558,10 +572,10 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
token = strtok_r(tmp, ",", &tok_buf);
while(token != NULL) {
if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH)) {
if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH)) {
foundAuth = TRUE;
}
else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_INT)) {
else if(strcasecompare(token, DIGEST_QOP_VALUE_STRING_AUTH_INT)) {
foundAuthInt = TRUE;
}
token = strtok_r(NULL, ",", &tok_buf);
@@ -583,15 +597,15 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
return CURLE_OUT_OF_MEMORY;
}
}
else if(Curl_raw_equal(value, "algorithm")) {
else if(strcasecompare(value, "algorithm")) {
free(digest->algorithm);
digest->algorithm = strdup(content);
if(!digest->algorithm)
return CURLE_OUT_OF_MEMORY;
if(Curl_raw_equal(content, "MD5-sess"))
if(strcasecompare(content, "MD5-sess"))
digest->algo = CURLDIGESTALGO_MD5SESS;
else if(Curl_raw_equal(content, "MD5"))
else if(strcasecompare(content, "MD5"))
digest->algo = CURLDIGESTALGO_MD5;
else
return CURLE_BAD_CONTENT_ENCODING;
@@ -730,7 +744,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
md5this = (unsigned char *) aprintf("%s:%s", request, uripath);
if(digest->qop && Curl_raw_equal(digest->qop, "auth-int")) {
if(digest->qop && strcasecompare(digest->qop, "auth-int")) {
/* We don't support auth-int for PUT or POST at the moment.
TODO: replace md5 of empty string with entity-body for PUT/POST */
unsigned char *md5this2 = (unsigned char *)
@@ -806,7 +820,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
digest->qop,
request_digest);
if(Curl_raw_equal(digest->qop, "auth"))
if(strcasecompare(digest->qop, "auth"))
digest->nc++; /* The nc (from RFC) has to be a 8 hex digit number 0
padded which tells to the server how many times you are
using the same nonce in the qop=auth mode */
+23 -2
View File
@@ -37,12 +37,33 @@
#include "curl_multibyte.h"
#include "sendf.h"
#include "strdup.h"
#include "rawstr.h"
#include "strcase.h"
/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"
/*
* Curl_auth_is_digest_supported()
*
* This is used to evaluate if DIGEST is supported.
*
* Parameters: None
*
* Returns TRUE if DIGEST is supported by Windows SSPI.
*/
bool Curl_auth_is_digest_supported(void)
{
PSecPkgInfo SecurityPackage;
SECURITY_STATUS status;
/* Query the security package for Digest */
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
&SecurityPackage);
return (status == SEC_E_OK ? TRUE : FALSE);
}
/*
* Curl_auth_create_digest_md5_message()
*
@@ -256,7 +277,7 @@ CURLcode Curl_override_sspi_http_realm(const char *chlg,
/* Extract a value=content pair */
if(Curl_auth_digest_get_pair(chlg, value, content, &chlg)) {
if(Curl_raw_equal(value, "realm")) {
if(strcasecompare(value, "realm")) {
/* Setup identity's domain and length */
domain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *) content);
+14
View File
@@ -41,6 +41,20 @@
#include "curl_memory.h"
#include "memdebug.h"
/*
* Curl_auth_is_gssapi_supported()
*
* This is used to evaluate if GSSAPI (Kerberos V5) is supported.
*
* Parameters: None
*
* Returns TRUE if Kerberos V5 is supported by the GSS-API library.
*/
bool Curl_auth_is_gssapi_supported(void)
{
return TRUE;
}
/*
* Curl_auth_create_gssapi_user_message()
*
+22
View File
@@ -39,6 +39,28 @@
#include "curl_memory.h"
#include "memdebug.h"
/*
* Curl_auth_is_gssapi_supported()
*
* This is used to evaluate if GSSAPI (Kerberos V5) is supported.
*
* Parameters: None
*
* Returns TRUE if Kerberos V5 is supported by Windows SSPI.
*/
bool Curl_auth_is_gssapi_supported(void)
{
PSecPkgInfo SecurityPackage;
SECURITY_STATUS status;
/* Query the security package for Kerberos */
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
TEXT(SP_NAME_KERBEROS),
&SecurityPackage);
return (status == SEC_E_OK ? TRUE : FALSE);
}
/*
* Curl_auth_create_gssapi_user_message()
*
+14
View File
@@ -216,6 +216,20 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
from the beginning of the NTLM message.
*/
/*
* Curl_auth_is_ntlm_supported()
*
* This is used to evaluate if NTLM is supported.
*
* Parameters: None
*
* Returns TRUE as NTLM as handled by libcurl.
*/
bool Curl_auth_is_ntlm_supported(void)
{
return TRUE;
}
/*
* Curl_auth_decode_ntlm_type2_message()
*
+21
View File
@@ -37,6 +37,27 @@
#include "curl_memory.h"
#include "memdebug.h"
/*
* Curl_auth_is_ntlm_supported()
*
* This is used to evaluate if NTLM is supported.
*
* Parameters: None
*
* Returns TRUE if NTLM is supported by Windows SSPI.
*/
bool Curl_auth_is_ntlm_supported(void)
{
PSecPkgInfo SecurityPackage;
SECURITY_STATUS status;
/* Query the security package for NTLM */
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM),
&SecurityPackage);
return (status == SEC_E_OK ? TRUE : FALSE);
}
/*
* Curl_auth_create_ntlm_type1_message()
*
@@ -40,6 +40,20 @@
#include "curl_memory.h"
#include "memdebug.h"
/*
* Curl_auth_is_spnego_supported()
*
* This is used to evaluate if SPNEGO (Negotiate) is supported.
*
* Parameters: None
*
* Returns TRUE if Negotiate supported by the GSS-API library.
*/
bool Curl_auth_is_spnego_supported(void)
{
return TRUE;
}
/*
* Curl_auth_decode_spnego_message()
*
+25 -1
View File
@@ -39,6 +39,28 @@
#include "curl_memory.h"
#include "memdebug.h"
/*
* Curl_auth_is_spnego_supported()
*
* This is used to evaluate if SPNEGO (Negotiate) is supported.
*
* Parameters: None
*
* Returns TRUE if Negotiate is supported by Windows SSPI.
*/
bool Curl_auth_is_spnego_supported(void)
{
PSecPkgInfo SecurityPackage;
SECURITY_STATUS status;
/* Query the security package for Negotiate */
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
TEXT(SP_NAME_NEGOTIATE),
&SecurityPackage);
return (status == SEC_E_OK ? TRUE : FALSE);
}
/*
* Curl_auth_decode_spnego_message()
*
@@ -249,8 +271,10 @@ CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data,
if(result)
return result;
if(!*outptr || !*outlen)
if(!*outptr || !*outlen) {
free(*outptr);
return CURLE_REMOTE_ACCESS_DENIED;
}
return CURLE_OK;
}
+41
View File
@@ -104,3 +104,44 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
}
#endif /* USE_WINDOWS_SSPI */
/*
* Curl_auth_user_contains_domain()
*
* This is used to test if the specified user contains a Windows domain name as
* follows:
*
* User\Domain (Down-level Logon Name)
* User/Domain (curl Down-level format - for compatibility with existing code)
* User@Domain (User Principal Name)
*
* Note: The user name may be empty when using a GSS-API library or Windows SSPI
* as the user and domain are either obtained from the credientals cache when
* using GSS-API or via the currently logged in user's credientals when using
* Windows SSPI.
*
* Parameters:
*
* user [in] - The user name.
*
* Returns TRUE on success; otherwise FALSE.
*/
bool Curl_auth_user_contains_domain(const char *user)
{
bool valid = FALSE;
if(user && *user) {
/* Check we have a domain name or UPN present */
char *p = strpbrk(user, "\\/@");
valid = (p != NULL && p > user && p < user + strlen(user) - 1 ? TRUE :
FALSE);
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
else
/* User and domain are obtained from the GSS-API credientials cache or the
currently logged in user from Windows */
valid = TRUE;
#endif
return valid;
}
+15
View File
@@ -55,6 +55,9 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
const char *realm);
#endif
/* This is used to test if the user contains a Windows domain name */
bool Curl_auth_user_contains_domain(const char *user);
/* This is used to generate a base64 encoded PLAIN cleartext message */
CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
const char *userp,
@@ -83,6 +86,9 @@ CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data,
const char *passwdp,
char **outptr, size_t *outlen);
/* This is used to evaluate if DIGEST is supported */
bool Curl_auth_is_digest_supported(void);
/* This is used to generate a base64 encoded DIGEST-MD5 response message */
CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
const char *chlg64,
@@ -109,6 +115,9 @@ void Curl_auth_digest_cleanup(struct digestdata *digest);
#endif /* !CURL_DISABLE_CRYPTO_AUTH */
#if defined(USE_NTLM)
/* This is used to evaluate if NTLM is supported */
bool Curl_auth_is_ntlm_supported(void);
/* This is used to generate a base64 encoded NTLM type-1 message */
CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
const char *passwdp,
@@ -140,6 +149,9 @@ CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data,
const char *bearer,
char **outptr, size_t *outlen);
#if defined(USE_KERBEROS5)
/* This is used to evaluate if GSSAPI (Kerberos V5) is supported */
bool Curl_auth_is_gssapi_supported(void);
/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) user token
message */
CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
@@ -165,6 +177,9 @@ void Curl_auth_gssapi_cleanup(struct kerberos5data *krb5);
#endif /* USE_KERBEROS5 */
#if defined(USE_SPNEGO)
/* This is used to evaluate if SPNEGO (Negotiate) is supported */
bool Curl_auth_is_spnego_supported(void);
/* This is used to decode a base64 encoded SPNEGO (Negotiate) challenge
message */
CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
+7 -7
View File
@@ -36,8 +36,8 @@
# include <ares.h>
#endif
#ifdef USE_LIBIDN
#include <stringprep.h>
#ifdef USE_LIBIDN2
#include <idn2.h>
#endif
#ifdef USE_LIBPSL
@@ -111,9 +111,9 @@ char *curl_version(void)
left -= len;
ptr += len;
#endif
#ifdef USE_LIBIDN
if(stringprep_check_version(LIBIDN_REQUIRED_VERSION)) {
len = snprintf(ptr, left, " libidn/%s", stringprep_check_version(NULL));
#ifdef USE_LIBIDN2
if(idn2_check_version(IDN2_VERSION)) {
len = snprintf(ptr, left, " libidn2/%s", idn2_check_version(NULL));
left -= len;
ptr += len;
}
@@ -365,10 +365,10 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
version_info.ares_num = aresnum;
}
#endif
#ifdef USE_LIBIDN
#ifdef USE_LIBIDN2
/* This returns a version string if we use the given version or later,
otherwise it returns NULL */
version_info.libidn = stringprep_check_version(LIBIDN_REQUIRED_VERSION);
version_info.libidn = idn2_check_version(IDN2_VERSION);
if(version_info.libidn)
version_info.features |= CURL_VERSION_IDN;
#elif defined(USE_WIN32_IDN)
+1 -2
View File
@@ -579,8 +579,7 @@ int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
*/
if(connssl->ssl) {
int what = Curl_socket_ready(conn->sock[sockindex],
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
int what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
if(what > 0) {
/* Something to read, let's do it and hope that it is the close
notify alert from the server. buf is managed internally by
+5 -4
View File
@@ -55,7 +55,7 @@ and that's a problem since options.h hasn't been included yet. */
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
#include "rawstr.h"
#include "strcase.h"
#include "x509asn1.h"
#include "curl_printf.h"
@@ -118,9 +118,9 @@ static int do_file_type(const char *type)
{
if(!type || !type[0])
return SSL_FILETYPE_PEM;
if(Curl_raw_equal(type, "PEM"))
if(strcasecompare(type, "PEM"))
return SSL_FILETYPE_PEM;
if(Curl_raw_equal(type, "DER"))
if(strcasecompare(type, "DER"))
return SSL_FILETYPE_ASN1;
return -1;
}
@@ -803,7 +803,8 @@ cyassl_connect_common(struct connectdata *conn,
curl_socket_t readfd = ssl_connect_2_reading==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking?0:timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+17 -7
View File
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2012 - 2014, Nick Zitzmann, <nickzman@gmail.com>.
* Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2012 - 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
@@ -920,7 +920,7 @@ static OSStatus CopyIdentityWithLabel(char *label,
#if CURL_SUPPORT_MAC_10_6
/* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */
status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
#endif /* CURL_SUPPORT_MAC_10_7 */
#endif /* CURL_SUPPORT_MAC_10_6 */
}
#elif CURL_SUPPORT_MAC_10_6
/* For developers building on older cats, we have no choice but to fall back
@@ -955,7 +955,7 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
/* Here we go: */
status = SecPKCS12Import(pkcs_data, options, &items);
if(status == noErr && items && CFArrayGetCount(items)) {
if(status == errSecSuccess && items && CFArrayGetCount(items)) {
CFDictionaryRef identity_and_trust = CFArrayGetValueAtIndex(items, 0L);
const void *temp_identity = CFDictionaryGetValue(identity_and_trust,
kSecImportItemIdentity);
@@ -1438,6 +1438,16 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
/* Disable IDEA: */
case SSL_RSA_WITH_IDEA_CBC_SHA:
case SSL_RSA_WITH_IDEA_CBC_MD5:
/* Disable RC4: */
case SSL_RSA_WITH_RC4_128_MD5:
case SSL_RSA_WITH_RC4_128_SHA:
case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */
case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/
case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */
case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */
case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */
case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */
break;
default: /* enable everything else */
allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
@@ -2140,7 +2150,8 @@ darwinssl_connect_common(struct connectdata *conn,
curl_socket_t readfd = ssl_connect_2_reading ==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking?0:timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -2262,8 +2273,7 @@ int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
rc = 0;
what = Curl_socket_ready(conn->sock[sockindex],
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
for(;;) {
if(what < 0) {
@@ -2291,7 +2301,7 @@ int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
if(nread <= 0)
break;
what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
what = SOCKET_READABLE(conn->sock[sockindex], 0);
}
return rc;
+5 -5
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
@@ -72,7 +72,7 @@
#include "vtls.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
#include "strequal.h"
#include "strcase.h"
#include "x509asn1.h"
#include "curl_printf.h"
@@ -1001,8 +1001,8 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
close_one(connssl, data);
rc = 0;
what = Curl_socket_ready(conn->sock[sockindex],
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
what = SOCKET_READABLE(conn->sock[sockindex],
SSL_SHUTDOWN_TIMEOUT);
for(;;) {
if(what < 0) {
@@ -1031,7 +1031,7 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
if(nread <= 0)
break;
what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
what = SOCKET_READABLE(conn->sock[sockindex], 0);
}
return rc;
+6 -6
View File
@@ -52,7 +52,7 @@
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
#include "rawstr.h"
#include "strcase.h"
#include "warnless.h"
#include "x509asn1.h"
#include "curl_printf.h"
@@ -289,7 +289,7 @@ static CURLcode handshake(struct connectdata *conn,
curl_socket_t readfd = ssl_connect_2_reading==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_ready(readfd, writefd,
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking?0:
timeout_ms?timeout_ms:1000);
if(what < 0) {
@@ -356,9 +356,9 @@ static gnutls_x509_crt_fmt_t do_file_type(const char *type)
{
if(!type || !type[0])
return GNUTLS_X509_FMT_PEM;
if(Curl_raw_equal(type, "PEM"))
if(strcasecompare(type, "PEM"))
return GNUTLS_X509_FMT_PEM;
if(Curl_raw_equal(type, "DER"))
if(strcasecompare(type, "DER"))
return GNUTLS_X509_FMT_DER;
return -1;
}
@@ -1445,8 +1445,8 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
if(conn->ssl[sockindex].session) {
while(!done) {
int what = Curl_socket_ready(conn->sock[sockindex],
CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
int what = SOCKET_READABLE(conn->sock[sockindex],
SSL_SHUTDOWN_TIMEOUT);
if(what > 0) {
/* Something to read, let's do it and hope that it is the close
notify alert from the server */
+11 -3
View File
@@ -31,7 +31,7 @@
#ifdef USE_MBEDTLS
#include <mbedtls/net.h>
#include <mbedtls/net_sockets.h>
#include <mbedtls/ssl.h>
#include <mbedtls/certs.h>
#include <mbedtls/x509.h>
@@ -50,7 +50,6 @@
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
#include "rawstr.h"
#include "polarssl_threadlock.h"
/* The last 3 #include files should be in this order */
@@ -420,7 +419,15 @@ mbed_connect_step1(struct connectdata *conn,
#endif
#ifdef MBEDTLS_DEBUG
/* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */
mbedtls_ssl_conf_dbg(&connssl->config, mbed_debug, data);
/* - 0 No debug
* - 1 Error
* - 2 State change
* - 3 Informational
* - 4 Verbose
*/
mbedtls_debug_set_threshold(4);
#endif
connssl->connecting_state = ssl_connect_2;
@@ -765,7 +772,8 @@ mbed_connect_common(struct connectdata *conn,
curl_socket_t readfd = ssl_connect_2_reading==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_ready(readfd, writefd, nonblocking ? 0 : timeout_ms);
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking ? 0 : timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
+52 -16
View File
@@ -34,7 +34,7 @@
#include "formdata.h" /* for the boundary function */
#include "url.h" /* for the ssl config check function */
#include "connect.h"
#include "strequal.h"
#include "strcase.h"
#include "select.h"
#include "vtls.h"
#include "llist.h"
@@ -64,7 +64,7 @@
#include <ocsp.h>
#endif
#include "rawstr.h"
#include "strcase.h"
#include "warnless.h"
#include "x509asn1.h"
@@ -78,13 +78,12 @@
#define SLOTSIZE 13
PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
PRLock * nss_initlock = NULL;
PRLock * nss_crllock = NULL;
struct curl_llist *nss_crl_list = NULL;
NSSInitContext * nss_context = NULL;
volatile int initialized = 0;
static PRLock *nss_initlock = NULL;
static PRLock *nss_crllock = NULL;
static PRLock *nss_findslot_lock = NULL;
static struct curl_llist *nss_crl_list = NULL;
static NSSInitContext *nss_context = NULL;
static volatile int initialized = 0;
typedef struct {
const char *name;
@@ -150,7 +149,7 @@ static const cipher_s cipherlist[] = {
{"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA},
{"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA},
{"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA},
{"echde_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA},
{"ecdhe_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA},
{"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
{"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA},
{"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
@@ -180,10 +179,29 @@ static const cipher_s cipherlist[] = {
{"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
{"ecdh_rsa_aes_128_gcm_sha_256", TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256},
#endif
#ifdef TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
/* cipher suites using SHA384 */
{"rsa_aes_256_gcm_sha_384", TLS_RSA_WITH_AES_256_GCM_SHA384},
{"dhe_rsa_aes_256_gcm_sha_384", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
{"dhe_dss_aes_256_gcm_sha_384", TLS_DHE_DSS_WITH_AES_256_GCM_SHA384},
{"ecdhe_ecdsa_aes_256_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
{"ecdhe_rsa_aes_256_sha_384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
{"ecdhe_ecdsa_aes_256_gcm_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
{"ecdhe_rsa_aes_256_gcm_sha_384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
#endif
#ifdef TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
/* chacha20-poly1305 cipher suites */
{"ecdhe_rsa_chacha20_poly1305_sha_256",
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
{"ecdhe_ecdsa_chacha20_poly1305_sha_256",
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
{"dhe_rsa_chacha20_poly1305_sha_256",
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
#endif
};
static const char* pem_library = "libnsspem.so";
SECMODModule* mod = NULL;
static SECMODModule* mod = NULL;
/* NSPR I/O layer we use to detect blocking direction during SSL handshake */
static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
@@ -243,7 +261,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model,
found = PR_FALSE;
for(i=0; i<NUM_OF_CIPHERS; i++) {
if(Curl_raw_equal(cipher, cipherlist[i].name)) {
if(strcasecompare(cipher, cipherlist[i].name)) {
cipher_state[i] = PR_TRUE;
found = PR_TRUE;
break;
@@ -340,6 +358,19 @@ static char* dup_nickname(struct Curl_easy *data, enum dupstring cert_kind)
return NULL;
}
/* Lock/unlock wrapper for PK11_FindSlotByName() to work around race condition
* in nssSlot_IsTokenPresent() causing spurious SEC_ERROR_NO_TOKEN. For more
* details, go to <https://bugzilla.mozilla.org/1297397>.
*/
static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
{
PK11SlotInfo *slot;
PR_Lock(nss_initlock);
slot = PK11_FindSlotByName(slot_name);
PR_Unlock(nss_initlock);
return slot;
}
/* Call PK11_CreateGenericObject() with the given obj_class and filename. If
* the call succeeds, append the object handle to the list of objects so that
* the object can be destroyed in Curl_nss_close(). */
@@ -362,7 +393,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
if(!slot_name)
return CURLE_OUT_OF_MEMORY;
slot = PK11_FindSlotByName(slot_name);
slot = nss_find_slot_by_name(slot_name);
free(slot_name);
if(!slot)
return result;
@@ -563,7 +594,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
return result;
}
slot = PK11_FindSlotByName("PEM Token #1");
slot = nss_find_slot_by_name("PEM Token #1");
if(!slot)
return CURLE_SSL_CERTPROBLEM;
@@ -1013,7 +1044,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
struct CERTCertificateStr *cert;
struct SECKEYPrivateKeyStr *key;
PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname);
PK11SlotInfo *slot = nss_find_slot_by_name(pem_slotname);
if(NULL == slot) {
failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
return SECFailure;
@@ -1249,6 +1280,7 @@ int Curl_nss_init(void)
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
nss_initlock = PR_NewLock();
nss_crllock = PR_NewLock();
nss_findslot_lock = PR_NewLock();
}
/* We will actually initialize NSS later */
@@ -1303,6 +1335,7 @@ void Curl_nss_cleanup(void)
PR_DestroyLock(nss_initlock);
PR_DestroyLock(nss_crllock);
PR_DestroyLock(nss_findslot_lock);
nss_initlock = NULL;
initialized = 0;
@@ -1888,8 +1921,11 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex,
const bool blocking = (done == NULL);
CURLcode result;
if(connssl->state == ssl_connection_complete)
if(connssl->state == ssl_connection_complete) {
if(!blocking)
*done = TRUE;
return CURLE_OK;
}
if(connssl->connecting_state == ssl_connect_1) {
result = nss_setup_connect(conn, sockindex);

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