mirror of
https://github.com/Kitware/CMake.git
synced 2026-04-25 15:49:08 -05:00
Merge topic 'update-curl'
8443dfa946curl: Work around missing OpenSSL symbol on machine with LCC 1.23f9f5957884Merge branch 'upstream-curl' into update-curldac458ddbfcurl 2022-12-21 (c12fb3dd)39dcf9469dcurl: Update script to get curl 7.87.0b2fe717a49file: Avoid using deprecated curl progress callback1cd38de47fctest: Drop unnecessary use of deprecated CURLOPT_PUT Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !8131
This commit is contained in:
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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: ");
|
||||
|
||||
|
||||
@@ -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 ] },
|
||||
|
||||
@@ -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/*
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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) &&
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
+1084
-878
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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"));
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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"));
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user