Merge topic 'update-curl'

8443dfa946 curl: Work around missing OpenSSL symbol on machine with LCC 1.23
f9f5957884 Merge branch 'upstream-curl' into update-curl
dac458ddbf curl 2022-12-21 (c12fb3dd)
39dcf9469d curl: Update script to get curl 7.87.0
b2fe717a49 file: Avoid using deprecated curl progress callback
1cd38de47f ctest: Drop unnecessary use of deprecated CURLOPT_PUT

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !8131
This commit is contained in:
Brad King
2023-01-31 14:13:15 +00:00
committed by Kitware Robot
146 changed files with 8352 additions and 6124 deletions
-2
View File
@@ -118,8 +118,6 @@ bool cmCTestCurl::UploadFile(std::string const& local_file,
/* enable uploading */
curl_easy_setopt(this->Curl, CURLOPT_UPLOAD, 1);
/* HTTP PUT please */
::curl_easy_setopt(this->Curl, CURLOPT_PUT, 1);
::curl_easy_setopt(this->Curl, CURLOPT_VERBOSE, 1);
FILE* ftpfile = cmsys::SystemTools::Fopen(local_file, "rb");
-2
View File
@@ -223,8 +223,6 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(
submitInactivityTimeout);
}
/* HTTP PUT please */
::curl_easy_setopt(curl, CURLOPT_PUT, 1);
::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
+21 -9
View File
@@ -1629,6 +1629,14 @@ int cmFileCommandCurlDebugCallback(CURL*, curl_infotype type, char* chPtr,
return 0;
}
# if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM >= 0x072000
const CURLoption CM_CURLOPT_XFERINFOFUNCTION = CURLOPT_XFERINFOFUNCTION;
using cm_curl_off_t = curl_off_t;
# else
const CURLoption CM_CURLOPT_XFERINFOFUNCTION = CURLOPT_PROGRESSFUNCTION;
using cm_curl_off_t = double;
# endif
class cURLProgressHelper
{
public:
@@ -1638,12 +1646,14 @@ public:
{
}
bool UpdatePercentage(double value, double total, std::string& status)
bool UpdatePercentage(cm_curl_off_t value, cm_curl_off_t total,
std::string& status)
{
long OldPercentage = this->CurrentPercentage;
if (total > 0.0) {
this->CurrentPercentage = std::lround(value / total * 100.0);
if (total > 0) {
this->CurrentPercentage = std::lround(
static_cast<double>(value) / static_cast<double>(total) * 100.0);
if (this->CurrentPercentage > 100) {
// Avoid extra progress reports for unexpected data beyond total.
this->CurrentPercentage = 100;
@@ -1668,8 +1678,9 @@ private:
std::string Text;
};
int cmFileDownloadProgressCallback(void* clientp, double dltotal, double dlnow,
double ultotal, double ulnow)
int cmFileDownloadProgressCallback(void* clientp, cm_curl_off_t dltotal,
cm_curl_off_t dlnow, cm_curl_off_t ultotal,
cm_curl_off_t ulnow)
{
cURLProgressHelper* helper = reinterpret_cast<cURLProgressHelper*>(clientp);
@@ -1685,8 +1696,9 @@ int cmFileDownloadProgressCallback(void* clientp, double dltotal, double dlnow,
return 0;
}
int cmFileUploadProgressCallback(void* clientp, double dltotal, double dlnow,
double ultotal, double ulnow)
int cmFileUploadProgressCallback(void* clientp, cm_curl_off_t dltotal,
cm_curl_off_t dlnow, cm_curl_off_t ultotal,
cm_curl_off_t ulnow)
{
cURLProgressHelper* helper = reinterpret_cast<cURLProgressHelper*>(clientp);
@@ -2062,7 +2074,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
res = ::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
check_curl_result(res, "DOWNLOAD cannot set noprogress value: ");
res = ::curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION,
res = ::curl_easy_setopt(curl, CM_CURLOPT_XFERINFOFUNCTION,
cmFileDownloadProgressCallback);
check_curl_result(res, "DOWNLOAD cannot set progress function: ");
@@ -2376,7 +2388,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args,
res = ::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
check_curl_result(res, "UPLOAD cannot set noprogress value: ");
res = ::curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION,
res = ::curl_easy_setopt(curl, CM_CURLOPT_XFERINFOFUNCTION,
cmFileUploadProgressCallback);
check_curl_result(res, "UPLOAD cannot set progress function: ");
+1
View File
@@ -101,6 +101,7 @@
# Wrappers for 3rd-party libraries
{ include: [ "@<.*curl/curlver.h>", private, "<cm3p/curl/curl.h>", public ] },
{ include: [ "@<.*curl/system.h>", private, "<cm3p/curl/curl.h>", public ] },
{ include: [ "@<.*json/config.h>", private, "<cm3p/json/value.h>", public ] },
{ include: [ "@<.*json/forwards.h>", private, "<cm3p/json/value.h>", public ] },
{ include: [ "@<.*uv/.+\\.h>", private, "<cm3p/uv.h>", public ] },
+1 -1
View File
@@ -8,7 +8,7 @@ readonly name="curl"
readonly ownership="Curl Upstream <curl-library@lists.haxx.se>"
readonly subtree="Utilities/cmcurl"
readonly repo="https://github.com/curl/curl.git"
readonly tag="curl-7_86_0"
readonly tag="curl-7_87_0"
readonly shortlog=false
readonly paths="
CMake/*
+40 -40
View File
@@ -85,51 +85,51 @@ endif()
unset(CMAKE_TRY_COMPILE_TARGET_TYPE)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(NOT CMAKE_CROSSCOMPILING)
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "iOS")
# only try this on non-apple platforms
# only try this on non-apple platforms
# if not cross-compilation...
include(CheckCSourceRuns)
set(CMAKE_REQUIRED_FLAGS "")
if(HAVE_SYS_POLL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
elseif(HAVE_POLL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_POLL_H")
endif()
check_c_source_runs("
#include <stdlib.h>
#include <sys/time.h>
# if not cross-compilation...
include(CheckCSourceRuns)
set(CMAKE_REQUIRED_FLAGS "")
if(HAVE_SYS_POLL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
elseif(HAVE_POLL_H)
set(CMAKE_REQUIRED_FLAGS "-DHAVE_POLL_H")
endif()
check_c_source_runs("
#include <stdlib.h>
#include <sys/time.h>
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
#elif HAVE_POLL_H
# include <poll.h>
#endif
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
#elif HAVE_POLL_H
# include <poll.h>
#endif
int main(void)
{
if(0 != poll(0, 0, 10)) {
return 1; /* fail */
}
else {
/* detect the 10.12 poll() breakage */
struct timeval before, after;
int rc;
size_t us;
gettimeofday(&before, NULL);
rc = poll(NULL, 0, 500);
gettimeofday(&after, NULL);
us = (after.tv_sec - before.tv_sec) * 1000000 +
(after.tv_usec - before.tv_usec);
if(us < 400000) {
return 1;
int main(void)
{
if(0 != poll(0, 0, 10)) {
return 1; /* fail */
}
}
return 0;
else {
/* detect the 10.12 poll() breakage */
struct timeval before, after;
int rc;
size_t us;
gettimeofday(&before, NULL);
rc = poll(NULL, 0, 500);
gettimeofday(&after, NULL);
us = (after.tv_sec - before.tv_sec) * 1000000 +
(after.tv_usec - before.tv_usec);
if(us < 400000) {
return 1;
}
}
return 0;
}" HAVE_POLL_FINE)
endif()
endif()
@@ -34,7 +34,6 @@ if(NOT UNIX)
set(HAVE_NETDB_H 0)
set(HAVE_NETINET_IN_H 0)
set(HAVE_NET_IF_H 0)
set(HAVE_PROCESS_H 1)
set(HAVE_PWD_H 0)
set(HAVE_SETJMP_H 1)
set(HAVE_SIGNAL_H 1)
@@ -71,7 +70,6 @@ if(NOT UNIX)
set(HAVE_UTIME 1)
set(HAVE_RAND_EGD 0)
set(HAVE_GMTIME_R 0)
set(HAVE_GETADDRINFO_THREADSAFE 1)
set(HAVE_GETHOSTBYNAME_R 0)
set(HAVE_SIGNAL 1)
+8 -8
View File
@@ -275,7 +275,7 @@ 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)
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
if(PICKY_COMPILER)
foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wfloat-equal -Wsign-compare -Wundef -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wvla -Wdouble-promotion -Wenum-conversion -Warith-conversion)
# surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
@@ -867,7 +867,6 @@ if(WIN32)
option(USE_WIN32_IDN "Use WinIDN for IDN support" OFF)
if(USE_WIN32_IDN)
list(APPEND CURL_LIBS "normaliz")
set(WANT_IDN_PROTOTYPES ON)
endif()
endif()
@@ -1016,6 +1015,7 @@ if(CURL_USE_GSSAPI)
include_directories(${GSS_INCLUDE_DIR})
link_directories(${GSS_LINK_DIRECTORIES})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_FLAGS}")
string(REPLACE ";" " " GSS_LINKER_FLAGS "${GSS_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
@@ -1146,8 +1146,6 @@ check_include_file_concat("sys/utime.h" HAVE_SYS_UTIME_H)
check_include_file_concat("sys/xattr.h" HAVE_SYS_XATTR_H)
check_include_file_concat("arpa/inet.h" HAVE_ARPA_INET_H)
check_include_file_concat("arpa/tftp.h" HAVE_ARPA_TFTP_H)
check_include_file_concat("assert.h" HAVE_ASSERT_H)
check_include_file_concat("errno.h" HAVE_ERRNO_H)
check_include_file_concat("fcntl.h" HAVE_FCNTL_H)
check_include_file_concat("idn2.h" HAVE_IDN2_H)
check_include_file_concat("ifaddrs.h" HAVE_IFADDRS_H)
@@ -1178,7 +1176,6 @@ check_include_file_concat("time.h" HAVE_TIME_H)
check_include_file_concat("unistd.h" HAVE_UNISTD_H)
check_include_file_concat("utime.h" HAVE_UTIME_H)
check_include_file_concat("process.h" HAVE_PROCESS_H)
check_include_file_concat("stddef.h" HAVE_STDDEF_H)
check_include_file_concat("stdint.h" HAVE_STDINT_H)
check_include_file_concat("sys/utsname.h" HAVE_SYS_UTSNAME_H)
@@ -1235,8 +1232,8 @@ check_symbol_exists(_strtoi64 "${CURL_INCLUDES}" HAVE__STRTOI64)
check_symbol_exists(strerror_r "${CURL_INCLUDES}" HAVE_STRERROR_R)
check_symbol_exists(siginterrupt "${CURL_INCLUDES}" HAVE_SIGINTERRUPT)
check_symbol_exists(getaddrinfo "${CURL_INCLUDES}" HAVE_GETADDRINFO)
if(NOT HAVE_GETADDRINFO)
set(HAVE_GETADDRINFO_THREADSAFE OFF)
if(WIN32)
set(HAVE_GETADDRINFO_THREADSAFE ${HAVE_GETADDRINFO})
endif()
check_symbol_exists(freeaddrinfo "${CURL_INCLUDES}" HAVE_FREEADDRINFO)
check_symbol_exists(pipe "${CURL_INCLUDES}" HAVE_PIPE)
@@ -1638,7 +1635,10 @@ _add_if("TLS-SRP" USE_TLS_SRP)
_add_if("HTTP2" USE_NGHTTP2)
_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE)
_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS OR USE_NSS))
# TODO wolfSSL only support this from v5.0.0 onwards
_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS OR USE_NSS
OR USE_SCHANNEL OR USE_RUSTLS OR USE_BEARSSL OR
USE_MBEDTLS OR USE_SECTRANSP))
_add_if("unicode" ENABLE_UNICODE)
_add_if("threadsafe" HAVE_ATOMIC OR (WIN32 AND
HAVE_WIN32_WINNT GREATER_EQUAL 0x600))
+154 -80
View File
@@ -33,6 +33,22 @@
#define CURL_STRICTER
#endif
/* Compile-time deprecation macros. */
#if defined(__GNUC__) && (__GNUC__ >= 6) && \
!defined(__INTEL_COMPILER) && \
!defined(CURL_DISABLE_DEPRECATION) && !defined(BUILDING_LIBCURL)
#define CURL_DEPRECATED(version, message) \
__attribute__((deprecated("since " # version ". " message)))
#define CURL_IGNORE_DEPRECATION(statements) \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \
statements \
_Pragma("GCC diagnostic pop")
#else
#define CURL_DEPRECATED(version, message)
#define CURL_IGNORE_DEPRECATION(statements) statements
#endif
#include "curlver.h" /* libcurl version defines */
#include "system.h" /* determine things run-time */
@@ -76,7 +92,7 @@
defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \
(defined(__MidnightBSD_version) && (__MidnightBSD_version < 100000)) || \
defined(__sun__)
defined(__sun__) || defined(__serenity__)
#include <sys/select.h>
#endif
@@ -145,11 +161,11 @@ typedef enum {
CURLSSLBACKEND_NSS = 3,
CURLSSLBACKEND_OBSOLETE4 = 4, /* Was QSOSSL. */
CURLSSLBACKEND_GSKIT = 5,
CURLSSLBACKEND_POLARSSL = 6,
CURLSSLBACKEND_POLARSSL CURL_DEPRECATED(7.69.0, "") = 6,
CURLSSLBACKEND_WOLFSSL = 7,
CURLSSLBACKEND_SCHANNEL = 8,
CURLSSLBACKEND_SECURETRANSPORT = 9,
CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */
CURLSSLBACKEND_AXTLS CURL_DEPRECATED(7.61.0, "") = 10,
CURLSSLBACKEND_MBEDTLS = 11,
CURLSSLBACKEND_MESALINK = 12,
CURLSSLBACKEND_BEARSSL = 13,
@@ -256,6 +272,10 @@ typedef int (*curl_xferinfo_callback)(void *clientp,
will signal libcurl to pause receiving on the current transfer. */
#define CURL_WRITEFUNC_PAUSE 0x10000001
/* This is a magic return code for the write callback that, when returned,
will signal an error from the callback. */
#define CURL_WRITEFUNC_ERROR 0xFFFFFFFF
typedef size_t (*curl_write_callback)(char *buffer,
size_t size,
size_t nitems,
@@ -368,7 +388,7 @@ typedef int (*curl_seek_callback)(void *instream,
#define CURL_READFUNC_PAUSE 0x10000001
/* Return code for when the trailing headers' callback has terminated
without any errors*/
without any errors */
#define CURL_TRAILERFUNC_OK 0
/* Return code for when was an error in the trailing header's list and we
want to abort the request */
@@ -450,7 +470,7 @@ typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size);
#define CURL_DID_MEMORY_FUNC_TYPEDEFS
#endif
/* the kind of data that is passed to information_callback*/
/* the kind of data that is passed to information_callback */
typedef enum {
CURLINFO_TEXT = 0,
CURLINFO_HEADER_IN, /* 1 */
@@ -698,7 +718,7 @@ typedef enum {
#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40
#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72
#endif /*!CURL_NO_OLDIES*/
#endif /* !CURL_NO_OLDIES */
/*
* Proxy error codes. Returned in CURLINFO_PROXY_ERROR if CURLE_PROXY was
@@ -843,7 +863,7 @@ enum curl_khstat {
CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now.
Causes a CURLE_PEER_FAILED_VERIFICATION error but the
connection will be left intact etc */
CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key*/
CURLKHSTAT_FINE_REPLACE, /* accept and replace the wrong key */
CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */
};
@@ -864,13 +884,13 @@ typedef int
/* CURLOPT_SSH_KEYDATA */
typedef int
(*curl_sshhostkeycallback) (void *clientp,/* custom pointer passed*/
(*curl_sshhostkeycallback) (void *clientp,/* custom pointer passed */
/* with CURLOPT_SSH_HOSTKEYDATA */
int keytype, /* CURLKHTYPE */
const char *key, /*hostkey to check*/
size_t keylen); /*length of the key*/
/*return CURLE_OK to accept*/
/*or something else to refuse*/
const char *key, /* hostkey to check */
size_t keylen); /* length of the key */
/* return CURLE_OK to accept */
/* or something else to refuse */
/* parameter for the CURLOPT_USE_SSL option */
@@ -932,7 +952,7 @@ typedef enum {
#define CURLFTPSSL_ALL CURLUSESSL_ALL
#define CURLFTPSSL_LAST CURLUSESSL_LAST
#define curl_ftpssl curl_usessl
#endif /*!CURL_NO_OLDIES*/
#endif /* !CURL_NO_OLDIES */
/* parameter for the CURLOPT_FTP_SSL_CCC option */
typedef enum {
@@ -1058,6 +1078,7 @@ typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy,
#define CURLOPT(na,t,nu) na = t + nu
#define CURLOPTDEPRECATED(na,t,nu,v,m) na CURL_DEPRECATED(v,m) = t + nu
/* CURLOPT aliases that make no run-time difference */
@@ -1119,7 +1140,7 @@ typedef enum {
/* Time-out the read operation after this amount of seconds */
CURLOPT(CURLOPT_TIMEOUT, CURLOPTTYPE_LONG, 13),
/* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
/* If CURLOPT_READDATA is used, this can be used to inform libcurl about
* how large the file being sent really is. That allows better error
* checking and better verifies that the upload was successful. -1 means
* unknown size.
@@ -1171,7 +1192,8 @@ typedef enum {
CURLOPT(CURLOPT_HTTPHEADER, CURLOPTTYPE_SLISTPOINT, 23),
/* This points to a linked list of post entries, struct curl_httppost */
CURLOPT(CURLOPT_HTTPPOST, CURLOPTTYPE_OBJECTPOINT, 24),
CURLOPTDEPRECATED(CURLOPT_HTTPPOST, CURLOPTTYPE_OBJECTPOINT, 24,
7.56.0, "Use CURLOPT_MIMEPOST"),
/* name of the file keeping your private SSL-certificate */
CURLOPT(CURLOPT_SSLCERT, CURLOPTTYPE_STRINGPOINT, 25),
@@ -1261,7 +1283,8 @@ typedef enum {
CURLOPT(CURLOPT_TRANSFERTEXT, CURLOPTTYPE_LONG, 53),
/* HTTP PUT */
CURLOPT(CURLOPT_PUT, CURLOPTTYPE_LONG, 54),
CURLOPTDEPRECATED(CURLOPT_PUT, CURLOPTTYPE_LONG, 54,
7.12.1, "Use CURLOPT_UPLOAD"),
/* 55 = OBSOLETE */
@@ -1269,7 +1292,8 @@ typedef enum {
* Function that will be called instead of the internal progress display
* function. This function should be defined as the curl_progress_callback
* prototype defines. */
CURLOPT(CURLOPT_PROGRESSFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 56),
CURLOPTDEPRECATED(CURLOPT_PROGRESSFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 56,
7.32.0, "Use CURLOPT_XFERINFOFUNCTION"),
/* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
callbacks */
@@ -1286,7 +1310,7 @@ typedef enum {
/* size of the POST input data, if strlen() is not good to use */
CURLOPT(CURLOPT_POSTFIELDSIZE, CURLOPTTYPE_LONG, 60),
/* tunnel non-http operations through a HTTP proxy */
/* tunnel non-http operations through an HTTP proxy */
CURLOPT(CURLOPT_HTTPPROXYTUNNEL, CURLOPTTYPE_LONG, 61),
/* Set the interface string to use as outgoing network interface */
@@ -1337,10 +1361,12 @@ typedef enum {
/* Set to a file name that contains random data for libcurl to use to
seed the random engine when doing SSL connects. */
CURLOPT(CURLOPT_RANDOM_FILE, CURLOPTTYPE_STRINGPOINT, 76),
CURLOPTDEPRECATED(CURLOPT_RANDOM_FILE, CURLOPTTYPE_STRINGPOINT, 76,
7.84.0, "Serves no purpose anymore"),
/* Set to the Entropy Gathering Daemon socket pathname */
CURLOPT(CURLOPT_EGDSOCKET, CURLOPTTYPE_STRINGPOINT, 77),
CURLOPTDEPRECATED(CURLOPT_EGDSOCKET, CURLOPTTYPE_STRINGPOINT, 77,
7.84.0, "Serves no purpose anymore"),
/* Time-out connect operations after this amount of seconds, if connects are
OK within this time, then fine... This only aborts the connect phase. */
@@ -1395,7 +1421,8 @@ typedef enum {
/* Non-zero value means to use the global dns cache */
/* DEPRECATED, do not use! */
CURLOPT(CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOPTTYPE_LONG, 91),
CURLOPTDEPRECATED(CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOPTTYPE_LONG, 91,
7.11.1, "Use CURLOPT_SHARE"),
/* DNS cache timeout */
CURLOPT(CURLOPT_DNS_CACHE_TIMEOUT, CURLOPTTYPE_LONG, 92),
@@ -1550,8 +1577,10 @@ typedef enum {
*/
CURLOPT(CURLOPT_FTPSSLAUTH, CURLOPTTYPE_VALUES, 129),
CURLOPT(CURLOPT_IOCTLFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 130),
CURLOPT(CURLOPT_IOCTLDATA, CURLOPTTYPE_CBPOINT, 131),
CURLOPTDEPRECATED(CURLOPT_IOCTLFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 130,
7.18.0, "Use CURLOPT_SEEKFUNCTION"),
CURLOPTDEPRECATED(CURLOPT_IOCTLDATA, CURLOPTTYPE_CBPOINT, 131,
7.18.0, "Use CURLOPT_SEEKDATA"),
/* 132 OBSOLETE. Gone in 7.16.0 */
/* 133 OBSOLETE. Gone in 7.16.0 */
@@ -1590,16 +1619,22 @@ typedef enum {
/* Function that will be called to convert from the
network encoding (instead of using the iconv calls in libcurl) */
CURLOPT(CURLOPT_CONV_FROM_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 142),
CURLOPTDEPRECATED(CURLOPT_CONV_FROM_NETWORK_FUNCTION,
CURLOPTTYPE_FUNCTIONPOINT, 142,
7.82.0, "Serves no purpose anymore"),
/* Function that will be called to convert to the
network encoding (instead of using the iconv calls in libcurl) */
CURLOPT(CURLOPT_CONV_TO_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 143),
CURLOPTDEPRECATED(CURLOPT_CONV_TO_NETWORK_FUNCTION,
CURLOPTTYPE_FUNCTIONPOINT, 143,
7.82.0, "Serves no purpose anymore"),
/* Function that will be called to convert from UTF8
(instead of using the iconv calls in libcurl)
Note that this is used only for SSL certificate processing */
CURLOPT(CURLOPT_CONV_FROM_UTF8_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 144),
CURLOPTDEPRECATED(CURLOPT_CONV_FROM_UTF8_FUNCTION,
CURLOPTTYPE_FUNCTIONPOINT, 144,
7.82.0, "Serves no purpose anymore"),
/* if the connection proceeds too quickly then need to slow it down */
/* limit-rate: maximum number of bytes per second to send or receive */
@@ -1700,7 +1735,9 @@ typedef enum {
/* Socks Service */
/* DEPRECATED, do not use! */
CURLOPT(CURLOPT_SOCKS5_GSSAPI_SERVICE, CURLOPTTYPE_STRINGPOINT, 179),
CURLOPTDEPRECATED(CURLOPT_SOCKS5_GSSAPI_SERVICE,
CURLOPTTYPE_STRINGPOINT, 179,
7.49.0, "Use CURLOPT_PROXY_SERVICE_NAME"),
/* Socks Service */
CURLOPT(CURLOPT_SOCKS5_GSSAPI_NEC, CURLOPTTYPE_LONG, 180),
@@ -1709,12 +1746,14 @@ typedef enum {
transfer, which thus helps the app which takes URLs from users or other
external inputs and want to restrict what protocol(s) to deal
with. Defaults to CURLPROTO_ALL. */
CURLOPT(CURLOPT_PROTOCOLS, CURLOPTTYPE_LONG, 181),
CURLOPTDEPRECATED(CURLOPT_PROTOCOLS, CURLOPTTYPE_LONG, 181,
7.85.0, "Use CURLOPT_PROTOCOLS_STR"),
/* set the bitmask for the protocols that libcurl is allowed to follow to,
as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
to be set in both bitmasks to be allowed to get redirected to. */
CURLOPT(CURLOPT_REDIR_PROTOCOLS, CURLOPTTYPE_LONG, 182),
CURLOPTDEPRECATED(CURLOPT_REDIR_PROTOCOLS, CURLOPTTYPE_LONG, 182,
7.85.0, "Use CURLOPT_REDIR_PROTOCOLS_STR"),
/* set the SSH knownhost file name to use */
CURLOPT(CURLOPT_SSH_KNOWNHOSTS, CURLOPTTYPE_STRINGPOINT, 183),
@@ -1859,12 +1898,13 @@ typedef enum {
CURLOPT(CURLOPT_LOGIN_OPTIONS, CURLOPTTYPE_STRINGPOINT, 224),
/* Enable/disable TLS NPN extension (http2 over ssl might fail without) */
CURLOPT(CURLOPT_SSL_ENABLE_NPN, CURLOPTTYPE_LONG, 225),
CURLOPTDEPRECATED(CURLOPT_SSL_ENABLE_NPN, CURLOPTTYPE_LONG, 225,
7.86.0, "Has no function"),
/* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */
CURLOPT(CURLOPT_SSL_ENABLE_ALPN, CURLOPTTYPE_LONG, 226),
/* Time to wait for a response to a HTTP request containing an
/* Time to wait for a response to an HTTP request containing an
* Expect: 100-continue header before sending the data anyway. */
CURLOPT(CURLOPT_EXPECT_100_TIMEOUT_MS, CURLOPTTYPE_LONG, 227),
@@ -2157,6 +2197,12 @@ typedef enum {
/* websockets options */
CURLOPT(CURLOPT_WS_OPTIONS, CURLOPTTYPE_LONG, 320),
/* CA cache timeout */
CURLOPT(CURLOPT_CA_CACHE_TIMEOUT, CURLOPTTYPE_LONG, 321),
/* Can leak things, gonna exit() soon */
CURLOPT(CURLOPT_QUICK_EXIT, CURLOPTTYPE_LONG, 322),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -2444,30 +2490,32 @@ CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part,
int take_ownership);
typedef enum {
CURLFORM_NOTHING, /********* the first one is unused ************/
CURLFORM_COPYNAME,
CURLFORM_PTRNAME,
CURLFORM_NAMELENGTH,
CURLFORM_COPYCONTENTS,
CURLFORM_PTRCONTENTS,
CURLFORM_CONTENTSLENGTH,
CURLFORM_FILECONTENT,
CURLFORM_ARRAY,
/********* the first one is unused ************/
CURLFORM_NOTHING CURL_DEPRECATED(7.56.0, ""),
CURLFORM_COPYNAME CURL_DEPRECATED(7.56.0, "Use curl_mime_name()"),
CURLFORM_PTRNAME CURL_DEPRECATED(7.56.0, "Use curl_mime_name()"),
CURLFORM_NAMELENGTH CURL_DEPRECATED(7.56.0, ""),
CURLFORM_COPYCONTENTS CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"),
CURLFORM_PTRCONTENTS CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"),
CURLFORM_CONTENTSLENGTH CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"),
CURLFORM_FILECONTENT CURL_DEPRECATED(7.56.0, "Use curl_mime_data_cb()"),
CURLFORM_ARRAY CURL_DEPRECATED(7.56.0, ""),
CURLFORM_OBSOLETE,
CURLFORM_FILE,
CURLFORM_FILE CURL_DEPRECATED(7.56.0, "Use curl_mime_filedata()"),
CURLFORM_BUFFER,
CURLFORM_BUFFERPTR,
CURLFORM_BUFFERLENGTH,
CURLFORM_BUFFER CURL_DEPRECATED(7.56.0, "Use curl_mime_filename()"),
CURLFORM_BUFFERPTR CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"),
CURLFORM_BUFFERLENGTH CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"),
CURLFORM_CONTENTTYPE,
CURLFORM_CONTENTHEADER,
CURLFORM_FILENAME,
CURLFORM_CONTENTTYPE CURL_DEPRECATED(7.56.0, "Use curl_mime_type()"),
CURLFORM_CONTENTHEADER CURL_DEPRECATED(7.56.0, "Use curl_mime_headers()"),
CURLFORM_FILENAME CURL_DEPRECATED(7.56.0, "Use curl_mime_filename()"),
CURLFORM_END,
CURLFORM_OBSOLETE2,
CURLFORM_STREAM,
CURLFORM_CONTENTLEN, /* added in 7.46.0, provide a curl_off_t length */
CURLFORM_STREAM CURL_DEPRECATED(7.56.0, "Use curl_mime_data_cb()"),
CURLFORM_CONTENTLEN /* added in 7.46.0, provide a curl_off_t length */
CURL_DEPRECATED(7.56.0, "Use curl_mime_data()"),
CURLFORM_LASTENTRY /* the last unused */
} CURLformoption;
@@ -2495,15 +2543,16 @@ struct curl_forms {
*
***************************************************************************/
typedef enum {
CURL_FORMADD_OK, /* first, no error */
CURL_FORMADD_OK CURL_DEPRECATED(7.56.0, ""), /* 1st, no error */
CURL_FORMADD_MEMORY,
CURL_FORMADD_OPTION_TWICE,
CURL_FORMADD_NULL,
CURL_FORMADD_UNKNOWN_OPTION,
CURL_FORMADD_INCOMPLETE,
CURL_FORMADD_ILLEGAL_ARRAY,
CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */
CURL_FORMADD_MEMORY CURL_DEPRECATED(7.56.0, ""),
CURL_FORMADD_OPTION_TWICE CURL_DEPRECATED(7.56.0, ""),
CURL_FORMADD_NULL CURL_DEPRECATED(7.56.0, ""),
CURL_FORMADD_UNKNOWN_OPTION CURL_DEPRECATED(7.56.0, ""),
CURL_FORMADD_INCOMPLETE CURL_DEPRECATED(7.56.0, ""),
CURL_FORMADD_ILLEGAL_ARRAY CURL_DEPRECATED(7.56.0, ""),
/* libcurl was built with form api disabled */
CURL_FORMADD_DISABLED CURL_DEPRECATED(7.56.0, ""),
CURL_FORMADD_LAST /* last */
} CURLFORMcode;
@@ -2517,9 +2566,10 @@ typedef enum {
* adds one part that together construct a full post. Then use
* CURLOPT_HTTPPOST to send it off to libcurl.
*/
CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
struct curl_httppost **last_post,
...);
CURL_EXTERN CURLFORMcode CURL_DEPRECATED(7.56.0, "Use curl_mime_init()")
curl_formadd(struct curl_httppost **httppost,
struct curl_httppost **last_post,
...);
/*
* callback function for curl_formget()
@@ -2542,8 +2592,9 @@ typedef size_t (*curl_formget_callback)(void *arg, const char *buf,
* the curl_formget_callback function.
* Returns 0 on success.
*/
CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
curl_formget_callback append);
CURL_EXTERN int CURL_DEPRECATED(7.56.0, "")
curl_formget(struct curl_httppost *form, void *arg,
curl_formget_callback append);
/*
* NAME curl_formfree()
*
@@ -2551,7 +2602,8 @@ CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
*
* Free a multipart formpost previously built with curl_formadd().
*/
CURL_EXTERN void curl_formfree(struct curl_httppost *form);
CURL_EXTERN void CURL_DEPRECATED(7.56.0, "Use curl_mime_free()")
curl_formfree(struct curl_httppost *form);
/*
* NAME curl_getenv()
@@ -2720,8 +2772,8 @@ CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
* Appends a string to a linked list. If no list exists, it will be created
* first. Returns the new list, after appending.
*/
CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
const char *);
CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *list,
const char *data);
/*
* NAME curl_slist_free_all()
@@ -2730,7 +2782,7 @@ CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
*
* free a previously built curl_slist.
*/
CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
CURL_EXTERN void curl_slist_free_all(struct curl_slist *list);
/*
* NAME curl_getdate()
@@ -2778,22 +2830,35 @@ typedef enum {
CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4,
CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5,
CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7,
CURLINFO_SIZE_UPLOAD CURL_DEPRECATED(7.55.0, "Use CURLINFO_SIZE_UPLOAD_T")
= CURLINFO_DOUBLE + 7,
CURLINFO_SIZE_UPLOAD_T = CURLINFO_OFF_T + 7,
CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8,
CURLINFO_SIZE_DOWNLOAD
CURL_DEPRECATED(7.55.0, "Use CURLINFO_SIZE_DOWNLOAD_T")
= CURLINFO_DOUBLE + 8,
CURLINFO_SIZE_DOWNLOAD_T = CURLINFO_OFF_T + 8,
CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9,
CURLINFO_SPEED_DOWNLOAD
CURL_DEPRECATED(7.55.0, "Use CURLINFO_SPEED_DOWNLOAD_T")
= CURLINFO_DOUBLE + 9,
CURLINFO_SPEED_DOWNLOAD_T = CURLINFO_OFF_T + 9,
CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10,
CURLINFO_SPEED_UPLOAD
CURL_DEPRECATED(7.55.0, "Use CURLINFO_SPEED_UPLOAD_T")
= CURLINFO_DOUBLE + 10,
CURLINFO_SPEED_UPLOAD_T = CURLINFO_OFF_T + 10,
CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11,
CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12,
CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
CURLINFO_FILETIME = CURLINFO_LONG + 14,
CURLINFO_FILETIME_T = CURLINFO_OFF_T + 14,
CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
CURLINFO_CONTENT_LENGTH_DOWNLOAD
CURL_DEPRECATED(7.55.0,
"Use CURLINFO_CONTENT_LENGTH_DOWNLOAD_T")
= CURLINFO_DOUBLE + 15,
CURLINFO_CONTENT_LENGTH_DOWNLOAD_T = CURLINFO_OFF_T + 15,
CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
CURLINFO_CONTENT_LENGTH_UPLOAD
CURL_DEPRECATED(7.55.0,
"Use CURLINFO_CONTENT_LENGTH_UPLOAD_T")
= CURLINFO_DOUBLE + 16,
CURLINFO_CONTENT_LENGTH_UPLOAD_T = CURLINFO_OFF_T + 16,
CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18,
@@ -2807,7 +2872,8 @@ typedef enum {
CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26,
CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27,
CURLINFO_COOKIELIST = CURLINFO_SLIST + 28,
CURLINFO_LASTSOCKET = CURLINFO_LONG + 29,
CURLINFO_LASTSOCKET CURL_DEPRECATED(7.45.0, "Use CURLINFO_ACTIVESOCKET")
= CURLINFO_LONG + 29,
CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30,
CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31,
CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32,
@@ -2821,12 +2887,14 @@ typedef enum {
CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
CURLINFO_TLS_SESSION = CURLINFO_PTR + 43,
CURLINFO_TLS_SESSION CURL_DEPRECATED(7.48.0, "Use CURLINFO_TLS_SSL_PTR")
= CURLINFO_PTR + 43,
CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44,
CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45,
CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46,
CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
CURLINFO_PROTOCOL = CURLINFO_LONG + 48,
CURLINFO_PROTOCOL CURL_DEPRECATED(7.85.0, "Use CURLINFO_SCHEME")
= CURLINFO_LONG + 48,
CURLINFO_SCHEME = CURLINFO_STRING + 49,
CURLINFO_TOTAL_TIME_T = CURLINFO_OFF_T + 50,
CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51,
@@ -2927,8 +2995,9 @@ typedef enum {
} CURLSHoption;
CURL_EXTERN CURLSH *curl_share_init(void);
CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *);
CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *share, CURLSHoption option,
...);
CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *share);
/****************************************************************************
* Structures for querying information about the curl library at runtime.
@@ -2945,6 +3014,7 @@ typedef enum {
CURLVERSION_EIGHTH,
CURLVERSION_NINTH,
CURLVERSION_TENTH,
CURLVERSION_ELEVENTH,
CURLVERSION_LAST /* never actually use this */
} CURLversion;
@@ -2953,7 +3023,7 @@ typedef enum {
meant to be a built-in version number for what kind of struct the caller
expects. If the struct ever changes, we redefine the NOW to another enum
from above. */
#define CURLVERSION_NOW CURLVERSION_TENTH
#define CURLVERSION_NOW CURLVERSION_ELEVENTH
struct curl_version_info_data {
CURLversion age; /* age of the returned struct */
@@ -3009,6 +3079,10 @@ struct curl_version_info_data {
/* These fields were added in CURLVERSION_TENTH */
const char *gsasl_version; /* human readable string. */
/* These fields were added in CURLVERSION_ELEVENTH */
/* feature_names is terminated by an entry with a NULL feature name */
const char * const *feature_names;
};
typedef struct curl_version_info_data curl_version_info_data;
@@ -3102,7 +3176,7 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)
#ifdef __cplusplus
}
} /* end of extern "C" */
#endif
/* unfortunately, the easy.h and multi.h include files need options and info
@@ -3131,6 +3205,6 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
#endif
#endif /* __STDC__ >= 1 */
#endif /* gcc >= 4.3 && !__cplusplus */
#endif /* gcc >= 4.3 && !__cplusplus && !CURL_DISABLE_TYPECHECK */
#endif /* CURLINC_CURL_H */
+3 -3
View File
@@ -32,12 +32,12 @@
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.86.0"
#define LIBCURL_VERSION "7.87.0"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 86
#define LIBCURL_VERSION_MINOR 87
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
@@ -59,7 +59,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 0x075600
#define LIBCURL_VERSION_NUM 0x075700
/*
* This is the date and time when the full source package was created. The
+1 -1
View File
@@ -119,7 +119,7 @@ CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl);
#ifdef __cplusplus
}
} /* end of extern "C" */
#endif
#endif
+1 -1
View File
@@ -46,7 +46,7 @@ CURL_EXTERN char *curl_maprintf(const char *format, ...);
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
#ifdef __cplusplus
}
} /* end of extern "C" */
#endif
#endif /* CURLINC_MPRINTF_H */
+4 -4
View File
@@ -318,16 +318,16 @@ typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
void *userp); /* private callback
pointer */
CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
int *running_handles);
CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()")
curl_multi_socket(CURLM *multi_handle, curl_socket_t s, int *running_handles);
CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
curl_socket_t s,
int ev_bitmask,
int *running_handles);
CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
int *running_handles);
CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()")
curl_multi_socket_all(CURLM *multi_handle, int *running_handles);
#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
/* This macro below was added in 7.16.3 to push users who recompile to use
+21 -1
View File
@@ -164,13 +164,33 @@
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(__MWERKS__)
#elif defined(macintosh)
# include <ConditionalMacros.h>
# if TYPE_LONGLONG
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(__TANDEM)
# if ! defined(__LP64)
/* Required for 32-bit NonStop builds only. */
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
# endif
#elif defined(_WIN32_WCE)
# define CURL_TYPEOF_CURL_OFF_T __int64
+100 -94
View File
@@ -42,107 +42,113 @@
*/
#define curl_easy_setopt(handle, option, value) \
__extension__({ \
__typeof__(option) _curl_opt = option; \
CURL_IGNORE_DEPRECATION(__typeof__(option) _curl_opt = option;) \
if(__builtin_constant_p(_curl_opt)) { \
if(curlcheck_long_option(_curl_opt)) \
if(!curlcheck_long(value)) \
_curl_easy_setopt_err_long(); \
if(curlcheck_off_t_option(_curl_opt)) \
if(!curlcheck_off_t(value)) \
_curl_easy_setopt_err_curl_off_t(); \
if(curlcheck_string_option(_curl_opt)) \
if(!curlcheck_string(value)) \
_curl_easy_setopt_err_string(); \
if(curlcheck_write_cb_option(_curl_opt)) \
if(!curlcheck_write_cb(value)) \
_curl_easy_setopt_err_write_callback(); \
if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
if(!curlcheck_resolver_start_callback(value)) \
_curl_easy_setopt_err_resolver_start_callback(); \
if((_curl_opt) == CURLOPT_READFUNCTION) \
if(!curlcheck_read_cb(value)) \
_curl_easy_setopt_err_read_cb(); \
if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
if(!curlcheck_ioctl_cb(value)) \
_curl_easy_setopt_err_ioctl_cb(); \
if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
if(!curlcheck_sockopt_cb(value)) \
_curl_easy_setopt_err_sockopt_cb(); \
if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
if(!curlcheck_opensocket_cb(value)) \
_curl_easy_setopt_err_opensocket_cb(); \
if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
if(!curlcheck_progress_cb(value)) \
_curl_easy_setopt_err_progress_cb(); \
if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
if(!curlcheck_debug_cb(value)) \
_curl_easy_setopt_err_debug_cb(); \
if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
if(!curlcheck_ssl_ctx_cb(value)) \
_curl_easy_setopt_err_ssl_ctx_cb(); \
if(curlcheck_conv_cb_option(_curl_opt)) \
if(!curlcheck_conv_cb(value)) \
_curl_easy_setopt_err_conv_cb(); \
if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
if(!curlcheck_seek_cb(value)) \
_curl_easy_setopt_err_seek_cb(); \
if(curlcheck_cb_data_option(_curl_opt)) \
if(!curlcheck_cb_data(value)) \
_curl_easy_setopt_err_cb_data(); \
if((_curl_opt) == CURLOPT_ERRORBUFFER) \
if(!curlcheck_error_buffer(value)) \
_curl_easy_setopt_err_error_buffer(); \
if((_curl_opt) == CURLOPT_STDERR) \
if(!curlcheck_FILE(value)) \
_curl_easy_setopt_err_FILE(); \
if(curlcheck_postfields_option(_curl_opt)) \
if(!curlcheck_postfields(value)) \
_curl_easy_setopt_err_postfields(); \
if((_curl_opt) == CURLOPT_HTTPPOST) \
if(!curlcheck_arr((value), struct curl_httppost)) \
_curl_easy_setopt_err_curl_httpost(); \
if((_curl_opt) == CURLOPT_MIMEPOST) \
if(!curlcheck_ptr((value), curl_mime)) \
_curl_easy_setopt_err_curl_mimepost(); \
if(curlcheck_slist_option(_curl_opt)) \
if(!curlcheck_arr((value), struct curl_slist)) \
_curl_easy_setopt_err_curl_slist(); \
if((_curl_opt) == CURLOPT_SHARE) \
if(!curlcheck_ptr((value), CURLSH)) \
_curl_easy_setopt_err_CURLSH(); \
(void) option; \
CURL_IGNORE_DEPRECATION( \
if(curlcheck_long_option(_curl_opt)) \
if(!curlcheck_long(value)) \
_curl_easy_setopt_err_long(); \
if(curlcheck_off_t_option(_curl_opt)) \
if(!curlcheck_off_t(value)) \
_curl_easy_setopt_err_curl_off_t(); \
if(curlcheck_string_option(_curl_opt)) \
if(!curlcheck_string(value)) \
_curl_easy_setopt_err_string(); \
if(curlcheck_write_cb_option(_curl_opt)) \
if(!curlcheck_write_cb(value)) \
_curl_easy_setopt_err_write_callback(); \
if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
if(!curlcheck_resolver_start_callback(value)) \
_curl_easy_setopt_err_resolver_start_callback(); \
if((_curl_opt) == CURLOPT_READFUNCTION) \
if(!curlcheck_read_cb(value)) \
_curl_easy_setopt_err_read_cb(); \
if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
if(!curlcheck_ioctl_cb(value)) \
_curl_easy_setopt_err_ioctl_cb(); \
if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
if(!curlcheck_sockopt_cb(value)) \
_curl_easy_setopt_err_sockopt_cb(); \
if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
if(!curlcheck_opensocket_cb(value)) \
_curl_easy_setopt_err_opensocket_cb(); \
if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
if(!curlcheck_progress_cb(value)) \
_curl_easy_setopt_err_progress_cb(); \
if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
if(!curlcheck_debug_cb(value)) \
_curl_easy_setopt_err_debug_cb(); \
if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
if(!curlcheck_ssl_ctx_cb(value)) \
_curl_easy_setopt_err_ssl_ctx_cb(); \
if(curlcheck_conv_cb_option(_curl_opt)) \
if(!curlcheck_conv_cb(value)) \
_curl_easy_setopt_err_conv_cb(); \
if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
if(!curlcheck_seek_cb(value)) \
_curl_easy_setopt_err_seek_cb(); \
if(curlcheck_cb_data_option(_curl_opt)) \
if(!curlcheck_cb_data(value)) \
_curl_easy_setopt_err_cb_data(); \
if((_curl_opt) == CURLOPT_ERRORBUFFER) \
if(!curlcheck_error_buffer(value)) \
_curl_easy_setopt_err_error_buffer(); \
if((_curl_opt) == CURLOPT_STDERR) \
if(!curlcheck_FILE(value)) \
_curl_easy_setopt_err_FILE(); \
if(curlcheck_postfields_option(_curl_opt)) \
if(!curlcheck_postfields(value)) \
_curl_easy_setopt_err_postfields(); \
if((_curl_opt) == CURLOPT_HTTPPOST) \
if(!curlcheck_arr((value), struct curl_httppost)) \
_curl_easy_setopt_err_curl_httpost(); \
if((_curl_opt) == CURLOPT_MIMEPOST) \
if(!curlcheck_ptr((value), curl_mime)) \
_curl_easy_setopt_err_curl_mimepost(); \
if(curlcheck_slist_option(_curl_opt)) \
if(!curlcheck_arr((value), struct curl_slist)) \
_curl_easy_setopt_err_curl_slist(); \
if((_curl_opt) == CURLOPT_SHARE) \
if(!curlcheck_ptr((value), CURLSH)) \
_curl_easy_setopt_err_CURLSH(); \
) \
} \
curl_easy_setopt(handle, _curl_opt, value); \
})
/* wraps curl_easy_getinfo() with typechecking */
#define curl_easy_getinfo(handle, info, arg) \
__extension__({ \
__typeof__(info) _curl_info = info; \
__extension__({ \
CURL_IGNORE_DEPRECATION(__typeof__(info) _curl_info = info;) \
if(__builtin_constant_p(_curl_info)) { \
if(curlcheck_string_info(_curl_info)) \
if(!curlcheck_arr((arg), char *)) \
_curl_easy_getinfo_err_string(); \
if(curlcheck_long_info(_curl_info)) \
if(!curlcheck_arr((arg), long)) \
_curl_easy_getinfo_err_long(); \
if(curlcheck_double_info(_curl_info)) \
if(!curlcheck_arr((arg), double)) \
_curl_easy_getinfo_err_double(); \
if(curlcheck_slist_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_slist *)) \
_curl_easy_getinfo_err_curl_slist(); \
if(curlcheck_tlssessioninfo_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \
_curl_easy_getinfo_err_curl_tlssesssioninfo(); \
if(curlcheck_certinfo_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_certinfo *)) \
_curl_easy_getinfo_err_curl_certinfo(); \
if(curlcheck_socket_info(_curl_info)) \
if(!curlcheck_arr((arg), curl_socket_t)) \
_curl_easy_getinfo_err_curl_socket(); \
if(curlcheck_off_t_info(_curl_info)) \
if(!curlcheck_arr((arg), curl_off_t)) \
_curl_easy_getinfo_err_curl_off_t(); \
(void) info; \
CURL_IGNORE_DEPRECATION( \
if(curlcheck_string_info(_curl_info)) \
if(!curlcheck_arr((arg), char *)) \
_curl_easy_getinfo_err_string(); \
if(curlcheck_long_info(_curl_info)) \
if(!curlcheck_arr((arg), long)) \
_curl_easy_getinfo_err_long(); \
if(curlcheck_double_info(_curl_info)) \
if(!curlcheck_arr((arg), double)) \
_curl_easy_getinfo_err_double(); \
if(curlcheck_slist_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_slist *)) \
_curl_easy_getinfo_err_curl_slist(); \
if(curlcheck_tlssessioninfo_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \
_curl_easy_getinfo_err_curl_tlssesssioninfo(); \
if(curlcheck_certinfo_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_certinfo *)) \
_curl_easy_getinfo_err_curl_certinfo(); \
if(curlcheck_socket_info(_curl_info)) \
if(!curlcheck_arr((arg), curl_socket_t)) \
_curl_easy_getinfo_err_curl_socket(); \
if(curlcheck_off_t_info(_curl_info)) \
if(!curlcheck_arr((arg), curl_off_t)) \
_curl_easy_getinfo_err_curl_off_t(); \
) \
} \
curl_easy_getinfo(handle, _curl_info, arg); \
})
@@ -436,7 +442,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(CURLINFO_OFF_T < (info))
/* typecheck helpers -- check whether given expression has requested type*/
/* typecheck helpers -- check whether given expression has requested type */
/* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros,
* otherwise define a new macro. Search for __builtin_types_compatible_p
+28
View File
@@ -123,12 +123,40 @@ endif()
target_link_libraries(${LIB_NAME} PRIVATE ${CURL_LIBS})
if(0) # This code not needed for building within CMake.
transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake)
endif()
set_target_properties(${LIB_NAME} PROPERTIES
COMPILE_DEFINITIONS BUILDING_LIBCURL
OUTPUT_NAME ${LIBCURL_OUTPUT_NAME}
)
if(0) # This code not needed for building within CMake.
if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
CMAKE_SYSTEM_NAME STREQUAL "GNU/kFreeBSD" OR
# FreeBSD comes with the a.out and elf flavours
# but a.out was supported up to version 3.x and
# elf from 3.x. I cannot imagine someone runnig
# CMake on those ancient systems
CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
CMAKE_SYSTEM_NAME STREQUAL "Haiku")
math(EXPR CMAKESONAME "${VERSIONCHANGE} - ${VERSIONDEL}")
set(CMAKEVERSION "${CMAKESONAME}.${VERSIONDEL}.${VERSIONADD}")
set_target_properties(${LIB_NAME} PROPERTIES
VERSION ${CMAKEVERSION}
SOVERSION ${CMAKESONAME}
)
endif()
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})
+5 -1
View File
@@ -74,6 +74,7 @@ LIB_VTLS_HFILES = \
vtls/schannel.h \
vtls/sectransp.h \
vtls/vtls.h \
vtls/vtls_int.h \
vtls/wolfssl.h \
vtls/x509asn1.h
@@ -105,6 +106,7 @@ LIB_CFILES = \
base64.c \
bufref.c \
c-hyper.c \
cfilters.c \
conncache.c \
connect.c \
content_encoding.c \
@@ -160,7 +162,7 @@ LIB_CFILES = \
http_ntlm.c \
http_proxy.c \
http_aws_sigv4.c \
idn_win32.c \
idn.c \
if2ip.c \
imap.c \
inet_ntop.c \
@@ -227,6 +229,7 @@ LIB_HFILES = \
asyn.h \
bufref.h \
c-hyper.h \
cfilters.h \
conncache.h \
connect.h \
content_encoding.h \
@@ -290,6 +293,7 @@ LIB_HFILES = \
http_ntlm.h \
http_proxy.h \
http_aws_sigv4.h \
idn.h \
if2ip.h \
imap.h \
inet_ntop.h \
+11 -5
View File
@@ -517,15 +517,21 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
dsthost = srchost;
}
if(*p == ':') {
/* a port number */
unsigned long port = strtoul(++p, &end_ptr, 10);
if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
unsigned long port = 0;
p++;
if(ISDIGIT(*p))
/* a port number */
port = strtoul(p, &end_ptr, 10);
else
end_ptr = (char *)p; /* not left uninitialized */
if(!port || port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
infof(data, "Unknown alt-svc port number, ignoring.");
valid = FALSE;
}
else
else {
dstport = curlx_ultous(port);
p = end_ptr;
p = end_ptr;
}
}
if(*p++ != '\"')
break;
-9
View File
@@ -47,15 +47,6 @@
#include <inet.h>
#endif
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
+4 -15
View File
@@ -44,19 +44,8 @@
#include <inet.h>
#endif
#if defined(USE_THREADS_POSIX)
# ifdef HAVE_PTHREAD_H
# include <pthread.h>
# endif
#elif defined(USE_THREADS_WIN32)
# ifdef HAVE_PROCESS_H
# include <process.h>
# endif
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
# include <pthread.h>
#endif
#ifdef HAVE_GETADDRINFO
@@ -75,7 +64,6 @@
#include "inet_ntop.h"
#include "curl_threads.h"
#include "connect.h"
#include "socketpair.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -541,7 +529,8 @@ void Curl_resolver_kill(struct Curl_easy *data)
/* If we're still resolving, we must wait for the threads to fully clean up,
unfortunately. Otherwise, we can simply cancel to clean up any resolver
data. */
if(td && td->thread_hnd != curl_thread_t_null)
if(td && td->thread_hnd != curl_thread_t_null
&& (data->set.quick_exit != 1L))
(void)thread_wait_resolv(data, NULL, FALSE);
else
Curl_resolver_cancel(data);
+93 -102
View File
@@ -37,8 +37,7 @@
#include "warnless.h"
#include "curl_base64.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
/* The last 2 #include files should be in this order */
#include "curl_memory.h"
#include "memdebug.h"
@@ -52,39 +51,12 @@ static const char base64[]=
static const char base64url[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
static size_t decodeQuantum(unsigned char *dest, const char *src)
{
size_t padding = 0;
const char *s;
unsigned long i, x = 0;
for(i = 0, s = src; i < 4; i++, s++) {
if(*s == '=') {
x <<= 6;
padding++;
}
else {
const char *p = strchr(base64, *s);
if(p)
x = (x << 6) + curlx_uztoul(p - base64);
else
return 0;
}
}
if(padding < 1)
dest[2] = curlx_ultouc(x & 0xFFUL);
x >>= 8;
if(padding < 2)
dest[1] = curlx_ultouc(x & 0xFFUL);
x >>= 8;
dest[0] = curlx_ultouc(x & 0xFFUL);
return 3 - padding;
}
static const unsigned char decodetable[] =
{ 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255,
255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51 };
/*
* Curl_base64_decode()
*
@@ -106,10 +78,11 @@ CURLcode Curl_base64_decode(const char *src,
size_t padding = 0;
size_t i;
size_t numQuantums;
size_t fullQuantums;
size_t rawlen = 0;
const char *padptr;
unsigned char *pos;
unsigned char *newstr;
unsigned char lookup[256];
*outptr = NULL;
*outlen = 0;
@@ -119,21 +92,18 @@ CURLcode Curl_base64_decode(const char *src,
if(!srclen || srclen % 4)
return CURLE_BAD_CONTENT_ENCODING;
/* Find the position of any = padding characters */
padptr = strchr(src, '=');
if(padptr) {
/* srclen is at least 4 here */
while(src[srclen - 1 - padding] == '=') {
/* count padding characters */
padding++;
/* A maximum of two = padding characters is allowed */
if(padptr[1] == '=')
padding++;
/* Check the = padding characters weren't part way through the input */
if(padptr + padding != src + srclen)
if(padding > 2)
return CURLE_BAD_CONTENT_ENCODING;
}
/* Calculate the number of quantums */
numQuantums = srclen / 4;
fullQuantums = numQuantums - (padding ? 1 : 0);
/* Calculate the size of the decoded string */
rawlen = (numQuantums * 3) - padding;
@@ -145,17 +115,59 @@ CURLcode Curl_base64_decode(const char *src,
pos = newstr;
/* Decode the quantums */
for(i = 0; i < numQuantums; i++) {
size_t result = decodeQuantum(pos, src);
if(!result) {
free(newstr);
memset(lookup, 0xff, sizeof(lookup));
memcpy(&lookup['+'], decodetable, sizeof(decodetable));
/* replaces
{
unsigned char c;
const unsigned char *p = (const unsigned char *)base64;
for(c = 0; *p; c++, p++)
lookup[*p] = c;
}
*/
return CURLE_BAD_CONTENT_ENCODING;
/* Decode the complete quantums first */
for(i = 0; i < fullQuantums; i++) {
unsigned char val;
unsigned int x = 0;
int j;
for(j = 0; j < 4; j++) {
val = lookup[(unsigned char)*src++];
if(val == 0xff) /* bad symbol */
goto bad;
x = (x << 6) | val;
}
pos += result;
src += 4;
pos[2] = x & 0xff;
pos[1] = (x >> 8) & 0xff;
pos[0] = (x >> 16) & 0xff;
pos += 3;
}
if(padding) {
/* this means either 8 or 16 bits output */
unsigned char val;
unsigned int x = 0;
int j;
size_t padc = 0;
for(j = 0; j < 4; j++) {
if(*src == '=') {
x <<= 6;
src++;
if(++padc > padding)
/* this is a badly placed '=' symbol! */
goto bad;
}
else {
val = lookup[(unsigned char)*src++];
if(val == 0xff) /* bad symbol */
goto bad;
x = (x << 6) | val;
}
}
if(padding == 1)
pos[1] = (x >> 8) & 0xff;
pos[0] = (x >> 16) & 0xff;
pos += 3 - padding;
}
/* Zero terminate */
@@ -166,81 +178,60 @@ CURLcode Curl_base64_decode(const char *src,
*outlen = rawlen;
return CURLE_OK;
bad:
free(newstr);
return CURLE_BAD_CONTENT_ENCODING;
}
static CURLcode base64_encode(const char *table64,
const char *inputbuff, size_t insize,
char **outptr, size_t *outlen)
{
unsigned char ibuf[3];
unsigned char obuf[4];
int i;
int inputparts;
char *output;
char *base64data;
const char *indata = inputbuff;
const unsigned char *in = (unsigned char *)inputbuff;
const char *padstr = &table64[64]; /* Point to padding string. */
*outptr = NULL;
*outlen = 0;
if(!insize)
insize = strlen(indata);
insize = strlen(inputbuff);
#if SIZEOF_SIZE_T == 4
if(insize > UINT_MAX/4)
return CURLE_OUT_OF_MEMORY;
#endif
base64data = output = malloc(insize * 4 / 3 + 4);
base64data = output = malloc((insize + 2) / 3 * 4 + 1);
if(!output)
return CURLE_OUT_OF_MEMORY;
while(insize > 0) {
for(i = inputparts = 0; i < 3; i++) {
if(insize > 0) {
inputparts++;
ibuf[i] = (unsigned char) *indata;
indata++;
insize--;
while(insize >= 3) {
*output++ = table64[ in[0] >> 2 ];
*output++ = table64[ ((in[0] & 0x03) << 4) | (in[1] >> 4) ];
*output++ = table64[ ((in[1] & 0x0F) << 2) | ((in[2] & 0xC0) >> 6) ];
*output++ = table64[ in[2] & 0x3F ];
insize -= 3;
in += 3;
}
if(insize) {
/* this is only one or two bytes now */
*output++ = table64[ in[0] >> 2 ];
if(insize == 1) {
*output++ = table64[ ((in[0] & 0x03) << 4) ];
if(*padstr) {
*output++ = *padstr;
*output++ = *padstr;
}
else
ibuf[i] = 0;
}
obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
((ibuf[1] & 0xF0) >> 4));
obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
((ibuf[2] & 0xC0) >> 6));
obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
switch(inputparts) {
case 1: /* only one byte read */
i = msnprintf(output, 5, "%c%c%s%s",
table64[obuf[0]],
table64[obuf[1]],
padstr,
padstr);
break;
case 2: /* two bytes read */
i = msnprintf(output, 5, "%c%c%c%s",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]],
padstr);
break;
default:
i = msnprintf(output, 5, "%c%c%c%c",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]],
table64[obuf[3]]);
break;
else {
/* insize == 2 */
*output++ = table64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xF0) >> 4) ];
*output++ = table64[ ((in[1] & 0x0F) << 2) ];
if(*padstr)
*output++ = *padstr;
}
output += i;
}
/* Zero terminate */
+46 -25
View File
@@ -163,6 +163,10 @@ static int hyper_each_header(void *userdata,
writetype = CLIENTWRITE_HEADER;
if(data->set.include_header)
writetype |= CLIENTWRITE_BODY;
if(data->state.hconnect)
writetype |= CLIENTWRITE_CONNECT;
if(data->req.httpcode/100 == 1)
writetype |= CLIENTWRITE_1XX;
result = Curl_client_write(data, writetype, headp, len);
if(result) {
data->state.hresult = CURLE_ABORTED_BY_CALLBACK;
@@ -170,8 +174,8 @@ static int hyper_each_header(void *userdata,
}
}
data->info.header_size += (long)len;
data->req.headerbytecount += (long)len;
data->info.header_size += (curl_off_t)len;
data->req.headerbytecount += (curl_off_t)len;
return HYPER_ITER_CONTINUE;
}
@@ -245,7 +249,7 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk)
}
/*
* Hyper does not consider the status line, the first line in a HTTP/1
* Hyper does not consider the status line, the first line in an HTTP/1
* response, to be a header. The libcurl API does. This function sends the
* status line in the header callback. */
static CURLcode status_line(struct Curl_easy *data,
@@ -260,23 +264,25 @@ static CURLcode status_line(struct Curl_easy *data,
int writetype;
vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" :
(http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0");
conn->httpversion =
http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
(http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
if(http_version == HYPER_HTTP_VERSION_1_0)
data->state.httpwant = CURL_HTTP_VERSION_1_0;
if(data->state.hconnect)
/* CONNECT */
data->info.httpproxycode = http_status;
/* We need to set 'httpcodeq' for functions that check the response code in
a single place. */
data->req.httpcode = http_status;
result = Curl_http_statusline(data, conn);
if(result)
return result;
if(data->state.hconnect)
/* CONNECT */
data->info.httpproxycode = http_status;
else {
conn->httpversion =
http_version == HYPER_HTTP_VERSION_1_1 ? 11 :
(http_version == HYPER_HTTP_VERSION_2 ? 20 : 10);
if(http_version == HYPER_HTTP_VERSION_1_0)
data->state.httpwant = CURL_HTTP_VERSION_1_0;
result = Curl_http_statusline(data, conn);
if(result)
return result;
}
Curl_dyn_reset(&data->state.headerb);
@@ -299,9 +305,8 @@ static CURLcode status_line(struct Curl_easy *data,
if(result)
return result;
}
data->info.header_size += (long)len;
data->req.headerbytecount += (long)len;
data->req.httpcode = http_status;
data->info.header_size += (curl_off_t)len;
data->req.headerbytecount += (curl_off_t)len;
return CURLE_OK;
}
@@ -415,8 +420,10 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data,
break;
}
else if(h->endtask == task) {
/* end of transfer */
/* end of transfer, forget the task handled, we might get a
* new one with the same address in the future. */
*done = TRUE;
h->endtask = NULL;
infof(data, "hyperstream is done");
if(!k->bodywrites) {
/* hyper doesn't always call the body write callback */
@@ -679,7 +686,7 @@ static int uploadpostfields(void *userdata, hyper_context *ctx,
return HYPER_POLL_ERROR;
}
/* increasing the writebytecount here is a little premature but we
don't know exactly when the body is sent*/
don't know exactly when the body is sent */
data->req.writebytecount += (size_t)data->req.p.http->postsize;
Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
data->req.upload_done = TRUE;
@@ -692,6 +699,7 @@ static int uploadstreamed(void *userdata, hyper_context *ctx,
{
size_t fillcount;
struct Curl_easy *data = (struct Curl_easy *)userdata;
struct connectdata *conn = (struct connectdata *)data->conn;
CURLcode result;
(void)ctx;
@@ -706,7 +714,15 @@ static int uploadstreamed(void *userdata, hyper_context *ctx,
return HYPER_POLL_PENDING;
}
result = Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount);
if(data->req.upload_chunky && conn->bits.authneg) {
fillcount = 0;
data->req.upload_chunky = FALSE;
result = CURLE_OK;
}
else {
result = Curl_fillreadbuffer(data, data->set.upload_buffer_size,
&fillcount);
}
if(result) {
data->state.hresult = result;
return HYPER_POLL_ERROR;
@@ -732,7 +748,7 @@ static int uploadstreamed(void *userdata, hyper_context *ctx,
return HYPER_POLL_ERROR;
}
/* increasing the writebytecount here is a little premature but we
don't know exactly when the body is sent*/
don't know exactly when the body is sent */
data->req.writebytecount += fillcount;
Curl_pgrsSetUploadCounter(data, fillcount);
}
@@ -740,7 +756,7 @@ static int uploadstreamed(void *userdata, hyper_context *ctx,
}
/*
* bodysend() sets up headers in the outgoing request for a HTTP transfer that
* bodysend() sets up headers in the outgoing request for an HTTP transfer that
* sends a body
*/
@@ -845,7 +861,7 @@ static void http1xx_cb(void *arg, struct hyper_response *resp)
}
/*
* Curl_http() gets called from the generic multi_do() function when a HTTP
* Curl_http() gets called from the generic multi_do() function when an HTTP
* request is to be performed. This creates and sends a properly constructed
* HTTP request.
*/
@@ -1159,7 +1175,12 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"\r\n", 2);
data->req.upload_chunky = FALSE;
if(data->req.upload_chunky && conn->bits.authneg) {
data->req.upload_chunky = TRUE;
}
else {
data->req.upload_chunky = FALSE;
}
sendtask = hyper_clientconn_send(client, req);
if(!sendtask) {
failf(data, "hyper_clientconn_send");
+502
View File
@@ -0,0 +1,502 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2022, 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.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.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#include "urldata.h"
#include "strerror.h"
#include "cfilters.h"
#include "connect.h"
#include "url.h" /* for Curl_safefree() */
#include "sendf.h"
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h"
#include "progress.h"
#include "warnless.h"
#include "http_proxy.h"
#include "socks.h"
#include "vtls/vtls.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
void Curl_cf_def_destroy_this(struct Curl_cfilter *cf, struct Curl_easy *data)
{
(void)cf;
(void)data;
}
CURLcode Curl_cf_def_setup(struct Curl_cfilter *cf,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost)
{
DEBUGASSERT(cf->next);
return cf->next->cft->setup(cf->next, data, remotehost);
}
void Curl_cf_def_attach_data(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
(void)cf;
(void)data;
}
void Curl_cf_def_detach_data(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
(void)cf;
(void)data;
}
void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
DEBUGASSERT(cf->next);
cf->connected = FALSE;
cf->next->cft->close(cf->next, data);
}
CURLcode Curl_cf_def_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
{
DEBUGASSERT(cf->next);
return cf->next->cft->connect(cf->next, data, blocking, done);
}
void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
const char **phost, const char **pdisplay_host,
int *pport)
{
DEBUGASSERT(cf->next);
cf->next->cft->get_host(cf->next, data, phost, pdisplay_host, pport);
}
int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
{
DEBUGASSERT(cf->next);
return cf->next->cft->get_select_socks(cf->next, data, socks);
}
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
DEBUGASSERT(cf->next);
return cf->next->cft->has_data_pending(cf->next, data);
}
ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
DEBUGASSERT(cf->next);
return cf->next->cft->do_send(cf->next, data, buf, len, err);
}
ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err)
{
DEBUGASSERT(cf->next);
return cf->next->cft->do_recv(cf->next, data, buf, len, err);
}
void Curl_conn_cf_discard_all(struct Curl_easy *data,
struct connectdata *conn, int index)
{
struct Curl_cfilter *cfn, *cf = conn->cfilter[index];
if(cf) {
conn->cfilter[index] = NULL;
while(cf) {
cfn = cf->next;
cf->cft->destroy(cf, data);
free(cf);
cf = cfn;
}
}
}
void Curl_conn_close(struct Curl_easy *data, int index)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data->conn);
/* it is valid to call that without filters being present */
cf = data->conn->cfilter[index];
if(cf) {
cf->cft->close(cf, data);
}
}
ssize_t Curl_conn_recv(struct Curl_easy *data, int num, char *buf,
size_t len, CURLcode *code)
{
struct Curl_cfilter *cf;
ssize_t nread;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[num];
while(cf && !cf->connected) {
cf = cf->next;
}
if(cf) {
nread = cf->cft->do_recv(cf, data, buf, len, code);
/* DEBUGF(infof(data, "Curl_conn_recv(handle=%p, index=%d)"
"-> %ld, err=%d", data, num, nread, *code));*/
return nread;
}
failf(data, "no filter connected, conn=%ld, sockindex=%d",
data->conn->connection_id, num);
*code = CURLE_FAILED_INIT;
return -1;
}
ssize_t Curl_conn_send(struct Curl_easy *data, int num,
const void *mem, size_t len, CURLcode *code)
{
struct Curl_cfilter *cf;
ssize_t nwritten;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[num];
while(cf && !cf->connected) {
cf = cf->next;
}
if(cf) {
nwritten = cf->cft->do_send(cf, data, mem, len, code);
/* DEBUGF(infof(data, "Curl_conn_send(handle=%p, index=%d, len=%ld)"
" -> %ld, err=%d", data, num, len, nwritten, *code));*/
return nwritten;
}
failf(data, "no filter connected, conn=%ld, sockindex=%d",
data->conn->connection_id, num);
*code = CURLE_FAILED_INIT;
return -1;
}
CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
const struct Curl_cftype *cft,
void *ctx)
{
struct Curl_cfilter *cf;
CURLcode result = CURLE_OUT_OF_MEMORY;
DEBUGASSERT(cft);
cf = calloc(sizeof(*cf), 1);
if(!cf)
goto out;
cf->cft = cft;
cf->ctx = ctx;
result = CURLE_OK;
out:
*pcf = cf;
return result;
}
void Curl_conn_cf_add(struct Curl_easy *data,
struct connectdata *conn,
int index,
struct Curl_cfilter *cf)
{
(void)data;
DEBUGASSERT(conn);
DEBUGASSERT(!cf->conn);
DEBUGASSERT(!cf->next);
DEBUGF(infof(data, CMSGI(conn, index, "cf_add(filter=%s)"),
cf->cft->name));
cf->next = conn->cfilter[index];
cf->conn = conn;
cf->sockindex = index;
conn->cfilter[index] = cf;
}
void Curl_conn_cf_discard(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct Curl_cfilter **pprev = &cf->conn->cfilter[cf->sockindex];
/* remove from chain if still in there */
DEBUGASSERT(cf);
while (*pprev) {
if (*pprev == cf) {
*pprev = cf->next;
break;
}
pprev = &((*pprev)->next);
}
cf->cft->destroy(cf, data);
free(cf);
}
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
return cf->cft->do_send(cf, data, buf, len, err);
}
ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err)
{
return cf->cft->do_recv(cf, data, buf, len, err);
}
CURLcode Curl_conn_setup(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost,
int ssl_mode)
{
struct Curl_cfilter *cf;
CURLcode result;
DEBUGASSERT(data);
/* If no filter is set, we have the "default" setup of connection filters.
* The filter chain from botton to top will be:
* - SOCKET socket filter for outgoing connection to remotehost
* if http_proxy tunneling is engaged:
* - SSL if proxytype is CURLPROXY_HTTPS
* - HTTP_PROXY_TUNNEL
* otherwise, if socks_proxy is engaged:
* - SOCKS_PROXY_TUNNEL
* - SSL if conn->handler has PROTOPT_SSL
*/
if(!conn->cfilter[sockindex]) {
DEBUGF(infof(data, DMSGI(data, sockindex, "setup, init filter chain")));
result = Curl_conn_socket_set(data, conn, sockindex);
if(result)
goto out;
#ifndef CURL_DISABLE_PROXY
if(conn->bits.socksproxy) {
result = Curl_conn_socks_proxy_add(data, conn, sockindex);
if(result)
goto out;
}
if(conn->bits.httpproxy) {
#ifdef USE_SSL
if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
result = Curl_ssl_cfilter_proxy_add(data, conn, sockindex);
if(result)
goto out;
}
#endif /* USE_SSL */
#if !defined(CURL_DISABLE_HTTP)
if(conn->bits.tunnel_proxy) {
result = Curl_conn_http_proxy_add(data, conn, sockindex);
if(result)
goto out;
}
#endif /* !CURL_DISABLE_HTTP */
}
#endif /* !CURL_DISABLE_PROXY */
#ifdef USE_SSL
if(ssl_mode == CURL_CF_SSL_ENABLE
|| (ssl_mode != CURL_CF_SSL_DISABLE
&& conn->handler->flags & PROTOPT_SSL)) {
result = Curl_ssl_cfilter_add(data, conn, sockindex);
if(result)
goto out;
}
#else
(void)ssl_mode;
#endif /* USE_SSL */
#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
if(data->set.haproxyprotocol) {
result = Curl_conn_haproxy_add(data, conn, sockindex);
if(result)
goto out;
}
#endif /* !CURL_DISABLE_PROXY && !CURL_DISABLE_HTTP */
}
DEBUGASSERT(conn->cfilter[sockindex]);
cf = data->conn->cfilter[sockindex];
result = cf->cft->setup(cf, data, remotehost);
out:
return result;
}
CURLcode Curl_conn_connect(struct Curl_easy *data,
int sockindex,
bool blocking,
bool *done)
{
struct Curl_cfilter *cf;
CURLcode result;
DEBUGASSERT(data);
cf = data->conn->cfilter[sockindex];
DEBUGASSERT(cf);
result = cf->cft->connect(cf, data, blocking, done);
DEBUGF(infof(data, DMSGI(data, sockindex, "connect(block=%d)-> %d, done=%d"),
blocking, result, *done));
return result;
}
bool Curl_conn_is_connected(struct connectdata *conn, int sockindex)
{
struct Curl_cfilter *cf;
cf = conn->cfilter[sockindex];
return cf && cf->connected;
}
bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex)
{
struct Curl_cfilter *cf;
cf = data->conn->cfilter[sockindex];
while(cf) {
if(cf->connected)
return TRUE;
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
return FALSE;
cf = cf->next;
}
return FALSE;
}
bool Curl_conn_is_ssl(struct Curl_easy *data, int sockindex)
{
struct Curl_cfilter *cf = data->conn? data->conn->cfilter[sockindex] : NULL;
(void)data;
for(; cf; cf = cf->next) {
if(cf->cft->flags & CF_TYPE_SSL)
return TRUE;
if(cf->cft->flags & CF_TYPE_IP_CONNECT)
return FALSE;
}
return FALSE;
}
bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
{
struct Curl_cfilter *cf;
(void)data;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
if(Curl_recv_has_postponed_data(data->conn, sockindex))
return TRUE;
cf = data->conn->cfilter[sockindex];
while(cf && !cf->connected) {
cf = cf->next;
}
if(cf) {
return cf->cft->has_data_pending(cf, data);
}
return FALSE;
}
int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
curl_socket_t *socks)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[sockindex];
if(cf) {
return cf->cft->get_select_socks(cf, data, socks);
}
return GETSOCK_BLANK;
}
void Curl_conn_attach_data(struct connectdata *conn,
struct Curl_easy *data)
{
size_t i;
struct Curl_cfilter *cf;
for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
cf = conn->cfilter[i];
if(cf) {
while(cf) {
cf->cft->attach_data(cf, data);
cf = cf->next;
}
}
}
}
void Curl_conn_detach_data(struct connectdata *conn,
struct Curl_easy *data)
{
size_t i;
struct Curl_cfilter *cf;
for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
cf = conn->cfilter[i];
if(cf) {
while(cf) {
cf->cft->detach_data(cf, data);
cf = cf->next;
}
}
}
}
void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
const char **phost, const char **pdisplay_host,
int *pport)
{
struct Curl_cfilter *cf;
DEBUGASSERT(data->conn);
cf = data->conn->cfilter[sockindex];
if(cf) {
cf->cft->get_host(cf, data, phost, pdisplay_host, pport);
}
else {
/* Some filter ask during shutdown for this, mainly for debugging
* purposes. We hand out the defaults, however this is not always
* accurate, as the connction might be tunneled, etc. But all that
* state is already gone here. */
*phost = data->conn->host.name;
*pdisplay_host = data->conn->host.dispname;
*pport = data->conn->remote_port;
}
}
+315
View File
@@ -0,0 +1,315 @@
#ifndef HEADER_CURL_CFILTERS_H
#define HEADER_CURL_CFILTERS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2022, 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.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.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
struct Curl_cfilter;
struct Curl_easy;
struct Curl_dns_entry;
struct connectdata;
/* Callback to destroy resources held by this filter instance.
* Implementations MUST NOT chain calls to cf->next.
*/
typedef void Curl_cft_destroy_this(struct Curl_cfilter *cf,
struct Curl_easy *data);
/* Setup the connection for `data`, using destination `remotehost`.
*/
typedef CURLcode Curl_cft_setup(struct Curl_cfilter *cf,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost);
typedef void Curl_cft_close(struct Curl_cfilter *cf,
struct Curl_easy *data);
typedef CURLcode Curl_cft_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done);
/* Return the hostname and port the connection goes to.
* This may change with the connection state of filters when tunneling
* is involved.
* @param cf the filter to ask
* @param data the easy handle currently active
* @param phost on return, points to the relevant, real hostname.
* this is owned by the connection.
* @param pdisplay_host on return, points to the printable hostname.
* this is owned by the connection.
* @param pport on return, contains the port number
*/
typedef void Curl_cft_get_host(struct Curl_cfilter *cf,
struct Curl_easy *data,
const char **phost,
const char **pdisplay_host,
int *pport);
/* Filters may return sockets and fdset flags they are waiting for.
* The passes array has room for up to MAX_SOCKSPEREASYHANDLE sockets.
* @return read/write fdset for index in socks
* or GETSOCK_BLANK when nothing to wait on
*/
typedef int Curl_cft_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks);
typedef bool Curl_cft_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
typedef ssize_t Curl_cft_send(struct Curl_cfilter *cf,
struct Curl_easy *data, /* transfer */
const void *buf, /* data to write */
size_t len, /* amount to write */
CURLcode *err); /* error to return */
typedef ssize_t Curl_cft_recv(struct Curl_cfilter *cf,
struct Curl_easy *data, /* transfer */
char *buf, /* store data here */
size_t len, /* amount to read */
CURLcode *err); /* error to return */
typedef void Curl_cft_attach_data(struct Curl_cfilter *cf,
struct Curl_easy *data);
typedef void Curl_cft_detach_data(struct Curl_cfilter *cf,
struct Curl_easy *data);
/**
* The easy handle `data` is being detached (no longer served)
* by connection `conn`. All filters are informed to release any resources
* related to `data`.
* Note: there may be several `data` attached to a connection at the same
* time.
*/
void Curl_conn_detach(struct connectdata *conn, struct Curl_easy *data);
#define CF_TYPE_IP_CONNECT (1 << 0)
#define CF_TYPE_SSL (1 << 1)
/* A connection filter type, e.g. specific implementation. */
struct Curl_cftype {
const char *name; /* name of the filter type */
long flags; /* flags of filter type */
Curl_cft_destroy_this *destroy; /* destroy resources of this cf */
Curl_cft_setup *setup; /* setup for a connection */
Curl_cft_connect *connect; /* establish connection */
Curl_cft_close *close; /* close conn */
Curl_cft_get_host *get_host; /* host filter talks to */
Curl_cft_get_select_socks *get_select_socks;/* sockets to select on */
Curl_cft_data_pending *has_data_pending;/* conn has data pending */
Curl_cft_send *do_send; /* send data */
Curl_cft_recv *do_recv; /* receive data */
Curl_cft_attach_data *attach_data; /* data is being handled here */
Curl_cft_detach_data *detach_data; /* data is no longer handled here */
};
/* A connection filter instance, e.g. registered at a connection */
struct Curl_cfilter {
const struct Curl_cftype *cft; /* the type providing implementation */
struct Curl_cfilter *next; /* next filter in chain */
void *ctx; /* filter type specific settings */
struct connectdata *conn; /* the connection this filter belongs to */
int sockindex; /* TODO: like to get rid off this */
BIT(connected); /* != 0 iff this filter is connected */
};
/* Default implementations for the type functions, implementing nop. */
void Curl_cf_def_destroy_this(struct Curl_cfilter *cf,
struct Curl_easy *data);
/* Default implementations for the type functions, implementing pass-through
* the filter chain. */
CURLcode Curl_cf_def_setup(struct Curl_cfilter *cf,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost);
void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data);
CURLcode Curl_cf_def_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done);
void Curl_cf_def_get_host(struct Curl_cfilter *cf, struct Curl_easy *data,
const char **phost, const char **pdisplay_host,
int *pport);
int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks);
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data);
ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err);
ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err);
void Curl_cf_def_attach_data(struct Curl_cfilter *cf,
struct Curl_easy *data);
void Curl_cf_def_detach_data(struct Curl_cfilter *cf,
struct Curl_easy *data);
/**
* Create a new filter instance, unattached to the filter chain.
* Use Curl_conn_cf_add() to add it to the chain.
* @param pcf on success holds the created instance
* @parm cft the filter type
* @param ctx the type specific context to use
*/
CURLcode Curl_cf_create(struct Curl_cfilter **pcf,
const struct Curl_cftype *cft,
void *ctx);
/**
* Add a filter instance to the `sockindex` filter chain at connection
* `data->conn`. The filter must not already be attached. It is inserted at
* the start of the chain (top).
*/
void Curl_conn_cf_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
struct Curl_cfilter *cf);
/**
* Remove and destroy all filters at chain `sockindex` on connection `conn`.
*/
void Curl_conn_cf_discard_all(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
/**
* Discard, e.g. remove and destroy a specific filter instance.
* If the filter is attached to a connection, it will be removed before
* it is destroyed.
*/
void Curl_conn_cf_discard(struct Curl_cfilter *cf, struct Curl_easy *data);
ssize_t Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err);
ssize_t Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err);
#define CURL_CF_SSL_DEFAULT -1
#define CURL_CF_SSL_DISABLE 0
#define CURL_CF_SSL_ENABLE 1
/**
* Setup the filter chain at `sockindex` in connection `conn`, invoking
* the instance `setup(remotehost)` methods. If no filter chain is
* installed yet, inspects the configuration in `data` to install a
* suitable filter chain.
*/
CURLcode Curl_conn_setup(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
const struct Curl_dns_entry *remotehost,
int ssl_mode);
/**
* Bring the filter chain at `sockindex` for connection `data->conn` into
* connected state. Which will set `*done` to TRUE.
* This can be called on an already connected chain with no side effects.
* When not `blocking`, calls may return without error and `*done != TRUE`,
* while the individual filters negotiated the connection.
*/
CURLcode Curl_conn_connect(struct Curl_easy *data, int sockindex,
bool blocking, bool *done);
/**
* Check if the filter chain at `sockindex` for connection `conn` is
* completely connected.
*/
bool Curl_conn_is_connected(struct connectdata *conn, int sockindex);
/**
* Determine if we have reached the remote host on IP level, e.g.
* have a TCP connection. This turns TRUE before a possible SSL
* handshake has been started/done.
*/
bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex);
/**
* Determine if the connection is using SSL to the remote host
* (or will be once connected). This will return FALSE, if SSL
* is only used in proxying and not for the tunnel itself.
*/
bool Curl_conn_is_ssl(struct Curl_easy *data, int sockindex);
/**
* Close the filter chain at `sockindex` for connection `data->conn`.
* Filters remain in place and may be connected again afterwards.
*/
void Curl_conn_close(struct Curl_easy *data, int sockindex);
/**
* Return if data is pending in some connection filter at chain
* `sockindex` for connection `data->conn`.
*/
bool Curl_conn_data_pending(struct Curl_easy *data,
int sockindex);
/**
* Get any select fd flags and the socket filters at chain `sockindex`
* at connection `conn` might be waiting for.
*/
int Curl_conn_get_select_socks(struct Curl_easy *data, int sockindex,
curl_socket_t *socks);
/**
* Receive data through the filter chain at `sockindex` for connection
* `data->conn`. Copy at most `len` bytes into `buf`. Return the
* actuel number of bytes copied or a negative value on error.
* The error code is placed into `*code`.
*/
ssize_t Curl_conn_recv(struct Curl_easy *data, int sockindex, char *buf,
size_t len, CURLcode *code);
/**
* Send `len` bytes of data from `buf` through the filter chain `sockindex`
* at connection `data->conn`. Return the actual number of bytes written
* or a negative value on error.
* The error code is placed into `*code`.
*/
ssize_t Curl_conn_send(struct Curl_easy *data, int sockindex,
const void *buf, size_t len, CURLcode *code);
/**
* The easy handle `data` is being attached (served) by connection `conn`.
* All filters are informed to adapt to handling `data`.
* Note: there may be several `data` attached to a connection at the same
* time.
*/
void Curl_conn_attach_data(struct connectdata *conn,
struct Curl_easy *data);
/**
* The easy handle `data` is being detached (no longer served)
* by connection `conn`. All filters are informed to release any resources
* related to `data`.
* Note: there may be several `data` attached to a connection at the same
* time.
*/
void Curl_conn_detach_data(struct connectdata *conn,
struct Curl_easy *data);
void Curl_conn_get_host(struct Curl_easy *data, int sockindex,
const char **phost, const char **pdisplay_host,
int *pport);
#endif /* HEADER_CURL_CFILTERS_H */
+332 -129
View File
@@ -48,13 +48,6 @@
#include <arpa/inet.h>
#endif
#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
#include <sys/filio.h>
#endif
#ifdef NETWARE
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
@@ -64,6 +57,7 @@
#include "sendf.h"
#include "if2ip.h"
#include "strerror.h"
#include "cfilters.h"
#include "connect.h"
#include "select.h"
#include "url.h" /* for Curl_safefree() */
@@ -79,7 +73,6 @@
#include "share.h"
#include "version_win32.h"
#include "quic.h"
#include "socks.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -237,10 +230,9 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
return timeout_ms;
}
static CURLcode bindlocal(struct Curl_easy *data,
static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
curl_socket_t sockfd, int af, unsigned int scope)
{
struct connectdata *conn = data->conn;
struct Curl_sockaddr_storage sa;
struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
@@ -398,18 +390,23 @@ static CURLcode bindlocal(struct Curl_easy *data,
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
char *scope_ptr = strchr(myhost, '%');
if(scope_ptr)
*(scope_ptr++) = 0;
*(scope_ptr++) = '\0';
#endif
if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
si6->sin6_family = AF_INET6;
si6->sin6_port = htons(port);
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
if(scope_ptr)
if(scope_ptr) {
/* The "myhost" string either comes from Curl_if2ip or from
Curl_printable_address. The latter returns only numeric scope
IDs and the former returns none at all. So the scope ID, if
present, is known to be numeric */
si6->sin6_scope_id = atoi(scope_ptr);
unsigned long scope_id = strtoul(scope_ptr, NULL, 10);
if(scope_id > UINT_MAX)
return CURLE_UNSUPPORTED_PROTOCOL;
si6->sin6_scope_id = (unsigned int)scope_id;
}
#endif
}
sizeof_sa = sizeof(struct sockaddr_in6);
@@ -771,123 +768,45 @@ void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
Curl_persistconninfo(data, conn, local_ip, local_port);
}
/* After a TCP connection to the proxy has been verified, this function does
the next magic steps. If 'done' isn't set TRUE, it is not done yet and
must be called again.
Note: this function's sub-functions call failf()
*/
static CURLcode connect_SOCKS(struct Curl_easy *data, int sockindex,
bool *done)
{
CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_PROXY
CURLproxycode pxresult = CURLPX_OK;
struct connectdata *conn = data->conn;
if(conn->bits.socksproxy) {
/* for the secondary socket (FTP), use the "connect to host"
* but ignore the "connect to port" (use the secondary port)
*/
const char * const host =
conn->bits.httpproxy ?
conn->http_proxy.host.name :
conn->bits.conn_to_host ?
conn->conn_to_host.name :
sockindex == SECONDARYSOCKET ?
conn->secondaryhostname : conn->host.name;
const int port =
conn->bits.httpproxy ? (int)conn->http_proxy.port :
sockindex == SECONDARYSOCKET ? conn->secondary_port :
conn->bits.conn_to_port ? conn->conn_to_port :
conn->remote_port;
switch(conn->socks_proxy.proxytype) {
case CURLPROXY_SOCKS5:
case CURLPROXY_SOCKS5_HOSTNAME:
pxresult = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
host, port, sockindex, data, done);
break;
case CURLPROXY_SOCKS4:
case CURLPROXY_SOCKS4A:
pxresult = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
data, done);
break;
default:
failf(data, "unknown proxytype option given");
result = CURLE_COULDNT_CONNECT;
} /* switch proxytype */
if(pxresult) {
result = CURLE_PROXY;
data->info.pxcode = pxresult;
}
}
else
#else
(void)data;
(void)sockindex;
#endif /* CURL_DISABLE_PROXY */
*done = TRUE; /* no SOCKS proxy, so consider us connected */
return result;
}
/*
* post_SOCKS() is called after a successful connect to the peer, which
* *could* be a SOCKS proxy
* post_connect() is called after a successful connect to the peer
*/
static void post_SOCKS(struct Curl_easy *data,
static void post_connect(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
bool *connected)
int sockindex)
{
conn->bits.tcpconnect[sockindex] = TRUE;
*connected = TRUE;
if(sockindex == FIRSTSOCKET)
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
Curl_updateconninfo(data, conn, conn->sock[sockindex]);
Curl_verboseconnect(data, conn);
data->info.numconnects++; /* to track the number of connections made */
}
/*
* Curl_is_connected() checks if the socket has connected.
* is_connected() checks if the socket has connected.
*/
CURLcode Curl_is_connected(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
bool *connected)
static CURLcode is_connected(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
bool *connected)
{
CURLcode result = CURLE_OK;
timediff_t allow;
int error = 0;
struct curltime now;
int rc = 0;
unsigned int i;
int i;
DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
*connected = FALSE; /* a very negative world view is best */
if(conn->bits.tcpconnect[sockindex]) {
/* we are connected already! */
*connected = TRUE;
return CURLE_OK;
}
now = Curl_now();
if(SOCKS_STATE(conn->cnnct.state)) {
/* still doing SOCKS */
result = connect_SOCKS(data, sockindex, connected);
if(!result && *connected)
post_SOCKS(data, conn, sockindex, connected);
return result;
}
/* Check if any of the conn->tempsock we use for establishing connections
* succeeded and, if so, close any ongoing other ones.
* Transfer the successful conn->tempsock to conn->sock[sockindex]
* and set conn->tempsock to CURL_SOCKET_BAD.
* If transport is QUIC, we need to shutdown the ongoing 'other'
* connect attempts in a QUIC appropriate way. */
for(i = 0; i<2; i++) {
const int other = i ^ 1;
if(conn->tempsock[i] == CURL_SOCKET_BAD)
@@ -901,7 +820,7 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
conn->sock[sockindex] = conn->tempsock[i];
conn->ip_addr = conn->tempaddr[i];
conn->tempsock[i] = CURL_SOCKET_BAD;
post_SOCKS(data, conn, sockindex, connected);
post_connect(data, conn, sockindex);
connkeep(conn, "HTTP/3 default");
if(conn->tempsock[other] != CURL_SOCKET_BAD)
Curl_quic_disconnect(data, conn, other);
@@ -963,14 +882,7 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
conn->tempsock[other] = CURL_SOCKET_BAD;
}
/* see if we need to kick off any SOCKS proxy magic once we
connected */
result = connect_SOCKS(data, sockindex, connected);
if(result || !*connected)
return result;
post_SOCKS(data, conn, sockindex, connected);
*connected = TRUE;
return CURLE_OK;
}
}
@@ -1207,7 +1119,7 @@ static CURLcode singleipconnect(struct Curl_easy *data,
return result;
/* store remote address and port used in this connection attempt */
if(!Curl_addr2string((struct sockaddr*)&addr.sa_addr, addr.addrlen,
if(!Curl_addr2string(&addr.sa_addr, addr.addrlen,
ipaddress, &port)) {
/* malformed address or bug in inet_ntop, try next address */
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
@@ -1261,8 +1173,8 @@ static CURLcode singleipconnect(struct Curl_easy *data,
|| addr.family == AF_INET6
#endif
) {
result = bindlocal(data, sockfd, addr.family,
Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
result = bindlocal(data, conn, sockfd, addr.family,
Curl_ipv6_scope(&addr.sa_addr));
if(result) {
Curl_closesocket(data, conn, sockfd); /* close socket and bail out */
if(result == CURLE_UNSUPPORTED_PROTOCOL) {
@@ -1521,12 +1433,13 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
/*
* Check if a connection seems to be alive.
*/
bool Curl_connalive(struct connectdata *conn)
bool Curl_connalive(struct Curl_easy *data, struct connectdata *conn)
{
(void)data;
/* First determine if ssl */
if(conn->ssl[FIRSTSOCKET].use) {
if(Curl_conn_is_ssl(data, FIRSTSOCKET)) {
/* use the SSL context */
if(!Curl_ssl_check_cxn(conn))
if(!Curl_ssl_check_cxn(data, conn))
return false; /* FIN received */
}
/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
@@ -1714,16 +1627,306 @@ void Curl_conncontrol(struct connectdata *conn,
}
}
/* Data received can be cached at various levels, so check them all here. */
bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
typedef enum {
SCFST_INIT,
SCFST_WAITING,
SCFST_DONE
} cf_connect_state;
struct socket_cf_ctx {
const struct Curl_dns_entry *remotehost;
cf_connect_state state;
};
static int socket_cf_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
{
struct connectdata *conn = cf->conn;
int i, s, rc = GETSOCK_BLANK;
(void)data;
if(cf->connected) {
return rc;
}
for(i = s = 0; i<2; i++) {
if(conn->tempsock[i] != CURL_SOCKET_BAD) {
socks[s] = conn->tempsock[i];
rc |= GETSOCK_WRITESOCK(s);
#ifdef ENABLE_QUIC
if(conn->transport == TRNSPRT_QUIC)
/* when connecting QUIC, we want to read the socket too */
rc |= GETSOCK_READSOCK(s);
#endif
s++;
}
}
return rc;
}
static CURLcode socket_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
{
struct connectdata *conn = cf->conn;
int sockindex = cf->sockindex;
struct socket_cf_ctx *ctx = cf->ctx;
CURLcode result = CURLE_OK;
if(cf->connected) {
*done = TRUE;
return CURLE_OK;
}
(void)blocking;
DEBUGASSERT(ctx);
*done = FALSE;
switch(ctx->state) {
case SCFST_INIT:
DEBUGASSERT(CURL_SOCKET_BAD == conn->sock[sockindex]);
DEBUGASSERT(!cf->connected);
result = Curl_connecthost(data, conn, ctx->remotehost);
if(!result)
ctx->state = SCFST_WAITING;
break;
case SCFST_WAITING:
result = is_connected(data, conn, sockindex, done);
if(!result && *done) {
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
if(Curl_conn_is_ssl(data, FIRSTSOCKET) ||
(conn->handler->protocol & PROTO_FAMILY_SSH))
Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
post_connect(data, conn, sockindex);
ctx->state = SCFST_DONE;
cf->connected = TRUE;
}
break;
case SCFST_DONE:
*done = TRUE;
break;
}
return result;
}
static CURLcode socket_cf_setup(struct Curl_cfilter *cf,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost)
{
struct socket_cf_ctx *ctx = cf->ctx;
(void)data;
DEBUGASSERT(ctx);
if(ctx->remotehost != remotehost) {
if(ctx->remotehost) {
/* switching dns entry? TODO: reset? */
}
ctx->remotehost = remotehost;
}
DEBUGF(infof(data, CFMSG(cf, "setup(remotehost=%s)"),
cf->conn->hostname_resolve));
return CURLE_OK;
}
static void socket_cf_close(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
int sockindex = cf->sockindex;
struct socket_cf_ctx *ctx = cf->ctx;
DEBUGASSERT(ctx);
/* close possibly still open sockets */
if(CURL_SOCKET_BAD != cf->conn->sock[sockindex]) {
Curl_closesocket(data, cf->conn, cf->conn->sock[sockindex]);
cf->conn->sock[sockindex] = CURL_SOCKET_BAD;
}
if(CURL_SOCKET_BAD != cf->conn->tempsock[sockindex]) {
Curl_closesocket(data, cf->conn, cf->conn->tempsock[sockindex]);
cf->conn->tempsock[sockindex] = CURL_SOCKET_BAD;
}
cf->connected = FALSE;
ctx->state = SCFST_INIT;
}
static void socket_cf_get_host(struct Curl_cfilter *cf,
struct Curl_easy *data,
const char **phost,
const char **pdisplay_host,
int *pport)
{
(void)data;
*phost = cf->conn->host.name;
*pdisplay_host = cf->conn->host.dispname;
*pport = cf->conn->port;
}
static bool socket_cf_data_pending(struct Curl_cfilter *cf,
const struct Curl_easy *data)
{
int readable;
DEBUGASSERT(conn);
(void)data;
DEBUGASSERT(cf);
if(Curl_ssl_data_pending(conn, sockindex) ||
Curl_recv_has_postponed_data(conn, sockindex))
return true;
readable = SOCKET_READABLE(conn->sock[sockindex], 0);
readable = SOCKET_READABLE(cf->conn->sock[cf->sockindex], 0);
return (readable > 0 && (readable & CURL_CSELECT_IN));
}
static ssize_t socket_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *buf, size_t len, CURLcode *err)
{
ssize_t nwritten;
nwritten = Curl_send_plain(data, cf->sockindex, buf, len, err);
return nwritten;
}
static ssize_t socket_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *buf, size_t len, CURLcode *err)
{
ssize_t nread;
nread = Curl_recv_plain(data, cf->sockindex, buf, len, err);
return nread;
}
static void socket_cf_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct socket_cf_ctx *state = cf->ctx;
(void)data;
if(cf->connected) {
socket_cf_close(cf, data);
}
/* release any resources held in state */
Curl_safefree(state);
}
static const struct Curl_cftype cft_socket = {
"SOCKET",
CF_TYPE_IP_CONNECT,
socket_cf_destroy,
socket_cf_setup,
socket_cf_connect,
socket_cf_close,
socket_cf_get_host,
socket_cf_get_select_socks,
socket_cf_data_pending,
socket_cf_send,
socket_cf_recv,
Curl_cf_def_attach_data,
Curl_cf_def_detach_data,
};
CURLcode Curl_conn_socket_set(struct Curl_easy *data,
struct connectdata *conn,
int sockindex)
{
CURLcode result;
struct Curl_cfilter *cf = NULL;
struct socket_cf_ctx *scf_ctx = NULL;
/* Need to be first */
DEBUGASSERT(conn);
DEBUGASSERT(!conn->cfilter[sockindex]);
scf_ctx = calloc(sizeof(*scf_ctx), 1);
if(!scf_ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
result = Curl_cf_create(&cf, &cft_socket, scf_ctx);
if(result)
goto out;
Curl_conn_cf_add(data, conn, sockindex, cf);
out:
if(result) {
Curl_safefree(cf);
Curl_safefree(scf_ctx);
}
return result;
}
static CURLcode socket_accept_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
{
/* we start accepted, if we ever close, we cannot go on */
(void)data;
(void)blocking;
if(cf->connected) {
*done = TRUE;
return CURLE_OK;
}
return CURLE_FAILED_INIT;
}
static CURLcode socket_accept_cf_setup(struct Curl_cfilter *cf,
struct Curl_easy *data,
const struct Curl_dns_entry *remotehost)
{
/* we start accepted, if we ever close, we cannot go on */
(void)data;
(void)remotehost;
if(cf->connected) {
return CURLE_OK;
}
return CURLE_FAILED_INIT;
}
static const struct Curl_cftype cft_socket_accept = {
"SOCKET-ACCEPT",
CF_TYPE_IP_CONNECT,
socket_cf_destroy,
socket_accept_cf_setup,
socket_accept_cf_connect,
socket_cf_close,
socket_cf_get_host, /* TODO: not accurate */
Curl_cf_def_get_select_socks,
socket_cf_data_pending,
socket_cf_send,
socket_cf_recv,
Curl_cf_def_attach_data,
Curl_cf_def_detach_data,
};
CURLcode Curl_conn_socket_accepted_set(struct Curl_easy *data,
struct connectdata *conn,
int sockindex, curl_socket_t *s)
{
CURLcode result;
struct Curl_cfilter *cf = NULL;
struct socket_cf_ctx *scf_ctx = NULL;
cf = conn->cfilter[sockindex];
if(cf && cf->cft == &cft_socket_accept) {
/* already an accept filter installed, just replace the socket */
scf_ctx = cf->ctx;
result = CURLE_OK;
}
else {
/* replace any existing */
Curl_conn_cf_discard_all(data, conn, sockindex);
scf_ctx = calloc(sizeof(*scf_ctx), 1);
if(!scf_ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
result = Curl_cf_create(&cf, &cft_socket_accept, scf_ctx);
if(result)
goto out;
Curl_conn_cf_add(data, conn, sockindex, cf);
}
/* close any existing socket and replace */
Curl_closesocket(data, conn, conn->sock[sockindex]);
conn->sock[sockindex] = *s;
conn->bits.sock_accepted = TRUE;
cf->connected = TRUE;
scf_ctx->state = SCFST_DONE;
out:
if(result) {
Curl_safefree(cf);
Curl_safefree(scf_ctx);
}
return result;
}
+9 -7
View File
@@ -29,11 +29,6 @@
#include "sockaddr.h"
#include "timeval.h"
CURLcode Curl_is_connected(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
bool *connected);
CURLcode Curl_connecthost(struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_dns_entry *host);
@@ -61,7 +56,7 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
/*
* Check if a connection seems to be alive.
*/
bool Curl_connalive(struct connectdata *conn);
bool Curl_connalive(struct Curl_easy *data, struct connectdata *conn);
#ifdef USE_WINSOCK
/* When you run a program that uses the Windows Sockets API, you may
@@ -153,6 +148,13 @@ void Curl_conncontrol(struct connectdata *conn,
#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP)
#endif
bool Curl_conn_data_pending(struct connectdata *conn, int sockindex);
CURLcode Curl_conn_socket_set(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
CURLcode Curl_conn_socket_accepted_set(struct Curl_easy *data,
struct connectdata *conn,
int sockindex,
curl_socket_t *s);
#endif /* HEADER_CURL_CONNECT_H */
+16 -10
View File
@@ -300,12 +300,11 @@ static char *sanitize_cookie_path(const char *cookie_path)
/* some stupid site sends path attribute with '"'. */
len = strlen(new_path);
if(new_path[0] == '\"') {
memmove((void *)new_path, (const void *)(new_path + 1), len);
memmove(new_path, new_path + 1, len);
len--;
}
if(len && (new_path[len - 1] == '\"')) {
new_path[len - 1] = 0x0;
len--;
new_path[--len] = 0x0;
}
/* RFC6265 5.2.4 The Path Attribute */
@@ -515,7 +514,7 @@ Curl_cookie_add(struct Curl_easy *data,
return NULL; /* bail out if we're this low on memory */
if(httpheader) {
/* This line was read off a HTTP-header */
/* This line was read off an HTTP-header */
char name[MAX_NAME];
char what[MAX_NAME];
const char *ptr;
@@ -605,9 +604,9 @@ Curl_cookie_add(struct Curl_easy *data,
* only test for names where that can possibly be true.
*/
if(nlen > 3 && name[0] == '_' && name[1] == '_') {
if(!strncmp("__Secure-", name, 9))
if(strncasecompare("__Secure-", name, 9))
co->prefix |= COOKIE_PREFIX__SECURE;
else if(!strncmp("__Host-", name, 7))
else if(strncasecompare("__Host-", name, 7))
co->prefix |= COOKIE_PREFIX__HOST;
}
@@ -780,10 +779,16 @@ Curl_cookie_add(struct Curl_easy *data,
offt = curlx_strtoofft((*co->maxage == '\"')?
&co->maxage[1]:&co->maxage[0], NULL, 10,
&co->expires);
if(offt == CURL_OFFT_FLOW)
switch(offt) {
case CURL_OFFT_FLOW:
/* overflow, used max value */
co->expires = CURL_OFF_T_MAX;
else if(!offt) {
break;
case CURL_OFFT_INVAL:
/* negative or otherwise bad, expire */
co->expires = 1;
break;
case CURL_OFFT_OK:
if(!co->expires)
/* already expired */
co->expires = 1;
@@ -792,6 +797,7 @@ Curl_cookie_add(struct Curl_easy *data,
co->expires = CURL_OFF_T_MAX;
else
co->expires += now;
break;
}
}
else if(co->expirestr) {
@@ -864,7 +870,7 @@ Curl_cookie_add(struct Curl_easy *data,
}
else {
/*
* This line is NOT a HTTP header style line, we do offer support for
* This line is NOT an HTTP header style line, we do offer support for
* reading the odd netscape cookies-file format here
*/
char *ptr;
@@ -1258,7 +1264,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
fp = NULL;
}
else {
fp = fopen(file, FOPEN_READTEXT);
fp = fopen(file, "rb");
if(!fp)
infof(data, "WARNING: failed to open cookie file \"%s\"", file);
}
-5
View File
@@ -47,11 +47,6 @@
# include <inet.h>
#endif
#if defined(NETWARE) && defined(__NOVELL_LIBC__)
# undef in_addr_t
# define in_addr_t unsigned long
#endif
#include <stddef.h>
#include "curl_addrinfo.h"
-12
View File
@@ -143,9 +143,6 @@
/* Define to 1 if you have the <arpa/tftp.h> header file. */
#cmakedefine HAVE_ARPA_TFTP_H 1
/* Define to 1 if you have the <assert.h> header file. */
#cmakedefine HAVE_ASSERT_H 1
/* Define to 1 if you have _Atomic support. */
#cmakedefine HAVE_ATOMIC 1
@@ -167,9 +164,6 @@
/* Define to 1 if you have the `closesocket' function. */
#cmakedefine HAVE_CLOSESOCKET 1
/* Define to 1 if you have the <errno.h> header file. */
#cmakedefine HAVE_ERRNO_H 1
/* Define to 1 if you have the fcntl function. */
#cmakedefine HAVE_FCNTL 1
@@ -590,9 +584,6 @@
/* Define to 1 if you have the ws2tcpip.h header file. */
#cmakedefine HAVE_WS2TCPIP_H 1
/* Define if you have the <process.h> header file. */
#cmakedefine HAVE_PROCESS_H 1
/* Define to 1 if you need the lber.h header file even with ldap.h */
#cmakedefine NEED_LBER_H 1
@@ -806,8 +797,5 @@ ${SIZEOF_TIME_T_CODE}
/* to enable Windows IDN */
#cmakedefine USE_WIN32_IDN 1
/* to make the compiler know the prototypes of Windows IDN APIs */
#cmakedefine WANT_IDN_PROTOTYPES 1
/* Define to 1 to enable websocket support. */
#cmakedefine USE_WEBSOCKETS 1
-9
View File
@@ -33,13 +33,4 @@ unsigned int Curl_read32_le(const unsigned char *buf);
/* Converts a 16-bit integer from big endian */
unsigned short Curl_read16_be(const unsigned char *buf);
#if (SIZEOF_CURL_OFF_T > 4)
/* Converts a 64-bit integer to little endian */
#if defined(HAVE_LONGLONG)
void Curl_write64_le(const long long value, unsigned char *buffer);
#else
void Curl_write64_le(const __int64 value, unsigned char *buffer);
#endif
#endif
#endif /* HEADER_CURL_ENDIAN_H */
+3 -4
View File
@@ -76,9 +76,9 @@ static int parsekeyword(unsigned char **pattern, unsigned char *charset)
parsekey_state state = CURLFNM_PKW_INIT;
#define KEYLEN 10
char keyword[KEYLEN] = { 0 };
int found = FALSE;
int i;
unsigned char *p = *pattern;
bool found = FALSE;
for(i = 0; !found; i++) {
char c = *p++;
if(i >= KEYLEN)
@@ -368,14 +368,13 @@ int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
*/
int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
{
int rc;
(void)ptr; /* the argument is specified by the curl_fnmatch_callback
prototype, but not used by Curl_fnmatch() */
if(!pattern || !string) {
return CURL_FNMATCH_FAIL;
}
rc = fnmatch(pattern, string, 0);
switch(rc) {
switch(fnmatch(pattern, string, 0)) {
case 0:
return CURL_FNMATCH_MATCH;
case FNM_NOMATCH:
+27 -3
View File
@@ -41,17 +41,41 @@ char *Curl_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(!rlen)
break;
if(b[rlen-1] == '\n') {
/* b is \n terminated */
if(partial) {
partial = FALSE;
continue;
}
return b;
}
/* read a partial, discard the next piece that ends with newline */
partial = TRUE;
else if(feof(input)) {
if(partial)
/* Line is already too large to return, ignore rest */
break;
if(rlen + 1 < (size_t) len) {
/* b is EOF terminated, insert missing \n */
b[rlen] = '\n';
b[rlen + 1] = '\0';
return b;
}
else
/* Maximum buffersize reached + EOF
* This line is impossible to add a \n to so we'll ignore it
*/
break;
}
else
/* Maximum buffersize reached */
partial = TRUE;
}
else
break;
+5 -4
View File
@@ -186,9 +186,9 @@ static void setup_des_key(const unsigned char *key_56,
#elif defined(USE_NSS)
/*
* Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using
* the expanded key. The caller is responsible for giving 64 bit of valid
* data is IN and (at least) 64 bit large buffer as OUT.
* encrypt_des() expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of
* data, using the expanded key. IN should point to 64 bits of source data,
* OUT to a 64 bit output buffer.
*/
static bool encrypt_des(const unsigned char *in, unsigned char *out,
const unsigned char *key_56)
@@ -658,7 +658,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
LONGQUARTET(tw.dwLowDateTime), LONGQUARTET(tw.dwHighDateTime));
memcpy(ptr + 32, challenge_client, 8);
memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len);
if(ntlm->target_info_len)
memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len);
/* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
memcpy(ptr + 8, &ntlm->nonce[0], 8);
+1 -1
View File
@@ -385,7 +385,7 @@ CURLcode Curl_output_ntlm_wb(struct Curl_easy *data, struct connectdata *conn,
bool proxy)
{
/* point to the address of the pointer that holds the string to send to the
server, which is for a plain host or for a HTTP proxy */
server, which is for a plain host or for an HTTP proxy */
char **allocuserpwd;
/* point to the name and password for this */
const char *userp;
+7 -7
View File
@@ -71,10 +71,14 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data,
/* It is referenced to the home directory, so strip the
leading '/' */
memcpy(real_path, homedir, homelen);
real_path[homelen] = '/';
real_path[homelen + 1] = '\0';
/* Only add a trailing '/' if homedir does not end with one */
if(homelen == 0 || real_path[homelen - 1] != '/') {
real_path[homelen] = '/';
homelen++;
real_path[homelen] = '\0';
}
if(working_path_len > 3) {
memcpy(real_path + homelen + 1, working_path + 3,
memcpy(real_path + homelen, working_path + 3,
1 + working_path_len -3);
}
}
@@ -148,15 +152,12 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
break;
}
if(cp[i] == '\0') { /* End of string */
/*error("Unterminated quote");*/
goto fail;
}
if(cp[i] == '\\') { /* Escaped characters */
i++;
if(cp[i] != '\'' && cp[i] != '\"' &&
cp[i] != '\\') {
/*error("Bad escaped character '\\%c'",
cp[i]);*/
goto fail;
}
}
@@ -164,7 +165,6 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
}
if(j == 0) {
/*error("Empty quotes");*/
goto fail;
}
*cpp = cp + i + strspn(cp + i, WHITESPACE);
+2 -2
View File
@@ -44,12 +44,12 @@ CURLcode Curl_range(struct Curl_easy *data)
if(data->state.use_range && data->state.range) {
CURLofft from_t;
CURLofft to_t;
from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
from_t = curlx_strtoofft(data->state.range, &ptr, 10, &from);
if(from_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
ptr++;
to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
to_t = curlx_strtoofft(ptr, &ptr2, 10, &to);
if(to_t == CURL_OFFT_FLOW)
return CURLE_RANGE_ERROR;
if((to_t == CURL_OFFT_INVAL) && !from_t) {
+6 -6
View File
@@ -85,7 +85,7 @@ const struct Curl_handler Curl_handler_rtmp = {
PORT_RTMP, /* defport */
CURLPROTO_RTMP, /* protocol */
CURLPROTO_RTMP, /* family */
PROTOPT_NONE /* flags*/
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmpt = {
@@ -108,7 +108,7 @@ const struct Curl_handler Curl_handler_rtmpt = {
PORT_RTMPT, /* defport */
CURLPROTO_RTMPT, /* protocol */
CURLPROTO_RTMPT, /* family */
PROTOPT_NONE /* flags*/
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmpe = {
@@ -131,7 +131,7 @@ const struct Curl_handler Curl_handler_rtmpe = {
PORT_RTMP, /* defport */
CURLPROTO_RTMPE, /* protocol */
CURLPROTO_RTMPE, /* family */
PROTOPT_NONE /* flags*/
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmpte = {
@@ -154,7 +154,7 @@ const struct Curl_handler Curl_handler_rtmpte = {
PORT_RTMPT, /* defport */
CURLPROTO_RTMPTE, /* protocol */
CURLPROTO_RTMPTE, /* family */
PROTOPT_NONE /* flags*/
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmps = {
@@ -177,7 +177,7 @@ const struct Curl_handler Curl_handler_rtmps = {
PORT_RTMPS, /* defport */
CURLPROTO_RTMPS, /* protocol */
CURLPROTO_RTMP, /* family */
PROTOPT_NONE /* flags*/
PROTOPT_NONE /* flags */
};
const struct Curl_handler Curl_handler_rtmpts = {
@@ -200,7 +200,7 @@ const struct Curl_handler Curl_handler_rtmpts = {
PORT_RTMPS, /* defport */
CURLPROTO_RTMPTS, /* protocol */
CURLPROTO_RTMPT, /* family */
PROTOPT_NONE /* flags*/
PROTOPT_NONE /* flags */
};
static CURLcode rtmp_setup_connection(struct Curl_easy *data,
+7 -4
View File
@@ -44,6 +44,7 @@
#include "curl_base64.h"
#include "curl_md5.h"
#include "vauth/vauth.h"
#include "cfilters.h"
#include "vtls/vtls.h"
#include "curl_hmac.h"
#include "curl_sasl.h"
@@ -340,8 +341,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
struct bufref resp;
saslstate state1 = SASL_STOP;
saslstate state2 = SASL_FINAL;
const char * const hostname = SSL_HOST_NAME();
const long int port = SSL_HOST_PORT();
const char *hostname, *disp_hostname;
int port;
#if defined(USE_KERBEROS5) || defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
@@ -350,6 +351,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
const char *oauth_bearer = data->set.str[STRING_BEARER];
struct bufref nullmsg;
Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &disp_hostname, &port);
Curl_bufref_init(&nullmsg);
Curl_bufref_init(&resp);
sasl->force_ir = force_ir; /* Latch for future use */
@@ -525,8 +527,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
struct connectdata *conn = data->conn;
saslstate newstate = SASL_FINAL;
struct bufref resp;
const char * const hostname = SSL_HOST_NAME();
const long int port = SSL_HOST_PORT();
const char *hostname, *disp_hostname;
int port;
#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
@@ -536,6 +538,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
const char *oauth_bearer = data->set.str[STRING_BEARER];
struct bufref serverdata;
Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &disp_hostname, &port);
Curl_bufref_init(&serverdata);
Curl_bufref_init(&resp);
*progress = SASL_INPROGRESS;
+6 -4
View File
@@ -92,7 +92,7 @@
# endif
#endif
#if defined(macintosh) && defined(__MRC__)
#ifdef macintosh
# include "config-mac.h"
#endif
@@ -112,6 +112,10 @@
# include "config-plan9.h"
#endif
#ifdef MSDOS
# include "config-dos.h"
#endif
#endif /* HAVE_CONFIG_H */
#if defined(_MSC_VER)
@@ -322,9 +326,7 @@
#endif
#include <stdio.h>
#ifdef HAVE_ASSERT_H
#include <assert.h>
#endif
#ifdef __TANDEM /* for ns*-tandem-nsk systems */
# if ! defined __LP64
@@ -708,7 +710,7 @@
# define UNUSED_PARAM __attribute__((__unused__))
# define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
# define UNUSED_PARAM /*NOTHING*/
# define UNUSED_PARAM /* NOTHING */
# define WARN_UNUSED_RESULT
#endif
+1 -4
View File
@@ -34,10 +34,7 @@
#include <string.h>
#include <stdarg.h>
#include <time.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -287,7 +284,7 @@ typedef unsigned int bit;
*/
#undef DEBUGASSERT
#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H)
#if defined(DEBUGBUILD)
#define DEBUGASSERT(x) assert(x)
#else
#define DEBUGASSERT(x) do { } while(0)
+1 -1
View File
@@ -33,7 +33,7 @@ extern const struct HMAC_params Curl_HMAC_SHA256[1];
#ifdef USE_WOLFSSL
/* SHA256_DIGEST_LENGTH is an enum value in wolfSSL. Need to import it from
* sha.h*/
* sha.h */
#include <wolfssl/options.h>
#include <wolfssl/openssl/sha.h>
#else
+1 -3
View File
@@ -31,9 +31,7 @@
# include <pthread.h>
# endif
#elif defined(USE_THREADS_WIN32)
# ifdef HAVE_PROCESS_H
# include <process.h>
# endif
# include <process.h>
#endif
#include "curl_threads.h"
+1 -1
View File
@@ -319,4 +319,4 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
return CURLE_OK;
}
#endif /*CURL_DISABLE_DICT*/
#endif /* CURL_DISABLE_DICT */
+2 -3
View File
@@ -71,7 +71,6 @@
#include "mime.h"
#include "amigaos.h"
#include "warnless.h"
#include "multiif.h"
#include "sigpipe.h"
#include "vssh/ssh.h"
#include "setopt.h"
@@ -829,7 +828,7 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
/* Copy src->set into dst->set first, then deal with the strings
afterwards */
dst->set = src->set;
Curl_mime_initpart(&dst->set.mimepost, dst);
Curl_mime_initpart(&dst->set.mimepost);
/* clear all string pointers first */
memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
@@ -863,7 +862,7 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
}
/* Duplicate mime data. */
result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost);
result = Curl_mime_duppart(dst, &dst->set.mimepost, &src->set.mimepost);
if(src->set.resolve)
dst->state.resolve = dst->set.resolve;
+3 -1
View File
@@ -42,6 +42,7 @@ struct curl_easyoption Curl_easyopts[] = {
{"CAINFO", CURLOPT_CAINFO, CURLOT_STRING, 0},
{"CAINFO_BLOB", CURLOPT_CAINFO_BLOB, CURLOT_BLOB, 0},
{"CAPATH", CURLOPT_CAPATH, CURLOT_STRING, 0},
{"CA_CACHE_TIMEOUT", CURLOPT_CA_CACHE_TIMEOUT, CURLOT_LONG, 0},
{"CERTINFO", CURLOPT_CERTINFO, CURLOT_LONG, 0},
{"CHUNK_BGN_FUNCTION", CURLOPT_CHUNK_BGN_FUNCTION, CURLOT_FUNCTION, 0},
{"CHUNK_DATA", CURLOPT_CHUNK_DATA, CURLOT_CBPTR, 0},
@@ -241,6 +242,7 @@ struct curl_easyoption Curl_easyopts[] = {
CURLOT_STRING, 0},
{"PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE, CURLOT_LONG, 0},
{"PUT", CURLOPT_PUT, CURLOT_LONG, 0},
{"QUICK_EXIT", CURLOPT_QUICK_EXIT, CURLOT_LONG, 0},
{"QUOTE", CURLOPT_QUOTE, CURLOT_SLIST, 0},
{"RANDOM_FILE", CURLOPT_RANDOM_FILE, CURLOT_STRING, 0},
{"RANGE", CURLOPT_RANGE, CURLOT_STRING, 0},
@@ -368,6 +370,6 @@ struct curl_easyoption Curl_easyopts[] = {
*/
int Curl_easyopts_check(void)
{
return ((CURLOPT_LASTENTRY%10000) != (320 + 1));
return ((CURLOPT_LASTENTRY%10000) != (322 + 1));
}
#endif
+1 -1
View File
@@ -202,7 +202,7 @@ char *curl_easy_unescape(struct Curl_easy *data, const char *string,
char *str = NULL;
(void)data;
if(length >= 0) {
size_t inputlen = length;
size_t inputlen = (size_t)length;
size_t outputlen;
CURLcode res = Curl_urldecode(string, inputlen, &str, &outputlen,
REJECT_NADA);
+18 -7
View File
@@ -150,9 +150,19 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
char *actual_path;
#endif
size_t real_path_len;
CURLcode result;
CURLcode result = Curl_urldecode(data->state.up.path, 0, &real_path,
&real_path_len, REJECT_ZERO);
if(file->path) {
/* already connected.
* the handler->connect_it() is normally only called once, but
* FILE does a special check on setting up the connection which
* calls this explicitly. */
*done = TRUE;
return CURLE_OK;
}
result = Curl_urldecode(data->state.up.path, 0, &real_path,
&real_path_len, REJECT_ZERO);
if(result)
return result;
@@ -226,6 +236,7 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
file->path = real_path;
#endif
#endif
Curl_safefree(file->freepath);
file->freepath = real_path; /* free this when done */
file->fd = fd;
@@ -329,7 +340,7 @@ static CURLcode file_upload(struct Curl_easy *data)
while(!result) {
size_t nread;
size_t nwrite;
ssize_t nwrite;
size_t readcount;
result = Curl_fillreadbuffer(data, data->set.buffer_size, &readcount);
if(result)
@@ -340,7 +351,7 @@ static CURLcode file_upload(struct Curl_easy *data)
nread = readcount;
/*skip bytes before resume point*/
/* skip bytes before resume point */
if(data->state.resume_from) {
if((curl_off_t)nread <= data->state.resume_from) {
data->state.resume_from -= nread;
@@ -358,7 +369,7 @@ static CURLcode file_upload(struct Curl_easy *data)
/* write the data to the target */
nwrite = write(fd, buf2, nread);
if(nwrite != nread) {
if((size_t)nwrite != nread) {
result = CURLE_SEND_ERROR;
break;
}
@@ -471,13 +482,13 @@ static CURLcode file_do(struct Curl_easy *data, bool *done)
tm->tm_hour,
tm->tm_min,
tm->tm_sec,
data->set.opt_no_body ? "": "\r\n");
data->req.no_body ? "": "\r\n");
result = Curl_client_write(data, CLIENTWRITE_HEADER, header, headerlen);
if(result)
return result;
/* set the file size to make it available post transfer */
Curl_pgrsSetDownloadSize(data, expected_size);
if(data->set.opt_no_body)
if(data->req.no_body)
return result;
}
+10 -12
View File
@@ -59,7 +59,7 @@
*
* AddHttpPost()
*
* Adds a HttpPost structure to the list, if parent_post is given becomes
* Adds an HttpPost structure to the list, if parent_post is given becomes
* a subpost of parent_post instead of a direct list element.
*
* Returns newly allocated HttpPost on success and NULL if malloc failed.
@@ -135,15 +135,13 @@ static struct FormInfo *AddFormInfo(char *value,
{
struct FormInfo *form_info;
form_info = calloc(1, sizeof(struct FormInfo));
if(form_info) {
if(value)
form_info->value = value;
if(contenttype)
form_info->contenttype = contenttype;
form_info->flags = HTTPPOST_FILENAME;
}
else
if(!form_info)
return NULL;
if(value)
form_info->value = value;
if(contenttype)
form_info->contenttype = contenttype;
form_info->flags = HTTPPOST_FILENAME;
if(parent_form_info) {
/* now, point our 'more' to the original 'more' */
@@ -199,7 +197,7 @@ static struct FormInfo *AddFormInfo(char *value,
* CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed
* CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used
* CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error)
* CURL_FORMADD_MEMORY if a HttpPost struct cannot be allocated
* CURL_FORMADD_MEMORY if an HttpPost struct cannot be allocated
* CURL_FORMADD_MEMORY if some allocation for string copying failed.
* CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array
*
@@ -717,10 +715,10 @@ int curl_formget(struct curl_httppost *form, void *arg,
CURLcode result;
curl_mimepart toppart;
Curl_mime_initpart(&toppart, NULL); /* default form is empty */
Curl_mime_initpart(&toppart); /* default form is empty */
result = Curl_getformdata(NULL, &toppart, form, NULL);
if(!result)
result = Curl_mime_prepare_headers(&toppart, "multipart/form-data",
result = Curl_mime_prepare_headers(NULL, &toppart, "multipart/form-data",
NULL, MIMESTRATEGY_FORM);
while(!result) {
+107 -143
View File
@@ -43,11 +43,6 @@
#include <inet.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
@@ -65,6 +60,7 @@
#include "strtoofft.h"
#include "strcase.h"
#include "vtls/vtls.h"
#include "cfilters.h"
#include "connect.h"
#include "strerror.h"
#include "inet_ntop.h"
@@ -74,7 +70,6 @@
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
#include "multiif.h"
#include "url.h"
#include "strcase.h"
#include "speedcheck.h"
#include "warnless.h"
#include "http_proxy.h"
@@ -219,14 +214,8 @@ const struct Curl_handler Curl_handler_ftps = {
static void close_secondarysocket(struct Curl_easy *data,
struct connectdata *conn)
{
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
}
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
#ifndef CURL_DISABLE_PROXY
conn->bits.proxy_ssl_connected[SECONDARYSOCKET] = FALSE;
#endif
Curl_conn_close(data, SECONDARYSOCKET);
Curl_conn_cf_discard_all(data, conn, SECONDARYSOCKET);
}
/*
@@ -278,13 +267,13 @@ static CURLcode AcceptServerConnect(struct Curl_easy *data)
struct sockaddr_in add;
#endif
curl_socklen_t size = (curl_socklen_t) sizeof(add);
CURLcode result;
if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) {
size = sizeof(add);
s = accept(sock, (struct sockaddr *) &add, &size);
}
Curl_closesocket(data, conn, sock); /* close the first socket */
if(CURL_SOCKET_BAD == s) {
failf(data, "Error accept()ing server connect");
@@ -295,9 +284,11 @@ static CURLcode AcceptServerConnect(struct Curl_easy *data)
not needing DO_MORE anymore */
conn->bits.do_more = FALSE;
conn->sock[SECONDARYSOCKET] = s;
(void)curlx_nonblock(s, TRUE); /* enable non-blocking */
conn->bits.sock_accepted = TRUE;
/* Replace any filter on SECONDARY with one listeing on this socket */
result = Curl_conn_socket_accepted_set(data, conn, SECONDARYSOCKET, &s);
if(result)
return result;
if(data->set.fsockopt) {
int error = 0;
@@ -441,15 +432,12 @@ static CURLcode InitiateTransfer(struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
bool connected;
if(conn->bits.ftp_use_data_ssl) {
/* since we only have a plaintext TCP connection here, we must now
* do the TLS stuff */
infof(data, "Doing the SSL/TLS handshake on the data stream");
result = Curl_ssl_connect(data, conn, SECONDARYSOCKET);
if(result)
return result;
}
DEBUGF(infof(data, "ftp InitiateTransfer()"));
result = Curl_conn_connect(data, SECONDARYSOCKET, TRUE, &connected);
if(result || !connected)
return result;
if(conn->proto.ftpc.state_saved == FTP_STOR) {
/* When we know we're uploading a specified file, we can get the file
@@ -497,22 +485,23 @@ static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected)
if(timeout_ms < 0) {
/* if a timeout was already reached, bail out */
failf(data, "Accept timeout occurred while waiting server connect");
return CURLE_FTP_ACCEPT_TIMEOUT;
result = CURLE_FTP_ACCEPT_TIMEOUT;
goto out;
}
/* see if the connection request is already here */
result = ReceivedServerConnect(data, connected);
if(result)
return result;
goto out;
if(*connected) {
result = AcceptServerConnect(data);
if(result)
return result;
goto out;
result = InitiateTransfer(data);
if(result)
return result;
goto out;
}
else {
/* Add timeout to multi handle and break out of the loop */
@@ -521,6 +510,8 @@ static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected)
EXPIRE_FTP_ACCEPT);
}
out:
DEBUGF(infof(data, "ftp AllowServerConnect() -> %d", result));
return result;
}
@@ -672,7 +663,7 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
* wait for more data anyway.
*/
}
else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) {
else if(!Curl_conn_data_pending(data, FIRSTSOCKET)) {
switch(SOCKET_READABLE(sockfd, interval_ms)) {
case -1: /* select() error, stop reading */
failf(data, "FTP response aborted due to select/poll error: %d",
@@ -821,8 +812,10 @@ static int ftp_domore_getsock(struct Curl_easy *data,
* handle ordinary commands.
*/
if(SOCKS_STATE(conn->cnnct.state))
return Curl_SOCKS_getsock(conn, socks, SECONDARYSOCKET);
DEBUGF(infof(data, "ftp_domore_getsock()"));
if(conn->cfilter[SECONDARYSOCKET]
&& !Curl_conn_is_connected(conn, SECONDARYSOCKET))
return Curl_conn_get_select_socks(data, SECONDARYSOCKET, socks);
if(FTP_STOP == ftpc->state) {
int bits = GETSOCK_READSOCK(0);
@@ -917,7 +910,7 @@ typedef enum {
static CURLcode ftp_state_use_port(struct Curl_easy *data,
ftpport fcmd) /* start with this */
{
CURLcode result = CURLE_OK;
CURLcode result = CURLE_FTP_PORT_FAILED;
struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
curl_socket_t portsock = CURL_SOCKET_BAD;
@@ -966,8 +959,10 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
char *port_sep = NULL;
addr = calloc(addrlen + 1, 1);
if(!addr)
return CURLE_OUT_OF_MEMORY;
if(!addr) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
#ifdef ENABLE_IPV6
if(*string_ftpport == '[') {
@@ -1027,7 +1022,6 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
if(port_min > port_max)
port_min = port_max = 0;
if(*addr != '\0') {
/* attempt to get the address of the given interface name */
switch(Curl_if2ip(conn->ip_addr->ai_family,
@@ -1041,7 +1035,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
host = addr;
break;
case IF2IP_AF_NOT_SUPPORTED:
return CURLE_FTP_PORT_FAILED;
goto out;
case IF2IP_FOUND:
host = hbuf; /* use the hbuf for host name */
}
@@ -1059,8 +1053,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
failf(data, "getsockname() failed: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
free(addr);
return CURLE_FTP_PORT_FAILED;
goto out;
}
switch(sa->sa_family) {
#ifdef ENABLE_IPV6
@@ -1072,8 +1065,9 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
r = Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
break;
}
if(!r)
return CURLE_FTP_PORT_FAILED;
if(!r) {
goto out;
}
host = hbuf; /* use this host name */
possibly_non_local = FALSE; /* we know it is local now */
}
@@ -1093,11 +1087,9 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
if(!res) {
failf(data, "failed to resolve the address provided to PORT: %s", host);
free(addr);
return CURLE_FTP_PORT_FAILED;
goto out;
}
free(addr);
host = NULL;
/* step 2, create a socket for the requested address */
@@ -1105,8 +1097,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
portsock = CURL_SOCKET_BAD;
error = 0;
for(ai = res; ai; ai = ai->ai_next) {
result = Curl_socket(data, ai, NULL, &portsock);
if(result) {
if(Curl_socket(data, ai, NULL, &portsock)) {
error = SOCKERRNO;
continue;
}
@@ -1115,8 +1106,9 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
if(!ai) {
failf(data, "socket failure: %s",
Curl_strerror(error, buffer, sizeof(buffer)));
return CURLE_FTP_PORT_FAILED;
goto out;
}
DEBUGF(infof(data, "ftp_state_use_port(), opened socket"));
/* step 3, bind to a suitable local address */
@@ -1145,8 +1137,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
failf(data, "getsockname() failed: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
goto out;
}
port = port_min;
possibly_non_local = FALSE; /* don't try this again */
@@ -1155,8 +1146,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
if(error != EADDRINUSE && error != EACCES) {
failf(data, "bind(port=%hu) failed: %s", port,
Curl_strerror(error, buffer, sizeof(buffer)));
Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
goto out;
}
}
else
@@ -1165,31 +1155,30 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
port++;
}
/* maybe all ports were in use already*/
/* maybe all ports were in use already */
if(port > port_max) {
failf(data, "bind() failed, we ran out of ports");
Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
goto out;
}
/* get the name again after the bind() so that we can extract the
port number it uses now */
sslen = sizeof(ss);
if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
if(getsockname(portsock, sa, &sslen)) {
failf(data, "getsockname() failed: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
goto out;
}
DEBUGF(infof(data, "ftp_state_use_port(), socket bound to port %d", port));
/* step 4, listen on the socket */
if(listen(portsock, 1)) {
failf(data, "socket failure: %s",
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
Curl_closesocket(data, conn, portsock);
return CURLE_FTP_PORT_FAILED;
goto out;
}
DEBUGF(infof(data, "ftp_state_use_port(), listening on %d", port));
/* step 5, send the proper FTP command */
@@ -1242,12 +1231,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
if(result) {
failf(data, "Failure sending EPRT command: %s",
curl_easy_strerror(result));
Curl_closesocket(data, conn, portsock);
/* don't retry using PORT */
ftpc->count1 = PORT;
/* bail out */
state(data, FTP_STOP);
return result;
goto out;
}
break;
}
@@ -1273,10 +1257,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
if(result) {
failf(data, "Failure sending PORT command: %s",
curl_easy_strerror(result));
Curl_closesocket(data, conn, portsock);
/* bail out */
state(data, FTP_STOP);
return result;
goto out;
}
break;
}
@@ -1285,23 +1266,21 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
/* store which command was sent */
ftpc->count1 = fcmd;
close_secondarysocket(data, conn);
/* we set the secondary socket variable to this for now, it is only so that
the cleanup function will close it in case we fail before the true
secondary stuff is made */
conn->sock[SECONDARYSOCKET] = portsock;
/* this tcpconnect assignment below is a hackish work-around to make the
multi interface with active FTP work - as it will not wait for a
(passive) connect in Curl_is_connected().
The *proper* fix is to make sure that the active connection from the
server is done in a non-blocking way. Currently, it is still BLOCKING.
*/
conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
/* Replace any filter on SECONDARY with one listeing on this socket */
result = Curl_conn_socket_accepted_set(data, conn, SECONDARYSOCKET,
&portsock);
if(result)
goto out;
portsock = CURL_SOCKET_BAD; /* now held in filter */
state(data, FTP_PORT);
out:
if(result) {
state(data, FTP_STOP);
}
if(portsock != CURL_SOCKET_BAD)
Curl_closesocket(data, conn, portsock);
free(addr);
return result;
}
@@ -1525,7 +1504,7 @@ static CURLcode ftp_state_type(struct Curl_easy *data)
/* If we have selected NOBODY and HEADER, it means that we only want file
information. Which in FTP can't be much more than the file size and
date. */
if(data->set.opt_no_body && ftpc->file &&
if(data->req.no_body && ftpc->file &&
ftp_need_type(conn, data->state.prefer_ascii)) {
/* The SIZE command is _not_ RFC 959 specified, and therefore many servers
may not support it! It is however the only way we have to get a file's
@@ -1804,6 +1783,8 @@ static CURLcode ftp_epsv_disable(struct Curl_easy *data,
infof(data, "Failed EPSV attempt. Disabling EPSV");
/* disable it for next transfer */
conn->bits.ftp_use_epsv = FALSE;
Curl_conn_close(data, SECONDARYSOCKET);
Curl_conn_cf_discard_all(data, conn, SECONDARYSOCKET);
data->state.errorbuf = FALSE; /* allow error message to get
rewritten */
result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PASV");
@@ -1951,7 +1932,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
*/
const char * const host_name = conn->bits.socksproxy ?
conn->socks_proxy.host.name : conn->http_proxy.host.name;
rc = Curl_resolv(data, host_name, (int)conn->port, FALSE, &addr);
rc = Curl_resolv(data, host_name, conn->port, FALSE, &addr);
if(rc == CURLRESOLV_PENDING)
/* BLOCKING, ignores the return code but 'addr' will be NULL in
case of failure */
@@ -1993,8 +1974,9 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
}
}
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
result = Curl_connecthost(data, conn, addr);
result = Curl_conn_setup(data, conn, SECONDARYSOCKET, addr,
conn->bits.ftp_use_data_ssl?
CURL_CF_SSL_ENABLE : CURL_CF_SSL_DISABLE);
if(result) {
Curl_resolv_unlock(data, addr); /* we're done using this address */
@@ -2092,9 +2074,9 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data,
#ifdef CURL_FTP_HTTPSTYLE_HEAD
/* If we asked for a time of the file and we actually got one as well,
we "emulate" a HTTP-style header in our output. */
we "emulate" an HTTP-style header in our output. */
if(data->set.opt_no_body &&
if(data->req.no_body &&
ftpc->file &&
data->set.get_filetime &&
(data->info.filetime >= 0) ) {
@@ -2210,6 +2192,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
struct connectdata *conn = data->conn;
struct ftp_conn *ftpc = &conn->proto.ftpc;
DEBUGF(infof(data, "ftp_state_retr()"));
if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
failf(data, "Maximum file size exceeded");
return CURLE_FILESIZE_EXCEEDED;
@@ -2310,7 +2293,7 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data,
else
fdigit = start;
/* ignores parsing errors, which will make the size remain unknown */
(void)curlx_strtoofft(fdigit, NULL, 0, &filesize);
(void)curlx_strtoofft(fdigit, NULL, 10, &filesize);
}
else if(ftpcode == 550) { /* "No such file or directory" */
@@ -2465,6 +2448,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
if((instate != FTP_LIST) &&
!data->state.prefer_ascii &&
!data->set.ignorecl &&
(ftp->downloadsize < 1)) {
/*
* It seems directory listings either don't show the size or very
@@ -2495,7 +2479,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data,
if(bytes) {
++bytes;
/* get the number! */
(void)curlx_strtoofft(bytes, NULL, 0, &size);
(void)curlx_strtoofft(bytes, NULL, 10, &size);
}
}
}
@@ -2756,8 +2740,16 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
*/
if((ftpcode == 234) || (ftpcode == 334)) {
/* Curl_ssl_connect is BLOCKING */
result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
/* this was BLOCKING, keep it so for now */
bool done;
if(!Curl_conn_is_ssl(data, FIRSTSOCKET)) {
result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
if(result) {
/* we failed and bail out */
return CURLE_USE_SSL_FAILED;
}
}
result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, &done);
if(!result) {
conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
conn->bits.ftp_use_control_ssl = TRUE; /* SSL on control */
@@ -2823,7 +2815,7 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
case FTP_CCC:
if(ftpcode < 500) {
/* First shut down the SSL layer (note: this call will block) */
result = Curl_ssl_shutdown(data, conn, FIRSTSOCKET);
result = Curl_ssl_cfilter_remove(data, FIRSTSOCKET);
if(result)
failf(data, "Failed to clear the command channel (CCC)");
@@ -3167,7 +3159,7 @@ static CURLcode ftp_connect(struct Curl_easy *data,
if(conn->handler->flags & PROTOPT_SSL) {
/* BLOCKING */
result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, done);
if(result)
return result;
conn->bits.ftp_use_control_ssl = TRUE;
@@ -3310,14 +3302,6 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
}
}
if(conn->ssl[SECONDARYSOCKET].use) {
/* The secondary socket is using SSL so we must close down that part
first before we close the socket for real */
Curl_ssl_close(data, conn, SECONDARYSOCKET);
/* Note that we keep "use" set to TRUE since that (next) connection is
still requested to use SSL */
}
close_secondarysocket(data, conn);
}
@@ -3571,23 +3555,15 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
* complete */
struct FTP *ftp = NULL;
/* if the second connection isn't done yet, wait for it */
if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
if(Curl_connect_ongoing(conn)) {
/* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
aren't used so we blank their arguments. */
result = Curl_proxyCONNECT(data, SECONDARYSOCKET, NULL, 0);
return result;
}
result = Curl_is_connected(data, conn, SECONDARYSOCKET, &connected);
/* Ready to do more? */
if(connected) {
DEBUGF(infof(data, "DO-MORE connected phase starts"));
}
else {
/* if the second connection isn't done yet, wait for it to have
* connected to the remote host. When using proxy tunneling, this
* means the tunnel needs to have been establish. However, we
* can not expect the remote host to talk to us in any way yet.
* So, when using ftps: the SSL handshake will not start until we
* tell the remote server that we are there. */
if(conn->cfilter[SECONDARYSOCKET]) {
result = Curl_conn_connect(data, SECONDARYSOCKET, FALSE, &connected);
if(result || !Curl_conn_is_ip_connected(data, SECONDARYSOCKET)) {
if(result && (ftpc->count1 == 0)) {
*completep = -1; /* go back to DOING please */
/* this is a EPSV connect failing, try PASV instead */
@@ -3597,19 +3573,6 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
}
}
#ifndef CURL_DISABLE_PROXY
result = Curl_proxy_connect(data, SECONDARYSOCKET);
if(result)
return result;
if(CONNECT_SECONDARYSOCKET_PROXY_SSL())
return result;
if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
Curl_connect_ongoing(conn))
return result;
#endif
/* Curl_proxy_connect might have moved the protocol state */
ftp = data->req.p.ftp;
@@ -3739,11 +3702,10 @@ CURLcode ftp_perform(struct Curl_easy *data,
{
/* this is FTP and no proxy */
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
DEBUGF(infof(data, "DO phase starts"));
if(data->set.opt_no_body) {
if(data->req.no_body) {
/* requested no body means no transfer... */
struct FTP *ftp = data->req.p.ftp;
ftp->transfer = PPTRANSFER_INFO;
@@ -3759,7 +3721,7 @@ CURLcode ftp_perform(struct Curl_easy *data,
/* run the state-machine */
result = ftp_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[SECONDARYSOCKET];
*connected = Curl_conn_is_connected(data->conn, SECONDARYSOCKET);
infof(data, "ftp_perform ends with SECONDARY: %d", *connected);
@@ -4169,7 +4131,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
/* get path before last slash, except for / */
size_t dirlen = slashPos - rawPath;
if(dirlen == 0)
dirlen++;
dirlen = 1;
ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
if(!ftpc->dirs) {
@@ -4196,13 +4158,14 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
/* current position: begin of next path component */
const char *curPos = rawPath;
int dirAlloc = 0; /* number of entries allocated for the 'dirs' array */
/* number of entries allocated for the 'dirs' array */
size_t dirAlloc = 0;
const char *str = rawPath;
for(; *str != 0; ++str)
if (*str == '/')
++dirAlloc;
if(dirAlloc > 0) {
if(dirAlloc) {
ftpc->dirs = calloc(dirAlloc, sizeof(ftpc->dirs[0]));
if(!ftpc->dirs) {
free(rawPath);
@@ -4232,7 +4195,7 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data)
curPos = slashPos + 1;
}
}
DEBUGASSERT(ftpc->dirdepth <= dirAlloc);
DEBUGASSERT((size_t)ftpc->dirdepth <= dirAlloc);
fileName = curPos; /* the rest is the file name (or empty) */
}
break;
@@ -4375,6 +4338,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
{
char *type;
struct FTP *ftp;
CURLcode result = CURLE_OK;
data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1);
if(!ftp)
@@ -4416,7 +4380,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
ftp->downloadsize = 0;
conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
return CURLE_OK;
return result;
}
#endif /* CURL_DISABLE_FTP */
+3 -3
View File
@@ -205,9 +205,9 @@ CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data)
#define FTP_LP_MALFORMATED_PERM 0x01000000
static int ftp_pl_get_permission(const char *str)
static unsigned int ftp_pl_get_permission(const char *str)
{
int permissions = 0;
unsigned int permissions = 0;
/* USER */
if(str[0] == 'r')
permissions |= 1 << 8;
@@ -334,7 +334,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
struct ftp_parselist_data *parser = ftpwc->parser;
struct fileinfo *infop;
struct curl_fileinfo *finfo;
unsigned long i = 0;
size_t i = 0;
CURLcode result;
size_t retsize = bufflen;
+1 -7
View File
@@ -533,13 +533,7 @@ static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
#ifdef USE_SSL
if(conn && tsi->backend != CURLSSLBACKEND_NONE) {
unsigned int i;
for(i = 0; i < (sizeof(conn->ssl) / sizeof(conn->ssl[0])); ++i) {
if(conn->ssl[i].use) {
tsi->internals = Curl_ssl->get_internals(&conn->ssl[i], info);
break;
}
}
tsi->internals = Curl_ssl_get_internals(data, FIRSTSOCKET, info, 0);
}
#endif
}
+5 -2
View File
@@ -30,6 +30,7 @@
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
#include "cfilters.h"
#include "connect.h"
#include "progress.h"
#include "gopher.h"
@@ -117,7 +118,9 @@ static CURLcode gopher_connect(struct Curl_easy *data, bool *done)
static CURLcode gopher_connecting(struct Curl_easy *data, bool *done)
{
struct connectdata *conn = data->conn;
CURLcode result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
CURLcode result;
result = Curl_conn_connect(data, FIRSTSOCKET, TRUE, done);
if(result)
connclose(conn, "Failed TLS connection");
*done = TRUE;
@@ -236,4 +239,4 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done)
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
return CURLE_OK;
}
#endif /*CURL_DISABLE_GOPHER*/
#endif /* CURL_DISABLE_GOPHER */
+1 -1
View File
@@ -36,7 +36,7 @@
/*
* Curl_pseudo_headers() creates the array with pseudo headers to be
* used in a HTTP/2 or HTTP/3 request.
* used in an HTTP/2 or HTTP/3 request.
*/
#if defined(USE_NGHTTP2) || defined(ENABLE_QUIC)
+1 -1
View File
@@ -45,7 +45,7 @@ struct h2h3req {
/*
* Curl_pseudo_headers() creates the array with pseudo headers to be
* used in a HTTP/2 or HTTP/3 request. Returns an allocated struct.
* used in an HTTP/2 or HTTP/3 request. Returns an allocated struct.
* Free it with Curl_pseudo_free().
*/
CURLcode Curl_pseudo_headers(struct Curl_easy *data,
-4
View File
@@ -43,10 +43,6 @@
#include <inet.h>
#endif
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
-4
View File
@@ -48,10 +48,6 @@
#include <signal.h>
#endif
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
-5
View File
@@ -34,11 +34,6 @@
#include <setjmp.h>
#endif
#ifdef NETWARE
#undef in_addr_t
#define in_addr_t unsigned long
#endif
/* Allocate enough memory to hold the full name information structs and
* everything. OSF1 is known to require at least 8872 bytes. The buffer
* required for storing all possible aliases and IP numbers is according to
+7 -8
View File
@@ -43,10 +43,6 @@
#include <inet.h>
#endif
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
@@ -125,14 +121,15 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
int port)
{
#if !defined(HAVE_GETADDRINFO_THREADSAFE) && defined(HAVE_GETHOSTBYNAME_R_3)
#if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE)) && \
defined(HAVE_GETHOSTBYNAME_R_3)
int res;
#endif
struct Curl_addrinfo *ai = NULL;
struct hostent *h = NULL;
struct hostent *buf = NULL;
#if defined(HAVE_GETADDRINFO_THREADSAFE)
#if defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE)
struct addrinfo hints;
char sbuf[12];
char *sbufptr = NULL;
@@ -280,14 +277,16 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
h = NULL; /* set return code to NULL */
free(buf);
}
#else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
#else /* (HAVE_GETADDRINFO && HAVE_GETADDRINFO_THREADSAFE) ||
HAVE_GETHOSTBYNAME_R */
/*
* Here is code for platforms that don't have a thread safe
* getaddrinfo() nor gethostbyname_r() function or for which
* gethostbyname() is the preferred one.
*/
h = gethostbyname((void *)hostname);
#endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
#endif /* (HAVE_GETADDRINFO && HAVE_GETADDRINFO_THREADSAFE) ||
HAVE_GETHOSTBYNAME_R */
if(h) {
ai = Curl_he2ai(h, port);
-4
View File
@@ -43,10 +43,6 @@
#include <inet.h>
#endif
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
-4
View File
@@ -43,10 +43,6 @@
#include <inet.h>
#endif
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
+4 -5
View File
@@ -39,7 +39,6 @@
#include "parsedate.h"
#include "fopen.h"
#include "rename.h"
#include "strtoofft.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -158,7 +157,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
do {
while(*p && ISBLANK(*p))
p++;
if(Curl_strncasecompare("max-age=", p, 8)) {
if(strncasecompare("max-age=", p, 8)) {
bool quoted = FALSE;
CURLofft offt;
char *endp;
@@ -187,7 +186,7 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
}
gotma = TRUE;
}
else if(Curl_strncasecompare("includesubdomains", p, 17)) {
else if(strncasecompare("includesubdomains", p, 17)) {
if(gotinc)
return CURLE_BAD_FUNCTION_ARGUMENT;
subdomains = TRUE;
@@ -278,11 +277,11 @@ struct stsentry *Curl_hsts(struct hsts *h, const char *hostname,
if(ntail < hlen) {
size_t offs = hlen - ntail;
if((hostname[offs-1] == '.') &&
Curl_strncasecompare(&hostname[offs], sts->host, ntail))
strncasecompare(&hostname[offs], sts->host, ntail))
return sts;
}
}
if(Curl_strcasecompare(hostname, sts->host))
if(strcasecompare(hostname, sts->host))
return sts;
}
}
+88 -166
View File
@@ -80,6 +80,7 @@
#include "http_proxy.h"
#include "warnless.h"
#include "http2.h"
#include "cfilters.h"
#include "connect.h"
#include "strdup.h"
#include "altsvc.h"
@@ -101,18 +102,6 @@ static int http_getsock_do(struct Curl_easy *data,
curl_socket_t *socks);
static bool http_should_fail(struct Curl_easy *data);
#ifndef CURL_DISABLE_PROXY
static CURLcode add_haproxy_protocol_header(struct Curl_easy *data);
#endif
#ifdef USE_SSL
static CURLcode https_connecting(struct Curl_easy *data, bool *done);
static int https_getsock(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *socks);
#else
#define https_connecting(x,y) CURLE_COULDNT_CONNECT
#endif
static CURLcode http_setup_conn(struct Curl_easy *data,
struct connectdata *conn);
#ifdef USE_WEBSOCKETS
@@ -184,9 +173,9 @@ const struct Curl_handler Curl_handler_https = {
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
Curl_http_connect, /* connect_it */
https_connecting, /* connecting */
NULL, /* connecting */
ZERO_NULL, /* doing */
https_getsock, /* proto_getsock */
NULL, /* proto_getsock */
http_getsock_do, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
@@ -209,9 +198,9 @@ const struct Curl_handler Curl_handler_wss = {
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
Curl_http_connect, /* connect_it */
https_connecting, /* connecting */
NULL, /* connecting */
ZERO_NULL, /* doing */
https_getsock, /* proto_getsock */
NULL, /* proto_getsock */
http_getsock_do, /* doing_getsock */
ZERO_NULL, /* domore_getsock */
ZERO_NULL, /* perform_getsock */
@@ -229,6 +218,41 @@ const struct Curl_handler Curl_handler_wss = {
#endif
static CURLcode h3_setup_conn(struct Curl_easy *data,
struct connectdata *conn)
{
#ifdef ENABLE_QUIC
/* We want HTTP/3 directly, setup the filter chain ourself,
* overriding the default behaviour. */
DEBUGASSERT(conn->transport == TRNSPRT_QUIC);
if(!(conn->handler->flags & PROTOPT_SSL)) {
failf(data, "HTTP/3 requested for non-HTTPS URL");
return CURLE_URL_MALFORMAT;
}
#ifndef CURL_DISABLE_PROXY
if(conn->bits.socksproxy) {
failf(data, "HTTP/3 is not supported over a SOCKS proxy");
return CURLE_URL_MALFORMAT;
}
if(conn->bits.httpproxy && conn->bits.tunnel_proxy) {
failf(data, "HTTP/3 is not supported over a HTTP proxy");
return CURLE_URL_MALFORMAT;
}
#endif
DEBUGF(infof(data, "HTTP/3 direct conn setup(conn #%ld, index=%d)",
conn->connection_id, FIRSTSOCKET));
return Curl_conn_socket_set(data, conn, FIRSTSOCKET);
#else /* ENABLE_QUIC */
(void)conn;
(void)data;
DEBUGF(infof(data, "QUIC is not supported in this build"));
return CURLE_NOT_BUILT_IN;
#endif /* !ENABLE_QUIC */
}
static CURLcode http_setup_conn(struct Curl_easy *data,
struct connectdata *conn)
{
@@ -241,18 +265,15 @@ static CURLcode http_setup_conn(struct Curl_easy *data,
if(!http)
return CURLE_OUT_OF_MEMORY;
Curl_mime_initpart(&http->form, data);
Curl_mime_initpart(&http->form);
data->req.p.http = http;
if(data->state.httpwant == CURL_HTTP_VERSION_3) {
if(conn->handler->flags & PROTOPT_SSL)
/* Only go HTTP/3 directly on HTTPS URLs. It needs a UDP socket and does
the QUIC dance. */
conn->transport = TRNSPRT_QUIC;
else {
failf(data, "HTTP/3 requested for non-HTTPS URL");
return CURLE_URL_MALFORMAT;
}
conn->transport = TRNSPRT_QUIC;
}
if(conn->transport == TRNSPRT_QUIC) {
return h3_setup_conn(data, conn);
}
else {
if(!CONN_INUSE(conn))
@@ -555,7 +576,7 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data,
}
}
conn->bits.rewindaftersend = FALSE; /* default */
data->state.rewindbeforesend = FALSE; /* default */
if((expectsend == -1) || (expectsend > bytessent)) {
#if defined(USE_NTLM)
@@ -572,8 +593,8 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data,
/* rewind data when completely done sending! */
if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
conn->bits.rewindaftersend = TRUE;
infof(data, "Rewind stream after send");
data->state.rewindbeforesend = TRUE;
infof(data, "Rewind stream before next send");
}
return CURLE_OK;
@@ -600,8 +621,8 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data,
/* rewind data when completely done sending! */
if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
conn->bits.rewindaftersend = TRUE;
infof(data, "Rewind stream after send");
data->state.rewindbeforesend = TRUE;
infof(data, "Rewind stream before next send");
}
return CURLE_OK;
@@ -625,9 +646,11 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data,
closure so we can safely do the rewind right now */
}
if(bytessent)
/* we rewind now at once since if we already sent something */
return Curl_readrewind(data);
if(bytessent) {
/* mark for rewind since if we already sent something */
data->state.rewindbeforesend = TRUE;
infof(data, "Please rewind output before next send");
}
return CURLE_OK;
}
@@ -650,7 +673,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
if(!data->set.str[STRING_BEARER])
authmask &= (unsigned long)~CURLAUTH_BEARER;
if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
if(100 <= data->req.httpcode && data->req.httpcode <= 199)
/* this is a transient response code, ignore */
return CURLE_OK;
@@ -684,7 +707,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
if(pickhost || pickproxy) {
if((data->state.httpreq != HTTPREQ_GET) &&
(data->state.httpreq != HTTPREQ_HEAD) &&
!conn->bits.rewindaftersend) {
!data->state.rewindbeforesend) {
result = http_perhapsrewind(data, conn);
if(result)
return result;
@@ -1241,7 +1264,7 @@ static size_t readmoredata(char *buffer,
/* nothing to return */
return 0;
/* make sure that a HTTP request is never sent away chunked! */
/* make sure that an HTTP request is never sent away chunked! */
data->req.forbidchunk = (http->sending == HTTPSEND_REQUEST)?TRUE:FALSE;
if(data->set.max_send_speed &&
@@ -1539,48 +1562,13 @@ Curl_compareheader(const char *headerline, /* line to check */
*/
CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
{
CURLcode result;
struct connectdata *conn = data->conn;
/* We default to persistent connections. We set this already in this connect
function to make the re-use checks properly be able to check this bit. */
connkeep(conn, "HTTP default");
#ifndef CURL_DISABLE_PROXY
/* the CONNECT procedure might not have been completed */
result = Curl_proxy_connect(data, FIRSTSOCKET);
if(result)
return result;
if(conn->bits.proxy_connect_closed)
/* this is not an error, just part of the connection negotiation */
return CURLE_OK;
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */
if(Curl_connect_ongoing(conn))
/* nothing else to do except wait right now - we're not done here. */
return CURLE_OK;
if(data->set.haproxyprotocol) {
/* add HAProxy PROXY protocol header */
result = add_haproxy_protocol_header(data);
if(result)
return result;
}
#endif
if(conn->given->flags & PROTOPT_SSL) {
/* perform SSL initialization */
result = https_connecting(data, done);
if(result)
return result;
}
else
*done = TRUE;
return CURLE_OK;
return Curl_conn_connect(data, FIRSTSOCKET, FALSE, done);
}
/* this returns the socket to wait for in the DO and DOING state for the multi
@@ -1596,75 +1584,6 @@ static int http_getsock_do(struct Curl_easy *data,
return GETSOCK_WRITESOCK(0);
}
#ifndef CURL_DISABLE_PROXY
static CURLcode add_haproxy_protocol_header(struct Curl_easy *data)
{
struct dynbuf req;
CURLcode result;
const char *tcp_version;
DEBUGASSERT(data->conn);
Curl_dyn_init(&req, DYN_HAXPROXY);
#ifdef USE_UNIX_SOCKETS
if(data->conn->unix_domain_socket)
/* the buffer is large enough to hold this! */
result = Curl_dyn_addn(&req, STRCONST("PROXY UNKNOWN\r\n"));
else {
#endif
/* Emit the correct prefix for IPv6 */
tcp_version = data->conn->bits.ipv6 ? "TCP6" : "TCP4";
result = Curl_dyn_addf(&req, "PROXY %s %s %s %i %i\r\n",
tcp_version,
data->info.conn_local_ip,
data->info.conn_primary_ip,
data->info.conn_local_port,
data->info.conn_primary_port);
#ifdef USE_UNIX_SOCKETS
}
#endif
if(!result)
result = Curl_buffer_send(&req, data, &data->info.request_size,
0, FIRSTSOCKET);
return result;
}
#endif
#ifdef USE_SSL
static CURLcode https_connecting(struct Curl_easy *data, bool *done)
{
CURLcode result;
struct connectdata *conn = data->conn;
DEBUGASSERT((data) && (data->conn->handler->flags & PROTOPT_SSL));
#ifdef ENABLE_QUIC
if(conn->transport == TRNSPRT_QUIC) {
*done = TRUE;
return CURLE_OK;
}
#endif
/* perform SSL initialization for this socket */
result = Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET, done);
if(result)
connclose(conn, "Failed HTTPS connection");
return result;
}
static int https_getsock(struct Curl_easy *data,
struct connectdata *conn,
curl_socket_t *socks)
{
(void)data;
if(conn->handler->flags & PROTOPT_SSL)
return Curl_ssl->getsock(conn, socks);
return GETSOCK_BLANK;
}
#endif /* USE_SSL */
/*
* Curl_http_done() gets called after a single HTTP request has been
* performed.
@@ -2096,7 +2015,7 @@ void Curl_http_method(struct Curl_easy *data, struct connectdata *conn,
if(data->set.str[STRING_CUSTOMREQUEST])
request = data->set.str[STRING_CUSTOMREQUEST];
else {
if(data->set.opt_no_body)
if(data->req.no_body)
request = "HEAD";
else {
DEBUGASSERT((httpreq >= HTTPREQ_GET) && (httpreq <= HTTPREQ_HEAD));
@@ -2141,7 +2060,7 @@ CURLcode Curl_http_host(struct Curl_easy *data, struct connectdata *conn)
{
const char *ptr;
if(!data->state.this_is_a_follow) {
/* Free to avoid leaking memory on multiple requests*/
/* Free to avoid leaking memory on multiple requests */
free(data->state.first_host);
data->state.first_host = strdup(conn->host.name);
@@ -2384,7 +2303,7 @@ CURLcode Curl_http_body(struct Curl_easy *data, struct connectdata *conn,
cthdr = "multipart/form-data";
curl_mime_headers(http->sendit, data->set.headers, 0);
result = Curl_mime_prepare_headers(http->sendit, cthdr,
result = Curl_mime_prepare_headers(data, http->sendit, cthdr,
NULL, MIMESTRATEGY_FORM);
curl_mime_headers(http->sendit, NULL, 0);
if(!result)
@@ -2795,7 +2714,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
strcasecompare("localhost", host) ||
!strcmp(host, "127.0.0.1") ||
!strcmp(host, "[::1]") ? TRUE : FALSE;
!strcmp(host, "::1") ? TRUE : FALSE;
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
co = Curl_cookie_getlist(data, data->cookies, host, data->state.up.path,
secure_context);
@@ -2925,8 +2844,8 @@ CURLcode Curl_http_resume(struct Curl_easy *data,
data->state.resume_from = 0;
}
if(data->state.resume_from && !data->state.this_is_a_follow) {
/* do we still game? */
if(data->state.resume_from && !data->state.followlocation) {
/* only act on the first request */
/* Now, let's read off the proper amount of bytes from the
input. */
@@ -3027,14 +2946,14 @@ CURLcode Curl_http_firstwrite(struct Curl_easy *data,
if(data->set.timecondition && !data->state.range) {
/* A time condition has been set AND no ranges have been requested. This
seems to be what chapter 13.3.4 of RFC 2616 defines to be the correct
action for a HTTP/1.1 client */
action for an HTTP/1.1 client */
if(!Curl_meets_timecondition(data, k->timeofdoc)) {
*done = TRUE;
/* We're simulating a http 304 from server so we return
/* We're simulating an HTTP 304 from server so we return
what should have been returned from the server */
data->info.httpcode = 304;
infof(data, "Simulate a HTTP 304 response");
infof(data, "Simulate an HTTP 304 response");
/* we abort the transfer before it is completed == we ruin the
re-use ability. Close the connection */
streamclose(conn, "Simulated 304 handling");
@@ -3080,7 +2999,7 @@ CURLcode Curl_transferencode(struct Curl_easy *data)
#ifndef USE_HYPER
/*
* Curl_http() gets called from the generic multi_do() function when a HTTP
* Curl_http() gets called from the generic multi_do() function when an HTTP
* request is to be performed. This creates and sends a properly constructed
* HTTP request.
*/
@@ -3117,7 +3036,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
/* continue with HTTP/1.1 when explicitly requested */
break;
default:
/* Check if user wants to use HTTP/2 with clear TCP*/
/* Check if user wants to use HTTP/2 with clear TCP */
#ifdef USE_NGHTTP2
if(data->state.httpwant == CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
#ifndef CURL_DISABLE_PROXY
@@ -3140,7 +3059,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
}
}
else {
/* prepare for a http2 request */
/* prepare for an http2 request */
result = Curl_http2_setup(data, conn);
if(result)
return result;
@@ -3497,7 +3416,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
STRCONST("Proxy-Connection:"),
STRCONST("keep-alive"))) {
/*
* When a HTTP/1.0 reply comes when using a proxy, the
* When an HTTP/1.0 reply comes when using a proxy, the
* 'Proxy-Connection: keep-alive' line tells us the
* connection will be kept alive for our pleasure.
* Default action for 1.0 is to close.
@@ -3511,7 +3430,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
STRCONST("Proxy-Connection:"),
STRCONST("close"))) {
/*
* We get a HTTP/1.1 response from a proxy and it says it'll
* We get an HTTP/1.1 response from a proxy and it says it'll
* close down after this transfer.
*/
connclose(conn, "Proxy-Connection: asked to close after done");
@@ -3523,7 +3442,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
STRCONST("Connection:"),
STRCONST("keep-alive"))) {
/*
* A HTTP/1.0 reply with the 'Connection: keep-alive' line
* An HTTP/1.0 reply with the 'Connection: keep-alive' line
* tells us the connection will be kept alive for our
* pleasure. Default action for 1.0 is to close.
*
@@ -3634,7 +3553,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) ||
strcasecompare("localhost", host) ||
!strcmp(host, "127.0.0.1") ||
!strcmp(host, "[::1]") ? TRUE : FALSE;
!strcmp(host, "::1") ? TRUE : FALSE;
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
CURL_LOCK_ACCESS_SINGLE);
@@ -3708,6 +3627,9 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
result = http_perhapsrewind(data, conn);
if(result)
return result;
/* mark the next request as a followed location: */
data->state.this_is_a_follow = TRUE;
}
}
}
@@ -3724,7 +3646,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
#endif
)) {
CURLcode check =
Curl_hsts_parse(data->hsts, data->state.up.hostname,
Curl_hsts_parse(data->hsts, conn->host.name,
headp + strlen("Strict-Transport-Security:"));
if(check)
infof(data, "Illegal STS header skipped");
@@ -3751,7 +3673,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
result = Curl_altsvc_parse(data, data->asi,
headp + strlen("Alt-Svc:"),
id, conn->host.name,
curlx_uitous(conn->remote_port));
curlx_uitous((unsigned int)conn->remote_port));
if(result)
return result;
}
@@ -4012,7 +3934,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
switch(k->httpcode) {
case 100:
/*
* We have made a HTTP PUT or POST and this is 1.1-lingo
* We have made an 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
@@ -4176,7 +4098,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(k->httpcode >= 300) {
if((!conn->bits.authneg) && !conn->bits.close &&
!conn->bits.rewindaftersend) {
!data->state.rewindbeforesend) {
/*
* General treatment of errors when about to send data. Including :
* "417 Expectation Failed", while waiting for 100-continue.
@@ -4186,7 +4108,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* something else should've considered the big picture and we
* avoid this check.
*
* rewindaftersend indicates that something has told libcurl to
* rewindbeforesend indicates that something has told libcurl to
* continue sending even if it gets discarded
*/
@@ -4235,9 +4157,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
}
if(conn->bits.rewindaftersend) {
/* We rewind after a complete send, so thus we continue
sending now */
if(data->state.rewindbeforesend &&
(conn->writesockfd != CURL_SOCKET_BAD)) {
/* We rewind before next send, continue sending now */
infof(data, "Keep sending data to get tossed away");
k->keepon |= KEEP_SEND;
}
@@ -4250,7 +4172,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* If we requested a "no body", this is a good time to get
* out and return home.
*/
if(data->set.opt_no_body)
if(data->req.no_body)
*stop_reading = TRUE;
#ifndef CURL_DISABLE_RTSP
else if((conn->handler->protocol & CURLPROTO_RTSP) &&
+1 -1
View File
@@ -317,7 +317,7 @@ struct http_conn {
uint8_t binsettings[H2_BINSETTINGS_LEN];
size_t binlen; /* length of the binsettings data */
/* We associate the connnectdata struct with the connection, but we need to
/* We associate the connectdata struct with the connection, but we need to
make sure we can identify the current "driving" transfer. This is a
work-around for the lack of nghttp2_session_set_user_data() in older
nghttp2 versions that we want to support. (Added in 1.31.0) */
+7 -7
View File
@@ -109,7 +109,7 @@ static int http2_getsock(struct Curl_easy *data,
sock[0] = conn->sock[FIRSTSOCKET];
if(!(k->keepon & KEEP_RECV_PAUSE))
/* Unless paused - in a HTTP/2 connection we can basically always get a
/* Unless paused - in an HTTP/2 connection we can basically always get a
frame so we should always be ready for one */
bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
@@ -191,7 +191,7 @@ static bool http2_connisdead(struct Curl_easy *data, struct connectdata *conn)
}
else if(sval & CURL_CSELECT_IN) {
/* readable with no error. could still be closed */
dead = !Curl_connalive(conn);
dead = !Curl_connalive(data, conn);
if(!dead) {
/* This happens before we've sent off a request and the connection is
not in use by any other transfer, there shouldn't be any data here,
@@ -1024,9 +1024,9 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
if(!check)
/* no memory */
return NGHTTP2_ERR_CALLBACK_FAILURE;
if(!Curl_strcasecompare(check, (const char *)value) &&
if(!strcasecompare(check, (const char *)value) &&
((conn->remote_port != conn->given->defport) ||
!Curl_strcasecompare(conn->host.name, (const char *)value))) {
!strcasecompare(conn->host.name, (const char *)value))) {
/* This is push is not for the same authority that was asked for in
* the URL. RFC 7540 section 8.2 says: "A client MUST treat a
* PUSH_PROMISE for which the server is not authoritative as a stream
@@ -1120,7 +1120,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
/* nghttp2 guarantees that namelen > 0, and :status was already
received, and this is not pseudo-header field . */
/* convert to a HTTP1-style header */
/* convert to an HTTP1-style header */
result = Curl_dyn_addn(&stream->header_recvbuf, name, namelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -1351,7 +1351,7 @@ static CURLcode http2_init(struct Curl_easy *data, struct connectdata *conn)
}
/*
* Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
* Append headers to ask for an HTTP1.1 to HTTP2 upgrade.
*/
CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
struct Curl_easy *data)
@@ -2307,7 +2307,7 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
Curl_http2_remove_child(data->set.stream_depends_on, data);
}
/* Only call this function for a transfer that already got a HTTP/2
/* Only call this function for a transfer that already got an HTTP/2
CURLE_HTTP2_STREAM error! */
bool Curl_h2_http_1_1_error(struct Curl_easy *data)
{
+1 -1
View File
@@ -73,7 +73,7 @@ bool Curl_h2_http_1_1_error(struct Curl_easy *data);
#define Curl_http2_init_state(x)
#define Curl_http2_init_userset(x)
#define Curl_http2_done(x,y)
#define Curl_http2_done_sending(x,y)
#define Curl_http2_done_sending(x,y) (void)y
#define Curl_http2_add_child(x, y, z)
#define Curl_http2_remove_child(x, y)
#define Curl_http2_cleanup_dependencies(x)
+57 -17
View File
@@ -32,8 +32,6 @@
#include "http_aws_sigv4.h"
#include "curl_sha256.h"
#include "transfer.h"
#include "strcase.h"
#include "parsedate.h"
#include "sendf.h"
@@ -118,7 +116,7 @@ static void trim_headers(struct curl_slist *head)
}
}
/* maximum lenth for the aws sivg4 parts */
/* maximum length for the aws sivg4 parts */
#define MAX_SIGV4_LEN 64
#define MAX_SIGV4_LEN_TXT "64"
@@ -268,6 +266,40 @@ fail:
return ret;
}
#define CONTENT_SHA256_KEY_LEN (MAX_SIGV4_LEN + sizeof("X--Content-Sha256"))
/* try to parse a payload hash from the content-sha256 header */
static char *parse_content_sha_hdr(struct Curl_easy *data,
const char *provider1,
size_t *value_len)
{
char key[CONTENT_SHA256_KEY_LEN];
size_t key_len;
char *value;
size_t len;
key_len = msnprintf(key, sizeof(key), "x-%s-content-sha256", provider1);
value = Curl_checkheaders(data, key, key_len);
if(!value)
return NULL;
value = strchr(value, ':');
if(!value)
return NULL;
++value;
while(*value && ISBLANK(*value))
++value;
len = strlen(value);
while(len > 0 && ISBLANK(value[len-1]))
--len;
*value_len = len;
return value;
}
CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
{
CURLcode ret = CURLE_OUT_OF_MEMORY;
@@ -286,6 +318,8 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
struct dynbuf canonical_headers;
struct dynbuf signed_headers;
char *date_header = NULL;
char *payload_hash = NULL;
size_t payload_hash_len = 0;
const char *post_data = data->set.postfields;
size_t post_data_len = 0;
unsigned char sha_hash[32];
@@ -308,7 +342,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
return CURLE_OK;
}
/* we init thoses buffers here, so goto fail will free initialized dynbuf */
/* we init those buffers here, so goto fail will free initialized dynbuf */
Curl_dyn_init(&canonical_headers, CURL_MAX_HTTP_HEADER);
Curl_dyn_init(&signed_headers, CURL_MAX_HTTP_HEADER);
@@ -403,17 +437,23 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
memcpy(date, timestamp, sizeof(date));
date[sizeof(date) - 1] = 0;
if(post_data) {
if(data->set.postfieldsize < 0)
post_data_len = strlen(post_data);
else
post_data_len = (size_t)data->set.postfieldsize;
}
if(Curl_sha256it(sha_hash, (const unsigned char *) post_data,
post_data_len))
goto fail;
payload_hash = parse_content_sha_hdr(data, provider1, &payload_hash_len);
sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
if(!payload_hash) {
if(post_data) {
if(data->set.postfieldsize < 0)
post_data_len = strlen(post_data);
else
post_data_len = (size_t)data->set.postfieldsize;
}
if(Curl_sha256it(sha_hash, (const unsigned char *) post_data,
post_data_len))
goto fail;
sha256_to_hex(sha_hex, sha_hash, sizeof(sha_hex));
payload_hash = sha_hex;
payload_hash_len = strlen(sha_hex);
}
{
Curl_HttpReq httpreq;
@@ -427,13 +467,13 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
"%s\n" /* CanonicalQueryString */
"%s\n" /* CanonicalHeaders */
"%s\n" /* SignedHeaders */
"%s", /* HashedRequestPayload in hex */
"%.*s", /* HashedRequestPayload in hex */
method,
data->state.up.path,
data->state.up.query ? data->state.up.query : "",
Curl_dyn_ptr(&canonical_headers),
Curl_dyn_ptr(&signed_headers),
sha_hex);
(int)payload_hash_len, payload_hash);
if(!canonical_request)
goto fail;
}
@@ -460,7 +500,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data, bool proxy)
/*
* Google allows using RSA key instead of HMAC, so this code might change
* in the future. For now we ony support HMAC.
* in the future. For now we only support HMAC.
*/
str_to_sign = curl_maprintf("%s4-HMAC-SHA256\n" /* Algorithm */
"%s\n" /* RequestDateTime */
+1 -1
View File
@@ -113,7 +113,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
*wrote = 0; /* nothing's written yet */
/* the original data is written to the client, but we go on with the
chunk read process, to properly calculate the content length*/
chunk read process, to properly calculate the content length */
if(data->set.http_te_skip && !k->ignorebody) {
result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen);
if(result) {
+1 -1
View File
@@ -81,7 +81,7 @@ CURLcode Curl_output_digest(struct Curl_easy *data,
bool have_chlg;
/* Point to the address of the pointer that holds the string to send to the
server, which is for a plain host or for a HTTP proxy */
server, which is for a plain host or for an HTTP proxy */
char **allocuserpwd;
/* Point to the name and password for this */
+1 -1
View File
@@ -134,7 +134,7 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
struct bufref ntlmmsg;
/* point to the address of the pointer that holds the string to send to the
server, which is for a plain host or for a HTTP proxy */
server, which is for a plain host or for an HTTP proxy */
char **allocuserpwd;
/* point to the username, password, service and host */
File diff suppressed because it is too large Load Diff
+7 -43
View File
@@ -28,54 +28,18 @@
#include "urldata.h"
#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
/* ftp can use this as well */
CURLcode Curl_proxyCONNECT(struct Curl_easy *data,
int tunnelsocket,
const char *hostname, int remote_port);
/* Default proxy timeout in milliseconds */
#define PROXY_TIMEOUT (3600*1000)
CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex);
CURLcode Curl_conn_http_proxy_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
bool Curl_connect_complete(struct connectdata *conn);
bool Curl_connect_ongoing(struct connectdata *conn);
int Curl_connect_getsock(struct connectdata *conn);
void Curl_connect_done(struct Curl_easy *data);
CURLcode Curl_conn_haproxy_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex);
#else
#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN
#define Curl_proxy_connect(x,y) CURLE_OK
#define Curl_connect_complete(x) CURLE_OK
#define Curl_connect_ongoing(x) FALSE
#define Curl_connect_getsock(x) 0
#define Curl_connect_done(x)
#endif
void Curl_connect_free(struct Curl_easy *data);
/* struct for HTTP CONNECT state data */
struct http_connect_state {
struct HTTP http_proxy;
struct HTTP *prot_save;
struct dynbuf rcvbuf;
struct dynbuf req;
size_t nsend;
size_t headerlines;
enum keeponval {
KEEPON_DONE,
KEEPON_CONNECT,
KEEPON_IGNORE
} keepon;
curl_off_t cl; /* size of content to read and ignore */
enum {
TUNNEL_INIT, /* init/default/no tunnel state */
TUNNEL_CONNECT, /* CONNECT has been sent off */
TUNNEL_COMPLETE, /* CONNECT response received completely */
TUNNEL_EXIT
} tunnel_state;
BIT(chunked_encoding);
BIT(close_connection);
};
#endif /* !CURL_DISABLE_PROXY && !CURL_DISABLE_HTTP */
#endif /* HEADER_CURL_HTTP_PROXY_H */
+193
View File
@@ -0,0 +1,193 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2022, 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.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.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/*
* IDN conversions
*/
#include "curl_setup.h"
#include "urldata.h"
#include "idn.h"
#include "sendf.h"
#include "curl_multibyte.h"
#include "warnless.h"
#ifdef USE_LIBIDN2
#include <idn2.h>
#if defined(WIN32) && defined(UNICODE)
#define IDN2_LOOKUP(name, host, flags) \
idn2_lookup_u8((const uint8_t *)name, (uint8_t **)host, flags)
#else
#define IDN2_LOOKUP(name, host, flags) \
idn2_lookup_ul((const char *)name, (char **)host, flags)
#endif
#endif /* USE_LIBIDN2 */
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
#ifdef USE_WIN32_IDN
/* using Windows kernel32 and normaliz libraries. */
#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x600
WINBASEAPI int WINAPI IdnToAscii(DWORD dwFlags,
const WCHAR *lpUnicodeCharStr,
int cchUnicodeChar,
WCHAR *lpASCIICharStr,
int cchASCIIChar);
WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags,
const WCHAR *lpASCIICharStr,
int cchASCIIChar,
WCHAR *lpUnicodeCharStr,
int cchUnicodeChar);
#endif
#define IDN_MAX_LENGTH 255
bool Curl_win32_idn_to_ascii(const char *in, char **out)
{
bool success = FALSE;
wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
if(in_w) {
wchar_t punycode[IDN_MAX_LENGTH];
int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH);
curlx_unicodefree(in_w);
if(chars) {
char *mstr = curlx_convert_wchar_to_UTF8(punycode);
if(mstr) {
*out = strdup(mstr);
curlx_unicodefree(mstr);
if(*out)
success = TRUE;
}
}
}
return success;
}
#endif /* USE_WIN32_IDN */
/*
* Helpers for IDNA conversions.
*/
bool Curl_is_ASCII_name(const char *hostname)
{
/* get an UNSIGNED local version of the pointer */
const unsigned char *ch = (const unsigned char *)hostname;
if(!hostname) /* bad input, consider it ASCII! */
return TRUE;
while(*ch) {
if(*ch++ & 0x80)
return FALSE;
}
return TRUE;
}
#ifdef USE_IDN
/*
* Curl_idn_decode() returns an allocated IDN decoded string if it was
* possible. NULL on error.
*/
static char *Curl_idn_decode(const char *input)
{
char *decoded = NULL;
#ifdef USE_LIBIDN2
if(idn2_check_version(IDN2_VERSION)) {
int flags = IDN2_NFC_INPUT
#if IDN2_VERSION_NUMBER >= 0x00140000
/* IDN2_NFC_INPUT: Normalize input string using normalization form C.
IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
processing. */
| IDN2_NONTRANSITIONAL
#endif
;
int rc = IDN2_LOOKUP(input, &decoded, flags);
if(rc != IDN2_OK)
/* fallback to TR46 Transitional mode for better IDNA2003
compatibility */
rc = IDN2_LOOKUP(input, &decoded, IDN2_TRANSITIONAL);
if(rc != IDN2_OK)
decoded = NULL;
}
#elif defined(USE_WIN32_IDN)
if(!Curl_win32_idn_to_ascii(input, &decoded))
decoded = NULL;
#endif
return decoded;
}
/*
* Frees data allocated by idnconvert_hostname()
*/
void Curl_free_idnconverted_hostname(struct hostname *host)
{
#if defined(USE_LIBIDN2)
if(host->encalloc) {
idn2_free(host->encalloc); /* must be freed with idn2_free() since this was
allocated by libidn */
host->encalloc = NULL;
}
#elif defined(USE_WIN32_IDN)
free(host->encalloc); /* must be freed with free() since this was
allocated by Curl_win32_idn_to_ascii */
host->encalloc = NULL;
#else
(void)host;
#endif
}
#endif /* USE_IDN */
/*
* Perform any necessary IDN conversion of hostname
*/
CURLcode Curl_idnconvert_hostname(struct hostname *host)
{
/* set the name we use to display the host name */
host->dispname = host->name;
#ifdef USE_IDN
/* Check name for non-ASCII and convert hostname if we can */
if(!Curl_is_ASCII_name(host->name)) {
char *decoded = Curl_idn_decode(host->name);
if(decoded) {
/* successful */
host->encalloc = decoded;
/* change the name pointer to point to the encoded hostname */
host->name = host->encalloc;
}
else
return CURLE_URL_MALFORMAT;
}
#endif
return CURLE_OK;
}
+38
View File
@@ -0,0 +1,38 @@
#ifndef HEADER_CURL_IDN_H
#define HEADER_CURL_IDN_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2022, 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.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.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#ifdef USE_WIN32_IDN
bool Curl_win32_idn_to_ascii(const char *in, char **out);
#endif /* USE_WIN32_IDN */
bool Curl_is_ASCII_name(const char *hostname);
CURLcode Curl_idnconvert_hostname(struct hostname *host);
#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
#define USE_IDN
void Curl_free_idnconverted_hostname(struct hostname *host);
#else
#define Curl_free_idnconverted_hostname(x)
#endif
#endif /* HEADER_CURL_IDN_H */
-121
View File
@@ -1,121 +0,0 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2022, 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.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.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/*
* IDN conversions using Windows kernel32 and normaliz libraries.
*/
#include "curl_setup.h"
#ifdef USE_WIN32_IDN
#include "curl_multibyte.h"
#include "curl_memory.h"
#include "warnless.h"
/* The last #include file should be: */
#include "memdebug.h"
#ifdef WANT_IDN_PROTOTYPES
# if defined(_SAL_VERSION)
WINNORMALIZEAPI int WINAPI
IdnToAscii(_In_ DWORD dwFlags,
_In_reads_(cchUnicodeChar) LPCWSTR lpUnicodeCharStr,
_In_ int cchUnicodeChar,
_Out_writes_opt_(cchASCIIChar) LPWSTR lpASCIICharStr,
_In_ int cchASCIIChar);
WINNORMALIZEAPI int WINAPI
IdnToUnicode(_In_ DWORD dwFlags,
_In_reads_(cchASCIIChar) LPCWSTR lpASCIICharStr,
_In_ int cchASCIIChar,
_Out_writes_opt_(cchUnicodeChar) LPWSTR lpUnicodeCharStr,
_In_ int cchUnicodeChar);
# else
WINBASEAPI int WINAPI IdnToAscii(DWORD dwFlags,
const WCHAR *lpUnicodeCharStr,
int cchUnicodeChar,
WCHAR *lpASCIICharStr,
int cchASCIIChar);
WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags,
const WCHAR *lpASCIICharStr,
int cchASCIIChar,
WCHAR *lpUnicodeCharStr,
int cchUnicodeChar);
# endif
#endif
#define IDN_MAX_LENGTH 255
bool Curl_win32_idn_to_ascii(const char *in, char **out);
bool Curl_win32_ascii_to_idn(const char *in, char **out);
bool Curl_win32_idn_to_ascii(const char *in, char **out)
{
bool success = FALSE;
wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
if(in_w) {
wchar_t punycode[IDN_MAX_LENGTH];
int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH);
curlx_unicodefree(in_w);
if(chars) {
char *mstr = curlx_convert_wchar_to_UTF8(punycode);
if(mstr) {
*out = strdup(mstr);
curlx_unicodefree(mstr);
if(*out)
success = TRUE;
}
}
}
return success;
}
bool Curl_win32_ascii_to_idn(const char *in, char **out)
{
bool success = FALSE;
wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
if(in_w) {
size_t in_len = wcslen(in_w) + 1;
wchar_t unicode[IDN_MAX_LENGTH];
int chars = IdnToUnicode(0, in_w, curlx_uztosi(in_len),
unicode, IDN_MAX_LENGTH);
curlx_unicodefree(in_w);
if(chars) {
char *mstr = curlx_convert_wchar_to_UTF8(unicode);
if(mstr) {
*out = strdup(mstr);
curlx_unicodefree(mstr);
if(*out)
success = TRUE;
}
}
}
return success;
}
#endif /* USE_WIN32_IDN */
+15 -15
View File
@@ -56,11 +56,6 @@
#include <inet.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
@@ -75,11 +70,11 @@
#include "strtoofft.h"
#include "strcase.h"
#include "vtls/vtls.h"
#include "cfilters.h"
#include "connect.h"
#include "select.h"
#include "multiif.h"
#include "url.h"
#include "strcase.h"
#include "bufref.h"
#include "curl_sasl.h"
#include "warnless.h"
@@ -479,9 +474,15 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
{
/* Start the SSL connection */
struct imap_conn *imapc = &conn->proto.imapc;
CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
FIRSTSOCKET, &imapc->ssldone);
CURLcode result;
if(!Curl_conn_is_ssl(data, FIRSTSOCKET)) {
result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
if(result)
goto out;
}
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &imapc->ssldone);
if(!result) {
if(imapc->state != IMAP_UPGRADETLS)
state(data, IMAP_UPGRADETLS);
@@ -491,7 +492,7 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
result = imap_perform_capability(data, conn);
}
}
out:
return result;
}
@@ -776,7 +777,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data)
/* Add external headers and mime version. */
curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
result = Curl_mime_prepare_headers(data, &data->set.mimepost, NULL,
NULL, MIMESTRATEGY_MAIL);
if(!result)
@@ -951,7 +952,7 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data,
line += wordlen;
}
}
else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
else if(data->set.use_ssl && !Curl_conn_is_ssl(data, FIRSTSOCKET)) {
/* PREAUTH is not compatible with STARTTLS. */
if(imapcode == IMAP_RESP_OK && imapc->tls_supported && !imapc->preauth) {
/* Switch to TLS connection now */
@@ -1385,8 +1386,7 @@ static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done)
struct imap_conn *imapc = &conn->proto.imapc;
if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
FIRSTSOCKET, &imapc->ssldone);
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &imapc->ssldone);
if(result || !imapc->ssldone)
return result;
}
@@ -1561,7 +1561,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
DEBUGF(infof(data, "DO phase starts"));
if(data->set.opt_no_body) {
if(data->req.no_body) {
/* Requested no body means no transfer */
imap->transfer = PPTRANSFER_INFO;
}
@@ -1603,7 +1603,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
/* Run the state-machine */
result = imap_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
*connected = Curl_conn_is_connected(conn, FIRSTSOCKET);
if(*dophase_done)
DEBUGF(infof(data, "DO phase is complete"));
+11 -8
View File
@@ -41,6 +41,9 @@
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include "urldata.h"
#include "curl_base64.h"
@@ -451,14 +454,14 @@ static int ftp_send_command(struct Curl_easy *data, const char *message, ...)
/* Read |len| from the socket |fd| and store it in |to|. Return a CURLcode
saying whether an error occurred or CURLE_OK if |len| was read. */
static CURLcode
socket_read(curl_socket_t fd, void *to, size_t len)
socket_read(struct Curl_easy *data, curl_socket_t fd, void *to, size_t len)
{
char *to_p = to;
CURLcode result;
ssize_t nread = 0;
while(len > 0) {
result = Curl_read_plain(fd, to_p, len, &nread);
result = Curl_read_plain(data, fd, to_p, len, &nread);
if(!result) {
len -= nread;
to_p += nread;
@@ -499,15 +502,15 @@ socket_write(struct Curl_easy *data, curl_socket_t fd, const void *to,
return CURLE_OK;
}
static CURLcode read_data(struct connectdata *conn,
curl_socket_t fd,
static CURLcode read_data(struct Curl_easy *data, curl_socket_t fd,
struct krb5buffer *buf)
{
struct connectdata *conn = data->conn;
int len;
CURLcode result;
int nread;
result = socket_read(fd, &len, sizeof(len));
result = socket_read(data, fd, &len, sizeof(len));
if(result)
return result;
@@ -522,7 +525,7 @@ static CURLcode read_data(struct connectdata *conn,
if(!len || !buf->data)
return CURLE_OUT_OF_MEMORY;
result = socket_read(fd, buf->data, len);
result = socket_read(data, fd, buf->data, len);
if(result)
return result;
nread = conn->mech->decode(conn->app_data, buf->data, len,
@@ -557,7 +560,7 @@ static ssize_t sec_recv(struct Curl_easy *data, int sockindex,
/* Handle clear text response. */
if(conn->sec_complete == 0 || conn->data_prot == PROT_CLEAR)
return sread(fd, buffer, len);
return Curl_recv_plain(data, sockindex, buffer, len, err);
if(conn->in_buffer.eof_flag) {
conn->in_buffer.eof_flag = 0;
@@ -570,7 +573,7 @@ static ssize_t sec_recv(struct Curl_easy *data, int sockindex,
buffer += bytes_read;
while(len > 0) {
if(read_data(conn, fd, &conn->in_buffer))
if(read_data(data, fd, &conn->in_buffer))
return -1;
if(conn->in_buffer.size == 0) {
if(bytes_read > 0)
+3 -5
View File
@@ -565,8 +565,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
result = Curl_client_write(data, CLIENTWRITE_BODY, (char *) name,
name_len);
result = Curl_client_write(data, CLIENTWRITE_BODY, name, name_len);
if(result) {
FREE_ON_WINLDAP(name);
ldap_memfree(dn);
@@ -622,8 +621,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
goto quit;
}
result = Curl_client_write(data, CLIENTWRITE_BODY,
(char *) attr, attr_len);
result = Curl_client_write(data, CLIENTWRITE_BODY, attr, attr_len);
if(result) {
ldap_value_free_len(vals);
FREE_ON_WINLDAP(attr);
@@ -648,7 +646,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
dlsize += attr_len + 3;
if((attr_len > 7) &&
(strcmp(";binary", (char *) attr + (attr_len - 7)) == 0)) {
(strcmp(";binary", attr + (attr_len - 7)) == 0)) {
/* Binary attribute, encode to base64. */
result = Curl_base64_encode(vals[i]->bv_val, vals[i]->bv_len,
&val_b64, &val_b64_sz);
+30 -43
View File
@@ -26,10 +26,11 @@
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
#include <string.h>
#include "curl_md4.h"
#include "warnless.h"
#ifdef USE_OPENSSL
#include <openssl/opensslconf.h>
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3) && \
@@ -53,21 +54,44 @@
#else
#include <mbedtls/config.h>
#endif
#if(MBEDTLS_VERSION_NUMBER >= 0x02070000)
#define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
#endif
#endif /* USE_MBEDTLS */
#if defined(USE_GNUTLS)
#include <nettle/md4.h>
/* When OpenSSL or wolfSSL is available, we use their MD4 functions. */
#elif defined(USE_WOLFSSL) && !defined(WOLFSSL_NO_MD4)
#include <wolfssl/openssl/md4.h>
#elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
#include <openssl/md4.h>
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
(__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \
(__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
(__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
#define AN_APPLE_OS
#include <CommonCrypto/CommonDigest.h>
#elif defined(USE_WIN32_CRYPTO)
#include <wincrypt.h>
#elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C))
#include <mbedtls/md4.h>
#endif
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#if defined(USE_WOLFSSL) && !defined(WOLFSSL_NO_MD4)
#elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
#elif defined(USE_GNUTLS)
typedef struct md4_ctx MD4_CTX;
static void MD4_Init(MD4_CTX *ctx)
@@ -85,27 +109,7 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
md4_digest(ctx, MD4_DIGEST_SIZE, result);
}
/* When OpenSSL or wolfSSL is available, we use their MD4 functions. */
#elif defined(USE_WOLFSSL) && !defined(WOLFSSL_NO_MD4)
#include <wolfssl/openssl/md4.h>
#elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
#include <openssl/md4.h>
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
(__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \
(__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
(__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
#include <CommonCrypto/CommonDigest.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#elif defined(AN_APPLE_OS)
typedef CC_MD4_CTX MD4_CTX;
static void MD4_Init(MD4_CTX *ctx)
@@ -125,13 +129,6 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
#elif defined(USE_WIN32_CRYPTO)
#include <wincrypt.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
struct md4_ctx {
HCRYPTPROV hCryptProv;
HCRYPTHASH hHash;
@@ -171,13 +168,6 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
#elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C))
#include <mbedtls/md4.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
struct md4_ctx {
void *data;
unsigned long size;
@@ -255,9 +245,6 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
* compile-time configuration.
*/
#include <string.h>
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD4_u32plus;
+24 -41
View File
@@ -26,6 +26,7 @@
#ifndef CURL_DISABLE_CRYPTO_AUTH
#include <string.h>
#include <curl/curl.h>
#include "curl_md5.h"
@@ -56,12 +57,32 @@
#endif
#if defined(USE_GNUTLS)
#include <nettle/md5.h>
#elif defined(USE_OPENSSL_MD5)
#include <openssl/md5.h>
#elif defined(USE_WOLFSSL_MD5)
#include <wolfssl/openssl/md5.h>
#elif defined(USE_MBEDTLS)
#include <mbedtls/md5.h>
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
(__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \
(__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
(__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
#define AN_APPLE_OS
#include <CommonCrypto/CommonDigest.h>
#elif defined(USE_WIN32_CRYPTO)
#include <wincrypt.h>
#endif
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#if defined(USE_GNUTLS)
typedef struct md5_ctx my_md5_ctx;
static CURLcode my_md5_init(my_md5_ctx *ctx)
@@ -84,17 +105,6 @@ static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
#elif defined(USE_OPENSSL_MD5) || defined(USE_WOLFSSL_MD5)
/* When OpenSSL or wolfSSL is available, we use their MD5 functions. */
#if defined(USE_OPENSSL_MD5)
#include <openssl/md5.h>
#elif defined(USE_WOLFSSL_MD5)
#include <wolfssl/openssl/md5.h>
#endif
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
typedef MD5_CTX my_md5_ctx;
static CURLcode my_md5_init(my_md5_ctx *ctx)
@@ -119,13 +129,6 @@ static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
#elif defined(USE_MBEDTLS)
#include <mbedtls/md5.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
typedef mbedtls_md5_context my_md5_ctx;
static CURLcode my_md5_init(my_md5_ctx *ctx)
@@ -162,12 +165,7 @@ static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
#endif
}
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
(__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \
defined(__MAC_OS_X_VERSION_MIN_ALLOWED) && \
(__MAC_OS_X_VERSION_MIN_ALLOWED < 101500)) || \
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
(__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
#elif defined(AN_APPLE_OS)
/* For Apple operating systems: CommonCrypto has the functions we need.
These functions are available on Tiger and later, as well as iOS 2.0
@@ -175,11 +173,7 @@ static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
Declaring the functions as static like this seems to be a bit more
reliable than defining COMMON_DIGEST_FOR_OPENSSL on older cats. */
# include <CommonCrypto/CommonDigest.h>
# define my_md5_ctx CC_MD5_CTX
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
static CURLcode my_md5_init(my_md5_ctx *ctx)
{
@@ -203,11 +197,6 @@ static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
#elif defined(USE_WIN32_CRYPTO)
#include <wincrypt.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
struct md5_ctx {
HCRYPTPROV hCryptProv;
HCRYPTHASH hHash;
@@ -288,12 +277,6 @@ static void my_md5_final(unsigned char *digest, my_md5_ctx *ctx)
* compile-time configuration.
*/
#include <string.h>
/* The last #include files should be: */
#include "curl_memory.h"
#include "memdebug.h"
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD5_u32plus;
+15 -19
View File
@@ -1175,7 +1175,7 @@ void Curl_mime_cleanpart(curl_mimepart *part)
Curl_safefree(part->mimetype);
Curl_safefree(part->name);
Curl_safefree(part->filename);
Curl_mime_initpart(part, part->easy);
Curl_mime_initpart(part);
}
/* Recursively delete a mime handle and its parts. */
@@ -1195,7 +1195,8 @@ void curl_mime_free(curl_mime *mime)
}
}
CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
CURLcode Curl_mime_duppart(struct Curl_easy *data,
curl_mimepart *dst, const curl_mimepart *src)
{
curl_mime *mime;
curl_mimepart *d;
@@ -1224,13 +1225,13 @@ CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
case MIMEKIND_MULTIPART:
/* No one knows about the cloned subparts, thus always attach ownership
to the part. */
mime = curl_mime_init(dst->easy);
mime = curl_mime_init(data);
res = mime? curl_mime_subparts(dst, mime): CURLE_OUT_OF_MEMORY;
/* Duplicate subparts. */
for(s = ((curl_mime *) src->arg)->firstpart; !res && s; s = s->nextpart) {
d = curl_mime_addpart(mime);
res = d? Curl_mime_duppart(d, s): CURLE_OUT_OF_MEMORY;
res = d? Curl_mime_duppart(data, d, s): CURLE_OUT_OF_MEMORY;
}
break;
default: /* Invalid kind: should not occur. */
@@ -1282,7 +1283,6 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
mime = (curl_mime *) malloc(sizeof(*mime));
if(mime) {
mime->easy = easy;
mime->parent = NULL;
mime->firstpart = NULL;
mime->lastpart = NULL;
@@ -1302,10 +1302,9 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
}
/* Initialize a mime part. */
void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
void Curl_mime_initpart(curl_mimepart *part)
{
memset((char *) part, 0, sizeof(*part));
part->easy = easy;
part->lastreadstatus = 1; /* Successful read status. */
mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
}
@@ -1321,7 +1320,7 @@ curl_mimepart *curl_mime_addpart(curl_mime *mime)
part = (curl_mimepart *) malloc(sizeof(*part));
if(part) {
Curl_mime_initpart(part, mime->easy);
Curl_mime_initpart(part);
part->parent = mime;
if(mime->lastpart)
@@ -1551,10 +1550,6 @@ CURLcode Curl_mime_set_subparts(curl_mimepart *part,
cleanup_part_content(part);
if(subparts) {
/* Must belong to the same data handle. */
if(part->easy && subparts->easy && part->easy != subparts->easy)
return CURLE_BAD_FUNCTION_ARGUMENT;
/* Should not have been attached already. */
if(subparts->parent)
return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -1565,8 +1560,7 @@ CURLcode Curl_mime_set_subparts(curl_mimepart *part,
while(root->parent && root->parent->parent)
root = root->parent->parent;
if(subparts == root) {
if(part->easy)
failf(part->easy, "Can't add itself as a subpart");
/* Can't add as a subpart of itself. */
return CURLE_BAD_FUNCTION_ARGUMENT;
}
}
@@ -1636,7 +1630,7 @@ static size_t slist_size(struct curl_slist *s,
static curl_off_t multipart_size(curl_mime *mime)
{
curl_off_t size;
size_t boundarysize;
curl_off_t boundarysize;
curl_mimepart *part;
if(!mime)
@@ -1766,7 +1760,8 @@ static bool content_type_match(const char *contenttype,
return FALSE;
}
CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
CURLcode Curl_mime_prepare_headers(struct Curl_easy *data,
curl_mimepart *part,
const char *contenttype,
const char *disposition,
enum mimestrategy strategy)
@@ -1835,12 +1830,12 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
char *filename = NULL;
if(part->name) {
name = escape_string(part->easy, part->name, strategy);
name = escape_string(data, part->name, strategy);
if(!name)
ret = CURLE_OUT_OF_MEMORY;
}
if(!ret && part->filename) {
filename = escape_string(part->easy, part->filename, strategy);
filename = escape_string(data, part->filename, strategy);
if(!filename)
ret = CURLE_OUT_OF_MEMORY;
}
@@ -1897,7 +1892,8 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
if(content_type_match(contenttype, STRCONST("multipart/form-data")))
disposition = "form-data";
for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) {
ret = Curl_mime_prepare_headers(subpart, NULL, disposition, strategy);
ret = Curl_mime_prepare_headers(data, subpart, NULL,
disposition, strategy);
if(ret)
return ret;
}
+8 -8
View File
@@ -99,7 +99,6 @@ struct mime_state {
/* A mime multipart. */
struct curl_mime {
struct Curl_easy *easy; /* The associated easy handle. */
curl_mimepart *parent; /* Parent part. */
curl_mimepart *firstpart; /* First part. */
curl_mimepart *lastpart; /* Last part. */
@@ -109,7 +108,6 @@ struct curl_mime {
/* A mime part. */
struct curl_mimepart {
struct Curl_easy *easy; /* The associated easy handle. */
curl_mime *parent; /* Parent mime structure. */
curl_mimepart *nextpart; /* Forward linked list. */
enum mimekind kind; /* The part kind. */
@@ -139,14 +137,16 @@ CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
!defined(CURL_DISABLE_IMAP))
/* Prototypes. */
void Curl_mime_initpart(struct curl_mimepart *part, struct Curl_easy *easy);
void Curl_mime_initpart(struct curl_mimepart *part);
void Curl_mime_cleanpart(struct curl_mimepart *part);
CURLcode Curl_mime_duppart(struct curl_mimepart *dst,
CURLcode Curl_mime_duppart(struct Curl_easy *data,
struct curl_mimepart *dst,
const curl_mimepart *src);
CURLcode Curl_mime_set_subparts(struct curl_mimepart *part,
struct curl_mime *subparts,
int take_ownership);
CURLcode Curl_mime_prepare_headers(struct curl_mimepart *part,
CURLcode Curl_mime_prepare_headers(struct Curl_easy *data,
struct curl_mimepart *part,
const char *contenttype,
const char *disposition,
enum mimestrategy strategy);
@@ -159,11 +159,11 @@ void Curl_mime_unpause(struct curl_mimepart *part);
#else
/* if disabled */
#define Curl_mime_initpart(x,y)
#define Curl_mime_initpart(x)
#define Curl_mime_cleanpart(x)
#define Curl_mime_duppart(x,y) CURLE_OK /* Nothing to duplicate. Succeed */
#define Curl_mime_duppart(x,y,z) CURLE_OK /* Nothing to duplicate. Succeed */
#define Curl_mime_set_subparts(a,b,c) CURLE_NOT_BUILT_IN
#define Curl_mime_prepare_headers(a,b,c,d) CURLE_NOT_BUILT_IN
#define Curl_mime_prepare_headers(a,b,c,d,e) CURLE_NOT_BUILT_IN
#define Curl_mime_size(x) (curl_off_t) -1
#define Curl_mime_read NULL
#define Curl_mime_rewind(x) ((void)x, CURLE_NOT_BUILT_IN)
+2 -2
View File
@@ -242,7 +242,7 @@ static int init_connpack(char *packet, char *remain, int remain_pos)
/* keep-alive 0 = disabled */
packet[remain_pos + 9] = 0x00;
packet[remain_pos + 10] = 0x3c;
/*end of variable header*/
/* end of variable header */
return remain_pos + 10;
}
@@ -251,7 +251,7 @@ static CURLcode mqtt_connect(struct Curl_easy *data)
CURLcode result = CURLE_OK;
int pos = 0;
int rc = 0;
/*remain length*/
/* remain length */
int remain_pos = 0;
char remain[4] = {0};
size_t packetlen = 0;
+127 -114
View File
@@ -29,6 +29,7 @@
#include "urldata.h"
#include "transfer.h"
#include "url.h"
#include "cfilters.h"
#include "connect.h"
#include "progress.h"
#include "easyif.h"
@@ -160,7 +161,7 @@ static void mstate(struct Curl_easy *data, CURLMstate state
NULL, /* TUNNELING */
NULL, /* PROTOCONNECT */
NULL, /* PROTOCONNECTING */
Curl_connect_free, /* DO */
NULL, /* DO */
NULL, /* DOING */
NULL, /* DOING_MORE */
before_perform, /* DID */
@@ -709,6 +710,11 @@ static CURLcode multi_done(struct Curl_easy *data,
#endif
) || conn->bits.close
|| (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
DEBUGF(infof(data, "multi_done, not re-using connection=%ld, forbid=%d"
", close=%d, premature=%d, stream=%d",
conn->connection_id,
data->set.reuse_forbid, conn->bits.close, premature,
(conn->handler->flags & PROTOPT_STREAM)));
connclose(conn, "disconnecting");
Curl_conncache_remove_conn(data, conn, FALSE);
CONNCACHE_UNLOCK(data);
@@ -948,9 +954,8 @@ void Curl_detach_connection(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
if(conn) {
Curl_connect_done(data); /* if mid-CONNECT, shut it down */
Curl_conn_detach_data(conn, data);
Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL);
Curl_ssl_detach_conn(data, conn);
}
data->conn = NULL;
}
@@ -968,53 +973,9 @@ void Curl_attach_connection(struct Curl_easy *data,
data->conn = conn;
Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data,
&data->conn_queue);
Curl_conn_attach_data(conn, data);
if(conn->handler->attach)
conn->handler->attach(data, conn);
Curl_ssl_associate_conn(data, conn);
}
static int waitconnect_getsock(struct connectdata *conn,
curl_socket_t *sock)
{
int i;
int s = 0;
int rc = 0;
#ifdef USE_SSL
#ifndef CURL_DISABLE_PROXY
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
return Curl_ssl->getsock(conn, sock);
#endif
#endif
if(SOCKS_STATE(conn->cnnct.state))
return Curl_SOCKS_getsock(conn, sock, FIRSTSOCKET);
for(i = 0; i<2; i++) {
if(conn->tempsock[i] != CURL_SOCKET_BAD) {
sock[s] = conn->tempsock[i];
rc |= GETSOCK_WRITESOCK(s);
#ifdef ENABLE_QUIC
if(conn->transport == TRNSPRT_QUIC)
/* when connecting QUIC, we want to read the socket too */
rc |= GETSOCK_READSOCK(s);
#endif
s++;
}
}
return rc;
}
static int waitproxyconnect_getsock(struct connectdata *conn,
curl_socket_t *sock)
{
sock[0] = conn->sock[FIRSTSOCKET];
if(conn->connect_state)
return Curl_connect_getsock(conn);
return GETSOCK_WRITESOCK(0);
}
static int domore_getsock(struct Curl_easy *data,
@@ -1076,10 +1037,8 @@ static int multi_getsock(struct Curl_easy *data,
return doing_getsock(data, conn, socks);
case MSTATE_TUNNELING:
return waitproxyconnect_getsock(conn, socks);
case MSTATE_CONNECTING:
return waitconnect_getsock(conn, socks);
return Curl_conn_get_select_socks(data, FIRSTSOCKET, socks);
case MSTATE_DOING_MORE:
return domore_getsock(data, conn, socks);
@@ -1737,7 +1696,8 @@ static CURLcode protocol_connect(struct Curl_easy *data,
*protocol_done = FALSE;
if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
if(Curl_conn_is_connected(conn, FIRSTSOCKET)
&& conn->bits.protoconnstart) {
/* We already are connected, get back. This may happen when the connect
worked fine in the first call, like when we connect to a local server
or proxy. Note that we don't know if the protocol is actually done.
@@ -1751,21 +1711,6 @@ static CURLcode protocol_connect(struct Curl_easy *data,
}
if(!conn->bits.protoconnstart) {
#ifndef CURL_DISABLE_PROXY
result = Curl_proxy_connect(data, FIRSTSOCKET);
if(result)
return result;
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
/* wait for HTTPS proxy SSL initialization to complete */
return CURLE_OK;
if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
Curl_connect_ongoing(conn))
/* when using an HTTP tunnel proxy, await complete tunnel establishment
before proceeding further. Return CURLE_OK so we'll be called again */
return CURLE_OK;
#endif
if(conn->handler->connect_it) {
/* is there a protocol-specific connect() procedure? */
@@ -1784,6 +1729,90 @@ static CURLcode protocol_connect(struct Curl_easy *data,
return result; /* pass back status */
}
/*
* readrewind() rewinds the read stream. This is typically used for HTTP
* POST/PUT with multi-pass authentication when a sending was denied and a
* resend is necessary.
*/
static CURLcode readrewind(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
curl_mimepart *mimepart = &data->set.mimepost;
DEBUGASSERT(conn);
data->state.rewindbeforesend = FALSE; /* we rewind now */
/* explicitly switch off sending data on this connection now since we are
about to restart a new transfer and thus we want to avoid inadvertently
sending more data on the existing connection until the next transfer
starts */
data->req.keepon &= ~KEEP_SEND;
/* We have sent away data. If not using CURLOPT_POSTFIELDS or
CURLOPT_HTTPPOST, call app to rewind
*/
if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
struct HTTP *http = data->req.p.http;
if(http->sendit)
mimepart = http->sendit;
}
if(data->set.postfields ||
(data->state.httpreq == HTTPREQ_GET) ||
(data->state.httpreq == HTTPREQ_HEAD))
; /* no need to rewind */
else if(data->state.httpreq == HTTPREQ_POST_MIME ||
data->state.httpreq == HTTPREQ_POST_FORM) {
CURLcode result = Curl_mime_rewind(mimepart);
if(result) {
failf(data, "Cannot rewind mime/post data");
return result;
}
}
else {
if(data->set.seek_func) {
int err;
Curl_set_in_callback(data, true);
err = (data->set.seek_func)(data->set.seek_client, 0, SEEK_SET);
Curl_set_in_callback(data, false);
if(err) {
failf(data, "seek callback returned error %d", (int)err);
return CURLE_SEND_FAIL_REWIND;
}
}
else if(data->set.ioctl_func) {
curlioerr err;
Curl_set_in_callback(data, true);
err = (data->set.ioctl_func)(data, CURLIOCMD_RESTARTREAD,
data->set.ioctl_client);
Curl_set_in_callback(data, false);
infof(data, "the ioctl callback returned %d", (int)err);
if(err) {
failf(data, "ioctl callback returned error %d", (int)err);
return CURLE_SEND_FAIL_REWIND;
}
}
else {
/* If no CURLOPT_READFUNCTION is used, we know that we operate on a
given FILE * stream and we can actually attempt to rewind that
ourselves with fseek() */
if(data->state.fread_func == (curl_read_callback)fread) {
if(-1 != fseek(data->state.in, 0, SEEK_SET))
/* successful rewind */
return CURLE_OK;
}
/* no callback set or failure above, makes us fail at once */
failf(data, "necessary data rewind wasn't possible");
return CURLE_SEND_FAIL_REWIND;
}
}
return CURLE_OK;
}
/*
* Curl_preconnect() is called immediately before a connect starts. When a
* redirect is followed, this is then called multiple times during a single
@@ -1796,6 +1825,7 @@ CURLcode Curl_preconnect(struct Curl_easy *data)
if(!data->state.buffer)
return CURLE_OUT_OF_MEMORY;
}
return CURLE_OK;
}
@@ -1901,7 +1931,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(data->set.connecttimeout)
Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
result = Curl_connect(data, &async, &protocol_connected);
result = Curl_connect(data, &async, &connected);
if(CURLE_NO_CONNECTION_AVAILABLE == result) {
/* There was no connection available. We will go to the pending
state and wait for an available connection. */
@@ -1929,15 +1959,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
WAITDO or DO! */
rc = CURLM_CALL_MULTI_PERFORM;
if(protocol_connected)
multistate(data, MSTATE_DO);
if(connected)
multistate(data, MSTATE_PROTOCONNECT);
else {
#ifndef CURL_DISABLE_HTTP
if(Curl_connect_ongoing(data->conn))
multistate(data, MSTATE_TUNNELING);
else
#endif
multistate(data, MSTATE_CONNECTING);
multistate(data, MSTATE_CONNECTING);
}
}
}
@@ -1989,7 +2014,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(dns) {
/* Perform the next step in the connection phase, and then move on
to the WAITCONNECT state */
result = Curl_once_resolved(data, &protocol_connected);
result = Curl_once_resolved(data, &connected);
if(result)
/* if Curl_once_resolved() returns failure, the connection struct
@@ -1998,15 +2023,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
else {
/* call again please so that we get the next socket setup */
rc = CURLM_CALL_MULTI_PERFORM;
if(protocol_connected)
multistate(data, MSTATE_DO);
if(connected)
multistate(data, MSTATE_PROTOCONNECT);
else {
#ifndef CURL_DISABLE_HTTP
if(Curl_connect_ongoing(data->conn))
multistate(data, MSTATE_TUNNELING);
else
#endif
multistate(data, MSTATE_CONNECTING);
multistate(data, MSTATE_CONNECTING);
}
}
}
@@ -2035,16 +2055,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
else
#endif
if(!result) {
if(
#ifndef CURL_DISABLE_PROXY
(data->conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
#endif
Curl_connect_complete(data->conn)) {
rc = CURLM_CALL_MULTI_PERFORM;
/* initiate protocol connect phase */
multistate(data, MSTATE_PROTOCONNECT);
}
rc = CURLM_CALL_MULTI_PERFORM;
/* initiate protocol connect phase */
multistate(data, MSTATE_PROTOCONNECT);
}
else
stream_error = TRUE;
@@ -2054,27 +2067,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case MSTATE_CONNECTING:
/* awaiting a completion of an asynch TCP connect */
DEBUGASSERT(data->conn);
result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected);
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &connected);
if(connected && !result) {
#ifndef CURL_DISABLE_HTTP
if(
#ifndef CURL_DISABLE_PROXY
(data->conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
!data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
#endif
Curl_connect_ongoing(data->conn)) {
multistate(data, MSTATE_TUNNELING);
break;
}
#endif
rc = CURLM_CALL_MULTI_PERFORM;
#ifndef CURL_DISABLE_PROXY
multistate(data,
data->conn->bits.tunnel_proxy?
MSTATE_TUNNELING : MSTATE_PROTOCONNECT);
#else
multistate(data, MSTATE_PROTOCONNECT);
#endif
}
else if(result) {
/* failure detected */
@@ -2086,7 +2082,19 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
break;
case MSTATE_PROTOCONNECT:
result = protocol_connect(data, &protocol_connected);
if(data->state.rewindbeforesend)
result = readrewind(data);
if(!result && data->conn->bits.reuse) {
/* ftp seems to hang when protoconnect on reused connection
* since we handle PROTOCONNECT in general inside the filers, it
* seems wrong to restart this on a reused connection. */
multistate(data, MSTATE_DO);
rc = CURLM_CALL_MULTI_PERFORM;
break;
}
if(!result)
result = protocol_connect(data, &protocol_connected);
if(!result && !protocol_connected)
/* switch to waiting state */
multistate(data, MSTATE_PROTOCONNECTING);
@@ -2770,6 +2778,11 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
wakeup_close(multi->wakeup_pair[1]);
#endif
#endif
#ifdef USE_SSL
Curl_free_multi_ssl_backend_data(multi->ssl_backend_data);
#endif
free(multi);
return CURLM_OK;
+8
View File
@@ -79,6 +79,10 @@ typedef enum {
/* value for MAXIMUM CONCURRENT STREAMS upper limit */
#define INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1)
/* Curl_multi SSL backend-specific data; declared differently by each SSL
backend */
struct multi_ssl_backend_data;
/* This is the struct known as CURLM on the outside */
struct Curl_multi {
/* First a simple identifier to easier detect if a user mix up
@@ -118,6 +122,10 @@ struct Curl_multi {
times of all currently set timers */
struct Curl_tree *timetree;
#if defined(USE_SSL)
struct multi_ssl_backend_data *ssl_backend_data;
#endif
/* 'sockhash' is the lookup hash for socket descriptor => easy handles (note
the pluralis form, there can be more than one easy handle waiting on the
same actual socket) */
-3
View File
@@ -31,9 +31,6 @@
#include <fcntl.h>
#endif
#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
#include <sys/filio.h>
#endif
#ifdef __VMS
#include <in.h>
#include <inet.h>
+51 -18
View File
@@ -34,6 +34,10 @@
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
/*
* Curl_cidr4_match() returns TRUE if the given IPv4 address is within the
* specified CIDR address range.
@@ -117,6 +121,13 @@ enum nametype {
****************************************************************/
bool Curl_check_noproxy(const char *name, const char *no_proxy)
{
/*
* If we don't have a hostname at all, like for example with a FILE
* transfer, we have nothing to interrogate the noproxy list with.
*/
if(!name || name[0] == '\0')
return FALSE;
/* no_proxy=domain1.dom,host.domain2.dom
* (a comma-separated list of hosts which should
* not be proxied, or an asterisk to override
@@ -149,9 +160,14 @@ bool Curl_check_noproxy(const char *name, const char *no_proxy)
}
else {
unsigned int address;
namelen = strlen(name);
if(1 == Curl_inet_pton(AF_INET, name, &address))
type = TYPE_IPV4;
namelen = strlen(name);
else {
/* ignore trailing dots in the host name */
if(name[namelen - 1] == '.')
namelen--;
}
}
while(*p) {
@@ -173,33 +189,50 @@ bool Curl_check_noproxy(const char *name, const char *no_proxy)
if(tokenlen) {
switch(type) {
case TYPE_HOST:
if(*token == '.') {
++token;
--tokenlen;
/* tailmatch */
match = (tokenlen <= namelen) &&
strncasecompare(token, name + (namelen - tokenlen), namelen);
/* ignore trailing dots in the token to check */
if(token[tokenlen - 1] == '.')
tokenlen--;
if(tokenlen && (*token == '.')) {
/* ignore leading token dot as well */
token++;
tokenlen--;
}
else
match = (tokenlen == namelen) &&
strncasecompare(token, name, namelen);
/* A: example.com matches 'example.com'
B: www.example.com matches 'example.com'
C: nonexample.com DOES NOT match 'example.com'
*/
if(tokenlen == namelen)
/* case A, exact match */
match = strncasecompare(token, name, namelen);
else if(tokenlen < namelen) {
/* case B, tailmatch domain */
match = (name[namelen - tokenlen - 1] == '.') &&
strncasecompare(token, name + (namelen - tokenlen),
tokenlen);
}
/* case C passes through, not a match */
break;
case TYPE_IPV4:
/* FALLTHROUGH */
case TYPE_IPV6: {
const char *check = token;
char *slash = strchr(check, '/');
char *slash;
unsigned int bits = 0;
char checkip[128];
if(tokenlen >= sizeof(checkip))
/* this cannot match */
break;
/* copy the check name to a temp buffer */
memcpy(checkip, check, tokenlen);
checkip[tokenlen] = 0;
check = checkip;
slash = strchr(check, '/');
/* if the slash is part of this token, use it */
if(slash && (slash < &check[tokenlen])) {
if(slash) {
bits = atoi(slash + 1);
/* copy the check name to a temp buffer */
if(tokenlen >= sizeof(checkip))
break;
memcpy(checkip, check, tokenlen);
checkip[ slash - check ] = 0;
check = checkip;
*slash = 0; /* null terminate there */
}
if(type == TYPE_IPV6)
match = Curl_cidr6_match(name, check, bits);
+3 -3
View File
@@ -47,6 +47,7 @@
#include "transfer.h"
#include "curl_ldap.h"
#include "curl_base64.h"
#include "cfilters.h"
#include "connect.h"
#include "curl_sasl.h"
#include "strcase.h"
@@ -500,8 +501,7 @@ static CURLcode oldap_ssl_connect(struct Curl_easy *data, ldapstate newstate)
struct ldapconninfo *li = conn->proto.ldapc;
bool ssldone = 0;
result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
FIRSTSOCKET, &ssldone);
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssldone);
if(!result) {
state(data, newstate);
@@ -1153,7 +1153,7 @@ ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
(void)arg;
if(opt == LBER_SB_OPT_DATA_READY) {
struct Curl_easy *data = sbiod->sbiod_pvt;
return Curl_ssl_data_pending(data->conn, FIRSTSOCKET);
return Curl_conn_data_pending(data, FIRSTSOCKET);
}
return 0;
}
+3 -2
View File
@@ -28,6 +28,7 @@
#include "curl_setup.h"
#include "urldata.h"
#include "cfilters.h"
#include "sendf.h"
#include "select.h"
#include "progress.h"
@@ -102,12 +103,12 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data,
else
interval_ms = 0; /* immediate */
if(Curl_ssl_data_pending(conn, FIRSTSOCKET))
if(Curl_conn_data_pending(data, FIRSTSOCKET))
rc = 1;
else if(Curl_pp_moredata(pp))
/* We are receiving and there is data in the cache so just read it */
rc = 1;
else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET))
else if(!pp->sendleft && Curl_conn_data_pending(data, FIRSTSOCKET))
/* We are receiving and there is data ready in the SSL library */
rc = 1;
else
+16 -16
View File
@@ -58,11 +58,6 @@
#include <inet.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
@@ -76,6 +71,7 @@
#include "strtoofft.h"
#include "strcase.h"
#include "vtls/vtls.h"
#include "cfilters.h"
#include "connect.h"
#include "select.h"
#include "multiif.h"
@@ -373,9 +369,15 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
{
/* Start the SSL connection */
struct pop3_conn *pop3c = &conn->proto.pop3c;
CURLcode result =
Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET,
&pop3c->ssldone);
CURLcode result;
if(!Curl_conn_is_ssl(data, FIRSTSOCKET)) {
result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
if(result)
goto out;
}
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &pop3c->ssldone);
if(!result) {
if(pop3c->state != POP3_UPGRADETLS)
@@ -386,7 +388,7 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
result = pop3_perform_capa(data, conn);
}
}
out:
return result;
}
@@ -767,7 +769,7 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
if(pop3code != '+')
pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
if(!data->set.use_ssl || conn->ssl[FIRSTSOCKET].use)
if(!data->set.use_ssl || Curl_conn_is_ssl(data, FIRSTSOCKET))
result = pop3_perform_authentication(data, conn);
else if(pop3code == '+' && pop3c->tls_supported)
/* Switch to TLS connection now */
@@ -948,7 +950,7 @@ static CURLcode pop3_state_command_resp(struct Curl_easy *data,
content so send it as such. Note that there may even be additional
"headers" after the body */
if(!data->set.opt_no_body) {
if(!data->req.no_body) {
result = Curl_pop3_write(data, pp->cache, pp->cache_size);
if(result)
return result;
@@ -1054,8 +1056,7 @@ static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done)
struct pop3_conn *pop3c = &conn->proto.pop3c;
if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
FIRSTSOCKET, &pop3c->ssldone);
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &pop3c->ssldone);
if(result || !pop3c->ssldone)
return result;
}
@@ -1192,12 +1193,11 @@ static CURLcode pop3_perform(struct Curl_easy *data, bool *connected,
{
/* This is POP3 and no proxy */
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct POP3 *pop3 = data->req.p.pop3;
DEBUGF(infof(data, "DO phase starts"));
if(data->set.opt_no_body) {
if(data->req.no_body) {
/* Requested no body means no transfer */
pop3->transfer = PPTRANSFER_INFO;
}
@@ -1211,7 +1211,7 @@ static CURLcode pop3_perform(struct Curl_easy *data, bool *connected,
/* Run the state-machine */
result = pop3_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
*connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
if(*dophase_done)
DEBUGF(infof(data, "DO phase is complete"));
+4
View File
@@ -27,10 +27,14 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <curl/curl.h>
#include "vtls/vtls.h"
#include "sendf.h"
#include "timeval.h"
#include "rand.h"
/* The last 3 #include files should be in this order */
+22 -10
View File
@@ -141,7 +141,7 @@ static CURLcode rtsp_setup_connection(struct Curl_easy *data,
* Instead, if it is readable, run Curl_connalive() to peek at the socket
* and distinguish between closed and data.
*/
static bool rtsp_connisdead(struct connectdata *check)
static bool rtsp_connisdead(struct Curl_easy *data, struct connectdata *check)
{
int sval;
bool ret_val = TRUE;
@@ -157,7 +157,7 @@ static bool rtsp_connisdead(struct connectdata *check)
}
else if(sval & CURL_CSELECT_IN) {
/* readable with no error. could still be closed */
ret_val = !Curl_connalive(check);
ret_val = !Curl_connalive(data, check);
}
return ret_val;
@@ -174,7 +174,7 @@ static unsigned int rtsp_conncheck(struct Curl_easy *data,
(void)data;
if(checks_to_perform & CONNCHECK_ISDEAD) {
if(rtsp_connisdead(conn))
if(rtsp_connisdead(data, conn))
ret_val |= CONNRESULT_DEAD;
}
@@ -267,11 +267,23 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq;
rtsp->CSeq_recv = 0;
/* Setup the first_* fields to allow auth details get sent
to this origin */
if(!data->state.first_host) {
data->state.first_host = strdup(conn->host.name);
if(!data->state.first_host)
return CURLE_OUT_OF_MEMORY;
data->state.first_remote_port = conn->remote_port;
data->state.first_remote_protocol = conn->handler->protocol;
}
/* Setup the 'p_request' pointer to the proper p_request string
* Since all RTSP requests are included here, there is no need to
* support custom requests like HTTP.
**/
data->set.opt_no_body = TRUE; /* most requests don't contain a body */
data->req.no_body = TRUE; /* most requests don't contain a body */
switch(rtspreq) {
default:
failf(data, "Got invalid RTSP request");
@@ -281,7 +293,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
break;
case RTSPREQ_DESCRIBE:
p_request = "DESCRIBE";
data->set.opt_no_body = FALSE;
data->req.no_body = FALSE;
break;
case RTSPREQ_ANNOUNCE:
p_request = "ANNOUNCE";
@@ -301,7 +313,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
case RTSPREQ_GET_PARAMETER:
/* GET_PARAMETER's no_body status is determined later */
p_request = "GET_PARAMETER";
data->set.opt_no_body = FALSE;
data->req.no_body = FALSE;
break;
case RTSPREQ_SET_PARAMETER:
p_request = "SET_PARAMETER";
@@ -311,8 +323,8 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
break;
case RTSPREQ_RECEIVE:
p_request = "";
/* Treat interleaved RTP as body*/
data->set.opt_no_body = FALSE;
/* Treat interleaved RTP as body */
data->req.no_body = FALSE;
break;
case RTSPREQ_LAST:
failf(data, "Got invalid RTSP request: RTSPREQ_LAST");
@@ -561,7 +573,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done)
else if(rtspreq == RTSPREQ_GET_PARAMETER) {
/* Check for an empty GET_PARAMETER (heartbeat) request */
data->state.httpreq = HTTPREQ_HEAD;
data->set.opt_no_body = TRUE;
data->req.no_body = TRUE;
}
}
@@ -650,7 +662,7 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
rtp_length = RTP_PKT_LENGTH(rtp);
if(rtp_dataleft < rtp_length + 4) {
/* Need more - incomplete payload*/
/* Need more - incomplete payload */
*readmore = TRUE;
break;
}
+1 -1
View File
@@ -62,7 +62,7 @@ struct RTSP {
* HTTP functions can safely treat this as an HTTP struct, but RTSP aware
* functions can also index into the later elements.
*/
struct HTTP http_wrapper; /*wrap HTTP to do the heavy lifting */
struct HTTP http_wrapper; /* wrap HTTP to do the heavy lifting */
long CSeq_sent; /* CSeq of this request */
long CSeq_recv; /* CSeq received */
+62 -37
View File
@@ -38,6 +38,7 @@
#include "urldata.h"
#include "sendf.h"
#include "cfilters.h"
#include "connect.h"
#include "vtls/vtls.h"
#include "vssh/ssh.h"
@@ -151,13 +152,15 @@ static CURLcode pre_receive_plain(struct Curl_easy *data,
const curl_socket_t sockfd = conn->sock[num];
struct postponed_data * const psnd = &(conn->postponed[num]);
size_t bytestorecv = psnd->allocated_size - psnd->recv_size;
ssize_t recvedbytes;
/* WinSock will destroy unread received data if send() is
failed.
To avoid lossage of received data, recv() must be
performed before every send() if any incoming data is
available. However, skip this, if buffer is already full. */
if((conn->handler->protocol&PROTO_FAMILY_HTTP) != 0 &&
conn->recv[num] == Curl_recv_plain &&
conn->recv[num] == Curl_conn_recv &&
(!psnd->buffer || bytestorecv)) {
const int readymask = Curl_socket_check(sockfd, CURL_SOCKET_BAD,
CURL_SOCKET_BAD, 0);
@@ -176,16 +179,12 @@ static CURLcode pre_receive_plain(struct Curl_easy *data,
#endif /* DEBUGBUILD */
bytestorecv = psnd->allocated_size;
}
if(psnd->buffer) {
ssize_t recvedbytes;
DEBUGASSERT(psnd->bindsock == sockfd);
recvedbytes = sread(sockfd, psnd->buffer + psnd->recv_size,
bytestorecv);
if(recvedbytes > 0)
psnd->recv_size += recvedbytes;
}
else
psnd->allocated_size = 0;
DEBUGASSERT(psnd->bindsock == sockfd);
recvedbytes = sread(sockfd, psnd->buffer + psnd->recv_size,
bytestorecv);
if(recvedbytes > 0)
psnd->recv_size += recvedbytes;
}
}
return CURLE_OK;
@@ -339,6 +338,7 @@ CURLcode Curl_write(struct Curl_easy *data,
}
}
/* Curl_send_plain sends raw data without a size restriction on 'len'. */
ssize_t Curl_send_plain(struct Curl_easy *data, int num,
const void *mem, size_t len, CURLcode *code)
{
@@ -387,7 +387,6 @@ ssize_t Curl_send_plain(struct Curl_easy *data, int num,
#endif
) {
/* this is just a case of EWOULDBLOCK */
bytes_written = 0;
*code = CURLE_AGAIN;
}
else {
@@ -404,7 +403,12 @@ ssize_t Curl_send_plain(struct Curl_easy *data, int num,
/*
* Curl_write_plain() is an internal write function that sends data to the
* server using plain sockets only. Otherwise meant to have the exact same
* proto as Curl_write()
* proto as Curl_write().
*
* This function wraps Curl_send_plain(). The only difference besides the
* prototype is '*written' (bytes written) is set to 0 on error.
* 'sockfd' must be one of the connection's two main sockets and the value of
* 'len' must not be changed.
*/
CURLcode Curl_write_plain(struct Curl_easy *data,
curl_socket_t sockfd,
@@ -416,13 +420,22 @@ CURLcode Curl_write_plain(struct Curl_easy *data,
struct connectdata *conn = data->conn;
int num;
DEBUGASSERT(conn);
DEBUGASSERT(sockfd == conn->sock[FIRSTSOCKET] ||
sockfd == conn->sock[SECONDARYSOCKET]);
if(sockfd != conn->sock[FIRSTSOCKET] &&
sockfd != conn->sock[SECONDARYSOCKET])
return CURLE_BAD_FUNCTION_ARGUMENT;
num = (sockfd == conn->sock[SECONDARYSOCKET]);
*written = Curl_send_plain(data, num, mem, len, &result);
if(*written == -1)
*written = 0;
return result;
}
/* Curl_recv_plain receives raw data without a size restriction on 'len'. */
ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf,
size_t len, CURLcode *code)
{
@@ -664,30 +677,39 @@ CURLcode Curl_client_write(struct Curl_easy *data,
return chop_write(data, type, ptr, len);
}
CURLcode Curl_read_plain(curl_socket_t sockfd,
char *buf,
size_t bytesfromsocket,
ssize_t *n)
/*
* Curl_read_plain() is an internal read function that reads data from the
* server using plain sockets only. Otherwise meant to have the exact same
* proto as Curl_read().
*
* This function wraps Curl_recv_plain(). The only difference besides the
* prototype is '*n' (bytes read) is set to 0 on error.
* 'sockfd' must be one of the connection's two main sockets and the value of
* 'sizerequested' must not be changed.
*/
CURLcode Curl_read_plain(struct Curl_easy *data, /* transfer */
curl_socket_t sockfd, /* read from this socket */
char *buf, /* store read data here */
size_t sizerequested, /* max amount to read */
ssize_t *n) /* amount bytes read */
{
ssize_t nread = sread(sockfd, buf, bytesfromsocket);
CURLcode result;
struct connectdata *conn = data->conn;
int num;
DEBUGASSERT(conn);
DEBUGASSERT(sockfd == conn->sock[FIRSTSOCKET] ||
sockfd == conn->sock[SECONDARYSOCKET]);
if(sockfd != conn->sock[FIRSTSOCKET] &&
sockfd != conn->sock[SECONDARYSOCKET])
return CURLE_BAD_FUNCTION_ARGUMENT;
if(-1 == nread) {
const int err = SOCKERRNO;
const bool return_error =
#ifdef USE_WINSOCK
WSAEWOULDBLOCK == err
#else
EWOULDBLOCK == err || EAGAIN == err || EINTR == err
#endif
;
*n = 0; /* no data returned */
if(return_error)
return CURLE_AGAIN;
return CURLE_RECV_ERROR;
}
num = (sockfd == conn->sock[SECONDARYSOCKET]);
*n = nread;
return CURLE_OK;
*n = Curl_recv_plain(data, num, buf, sizerequested, &result);
if(*n == -1)
*n = 0;
return result;
}
/*
@@ -720,11 +742,14 @@ CURLcode Curl_read(struct Curl_easy *data, /* transfer */
nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result);
if(nread < 0)
return result;
goto out;
*n += nread;
return CURLE_OK;
result = CURLE_OK;
out:
/* DEBUGF(infof(data, "Curl_read(handle=%p) -> %d, nread=%ld",
data, result, nread)); */
return result;
}
/* return 0 on success */
+3 -2
View File
@@ -61,9 +61,10 @@ CURLcode Curl_client_write(struct Curl_easy *data, int type, char *ptr,
bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex);
/* internal read-function, does plain socket only */
CURLcode Curl_read_plain(curl_socket_t sockfd,
CURLcode Curl_read_plain(struct Curl_easy *data,
curl_socket_t sockfd,
char *buf,
size_t bytesfromsocket,
size_t sizerequested,
ssize_t *n);
ssize_t Curl_recv_plain(struct Curl_easy *data, int num, char *buf,
+34 -22
View File
@@ -204,6 +204,15 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.dns_cache_timeout = (int)arg;
break;
case CURLOPT_CA_CACHE_TIMEOUT:
arg = va_arg(param, long);
if(arg < -1)
return CURLE_BAD_FUNCTION_ARGUMENT;
else if(arg > INT_MAX)
arg = INT_MAX;
data->set.general_ssl.ca_cache_timeout = (int)arg;
break;
case CURLOPT_DNS_USE_GLOBAL_CACHE:
/* deprecated */
break;
@@ -220,7 +229,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif
case CURLOPT_TLS13_CIPHERS:
if(Curl_ssl_tls13_ciphersuites()) {
if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) {
/* set preferred list of TLS 1.3 cipher suites */
result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST],
va_arg(param, char *));
@@ -230,7 +239,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_TLS13_CIPHERS:
if(Curl_ssl_tls13_ciphersuites()) {
if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) {
/* set preferred list of TLS 1.3 cipher suites for proxy */
result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_PROXY],
va_arg(param, char *));
@@ -406,7 +415,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if((arg < CURL_TIMECOND_NONE) || (arg >= CURL_TIMECOND_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.timecondition = (curl_TimeCond)arg;
data->set.timecondition = (unsigned char)(curl_TimeCond)arg;
break;
case CURLOPT_TIMEVALUE:
/*
@@ -598,7 +607,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_FOLLOWLOCATION:
/*
* Follow Location: header hints on a HTTP-server.
* Follow Location: header hints on an HTTP-server.
*/
data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
break;
@@ -914,7 +923,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_EXPECT_100_TIMEOUT_MS:
/*
* Time to wait for a response to a HTTP request containing an
* Time to wait for a response to an HTTP request containing an
* Expect: 100-continue header before sending the data anyway.
*/
arg = va_arg(param, long);
@@ -1048,7 +1057,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if((arg < 0) || (arg > 65535))
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.proxyport = arg;
data->set.proxyport = (unsigned short)arg;
break;
case CURLOPT_PROXYAUTH:
@@ -1135,7 +1144,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME))
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.proxytype = (curl_proxytype)arg;
data->set.proxytype = (unsigned char)(curl_proxytype)arg;
break;
case CURLOPT_PROXY_TRANSFER_MODE:
@@ -1157,7 +1166,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_SOCKS5_AUTH:
data->set.socks5auth = va_arg(param, unsigned long);
data->set.socks5auth = (unsigned char)va_arg(param, unsigned long);
if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
result = CURLE_NOT_BUILT_IN;
break;
@@ -1234,7 +1243,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.ftp_filemethod = (curl_ftpfile)arg;
data->set.ftp_filemethod = (unsigned char)(curl_ftpfile)arg;
break;
case CURLOPT_FTPPORT:
/*
@@ -1261,7 +1270,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if((arg < CURLFTPSSL_CCC_NONE) || (arg >= CURLFTPSSL_CCC_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.ftp_ccc = (curl_ftpccc)arg;
data->set.ftp_ccc = (unsigned char)(curl_ftpccc)arg;
break;
case CURLOPT_FTP_SKIP_PASV_IP:
@@ -1289,7 +1298,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = va_arg(param, long);
if((arg < CURLFTPAUTH_DEFAULT) || (arg >= CURLFTPAUTH_LAST))
return CURLE_BAD_FUNCTION_ARGUMENT;
data->set.ftpsslauth = (curl_ftpauth)arg;
data->set.ftpsslauth = (unsigned char)(curl_ftpauth)arg;
break;
case CURLOPT_KRBLEVEL:
/*
@@ -1992,7 +2001,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set a SSL_CTX callback
*/
#ifdef USE_SSL
if(Curl_ssl->supports & SSLSUPP_SSL_CTX)
if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX))
data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
else
#endif
@@ -2003,7 +2012,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set a SSL_CTX callback parameter pointer
*/
#ifdef USE_SSL
if(Curl_ssl->supports & SSLSUPP_SSL_CTX)
if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX))
data->set.ssl.fsslctxp = va_arg(param, void *);
else
#endif
@@ -2013,7 +2022,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
/*
* Enable TLS false start.
*/
if(!Curl_ssl_false_start()) {
if(!Curl_ssl_false_start(data)) {
result = CURLE_NOT_BUILT_IN;
break;
}
@@ -2022,7 +2031,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_CERTINFO:
#ifdef USE_SSL
if(Curl_ssl->supports & SSLSUPP_CERTINFO)
if(Curl_ssl_supports(data, SSLSUPP_CERTINFO))
data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
else
#endif
@@ -2034,7 +2043,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Specify file name of the public key in DER format.
*/
#ifdef USE_SSL
if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
va_arg(param, char *));
else
@@ -2048,7 +2057,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Specify file name of the public key in DER format.
*/
#ifdef USE_SSL
if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
va_arg(param, char *));
else
@@ -2069,7 +2078,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Specify entire PEM of the CA certificate
*/
#ifdef USE_SSL
if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB)
if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO],
va_arg(param, struct curl_blob *));
else
@@ -2092,7 +2101,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Specify entire PEM of the CA certificate
*/
#ifdef USE_SSL
if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB)
if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY],
va_arg(param, struct curl_blob *));
else
@@ -2106,7 +2115,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* certificates which have been prepared using openssl c_rehash utility.
*/
#ifdef USE_SSL
if(Curl_ssl->supports & SSLSUPP_CA_PATH)
if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
/* This does not work on windows. */
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH],
va_arg(param, char *));
@@ -2121,7 +2130,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* CA certificates which have been prepared using openssl c_rehash utility.
*/
#ifdef USE_SSL
if(Curl_ssl->supports & SSLSUPP_CA_PATH)
if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
/* This does not work on windows. */
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
va_arg(param, char *));
@@ -2205,7 +2214,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
else if(arg < READBUFFER_MIN)
arg = READBUFFER_MIN;
data->set.buffer_size = (int)arg;
data->set.buffer_size = (unsigned int)arg;
break;
case CURLOPT_UPLOAD_BUFFERSIZE:
@@ -3107,6 +3116,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
}
#endif
case CURLOPT_QUICK_EXIT:
data->set.quick_exit = (0 != va_arg(param, long)) ? 1L:0L;
break;
default:
/* unknown tag and its companion, just ignore: */
result = CURLE_UNKNOWN_OPTION;
+4 -4
View File
@@ -49,11 +49,11 @@ extern int Curl_getaddrinfo_a(const char *nodename,
struct addrinfo **res);
#define getaddrinfo Curl_getaddrinfo_a
/* Note socklen_t must be used as this is declared before curl_socklen_t */
extern int Curl_getnameinfo_a(const struct sockaddr *sa,
curl_socklen_t salen,
char *nodename, curl_socklen_t nodenamelen,
char *servname, curl_socklen_t servnamelen,
socklen_t salen,
char *nodename, socklen_t nodenamelen,
char *servname, socklen_t servnamelen,
int flags);
#define getnameinfo Curl_getnameinfo_a
+31 -42
View File
@@ -57,6 +57,36 @@
#endif
#endif /* USE_MBEDTLS */
#if defined(USE_OPENSSL_SHA256)
/* When OpenSSL or wolfSSL is available is available we use their
* SHA256-functions.
*/
#if defined(USE_OPENSSL)
#include <openssl/evp.h>
#elif defined(USE_WOLFSSL)
#include <wolfssl/openssl/evp.h>
#endif
#elif defined(USE_GNUTLS)
#include <nettle/sha.h>
#elif defined(USE_MBEDTLS)
#include <mbedtls/sha256.h>
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
(__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
(__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
#include <CommonCrypto/CommonDigest.h>
#define AN_APPLE_OS
#elif defined(USE_WIN32_CRYPTO)
#include <wincrypt.h>
#endif
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
/* Please keep the SSL backend-specific #if branches in this order:
*
* 1. USE_OPENSSL
@@ -71,20 +101,6 @@
#if defined(USE_OPENSSL_SHA256)
/* When OpenSSL or wolfSSL is available is available we use their
* SHA256-functions.
*/
#if defined(USE_OPENSSL)
#include <openssl/evp.h>
#elif defined(USE_WOLFSSL)
#include <wolfssl/openssl/evp.h>
#endif
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
struct sha256_ctx {
EVP_MD_CTX *openssl_ctx;
};
@@ -115,13 +131,6 @@ static void my_sha256_final(unsigned char *digest, my_sha256_ctx *ctx)
#elif defined(USE_GNUTLS)
#include <nettle/sha.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
typedef struct sha256_ctx my_sha256_ctx;
static CURLcode my_sha256_init(my_sha256_ctx *ctx)
@@ -144,13 +153,6 @@ static void my_sha256_final(unsigned char *digest, my_sha256_ctx *ctx)
#elif defined(USE_MBEDTLS)
#include <mbedtls/sha256.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
typedef mbedtls_sha256_context my_sha256_ctx;
static CURLcode my_sha256_init(my_sha256_ctx *ctx)
@@ -183,18 +185,7 @@ static void my_sha256_final(unsigned char *digest, my_sha256_ctx *ctx)
#endif
}
#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
(__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
(defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
(__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
#include <CommonCrypto/CommonDigest.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#elif defined(AN_APPLE_OS)
typedef CC_SHA256_CTX my_sha256_ctx;
static CURLcode my_sha256_init(my_sha256_ctx *ctx)
@@ -217,8 +208,6 @@ static void my_sha256_final(unsigned char *digest, my_sha256_ctx *ctx)
#elif defined(USE_WIN32_CRYPTO)
#include <wincrypt.h>
struct sha256_ctx {
HCRYPTPROV hCryptProv;
HCRYPTHASH hHash;
+5 -20
View File
@@ -30,19 +30,15 @@
#define BUILDING_CURL_SMB_C
#ifdef HAVE_PROCESS_H
#include <process.h>
#ifdef CURL_WINDOWS_APP
#ifdef WIN32
#define getpid GetCurrentProcessId
#elif defined(WIN32)
#define getpid _getpid
#endif
#endif
#include "smb.h"
#include "urldata.h"
#include "sendf.h"
#include "multiif.h"
#include "cfilters.h"
#include "connect.h"
#include "progress.h"
#include "transfer.h"
@@ -62,8 +58,6 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done);
static CURLcode smb_connection_state(struct Curl_easy *data, bool *done);
static CURLcode smb_do(struct Curl_easy *data, bool *done);
static CURLcode smb_request_state(struct Curl_easy *data, bool *done);
static CURLcode smb_done(struct Curl_easy *data, CURLcode status,
bool premature);
static CURLcode smb_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead);
static int smb_getsock(struct Curl_easy *data, struct connectdata *conn,
@@ -78,7 +72,7 @@ const struct Curl_handler Curl_handler_smb = {
"SMB", /* scheme */
smb_setup_connection, /* setup_connection */
smb_do, /* do_it */
smb_done, /* done */
ZERO_NULL, /* done */
ZERO_NULL, /* do_more */
smb_connect, /* connect_it */
smb_connection_state, /* connecting */
@@ -105,7 +99,7 @@ const struct Curl_handler Curl_handler_smbs = {
"SMBS", /* scheme */
smb_setup_connection, /* setup_connection */
smb_do, /* do_it */
smb_done, /* done */
ZERO_NULL, /* done */
ZERO_NULL, /* do_more */
smb_connect, /* connect_it */
smb_connection_state, /* connecting */
@@ -671,8 +665,7 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
#ifdef USE_SSL
if((conn->handler->flags & PROTOPT_SSL)) {
bool ssl_done = FALSE;
result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
FIRSTSOCKET, &ssl_done);
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssl_done);
if(result && result != CURLE_AGAIN)
return result;
if(!ssl_done)
@@ -941,14 +934,6 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done)
return CURLE_OK;
}
static CURLcode smb_done(struct Curl_easy *data, CURLcode status,
bool premature)
{
(void) premature;
Curl_safefree(data->req.p.smb);
return status;
}
static CURLcode smb_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead)
{
+27 -26
View File
@@ -60,11 +60,6 @@
#include <inet.h>
#endif
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
@@ -79,6 +74,7 @@
#include "strtoofft.h"
#include "strcase.h"
#include "vtls/vtls.h"
#include "cfilters.h"
#include "connect.h"
#include "select.h"
#include "multiif.h"
@@ -87,6 +83,7 @@
#include "bufref.h"
#include "curl_sasl.h"
#include "warnless.h"
#include "idn.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -109,7 +106,7 @@ static CURLcode smtp_setup_connection(struct Curl_easy *data,
static CURLcode smtp_parse_url_options(struct connectdata *conn);
static CURLcode smtp_parse_url_path(struct Curl_easy *data);
static CURLcode smtp_parse_custom_request(struct Curl_easy *data);
static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
static CURLcode smtp_parse_address(const char *fqma,
char **address, struct hostname *host);
static CURLcode smtp_perform_auth(struct Curl_easy *data, const char *mech,
const struct bufref *initresp);
@@ -400,10 +397,15 @@ static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
/* Start the SSL connection */
struct connectdata *conn = data->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
FIRSTSOCKET,
&smtpc->ssldone);
CURLcode result;
if(!Curl_conn_is_ssl(data, FIRSTSOCKET)) {
result = Curl_ssl_cfilter_add(data, conn, FIRSTSOCKET);
if(result)
goto out;
}
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &smtpc->ssldone);
if(!result) {
if(smtpc->state != SMTP_UPGRADETLS)
state(data, SMTP_UPGRADETLS);
@@ -413,7 +415,7 @@ static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
result = smtp_perform_ehlo(data);
}
}
out:
return result;
}
@@ -540,7 +542,7 @@ static CURLcode smtp_perform_command(struct Curl_easy *data)
/* Parse the mailbox to verify into the local address and host name
parts, converting the host name to an IDN A-label if necessary */
result = smtp_parse_address(data, smtp->rcpt->data,
result = smtp_parse_address(smtp->rcpt->data,
&address, &host);
if(result)
return result;
@@ -614,7 +616,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
/* Parse the FROM mailbox into the local address and host name parts,
converting the host name to an IDN A-label if necessary */
result = smtp_parse_address(data, data->set.str[STRING_MAIL_FROM],
result = smtp_parse_address(data->set.str[STRING_MAIL_FROM],
&address, &host);
if(result)
return result;
@@ -652,7 +654,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
/* Parse the AUTH mailbox into the local address and host name parts,
converting the host name to an IDN A-label if necessary */
result = smtp_parse_address(data, data->set.str[STRING_MAIL_AUTH],
result = smtp_parse_address(data->set.str[STRING_MAIL_AUTH],
&address, &host);
if(result) {
free(from);
@@ -696,7 +698,7 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data)
/* Add external headers and mime version. */
curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
result = Curl_mime_prepare_headers(data, &data->set.mimepost, NULL,
NULL, MIMESTRATEGY_MAIL);
if(!result)
@@ -789,7 +791,7 @@ static CURLcode smtp_perform_rcpt_to(struct Curl_easy *data)
/* Parse the recipient mailbox into the local address and host name parts,
converting the host name to an IDN A-label if necessary */
result = smtp_parse_address(data, smtp->rcpt->data,
result = smtp_parse_address(smtp->rcpt->data,
&address, &host);
if(result)
return result;
@@ -888,7 +890,8 @@ static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2 && smtpcode != 1) {
if(data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use)
if(data->set.use_ssl <= CURLUSESSL_TRY
|| Curl_conn_is_ssl(data, FIRSTSOCKET))
result = smtp_perform_helo(data, conn);
else {
failf(data, "Remote access denied: %d", smtpcode);
@@ -953,7 +956,7 @@ static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
}
if(smtpcode != 1) {
if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
if(data->set.use_ssl && !Curl_conn_is_ssl(data, FIRSTSOCKET)) {
/* We don't have a SSL/TLS connection yet, but SSL is requested */
if(smtpc->tls_supported)
/* Switch to TLS connection now */
@@ -1043,7 +1046,7 @@ static CURLcode smtp_state_command_resp(struct Curl_easy *data, int smtpcode,
}
else {
/* Temporarily add the LF character back and send as body to the client */
if(!data->set.opt_no_body) {
if(!data->req.no_body) {
line[len] = '\n';
result = Curl_client_write(data, CLIENTWRITE_BODY, line, len + 1);
line[len] = '\0';
@@ -1285,8 +1288,7 @@ static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done)
struct smtp_conn *smtpc = &conn->proto.smtpc;
if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) {
result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
FIRSTSOCKET, &smtpc->ssldone);
result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &smtpc->ssldone);
if(result || !smtpc->ssldone)
return result;
}
@@ -1479,12 +1481,11 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
{
/* This is SMTP and no proxy */
CURLcode result = CURLE_OK;
struct connectdata *conn = data->conn;
struct SMTP *smtp = data->req.p.smtp;
DEBUGF(infof(data, "DO phase starts"));
if(data->set.opt_no_body) {
if(data->req.no_body) {
/* Requested no body means no transfer */
smtp->transfer = PPTRANSFER_INFO;
}
@@ -1519,7 +1520,7 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
/* Run the state-machine */
result = smtp_multi_statemach(data, dophase_done);
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
*connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
if(*dophase_done)
DEBUGF(infof(data, "DO phase is complete"));
@@ -1782,8 +1783,8 @@ static CURLcode smtp_parse_custom_request(struct Curl_easy *data)
* calling function deems it to be) then the input will simply be returned in
* the address part with the host name being NULL.
*/
static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
char **address, struct hostname *host)
static CURLcode smtp_parse_address(const char *fqma, char **address,
struct hostname *host)
{
CURLcode result = CURLE_OK;
size_t length;
@@ -1807,7 +1808,7 @@ static CURLcode smtp_parse_address(struct Curl_easy *data, const char *fqma,
host->name = host->name + 1;
/* Attempt to convert the host name to IDN ACE */
(void) Curl_idnconvert_hostname(data, host);
(void) Curl_idnconvert_hostname(host);
/* If Curl_idnconvert_hostname() fails then we shall attempt to continue
and send the host name using UTF-8 rather than as 7-bit ACE (which is
+330 -127
View File
@@ -36,17 +36,52 @@
#include "urldata.h"
#include "sendf.h"
#include "select.h"
#include "cfilters.h"
#include "connect.h"
#include "timeval.h"
#include "socks.h"
#include "multiif.h" /* for getsock macros */
#include "inet_pton.h"
#include "url.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
/* for the (SOCKS) connect state machine */
enum connect_t {
CONNECT_INIT,
CONNECT_SOCKS_INIT, /* 1 */
CONNECT_SOCKS_SEND, /* 2 waiting to send more first data */
CONNECT_SOCKS_READ_INIT, /* 3 set up read */
CONNECT_SOCKS_READ, /* 4 read server response */
CONNECT_GSSAPI_INIT, /* 5 */
CONNECT_AUTH_INIT, /* 6 setup outgoing auth buffer */
CONNECT_AUTH_SEND, /* 7 send auth */
CONNECT_AUTH_READ, /* 8 read auth response */
CONNECT_REQ_INIT, /* 9 init SOCKS "request" */
CONNECT_RESOLVING, /* 10 */
CONNECT_RESOLVED, /* 11 */
CONNECT_RESOLVE_REMOTE, /* 12 */
CONNECT_REQ_SEND, /* 13 */
CONNECT_REQ_SENDING, /* 14 */
CONNECT_REQ_READ, /* 15 */
CONNECT_REQ_READ_MORE, /* 16 */
CONNECT_DONE /* 17 connected fine to the remote or the SOCKS proxy */
};
struct socks_state {
enum connect_t state;
ssize_t outstanding; /* send this many bytes more */
unsigned char *outp; /* send from this pointer */
const char *hostname;
int remote_port;
const char *proxy_user;
const char *proxy_password;
};
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
/*
* Helper read-from-socket functions. Does the same as Curl_read() but it
@@ -77,7 +112,7 @@ int Curl_blockread_all(struct Curl_easy *data, /* transfer */
result = ~CURLE_OK;
break;
}
result = Curl_read_plain(sockfd, buf, buffersize, &nread);
result = Curl_read_plain(data, sockfd, buf, buffersize, &nread);
if(CURLE_AGAIN == result)
continue;
if(result)
@@ -104,21 +139,20 @@ int Curl_blockread_all(struct Curl_easy *data, /* transfer */
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
#define DEBUG_AND_VERBOSE
#define sxstate(x,y) socksstate(x,y, __LINE__)
#define sxstate(x,d,y) socksstate(x,d,y, __LINE__)
#else
#define sxstate(x,y) socksstate(x,y)
#define sxstate(x,d,y) socksstate(x,d,y)
#endif
/* always use this function to change state, to make debugging easier */
static void socksstate(struct Curl_easy *data,
static void socksstate(struct socks_state *sx, struct Curl_easy *data,
enum connect_t state
#ifdef DEBUG_AND_VERBOSE
, int lineno
#endif
)
{
struct connectdata *conn = data->conn;
enum connect_t oldstate = conn->cnnct.state;
enum connect_t oldstate = sx->state;
#ifdef DEBUG_AND_VERBOSE
/* synced with the state list in urldata.h */
static const char * const statename[] = {
@@ -143,40 +177,21 @@ static void socksstate(struct Curl_easy *data,
};
#endif
(void)data;
if(oldstate == state)
/* don't bother when the new state is the same as the old state */
return;
conn->cnnct.state = state;
sx->state = state;
#ifdef DEBUG_AND_VERBOSE
infof(data,
"SXSTATE: %s => %s conn %p; line %d",
statename[oldstate], statename[conn->cnnct.state], conn,
"SXSTATE: %s => %s; line %d",
statename[oldstate], statename[sx->state],
lineno);
#endif
}
int Curl_SOCKS_getsock(struct connectdata *conn, curl_socket_t *sock,
int sockindex)
{
int rc = 0;
sock[0] = conn->sock[sockindex];
switch(conn->cnnct.state) {
case CONNECT_RESOLVING:
case CONNECT_SOCKS_READ:
case CONNECT_AUTH_READ:
case CONNECT_REQ_READ:
case CONNECT_REQ_READ_MORE:
rc = GETSOCK_READSOCK(0);
break;
default:
rc = GETSOCK_WRITESOCK(0);
break;
}
return rc;
}
/*
* This function logs in to a SOCKS4 proxy and sends the specifics to the final
* destination server.
@@ -188,20 +203,16 @@ int Curl_SOCKS_getsock(struct connectdata *conn, curl_socket_t *sock,
* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
* Nonsupport "Identification Protocol (RFC1413)"
*/
CURLproxycode Curl_SOCKS4(const char *proxy_user,
const char *hostname,
int remote_port,
int sockindex,
struct Curl_easy *data,
bool *done)
static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
struct socks_state *sx,
struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
struct connectdata *conn = cf->conn;
const bool protocol4a =
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
unsigned char *socksreq = (unsigned char *)data->state.buffer;
CURLcode result;
curl_socket_t sockfd = conn->sock[sockindex];
struct connstate *sx = &conn->cnnct;
curl_socket_t sockfd = conn->sock[cf->sockindex];
struct Curl_dns_entry *dns = NULL;
ssize_t actualread;
ssize_t written;
@@ -209,18 +220,16 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
/* make sure that the buffer is at least 600 bytes */
DEBUGASSERT(READBUFFER_MIN >= 600);
if(!SOCKS_STATE(sx->state) && !*done)
sxstate(data, CONNECT_SOCKS_INIT);
switch(sx->state) {
case CONNECT_SOCKS_INIT:
/* SOCKS4 can only do IPv4, insist! */
conn->ip_version = CURL_IPRESOLVE_V4;
if(conn->bits.httpproxy)
infof(data, "SOCKS4%s: connecting to HTTP proxy %s port %d",
protocol4a ? "a" : "", hostname, remote_port);
protocol4a ? "a" : "", sx->hostname, sx->remote_port);
infof(data, "SOCKS4 communication to %s:%d", hostname, remote_port);
infof(data, "SOCKS4 communication to %s:%d",
sx->hostname, sx->remote_port);
/*
* Compose socks4 request
@@ -235,40 +244,40 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
socksreq[0] = 4; /* version (SOCKS4) */
socksreq[1] = 1; /* connect */
socksreq[2] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */
socksreq[3] = (unsigned char)(remote_port & 0xff); /* PORT LSB */
socksreq[2] = (unsigned char)((sx->remote_port >> 8) & 0xff); /* MSB */
socksreq[3] = (unsigned char)(sx->remote_port & 0xff); /* LSB */
/* DNS resolve only for SOCKS4, not SOCKS4a */
if(!protocol4a) {
enum resolve_t rc =
Curl_resolv(data, hostname, remote_port, FALSE, &dns);
Curl_resolv(data, sx->hostname, sx->remote_port, FALSE, &dns);
if(rc == CURLRESOLV_ERROR)
return CURLPX_RESOLVE_HOST;
else if(rc == CURLRESOLV_PENDING) {
sxstate(data, CONNECT_RESOLVING);
infof(data, "SOCKS4 non-blocking resolve of %s", hostname);
sxstate(sx, data, CONNECT_RESOLVING);
infof(data, "SOCKS4 non-blocking resolve of %s", sx->hostname);
return CURLPX_OK;
}
sxstate(data, CONNECT_RESOLVED);
sxstate(sx, data, CONNECT_RESOLVED);
goto CONNECT_RESOLVED;
}
/* socks4a doesn't resolve anything locally */
sxstate(data, CONNECT_REQ_INIT);
sxstate(sx, data, CONNECT_REQ_INIT);
goto CONNECT_REQ_INIT;
case CONNECT_RESOLVING:
/* check if we have the name resolved by now */
dns = Curl_fetch_addr(data, hostname, (int)conn->port);
dns = Curl_fetch_addr(data, sx->hostname, (int)conn->port);
if(dns) {
#ifdef CURLRES_ASYNCH
data->state.async.dns = dns;
data->state.async.done = TRUE;
#endif
infof(data, "Hostname '%s' was found", hostname);
sxstate(data, CONNECT_RESOLVED);
infof(data, "Hostname '%s' was found", sx->hostname);
sxstate(sx, data, CONNECT_RESOLVED);
}
else {
result = Curl_resolv_check(data, &dns);
@@ -309,11 +318,11 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
}
else
failf(data, "SOCKS4 connection to %s not supported", hostname);
failf(data, "SOCKS4 connection to %s not supported", sx->hostname);
}
else
failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
hostname);
sx->hostname);
if(!hp)
return CURLPX_RESOLVE_HOST;
@@ -325,14 +334,14 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
* This is currently not supporting "Identification Protocol (RFC1413)".
*/
socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
if(proxy_user) {
size_t plen = strlen(proxy_user);
if(sx->proxy_user) {
size_t plen = strlen(sx->proxy_user);
if(plen >= (size_t)data->set.buffer_size - 8) {
failf(data, "Too long SOCKS proxy user name, can't use");
return CURLPX_LONG_USER;
}
/* copy the proxy name WITH trailing zero */
memcpy(socksreq + 8, proxy_user, plen + 1);
memcpy(socksreq + 8, sx->proxy_user, plen + 1);
}
/*
@@ -350,9 +359,9 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
socksreq[6] = 0;
socksreq[7] = 1;
/* append hostname */
hostnamelen = strlen(hostname) + 1; /* length including NUL */
hostnamelen = strlen(sx->hostname) + 1; /* length including NUL */
if(hostnamelen <= 255)
strcpy((char *)socksreq + packetsize, hostname);
strcpy((char *)socksreq + packetsize, sx->hostname);
else {
failf(data, "SOCKS4: too long host name");
return CURLPX_LONG_HOSTNAME;
@@ -361,7 +370,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
}
sx->outp = socksreq;
sx->outstanding = packetsize;
sxstate(data, CONNECT_REQ_SENDING);
sxstate(sx, data, CONNECT_REQ_SENDING);
}
/* FALLTHROUGH */
case CONNECT_REQ_SENDING:
@@ -382,12 +391,12 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
/* done sending! */
sx->outstanding = 8; /* receive data size */
sx->outp = socksreq;
sxstate(data, CONNECT_SOCKS_READ);
sxstate(sx, data, CONNECT_SOCKS_READ);
/* FALLTHROUGH */
case CONNECT_SOCKS_READ:
/* Receive response */
result = Curl_read_plain(sockfd, (char *)sx->outp,
result = Curl_read_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &actualread);
if(result && (CURLE_AGAIN != result)) {
failf(data, "SOCKS4: Failed receiving connect request ack: %s",
@@ -405,7 +414,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
sx->outp += actualread;
return CURLPX_OK;
}
sxstate(data, CONNECT_DONE);
sxstate(sx, data, CONNECT_DONE);
break;
default: /* lots of unused states in SOCKS4 */
break;
@@ -478,7 +487,6 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
return CURLPX_UNKNOWN_FAIL;
}
*done = TRUE;
return CURLPX_OK; /* Proxy was successful! */
}
@@ -486,13 +494,9 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
* This function logs in to a SOCKS5 proxy and sends the specifics to the final
* destination server.
*/
CURLproxycode Curl_SOCKS5(const char *proxy_user,
const char *proxy_password,
const char *hostname,
int remote_port,
int sockindex,
struct Curl_easy *data,
bool *done)
static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
struct socks_state *sx,
struct Curl_easy *data)
{
/*
According to the RFC1928, section "6. Replies". This is what a SOCK5
@@ -510,31 +514,28 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
o REP Reply field:
o X'00' succeeded
*/
struct connectdata *conn = data->conn;
struct connectdata *conn = cf->conn;
unsigned char *socksreq = (unsigned char *)data->state.buffer;
char dest[256] = "unknown"; /* printable hostname:port */
int idx;
ssize_t actualread;
ssize_t written;
CURLcode result;
curl_socket_t sockfd = conn->sock[sockindex];
curl_socket_t sockfd = conn->sock[cf->sockindex];
bool socks5_resolve_local =
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
const size_t hostname_len = strlen(hostname);
const size_t hostname_len = strlen(sx->hostname);
ssize_t len = 0;
const unsigned long auth = data->set.socks5auth;
const unsigned char auth = data->set.socks5auth;
bool allow_gssapi = FALSE;
struct connstate *sx = &conn->cnnct;
struct Curl_dns_entry *dns = NULL;
if(!SOCKS_STATE(sx->state) && !*done)
sxstate(data, CONNECT_SOCKS_INIT);
DEBUGASSERT(auth & (CURLAUTH_BASIC | CURLAUTH_GSSAPI));
switch(sx->state) {
case CONNECT_SOCKS_INIT:
if(conn->bits.httpproxy)
infof(data, "SOCKS5: connecting to HTTP proxy %s port %d",
hostname, remote_port);
sx->hostname, sx->remote_port);
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
if(!socks5_resolve_local && hostname_len > 255) {
@@ -545,11 +546,11 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
infof(data,
"warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu",
"warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %u",
auth);
if(!(auth & CURLAUTH_BASIC))
/* disable username/password auth */
proxy_user = NULL;
sx->proxy_user = NULL;
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
if(auth & CURLAUTH_GSSAPI)
allow_gssapi = TRUE;
@@ -561,23 +562,23 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
socksreq[idx++] = 0; /* no authentication */
if(allow_gssapi)
socksreq[idx++] = 1; /* GSS-API */
if(proxy_user)
if(sx->proxy_user)
socksreq[idx++] = 2; /* username/password */
/* write the number of authentication methods */
socksreq[1] = (unsigned char) (idx - 2);
result = Curl_write_plain(data, sockfd, (char *)socksreq, idx, &written);
result = Curl_write_plain(data, sockfd, socksreq, idx, &written);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Unable to send initial SOCKS5 request.");
return CURLPX_SEND_CONNECT;
}
if(written != idx) {
sxstate(data, CONNECT_SOCKS_SEND);
sxstate(sx, data, CONNECT_SOCKS_SEND);
sx->outstanding = idx - written;
sx->outp = &socksreq[written];
return CURLPX_OK;
}
sxstate(data, CONNECT_SOCKS_READ);
sxstate(sx, data, CONNECT_SOCKS_READ);
goto CONNECT_SOCKS_READ_INIT;
case CONNECT_SOCKS_SEND:
result = Curl_write_plain(data, sockfd, (char *)sx->outp,
@@ -599,7 +600,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
sx->outp = socksreq; /* store it here */
/* FALLTHROUGH */
case CONNECT_SOCKS_READ:
result = Curl_read_plain(sockfd, (char *)sx->outp,
result = Curl_read_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &actualread);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Unable to receive initial SOCKS5 response.");
@@ -622,18 +623,18 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
}
else if(socksreq[1] == 0) {
/* DONE! No authentication needed. Send request. */
sxstate(data, CONNECT_REQ_INIT);
sxstate(sx, data, CONNECT_REQ_INIT);
goto CONNECT_REQ_INIT;
}
else if(socksreq[1] == 2) {
/* regular name + password authentication */
sxstate(data, CONNECT_AUTH_INIT);
sxstate(sx, data, CONNECT_AUTH_INIT);
goto CONNECT_AUTH_INIT;
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
else if(allow_gssapi && (socksreq[1] == 1)) {
sxstate(data, CONNECT_GSSAPI_INIT);
result = Curl_SOCKS5_gssapi_negotiate(sockindex, data);
sxstate(sx, data, CONNECT_GSSAPI_INIT);
result = Curl_SOCKS5_gssapi_negotiate(cf->sockindex, data);
if(result) {
failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
return CURLPX_GSSAPI;
@@ -668,9 +669,9 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
case CONNECT_AUTH_INIT: {
/* Needs user name and password */
size_t proxy_user_len, proxy_password_len;
if(proxy_user && proxy_password) {
proxy_user_len = strlen(proxy_user);
proxy_password_len = strlen(proxy_password);
if(sx->proxy_user && sx->proxy_password) {
proxy_user_len = strlen(sx->proxy_user);
proxy_password_len = strlen(sx->proxy_password);
}
else {
proxy_user_len = 0;
@@ -687,32 +688,32 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
len = 0;
socksreq[len++] = 1; /* username/pw subnegotiation version */
socksreq[len++] = (unsigned char) proxy_user_len;
if(proxy_user && proxy_user_len) {
if(sx->proxy_user && proxy_user_len) {
/* the length must fit in a single byte */
if(proxy_user_len >= 255) {
if(proxy_user_len > 255) {
failf(data, "Excessive user name length for proxy auth");
return CURLPX_LONG_USER;
}
memcpy(socksreq + len, proxy_user, proxy_user_len);
memcpy(socksreq + len, sx->proxy_user, proxy_user_len);
}
len += proxy_user_len;
socksreq[len++] = (unsigned char) proxy_password_len;
if(proxy_password && proxy_password_len) {
if(sx->proxy_password && proxy_password_len) {
/* the length must fit in a single byte */
if(proxy_password_len > 255) {
failf(data, "Excessive password length for proxy auth");
return CURLPX_LONG_PASSWD;
}
memcpy(socksreq + len, proxy_password, proxy_password_len);
memcpy(socksreq + len, sx->proxy_password, proxy_password_len);
}
len += proxy_password_len;
sxstate(data, CONNECT_AUTH_SEND);
sxstate(sx, data, CONNECT_AUTH_SEND);
sx->outstanding = len;
sx->outp = socksreq;
}
/* FALLTHROUGH */
case CONNECT_AUTH_SEND:
result = Curl_write_plain(data, sockfd, (char *)sx->outp,
result = Curl_write_plain(data, sockfd, sx->outp,
sx->outstanding, &written);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to send SOCKS5 sub-negotiation request.");
@@ -726,10 +727,10 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
}
sx->outp = socksreq;
sx->outstanding = 2;
sxstate(data, CONNECT_AUTH_READ);
sxstate(sx, data, CONNECT_AUTH_READ);
/* FALLTHROUGH */
case CONNECT_AUTH_READ:
result = Curl_read_plain(sockfd, (char *)sx->outp,
result = Curl_read_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &actualread);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
@@ -754,36 +755,36 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
}
/* Everything is good so far, user was authenticated! */
sxstate(data, CONNECT_REQ_INIT);
sxstate(sx, data, CONNECT_REQ_INIT);
/* FALLTHROUGH */
CONNECT_REQ_INIT:
case CONNECT_REQ_INIT:
if(socks5_resolve_local) {
enum resolve_t rc = Curl_resolv(data, hostname, remote_port,
enum resolve_t rc = Curl_resolv(data, sx->hostname, sx->remote_port,
FALSE, &dns);
if(rc == CURLRESOLV_ERROR)
return CURLPX_RESOLVE_HOST;
if(rc == CURLRESOLV_PENDING) {
sxstate(data, CONNECT_RESOLVING);
sxstate(sx, data, CONNECT_RESOLVING);
return CURLPX_OK;
}
sxstate(data, CONNECT_RESOLVED);
sxstate(sx, data, CONNECT_RESOLVED);
goto CONNECT_RESOLVED;
}
goto CONNECT_RESOLVE_REMOTE;
case CONNECT_RESOLVING:
/* check if we have the name resolved by now */
dns = Curl_fetch_addr(data, hostname, remote_port);
dns = Curl_fetch_addr(data, sx->hostname, sx->remote_port);
if(dns) {
#ifdef CURLRES_ASYNCH
data->state.async.dns = dns;
data->state.async.done = TRUE;
#endif
infof(data, "SOCKS5: hostname '%s' found", hostname);
infof(data, "SOCKS5: hostname '%s' found", sx->hostname);
}
if(!dns) {
@@ -803,13 +804,13 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
hp = dns->addr;
if(!hp) {
failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
hostname);
sx->hostname);
return CURLPX_RESOLVE_HOST;
}
Curl_printable_address(hp, dest, sizeof(dest));
destlen = strlen(dest);
msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", remote_port);
msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", sx->remote_port);
len = 0;
socksreq[len++] = 5; /* version (SOCKS5) */
@@ -866,7 +867,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
#ifdef ENABLE_IPV6
if(conn->bits.ipv6_ip) {
char ip6[16];
if(1 != Curl_inet_pton(AF_INET6, hostname, ip6))
if(1 != Curl_inet_pton(AF_INET6, sx->hostname, ip6))
return CURLPX_BAD_ADDRESS_TYPE;
socksreq[len++] = 4;
memcpy(&socksreq[len], ip6, sizeof(ip6));
@@ -874,7 +875,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
}
else
#endif
if(1 == Curl_inet_pton(AF_INET, hostname, ip4)) {
if(1 == Curl_inet_pton(AF_INET, sx->hostname, ip4)) {
socksreq[len++] = 1;
memcpy(&socksreq[len], ip4, sizeof(ip4));
len += sizeof(ip4);
@@ -882,20 +883,20 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
else {
socksreq[len++] = 3;
socksreq[len++] = (char) hostname_len; /* one byte address length */
memcpy(&socksreq[len], hostname, hostname_len); /* address w/o NULL */
memcpy(&socksreq[len], sx->hostname, hostname_len); /* w/o NULL */
len += hostname_len;
}
infof(data, "SOCKS5 connect to %s:%d (remotely resolved)",
hostname, remote_port);
sx->hostname, sx->remote_port);
}
/* FALLTHROUGH */
CONNECT_REQ_SEND:
case CONNECT_REQ_SEND:
/* PORT MSB */
socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff);
socksreq[len++] = (unsigned char)((sx->remote_port >> 8) & 0xff);
/* PORT LSB */
socksreq[len++] = (unsigned char)(remote_port & 0xff);
socksreq[len++] = (unsigned char)(sx->remote_port & 0xff);
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
if(conn->socks5_gssapi_enctype) {
@@ -905,7 +906,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
#endif
sx->outp = socksreq;
sx->outstanding = len;
sxstate(data, CONNECT_REQ_SENDING);
sxstate(sx, data, CONNECT_REQ_SENDING);
/* FALLTHROUGH */
case CONNECT_REQ_SENDING:
result = Curl_write_plain(data, sockfd, (char *)sx->outp,
@@ -928,10 +929,10 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
#endif
sx->outstanding = 10; /* minimum packet size is 10 */
sx->outp = socksreq;
sxstate(data, CONNECT_REQ_READ);
sxstate(sx, data, CONNECT_REQ_READ);
/* FALLTHROUGH */
case CONNECT_REQ_READ:
result = Curl_read_plain(sockfd, (char *)sx->outp,
result = Curl_read_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &actualread);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
@@ -958,7 +959,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
CURLproxycode rc = CURLPX_REPLY_UNASSIGNED;
int code = socksreq[1];
failf(data, "Can't complete SOCKS5 connection to %s. (%d)",
hostname, (unsigned char)socksreq[1]);
sx->hostname, (unsigned char)socksreq[1]);
if(code < 9) {
/* RFC 1928 section 6 lists: */
static const CURLproxycode lookup[] = {
@@ -1019,10 +1020,10 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
if(len > 10) {
sx->outstanding = len - 10; /* get the rest */
sx->outp = &socksreq[10];
sxstate(data, CONNECT_REQ_READ_MORE);
sxstate(sx, data, CONNECT_REQ_READ_MORE);
}
else {
sxstate(data, CONNECT_DONE);
sxstate(sx, data, CONNECT_DONE);
break;
}
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
@@ -1030,7 +1031,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
#endif
/* FALLTHROUGH */
case CONNECT_REQ_READ_MORE:
result = Curl_read_plain(sockfd, (char *)sx->outp,
result = Curl_read_plain(data, sockfd, (char *)sx->outp,
sx->outstanding, &actualread);
if(result && (CURLE_AGAIN != result)) {
failf(data, "Failed to receive SOCKS5 connect request ack.");
@@ -1047,12 +1048,214 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
sx->outp += actualread;
return CURLPX_OK;
}
sxstate(data, CONNECT_DONE);
sxstate(sx, data, CONNECT_DONE);
}
infof(data, "SOCKS5 request granted.");
*done = TRUE;
return CURLPX_OK; /* Proxy was successful! */
}
static CURLcode connect_SOCKS(struct Curl_cfilter *cf,
struct socks_state *sxstate,
struct Curl_easy *data)
{
CURLcode result = CURLE_OK;
CURLproxycode pxresult = CURLPX_OK;
struct connectdata *conn = cf->conn;
switch(conn->socks_proxy.proxytype) {
case CURLPROXY_SOCKS5:
case CURLPROXY_SOCKS5_HOSTNAME:
pxresult = do_SOCKS5(cf, sxstate, data);
break;
case CURLPROXY_SOCKS4:
case CURLPROXY_SOCKS4A:
pxresult = do_SOCKS4(cf, sxstate, data);
break;
default:
failf(data, "unknown proxytype option given");
result = CURLE_COULDNT_CONNECT;
} /* switch proxytype */
if(pxresult) {
result = CURLE_PROXY;
data->info.pxcode = pxresult;
}
return result;
}
static void socks_proxy_cf_free(struct Curl_cfilter *cf)
{
struct socks_state *sxstate = cf->ctx;
if(sxstate) {
free(sxstate);
cf->ctx = NULL;
}
}
/* After a TCP connection to the proxy has been verified, this function does
the next magic steps. If 'done' isn't set TRUE, it is not done yet and
must be called again.
Note: this function's sub-functions call failf()
*/
static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
bool blocking, bool *done)
{
CURLcode result;
struct connectdata *conn = cf->conn;
int sockindex = cf->sockindex;
struct socks_state *sx = cf->ctx;
if(cf->connected) {
*done = TRUE;
return CURLE_OK;
}
result = cf->next->cft->connect(cf->next, data, blocking, done);
if(result || !*done)
return result;
if(!sx) {
sx = calloc(sizeof(*sx), 1);
if(!sx)
return CURLE_OUT_OF_MEMORY;
cf->ctx = sx;
}
if(sx->state == CONNECT_INIT) {
/* for the secondary socket (FTP), use the "connect to host"
* but ignore the "connect to port" (use the secondary port)
*/
sxstate(sx, data, CONNECT_SOCKS_INIT);
sx->hostname =
conn->bits.httpproxy ?
conn->http_proxy.host.name :
conn->bits.conn_to_host ?
conn->conn_to_host.name :
sockindex == SECONDARYSOCKET ?
conn->secondaryhostname : conn->host.name;
sx->remote_port =
conn->bits.httpproxy ? (int)conn->http_proxy.port :
sockindex == SECONDARYSOCKET ? conn->secondary_port :
conn->bits.conn_to_port ? conn->conn_to_port :
conn->remote_port;
sx->proxy_user = conn->socks_proxy.user;
sx->proxy_password = conn->socks_proxy.passwd;
}
result = connect_SOCKS(cf, sx, data);
if(!result && sx->state == CONNECT_DONE) {
cf->connected = TRUE;
Curl_updateconninfo(data, conn, conn->sock[cf->sockindex]);
Curl_verboseconnect(data, conn);
socks_proxy_cf_free(cf);
}
*done = cf->connected;
return result;
}
static int socks_cf_get_select_socks(struct Curl_cfilter *cf,
struct Curl_easy *data,
curl_socket_t *socks)
{
struct socks_state *sx = cf->ctx;
int fds;
fds = cf->next->cft->get_select_socks(cf->next, data, socks);
if(!fds && cf->next->connected && !cf->connected && sx) {
/* If we are not connected, the filter below is and has nothing
* to wait on, we determine what to wait for. */
socks[0] = cf->conn->sock[cf->sockindex];
switch(sx->state) {
case CONNECT_RESOLVING:
case CONNECT_SOCKS_READ:
case CONNECT_AUTH_READ:
case CONNECT_REQ_READ:
case CONNECT_REQ_READ_MORE:
fds = GETSOCK_READSOCK(0);
break;
default:
fds = GETSOCK_WRITESOCK(0);
break;
}
}
return fds;
}
static void socks_proxy_cf_close(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
DEBUGASSERT(cf->next);
cf->connected = FALSE;
socks_proxy_cf_free(cf);
cf->next->cft->close(cf->next, data);
}
static void socks_proxy_cf_destroy(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
(void)data;
socks_proxy_cf_free(cf);
}
static void socks_proxy_cf_detach_data(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
(void)data;
socks_proxy_cf_free(cf);
}
static void socks_cf_get_host(struct Curl_cfilter *cf,
struct Curl_easy *data,
const char **phost,
const char **pdisplay_host,
int *pport)
{
(void)data;
if(!cf->connected) {
*phost = cf->conn->socks_proxy.host.name;
*pdisplay_host = cf->conn->http_proxy.host.dispname;
*pport = (int)cf->conn->socks_proxy.port;
}
else {
cf->next->cft->get_host(cf->next, data, phost, pdisplay_host, pport);
}
}
static const struct Curl_cftype cft_socks_proxy = {
"SOCKS-PROXYY",
CF_TYPE_IP_CONNECT,
socks_proxy_cf_destroy,
Curl_cf_def_setup,
socks_proxy_cf_connect,
socks_proxy_cf_close,
socks_cf_get_host,
socks_cf_get_select_socks,
Curl_cf_def_data_pending,
Curl_cf_def_send,
Curl_cf_def_recv,
Curl_cf_def_attach_data,
socks_proxy_cf_detach_data,
};
CURLcode Curl_conn_socks_proxy_add(struct Curl_easy *data,
struct connectdata *conn,
int sockindex)
{
struct Curl_cfilter *cf;
CURLcode result;
result = Curl_cf_create(&cf, &cft_socks_proxy, NULL);
if(!result)
Curl_conn_cf_add(data, conn, sockindex, cf);
return result;
}
#endif /* CURL_DISABLE_PROXY */

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