[Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-47-g3373f1e

Brad King brad.king at kitware.com
Wed Feb 8 10:49:36 EST 2017


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  3373f1efa71ea5cc3cb98238b25c5dd08420748c (commit)
       via  4ed9498bbdc13344a7f81b2c213a175bb719121d (commit)
       via  37d47b4375fd8c15f90bd1b03f6a2c1a0ac58636 (commit)
       via  73ae67006c952b8804f2566e868bc3acf7539857 (commit)
       via  1df9d5f91944e0b5ba00815d55bb7dc545053b4c (commit)
       via  4cc2908fdaaf1ab8afe5c2ae5dbb3401859a9aab (commit)
       via  f4a3290ae7ae096f8b92f7adfba7088e6918bc0b (commit)
      from  db47cc7584e076fa6ebfbf9cf71317c15fc4e691 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3373f1efa71ea5cc3cb98238b25c5dd08420748c
commit 3373f1efa71ea5cc3cb98238b25c5dd08420748c
Merge: db47cc7 4ed9498
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Feb 8 10:49:29 2017 -0500
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Wed Feb 8 10:49:29 2017 -0500

    Merge topic 'update-curl' into next
    
    4ed9498b Help: Add notes for topic 'update-curl'
    37d47b43 Tests: Fix `file://` URLs given to curl
    73ae6700 curl: Fix passing _WINSOCKAPI_ macro to compiler
    1df9d5f9 Merge branch 'upstream-curl' into update-curl
    4cc2908f curl 2016-12-22 (44b9b4d4)
    f4a3290a curl: Update script to get curl 7.52.1


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4ed9498bbdc13344a7f81b2c213a175bb719121d
commit 4ed9498bbdc13344a7f81b2c213a175bb719121d
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Feb 7 14:36:49 2017 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Feb 7 14:37:42 2017 -0500

    Help: Add notes for topic 'update-curl'

diff --git a/Help/release/dev/update-curl.rst b/Help/release/dev/update-curl.rst
new file mode 100644
index 0000000..852ad5a
--- /dev/null
+++ b/Help/release/dev/update-curl.rst
@@ -0,0 +1,6 @@
+update-curl
+-----------
+
+* The version of curl bundled with CMake no longer accepts URLs of the form
+  ``file://c:/...`` on Windows due to a change in upstream curl 7.52.  Use
+  the form ``file:///c:/...`` instead to work on all versions.

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=37d47b4375fd8c15f90bd1b03f6a2c1a0ac58636
commit 37d47b4375fd8c15f90bd1b03f6a2c1a0ac58636
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Feb 7 14:25:49 2017 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Feb 7 14:28:48 2017 -0500

    Tests: Fix `file://` URLs given to curl
    
    Since upstream curl commit curl-7_52_0~131 (URL-parser: for
    file://[host]/ URLs, the [host] must be localhost, 2016-11-11) we can no
    longer use URLs of the form `file://c:/...` on Windows.  These worked
    only accidentally before.  Use `file:///c:/...` instead.

diff --git a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in b/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in
index 4a47c06..82280dd 100644
--- a/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in
+++ b/Tests/CMakeTests/FileDownloadBadHashTest.cmake.in
@@ -1,4 +1,4 @@
-set(url "file://@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png")
+set(url "file:///@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png")
 set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads")
 
 file(DOWNLOAD
diff --git a/Tests/CMakeTests/FileDownloadTest.cmake.in b/Tests/CMakeTests/FileDownloadTest.cmake.in
index 83ade2b..48b4afe 100644
--- a/Tests/CMakeTests/FileDownloadTest.cmake.in
+++ b/Tests/CMakeTests/FileDownloadTest.cmake.in
@@ -1,4 +1,4 @@
-set(url "file://@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png")
+set(url "file:///@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png")
 set(dir "@CMAKE_CURRENT_BINARY_DIR@/downloads")
 
 message(STATUS "FileDownload:1")
diff --git a/Tests/CMakeTests/FileUploadTest.cmake.in b/Tests/CMakeTests/FileUploadTest.cmake.in
index 8577aef..452090f 100644
--- a/Tests/CMakeTests/FileUploadTest.cmake.in
+++ b/Tests/CMakeTests/FileUploadTest.cmake.in
@@ -10,7 +10,7 @@ endif()
 file(MAKE_DIRECTORY "@CMAKE_CURRENT_BINARY_DIR@/uploads")
 
 set(filename "@CMAKE_CURRENT_SOURCE_DIR@/FileDownloadInput.png")
-set(urlbase "file://@CMAKE_CURRENT_BINARY_DIR@/uploads")
+set(urlbase "file:///@CMAKE_CURRENT_BINARY_DIR@/uploads")
 
 message(STATUS "FileUpload:1")
 file(UPLOAD
diff --git a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake
index ca72692..02e67dc 100644
--- a/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake
+++ b/Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake
@@ -1,5 +1,5 @@
 file(DOWNLOAD
-  "file://${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-hash-mismatch.txt"
+  "file:///${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-hash-mismatch.txt"
   ${CMAKE_CURRENT_BINARY_DIR}/hash-mismatch.txt
   EXPECTED_HASH SHA1=0123456789abcdef0123456789abcdef01234567
   STATUS status
diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake
index 2e3fbe1..862d833 100644
--- a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake
+++ b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake
@@ -1,5 +1,5 @@
 file(DOWNLOAD
-  "file://${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt"
+  "file:///${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt"
   "${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt"
   JUNK
   )
diff --git a/Tests/RunCMake/file/UPLOAD-unused-argument.cmake b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake
index 94ac9ac..408da0e 100644
--- a/Tests/RunCMake/file/UPLOAD-unused-argument.cmake
+++ b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake
@@ -1,5 +1,5 @@
 file(UPLOAD
   "${CMAKE_CURRENT_SOURCE_DIR}/UPLOAD-unused-argument.txt"
-  "file://${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt"
+  "file:///${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt"
   JUNK
   )

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=73ae67006c952b8804f2566e868bc3acf7539857
commit 73ae67006c952b8804f2566e868bc3acf7539857
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Feb 7 11:39:49 2017 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Feb 7 11:39:49 2017 -0500

    curl: Fix passing _WINSOCKAPI_ macro to compiler
    
    Define `_WINSOCKAPI_` blank rather than to 1 in order to match the
    value used by Microsoft's winsock header files.
    
    Backported from upstream curl commit 192466e0 (cmake: Fix passing
    _WINSOCKAPI_ macro to compiler, 2017-01-09).
    
    Fixes: #16545

diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 5cef59f..6a34e8d 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -316,7 +316,7 @@ include (CheckCSourceCompiles)
 
 # On windows preload settings
 if(WIN32)
-  set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_")
+  set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_=")
   include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake)
 endif(WIN32)
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1df9d5f91944e0b5ba00815d55bb7dc545053b4c
commit 1df9d5f91944e0b5ba00815d55bb7dc545053b4c
Merge: f4a3290 4cc2908
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Feb 7 11:38:00 2017 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Feb 7 11:38:00 2017 -0500

    Merge branch 'upstream-curl' into update-curl
    
    * upstream-curl:
      curl 2016-12-22 (44b9b4d4)

diff --cc Utilities/cmcurl/CMakeLists.txt
index 262554d,0000000..5cef59f
mode 100644,000000..100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@@ -1,1279 -1,0 +1,1283 @@@
 +# Set curl options as needed for CMake build
 +set(BUILD_CURL_EXE OFF CACHE INTERNAL "No curl exe")
 +set(BUILD_DASHBOARD_REPORTS OFF CACHE INTERNAL "No curl dashboard reports")
 +set(BUILD_RELEASE_DEBUG_DIRS OFF CACHE INTERNAL "No curl release/debug dirs")
 +set(CMAKE_USE_GSSAPI OFF CACHE INTERNAL "Disable curl gssapi")
 +set(CMAKE_USE_LIBSSH2 OFF CACHE INTERNAL "Disable curl libssh2")
 +set(CMAKE_USE_OPENLDAP OFF CACHE INTERNAL "No curl OpenLDAP")
 +set(CURL_DISABLE_COOKIES OFF CACHE INTERNAL "Do not disable curl cookie support")
 +set(CURL_DISABLE_CRYPTO_AUTH OFF CACHE INTERNAL "Do not disable curl crypto auth")
 +set(CURL_DISABLE_DICT ON CACHE INTERNAL "Disable curl dict protocol?")
 +set(CURL_DISABLE_FILE OFF CACHE INTERNAL "Disable curl file protocol?")
 +set(CURL_DISABLE_FTP OFF CACHE INTERNAL "Disable curl ftp protocol?")
 +set(CURL_DISABLE_GOPHER ON CACHE INTERNAL "Disable curl gopher protocol?")
 +set(CURL_DISABLE_HTTP OFF CACHE INTERNAL "Disable curl http protocol?")
 +set(CURL_DISABLE_IMAP ON CACHE INTERNAL "Disable curl imap protocol?")
 +set(CURL_DISABLE_LDAP ON CACHE INTERNAL "Disable curl ldap protocol?")
 +set(CURL_DISABLE_LDAPS ON CACHE INTERNAL "Disable curl ldaps protocol?")
 +set(CURL_DISABLE_POP3 ON CACHE INTERNAL "Disable curl pop3 protocol?")
 +set(CURL_DISABLE_PROXY OFF CACHE INTERNAL "Do not disable curl proxy")
 +set(CURL_DISABLE_RTSP ON CACHE INTERNAL "Disable curl rtsp protocol?")
 +set(CURL_DISABLE_SMTP ON CACHE INTERNAL "Disable curl smtp protocol?")
 +set(CURL_DISABLE_TELNET ON CACHE INTERNAL "Disable curl telnet protocol?")
 +set(CURL_DISABLE_TFTP ON CACHE INTERNAL "Disable curl tftp protocol?")
 +set(CURL_DISABLE_VERBOSE_STRINGS OFF CACHE INTERNAL "Do not disable curl verbosity")
 +set(CURL_HIDDEN_SYMBOLS OFF CACHE INTERNAL "No curl hidden symbols")
 +set(CURL_STATICLIB ON CACHE INTERNAL "Static curl")
 +set(DISABLED_THREADSAFE OFF CACHE INTERNAL "Curl can use thread-safe functions")
 +set(ENABLE_ARES OFF CACHE INTERNAL "No curl c-ares support")
 +set(ENABLE_CURLDEBUG OFF CACHE INTERNAL "No curl TrackMemory features")
 +set(ENABLE_DEBUG OFF CACHE INTERNAL "No curl debug features")
 +set(ENABLE_IPV6 OFF CACHE INTERNAL "No curl IPv6 support")
 +set(ENABLE_MANUAL OFF CACHE INTERNAL "No curl built-in manual")
 +set(ENABLE_THREADED_RESOLVER OFF CACHE INTERNAL "No curl POSIX threaded DNS lookup")
 +set(ENABLE_UNIX_SOCKETS OFF CACHE INTERNAL "No curl Unix domain sockets support")
 +set(HTTP_ONLY OFF CACHE INTERNAL "Curl is not http-only")
 +set(USE_WIN32_LDAP OFF CACHE INTERNAL "No curl Windows LDAP")
 +
 +# Windows Vista and above have inet_pton, but this will link on
 +# older versions and then the executable will fail to launch at
 +# runtime on older versions because no DLL provides the symbol.
 +if(WIN32)
 +  set(HAVE_INET_PTON 0 CACHE INTERNAL "Do not use inet_pton")
 +endif()
 +
 +# Starting with OSX 10.11 there is an unrelated libnetwork library which will
 +# be picked up during curl configuration. Linking against this library is
 +# unnecessary and breaks backward compatibility of the resulting binaries
 +# because libnetwork is unavailable on older OSX versions.
 +if(APPLE)
 +  set(HAVE_LIBNETWORK 0 CACHE INTERNAL "Do not use libnetwork")
 +endif(APPLE)
 +
 +# Disable warnings to avoid changing 3rd party code.
 +if(CMAKE_C_COMPILER_ID MATCHES
 +    "^(GNU|Clang|AppleClang|XL|VisualAge|SunPro|MIPSpro|HP|Intel)$")
 +  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
 +elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale")
 +  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall")
 +endif()
 +
 +#***************************************************************************
 +#                                  _   _ ____  _
 +#  Project                     ___| | | |  _ \| |
 +#                             / __| | | | |_) | |
 +#                            | (__| |_| |  _ <| |___
 +#                             \___|\___/|_| \_\_____|
 +#
 +# Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
 +#
 +# This software is licensed as described in the file COPYING, which
 +# you should have received as part of this distribution. The terms
 +# are also available at https://curl.haxx.se/docs/copyright.html.
 +#
 +# You may opt to use, copy, modify, merge, publish, distribute and/or sell
 +# copies of the Software, and permit persons to whom the Software is
 +# furnished to do so, under the terms of the COPYING file.
 +#
 +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 +# KIND, either express or implied.
 +#
 +###########################################################################
 +# curl/libcurl CMake script
 +# by Tetetest and Sukender (Benoit Neil)
 +
 +# TODO:
 +# The output .so file lacks the soname number which we currently have within the lib/Makefile.am file
 +# Add full (4 or 5 libs) SSL support
 +# Add INSTALL target (EXTRA_DIST variables in Makefile.am may be moved to Makefile.inc so that CMake/CPack is aware of what's to include).
 +# Add CTests(?)
 +# Check on all possible platforms
 +# Test with as many configurations possible (With or without any option)
 +# Create scripts that help keeping the CMake build system up to date (to reduce maintenance). According to Tetetest:
 +#  - lists of headers that 'configure' checks for;
 +#  - curl-specific tests (the ones that are in m4/curl-*.m4 files);
 +#  - (most obvious thing:) curl version numbers.
 +# Add documentation subproject
 +#
 +# To check:
 +# (From Daniel Stenberg) The cmake build selected to run gcc with -fPIC on my box while the plain configure script did not.
 +# (From Daniel Stenberg) The gcc command line use neither -g nor any -O options. As a developer, I also treasure our configure scripts's --enable-debug option that sets a long range of "picky" compiler options.
 +cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
 +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
 +include(Utilities)
 +include(Macros)
 +include(CMakeDependentOption)
 +
 +project( CURL C )
 +
 +if(0) # This code not needed for building within CMake.
 +message(WARNING "the curl cmake build system is poorly maintained. Be aware")
 +endif()
 +
 +file (READ ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS)
 +string (REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*"
 +  CURL_VERSION ${CURL_VERSION_H_CONTENTS})
 +string (REGEX REPLACE "[^\"]+\"" "" CURL_VERSION ${CURL_VERSION})
 +string (REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+"
 +  CURL_VERSION_NUM ${CURL_VERSION_H_CONTENTS})
 +string (REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM})
 +
 +include_regular_expression("^.*$")    # Sukender: Is it necessary?
 +
 +# Setup package meta-data
 +# SET(PACKAGE "curl")
 +if(0) # This code not needed for building within CMake.
 +message(STATUS "curl version=[${CURL_VERSION}]")
 +endif()
 +# SET(PACKAGE_TARNAME "curl")
 +# SET(PACKAGE_NAME "curl")
 +# SET(PACKAGE_VERSION "-")
 +# SET(PACKAGE_STRING "curl-")
 +# SET(PACKAGE_BUGREPORT "a suitable curl mailing list => https://curl.haxx.se/mail/")
 +set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
 +set(OS "\"${CMAKE_SYSTEM_NAME}\"")
 +
 +include_directories(${PROJECT_BINARY_DIR}/include/curl)
 +include_directories( ${CURL_SOURCE_DIR}/include )
 +
 +option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
 +option(CURL_STATICLIB "Set to ON to build libcurl with static linking." OFF)
 +option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
 +if(WIN32)
 +  CMAKE_DEPENDENT_OPTION(ENABLE_THREADED_RESOLVER
 +                         "Set to ON to enable threaded DNS lookup"
 +                         ON "NOT ENABLE_ARES"
 +                         OFF)
 +else()
 +  option(ENABLE_THREADED_RESOLVER "Set to ON to enable POSIX threaded DNS lookup" OFF)
 +endif()
 +option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF)
 +option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OFF)
 +
 +if (ENABLE_DEBUG)
 +  # DEBUGBUILD will be defined only for Debug builds
 +  if(NOT CMAKE_VERSION VERSION_LESS 3.0)
 +    set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUGBUILD>)
 +  else()
 +    set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUGBUILD)
 +  endif()
 +  set(ENABLE_CURLDEBUG ON)
 +endif()
 +
 +if (ENABLE_CURLDEBUG)
 +  set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS CURLDEBUG)
 +endif()
 +
 +# initialize CURL_LIBS
 +set(CURL_LIBS "")
 +
 +if(ENABLE_THREADED_RESOLVER AND ENABLE_ARES)
 +  message(FATAL_ERROR "Options ENABLE_THREADED_RESOLVER and ENABLE_ARES are mutually exclusive")
 +endif()
 +
 +if(ENABLE_ARES)
 +  set(USE_ARES 1)
 +  find_package(CARES REQUIRED)
 +  list(APPEND CURL_LIBS ${CARES_LIBRARY} )
 +  set(CURL_LIBS ${CURL_LIBS} ${CARES_LIBRARY})
 +endif()
 +
 +if(MSVC)
 +  option(BUILD_RELEASE_DEBUG_DIRS "Set OFF to build each configuration to a separate directory" OFF)
 +  mark_as_advanced(BUILD_RELEASE_DEBUG_DIRS)
 +endif()
 +
 +if(0) # This code not needed for building within CMake.
 +include(CurlSymbolHiding)
 +endif()
 +
 +option(HTTP_ONLY "disables all protocols except HTTP (This overrides all CURL_DISABLE_* options)" OFF)
 +mark_as_advanced(HTTP_ONLY)
 +option(CURL_DISABLE_FTP "disables FTP" OFF)
 +mark_as_advanced(CURL_DISABLE_FTP)
 +option(CURL_DISABLE_LDAP "disables LDAP" OFF)
 +mark_as_advanced(CURL_DISABLE_LDAP)
 +option(CURL_DISABLE_TELNET "disables Telnet" OFF)
 +mark_as_advanced(CURL_DISABLE_TELNET)
 +option(CURL_DISABLE_DICT "disables DICT" OFF)
 +mark_as_advanced(CURL_DISABLE_DICT)
 +option(CURL_DISABLE_FILE "disables FILE" OFF)
 +mark_as_advanced(CURL_DISABLE_FILE)
 +option(CURL_DISABLE_TFTP "disables TFTP" OFF)
 +mark_as_advanced(CURL_DISABLE_TFTP)
 +option(CURL_DISABLE_HTTP "disables HTTP" OFF)
 +mark_as_advanced(CURL_DISABLE_HTTP)
 +
 +option(CURL_DISABLE_LDAPS "to disable LDAPS" OFF)
 +mark_as_advanced(CURL_DISABLE_LDAPS)
 +
 +option(CURL_DISABLE_RTSP "to disable RTSP" OFF)
 +mark_as_advanced(CURL_DISABLE_RTSP)
 +option(CURL_DISABLE_PROXY "to disable proxy" OFF)
 +mark_as_advanced(CURL_DISABLE_PROXY)
 +option(CURL_DISABLE_POP3 "to disable POP3" OFF)
 +mark_as_advanced(CURL_DISABLE_POP3)
 +option(CURL_DISABLE_IMAP "to disable IMAP" OFF)
 +mark_as_advanced(CURL_DISABLE_IMAP)
 +option(CURL_DISABLE_SMTP "to disable SMTP" OFF)
 +mark_as_advanced(CURL_DISABLE_SMTP)
 +option(CURL_DISABLE_GOPHER "to disable Gopher" OFF)
 +mark_as_advanced(CURL_DISABLE_GOPHER)
 +
 +if(HTTP_ONLY)
 +  set(CURL_DISABLE_FTP ON)
 +  set(CURL_DISABLE_LDAP ON)
 +  set(CURL_DISABLE_LDAPS ON)
 +  set(CURL_DISABLE_TELNET ON)
 +  set(CURL_DISABLE_DICT ON)
 +  set(CURL_DISABLE_FILE ON)
 +  set(CURL_DISABLE_TFTP ON)
 +  set(CURL_DISABLE_RTSP ON)
 +  set(CURL_DISABLE_POP3 ON)
 +  set(CURL_DISABLE_IMAP ON)
 +  set(CURL_DISABLE_SMTP ON)
 +  set(CURL_DISABLE_GOPHER ON)
 +endif()
 +
 +option(CURL_DISABLE_COOKIES "to disable cookies support" OFF)
 +mark_as_advanced(CURL_DISABLE_COOKIES)
 +
 +option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF)
 +mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH)
 +option(CURL_DISABLE_VERBOSE_STRINGS "to disable verbose strings" OFF)
 +mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS)
 +option(DISABLED_THREADSAFE "Set to explicitly specify we don't want to use thread-safe functions" OFF)
 +mark_as_advanced(DISABLED_THREADSAFE)
 +option(ENABLE_IPV6 "Define if you want to enable IPv6 support" ON)
 +mark_as_advanced(ENABLE_IPV6)
 +if(ENABLE_IPV6 AND NOT WIN32)
 +  include(CheckStructHasMember)
 +  check_struct_has_member("struct sockaddr_in6" sin6_addr "netinet/in.h"
 +                          HAVE_SOCKADDR_IN6_SIN6_ADDR)
 +  check_struct_has_member("struct sockaddr_in6" sin6_scope_id "netinet/in.h"
 +                          HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
 +  if(NOT HAVE_SOCKADDR_IN6_SIN6_ADDR)
 +    message(WARNING "struct sockaddr_in6 not available, disabling IPv6 support")
 +    # Force the feature off as this name is used as guard macro...
 +    set(ENABLE_IPV6 OFF
 +        CACHE BOOL "Define if you want to enable IPv6 support" FORCE)
 +  endif()
 +endif()
 +
 +option(ENABLE_MANUAL "to provide the built-in manual" ON)
 +unset(USE_MANUAL CACHE) # TODO: cache NROFF/NROFF_MANOPT/USE_MANUAL vars?
 +if(ENABLE_MANUAL)
 +  find_program(NROFF NAMES gnroff nroff)
 +  if(NROFF)
 +    # Need a way to write to stdin, this will do
 +    file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt" "test")
 +    # Tests for a valid nroff option to generate a manpage
 +    foreach(_MANOPT "-man" "-mandoc")
 +      execute_process(COMMAND "${NROFF}" ${_MANOPT}
 +        OUTPUT_VARIABLE NROFF_MANOPT_OUTPUT
 +        INPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt"
 +        ERROR_QUIET)
 +      # Save the option if it was valid
 +      if(NROFF_MANOPT_OUTPUT)
 +        message("Found *nroff option: -- ${_MANOPT}")
 +        set(NROFF_MANOPT ${_MANOPT})
 +        set(USE_MANUAL 1)
 +        break()
 +      endif()
 +    endforeach()
 +    # No need for the temporary file
 +    file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt")
 +    if(NOT USE_MANUAL)
 +      message(WARNING "Found no *nroff option to get plaintext from man pages")
 +    endif()
 +  else()
 +    message(WARNING "Found no *nroff program")
 +  endif()
 +endif()
 +
 +# We need ansi c-flags, especially on HP
 +set(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}")
 +set(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS})
 +
 +# Disable warnings on Borland to avoid changing 3rd party code.
 +if(BORLAND)
 +  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-")
 +endif(BORLAND)
 +
 +# If we are on AIX, do the _ALL_SOURCE magic
 +if(${CMAKE_SYSTEM_NAME} MATCHES AIX)
 +  set(_ALL_SOURCE 1)
 +endif(${CMAKE_SYSTEM_NAME} MATCHES AIX)
 +
 +# Include all the necessary files for macros
 +include (CheckFunctionExists)
 +include (CheckIncludeFile)
 +include (CheckIncludeFiles)
 +include (CheckLibraryExists)
 +include (CheckSymbolExists)
 +include (CheckTypeSize)
 +include (CheckCSourceCompiles)
 +
 +# On windows preload settings
 +if(WIN32)
 +  set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WINSOCKAPI_")
 +  include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/Platforms/WindowsCache.cmake)
 +endif(WIN32)
 +
 +if(ENABLE_THREADED_RESOLVER)
 +  if(WIN32)
 +    set(USE_THREADS_WIN32 ON)
 +  else()
 +    check_include_file_concat("pthread.h" HAVE_PTHREAD_H)
 +    if(HAVE_PTHREAD_H)
 +      set(CMAKE_THREAD_PREFER_PTHREAD 1)
 +      find_package(Threads)
 +      if(CMAKE_USE_PTHREADS_INIT)
 +        set(CURL_LIBS ${CURL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
 +        set(USE_THREADS_POSIX 1)
 +      endif()
 +    endif()
 +  endif()
 +endif()
 +
 +# Check for all needed libraries
 +if(0) # This code not needed for building within CMake.
 +check_library_exists_concat("dl"     dlopen       HAVE_LIBDL)
 +else()
 +  # Use the cmake-defined dl libs as dl is should not be used
 +  # on HPUX, but rather dld this avoids a warning
 +  list(APPEND CURL_LIBS ${CMAKE_DL_LIBS})
 +endif()
 +check_library_exists_concat("socket" connect      HAVE_LIBSOCKET)
 +check_library_exists("c" gethostbyname "" NOT_NEED_LIBNSL)
 +
 +# Yellowtab Zeta needs different libraries than BeOS 5.
 +if(BEOS)
 +  set(NOT_NEED_LIBNSL 1)
 +  check_library_exists_concat("bind" gethostbyname HAVE_LIBBIND)
 +  check_library_exists_concat("bnetapi" closesocket HAVE_LIBBNETAPI)
 +endif(BEOS)
 +
 +check_library_exists_concat("network" recv HAVE_LIBNETWORK)
 +
 +if(NOT NOT_NEED_LIBNSL)
 +  check_library_exists_concat("nsl"    gethostbyname  HAVE_LIBNSL)
 +endif(NOT NOT_NEED_LIBNSL)
 +
 +check_function_exists(gethostname HAVE_GETHOSTNAME)
 +
 +if(WIN32)
 +  check_library_exists_concat("ws2_32" getch        HAVE_LIBWS2_32)
 +  check_library_exists_concat("winmm"  getch        HAVE_LIBWINMM)
 +endif()
 +
 +set(USE_OPENSSL OFF)
 +set(HAVE_LIBCRYPTO OFF)
 +set(HAVE_LIBSSL OFF)
 +
 +if(CMAKE_USE_OPENSSL)
 +  find_package(OpenSSL)
 +  if(OPENSSL_FOUND)
 +    list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})
 +    set(USE_OPENSSL ON)
 +    set(HAVE_LIBCRYPTO ON)
 +    set(HAVE_LIBSSL ON)
 +    include_directories(${OPENSSL_INCLUDE_DIR})
 +    set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
 +    check_include_file("openssl/crypto.h" HAVE_OPENSSL_CRYPTO_H)
 +    check_include_file("openssl/engine.h" HAVE_OPENSSL_ENGINE_H)
 +    check_include_file("openssl/err.h"    HAVE_OPENSSL_ERR_H)
 +    check_include_file("openssl/pem.h"    HAVE_OPENSSL_PEM_H)
 +    check_include_file("openssl/pkcs12.h" HAVE_OPENSSL_PKCS12_H)
 +    check_include_file("openssl/rsa.h"    HAVE_OPENSSL_RSA_H)
 +    check_include_file("openssl/ssl.h"    HAVE_OPENSSL_SSL_H)
 +    check_include_file("openssl/x509.h"   HAVE_OPENSSL_X509_H)
 +    check_include_file("openssl/rand.h"   HAVE_OPENSSL_RAND_H)
 +
 +    # Optionally build with a specific CA cert bundle.
 +    if(CURL_CA_BUNDLE)
 +      add_definitions(-DCURL_CA_BUNDLE="${CURL_CA_BUNDLE}")
 +    endif()
 +    # Optionally build with a specific CA cert dir.
 +    if(CURL_CA_PATH)
 +      add_definitions(-DCURL_CA_PATH="${CURL_CA_PATH}")
 +    endif()
 +  endif()
 +elseif(WIN32)
 +  # Use Windows SSL/TLS native implementation.
 +  set(CURL_WINDOWS_SSPI ON)
 +elseif(APPLE)
 +  # Use OS X SSL/TLS native implementation if available on target version.
 +  if(CMAKE_OSX_DEPLOYMENT_TARGET)
 +    set(OSX_VERSION ${CMAKE_OSX_DEPLOYMENT_TARGET})
 +  else()
 +    execute_process(
 +      COMMAND sw_vers -productVersion
 +      OUTPUT_VARIABLE OSX_VERSION
 +      OUTPUT_STRIP_TRAILING_WHITESPACE
 +      )
 +  endif()
 +  if(NOT OSX_VERSION VERSION_LESS 10.6 AND
 +     CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
 +    add_definitions(-DUSE_DARWINSSL)
 +    list(APPEND CURL_LIBS
 +      "-framework CoreFoundation"
 +      "-framework Security"
 +      )
 +  endif()
 +endif()
 +
 +option(USE_NGHTTP2 "Use Nghttp2 library" OFF)
 +if(USE_NGHTTP2)
 +  find_package(NGHTTP2 REQUIRED)
 +  include_directories(${NGHTTP2_INCLUDE_DIRS})
 +  list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES})
 +endif()
 +
 +if(NOT CURL_DISABLE_LDAP)
 +  if(WIN32)
 +    option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON)
 +    if(USE_WIN32_LDAP)
 +      check_library_exists_concat("wldap32" cldap_open HAVE_WLDAP32)
 +      if(NOT HAVE_WLDAP32)
 +        set(USE_WIN32_LDAP OFF)
 +      endif()
 +    endif()
 +  endif()
 +
 +  option(CMAKE_USE_OPENLDAP "Use OpenLDAP code." OFF)
 +  mark_as_advanced(CMAKE_USE_OPENLDAP)
 +  set(CMAKE_LDAP_LIB "ldap" CACHE STRING "Name or full path to ldap library")
 +  set(CMAKE_LBER_LIB "lber" CACHE STRING "Name or full path to lber library")
 +
 +  if(CMAKE_USE_OPENLDAP AND USE_WIN32_LDAP)
 +    message(FATAL_ERROR "Cannot use USE_WIN32_LDAP and CMAKE_USE_OPENLDAP at the same time")
 +  endif()
 +
 +  # Now that we know, we're not using windows LDAP...
 +  if(USE_WIN32_LDAP)
 +    check_include_file_concat("winldap.h" HAVE_WINLDAP_H)
 +    check_include_file_concat("winber.h"  HAVE_WINBER_H)
 +  else()
 +    # Check for LDAP
 +    set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES})
 +    check_library_exists_concat(${CMAKE_LDAP_LIB} ldap_init HAVE_LIBLDAP)
 +    check_library_exists_concat(${CMAKE_LBER_LIB} ber_init HAVE_LIBLBER)
 +
 +    set(CMAKE_REQUIRED_INCLUDES_BAK ${CMAKE_REQUIRED_INCLUDES})
 +    set(CMAKE_LDAP_INCLUDE_DIR "" CACHE STRING "Path to LDAP include directory")
 +    if(CMAKE_LDAP_INCLUDE_DIR)
 +      list(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_LDAP_INCLUDE_DIR})
 +    endif()
 +    check_include_file_concat("ldap.h"           HAVE_LDAP_H)
 +    check_include_file_concat("lber.h"           HAVE_LBER_H)
 +
 +    if(NOT HAVE_LDAP_H)
 +      message(STATUS "LDAP_H not found CURL_DISABLE_LDAP set ON")
 +      set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
 +      set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) #LDAP includes won't be used
 +    elseif(NOT HAVE_LIBLDAP)
 +      message(STATUS "LDAP library '${CMAKE_LDAP_LIB}' not found CURL_DISABLE_LDAP set ON")
 +      set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
 +      set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_BAK}) #LDAP includes won't be used
 +    else()
 +      if(CMAKE_USE_OPENLDAP)
 +        set(USE_OPENLDAP ON)
 +      endif()
 +      if(CMAKE_LDAP_INCLUDE_DIR)
 +        include_directories(${CMAKE_LDAP_INCLUDE_DIR})
 +      endif()
 +      set(NEED_LBER_H ON)
 +      set(_HEADER_LIST)
 +      if(HAVE_WINDOWS_H)
 +        list(APPEND _HEADER_LIST "windows.h")
 +      endif()
 +      if(HAVE_SYS_TYPES_H)
 +        list(APPEND _HEADER_LIST "sys/types.h")
 +      endif()
 +      list(APPEND _HEADER_LIST "ldap.h")
 +
 +      set(_SRC_STRING "")
 +      foreach(_HEADER ${_HEADER_LIST})
 +        set(_INCLUDE_STRING "${_INCLUDE_STRING}#include <${_HEADER}>\n")
 +      endforeach()
 +
 +      set(_SRC_STRING
 +        "
 +        ${_INCLUDE_STRING}
 +        int main(int argc, char ** argv)
 +        {
 +          BerValue *bvp = NULL;
 +          BerElement *bep = ber_init(bvp);
 +          ber_free(bep, 1);
 +          return 0;
 +        }"
 +      )
 +      set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DLDAP_DEPRECATED=1")
 +      list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LDAP_LIB})
 +      if(HAVE_LIBLBER)
 +        list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB})
 +      endif()
 +      check_c_source_compiles("${_SRC_STRING}" NOT_NEED_LBER_H)
 +
 +      if(NOT_NEED_LBER_H)
 +        set(NEED_LBER_H OFF)
 +      else()
 +        set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DNEED_LBER_H")
 +      endif()
 +    endif()
 +  endif()
 +
 +endif()
 +
 +# No ldap, no ldaps.
 +if(CURL_DISABLE_LDAP)
 +  if(NOT CURL_DISABLE_LDAPS)
 +    message(STATUS "LDAP needs to be enabled to support LDAPS")
 +    set(CURL_DISABLE_LDAPS ON CACHE BOOL "" FORCE)
 +  endif()
 +endif()
 +
 +if(NOT CURL_DISABLE_LDAPS)
 +  check_include_file_concat("ldap_ssl.h" HAVE_LDAP_SSL_H)
 +  check_include_file_concat("ldapssl.h"  HAVE_LDAPSSL_H)
 +endif()
 +
 +# Check for idn
 +check_library_exists_concat("idn2" idn2_lookup_ul HAVE_LIBIDN2)
 +
 +# Check for symbol dlopen (same as HAVE_LIBDL)
 +check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN)
 +
 +if(0) # This code not needed for building within CMake.
 +option(CURL_ZLIB "Set to ON to enable building curl with zlib support." ON)
 +set(HAVE_LIBZ OFF)
 +set(HAVE_ZLIB_H OFF)
 +set(HAVE_ZLIB OFF)
 +if(CURL_ZLIB)
 +  find_package(ZLIB QUIET)
 +  if(ZLIB_FOUND)
 +    set(HAVE_ZLIB_H ON)
 +    set(HAVE_ZLIB ON)
 +    set(HAVE_LIBZ ON)
 +    list(APPEND CURL_LIBS ${ZLIB_LIBRARIES})
 +    include_directories(${ZLIB_INCLUDE_DIRS})
 +    list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS})
 +  endif()
 +endif()
 +endif()
 +
 +#-----------------------------------------------------------------------------
 +# CMake-specific curl code.
 +
 +if(CURL_SPECIAL_LIBZ)
 +  set(CURL_LIBS ${CURL_LIBS} "${CURL_SPECIAL_LIBZ}")
 +  include_directories(${CURL_SPECIAL_LIBZ_INCLUDES})
 +  set(HAVE_LIBZ 0)
 +  set(HAVE_ZLIB_H 0)
 +endif()
 +
 +#libSSH2
 +option(CMAKE_USE_LIBSSH2 "Use libSSH2" ON)
 +mark_as_advanced(CMAKE_USE_LIBSSH2)
 +set(USE_LIBSSH2 OFF)
 +set(HAVE_LIBSSH2 OFF)
 +set(HAVE_LIBSSH2_H OFF)
 +
 +if(CMAKE_USE_LIBSSH2)
 +  find_package(LibSSH2)
 +  if(LIBSSH2_FOUND)
 +    list(APPEND CURL_LIBS ${LIBSSH2_LIBRARY})
 +    set(CMAKE_REQUIRED_LIBRARIES ${LIBSSH2_LIBRARY})
 +    list(APPEND CMAKE_REQUIRED_INCLUDES "${LIBSSH2_INCLUDE_DIR}")
 +    include_directories("${LIBSSH2_INCLUDE_DIR}")
 +    set(HAVE_LIBSSH2 ON)
 +    set(USE_LIBSSH2 ON)
 +
 +    # find_package has already found the headers
 +    set(HAVE_LIBSSH2_H ON)
 +    set(CURL_INCLUDES ${CURL_INCLUDES} "${LIBSSH2_INCLUDE_DIR}/libssh2.h")
 +    set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -DHAVE_LIBSSH2_H")
 +
 +    # now check for specific libssh2 symbols as they were added in different versions
 +    set(CMAKE_EXTRA_INCLUDE_FILES "libssh2.h")
 +    check_function_exists(libssh2_version           HAVE_LIBSSH2_VERSION)
 +    check_function_exists(libssh2_init              HAVE_LIBSSH2_INIT)
 +    check_function_exists(libssh2_exit              HAVE_LIBSSH2_EXIT)
 +    check_function_exists(libssh2_scp_send64        HAVE_LIBSSH2_SCP_SEND64)
 +    check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE)
 +    set(CMAKE_EXTRA_INCLUDE_FILES "")
 +
 +  endif(LIBSSH2_FOUND)
 +endif(CMAKE_USE_LIBSSH2)
 +
 +option(CMAKE_USE_GSSAPI "Use GSSAPI implementation (right now only Heimdal is supported with CMake build)" OFF)
 +mark_as_advanced(CMAKE_USE_GSSAPI)
 +
 +if(CMAKE_USE_GSSAPI)
 +  find_package(GSS)
 +
 +  set(HAVE_GSSAPI ${GSS_FOUND})
 +  if(GSS_FOUND)
 +
 +    message(STATUS "Found ${GSS_FLAVOUR} GSSAPI version: \"${GSS_VERSION}\"")
 +
 +    list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIRECTORIES})
 +    check_include_file_concat("gssapi/gssapi.h"  HAVE_GSSAPI_GSSAPI_H)
 +    check_include_file_concat("gssapi/gssapi_generic.h" HAVE_GSSAPI_GSSAPI_GENERIC_H)
 +    check_include_file_concat("gssapi/gssapi_krb5.h" HAVE_GSSAPI_GSSAPI_KRB5_H)
 +
 +    if(GSS_FLAVOUR STREQUAL "Heimdal")
 +      set(HAVE_GSSHEIMDAL ON)
 +    else() # MIT
 +      set(HAVE_GSSMIT ON)
 +      set(_INCLUDE_LIST "")
 +      if(HAVE_GSSAPI_GSSAPI_H)
 +        list(APPEND _INCLUDE_LIST "gssapi/gssapi.h")
 +      endif()
 +      if(HAVE_GSSAPI_GSSAPI_GENERIC_H)
 +        list(APPEND _INCLUDE_LIST "gssapi/gssapi_generic.h")
 +      endif()
 +      if(HAVE_GSSAPI_GSSAPI_KRB5_H)
 +        list(APPEND _INCLUDE_LIST "gssapi/gssapi_krb5.h")
 +      endif()
 +
 +      string(REPLACE ";" " " _COMPILER_FLAGS_STR "${GSS_COMPILER_FLAGS}")
 +      string(REPLACE ";" " " _LINKER_FLAGS_STR "${GSS_LINKER_FLAGS}")
 +
 +      foreach(_dir ${GSS_LINK_DIRECTORIES})
 +        set(_LINKER_FLAGS_STR "${_LINKER_FLAGS_STR} -L\"${_dir}\"")
 +      endforeach()
 +
 +      set(CMAKE_REQUIRED_FLAGS "${_COMPILER_FLAGS_STR} ${_LINKER_FLAGS_STR}")
 +      set(CMAKE_REQUIRED_LIBRARIES ${GSS_LIBRARIES})
 +      check_symbol_exists("GSS_C_NT_HOSTBASED_SERVICE" ${_INCLUDE_LIST} HAVE_GSS_C_NT_HOSTBASED_SERVICE)
 +      if(NOT HAVE_GSS_C_NT_HOSTBASED_SERVICE)
 +        set(HAVE_OLD_GSSMIT ON)
 +      endif()
 +
 +    endif()
 +
 +    include_directories(${GSS_INCLUDE_DIRECTORIES})
 +    link_directories(${GSS_LINK_DIRECTORIES})
 +    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_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}")
 +    list(APPEND CURL_LIBS ${GSS_LIBRARIES})
 +
 +  else()
 +    message(WARNING "GSSAPI support has been requested but no supporting libraries found. Skipping.")
 +  endif()
 +endif()
 +
 +option(ENABLE_UNIX_SOCKETS "Define if you want Unix domain sockets support" ON)
 +if(ENABLE_UNIX_SOCKETS)
 +  include(CheckStructHasMember)
 +  check_struct_has_member("struct sockaddr_un" sun_path "sys/un.h" USE_UNIX_SOCKETS)
 +else()
 +  unset(USE_UNIX_SOCKETS CACHE)
 +endif()
 +
 +
 +# Check for header files
 +if(NOT UNIX)
 +  check_include_file_concat("windows.h"      HAVE_WINDOWS_H)
 +  check_include_file_concat("winsock.h"      HAVE_WINSOCK_H)
 +  check_include_file_concat("ws2tcpip.h"     HAVE_WS2TCPIP_H)
 +  check_include_file_concat("winsock2.h"     HAVE_WINSOCK2_H)
 +  if(CURL_WINDOWS_SSPI)
 +    set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DSECURITY_WIN32")
 +    check_include_file_concat("sspi.h"       HAVE_SSPI_H)
 +    if(HAVE_SSPI_H)
 +      check_include_file_concat("schannel.h" HAVE_SCHANNEL_H)
 +      set(USE_WINDOWS_SSPI ON)
 +      if(HAVE_SCHANNEL_H)
 +        set(USE_SCHANNEL ON)
 +        set(SSL_ENABLED ON)
 +        set(CURL_LIBS ${CURL_LIBS} "crypt32")
 +      endif()
 +    endif()
 +  endif()
 +else()
 +  set(HAVE_WINDOWS_H 0)
 +  set(HAVE_WINSOCK_H 0)
 +  set(HAVE_WS2TCPIP_H 0)
 +  set(HAVE_WINSOCK2_H 0)
 +endif()
 +
 +check_include_file_concat("stdio.h"          HAVE_STDIO_H)
 +check_include_file_concat("inttypes.h"       HAVE_INTTYPES_H)
 +check_include_file_concat("sys/filio.h"      HAVE_SYS_FILIO_H)
 +check_include_file_concat("sys/ioctl.h"      HAVE_SYS_IOCTL_H)
 +check_include_file_concat("sys/param.h"      HAVE_SYS_PARAM_H)
 +check_include_file_concat("sys/poll.h"       HAVE_SYS_POLL_H)
 +check_include_file_concat("sys/resource.h"   HAVE_SYS_RESOURCE_H)
 +check_include_file_concat("sys/select.h"     HAVE_SYS_SELECT_H)
 +check_include_file_concat("sys/socket.h"     HAVE_SYS_SOCKET_H)
 +check_include_file_concat("sys/sockio.h"     HAVE_SYS_SOCKIO_H)
 +check_include_file_concat("sys/stat.h"       HAVE_SYS_STAT_H)
 +check_include_file_concat("sys/time.h"       HAVE_SYS_TIME_H)
 +check_include_file_concat("sys/types.h"      HAVE_SYS_TYPES_H)
 +check_include_file_concat("sys/uio.h"        HAVE_SYS_UIO_H)
 +check_include_file_concat("sys/un.h"         HAVE_SYS_UN_H)
 +check_include_file_concat("sys/utime.h"      HAVE_SYS_UTIME_H)
 +check_include_file_concat("alloca.h"         HAVE_ALLOCA_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("crypto.h"         HAVE_CRYPTO_H)
 +check_include_file_concat("des.h"            HAVE_DES_H)
 +check_include_file_concat("err.h"            HAVE_ERR_H)
 +check_include_file_concat("errno.h"          HAVE_ERRNO_H)
 +check_include_file_concat("fcntl.h"          HAVE_FCNTL_H)
 +check_include_file_concat("idn2.h"           HAVE_IDN2_H)
 +check_include_file_concat("ifaddrs.h"        HAVE_IFADDRS_H)
 +check_include_file_concat("io.h"             HAVE_IO_H)
 +check_include_file_concat("krb.h"            HAVE_KRB_H)
 +check_include_file_concat("libgen.h"         HAVE_LIBGEN_H)
 +check_include_file_concat("limits.h"         HAVE_LIMITS_H)
 +check_include_file_concat("locale.h"         HAVE_LOCALE_H)
 +check_include_file_concat("net/if.h"         HAVE_NET_IF_H)
 +check_include_file_concat("netdb.h"          HAVE_NETDB_H)
 +check_include_file_concat("netinet/in.h"     HAVE_NETINET_IN_H)
 +check_include_file_concat("netinet/tcp.h"    HAVE_NETINET_TCP_H)
 +
 +check_include_file_concat("pem.h"            HAVE_PEM_H)
 +check_include_file_concat("poll.h"           HAVE_POLL_H)
 +check_include_file_concat("pwd.h"            HAVE_PWD_H)
 +check_include_file_concat("rsa.h"            HAVE_RSA_H)
 +check_include_file_concat("setjmp.h"         HAVE_SETJMP_H)
 +check_include_file_concat("sgtty.h"          HAVE_SGTTY_H)
 +check_include_file_concat("signal.h"         HAVE_SIGNAL_H)
 +check_include_file_concat("ssl.h"            HAVE_SSL_H)
 +check_include_file_concat("stdbool.h"        HAVE_STDBOOL_H)
 +check_include_file_concat("stdint.h"         HAVE_STDINT_H)
 +check_include_file_concat("stdio.h"          HAVE_STDIO_H)
 +check_include_file_concat("stdlib.h"         HAVE_STDLIB_H)
 +check_include_file_concat("string.h"         HAVE_STRING_H)
 +check_include_file_concat("strings.h"        HAVE_STRINGS_H)
 +check_include_file_concat("stropts.h"        HAVE_STROPTS_H)
 +check_include_file_concat("termio.h"         HAVE_TERMIO_H)
 +check_include_file_concat("termios.h"        HAVE_TERMIOS_H)
 +check_include_file_concat("time.h"           HAVE_TIME_H)
 +check_include_file_concat("unistd.h"         HAVE_UNISTD_H)
 +check_include_file_concat("utime.h"          HAVE_UTIME_H)
 +check_include_file_concat("x509.h"           HAVE_X509_H)
 +
 +check_include_file_concat("process.h"        HAVE_PROCESS_H)
 +check_include_file_concat("stddef.h"         HAVE_STDDEF_H)
 +check_include_file_concat("dlfcn.h"          HAVE_DLFCN_H)
 +check_include_file_concat("malloc.h"         HAVE_MALLOC_H)
 +check_include_file_concat("memory.h"         HAVE_MEMORY_H)
 +check_include_file_concat("netinet/if_ether.h" HAVE_NETINET_IF_ETHER_H)
 +check_include_file_concat("stdint.h"        HAVE_STDINT_H)
 +check_include_file_concat("sockio.h"        HAVE_SOCKIO_H)
 +check_include_file_concat("sys/utsname.h"   HAVE_SYS_UTSNAME_H)
 +
 +check_type_size(size_t  SIZEOF_SIZE_T)
 +check_type_size(ssize_t  SIZEOF_SSIZE_T)
 +check_type_size("long long"  SIZEOF_LONG_LONG)
 +check_type_size("long"  SIZEOF_LONG)
 +check_type_size("short"  SIZEOF_SHORT)
 +check_type_size("int"  SIZEOF_INT)
 +check_type_size("__int64"  SIZEOF___INT64)
 +check_type_size("time_t"  SIZEOF_TIME_T)
 +
 +# Make public versions of some type sizes for curlbuild.h.
 +foreach(t INT LONG LONG_LONG SSIZE_T)
 +  string(REPLACE "SIZEOF_" "CURL_SIZEOF_" CURL_SIZEOF_${t}_CODE "${SIZEOF_${t}_CODE}")
 +endforeach()
 +
 +if(HAVE_SIZEOF_LONG_LONG)
 +  set(HAVE_LONGLONG 1)
 +  set(HAVE_LL 1)
 +endif(HAVE_SIZEOF_LONG_LONG)
 +
 +find_file(RANDOM_FILE urandom /dev)
 +mark_as_advanced(RANDOM_FILE)
 +
 +# Check for some functions that are used
 +if(HAVE_LIBWS2_32)
 +  set(CMAKE_REQUIRED_LIBRARIES ws2_32)
 +elseif(HAVE_LIBSOCKET)
 +  set(CMAKE_REQUIRED_LIBRARIES socket)
 +endif()
 +
 +check_symbol_exists(basename      "${CURL_INCLUDES}" HAVE_BASENAME)
 +check_symbol_exists(socket        "${CURL_INCLUDES}" HAVE_SOCKET)
- check_symbol_exists(poll          "${CURL_INCLUDES}" HAVE_POLL)
++# poll on macOS is unreliable, it first did not exist, then was broken until
++# fixed in 10.9 only to break again in 10.12.
++if(NOT APPLE)
++  check_symbol_exists(poll        "${CURL_INCLUDES}" HAVE_POLL)
++endif()
 +check_symbol_exists(select        "${CURL_INCLUDES}" HAVE_SELECT)
 +check_symbol_exists(strdup        "${CURL_INCLUDES}" HAVE_STRDUP)
 +check_symbol_exists(strstr        "${CURL_INCLUDES}" HAVE_STRSTR)
 +check_symbol_exists(strtok_r      "${CURL_INCLUDES}" HAVE_STRTOK_R)
 +check_symbol_exists(strftime      "${CURL_INCLUDES}" HAVE_STRFTIME)
 +check_symbol_exists(uname         "${CURL_INCLUDES}" HAVE_UNAME)
 +check_symbol_exists(strcasecmp    "${CURL_INCLUDES}" HAVE_STRCASECMP)
 +check_symbol_exists(stricmp       "${CURL_INCLUDES}" HAVE_STRICMP)
 +check_symbol_exists(strcmpi       "${CURL_INCLUDES}" HAVE_STRCMPI)
 +check_symbol_exists(strncmpi      "${CURL_INCLUDES}" HAVE_STRNCMPI)
 +check_symbol_exists(alarm         "${CURL_INCLUDES}" HAVE_ALARM)
 +if(NOT HAVE_STRNCMPI)
 +  set(HAVE_STRCMPI)
 +endif(NOT HAVE_STRNCMPI)
 +check_symbol_exists(gethostbyaddr "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR)
 +check_symbol_exists(gethostbyaddr_r "${CURL_INCLUDES}" HAVE_GETHOSTBYADDR_R)
 +check_symbol_exists(gettimeofday  "${CURL_INCLUDES}" HAVE_GETTIMEOFDAY)
 +check_symbol_exists(inet_addr     "${CURL_INCLUDES}" HAVE_INET_ADDR)
 +check_symbol_exists(inet_ntoa     "${CURL_INCLUDES}" HAVE_INET_NTOA)
 +check_symbol_exists(inet_ntoa_r   "${CURL_INCLUDES}" HAVE_INET_NTOA_R)
 +check_symbol_exists(tcsetattr     "${CURL_INCLUDES}" HAVE_TCSETATTR)
 +check_symbol_exists(tcgetattr     "${CURL_INCLUDES}" HAVE_TCGETATTR)
 +check_symbol_exists(perror        "${CURL_INCLUDES}" HAVE_PERROR)
 +check_symbol_exists(closesocket   "${CURL_INCLUDES}" HAVE_CLOSESOCKET)
 +check_symbol_exists(setvbuf       "${CURL_INCLUDES}" HAVE_SETVBUF)
 +check_symbol_exists(sigsetjmp     "${CURL_INCLUDES}" HAVE_SIGSETJMP)
 +check_symbol_exists(getpass_r     "${CURL_INCLUDES}" HAVE_GETPASS_R)
 +check_symbol_exists(strlcat       "${CURL_INCLUDES}" HAVE_STRLCAT)
 +check_symbol_exists(getpwuid      "${CURL_INCLUDES}" HAVE_GETPWUID)
 +check_symbol_exists(geteuid       "${CURL_INCLUDES}" HAVE_GETEUID)
 +check_symbol_exists(utime         "${CURL_INCLUDES}" HAVE_UTIME)
 +if(CMAKE_USE_OPENSSL)
 +  check_symbol_exists(RAND_status   "${CURL_INCLUDES}" HAVE_RAND_STATUS)
 +  check_symbol_exists(RAND_screen   "${CURL_INCLUDES}" HAVE_RAND_SCREEN)
 +  check_symbol_exists(RAND_egd      "${CURL_INCLUDES}" HAVE_RAND_EGD)
 +  if(HAVE_LIBCRYPTO AND HAVE_LIBSSL)
 +    set(USE_OPENSSL 1)
 +  endif(HAVE_LIBCRYPTO AND HAVE_LIBSSL)
 +endif(CMAKE_USE_OPENSSL)
 +check_symbol_exists(gmtime_r      "${CURL_INCLUDES}" HAVE_GMTIME_R)
 +check_symbol_exists(localtime_r   "${CURL_INCLUDES}" HAVE_LOCALTIME_R)
 +
 +check_symbol_exists(gethostbyname   "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME)
 +check_symbol_exists(gethostbyname_r "${CURL_INCLUDES}" HAVE_GETHOSTBYNAME_R)
 +
 +check_symbol_exists(signal        "${CURL_INCLUDES}" HAVE_SIGNAL_FUNC)
 +check_symbol_exists(SIGALRM       "${CURL_INCLUDES}" HAVE_SIGNAL_MACRO)
 +if(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
 +  set(HAVE_SIGNAL 1)
 +endif(HAVE_SIGNAL_FUNC AND HAVE_SIGNAL_MACRO)
 +check_symbol_exists(uname          "${CURL_INCLUDES}" HAVE_UNAME)
 +check_symbol_exists(strtoll        "${CURL_INCLUDES}" HAVE_STRTOLL)
 +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(perror         "${CURL_INCLUDES}" HAVE_PERROR)
 +check_symbol_exists(fork           "${CURL_INCLUDES}" HAVE_FORK)
 +check_symbol_exists(getaddrinfo    "${CURL_INCLUDES}" HAVE_GETADDRINFO)
 +check_symbol_exists(freeaddrinfo   "${CURL_INCLUDES}" HAVE_FREEADDRINFO)
 +check_symbol_exists(freeifaddrs    "${CURL_INCLUDES}" HAVE_FREEIFADDRS)
 +check_symbol_exists(pipe           "${CURL_INCLUDES}" HAVE_PIPE)
 +check_symbol_exists(ftruncate      "${CURL_INCLUDES}" HAVE_FTRUNCATE)
 +check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
 +check_symbol_exists(getrlimit      "${CURL_INCLUDES}" HAVE_GETRLIMIT)
 +check_symbol_exists(setlocale      "${CURL_INCLUDES}" HAVE_SETLOCALE)
 +check_symbol_exists(setrlimit      "${CURL_INCLUDES}" HAVE_SETRLIMIT)
 +check_symbol_exists(fcntl          "${CURL_INCLUDES}" HAVE_FCNTL)
 +check_symbol_exists(ioctl          "${CURL_INCLUDES}" HAVE_IOCTL)
 +check_symbol_exists(setsockopt     "${CURL_INCLUDES}" HAVE_SETSOCKOPT)
 +
 +# symbol exists in win32, but function does not.
 +check_function_exists(inet_pton HAVE_INET_PTON)
 +
 +# sigaction and sigsetjmp are special. Use special mechanism for
 +# detecting those, but only if previous attempt failed.
 +if(HAVE_SIGNAL_H)
 +  check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION)
 +endif(HAVE_SIGNAL_H)
 +
 +if(NOT HAVE_SIGSETJMP)
 +  if(HAVE_SETJMP_H)
 +    check_symbol_exists(sigsetjmp "setjmp.h" HAVE_MACRO_SIGSETJMP)
 +    if(HAVE_MACRO_SIGSETJMP)
 +      set(HAVE_SIGSETJMP 1)
 +    endif(HAVE_MACRO_SIGSETJMP)
 +  endif(HAVE_SETJMP_H)
 +endif(NOT HAVE_SIGSETJMP)
 +
 +# If there is no stricmp(), do not allow LDAP to parse URLs
 +if(NOT HAVE_STRICMP)
 +  set(HAVE_LDAP_URL_PARSE 1)
 +endif(NOT HAVE_STRICMP)
 +
 +# Do curl specific tests
 +foreach(CURL_TEST
 +    HAVE_FCNTL_O_NONBLOCK
 +    HAVE_IOCTLSOCKET
 +    HAVE_IOCTLSOCKET_CAMEL
 +    HAVE_IOCTLSOCKET_CAMEL_FIONBIO
 +    HAVE_IOCTLSOCKET_FIONBIO
 +    HAVE_IOCTL_FIONBIO
 +    HAVE_IOCTL_SIOCGIFADDR
 +    HAVE_SETSOCKOPT_SO_NONBLOCK
 +    HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
 +    TIME_WITH_SYS_TIME
 +    HAVE_O_NONBLOCK
 +    HAVE_GETHOSTBYADDR_R_5
 +    HAVE_GETHOSTBYADDR_R_7
 +    HAVE_GETHOSTBYADDR_R_8
 +    HAVE_GETHOSTBYADDR_R_5_REENTRANT
 +    HAVE_GETHOSTBYADDR_R_7_REENTRANT
 +    HAVE_GETHOSTBYADDR_R_8_REENTRANT
 +    HAVE_GETHOSTBYNAME_R_3
 +    HAVE_GETHOSTBYNAME_R_5
 +    HAVE_GETHOSTBYNAME_R_6
 +    HAVE_GETHOSTBYNAME_R_3_REENTRANT
 +    HAVE_GETHOSTBYNAME_R_5_REENTRANT
 +    HAVE_GETHOSTBYNAME_R_6_REENTRANT
 +    HAVE_SOCKLEN_T
 +    HAVE_IN_ADDR_T
 +    HAVE_BOOL_T
 +    STDC_HEADERS
 +    RETSIGTYPE_TEST
 +    HAVE_INET_NTOA_R_DECL
 +    HAVE_INET_NTOA_R_DECL_REENTRANT
 +    HAVE_GETADDRINFO
 +    HAVE_FILE_OFFSET_BITS
 +    )
 +  curl_internal_test(${CURL_TEST})
 +endforeach(CURL_TEST)
 +
 +if(HAVE_FILE_OFFSET_BITS)
 +  set(_FILE_OFFSET_BITS 64)
 +  set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
 +endif(HAVE_FILE_OFFSET_BITS)
 +check_type_size("off_t"  SIZEOF_OFF_T)
 +set(CMAKE_REQUIRED_FLAGS)
 +
 +foreach(CURL_TEST
 +    HAVE_GLIBC_STRERROR_R
 +    HAVE_POSIX_STRERROR_R
 +    )
 +  curl_internal_test_run(${CURL_TEST})
 +endforeach(CURL_TEST)
 +
 +# Check for reentrant
 +foreach(CURL_TEST
 +    HAVE_GETHOSTBYADDR_R_5
 +    HAVE_GETHOSTBYADDR_R_7
 +    HAVE_GETHOSTBYADDR_R_8
 +    HAVE_GETHOSTBYNAME_R_3
 +    HAVE_GETHOSTBYNAME_R_5
 +    HAVE_GETHOSTBYNAME_R_6
 +    HAVE_INET_NTOA_R_DECL_REENTRANT)
 +  if(NOT ${CURL_TEST})
 +    if(${CURL_TEST}_REENTRANT)
 +      set(NEED_REENTRANT 1)
 +    endif(${CURL_TEST}_REENTRANT)
 +  endif(NOT ${CURL_TEST})
 +endforeach(CURL_TEST)
 +
 +if(NEED_REENTRANT)
 +  foreach(CURL_TEST
 +      HAVE_GETHOSTBYADDR_R_5
 +      HAVE_GETHOSTBYADDR_R_7
 +      HAVE_GETHOSTBYADDR_R_8
 +      HAVE_GETHOSTBYNAME_R_3
 +      HAVE_GETHOSTBYNAME_R_5
 +      HAVE_GETHOSTBYNAME_R_6)
 +    set(${CURL_TEST} 0)
 +    if(${CURL_TEST}_REENTRANT)
 +      set(${CURL_TEST} 1)
 +    endif(${CURL_TEST}_REENTRANT)
 +  endforeach(CURL_TEST)
 +endif(NEED_REENTRANT)
 +
 +if(HAVE_INET_NTOA_R_DECL_REENTRANT)
 +  set(HAVE_INET_NTOA_R_DECL 1)
 +  set(NEED_REENTRANT 1)
 +endif(HAVE_INET_NTOA_R_DECL_REENTRANT)
 +
 +# Some other minor tests
 +
 +if(NOT HAVE_IN_ADDR_T)
 +  set(in_addr_t "unsigned long")
 +endif(NOT HAVE_IN_ADDR_T)
 +
 +# Fix libz / zlib.h
 +
 +if(NOT CURL_SPECIAL_LIBZ)
 +  if(NOT HAVE_LIBZ)
 +    set(HAVE_ZLIB_H 0)
 +  endif(NOT HAVE_LIBZ)
 +
 +  if(NOT HAVE_ZLIB_H)
 +    set(HAVE_LIBZ 0)
 +  endif(NOT HAVE_ZLIB_H)
 +endif(NOT CURL_SPECIAL_LIBZ)
 +
 +# Check for nonblocking
 +set(HAVE_DISABLED_NONBLOCKING 1)
 +if(HAVE_FIONBIO OR
 +    HAVE_IOCTLSOCKET OR
 +    HAVE_IOCTLSOCKET_CASE OR
 +    HAVE_O_NONBLOCK)
 +  set(HAVE_DISABLED_NONBLOCKING)
 +endif(HAVE_FIONBIO OR
 +  HAVE_IOCTLSOCKET OR
 +  HAVE_IOCTLSOCKET_CASE OR
 +  HAVE_O_NONBLOCK)
 +
 +if(RETSIGTYPE_TEST)
 +  set(RETSIGTYPE void)
 +else(RETSIGTYPE_TEST)
 +  set(RETSIGTYPE int)
 +endif(RETSIGTYPE_TEST)
 +
 +if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
 +  include(CheckCCompilerFlag)
 +  check_c_compiler_flag(-Wno-long-double HAVE_C_FLAG_Wno_long_double)
 +  if(HAVE_C_FLAG_Wno_long_double)
 +    # The Mac version of GCC warns about use of long double.  Disable it.
 +    get_source_file_property(MPRINTF_COMPILE_FLAGS mprintf.c COMPILE_FLAGS)
 +    if(MPRINTF_COMPILE_FLAGS)
 +      set(MPRINTF_COMPILE_FLAGS "${MPRINTF_COMPILE_FLAGS} -Wno-long-double")
 +    else(MPRINTF_COMPILE_FLAGS)
 +      set(MPRINTF_COMPILE_FLAGS "-Wno-long-double")
 +    endif(MPRINTF_COMPILE_FLAGS)
 +    set_source_files_properties(mprintf.c PROPERTIES
 +      COMPILE_FLAGS ${MPRINTF_COMPILE_FLAGS})
 +  endif(HAVE_C_FLAG_Wno_long_double)
 +endif(CMAKE_COMPILER_IS_GNUCC AND APPLE)
 +
 +if(HAVE_SOCKLEN_T)
 +  set(CURL_HAVE_SOCKLEN_T 1)
 +  set(CURL_TYPEOF_CURL_SOCKLEN_T "socklen_t")
 +  if(WIN32)
 +    set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h;ws2tcpip.h")
 +  elseif(HAVE_SYS_SOCKET_H)
 +    set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
 +  endif()
 +  check_type_size("socklen_t" CURL_SIZEOF_CURL_SOCKLEN_T)
 +  set(CMAKE_EXTRA_INCLUDE_FILES)
 +  if(NOT HAVE_CURL_SIZEOF_CURL_SOCKLEN_T)
 +    message(FATAL_ERROR
 +     "Check for sizeof socklen_t failed, see CMakeFiles/CMakerror.log")
 +  endif()
 +else()
 +  set(CURL_HAVE_SOCKLEN_T 0)
 +endif()
 +
 +# TODO test which of these headers are required for the typedefs used in curlbuild.h
 +if(WIN32)
 +  set(CURL_PULL_WS2TCPIP_H ${HAVE_WS2TCPIP_H})
 +else()
 +  set(CURL_PULL_SYS_TYPES_H ${HAVE_SYS_TYPES_H})
 +  set(CURL_PULL_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H})
 +  set(CURL_PULL_SYS_POLL_H ${HAVE_SYS_POLL_H})
 +endif()
 +set(CURL_PULL_STDINT_H ${HAVE_STDINT_H})
 +set(CURL_PULL_INTTYPES_H ${HAVE_INTTYPES_H})
 +
 +include(CMake/OtherTests.cmake)
 +
 +add_definitions(-DHAVE_CONFIG_H)
 +
 +# For windows, do not allow the compiler to use default target (Vista).
 +if(WIN32)
 +  add_definitions(-D_WIN32_WINNT=0x0501)
 +endif(WIN32)
 +
 +# For windows, all compilers used by cmake should support large files
 +if(WIN32)
 +  set(USE_WIN32_LARGE_FILES ON)
 +endif(WIN32)
 +
 +if(MSVC)
 +  add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
 +endif(MSVC)
 +
 +# Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it).
 +function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
 +  file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT)
 +  string(REPLACE "$(top_srcdir)"   "\${CURL_SOURCE_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
 +  string(REPLACE "$(top_builddir)" "\${CURL_BINARY_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
 +
 +  string(REGEX REPLACE "\\\\\n" "§!§" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
 +  string(REGEX REPLACE "([a-zA-Z_][a-zA-Z0-9_]*)[\t ]*=[\t ]*([^\n]*)" "SET(\\1 \\2)" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
 +  string(REPLACE "§!§" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
 +
 +  string(REGEX REPLACE "\\$\\(([a-zA-Z_][a-zA-Z0-9_]*)\\)" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})    # Replace $() with ${}
 +  string(REGEX REPLACE "@([a-zA-Z_][a-zA-Z0-9_]*)@" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})    # Replace @@ with ${}, even if that may not be read by CMake scripts.
 +  file(WRITE ${OUTPUT_FILE} ${MAKEFILE_INC_TEXT})
 +
 +endfunction()
 +
 +add_subdirectory(lib)
 +if(BUILD_CURL_EXE)
 +  add_subdirectory(src)
 +endif()
 +
 +#-----------------------------------------------------------------------------
 +# CMake-specific curl code.
 +add_executable(LIBCURL curltest.c)
 +target_link_libraries(LIBCURL cmcurl)
 +
 +if(CMAKE_CURL_TEST_URL)
 +  add_test(curl LIBCURL ${CMAKE_CURL_TEST_URL})
 +endif()
 +
 +install(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmcurl)
 +#-----------------------------------------------------------------------------
 +
 +if(0) # This code not needed for building within CMake.
 +include(CTest)
 +if(BUILD_TESTING)
 +  add_subdirectory(tests)
 +endif()
 +
 +# TODO support GNUTLS, NSS, POLARSSL, AXTLS, CYASSL, WINSSL, DARWINSSL
 +if(USE_OPENSSL)
 +  set(SSL_ENABLED 1)
 +endif()
 +
 +# Helper to populate a list (_items) with a label when conditions (the remaining
 +# args) are satisfied
 +function(_add_if label)
 +  # TODO need to disable policy CMP0054 (CMake 3.1) to allow this indirection
 +  if(${ARGN})
 +    set(_items ${_items} "${label}" PARENT_SCOPE)
 +  endif()
 +endfunction()
 +
 +# Clear list and try to detect available features
 +set(_items)
 +_add_if("WinSSL"        SSL_ENABLED AND USE_WINDOWS_SSPI)
 +_add_if("OpenSSL"       SSL_ENABLED AND USE_OPENSSL)
 +_add_if("IPv6"          ENABLE_IPV6)
 +_add_if("unix-sockets"  USE_UNIX_SOCKETS)
 +_add_if("libz"          HAVE_LIBZ)
 +_add_if("AsynchDNS"     USE_ARES OR USE_THREADS_POSIX OR USE_THREADS_WIN32)
 +_add_if("IDN"           HAVE_LIBIDN2)
 +_add_if("Largefile"     (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND
 +                        ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES))
 +# TODO SSP1 (WinSSL) check is missing
 +_add_if("SSPI"          USE_WINDOWS_SSPI)
 +_add_if("GSS-API"       HAVE_GSSAPI)
 +# TODO SSP1 missing for SPNEGO
 +_add_if("SPNEGO"        NOT CURL_DISABLE_CRYPTO_AUTH AND
 +                        (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
 +_add_if("Kerberos"      NOT CURL_DISABLE_CRYPTO_AUTH AND
 +                        (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
 +# NTLM support requires crypto function adaptions from various SSL libs
 +# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS, DARWINSSL
 +if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR
 +   USE_WINDOWS_SSPI OR GNUTLS_ENABLED OR NSS_ENABLED OR DARWINSSL_ENABLED))
 +  _add_if("NTLM"        1)
 +  # TODO missing option (autoconf: --enable-ntlm-wb)
 +  _add_if("NTLM_WB"     NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
 +endif()
 +# TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP
 +_add_if("TLS-SRP"       USE_TLS_SRP)
 +# TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header
 +_add_if("HTTP2"         USE_NGHTTP2)
 +string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
 +message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
 +
 +# Clear list and try to detect available protocols
 +set(_items)
 +_add_if("HTTP"          NOT CURL_DISABLE_HTTP)
 +_add_if("HTTPS"         NOT CURL_DISABLE_HTTP AND SSL_ENABLED)
 +_add_if("FTP"           NOT CURL_DISABLE_FTP)
 +_add_if("FTPS"          NOT CURL_DISABLE_FTP AND SSL_ENABLED)
 +_add_if("FILE"          NOT CURL_DISABLE_FILE)
 +_add_if("TELNET"        NOT CURL_DISABLE_TELNET)
 +_add_if("LDAP"          NOT CURL_DISABLE_LDAP)
 +# CURL_DISABLE_LDAP implies CURL_DISABLE_LDAPS
 +# TODO check HAVE_LDAP_SSL (in autoconf this is enabled with --enable-ldaps)
 +_add_if("LDAPS"         NOT CURL_DISABLE_LDAPS AND
 +                        ((USE_OPENLDAP AND SSL_ENABLED) OR
 +                        (NOT USE_OPENLDAP AND HAVE_LDAP_SSL)))
 +_add_if("DICT"          NOT CURL_DISABLE_DICT)
 +_add_if("TFTP"          NOT CURL_DISABLE_TFTP)
 +_add_if("GOPHER"        NOT CURL_DISABLE_GOPHER)
 +_add_if("POP3"          NOT CURL_DISABLE_POP3)
 +_add_if("POP3S"         NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
 +_add_if("IMAP"          NOT CURL_DISABLE_IMAP)
 +_add_if("IMAPS"         NOT CURL_DISABLE_IMAP AND SSL_ENABLED)
 +_add_if("SMTP"          NOT CURL_DISABLE_SMTP)
 +_add_if("SMTPS"         NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
 +_add_if("SCP"           USE_LIBSSH2)
 +_add_if("SFTP"          USE_LIBSSH2)
 +_add_if("RTSP"          NOT CURL_DISABLE_RTSP)
 +_add_if("RTMP"          USE_LIBRTMP)
 +list(SORT _items)
 +string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}")
 +message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
 +
 +# curl-config needs the following options to be set.
 +set(CC                      "${CMAKE_C_COMPILER}")
 +# TODO probably put a -D... options here?
 +set(CONFIGURE_OPTIONS       "")
 +# TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB?
 +set(CPPFLAG_CURL_STATICLIB  "")
 +# TODO need to set this (see CURL_CHECK_CA_BUNDLE in acinclude.m4)
 +set(CURL_CA_BUNDLE          "")
 +set(CURLVERSION             "${CURL_VERSION}")
 +set(ENABLE_SHARED           "yes")
 +if(CURL_STATICLIB)
 +  set(ENABLE_STATIC         "yes")
 +else()
 +  set(ENABLE_STATIC         "no")
 +endif()
 +set(exec_prefix             "\${prefix}")
 +set(includedir              "\${prefix}/include")
 +set(LDFLAGS                 "${CMAKE_SHARED_LINKER_FLAGS}")
 +set(LIBCURL_LIBS            "")
 +set(libdir                  "${CMAKE_INSTALL_PREFIX}/lib")
 +foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS})
 +  if(_lib MATCHES ".*/.*")
 +    set(LIBCURL_LIBS          "${LIBCURL_LIBS} ${_lib}")
 +  else()
 +    set(LIBCURL_LIBS          "${LIBCURL_LIBS} -l${_lib}")
 +  endif()
 +endforeach()
 +# "a" (Linux) or "lib" (Windows)
 +string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
 +set(prefix                  "${CMAKE_INSTALL_PREFIX}")
 +# Set this to "yes" to append all libraries on which -lcurl is dependent
 +set(REQUIRE_LIB_DEPS        "no")
 +# SUPPORT_FEATURES
 +# SUPPORT_PROTOCOLS
 +set(VERSIONNUM              "${CURL_VERSION_NUM}")
 +
 +# Finally generate a "curl-config" matching this config
 +configure_file("${CURL_SOURCE_DIR}/curl-config.in"
 +               "${CURL_BINARY_DIR}/curl-config" @ONLY)
 +install(FILES "${CURL_BINARY_DIR}/curl-config"
 +        DESTINATION bin
 +        PERMISSIONS
 +          OWNER_READ OWNER_WRITE OWNER_EXECUTE
 +          GROUP_READ GROUP_EXECUTE
 +          WORLD_READ WORLD_EXECUTE)
 +
 +# Finally generate a pkg-config file matching this config
 +configure_file("${CURL_SOURCE_DIR}/libcurl.pc.in"
 +               "${CURL_BINARY_DIR}/libcurl.pc" @ONLY)
 +install(FILES "${CURL_BINARY_DIR}/libcurl.pc"
 +        DESTINATION lib/pkgconfig)
 +
 +# This needs to be run very last so other parts of the scripts can take advantage of this.
 +if(NOT CURL_CONFIG_HAS_BEEN_RUN_BEFORE)
 +  set(CURL_CONFIG_HAS_BEEN_RUN_BEFORE 1 CACHE INTERNAL "Flag to track whether this is the first time running CMake or if CMake has been configured before")
 +endif()
 +
 +# Installation.
 +# First, install generated curlbuild.h
 +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/curl/curlbuild.h"
 +    DESTINATION include/curl )
 +# Next, install other headers excluding curlbuild.h
 +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/curl"
 +    DESTINATION include
 +    FILES_MATCHING PATTERN "*.h"
 +    PATTERN "curlbuild.h" EXCLUDE)
 +
 +
 +# Workaround for MSVS10 to avoid the Dialog Hell
 +# FIXME: This could be removed with future version of CMake.
 +if(MSVC_VERSION EQUAL 1600)
 +  set(CURL_SLN_FILENAME "${CMAKE_CURRENT_BINARY_DIR}/CURL.sln")
 +  if(EXISTS "${CURL_SLN_FILENAME}")
 +    file(APPEND "${CURL_SLN_FILENAME}" "\n# This should be regenerated!\n")
 +  endif()
 +endif()
 +endif()
diff --cc Utilities/cmcurl/include/curl/curl.h
index aa1034b,0000000..daca8d1
mode 100644,000000..100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@@ -1,2456 -1,0 +1,2530 @@@
 +#ifndef __CURL_CURL_H
 +#define __CURL_CURL_H
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
 + * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
 + *
 + * This software is licensed as described in the file COPYING, which
 + * you should have received as part of this distribution. The terms
 + * are also available at https://curl.haxx.se/docs/copyright.html.
 + *
 + * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 + * copies of the Software, and permit persons to whom the Software is
 + * furnished to do so, under the terms of the COPYING file.
 + *
 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 + * KIND, either express or implied.
 + *
 + ***************************************************************************/
 +
 +/*
 + * If you have libcurl problems, all docs and details are found here:
 + *   https://curl.haxx.se/libcurl/
 + *
 + * curl-library mailing list subscription and unsubscription web interface:
 + *   https://cool.haxx.se/mailman/listinfo/curl-library/
 + */
 +
 +#ifdef CURL_NO_OLDIES
 +#define CURL_STRICTER
 +#endif
 +
 +#include "curlver.h"         /* libcurl version defines   */
 +#include "cmcurl/include/curl/curlbuild.h" /* libcurl build definitions */
 +#include "curlrules.h"       /* libcurl rules enforcement */
 +
 +/*
 + * Define WIN32 when build target is Win32 API
 + */
 +
 +#if (defined(_WIN32) || defined(__WIN32__)) && \
 +     !defined(WIN32) && !defined(__SYMBIAN32__)
 +#define WIN32
 +#endif
 +
 +#include <stdio.h>
 +#include <limits.h>
 +
 +#if defined(__FreeBSD__) && (__FreeBSD__ >= 2)
 +/* Needed for __FreeBSD_version symbol definition */
 +#include <osreldate.h>
 +#endif
 +
 +/* The include stuff here below is mainly for time_t! */
 +#include <sys/types.h>
 +#include <time.h>
 +
 +#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
 +#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \
 +      defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H))
 +/* The check above prevents the winsock2 inclusion if winsock.h already was
 +   included, since they can't co-exist without problems */
 +#include <winsock2.h>
 +#include <ws2tcpip.h>
 +#endif
 +#endif
 +
 +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish
 +   libc5-based Linux systems. Only include it on systems that are known to
 +   require it! */
 +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
 +    defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
 +    defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
 +   (defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
 +#include <sys/select.h>
 +#endif
 +
 +#if !defined(WIN32) && !defined(_WIN32_WCE)
 +#include <sys/socket.h>
 +#endif
 +
 +#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__)
 +#include <sys/time.h>
 +#endif
 +
 +#if defined __BEOS__ || defined __HAIKU__
 +#include <support/SupportDefs.h>
 +#endif
 +
 +#ifdef  __cplusplus
 +extern "C" {
 +#endif
 +
 +#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
 +typedef struct Curl_easy CURL;
 +typedef struct Curl_share CURLSH;
 +#else
 +typedef void CURL;
 +typedef void CURLSH;
 +#endif
 +
 +/*
 + * libcurl external API function linkage decorations.
 + */
 +
 +#ifdef CURL_STATICLIB
 +#  define CURL_EXTERN
 +#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)
 +#  if defined(BUILDING_LIBCURL)
 +#    define CURL_EXTERN  __declspec(dllexport)
 +#  else
 +#    define CURL_EXTERN  __declspec(dllimport)
 +#  endif
 +#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS)
 +#  define CURL_EXTERN CURL_EXTERN_SYMBOL
 +#else
 +#  define CURL_EXTERN
 +#endif
 +
 +#ifndef curl_socket_typedef
 +/* socket typedef */
 +#if defined(WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
 +typedef SOCKET curl_socket_t;
 +#define CURL_SOCKET_BAD INVALID_SOCKET
 +#else
 +typedef int curl_socket_t;
 +#define CURL_SOCKET_BAD -1
 +#endif
 +#define curl_socket_typedef
 +#endif /* curl_socket_typedef */
 +
 +struct curl_httppost {
 +  struct curl_httppost *next;       /* next entry in the list */
 +  char *name;                       /* pointer to allocated name */
 +  long namelength;                  /* length of name length */
 +  char *contents;                   /* pointer to allocated data contents */
 +  long contentslength;              /* length of contents field, see also
 +                                       CURL_HTTPPOST_LARGE */
 +  char *buffer;                     /* pointer to allocated buffer contents */
 +  long bufferlength;                /* length of buffer field */
 +  char *contenttype;                /* Content-Type */
-   struct curl_slist* contentheader; /* list of extra headers for this form */
++  struct curl_slist *contentheader; /* list of extra headers for this form */
 +  struct curl_httppost *more;       /* if one field name has more than one
 +                                       file, this link should link to following
 +                                       files */
 +  long flags;                       /* as defined below */
 +
 +/* specified content is a file name */
 +#define CURL_HTTPPOST_FILENAME (1<<0)
 +/* specified content is a file name */
 +#define CURL_HTTPPOST_READFILE (1<<1)
 +/* name is only stored pointer do not free in formfree */
 +#define CURL_HTTPPOST_PTRNAME (1<<2)
 +/* contents is only stored pointer do not free in formfree */
 +#define CURL_HTTPPOST_PTRCONTENTS (1<<3)
 +/* upload file from buffer */
 +#define CURL_HTTPPOST_BUFFER (1<<4)
 +/* upload file from pointer contents */
 +#define CURL_HTTPPOST_PTRBUFFER (1<<5)
 +/* upload file contents by using the regular read callback to get the data and
 +   pass the given pointer as custom pointer */
 +#define CURL_HTTPPOST_CALLBACK (1<<6)
 +/* use size in 'contentlen', added in 7.46.0 */
 +#define CURL_HTTPPOST_LARGE (1<<7)
 +
 +  char *showfilename;               /* The file name to show. If not set, the
 +                                       actual file name will be used (if this
 +                                       is a file part) */
 +  void *userp;                      /* custom pointer used for
 +                                       HTTPPOST_CALLBACK posts */
 +  curl_off_t contentlen;            /* alternative length of contents
 +                                       field. Used if CURL_HTTPPOST_LARGE is
 +                                       set. Added in 7.46.0 */
 +};
 +
 +/* This is the CURLOPT_PROGRESSFUNCTION callback proto. It is now considered
 +   deprecated but was the only choice up until 7.31.0 */
 +typedef int (*curl_progress_callback)(void *clientp,
 +                                      double dltotal,
 +                                      double dlnow,
 +                                      double ultotal,
 +                                      double ulnow);
 +
 +/* This is the CURLOPT_XFERINFOFUNCTION callback proto. It was introduced in
 +   7.32.0, it avoids floating point and provides more detailed information. */
 +typedef int (*curl_xferinfo_callback)(void *clientp,
 +                                      curl_off_t dltotal,
 +                                      curl_off_t dlnow,
 +                                      curl_off_t ultotal,
 +                                      curl_off_t ulnow);
 +
 +#ifndef CURL_MAX_WRITE_SIZE
 +  /* Tests have proven that 20K is a very bad buffer size for uploads on
 +     Windows, while 16K for some odd reason performed a lot better.
 +     We do the ifndef check to allow this value to easier be changed at build
 +     time for those who feel adventurous. The practical minimum is about
 +     400 bytes since libcurl uses a buffer of this size as a scratch area
 +     (unrelated to network send operations). */
 +#define CURL_MAX_WRITE_SIZE 16384
 +#endif
 +
 +#ifndef CURL_MAX_HTTP_HEADER
 +/* The only reason to have a max limit for this is to avoid the risk of a bad
 +   server feeding libcurl with a never-ending header that will cause reallocs
 +   infinitely */
 +#define CURL_MAX_HTTP_HEADER (100*1024)
 +#endif
 +
 +/* This is a magic return code for the write callback that, when returned,
 +   will signal libcurl to pause receiving on the current transfer. */
 +#define CURL_WRITEFUNC_PAUSE 0x10000001
 +
 +typedef size_t (*curl_write_callback)(char *buffer,
 +                                      size_t size,
 +                                      size_t nitems,
 +                                      void *outstream);
 +
 +
 +
 +/* enumeration of file types */
 +typedef enum {
 +  CURLFILETYPE_FILE = 0,
 +  CURLFILETYPE_DIRECTORY,
 +  CURLFILETYPE_SYMLINK,
 +  CURLFILETYPE_DEVICE_BLOCK,
 +  CURLFILETYPE_DEVICE_CHAR,
 +  CURLFILETYPE_NAMEDPIPE,
 +  CURLFILETYPE_SOCKET,
 +  CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */
 +
 +  CURLFILETYPE_UNKNOWN /* should never occur */
 +} curlfiletype;
 +
 +#define CURLFINFOFLAG_KNOWN_FILENAME    (1<<0)
 +#define CURLFINFOFLAG_KNOWN_FILETYPE    (1<<1)
 +#define CURLFINFOFLAG_KNOWN_TIME        (1<<2)
 +#define CURLFINFOFLAG_KNOWN_PERM        (1<<3)
 +#define CURLFINFOFLAG_KNOWN_UID         (1<<4)
 +#define CURLFINFOFLAG_KNOWN_GID         (1<<5)
 +#define CURLFINFOFLAG_KNOWN_SIZE        (1<<6)
 +#define CURLFINFOFLAG_KNOWN_HLINKCOUNT  (1<<7)
 +
 +/* Content of this structure depends on information which is known and is
 +   achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man
 +   page for callbacks returning this structure -- some fields are mandatory,
 +   some others are optional. The FLAG field has special meaning. */
 +struct curl_fileinfo {
 +  char *filename;
 +  curlfiletype filetype;
 +  time_t time;
 +  unsigned int perm;
 +  int uid;
 +  int gid;
 +  curl_off_t size;
 +  long int hardlinks;
 +
 +  struct {
 +    /* If some of these fields is not NULL, it is a pointer to b_data. */
 +    char *time;
 +    char *perm;
 +    char *user;
 +    char *group;
 +    char *target; /* pointer to the target filename of a symlink */
 +  } strings;
 +
 +  unsigned int flags;
 +
 +  /* used internally */
-   char * b_data;
++  char *b_data;
 +  size_t b_size;
 +  size_t b_used;
 +};
 +
 +/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */
 +#define CURL_CHUNK_BGN_FUNC_OK      0
 +#define CURL_CHUNK_BGN_FUNC_FAIL    1 /* tell the lib to end the task */
 +#define CURL_CHUNK_BGN_FUNC_SKIP    2 /* skip this chunk over */
 +
 +/* if splitting of data transfer is enabled, this callback is called before
 +   download of an individual chunk started. Note that parameter "remains" works
 +   only for FTP wildcard downloading (for now), otherwise is not used */
 +typedef long (*curl_chunk_bgn_callback)(const void *transfer_info,
 +                                        void *ptr,
 +                                        int remains);
 +
 +/* return codes for CURLOPT_CHUNK_END_FUNCTION */
 +#define CURL_CHUNK_END_FUNC_OK      0
 +#define CURL_CHUNK_END_FUNC_FAIL    1 /* tell the lib to end the task */
 +
 +/* If splitting of data transfer is enabled this callback is called after
 +   download of an individual chunk finished.
 +   Note! After this callback was set then it have to be called FOR ALL chunks.
 +   Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC.
 +   This is the reason why we don't need "transfer_info" parameter in this
 +   callback and we are not interested in "remains" parameter too. */
 +typedef long (*curl_chunk_end_callback)(void *ptr);
 +
 +/* return codes for FNMATCHFUNCTION */
 +#define CURL_FNMATCHFUNC_MATCH    0 /* string corresponds to the pattern */
 +#define CURL_FNMATCHFUNC_NOMATCH  1 /* pattern doesn't match the string */
 +#define CURL_FNMATCHFUNC_FAIL     2 /* an error occurred */
 +
 +/* callback type for wildcard downloading pattern matching. If the
 +   string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */
 +typedef int (*curl_fnmatch_callback)(void *ptr,
 +                                     const char *pattern,
 +                                     const char *string);
 +
 +/* These are the return codes for the seek callbacks */
 +#define CURL_SEEKFUNC_OK       0
 +#define CURL_SEEKFUNC_FAIL     1 /* fail the entire transfer */
 +#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so
 +                                    libcurl might try other means instead */
 +typedef int (*curl_seek_callback)(void *instream,
 +                                  curl_off_t offset,
 +                                  int origin); /* 'whence' */
 +
 +/* This is a return code for the read callback that, when returned, will
 +   signal libcurl to immediately abort the current transfer. */
 +#define CURL_READFUNC_ABORT 0x10000000
 +/* This is a return code for the read callback that, when returned, will
 +   signal libcurl to pause sending data on the current transfer. */
 +#define CURL_READFUNC_PAUSE 0x10000001
 +
 +typedef size_t (*curl_read_callback)(char *buffer,
 +                                      size_t size,
 +                                      size_t nitems,
 +                                      void *instream);
 +
 +typedef enum  {
 +  CURLSOCKTYPE_IPCXN,  /* socket created for a specific IP connection */
 +  CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
 +  CURLSOCKTYPE_LAST    /* never use */
 +} curlsocktype;
 +
 +/* The return code from the sockopt_callback can signal information back
 +   to libcurl: */
 +#define CURL_SOCKOPT_OK 0
 +#define CURL_SOCKOPT_ERROR 1 /* causes libcurl to abort and return
 +                                CURLE_ABORTED_BY_CALLBACK */
 +#define CURL_SOCKOPT_ALREADY_CONNECTED 2
 +
 +typedef int (*curl_sockopt_callback)(void *clientp,
 +                                     curl_socket_t curlfd,
 +                                     curlsocktype purpose);
 +
 +struct curl_sockaddr {
 +  int family;
 +  int socktype;
 +  int protocol;
 +  unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it
 +                           turned really ugly and painful on the systems that
 +                           lack this type */
 +  struct sockaddr addr;
 +};
 +
 +typedef curl_socket_t
 +(*curl_opensocket_callback)(void *clientp,
 +                            curlsocktype purpose,
 +                            struct curl_sockaddr *address);
 +
 +typedef int
 +(*curl_closesocket_callback)(void *clientp, curl_socket_t item);
 +
 +typedef enum {
 +  CURLIOE_OK,            /* I/O operation successful */
 +  CURLIOE_UNKNOWNCMD,    /* command was unknown to callback */
 +  CURLIOE_FAILRESTART,   /* failed to restart the read */
 +  CURLIOE_LAST           /* never use */
 +} curlioerr;
 +
 +typedef enum  {
 +  CURLIOCMD_NOP,         /* no operation */
 +  CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
 +  CURLIOCMD_LAST         /* never use */
 +} curliocmd;
 +
 +typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
 +                                         int cmd,
 +                                         void *clientp);
 +
 +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS
 +/*
 + * The following typedef's are signatures of malloc, free, realloc, strdup and
 + * calloc respectively.  Function pointers of these types can be passed to the
 + * curl_global_init_mem() function to set user defined memory management
 + * callback routines.
 + */
 +typedef void *(*curl_malloc_callback)(size_t size);
 +typedef void (*curl_free_callback)(void *ptr);
 +typedef void *(*curl_realloc_callback)(void *ptr, size_t size);
 +typedef char *(*curl_strdup_callback)(const char *str);
 +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*/
 +typedef enum {
 +  CURLINFO_TEXT = 0,
 +  CURLINFO_HEADER_IN,    /* 1 */
 +  CURLINFO_HEADER_OUT,   /* 2 */
 +  CURLINFO_DATA_IN,      /* 3 */
 +  CURLINFO_DATA_OUT,     /* 4 */
 +  CURLINFO_SSL_DATA_IN,  /* 5 */
 +  CURLINFO_SSL_DATA_OUT, /* 6 */
 +  CURLINFO_END
 +} curl_infotype;
 +
 +typedef int (*curl_debug_callback)
 +       (CURL *handle,      /* the handle/transfer this concerns */
 +        curl_infotype type, /* what kind of data */
 +        char *data,        /* points to the data */
 +        size_t size,       /* size of the data pointed to */
 +        void *userptr);    /* whatever the user please */
 +
 +/* All possible error codes from all sorts of curl functions. Future versions
 +   may return other values, stay prepared.
 +
 +   Always add new return codes last. Never *EVER* remove any. The return
 +   codes must remain the same!
 + */
 +
 +typedef enum {
 +  CURLE_OK = 0,
 +  CURLE_UNSUPPORTED_PROTOCOL,    /* 1 */
 +  CURLE_FAILED_INIT,             /* 2 */
 +  CURLE_URL_MALFORMAT,           /* 3 */
 +  CURLE_NOT_BUILT_IN,            /* 4 - [was obsoleted in August 2007 for
 +                                    7.17.0, reused in April 2011 for 7.21.5] */
 +  CURLE_COULDNT_RESOLVE_PROXY,   /* 5 */
 +  CURLE_COULDNT_RESOLVE_HOST,    /* 6 */
 +  CURLE_COULDNT_CONNECT,         /* 7 */
 +  CURLE_WEIRD_SERVER_REPLY,      /* 8 */
 +  CURLE_REMOTE_ACCESS_DENIED,    /* 9 a service was denied by the server
 +                                    due to lack of access - when login fails
 +                                    this is not returned. */
 +  CURLE_FTP_ACCEPT_FAILED,       /* 10 - [was obsoleted in April 2006 for
 +                                    7.15.4, reused in Dec 2011 for 7.24.0]*/
 +  CURLE_FTP_WEIRD_PASS_REPLY,    /* 11 */
 +  CURLE_FTP_ACCEPT_TIMEOUT,      /* 12 - timeout occurred accepting server
 +                                    [was obsoleted in August 2007 for 7.17.0,
 +                                    reused in Dec 2011 for 7.24.0]*/
 +  CURLE_FTP_WEIRD_PASV_REPLY,    /* 13 */
 +  CURLE_FTP_WEIRD_227_FORMAT,    /* 14 */
 +  CURLE_FTP_CANT_GET_HOST,       /* 15 */
 +  CURLE_HTTP2,                   /* 16 - A problem in the http2 framing layer.
 +                                    [was obsoleted in August 2007 for 7.17.0,
 +                                    reused in July 2014 for 7.38.0] */
 +  CURLE_FTP_COULDNT_SET_TYPE,    /* 17 */
 +  CURLE_PARTIAL_FILE,            /* 18 */
 +  CURLE_FTP_COULDNT_RETR_FILE,   /* 19 */
 +  CURLE_OBSOLETE20,              /* 20 - NOT USED */
 +  CURLE_QUOTE_ERROR,             /* 21 - quote command failure */
 +  CURLE_HTTP_RETURNED_ERROR,     /* 22 */
 +  CURLE_WRITE_ERROR,             /* 23 */
 +  CURLE_OBSOLETE24,              /* 24 - NOT USED */
 +  CURLE_UPLOAD_FAILED,           /* 25 - failed upload "command" */
 +  CURLE_READ_ERROR,              /* 26 - couldn't open/read from file */
 +  CURLE_OUT_OF_MEMORY,           /* 27 */
 +  /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error
 +           instead of a memory allocation error if CURL_DOES_CONVERSIONS
 +           is defined
 +  */
 +  CURLE_OPERATION_TIMEDOUT,      /* 28 - the timeout time was reached */
 +  CURLE_OBSOLETE29,              /* 29 - NOT USED */
 +  CURLE_FTP_PORT_FAILED,         /* 30 - FTP PORT operation failed */
 +  CURLE_FTP_COULDNT_USE_REST,    /* 31 - the REST command failed */
 +  CURLE_OBSOLETE32,              /* 32 - NOT USED */
 +  CURLE_RANGE_ERROR,             /* 33 - RANGE "command" didn't work */
 +  CURLE_HTTP_POST_ERROR,         /* 34 */
 +  CURLE_SSL_CONNECT_ERROR,       /* 35 - wrong when connecting with SSL */
 +  CURLE_BAD_DOWNLOAD_RESUME,     /* 36 - couldn't resume download */
 +  CURLE_FILE_COULDNT_READ_FILE,  /* 37 */
 +  CURLE_LDAP_CANNOT_BIND,        /* 38 */
 +  CURLE_LDAP_SEARCH_FAILED,      /* 39 */
 +  CURLE_OBSOLETE40,              /* 40 - NOT USED */
 +  CURLE_FUNCTION_NOT_FOUND,      /* 41 */
 +  CURLE_ABORTED_BY_CALLBACK,     /* 42 */
 +  CURLE_BAD_FUNCTION_ARGUMENT,   /* 43 */
 +  CURLE_OBSOLETE44,              /* 44 - NOT USED */
 +  CURLE_INTERFACE_FAILED,        /* 45 - CURLOPT_INTERFACE failed */
 +  CURLE_OBSOLETE46,              /* 46 - NOT USED */
 +  CURLE_TOO_MANY_REDIRECTS,      /* 47 - catch endless re-direct loops */
 +  CURLE_UNKNOWN_OPTION,          /* 48 - User specified an unknown option */
 +  CURLE_TELNET_OPTION_SYNTAX,    /* 49 - Malformed telnet option */
 +  CURLE_OBSOLETE50,              /* 50 - NOT USED */
 +  CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint
 +                                     wasn't verified fine */
 +  CURLE_GOT_NOTHING,             /* 52 - when this is a specific error */
 +  CURLE_SSL_ENGINE_NOTFOUND,     /* 53 - SSL crypto engine not found */
 +  CURLE_SSL_ENGINE_SETFAILED,    /* 54 - can not set SSL crypto engine as
 +                                    default */
 +  CURLE_SEND_ERROR,              /* 55 - failed sending network data */
 +  CURLE_RECV_ERROR,              /* 56 - failure in receiving network data */
 +  CURLE_OBSOLETE57,              /* 57 - NOT IN USE */
 +  CURLE_SSL_CERTPROBLEM,         /* 58 - problem with the local certificate */
 +  CURLE_SSL_CIPHER,              /* 59 - couldn't use specified cipher */
 +  CURLE_SSL_CACERT,              /* 60 - problem with the CA cert (path?) */
 +  CURLE_BAD_CONTENT_ENCODING,    /* 61 - Unrecognized/bad encoding */
 +  CURLE_LDAP_INVALID_URL,        /* 62 - Invalid LDAP URL */
 +  CURLE_FILESIZE_EXCEEDED,       /* 63 - Maximum file size exceeded */
 +  CURLE_USE_SSL_FAILED,          /* 64 - Requested FTP SSL level failed */
 +  CURLE_SEND_FAIL_REWIND,        /* 65 - Sending the data requires a rewind
 +                                    that failed */
 +  CURLE_SSL_ENGINE_INITFAILED,   /* 66 - failed to initialise ENGINE */
 +  CURLE_LOGIN_DENIED,            /* 67 - user, password or similar was not
 +                                    accepted and we failed to login */
 +  CURLE_TFTP_NOTFOUND,           /* 68 - file not found on server */
 +  CURLE_TFTP_PERM,               /* 69 - permission problem on server */
 +  CURLE_REMOTE_DISK_FULL,        /* 70 - out of disk space on server */
 +  CURLE_TFTP_ILLEGAL,            /* 71 - Illegal TFTP operation */
 +  CURLE_TFTP_UNKNOWNID,          /* 72 - Unknown transfer ID */
 +  CURLE_REMOTE_FILE_EXISTS,      /* 73 - File already exists */
 +  CURLE_TFTP_NOSUCHUSER,         /* 74 - No such user */
 +  CURLE_CONV_FAILED,             /* 75 - conversion failed */
 +  CURLE_CONV_REQD,               /* 76 - caller must register conversion
 +                                    callbacks using curl_easy_setopt options
 +                                    CURLOPT_CONV_FROM_NETWORK_FUNCTION,
 +                                    CURLOPT_CONV_TO_NETWORK_FUNCTION, and
 +                                    CURLOPT_CONV_FROM_UTF8_FUNCTION */
 +  CURLE_SSL_CACERT_BADFILE,      /* 77 - could not load CACERT file, missing
 +                                    or wrong format */
 +  CURLE_REMOTE_FILE_NOT_FOUND,   /* 78 - remote file not found */
 +  CURLE_SSH,                     /* 79 - error from the SSH layer, somewhat
 +                                    generic so the error message will be of
 +                                    interest when this has happened */
 +
 +  CURLE_SSL_SHUTDOWN_FAILED,     /* 80 - Failed to shut down the SSL
 +                                    connection */
 +  CURLE_AGAIN,                   /* 81 - socket is not ready for send/recv,
 +                                    wait till it's ready and try again (Added
 +                                    in 7.18.2) */
 +  CURLE_SSL_CRL_BADFILE,         /* 82 - could not load CRL file, missing or
 +                                    wrong format (Added in 7.19.0) */
 +  CURLE_SSL_ISSUER_ERROR,        /* 83 - Issuer check failed.  (Added in
 +                                    7.19.0) */
 +  CURLE_FTP_PRET_FAILED,         /* 84 - a PRET command failed */
 +  CURLE_RTSP_CSEQ_ERROR,         /* 85 - mismatch of RTSP CSeq numbers */
 +  CURLE_RTSP_SESSION_ERROR,      /* 86 - mismatch of RTSP Session Ids */
 +  CURLE_FTP_BAD_FILE_LIST,       /* 87 - unable to parse FTP file list */
 +  CURLE_CHUNK_FAILED,            /* 88 - chunk callback reported error */
 +  CURLE_NO_CONNECTION_AVAILABLE, /* 89 - No connection available, the
 +                                    session will be queued */
 +  CURLE_SSL_PINNEDPUBKEYNOTMATCH, /* 90 - specified pinned public key did not
 +                                     match */
 +  CURLE_SSL_INVALIDCERTSTATUS,   /* 91 - invalid certificate status */
 +  CURLE_HTTP2_STREAM,            /* 92 - stream error in HTTP/2 framing layer
 +                                    */
 +  CURL_LAST /* never use! */
 +} CURLcode;
 +
 +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
 +                          the obsolete stuff removed! */
 +
 +/* Previously obsolete error code re-used in 7.38.0 */
 +#define CURLE_OBSOLETE16 CURLE_HTTP2
 +
 +/* Previously obsolete error codes re-used in 7.24.0 */
 +#define CURLE_OBSOLETE10 CURLE_FTP_ACCEPT_FAILED
 +#define CURLE_OBSOLETE12 CURLE_FTP_ACCEPT_TIMEOUT
 +
 +/*  compatibility with older names */
 +#define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
 +#define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY
 +
 +/* The following were added in 7.21.5, April 2011 */
 +#define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
 +
 +/* The following were added in 7.17.1 */
 +/* These are scheduled to disappear by 2009 */
 +#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION
 +
 +/* The following were added in 7.17.0 */
 +/* These are scheduled to disappear by 2009 */
 +#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* no one should be using this! */
 +#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46
 +#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44
 +#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10
 +#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16
 +#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32
 +#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29
 +#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12
 +#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20
 +#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40
 +#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24
 +#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57
 +#define CURLE_URL_MALFORMAT_USER CURLE_NOT_BUILT_IN
 +
 +#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED
 +#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE
 +#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR
 +#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL
 +#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS
 +#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR
 +#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED
 +
 +/* The following were added earlier */
 +
 +#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT
 +
 +#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR
 +#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED
 +#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED
 +
 +#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
 +#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME
 +
 +/* This was the error code 50 in 7.7.3 and a few earlier versions, this
 +   is no longer used by libcurl but is instead #defined here only to not
 +   make programs break */
 +#define CURLE_ALREADY_COMPLETE 99999
 +
 +/* Provide defines for really old option names */
 +#define CURLOPT_FILE CURLOPT_WRITEDATA /* name changed in 7.9.7 */
 +#define CURLOPT_INFILE CURLOPT_READDATA /* name changed in 7.9.7 */
 +#define CURLOPT_WRITEHEADER CURLOPT_HEADERDATA
 +
 +/* Since long deprecated options with no code in the lib that does anything
 +   with them. */
 +#define CURLOPT_WRITEINFO CURLOPT_OBSOLETE40
 +#define CURLOPT_CLOSEPOLICY CURLOPT_OBSOLETE72
 +
 +#endif /*!CURL_NO_OLDIES*/
 +
 +/* This prototype applies to all conversion callbacks */
 +typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length);
 +
 +typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl,    /* easy handle */
 +                                          void *ssl_ctx, /* actually an
 +                                                            OpenSSL SSL_CTX */
 +                                          void *userptr);
 +
 +typedef enum {
 +  CURLPROXY_HTTP = 0,   /* added in 7.10, new in 7.19.4 default is to use
 +                           CONNECT HTTP/1.1 */
 +  CURLPROXY_HTTP_1_0 = 1,   /* added in 7.19.4, force to use CONNECT
 +                               HTTP/1.0  */
++  CURLPROXY_HTTPS = 2, /* added in 7.52.0 */
 +  CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
 +                           in 7.10 */
 +  CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
 +  CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */
 +  CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the
 +                                   host name rather than the IP address. added
 +                                   in 7.18.0 */
 +} curl_proxytype;  /* this enum was added in 7.10 */
 +
 +/*
 + * Bitmasks for CURLOPT_HTTPAUTH and CURLOPT_PROXYAUTH options:
 + *
 + * CURLAUTH_NONE         - No HTTP authentication
 + * CURLAUTH_BASIC        - HTTP Basic authentication (default)
 + * CURLAUTH_DIGEST       - HTTP Digest authentication
 + * CURLAUTH_NEGOTIATE    - HTTP Negotiate (SPNEGO) authentication
 + * CURLAUTH_GSSNEGOTIATE - Alias for CURLAUTH_NEGOTIATE (deprecated)
 + * CURLAUTH_NTLM         - HTTP NTLM authentication
 + * CURLAUTH_DIGEST_IE    - HTTP Digest authentication with IE flavour
 + * CURLAUTH_NTLM_WB      - HTTP NTLM authentication delegated to winbind helper
 + * CURLAUTH_ONLY         - Use together with a single other type to force no
 + *                         authentication or just that single type
 + * CURLAUTH_ANY          - All fine types set
 + * CURLAUTH_ANYSAFE      - All fine types except Basic
 + */
 +
 +#define CURLAUTH_NONE         ((unsigned long)0)
 +#define CURLAUTH_BASIC        (((unsigned long)1)<<0)
 +#define CURLAUTH_DIGEST       (((unsigned long)1)<<1)
 +#define CURLAUTH_NEGOTIATE    (((unsigned long)1)<<2)
 +/* Deprecated since the advent of CURLAUTH_NEGOTIATE */
 +#define CURLAUTH_GSSNEGOTIATE CURLAUTH_NEGOTIATE
 +#define CURLAUTH_NTLM         (((unsigned long)1)<<3)
 +#define CURLAUTH_DIGEST_IE    (((unsigned long)1)<<4)
 +#define CURLAUTH_NTLM_WB      (((unsigned long)1)<<5)
 +#define CURLAUTH_ONLY         (((unsigned long)1)<<31)
 +#define CURLAUTH_ANY          (~CURLAUTH_DIGEST_IE)
 +#define CURLAUTH_ANYSAFE      (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
 +
 +#define CURLSSH_AUTH_ANY       ~0     /* all types supported by the server */
 +#define CURLSSH_AUTH_NONE      0      /* none allowed, silly but complete */
 +#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */
 +#define CURLSSH_AUTH_PASSWORD  (1<<1) /* password */
 +#define CURLSSH_AUTH_HOST      (1<<2) /* host key files */
 +#define CURLSSH_AUTH_KEYBOARD  (1<<3) /* keyboard interactive */
 +#define CURLSSH_AUTH_AGENT     (1<<4) /* agent (ssh-agent, pageant...) */
 +#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY
 +
 +#define CURLGSSAPI_DELEGATION_NONE        0      /* no delegation (default) */
 +#define CURLGSSAPI_DELEGATION_POLICY_FLAG (1<<0) /* if permitted by policy */
 +#define CURLGSSAPI_DELEGATION_FLAG        (1<<1) /* delegate always */
 +
 +#define CURL_ERROR_SIZE 256
 +
 +enum curl_khtype {
 +  CURLKHTYPE_UNKNOWN,
 +  CURLKHTYPE_RSA1,
 +  CURLKHTYPE_RSA,
 +  CURLKHTYPE_DSS
 +};
 +
 +struct curl_khkey {
 +  const char *key; /* points to a zero-terminated string encoded with base64
 +                      if len is zero, otherwise to the "raw" data */
 +  size_t len;
 +  enum curl_khtype keytype;
 +};
 +
 +/* this is the set of return values expected from the curl_sshkeycallback
 +   callback */
 +enum curl_khstat {
 +  CURLKHSTAT_FINE_ADD_TO_FILE,
 +  CURLKHSTAT_FINE,
 +  CURLKHSTAT_REJECT, /* reject the connection, return an error */
 +  CURLKHSTAT_DEFER,  /* do not accept it, but we can't answer right now so
 +                        this causes a CURLE_DEFER error but otherwise the
 +                        connection will be left intact etc */
 +  CURLKHSTAT_LAST    /* not for use, only a marker for last-in-list */
 +};
 +
 +/* this is the set of status codes pass in to the callback */
 +enum curl_khmatch {
 +  CURLKHMATCH_OK,       /* match */
 +  CURLKHMATCH_MISMATCH, /* host found, key mismatch! */
 +  CURLKHMATCH_MISSING,  /* no matching host/key found */
 +  CURLKHMATCH_LAST      /* not for use, only a marker for last-in-list */
 +};
 +
 +typedef int
 +  (*curl_sshkeycallback) (CURL *easy,     /* easy handle */
 +                          const struct curl_khkey *knownkey, /* known */
 +                          const struct curl_khkey *foundkey, /* found */
 +                          enum curl_khmatch, /* libcurl's view on the keys */
 +                          void *clientp); /* custom pointer passed from app */
 +
 +/* parameter for the CURLOPT_USE_SSL option */
 +typedef enum {
 +  CURLUSESSL_NONE,    /* do not attempt to use SSL */
 +  CURLUSESSL_TRY,     /* try using SSL, proceed anyway otherwise */
 +  CURLUSESSL_CONTROL, /* SSL for the control connection or fail */
 +  CURLUSESSL_ALL,     /* SSL for all communication or fail */
 +  CURLUSESSL_LAST     /* not an option, never use */
 +} curl_usessl;
 +
 +/* Definition of bits for the CURLOPT_SSL_OPTIONS argument: */
 +
 +/* - ALLOW_BEAST tells libcurl to allow the BEAST SSL vulnerability in the
 +   name of improving interoperability with older servers. Some SSL libraries
 +   have introduced work-arounds for this flaw but those work-arounds sometimes
 +   make the SSL communication fail. To regain functionality with those broken
 +   servers, a user can this way allow the vulnerability back. */
 +#define CURLSSLOPT_ALLOW_BEAST (1<<0)
 +
 +/* - NO_REVOKE tells libcurl to disable certificate revocation checks for those
 +   SSL backends where such behavior is present. */
 +#define CURLSSLOPT_NO_REVOKE (1<<1)
 +
 +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
 +                          the obsolete stuff removed! */
 +
 +/* Backwards compatibility with older names */
 +/* These are scheduled to disappear by 2009 */
 +
 +#define CURLFTPSSL_NONE CURLUSESSL_NONE
 +#define CURLFTPSSL_TRY CURLUSESSL_TRY
 +#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL
 +#define CURLFTPSSL_ALL CURLUSESSL_ALL
 +#define CURLFTPSSL_LAST CURLUSESSL_LAST
 +#define curl_ftpssl curl_usessl
 +#endif /*!CURL_NO_OLDIES*/
 +
 +/* parameter for the CURLOPT_FTP_SSL_CCC option */
 +typedef enum {
 +  CURLFTPSSL_CCC_NONE,    /* do not send CCC */
 +  CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */
 +  CURLFTPSSL_CCC_ACTIVE,  /* Initiate the shutdown */
 +  CURLFTPSSL_CCC_LAST     /* not an option, never use */
 +} curl_ftpccc;
 +
 +/* parameter for the CURLOPT_FTPSSLAUTH option */
 +typedef enum {
 +  CURLFTPAUTH_DEFAULT, /* let libcurl decide */
 +  CURLFTPAUTH_SSL,     /* use "AUTH SSL" */
 +  CURLFTPAUTH_TLS,     /* use "AUTH TLS" */
 +  CURLFTPAUTH_LAST /* not an option, never use */
 +} curl_ftpauth;
 +
 +/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */
 +typedef enum {
 +  CURLFTP_CREATE_DIR_NONE,  /* do NOT create missing dirs! */
 +  CURLFTP_CREATE_DIR,       /* (FTP/SFTP) if CWD fails, try MKD and then CWD
 +                               again if MKD succeeded, for SFTP this does
 +                               similar magic */
 +  CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD
 +                               again even if MKD failed! */
 +  CURLFTP_CREATE_DIR_LAST   /* not an option, never use */
 +} curl_ftpcreatedir;
 +
 +/* parameter for the CURLOPT_FTP_FILEMETHOD option */
 +typedef enum {
 +  CURLFTPMETHOD_DEFAULT,   /* let libcurl pick */
 +  CURLFTPMETHOD_MULTICWD,  /* single CWD operation for each path part */
 +  CURLFTPMETHOD_NOCWD,     /* no CWD at all */
 +  CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */
 +  CURLFTPMETHOD_LAST       /* not an option, never use */
 +} curl_ftpmethod;
 +
 +/* bitmask defines for CURLOPT_HEADEROPT */
 +#define CURLHEADER_UNIFIED  0
 +#define CURLHEADER_SEPARATE (1<<0)
 +
 +/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
 +#define CURLPROTO_HTTP   (1<<0)
 +#define CURLPROTO_HTTPS  (1<<1)
 +#define CURLPROTO_FTP    (1<<2)
 +#define CURLPROTO_FTPS   (1<<3)
 +#define CURLPROTO_SCP    (1<<4)
 +#define CURLPROTO_SFTP   (1<<5)
 +#define CURLPROTO_TELNET (1<<6)
 +#define CURLPROTO_LDAP   (1<<7)
 +#define CURLPROTO_LDAPS  (1<<8)
 +#define CURLPROTO_DICT   (1<<9)
 +#define CURLPROTO_FILE   (1<<10)
 +#define CURLPROTO_TFTP   (1<<11)
 +#define CURLPROTO_IMAP   (1<<12)
 +#define CURLPROTO_IMAPS  (1<<13)
 +#define CURLPROTO_POP3   (1<<14)
 +#define CURLPROTO_POP3S  (1<<15)
 +#define CURLPROTO_SMTP   (1<<16)
 +#define CURLPROTO_SMTPS  (1<<17)
 +#define CURLPROTO_RTSP   (1<<18)
 +#define CURLPROTO_RTMP   (1<<19)
 +#define CURLPROTO_RTMPT  (1<<20)
 +#define CURLPROTO_RTMPE  (1<<21)
 +#define CURLPROTO_RTMPTE (1<<22)
 +#define CURLPROTO_RTMPS  (1<<23)
 +#define CURLPROTO_RTMPTS (1<<24)
 +#define CURLPROTO_GOPHER (1<<25)
 +#define CURLPROTO_SMB    (1<<26)
 +#define CURLPROTO_SMBS   (1<<27)
 +#define CURLPROTO_ALL    (~0) /* enable everything */
 +
 +/* long may be 32 or 64 bits, but we should never depend on anything else
 +   but 32 */
 +#define CURLOPTTYPE_LONG          0
 +#define CURLOPTTYPE_OBJECTPOINT   10000
 +#define CURLOPTTYPE_STRINGPOINT   10000
 +#define CURLOPTTYPE_FUNCTIONPOINT 20000
 +#define CURLOPTTYPE_OFF_T         30000
 +
 +/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the
 +   string options from the header file */
 +
 +/* name is uppercase CURLOPT_<name>,
 +   type is one of the defined CURLOPTTYPE_<type>
 +   number is unique identifier */
 +#ifdef CINIT
 +#undef CINIT
 +#endif
 +
 +#ifdef CURL_ISOCPP
 +#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
 +#else
 +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
 +#define LONG          CURLOPTTYPE_LONG
 +#define OBJECTPOINT   CURLOPTTYPE_OBJECTPOINT
 +#define STRINGPOINT   CURLOPTTYPE_OBJECTPOINT
 +#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
 +#define OFF_T         CURLOPTTYPE_OFF_T
 +#define CINIT(name,type,number) CURLOPT_/**/name = type + number
 +#endif
 +
 +/*
 + * This macro-mania below setups the CURLOPT_[what] enum, to be used with
 + * curl_easy_setopt(). The first argument in the CINIT() macro is the [what]
 + * word.
 + */
 +
 +typedef enum {
 +  /* This is the FILE * or void * the regular output should be written to. */
 +  CINIT(WRITEDATA, OBJECTPOINT, 1),
 +
 +  /* The full URL to get/put */
 +  CINIT(URL, STRINGPOINT, 2),
 +
 +  /* Port number to connect to, if other than default. */
 +  CINIT(PORT, LONG, 3),
 +
 +  /* Name of proxy to use. */
 +  CINIT(PROXY, STRINGPOINT, 4),
 +
 +  /* "user:password;options" to use when fetching. */
 +  CINIT(USERPWD, STRINGPOINT, 5),
 +
 +  /* "user:password" to use with proxy. */
 +  CINIT(PROXYUSERPWD, STRINGPOINT, 6),
 +
 +  /* Range to get, specified as an ASCII string. */
 +  CINIT(RANGE, STRINGPOINT, 7),
 +
 +  /* not used */
 +
 +  /* Specified file stream to upload from (use as input): */
 +  CINIT(READDATA, OBJECTPOINT, 9),
 +
 +  /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
 +   * bytes big. If this is not used, error messages go to stderr instead: */
 +  CINIT(ERRORBUFFER, OBJECTPOINT, 10),
 +
 +  /* Function that will be called to store the output (instead of fwrite). The
 +   * parameters will use fwrite() syntax, make sure to follow them. */
 +  CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
 +
 +  /* Function that will be called to read the input (instead of fread). The
 +   * parameters will use fread() syntax, make sure to follow them. */
 +  CINIT(READFUNCTION, FUNCTIONPOINT, 12),
 +
 +  /* Time-out the read operation after this amount of seconds */
 +  CINIT(TIMEOUT, LONG, 13),
 +
 +  /* If the CURLOPT_INFILE 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.
 +   *
 +   * For large file support, there is also a _LARGE version of the key
 +   * which takes an off_t type, allowing platforms with larger off_t
 +   * sizes to handle larger files.  See below for INFILESIZE_LARGE.
 +   */
 +  CINIT(INFILESIZE, LONG, 14),
 +
 +  /* POST static input fields. */
 +  CINIT(POSTFIELDS, OBJECTPOINT, 15),
 +
 +  /* Set the referrer page (needed by some CGIs) */
 +  CINIT(REFERER, STRINGPOINT, 16),
 +
 +  /* Set the FTP PORT string (interface name, named or numerical IP address)
 +     Use i.e '-' to use default address. */
 +  CINIT(FTPPORT, STRINGPOINT, 17),
 +
 +  /* Set the User-Agent string (examined by some CGIs) */
 +  CINIT(USERAGENT, STRINGPOINT, 18),
 +
 +  /* If the download receives less than "low speed limit" bytes/second
 +   * during "low speed time" seconds, the operations is aborted.
 +   * You could i.e if you have a pretty high speed connection, abort if
 +   * it is less than 2000 bytes/sec during 20 seconds.
 +   */
 +
 +  /* Set the "low speed limit" */
 +  CINIT(LOW_SPEED_LIMIT, LONG, 19),
 +
 +  /* Set the "low speed time" */
 +  CINIT(LOW_SPEED_TIME, LONG, 20),
 +
 +  /* Set the continuation offset.
 +   *
 +   * Note there is also a _LARGE version of this key which uses
 +   * off_t types, allowing for large file offsets on platforms which
 +   * use larger-than-32-bit off_t's.  Look below for RESUME_FROM_LARGE.
 +   */
 +  CINIT(RESUME_FROM, LONG, 21),
 +
 +  /* Set cookie in request: */
 +  CINIT(COOKIE, STRINGPOINT, 22),
 +
 +  /* This points to a linked list of headers, struct curl_slist kind. This
 +     list is also used for RTSP (in spite of its name) */
 +  CINIT(HTTPHEADER, OBJECTPOINT, 23),
 +
 +  /* This points to a linked list of post entries, struct curl_httppost */
 +  CINIT(HTTPPOST, OBJECTPOINT, 24),
 +
 +  /* name of the file keeping your private SSL-certificate */
 +  CINIT(SSLCERT, STRINGPOINT, 25),
 +
 +  /* password for the SSL or SSH private key */
 +  CINIT(KEYPASSWD, STRINGPOINT, 26),
 +
 +  /* send TYPE parameter? */
 +  CINIT(CRLF, LONG, 27),
 +
 +  /* send linked-list of QUOTE commands */
 +  CINIT(QUOTE, OBJECTPOINT, 28),
 +
 +  /* send FILE * or void * to store headers to, if you use a callback it
 +     is simply passed to the callback unmodified */
 +  CINIT(HEADERDATA, OBJECTPOINT, 29),
 +
 +  /* point to a file to read the initial cookies from, also enables
 +     "cookie awareness" */
 +  CINIT(COOKIEFILE, STRINGPOINT, 31),
 +
 +  /* What version to specifically try to use.
 +     See CURL_SSLVERSION defines below. */
 +  CINIT(SSLVERSION, LONG, 32),
 +
 +  /* What kind of HTTP time condition to use, see defines */
 +  CINIT(TIMECONDITION, LONG, 33),
 +
 +  /* Time to use with the above condition. Specified in number of seconds
 +     since 1 Jan 1970 */
 +  CINIT(TIMEVALUE, LONG, 34),
 +
 +  /* 35 = OBSOLETE */
 +
 +  /* Custom request, for customizing the get command like
 +     HTTP: DELETE, TRACE and others
 +     FTP: to use a different list command
 +     */
 +  CINIT(CUSTOMREQUEST, STRINGPOINT, 36),
 +
 +  /* FILE handle to use instead of stderr */
 +  CINIT(STDERR, OBJECTPOINT, 37),
 +
 +  /* 38 is not used */
 +
 +  /* send linked-list of post-transfer QUOTE commands */
 +  CINIT(POSTQUOTE, OBJECTPOINT, 39),
 +
 +  CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */
 +
 +  CINIT(VERBOSE, LONG, 41),      /* talk a lot */
 +  CINIT(HEADER, LONG, 42),       /* throw the header out too */
 +  CINIT(NOPROGRESS, LONG, 43),   /* shut off the progress meter */
 +  CINIT(NOBODY, LONG, 44),       /* use HEAD to get http document */
 +  CINIT(FAILONERROR, LONG, 45),  /* no output on http error codes >= 400 */
 +  CINIT(UPLOAD, LONG, 46),       /* this is an upload */
 +  CINIT(POST, LONG, 47),         /* HTTP POST method */
 +  CINIT(DIRLISTONLY, LONG, 48),  /* bare names when listing directories */
 +
 +  CINIT(APPEND, LONG, 50),       /* Append instead of overwrite on upload! */
 +
 +  /* Specify whether to read the user+password from the .netrc or the URL.
 +   * This must be one of the CURL_NETRC_* enums below. */
 +  CINIT(NETRC, LONG, 51),
 +
 +  CINIT(FOLLOWLOCATION, LONG, 52),  /* use Location: Luke! */
 +
 +  CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
 +  CINIT(PUT, LONG, 54),          /* HTTP PUT */
 +
 +  /* 55 = OBSOLETE */
 +
 +  /* DEPRECATED
 +   * Function that will be called instead of the internal progress display
 +   * function. This function should be defined as the curl_progress_callback
 +   * prototype defines. */
 +  CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
 +
 +  /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
 +     callbacks */
 +  CINIT(PROGRESSDATA, OBJECTPOINT, 57),
 +#define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
 +
 +  /* We want the referrer field set automatically when following locations */
 +  CINIT(AUTOREFERER, LONG, 58),
 +
 +  /* Port of the proxy, can be set in the proxy string as well with:
 +     "[host]:[port]" */
 +  CINIT(PROXYPORT, LONG, 59),
 +
 +  /* size of the POST input data, if strlen() is not good to use */
 +  CINIT(POSTFIELDSIZE, LONG, 60),
 +
 +  /* tunnel non-http operations through a HTTP proxy */
 +  CINIT(HTTPPROXYTUNNEL, LONG, 61),
 +
 +  /* Set the interface string to use as outgoing network interface */
 +  CINIT(INTERFACE, STRINGPOINT, 62),
 +
 +  /* Set the krb4/5 security level, this also enables krb4/5 awareness.  This
 +   * is a string, 'clear', 'safe', 'confidential' or 'private'.  If the string
 +   * is set but doesn't match one of these, 'private' will be used.  */
 +  CINIT(KRBLEVEL, STRINGPOINT, 63),
 +
 +  /* Set if we should verify the peer in ssl handshake, set 1 to verify. */
 +  CINIT(SSL_VERIFYPEER, LONG, 64),
 +
 +  /* The CApath or CAfile used to validate the peer certificate
 +     this option is used only if SSL_VERIFYPEER is true */
 +  CINIT(CAINFO, STRINGPOINT, 65),
 +
 +  /* 66 = OBSOLETE */
 +  /* 67 = OBSOLETE */
 +
 +  /* Maximum number of http redirects to follow */
 +  CINIT(MAXREDIRS, LONG, 68),
 +
 +  /* Pass a long set to 1 to get the date of the requested document (if
 +     possible)! Pass a zero to shut it off. */
 +  CINIT(FILETIME, LONG, 69),
 +
 +  /* This points to a linked list of telnet options */
 +  CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
 +
 +  /* Max amount of cached alive connections */
 +  CINIT(MAXCONNECTS, LONG, 71),
 +
 +  CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */
 +
 +  /* 73 = OBSOLETE */
 +
 +  /* Set to explicitly use a new connection for the upcoming transfer.
 +     Do not use this unless you're absolutely sure of this, as it makes the
 +     operation slower and is less friendly for the network. */
 +  CINIT(FRESH_CONNECT, LONG, 74),
 +
 +  /* Set to explicitly forbid the upcoming transfer's connection to be re-used
 +     when done. Do not use this unless you're absolutely sure of this, as it
 +     makes the operation slower and is less friendly for the network. */
 +  CINIT(FORBID_REUSE, LONG, 75),
 +
 +  /* Set to a file name that contains random data for libcurl to use to
 +     seed the random engine when doing SSL connects. */
 +  CINIT(RANDOM_FILE, STRINGPOINT, 76),
 +
 +  /* Set to the Entropy Gathering Daemon socket pathname */
 +  CINIT(EGDSOCKET, STRINGPOINT, 77),
 +
 +  /* Time-out connect operations after this amount of seconds, if connects are
 +     OK within this time, then fine... This only aborts the connect phase. */
 +  CINIT(CONNECTTIMEOUT, LONG, 78),
 +
 +  /* Function that will be called to store headers (instead of fwrite). The
 +   * parameters will use fwrite() syntax, make sure to follow them. */
 +  CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
 +
 +  /* Set this to force the HTTP request to get back to GET. Only really usable
 +     if POST, PUT or a custom request have been used first.
 +   */
 +  CINIT(HTTPGET, LONG, 80),
 +
 +  /* Set if we should verify the Common name from the peer certificate in ssl
 +   * handshake, set 1 to check existence, 2 to ensure that it matches the
 +   * provided hostname. */
 +  CINIT(SSL_VERIFYHOST, LONG, 81),
 +
 +  /* Specify which file name to write all known cookies in after completed
 +     operation. Set file name to "-" (dash) to make it go to stdout. */
 +  CINIT(COOKIEJAR, STRINGPOINT, 82),
 +
 +  /* Specify which SSL ciphers to use */
 +  CINIT(SSL_CIPHER_LIST, STRINGPOINT, 83),
 +
 +  /* Specify which HTTP version to use! This must be set to one of the
 +     CURL_HTTP_VERSION* enums set below. */
 +  CINIT(HTTP_VERSION, LONG, 84),
 +
 +  /* Specifically switch on or off the FTP engine's use of the EPSV command. By
 +     default, that one will always be attempted before the more traditional
 +     PASV command. */
 +  CINIT(FTP_USE_EPSV, LONG, 85),
 +
 +  /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
 +  CINIT(SSLCERTTYPE, STRINGPOINT, 86),
 +
 +  /* name of the file keeping your private SSL-key */
 +  CINIT(SSLKEY, STRINGPOINT, 87),
 +
 +  /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
 +  CINIT(SSLKEYTYPE, STRINGPOINT, 88),
 +
 +  /* crypto engine for the SSL-sub system */
 +  CINIT(SSLENGINE, STRINGPOINT, 89),
 +
 +  /* set the crypto engine for the SSL-sub system as default
 +     the param has no meaning...
 +   */
 +  CINIT(SSLENGINE_DEFAULT, LONG, 90),
 +
 +  /* Non-zero value means to use the global dns cache */
 +  CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */
 +
 +  /* DNS cache timeout */
 +  CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
 +
 +  /* send linked-list of pre-transfer QUOTE commands */
 +  CINIT(PREQUOTE, OBJECTPOINT, 93),
 +
 +  /* set the debug function */
 +  CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94),
 +
 +  /* set the data for the debug function */
 +  CINIT(DEBUGDATA, OBJECTPOINT, 95),
 +
 +  /* mark this as start of a cookie session */
 +  CINIT(COOKIESESSION, LONG, 96),
 +
 +  /* The CApath directory used to validate the peer certificate
 +     this option is used only if SSL_VERIFYPEER is true */
 +  CINIT(CAPATH, STRINGPOINT, 97),
 +
 +  /* Instruct libcurl to use a smaller receive buffer */
 +  CINIT(BUFFERSIZE, LONG, 98),
 +
 +  /* Instruct libcurl to not use any signal/alarm handlers, even when using
 +     timeouts. This option is useful for multi-threaded applications.
 +     See libcurl-the-guide for more background information. */
 +  CINIT(NOSIGNAL, LONG, 99),
 +
 +  /* Provide a CURLShare for mutexing non-ts data */
 +  CINIT(SHARE, OBJECTPOINT, 100),
 +
 +  /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
-      CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
++     CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and
++     CURLPROXY_SOCKS5. */
 +  CINIT(PROXYTYPE, LONG, 101),
 +
 +  /* Set the Accept-Encoding string. Use this to tell a server you would like
 +     the response to be compressed. Before 7.21.6, this was known as
 +     CURLOPT_ENCODING */
 +  CINIT(ACCEPT_ENCODING, STRINGPOINT, 102),
 +
 +  /* Set pointer to private data */
 +  CINIT(PRIVATE, OBJECTPOINT, 103),
 +
 +  /* Set aliases for HTTP 200 in the HTTP Response header */
 +  CINIT(HTTP200ALIASES, OBJECTPOINT, 104),
 +
 +  /* Continue to send authentication (user+password) when following locations,
 +     even when hostname changed. This can potentially send off the name
 +     and password to whatever host the server decides. */
 +  CINIT(UNRESTRICTED_AUTH, LONG, 105),
 +
 +  /* Specifically switch on or off the FTP engine's use of the EPRT command (
 +     it also disables the LPRT attempt). By default, those ones will always be
 +     attempted before the good old traditional PORT command. */
 +  CINIT(FTP_USE_EPRT, LONG, 106),
 +
 +  /* Set this to a bitmask value to enable the particular authentications
 +     methods you like. Use this in combination with CURLOPT_USERPWD.
 +     Note that setting multiple bits may cause extra network round-trips. */
 +  CINIT(HTTPAUTH, LONG, 107),
 +
 +  /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx
 +     in second argument. The function must be matching the
 +     curl_ssl_ctx_callback proto. */
 +  CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108),
 +
 +  /* Set the userdata for the ssl context callback function's third
 +     argument */
 +  CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
 +
 +  /* FTP Option that causes missing dirs to be created on the remote server.
 +     In 7.19.4 we introduced the convenience enums for this option using the
 +     CURLFTP_CREATE_DIR prefix.
 +  */
 +  CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110),
 +
 +  /* Set this to a bitmask value to enable the particular authentications
 +     methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
 +     Note that setting multiple bits may cause extra network round-trips. */
 +  CINIT(PROXYAUTH, LONG, 111),
 +
 +  /* FTP option that changes the timeout, in seconds, associated with
 +     getting a response.  This is different from transfer timeout time and
 +     essentially places a demand on the FTP server to acknowledge commands
 +     in a timely manner. */
 +  CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112),
 +#define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
 +
 +  /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
 +     tell libcurl to resolve names to those IP versions only. This only has
 +     affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
 +  CINIT(IPRESOLVE, LONG, 113),
 +
 +  /* Set this option to limit the size of a file that will be downloaded from
 +     an HTTP or FTP server.
 +
 +     Note there is also _LARGE version which adds large file support for
 +     platforms which have larger off_t sizes.  See MAXFILESIZE_LARGE below. */
 +  CINIT(MAXFILESIZE, LONG, 114),
 +
 +  /* See the comment for INFILESIZE above, but in short, specifies
 +   * the size of the file being uploaded.  -1 means unknown.
 +   */
 +  CINIT(INFILESIZE_LARGE, OFF_T, 115),
 +
 +  /* Sets the continuation offset.  There is also a LONG version of this;
 +   * look above for RESUME_FROM.
 +   */
 +  CINIT(RESUME_FROM_LARGE, OFF_T, 116),
 +
 +  /* Sets the maximum size of data that will be downloaded from
 +   * an HTTP or FTP server.  See MAXFILESIZE above for the LONG version.
 +   */
 +  CINIT(MAXFILESIZE_LARGE, OFF_T, 117),
 +
 +  /* Set this option to the file name of your .netrc file you want libcurl
 +     to parse (using the CURLOPT_NETRC option). If not set, libcurl will do
 +     a poor attempt to find the user's home directory and check for a .netrc
 +     file in there. */
 +  CINIT(NETRC_FILE, STRINGPOINT, 118),
 +
 +  /* Enable SSL/TLS for FTP, pick one of:
 +     CURLUSESSL_TRY     - try using SSL, proceed anyway otherwise
 +     CURLUSESSL_CONTROL - SSL for the control connection or fail
 +     CURLUSESSL_ALL     - SSL for all communication or fail
 +  */
 +  CINIT(USE_SSL, LONG, 119),
 +
 +  /* The _LARGE version of the standard POSTFIELDSIZE option */
 +  CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
 +
 +  /* Enable/disable the TCP Nagle algorithm */
 +  CINIT(TCP_NODELAY, LONG, 121),
 +
 +  /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
 +  /* 123 OBSOLETE. Gone in 7.16.0 */
 +  /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
 +  /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
 +  /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
 +  /* 127 OBSOLETE. Gone in 7.16.0 */
 +  /* 128 OBSOLETE. Gone in 7.16.0 */
 +
 +  /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option
 +     can be used to change libcurl's default action which is to first try
 +     "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK
 +     response has been received.
 +
 +     Available parameters are:
 +     CURLFTPAUTH_DEFAULT - let libcurl decide
 +     CURLFTPAUTH_SSL     - try "AUTH SSL" first, then TLS
 +     CURLFTPAUTH_TLS     - try "AUTH TLS" first, then SSL
 +  */
 +  CINIT(FTPSSLAUTH, LONG, 129),
 +
 +  CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130),
 +  CINIT(IOCTLDATA, OBJECTPOINT, 131),
 +
 +  /* 132 OBSOLETE. Gone in 7.16.0 */
 +  /* 133 OBSOLETE. Gone in 7.16.0 */
 +
 +  /* zero terminated string for pass on to the FTP server when asked for
 +     "account" info */
 +  CINIT(FTP_ACCOUNT, STRINGPOINT, 134),
 +
 +  /* feed cookie into cookie engine */
 +  CINIT(COOKIELIST, STRINGPOINT, 135),
 +
 +  /* ignore Content-Length */
 +  CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
 +
 +  /* Set to non-zero to skip the IP address received in a 227 PASV FTP server
 +     response. Typically used for FTP-SSL purposes but is not restricted to
 +     that. libcurl will then instead use the same IP address it used for the
 +     control connection. */
 +  CINIT(FTP_SKIP_PASV_IP, LONG, 137),
 +
 +  /* Select "file method" to use when doing FTP, see the curl_ftpmethod
 +     above. */
 +  CINIT(FTP_FILEMETHOD, LONG, 138),
 +
 +  /* Local port number to bind the socket to */
 +  CINIT(LOCALPORT, LONG, 139),
 +
 +  /* Number of ports to try, including the first one set with LOCALPORT.
 +     Thus, setting it to 1 will make no additional attempts but the first.
 +  */
 +  CINIT(LOCALPORTRANGE, LONG, 140),
 +
 +  /* no transfer, set up connection and let application use the socket by
 +     extracting it with CURLINFO_LASTSOCKET */
 +  CINIT(CONNECT_ONLY, LONG, 141),
 +
 +  /* Function that will be called to convert from the
 +     network encoding (instead of using the iconv calls in libcurl) */
 +  CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142),
 +
 +  /* Function that will be called to convert to the
 +     network encoding (instead of using the iconv calls in libcurl) */
 +  CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143),
 +
 +  /* 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 */
 +  CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
 +
 +  /* if the connection proceeds too quickly then need to slow it down */
 +  /* limit-rate: maximum number of bytes per second to send or receive */
 +  CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145),
 +  CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146),
 +
 +  /* Pointer to command string to send if USER/PASS fails. */
 +  CINIT(FTP_ALTERNATIVE_TO_USER, STRINGPOINT, 147),
 +
 +  /* callback function for setting socket options */
 +  CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148),
 +  CINIT(SOCKOPTDATA, OBJECTPOINT, 149),
 +
 +  /* set to 0 to disable session ID re-use for this transfer, default is
 +     enabled (== 1) */
 +  CINIT(SSL_SESSIONID_CACHE, LONG, 150),
 +
 +  /* allowed SSH authentication methods */
 +  CINIT(SSH_AUTH_TYPES, LONG, 151),
 +
 +  /* Used by scp/sftp to do public/private key authentication */
 +  CINIT(SSH_PUBLIC_KEYFILE, STRINGPOINT, 152),
 +  CINIT(SSH_PRIVATE_KEYFILE, STRINGPOINT, 153),
 +
 +  /* Send CCC (Clear Command Channel) after authentication */
 +  CINIT(FTP_SSL_CCC, LONG, 154),
 +
 +  /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */
 +  CINIT(TIMEOUT_MS, LONG, 155),
 +  CINIT(CONNECTTIMEOUT_MS, LONG, 156),
 +
 +  /* set to zero to disable the libcurl's decoding and thus pass the raw body
 +     data to the application even when it is encoded/compressed */
 +  CINIT(HTTP_TRANSFER_DECODING, LONG, 157),
 +  CINIT(HTTP_CONTENT_DECODING, LONG, 158),
 +
 +  /* Permission used when creating new files and directories on the remote
 +     server for protocols that support it, SFTP/SCP/FILE */
 +  CINIT(NEW_FILE_PERMS, LONG, 159),
 +  CINIT(NEW_DIRECTORY_PERMS, LONG, 160),
 +
 +  /* Set the behaviour of POST when redirecting. Values must be set to one
 +     of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
 +  CINIT(POSTREDIR, LONG, 161),
 +
 +  /* used by scp/sftp to verify the host's public key */
 +  CINIT(SSH_HOST_PUBLIC_KEY_MD5, STRINGPOINT, 162),
 +
 +  /* Callback function for opening socket (instead of socket(2)). Optionally,
 +     callback is able change the address or refuse to connect returning
 +     CURL_SOCKET_BAD.  The callback should have type
 +     curl_opensocket_callback */
 +  CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
 +  CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
 +
 +  /* POST volatile input fields. */
 +  CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
 +
 +  /* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */
 +  CINIT(PROXY_TRANSFER_MODE, LONG, 166),
 +
 +  /* Callback function for seeking in the input stream */
 +  CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
 +  CINIT(SEEKDATA, OBJECTPOINT, 168),
 +
 +  /* CRL file */
 +  CINIT(CRLFILE, STRINGPOINT, 169),
 +
 +  /* Issuer certificate */
 +  CINIT(ISSUERCERT, STRINGPOINT, 170),
 +
 +  /* (IPv6) Address scope */
 +  CINIT(ADDRESS_SCOPE, LONG, 171),
 +
 +  /* Collect certificate chain info and allow it to get retrievable with
 +     CURLINFO_CERTINFO after the transfer is complete. */
 +  CINIT(CERTINFO, LONG, 172),
 +
 +  /* "name" and "pwd" to use when fetching. */
 +  CINIT(USERNAME, STRINGPOINT, 173),
 +  CINIT(PASSWORD, STRINGPOINT, 174),
 +
 +    /* "name" and "pwd" to use with Proxy when fetching. */
 +  CINIT(PROXYUSERNAME, STRINGPOINT, 175),
 +  CINIT(PROXYPASSWORD, STRINGPOINT, 176),
 +
 +  /* Comma separated list of hostnames defining no-proxy zones. These should
 +     match both hostnames directly, and hostnames within a domain. For
 +     example, local.com will match local.com and www.local.com, but NOT
 +     notlocal.com or www.notlocal.com. For compatibility with other
 +     implementations of this, .local.com will be considered to be the same as
 +     local.com. A single * is the only valid wildcard, and effectively
 +     disables the use of proxy. */
 +  CINIT(NOPROXY, STRINGPOINT, 177),
 +
 +  /* block size for TFTP transfers */
 +  CINIT(TFTP_BLKSIZE, LONG, 178),
 +
 +  /* Socks Service */
 +  CINIT(SOCKS5_GSSAPI_SERVICE, STRINGPOINT, 179), /* DEPRECATED, do not use! */
 +
 +  /* Socks Service */
 +  CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
 +
 +  /* set the bitmask for the protocols that are allowed to be used for the
 +     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. */
 +  CINIT(PROTOCOLS, LONG, 181),
 +
 +  /* 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. Defaults
 +     to all protocols except FILE and SCP. */
 +  CINIT(REDIR_PROTOCOLS, LONG, 182),
 +
 +  /* set the SSH knownhost file name to use */
 +  CINIT(SSH_KNOWNHOSTS, STRINGPOINT, 183),
 +
 +  /* set the SSH host key callback, must point to a curl_sshkeycallback
 +     function */
 +  CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184),
 +
 +  /* set the SSH host key callback custom pointer */
 +  CINIT(SSH_KEYDATA, OBJECTPOINT, 185),
 +
 +  /* set the SMTP mail originator */
 +  CINIT(MAIL_FROM, STRINGPOINT, 186),
 +
 +  /* set the list of SMTP mail receiver(s) */
 +  CINIT(MAIL_RCPT, OBJECTPOINT, 187),
 +
 +  /* FTP: send PRET before PASV */
 +  CINIT(FTP_USE_PRET, LONG, 188),
 +
 +  /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
 +  CINIT(RTSP_REQUEST, LONG, 189),
 +
 +  /* The RTSP session identifier */
 +  CINIT(RTSP_SESSION_ID, STRINGPOINT, 190),
 +
 +  /* The RTSP stream URI */
 +  CINIT(RTSP_STREAM_URI, STRINGPOINT, 191),
 +
 +  /* The Transport: header to use in RTSP requests */
 +  CINIT(RTSP_TRANSPORT, STRINGPOINT, 192),
 +
 +  /* Manually initialize the client RTSP CSeq for this handle */
 +  CINIT(RTSP_CLIENT_CSEQ, LONG, 193),
 +
 +  /* Manually initialize the server RTSP CSeq for this handle */
 +  CINIT(RTSP_SERVER_CSEQ, LONG, 194),
 +
 +  /* The stream to pass to INTERLEAVEFUNCTION. */
 +  CINIT(INTERLEAVEDATA, OBJECTPOINT, 195),
 +
 +  /* Let the application define a custom write method for RTP data */
 +  CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196),
 +
 +  /* Turn on wildcard matching */
 +  CINIT(WILDCARDMATCH, LONG, 197),
 +
 +  /* Directory matching callback called before downloading of an
 +     individual file (chunk) started */
 +  CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198),
 +
 +  /* Directory matching callback called after the file (chunk)
 +     was downloaded, or skipped */
 +  CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199),
 +
 +  /* Change match (fnmatch-like) callback for wildcard matching */
 +  CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200),
 +
 +  /* Let the application define custom chunk data pointer */
 +  CINIT(CHUNK_DATA, OBJECTPOINT, 201),
 +
 +  /* FNMATCH_FUNCTION user pointer */
 +  CINIT(FNMATCH_DATA, OBJECTPOINT, 202),
 +
 +  /* send linked-list of name:port:address sets */
 +  CINIT(RESOLVE, OBJECTPOINT, 203),
 +
 +  /* Set a username for authenticated TLS */
 +  CINIT(TLSAUTH_USERNAME, STRINGPOINT, 204),
 +
 +  /* Set a password for authenticated TLS */
 +  CINIT(TLSAUTH_PASSWORD, STRINGPOINT, 205),
 +
 +  /* Set authentication type for authenticated TLS */
 +  CINIT(TLSAUTH_TYPE, STRINGPOINT, 206),
 +
 +  /* Set to 1 to enable the "TE:" header in HTTP requests to ask for
 +     compressed transfer-encoded responses. Set to 0 to disable the use of TE:
 +     in outgoing requests. The current default is 0, but it might change in a
 +     future libcurl release.
 +
 +     libcurl will ask for the compressed methods it knows of, and if that
 +     isn't any, it will not ask for transfer-encoding at all even if this
 +     option is set to 1.
 +
 +  */
 +  CINIT(TRANSFER_ENCODING, LONG, 207),
 +
 +  /* Callback function for closing socket (instead of close(2)). The callback
 +     should have type curl_closesocket_callback */
 +  CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208),
 +  CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209),
 +
 +  /* allow GSSAPI credential delegation */
 +  CINIT(GSSAPI_DELEGATION, LONG, 210),
 +
 +  /* Set the name servers to use for DNS resolution */
 +  CINIT(DNS_SERVERS, STRINGPOINT, 211),
 +
 +  /* Time-out accept operations (currently for FTP only) after this amount
 +     of miliseconds. */
 +  CINIT(ACCEPTTIMEOUT_MS, LONG, 212),
 +
 +  /* Set TCP keepalive */
 +  CINIT(TCP_KEEPALIVE, LONG, 213),
 +
 +  /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */
 +  CINIT(TCP_KEEPIDLE, LONG, 214),
 +  CINIT(TCP_KEEPINTVL, LONG, 215),
 +
 +  /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
 +  CINIT(SSL_OPTIONS, LONG, 216),
 +
 +  /* Set the SMTP auth originator */
 +  CINIT(MAIL_AUTH, STRINGPOINT, 217),
 +
 +  /* Enable/disable SASL initial response */
 +  CINIT(SASL_IR, LONG, 218),
 +
 +  /* Function that will be called instead of the internal progress display
 +   * function. This function should be defined as the curl_xferinfo_callback
 +   * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
 +  CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
 +
 +  /* The XOAUTH2 bearer token */
 +  CINIT(XOAUTH2_BEARER, STRINGPOINT, 220),
 +
 +  /* Set the interface string to use as outgoing network
 +   * interface for DNS requests.
 +   * Only supported by the c-ares DNS backend */
 +  CINIT(DNS_INTERFACE, STRINGPOINT, 221),
 +
 +  /* Set the local IPv4 address to use for outgoing DNS requests.
 +   * Only supported by the c-ares DNS backend */
 +  CINIT(DNS_LOCAL_IP4, STRINGPOINT, 222),
 +
 +  /* Set the local IPv4 address to use for outgoing DNS requests.
 +   * Only supported by the c-ares DNS backend */
 +  CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223),
 +
 +  /* Set authentication options directly */
 +  CINIT(LOGIN_OPTIONS, STRINGPOINT, 224),
 +
 +  /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */
 +  CINIT(SSL_ENABLE_NPN, LONG, 225),
 +
 +  /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */
 +  CINIT(SSL_ENABLE_ALPN, LONG, 226),
 +
 +  /* Time to wait for a response to a HTTP request containing an
 +   * Expect: 100-continue header before sending the data anyway. */
 +  CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227),
 +
 +  /* This points to a linked list of headers used for proxy requests only,
 +     struct curl_slist kind */
 +  CINIT(PROXYHEADER, OBJECTPOINT, 228),
 +
 +  /* Pass in a bitmask of "header options" */
 +  CINIT(HEADEROPT, LONG, 229),
 +
 +  /* The public key in DER form used to validate the peer public key
 +     this option is used only if SSL_VERIFYPEER is true */
 +  CINIT(PINNEDPUBLICKEY, STRINGPOINT, 230),
 +
 +  /* Path to Unix domain socket */
 +  CINIT(UNIX_SOCKET_PATH, STRINGPOINT, 231),
 +
 +  /* Set if we should verify the certificate status. */
 +  CINIT(SSL_VERIFYSTATUS, LONG, 232),
 +
 +  /* Set if we should enable TLS false start. */
 +  CINIT(SSL_FALSESTART, LONG, 233),
 +
 +  /* Do not squash dot-dot sequences */
 +  CINIT(PATH_AS_IS, LONG, 234),
 +
 +  /* Proxy Service Name */
 +  CINIT(PROXY_SERVICE_NAME, STRINGPOINT, 235),
 +
 +  /* Service Name */
 +  CINIT(SERVICE_NAME, STRINGPOINT, 236),
 +
 +  /* Wait/don't wait for pipe/mutex to clarify */
 +  CINIT(PIPEWAIT, LONG, 237),
 +
 +  /* Set the protocol used when curl is given a URL without a protocol */
 +  CINIT(DEFAULT_PROTOCOL, STRINGPOINT, 238),
 +
 +  /* Set stream weight, 1 - 256 (default is 16) */
 +  CINIT(STREAM_WEIGHT, LONG, 239),
 +
 +  /* Set stream dependency on another CURL handle */
 +  CINIT(STREAM_DEPENDS, OBJECTPOINT, 240),
 +
 +  /* Set E-xclusive stream dependency on another CURL handle */
 +  CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241),
 +
 +  /* Do not send any tftp option requests to the server */
 +  CINIT(TFTP_NO_OPTIONS, LONG, 242),
 +
 +  /* Linked-list of host:port:connect-to-host:connect-to-port,
 +     overrides the URL's host:port (only for the network layer) */
 +  CINIT(CONNECT_TO, OBJECTPOINT, 243),
 +
 +  /* Set TCP Fast Open */
 +  CINIT(TCP_FASTOPEN, LONG, 244),
 +
 +  /* Continue to send data if the server responds early with an
 +   * HTTP status code >= 300 */
 +  CINIT(KEEP_SENDING_ON_ERROR, LONG, 245),
 +
++  /* The CApath or CAfile used to validate the proxy certificate
++     this option is used only if PROXY_SSL_VERIFYPEER is true */
++  CINIT(PROXY_CAINFO, STRINGPOINT, 246),
++
++  /* The CApath directory used to validate the proxy certificate
++     this option is used only if PROXY_SSL_VERIFYPEER is true */
++  CINIT(PROXY_CAPATH, STRINGPOINT, 247),
++
++  /* Set if we should verify the proxy in ssl handshake,
++     set 1 to verify. */
++  CINIT(PROXY_SSL_VERIFYPEER, LONG, 248),
++
++  /* Set if we should verify the Common name from the proxy certificate in ssl
++   * handshake, set 1 to check existence, 2 to ensure that it matches
++   * the provided hostname. */
++  CINIT(PROXY_SSL_VERIFYHOST, LONG, 249),
++
++  /* What version to specifically try to use for proxy.
++     See CURL_SSLVERSION defines below. */
++  CINIT(PROXY_SSLVERSION, LONG, 250),
++
++  /* Set a username for authenticated TLS for proxy */
++  CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251),
++
++  /* Set a password for authenticated TLS for proxy */
++  CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252),
++
++  /* Set authentication type for authenticated TLS for proxy */
++  CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253),
++
++  /* name of the file keeping your private SSL-certificate for proxy */
++  CINIT(PROXY_SSLCERT, STRINGPOINT, 254),
++
++  /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for
++     proxy */
++  CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255),
++
++  /* name of the file keeping your private SSL-key for proxy */
++  CINIT(PROXY_SSLKEY, STRINGPOINT, 256),
++
++  /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for
++     proxy */
++  CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257),
++
++  /* password for the SSL private key for proxy */
++  CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258),
++
++  /* Specify which SSL ciphers to use for proxy */
++  CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259),
++
++  /* CRL file for proxy */
++  CINIT(PROXY_CRLFILE, STRINGPOINT, 260),
++
++  /* Enable/disable specific SSL features with a bitmask for proxy, see
++     CURLSSLOPT_* */
++  CINIT(PROXY_SSL_OPTIONS, LONG, 261),
++
++  /* Name of pre proxy to use. */
++  CINIT(PRE_PROXY, STRINGPOINT, 262),
++
++  /* The public key in DER form used to validate the proxy public key
++     this option is used only if PROXY_SSL_VERIFYPEER is true */
++  CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263),
++
 +  CURLOPT_LASTENTRY /* the last unused */
 +} CURLoption;
 +
 +#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
 +                          the obsolete stuff removed! */
 +
 +/* Backwards compatibility with older names */
 +/* These are scheduled to disappear by 2011 */
 +
 +/* This was added in version 7.19.1 */
 +#define CURLOPT_POST301 CURLOPT_POSTREDIR
 +
 +/* These are scheduled to disappear by 2009 */
 +
 +/* The following were added in 7.17.0 */
 +#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD
 +#define CURLOPT_FTPAPPEND CURLOPT_APPEND
 +#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY
 +#define CURLOPT_FTP_SSL CURLOPT_USE_SSL
 +
 +/* The following were added earlier */
 +
 +#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD
 +#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL
 +
 +#else
 +/* This is set if CURL_NO_OLDIES is defined at compile-time */
 +#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */
 +#endif
 +
 +
 +  /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host
 +     name resolves addresses using more than one IP protocol version, this
 +     option might be handy to force libcurl to use a specific IP version. */
 +#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP
 +                                     versions that your system allows */
 +#define CURL_IPRESOLVE_V4       1 /* resolve to IPv4 addresses */
 +#define CURL_IPRESOLVE_V6       2 /* resolve to IPv6 addresses */
 +
 +  /* three convenient "aliases" that follow the name scheme better */
 +#define CURLOPT_RTSPHEADER CURLOPT_HTTPHEADER
 +
 +  /* These enums are for use with the CURLOPT_HTTP_VERSION option. */
 +enum {
 +  CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd
 +                             like the library to choose the best possible
 +                             for us! */
 +  CURL_HTTP_VERSION_1_0,  /* please use HTTP 1.0 in the request */
 +  CURL_HTTP_VERSION_1_1,  /* please use HTTP 1.1 in the request */
 +  CURL_HTTP_VERSION_2_0,  /* please use HTTP 2 in the request */
 +  CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */
 +  CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE,  /* please use HTTP 2 without HTTP/1.1
 +                                           Upgrade */
 +
 +  CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
 +};
 +
 +/* Convenience definition simple because the name of the version is HTTP/2 and
 +   not 2.0. The 2_0 version of the enum name was set while the version was
 +   still planned to be 2.0 and we stick to it for compatibility. */
 +#define CURL_HTTP_VERSION_2 CURL_HTTP_VERSION_2_0
 +
 +/*
 + * Public API enums for RTSP requests
 + */
 +enum {
 +    CURL_RTSPREQ_NONE, /* first in list */
 +    CURL_RTSPREQ_OPTIONS,
 +    CURL_RTSPREQ_DESCRIBE,
 +    CURL_RTSPREQ_ANNOUNCE,
 +    CURL_RTSPREQ_SETUP,
 +    CURL_RTSPREQ_PLAY,
 +    CURL_RTSPREQ_PAUSE,
 +    CURL_RTSPREQ_TEARDOWN,
 +    CURL_RTSPREQ_GET_PARAMETER,
 +    CURL_RTSPREQ_SET_PARAMETER,
 +    CURL_RTSPREQ_RECORD,
 +    CURL_RTSPREQ_RECEIVE,
 +    CURL_RTSPREQ_LAST /* last in list */
 +};
 +
 +  /* These enums are for use with the CURLOPT_NETRC option. */
 +enum CURL_NETRC_OPTION {
 +  CURL_NETRC_IGNORED,     /* The .netrc will never be read.
 +                           * This is the default. */
 +  CURL_NETRC_OPTIONAL,    /* A user:password in the URL will be preferred
 +                           * to one in the .netrc. */
 +  CURL_NETRC_REQUIRED,    /* A user:password in the URL will be ignored.
 +                           * Unless one is set programmatically, the .netrc
 +                           * will be queried. */
 +  CURL_NETRC_LAST
 +};
 +
 +enum {
 +  CURL_SSLVERSION_DEFAULT,
 +  CURL_SSLVERSION_TLSv1, /* TLS 1.x */
 +  CURL_SSLVERSION_SSLv2,
 +  CURL_SSLVERSION_SSLv3,
 +  CURL_SSLVERSION_TLSv1_0,
 +  CURL_SSLVERSION_TLSv1_1,
 +  CURL_SSLVERSION_TLSv1_2,
++  CURL_SSLVERSION_TLSv1_3,
 +
 +  CURL_SSLVERSION_LAST /* never use, keep last */
 +};
 +
 +enum CURL_TLSAUTH {
 +  CURL_TLSAUTH_NONE,
 +  CURL_TLSAUTH_SRP,
 +  CURL_TLSAUTH_LAST /* never use, keep last */
 +};
 +
 +/* symbols to use with CURLOPT_POSTREDIR.
 +   CURL_REDIR_POST_301, CURL_REDIR_POST_302 and CURL_REDIR_POST_303
 +   can be bitwise ORed so that CURL_REDIR_POST_301 | CURL_REDIR_POST_302
 +   | CURL_REDIR_POST_303 == CURL_REDIR_POST_ALL */
 +
 +#define CURL_REDIR_GET_ALL  0
 +#define CURL_REDIR_POST_301 1
 +#define CURL_REDIR_POST_302 2
 +#define CURL_REDIR_POST_303 4
 +#define CURL_REDIR_POST_ALL \
 +    (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303)
 +
 +typedef enum {
 +  CURL_TIMECOND_NONE,
 +
 +  CURL_TIMECOND_IFMODSINCE,
 +  CURL_TIMECOND_IFUNMODSINCE,
 +  CURL_TIMECOND_LASTMOD,
 +
 +  CURL_TIMECOND_LAST
 +} curl_TimeCond;
 +
 +
 +/* curl_strequal() and curl_strnequal() are subject for removal in a future
-    libcurl, see lib/README.curlx for details */
++   libcurl, see lib/README.curlx for details
++
++   !checksrc! disable SPACEBEFOREPAREN 2
++*/
 +CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
 +CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
 +
 +/* name is uppercase CURLFORM_<name> */
 +#ifdef CFINIT
 +#undef CFINIT
 +#endif
 +
 +#ifdef CURL_ISOCPP
 +#define CFINIT(name) CURLFORM_ ## name
 +#else
 +/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
 +#define CFINIT(name) CURLFORM_/**/name
 +#endif
 +
 +typedef enum {
 +  CFINIT(NOTHING),        /********* the first one is unused ************/
 +
 +  /*  */
 +  CFINIT(COPYNAME),
 +  CFINIT(PTRNAME),
 +  CFINIT(NAMELENGTH),
 +  CFINIT(COPYCONTENTS),
 +  CFINIT(PTRCONTENTS),
 +  CFINIT(CONTENTSLENGTH),
 +  CFINIT(FILECONTENT),
 +  CFINIT(ARRAY),
 +  CFINIT(OBSOLETE),
 +  CFINIT(FILE),
 +
 +  CFINIT(BUFFER),
 +  CFINIT(BUFFERPTR),
 +  CFINIT(BUFFERLENGTH),
 +
 +  CFINIT(CONTENTTYPE),
 +  CFINIT(CONTENTHEADER),
 +  CFINIT(FILENAME),
 +  CFINIT(END),
 +  CFINIT(OBSOLETE2),
 +
 +  CFINIT(STREAM),
 +  CFINIT(CONTENTLEN), /* added in 7.46.0, provide a curl_off_t length */
 +
 +  CURLFORM_LASTENTRY /* the last unused */
 +} CURLformoption;
 +
 +#undef CFINIT /* done */
 +
 +/* structure to be used as parameter for CURLFORM_ARRAY */
 +struct curl_forms {
 +  CURLformoption option;
 +  const char     *value;
 +};
 +
 +/* use this for multipart formpost building */
 +/* Returns code for curl_formadd()
 + *
 + * Returns:
 + * CURL_FORMADD_OK             on success
 + * CURL_FORMADD_MEMORY         if the FormInfo allocation fails
 + * CURL_FORMADD_OPTION_TWICE   if one option is given twice for one Form
 + * CURL_FORMADD_NULL           if a null pointer was given for a char
 + * 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 curl_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
 + *
 + ***************************************************************************/
 +typedef enum {
 +  CURL_FORMADD_OK, /* first, 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_LAST /* last */
 +} CURLFORMcode;
 +
 +/*
 + * NAME curl_formadd()
 + *
 + * DESCRIPTION
 + *
 + * Pretty advanced function for building multi-part formposts. Each invoke
 + * 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,
 +                                      ...);
 +
 +/*
 + * callback function for curl_formget()
 + * The void *arg pointer will be the one passed as second argument to
 + *   curl_formget().
 + * The character buffer passed to it must not be freed.
 + * Should return the buffer length passed to it as the argument "len" on
 + *   success.
 + */
 +typedef size_t (*curl_formget_callback)(void *arg, const char *buf,
 +                                        size_t len);
 +
 +/*
 + * NAME curl_formget()
 + *
 + * DESCRIPTION
 + *
 + * Serialize a curl_httppost struct built with curl_formadd().
 + * Accepts a void pointer as second argument which will be passed to
 + * the curl_formget_callback function.
 + * Returns 0 on success.
 + */
 +CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
 +                             curl_formget_callback append);
 +/*
 + * NAME curl_formfree()
 + *
 + * DESCRIPTION
 + *
 + * Free a multipart formpost previously built with curl_formadd().
 + */
 +CURL_EXTERN void curl_formfree(struct curl_httppost *form);
 +
 +/*
 + * NAME curl_getenv()
 + *
 + * DESCRIPTION
 + *
 + * Returns a malloc()'ed string that MUST be curl_free()ed after usage is
 + * complete. DEPRECATED - see lib/README.curlx
 + */
 +CURL_EXTERN char *curl_getenv(const char *variable);
 +
 +/*
 + * NAME curl_version()
 + *
 + * DESCRIPTION
 + *
 + * Returns a static ascii string of the libcurl version.
 + */
 +CURL_EXTERN char *curl_version(void);
 +
 +/*
 + * NAME curl_easy_escape()
 + *
 + * DESCRIPTION
 + *
 + * Escapes URL strings (converts all letters consider illegal in URLs to their
 + * %XX versions). This function returns a new allocated string or NULL if an
 + * error occurred.
 + */
 +CURL_EXTERN char *curl_easy_escape(CURL *handle,
 +                                   const char *string,
 +                                   int length);
 +
 +/* the previous version: */
 +CURL_EXTERN char *curl_escape(const char *string,
 +                              int length);
 +
 +
 +/*
 + * NAME curl_easy_unescape()
 + *
 + * DESCRIPTION
 + *
 + * Unescapes URL encoding in strings (converts all %XX codes to their 8bit
 + * versions). This function returns a new allocated string or NULL if an error
 + * occurred.
 + * Conversion Note: On non-ASCII platforms the ASCII %XX codes are
 + * converted into the host encoding.
 + */
 +CURL_EXTERN char *curl_easy_unescape(CURL *handle,
 +                                     const char *string,
 +                                     int length,
 +                                     int *outlength);
 +
 +/* the previous version */
 +CURL_EXTERN char *curl_unescape(const char *string,
 +                                int length);
 +
 +/*
 + * NAME curl_free()
 + *
 + * DESCRIPTION
 + *
 + * Provided for de-allocation in the same translation unit that did the
 + * allocation. Added in libcurl 7.10
 + */
 +CURL_EXTERN void curl_free(void *p);
 +
 +/*
 + * NAME curl_global_init()
 + *
 + * DESCRIPTION
 + *
 + * curl_global_init() should be invoked exactly once for each application that
 + * uses libcurl and before any call of other libcurl functions.
 + *
 + * This function is not thread-safe!
 + */
 +CURL_EXTERN CURLcode curl_global_init(long flags);
 +
 +/*
 + * NAME curl_global_init_mem()
 + *
 + * DESCRIPTION
 + *
 + * curl_global_init() or curl_global_init_mem() should be invoked exactly once
 + * for each application that uses libcurl.  This function can be used to
 + * initialize libcurl and set user defined memory management callback
 + * functions.  Users can implement memory management routines to check for
 + * memory leaks, check for mis-use of the curl library etc.  User registered
 + * callback routines with be invoked by this library instead of the system
 + * memory management routines like malloc, free etc.
 + */
 +CURL_EXTERN CURLcode curl_global_init_mem(long flags,
 +                                          curl_malloc_callback m,
 +                                          curl_free_callback f,
 +                                          curl_realloc_callback r,
 +                                          curl_strdup_callback s,
 +                                          curl_calloc_callback c);
 +
 +/*
 + * NAME curl_global_cleanup()
 + *
 + * DESCRIPTION
 + *
 + * curl_global_cleanup() should be invoked exactly once for each application
 + * that uses libcurl
 + */
 +CURL_EXTERN void curl_global_cleanup(void);
 +
 +/* linked-list structure for the CURLOPT_QUOTE option (and other) */
 +struct curl_slist {
 +  char *data;
 +  struct curl_slist *next;
 +};
 +
 +/*
 + * NAME curl_slist_append()
 + *
 + * DESCRIPTION
 + *
 + * 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 *);
 +
 +/*
 + * NAME curl_slist_free_all()
 + *
 + * DESCRIPTION
 + *
 + * free a previously built curl_slist.
 + */
 +CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
 +
 +/*
 + * NAME curl_getdate()
 + *
 + * DESCRIPTION
 + *
 + * Returns the time, in seconds since 1 Jan 1970 of the time string given in
 + * the first argument. The time argument in the second parameter is unused
 + * and should be set to NULL.
 + */
 +CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
 +
 +/* info about the certificate chain, only for OpenSSL builds. Asked
 +   for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */
 +struct curl_certinfo {
 +  int num_of_certs;             /* number of certificates with information */
 +  struct curl_slist **certinfo; /* for each index in this array, there's a
 +                                   linked list with textual information in the
 +                                   format "name: value" */
 +};
 +
 +/* enum for the different supported SSL backends */
 +typedef enum {
 +  CURLSSLBACKEND_NONE = 0,
 +  CURLSSLBACKEND_OPENSSL = 1,
 +  CURLSSLBACKEND_GNUTLS = 2,
 +  CURLSSLBACKEND_NSS = 3,
 +  CURLSSLBACKEND_OBSOLETE4 = 4,  /* Was QSOSSL. */
 +  CURLSSLBACKEND_GSKIT = 5,
 +  CURLSSLBACKEND_POLARSSL = 6,
 +  CURLSSLBACKEND_CYASSL = 7,
 +  CURLSSLBACKEND_SCHANNEL = 8,
 +  CURLSSLBACKEND_DARWINSSL = 9,
 +  CURLSSLBACKEND_AXTLS = 10,
 +  CURLSSLBACKEND_MBEDTLS = 11
 +} curl_sslbackend;
 +
 +/* aliases for library clones and renames */
 +#define CURLSSLBACKEND_LIBRESSL 1
 +#define CURLSSLBACKEND_BORINGSSL 1
 +#define CURLSSLBACKEND_WOLFSSL 6
 +
 +/* Information about the SSL library used and the respective internal SSL
 +   handle, which can be used to obtain further information regarding the
 +   connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */
 +struct curl_tlssessioninfo {
 +  curl_sslbackend backend;
 +  void *internals;
 +};
 +
 +#define CURLINFO_STRING   0x100000
 +#define CURLINFO_LONG     0x200000
 +#define CURLINFO_DOUBLE   0x300000
 +#define CURLINFO_SLIST    0x400000
 +#define CURLINFO_SOCKET   0x500000
 +#define CURLINFO_MASK     0x0fffff
 +#define CURLINFO_TYPEMASK 0xf00000
 +
 +typedef enum {
 +  CURLINFO_NONE, /* first, never use this */
 +  CURLINFO_EFFECTIVE_URL    = CURLINFO_STRING + 1,
 +  CURLINFO_RESPONSE_CODE    = CURLINFO_LONG   + 2,
 +  CURLINFO_TOTAL_TIME       = CURLINFO_DOUBLE + 3,
 +  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_DOWNLOAD    = CURLINFO_DOUBLE + 8,
 +  CURLINFO_SPEED_DOWNLOAD   = CURLINFO_DOUBLE + 9,
 +  CURLINFO_SPEED_UPLOAD     = CURLINFO_DOUBLE + 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_CONTENT_LENGTH_DOWNLOAD   = CURLINFO_DOUBLE + 15,
 +  CURLINFO_CONTENT_LENGTH_UPLOAD     = CURLINFO_DOUBLE + 16,
 +  CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
 +  CURLINFO_CONTENT_TYPE     = CURLINFO_STRING + 18,
 +  CURLINFO_REDIRECT_TIME    = CURLINFO_DOUBLE + 19,
 +  CURLINFO_REDIRECT_COUNT   = CURLINFO_LONG   + 20,
 +  CURLINFO_PRIVATE          = CURLINFO_STRING + 21,
 +  CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG   + 22,
 +  CURLINFO_HTTPAUTH_AVAIL   = CURLINFO_LONG   + 23,
 +  CURLINFO_PROXYAUTH_AVAIL  = CURLINFO_LONG   + 24,
 +  CURLINFO_OS_ERRNO         = CURLINFO_LONG   + 25,
 +  CURLINFO_NUM_CONNECTS     = CURLINFO_LONG   + 26,
 +  CURLINFO_SSL_ENGINES      = CURLINFO_SLIST  + 27,
 +  CURLINFO_COOKIELIST       = CURLINFO_SLIST  + 28,
 +  CURLINFO_LASTSOCKET       = CURLINFO_LONG   + 29,
 +  CURLINFO_FTP_ENTRY_PATH   = CURLINFO_STRING + 30,
 +  CURLINFO_REDIRECT_URL     = CURLINFO_STRING + 31,
 +  CURLINFO_PRIMARY_IP       = CURLINFO_STRING + 32,
 +  CURLINFO_APPCONNECT_TIME  = CURLINFO_DOUBLE + 33,
 +  CURLINFO_CERTINFO         = CURLINFO_SLIST  + 34,
 +  CURLINFO_CONDITION_UNMET  = CURLINFO_LONG   + 35,
 +  CURLINFO_RTSP_SESSION_ID  = CURLINFO_STRING + 36,
 +  CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG   + 37,
 +  CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG   + 38,
 +  CURLINFO_RTSP_CSEQ_RECV   = CURLINFO_LONG   + 39,
 +  CURLINFO_PRIMARY_PORT     = CURLINFO_LONG   + 40,
 +  CURLINFO_LOCAL_IP         = CURLINFO_STRING + 41,
 +  CURLINFO_LOCAL_PORT       = CURLINFO_LONG   + 42,
 +  CURLINFO_TLS_SESSION      = CURLINFO_SLIST  + 43,
 +  CURLINFO_ACTIVESOCKET     = CURLINFO_SOCKET + 44,
 +  CURLINFO_TLS_SSL_PTR      = CURLINFO_SLIST  + 45,
 +  CURLINFO_HTTP_VERSION     = CURLINFO_LONG   + 46,
++  CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
++  CURLINFO_PROTOCOL         = CURLINFO_LONG   + 48,
++  CURLINFO_SCHEME           = CURLINFO_STRING + 49,
 +  /* Fill in new entries below here! */
 +
-   CURLINFO_LASTONE          = 46
++  CURLINFO_LASTONE          = 49
 +} CURLINFO;
 +
 +/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
 +   CURLINFO_HTTP_CODE */
 +#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE
 +
 +typedef enum {
 +  CURLCLOSEPOLICY_NONE, /* first, never use this */
 +
 +  CURLCLOSEPOLICY_OLDEST,
 +  CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
 +  CURLCLOSEPOLICY_LEAST_TRAFFIC,
 +  CURLCLOSEPOLICY_SLOWEST,
 +  CURLCLOSEPOLICY_CALLBACK,
 +
 +  CURLCLOSEPOLICY_LAST /* last, never use this */
 +} curl_closepolicy;
 +
 +#define CURL_GLOBAL_SSL (1<<0)
 +#define CURL_GLOBAL_WIN32 (1<<1)
 +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32)
 +#define CURL_GLOBAL_NOTHING 0
 +#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL
 +#define CURL_GLOBAL_ACK_EINTR (1<<2)
 +
 +
 +/*****************************************************************************
 + * Setup defines, protos etc for the sharing stuff.
 + */
 +
 +/* Different data locks for a single share */
 +typedef enum {
 +  CURL_LOCK_DATA_NONE = 0,
 +  /*  CURL_LOCK_DATA_SHARE is used internally to say that
 +   *  the locking is just made to change the internal state of the share
 +   *  itself.
 +   */
 +  CURL_LOCK_DATA_SHARE,
 +  CURL_LOCK_DATA_COOKIE,
 +  CURL_LOCK_DATA_DNS,
 +  CURL_LOCK_DATA_SSL_SESSION,
 +  CURL_LOCK_DATA_CONNECT,
 +  CURL_LOCK_DATA_LAST
 +} curl_lock_data;
 +
 +/* Different lock access types */
 +typedef enum {
 +  CURL_LOCK_ACCESS_NONE = 0,   /* unspecified action */
 +  CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */
 +  CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */
 +  CURL_LOCK_ACCESS_LAST        /* never use */
 +} curl_lock_access;
 +
 +typedef void (*curl_lock_function)(CURL *handle,
 +                                   curl_lock_data data,
 +                                   curl_lock_access locktype,
 +                                   void *userptr);
 +typedef void (*curl_unlock_function)(CURL *handle,
 +                                     curl_lock_data data,
 +                                     void *userptr);
 +
 +
 +typedef enum {
 +  CURLSHE_OK,  /* all is fine */
 +  CURLSHE_BAD_OPTION, /* 1 */
 +  CURLSHE_IN_USE,     /* 2 */
 +  CURLSHE_INVALID,    /* 3 */
 +  CURLSHE_NOMEM,      /* 4 out of memory */
 +  CURLSHE_NOT_BUILT_IN, /* 5 feature not present in lib */
 +  CURLSHE_LAST        /* never use */
 +} CURLSHcode;
 +
 +typedef enum {
 +  CURLSHOPT_NONE,  /* don't use */
 +  CURLSHOPT_SHARE,   /* specify a data type to share */
 +  CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */
 +  CURLSHOPT_LOCKFUNC,   /* pass in a 'curl_lock_function' pointer */
 +  CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */
 +  CURLSHOPT_USERDATA,   /* pass in a user data pointer used in the lock/unlock
 +                           callback functions */
 +  CURLSHOPT_LAST  /* never use */
 +} CURLSHoption;
 +
 +CURL_EXTERN CURLSH *curl_share_init(void);
 +CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...);
 +CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *);
 +
 +/****************************************************************************
 + * Structures for querying information about the curl library at runtime.
 + */
 +
 +typedef enum {
 +  CURLVERSION_FIRST,
 +  CURLVERSION_SECOND,
 +  CURLVERSION_THIRD,
 +  CURLVERSION_FOURTH,
 +  CURLVERSION_LAST /* never actually use this */
 +} CURLversion;
 +
 +/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by
 +   basically all programs ever that want to get version information. It is
 +   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_FOURTH
 +
 +typedef struct {
 +  CURLversion age;          /* age of the returned struct */
 +  const char *version;      /* LIBCURL_VERSION */
 +  unsigned int version_num; /* LIBCURL_VERSION_NUM */
 +  const char *host;         /* OS/host/cpu/machine when configured */
 +  int features;             /* bitmask, see defines below */
 +  const char *ssl_version;  /* human readable string */
 +  long ssl_version_num;     /* not used anymore, always 0 */
 +  const char *libz_version; /* human readable string */
 +  /* protocols is terminated by an entry with a NULL protoname */
 +  const char * const *protocols;
 +
 +  /* The fields below this were added in CURLVERSION_SECOND */
 +  const char *ares;
 +  int ares_num;
 +
 +  /* This field was added in CURLVERSION_THIRD */
 +  const char *libidn;
 +
 +  /* These field were added in CURLVERSION_FOURTH */
 +
 +  /* Same as '_libiconv_version' if built with HAVE_ICONV */
 +  int iconv_ver_num;
 +
 +  const char *libssh_version; /* human readable string */
 +
 +} curl_version_info_data;
 +
 +#define CURL_VERSION_IPV6         (1<<0)  /* IPv6-enabled */
 +#define CURL_VERSION_KERBEROS4    (1<<1)  /* Kerberos V4 auth is supported
 +                                             (deprecated) */
 +#define CURL_VERSION_SSL          (1<<2)  /* SSL options are present */
 +#define CURL_VERSION_LIBZ         (1<<3)  /* libz features are present */
 +#define CURL_VERSION_NTLM         (1<<4)  /* NTLM auth is supported */
 +#define CURL_VERSION_GSSNEGOTIATE (1<<5)  /* Negotiate auth is supported
 +                                             (deprecated) */
 +#define CURL_VERSION_DEBUG        (1<<6)  /* Built with debug capabilities */
 +#define CURL_VERSION_ASYNCHDNS    (1<<7)  /* Asynchronous DNS resolves */
 +#define CURL_VERSION_SPNEGO       (1<<8)  /* SPNEGO auth is supported */
 +#define CURL_VERSION_LARGEFILE    (1<<9)  /* Supports files larger than 2GB */
 +#define CURL_VERSION_IDN          (1<<10) /* Internationized Domain Names are
 +                                             supported */
 +#define CURL_VERSION_SSPI         (1<<11) /* Built against Windows SSPI */
 +#define CURL_VERSION_CONV         (1<<12) /* Character conversions supported */
 +#define CURL_VERSION_CURLDEBUG    (1<<13) /* Debug memory tracking supported */
 +#define CURL_VERSION_TLSAUTH_SRP  (1<<14) /* TLS-SRP auth is supported */
 +#define CURL_VERSION_NTLM_WB      (1<<15) /* NTLM delegation to winbind helper
 +                                             is suported */
 +#define CURL_VERSION_HTTP2        (1<<16) /* HTTP2 support built-in */
 +#define CURL_VERSION_GSSAPI       (1<<17) /* Built against a GSS-API library */
 +#define CURL_VERSION_KERBEROS5    (1<<18) /* Kerberos V5 auth is supported */
 +#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */
 +#define CURL_VERSION_PSL          (1<<20) /* Mozilla's Public Suffix List, used
 +                                             for cookie domain verification */
++#define CURL_VERSION_HTTPS_PROXY  (1<<21) /* HTTPS-proxy support built-in */
 +
 + /*
 + * NAME curl_version_info()
 + *
 + * DESCRIPTION
 + *
 + * This function returns a pointer to a static copy of the version info
 + * struct. See above.
 + */
 +CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion);
 +
 +/*
 + * NAME curl_easy_strerror()
 + *
 + * DESCRIPTION
 + *
 + * The curl_easy_strerror function may be used to turn a CURLcode value
 + * into the equivalent human readable error string.  This is useful
 + * for printing meaningful error messages.
 + */
 +CURL_EXTERN const char *curl_easy_strerror(CURLcode);
 +
 +/*
 + * NAME curl_share_strerror()
 + *
 + * DESCRIPTION
 + *
 + * The curl_share_strerror function may be used to turn a CURLSHcode value
 + * into the equivalent human readable error string.  This is useful
 + * for printing meaningful error messages.
 + */
 +CURL_EXTERN const char *curl_share_strerror(CURLSHcode);
 +
 +/*
 + * NAME curl_easy_pause()
 + *
 + * DESCRIPTION
 + *
 + * The curl_easy_pause function pauses or unpauses transfers. Select the new
 + * state by setting the bitmask, use the convenience defines below.
 + *
 + */
 +CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask);
 +
 +#define CURLPAUSE_RECV      (1<<0)
 +#define CURLPAUSE_RECV_CONT (0)
 +
 +#define CURLPAUSE_SEND      (1<<2)
 +#define CURLPAUSE_SEND_CONT (0)
 +
 +#define CURLPAUSE_ALL       (CURLPAUSE_RECV|CURLPAUSE_SEND)
 +#define CURLPAUSE_CONT      (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT)
 +
 +#ifdef  __cplusplus
 +}
 +#endif
 +
 +/* unfortunately, the easy.h and multi.h include files need options and info
 +  stuff before they can be included! */
 +#include "easy.h" /* nothing in curl is fun without the easy stuff */
 +#include "multi.h"
 +
 +/* the typechecker doesn't work in C++ (yet) */
 +#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \
 +    ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \
 +    !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK)
 +#include "typecheck-gcc.h"
 +#else
 +#if defined(__STDC__) && (__STDC__ >= 1)
 +#if 0 /* Triggers clang -Wdisabled-macro-expansion, skip for CMake.  */
 +/* This preprocessor magic that replaces a call with the exact same call is
 +   only done to make sure application authors pass exactly three arguments
 +   to these functions. */
 +#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param)
 +#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg)
 +#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
 +#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
 +#endif
 +#endif /* __STDC__ >= 1 */
 +#endif /* gcc >= 4.3 && !__cplusplus */
 +
 +#endif /* __CURL_CURL_H */
diff --cc Utilities/cmcurl/include/curl/curlver.h
index 2415d1a,0000000..3967ad2
mode 100644,000000..100644
--- a/Utilities/cmcurl/include/curl/curlver.h
+++ b/Utilities/cmcurl/include/curl/curlver.h
@@@ -1,77 -1,0 +1,77 @@@
 +#ifndef __CURL_CURLVER_H
 +#define __CURL_CURLVER_H
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
 + * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
 + *
 + * This software is licensed as described in the file COPYING, which
 + * you should have received as part of this distribution. The terms
 + * are also available at https://curl.haxx.se/docs/copyright.html.
 + *
 + * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 + * copies of the Software, and permit persons to whom the Software is
 + * furnished to do so, under the terms of the COPYING file.
 + *
 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 + * KIND, either express or implied.
 + *
 + ***************************************************************************/
 +
 +/* This header file contains nothing but libcurl version info, generated by
 +   a script at release-time. This was made its own header file in 7.11.2 */
 +
 +/* This is the global package copyright */
 +#define LIBCURL_COPYRIGHT "1996 - 2016 Daniel Stenberg, <daniel at haxx.se>."
 +
 +/* This is the version number of the libcurl package from which this header
 +   file origins: */
- #define LIBCURL_VERSION "7.51.0"
++#define LIBCURL_VERSION "7.52.1"
 +
 +/* The numeric version number is also available "in parts" by using these
 +   defines: */
 +#define LIBCURL_VERSION_MAJOR 7
- #define LIBCURL_VERSION_MINOR 51
- #define LIBCURL_VERSION_PATCH 0
++#define LIBCURL_VERSION_MINOR 52
++#define LIBCURL_VERSION_PATCH 1
 +
 +/* This is the numeric version of the libcurl version number, meant for easier
 +   parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
 +   always follow this syntax:
 +
 +         0xXXYYZZ
 +
 +   Where XX, YY and ZZ are the main version, release and patch numbers in
 +   hexadecimal (using 8 bits each). All three numbers are always represented
 +   using two digits.  1.2 would appear as "0x010200" while version 9.11.7
 +   appears as "0x090b07".
 +
 +   This 6-digit (24 bits) hexadecimal number does not show pre-release number,
 +   and it is always a greater number in a more recent release. It makes
 +   comparisons with greater than and less than work.
 +
 +   Note: This define is the full hex number and _does not_ use the
 +   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 0x073300
++#define LIBCURL_VERSION_NUM 0x073401
 +
 +/*
 + * This is the date and time when the full source package was created. The
 + * timestamp is not stored in git, as the timestamp is properly set in the
 + * tarballs by the maketgz script.
 + *
 + * The format of the date should follow this template:
 + *
 + * "Mon Feb 12 11:35:33 UTC 2007"
 + */
 +#define LIBCURL_TIMESTAMP "DEV"
 +
 +#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
 +#define CURL_AT_LEAST_VERSION(x,y,z) \
 +  (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
 +
 +#endif /* __CURL_CURLVER_H */
diff --cc Utilities/cmcurl/lib/curl_setup.h
index 4eb17a1,0000000..c861e97
mode 100644,000000..100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@@ -1,780 -1,0 +1,780 @@@
 +#ifndef HEADER_CURL_SETUP_H
 +#define HEADER_CURL_SETUP_H
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
 + * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
 + *
 + * This software is licensed as described in the file COPYING, which
 + * you should have received as part of this distribution. The terms
 + * are also available at https://curl.haxx.se/docs/copyright.html.
 + *
 + * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 + * copies of the Software, and permit persons to whom the Software is
 + * furnished to do so, under the terms of the COPYING file.
 + *
 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 + * KIND, either express or implied.
 + *
 + ***************************************************************************/
 +
 +/*
 + * Define WIN32 when build target is Win32 API
 + */
 +
 +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) && \
 +    !defined(__SYMBIAN32__)
 +#define WIN32
 +#endif
 +
 +/*
 + * Include configuration script results or hand-crafted
 + * configuration file for platforms which lack config tool.
 + */
 +
 +#ifdef HAVE_CONFIG_H
 +
 +#include "curl_config.h"
 +
 +#else /* HAVE_CONFIG_H */
 +
 +#ifdef _WIN32_WCE
 +#  include "config-win32ce.h"
 +#else
 +#  ifdef WIN32
 +#    include "config-win32.h"
 +#  endif
 +#endif
 +
 +#if defined(macintosh) && defined(__MRC__)
 +#  include "config-mac.h"
 +#endif
 +
 +#ifdef __riscos__
 +#  include "config-riscos.h"
 +#endif
 +
 +#ifdef __AMIGA__
 +#  include "config-amigaos.h"
 +#endif
 +
 +#ifdef __SYMBIAN32__
 +#  include "config-symbian.h"
 +#endif
 +
 +#ifdef __OS400__
 +#  include "config-os400.h"
 +#endif
 +
 +#ifdef TPF
 +#  include "config-tpf.h"
 +#endif
 +
 +#ifdef __VXWORKS__
 +#  include "config-vxworks.h"
 +#endif
 +
 +#endif /* HAVE_CONFIG_H */
 +
 +#if defined(_MSC_VER)
 +# pragma warning(push,1)
 +#endif
 +
 +/* ================================================================ */
 +/* Definition of preprocessor macros/symbols which modify compiler  */
 +/* behavior or generated code characteristics must be done here,   */
 +/* as appropriate, before any system header file is included. It is */
 +/* also possible to have them defined in the config file included   */
 +/* before this point. As a result of all this we frown inclusion of */
 +/* system header files in our config files, avoid this at any cost. */
 +/* ================================================================ */
 +
 +/*
 + * AIX 4.3 and newer needs _THREAD_SAFE defined to build
 + * proper reentrant code. Others may also need it.
 + */
 +
 +#ifdef NEED_THREAD_SAFE
 +#  ifndef _THREAD_SAFE
 +#    define _THREAD_SAFE
 +#  endif
 +#endif
 +
 +/*
 + * Tru64 needs _REENTRANT set for a few function prototypes and
 + * things to appear in the system header files. Unixware needs it
 + * to build proper reentrant code. Others may also need it.
 + */
 +
 +#ifdef NEED_REENTRANT
 +#  ifndef _REENTRANT
 +#    define _REENTRANT
 +#  endif
 +#endif
 +
 +/* Solaris needs this to get a POSIX-conformant getpwuid_r */
 +#if defined(sun) || defined(__sun)
 +#  ifndef _POSIX_PTHREAD_SEMANTICS
 +#    define _POSIX_PTHREAD_SEMANTICS 1
 +#  endif
 +#endif
 +
 +/* ================================================================ */
 +/*  If you need to include a system header file for your platform,  */
 +/*  please, do it beyond the point further indicated in this file.  */
 +/* ================================================================ */
 +
 +/*
 + * libcurl's external interface definitions are also used internally,
 + * and might also include required system header files to define them.
 + */
 +
 +#include <curl/curlbuild.h>
 +
 +/*
 + * Compile time sanity checks must also be done when building the library.
 + */
 +
 +#include <curl/curlrules.h>
 +
 +/*
 + * Ensure that no one is using the old SIZEOF_CURL_OFF_T macro
 + */
 +
 +#ifdef SIZEOF_CURL_OFF_T
 +#  error "SIZEOF_CURL_OFF_T shall not be defined!"
 +   Error Compilation_aborted_SIZEOF_CURL_OFF_T_shall_not_be_defined
 +#endif
 +
 +/*
 + * Disable other protocols when http is the only one desired.
 + */
 +
 +#ifdef HTTP_ONLY
 +#  ifndef CURL_DISABLE_TFTP
 +#    define CURL_DISABLE_TFTP
 +#  endif
 +#  ifndef CURL_DISABLE_FTP
 +#    define CURL_DISABLE_FTP
 +#  endif
 +#  ifndef CURL_DISABLE_LDAP
 +#    define CURL_DISABLE_LDAP
 +#  endif
 +#  ifndef CURL_DISABLE_TELNET
 +#    define CURL_DISABLE_TELNET
 +#  endif
 +#  ifndef CURL_DISABLE_DICT
 +#    define CURL_DISABLE_DICT
 +#  endif
 +#  ifndef CURL_DISABLE_FILE
 +#    define CURL_DISABLE_FILE
 +#  endif
 +#  ifndef CURL_DISABLE_RTSP
 +#    define CURL_DISABLE_RTSP
 +#  endif
 +#  ifndef CURL_DISABLE_POP3
 +#    define CURL_DISABLE_POP3
 +#  endif
 +#  ifndef CURL_DISABLE_IMAP
 +#    define CURL_DISABLE_IMAP
 +#  endif
 +#  ifndef CURL_DISABLE_SMTP
 +#    define CURL_DISABLE_SMTP
 +#  endif
 +#  ifndef CURL_DISABLE_RTMP
 +#    define CURL_DISABLE_RTMP
 +#  endif
 +#  ifndef CURL_DISABLE_GOPHER
 +#    define CURL_DISABLE_GOPHER
 +#  endif
 +#  ifndef CURL_DISABLE_SMB
 +#    define CURL_DISABLE_SMB
 +#  endif
 +#endif
 +
 +/*
 + * When http is disabled rtsp is not supported.
 + */
 +
 +#if defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_RTSP)
 +#  define CURL_DISABLE_RTSP
 +#endif
 +
 +/* ================================================================ */
 +/* No system header file shall be included in this file before this */
 +/* point. The only allowed ones are those included from curlbuild.h */
 +/* ================================================================ */
 +
 +/*
 + * OS/400 setup file includes some system headers.
 + */
 +
 +#ifdef __OS400__
 +#  include "setup-os400.h"
 +#endif
 +
 +/*
 + * VMS setup file includes some system headers.
 + */
 +
 +#ifdef __VMS
 +#  include "setup-vms.h"
 +#endif
 +
 +/*
 + * Use getaddrinfo to resolve the IPv4 address literal. If the current network
 + * interface doesn’t support IPv4, but supports IPv6, NAT64, and DNS64,
 + * performing this task will result in a synthesized IPv6 address.
 + */
 +#ifdef  __APPLE__
 +#define USE_RESOLVE_ON_IPS 1
 +#endif
 +
 +/*
 + * Include header files for windows builds before redefining anything.
 + * Use this preprocessor block only to include or exclude windows.h,
 + * winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs
 + * to any other further and independent block.  Under Cygwin things work
 + * just as under linux (e.g. <sys/socket.h>) and the winsock headers should
 + * never be included when __CYGWIN__ is defined.  configure script takes
 + * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK_H, HAVE_WINSOCK2_H,
 + * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined.
 + */
 +
 +#ifdef HAVE_WINDOWS_H
 +#  if defined(UNICODE) && !defined(_UNICODE)
 +#    define _UNICODE
 +#  endif
 +#  if defined(_UNICODE) && !defined(UNICODE)
 +#    define UNICODE
 +#  endif
 +#  ifndef WIN32_LEAN_AND_MEAN
 +#    define WIN32_LEAN_AND_MEAN
 +#  endif
 +#  include <windows.h>
 +#  ifdef HAVE_WINSOCK2_H
 +#    include <winsock2.h>
 +#    ifdef HAVE_WS2TCPIP_H
 +#      include <ws2tcpip.h>
 +#    endif
 +#  else
 +#    ifdef HAVE_WINSOCK_H
 +#      include <winsock.h>
 +#    endif
 +#  endif
 +#  include <tchar.h>
 +#  ifdef UNICODE
 +     typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
 +#  endif
 +#endif
 +
 +/*
 + * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else
 + * define USE_WINSOCK to 1 if we have and use WINSOCK  API, else
 + * undefine USE_WINSOCK.
 + */
 +
 +#undef USE_WINSOCK
 +
 +#ifdef HAVE_WINSOCK2_H
 +#  define USE_WINSOCK 2
 +#else
 +#  ifdef HAVE_WINSOCK_H
 +#    define USE_WINSOCK 1
 +#  endif
 +#endif
 +
 +#ifdef USE_LWIPSOCK
 +#  include <lwip/init.h>
 +#  include <lwip/sockets.h>
 +#  include <lwip/netdb.h>
 +#endif
 +
 +#ifdef HAVE_EXTRA_STRICMP_H
 +#  include <extra/stricmp.h>
 +#endif
 +
 +#ifdef HAVE_EXTRA_STRDUP_H
 +#  include <extra/strdup.h>
 +#endif
 +
 +#ifdef TPF
 +#  include <strings.h>    /* for bzero, strcasecmp, and strncasecmp */
 +#  include <string.h>     /* for strcpy and strlen */
 +#  include <stdlib.h>     /* for rand and srand */
 +#  include <sys/socket.h> /* for select and ioctl*/
 +#  include <netdb.h>      /* for in_addr_t definition */
 +#  include <tpf/sysapi.h> /* for tpf_process_signals */
 +   /* change which select is used for libcurl */
 +#  define select(a,b,c,d,e) tpf_select_libcurl(a,b,c,d,e)
 +#endif
 +
 +#ifdef __VXWORKS__
 +#  include <sockLib.h>    /* for generic BSD socket functions */
 +#  include <ioLib.h>      /* for basic I/O interface functions */
 +#endif
 +
 +#ifdef __AMIGA__
 +#  ifndef __ixemul__
 +#    include <exec/types.h>
 +#    include <exec/execbase.h>
 +#    include <proto/exec.h>
 +#    include <proto/dos.h>
 +#    define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
 +#  endif
 +#endif
 +
 +#include <stdio.h>
 +#ifdef HAVE_ASSERT_H
 +#include <assert.h>
 +#endif
 +
 +#ifdef __TANDEM /* for nsr-tandem-nsk systems */
 +#include <floss.h>
 +#endif
 +
 +#ifndef STDC_HEADERS /* no standard C headers! */
 +#include <curl/stdcheaders.h>
 +#endif
 +
 +#ifdef __POCC__
 +#  include <sys/types.h>
 +#  include <unistd.h>
 +#  define sys_nerr EILSEQ
 +#endif
 +
 +/*
 + * Salford-C kludge section (mostly borrowed from wxWidgets).
 + */
 +#ifdef __SALFORDC__
 +  #pragma suppress 353             /* Possible nested comments */
 +  #pragma suppress 593             /* Define not used */
 +  #pragma suppress 61              /* enum has no name */
 +  #pragma suppress 106             /* unnamed, unused parameter */
 +  #include <clib.h>
 +#endif
 +
 +/* Default Windows file API selection.  */
 +#ifdef _WIN32
 +# if defined(_MSC_VER) && (_INTEGRAL_MAX_BITS >= 64)
 +#  define USE_WIN32_LARGE_FILES
 +# elif defined(__MINGW32__)
 +#  define USE_WIN32_LARGE_FILES
 +# else
 +#  define USE_WIN32_SMALL_FILES
 +# endif
 +#endif
 +
 +/*
 + * Large file (>2Gb) support using WIN32 functions.
 + */
 +
 +#ifdef USE_WIN32_LARGE_FILES
 +#  include <io.h>
 +#  include <sys/types.h>
 +#  include <sys/stat.h>
 +#  undef  lseek
 +#  define lseek(fdes,offset,whence)  _lseeki64(fdes, offset, whence)
 +#  undef  fstat
 +#  define fstat(fdes,stp)            _fstati64(fdes, stp)
 +#  undef  stat
 +#  define stat(fname,stp)            _stati64(fname, stp)
 +#  define struct_stat                struct _stati64
 +#  define LSEEK_ERROR                (__int64)-1
 +#endif
 +
 +/*
 + * Small file (<2Gb) support using WIN32 functions.
 + */
 +
 +#ifdef USE_WIN32_SMALL_FILES
 +#  include <io.h>
 +#  include <sys/types.h>
 +#  include <sys/stat.h>
 +#  ifndef _WIN32_WCE
 +#    undef  lseek
 +#    define lseek(fdes,offset,whence)  _lseek(fdes, (long)offset, whence)
 +#    define fstat(fdes,stp)            _fstat(fdes, stp)
 +#    define stat(fname,stp)            _stat(fname, stp)
 +#    define struct_stat                struct _stat
 +#  endif
 +#  define LSEEK_ERROR                (long)-1
 +#endif
 +
 +#ifndef struct_stat
 +#  define struct_stat struct stat
 +#endif
 +
 +#ifndef LSEEK_ERROR
 +#  define LSEEK_ERROR (off_t)-1
 +#endif
 +
 +/*
 + * Default sizeof(off_t) in case it hasn't been defined in config file.
 + */
 +
 +#ifndef SIZEOF_OFF_T
 +#  if defined(__VMS) && !defined(__VAX)
 +#    if defined(_LARGEFILE)
 +#      define SIZEOF_OFF_T 8
 +#    endif
 +#  elif defined(__OS400__) && defined(__ILEC400__)
 +#    if defined(_LARGE_FILES)
 +#      define SIZEOF_OFF_T 8
 +#    endif
 +#  elif defined(__MVS__) && defined(__IBMC__)
 +#    if defined(_LP64) || defined(_LARGE_FILES)
 +#      define SIZEOF_OFF_T 8
 +#    endif
 +#  elif defined(__370__) && defined(__IBMC__)
 +#    if defined(_LP64) || defined(_LARGE_FILES)
 +#      define SIZEOF_OFF_T 8
 +#    endif
 +#  endif
 +#  ifndef SIZEOF_OFF_T
 +#    define SIZEOF_OFF_T 4
 +#  endif
 +#endif
 +
 +/*
 + * Arg 2 type for gethostname in case it hasn't been defined in config file.
 + */
 +
 +#ifndef GETHOSTNAME_TYPE_ARG2
 +#  ifdef USE_WINSOCK
 +#    define GETHOSTNAME_TYPE_ARG2 int
 +#  else
 +#    define GETHOSTNAME_TYPE_ARG2 size_t
 +#  endif
 +#endif
 +
 +/* Below we define some functions. They should
 +
 +   4. set the SIGALRM signal timeout
 +   5. set dir/file naming defines
 +   */
 +
 +#ifdef WIN32
 +
 +#  define DIR_CHAR      "\\"
 +#  define DOT_CHAR      "_"
 +
 +#else /* WIN32 */
 +
 +#  ifdef MSDOS  /* Watt-32 */
 +
 +#    include <sys/ioctl.h>
 +#    define select(n,r,w,x,t) select_s(n,r,w,x,t)
 +#    define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z))
 +#    include <tcp.h>
 +#    ifdef word
 +#      undef word
 +#    endif
 +#    ifdef byte
 +#      undef byte
 +#    endif
 +
 +#  endif /* MSDOS */
 +
 +#  ifdef __minix
 +     /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */
-      extern char * strtok_r(char *s, const char *delim, char **last);
-      extern struct tm * gmtime_r(const time_t * const timep, struct tm *tmp);
++     extern char *strtok_r(char *s, const char *delim, char **last);
++     extern struct tm *gmtime_r(const time_t * const timep, struct tm *tmp);
 +#  endif
 +
 +#  define DIR_CHAR      "/"
 +#  ifndef DOT_CHAR
 +#    define DOT_CHAR      "."
 +#  endif
 +
 +#  ifdef MSDOS
 +#    undef DOT_CHAR
 +#    define DOT_CHAR      "_"
 +#  endif
 +
 +#  ifndef fileno /* sunos 4 have this as a macro! */
 +     int fileno(FILE *stream);
 +#  endif
 +
 +#endif /* WIN32 */
 +
 +/*
 + * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN
 + * defined in ws2tcpip.h as well as to provide IPv6 support.
 + * Does not apply if lwIP is used.
 + */
 +
 +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(USE_LWIPSOCK)
 +#  if !defined(HAVE_WS2TCPIP_H) || \
 +     ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN))
 +#    undef HAVE_GETADDRINFO_THREADSAFE
 +#    undef HAVE_FREEADDRINFO
 +#    undef HAVE_GETADDRINFO
 +#    undef HAVE_GETNAMEINFO
 +#    undef ENABLE_IPV6
 +#  endif
 +#endif
 +
 +/* ---------------------------------------------------------------- */
 +/*             resolver specialty compile-time defines              */
 +/*         CURLRES_* defines to use in the host*.c sources          */
 +/* ---------------------------------------------------------------- */
 +
 +/*
 + * lcc-win32 doesn't have _beginthreadex(), lacks threads support.
 + */
 +
 +#if defined(__LCC__) && defined(WIN32)
 +#  undef USE_THREADS_POSIX
 +#  undef USE_THREADS_WIN32
 +#endif
 +
 +/*
 + * MSVC threads support requires a multi-threaded runtime library.
 + * _beginthreadex() is not available in single-threaded ones.
 + */
 +
 +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT)
 +#  undef USE_THREADS_POSIX
 +#  undef USE_THREADS_WIN32
 +#endif
 +
 +/*
 + * Mutually exclusive CURLRES_* definitions.
 + */
 +
 +#ifdef USE_ARES
 +#  define CURLRES_ASYNCH
 +#  define CURLRES_ARES
 +/* now undef the stock libc functions just to avoid them being used */
 +#  undef HAVE_GETADDRINFO
 +#  undef HAVE_FREEADDRINFO
 +#  undef HAVE_GETHOSTBYNAME
 +#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
 +#  define CURLRES_ASYNCH
 +#  define CURLRES_THREADED
 +#else
 +#  define CURLRES_SYNCH
 +#endif
 +
 +#ifdef ENABLE_IPV6
 +#  define CURLRES_IPV6
 +#else
 +#  define CURLRES_IPV4
 +#endif
 +
 +/* ---------------------------------------------------------------- */
 +
 +/*
 + * When using WINSOCK, TELNET protocol requires WINSOCK2 API.
 + */
 +
 +#if defined(USE_WINSOCK) && (USE_WINSOCK != 2)
 +#  define CURL_DISABLE_TELNET 1
 +#endif
 +
 +/*
 + * msvc 6.0 does not have struct sockaddr_storage and
 + * does not define IPPROTO_ESP in winsock2.h. But both
 + * are available if PSDK is properly installed.
 + */
 +
 +#if defined(_MSC_VER) && !defined(__POCC__)
 +#  if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP))
 +#    undef HAVE_STRUCT_SOCKADDR_STORAGE
 +#  endif
 +#endif
 +
 +/*
 + * Intentionally fail to build when using msvc 6.0 without PSDK installed.
 + * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK
 + * in lib/config-win32.h although absolutely discouraged and unsupported.
 + */
 +
 +#if defined(_MSC_VER) && !defined(__POCC__)
 +#  if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_))
 +#    if !defined(ALLOW_MSVC6_WITHOUT_PSDK)
 +#      error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \
 +             "Windows Server 2003 PSDK"
 +#    else
 +#      define CURL_DISABLE_LDAP 1
 +#    endif
 +#  endif
 +#endif
 +
 +#ifdef NETWARE
 +int netware_init(void);
 +#ifndef __NOVELL_LIBC__
 +#include <sys/bsdskt.h>
 +#include <sys/timeval.h>
 +#endif
 +#endif
 +
 +#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H)
 +/* The lib and header are present */
 +#define USE_LIBIDN2
 +#endif
 +
 +#ifndef SIZEOF_TIME_T
 +/* assume default size of time_t to be 32 bit */
 +#define SIZEOF_TIME_T 4
 +#endif
 +
 +#define LIBIDN_REQUIRED_VERSION "0.4.1"
 +
 +#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
 +    defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_MBEDTLS) || \
 +    defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
 +    defined(USE_DARWINSSL) || defined(USE_GSKIT)
 +#define USE_SSL    /* SSL support has been enabled */
 +#endif
 +
 +/* Single point where USE_SPNEGO definition might be defined */
 +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
 +    (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
 +#define USE_SPNEGO
 +#endif
 +
 +/* Single point where USE_KERBEROS5 definition might be defined */
 +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \
 +    (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI))
 +#define USE_KERBEROS5
 +#endif
 +
 +/* Single point where USE_NTLM definition might be defined */
 +#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
 +#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
 +    defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \
 +    defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
 +
 +#define USE_NTLM
 +
 +#elif defined(USE_MBEDTLS)
 +#  include <mbedtls/md4.h>
 +#  if defined(MBEDTLS_MD4_C)
 +#define USE_NTLM
 +#  endif
 +
 +#endif
 +#endif
 +
 +/* non-configure builds may define CURL_WANTS_CA_BUNDLE_ENV */
 +#if defined(CURL_WANTS_CA_BUNDLE_ENV) && !defined(CURL_CA_BUNDLE)
 +#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE")
 +#endif
 +
 +/*
 + * Provide a mechanism to silence picky compilers, such as gcc 4.6+.
 + * Parameters should of course normally not be unused, but for example when
 + * we have multiple implementations of the same interface it may happen.
 + */
 +
 +#if defined(__GNUC__) && ((__GNUC__ >= 3) || \
 +  ((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7)))
 +#  define UNUSED_PARAM __attribute__((__unused__))
 +#  define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
 +#else
 +#  define UNUSED_PARAM /*NOTHING*/
 +#  define WARN_UNUSED_RESULT
 +#endif
 +
 +/*
 + * Include macros and defines that should only be processed once.
 + */
 +
 +#ifndef HEADER_CURL_SETUP_ONCE_H
 +#include "curl_setup_once.h"
 +#endif
 +
 +/*
 + * Definition of our NOP statement Object-like macro
 + */
 +
 +#ifndef Curl_nop_stmt
 +#  define Curl_nop_stmt do { } WHILE_FALSE
 +#endif
 +
 +/*
 + * Ensure that Winsock and lwIP TCP/IP stacks are not mixed.
 + */
 +
 +#if defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H)
 +#  if defined(SOCKET) || \
 +     defined(USE_WINSOCK) || \
 +     defined(HAVE_WINSOCK_H) || \
 +     defined(HAVE_WINSOCK2_H) || \
 +     defined(HAVE_WS2TCPIP_H)
 +#    error "Winsock and lwIP TCP/IP stack definitions shall not coexist!"
 +#  endif
 +#endif
 +
 +/*
 + * Portable symbolic names for Winsock shutdown() mode flags.
 + */
 +
 +#ifdef USE_WINSOCK
 +#  define SHUT_RD   0x00
 +#  define SHUT_WR   0x01
 +#  define SHUT_RDWR 0x02
 +#endif
 +
 +/* Define S_ISREG if not defined by system headers, f.e. MSVC */
 +#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
 +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
 +#endif
 +
 +/* Define S_ISDIR if not defined by system headers, f.e. MSVC */
 +#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
 +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
 +#endif
 +
 +/* In Windows the default file mode is text but an application can override it.
 +Therefore we specify it explicitly. https://github.com/curl/curl/pull/258
 +*/
 +#if defined(WIN32) || defined(MSDOS)
 +#define FOPEN_READTEXT "rt"
 +#define FOPEN_WRITETEXT "wt"
 +#elif defined(__CYGWIN__)
 +/* Cygwin has specific behavior we need to address when WIN32 is not defined.
 +https://cygwin.com/cygwin-ug-net/using-textbinary.html
 +For write we want our output to have line endings of LF and be compatible with
 +other Cygwin utilities. For read we want to handle input that may have line
 +endings either CRLF or LF so 't' is appropriate.
 +*/
 +#define FOPEN_READTEXT "rt"
 +#define FOPEN_WRITETEXT "w"
 +#else
 +#define FOPEN_READTEXT "r"
 +#define FOPEN_WRITETEXT "w"
 +#endif
 +
 +/* WinSock destroys recv() buffer when send() failed.
 + * Enabled automatically for Windows and for Cygwin as Cygwin sockets are
 + * wrappers for WinSock sockets. https://github.com/curl/curl/issues/657
 + * Define DONT_USE_RECV_BEFORE_SEND_WORKAROUND to force disable workaround.
 + */
 +#if !defined(DONT_USE_RECV_BEFORE_SEND_WORKAROUND)
 +#  if defined(WIN32) || defined(__CYGWIN__)
 +#    define USE_RECV_BEFORE_SEND_WORKAROUND
 +#  endif
 +#else  /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */
 +#  ifdef USE_RECV_BEFORE_SEND_WORKAROUND
 +#    undef USE_RECV_BEFORE_SEND_WORKAROUND
 +#  endif
 +#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUNDS */
 +
 +/* Detect Windows App environment which has a restricted access
 + * to the Win32 APIs. */
 +# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)
 +#  include <winapifamily.h>
 +#  if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
 +     !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
 +#    define CURL_WINDOWS_APP
 +#  endif
 +# endif
 +
 +#endif /* HEADER_CURL_SETUP_H */
diff --cc Utilities/cmcurl/lib/ftp.c
index 9d0a03c,0000000..89c7e40
mode 100644,000000..100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@@ -1,4609 -1,0 +1,4549 @@@
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
 + * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
 + *
 + * This software is licensed as described in the file COPYING, which
 + * you should have received as part of this distribution. The terms
 + * are also available at https://curl.haxx.se/docs/copyright.html.
 + *
 + * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 + * copies of the Software, and permit persons to whom the Software is
 + * furnished to do so, under the terms of the COPYING file.
 + *
 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 + * KIND, either express or implied.
 + *
 + ***************************************************************************/
 +
 +#include "curl_setup.h"
 +
 +#ifndef CURL_DISABLE_FTP
 +
 +#ifdef HAVE_NETINET_IN_H
 +#include <netinet/in.h>
 +#endif
 +#ifdef HAVE_ARPA_INET_H
 +#include <arpa/inet.h>
 +#endif
 +#ifdef HAVE_UTSNAME_H
 +#include <sys/utsname.h>
 +#endif
 +#ifdef HAVE_NETDB_H
 +#include <netdb.h>
 +#endif
 +#ifdef __VMS
 +#include <in.h>
 +#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"
 +#include "if2ip.h"
 +#include "hostip.h"
 +#include "progress.h"
 +#include "transfer.h"
 +#include "escape.h"
 +#include "http.h" /* for HTTP proxy tunnel stuff */
 +#include "socks.h"
 +#include "ftp.h"
 +#include "fileinfo.h"
 +#include "ftplistparser.h"
 +#include "curl_sec.h"
 +#include "strtoofft.h"
 +#include "strcase.h"
 +#include "vtls/vtls.h"
 +#include "connect.h"
 +#include "strerror.h"
 +#include "inet_ntop.h"
 +#include "inet_pton.h"
 +#include "select.h"
 +#include "parsedate.h" /* for the week day and month names */
 +#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"
 +#include "non-ascii.h"
 +/* The last 3 #include files should be in this order */
 +#include "curl_printf.h"
 +#include "curl_memory.h"
 +#include "memdebug.h"
 +
 +#ifndef NI_MAXHOST
 +#define NI_MAXHOST 1025
 +#endif
 +#ifndef INET_ADDRSTRLEN
 +#define INET_ADDRSTRLEN 16
 +#endif
 +
 +#ifdef CURL_DISABLE_VERBOSE_STRINGS
 +#define ftp_pasv_verbose(a,b,c,d)  Curl_nop_stmt
 +#endif
 +
 +/* Local API functions */
 +#ifndef DEBUGBUILD
 +static void _state(struct connectdata *conn,
 +                   ftpstate newstate);
 +#define state(x,y) _state(x,y)
 +#else
 +static void _state(struct connectdata *conn,
 +                   ftpstate newstate,
 +                   int lineno);
 +#define state(x,y) _state(x,y,__LINE__)
 +#endif
 +
 +static CURLcode ftp_sendquote(struct connectdata *conn,
 +                              struct curl_slist *quote);
 +static CURLcode ftp_quit(struct connectdata *conn);
 +static CURLcode ftp_parse_url_path(struct connectdata *conn);
 +static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done);
 +#ifndef CURL_DISABLE_VERBOSE_STRINGS
 +static void ftp_pasv_verbose(struct connectdata *conn,
 +                             Curl_addrinfo *ai,
 +                             char *newhost, /* ascii version */
 +                             int port);
 +#endif
 +static CURLcode ftp_state_prepare_transfer(struct connectdata *conn);
 +static CURLcode ftp_state_mdtm(struct connectdata *conn);
 +static CURLcode ftp_state_quote(struct connectdata *conn,
 +                                bool init, ftpstate instate);
 +static CURLcode ftp_nb_type(struct connectdata *conn,
 +                            bool ascii, ftpstate newstate);
 +static int ftp_need_type(struct connectdata *conn,
 +                         bool ascii);
 +static CURLcode ftp_do(struct connectdata *conn, bool *done);
 +static CURLcode ftp_done(struct connectdata *conn,
 +                         CURLcode, bool premature);
 +static CURLcode ftp_connect(struct connectdata *conn, bool *done);
 +static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection);
 +static CURLcode ftp_do_more(struct connectdata *conn, int *completed);
 +static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done);
 +static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks,
 +                       int numsocks);
 +static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
 +                              int numsocks);
 +static CURLcode ftp_doing(struct connectdata *conn,
 +                          bool *dophase_done);
 +static CURLcode ftp_setup_connection(struct connectdata * conn);
 +
 +static CURLcode init_wc_data(struct connectdata *conn);
 +static CURLcode wc_statemach(struct connectdata *conn);
 +
 +static void wc_data_dtor(void *ptr);
 +
 +static CURLcode ftp_state_retr(struct connectdata *conn, curl_off_t filesize);
 +
 +static CURLcode ftp_readresp(curl_socket_t sockfd,
 +                             struct pingpong *pp,
 +                             int *ftpcode,
 +                             size_t *size);
 +static CURLcode ftp_dophase_done(struct connectdata *conn,
 +                                 bool connected);
 +
 +/* easy-to-use macro: */
 +#define PPSENDF(x,y,z)  result = Curl_pp_sendf(x,y,z); \
 +                        if(result)                     \
 +                          return result
 +
 +
 +/*
 + * FTP protocol handler.
 + */
 +
 +const struct Curl_handler Curl_handler_ftp = {
 +  "FTP",                           /* scheme */
 +  ftp_setup_connection,            /* setup_connection */
 +  ftp_do,                          /* do_it */
 +  ftp_done,                        /* done */
 +  ftp_do_more,                     /* do_more */
 +  ftp_connect,                     /* connect_it */
 +  ftp_multi_statemach,             /* connecting */
 +  ftp_doing,                       /* doing */
 +  ftp_getsock,                     /* proto_getsock */
 +  ftp_getsock,                     /* doing_getsock */
 +  ftp_domore_getsock,              /* domore_getsock */
 +  ZERO_NULL,                       /* perform_getsock */
 +  ftp_disconnect,                  /* disconnect */
 +  ZERO_NULL,                       /* readwrite */
 +  PORT_FTP,                        /* defport */
 +  CURLPROTO_FTP,                   /* protocol */
 +  PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD
 +  | PROTOPT_NOURLQUERY /* flags */
 +};
 +
 +
 +#ifdef USE_SSL
 +/*
 + * FTPS protocol handler.
 + */
 +
 +const struct Curl_handler Curl_handler_ftps = {
 +  "FTPS",                          /* scheme */
 +  ftp_setup_connection,            /* setup_connection */
 +  ftp_do,                          /* do_it */
 +  ftp_done,                        /* done */
 +  ftp_do_more,                     /* do_more */
 +  ftp_connect,                     /* connect_it */
 +  ftp_multi_statemach,             /* connecting */
 +  ftp_doing,                       /* doing */
 +  ftp_getsock,                     /* proto_getsock */
 +  ftp_getsock,                     /* doing_getsock */
 +  ftp_domore_getsock,              /* domore_getsock */
 +  ZERO_NULL,                       /* perform_getsock */
 +  ftp_disconnect,                  /* disconnect */
 +  ZERO_NULL,                       /* readwrite */
 +  PORT_FTPS,                       /* defport */
 +  CURLPROTO_FTPS,                  /* protocol */
 +  PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |
 +  PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY /* flags */
 +};
 +#endif
 +
 +#ifndef CURL_DISABLE_HTTP
 +/*
 + * HTTP-proxyed FTP protocol handler.
 + */
 +
 +static const struct Curl_handler Curl_handler_ftp_proxy = {
 +  "FTP",                                /* scheme */
 +  Curl_http_setup_conn,                 /* setup_connection */
 +  Curl_http,                            /* do_it */
 +  Curl_http_done,                       /* done */
 +  ZERO_NULL,                            /* do_more */
 +  ZERO_NULL,                            /* connect_it */
 +  ZERO_NULL,                            /* connecting */
 +  ZERO_NULL,                            /* doing */
 +  ZERO_NULL,                            /* proto_getsock */
 +  ZERO_NULL,                            /* doing_getsock */
 +  ZERO_NULL,                            /* domore_getsock */
 +  ZERO_NULL,                            /* perform_getsock */
 +  ZERO_NULL,                            /* disconnect */
 +  ZERO_NULL,                            /* readwrite */
 +  PORT_FTP,                             /* defport */
 +  CURLPROTO_HTTP,                       /* protocol */
 +  PROTOPT_NONE                          /* flags */
 +};
 +
 +
 +#ifdef USE_SSL
 +/*
 + * HTTP-proxyed FTPS protocol handler.
 + */
 +
 +static const struct Curl_handler Curl_handler_ftps_proxy = {
 +  "FTPS",                               /* scheme */
 +  Curl_http_setup_conn,                 /* setup_connection */
 +  Curl_http,                            /* do_it */
 +  Curl_http_done,                       /* done */
 +  ZERO_NULL,                            /* do_more */
 +  ZERO_NULL,                            /* connect_it */
 +  ZERO_NULL,                            /* connecting */
 +  ZERO_NULL,                            /* doing */
 +  ZERO_NULL,                            /* proto_getsock */
 +  ZERO_NULL,                            /* doing_getsock */
 +  ZERO_NULL,                            /* domore_getsock */
 +  ZERO_NULL,                            /* perform_getsock */
 +  ZERO_NULL,                            /* disconnect */
 +  ZERO_NULL,                            /* readwrite */
 +  PORT_FTPS,                            /* defport */
 +  CURLPROTO_HTTP,                       /* protocol */
 +  PROTOPT_NONE                          /* flags */
 +};
 +#endif
 +#endif
 +
 +static void close_secondarysocket(struct connectdata *conn)
 +{
 +  if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
 +    Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
 +    conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
 +  }
 +  conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
 +  conn->tunnel_state[SECONDARYSOCKET] = TUNNEL_INIT;
 +}
 +
 +/*
 + * NOTE: back in the old days, we added code in the FTP code that made NOBODY
 + * requests on files respond with headers passed to the client/stdout that
 + * looked like HTTP ones.
 + *
 + * This approach is not very elegant, it causes confusion and is error-prone.
 + * It is subject for removal at the next (or at least a future) soname bump.
 + * Until then you can test the effects of the removal by undefining the
 + * following define named CURL_FTP_HTTPSTYLE_HEAD.
 + */
 +#define CURL_FTP_HTTPSTYLE_HEAD 1
 +
 +static void freedirs(struct ftp_conn *ftpc)
 +{
 +  int i;
 +  if(ftpc->dirs) {
 +    for(i=0; i < ftpc->dirdepth; i++) {
 +      free(ftpc->dirs[i]);
 +      ftpc->dirs[i]=NULL;
 +    }
 +    free(ftpc->dirs);
 +    ftpc->dirs = NULL;
 +    ftpc->dirdepth = 0;
 +  }
 +  Curl_safefree(ftpc->file);
 +
 +  /* no longer of any use */
 +  Curl_safefree(ftpc->newhost);
 +}
 +
 +/* Returns non-zero if the given string contains CR (\r) or LF (\n),
 +   which are not allowed within RFC 959 <string>.
 +   Note: The input string is in the client's encoding which might
 +   not be ASCII, so escape sequences \r & \n must be used instead
 +   of hex values 0x0d & 0x0a.
 +*/
 +static bool isBadFtpString(const char *string)
 +{
 +  return ((NULL != strchr(string, '\r')) ||
 +          (NULL != strchr(string, '\n'))) ? TRUE : FALSE;
 +}
 +
 +/***********************************************************************
 + *
 + * AcceptServerConnect()
 + *
 + * After connection request is received from the server this function is
 + * called to accept the connection and close the listening socket
 + *
 + */
 +static CURLcode AcceptServerConnect(struct connectdata *conn)
 +{
 +  struct Curl_easy *data = conn->data;
 +  curl_socket_t sock = conn->sock[SECONDARYSOCKET];
 +  curl_socket_t s = CURL_SOCKET_BAD;
 +#ifdef ENABLE_IPV6
 +  struct Curl_sockaddr_storage add;
 +#else
 +  struct sockaddr_in add;
 +#endif
 +  curl_socklen_t size = (curl_socklen_t) sizeof(add);
 +
 +  if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) {
 +    size = sizeof(add);
 +
 +    s=accept(sock, (struct sockaddr *) &add, &size);
 +  }
 +  Curl_closesocket(conn, sock); /* close the first socket */
 +
 +  if(CURL_SOCKET_BAD == s) {
 +    failf(data, "Error accept()ing server connect");
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +  infof(data, "Connection accepted from server\n");
 +  /* when this happens within the DO state it is important that we mark us as
 +     not needing DO_MORE anymore */
 +  conn->bits.do_more = FALSE;
 +
 +  conn->sock[SECONDARYSOCKET] = s;
 +  (void)curlx_nonblock(s, TRUE); /* enable non-blocking */
 +  conn->sock_accepted[SECONDARYSOCKET] = TRUE;
 +
 +  if(data->set.fsockopt) {
 +    int error = 0;
 +
 +    /* activate callback for setting socket options */
 +    error = data->set.fsockopt(data->set.sockopt_client,
 +                               s,
 +                               CURLSOCKTYPE_ACCEPT);
 +
 +    if(error) {
 +      close_secondarysocket(conn);
 +      return CURLE_ABORTED_BY_CALLBACK;
 +    }
 +  }
 +
 +  return CURLE_OK;
 +
 +}
 +
 +/*
 + * ftp_timeleft_accept() returns the amount of milliseconds left allowed for
 + * waiting server to connect. If the value is negative, the timeout time has
 + * already elapsed.
 + *
 + * The start time is stored in progress.t_acceptdata - as set with
 + * Curl_pgrsTime(..., TIMER_STARTACCEPT);
 + *
 + */
- static long ftp_timeleft_accept(struct Curl_easy *data)
++static time_t ftp_timeleft_accept(struct Curl_easy *data)
 +{
-   long timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
-   long other;
++  time_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
++  time_t other;
 +  struct timeval now;
 +
 +  if(data->set.accepttimeout > 0)
 +    timeout_ms = data->set.accepttimeout;
 +
 +  now = Curl_tvnow();
 +
 +  /* check if the generic timeout possibly is set shorter */
 +  other =  Curl_timeleft(data, &now, FALSE);
 +  if(other && (other < timeout_ms))
 +    /* note that this also works fine for when other happens to be negative
 +       due to it already having elapsed */
 +    timeout_ms = other;
 +  else {
 +    /* subtract elapsed time */
 +    timeout_ms -= Curl_tvdiff(now, data->progress.t_acceptdata);
 +    if(!timeout_ms)
 +      /* avoid returning 0 as that means no timeout! */
 +      return -1;
 +  }
 +
 +  return timeout_ms;
 +}
 +
 +
 +/***********************************************************************
 + *
 + * ReceivedServerConnect()
 + *
 + * After allowing server to connect to us from data port, this function
 + * checks both data connection for connection establishment and ctrl
 + * connection for a negative response regarding a failure in connecting
 + *
 + */
 +static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
 +{
 +  struct Curl_easy *data = conn->data;
 +  curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET];
 +  curl_socket_t data_sock = conn->sock[SECONDARYSOCKET];
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +  int result;
-   long timeout_ms;
++  time_t timeout_ms;
 +  ssize_t nread;
 +  int ftpcode;
 +
 +  *received = FALSE;
 +
 +  timeout_ms = ftp_timeleft_accept(data);
 +  infof(data, "Checking for server connect\n");
 +  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;
 +  }
 +
 +  /* First check whether there is a cached response from server */
 +  if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
 +    /* Data connection could not be established, let's return */
 +    infof(data, "There is negative response in cache while serv connect\n");
 +    Curl_GetFTPResponse(&nread, conn, &ftpcode);
 +    return CURLE_FTP_ACCEPT_FAILED;
 +  }
 +
 +  result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0);
 +
 +  /* see if the connection request is already here */
-   switch (result) {
++  switch(result) {
 +  case -1: /* error */
 +    /* let's die here */
 +    failf(data, "Error while waiting for server connect");
 +    return CURLE_FTP_ACCEPT_FAILED;
 +  case 0:  /* Server connect is not received yet */
 +    break; /* loop */
 +  default:
 +
 +    if(result & CURL_CSELECT_IN2) {
 +      infof(data, "Ready to accept data connection from server\n");
 +      *received = TRUE;
 +    }
 +    else if(result & CURL_CSELECT_IN) {
 +      infof(data, "Ctrl conn has data while waiting for data conn\n");
 +      Curl_GetFTPResponse(&nread, conn, &ftpcode);
 +
 +      if(ftpcode/100 > 3)
 +        return CURLE_FTP_ACCEPT_FAILED;
 +
 +      return CURLE_WEIRD_SERVER_REPLY;
 +    }
 +
 +    break;
 +  } /* switch() */
 +
 +  return CURLE_OK;
 +}
 +
 +
 +/***********************************************************************
 + *
 + * InitiateTransfer()
 + *
 + * After connection from server is accepted this function is called to
 + * setup transfer parameters and initiate the data transfer.
 + *
 + */
 +static CURLcode InitiateTransfer(struct connectdata *conn)
 +{
 +  struct Curl_easy *data = conn->data;
 +  struct FTP *ftp = data->req.protop;
 +  CURLcode result = CURLE_OK;
 +
-   if(conn->ssl[SECONDARYSOCKET].use) {
++  if(conn->bits.ftp_use_data_ssl) {
 +    /* since we only have a plaintext TCP connection here, we must now
 +     * do the TLS stuff */
 +    infof(data, "Doing the SSL/TLS handshake on the data stream\n");
 +    result = Curl_ssl_connect(conn, SECONDARYSOCKET);
 +    if(result)
 +      return result;
 +  }
 +
 +  if(conn->proto.ftpc.state_saved == FTP_STOR) {
 +    *(ftp->bytecountp)=0;
 +
 +    /* When we know we're uploading a specified file, we can get the file
 +       size prior to the actual upload. */
 +
 +    Curl_pgrsSetUploadSize(data, data->state.infilesize);
 +
 +    /* set the SO_SNDBUF for the secondary socket for those who need it */
 +    Curl_sndbufset(conn->sock[SECONDARYSOCKET]);
 +
 +    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
 +                        SECONDARYSOCKET, ftp->bytecountp);
 +  }
 +  else {
 +    /* FTP download: */
 +    Curl_setup_transfer(conn, SECONDARYSOCKET,
 +                        conn->proto.ftpc.retr_size_saved, FALSE,
 +                        ftp->bytecountp, -1, NULL); /* no upload here */
 +  }
 +
 +  conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
 +  state(conn, FTP_STOP);
 +
 +  return CURLE_OK;
 +}
 +
 +/***********************************************************************
 + *
 + * AllowServerConnect()
 + *
 + * When we've issue the PORT command, we have told the server to connect to
 + * us. This function checks whether data connection is established if so it is
 + * accepted.
 + *
 + */
 +static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
 +{
 +  struct Curl_easy *data = conn->data;
-   long timeout_ms;
++  time_t timeout_ms;
 +  CURLcode result = CURLE_OK;
 +
 +  *connected = FALSE;
 +  infof(data, "Preparing for accepting server on data port\n");
 +
 +  /* Save the time we start accepting server connect */
 +  Curl_pgrsTime(data, TIMER_STARTACCEPT);
 +
 +  timeout_ms = ftp_timeleft_accept(data);
 +  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;
 +  }
 +
 +  /* see if the connection request is already here */
 +  result = ReceivedServerConnect(conn, connected);
 +  if(result)
 +    return result;
 +
 +  if(*connected) {
 +    result = AcceptServerConnect(conn);
 +    if(result)
 +      return result;
 +
 +    result = InitiateTransfer(conn);
 +    if(result)
 +      return result;
 +  }
 +  else {
 +    /* Add timeout to multi handle and break out of the loop */
 +    if(!result && *connected == FALSE) {
 +      if(data->set.accepttimeout > 0)
 +        Curl_expire(data, data->set.accepttimeout);
 +      else
 +        Curl_expire(data, DEFAULT_ACCEPT_TIMEOUT);
 +    }
 +  }
 +
 +  return result;
 +}
 +
 +/* macro to check for a three-digit ftp status code at the start of the
 +   given string */
 +#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) &&       \
 +                          ISDIGIT(line[2]))
 +
 +/* macro to check for the last line in an FTP server response */
 +#define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3]))
 +
 +static bool ftp_endofresp(struct connectdata *conn, char *line, size_t len,
 +                          int *code)
 +{
 +  (void)conn;
 +
 +  if((len > 3) && LASTLINE(line)) {
 +    *code = curlx_sltosi(strtol(line, NULL, 10));
 +    return TRUE;
 +  }
 +
 +  return FALSE;
 +}
 +
 +static CURLcode ftp_readresp(curl_socket_t sockfd,
 +                             struct pingpong *pp,
 +                             int *ftpcode, /* return the ftp-code if done */
 +                             size_t *size) /* size of the response */
 +{
 +  struct connectdata *conn = pp->conn;
 +  struct Curl_easy *data = conn->data;
 +#ifdef HAVE_GSSAPI
 +  char * const buf = data->state.buffer;
 +#endif
 +  CURLcode result = CURLE_OK;
 +  int code;
 +
 +  result = Curl_pp_readresp(sockfd, pp, &code, size);
 +
 +#if defined(HAVE_GSSAPI)
 +  /* handle the security-oriented responses 6xx ***/
 +  /* FIXME: some errorchecking perhaps... ***/
 +  switch(code) {
 +  case 631:
 +    code = Curl_sec_read_msg(conn, buf, PROT_SAFE);
 +    break;
 +  case 632:
 +    code = Curl_sec_read_msg(conn, buf, PROT_PRIVATE);
 +    break;
 +  case 633:
 +    code = Curl_sec_read_msg(conn, buf, PROT_CONFIDENTIAL);
 +    break;
 +  default:
 +    /* normal ftp stuff we pass through! */
 +    break;
 +  }
 +#endif
 +
 +  /* store the latest code for later retrieval */
 +  data->info.httpcode=code;
 +
 +  if(ftpcode)
 +    *ftpcode = code;
 +
 +  if(421 == code) {
 +    /* 421 means "Service not available, closing control connection." and FTP
 +     * servers use it to signal that idle session timeout has been exceeded.
 +     * If we ignored the response, it could end up hanging in some cases.
 +     *
 +     * This response code can come at any point so having it treated
 +     * generically is a good idea.
 +     */
 +    infof(data, "We got a 421 - timeout!\n");
 +    state(conn, FTP_STOP);
 +    return CURLE_OPERATION_TIMEDOUT;
 +  }
 +
 +  return result;
 +}
 +
 +/* --- parse FTP server responses --- */
 +
 +/*
 + * Curl_GetFTPResponse() is a BLOCKING function to read the full response
 + * from a server after a command.
 + *
 + */
 +
 +CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
 +                             struct connectdata *conn,
 +                             int *ftpcode) /* return the ftp-code */
 +{
 +  /*
 +   * We cannot read just one byte per read() and then go back to select() as
 +   * the OpenSSL read() doesn't grok that properly.
 +   *
 +   * Alas, read as much as possible, split up into lines, use the ending
 +   * line in a response or continue reading.  */
 +
 +  curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
-   long timeout;              /* timeout in milliseconds */
-   long interval_ms;
++  time_t timeout;              /* timeout in milliseconds */
++  time_t interval_ms;
 +  struct Curl_easy *data = conn->data;
 +  CURLcode result = CURLE_OK;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +  size_t nread;
 +  int cache_skip=0;
 +  int value_to_be_ignored=0;
 +
 +  if(ftpcode)
 +    *ftpcode = 0; /* 0 for errors */
 +  else
 +    /* make the pointer point to something for the rest of this function */
 +    ftpcode = &value_to_be_ignored;
 +
 +  *nreadp=0;
 +
 +  while(!*ftpcode && !result) {
 +    /* check and reset timeout value every lap */
 +    timeout = Curl_pp_state_timeout(pp);
 +
 +    if(timeout <=0) {
 +      failf(data, "FTP response timeout");
 +      return CURLE_OPERATION_TIMEDOUT; /* already too little time */
 +    }
 +
 +    interval_ms = 1000;  /* use 1 second timeout intervals */
 +    if(timeout < interval_ms)
 +      interval_ms = timeout;
 +
 +    /*
 +     * Since this function is blocking, we need to wait here for input on the
 +     * connection and only then we call the response reading function. We do
 +     * timeout at least every second to make the timeout check run.
 +     *
 +     * A caution here is that the ftp_readresp() function has a cache that may
 +     * contain pieces of a response from the previous invoke and we need to
 +     * make sure we don't just wait for input while there is unhandled data in
 +     * that cache. But also, if the cache is there, we call ftp_readresp() and
 +     * the cache wasn't good enough to continue we must not just busy-loop
 +     * around this function.
 +     *
 +     */
 +
 +    if(pp->cache && (cache_skip < 2)) {
 +      /*
 +       * There's a cache left since before. We then skipping the wait for
 +       * socket action, unless this is the same cache like the previous round
 +       * as then the cache was deemed not enough to act on and we then need to
 +       * wait for more data anyway.
 +       */
 +    }
-     else {
-       switch (SOCKET_READABLE(sockfd, interval_ms)) {
++    else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) {
++      switch(SOCKET_READABLE(sockfd, interval_ms)) {
 +      case -1: /* select() error, stop reading */
 +        failf(data, "FTP response aborted due to select/poll error: %d",
 +              SOCKERRNO);
 +        return CURLE_RECV_ERROR;
 +
 +      case 0: /* timeout */
 +        if(Curl_pgrsUpdate(conn))
 +          return CURLE_ABORTED_BY_CALLBACK;
 +        continue; /* just continue in our loop for the timeout duration */
 +
 +      default: /* for clarity */
 +        break;
 +      }
 +    }
 +    result = ftp_readresp(sockfd, pp, ftpcode, &nread);
 +    if(result)
 +      break;
 +
 +    if(!nread && pp->cache)
 +      /* bump cache skip counter as on repeated skips we must wait for more
 +         data */
 +      cache_skip++;
 +    else
 +      /* when we got data or there is no cache left, we reset the cache skip
 +         counter */
 +      cache_skip=0;
 +
 +    *nreadp += nread;
 +
 +  } /* while there's buffer left and loop is requested */
 +
 +  pp->pending_resp = FALSE;
 +
 +  return result;
 +}
 +
 +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
 +  /* for debug purposes */
 +static const char * const ftp_state_names[]={
 +  "STOP",
 +  "WAIT220",
 +  "AUTH",
 +  "USER",
 +  "PASS",
 +  "ACCT",
 +  "PBSZ",
 +  "PROT",
 +  "CCC",
 +  "PWD",
 +  "SYST",
 +  "NAMEFMT",
 +  "QUOTE",
 +  "RETR_PREQUOTE",
 +  "STOR_PREQUOTE",
 +  "POSTQUOTE",
 +  "CWD",
 +  "MKD",
 +  "MDTM",
 +  "TYPE",
 +  "LIST_TYPE",
 +  "RETR_TYPE",
 +  "STOR_TYPE",
 +  "SIZE",
 +  "RETR_SIZE",
 +  "STOR_SIZE",
 +  "REST",
 +  "RETR_REST",
 +  "PORT",
 +  "PRET",
 +  "PASV",
 +  "LIST",
 +  "RETR",
 +  "STOR",
 +  "QUIT"
 +};
 +#endif
 +
 +/* This is the ONLY way to change FTP state! */
 +static void _state(struct connectdata *conn,
 +                   ftpstate newstate
 +#ifdef DEBUGBUILD
 +                   , int lineno
 +#endif
 +  )
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +#if defined(DEBUGBUILD)
 +
 +#if defined(CURL_DISABLE_VERBOSE_STRINGS)
 +  (void) lineno;
 +#else
 +  if(ftpc->state != newstate)
 +    infof(conn->data, "FTP %p (line %d) state change from %s to %s\n",
 +          (void *)ftpc, lineno, ftp_state_names[ftpc->state],
 +          ftp_state_names[newstate]);
 +#endif
 +#endif
 +
 +  ftpc->state = newstate;
 +}
 +
 +static CURLcode ftp_state_user(struct connectdata *conn)
 +{
 +  CURLcode result;
 +  struct FTP *ftp = conn->data->req.protop;
 +  /* send USER */
 +  PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:"");
 +
 +  state(conn, FTP_USER);
 +  conn->data->state.ftp_trying_alternative = FALSE;
 +
 +  return CURLE_OK;
 +}
 +
 +static CURLcode ftp_state_pwd(struct connectdata *conn)
 +{
 +  CURLcode result;
 +
 +  /* send PWD to discover our entry point */
 +  PPSENDF(&conn->proto.ftpc.pp, "%s", "PWD");
 +  state(conn, FTP_PWD);
 +
 +  return CURLE_OK;
 +}
 +
 +/* For the FTP "protocol connect" and "doing" phases only */
 +static int ftp_getsock(struct connectdata *conn,
 +                       curl_socket_t *socks,
 +                       int numsocks)
 +{
 +  return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
 +}
 +
 +/* For the FTP "DO_MORE" phase only */
 +static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks,
 +                              int numsocks)
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if(!numsocks)
 +    return GETSOCK_BLANK;
 +
 +  /* When in DO_MORE state, we could be either waiting for us to connect to a
 +   * remote site, or we could wait for that site to connect to us. Or just
 +   * handle ordinary commands.
 +   */
 +
 +  if(FTP_STOP == ftpc->state) {
 +    int bits = GETSOCK_READSOCK(0);
 +
 +    /* if stopped and still in this state, then we're also waiting for a
 +       connect on the secondary connection */
 +    socks[0] = conn->sock[FIRSTSOCKET];
 +
 +    if(!conn->data->set.ftp_use_port) {
 +      int s;
 +      int i;
 +      /* PORT is used to tell the server to connect to us, and during that we
 +         don't do happy eyeballs, but we do if we connect to the server */
 +      for(s=1, i=0; i<2; i++) {
 +        if(conn->tempsock[i] != CURL_SOCKET_BAD) {
 +          socks[s] = conn->tempsock[i];
 +          bits |= GETSOCK_WRITESOCK(s++);
 +        }
 +      }
 +    }
 +    else {
 +      socks[1] = conn->sock[SECONDARYSOCKET];
 +      bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1);
 +    }
 +
 +    return bits;
 +  }
 +  else
 +    return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks);
 +}
 +
 +/* This is called after the FTP_QUOTE state is passed.
 +
 +   ftp_state_cwd() sends the range of CWD commands to the server to change to
 +   the correct directory. It may also need to send MKD commands to create
 +   missing ones, if that option is enabled.
 +*/
 +static CURLcode ftp_state_cwd(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if(ftpc->cwddone)
 +    /* already done and fine */
 +    result = ftp_state_mdtm(conn);
 +  else {
 +    ftpc->count2 = 0; /* count2 counts failed CWDs */
 +
 +    /* count3 is set to allow a MKD to fail once. In the case when first CWD
 +       fails and then MKD fails (due to another session raced it to create the
 +       dir) this then allows for a second try to CWD to it */
 +    ftpc->count3 = (conn->data->set.ftp_create_missing_dirs==2)?1:0;
 +
 +    if(conn->bits.reuse && ftpc->entrypath) {
 +      /* This is a re-used connection. Since we change directory to where the
 +         transfer is taking place, we must first get back to the original dir
 +         where we ended up after login: */
 +      ftpc->count1 = 0; /* we count this as the first path, then we add one
 +                          for all upcoming ones in the ftp->dirs[] array */
 +      PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->entrypath);
 +      state(conn, FTP_CWD);
 +    }
 +    else {
 +      if(ftpc->dirdepth) {
 +        ftpc->count1 = 1;
 +        /* issue the first CWD, the rest is sent when the CWD responses are
 +           received... */
 +        PPSENDF(&conn->proto.ftpc.pp, "CWD %s", ftpc->dirs[ftpc->count1 -1]);
 +        state(conn, FTP_CWD);
 +      }
 +      else {
 +        /* No CWD necessary */
 +        result = ftp_state_mdtm(conn);
 +      }
 +    }
 +  }
 +  return result;
 +}
 +
 +typedef enum {
 +  EPRT,
 +  PORT,
 +  DONE
 +} ftpport;
 +
 +static CURLcode ftp_state_use_port(struct connectdata *conn,
 +                                   ftpport fcmd) /* start with this */
 +
 +{
 +  CURLcode result = CURLE_OK;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct Curl_easy *data=conn->data;
 +  curl_socket_t portsock= CURL_SOCKET_BAD;
 +  char myhost[256] = "";
 +
 +  struct Curl_sockaddr_storage ss;
 +  Curl_addrinfo *res, *ai;
 +  curl_socklen_t sslen;
 +  char hbuf[NI_MAXHOST];
 +  struct sockaddr *sa=(struct sockaddr *)&ss;
 +  struct sockaddr_in * const sa4 = (void *)sa;
 +#ifdef ENABLE_IPV6
 +  struct sockaddr_in6 * const sa6 = (void *)sa;
 +#endif
 +  char tmp[1024];
 +  static const char mode[][5] = { "EPRT", "PORT" };
 +  int rc;
 +  int error;
 +  char *host = NULL;
 +  char *string_ftpport = data->set.str[STRING_FTPPORT];
 +  struct Curl_dns_entry *h=NULL;
 +  unsigned short port_min = 0;
 +  unsigned short port_max = 0;
 +  unsigned short port;
 +  bool possibly_non_local = TRUE;
 +
 +  char *addr = NULL;
 +
 +  /* Step 1, figure out what is requested,
 +   * accepted format :
 +   * (ipv4|ipv6|domain|interface)?(:port(-range)?)?
 +   */
 +
 +  if(data->set.str[STRING_FTPPORT] &&
 +     (strlen(data->set.str[STRING_FTPPORT]) > 1)) {
 +
 +#ifdef ENABLE_IPV6
 +    size_t addrlen = INET6_ADDRSTRLEN > strlen(string_ftpport) ?
 +      INET6_ADDRSTRLEN : strlen(string_ftpport);
 +#else
 +    size_t addrlen = INET_ADDRSTRLEN > strlen(string_ftpport) ?
 +      INET_ADDRSTRLEN : strlen(string_ftpport);
 +#endif
 +    char *ip_start = string_ftpport;
 +    char *ip_end = NULL;
 +    char *port_start = NULL;
 +    char *port_sep = NULL;
 +
 +    addr = calloc(addrlen+1, 1);
 +    if(!addr)
 +      return CURLE_OUT_OF_MEMORY;
 +
 +#ifdef ENABLE_IPV6
 +    if(*string_ftpport == '[') {
 +      /* [ipv6]:port(-range) */
 +      ip_start = string_ftpport + 1;
-       if((ip_end = strchr(string_ftpport, ']')) != NULL)
++      ip_end = strchr(string_ftpport, ']');
++      if(ip_end)
 +        strncpy(addr, ip_start, ip_end - ip_start);
 +    }
 +    else
 +#endif
 +      if(*string_ftpport == ':') {
 +        /* :port */
 +        ip_end = string_ftpport;
-     }
-     else if((ip_end = strchr(string_ftpport, ':')) != NULL) {
-         /* either ipv6 or (ipv4|domain|interface):port(-range) */
- #ifdef ENABLE_IPV6
-       if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
-         /* ipv6 */
-         port_min = port_max = 0;
-         strcpy(addr, string_ftpport);
-         ip_end = NULL; /* this got no port ! */
 +      }
-       else
++      else {
++        ip_end = strchr(string_ftpport, ':');
++        if(ip_end) {
++          /* either ipv6 or (ipv4|domain|interface):port(-range) */
++#ifdef ENABLE_IPV6
++          if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
++            /* ipv6 */
++            port_min = port_max = 0;
++            strcpy(addr, string_ftpport);
++            ip_end = NULL; /* this got no port ! */
++          }
++          else
 +#endif
-         /* (ipv4|domain|interface):port(-range) */
-         strncpy(addr, string_ftpport, ip_end - ip_start);
-     }
-     else
-       /* ipv4|interface */
-       strcpy(addr, string_ftpport);
++            /* (ipv4|domain|interface):port(-range) */
++            strncpy(addr, string_ftpport, ip_end - ip_start);
++        }
++        else
++          /* ipv4|interface */
++          strcpy(addr, string_ftpport);
++      }
 +
 +    /* parse the port */
 +    if(ip_end != NULL) {
-       if((port_start = strchr(ip_end, ':')) != NULL) {
++      port_start = strchr(ip_end, ':');
++      if(port_start) {
 +        port_min = curlx_ultous(strtoul(port_start+1, NULL, 10));
-         if((port_sep = strchr(port_start, '-')) != NULL) {
++        port_sep = strchr(port_start, '-');
++        if(port_sep) {
 +          port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10));
 +        }
 +        else
 +          port_max = port_min;
 +      }
 +    }
 +
 +    /* correct errors like:
 +     *  :1234-1230
 +     *  :-4711,  in this case port_min is (unsigned)-1,
 +     *           therefore port_min > port_max for all cases
 +     *           but port_max = (unsigned)-1
 +     */
 +    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,
 +                        Curl_ipv6_scope(conn->ip_addr->ai_addr),
 +                        conn->scope_id, addr, hbuf, sizeof(hbuf))) {
 +        case IF2IP_NOT_FOUND:
 +          /* not an interface, use the given string as host name instead */
 +          host = addr;
 +          break;
 +        case IF2IP_AF_NOT_SUPPORTED:
 +          return CURLE_FTP_PORT_FAILED;
 +        case IF2IP_FOUND:
 +          host = hbuf; /* use the hbuf for host name */
 +      }
 +    }
 +    else
 +      /* there was only a port(-range) given, default the host */
 +      host = NULL;
 +  } /* data->set.ftpport */
 +
 +  if(!host) {
 +    /* not an interface and not a host name, get default by extracting
 +       the IP from the control connection */
 +
 +    sslen = sizeof(ss);
 +    if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
 +      failf(data, "getsockname() failed: %s",
 +          Curl_strerror(conn, SOCKERRNO) );
 +      free(addr);
 +      return CURLE_FTP_PORT_FAILED;
 +    }
 +    switch(sa->sa_family) {
 +#ifdef ENABLE_IPV6
 +    case AF_INET6:
 +      Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
 +      break;
 +#endif
 +    default:
 +      Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
 +      break;
 +    }
 +    host = hbuf; /* use this host name */
 +    possibly_non_local = FALSE; /* we know it is local now */
 +  }
 +
 +  /* resolv ip/host to ip */
 +  rc = Curl_resolv(conn, host, 0, &h);
 +  if(rc == CURLRESOLV_PENDING)
 +    (void)Curl_resolver_wait_resolv(conn, &h);
 +  if(h) {
 +    res = h->addr;
 +    /* when we return from this function, we can forget about this entry
 +       to we can unlock it now already */
 +    Curl_resolv_unlock(data, h);
 +  } /* (h) */
 +  else
 +    res = NULL; /* failure! */
 +
 +  if(res == NULL) {
 +    failf(data, "failed to resolve the address provided to PORT: %s", host);
 +    free(addr);
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  free(addr);
 +  host = NULL;
 +
 +  /* step 2, create a socket for the requested address */
 +
 +  portsock = CURL_SOCKET_BAD;
 +  error = 0;
 +  for(ai = res; ai; ai = ai->ai_next) {
 +    result = Curl_socket(conn, ai, NULL, &portsock);
 +    if(result) {
 +      error = SOCKERRNO;
 +      continue;
 +    }
 +    break;
 +  }
 +  if(!ai) {
 +    failf(data, "socket failure: %s", Curl_strerror(conn, error));
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  /* step 3, bind to a suitable local address */
 +
 +  memcpy(sa, ai->ai_addr, ai->ai_addrlen);
 +  sslen = ai->ai_addrlen;
 +
 +  for(port = port_min; port <= port_max;) {
 +    if(sa->sa_family == AF_INET)
 +      sa4->sin_port = htons(port);
 +#ifdef ENABLE_IPV6
 +    else
 +      sa6->sin6_port = htons(port);
 +#endif
 +    /* Try binding the given address. */
 +    if(bind(portsock, sa, sslen) ) {
 +      /* It failed. */
 +      error = SOCKERRNO;
 +      if(possibly_non_local && (error == EADDRNOTAVAIL)) {
 +        /* The requested bind address is not local.  Use the address used for
 +         * the control connection instead and restart the port loop
 +         */
 +
 +        infof(data, "bind(port=%hu) on non-local address failed: %s\n", port,
 +              Curl_strerror(conn, error) );
 +
 +        sslen = sizeof(ss);
 +        if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
 +          failf(data, "getsockname() failed: %s",
 +                Curl_strerror(conn, SOCKERRNO) );
 +          Curl_closesocket(conn, portsock);
 +          return CURLE_FTP_PORT_FAILED;
 +        }
 +        port = port_min;
 +        possibly_non_local = FALSE; /* don't try this again */
 +        continue;
 +      }
 +      else if(error != EADDRINUSE && error != EACCES) {
 +        failf(data, "bind(port=%hu) failed: %s", port,
 +              Curl_strerror(conn, error) );
 +        Curl_closesocket(conn, portsock);
 +        return CURLE_FTP_PORT_FAILED;
 +      }
 +    }
 +    else
 +      break;
 +
 +    port++;
 +  }
 +
 +  /* maybe all ports were in use already*/
 +  if(port > port_max) {
 +    failf(data, "bind() failed, we ran out of ports!");
 +    Curl_closesocket(conn, portsock);
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  /* 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)) {
 +    failf(data, "getsockname() failed: %s",
 +          Curl_strerror(conn, SOCKERRNO) );
 +    Curl_closesocket(conn, portsock);
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  /* step 4, listen on the socket */
 +
 +  if(listen(portsock, 1)) {
 +    failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO));
 +    Curl_closesocket(conn, portsock);
 +    return CURLE_FTP_PORT_FAILED;
 +  }
 +
 +  /* step 5, send the proper FTP command */
 +
 +  /* get a plain printable version of the numerical address to work with
 +     below */
 +  Curl_printable_address(ai, myhost, sizeof(myhost));
 +
 +#ifdef ENABLE_IPV6
 +  if(!conn->bits.ftp_use_eprt && conn->bits.ipv6)
 +    /* EPRT is disabled but we are connected to a IPv6 host, so we ignore the
 +       request and enable EPRT again! */
 +    conn->bits.ftp_use_eprt = TRUE;
 +#endif
 +
 +  for(; fcmd != DONE; fcmd++) {
 +
 +    if(!conn->bits.ftp_use_eprt && (EPRT == fcmd))
 +      /* if disabled, goto next */
 +      continue;
 +
 +    if((PORT == fcmd) && sa->sa_family != AF_INET)
 +      /* PORT is IPv4 only */
 +      continue;
 +
 +    switch(sa->sa_family) {
 +    case AF_INET:
 +      port = ntohs(sa4->sin_port);
 +      break;
 +#ifdef ENABLE_IPV6
 +    case AF_INET6:
 +      port = ntohs(sa6->sin6_port);
 +      break;
 +#endif
 +    default:
 +      continue; /* might as well skip this */
 +    }
 +
 +    if(EPRT == fcmd) {
 +      /*
 +       * Two fine examples from RFC2428;
 +       *
 +       * EPRT |1|132.235.1.2|6275|
 +       *
 +       * EPRT |2|1080::8:800:200C:417A|5282|
 +       */
 +
 +      result = Curl_pp_sendf(&ftpc->pp, "%s |%d|%s|%hu|", mode[fcmd],
 +                             sa->sa_family == AF_INET?1:2,
 +                             myhost, port);
 +      if(result) {
 +        failf(data, "Failure sending EPRT command: %s",
 +              curl_easy_strerror(result));
 +        Curl_closesocket(conn, portsock);
 +        /* don't retry using PORT */
 +        ftpc->count1 = PORT;
 +        /* bail out */
 +        state(conn, FTP_STOP);
 +        return result;
 +      }
 +      break;
 +    }
 +    else if(PORT == fcmd) {
 +      char *source = myhost;
 +      char *dest = tmp;
 +
 +      /* translate x.x.x.x to x,x,x,x */
 +      while(source && *source) {
 +        if(*source == '.')
 +          *dest=',';
 +        else
 +          *dest = *source;
 +        dest++;
 +        source++;
 +      }
 +      *dest = 0;
 +      snprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
 +
 +      result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
 +      if(result) {
 +        failf(data, "Failure sending PORT command: %s",
 +              curl_easy_strerror(result));
 +        Curl_closesocket(conn, portsock);
 +        /* bail out */
 +        state(conn, FTP_STOP);
 +        return result;
 +      }
 +      break;
 +    }
 +  }
 +
 +  /* store which command was sent */
 +  ftpc->count1 = fcmd;
 +
 +  close_secondarysocket(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;
 +
 +  state(conn, FTP_PORT);
 +  return result;
 +}
 +
 +static CURLcode ftp_state_use_pasv(struct connectdata *conn)
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  CURLcode result = CURLE_OK;
 +  /*
 +    Here's the excecutive summary on what to do:
 +
 +    PASV is RFC959, expect:
 +    227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
 +
 +    LPSV is RFC1639, expect:
 +    228 Entering Long Passive Mode (4,4,a1,a2,a3,a4,2,p1,p2)
 +
 +    EPSV is RFC2428, expect:
 +    229 Entering Extended Passive Mode (|||port|)
 +
 +  */
 +
 +  static const char mode[][5] = { "EPSV", "PASV" };
 +  int modeoff;
 +
 +#ifdef PF_INET6
 +  if(!conn->bits.ftp_use_epsv && conn->bits.ipv6)
 +    /* EPSV is disabled but we are connected to a IPv6 host, so we ignore the
 +       request and enable EPSV again! */
 +    conn->bits.ftp_use_epsv = TRUE;
 +#endif
 +
 +  modeoff = conn->bits.ftp_use_epsv?0:1;
 +
 +  PPSENDF(&ftpc->pp, "%s", mode[modeoff]);
 +
 +  ftpc->count1 = modeoff;
 +  state(conn, FTP_PASV);
 +  infof(conn->data, "Connect data stream passively\n");
 +
 +  return result;
 +}
 +
 +/*
 + * ftp_state_prepare_transfer() starts PORT, PASV or PRET etc.
 + *
 + * REST is the last command in the chain of commands when a "head"-like
 + * request is made. Thus, if an actual transfer is to be made this is where we
 + * take off for real.
 + */
 +static CURLcode ftp_state_prepare_transfer(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct FTP *ftp = conn->data->req.protop;
 +  struct Curl_easy *data = conn->data;
 +
 +  if(ftp->transfer != FTPTRANSFER_BODY) {
 +    /* doesn't transfer any data */
 +
 +    /* still possibly do PRE QUOTE jobs */
 +    state(conn, FTP_RETR_PREQUOTE);
 +    result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
 +  }
 +  else if(data->set.ftp_use_port) {
 +    /* We have chosen to use the PORT (or similar) command */
 +    result = ftp_state_use_port(conn, EPRT);
 +  }
 +  else {
 +    /* We have chosen (this is default) to use the PASV (or similar) command */
 +    if(data->set.ftp_use_pret) {
 +      /* The user has requested that we send a PRET command
 +         to prepare the server for the upcoming PASV */
 +      if(!conn->proto.ftpc.file) {
 +        PPSENDF(&conn->proto.ftpc.pp, "PRET %s",
 +                data->set.str[STRING_CUSTOMREQUEST]?
 +                data->set.str[STRING_CUSTOMREQUEST]:
 +                (data->set.ftp_list_only?"NLST":"LIST"));
 +      }
 +      else if(data->set.upload) {
 +        PPSENDF(&conn->proto.ftpc.pp, "PRET STOR %s", conn->proto.ftpc.file);
 +      }
 +      else {
 +        PPSENDF(&conn->proto.ftpc.pp, "PRET RETR %s", conn->proto.ftpc.file);
 +      }
 +      state(conn, FTP_PRET);
 +    }
 +    else {
 +      result = ftp_state_use_pasv(conn);
 +    }
 +  }
 +  return result;
 +}
 +
 +static CURLcode ftp_state_rest(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct FTP *ftp = conn->data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if((ftp->transfer != FTPTRANSFER_BODY) && ftpc->file) {
 +    /* if a "head"-like request is being made (on a file) */
 +
 +    /* Determine if server can respond to REST command and therefore
 +       whether it supports range */
 +    PPSENDF(&conn->proto.ftpc.pp, "REST %d", 0);
 +
 +    state(conn, FTP_REST);
 +  }
 +  else
 +    result = ftp_state_prepare_transfer(conn);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_size(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct FTP *ftp = conn->data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if((ftp->transfer == FTPTRANSFER_INFO) && ftpc->file) {
 +    /* if a "head"-like request is being made (on a file) */
 +
 +    /* we know ftpc->file is a valid pointer to a file name */
 +    PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
 +
 +    state(conn, FTP_SIZE);
 +  }
 +  else
 +    result = ftp_state_rest(conn);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_list(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +
 +  /* If this output is to be machine-parsed, the NLST command might be better
 +     to use, since the LIST command output is not specified or standard in any
 +     way. It has turned out that the NLST list output is not the same on all
 +     servers either... */
 +
 +  /*
 +     if FTPFILE_NOCWD was specified, we are currently in
 +     the user's home directory, so we should add the path
 +     as argument for the LIST / NLST / or custom command.
 +     Whether the server will support this, is uncertain.
 +
 +     The other ftp_filemethods will CWD into dir/dir/ first and
 +     then just do LIST (in that case: nothing to do here)
 +  */
 +  char *cmd, *lstArg, *slashPos;
 +
 +  lstArg = NULL;
 +  if((data->set.ftp_filemethod == FTPFILE_NOCWD) &&
 +     data->state.path &&
 +     data->state.path[0] &&
 +     strchr(data->state.path, '/')) {
 +
 +    lstArg = strdup(data->state.path);
 +    if(!lstArg)
 +      return CURLE_OUT_OF_MEMORY;
 +
 +    /* Check if path does not end with /, as then we cut off the file part */
 +    if(lstArg[strlen(lstArg) - 1] != '/')  {
 +
 +      /* chop off the file part if format is dir/dir/file */
 +      slashPos = strrchr(lstArg, '/');
 +      if(slashPos)
 +        *(slashPos+1) = '\0';
 +    }
 +  }
 +
 +  cmd = aprintf("%s%s%s",
 +                data->set.str[STRING_CUSTOMREQUEST]?
 +                data->set.str[STRING_CUSTOMREQUEST]:
 +                (data->set.ftp_list_only?"NLST":"LIST"),
 +                lstArg? " ": "",
 +                lstArg? lstArg: "");
 +
 +  if(!cmd) {
 +    free(lstArg);
 +    return CURLE_OUT_OF_MEMORY;
 +  }
 +
 +  result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", cmd);
 +
 +  free(lstArg);
 +  free(cmd);
 +
 +  if(result)
 +    return result;
 +
 +  state(conn, FTP_LIST);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_retr_prequote(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +
 +  /* We've sent the TYPE, now we must send the list of prequote strings */
 +
 +  result = ftp_state_quote(conn, TRUE, FTP_RETR_PREQUOTE);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_stor_prequote(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +
 +  /* We've sent the TYPE, now we must send the list of prequote strings */
 +
 +  result = ftp_state_quote(conn, TRUE, FTP_STOR_PREQUOTE);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_type(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct FTP *ftp = conn->data->req.protop;
 +  struct Curl_easy *data = conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  /* If we have selected NOBODY and HEADER, it means that we only want file
 +     information. Which in FTP can't be much more than the file size and
 +     date. */
 +  if(data->set.opt_no_body && ftpc->file &&
 +     ftp_need_type(conn, data->set.prefer_ascii)) {
 +    /* The SIZE command is _not_ RFC 959 specified, and therefor many servers
 +       may not support it! It is however the only way we have to get a file's
 +       size! */
 +
 +    ftp->transfer = FTPTRANSFER_INFO;
 +    /* this means no actual transfer will be made */
 +
 +    /* Some servers return different sizes for different modes, and thus we
 +       must set the proper type before we check the size */
 +    result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_TYPE);
 +    if(result)
 +      return result;
 +  }
 +  else
 +    result = ftp_state_size(conn);
 +
 +  return result;
 +}
 +
 +/* This is called after the CWD commands have been done in the beginning of
 +   the DO phase */
 +static CURLcode ftp_state_mdtm(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  /* Requested time of file or time-depended transfer? */
 +  if((data->set.get_filetime || data->set.timecondition) && ftpc->file) {
 +
 +    /* we have requested to get the modified-time of the file, this is a white
 +       spot as the MDTM is not mentioned in RFC959 */
 +    PPSENDF(&ftpc->pp, "MDTM %s", ftpc->file);
 +
 +    state(conn, FTP_MDTM);
 +  }
 +  else
 +    result = ftp_state_type(conn);
 +
 +  return result;
 +}
 +
 +
 +/* This is called after the TYPE and possible quote commands have been sent */
 +static CURLcode ftp_state_ul_setup(struct connectdata *conn,
 +                                   bool sizechecked)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct FTP *ftp = conn->data->req.protop;
 +  struct Curl_easy *data = conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  int seekerr = CURL_SEEKFUNC_OK;
 +
 +  if((data->state.resume_from && !sizechecked) ||
 +     ((data->state.resume_from > 0) && sizechecked)) {
 +    /* we're about to continue the uploading of a file */
 +    /* 1. get already existing file's size. We use the SIZE command for this
 +       which may not exist in the server!  The SIZE command is not in
 +       RFC959. */
 +
 +    /* 2. This used to set REST. But since we can do append, we
 +       don't another ftp command. We just skip the source file
 +       offset and then we APPEND the rest on the file instead */
 +
 +    /* 3. pass file-size number of bytes in the source file */
 +    /* 4. lower the infilesize counter */
 +    /* => transfer as usual */
 +
 +    if(data->state.resume_from < 0) {
 +      /* Got no given size to start from, figure it out */
 +      PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
 +      state(conn, FTP_STOR_SIZE);
 +      return result;
 +    }
 +
 +    /* enable append */
 +    data->set.ftp_append = TRUE;
 +
 +    /* Let's read off the proper amount of bytes from the input. */
 +    if(conn->seek_func) {
 +      seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
 +                                SEEK_SET);
 +    }
 +
 +    if(seekerr != CURL_SEEKFUNC_OK) {
 +      if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
 +        failf(data, "Could not seek stream");
 +        return CURLE_FTP_COULDNT_USE_REST;
 +      }
 +      /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
 +      else {
 +        curl_off_t passed=0;
 +        do {
 +          size_t readthisamountnow =
 +            (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
 +            BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
 +
 +          size_t actuallyread =
 +            data->state.fread_func(data->state.buffer, 1, readthisamountnow,
 +                                   data->state.in);
 +
 +          passed += actuallyread;
 +          if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
 +            /* this checks for greater-than only to make sure that the
 +               CURL_READFUNC_ABORT return code still aborts */
 +            failf(data, "Failed to read data");
 +            return CURLE_FTP_COULDNT_USE_REST;
 +          }
 +        } while(passed < data->state.resume_from);
 +      }
 +    }
 +    /* now, decrease the size of the read */
 +    if(data->state.infilesize>0) {
 +      data->state.infilesize -= data->state.resume_from;
 +
 +      if(data->state.infilesize <= 0) {
 +        infof(data, "File already completely uploaded\n");
 +
 +        /* no data to transfer */
 +        Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
 +
 +        /* Set ->transfer so that we won't get any error in
 +         * ftp_done() because we didn't transfer anything! */
 +        ftp->transfer = FTPTRANSFER_NONE;
 +
 +        state(conn, FTP_STOP);
 +        return CURLE_OK;
 +      }
 +    }
 +    /* we've passed, proceed as normal */
 +  } /* resume_from */
 +
 +  PPSENDF(&ftpc->pp, data->set.ftp_append?"APPE %s":"STOR %s",
 +          ftpc->file);
 +
 +  state(conn, FTP_STOR);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_quote(struct connectdata *conn,
 +                                bool init,
 +                                ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  struct FTP *ftp = data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  bool quote=FALSE;
 +  struct curl_slist *item;
 +
 +  switch(instate) {
 +  case FTP_QUOTE:
 +  default:
 +    item = data->set.quote;
 +    break;
 +  case FTP_RETR_PREQUOTE:
 +  case FTP_STOR_PREQUOTE:
 +    item = data->set.prequote;
 +    break;
 +  case FTP_POSTQUOTE:
 +    item = data->set.postquote;
 +    break;
 +  }
 +
 +  /*
 +   * This state uses:
 +   * 'count1' to iterate over the commands to send
 +   * 'count2' to store wether to allow commands to fail
 +   */
 +
 +  if(init)
 +    ftpc->count1 = 0;
 +  else
 +    ftpc->count1++;
 +
 +  if(item) {
 +    int i = 0;
 +
 +    /* Skip count1 items in the linked list */
 +    while((i< ftpc->count1) && item) {
 +      item = item->next;
 +      i++;
 +    }
 +    if(item) {
 +      char *cmd = item->data;
 +      if(cmd[0] == '*') {
 +        cmd++;
 +        ftpc->count2 = 1; /* the sent command is allowed to fail */
 +      }
 +      else
 +        ftpc->count2 = 0; /* failure means cancel operation */
 +
 +      PPSENDF(&ftpc->pp, "%s", cmd);
 +      state(conn, instate);
 +      quote = TRUE;
 +    }
 +  }
 +
 +  if(!quote) {
 +    /* No more quote to send, continue to ... */
 +    switch(instate) {
 +    case FTP_QUOTE:
 +    default:
 +      result = ftp_state_cwd(conn);
 +      break;
 +    case FTP_RETR_PREQUOTE:
 +      if(ftp->transfer != FTPTRANSFER_BODY)
 +        state(conn, FTP_STOP);
 +      else {
 +        if(ftpc->known_filesize != -1) {
 +          Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
 +          result = ftp_state_retr(conn, ftpc->known_filesize);
 +        }
 +        else {
 +          if(data->set.ignorecl) {
 +            /* This code is to support download of growing files.  It prevents
 +               the state machine from requesting the file size from the
 +               server.  With an unknown file size the download continues until
 +               the server terminates it, otherwise the client stops if the
 +               received byte count exceeds the reported file size.  Set option
 +               CURLOPT_IGNORE_CONTENT_LENGTH to 1 to enable this behavior.*/
 +            PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
 +            state(conn, FTP_RETR);
 +          }
 +          else {
 +            PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
 +            state(conn, FTP_RETR_SIZE);
 +          }
 +        }
 +      }
 +      break;
 +    case FTP_STOR_PREQUOTE:
 +      result = ftp_state_ul_setup(conn, FALSE);
 +      break;
 +    case FTP_POSTQUOTE:
 +      break;
 +    }
 +  }
 +
 +  return result;
 +}
 +
 +/* called from ftp_state_pasv_resp to switch to PASV in case of EPSV
 +   problems */
 +static CURLcode ftp_epsv_disable(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +
 +  if(conn->bits.ipv6) {
 +    /* We can't disable EPSV when doing IPv6, so this is instead a fail */
 +    failf(conn->data, "Failed EPSV attempt, exiting\n");
 +    return CURLE_WEIRD_SERVER_REPLY;
 +  }
 +
 +  infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n");
 +  /* disable it for next transfer */
 +  conn->bits.ftp_use_epsv = FALSE;
 +  conn->data->state.errorbuf = FALSE; /* allow error message to get
 +                                         rewritten */
 +  PPSENDF(&conn->proto.ftpc.pp, "%s", "PASV");
 +  conn->proto.ftpc.count1++;
 +  /* remain in/go to the FTP_PASV state */
 +  state(conn, FTP_PASV);
 +  return result;
 +}
 +
- /*
-  * Perform the necessary magic that needs to be done once the TCP connection
-  * to the proxy has completed.
-  */
- static CURLcode proxy_magic(struct connectdata *conn,
-                             char *newhost, unsigned short newport,
-                             bool *magicdone)
- {
-   CURLcode result = CURLE_OK;
-   struct Curl_easy *data = conn->data;
- 
- #if defined(CURL_DISABLE_PROXY)
-   (void) newhost;
-   (void) newport;
- #endif
- 
-   *magicdone = FALSE;
- 
-   switch(conn->proxytype) {
-   case CURLPROXY_SOCKS5:
-   case CURLPROXY_SOCKS5_HOSTNAME:
-     result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost,
-                          newport, SECONDARYSOCKET, conn);
-     *magicdone = TRUE;
-     break;
-   case CURLPROXY_SOCKS4:
-     result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
-                          SECONDARYSOCKET, conn, FALSE);
-     *magicdone = TRUE;
-     break;
-   case CURLPROXY_SOCKS4A:
-     result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
-                          SECONDARYSOCKET, conn, TRUE);
-     *magicdone = TRUE;
-     break;
-   case CURLPROXY_HTTP:
-   case CURLPROXY_HTTP_1_0:
-     /* do nothing here. handled later. */
-     break;
-   default:
-     failf(data, "unknown proxytype option given");
-     result = CURLE_COULDNT_CONNECT;
-     break;
-   }
- 
-   if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
-     /* BLOCKING */
-     /* We want "seamless" FTP operations through HTTP proxy tunnel */
- 
-     /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
-      * member conn->proto.http; we want FTP through HTTP and we have to
-      * change the member temporarily for connecting to the HTTP proxy. After
-      * Curl_proxyCONNECT we have to set back the member to the original
-      * struct FTP pointer
-      */
-     struct HTTP http_proxy;
-     struct FTP *ftp_save = data->req.protop;
-     memset(&http_proxy, 0, sizeof(http_proxy));
-     data->req.protop = &http_proxy;
- 
-     result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE);
- 
-     data->req.protop = ftp_save;
- 
-     if(result)
-       return result;
- 
-     if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
-       /* the CONNECT procedure is not complete, the tunnel is not yet up */
-       state(conn, FTP_STOP); /* this phase is completed */
-       return result;
-     }
-     else
-       *magicdone = TRUE;
-   }
- 
-   return result;
- }
 +
 +static char *control_address(struct connectdata *conn)
 +{
 +  /* Returns the control connection IP address.
 +     If a proxy tunnel is used, returns the original host name instead, because
 +     the effective control connection address is the proxy address,
 +     not the ftp host. */
-   if(conn->bits.tunnel_proxy ||
-      conn->proxytype == CURLPROXY_SOCKS5 ||
-      conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
-      conn->proxytype == CURLPROXY_SOCKS4 ||
-      conn->proxytype == CURLPROXY_SOCKS4A)
++  if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
 +    return conn->host.name;
 +
 +  return conn->ip_addr_str;
 +}
 +
 +static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
 +                                    int ftpcode)
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  CURLcode result;
 +  struct Curl_easy *data=conn->data;
 +  struct Curl_dns_entry *addr=NULL;
 +  int rc;
 +  unsigned short connectport; /* the local port connect() should use! */
 +  char *str=&data->state.buffer[4];  /* start on the first letter */
 +
 +  /* if we come here again, make sure the former name is cleared */
 +  Curl_safefree(ftpc->newhost);
 +
 +  if((ftpc->count1 == 0) &&
 +     (ftpcode == 229)) {
 +    /* positive EPSV response */
 +    char *ptr = strchr(str, '(');
 +    if(ptr) {
 +      unsigned int num;
 +      char separator[4];
 +      ptr++;
 +      if(5 == sscanf(ptr, "%c%c%c%u%c",
 +                     &separator[0],
 +                     &separator[1],
 +                     &separator[2],
 +                     &num,
 +                     &separator[3])) {
 +        const char sep1 = separator[0];
 +        int i;
 +
 +        /* The four separators should be identical, or else this is an oddly
 +           formatted reply and we bail out immediately. */
 +        for(i=1; i<4; i++) {
 +          if(separator[i] != sep1) {
 +            ptr=NULL; /* set to NULL to signal error */
 +            break;
 +          }
 +        }
 +        if(num > 0xffff) {
 +          failf(data, "Illegal port number in EPSV reply");
 +          return CURLE_FTP_WEIRD_PASV_REPLY;
 +        }
 +        if(ptr) {
 +          ftpc->newport = (unsigned short)(num & 0xffff);
 +          ftpc->newhost = strdup(control_address(conn));
 +          if(!ftpc->newhost)
 +            return CURLE_OUT_OF_MEMORY;
 +        }
 +      }
 +      else
 +        ptr=NULL;
 +    }
 +    if(!ptr) {
 +      failf(data, "Weirdly formatted EPSV reply");
 +      return CURLE_FTP_WEIRD_PASV_REPLY;
 +    }
 +  }
 +  else if((ftpc->count1 == 1) &&
 +          (ftpcode == 227)) {
 +    /* positive PASV response */
 +    int ip[4];
 +    int port[2];
 +
 +    /*
 +     * Scan for a sequence of six comma-separated numbers and use them as
 +     * IP+port indicators.
 +     *
 +     * Found reply-strings include:
 +     * "227 Entering Passive Mode (127,0,0,1,4,51)"
 +     * "227 Data transfer will passively listen to 127,0,0,1,4,51"
 +     * "227 Entering passive mode. 127,0,0,1,4,51"
 +     */
 +    while(*str) {
 +      if(6 == sscanf(str, "%d,%d,%d,%d,%d,%d",
 +                     &ip[0], &ip[1], &ip[2], &ip[3],
 +                     &port[0], &port[1]))
 +        break;
 +      str++;
 +    }
 +
 +    if(!*str) {
 +      failf(data, "Couldn't interpret the 227-response");
 +      return CURLE_FTP_WEIRD_227_FORMAT;
 +    }
 +
 +    /* we got OK from server */
 +    if(data->set.ftp_skip_ip) {
 +      /* told to ignore the remotely given IP but instead use the host we used
 +         for the control connection */
 +      infof(data, "Skip %d.%d.%d.%d for data connection, re-use %s instead\n",
 +            ip[0], ip[1], ip[2], ip[3],
 +            conn->host.name);
 +      ftpc->newhost = strdup(control_address(conn));
 +    }
 +    else
 +      ftpc->newhost = aprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
 +
 +    if(!ftpc->newhost)
 +      return CURLE_OUT_OF_MEMORY;
 +
 +    ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff);
 +  }
 +  else if(ftpc->count1 == 0) {
 +    /* EPSV failed, move on to PASV */
 +    return ftp_epsv_disable(conn);
 +  }
 +  else {
 +    failf(data, "Bad PASV/EPSV response: %03d", ftpcode);
 +    return CURLE_FTP_WEIRD_PASV_REPLY;
 +  }
 +
 +  if(conn->bits.proxy) {
 +    /*
 +     * This connection uses a proxy and we need to connect to the proxy again
 +     * here. We don't want to rely on a former host lookup that might've
 +     * expired now, instead we remake the lookup here and now!
 +     */
-     rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr);
++    const char * const host_name = conn->bits.socksproxy ?
++      conn->socks_proxy.host.name : conn->http_proxy.host.name;
++    rc = Curl_resolv(conn, host_name, (int)conn->port, &addr);
 +    if(rc == CURLRESOLV_PENDING)
 +      /* BLOCKING, ignores the return code but 'addr' will be NULL in
 +         case of failure */
 +      (void)Curl_resolver_wait_resolv(conn, &addr);
 +
 +    connectport =
 +      (unsigned short)conn->port; /* we connect to the proxy's port */
 +
 +    if(!addr) {
-       failf(data, "Can't resolve proxy host %s:%hu",
-             conn->proxy.name, connectport);
++      failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport);
 +      return CURLE_FTP_CANT_GET_HOST;
 +    }
 +  }
 +  else {
 +    /* normal, direct, ftp connection */
 +    rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr);
 +    if(rc == CURLRESOLV_PENDING)
 +      /* BLOCKING */
 +      (void)Curl_resolver_wait_resolv(conn, &addr);
 +
 +    connectport = ftpc->newport; /* we connect to the remote port */
 +
 +    if(!addr) {
 +      failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport);
 +      return CURLE_FTP_CANT_GET_HOST;
 +    }
 +  }
 +
 +  conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
 +  result = Curl_connecthost(conn, addr);
 +
 +  if(result) {
 +    Curl_resolv_unlock(data, addr); /* we're done using this address */
 +    if(ftpc->count1 == 0 && ftpcode == 229)
 +      return ftp_epsv_disable(conn);
 +
 +    return result;
 +  }
 +
 +
 +  /*
 +   * When this is used from the multi interface, this might've returned with
 +   * the 'connected' set to FALSE and thus we are now awaiting a non-blocking
 +   * connect to connect.
 +   */
 +
 +  if(data->set.verbose)
 +    /* this just dumps information about this second connection */
 +    ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport);
 +
++  Curl_safefree(conn->secondaryhostname);
++  conn->secondaryhostname = strdup(ftpc->newhost);
++  conn->secondary_port = ftpc->newport;
++
 +  Curl_resolv_unlock(data, addr); /* we're done using this address */
 +  conn->bits.do_more = TRUE;
 +  state(conn, FTP_STOP); /* this phase is completed */
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_port_resp(struct connectdata *conn,
 +                                    int ftpcode)
 +{
 +  struct Curl_easy *data = conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  ftpport fcmd = (ftpport)ftpc->count1;
 +  CURLcode result = CURLE_OK;
 +
 +  /* The FTP spec tells a positive response should have code 200.
 +     Be more permissive here to tolerate deviant servers. */
 +  if(ftpcode / 100 != 2) {
 +    /* the command failed */
 +
 +    if(EPRT == fcmd) {
 +      infof(data, "disabling EPRT usage\n");
 +      conn->bits.ftp_use_eprt = FALSE;
 +    }
 +    fcmd++;
 +
 +    if(fcmd == DONE) {
 +      failf(data, "Failed to do PORT");
 +      result = CURLE_FTP_PORT_FAILED;
 +    }
 +    else
 +      /* try next */
 +      result = ftp_state_use_port(conn, fcmd);
 +  }
 +  else {
 +    infof(data, "Connect data stream actively\n");
 +    state(conn, FTP_STOP); /* end of DO phase */
 +    result = ftp_dophase_done(conn, FALSE);
 +  }
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
 +                                    int ftpcode)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data=conn->data;
 +  struct FTP *ftp = data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  switch(ftpcode) {
 +  case 213:
 +    {
 +      /* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
 +         last .sss part is optional and means fractions of a second */
 +      int year, month, day, hour, minute, second;
 +      char *buf = data->state.buffer;
 +      if(6 == sscanf(buf+4, "%04d%02d%02d%02d%02d%02d",
 +                     &year, &month, &day, &hour, &minute, &second)) {
 +        /* we have a time, reformat it */
 +        time_t secs=time(NULL);
 +        /* using the good old yacc/bison yuck */
 +        snprintf(buf, sizeof(conn->data->state.buffer),
 +                 "%04d%02d%02d %02d:%02d:%02d GMT",
 +                 year, month, day, hour, minute, second);
 +        /* now, convert this into a time() value: */
 +        data->info.filetime = (long)curl_getdate(buf, &secs);
 +      }
 +
 +#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. */
 +
 +      if(data->set.opt_no_body &&
 +         ftpc->file &&
 +         data->set.get_filetime &&
 +         (data->info.filetime>=0) ) {
 +        time_t filetime = (time_t)data->info.filetime;
 +        struct tm buffer;
 +        const struct tm *tm = &buffer;
 +
 +        result = Curl_gmtime(filetime, &buffer);
 +        if(result)
 +          return result;
 +
 +        /* format: "Tue, 15 Nov 1994 12:45:26" */
 +        snprintf(buf, BUFSIZE-1,
 +                 "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
 +                 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
 +                 tm->tm_mday,
 +                 Curl_month[tm->tm_mon],
 +                 tm->tm_year + 1900,
 +                 tm->tm_hour,
 +                 tm->tm_min,
 +                 tm->tm_sec);
 +        result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
 +        if(result)
 +          return result;
 +      } /* end of a ridiculous amount of conditionals */
 +#endif
 +    }
 +    break;
 +  default:
 +    infof(data, "unsupported MDTM reply format\n");
 +    break;
 +  case 550: /* "No such file or directory" */
 +    failf(data, "Given file does not exist");
 +    result = CURLE_FTP_COULDNT_RETR_FILE;
 +    break;
 +  }
 +
 +  if(data->set.timecondition) {
 +    if((data->info.filetime > 0) && (data->set.timevalue > 0)) {
 +      switch(data->set.timecondition) {
 +      case CURL_TIMECOND_IFMODSINCE:
 +      default:
 +        if(data->info.filetime <= data->set.timevalue) {
 +          infof(data, "The requested document is not new enough\n");
 +          ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
 +          data->info.timecond = TRUE;
 +          state(conn, FTP_STOP);
 +          return CURLE_OK;
 +        }
 +        break;
 +      case CURL_TIMECOND_IFUNMODSINCE:
 +        if(data->info.filetime > data->set.timevalue) {
 +          infof(data, "The requested document is not old enough\n");
 +          ftp->transfer = FTPTRANSFER_NONE; /* mark to not transfer data */
 +          data->info.timecond = TRUE;
 +          state(conn, FTP_STOP);
 +          return CURLE_OK;
 +        }
 +        break;
 +      } /* switch */
 +    }
 +    else {
 +      infof(data, "Skipping time comparison\n");
 +    }
 +  }
 +
 +  if(!result)
 +    result = ftp_state_type(conn);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_type_resp(struct connectdata *conn,
 +                                    int ftpcode,
 +                                    ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data=conn->data;
 +
 +  if(ftpcode/100 != 2) {
 +    /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a
 +       successful 'TYPE I'. While that is not as RFC959 says, it is still a
 +       positive response code and we allow that. */
 +    failf(data, "Couldn't set desired mode");
 +    return CURLE_FTP_COULDNT_SET_TYPE;
 +  }
 +  if(ftpcode != 200)
 +    infof(data, "Got a %03d response code instead of the assumed 200\n",
 +          ftpcode);
 +
 +  if(instate == FTP_TYPE)
 +    result = ftp_state_size(conn);
 +  else if(instate == FTP_LIST_TYPE)
 +    result = ftp_state_list(conn);
 +  else if(instate == FTP_RETR_TYPE)
 +    result = ftp_state_retr_prequote(conn);
 +  else if(instate == FTP_STOR_TYPE)
 +    result = ftp_state_stor_prequote(conn);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_retr(struct connectdata *conn,
 +                                         curl_off_t filesize)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data=conn->data;
 +  struct FTP *ftp = data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
 +    failf(data, "Maximum file size exceeded");
 +    return CURLE_FILESIZE_EXCEEDED;
 +  }
 +  ftp->downloadsize = filesize;
 +
 +  if(data->state.resume_from) {
 +    /* We always (attempt to) get the size of downloads, so it is done before
 +       this even when not doing resumes. */
 +    if(filesize == -1) {
 +      infof(data, "ftp server doesn't support SIZE\n");
 +      /* We couldn't get the size and therefore we can't know if there really
 +         is a part of the file left to get, although the server will just
 +         close the connection when we start the connection so it won't cause
 +         us any harm, just not make us exit as nicely. */
 +    }
 +    else {
 +      /* We got a file size report, so we check that there actually is a
 +         part of the file left to get, or else we go home.  */
 +      if(data->state.resume_from< 0) {
 +        /* We're supposed to download the last abs(from) bytes */
 +        if(filesize < -data->state.resume_from) {
 +          failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
 +                ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
 +                data->state.resume_from, filesize);
 +          return CURLE_BAD_DOWNLOAD_RESUME;
 +        }
 +        /* convert to size to download */
 +        ftp->downloadsize = -data->state.resume_from;
 +        /* download from where? */
 +        data->state.resume_from = filesize - ftp->downloadsize;
 +      }
 +      else {
 +        if(filesize < data->state.resume_from) {
 +          failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
 +                ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
 +                data->state.resume_from, filesize);
 +          return CURLE_BAD_DOWNLOAD_RESUME;
 +        }
 +        /* Now store the number of bytes we are expected to download */
 +        ftp->downloadsize = filesize-data->state.resume_from;
 +      }
 +    }
 +
 +    if(ftp->downloadsize == 0) {
 +      /* no data to transfer */
 +      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
 +      infof(data, "File already completely downloaded\n");
 +
 +      /* Set ->transfer so that we won't get any error in ftp_done()
 +       * because we didn't transfer the any file */
 +      ftp->transfer = FTPTRANSFER_NONE;
 +      state(conn, FTP_STOP);
 +      return CURLE_OK;
 +    }
 +
 +    /* Set resume file transfer offset */
 +    infof(data, "Instructs server to resume from offset %"
 +          CURL_FORMAT_CURL_OFF_T "\n", data->state.resume_from);
 +
 +    PPSENDF(&ftpc->pp, "REST %" CURL_FORMAT_CURL_OFF_T,
 +            data->state.resume_from);
 +
 +    state(conn, FTP_RETR_REST);
 +  }
 +  else {
 +    /* no resume */
 +    PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
 +    state(conn, FTP_RETR);
 +  }
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_size_resp(struct connectdata *conn,
 +                                    int ftpcode,
 +                                    ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data=conn->data;
 +  curl_off_t filesize;
 +  char *buf = data->state.buffer;
 +
 +  /* get the size from the ascii string: */
 +  filesize = (ftpcode == 213)?curlx_strtoofft(buf+4, NULL, 0):-1;
 +
 +  if(instate == FTP_SIZE) {
 +#ifdef CURL_FTP_HTTPSTYLE_HEAD
 +    if(-1 != filesize) {
 +      snprintf(buf, sizeof(data->state.buffer),
 +               "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
 +      result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
 +      if(result)
 +        return result;
 +    }
 +#endif
 +    Curl_pgrsSetDownloadSize(data, filesize);
 +    result = ftp_state_rest(conn);
 +  }
 +  else if(instate == FTP_RETR_SIZE) {
 +    Curl_pgrsSetDownloadSize(data, filesize);
 +    result = ftp_state_retr(conn, filesize);
 +  }
 +  else if(instate == FTP_STOR_SIZE) {
 +    data->state.resume_from = filesize;
 +    result = ftp_state_ul_setup(conn, TRUE);
 +  }
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_rest_resp(struct connectdata *conn,
 +                                    int ftpcode,
 +                                    ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  switch(instate) {
 +  case FTP_REST:
 +  default:
 +#ifdef CURL_FTP_HTTPSTYLE_HEAD
 +    if(ftpcode == 350) {
 +      char buffer[24]= { "Accept-ranges: bytes\r\n" };
 +      result = Curl_client_write(conn, CLIENTWRITE_BOTH, buffer, 0);
 +      if(result)
 +        return result;
 +    }
 +#endif
 +    result = ftp_state_prepare_transfer(conn);
 +    break;
 +
 +  case FTP_RETR_REST:
 +    if(ftpcode != 350) {
 +      failf(conn->data, "Couldn't use REST");
 +      result = CURLE_FTP_COULDNT_USE_REST;
 +    }
 +    else {
 +      PPSENDF(&ftpc->pp, "RETR %s", ftpc->file);
 +      state(conn, FTP_RETR);
 +    }
 +    break;
 +  }
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_state_stor_resp(struct connectdata *conn,
 +                                    int ftpcode, ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +
 +  if(ftpcode>=400) {
 +    failf(data, "Failed FTP upload: %0d", ftpcode);
 +    state(conn, FTP_STOP);
 +    /* oops, we never close the sockets! */
 +    return CURLE_UPLOAD_FAILED;
 +  }
 +
 +  conn->proto.ftpc.state_saved = instate;
 +
 +  /* PORT means we are now awaiting the server to connect to us. */
 +  if(data->set.ftp_use_port) {
 +    bool connected;
 +
 +    state(conn, FTP_STOP); /* no longer in STOR state */
 +
 +    result = AllowServerConnect(conn, &connected);
 +    if(result)
 +      return result;
 +
 +    if(!connected) {
 +      struct ftp_conn *ftpc = &conn->proto.ftpc;
 +      infof(data, "Data conn was not available immediately\n");
 +      ftpc->wait_data_conn = TRUE;
 +    }
 +
 +    return CURLE_OK;
 +  }
 +  else
 +    return InitiateTransfer(conn);
 +}
 +
 +/* for LIST and RETR responses */
 +static CURLcode ftp_state_get_resp(struct connectdata *conn,
 +                                    int ftpcode,
 +                                    ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  struct FTP *ftp = data->req.protop;
 +  char *buf = data->state.buffer;
 +
 +  if((ftpcode == 150) || (ftpcode == 125)) {
 +
 +    /*
 +      A;
 +      150 Opening BINARY mode data connection for /etc/passwd (2241
 +      bytes).  (ok, the file is being transferred)
 +
 +      B:
 +      150 Opening ASCII mode data connection for /bin/ls
 +
 +      C:
 +      150 ASCII data connection for /bin/ls (137.167.104.91,37445) (0 bytes).
 +
 +      D:
 +      150 Opening ASCII mode data connection for [file] (0.0.0.0,0) (545 bytes)
 +
 +      E:
 +      125 Data connection already open; Transfer starting. */
 +
 +    curl_off_t size=-1; /* default unknown size */
 +
 +
 +    /*
 +     * It appears that there are FTP-servers that return size 0 for files when
 +     * SIZE is used on the file while being in BINARY mode. To work around
 +     * that (stupid) behavior, we attempt to parse the RETR response even if
 +     * the SIZE returned size zero.
 +     *
 +     * Debugging help from Salvatore Sorrentino on February 26, 2003.
 +     */
 +
 +    if((instate != FTP_LIST) &&
 +       !data->set.prefer_ascii &&
 +       (ftp->downloadsize < 1)) {
 +      /*
 +       * It seems directory listings either don't show the size or very
 +       * often uses size 0 anyway. ASCII transfers may very well turn out
 +       * that the transferred amount of data is not the same as this line
 +       * tells, why using this number in those cases only confuses us.
 +       *
 +       * Example D above makes this parsing a little tricky */
 +      char *bytes;
 +      bytes=strstr(buf, " bytes");
 +      if(bytes--) {
 +        long in=(long)(bytes-buf);
 +        /* this is a hint there is size information in there! ;-) */
 +        while(--in) {
 +          /* scan for the left parenthesis and break there */
 +          if('(' == *bytes)
 +            break;
 +          /* skip only digits */
 +          if(!ISDIGIT(*bytes)) {
 +            bytes=NULL;
 +            break;
 +          }
 +          /* one more estep backwards */
 +          bytes--;
 +        }
 +        /* if we have nothing but digits: */
 +        if(bytes++) {
 +          /* get the number! */
 +          size = curlx_strtoofft(bytes, NULL, 0);
 +        }
 +      }
 +    }
 +    else if(ftp->downloadsize > -1)
 +      size = ftp->downloadsize;
 +
 +    if(size > data->req.maxdownload && data->req.maxdownload > 0)
 +      size = data->req.size = data->req.maxdownload;
 +    else if((instate != FTP_LIST) && (data->set.prefer_ascii))
 +      size = -1; /* kludge for servers that understate ASCII mode file size */
 +
 +    infof(data, "Maxdownload = %" CURL_FORMAT_CURL_OFF_T "\n",
 +          data->req.maxdownload);
 +
 +    if(instate != FTP_LIST)
 +      infof(data, "Getting file with size: %" CURL_FORMAT_CURL_OFF_T "\n",
 +            size);
 +
 +    /* FTP download: */
 +    conn->proto.ftpc.state_saved = instate;
 +    conn->proto.ftpc.retr_size_saved = size;
 +
 +    if(data->set.ftp_use_port) {
 +      bool connected;
 +
 +      result = AllowServerConnect(conn, &connected);
 +      if(result)
 +        return result;
 +
 +      if(!connected) {
 +        struct ftp_conn *ftpc = &conn->proto.ftpc;
 +        infof(data, "Data conn was not available immediately\n");
 +        state(conn, FTP_STOP);
 +        ftpc->wait_data_conn = TRUE;
 +      }
 +    }
 +    else
 +      return InitiateTransfer(conn);
 +  }
 +  else {
 +    if((instate == FTP_LIST) && (ftpcode == 450)) {
 +      /* simply no matching files in the dir listing */
 +      ftp->transfer = FTPTRANSFER_NONE; /* don't download anything */
 +      state(conn, FTP_STOP); /* this phase is over */
 +    }
 +    else {
 +      failf(data, "RETR response: %03d", ftpcode);
 +      return instate == FTP_RETR && ftpcode == 550?
 +        CURLE_REMOTE_FILE_NOT_FOUND:
 +        CURLE_FTP_COULDNT_RETR_FILE;
 +    }
 +  }
 +
 +  return result;
 +}
 +
 +/* after USER, PASS and ACCT */
 +static CURLcode ftp_state_loggedin(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +
 +  if(conn->ssl[FIRSTSOCKET].use) {
 +    /* PBSZ = PROTECTION BUFFER SIZE.
 +
 +    The 'draft-murray-auth-ftp-ssl' (draft 12, page 7) says:
 +
 +    Specifically, the PROT command MUST be preceded by a PBSZ
 +    command and a PBSZ command MUST be preceded by a successful
 +    security data exchange (the TLS negotiation in this case)
 +
 +    ... (and on page 8):
 +
 +    Thus the PBSZ command must still be issued, but must have a
 +    parameter of '0' to indicate that no buffering is taking place
 +    and the data connection should not be encapsulated.
 +    */
 +    PPSENDF(&conn->proto.ftpc.pp, "PBSZ %d", 0);
 +    state(conn, FTP_PBSZ);
 +  }
 +  else {
 +    result = ftp_state_pwd(conn);
 +  }
 +  return result;
 +}
 +
 +/* for USER and PASS responses */
 +static CURLcode ftp_state_user_resp(struct connectdata *conn,
 +                                    int ftpcode,
 +                                    ftpstate instate)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  struct FTP *ftp = data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  (void)instate; /* no use for this yet */
 +
 +  /* some need password anyway, and others just return 2xx ignored */
 +  if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
 +    /* 331 Password required for ...
 +       (the server requires to send the user's password too) */
 +    PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:"");
 +    state(conn, FTP_PASS);
 +  }
 +  else if(ftpcode/100 == 2) {
 +    /* 230 User ... logged in.
 +       (the user logged in with or without password) */
 +    result = ftp_state_loggedin(conn);
 +  }
 +  else if(ftpcode == 332) {
 +    if(data->set.str[STRING_FTP_ACCOUNT]) {
 +      PPSENDF(&ftpc->pp, "ACCT %s", data->set.str[STRING_FTP_ACCOUNT]);
 +      state(conn, FTP_ACCT);
 +    }
 +    else {
 +      failf(data, "ACCT requested but none available");
 +      result = CURLE_LOGIN_DENIED;
 +    }
 +  }
 +  else {
 +    /* All other response codes, like:
 +
 +    530 User ... access denied
 +    (the server denies to log the specified user) */
 +
 +    if(conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] &&
 +        !conn->data->state.ftp_trying_alternative) {
 +      /* Ok, USER failed.  Let's try the supplied command. */
 +      PPSENDF(&conn->proto.ftpc.pp, "%s",
 +              conn->data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]);
 +      conn->data->state.ftp_trying_alternative = TRUE;
 +      state(conn, FTP_USER);
 +      result = CURLE_OK;
 +    }
 +    else {
 +      failf(data, "Access denied: %03d", ftpcode);
 +      result = CURLE_LOGIN_DENIED;
 +    }
 +  }
 +  return result;
 +}
 +
 +/* for ACCT response */
 +static CURLcode ftp_state_acct_resp(struct connectdata *conn,
 +                                    int ftpcode)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct Curl_easy *data = conn->data;
 +  if(ftpcode != 230) {
 +    failf(data, "ACCT rejected by server: %03d", ftpcode);
 +    result = CURLE_FTP_WEIRD_PASS_REPLY; /* FIX */
 +  }
 +  else
 +    result = ftp_state_loggedin(conn);
 +
 +  return result;
 +}
 +
 +
 +static CURLcode ftp_statemach_act(struct connectdata *conn)
 +{
 +  CURLcode result;
 +  curl_socket_t sock = conn->sock[FIRSTSOCKET];
 +  struct Curl_easy *data=conn->data;
 +  int ftpcode;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +  static const char ftpauth[][4]  = { "SSL", "TLS" };
 +  size_t nread = 0;
 +
 +  if(pp->sendleft)
 +    return Curl_pp_flushsend(pp);
 +
 +  result = ftp_readresp(sock, pp, &ftpcode, &nread);
 +  if(result)
 +    return result;
 +
 +  if(ftpcode) {
 +    /* we have now received a full FTP server response */
 +    switch(ftpc->state) {
 +    case FTP_WAIT220:
 +      if(ftpcode == 230)
 +        /* 230 User logged in - already! */
 +        return ftp_state_user_resp(conn, ftpcode, ftpc->state);
 +      else if(ftpcode != 220) {
 +        failf(data, "Got a %03d ftp-server response when 220 was expected",
 +              ftpcode);
 +        return CURLE_WEIRD_SERVER_REPLY;
 +      }
 +
 +      /* We have received a 220 response fine, now we proceed. */
 +#ifdef HAVE_GSSAPI
 +      if(data->set.krb) {
 +        /* If not anonymous login, try a secure login. Note that this
 +           procedure is still BLOCKING. */
 +
 +        Curl_sec_request_prot(conn, "private");
 +        /* We set private first as default, in case the line below fails to
 +           set a valid level */
 +        Curl_sec_request_prot(conn, data->set.str[STRING_KRB_LEVEL]);
 +
 +        if(Curl_sec_login(conn))
 +          infof(data, "Logging in with password in cleartext!\n");
 +        else
 +          infof(data, "Authentication successful\n");
 +      }
 +#endif
 +
-       if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
++      if(data->set.use_ssl &&
++         (!conn->ssl[FIRSTSOCKET].use ||
++          (conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
++           !conn->proxy_ssl[FIRSTSOCKET].use))) {
 +        /* We don't have a SSL/TLS connection yet, but FTPS is
 +           requested. Try a FTPS connection now */
 +
 +        ftpc->count3=0;
 +        switch(data->set.ftpsslauth) {
 +        case CURLFTPAUTH_DEFAULT:
 +        case CURLFTPAUTH_SSL:
 +          ftpc->count2 = 1; /* add one to get next */
 +          ftpc->count1 = 0;
 +          break;
 +        case CURLFTPAUTH_TLS:
 +          ftpc->count2 = -1; /* subtract one to get next */
 +          ftpc->count1 = 1;
 +          break;
 +        default:
 +          failf(data, "unsupported parameter to CURLOPT_FTPSSLAUTH: %d",
 +                (int)data->set.ftpsslauth);
 +          return CURLE_UNKNOWN_OPTION; /* we don't know what to do */
 +        }
 +        PPSENDF(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
 +        state(conn, FTP_AUTH);
 +      }
 +      else {
 +        result = ftp_state_user(conn);
 +        if(result)
 +          return result;
 +      }
 +
 +      break;
 +
 +    case FTP_AUTH:
 +      /* we have gotten the response to a previous AUTH command */
 +
 +      /* RFC2228 (page 5) says:
 +       *
 +       * If the server is willing to accept the named security mechanism,
 +       * and does not require any security data, it must respond with
 +       * reply code 234/334.
 +       */
 +
 +      if((ftpcode == 234) || (ftpcode == 334)) {
 +        /* Curl_ssl_connect is BLOCKING */
 +        result = Curl_ssl_connect(conn, FIRSTSOCKET);
 +        if(!result) {
-           conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */
++          conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
 +          result = ftp_state_user(conn);
 +        }
 +      }
 +      else if(ftpc->count3 < 1) {
 +        ftpc->count3++;
 +        ftpc->count1 += ftpc->count2; /* get next attempt */
 +        result = Curl_pp_sendf(&ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]);
 +        /* remain in this same state */
 +      }
 +      else {
 +        if(data->set.use_ssl > CURLUSESSL_TRY)
 +          /* we failed and CURLUSESSL_CONTROL or CURLUSESSL_ALL is set */
 +          result = CURLE_USE_SSL_FAILED;
 +        else
 +          /* ignore the failure and continue */
 +          result = ftp_state_user(conn);
 +      }
 +
 +      if(result)
 +        return result;
 +      break;
 +
 +    case FTP_USER:
 +    case FTP_PASS:
 +      result = ftp_state_user_resp(conn, ftpcode, ftpc->state);
 +      break;
 +
 +    case FTP_ACCT:
 +      result = ftp_state_acct_resp(conn, ftpcode);
 +      break;
 +
 +    case FTP_PBSZ:
 +      PPSENDF(&ftpc->pp, "PROT %c",
 +              data->set.use_ssl == CURLUSESSL_CONTROL ? 'C' : 'P');
 +      state(conn, FTP_PROT);
 +
 +      break;
 +
 +    case FTP_PROT:
 +      if(ftpcode/100 == 2)
 +        /* We have enabled SSL for the data connection! */
-         conn->ssl[SECONDARYSOCKET].use =
++        conn->bits.ftp_use_data_ssl =
 +          (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
 +      /* FTP servers typically responds with 500 if they decide to reject
 +         our 'P' request */
 +      else if(data->set.use_ssl > CURLUSESSL_CONTROL)
 +        /* we failed and bails out */
 +        return CURLE_USE_SSL_FAILED;
 +
 +      if(data->set.ftp_ccc) {
 +        /* CCC - Clear Command Channel
 +         */
 +        PPSENDF(&ftpc->pp, "%s", "CCC");
 +        state(conn, FTP_CCC);
 +      }
 +      else {
 +        result = ftp_state_pwd(conn);
 +        if(result)
 +          return result;
 +      }
 +      break;
 +
 +    case FTP_CCC:
 +      if(ftpcode < 500) {
 +        /* First shut down the SSL layer (note: this call will block) */
 +        result = Curl_ssl_shutdown(conn, FIRSTSOCKET);
 +
 +        if(result) {
 +          failf(conn->data, "Failed to clear the command channel (CCC)");
 +          return result;
 +        }
 +      }
 +
 +      /* Then continue as normal */
 +      result = ftp_state_pwd(conn);
 +      if(result)
 +        return result;
 +      break;
 +
 +    case FTP_PWD:
 +      if(ftpcode == 257) {
 +        char *ptr=&data->state.buffer[4];  /* start on the first letter */
 +        char *dir;
 +        char *store;
 +
 +        dir = malloc(nread + 1);
 +        if(!dir)
 +          return CURLE_OUT_OF_MEMORY;
 +
 +        /* Reply format is like
 +           257<space>[rubbish]"<directory-name>"<space><commentary> and the
 +           RFC959 says
 +
 +           The directory name can contain any character; embedded
 +           double-quotes should be escaped by double-quotes (the
 +           "quote-doubling" convention).
 +        */
 +
 +        /* scan for the first double-quote for non-standard responses */
 +        while(ptr < &data->state.buffer[sizeof(data->state.buffer)]
 +              && *ptr != '\n' && *ptr != '\0' && *ptr != '"')
 +          ptr++;
 +
 +        if('\"' == *ptr) {
 +          /* it started good */
 +          ptr++;
 +          for(store = dir; *ptr;) {
 +            if('\"' == *ptr) {
 +              if('\"' == ptr[1]) {
 +                /* "quote-doubling" */
 +                *store = ptr[1];
 +                ptr++;
 +              }
 +              else {
 +                /* end of path */
 +                *store = '\0'; /* zero terminate */
 +                break; /* get out of this loop */
 +              }
 +            }
 +            else
 +              *store = *ptr;
 +            store++;
 +            ptr++;
 +          }
 +
 +          /* If the path name does not look like an absolute path (i.e.: it
 +             does not start with a '/'), we probably need some server-dependent
 +             adjustments. For example, this is the case when connecting to
 +             an OS400 FTP server: this server supports two name syntaxes,
 +             the default one being incompatible with standard pathes. In
 +             addition, this server switches automatically to the regular path
 +             syntax when one is encountered in a command: this results in
 +             having an entrypath in the wrong syntax when later used in CWD.
 +               The method used here is to check the server OS: we do it only
 +             if the path name looks strange to minimize overhead on other
 +             systems. */
 +
 +          if(!ftpc->server_os && dir[0] != '/') {
 +
 +            result = Curl_pp_sendf(&ftpc->pp, "%s", "SYST");
 +            if(result) {
 +              free(dir);
 +              return result;
 +            }
 +            Curl_safefree(ftpc->entrypath);
 +            ftpc->entrypath = dir; /* remember this */
 +            infof(data, "Entry path is '%s'\n", ftpc->entrypath);
 +            /* also save it where getinfo can access it: */
 +            data->state.most_recent_ftp_entrypath = ftpc->entrypath;
 +            state(conn, FTP_SYST);
 +            break;
 +          }
 +
 +          Curl_safefree(ftpc->entrypath);
 +          ftpc->entrypath = dir; /* remember this */
 +          infof(data, "Entry path is '%s'\n", ftpc->entrypath);
 +          /* also save it where getinfo can access it: */
 +          data->state.most_recent_ftp_entrypath = ftpc->entrypath;
 +        }
 +        else {
 +          /* couldn't get the path */
 +          free(dir);
 +          infof(data, "Failed to figure out path\n");
 +        }
 +      }
 +      state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
 +      DEBUGF(infof(data, "protocol connect phase DONE\n"));
 +      break;
 +
 +    case FTP_SYST:
 +      if(ftpcode == 215) {
 +        char *ptr=&data->state.buffer[4];  /* start on the first letter */
 +        char *os;
 +        char *store;
 +
 +        os = malloc(nread + 1);
 +        if(!os)
 +          return CURLE_OUT_OF_MEMORY;
 +
 +        /* Reply format is like
 +           215<space><OS-name><space><commentary>
 +        */
 +        while(*ptr == ' ')
 +          ptr++;
 +        for(store = os; *ptr && *ptr != ' ';)
 +          *store++ = *ptr++;
 +        *store = '\0'; /* zero terminate */
 +
 +        /* Check for special servers here. */
 +
 +        if(strcasecompare(os, "OS/400")) {
 +          /* Force OS400 name format 1. */
 +          result = Curl_pp_sendf(&ftpc->pp, "%s", "SITE NAMEFMT 1");
 +          if(result) {
 +            free(os);
 +            return result;
 +          }
 +          /* remember target server OS */
 +          Curl_safefree(ftpc->server_os);
 +          ftpc->server_os = os;
 +          state(conn, FTP_NAMEFMT);
 +          break;
 +        }
 +        else {
 +          /* Nothing special for the target server. */
 +          /* remember target server OS */
 +          Curl_safefree(ftpc->server_os);
 +          ftpc->server_os = os;
 +        }
 +      }
 +      else {
 +        /* Cannot identify server OS. Continue anyway and cross fingers. */
 +      }
 +
 +      state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
 +      DEBUGF(infof(data, "protocol connect phase DONE\n"));
 +      break;
 +
 +    case FTP_NAMEFMT:
 +      if(ftpcode == 250) {
 +        /* Name format change successful: reload initial path. */
 +        ftp_state_pwd(conn);
 +        break;
 +      }
 +
 +      state(conn, FTP_STOP); /* we are done with the CONNECT phase! */
 +      DEBUGF(infof(data, "protocol connect phase DONE\n"));
 +      break;
 +
 +    case FTP_QUOTE:
 +    case FTP_POSTQUOTE:
 +    case FTP_RETR_PREQUOTE:
 +    case FTP_STOR_PREQUOTE:
 +      if((ftpcode >= 400) && !ftpc->count2) {
 +        /* failure response code, and not allowed to fail */
 +        failf(conn->data, "QUOT command failed with %03d", ftpcode);
 +        return CURLE_QUOTE_ERROR;
 +      }
 +      result = ftp_state_quote(conn, FALSE, ftpc->state);
 +      if(result)
 +        return result;
 +
 +      break;
 +
 +    case FTP_CWD:
 +      if(ftpcode/100 != 2) {
 +        /* failure to CWD there */
 +        if(conn->data->set.ftp_create_missing_dirs &&
 +           ftpc->count1 && !ftpc->count2) {
 +          /* try making it */
 +          ftpc->count2++; /* counter to prevent CWD-MKD loops */
 +          PPSENDF(&ftpc->pp, "MKD %s", ftpc->dirs[ftpc->count1 - 1]);
 +          state(conn, FTP_MKD);
 +        }
 +        else {
 +          /* return failure */
 +          failf(data, "Server denied you to change to the given directory");
 +          ftpc->cwdfail = TRUE; /* don't remember this path as we failed
 +                                   to enter it */
 +          return CURLE_REMOTE_ACCESS_DENIED;
 +        }
 +      }
 +      else {
 +        /* success */
 +        ftpc->count2=0;
 +        if(++ftpc->count1 <= ftpc->dirdepth) {
 +          /* send next CWD */
 +          PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]);
 +        }
 +        else {
 +          result = ftp_state_mdtm(conn);
 +          if(result)
 +            return result;
 +        }
 +      }
 +      break;
 +
 +    case FTP_MKD:
 +      if((ftpcode/100 != 2) && !ftpc->count3--) {
 +        /* failure to MKD the dir */
 +        failf(data, "Failed to MKD dir: %03d", ftpcode);
 +        return CURLE_REMOTE_ACCESS_DENIED;
 +      }
 +      state(conn, FTP_CWD);
 +      /* send CWD */
 +      PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->count1 - 1]);
 +      break;
 +
 +    case FTP_MDTM:
 +      result = ftp_state_mdtm_resp(conn, ftpcode);
 +      break;
 +
 +    case FTP_TYPE:
 +    case FTP_LIST_TYPE:
 +    case FTP_RETR_TYPE:
 +    case FTP_STOR_TYPE:
 +      result = ftp_state_type_resp(conn, ftpcode, ftpc->state);
 +      break;
 +
 +    case FTP_SIZE:
 +    case FTP_RETR_SIZE:
 +    case FTP_STOR_SIZE:
 +      result = ftp_state_size_resp(conn, ftpcode, ftpc->state);
 +      break;
 +
 +    case FTP_REST:
 +    case FTP_RETR_REST:
 +      result = ftp_state_rest_resp(conn, ftpcode, ftpc->state);
 +      break;
 +
 +    case FTP_PRET:
 +      if(ftpcode != 200) {
 +        /* there only is this one standard OK return code. */
 +        failf(data, "PRET command not accepted: %03d", ftpcode);
 +        return CURLE_FTP_PRET_FAILED;
 +      }
 +      result = ftp_state_use_pasv(conn);
 +      break;
 +
 +    case FTP_PASV:
 +      result = ftp_state_pasv_resp(conn, ftpcode);
 +      break;
 +
 +    case FTP_PORT:
 +      result = ftp_state_port_resp(conn, ftpcode);
 +      break;
 +
 +    case FTP_LIST:
 +    case FTP_RETR:
 +      result = ftp_state_get_resp(conn, ftpcode, ftpc->state);
 +      break;
 +
 +    case FTP_STOR:
 +      result = ftp_state_stor_resp(conn, ftpcode, ftpc->state);
 +      break;
 +
 +    case FTP_QUIT:
 +      /* fallthrough, just stop! */
 +    default:
 +      /* internal error */
 +      state(conn, FTP_STOP);
 +      break;
 +    }
 +  } /* if(ftpcode) */
 +
 +  return result;
 +}
 +
 +
 +/* called repeatedly until done from multi.c */
 +static CURLcode ftp_multi_statemach(struct connectdata *conn,
 +                                    bool *done)
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE);
 +
 +  /* Check for the state outside of the Curl_socket_check() return code checks
 +     since at times we are in fact already in this state when this function
 +     gets called. */
 +  *done = (ftpc->state == FTP_STOP) ? TRUE : FALSE;
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_block_statemach(struct connectdata *conn)
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +  CURLcode result = CURLE_OK;
 +
 +  while(ftpc->state != FTP_STOP) {
 +    result = Curl_pp_statemach(pp, TRUE);
 +    if(result)
 +      break;
 +  }
 +
 +  return result;
 +}
 +
 +/*
 + * ftp_connect() should do everything that is to be considered a part of
 + * the connection phase.
 + *
 + * The variable 'done' points to will be TRUE if the protocol-layer connect
 + * phase is done when this function returns, or FALSE if not.
 + *
 + */
 +static CURLcode ftp_connect(struct connectdata *conn,
 +                                 bool *done) /* see description above */
 +{
 +  CURLcode result;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +
 +  *done = FALSE; /* default to not done yet */
 +
 +  /* We always support persistent connections on ftp */
 +  connkeep(conn, "FTP default");
 +
 +  pp->response_time = RESP_TIMEOUT; /* set default response time-out */
 +  pp->statemach_act = ftp_statemach_act;
 +  pp->endofresp = ftp_endofresp;
 +  pp->conn = conn;
 +
 +  if(conn->handler->flags & PROTOPT_SSL) {
 +    /* BLOCKING */
 +    result = Curl_ssl_connect(conn, FIRSTSOCKET);
 +    if(result)
 +      return result;
 +  }
 +
 +  Curl_pp_init(pp); /* init the generic pingpong data */
 +
 +  /* When we connect, we start in the state where we await the 220
 +     response */
 +  state(conn, FTP_WAIT220);
 +
 +  result = ftp_multi_statemach(conn, done);
 +
 +  return result;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_done()
 + *
 + * The DONE function. This does what needs to be done after a single DO has
 + * performed.
 + *
 + * Input argument is already checked for validity.
 + */
 +static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
 +                         bool premature)
 +{
 +  struct Curl_easy *data = conn->data;
 +  struct FTP *ftp = data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +  ssize_t nread;
 +  int ftpcode;
 +  CURLcode result = CURLE_OK;
-   char *path;
++  char *path = NULL;
 +  const char *path_to_use = data->state.path;
 +
 +  if(!ftp)
 +    return CURLE_OK;
 +
 +  switch(status) {
 +  case CURLE_BAD_DOWNLOAD_RESUME:
 +  case CURLE_FTP_WEIRD_PASV_REPLY:
 +  case CURLE_FTP_PORT_FAILED:
 +  case CURLE_FTP_ACCEPT_FAILED:
 +  case CURLE_FTP_ACCEPT_TIMEOUT:
 +  case CURLE_FTP_COULDNT_SET_TYPE:
 +  case CURLE_FTP_COULDNT_RETR_FILE:
 +  case CURLE_PARTIAL_FILE:
 +  case CURLE_UPLOAD_FAILED:
 +  case CURLE_REMOTE_ACCESS_DENIED:
 +  case CURLE_FILESIZE_EXCEEDED:
 +  case CURLE_REMOTE_FILE_NOT_FOUND:
 +  case CURLE_WRITE_ERROR:
 +    /* the connection stays alive fine even though this happened */
 +    /* fall-through */
 +  case CURLE_OK: /* doesn't affect the control connection's status */
 +    if(!premature)
 +      break;
 +
 +    /* until we cope better with prematurely ended requests, let them
 +     * fallback as if in complete failure */
 +  default:       /* by default, an error means the control connection is
 +                    wedged and should not be used anymore */
 +    ftpc->ctl_valid = FALSE;
 +    ftpc->cwdfail = TRUE; /* set this TRUE to prevent us to remember the
 +                             current path, as this connection is going */
 +    connclose(conn, "FTP ended with bad error code");
 +    result = status;      /* use the already set error code */
 +    break;
 +  }
 +
 +  /* now store a copy of the directory we are in */
 +  free(ftpc->prevpath);
 +
 +  if(data->set.wildcardmatch) {
 +    if(data->set.chunk_end && ftpc->file) {
 +      data->set.chunk_end(data->wildcard.customptr);
 +    }
 +    ftpc->known_filesize = -1;
 +  }
 +
 +  if(!result)
 +    /* get the "raw" path */
 +    result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE);
 +  if(result) {
 +    /* We can limp along anyway (and should try to since we may already be in
 +     * the error path) */
 +    ftpc->ctl_valid = FALSE; /* mark control connection as bad */
 +    connclose(conn, "FTP: out of memory!"); /* mark for connection closure */
 +    ftpc->prevpath = NULL; /* no path remembering */
 +  }
 +  else {
 +    size_t flen = ftpc->file?strlen(ftpc->file):0; /* file is "raw" already */
 +    size_t dlen = strlen(path)-flen;
 +    if(!ftpc->cwdfail) {
 +      if(dlen && (data->set.ftp_filemethod != FTPFILE_NOCWD)) {
 +        ftpc->prevpath = path;
 +        if(flen)
 +          /* if 'path' is not the whole string */
 +          ftpc->prevpath[dlen]=0; /* terminate */
 +      }
 +      else {
 +        /* we never changed dir */
 +        ftpc->prevpath=strdup("");
 +        free(path);
 +      }
 +      if(ftpc->prevpath)
 +        infof(data, "Remembering we are in dir \"%s\"\n", ftpc->prevpath);
 +    }
 +    else {
 +      ftpc->prevpath = NULL; /* no path */
 +      free(path);
 +    }
 +  }
 +  /* free the dir tree and file parts */
 +  freedirs(ftpc);
 +
 +  /* shut down the socket to inform the server we're done */
 +
 +#ifdef _WIN32_WCE
 +  shutdown(conn->sock[SECONDARYSOCKET], 2);  /* SD_BOTH */
 +#endif
 +
 +  if(conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) {
 +    if(!result && ftpc->dont_check && data->req.maxdownload > 0) {
 +      /* partial download completed */
 +      result = Curl_pp_sendf(pp, "%s", "ABOR");
 +      if(result) {
 +        failf(data, "Failure sending ABOR command: %s",
 +              curl_easy_strerror(result));
 +        ftpc->ctl_valid = FALSE; /* mark control connection as bad */
 +        connclose(conn, "ABOR command failed"); /* connection closure */
 +      }
 +    }
 +
 +    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(conn, SECONDARYSOCKET);
 +
 +      /* Note that we keep "use" set to TRUE since that (next) connection is
 +         still requested to use SSL */
 +    }
 +    close_secondarysocket(conn);
 +  }
 +
 +  if(!result && (ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid &&
 +     pp->pending_resp && !premature) {
 +    /*
 +     * Let's see what the server says about the transfer we just performed,
 +     * but lower the timeout as sometimes this connection has died while the
 +     * data has been transferred. This happens when doing through NATs etc that
 +     * abandon old silent connections.
 +     */
 +    long old_time = pp->response_time;
 +
 +    pp->response_time = 60*1000; /* give it only a minute for now */
 +    pp->response = Curl_tvnow(); /* timeout relative now */
 +
 +    result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
 +
 +    pp->response_time = old_time; /* set this back to previous value */
 +
 +    if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) {
 +      failf(data, "control connection looks dead");
 +      ftpc->ctl_valid = FALSE; /* mark control connection as bad */
 +      connclose(conn, "Timeout or similar in FTP DONE operation"); /* close */
 +    }
 +
 +    if(result)
 +      return result;
 +
 +    if(ftpc->dont_check && data->req.maxdownload > 0) {
 +      /* we have just sent ABOR and there is no reliable way to check if it was
 +       * successful or not; we have to close the connection now */
 +      infof(data, "partial download completed, closing connection\n");
 +      connclose(conn, "Partial download with no ability to check");
 +      return result;
 +    }
 +
 +    if(!ftpc->dont_check) {
 +      /* 226 Transfer complete, 250 Requested file action okay, completed. */
 +      if((ftpcode != 226) && (ftpcode != 250)) {
 +        failf(data, "server did not report OK, got %d", ftpcode);
 +        result = CURLE_PARTIAL_FILE;
 +      }
 +    }
 +  }
 +
 +  if(result || premature)
 +    /* the response code from the transfer showed an error already so no
 +       use checking further */
 +    ;
 +  else if(data->set.upload) {
 +    if((-1 != data->state.infilesize) &&
 +       (data->state.infilesize != *ftp->bytecountp) &&
 +       !data->set.crlf &&
 +       (ftp->transfer == FTPTRANSFER_BODY)) {
 +      failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
 +            " out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
 +            *ftp->bytecountp, data->state.infilesize);
 +      result = CURLE_PARTIAL_FILE;
 +    }
 +  }
 +  else {
 +    if((-1 != data->req.size) &&
 +       (data->req.size != *ftp->bytecountp) &&
 +#ifdef CURL_DO_LINEEND_CONV
 +       /* Most FTP servers don't adjust their file SIZE response for CRLFs, so
 +        * we'll check to see if the discrepancy can be explained by the number
 +        * of CRLFs we've changed to LFs.
 +        */
 +       ((data->req.size + data->state.crlf_conversions) !=
 +        *ftp->bytecountp) &&
 +#endif /* CURL_DO_LINEEND_CONV */
 +       (data->req.maxdownload != *ftp->bytecountp)) {
 +      failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T
 +            " bytes", *ftp->bytecountp);
 +      result = CURLE_PARTIAL_FILE;
 +    }
 +    else if(!ftpc->dont_check &&
 +            !*ftp->bytecountp &&
 +            (data->req.size>0)) {
 +      failf(data, "No data was received!");
 +      result = CURLE_FTP_COULDNT_RETR_FILE;
 +    }
 +  }
 +
 +  /* clear these for next connection */
 +  ftp->transfer = FTPTRANSFER_BODY;
 +  ftpc->dont_check = FALSE;
 +
 +  /* Send any post-transfer QUOTE strings? */
 +  if(!status && !result && !premature && data->set.postquote)
 +    result = ftp_sendquote(conn, data->set.postquote);
 +
 +  return result;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_sendquote()
 + *
 + * Where a 'quote' means a list of custom commands to send to the server.
 + * The quote list is passed as an argument.
 + *
 + * BLOCKING
 + */
 +
 +static
 +CURLcode ftp_sendquote(struct connectdata *conn, struct curl_slist *quote)
 +{
 +  struct curl_slist *item;
 +  ssize_t nread;
 +  int ftpcode;
 +  CURLcode result;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +
 +  item = quote;
 +  while(item) {
 +    if(item->data) {
 +      char *cmd = item->data;
 +      bool acceptfail = FALSE;
 +
 +      /* if a command starts with an asterisk, which a legal FTP command never
 +         can, the command will be allowed to fail without it causing any
 +         aborts or cancels etc. It will cause libcurl to act as if the command
 +         is successful, whatever the server reponds. */
 +
 +      if(cmd[0] == '*') {
 +        cmd++;
 +        acceptfail = TRUE;
 +      }
 +
 +      PPSENDF(&conn->proto.ftpc.pp, "%s", cmd);
 +
 +      pp->response = Curl_tvnow(); /* timeout relative now */
 +
 +      result = Curl_GetFTPResponse(&nread, conn, &ftpcode);
 +      if(result)
 +        return result;
 +
 +      if(!acceptfail && (ftpcode >= 400)) {
 +        failf(conn->data, "QUOT string not accepted: %s", cmd);
 +        return CURLE_QUOTE_ERROR;
 +      }
 +    }
 +
 +    item = item->next;
 +  }
 +
 +  return CURLE_OK;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_need_type()
 + *
 + * Returns TRUE if we in the current situation should send TYPE
 + */
 +static int ftp_need_type(struct connectdata *conn,
 +                         bool ascii_wanted)
 +{
 +  return conn->proto.ftpc.transfertype != (ascii_wanted?'A':'I');
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_nb_type()
 + *
 + * Set TYPE. We only deal with ASCII or BINARY so this function
 + * sets one of them.
 + * If the transfer type is not sent, simulate on OK response in newstate
 + */
 +static CURLcode ftp_nb_type(struct connectdata *conn,
 +                            bool ascii, ftpstate newstate)
 +{
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  CURLcode result;
 +  char want = (char)(ascii?'A':'I');
 +
 +  if(ftpc->transfertype == want) {
 +    state(conn, newstate);
 +    return ftp_state_type_resp(conn, 200, newstate);
 +  }
 +
 +  PPSENDF(&ftpc->pp, "TYPE %c", want);
 +  state(conn, newstate);
 +
 +  /* keep track of our current transfer type */
 +  ftpc->transfertype = want;
 +  return CURLE_OK;
 +}
 +
 +/***************************************************************************
 + *
 + * ftp_pasv_verbose()
 + *
 + * This function only outputs some informationals about this second connection
 + * when we've issued a PASV command before and thus we have connected to a
 + * possibly new IP address.
 + *
 + */
 +#ifndef CURL_DISABLE_VERBOSE_STRINGS
 +static void
 +ftp_pasv_verbose(struct connectdata *conn,
 +                 Curl_addrinfo *ai,
 +                 char *newhost, /* ascii version */
 +                 int port)
 +{
 +  char buf[256];
 +  Curl_printable_address(ai, buf, sizeof(buf));
 +  infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port);
 +}
 +#endif
 +
 +/*
 +  Check if this is a range download, and if so, set the internal variables
 +  properly.
 + */
 +
 +static CURLcode ftp_range(struct connectdata *conn)
 +{
 +  curl_off_t from, to;
 +  char *ptr;
 +  char *ptr2;
 +  struct Curl_easy *data = conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if(data->state.use_range && data->state.range) {
 +    from=curlx_strtoofft(data->state.range, &ptr, 0);
 +    while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
 +      ptr++;
 +    to=curlx_strtoofft(ptr, &ptr2, 0);
 +    if(ptr == ptr2) {
 +      /* we didn't get any digit */
 +      to=-1;
 +    }
 +    if((-1 == to) && (from>=0)) {
 +      /* X - */
 +      data->state.resume_from = from;
 +      DEBUGF(infof(conn->data, "FTP RANGE %" CURL_FORMAT_CURL_OFF_T
 +                   " to end of file\n", from));
 +    }
 +    else if(from < 0) {
 +      /* -Y */
 +      data->req.maxdownload = -from;
 +      data->state.resume_from = from;
 +      DEBUGF(infof(conn->data, "FTP RANGE the last %" CURL_FORMAT_CURL_OFF_T
 +                   " bytes\n", -from));
 +    }
 +    else {
 +      /* X-Y */
 +      data->req.maxdownload = (to-from)+1; /* include last byte */
 +      data->state.resume_from = from;
 +      DEBUGF(infof(conn->data, "FTP RANGE from %" CURL_FORMAT_CURL_OFF_T
 +                   " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
 +                   from, data->req.maxdownload));
 +    }
 +    DEBUGF(infof(conn->data, "range-download from %" CURL_FORMAT_CURL_OFF_T
 +                 " to %" CURL_FORMAT_CURL_OFF_T ", totally %"
 +                 CURL_FORMAT_CURL_OFF_T " bytes\n",
 +                 from, to, data->req.maxdownload));
 +    ftpc->dont_check = TRUE; /* dont check for successful transfer */
 +  }
 +  else
 +    data->req.maxdownload = -1;
 +  return CURLE_OK;
 +}
 +
 +
 +/*
 + * ftp_do_more()
 + *
 + * This function shall be called when the second FTP (data) connection is
 + * connected.
 + *
 + * 'complete' can return 0 for incomplete, 1 for done and -1 for go back
 + * (which basically is only for when PASV is being sent to retry a failed
 + * EPSV).
 + */
 +
 +static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
 +{
 +  struct Curl_easy *data=conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  CURLcode result = CURLE_OK;
 +  bool connected = FALSE;
 +  bool complete = FALSE;
 +
 +  /* the ftp struct is inited in ftp_connect() */
 +  struct FTP *ftp = data->req.protop;
 +
 +  /* if the second connection isn't done yet, wait for it */
 +  if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
 +    if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) {
 +      /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
 +         aren't used so we blank their arguments. TODO: make this nicer */
 +      result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0, FALSE);
 +
 +      return result;
 +    }
 +
 +    result = Curl_is_connected(conn, SECONDARYSOCKET, &connected);
 +
 +    /* Ready to do more? */
 +    if(connected) {
 +      DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
-       if(conn->bits.proxy) {
-         infof(data, "Connection to proxy confirmed\n");
-         result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected);
-       }
 +    }
 +    else {
 +      if(result && (ftpc->count1 == 0)) {
 +        *completep = -1; /* go back to DOING please */
 +        /* this is a EPSV connect failing, try PASV instead */
 +        return ftp_epsv_disable(conn);
 +      }
 +      return result;
 +    }
 +  }
 +
++  result = Curl_proxy_connect(conn, SECONDARYSOCKET);
++  if(result)
++    return result;
++
++  if(CONNECT_SECONDARYSOCKET_PROXY_SSL())
++    return result;
++
++  if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
++     conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE)
++    return result;
++
++
 +  if(ftpc->state) {
 +    /* already in a state so skip the initial commands.
 +       They are only done to kickstart the do_more state */
 +    result = ftp_multi_statemach(conn, &complete);
 +
 +    *completep = (int)complete;
 +
 +    /* if we got an error or if we don't wait for a data connection return
 +       immediately */
 +    if(result || (ftpc->wait_data_conn != TRUE))
 +      return result;
 +
 +    if(ftpc->wait_data_conn)
 +      /* if we reach the end of the FTP state machine here, *complete will be
 +         TRUE but so is ftpc->wait_data_conn, which says we need to wait for
 +         the data connection and therefore we're not actually complete */
 +      *completep = 0;
 +  }
 +
 +  if(ftp->transfer <= FTPTRANSFER_INFO) {
 +    /* a transfer is about to take place, or if not a file name was given
 +       so we'll do a SIZE on it later and then we need the right TYPE first */
 +
 +    if(ftpc->wait_data_conn == TRUE) {
 +      bool serv_conned;
 +
 +      result = ReceivedServerConnect(conn, &serv_conned);
 +      if(result)
 +        return result; /* Failed to accept data connection */
 +
 +      if(serv_conned) {
 +        /* It looks data connection is established */
 +        result = AcceptServerConnect(conn);
 +        ftpc->wait_data_conn = FALSE;
 +        if(!result)
 +          result = InitiateTransfer(conn);
 +
 +        if(result)
 +          return result;
 +
 +        *completep = 1; /* this state is now complete when the server has
 +                           connected back to us */
 +      }
 +    }
 +    else if(data->set.upload) {
 +      result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_STOR_TYPE);
 +      if(result)
 +        return result;
 +
 +      result = ftp_multi_statemach(conn, &complete);
 +      if(ftpc->wait_data_conn)
 +        /* if we reach the end of the FTP state machine here, *complete will be
 +           TRUE but so is ftpc->wait_data_conn, which says we need to wait for
 +           the data connection and therefore we're not actually complete */
 +        *completep = 0;
 +      else
 +        *completep = (int)complete;
 +    }
 +    else {
 +      /* download */
 +      ftp->downloadsize = -1; /* unknown as of yet */
 +
 +      result = ftp_range(conn);
 +      if(result)
 +        ;
 +      else if(data->set.ftp_list_only || !ftpc->file) {
 +        /* The specified path ends with a slash, and therefore we think this
 +           is a directory that is requested, use LIST. But before that we
 +           need to set ASCII transfer mode. */
 +
 +        /* But only if a body transfer was requested. */
 +        if(ftp->transfer == FTPTRANSFER_BODY) {
 +          result = ftp_nb_type(conn, TRUE, FTP_LIST_TYPE);
 +          if(result)
 +            return result;
 +        }
 +        /* otherwise just fall through */
 +      }
 +      else {
 +        result = ftp_nb_type(conn, data->set.prefer_ascii, FTP_RETR_TYPE);
 +        if(result)
 +          return result;
 +      }
 +
 +      result = ftp_multi_statemach(conn, &complete);
 +      *completep = (int)complete;
 +    }
 +    return result;
 +  }
 +
 +  if(!result && (ftp->transfer != FTPTRANSFER_BODY))
 +    /* no data to transfer. FIX: it feels like a kludge to have this here
 +       too! */
 +    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
 +
 +  if(!ftpc->wait_data_conn) {
 +    /* no waiting for the data connection so this is now complete */
 +    *completep = 1;
 +    DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result));
 +  }
 +
 +  return result;
 +}
 +
 +
 +
 +/***********************************************************************
 + *
 + * ftp_perform()
 + *
 + * This is the actual DO function for FTP. Get a file/directory according to
 + * the options previously setup.
 + */
 +
 +static
 +CURLcode ftp_perform(struct connectdata *conn,
 +                     bool *connected,  /* connect status after PASV / PORT */
 +                     bool *dophase_done)
 +{
 +  /* this is FTP and no proxy */
 +  CURLcode result=CURLE_OK;
 +
 +  DEBUGF(infof(conn->data, "DO phase starts\n"));
 +
 +  if(conn->data->set.opt_no_body) {
 +    /* requested no body means no transfer... */
 +    struct FTP *ftp = conn->data->req.protop;
 +    ftp->transfer = FTPTRANSFER_INFO;
 +  }
 +
 +  *dophase_done = FALSE; /* not done yet */
 +
 +  /* start the first command in the DO phase */
 +  result = ftp_state_quote(conn, TRUE, FTP_QUOTE);
 +  if(result)
 +    return result;
 +
 +  /* run the state-machine */
 +  result = ftp_multi_statemach(conn, dophase_done);
 +
 +  *connected = conn->bits.tcpconnect[SECONDARYSOCKET];
 +
 +  infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected);
 +
 +  if(*dophase_done) {
 +    DEBUGF(infof(conn->data, "DO phase is complete1\n"));
 +  }
 +
 +  return result;
 +}
 +
 +static void wc_data_dtor(void *ptr)
 +{
 +  struct ftp_wc_tmpdata *tmp = ptr;
 +  if(tmp)
 +    Curl_ftp_parselist_data_free(&tmp->parser);
 +  free(tmp);
 +}
 +
 +static CURLcode init_wc_data(struct connectdata *conn)
 +{
 +  char *last_slash;
 +  char *path = conn->data->state.path;
 +  struct WildcardData *wildcard = &(conn->data->wildcard);
 +  CURLcode result = CURLE_OK;
 +  struct ftp_wc_tmpdata *ftp_tmp;
 +
 +  last_slash = strrchr(conn->data->state.path, '/');
 +  if(last_slash) {
 +    last_slash++;
 +    if(last_slash[0] == '\0') {
 +      wildcard->state = CURLWC_CLEAN;
 +      result = ftp_parse_url_path(conn);
 +      return result;
 +    }
 +    else {
 +      wildcard->pattern = strdup(last_slash);
 +      if(!wildcard->pattern)
 +        return CURLE_OUT_OF_MEMORY;
 +      last_slash[0] = '\0'; /* cut file from path */
 +    }
 +  }
 +  else { /* there is only 'wildcard pattern' or nothing */
 +    if(path[0]) {
 +      wildcard->pattern = strdup(path);
 +      if(!wildcard->pattern)
 +        return CURLE_OUT_OF_MEMORY;
 +      path[0] = '\0';
 +    }
 +    else { /* only list */
 +      wildcard->state = CURLWC_CLEAN;
 +      result = ftp_parse_url_path(conn);
 +      return result;
 +    }
 +  }
 +
 +  /* program continues only if URL is not ending with slash, allocate needed
 +     resources for wildcard transfer */
 +
 +  /* allocate ftp protocol specific temporary wildcard data */
 +  ftp_tmp = calloc(1, sizeof(struct ftp_wc_tmpdata));
 +  if(!ftp_tmp) {
 +    Curl_safefree(wildcard->pattern);
 +    return CURLE_OUT_OF_MEMORY;
 +  }
 +
 +  /* INITIALIZE parselist structure */
 +  ftp_tmp->parser = Curl_ftp_parselist_data_alloc();
 +  if(!ftp_tmp->parser) {
 +    Curl_safefree(wildcard->pattern);
 +    free(ftp_tmp);
 +    return CURLE_OUT_OF_MEMORY;
 +  }
 +
 +  wildcard->tmp = ftp_tmp; /* put it to the WildcardData tmp pointer */
 +  wildcard->tmp_dtor = wc_data_dtor;
 +
 +  /* wildcard does not support NOCWD option (assert it?) */
 +  if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD)
 +    conn->data->set.ftp_filemethod = FTPFILE_MULTICWD;
 +
 +  /* try to parse ftp url */
 +  result = ftp_parse_url_path(conn);
 +  if(result) {
 +    Curl_safefree(wildcard->pattern);
 +    wildcard->tmp_dtor(wildcard->tmp);
 +    wildcard->tmp_dtor = ZERO_NULL;
 +    wildcard->tmp = NULL;
 +    return result;
 +  }
 +
 +  wildcard->path = strdup(conn->data->state.path);
 +  if(!wildcard->path) {
 +    Curl_safefree(wildcard->pattern);
 +    wildcard->tmp_dtor(wildcard->tmp);
 +    wildcard->tmp_dtor = ZERO_NULL;
 +    wildcard->tmp = NULL;
 +    return CURLE_OUT_OF_MEMORY;
 +  }
 +
 +  /* backup old write_function */
 +  ftp_tmp->backup.write_function = conn->data->set.fwrite_func;
 +  /* parsing write function */
 +  conn->data->set.fwrite_func = Curl_ftp_parselist;
 +  /* backup old file descriptor */
 +  ftp_tmp->backup.file_descriptor = conn->data->set.out;
 +  /* let the writefunc callback know what curl pointer is working with */
 +  conn->data->set.out = conn;
 +
 +  infof(conn->data, "Wildcard - Parsing started\n");
 +  return CURLE_OK;
 +}
 +
 +/* This is called recursively */
 +static CURLcode wc_statemach(struct connectdata *conn)
 +{
 +  struct WildcardData * const wildcard = &(conn->data->wildcard);
 +  CURLcode result = CURLE_OK;
 +
-   switch (wildcard->state) {
++  switch(wildcard->state) {
 +  case CURLWC_INIT:
 +    result = init_wc_data(conn);
 +    if(wildcard->state == CURLWC_CLEAN)
 +      /* only listing! */
 +      break;
 +    else
 +      wildcard->state = result ? CURLWC_ERROR : CURLWC_MATCHING;
 +    break;
 +
 +  case CURLWC_MATCHING: {
 +    /* In this state is LIST response successfully parsed, so lets restore
 +       previous WRITEFUNCTION callback and WRITEDATA pointer */
 +    struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
 +    conn->data->set.fwrite_func = ftp_tmp->backup.write_function;
 +    conn->data->set.out = ftp_tmp->backup.file_descriptor;
 +    ftp_tmp->backup.write_function = ZERO_NULL;
 +    ftp_tmp->backup.file_descriptor = NULL;
 +    wildcard->state = CURLWC_DOWNLOADING;
 +
 +    if(Curl_ftp_parselist_geterror(ftp_tmp->parser)) {
 +      /* error found in LIST parsing */
 +      wildcard->state = CURLWC_CLEAN;
 +      return wc_statemach(conn);
 +    }
 +    else if(wildcard->filelist->size == 0) {
 +      /* no corresponding file */
 +      wildcard->state = CURLWC_CLEAN;
 +      return CURLE_REMOTE_FILE_NOT_FOUND;
 +    }
 +    return wc_statemach(conn);
 +  }
 +
 +  case CURLWC_DOWNLOADING: {
 +    /* filelist has at least one file, lets get first one */
 +    struct ftp_conn *ftpc = &conn->proto.ftpc;
 +    struct curl_fileinfo *finfo = wildcard->filelist->head->ptr;
 +
 +    char *tmp_path = aprintf("%s%s", wildcard->path, finfo->filename);
 +    if(!tmp_path)
 +      return CURLE_OUT_OF_MEMORY;
 +
 +    /* switch default "state.pathbuffer" and tmp_path, good to see
 +       ftp_parse_url_path function to understand this trick */
 +    Curl_safefree(conn->data->state.pathbuffer);
 +    conn->data->state.pathbuffer = tmp_path;
 +    conn->data->state.path = tmp_path;
 +
 +    infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
 +    if(conn->data->set.chunk_bgn) {
 +      long userresponse = conn->data->set.chunk_bgn(
 +          finfo, wildcard->customptr, (int)wildcard->filelist->size);
 +      switch(userresponse) {
 +      case CURL_CHUNK_BGN_FUNC_SKIP:
 +        infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
 +              finfo->filename);
 +        wildcard->state = CURLWC_SKIP;
 +        return wc_statemach(conn);
 +      case CURL_CHUNK_BGN_FUNC_FAIL:
 +        return CURLE_CHUNK_FAILED;
 +      }
 +    }
 +
 +    if(finfo->filetype != CURLFILETYPE_FILE) {
 +      wildcard->state = CURLWC_SKIP;
 +      return wc_statemach(conn);
 +    }
 +
 +    if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
 +      ftpc->known_filesize = finfo->size;
 +
 +    result = ftp_parse_url_path(conn);
 +    if(result)
 +      return result;
 +
 +    /* we don't need the Curl_fileinfo of first file anymore */
 +    Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL);
 +
 +    if(wildcard->filelist->size == 0) { /* remains only one file to down. */
 +      wildcard->state = CURLWC_CLEAN;
 +      /* after that will be ftp_do called once again and no transfer
 +         will be done because of CURLWC_CLEAN state */
 +      return CURLE_OK;
 +    }
 +  } break;
 +
 +  case CURLWC_SKIP: {
 +    if(conn->data->set.chunk_end)
 +      conn->data->set.chunk_end(conn->data->wildcard.customptr);
 +    Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL);
 +    wildcard->state = (wildcard->filelist->size == 0) ?
 +                      CURLWC_CLEAN : CURLWC_DOWNLOADING;
 +    return wc_statemach(conn);
 +  }
 +
 +  case CURLWC_CLEAN: {
 +    struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
 +    result = CURLE_OK;
 +    if(ftp_tmp)
 +      result = Curl_ftp_parselist_geterror(ftp_tmp->parser);
 +
 +    wildcard->state = result ? CURLWC_ERROR : CURLWC_DONE;
 +  } break;
 +
 +  case CURLWC_DONE:
 +  case CURLWC_ERROR:
 +    break;
 +  }
 +
 +  return result;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_do()
 + *
 + * This function is registered as 'curl_do' function. It decodes the path
 + * parts etc as a wrapper to the actual DO function (ftp_perform).
 + *
 + * The input argument is already checked for validity.
 + */
 +static CURLcode ftp_do(struct connectdata *conn, bool *done)
 +{
 +  CURLcode result = CURLE_OK;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  *done = FALSE; /* default to false */
 +  ftpc->wait_data_conn = FALSE; /* default to no such wait */
 +
 +  if(conn->data->set.wildcardmatch) {
 +    result = wc_statemach(conn);
 +    if(conn->data->wildcard.state == CURLWC_SKIP ||
 +      conn->data->wildcard.state == CURLWC_DONE) {
 +      /* do not call ftp_regular_transfer */
 +      return CURLE_OK;
 +    }
 +    if(result) /* error, loop or skipping the file */
 +      return result;
 +  }
 +  else { /* no wildcard FSM needed */
 +    result = ftp_parse_url_path(conn);
 +    if(result)
 +      return result;
 +  }
 +
 +  result = ftp_regular_transfer(conn, done);
 +
 +  return result;
 +}
 +
 +
 +CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
 +{
 +  ssize_t bytes_written;
 +#define SBUF_SIZE 1024
 +  char s[SBUF_SIZE];
 +  size_t write_len;
 +  char *sptr=s;
 +  CURLcode result = CURLE_OK;
 +#ifdef HAVE_GSSAPI
 +  enum protection_level data_sec = conn->data_prot;
 +#endif
 +
 +  write_len = strlen(cmd);
 +  if(write_len > (sizeof(s) -3))
 +    return CURLE_BAD_FUNCTION_ARGUMENT;
 +
 +  strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
 +  write_len +=2;
 +
 +  bytes_written=0;
 +
 +  result = Curl_convert_to_network(conn->data, s, write_len);
 +  /* Curl_convert_to_network calls failf if unsuccessful */
 +  if(result)
 +    return result;
 +
 +  for(;;) {
 +#ifdef HAVE_GSSAPI
 +    conn->data_prot = PROT_CMD;
 +#endif
 +    result = Curl_write(conn, conn->sock[FIRSTSOCKET], sptr, write_len,
 +                        &bytes_written);
 +#ifdef HAVE_GSSAPI
 +    DEBUGASSERT(data_sec > PROT_NONE && data_sec < PROT_LAST);
 +    conn->data_prot = data_sec;
 +#endif
 +
 +    if(result)
 +      break;
 +
 +    if(conn->data->set.verbose)
 +      Curl_debug(conn->data, CURLINFO_HEADER_OUT,
 +                 sptr, (size_t)bytes_written, conn);
 +
 +    if(bytes_written != (ssize_t)write_len) {
 +      write_len -= bytes_written;
 +      sptr += bytes_written;
 +    }
 +    else
 +      break;
 +  }
 +
 +  return result;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_quit()
 + *
 + * This should be called before calling sclose() on an ftp control connection
 + * (not data connections). We should then wait for the response from the
 + * server before returning. The calling code should then try to close the
 + * connection.
 + *
 + */
 +static CURLcode ftp_quit(struct connectdata *conn)
 +{
 +  CURLcode result = CURLE_OK;
 +
 +  if(conn->proto.ftpc.ctl_valid) {
 +    result = Curl_pp_sendf(&conn->proto.ftpc.pp, "%s", "QUIT");
 +    if(result) {
 +      failf(conn->data, "Failure sending QUIT command: %s",
 +            curl_easy_strerror(result));
 +      conn->proto.ftpc.ctl_valid = FALSE; /* mark control connection as bad */
 +      connclose(conn, "QUIT command failed"); /* mark for connection closure */
 +      state(conn, FTP_STOP);
 +      return result;
 +    }
 +
 +    state(conn, FTP_QUIT);
 +
 +    result = ftp_block_statemach(conn);
 +  }
 +
 +  return result;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_disconnect()
 + *
 + * Disconnect from an FTP server. Cleanup protocol-specific per-connection
 + * resources. BLOCKING.
 + */
 +static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
 +{
 +  struct ftp_conn *ftpc= &conn->proto.ftpc;
 +  struct pingpong *pp = &ftpc->pp;
 +
 +  /* We cannot send quit unconditionally. If this connection is stale or
 +     bad in any way, sending quit and waiting around here will make the
 +     disconnect wait in vain and cause more problems than we need to.
 +
 +     ftp_quit() will check the state of ftp->ctl_valid. If it's ok it
 +     will try to send the QUIT command, otherwise it will just return.
 +  */
 +  if(dead_connection)
 +    ftpc->ctl_valid = FALSE;
 +
 +  /* The FTP session may or may not have been allocated/setup at this point! */
 +  (void)ftp_quit(conn); /* ignore errors on the QUIT */
 +
 +  if(ftpc->entrypath) {
 +    struct Curl_easy *data = conn->data;
 +    if(data->state.most_recent_ftp_entrypath == ftpc->entrypath) {
 +      data->state.most_recent_ftp_entrypath = NULL;
 +    }
 +    free(ftpc->entrypath);
 +    ftpc->entrypath = NULL;
 +  }
 +
 +  freedirs(ftpc);
 +  free(ftpc->prevpath);
 +  ftpc->prevpath = NULL;
 +  free(ftpc->server_os);
 +  ftpc->server_os = NULL;
 +
 +  Curl_pp_disconnect(pp);
 +
 +#ifdef HAVE_GSSAPI
 +  Curl_sec_end(conn);
 +#endif
 +
 +  return CURLE_OK;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_parse_url_path()
 + *
 + * Parse the URL path into separate path components.
 + *
 + */
 +static
 +CURLcode ftp_parse_url_path(struct connectdata *conn)
 +{
 +  struct Curl_easy *data = conn->data;
 +  /* the ftp struct is already inited in ftp_connect() */
 +  struct FTP *ftp = data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  const char *slash_pos;  /* position of the first '/' char in curpos */
 +  const char *path_to_use = data->state.path;
 +  const char *cur_pos;
 +  const char *filename = NULL;
 +
-   cur_pos = path_to_use; /* current position in path. point at the begin
-                             of next path component */
++  cur_pos = path_to_use; /* current position in path. point at the begin of
++                            next path component */
 +
 +  ftpc->ctl_valid = FALSE;
 +  ftpc->cwdfail = FALSE;
 +
 +  switch(data->set.ftp_filemethod) {
 +  case FTPFILE_NOCWD:
 +    /* fastest, but less standard-compliant */
 +
 +    /*
 +      The best time to check whether the path is a file or directory is right
 +      here. so:
 +
 +      the first condition in the if() right here, is there just in case
 +      someone decides to set path to NULL one day
 +   */
 +    if(path_to_use[0] &&
 +       (path_to_use[strlen(path_to_use) - 1] != '/') )
 +      filename = path_to_use;  /* this is a full file path */
 +    /*
 +      else {
 +        ftpc->file is not used anywhere other than for operations on a file.
 +        In other words, never for directory operations.
 +        So we can safely leave filename as NULL here and use it as a
 +        argument in dir/file decisions.
 +      }
 +    */
 +    break;
 +
 +  case FTPFILE_SINGLECWD:
 +    /* get the last slash */
 +    if(!path_to_use[0]) {
 +      /* no dir, no file */
 +      ftpc->dirdepth = 0;
 +      break;
 +    }
 +    slash_pos=strrchr(cur_pos, '/');
 +    if(slash_pos || !*cur_pos) {
 +      size_t dirlen = slash_pos-cur_pos;
 +      CURLcode result;
 +
 +      ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0]));
 +      if(!ftpc->dirs)
 +        return CURLE_OUT_OF_MEMORY;
 +
 +      if(!dirlen)
 +        dirlen++;
 +
 +      result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/",
 +                              slash_pos ? dirlen : 1,
 +                              &ftpc->dirs[0], NULL,
 +                              FALSE);
 +      if(result) {
 +        freedirs(ftpc);
 +        return result;
 +      }
 +      ftpc->dirdepth = 1; /* we consider it to be a single dir */
 +      filename = slash_pos ? slash_pos+1 : cur_pos; /* rest is file name */
 +    }
 +    else
 +      filename = cur_pos;  /* this is a file name only */
 +    break;
 +
 +  default: /* allow pretty much anything */
 +  case FTPFILE_MULTICWD:
 +    ftpc->dirdepth = 0;
 +    ftpc->diralloc = 5; /* default dir depth to allocate */
 +    ftpc->dirs = calloc(ftpc->diralloc, sizeof(ftpc->dirs[0]));
 +    if(!ftpc->dirs)
 +      return CURLE_OUT_OF_MEMORY;
 +
 +    /* we have a special case for listing the root dir only */
 +    if(!strcmp(path_to_use, "/")) {
 +      cur_pos++; /* make it point to the zero byte */
 +      ftpc->dirs[0] = strdup("/");
 +      ftpc->dirdepth++;
 +    }
 +    else {
 +      /* parse the URL path into separate path components */
 +      while((slash_pos = strchr(cur_pos, '/')) != NULL) {
 +        /* 1 or 0 pointer offset to indicate absolute directory */
 +        ssize_t absolute_dir = ((cur_pos - data->state.path > 0) &&
 +                                (ftpc->dirdepth == 0))?1:0;
 +
 +        /* seek out the next path component */
 +        if(slash_pos-cur_pos) {
 +          /* we skip empty path components, like "x//y" since the FTP command
 +             CWD requires a parameter and a non-existent parameter a) doesn't
 +             work on many servers and b) has no effect on the others. */
 +          size_t len = slash_pos - cur_pos + absolute_dir;
 +          CURLcode result =
 +            Curl_urldecode(conn->data, cur_pos - absolute_dir, len,
 +                           &ftpc->dirs[ftpc->dirdepth], NULL,
 +                           TRUE);
 +          if(result) {
 +            free(ftpc->dirs[ftpc->dirdepth]);
 +            freedirs(ftpc);
 +            return result;
 +          }
 +        }
 +        else {
 +          cur_pos = slash_pos + 1; /* jump to the rest of the string */
 +          if(!ftpc->dirdepth) {
 +            /* path starts with a slash, add that as a directory */
 +            ftpc->dirs[ftpc->dirdepth] = strdup("/");
 +            if(!ftpc->dirs[ftpc->dirdepth++]) { /* run out of memory ... */
 +              failf(data, "no memory");
 +              freedirs(ftpc);
 +              return CURLE_OUT_OF_MEMORY;
 +            }
 +          }
 +          continue;
 +        }
 +
 +        cur_pos = slash_pos + 1; /* jump to the rest of the string */
 +        if(++ftpc->dirdepth >= ftpc->diralloc) {
 +          /* enlarge array */
 +          char **bigger;
 +          ftpc->diralloc *= 2; /* double the size each time */
 +          bigger = realloc(ftpc->dirs, ftpc->diralloc * sizeof(ftpc->dirs[0]));
 +          if(!bigger) {
 +            freedirs(ftpc);
 +            return CURLE_OUT_OF_MEMORY;
 +          }
 +          ftpc->dirs = bigger;
 +        }
 +      }
 +    }
 +    filename = cur_pos;  /* the rest is the file name */
 +    break;
 +  } /* switch */
 +
 +  if(filename && *filename) {
 +    CURLcode result =
 +      Curl_urldecode(conn->data, filename, 0,  &ftpc->file, NULL, TRUE);
 +
 +    if(result) {
 +      freedirs(ftpc);
 +      return result;
 +    }
 +  }
 +  else
 +    ftpc->file=NULL; /* instead of point to a zero byte, we make it a NULL
 +                       pointer */
 +
 +  if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) {
 +    /* We need a file name when uploading. Return error! */
 +    failf(data, "Uploading to a URL without a file name!");
 +    return CURLE_URL_MALFORMAT;
 +  }
 +
 +  ftpc->cwddone = FALSE; /* default to not done */
 +
 +  if(ftpc->prevpath) {
 +    /* prevpath is "raw" so we convert the input path before we compare the
 +       strings */
 +    size_t dlen;
 +    char *path;
 +    CURLcode result =
 +      Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, FALSE);
 +    if(result) {
 +      freedirs(ftpc);
 +      return result;
 +    }
 +
 +    dlen -= ftpc->file?strlen(ftpc->file):0;
 +    if((dlen == strlen(ftpc->prevpath)) &&
 +       !strncmp(path, ftpc->prevpath, dlen)) {
 +      infof(data, "Request has same path as previous transfer\n");
 +      ftpc->cwddone = TRUE;
 +    }
 +    free(path);
 +  }
 +
 +  return CURLE_OK;
 +}
 +
 +/* call this when the DO phase has completed */
 +static CURLcode ftp_dophase_done(struct connectdata *conn,
 +                                 bool connected)
 +{
 +  struct FTP *ftp = conn->data->req.protop;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +
 +  if(connected) {
 +    int completed;
 +    CURLcode result = ftp_do_more(conn, &completed);
 +
 +    if(result) {
 +      close_secondarysocket(conn);
 +      return result;
 +    }
 +  }
 +
 +  if(ftp->transfer != FTPTRANSFER_BODY)
 +    /* no data to transfer */
 +    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
 +  else if(!connected)
 +    /* since we didn't connect now, we want do_more to get called */
 +    conn->bits.do_more = TRUE;
 +
 +  ftpc->ctl_valid = TRUE; /* seems good */
 +
 +  return CURLE_OK;
 +}
 +
 +/* called from multi.c while DOing */
 +static CURLcode ftp_doing(struct connectdata *conn,
 +                          bool *dophase_done)
 +{
 +  CURLcode result = ftp_multi_statemach(conn, dophase_done);
 +
 +  if(result)
 +    DEBUGF(infof(conn->data, "DO phase failed\n"));
 +  else if(*dophase_done) {
 +    result = ftp_dophase_done(conn, FALSE /* not connected */);
 +
 +    DEBUGF(infof(conn->data, "DO phase is complete2\n"));
 +  }
 +  return result;
 +}
 +
 +/***********************************************************************
 + *
 + * ftp_regular_transfer()
 + *
 + * The input argument is already checked for validity.
 + *
 + * Performs all commands done before a regular transfer between a local and a
 + * remote host.
 + *
 + * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the
 + * ftp_done() function without finding any major problem.
 + */
 +static
 +CURLcode ftp_regular_transfer(struct connectdata *conn,
 +                              bool *dophase_done)
 +{
 +  CURLcode result=CURLE_OK;
 +  bool connected=FALSE;
 +  struct Curl_easy *data = conn->data;
 +  struct ftp_conn *ftpc = &conn->proto.ftpc;
 +  data->req.size = -1; /* make sure this is unknown at this point */
 +
 +  Curl_pgrsSetUploadCounter(data, 0);
 +  Curl_pgrsSetDownloadCounter(data, 0);
 +  Curl_pgrsSetUploadSize(data, -1);
 +  Curl_pgrsSetDownloadSize(data, -1);
 +
 +  ftpc->ctl_valid = TRUE; /* starts good */
 +
 +  result = ftp_perform(conn,
 +                       &connected, /* have we connected after PASV/PORT */
 +                       dophase_done); /* all commands in the DO-phase done? */
 +
 +  if(!result) {
 +
 +    if(!*dophase_done)
 +      /* the DO phase has not completed yet */
 +      return CURLE_OK;
 +
 +    result = ftp_dophase_done(conn, connected);
 +
 +    if(result)
 +      return result;
 +  }
 +  else
 +    freedirs(ftpc);
 +
 +  return result;
 +}
 +
 +static CURLcode ftp_setup_connection(struct connectdata *conn)
 +{
 +  struct Curl_easy *data = conn->data;
 +  char *type;
 +  char command;
 +  struct FTP *ftp;
 +
 +  if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
 +    /* Unless we have asked to tunnel ftp operations through the proxy, we
 +       switch and use HTTP operations only */
 +#ifndef CURL_DISABLE_HTTP
 +    if(conn->handler == &Curl_handler_ftp)
 +      conn->handler = &Curl_handler_ftp_proxy;
 +    else {
 +#ifdef USE_SSL
 +      conn->handler = &Curl_handler_ftps_proxy;
 +#else
 +      failf(data, "FTPS not supported!");
 +      return CURLE_UNSUPPORTED_PROTOCOL;
 +#endif
 +    }
 +    /* set it up as a HTTP connection instead */
 +    return conn->handler->setup_connection(conn);
 +#else
 +    failf(data, "FTP over http proxy requires HTTP support built-in!");
 +    return CURLE_UNSUPPORTED_PROTOCOL;
 +#endif
 +  }
 +
 +  conn->data->req.protop = ftp = malloc(sizeof(struct FTP));
 +  if(NULL == ftp)
 +    return CURLE_OUT_OF_MEMORY;
 +
 +  data->state.path++;   /* don't include the initial slash */
 +  data->state.slash_removed = TRUE; /* we've skipped the slash */
 +
 +  /* FTP URLs support an extension like ";type=<typecode>" that
 +   * we'll try to get now! */
 +  type = strstr(data->state.path, ";type=");
 +
 +  if(!type)
 +    type = strstr(conn->host.rawalloc, ";type=");
 +
 +  if(type) {
 +    *type = 0;                     /* it was in the middle of the hostname */
 +    command = Curl_raw_toupper(type[6]);
 +    conn->bits.type_set = TRUE;
 +
-     switch (command) {
++    switch(command) {
 +    case 'A': /* ASCII mode */
 +      data->set.prefer_ascii = TRUE;
 +      break;
 +
 +    case 'D': /* directory mode */
 +      data->set.ftp_list_only = TRUE;
 +      break;
 +
 +    case 'I': /* binary mode */
 +    default:
 +      /* switch off ASCII */
 +      data->set.prefer_ascii = FALSE;
 +      break;
 +    }
 +  }
 +
 +  /* get some initial data into the ftp struct */
 +  ftp->bytecountp = &conn->data->req.bytecount;
 +  ftp->transfer = FTPTRANSFER_BODY;
 +  ftp->downloadsize = 0;
 +
 +  /* No need to duplicate user+password, the connectdata struct won't change
 +     during a session, but we re-init them here since on subsequent inits
 +     since the conn struct may have changed or been replaced.
 +  */
 +  ftp->user = conn->user;
 +  ftp->passwd = conn->passwd;
 +  if(isBadFtpString(ftp->user))
 +    return CURLE_URL_MALFORMAT;
 +  if(isBadFtpString(ftp->passwd))
 +    return CURLE_URL_MALFORMAT;
 +
 +  conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
 +
 +  return CURLE_OK;
 +}
 +
 +#endif /* CURL_DISABLE_FTP */
diff --cc Utilities/cmcurl/lib/mprintf.c
index 3cdd41a,0000000..4baa1cc
mode 100644,000000..100644
--- a/Utilities/cmcurl/lib/mprintf.c
+++ b/Utilities/cmcurl/lib/mprintf.c
@@@ -1,1166 -1,0 +1,1181 @@@
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
 + * Copyright (C) 1999 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
 + *
 + * This software is licensed as described in the file COPYING, which
 + * you should have received as part of this distribution. The terms
 + * are also available at https://curl.haxx.se/docs/copyright.html.
 + *
 + * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 + * copies of the Software, and permit persons to whom the Software is
 + * furnished to do so, under the terms of the COPYING file.
 + *
 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 + * KIND, either express or implied.
 + *
 + *
 + * Purpose:
 + *  A merge of Bjorn Reese's format() function and Daniel's dsprintf()
 + *  1.0. A full blooded printf() clone with full support for <num>$
 + *  everywhere (parameters, widths and precisions) including variabled
 + *  sized parameters (like doubles, long longs, long doubles and even
 + *  void * in 64-bit architectures).
 + *
 + * Current restrictions:
 + * - Max 128 parameters
 + * - No 'long double' support.
 + *
 + * If you ever want truly portable and good *printf() clones, the project that
 + * took on from here is named 'Trio' and you find more details on the trio web
 + * page at https://daniel.haxx.se/projects/trio/
 + */
 +
 +#include "curl_setup.h"
 +#include <curl/mprintf.h>
 +
 +#include "curl_memory.h"
 +/* The last #include file should be: */
 +#include "memdebug.h"
 +
 +/*
 + * If SIZEOF_SIZE_T has not been defined, default to the size of long.
 + */
 +
 +#ifndef SIZEOF_SIZE_T
 +#  define SIZEOF_SIZE_T CURL_SIZEOF_LONG
 +#endif
 +
 +#ifdef HAVE_LONGLONG
 +#  define LONG_LONG_TYPE long long
 +#  define HAVE_LONG_LONG_TYPE
 +#else
 +#  if defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
 +#    define LONG_LONG_TYPE __int64
 +#    define HAVE_LONG_LONG_TYPE
 +#  else
 +#    undef LONG_LONG_TYPE
 +#    undef HAVE_LONG_LONG_TYPE
 +#  endif
 +#endif
 +
 +/*
 + * Non-ANSI integer extensions
 + */
 +
 +#if (defined(__BORLANDC__) && (__BORLANDC__ >= 0x520)) || \
 +    (defined(__WATCOMC__) && defined(__386__)) || \
 +    (defined(__POCC__) && defined(_MSC_VER)) || \
 +    (defined(_WIN32_WCE)) || \
 +    (defined(__MINGW32__)) || \
 +    (defined(_MSC_VER) && (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64))
 +#  define MP_HAVE_INT_EXTENSIONS
 +#endif
 +
 +/*
 + * Max integer data types that mprintf.c is capable
 + */
 +
 +#ifdef HAVE_LONG_LONG_TYPE
 +#  define mp_intmax_t LONG_LONG_TYPE
 +#  define mp_uintmax_t unsigned LONG_LONG_TYPE
 +#else
 +#  define mp_intmax_t long
 +#  define mp_uintmax_t unsigned long
 +#endif
 +
- #define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
++#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should
++                        fit negative DBL_MAX (317 letters) */
 +#define MAX_PARAMETERS 128 /* lame static limit */
 +
 +#ifdef __AMIGA__
 +# undef FORMAT_INT
 +#endif
 +
 +/* Lower-case digits.  */
 +static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 +
 +/* Upper-case digits.  */
 +static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 +
 +#define OUTCHAR(x) \
 +  do{ \
 +    if(stream((unsigned char)(x), (FILE *)data) != -1) \
 +      done++; \
 +    else \
 +     return done; /* return immediately on failure */ \
 +  } WHILE_FALSE
 +
 +/* Data type to read from the arglist */
 +typedef enum  {
 +  FORMAT_UNKNOWN = 0,
 +  FORMAT_STRING,
 +  FORMAT_PTR,
 +  FORMAT_INT,
 +  FORMAT_INTPTR,
 +  FORMAT_LONG,
 +  FORMAT_LONGLONG,
 +  FORMAT_DOUBLE,
 +  FORMAT_LONGDOUBLE,
 +  FORMAT_WIDTH /* For internal use */
 +} FormatType;
 +
 +/* conversion and display flags */
 +enum {
 +  FLAGS_NEW        = 0,
 +  FLAGS_SPACE      = 1<<0,
 +  FLAGS_SHOWSIGN   = 1<<1,
 +  FLAGS_LEFT       = 1<<2,
 +  FLAGS_ALT        = 1<<3,
 +  FLAGS_SHORT      = 1<<4,
 +  FLAGS_LONG       = 1<<5,
 +  FLAGS_LONGLONG   = 1<<6,
 +  FLAGS_LONGDOUBLE = 1<<7,
 +  FLAGS_PAD_NIL    = 1<<8,
 +  FLAGS_UNSIGNED   = 1<<9,
 +  FLAGS_OCTAL      = 1<<10,
 +  FLAGS_HEX        = 1<<11,
 +  FLAGS_UPPER      = 1<<12,
 +  FLAGS_WIDTH      = 1<<13, /* '*' or '*<num>$' used */
 +  FLAGS_WIDTHPARAM = 1<<14, /* width PARAMETER was specified */
 +  FLAGS_PREC       = 1<<15, /* precision was specified */
 +  FLAGS_PRECPARAM  = 1<<16, /* precision PARAMETER was specified */
 +  FLAGS_CHAR       = 1<<17, /* %c story */
 +  FLAGS_FLOATE     = 1<<18, /* %e or %E */
 +  FLAGS_FLOATG     = 1<<19  /* %g or %G */
 +};
 +
 +typedef struct {
 +  FormatType type;
 +  int flags;
 +  long width;     /* width OR width parameter number */
 +  long precision; /* precision OR precision parameter number */
 +  union {
 +    char *str;
 +    void *ptr;
 +    union {
 +      mp_intmax_t as_signed;
 +      mp_uintmax_t as_unsigned;
 +    } num;
 +    double dnum;
 +  } data;
 +} va_stack_t;
 +
 +struct nsprintf {
 +  char *buffer;
 +  size_t length;
 +  size_t max;
 +};
 +
 +struct asprintf {
 +  char *buffer; /* allocated buffer */
 +  size_t len;   /* length of string */
 +  size_t alloc; /* length of alloc */
 +  int fail;     /* (!= 0) if an alloc has failed and thus
 +                   the output is not the complete data */
 +};
 +
 +static long dprintf_DollarString(char *input, char **end)
 +{
 +  int number=0;
 +  while(ISDIGIT(*input)) {
 +    number *= 10;
 +    number += *input-'0';
 +    input++;
 +  }
 +  if(number && ('$'==*input++)) {
 +    *end = input;
 +    return number;
 +  }
 +  return 0;
 +}
 +
 +static bool dprintf_IsQualifierNoDollar(const char *fmt)
 +{
 +#if defined(MP_HAVE_INT_EXTENSIONS)
 +  if(!strncmp(fmt, "I32", 3) || !strncmp(fmt, "I64", 3)) {
 +    return TRUE;
 +  }
 +#endif
 +
 +  switch(*fmt) {
 +  case '-': case '+': case ' ': case '#': case '.':
 +  case '0': case '1': case '2': case '3': case '4':
 +  case '5': case '6': case '7': case '8': case '9':
 +  case 'h': case 'l': case 'L': case 'z': case 'q':
 +  case '*': case 'O':
 +#if defined(MP_HAVE_INT_EXTENSIONS)
 +  case 'I':
 +#endif
 +    return TRUE;
 +
 +  default:
 +    return FALSE;
 +  }
 +}
 +
 +/******************************************************************
 + *
 + * Pass 1:
 + * Create an index with the type of each parameter entry and its
 + * value (may vary in size)
 + *
 + * Returns zero on success.
 + *
 + ******************************************************************/
 +
 +static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
 +                         va_list arglist)
 +{
 +  char *fmt = (char *)format;
 +  int param_num = 0;
 +  long this_param;
 +  long width;
 +  long precision;
 +  int flags;
 +  long max_param=0;
 +  long i;
 +
 +  while(*fmt) {
 +    if(*fmt++ == '%') {
 +      if(*fmt == '%') {
 +        fmt++;
 +        continue; /* while */
 +      }
 +
 +      flags = FLAGS_NEW;
 +
 +      /* Handle the positional case (N$) */
 +
 +      param_num++;
 +
 +      this_param = dprintf_DollarString(fmt, &fmt);
 +      if(0 == this_param)
 +        /* we got no positional, get the next counter */
 +        this_param = param_num;
 +
 +      if(this_param > max_param)
 +        max_param = this_param;
 +
 +      /*
 +       * The parameter with number 'i' should be used. Next, we need
 +       * to get SIZE and TYPE of the parameter. Add the information
 +       * to our array.
 +       */
 +
 +      width = 0;
 +      precision = 0;
 +
 +      /* Handle the flags */
 +
 +      while(dprintf_IsQualifierNoDollar(fmt)) {
 +#if defined(MP_HAVE_INT_EXTENSIONS)
 +        if(!strncmp(fmt, "I32", 3)) {
 +          flags |= FLAGS_LONG;
 +          fmt += 3;
 +        }
 +        else if(!strncmp(fmt, "I64", 3)) {
 +          flags |= FLAGS_LONGLONG;
 +          fmt += 3;
 +        }
 +        else
 +#endif
 +
 +        switch(*fmt++) {
 +        case ' ':
 +          flags |= FLAGS_SPACE;
 +          break;
 +        case '+':
 +          flags |= FLAGS_SHOWSIGN;
 +          break;
 +        case '-':
 +          flags |= FLAGS_LEFT;
 +          flags &= ~FLAGS_PAD_NIL;
 +          break;
 +        case '#':
 +          flags |= FLAGS_ALT;
 +          break;
 +        case '.':
-           flags |= FLAGS_PREC;
 +          if('*' == *fmt) {
 +            /* The precision is picked from a specified parameter */
 +
 +            flags |= FLAGS_PRECPARAM;
 +            fmt++;
 +            param_num++;
 +
 +            i = dprintf_DollarString(fmt, &fmt);
 +            if(i)
 +              precision = i;
 +            else
 +              precision = param_num;
 +
 +            if(precision > max_param)
 +              max_param = precision;
 +          }
 +          else {
 +            flags |= FLAGS_PREC;
 +            precision = strtol(fmt, &fmt, 10);
 +          }
 +          break;
 +        case 'h':
 +          flags |= FLAGS_SHORT;
 +          break;
 +#if defined(MP_HAVE_INT_EXTENSIONS)
 +        case 'I':
 +#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
 +          flags |= FLAGS_LONGLONG;
 +#else
 +          flags |= FLAGS_LONG;
 +#endif
 +          break;
 +#endif
 +        case 'l':
 +          if(flags & FLAGS_LONG)
 +            flags |= FLAGS_LONGLONG;
 +          else
 +            flags |= FLAGS_LONG;
 +          break;
 +        case 'L':
 +          flags |= FLAGS_LONGDOUBLE;
 +          break;
 +        case 'q':
 +          flags |= FLAGS_LONGLONG;
 +          break;
 +        case 'z':
 +          /* the code below generates a warning if -Wunreachable-code is
 +             used */
 +#if (SIZEOF_SIZE_T > CURL_SIZEOF_LONG)
 +          flags |= FLAGS_LONGLONG;
 +#else
 +          flags |= FLAGS_LONG;
 +#endif
 +          break;
 +        case 'O':
 +#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
 +          flags |= FLAGS_LONGLONG;
 +#else
 +          flags |= FLAGS_LONG;
 +#endif
 +          break;
 +        case '0':
 +          if(!(flags & FLAGS_LEFT))
 +            flags |= FLAGS_PAD_NIL;
 +          /* FALLTHROUGH */
 +        case '1': case '2': case '3': case '4':
 +        case '5': case '6': case '7': case '8': case '9':
 +          flags |= FLAGS_WIDTH;
 +          width = strtol(fmt-1, &fmt, 10);
 +          break;
 +        case '*':  /* Special case */
 +          flags |= FLAGS_WIDTHPARAM;
 +          param_num++;
 +
 +          i = dprintf_DollarString(fmt, &fmt);
 +          if(i)
 +            width = i;
 +          else
 +            width = param_num;
 +          if(width > max_param)
 +            max_param=width;
 +          break;
 +        default:
 +          break;
 +        }
 +      } /* switch */
 +
 +      /* Handle the specifier */
 +
 +      i = this_param - 1;
 +
 +      if((i < 0) || (i >= MAX_PARAMETERS))
 +        /* out of allowed range */
 +        return 1;
 +
 +      switch (*fmt) {
 +      case 'S':
 +        flags |= FLAGS_ALT;
 +        /* FALLTHROUGH */
 +      case 's':
 +        vto[i].type = FORMAT_STRING;
 +        break;
 +      case 'n':
 +        vto[i].type = FORMAT_INTPTR;
 +        break;
 +      case 'p':
 +        vto[i].type = FORMAT_PTR;
 +        break;
 +      case 'd': case 'i':
 +        vto[i].type = FORMAT_INT;
 +        break;
 +      case 'u':
 +        vto[i].type = FORMAT_INT;
 +        flags |= FLAGS_UNSIGNED;
 +        break;
 +      case 'o':
 +        vto[i].type = FORMAT_INT;
 +        flags |= FLAGS_OCTAL;
 +        break;
 +      case 'x':
 +        vto[i].type = FORMAT_INT;
 +        flags |= FLAGS_HEX|FLAGS_UNSIGNED;
 +        break;
 +      case 'X':
 +        vto[i].type = FORMAT_INT;
 +        flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED;
 +        break;
 +      case 'c':
 +        vto[i].type = FORMAT_INT;
 +        flags |= FLAGS_CHAR;
 +        break;
 +      case 'f':
 +        vto[i].type = FORMAT_DOUBLE;
 +        break;
 +      case 'e':
 +        vto[i].type = FORMAT_DOUBLE;
 +        flags |= FLAGS_FLOATE;
 +        break;
 +      case 'E':
 +        vto[i].type = FORMAT_DOUBLE;
 +        flags |= FLAGS_FLOATE|FLAGS_UPPER;
 +        break;
 +      case 'g':
 +        vto[i].type = FORMAT_DOUBLE;
 +        flags |= FLAGS_FLOATG;
 +        break;
 +      case 'G':
 +        vto[i].type = FORMAT_DOUBLE;
 +        flags |= FLAGS_FLOATG|FLAGS_UPPER;
 +        break;
 +      default:
 +        vto[i].type = FORMAT_UNKNOWN;
 +        break;
 +      } /* switch */
 +
 +      vto[i].flags = flags;
 +      vto[i].width = width;
 +      vto[i].precision = precision;
 +
 +      if(flags & FLAGS_WIDTHPARAM) {
 +        /* we have the width specified from a parameter, so we make that
 +           parameter's info setup properly */
 +        long k = width - 1;
 +        vto[i].width = k;
 +        vto[k].type = FORMAT_WIDTH;
 +        vto[k].flags = FLAGS_NEW;
 +        /* can't use width or precision of width! */
 +        vto[k].width = 0;
 +        vto[k].precision = 0;
 +      }
 +      if(flags & FLAGS_PRECPARAM) {
 +        /* we have the precision specified from a parameter, so we make that
 +           parameter's info setup properly */
 +        long k = precision - 1;
 +        vto[i].precision = k;
 +        vto[k].type = FORMAT_WIDTH;
 +        vto[k].flags = FLAGS_NEW;
 +        /* can't use width or precision of width! */
 +        vto[k].width = 0;
 +        vto[k].precision = 0;
 +      }
 +      *endpos++ = fmt + 1; /* end of this sequence */
 +    }
 +  }
 +
 +  /* Read the arg list parameters into our data list */
 +  for(i=0; i<max_param; i++) {
 +    /* Width/precision arguments must be read before the main argument
 +       they are attached to */
 +    if(vto[i].flags & FLAGS_WIDTHPARAM) {
 +      vto[vto[i].width].data.num.as_signed =
 +        (mp_intmax_t)va_arg(arglist, int);
 +    }
 +    if(vto[i].flags & FLAGS_PRECPARAM) {
 +      vto[vto[i].precision].data.num.as_signed =
 +        (mp_intmax_t)va_arg(arglist, int);
 +    }
 +
-     switch (vto[i].type) {
++    switch(vto[i].type) {
 +    case FORMAT_STRING:
 +      vto[i].data.str = va_arg(arglist, char *);
 +      break;
 +
 +    case FORMAT_INTPTR:
 +    case FORMAT_UNKNOWN:
 +    case FORMAT_PTR:
 +      vto[i].data.ptr = va_arg(arglist, void *);
 +      break;
 +
 +    case FORMAT_INT:
 +#ifdef HAVE_LONG_LONG_TYPE
 +      if((vto[i].flags & FLAGS_LONGLONG) && (vto[i].flags & FLAGS_UNSIGNED))
 +        vto[i].data.num.as_unsigned =
 +          (mp_uintmax_t)va_arg(arglist, mp_uintmax_t);
 +      else if(vto[i].flags & FLAGS_LONGLONG)
 +        vto[i].data.num.as_signed =
 +          (mp_intmax_t)va_arg(arglist, mp_intmax_t);
 +      else
 +#endif
 +      {
 +        if((vto[i].flags & FLAGS_LONG) && (vto[i].flags & FLAGS_UNSIGNED))
 +          vto[i].data.num.as_unsigned =
 +            (mp_uintmax_t)va_arg(arglist, unsigned long);
 +        else if(vto[i].flags & FLAGS_LONG)
 +          vto[i].data.num.as_signed =
 +            (mp_intmax_t)va_arg(arglist, long);
 +        else if(vto[i].flags & FLAGS_UNSIGNED)
 +          vto[i].data.num.as_unsigned =
 +            (mp_uintmax_t)va_arg(arglist, unsigned int);
 +        else
 +          vto[i].data.num.as_signed =
 +            (mp_intmax_t)va_arg(arglist, int);
 +      }
 +      break;
 +
 +    case FORMAT_DOUBLE:
 +      vto[i].data.dnum = va_arg(arglist, double);
 +      break;
 +
 +    case FORMAT_WIDTH:
 +      /* Argument has been read. Silently convert it into an integer
 +       * for later use
 +       */
 +      vto[i].type = FORMAT_INT;
 +      break;
 +
 +    default:
 +      break;
 +    }
 +  }
 +
 +  return 0;
 +
 +}
 +
 +static int dprintf_formatf(
 +  void *data, /* untouched by format(), just sent to the stream() function in
 +                 the second argument */
 +  /* function pointer called for each output character */
 +  int (*stream)(int, FILE *),
 +  const char *format,    /* %-formatted string */
 +  va_list ap_save) /* list of parameters */
 +{
 +  /* Base-36 digits for numbers.  */
 +  const char *digits = lower_digits;
 +
 +  /* Pointer into the format string.  */
 +  char *f;
 +
 +  /* Number of characters written.  */
 +  int done = 0;
 +
 +  long param; /* current parameter to read */
 +  long param_num=0; /* parameter counter */
 +
 +  va_stack_t vto[MAX_PARAMETERS];
 +  char *endpos[MAX_PARAMETERS];
 +  char **end;
 +
 +  char work[BUFFSIZE];
 +
 +  va_stack_t *p;
 +
 +  /* 'workend' points to the final buffer byte position, but with an extra
 +     byte as margin to avoid the (false?) warning Coverity gives us
 +     otherwise */
 +  char *workend = &work[sizeof(work) - 2];
 +
 +  /* Do the actual %-code parsing */
 +  if(dprintf_Pass1(format, vto, endpos, ap_save))
 +    return -1;
 +
 +  end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()
 +                       created for us */
 +
 +  f = (char *)format;
 +  while(*f != '\0') {
 +    /* Format spec modifiers.  */
 +    int is_alt;
 +
 +    /* Width of a field.  */
 +    long width;
 +
 +    /* Precision of a field.  */
 +    long prec;
 +
 +    /* Decimal integer is negative.  */
 +    int is_neg;
 +
 +    /* Base of a number to be written.  */
 +    long base;
 +
 +    /* Integral values to be written.  */
 +    mp_uintmax_t num;
 +
 +    /* Used to convert negative in positive.  */
 +    mp_intmax_t signed_num;
 +
 +    char *w;
 +
 +    if(*f != '%') {
 +      /* This isn't a format spec, so write everything out until the next one
 +         OR end of string is reached.  */
 +      do {
 +        OUTCHAR(*f);
 +      } while(*++f && ('%' != *f));
 +      continue;
 +    }
 +
 +    ++f;
 +
 +    /* Check for "%%".  Note that although the ANSI standard lists
 +       '%' as a conversion specifier, it says "The complete format
 +       specification shall be `%%'," so we can avoid all the width
 +       and precision processing.  */
 +    if(*f == '%') {
 +      ++f;
 +      OUTCHAR('%');
 +      continue;
 +    }
 +
 +    /* If this is a positional parameter, the position must follow immediately
 +       after the %, thus create a %<num>$ sequence */
 +    param=dprintf_DollarString(f, &f);
 +
 +    if(!param)
 +      param = param_num;
 +    else
 +      --param;
 +
 +    param_num++; /* increase this always to allow "%2$s %1$s %s" and then the
 +                    third %s will pick the 3rd argument */
 +
 +    p = &vto[param];
 +
 +    /* pick up the specified width */
 +    if(p->flags & FLAGS_WIDTHPARAM) {
 +      width = (long)vto[p->width].data.num.as_signed;
 +      param_num++; /* since the width is extracted from a parameter, we
 +                      must skip that to get to the next one properly */
 +      if(width < 0) {
 +        /* "A negative field width is taken as a '-' flag followed by a
 +           positive field width." */
 +        width = -width;
 +        p->flags |= FLAGS_LEFT;
 +        p->flags &= ~FLAGS_PAD_NIL;
 +      }
 +    }
 +    else
 +      width = p->width;
 +
 +    /* pick up the specified precision */
 +    if(p->flags & FLAGS_PRECPARAM) {
 +      prec = (long)vto[p->precision].data.num.as_signed;
 +      param_num++; /* since the precision is extracted from a parameter, we
 +                      must skip that to get to the next one properly */
 +      if(prec < 0)
 +        /* "A negative precision is taken as if the precision were
 +           omitted." */
 +        prec = -1;
 +    }
 +    else if(p->flags & FLAGS_PREC)
 +      prec = p->precision;
 +    else
 +      prec = -1;
 +
 +    is_alt = (p->flags & FLAGS_ALT) ? 1 : 0;
 +
-     switch (p->type) {
++    switch(p->type) {
 +    case FORMAT_INT:
 +      num = p->data.num.as_unsigned;
 +      if(p->flags & FLAGS_CHAR) {
 +        /* Character.  */
 +        if(!(p->flags & FLAGS_LEFT))
 +          while(--width > 0)
 +            OUTCHAR(' ');
 +        OUTCHAR((char) num);
 +        if(p->flags & FLAGS_LEFT)
 +          while(--width > 0)
 +            OUTCHAR(' ');
 +        break;
 +      }
 +      if(p->flags & FLAGS_OCTAL) {
 +        /* Octal unsigned integer.  */
 +        base = 8;
 +        goto unsigned_number;
 +      }
 +      else if(p->flags & FLAGS_HEX) {
 +        /* Hexadecimal unsigned integer.  */
 +
 +        digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
 +        base = 16;
 +        goto unsigned_number;
 +      }
 +      else if(p->flags & FLAGS_UNSIGNED) {
 +        /* Decimal unsigned integer.  */
 +        base = 10;
 +        goto unsigned_number;
 +      }
 +
 +      /* Decimal integer.  */
 +      base = 10;
 +
 +      is_neg = (p->data.num.as_signed < (mp_intmax_t)0) ? 1 : 0;
 +      if(is_neg) {
 +        /* signed_num might fail to hold absolute negative minimum by 1 */
 +        signed_num = p->data.num.as_signed + (mp_intmax_t)1;
 +        signed_num = -signed_num;
 +        num = (mp_uintmax_t)signed_num;
 +        num += (mp_uintmax_t)1;
 +      }
 +
 +      goto number;
 +
 +      unsigned_number:
 +      /* Unsigned number of base BASE.  */
 +      is_neg = 0;
 +
 +      number:
 +      /* Number of base BASE.  */
 +
 +      /* Supply a default precision if none was given.  */
 +      if(prec == -1)
 +        prec = 1;
 +
 +      /* Put the number in WORK.  */
 +      w = workend;
 +      while(num > 0) {
 +        *w-- = digits[num % base];
 +        num /= base;
 +      }
 +      width -= (long)(workend - w);
 +      prec -= (long)(workend - w);
 +
 +      if(is_alt && base == 8 && prec <= 0) {
 +        *w-- = '0';
 +        --width;
 +      }
 +
 +      if(prec > 0) {
 +        width -= prec;
 +        while(prec-- > 0)
 +          *w-- = '0';
 +      }
 +
 +      if(is_alt && base == 16)
 +        width -= 2;
 +
 +      if(is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE))
 +        --width;
 +
 +      if(!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL))
 +        while(width-- > 0)
 +          OUTCHAR(' ');
 +
 +      if(is_neg)
 +        OUTCHAR('-');
 +      else if(p->flags & FLAGS_SHOWSIGN)
 +        OUTCHAR('+');
 +      else if(p->flags & FLAGS_SPACE)
 +        OUTCHAR(' ');
 +
 +      if(is_alt && base == 16) {
 +        OUTCHAR('0');
 +        if(p->flags & FLAGS_UPPER)
 +          OUTCHAR('X');
 +        else
 +          OUTCHAR('x');
 +      }
 +
 +      if(!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL))
 +        while(width-- > 0)
 +          OUTCHAR('0');
 +
 +      /* Write the number.  */
 +      while(++w <= workend) {
 +        OUTCHAR(*w);
 +      }
 +
 +      if(p->flags & FLAGS_LEFT)
 +        while(width-- > 0)
 +          OUTCHAR(' ');
 +      break;
 +
 +    case FORMAT_STRING:
 +            /* String.  */
 +      {
 +        static const char null[] = "(nil)";
 +        const char *str;
 +        size_t len;
 +
 +        str = (char *) p->data.str;
 +        if(str == NULL) {
 +          /* Write null[] if there's space.  */
 +          if(prec == -1 || prec >= (long) sizeof(null) - 1) {
 +            str = null;
 +            len = sizeof(null) - 1;
 +            /* Disable quotes around (nil) */
 +            p->flags &= (~FLAGS_ALT);
 +          }
 +          else {
 +            str = "";
 +            len = 0;
 +          }
 +        }
 +        else if(prec != -1)
 +          len = (size_t)prec;
 +        else
 +          len = strlen(str);
 +
 +        width -= (len > LONG_MAX) ? LONG_MAX : (long)len;
 +
 +        if(p->flags & FLAGS_ALT)
 +          OUTCHAR('"');
 +
 +        if(!(p->flags&FLAGS_LEFT))
 +          while(width-- > 0)
 +            OUTCHAR(' ');
 +
 +        while((len-- > 0) && *str)
 +          OUTCHAR(*str++);
 +        if(p->flags&FLAGS_LEFT)
 +          while(width-- > 0)
 +            OUTCHAR(' ');
 +
 +        if(p->flags & FLAGS_ALT)
 +          OUTCHAR('"');
 +      }
 +      break;
 +
 +    case FORMAT_PTR:
 +      /* Generic pointer.  */
 +      {
 +        void *ptr;
 +        ptr = (void *) p->data.ptr;
 +        if(ptr != NULL) {
 +          /* If the pointer is not NULL, write it as a %#x spec.  */
 +          base = 16;
 +          digits = (p->flags & FLAGS_UPPER)? upper_digits : lower_digits;
 +          is_alt = 1;
 +          num = (size_t) ptr;
 +          is_neg = 0;
 +          goto number;
 +        }
 +        else {
 +          /* Write "(nil)" for a nil pointer.  */
 +          static const char strnil[] = "(nil)";
 +          const char *point;
 +
 +          width -= (long)(sizeof(strnil) - 1);
 +          if(p->flags & FLAGS_LEFT)
 +            while(width-- > 0)
 +              OUTCHAR(' ');
 +          for(point = strnil; *point != '\0'; ++point)
 +            OUTCHAR(*point);
 +          if(! (p->flags & FLAGS_LEFT))
 +            while(width-- > 0)
 +              OUTCHAR(' ');
 +        }
 +      }
 +      break;
 +
 +    case FORMAT_DOUBLE:
 +      {
 +        char formatbuf[32]="%";
 +        char *fptr = &formatbuf[1];
 +        size_t left = sizeof(formatbuf)-strlen(formatbuf);
 +        int len;
 +
 +        width = -1;
 +        if(p->flags & FLAGS_WIDTH)
 +          width = p->width;
 +        else if(p->flags & FLAGS_WIDTHPARAM)
 +          width = (long)vto[p->width].data.num.as_signed;
 +
 +        prec = -1;
 +        if(p->flags & FLAGS_PREC)
 +          prec = p->precision;
 +        else if(p->flags & FLAGS_PRECPARAM)
 +          prec = (long)vto[p->precision].data.num.as_signed;
 +
 +        if(p->flags & FLAGS_LEFT)
 +          *fptr++ = '-';
 +        if(p->flags & FLAGS_SHOWSIGN)
 +          *fptr++ = '+';
 +        if(p->flags & FLAGS_SPACE)
 +          *fptr++ = ' ';
 +        if(p->flags & FLAGS_ALT)
 +          *fptr++ = '#';
 +
 +        *fptr = 0;
 +
 +        if(width >= 0) {
++          if(width >= (long)sizeof(work))
++            width = sizeof(work)-1;
 +          /* RECURSIVE USAGE */
 +          len = curl_msnprintf(fptr, left, "%ld", width);
 +          fptr += len;
 +          left -= len;
 +        }
 +        if(prec >= 0) {
++          /* for each digit in the integer part, we can have one less
++             precision */
++          size_t maxprec = sizeof(work) - 2;
++          double val = p->data.dnum;
++          while(val >= 10.0) {
++            val /= 10;
++            maxprec--;
++          }
++
++          if(prec > (long)maxprec)
++            prec = (long)maxprec-1;
 +          /* RECURSIVE USAGE */
 +          len = curl_msnprintf(fptr, left, ".%ld", prec);
 +          fptr += len;
 +        }
 +        if(p->flags & FLAGS_LONG)
 +          *fptr++ = 'l';
 +
 +        if(p->flags & FLAGS_FLOATE)
 +          *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'E':'e');
 +        else if(p->flags & FLAGS_FLOATG)
 +          *fptr++ = (char)((p->flags & FLAGS_UPPER) ? 'G' : 'g');
 +        else
 +          *fptr++ = 'f';
 +
 +        *fptr = 0; /* and a final zero termination */
 +
 +        /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
 +           output characters */
 +        (sprintf)(work, formatbuf, p->data.dnum);
- 
++#ifdef CURLDEBUG
++        assert(strlen(work) <= sizeof(work));
++#endif
 +        for(fptr=work; *fptr; fptr++)
 +          OUTCHAR(*fptr);
 +      }
 +      break;
 +
 +    case FORMAT_INTPTR:
 +      /* Answer the count of characters written.  */
 +#ifdef HAVE_LONG_LONG_TYPE
 +      if(p->flags & FLAGS_LONGLONG)
 +        *(LONG_LONG_TYPE *) p->data.ptr = (LONG_LONG_TYPE)done;
 +      else
 +#endif
 +        if(p->flags & FLAGS_LONG)
 +          *(long *) p->data.ptr = (long)done;
 +      else if(!(p->flags & FLAGS_SHORT))
 +        *(int *) p->data.ptr = (int)done;
 +      else
 +        *(short *) p->data.ptr = (short)done;
 +      break;
 +
 +    default:
 +      break;
 +    }
 +    f = *end++; /* goto end of %-code */
 +
 +  }
 +  return done;
 +}
 +
 +/* fputc() look-alike */
 +static int addbyter(int output, FILE *data)
 +{
 +  struct nsprintf *infop=(struct nsprintf *)data;
 +  unsigned char outc = (unsigned char)output;
 +
 +  if(infop->length < infop->max) {
 +    /* only do this if we haven't reached max length yet */
 +    infop->buffer[0] = outc; /* store */
 +    infop->buffer++; /* increase pointer */
 +    infop->length++; /* we are now one byte larger */
 +    return outc;     /* fputc() returns like this on success */
 +  }
 +  return -1;
 +}
 +
 +int curl_mvsnprintf(char *buffer, size_t maxlength, const char *format,
 +                    va_list ap_save)
 +{
 +  int retcode;
 +  struct nsprintf info;
 +
 +  info.buffer = buffer;
 +  info.length = 0;
 +  info.max = maxlength;
 +
 +  retcode = dprintf_formatf(&info, addbyter, format, ap_save);
 +  if((retcode != -1) && info.max) {
 +    /* we terminate this with a zero byte */
 +    if(info.max == info.length)
 +      /* we're at maximum, scrap the last letter */
 +      info.buffer[-1] = 0;
 +    else
 +      info.buffer[0] = 0;
 +  }
 +  return retcode;
 +}
 +
 +int curl_msnprintf(char *buffer, size_t maxlength, const char *format, ...)
 +{
 +  int retcode;
 +  va_list ap_save; /* argument pointer */
 +  va_start(ap_save, format);
 +  retcode = curl_mvsnprintf(buffer, maxlength, format, ap_save);
 +  va_end(ap_save);
 +  return retcode;
 +}
 +
 +/* fputc() look-alike */
 +static int alloc_addbyter(int output, FILE *data)
 +{
 +  struct asprintf *infop=(struct asprintf *)data;
 +  unsigned char outc = (unsigned char)output;
 +
 +  if(!infop->buffer) {
 +    infop->buffer = malloc(32);
 +    if(!infop->buffer) {
 +      infop->fail = 1;
 +      return -1; /* fail */
 +    }
 +    infop->alloc = 32;
 +    infop->len =0;
 +  }
 +  else if(infop->len+1 >= infop->alloc) {
 +    char *newptr = NULL;
 +    size_t newsize = infop->alloc*2;
 +
 +    /* detect wrap-around or other overflow problems */
 +    if(newsize > infop->alloc)
 +      newptr = realloc(infop->buffer, newsize);
 +
 +    if(!newptr) {
 +      infop->fail = 1;
 +      return -1; /* fail */
 +    }
 +    infop->buffer = newptr;
 +    infop->alloc = newsize;
 +  }
 +
 +  infop->buffer[ infop->len ] = outc;
 +
 +  infop->len++;
 +
 +  return outc; /* fputc() returns like this on success */
 +}
 +
 +char *curl_maprintf(const char *format, ...)
 +{
 +  va_list ap_save; /* argument pointer */
 +  int retcode;
 +  struct asprintf info;
 +
 +  info.buffer = NULL;
 +  info.len = 0;
 +  info.alloc = 0;
 +  info.fail = 0;
 +
 +  va_start(ap_save, format);
 +  retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
 +  va_end(ap_save);
 +  if((-1 == retcode) || info.fail) {
 +    if(info.alloc)
 +      free(info.buffer);
 +    return NULL;
 +  }
 +  if(info.alloc) {
 +    info.buffer[info.len] = 0; /* we terminate this with a zero byte */
 +    return info.buffer;
 +  }
 +  else
 +    return strdup("");
 +}
 +
 +char *curl_mvaprintf(const char *format, va_list ap_save)
 +{
 +  int retcode;
 +  struct asprintf info;
 +
 +  info.buffer = NULL;
 +  info.len = 0;
 +  info.alloc = 0;
 +  info.fail = 0;
 +
 +  retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
 +  if((-1 == retcode) || info.fail) {
 +    if(info.alloc)
 +      free(info.buffer);
 +    return NULL;
 +  }
 +
 +  if(info.alloc) {
 +    info.buffer[info.len] = 0; /* we terminate this with a zero byte */
 +    return info.buffer;
 +  }
 +  else
 +    return strdup("");
 +}
 +
 +static int storebuffer(int output, FILE *data)
 +{
 +  char **buffer = (char **)data;
 +  unsigned char outc = (unsigned char)output;
 +  **buffer = outc;
 +  (*buffer)++;
 +  return outc; /* act like fputc() ! */
 +}
 +
 +int curl_msprintf(char *buffer, const char *format, ...)
 +{
 +  va_list ap_save; /* argument pointer */
 +  int retcode;
 +  va_start(ap_save, format);
 +  retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
 +  va_end(ap_save);
 +  *buffer=0; /* we terminate this with a zero byte */
 +  return retcode;
 +}
 +
 +int curl_mprintf(const char *format, ...)
 +{
 +  int retcode;
 +  va_list ap_save; /* argument pointer */
 +  va_start(ap_save, format);
 +
 +  retcode = dprintf_formatf(stdout, fputc, format, ap_save);
 +  va_end(ap_save);
 +  return retcode;
 +}
 +
 +int curl_mfprintf(FILE *whereto, const char *format, ...)
 +{
 +  int retcode;
 +  va_list ap_save; /* argument pointer */
 +  va_start(ap_save, format);
 +  retcode = dprintf_formatf(whereto, fputc, format, ap_save);
 +  va_end(ap_save);
 +  return retcode;
 +}
 +
 +int curl_mvsprintf(char *buffer, const char *format, va_list ap_save)
 +{
 +  int retcode;
 +  retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
 +  *buffer=0; /* we terminate this with a zero byte */
 +  return retcode;
 +}
 +
 +int curl_mvprintf(const char *format, va_list ap_save)
 +{
 +  return dprintf_formatf(stdout, fputc, format, ap_save);
 +}
 +
 +int curl_mvfprintf(FILE *whereto, const char *format, va_list ap_save)
 +{
 +  return dprintf_formatf(whereto, fputc, format, ap_save);
 +}
diff --cc Utilities/cmcurl/lib/rand.c
index 0000000,a51951c..a51951c
mode 000000,100644..100644
--- a/Utilities/cmcurl/lib/rand.c
+++ b/Utilities/cmcurl/lib/rand.c
diff --cc Utilities/cmcurl/lib/select.c
index d5caa70,0000000..6bb0ab1
mode 100644,000000..100644
--- a/Utilities/cmcurl/lib/select.c
+++ b/Utilities/cmcurl/lib/select.c
@@@ -1,583 -1,0 +1,583 @@@
 +/***************************************************************************
 + *                                  _   _ ____  _
 + *  Project                     ___| | | |  _ \| |
 + *                             / __| | | | |_) | |
 + *                            | (__| |_| |  _ <| |___
 + *                             \___|\___/|_| \_\_____|
 + *
 + * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
 + *
 + * This software is licensed as described in the file COPYING, which
 + * you should have received as part of this distribution. The terms
 + * are also available at https://curl.haxx.se/docs/copyright.html.
 + *
 + * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 + * copies of the Software, and permit persons to whom the Software is
 + * furnished to do so, under the terms of the COPYING file.
 + *
 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 + * KIND, either express or implied.
 + *
 + ***************************************************************************/
 +
 +#include "curl_setup.h"
 +
 +#ifdef HAVE_SYS_SELECT_H
 +#include <sys/select.h>
 +#endif
 +
 +#if !defined(HAVE_SELECT) && !defined(HAVE_POLL_FINE)
 +#error "We can't compile without select() or poll() support."
 +#endif
 +
 +#if defined(__BEOS__)
 +/* BeOS has FD_SET defined in socket.h */
 +#include <socket.h>
 +#endif
 +
 +#ifdef MSDOS
 +#include <dos.h>  /* delay() */
 +#endif
 +
 +#ifdef __VXWORKS__
 +#include <strings.h>  /* bzero() in FD_SET */
 +#endif
 +
 +#include <curl/curl.h>
 +
 +#include "urldata.h"
 +#include "connect.h"
 +#include "select.h"
 +#include "warnless.h"
 +
 +/* Convenience local macros */
 +#define ELAPSED_MS()  (int)curlx_tvdiff(curlx_tvnow(), initial_tv)
 +
 +int Curl_ack_eintr = 0;
 +#define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR)
 +
 +/*
 + * Internal function used for waiting a specific amount of ms
 + * in Curl_socket_check() and Curl_poll() when no file descriptor
 + * is provided to wait on, just being used to delay execution.
 + * WinSock select() and poll() timeout mechanisms need a valid
 + * socket descriptor in a not null file descriptor set to work.
 + * Waiting indefinitely with this function is not allowed, a
 + * zero or negative timeout value will return immediately.
 + * Timeout resolution, accuracy, as well as maximum supported
 + * value is system dependent, neither factor is a citical issue
 + * for the intended use of this function in the library.
 + *
 + * Return values:
 + *   -1 = system call error, invalid timeout value, or interrupted
 + *    0 = specified timeout has elapsed
 + */
 +int Curl_wait_ms(int timeout_ms)
 +{
 +#if !defined(MSDOS) && !defined(USE_WINSOCK)
 +#ifndef HAVE_POLL_FINE
 +  struct timeval pending_tv;
 +#endif
 +  struct timeval initial_tv;
 +  int pending_ms;
 +  int error;
 +#endif
 +  int r = 0;
 +
 +  if(!timeout_ms)
 +    return 0;
 +  if(timeout_ms < 0) {
 +    SET_SOCKERRNO(EINVAL);
 +    return -1;
 +  }
 +#if defined(MSDOS)
 +  delay(timeout_ms);
 +#elif defined(USE_WINSOCK)
 +  Sleep(timeout_ms);
 +#else
 +  pending_ms = timeout_ms;
 +  initial_tv = curlx_tvnow();
 +  do {
 +#if defined(HAVE_POLL_FINE)
 +    r = poll(NULL, 0, pending_ms);
 +#else
 +    pending_tv.tv_sec = pending_ms / 1000;
 +    pending_tv.tv_usec = (pending_ms % 1000) * 1000;
 +    r = select(0, NULL, NULL, NULL, &pending_tv);
 +#endif /* HAVE_POLL_FINE */
 +    if(r != -1)
 +      break;
 +    error = SOCKERRNO;
 +    if(error && ERROR_NOT_EINTR(error))
 +      break;
 +    pending_ms = timeout_ms - ELAPSED_MS();
 +    if(pending_ms <= 0) {
 +      r = 0;  /* Simulate a "call timed out" case */
 +      break;
 +    }
 +  } while(r == -1);
 +#endif /* USE_WINSOCK */
 +  if(r)
 +    r = -1;
 +  return r;
 +}
 +
 +/*
 + * Wait for read or write events on a set of file descriptors. It uses poll()
 + * when a fine poll() is available, in order to avoid limits with FD_SETSIZE,
 + * otherwise select() is used.  An error is returned if select() is being used
 + * and a file descriptor is too large for FD_SETSIZE.
 + *
 + * A negative timeout value makes this function wait indefinitely,
 + * unles no valid file descriptor is given, when this happens the
 + * negative timeout is ignored and the function times out immediately.
 + *
 + * Return values:
 + *   -1 = system call error or fd >= FD_SETSIZE
 + *    0 = timeout
 + *    [bitmask] = action as described below
 + *
 + * CURL_CSELECT_IN - first socket is readable
 + * CURL_CSELECT_IN2 - second socket is readable
 + * CURL_CSELECT_OUT - write socket is writable
 + * CURL_CSELECT_ERR - an error condition occurred
 + */
 +int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
 +                      curl_socket_t readfd1,
 +                      curl_socket_t writefd, /* socket to write to */
-                       long timeout_ms)       /* milliseconds to wait */
++                      time_t timeout_ms)     /* milliseconds to wait */
 +{
 +#ifdef HAVE_POLL_FINE
 +  struct pollfd pfd[3];
 +  int num;
 +#else
 +  struct timeval pending_tv;
 +  struct timeval *ptimeout;
 +  fd_set fds_read;
 +  fd_set fds_write;
 +  fd_set fds_err;
 +  curl_socket_t maxfd;
 +#endif
 +  struct timeval initial_tv = {0, 0};
 +  int pending_ms = 0;
 +  int error;
 +  int r;
 +  int ret;
 +
 +#if SIZEOF_LONG != SIZEOF_INT
 +  /* wrap-around precaution */
 +  if(timeout_ms >= INT_MAX)
 +    timeout_ms = INT_MAX;
 +#endif
 +
 +  if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
 +     (writefd == CURL_SOCKET_BAD)) {
 +    /* no sockets, just wait */
 +    r = Curl_wait_ms((int)timeout_ms);
 +    return r;
 +  }
 +
 +  /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
 +     time in this function does not need to be measured. This happens
 +     when function is called with a zero timeout or a negative timeout
 +     value indicating a blocking call should be performed. */
 +
 +  if(timeout_ms > 0) {
 +    pending_ms = (int)timeout_ms;
 +    initial_tv = curlx_tvnow();
 +  }
 +
 +#ifdef HAVE_POLL_FINE
 +
 +  num = 0;
 +  if(readfd0 != CURL_SOCKET_BAD) {
 +    pfd[num].fd = readfd0;
 +    pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
 +    pfd[num].revents = 0;
 +    num++;
 +  }
 +  if(readfd1 != CURL_SOCKET_BAD) {
 +    pfd[num].fd = readfd1;
 +    pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
 +    pfd[num].revents = 0;
 +    num++;
 +  }
 +  if(writefd != CURL_SOCKET_BAD) {
 +    pfd[num].fd = writefd;
 +    pfd[num].events = POLLWRNORM|POLLOUT;
 +    pfd[num].revents = 0;
 +    num++;
 +  }
 +
 +  do {
 +    if(timeout_ms < 0)
 +      pending_ms = -1;
 +    else if(!timeout_ms)
 +      pending_ms = 0;
 +    r = poll(pfd, num, pending_ms);
 +    if(r != -1)
 +      break;
 +    error = SOCKERRNO;
 +    if(error && ERROR_NOT_EINTR(error))
 +      break;
 +    if(timeout_ms > 0) {
 +      pending_ms = (int)(timeout_ms - ELAPSED_MS());
 +      if(pending_ms <= 0) {
 +        r = 0;  /* Simulate a "call timed out" case */
 +        break;
 +      }
 +    }
 +  } while(r == -1);
 +
 +  if(r < 0)
 +    return -1;
 +  if(r == 0)
 +    return 0;
 +
 +  ret = 0;
 +  num = 0;
 +  if(readfd0 != CURL_SOCKET_BAD) {
 +    if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
 +      ret |= CURL_CSELECT_IN;
 +    if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
 +      ret |= CURL_CSELECT_ERR;
 +    num++;
 +  }
 +  if(readfd1 != CURL_SOCKET_BAD) {
 +    if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP))
 +      ret |= CURL_CSELECT_IN2;
 +    if(pfd[num].revents & (POLLRDBAND|POLLPRI|POLLNVAL))
 +      ret |= CURL_CSELECT_ERR;
 +    num++;
 +  }
 +  if(writefd != CURL_SOCKET_BAD) {
 +    if(pfd[num].revents & (POLLWRNORM|POLLOUT))
 +      ret |= CURL_CSELECT_OUT;
 +    if(pfd[num].revents & (POLLERR|POLLHUP|POLLNVAL))
 +      ret |= CURL_CSELECT_ERR;
 +  }
 +
 +  return ret;
 +
 +#else  /* HAVE_POLL_FINE */
 +
 +  FD_ZERO(&fds_err);
 +  maxfd = (curl_socket_t)-1;
 +
 +  FD_ZERO(&fds_read);
 +  if(readfd0 != CURL_SOCKET_BAD) {
 +    VERIFY_SOCK(readfd0);
 +    FD_SET(readfd0, &fds_read);
 +    FD_SET(readfd0, &fds_err);
 +    maxfd = readfd0;
 +  }
 +  if(readfd1 != CURL_SOCKET_BAD) {
 +    VERIFY_SOCK(readfd1);
 +    FD_SET(readfd1, &fds_read);
 +    FD_SET(readfd1, &fds_err);
 +    if(readfd1 > maxfd)
 +      maxfd = readfd1;
 +  }
 +
 +  FD_ZERO(&fds_write);
 +  if(writefd != CURL_SOCKET_BAD) {
 +    VERIFY_SOCK(writefd);
 +    FD_SET(writefd, &fds_write);
 +    FD_SET(writefd, &fds_err);
 +    if(writefd > maxfd)
 +      maxfd = writefd;
 +  }
 +
 +  ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
 +
 +  do {
 +    if(timeout_ms > 0) {
 +      pending_tv.tv_sec = pending_ms / 1000;
 +      pending_tv.tv_usec = (pending_ms % 1000) * 1000;
 +    }
 +    else if(!timeout_ms) {
 +      pending_tv.tv_sec = 0;
 +      pending_tv.tv_usec = 0;
 +    }
 +
 +    /* WinSock select() must not be called with an fd_set that contains zero
 +       fd flags, or it will return WSAEINVAL.  But, it also can't be called
 +       with no fd_sets at all!  From the documentation:
 +
 +         Any two of the parameters, readfds, writefds, or exceptfds, can be
 +         given as null. At least one must be non-null, and any non-null
 +         descriptor set must contain at least one handle to a socket.
 +
 +       We know that we have at least one bit set in at least two fd_sets in
 +       this case, but we may have no bits set in either fds_read or fd_write,
 +       so check for that and handle it.  Luckily, with WinSock, we can _also_
 +       ask how many bits are set on an fd_set.
 +
 +       It is unclear why WinSock doesn't just handle this for us instead of
 +       calling this an error.
 +
 +       Note also that WinSock ignores the first argument, so we don't worry
 +       about the fact that maxfd is computed incorrectly with WinSock (since
 +       curl_socket_t is unsigned in such cases and thus -1 is the largest
 +       value).
 +    */
 +#ifdef USE_WINSOCK
 +    r = select((int)maxfd + 1,
 +               fds_read.fd_count ? &fds_read : NULL,
 +               fds_write.fd_count ? &fds_write : NULL,
 +               &fds_err, ptimeout);
 +#else
 +    r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
 +#endif
 +
 +    if(r != -1)
 +      break;
 +    error = SOCKERRNO;
 +    if(error && ERROR_NOT_EINTR(error))
 +      break;
 +    if(timeout_ms > 0) {
 +      pending_ms = (int)(timeout_ms - ELAPSED_MS());
 +      if(pending_ms <= 0) {
 +        r = 0;  /* Simulate a "call timed out" case */
 +        break;
 +      }
 +    }
 +  } while(r == -1);
 +
 +  if(r < 0)
 +    return -1;
 +  if(r == 0)
 +    return 0;
 +
 +  ret = 0;
 +  if(readfd0 != CURL_SOCKET_BAD) {
 +    if(FD_ISSET(readfd0, &fds_read))
 +      ret |= CURL_CSELECT_IN;
 +    if(FD_ISSET(readfd0, &fds_err))
 +      ret |= CURL_CSELECT_ERR;
 +  }
 +  if(readfd1 != CURL_SOCKET_BAD) {
 +    if(FD_ISSET(readfd1, &fds_read))
 +      ret |= CURL_CSELECT_IN2;
 +    if(FD_ISSET(readfd1, &fds_err))
 +      ret |= CURL_CSELECT_ERR;
 +  }
 +  if(writefd != CURL_SOCKET_BAD) {
 +    if(FD_ISSET(writefd, &fds_write))
 +      ret |= CURL_CSELECT_OUT;
 +    if(FD_ISSET(writefd, &fds_err))
 +      ret |= CURL_CSELECT_ERR;
 +  }
 +
 +  return ret;
 +
 +#endif  /* HAVE_POLL_FINE */
 +
 +}
 +
 +/*
 + * This is a wrapper around poll().  If poll() does not exist, then
 + * select() is used instead.  An error is returned if select() is
 + * being used and a file descriptor is too large for FD_SETSIZE.
 + * A negative timeout value makes this function wait indefinitely,
 + * unles no valid file descriptor is given, when this happens the
 + * negative timeout is ignored and the function times out immediately.
 + *
 + * Return values:
 + *   -1 = system call error or fd >= FD_SETSIZE
 + *    0 = timeout
 + *    N = number of structures with non zero revent fields
 + */
 +int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
 +{
 +#ifndef HAVE_POLL_FINE
 +  struct timeval pending_tv;
 +  struct timeval *ptimeout;
 +  fd_set fds_read;
 +  fd_set fds_write;
 +  fd_set fds_err;
 +  curl_socket_t maxfd;
 +#endif
 +  struct timeval initial_tv = {0, 0};
 +  bool fds_none = TRUE;
 +  unsigned int i;
 +  int pending_ms = 0;
 +  int error;
 +  int r;
 +
 +  if(ufds) {
 +    for(i = 0; i < nfds; i++) {
 +      if(ufds[i].fd != CURL_SOCKET_BAD) {
 +        fds_none = FALSE;
 +        break;
 +      }
 +    }
 +  }
 +  if(fds_none) {
 +    r = Curl_wait_ms(timeout_ms);
 +    return r;
 +  }
 +
 +  /* Avoid initial timestamp, avoid curlx_tvnow() call, when elapsed
 +     time in this function does not need to be measured. This happens
 +     when function is called with a zero timeout or a negative timeout
 +     value indicating a blocking call should be performed. */
 +
 +  if(timeout_ms > 0) {
 +    pending_ms = timeout_ms;
 +    initial_tv = curlx_tvnow();
 +  }
 +
 +#ifdef HAVE_POLL_FINE
 +
 +  do {
 +    if(timeout_ms < 0)
 +      pending_ms = -1;
 +    else if(!timeout_ms)
 +      pending_ms = 0;
 +    r = poll(ufds, nfds, pending_ms);
 +    if(r != -1)
 +      break;
 +    error = SOCKERRNO;
 +    if(error && ERROR_NOT_EINTR(error))
 +      break;
 +    if(timeout_ms > 0) {
 +      pending_ms = (int)(timeout_ms - ELAPSED_MS());
 +      if(pending_ms <= 0) {
 +        r = 0;  /* Simulate a "call timed out" case */
 +        break;
 +      }
 +    }
 +  } while(r == -1);
 +
 +  if(r < 0)
 +    return -1;
 +  if(r == 0)
 +    return 0;
 +
 +  for(i = 0; i < nfds; i++) {
 +    if(ufds[i].fd == CURL_SOCKET_BAD)
 +      continue;
 +    if(ufds[i].revents & POLLHUP)
 +      ufds[i].revents |= POLLIN;
 +    if(ufds[i].revents & POLLERR)
 +      ufds[i].revents |= (POLLIN|POLLOUT);
 +  }
 +
 +#else  /* HAVE_POLL_FINE */
 +
 +  FD_ZERO(&fds_read);
 +  FD_ZERO(&fds_write);
 +  FD_ZERO(&fds_err);
 +  maxfd = (curl_socket_t)-1;
 +
 +  for(i = 0; i < nfds; i++) {
 +    ufds[i].revents = 0;
 +    if(ufds[i].fd == CURL_SOCKET_BAD)
 +      continue;
 +    VERIFY_SOCK(ufds[i].fd);
 +    if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI|
 +                          POLLRDNORM|POLLWRNORM|POLLRDBAND)) {
 +      if(ufds[i].fd > maxfd)
 +        maxfd = ufds[i].fd;
 +      if(ufds[i].events & (POLLRDNORM|POLLIN))
 +        FD_SET(ufds[i].fd, &fds_read);
 +      if(ufds[i].events & (POLLWRNORM|POLLOUT))
 +        FD_SET(ufds[i].fd, &fds_write);
 +      if(ufds[i].events & (POLLRDBAND|POLLPRI))
 +        FD_SET(ufds[i].fd, &fds_err);
 +    }
 +  }
 +
 +#ifdef USE_WINSOCK
 +  /* WinSock select() can't handle zero events.  See the comment about this in
 +     Curl_check_socket(). */
 +  if(fds_read.fd_count == 0 && fds_write.fd_count == 0
 +     && fds_err.fd_count == 0) {
 +    r = Curl_wait_ms(timeout_ms);
 +    return r;
 +  }
 +#endif
 +
 +  ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
 +
 +  do {
 +    if(timeout_ms > 0) {
 +      pending_tv.tv_sec = pending_ms / 1000;
 +      pending_tv.tv_usec = (pending_ms % 1000) * 1000;
 +    }
 +    else if(!timeout_ms) {
 +      pending_tv.tv_sec = 0;
 +      pending_tv.tv_usec = 0;
 +    }
 +
 +#ifdef USE_WINSOCK
 +    r = select((int)maxfd + 1,
 +               /* WinSock select() can't handle fd_sets with zero bits set, so
 +                  don't give it such arguments.  See the comment about this in
 +                  Curl_check_socket().
 +               */
 +               fds_read.fd_count ? &fds_read : NULL,
 +               fds_write.fd_count ? &fds_write : NULL,
 +               fds_err.fd_count ? &fds_err : NULL, ptimeout);
 +#else
 +    r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
 +#endif
 +    if(r != -1)
 +      break;
 +    error = SOCKERRNO;
 +    if(error && ERROR_NOT_EINTR(error))
 +      break;
 +    if(timeout_ms > 0) {
 +      pending_ms = timeout_ms - ELAPSED_MS();
 +      if(pending_ms <= 0) {
 +        r = 0;  /* Simulate a "call timed out" case */
 +        break;
 +      }
 +    }
 +  } while(r == -1);
 +
 +  if(r < 0)
 +    return -1;
 +  if(r == 0)
 +    return 0;
 +
 +  r = 0;
 +  for(i = 0; i < nfds; i++) {
 +    ufds[i].revents = 0;
 +    if(ufds[i].fd == CURL_SOCKET_BAD)
 +      continue;
 +    if(FD_ISSET(ufds[i].fd, &fds_read))
 +      ufds[i].revents |= POLLIN;
 +    if(FD_ISSET(ufds[i].fd, &fds_write))
 +      ufds[i].revents |= POLLOUT;
 +    if(FD_ISSET(ufds[i].fd, &fds_err))
 +      ufds[i].revents |= POLLPRI;
 +    if(ufds[i].revents != 0)
 +      r++;
 +  }
 +
 +#endif  /* HAVE_POLL_FINE */
 +
 +  return r;
 +}
 +
 +#ifdef TPF
 +/*
 + * This is a replacement for select() on the TPF platform.
 + * It is used whenever libcurl calls select().
 + * The call below to tpf_process_signals() is required because
 + * TPF's select calls are not signal interruptible.
 + *
 + * Return values are the same as select's.
 + */
 +int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
 +                       fd_set* excepts, struct timeval* tv)
 +{
 +   int rc;
 +
 +   rc = tpf_select_bsd(maxfds, reads, writes, excepts, tv);
 +   tpf_process_signals();
 +   return rc;
 +}
 +#endif /* TPF */

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4cc2908fdaaf1ab8afe5c2ae5dbb3401859a9aab
commit 4cc2908fdaaf1ab8afe5c2ae5dbb3401859a9aab
Author:     Curl Upstream <curl-library at cool.haxx.se>
AuthorDate: Thu Dec 22 16:41:14 2016 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Feb 7 11:37:30 2017 -0500

    curl 2016-12-22 (44b9b4d4)
    
    Code extracted from:
    
        https://github.com/curl/curl.git
    
    at commit 44b9b4d4f56d6f6de92c89636994c03984e9cd01 (curl-7_52_1).

diff --git a/CMake/OtherTests.cmake b/CMake/OtherTests.cmake
index d599498..3b203c5 100644
--- a/CMake/OtherTests.cmake
+++ b/CMake/OtherTests.cmake
@@ -179,17 +179,20 @@ int main(void) {
 
 
 include(CheckCSourceRuns)
-set(CMAKE_REQUIRED_FLAGS)
-if(HAVE_SYS_POLL_H)
-  set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
-endif(HAVE_SYS_POLL_H)
-check_c_source_runs("
-  #ifdef HAVE_SYS_POLL_H
-  #  include <sys/poll.h>
-  #endif
-  int main(void) {
-    return poll((void *)0, 0, 10 /*ms*/);
-  }" HAVE_POLL_FINE)
+# See HAVE_POLL in CMakeLists.txt for why poll is disabled on macOS
+if(NOT APPLE)
+  set(CMAKE_REQUIRED_FLAGS)
+  if(HAVE_SYS_POLL_H)
+    set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
+  endif(HAVE_SYS_POLL_H)
+  check_c_source_runs("
+    #ifdef HAVE_SYS_POLL_H
+    #  include <sys/poll.h>
+    #endif
+    int main(void) {
+      return poll((void *)0, 0, 10 /*ms*/);
+    }" HAVE_POLL_FINE)
+endif()
 
 set(HAVE_SIG_ATOMIC_T 1)
 set(CMAKE_REQUIRED_FLAGS)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ed3f38a..a6a7368 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -742,7 +742,11 @@ endif()
 
 check_symbol_exists(basename      "${CURL_INCLUDES}" HAVE_BASENAME)
 check_symbol_exists(socket        "${CURL_INCLUDES}" HAVE_SOCKET)
-check_symbol_exists(poll          "${CURL_INCLUDES}" HAVE_POLL)
+# poll on macOS is unreliable, it first did not exist, then was broken until
+# fixed in 10.9 only to break again in 10.12.
+if(NOT APPLE)
+  check_symbol_exists(poll        "${CURL_INCLUDES}" HAVE_POLL)
+endif()
 check_symbol_exists(select        "${CURL_INCLUDES}" HAVE_SELECT)
 check_symbol_exists(strdup        "${CURL_INCLUDES}" HAVE_STRDUP)
 check_symbol_exists(strstr        "${CURL_INCLUDES}" HAVE_STRSTR)
diff --git a/include/curl/curl.h b/include/curl/curl.h
index 9c09cb9..5b4ae46 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -143,7 +143,7 @@ struct curl_httppost {
   char *buffer;                     /* pointer to allocated buffer contents */
   long bufferlength;                /* length of buffer field */
   char *contenttype;                /* Content-Type */
-  struct curl_slist* contentheader; /* list of extra headers for this form */
+  struct curl_slist *contentheader; /* list of extra headers for this form */
   struct curl_httppost *more;       /* if one field name has more than one
                                        file, this link should link to following
                                        files */
@@ -270,7 +270,7 @@ struct curl_fileinfo {
   unsigned int flags;
 
   /* used internally */
-  char * b_data;
+  char *b_data;
   size_t b_size;
   size_t b_used;
 };
@@ -640,6 +640,7 @@ typedef enum {
                            CONNECT HTTP/1.1 */
   CURLPROXY_HTTP_1_0 = 1,   /* added in 7.19.4, force to use CONNECT
                                HTTP/1.0  */
+  CURLPROXY_HTTPS = 2, /* added in 7.52.0 */
   CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already
                            in 7.10 */
   CURLPROXY_SOCKS5 = 5, /* added in 7.10 */
@@ -1206,7 +1207,8 @@ typedef enum {
   CINIT(SHARE, OBJECTPOINT, 100),
 
   /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
-     CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */
+     CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and
+     CURLPROXY_SOCKS5. */
   CINIT(PROXYTYPE, LONG, 101),
 
   /* Set the Accept-Encoding string. Use this to tell a server you would like
@@ -1704,6 +1706,70 @@ typedef enum {
    * HTTP status code >= 300 */
   CINIT(KEEP_SENDING_ON_ERROR, LONG, 245),
 
+  /* The CApath or CAfile used to validate the proxy certificate
+     this option is used only if PROXY_SSL_VERIFYPEER is true */
+  CINIT(PROXY_CAINFO, STRINGPOINT, 246),
+
+  /* The CApath directory used to validate the proxy certificate
+     this option is used only if PROXY_SSL_VERIFYPEER is true */
+  CINIT(PROXY_CAPATH, STRINGPOINT, 247),
+
+  /* Set if we should verify the proxy in ssl handshake,
+     set 1 to verify. */
+  CINIT(PROXY_SSL_VERIFYPEER, LONG, 248),
+
+  /* Set if we should verify the Common name from the proxy certificate in ssl
+   * handshake, set 1 to check existence, 2 to ensure that it matches
+   * the provided hostname. */
+  CINIT(PROXY_SSL_VERIFYHOST, LONG, 249),
+
+  /* What version to specifically try to use for proxy.
+     See CURL_SSLVERSION defines below. */
+  CINIT(PROXY_SSLVERSION, LONG, 250),
+
+  /* Set a username for authenticated TLS for proxy */
+  CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251),
+
+  /* Set a password for authenticated TLS for proxy */
+  CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252),
+
+  /* Set authentication type for authenticated TLS for proxy */
+  CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253),
+
+  /* name of the file keeping your private SSL-certificate for proxy */
+  CINIT(PROXY_SSLCERT, STRINGPOINT, 254),
+
+  /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for
+     proxy */
+  CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255),
+
+  /* name of the file keeping your private SSL-key for proxy */
+  CINIT(PROXY_SSLKEY, STRINGPOINT, 256),
+
+  /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for
+     proxy */
+  CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257),
+
+  /* password for the SSL private key for proxy */
+  CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258),
+
+  /* Specify which SSL ciphers to use for proxy */
+  CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259),
+
+  /* CRL file for proxy */
+  CINIT(PROXY_CRLFILE, STRINGPOINT, 260),
+
+  /* Enable/disable specific SSL features with a bitmask for proxy, see
+     CURLSSLOPT_* */
+  CINIT(PROXY_SSL_OPTIONS, LONG, 261),
+
+  /* Name of pre proxy to use. */
+  CINIT(PRE_PROXY, STRINGPOINT, 262),
+
+  /* The public key in DER form used to validate the proxy public key
+     this option is used only if PROXY_SSL_VERIFYPEER is true */
+  CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
@@ -1805,6 +1871,7 @@ enum {
   CURL_SSLVERSION_TLSv1_0,
   CURL_SSLVERSION_TLSv1_1,
   CURL_SSLVERSION_TLSv1_2,
+  CURL_SSLVERSION_TLSv1_3,
 
   CURL_SSLVERSION_LAST /* never use, keep last */
 };
@@ -1839,7 +1906,10 @@ typedef enum {
 
 
 /* curl_strequal() and curl_strnequal() are subject for removal in a future
-   libcurl, see lib/README.curlx for details */
+   libcurl, see lib/README.curlx for details
+
+   !checksrc! disable SPACEBEFOREPAREN 2
+*/
 CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
 CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
 
@@ -2209,9 +2279,12 @@ typedef enum {
   CURLINFO_ACTIVESOCKET     = CURLINFO_SOCKET + 44,
   CURLINFO_TLS_SSL_PTR      = CURLINFO_SLIST  + 45,
   CURLINFO_HTTP_VERSION     = CURLINFO_LONG   + 46,
+  CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
+  CURLINFO_PROTOCOL         = CURLINFO_LONG   + 48,
+  CURLINFO_SCHEME           = CURLINFO_STRING + 49,
   /* Fill in new entries below here! */
 
-  CURLINFO_LASTONE          = 46
+  CURLINFO_LASTONE          = 49
 } CURLINFO;
 
 /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -2372,6 +2445,7 @@ typedef struct {
 #define CURL_VERSION_UNIX_SOCKETS (1<<19) /* Unix domain sockets support */
 #define CURL_VERSION_PSL          (1<<20) /* Mozilla's Public Suffix List, used
                                              for cookie domain verification */
+#define CURL_VERSION_HTTPS_PROXY  (1<<21) /* HTTPS-proxy support built-in */
 
  /*
  * NAME curl_version_info()
diff --git a/include/curl/curlver.h b/include/curl/curlver.h
index 3bb0235..9126641 100644
--- a/include/curl/curlver.h
+++ b/include/curl/curlver.h
@@ -30,13 +30,13 @@
 
 /* This is the version number of the libcurl package from which this header
    file origins: */
-#define LIBCURL_VERSION "7.51.0-DEV"
+#define LIBCURL_VERSION "7.52.1-DEV"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 51
-#define LIBCURL_VERSION_PATCH 0
+#define LIBCURL_VERSION_MINOR 52
+#define LIBCURL_VERSION_PATCH 1
 
 /* This is the numeric version of the libcurl version number, meant for easier
    parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
@@ -57,7 +57,7 @@
    CURL_VERSION_BITS() macro since curl's own configure script greps for it
    and needs it to contain the full number.
 */
-#define LIBCURL_VERSION_NUM 0x073300
+#define LIBCURL_VERSION_NUM 0x073401
 
 /*
  * This is the date and time when the full source package was created. The
diff --git a/include/curl/easy.h b/include/curl/easy.h
index afc766c..752c504 100644
--- a/include/curl/easy.h
+++ b/include/curl/easy.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -58,7 +58,7 @@ CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
  * curl_easy_duphandle() for each new thread to avoid a series of identical
  * curl_easy_setopt() invokes in every thread.
  */
-CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl);
+CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
 
 /*
  * NAME curl_easy_reset()
diff --git a/include/curl/stdcheaders.h b/include/curl/stdcheaders.h
index 6f0f7f3..027b6f4 100644
--- a/include/curl/stdcheaders.h
+++ b/include/curl/stdcheaders.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -24,8 +24,8 @@
 
 #include <sys/types.h>
 
-size_t fread (void *, size_t, size_t, FILE *);
-size_t fwrite (const void *, size_t, size_t, FILE *);
+size_t fread(void *, size_t, size_t, FILE *);
+size_t fwrite(const void *, size_t, size_t, FILE *);
 
 int strcasecmp(const char *, const char *);
 int strncasecmp(const char *, const char *, size_t);
diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h
index 6ec8bcf..4eb896e 100644
--- a/include/curl/typecheck-gcc.h
+++ b/include/curl/typecheck-gcc.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -40,7 +40,7 @@
  */
 #define curl_easy_setopt(handle, option, value)                               \
 __extension__ ({                                                              \
-  __typeof__ (option) _curl_opt = option;                                     \
+  __typeof__(option) _curl_opt = option;                                     \
   if(__builtin_constant_p(_curl_opt)) {                                       \
     if(_curl_is_long_option(_curl_opt))                                       \
       if(!_curl_is_long(value))                                               \
@@ -110,7 +110,7 @@ __extension__ ({                                                              \
 /* FIXME: don't allow const pointers */
 #define curl_easy_getinfo(handle, info, arg)                                  \
 __extension__ ({                                                              \
-  __typeof__ (info) _curl_info = info;                                        \
+  __typeof__(info) _curl_info = info;                                        \
   if(__builtin_constant_p(_curl_info)) {                                      \
     if(_curl_is_string_info(_curl_info))                                      \
       if(!_curl_is_arr((arg), char *))                                        \
@@ -151,7 +151,7 @@ _CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
   "curl_easy_setopt expects a curl_off_t argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_string,
               "curl_easy_setopt expects a "
-              "string (char* or char[]) argument for this option"
+              "string ('char *' or char[]) argument for this option"
   )
 _CURL_WARNING(_curl_easy_setopt_err_write_callback,
   "curl_easy_setopt expects a curl_write_callback argument for this option")
@@ -182,24 +182,25 @@ _CURL_WARNING(_curl_easy_setopt_err_error_buffer,
               "curl_easy_setopt expects a "
               "char buffer of CURL_ERROR_SIZE as argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_FILE,
-  "curl_easy_setopt expects a FILE* argument for this option")
+  "curl_easy_setopt expects a 'FILE *' argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_postfields,
-  "curl_easy_setopt expects a void* or char* argument for this option")
+  "curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
-  "curl_easy_setopt expects a struct curl_httppost* argument for this option")
+              "curl_easy_setopt expects a 'struct curl_httppost *' "
+              "argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_curl_slist,
-  "curl_easy_setopt expects a struct curl_slist* argument for this option")
+  "curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_CURLSH,
   "curl_easy_setopt expects a CURLSH* argument for this option")
 
 _CURL_WARNING(_curl_easy_getinfo_err_string,
-  "curl_easy_getinfo expects a pointer to char * for this info")
+  "curl_easy_getinfo expects a pointer to 'char *' for this info")
 _CURL_WARNING(_curl_easy_getinfo_err_long,
   "curl_easy_getinfo expects a pointer to long for this info")
 _CURL_WARNING(_curl_easy_getinfo_err_double,
   "curl_easy_getinfo expects a pointer to double for this info")
 _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
-  "curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
+  "curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
 
 /* groups of curl_easy_setops options that take the same type of argument */
 
@@ -363,7 +364,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
 
 /* XXX: should evaluate to true iff expr is a pointer */
 #define _curl_is_any_ptr(expr)                                                \
-  (sizeof(expr) == sizeof(void*))
+  (sizeof(expr) == sizeof(void *))
 
 /* evaluates to true if expr is NULL */
 /* XXX: must not evaluate expr, so this check is not accurate */
@@ -455,12 +456,12 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
    _curl_callback_compatible((expr), _curl_read_callback4) ||                 \
    _curl_callback_compatible((expr), _curl_read_callback5) ||                 \
    _curl_callback_compatible((expr), _curl_read_callback6))
-typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*);
-typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*);
-typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*);
-typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*);
-typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*);
-typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*);
+typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void *);
+typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void *);
+typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE *);
+typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void *);
+typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void *);
+typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE *);
 
 /* evaluates to true if expr is of type curl_write_callback or "similar" */
 #define _curl_is_write_cb(expr)                                               \
@@ -473,14 +474,14 @@ typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*);
    _curl_callback_compatible((expr), _curl_write_callback4) ||                \
    _curl_callback_compatible((expr), _curl_write_callback5) ||                \
    _curl_callback_compatible((expr), _curl_write_callback6))
-typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*);
+typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void *);
 typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
-                                       const void*);
-typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*);
-typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*);
+                                       const void *);
+typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE *);
+typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void *);
 typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
-                                       const void*);
-typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*);
+                                       const void *);
+typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE *);
 
 /* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
 #define _curl_is_ioctl_cb(expr)                                         \
@@ -490,10 +491,10 @@ typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*);
    _curl_callback_compatible((expr), _curl_ioctl_callback2) ||                \
    _curl_callback_compatible((expr), _curl_ioctl_callback3) ||                \
    _curl_callback_compatible((expr), _curl_ioctl_callback4))
-typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*);
-typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*);
-typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*);
-typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*);
+typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void *);
+typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void *);
+typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void *);
+typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
 
 /* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
 #define _curl_is_sockopt_cb(expr)                                       \
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index 1328cad..19f5800 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -51,7 +51,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
   pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c        \
   openldap.c curl_gethostname.c gopher.c idn_win32.c                    \
   http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c      \
-  http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c               \
+  http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c        \
   curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c          \
   x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c
 
@@ -72,7 +72,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
   curl_sasl.h curl_multibyte.h hostcheck.h conncache.h                  \
   curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h       \
   x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h           \
-  curl_printf.h system_win32.h
+  curl_printf.h system_win32.h rand.h
 
 LIB_RCFILES = libcurl.rc
 
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index 2aed94f..c038c2a 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -169,7 +169,7 @@ int Curl_resolver_duphandle(void **to, void *from)
   return CURLE_OK;
 }
 
-static void destroy_async_data (struct Curl_async *async);
+static void destroy_async_data(struct Curl_async *async);
 
 /*
  * Cancel all possibly still on-going resolves for this connection.
@@ -184,7 +184,7 @@ void Curl_resolver_cancel(struct connectdata *conn)
 /*
  * destroy_async_data() cleans up async resolver data.
  */
-static void destroy_async_data (struct Curl_async *async)
+static void destroy_async_data(struct Curl_async *async)
 {
   free(async->hostname);
 
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index 7cce01a..26a15b1 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -155,8 +155,8 @@ struct thread_sync_data {
   curl_mutex_t * mtx;
   int done;
 
-  char * hostname;        /* hostname to resolve, Curl_async.hostname
-                             duplicate */
+  char *hostname;        /* hostname to resolve, Curl_async.hostname
+                            duplicate */
   int port;
   int sock_error;
   Curl_addrinfo *res;
@@ -169,7 +169,7 @@ struct thread_sync_data {
 struct thread_data {
   curl_thread_t thread_hnd;
   unsigned int poll_interval;
-  long interval_end;
+  time_t interval_end;
   struct thread_sync_data tsd;
 };
 
@@ -200,7 +200,7 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
 /* Initialize resolver thread synchronization data */
 static
 int init_thread_sync_data(struct thread_data * td,
-                           const char * hostname,
+                           const char *hostname,
                            int port,
                            const struct addrinfo *hints)
 {
@@ -263,7 +263,7 @@ static int getaddrinfo_complete(struct connectdata *conn)
  * For builds without ARES, but with ENABLE_IPV6, create a resolver thread
  * and wait on it.
  */
-static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
+static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
 {
   struct thread_sync_data *tsd = (struct thread_sync_data*)arg;
   struct thread_data *td = tsd->td;
@@ -303,7 +303,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread (void *arg)
 /*
  * gethostbyname_thread() resolves a name and then exits.
  */
-static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
+static unsigned int CURL_STDCALL gethostbyname_thread(void *arg)
 {
   struct thread_sync_data *tsd = (struct thread_sync_data *)arg;
   struct thread_data *td = tsd->td;
@@ -336,7 +336,7 @@ static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
 /*
  * destroy_async_data() cleans up async resolver data and thread handle.
  */
-static void destroy_async_data (struct Curl_async *async)
+static void destroy_async_data(struct Curl_async *async)
 {
   if(async->os_specific) {
     struct thread_data *td = (struct thread_data*) async->os_specific;
@@ -375,14 +375,14 @@ static void destroy_async_data (struct Curl_async *async)
  *
  * Returns FALSE in case of failure, otherwise TRUE.
  */
-static bool init_resolve_thread (struct connectdata *conn,
-                                 const char *hostname, int port,
-                                 const struct addrinfo *hints)
+static bool init_resolve_thread(struct connectdata *conn,
+                                const char *hostname, int port,
+                                const struct addrinfo *hints)
 {
   struct thread_data *td = calloc(1, sizeof(struct thread_data));
   int err = RESOLVER_ENOMEM;
 
-  conn->async.os_specific = (void*) td;
+  conn->async.os_specific = (void *)td;
   if(!td)
     goto err_exit;
 
@@ -525,7 +525,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
   }
   else {
     /* poll for name lookup done with exponential backoff up to 250ms */
-    long elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
+    time_t elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
     if(elapsed < 0)
       elapsed = 0;
 
diff --git a/lib/conncache.c b/lib/conncache.c
index 01b1b44..d8ef9a5 100644
--- a/lib/conncache.c
+++ b/lib/conncache.c
@@ -132,8 +132,10 @@ static char *hashkey(struct connectdata *conn)
 {
   const char *hostname;
 
-  if(conn->bits.proxy)
-    hostname = conn->proxy.name;
+  if(conn->bits.socksproxy)
+    hostname = conn->socks_proxy.host.name;
+  else if(conn->bits.httpproxy)
+    hostname = conn->http_proxy.host.name;
   else if(conn->bits.conn_to_host)
     hostname = conn->conn_to_host.name;
   else
diff --git a/lib/connect.c b/lib/connect.c
index 3df34d9..524d885 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -179,12 +179,12 @@ singleipconnect(struct connectdata *conn,
  *
  * @unittest: 1303
  */
-long Curl_timeleft(struct Curl_easy *data,
-                   struct timeval *nowp,
-                   bool duringconnect)
+time_t Curl_timeleft(struct Curl_easy *data,
+                     struct timeval *nowp,
+                     bool duringconnect)
 {
   int timeout_set = 0;
-  long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
+  time_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
   struct timeval now;
 
   /* if a timeout is set, use the most restrictive one */
@@ -194,7 +194,7 @@ long Curl_timeleft(struct Curl_easy *data,
   if(duringconnect && (data->set.connecttimeout > 0))
     timeout_set |= 2;
 
-  switch (timeout_set) {
+  switch(timeout_set) {
   case 1:
     timeout_ms = data->set.timeout;
     break;
@@ -601,26 +601,28 @@ void Curl_persistconninfo(struct connectdata *conn)
 {
   memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
   memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
+  conn->data->info.conn_scheme = conn->handler->scheme;
+  conn->data->info.conn_protocol = conn->handler->protocol;
   conn->data->info.conn_primary_port = conn->primary_port;
   conn->data->info.conn_local_port = conn->local_port;
 }
 
 /* retrieves ip address and port from a sockaddr structure */
-static bool getaddressinfo(struct sockaddr* sa, char* addr,
-                           long* port)
+static bool getaddressinfo(struct sockaddr *sa, char *addr,
+                           long *port)
 {
   unsigned short us_port;
-  struct sockaddr_in* si = NULL;
+  struct sockaddr_in *si = NULL;
 #ifdef ENABLE_IPV6
-  struct sockaddr_in6* si6 = NULL;
+  struct sockaddr_in6 *si6 = NULL;
 #endif
 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
-  struct sockaddr_un* su = NULL;
+  struct sockaddr_un *su = NULL;
 #endif
 
-  switch (sa->sa_family) {
+  switch(sa->sa_family) {
     case AF_INET:
-      si = (struct sockaddr_in*)(void*) sa;
+      si = (struct sockaddr_in *)(void *) sa;
       if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
                         addr, MAX_IPADR_LEN)) {
         us_port = ntohs(si->sin_port);
@@ -630,7 +632,7 @@ static bool getaddressinfo(struct sockaddr* sa, char* addr,
       break;
 #ifdef ENABLE_IPV6
     case AF_INET6:
-      si6 = (struct sockaddr_in6*)(void*) sa;
+      si6 = (struct sockaddr_in6 *)(void *) sa;
       if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
                         addr, MAX_IPADR_LEN)) {
         us_port = ntohs(si6->sin6_port);
@@ -722,7 +724,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
 {
   struct Curl_easy *data = conn->data;
   CURLcode result = CURLE_OK;
-  long allow;
+  time_t allow;
   int error = 0;
   struct timeval now;
   int rc;
@@ -843,7 +845,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
   if(result) {
     /* no more addresses to try */
 
-    const char* hostname;
+    const char *hostname;
 
     /* if the first address family runs out of addresses to try before
        the happy eyeball timeout, go ahead and try the next family now */
@@ -853,8 +855,10 @@ CURLcode Curl_is_connected(struct connectdata *conn,
         return result;
     }
 
-    if(conn->bits.proxy)
-      hostname = conn->proxy.name;
+    if(conn->bits.socksproxy)
+      hostname = conn->socks_proxy.host.name;
+    else if(conn->bits.httpproxy)
+      hostname = conn->http_proxy.host.name;
     else if(conn->bits.conn_to_host)
       hostname = conn->conn_to_host.name;
     else
@@ -1153,7 +1157,7 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
   struct timeval before = Curl_tvnow();
   CURLcode result = CURLE_COULDNT_CONNECT;
 
-  long timeout_ms = Curl_timeleft(data, &before, TRUE);
+  time_t timeout_ms = Curl_timeleft(data, &before, TRUE);
 
   if(timeout_ms < 0) {
     /* a precaution, no need to continue if time already is up */
@@ -1243,24 +1247,6 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
       /* only store this if the caller cares for it */
       *connp = c;
     sockfd = c->sock[FIRSTSOCKET];
-    /* we have a socket connected, let's determine if the server shut down */
-    /* determine if ssl */
-    if(c->ssl[FIRSTSOCKET].use) {
-      /* use the SSL context */
-      if(!Curl_ssl_check_cxn(c))
-        return CURL_SOCKET_BAD;   /* FIN received */
-    }
-/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
-#ifdef MSG_PEEK
-    else if(sockfd != CURL_SOCKET_BAD) {
-      /* use the socket */
-      char buf;
-      if(recv((RECV_TYPE_ARG1)sockfd, (RECV_TYPE_ARG2)&buf,
-              (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
-        return CURL_SOCKET_BAD;   /* FIN received */
-      }
-    }
-#endif
   }
   else
     return CURL_SOCKET_BAD;
@@ -1269,6 +1255,33 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
 }
 
 /*
+ * Check if a connection seems to be alive.
+ */
+bool Curl_connalive(struct connectdata *conn)
+{
+  /* First determine if ssl */
+  if(conn->ssl[FIRSTSOCKET].use) {
+    /* use the SSL context */
+    if(!Curl_ssl_check_cxn(conn))
+      return false;   /* FIN received */
+  }
+/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
+#ifdef MSG_PEEK
+  else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD)
+    return false;
+  else {
+    /* use the socket */
+    char buf;
+    if(recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
+            (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
+      return false;   /* FIN received */
+    }
+  }
+#endif
+  return true;
+}
+
+/*
  * Close a socket.
  *
  * 'conn' can be NULL, beware!
@@ -1391,3 +1404,16 @@ void Curl_conncontrol(struct connectdata *conn,
                                    should assign this bit */
   }
 }
+
+/* Data received can be cached at various levels, so check them all here. */
+bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
+{
+  int readable;
+
+  if(Curl_ssl_data_pending(conn, sockindex) ||
+     Curl_recv_has_postponed_data(conn, sockindex))
+    return true;
+
+  readable = SOCKET_READABLE(conn->sock[sockindex], 0);
+  return (readable > 0 && (readable & CURL_CSELECT_IN));
+}
diff --git a/lib/connect.h b/lib/connect.h
index a7cbc9b..5653cb4 100644
--- a/lib/connect.h
+++ b/lib/connect.h
@@ -35,9 +35,9 @@ CURLcode Curl_connecthost(struct connectdata *conn,
 
 /* generic function that returns how much time there's left to run, according
    to the timeouts set */
-long Curl_timeleft(struct Curl_easy *data,
-                   struct timeval *nowp,
-                   bool duringconnect);
+time_t Curl_timeleft(struct Curl_easy *data,
+                     struct timeval *nowp,
+                     bool duringconnect);
 
 #define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
 #define HAPPY_EYEBALLS_TIMEOUT     200 /* milliseconds to wait between
@@ -52,6 +52,11 @@ long Curl_timeleft(struct Curl_easy *data,
 curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
                                   struct connectdata **connp);
 
+/*
+ * Check if a connection seems to be alive.
+ */
+bool Curl_connalive(struct connectdata *conn);
+
 #ifdef USE_WINSOCK
 /* When you run a program that uses the Windows Sockets API, you may
    experience slow performance when you copy data to a TCP server.
@@ -137,4 +142,6 @@ 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);
+
 #endif /* HEADER_CURL_CONNECT_H */
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index fa36aca..5385058 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -28,8 +28,8 @@
 #include <curl/curl.h>
 #include "sendf.h"
 #include "content_encoding.h"
+#include "strdup.h"
 #include "curl_memory.h"
-
 #include "memdebug.h"
 
 /* Comment this out if zlib is always going to be at least ver. 1.2.0.4
@@ -69,11 +69,11 @@ process_zlib_error(struct connectdata *conn, z_stream *z)
 {
   struct Curl_easy *data = conn->data;
   if(z->msg)
-    failf (data, "Error while processing content unencoding: %s",
-           z->msg);
+    failf(data, "Error while processing content unencoding: %s",
+          z->msg);
   else
-    failf (data, "Error while processing content unencoding: "
-           "Unknown failure within decompression software.");
+    failf(data, "Error while processing content unencoding: "
+          "Unknown failure within decompression software.");
 
   return CURLE_BAD_CONTENT_ENCODING;
 }
@@ -327,14 +327,14 @@ Curl_unencode_gzip_write(struct connectdata *conn,
    * can handle the gzip header themselves.
    */
 
-  switch (k->zlib_init) {
+  switch(k->zlib_init) {
   /* Skip over gzip header? */
   case ZLIB_INIT:
   {
     /* Initial call state */
     ssize_t hlen;
 
-    switch (check_gzip_header((unsigned char *)k->str, nread, &hlen)) {
+    switch(check_gzip_header((unsigned char *)k->str, nread, &hlen)) {
     case GZIP_OK:
       z->next_in = (Bytef *)k->str + hlen;
       z->avail_in = (uInt)(nread - hlen);
@@ -371,18 +371,15 @@ Curl_unencode_gzip_write(struct connectdata *conn,
   {
     /* Need more gzip header data state */
     ssize_t hlen;
-    unsigned char *oldblock = z->next_in;
-
     z->avail_in += (uInt)nread;
-    z->next_in = realloc(z->next_in, z->avail_in);
+    z->next_in = Curl_saferealloc(z->next_in, z->avail_in);
     if(z->next_in == NULL) {
-      free(oldblock);
       return exit_zlib(z, &k->zlib_init, CURLE_OUT_OF_MEMORY);
     }
     /* Append the new block of data to the previous one */
     memcpy(z->next_in + z->avail_in - nread, k->str, nread);
 
-    switch (check_gzip_header(z->next_in, z->avail_in, &hlen)) {
+    switch(check_gzip_header(z->next_in, z->avail_in, &hlen)) {
     case GZIP_OK:
       /* This is the zlib stream data */
       free(z->next_in);
diff --git a/lib/cookie.c b/lib/cookie.c
index 1b3e645..092a226 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -146,12 +146,12 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
  * matching cookie path and url path
  * RFC6265 5.1.4 Paths and Path-Match
  */
-static bool pathmatch(const char* cookie_path, const char* request_uri)
+static bool pathmatch(const char *cookie_path, const char *request_uri)
 {
   size_t cookie_path_len;
   size_t uri_path_len;
-  char* uri_path = NULL;
-  char* pos;
+  char *uri_path = NULL;
+  char *pos;
   bool ret = FALSE;
 
   /* cookie_path must not have last '/' separator. ex: /sample */
@@ -798,8 +798,8 @@ Curl_cookie_add(struct Curl_easy *data,
   /* Check if the domain is a Public Suffix and if yes, ignore the cookie.
      This needs a libpsl compiled with builtin data. */
   if(domain && co->domain && !isip(co->domain)) {
-    if(((psl = psl_builtin()) != NULL)
-        && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) {
+    psl = psl_builtin();
+    if(psl && !psl_is_cookie_domain_acceptable(psl, domain, co->domain)) {
       infof(data,
             "cookie '%s' dropped, domain '%s' must not set cookies for '%s'\n",
             co->name, domain, co->domain);
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c
index 35eb2dd..61cdadd 100644
--- a/lib/curl_addrinfo.c
+++ b/lib/curl_addrinfo.c
@@ -146,7 +146,8 @@ Curl_getaddrinfo_ex(const char *nodename,
     if((size_t)ai->ai_addrlen < ss_size)
       continue;
 
-    if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) {
+    ca = malloc(sizeof(Curl_addrinfo));
+    if(!ca) {
       error = EAI_MEMORY;
       break;
     }
@@ -163,7 +164,8 @@ Curl_getaddrinfo_ex(const char *nodename,
     ca->ai_canonname = NULL;
     ca->ai_next      = NULL;
 
-    if((ca->ai_addr = malloc(ss_size)) == NULL) {
+    ca->ai_addr = malloc(ss_size);
+    if(!ca->ai_addr) {
       error = EAI_MEMORY;
       free(ca);
       break;
@@ -171,7 +173,8 @@ Curl_getaddrinfo_ex(const char *nodename,
     memcpy(ca->ai_addr, ai->ai_addr, ss_size);
 
     if(ai->ai_canonname != NULL) {
-      if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) {
+      ca->ai_canonname = strdup(ai->ai_canonname);
+      if(!ca->ai_canonname) {
         error = EAI_MEMORY;
         free(ca->ai_addr);
         free(ca);
@@ -286,21 +289,24 @@ Curl_he2ai(const struct hostent *he, int port)
     size_t ss_size;
 #ifdef ENABLE_IPV6
     if(he->h_addrtype == AF_INET6)
-      ss_size = sizeof (struct sockaddr_in6);
+      ss_size = sizeof(struct sockaddr_in6);
     else
 #endif
-      ss_size = sizeof (struct sockaddr_in);
+      ss_size = sizeof(struct sockaddr_in);
 
-    if((ai = calloc(1, sizeof(Curl_addrinfo))) == NULL) {
+    ai = calloc(1, sizeof(Curl_addrinfo));
+    if(!ai) {
       result = CURLE_OUT_OF_MEMORY;
       break;
     }
-    if((ai->ai_canonname = strdup(he->h_name)) == NULL) {
+    ai->ai_canonname = strdup(he->h_name);
+    if(!ai->ai_canonname) {
       result = CURLE_OUT_OF_MEMORY;
       free(ai);
       break;
     }
-    if((ai->ai_addr = calloc(1, ss_size)) == NULL) {
+    ai->ai_addr = calloc(1, ss_size);
+    if(!ai->ai_addr) {
       result = CURLE_OUT_OF_MEMORY;
       free(ai->ai_canonname);
       free(ai);
@@ -325,7 +331,7 @@ Curl_he2ai(const struct hostent *he, int port)
 
     /* leave the rest of the struct filled with zero */
 
-    switch (ai->ai_family) {
+    switch(ai->ai_family) {
     case AF_INET:
       addr = (void *)ai->ai_addr; /* storage area for this info */
 
@@ -475,8 +481,9 @@ Curl_addrinfo *Curl_str2addr(char *address, int port)
 /**
  * Given a path to a Unix domain socket, return a newly allocated Curl_addrinfo
  * struct initialized with this path.
+ * Set '*longpath' to TRUE if the error is a too long path.
  */
-Curl_addrinfo *Curl_unix2addr(const char *path)
+Curl_addrinfo *Curl_unix2addr(const char *path, int *longpath)
 {
   Curl_addrinfo *ai;
   struct sockaddr_un *sa_un;
@@ -485,8 +492,10 @@ Curl_addrinfo *Curl_unix2addr(const char *path)
   ai = calloc(1, sizeof(Curl_addrinfo));
   if(!ai)
     return NULL;
-  if((ai->ai_addr = calloc(1, sizeof(struct sockaddr_un))) == NULL) {
+  ai->ai_addr = calloc(1, sizeof(struct sockaddr_un));
+  if(!ai->ai_addr) {
     free(ai);
+    *longpath = FALSE;
     return NULL;
   }
   /* sun_path must be able to store the NUL-terminated path */
@@ -494,6 +503,7 @@ Curl_addrinfo *Curl_unix2addr(const char *path)
   if(path_len >= sizeof(sa_un->sun_path)) {
     free(ai->ai_addr);
     free(ai);
+    *longpath = TRUE;
     return NULL;
   }
 
@@ -576,7 +586,7 @@ void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port)
   struct sockaddr_in6 *addr6;
 #endif
   for(ca = addrinfo; ca != NULL; ca = ca->ai_next) {
-    switch (ca->ai_family) {
+    switch(ca->ai_family) {
     case AF_INET:
       addr = (void *)ca->ai_addr; /* storage area for this info */
       addr->sin_port = htons((unsigned short)port);
diff --git a/lib/curl_addrinfo.h b/lib/curl_addrinfo.h
index 1a681e6..4f24730 100644
--- a/lib/curl_addrinfo.h
+++ b/lib/curl_addrinfo.h
@@ -80,7 +80,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
 Curl_addrinfo *Curl_str2addr(char *dotted, int port);
 
 #ifdef USE_UNIX_SOCKETS
-Curl_addrinfo *Curl_unix2addr(const char *path);
+Curl_addrinfo *Curl_unix2addr(const char *path, int *longpath);
 #endif
 
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
diff --git a/lib/curl_endian.c b/lib/curl_endian.c
index 76deca6..c2d21de 100644
--- a/lib/curl_endian.c
+++ b/lib/curl_endian.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@
  *
  * Returns the integer.
  */
-unsigned short Curl_read16_le(unsigned char *buf)
+unsigned short Curl_read16_le(const unsigned char *buf)
 {
   return (unsigned short)(((unsigned short)buf[0]) |
                           ((unsigned short)buf[1] << 8));
@@ -56,7 +56,7 @@ unsigned short Curl_read16_le(unsigned char *buf)
  *
  * Returns the integer.
  */
-unsigned int Curl_read32_le(unsigned char *buf)
+unsigned int Curl_read32_le(const unsigned char *buf)
 {
   return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
          ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
@@ -77,7 +77,7 @@ unsigned int Curl_read32_le(unsigned char *buf)
  * Returns the integer.
  */
 #if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_le(unsigned char *buf)
+unsigned long long Curl_read64_le(const unsigned char *buf)
 {
   return ((unsigned long long)buf[0]) |
          ((unsigned long long)buf[1] << 8) |
@@ -89,7 +89,7 @@ unsigned long long Curl_read64_le(unsigned char *buf)
          ((unsigned long long)buf[7] << 56);
 }
 #else
-unsigned __int64 Curl_read64_le(unsigned char *buf)
+unsigned __int64 Curl_read64_le(const unsigned char *buf)
 {
   return ((unsigned __int64)buf[0]) | ((unsigned __int64)buf[1] << 8) |
          ((unsigned __int64)buf[2] << 16) | ((unsigned __int64)buf[3] << 24) |
@@ -113,7 +113,7 @@ unsigned __int64 Curl_read64_le(unsigned char *buf)
  *
  * Returns the integer.
  */
-unsigned short Curl_read16_be(unsigned char *buf)
+unsigned short Curl_read16_be(const unsigned char *buf)
 {
   return (unsigned short)(((unsigned short)buf[0] << 8) |
                           ((unsigned short)buf[1]));
@@ -132,7 +132,7 @@ unsigned short Curl_read16_be(unsigned char *buf)
  *
  * Returns the integer.
  */
-unsigned int Curl_read32_be(unsigned char *buf)
+unsigned int Curl_read32_be(const unsigned char *buf)
 {
   return ((unsigned int)buf[0] << 24) | ((unsigned int)buf[1] << 16) |
          ((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]);
@@ -153,7 +153,7 @@ unsigned int Curl_read32_be(unsigned char *buf)
  * Returns the integer.
  */
 #if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_be(unsigned char *buf)
+unsigned long long Curl_read64_be(const unsigned char *buf)
 {
   return ((unsigned long long)buf[0] << 56) |
          ((unsigned long long)buf[1] << 48) |
@@ -165,7 +165,7 @@ unsigned long long Curl_read64_be(unsigned char *buf)
          ((unsigned long long)buf[7]);
 }
 #else
-unsigned __int64 Curl_read64_be(unsigned char *buf)
+unsigned __int64 Curl_read64_be(const unsigned char *buf)
 {
   return ((unsigned __int64)buf[0] << 56) | ((unsigned __int64)buf[1] << 48) |
          ((unsigned __int64)buf[2] << 40) | ((unsigned __int64)buf[3] << 32) |
diff --git a/lib/curl_endian.h b/lib/curl_endian.h
index df8398c..8a2b07a 100644
--- a/lib/curl_endian.h
+++ b/lib/curl_endian.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,32 +23,32 @@
  ***************************************************************************/
 
 /* Converts a 16-bit integer from little endian */
-unsigned short Curl_read16_le(unsigned char *buf);
+unsigned short Curl_read16_le(const unsigned char *buf);
 
 /* Converts a 32-bit integer from little endian */
-unsigned int Curl_read32_le(unsigned char *buf);
+unsigned int Curl_read32_le(const unsigned char *buf);
 
 #if (CURL_SIZEOF_CURL_OFF_T > 4)
 /* Converts a 64-bit integer from little endian */
 #if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_le(unsigned char *buf);
+unsigned long long Curl_read64_le(const unsigned char *buf);
 #else
-unsigned __int64 Curl_read64_le(unsigned char *buf);
+unsigned __int64 Curl_read64_le(const unsigned char *buf);
 #endif
 #endif
 
 /* Converts a 16-bit integer from big endian */
-unsigned short Curl_read16_be(unsigned char *buf);
+unsigned short Curl_read16_be(const unsigned char *buf);
 
 /* Converts a 32-bit integer from big endian */
-unsigned int Curl_read32_be(unsigned char *buf);
+unsigned int Curl_read32_be(const unsigned char *buf);
 
 #if (CURL_SIZEOF_CURL_OFF_T > 4)
 /* Converts a 64-bit integer from big endian */
 #if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_be(unsigned char *buf);
+unsigned long long Curl_read64_be(const unsigned char *buf);
 #else
-unsigned __int64 Curl_read64_be(unsigned char *buf);
+unsigned __int64 Curl_read64_be(const unsigned char *buf);
 #endif
 #endif
 
diff --git a/lib/curl_gethostname.c b/lib/curl_gethostname.c
index 2591fd8..8337c72 100644
--- a/lib/curl_gethostname.c
+++ b/lib/curl_gethostname.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -48,8 +48,8 @@
  * For libcurl static library release builds no overriding takes place.
  */
 
-int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) {
-
+int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen)
+{
 #ifndef HAVE_GETHOSTNAME
 
   /* Allow compilation and return failure when unavailable */
@@ -59,7 +59,7 @@ int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen) {
 
 #else
   int err;
-  char* dot;
+  char *dot;
 
 #ifdef DEBUGBUILD
 
diff --git a/lib/curl_gssapi.c b/lib/curl_gssapi.c
index bf7c766..83f3fa0 100644
--- a/lib/curl_gssapi.c
+++ b/lib/curl_gssapi.c
@@ -94,7 +94,7 @@ static size_t display_gss_error(OM_uint32 status, int type,
     if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) {
       len += snprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
                       "%.*s. ", (int)status_string.length,
-                      (char*)status_string.value);
+                      (char *)status_string.value);
     }
     gss_release_buffer(&min_stat, &status_string);
   } while(!GSS_ERROR(maj_stat) && msg_ctx != 0);
diff --git a/lib/curl_hmac.h b/lib/curl_hmac.h
index 41703b4..756dc9e 100644
--- a/lib/curl_hmac.h
+++ b/lib/curl_hmac.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -24,11 +24,11 @@
 
 #ifndef CURL_DISABLE_CRYPTO_AUTH
 
-typedef void    (* HMAC_hinit_func)(void * context);
-typedef void    (* HMAC_hupdate_func)(void * context,
-                                      const unsigned char * data,
+typedef void    (* HMAC_hinit_func)(void *context);
+typedef void    (* HMAC_hupdate_func)(void *context,
+                                      const unsigned char *data,
                                       unsigned int len);
-typedef void    (* HMAC_hfinal_func)(unsigned char * result, void * context);
+typedef void    (* HMAC_hfinal_func)(unsigned char *result, void *context);
 
 
 /* Per-hash function HMAC parameters. */
@@ -46,21 +46,21 @@ typedef struct {
 /* HMAC computation context. */
 
 typedef struct {
-  const HMAC_params *   hmac_hash;      /* Hash function definition. */
-  void *                hmac_hashctxt1; /* Hash function context 1. */
-  void *                hmac_hashctxt2; /* Hash function context 2. */
+  const HMAC_params *hmac_hash; /* Hash function definition. */
+  void *hmac_hashctxt1;         /* Hash function context 1. */
+  void *hmac_hashctxt2;         /* Hash function context 2. */
 } HMAC_context;
 
 
 /* Prototypes. */
 
-HMAC_context * Curl_HMAC_init(const HMAC_params * hashparams,
-                              const unsigned char * key,
+HMAC_context * Curl_HMAC_init(const HMAC_params *hashparams,
+                              const unsigned char *key,
                               unsigned int keylen);
-int Curl_HMAC_update(HMAC_context * context,
-                     const unsigned char * data,
+int Curl_HMAC_update(HMAC_context *context,
+                     const unsigned char *data,
                      unsigned int len);
-int Curl_HMAC_final(HMAC_context * context, unsigned char * result);
+int Curl_HMAC_final(HMAC_context *context, unsigned char *result);
 
 #endif
 
diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c
index 812a073..73d983c 100644
--- a/lib/curl_ntlm_core.c
+++ b/lib/curl_ntlm_core.c
@@ -566,7 +566,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
     gcry_md_hd_t MD4pw;
     gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
     gcry_md_write(MD4pw, pw, 2 * len);
-    memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
+    memcpy(ntbuffer, gcry_md_read(MD4pw, 0), MD4_DIGEST_LENGTH);
     gcry_md_close(MD4pw);
 #elif defined(USE_MBEDTLS)
     mbedtls_md4(pw, 2 * len, ntbuffer);
diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c
index afdea16..6a90e62 100644
--- a/lib/curl_ntlm_wb.c
+++ b/lib/curl_ntlm_wb.c
@@ -51,6 +51,7 @@
 #include "curl_ntlm_wb.h"
 #include "url.h"
 #include "strerror.h"
+#include "strdup.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -156,7 +157,8 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
   }
   slash = strpbrk(username, "\\/");
   if(slash) {
-    if((domain = strdup(username)) == NULL)
+    domain = strdup(username);
+    if(!domain)
       return CURLE_OUT_OF_MEMORY;
     slash = domain + (slash - username);
     *slash = '\0';
@@ -293,11 +295,10 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
       buf[len_out - 1] = '\0';
       break;
     }
-    newbuf = realloc(buf, len_out + NTLM_BUFSIZE);
-    if(!newbuf) {
-      free(buf);
+    newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE);
+    if(!newbuf)
       return CURLE_OUT_OF_MEMORY;
-    }
+
     buf = newbuf;
   }
 
@@ -349,7 +350,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
 
   if(proxy) {
     allocuserpwd = &conn->allocptr.proxyuserpwd;
-    userp = conn->proxyuser;
+    userp = conn->http_proxy.user;
     ntlm = &conn->proxyntlm;
     authp = &conn->data->state.authproxy;
   }
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index 6b86962..807f5de 100644
--- a/lib/curl_sasl.c
+++ b/lib/curl_sasl.c
@@ -262,10 +262,13 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
   size_t len = 0;
   saslstate state1 = SASL_STOP;
   saslstate state2 = SASL_FINAL;
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
 #if defined(USE_KERBEROS5)
-  const char* service = data->set.str[STRING_SERVICE_NAME] ?
-                        data->set.str[STRING_SERVICE_NAME] :
-                        sasl->params->service;
+  const char *service = data->set.str[STRING_SERVICE_NAME] ?
+    data->set.str[STRING_SERVICE_NAME] :
+    sasl->params->service;
 #endif
 
   sasl->force_ir = force_ir;    /* Latch for future use */
@@ -341,8 +344,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
 
       if(force_ir || data->set.sasl_ir)
         result = Curl_auth_create_oauth_bearer_message(data, conn->user,
-                                                       conn->host.name,
-                                                       conn->port,
+                                                       hostname,
+                                                       port,
                                                        conn->oauth_bearer,
                                                        &resp, &len);
     }
@@ -408,6 +411,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   saslstate newstate = SASL_FINAL;
   char *resp = NULL;
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
 #if !defined(CURL_DISABLE_CRYPTO_AUTH)
   char *serverdata;
   char *chlg = NULL;
@@ -542,8 +548,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
     /* Create the authorisation message */
     if(sasl->authused == SASL_MECH_OAUTHBEARER) {
       result = Curl_auth_create_oauth_bearer_message(data, conn->user,
-                                                     conn->host.name,
-                                                     conn->port,
+                                                     hostname,
+                                                     port,
                                                      conn->oauth_bearer,
                                                      &resp, &len);
 
diff --git a/lib/curl_sec.h b/lib/curl_sec.h
index 3f94e14..7bdde26 100644
--- a/lib/curl_sec.h
+++ b/lib/curl_sec.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -30,8 +30,8 @@ struct Curl_sec_client_mech {
   void (*end)(void *);
   int (*check_prot)(void *, int);
   int (*overhead)(void *, int, int);
-  int (*encode)(void *, const void*, int, int, void**);
-  int (*decode)(void *, void*, int, int, struct connectdata *);
+  int (*encode)(void *, const void *, int, int, void **);
+  int (*decode)(void *, void *, int, int, struct connectdata *);
 };
 
 #define AUTH_OK         0
@@ -39,11 +39,11 @@ struct Curl_sec_client_mech {
 #define AUTH_ERROR      2
 
 #ifdef HAVE_GSSAPI
-int Curl_sec_read_msg (struct connectdata *conn, char *,
-                       enum protection_level);
-void Curl_sec_end (struct connectdata *);
-CURLcode Curl_sec_login (struct connectdata *);
-int Curl_sec_request_prot (struct connectdata *conn, const char *level);
+int Curl_sec_read_msg(struct connectdata *conn, char *,
+                      enum protection_level);
+void Curl_sec_end(struct connectdata *);
+CURLcode Curl_sec_login(struct connectdata *);
+int Curl_sec_request_prot(struct connectdata *conn, const char *level);
 
 extern struct Curl_sec_client_mech Curl_krb5_client_mech;
 #endif
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index 9619a1e..0fe3633 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -467,8 +467,8 @@
 
 #  ifdef __minix
      /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */
-     extern char * strtok_r(char *s, const char *delim, char **last);
-     extern struct tm * gmtime_r(const time_t * const timep, struct tm *tmp);
+     extern char *strtok_r(char *s, const char *delim, char **last);
+     extern struct tm *gmtime_r(const time_t * const timep, struct tm *tmp);
 #  endif
 
 #  define DIR_CHAR      "/"
diff --git a/lib/curl_threads.c b/lib/curl_threads.c
index c98d8bb..a78eff5 100644
--- a/lib/curl_threads.c
+++ b/lib/curl_threads.c
@@ -59,7 +59,7 @@ static void *curl_thread_create_thunk(void *arg)
   return 0;
 }
 
-curl_thread_t Curl_thread_create(unsigned int (*func) (void*), void *arg)
+curl_thread_t Curl_thread_create(unsigned int (*func) (void *), void *arg)
 {
   curl_thread_t t = malloc(sizeof(pthread_t));
   struct curl_actual_call *ac = malloc(sizeof(struct curl_actual_call));
@@ -100,7 +100,8 @@ int Curl_thread_join(curl_thread_t *hnd)
 
 #elif defined(USE_THREADS_WIN32)
 
-curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
+/* !checksrc! disable SPACEBEFOREPAREN 1 */
+curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
                                  void *arg)
 {
 #ifdef _WIN32_WCE
diff --git a/lib/curl_threads.h b/lib/curl_threads.h
index 8cbac63..9e0d14a 100644
--- a/lib/curl_threads.h
+++ b/lib/curl_threads.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -50,7 +50,8 @@
 
 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
 
-curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void*),
+/* !checksrc! disable SPACEBEFOREPAREN 1 */
+curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
                                  void *arg);
 
 void Curl_thread_destroy(curl_thread_t hnd);
diff --git a/lib/easy.c b/lib/easy.c
index eee1061..1242369 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -927,6 +927,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
 
   Curl_convert_setup(outcurl);
 
+  Curl_initinfo(outcurl);
+
   outcurl->magic = CURLEASY_MAGIC_NUMBER;
 
   /* we reach this point and thus we are OK */
diff --git a/lib/escape.c b/lib/escape.c
index 6657007..9c811b8 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -31,6 +31,7 @@
 #include "warnless.h"
 #include "non-ascii.h"
 #include "escape.h"
+#include "strdup.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -42,7 +43,7 @@
 */
 static bool Curl_isunreserved(unsigned char in)
 {
-  switch (in) {
+  switch(in) {
     case '0': case '1': case '2': case '3': case '4':
     case '5': case '6': case '7': case '8': case '9':
     case 'a': case 'b': case 'c': case 'd': case 'e':
@@ -109,11 +110,9 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
       newlen += 2; /* the size grows with two, since this'll become a %XX */
       if(newlen > alloc) {
         alloc *= 2;
-        testing_ptr = realloc(ns, alloc);
-        if(!testing_ptr) {
-          free(ns);
+        testing_ptr = Curl_saferealloc(ns, alloc);
+        if(!testing_ptr)
           return NULL;
-        }
         else {
           ns = testing_ptr;
         }
diff --git a/lib/file.c b/lib/file.c
index 272289e..3dbc0f2 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -313,7 +313,7 @@ static CURLcode file_upload(struct connectdata *conn)
   curl_off_t bytecount = 0;
   struct timeval now = Curl_tvnow();
   struct_stat file_stat;
-  const char* buf2;
+  const char *buf2;
 
   /*
    * Since FILE: doesn't do the full init, we need to provide some extra
diff --git a/lib/formdata.c b/lib/formdata.c
index 785f1a6..abd2da0 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -36,6 +36,7 @@
 #include "strcase.h"
 #include "sendf.h"
 #include "strdup.h"
+#include "rand.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -80,7 +81,7 @@ AddHttpPost(char *name, size_t namelength,
             char *buffer, size_t bufferlength,
             char *contenttype,
             long flags,
-            struct curl_slist* contentHeader,
+            struct curl_slist *contentHeader,
             char *showfilename, char *userp,
             struct curl_httppost *parent_post,
             struct curl_httppost **httppost,
@@ -315,7 +316,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
         break;
     }
 
-    switch (option) {
+    switch(option) {
     case CURLFORM_ARRAY:
       if(array_state)
         /* we don't support an array from within an array */
@@ -547,9 +548,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
       {
         /* this "cast increases required alignment of target type" but
            we consider it OK anyway */
-        struct curl_slist* list = array_state?
-          (struct curl_slist*)(void*)array_value:
-          va_arg(params, struct curl_slist*);
+        struct curl_slist *list = array_state?
+          (struct curl_slist *)(void *)array_value:
+          va_arg(params, struct curl_slist *);
 
         if(current_form->contentheader)
           return_value = CURL_FORMADD_OPTION_TWICE;
@@ -761,8 +762,8 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
  * and CD/DVD images should be either a STREAM_LF format or a fixed format.
  *
  */
-curl_off_t VmsRealFileSize(const char * name,
-                           const struct_stat * stat_buf)
+curl_off_t VmsRealFileSize(const char *name,
+                           const struct_stat *stat_buf)
 {
   char buffer[8192];
   curl_off_t count;
@@ -791,8 +792,8 @@ curl_off_t VmsRealFileSize(const char * name,
  *  if not to call a routine to get the correct size.
  *
  */
-static curl_off_t VmsSpecialSize(const char * name,
-                                 const struct_stat * stat_buf)
+static curl_off_t VmsSpecialSize(const char *name,
+                                 const struct_stat *stat_buf)
 {
   switch(stat_buf->st_fab_rfm) {
   case FAB$C_VAR:
@@ -948,8 +949,8 @@ void Curl_formclean(struct FormData **form_ptr)
     if(form->type <= FORM_CONTENT)
       free(form->line); /* free the line */
     free(form);       /* free the struct */
-
-  } while((form = next) != NULL); /* continue */
+    form = next;
+  } while(form); /* continue */
 
   *form_ptr = NULL;
 }
@@ -1030,8 +1031,8 @@ void curl_formfree(struct curl_httppost *form)
     free(form->contenttype); /* free the content type */
     free(form->showfilename); /* free the faked file name */
     free(form);       /* free the struct */
-
-  } while((form = next) != NULL); /* continue */
+    form = next;
+  } while(form); /* continue */
 }
 
 #ifndef HAVE_BASENAME
@@ -1166,7 +1167,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
   curl_off_t size = 0; /* support potentially ENORMOUS formposts */
   char *boundary;
   char *fileboundary = NULL;
-  struct curl_slist* curList;
+  struct curl_slist *curList;
 
   *finalform = NULL; /* default form is empty */
 
@@ -1373,8 +1374,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
       if(result)
         break;
     }
-
-  } while((post = post->next) != NULL); /* for each field */
+    post = post->next;
+  } while(post); /* for each field */
 
   /* end-boundary for everything */
   if(!result)
@@ -1426,13 +1427,14 @@ int Curl_FormInit(struct Form *form, struct FormData *formdata)
    *
    */
 # define fopen_read vmsfopenread
-static FILE * vmsfopenread(const char *file, const char *mode) {
+static FILE * vmsfopenread(const char *file, const char *mode)
+{
   struct_stat statbuf;
   int result;
 
   result = stat(file, &statbuf);
 
-  switch (statbuf.st_fab_rfm) {
+  switch(statbuf.st_fab_rfm) {
   case FAB$C_VAR:
   case FAB$C_VFC:
   case FAB$C_STMCR:
@@ -1569,8 +1571,12 @@ static char *formboundary(struct Curl_easy *data)
 {
   /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
      combinations */
-  return aprintf("------------------------%08x%08x",
-                 Curl_rand(data), Curl_rand(data));
+  unsigned int rnd[2];
+  CURLcode result = Curl_rand(data, &rnd[0], 2);
+  if(result)
+    return NULL;
+
+  return aprintf("------------------------%08x%08x", rnd[0], rnd[1]);
 }
 
 #else  /* CURL_DISABLE_HTTP */
diff --git a/lib/formdata.h b/lib/formdata.h
index 200470b..69629f6 100644
--- a/lib/formdata.h
+++ b/lib/formdata.h
@@ -65,7 +65,7 @@ typedef struct FormInfo {
                          file name will be used */
   bool showfilename_alloc;
   char *userp;        /* pointer for the read callback */
-  struct curl_slist* contentheader;
+  struct curl_slist *contentheader;
   struct FormInfo *more;
 } FormInfo;
 
diff --git a/lib/ftp.c b/lib/ftp.c
index b231731..fd77a5a 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -384,10 +384,10 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
  * Curl_pgrsTime(..., TIMER_STARTACCEPT);
  *
  */
-static long ftp_timeleft_accept(struct Curl_easy *data)
+static time_t ftp_timeleft_accept(struct Curl_easy *data)
 {
-  long timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
-  long other;
+  time_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT;
+  time_t other;
   struct timeval now;
 
   if(data->set.accepttimeout > 0)
@@ -430,7 +430,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   struct pingpong *pp = &ftpc->pp;
   int result;
-  long timeout_ms;
+  time_t timeout_ms;
   ssize_t nread;
   int ftpcode;
 
@@ -455,7 +455,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
   result = Curl_socket_check(ctrl_sock, data_sock, CURL_SOCKET_BAD, 0);
 
   /* see if the connection request is already here */
-  switch (result) {
+  switch(result) {
   case -1: /* error */
     /* let's die here */
     failf(data, "Error while waiting for server connect");
@@ -499,7 +499,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
   struct FTP *ftp = data->req.protop;
   CURLcode result = CURLE_OK;
 
-  if(conn->ssl[SECONDARYSOCKET].use) {
+  if(conn->bits.ftp_use_data_ssl) {
     /* since we only have a plaintext TCP connection here, we must now
      * do the TLS stuff */
     infof(data, "Doing the SSL/TLS handshake on the data stream\n");
@@ -547,7 +547,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
 static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
 {
   struct Curl_easy *data = conn->data;
-  long timeout_ms;
+  time_t timeout_ms;
   CURLcode result = CURLE_OK;
 
   *connected = FALSE;
@@ -687,8 +687,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
    * line in a response or continue reading.  */
 
   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
-  long timeout;              /* timeout in milliseconds */
-  long interval_ms;
+  time_t timeout;              /* timeout in milliseconds */
+  time_t interval_ms;
   struct Curl_easy *data = conn->data;
   CURLcode result = CURLE_OK;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
@@ -740,8 +740,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
        * wait for more data anyway.
        */
     }
-    else {
-      switch (SOCKET_READABLE(sockfd, interval_ms)) {
+    else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) {
+      switch(SOCKET_READABLE(sockfd, interval_ms)) {
       case -1: /* select() error, stop reading */
         failf(data, "FTP response aborted due to select/poll error: %d",
               SOCKERRNO);
@@ -1035,7 +1035,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
     if(*string_ftpport == '[') {
       /* [ipv6]:port(-range) */
       ip_start = string_ftpport + 1;
-      if((ip_end = strchr(string_ftpport, ']')) != NULL)
+      ip_end = strchr(string_ftpport, ']');
+      if(ip_end)
         strncpy(addr, ip_start, ip_end - ip_start);
     }
     else
@@ -1043,30 +1044,35 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
       if(*string_ftpport == ':') {
         /* :port */
         ip_end = string_ftpport;
-    }
-    else if((ip_end = strchr(string_ftpport, ':')) != NULL) {
-        /* either ipv6 or (ipv4|domain|interface):port(-range) */
-#ifdef ENABLE_IPV6
-      if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
-        /* ipv6 */
-        port_min = port_max = 0;
-        strcpy(addr, string_ftpport);
-        ip_end = NULL; /* this got no port ! */
       }
-      else
+      else {
+        ip_end = strchr(string_ftpport, ':');
+        if(ip_end) {
+          /* either ipv6 or (ipv4|domain|interface):port(-range) */
+#ifdef ENABLE_IPV6
+          if(Curl_inet_pton(AF_INET6, string_ftpport, sa6) == 1) {
+            /* ipv6 */
+            port_min = port_max = 0;
+            strcpy(addr, string_ftpport);
+            ip_end = NULL; /* this got no port ! */
+          }
+          else
 #endif
-        /* (ipv4|domain|interface):port(-range) */
-        strncpy(addr, string_ftpport, ip_end - ip_start);
-    }
-    else
-      /* ipv4|interface */
-      strcpy(addr, string_ftpport);
+            /* (ipv4|domain|interface):port(-range) */
+            strncpy(addr, string_ftpport, ip_end - ip_start);
+        }
+        else
+          /* ipv4|interface */
+          strcpy(addr, string_ftpport);
+      }
 
     /* parse the port */
     if(ip_end != NULL) {
-      if((port_start = strchr(ip_end, ':')) != NULL) {
+      port_start = strchr(ip_end, ':');
+      if(port_start) {
         port_min = curlx_ultous(strtoul(port_start+1, NULL, 10));
-        if((port_sep = strchr(port_start, '-')) != NULL) {
+        port_sep = strchr(port_start, '-');
+        if(port_sep) {
           port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10));
         }
         else
@@ -1850,84 +1856,6 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
   return result;
 }
 
-/*
- * Perform the necessary magic that needs to be done once the TCP connection
- * to the proxy has completed.
- */
-static CURLcode proxy_magic(struct connectdata *conn,
-                            char *newhost, unsigned short newport,
-                            bool *magicdone)
-{
-  CURLcode result = CURLE_OK;
-  struct Curl_easy *data = conn->data;
-
-#if defined(CURL_DISABLE_PROXY)
-  (void) newhost;
-  (void) newport;
-#endif
-
-  *magicdone = FALSE;
-
-  switch(conn->proxytype) {
-  case CURLPROXY_SOCKS5:
-  case CURLPROXY_SOCKS5_HOSTNAME:
-    result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost,
-                         newport, SECONDARYSOCKET, conn);
-    *magicdone = TRUE;
-    break;
-  case CURLPROXY_SOCKS4:
-    result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
-                         SECONDARYSOCKET, conn, FALSE);
-    *magicdone = TRUE;
-    break;
-  case CURLPROXY_SOCKS4A:
-    result = Curl_SOCKS4(conn->proxyuser, newhost, newport,
-                         SECONDARYSOCKET, conn, TRUE);
-    *magicdone = TRUE;
-    break;
-  case CURLPROXY_HTTP:
-  case CURLPROXY_HTTP_1_0:
-    /* do nothing here. handled later. */
-    break;
-  default:
-    failf(data, "unknown proxytype option given");
-    result = CURLE_COULDNT_CONNECT;
-    break;
-  }
-
-  if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
-    /* BLOCKING */
-    /* We want "seamless" FTP operations through HTTP proxy tunnel */
-
-    /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the
-     * member conn->proto.http; we want FTP through HTTP and we have to
-     * change the member temporarily for connecting to the HTTP proxy. After
-     * Curl_proxyCONNECT we have to set back the member to the original
-     * struct FTP pointer
-     */
-    struct HTTP http_proxy;
-    struct FTP *ftp_save = data->req.protop;
-    memset(&http_proxy, 0, sizeof(http_proxy));
-    data->req.protop = &http_proxy;
-
-    result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE);
-
-    data->req.protop = ftp_save;
-
-    if(result)
-      return result;
-
-    if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) {
-      /* the CONNECT procedure is not complete, the tunnel is not yet up */
-      state(conn, FTP_STOP); /* this phase is completed */
-      return result;
-    }
-    else
-      *magicdone = TRUE;
-  }
-
-  return result;
-}
 
 static char *control_address(struct connectdata *conn)
 {
@@ -1935,11 +1863,7 @@ static char *control_address(struct connectdata *conn)
      If a proxy tunnel is used, returns the original host name instead, because
      the effective control connection address is the proxy address,
      not the ftp host. */
-  if(conn->bits.tunnel_proxy ||
-     conn->proxytype == CURLPROXY_SOCKS5 ||
-     conn->proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
-     conn->proxytype == CURLPROXY_SOCKS4 ||
-     conn->proxytype == CURLPROXY_SOCKS4A)
+  if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
     return conn->host.name;
 
   return conn->ip_addr_str;
@@ -2063,7 +1987,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
      * here. We don't want to rely on a former host lookup that might've
      * expired now, instead we remake the lookup here and now!
      */
-    rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr);
+    const char * const host_name = conn->bits.socksproxy ?
+      conn->socks_proxy.host.name : conn->http_proxy.host.name;
+    rc = Curl_resolv(conn, host_name, (int)conn->port, &addr);
     if(rc == CURLRESOLV_PENDING)
       /* BLOCKING, ignores the return code but 'addr' will be NULL in
          case of failure */
@@ -2073,8 +1999,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
       (unsigned short)conn->port; /* we connect to the proxy's port */
 
     if(!addr) {
-      failf(data, "Can't resolve proxy host %s:%hu",
-            conn->proxy.name, connectport);
+      failf(data, "Can't resolve proxy host %s:%hu", host_name, connectport);
       return CURLE_FTP_CANT_GET_HOST;
     }
   }
@@ -2115,6 +2040,10 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
     /* this just dumps information about this second connection */
     ftp_pasv_verbose(conn, addr->addr, ftpc->newhost, connectport);
 
+  Curl_safefree(conn->secondaryhostname);
+  conn->secondaryhostname = strdup(ftpc->newhost);
+  conn->secondary_port = ftpc->newport;
+
   Curl_resolv_unlock(data, addr); /* we're done using this address */
   conn->bits.do_more = TRUE;
   state(conn, FTP_STOP); /* this phase is completed */
@@ -2763,7 +2692,10 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
       }
 #endif
 
-      if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
+      if(data->set.use_ssl &&
+         (!conn->ssl[FIRSTSOCKET].use ||
+          (conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
+           !conn->proxy_ssl[FIRSTSOCKET].use))) {
         /* We don't have a SSL/TLS connection yet, but FTPS is
            requested. Try a FTPS connection now */
 
@@ -2808,7 +2740,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
         /* Curl_ssl_connect is BLOCKING */
         result = Curl_ssl_connect(conn, FIRSTSOCKET);
         if(!result) {
-          conn->ssl[SECONDARYSOCKET].use = FALSE; /* clear-text data */
+          conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
           result = ftp_state_user(conn);
         }
       }
@@ -2850,7 +2782,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
     case FTP_PROT:
       if(ftpcode/100 == 2)
         /* We have enabled SSL for the data connection! */
-        conn->ssl[SECONDARYSOCKET].use =
+        conn->bits.ftp_use_data_ssl =
           (data->set.use_ssl != CURLUSESSL_CONTROL) ? TRUE : FALSE;
       /* FTP servers typically responds with 500 if they decide to reject
          our 'P' request */
@@ -3250,7 +3182,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
   ssize_t nread;
   int ftpcode;
   CURLcode result = CURLE_OK;
-  char *path;
+  char *path = NULL;
   const char *path_to_use = data->state.path;
 
   if(!ftp)
@@ -3666,10 +3598,6 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
     /* Ready to do more? */
     if(connected) {
       DEBUGF(infof(data, "DO-MORE connected phase starts\n"));
-      if(conn->bits.proxy) {
-        infof(data, "Connection to proxy confirmed\n");
-        result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected);
-      }
     }
     else {
       if(result && (ftpc->count1 == 0)) {
@@ -3681,6 +3609,18 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
     }
   }
 
+  result = Curl_proxy_connect(conn, SECONDARYSOCKET);
+  if(result)
+    return result;
+
+  if(CONNECT_SECONDARYSOCKET_PROXY_SSL())
+    return result;
+
+  if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
+     conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE)
+    return result;
+
+
   if(ftpc->state) {
     /* already in a state so skip the intial commands.
        They are only done to kickstart the do_more state */
@@ -3939,7 +3879,7 @@ static CURLcode wc_statemach(struct connectdata *conn)
   struct WildcardData * const wildcard = &(conn->data->wildcard);
   CURLcode result = CURLE_OK;
 
-  switch (wildcard->state) {
+  switch(wildcard->state) {
   case CURLWC_INIT:
     result = init_wc_data(conn);
     if(wildcard->state == CURLWC_CLEAN)
@@ -4246,8 +4186,8 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
   const char *cur_pos;
   const char *filename = NULL;
 
-  cur_pos = path_to_use; /* current position in path. point at the begin
-                            of next path component */
+  cur_pos = path_to_use; /* current position in path. point at the begin of
+                            next path component */
 
   ftpc->ctl_valid = FALSE;
   ftpc->cwdfail = FALSE;
@@ -4567,7 +4507,7 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
     command = Curl_raw_toupper(type[6]);
     conn->bits.type_set = TRUE;
 
-    switch (command) {
+    switch(command) {
     case 'A': /* ASCII mode */
       data->set.prefer_ascii = TRUE;
       break;
diff --git a/lib/ftp.h b/lib/ftp.h
index dbd8567..3bbf262 100644
--- a/lib/ftp.h
+++ b/lib/ftp.h
@@ -143,7 +143,7 @@ struct ftp_conn {
   ftpstate state_saved; /* transfer type saved to be reloaded after
                            data connection is established */
   curl_off_t retr_size_saved; /* Size of retrieved file saved */
-  char * server_os;     /* The target server operating system. */
+  char *server_os;     /* The target server operating system. */
   curl_off_t known_filesize; /* file size is different from -1, if wildcard
                                 LIST parsing was done and wc_statemach set
                                 it */
diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c
index 747dbba..f94b31b 100644
--- a/lib/ftplistparser.c
+++ b/lib/ftplistparser.c
@@ -396,9 +396,9 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
       }
     }
 
-    switch (parser->os_type) {
+    switch(parser->os_type) {
     case OS_TYPE_UNIX:
-      switch (parser->state.UNIX.main) {
+      switch(parser->state.UNIX.main) {
       case PL_UNIX_TOTALSIZE:
         switch(parser->state.UNIX.sub.total_dirsize) {
         case PL_UNIX_TOTALSIZE_INIT:
@@ -447,7 +447,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
         }
         break;
       case PL_UNIX_FILETYPE:
-        switch (c) {
+        switch(c) {
         case '-':
           finfo->filetype = CURLFILETYPE_FILE;
           break;
@@ -967,7 +967,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
         }
         break;
       case PL_WINNT_FILENAME:
-        switch (parser->state.NT.sub.filename) {
+        switch(parser->state.NT.sub.filename) {
         case PL_WINNT_FILENAME_PRESPACE:
           if(c != ' ') {
             parser->item_offset = finfo->b_used -1;
diff --git a/lib/getinfo.c b/lib/getinfo.c
index 9641d79..a1ce505 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -36,8 +36,11 @@
 #include "memdebug.h"
 
 /*
- * This is supposed to be called in the beginning of a perform() session and
- * in curl_easy_reset() and should reset all session-info variables.
+ * Initialize statistical and informational data.
+ *
+ * This function is called in curl_easy_reset, curl_easy_duphandle and at the
+ * beginning of a perform session. It must reset the session-info variables,
+ * in particular all variables in struct PureInfo.
  */
 CURLcode Curl_initinfo(struct Curl_easy *data)
 {
@@ -75,6 +78,9 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
   info->conn_primary_port = 0;
   info->conn_local_port = 0;
 
+  info->conn_scheme = 0;
+  info->conn_protocol = 0;
+
 #ifdef USE_SSL
   Curl_ssl_free_certinfo(data);
 #endif
@@ -83,7 +89,7 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
 }
 
 static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
-                             char **param_charp)
+                             const char **param_charp)
 {
   switch(info) {
   case CURLINFO_EFFECTIVE_URL:
@@ -120,6 +126,9 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info,
   case CURLINFO_RTSP_SESSION_ID:
     *param_charp = data->set.str[STRING_RTSP_SESSION_ID];
     break;
+  case CURLINFO_SCHEME:
+    *param_charp = data->info.conn_scheme;
+    break;
 
   default:
     return CURLE_UNKNOWN_OPTION;
@@ -157,6 +166,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
   case CURLINFO_SSL_VERIFYRESULT:
     *param_longp = data->set.ssl.certverifyresult;
     break;
+  case CURLINFO_PROXY_SSL_VERIFYRESULT:
+    *param_longp = data->set.proxy_ssl.certverifyresult;
+    break;
   case CURLINFO_REDIRECT_COUNT:
     *param_longp = data->set.followlocation;
     break;
@@ -208,7 +220,7 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
     *param_longp = data->state.rtsp_CSeq_recv;
     break;
   case CURLINFO_HTTP_VERSION:
-    switch (data->info.httpversion) {
+    switch(data->info.httpversion) {
     case 10:
       *param_longp = CURL_HTTP_VERSION_1_0;
       break;
@@ -223,6 +235,9 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
       break;
     }
     break;
+  case CURLINFO_PROTOCOL:
+    *param_longp = data->info.conn_protocol;
+    break;
 
   default:
     return CURLE_UNKNOWN_OPTION;
@@ -379,7 +394,7 @@ CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
   va_list arg;
   long *param_longp = NULL;
   double *param_doublep = NULL;
-  char **param_charp = NULL;
+  const char **param_charp = NULL;
   struct curl_slist **param_slistp = NULL;
   curl_socket_t *param_socketp = NULL;
   int type;
@@ -393,7 +408,7 @@ CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...)
   type = CURLINFO_TYPEMASK & (int)info;
   switch(type) {
   case CURLINFO_STRING:
-    param_charp = va_arg(arg, char **);
+    param_charp = va_arg(arg, const char **);
     if(param_charp)
       result = getinfo_char(data, info, param_charp);
     break;
diff --git a/lib/hash.c b/lib/hash.c
index 937381b..0655042 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -135,7 +135,7 @@ Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
 {
   struct curl_hash_element  *he;
   struct curl_llist_element *le;
-  struct curl_llist *l = FETCH_LIST (h, key, key_len);
+  struct curl_llist *l = FETCH_LIST(h, key, key_len);
 
   for(le = l->head; le; le = le->next) {
     he = (struct curl_hash_element *) le->ptr;
@@ -291,9 +291,9 @@ Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
   }
 }
 
-size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num)
+size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num)
 {
-  const char* key_str = (const char *) key;
+  const char *key_str = (const char *) key;
   const char *end = key_str + key_length;
   unsigned long h = 5381;
 
diff --git a/lib/hash.h b/lib/hash.h
index 57a17f0..a5a6cac 100644
--- a/lib/hash.h
+++ b/lib/hash.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -29,16 +29,16 @@
 #include "llist.h"
 
 /* Hash function prototype */
-typedef size_t (*hash_function) (void* key,
+typedef size_t (*hash_function) (void *key,
                                  size_t key_length,
                                  size_t slots_num);
 
 /*
    Comparator function prototype. Compares two keys.
 */
-typedef size_t (*comp_function) (void* key1,
+typedef size_t (*comp_function) (void *key1,
                                  size_t key1_len,
-                                 void*key2,
+                                 void *key2,
                                  size_t key2_len);
 
 typedef void (*curl_hash_dtor)(void *);
@@ -76,7 +76,7 @@ int Curl_hash_init(struct curl_hash *h,
 
 void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p);
 int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len);
-void *Curl_hash_pick(struct curl_hash *, void * key, size_t key_len);
+void *Curl_hash_pick(struct curl_hash *, void *key, size_t key_len);
 void Curl_hash_apply(struct curl_hash *h, void *user,
                      void (*cb)(void *user, void *ptr));
 int Curl_hash_count(struct curl_hash *h);
@@ -84,10 +84,9 @@ void Curl_hash_destroy(struct curl_hash *h);
 void Curl_hash_clean(struct curl_hash *h);
 void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user,
                                     int (*comp)(void *, void *));
-size_t Curl_hash_str(void* key, size_t key_length, size_t slots_num);
-size_t Curl_str_key_compare(void*k1, size_t key1_len, void*k2,
+size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num);
+size_t Curl_str_key_compare(void *k1, size_t key1_len, void *k2,
                             size_t key2_len);
-
 void Curl_hash_start_iterate(struct curl_hash *hash,
                              struct curl_hash_iterator *iter);
 struct curl_hash_element *
diff --git a/lib/hmac.c b/lib/hmac.c
index 3df4715..dae9505 100644
--- a/lib/hmac.c
+++ b/lib/hmac.c
@@ -49,12 +49,12 @@ static const unsigned char hmac_opad = 0x5C;
 
 HMAC_context *
 Curl_HMAC_init(const HMAC_params * hashparams,
-               const unsigned char * key,
+               const unsigned char *key,
                unsigned int keylen)
 {
   size_t i;
-  HMAC_context * ctxt;
-  unsigned char * hkey;
+  HMAC_context *ctxt;
+  unsigned char *hkey;
   unsigned char b;
 
   /* Create HMAC context. */
@@ -101,7 +101,7 @@ Curl_HMAC_init(const HMAC_params * hashparams,
 }
 
 int Curl_HMAC_update(HMAC_context * ctxt,
-                     const unsigned char * data,
+                     const unsigned char *data,
                      unsigned int len)
 {
   /* Update first hash calculation. */
@@ -110,7 +110,7 @@ int Curl_HMAC_update(HMAC_context * ctxt,
 }
 
 
-int Curl_HMAC_final(HMAC_context * ctxt, unsigned char * result)
+int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result)
 {
   const HMAC_params * hashparams = ctxt->hmac_hash;
 
diff --git a/lib/hostcheck.c b/lib/hostcheck.c
index f545254..cbd0893 100644
--- a/lib/hostcheck.c
+++ b/lib/hostcheck.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,7 +22,10 @@
 
 #include "curl_setup.h"
 
-#if defined(USE_OPENSSL) || defined(USE_AXTLS) || defined(USE_GSKIT)
+#if defined(USE_OPENSSL)                                \
+  || defined(USE_AXTLS)                                 \
+  || defined(USE_GSKIT)                                 \
+  || (defined(USE_SCHANNEL) && defined(_WIN32_WCE))
 /* these backends use functions from this file */
 
 #ifdef HAVE_NETINET_IN_H
@@ -144,4 +147,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
   return res;
 }
 
-#endif /* OPENSSL or AXTLS or GSKIT */
+#endif /* OPENSSL, AXTLS, GSKIT or schannel+wince */
diff --git a/lib/hostip.c b/lib/hostip.c
index 24a922e..fa4bad9 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -172,7 +172,7 @@ Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
   const struct in6_addr *ipaddr6;
 #endif
 
-  switch (ai->ai_family) {
+  switch(ai->ai_family) {
     case AF_INET:
       sa4 = (const void *)ai->ai_addr;
       ipaddr4 = &sa4->sin_addr;
@@ -568,7 +568,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
                         const char *hostname,
                         int port,
                         struct Curl_dns_entry **entry,
-                        long timeoutms)
+                        time_t timeoutms)
 {
 #ifdef USE_ALARM_TIMEOUT
 #ifdef HAVE_SIGACTION
diff --git a/lib/hostip.h b/lib/hostip.h
index 9098ee3..1dc4079 100644
--- a/lib/hostip.h
+++ b/lib/hostip.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -87,7 +87,7 @@ int Curl_resolv(struct connectdata *conn, const char *hostname,
                 int port, struct Curl_dns_entry **dnsentry);
 int Curl_resolv_timeout(struct connectdata *conn, const char *hostname,
                         int port, struct Curl_dns_entry **dnsentry,
-                        long timeoutms);
+                        time_t timeoutms);
 
 #ifdef CURLRES_IPV6
 /*
@@ -131,7 +131,7 @@ int Curl_mk_dnscache(struct curl_hash *hash);
 void Curl_hostcache_prune(struct Curl_easy *data);
 
 /* Return # of adresses in a Curl_addrinfo struct */
-int Curl_num_addresses (const Curl_addrinfo *addr);
+int Curl_num_addresses(const Curl_addrinfo *addr);
 
 #if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
 int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
@@ -143,7 +143,7 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
 #endif
 
 /* IPv4 threadsafe resolve function used for synch and asynch builds */
-Curl_addrinfo *Curl_ipv4_resolve_r(const char * hostname, int port);
+Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
 
 CURLcode Curl_async_resolved(struct connectdata *conn,
                              bool *protocol_connect);
diff --git a/lib/hostip4.c b/lib/hostip4.c
index 15895d7..e459328 100644
--- a/lib/hostip4.c
+++ b/lib/hostip4.c
@@ -291,7 +291,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
      * gethostbyname() is the preferred one.
      */
   else {
-    h = gethostbyname((void*)hostname);
+    h = gethostbyname((void *)hostname);
 #endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
   }
 
diff --git a/lib/http.c b/lib/http.c
index e7788e7..4c1c07f 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -76,6 +76,7 @@
 #include "pipeline.h"
 #include "http2.h"
 #include "connect.h"
+#include "strdup.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -287,8 +288,8 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
 
   if(proxy) {
     userp = &conn->allocptr.proxyuserpwd;
-    user = conn->proxyuser;
-    pwd = conn->proxypasswd;
+    user = conn->http_proxy.user;
+    pwd = conn->http_proxy.passwd;
   }
   else {
     userp = &conn->allocptr.userpwd;
@@ -544,8 +545,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
     }
   }
   if(http_should_fail(conn)) {
-    failf (data, "The requested URL returned error: %d",
-           data->req.httpcode);
+    failf(data, "The requested URL returned error: %d",
+          data->req.httpcode);
     result = CURLE_HTTP_RETURNED_ERROR;
   }
 
@@ -641,7 +642,7 @@ output_auth_headers(struct connectdata *conn,
   if(auth) {
     infof(data, "%s auth using %s with user '%s'\n",
           proxy ? "Proxy" : "Server", auth,
-          proxy ? (conn->proxyuser ? conn->proxyuser : "") :
+          proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") :
                   (conn->user ? conn->user : ""));
     authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
   }
@@ -839,9 +840,11 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
                   auth += strlen("NTLM");
                   while(*auth && ISSPACE(*auth))
                     auth++;
-                  if(*auth)
-                    if((conn->challenge_header = strdup(auth)) == NULL)
+                  if(*auth) {
+                    conn->challenge_header = strdup(auth);
+                    if(!conn->challenge_header)
                       return CURLE_OUT_OF_MEMORY;
+                  }
                 }
               }
 #endif
@@ -1098,7 +1101,9 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
     return result;
   }
 
-  if((conn->handler->flags & PROTOPT_SSL) && conn->httpversion != 20) {
+  if((conn->handler->flags & PROTOPT_SSL ||
+     conn->http_proxy.proxytype == CURLPROXY_HTTPS)
+     && conn->httpversion != 20) {
     /* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
        when we speak HTTPS, as if only a fraction of it is sent now, this data
        needs to fit into the normal read-callback buffer later on and that
@@ -1255,14 +1260,13 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
 
     if(in->buffer)
       /* we have a buffer, enlarge the existing one */
-      new_rb = realloc(in->buffer, new_size);
+      new_rb = Curl_saferealloc(in->buffer, new_size);
     else
       /* create a new buffer */
       new_rb = malloc(new_size);
 
     if(!new_rb) {
       /* If we failed, we cleanup the whole buffer and return error */
-      Curl_safefree(in->buffer);
       free(in);
       return CURLE_OUT_OF_MEMORY;
     }
@@ -1350,10 +1354,13 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
   connkeep(conn, "HTTP default");
 
   /* the CONNECT procedure might not have been completed */
-  result = Curl_proxy_connect(conn);
+  result = Curl_proxy_connect(conn, FIRSTSOCKET);
   if(result)
     return result;
 
+  if(CONNECT_FIRSTSOCKET_PROXY_SSL())
+    return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */
+
   if(conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)
     /* nothing else to do except wait right now - we're not done here. */
     return CURLE_OK;
@@ -1396,50 +1403,16 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
 
   return result;
 }
-#endif
 
-#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
-    defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \
-    defined(USE_MBEDTLS)
-/* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only.
-   It should be made to query the generic SSL layer instead. */
 static int https_getsock(struct connectdata *conn,
                          curl_socket_t *socks,
                          int numsocks)
 {
-  if(conn->handler->flags & PROTOPT_SSL) {
-    struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
-
-    if(!numsocks)
-      return GETSOCK_BLANK;
-
-    if(connssl->connecting_state == ssl_connect_2_writing) {
-      /* write mode */
-      socks[0] = conn->sock[FIRSTSOCKET];
-      return GETSOCK_WRITESOCK(0);
-    }
-    else if(connssl->connecting_state == ssl_connect_2_reading) {
-      /* read mode */
-      socks[0] = conn->sock[FIRSTSOCKET];
-      return GETSOCK_READSOCK(0);
-    }
-  }
-
-  return CURLE_OK;
-}
-#else
-#ifdef USE_SSL
-static int https_getsock(struct connectdata *conn,
-                         curl_socket_t *socks,
-                         int numsocks)
-{
-  (void)conn;
-  (void)socks;
-  (void)numsocks;
+  if(conn->handler->flags & PROTOPT_SSL)
+    return Curl_ssl_getsock(conn, socks, numsocks);
   return GETSOCK_BLANK;
 }
 #endif /* USE_SSL */
-#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */
 
 /*
  * Curl_http_done() gets called after a single HTTP request has been
@@ -2092,7 +2065,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
         /* when doing ftp, append ;type=<a|i> if not present */
         char *type = strstr(ppath, ";type=");
         if(type && type[6] && type[7] == 0) {
-          switch (Curl_raw_toupper(type[6])) {
+          switch(Curl_raw_toupper(type[6])) {
           case 'A':
           case 'D':
           case 'I':
@@ -2328,7 +2301,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
    * Free proxyuserpwd for Negotiate/NTLM. Cannot reuse as it is associated
    * with the connection and shouldn't be repeated over it either.
    */
-  switch (data->state.authproxy.picked) {
+  switch(data->state.authproxy.picked) {
   case CURLAUTH_NEGOTIATE:
   case CURLAUTH_NTLM:
   case CURLAUTH_NTLM_WB:
@@ -2782,7 +2755,7 @@ checkhttpprefix(struct Curl_easy *data,
   /* convert from the network encoding using a scratch area */
   char *scratch = strdup(s);
   if(NULL == scratch) {
-    failf (data, "Failed to allocate memory for conversion!");
+    failf(data, "Failed to allocate memory for conversion!");
     return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
   }
   if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
@@ -2820,7 +2793,7 @@ checkrtspprefix(struct Curl_easy *data,
   /* convert from the network encoding using a scratch area */
   char *scratch = strdup(s);
   if(NULL == scratch) {
-    failf (data, "Failed to allocate memory for conversion!");
+    failf(data, "Failed to allocate memory for conversion!");
     return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
   }
   if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
@@ -2872,8 +2845,8 @@ static CURLcode header_append(struct Curl_easy *data,
       /* The reason to have a max limit for this is to avoid the risk of a bad
          server feeding libcurl with a never-ending header that will cause
          reallocs infinitely */
-      failf (data, "Avoided giant realloc for header (max is %d)!",
-             CURL_MAX_HTTP_HEADER);
+      failf(data, "Avoided giant realloc for header (max is %d)!",
+            CURL_MAX_HTTP_HEADER);
       return CURLE_OUT_OF_MEMORY;
     }
 
@@ -2881,7 +2854,7 @@ static CURLcode header_append(struct Curl_easy *data,
     hbufp_index = k->hbufp - data->state.headerbuff;
     newbuff = realloc(data->state.headerbuff, newsize);
     if(!newbuff) {
-      failf (data, "Failed to alloc memory for big header!");
+      failf(data, "Failed to alloc memory for big header!");
       return CURLE_OUT_OF_MEMORY;
     }
     data->state.headersize=newsize;
@@ -3122,8 +3095,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
        * up and return an error.
        */
       if(http_should_fail(conn)) {
-        failf (data, "The requested URL returned error: %d",
-               k->httpcode);
+        failf(data, "The requested URL returned error: %d",
+              k->httpcode);
         return CURLE_HTTP_RETURNED_ERROR;
       }
 
diff --git a/lib/http2.c b/lib/http2.c
index cfdb327..4cc17ba 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -35,7 +35,7 @@
 #include "url.h"
 #include "connect.h"
 #include "strtoofft.h"
-
+#include "strdup.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -59,6 +59,12 @@
 #define nghttp2_session_callbacks_set_error_callback(x,y)
 #endif
 
+#if (NGHTTP2_VERSION_NUM >= 0x010c00)
+#define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1
+#endif
+
+#define HTTP2_HUGE_WINDOW_SIZE (1 << 30)
+
 /*
  * Curl_http2_init_state() is called when the easy handle is created and
  * allows for HTTP/2 specific init of state.
@@ -223,7 +229,8 @@ int Curl_http2_ver(char *p, size_t len)
 https://tools.ietf.org/html/rfc7540#page-77
 nghttp2_error_code enums are identical.
 */
-const char *Curl_http2_strerror(uint32_t err) {
+const char *Curl_http2_strerror(uint32_t err)
+{
 #ifndef NGHTTP2_HAS_HTTP2_STRERROR
   const char *str[] = {
     "NO_ERROR",             /* 0x0 */
@@ -841,10 +848,9 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
             stream->push_headers_alloc) {
       char **headp;
       stream->push_headers_alloc *= 2;
-      headp = realloc(stream->push_headers,
-                      stream->push_headers_alloc * sizeof(char *));
+      headp = Curl_saferealloc(stream->push_headers,
+                               stream->push_headers_alloc * sizeof(char *));
       if(!headp) {
-        free(stream->push_headers);
         stream->push_headers = NULL;
         return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
       }
@@ -966,7 +972,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
  */
 static nghttp2_settings_entry settings[] = {
   { NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 },
-  { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, NGHTTP2_INITIAL_WINDOW_SIZE },
+  { NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, HTTP2_HUGE_WINDOW_SIZE },
 };
 
 #define H2_BUFSIZE 32768
@@ -1572,6 +1578,72 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
 #define HEADER_OVERFLOW(x) \
   (x.namelen > (uint16_t)-1 || x.valuelen > (uint16_t)-1 - x.namelen)
 
+/*
+ * Check header memory for the token "trailers".
+ * Parse the tokens as separated by comma and surrounded by whitespace.
+ * Returns TRUE if found or FALSE if not.
+ */
+static bool contains_trailers(const char *p, size_t len)
+{
+  const char *end = p + len;
+  for(;;) {
+    for(; p != end && (*p == ' ' || *p == '\t'); ++p)
+      ;
+    if(p == end || (size_t)(end - p) < sizeof("trailers") - 1)
+      return FALSE;
+    if(strncasecompare("trailers", p, sizeof("trailers") - 1)) {
+      p += sizeof("trailers") - 1;
+      for(; p != end && (*p == ' ' || *p == '\t'); ++p)
+        ;
+      if(p == end || *p == ',')
+        return TRUE;
+    }
+    /* skip to next token */
+    for(; p != end && *p != ','; ++p)
+      ;
+    if(p == end)
+      return FALSE;
+    ++p;
+  }
+}
+
+typedef enum {
+  /* Send header to server */
+  HEADERINST_FORWARD,
+  /* Don't send header to server */
+  HEADERINST_IGNORE,
+  /* Discard header, and replace it with "te: trailers" */
+  HEADERINST_TE_TRAILERS
+} header_instruction;
+
+/* Decides how to treat given header field. */
+static header_instruction inspect_header(const char *name, size_t namelen,
+                                         const char *value, size_t valuelen) {
+  switch(namelen) {
+  case 2:
+    if(!strncasecompare("te", name, namelen))
+      return HEADERINST_FORWARD;
+
+    return contains_trailers(value, valuelen) ?
+           HEADERINST_TE_TRAILERS : HEADERINST_IGNORE;
+  case 7:
+    return strncasecompare("upgrade", name, namelen) ?
+           HEADERINST_IGNORE : HEADERINST_FORWARD;
+  case 10:
+    return (strncasecompare("connection", name, namelen) ||
+            strncasecompare("keep-alive", name, namelen)) ?
+           HEADERINST_IGNORE : HEADERINST_FORWARD;
+  case 16:
+    return strncasecompare("proxy-connection", name, namelen) ?
+           HEADERINST_IGNORE : HEADERINST_FORWARD;
+  case 17:
+    return strncasecompare("transfer-encoding", name, namelen) ?
+           HEADERINST_IGNORE : HEADERINST_FORWARD;
+  default:
+    return HEADERINST_FORWARD;
+  }
+}
+
 static ssize_t http2_send(struct connectdata *conn, int sockindex,
                           const void *mem, size_t len, CURLcode *err)
 {
@@ -1587,7 +1659,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
   size_t nheader;
   size_t i;
   size_t authority_idx;
-  char *hdbuf = (char*)mem;
+  char *hdbuf = (char *)mem;
   char *end, *line_end;
   nghttp2_data_provider data_prd;
   int32_t stream_id;
@@ -1725,7 +1797,6 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
   i = 3;
   while(i < nheader) {
     size_t hlen;
-    int skip = 0;
 
     hdbuf = line_end + 2;
 
@@ -1743,12 +1814,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
       goto fail;
     hlen = end - hdbuf;
 
-    if(hlen == 10 && strncasecompare("connection", hdbuf, 10)) {
-      /* skip Connection: headers! */
-      skip = 1;
-      --nheader;
-    }
-    else if(hlen == 4 && strncasecompare("host", hdbuf, 4)) {
+    if(hlen == 4 && strncasecompare("host", hdbuf, 4)) {
       authority_idx = i;
       nva[i].name = (unsigned char *)":authority";
       nva[i].namelen = strlen((char *)nva[i].name);
@@ -1761,16 +1827,28 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
     while(*hdbuf == ' ' || *hdbuf == '\t')
       ++hdbuf;
     end = line_end;
-    if(!skip) {
+
+    switch(inspect_header((const char *)nva[i].name, nva[i].namelen, hdbuf,
+                          end - hdbuf)) {
+    case HEADERINST_IGNORE:
+      /* skip header fields prohibited by HTTP/2 specification. */
+      --nheader;
+      continue;
+    case HEADERINST_TE_TRAILERS:
+      nva[i].value = (uint8_t*)"trailers";
+      nva[i].valuelen = sizeof("trailers") - 1;
+      break;
+    default:
       nva[i].value = (unsigned char *)hdbuf;
       nva[i].valuelen = (size_t)(end - hdbuf);
-      nva[i].flags = NGHTTP2_NV_FLAG_NONE;
-      if(HEADER_OVERFLOW(nva[i])) {
-        failf(conn->data, "Failed sending HTTP request: Header overflow");
-        goto fail;
-      }
-      ++i;
     }
+
+    nva[i].flags = NGHTTP2_NV_FLAG_NONE;
+    if(HEADER_OVERFLOW(nva[i])) {
+      failf(conn->data, "Failed sending HTTP request: Header overflow");
+      goto fail;
+    }
+    ++i;
   }
 
   /* :authority must come before non-pseudo header fields */
@@ -1961,7 +2039,8 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
   else {
     /* stream ID is unknown at this point */
     stream->stream_id = -1;
-    rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, NULL, 0);
+    rv = nghttp2_submit_settings(httpc->h2, NGHTTP2_FLAG_NONE, settings,
+                                 sizeof(settings) / sizeof(settings[0]));
     if(rv != 0) {
       failf(data, "nghttp2_submit_settings() failed: %s(%d)",
             nghttp2_strerror(rv), rv);
@@ -1969,6 +2048,16 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
     }
   }
 
+#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
+  rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0,
+                                             HTTP2_HUGE_WINDOW_SIZE);
+  if(rv != 0) {
+    failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
+          nghttp2_strerror(rv), rv);
+    return CURLE_HTTP2;
+  }
+#endif
+
   /* we are going to copy mem to httpc->inbuf.  This is required since
      mem is part of buffer pointed by stream->mem, and callbacks
      called by nghttp2_session_mem_recv() will write stream specific
@@ -1984,7 +2073,8 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
                     " after upgrade: len=%zu\n",
         nread);
 
-  memcpy(httpc->inbuf, mem, nread);
+  if(nread)
+    memcpy(httpc->inbuf, mem, nread);
   httpc->inbuflen = nread;
 
   nproc = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)httpc->inbuf,
@@ -2024,6 +2114,82 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
   return CURLE_OK;
 }
 
+void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child,
+                          bool exclusive)
+{
+  struct Curl_http2_dep **tail;
+  struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep));
+  dep->data = child;
+
+  if(parent->set.stream_dependents && exclusive) {
+    struct Curl_http2_dep *node = parent->set.stream_dependents;
+    while(node) {
+      node->data->set.stream_depends_on = child;
+      node = node->next;
+    }
+
+    tail = &child->set.stream_dependents;
+    while(*tail)
+      tail = &(*tail)->next;
+
+    DEBUGASSERT(!*tail);
+    *tail = parent->set.stream_dependents;
+    parent->set.stream_dependents = 0;
+  }
+
+  tail = &parent->set.stream_dependents;
+  while(*tail) {
+    (*tail)->data->set.stream_depends_e = FALSE;
+    tail = &(*tail)->next;
+  }
+
+  DEBUGASSERT(!*tail);
+  *tail = dep;
+
+  child->set.stream_depends_on = parent;
+  child->set.stream_depends_e = exclusive;
+}
+
+void Curl_http2_remove_child(struct Curl_easy *parent, struct Curl_easy *child)
+{
+  struct Curl_http2_dep *last = 0;
+  struct Curl_http2_dep *data = parent->set.stream_dependents;
+  DEBUGASSERT(child->set.stream_depends_on == parent);
+
+  while(data && data->data != child) {
+    last = data;
+    data = data->next;
+  }
+
+  DEBUGASSERT(data);
+
+  if(data) {
+    if(last) {
+      last->next = data->next;
+    }
+    else {
+      parent->set.stream_dependents = data->next;
+    }
+    free(data);
+  }
+
+  child->set.stream_depends_on = 0;
+  child->set.stream_depends_e = FALSE;
+}
+
+void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
+{
+  while(data->set.stream_dependents) {
+    struct Curl_easy *tmp = data->set.stream_dependents->data;
+    Curl_http2_remove_child(data, tmp);
+    if(data->set.stream_depends_on)
+      Curl_http2_add_child(data->set.stream_depends_on, tmp, FALSE);
+  }
+
+  if(data->set.stream_depends_on)
+    Curl_http2_remove_child(data->set.stream_depends_on, data);
+}
+
 #else /* !USE_NGHTTP2 */
 
 /* Satisfy external references even if http2 is not compiled in. */
diff --git a/lib/http2.h b/lib/http2.h
index 8917535..f405b3a 100644
--- a/lib/http2.h
+++ b/lib/http2.h
@@ -53,6 +53,11 @@ void Curl_http2_setup_conn(struct connectdata *conn);
 void Curl_http2_setup_req(struct Curl_easy *data);
 void Curl_http2_done(struct connectdata *conn, bool premature);
 CURLcode Curl_http2_done_sending(struct connectdata *conn);
+void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child,
+                          bool exclusive);
+void Curl_http2_remove_child(struct Curl_easy *parent,
+                             struct Curl_easy *child);
+void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
 #else /* USE_NGHTTP2 */
 #define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
@@ -65,6 +70,9 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn);
 #define Curl_http2_init_userset(x)
 #define Curl_http2_done(x,y)
 #define Curl_http2_done_sending(x)
+#define Curl_http2_add_child(x, y, z)
+#define Curl_http2_remove_child(x, y)
+#define Curl_http2_cleanup_dependencies(x)
 #endif
 
 #endif /* HEADER_CURL_HTTP2_H */
diff --git a/lib/http_chunks.c b/lib/http_chunks.c
index ea17109..1bdf697 100644
--- a/lib/http_chunks.c
+++ b/lib/http_chunks.c
@@ -190,8 +190,8 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
 
       /* Write the data portion available */
 #ifdef HAVE_LIBZ
-      switch (conn->data->set.http_ce_skip?
-              IDENTITY : data->req.auto_decoding) {
+      switch(conn->data->set.http_ce_skip?
+             IDENTITY : data->req.auto_decoding) {
       case IDENTITY:
 #endif
         if(!k->ignorebody) {
@@ -219,10 +219,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
         break;
 
       default:
-        failf (conn->data,
-               "Unrecognized content encoding type. "
-               "libcurl understands `identity', `deflate' and `gzip' "
-               "content encodings.");
+        failf(conn->data,
+              "Unrecognized content encoding type. "
+              "libcurl understands `identity', `deflate' and `gzip' "
+              "content encodings.");
         return CHUNKE_BAD_ENCODING;
       }
 #endif
@@ -360,7 +360,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
 
 const char *Curl_chunked_strerror(CHUNKcode code)
 {
-  switch (code) {
+  switch(code) {
   default:
     return "OK";
   case CHUNKE_TOO_LONG_HEX:
diff --git a/lib/http_digest.c b/lib/http_digest.c
index 184d00b..e2d865b 100644
--- a/lib/http_digest.c
+++ b/lib/http_digest.c
@@ -74,8 +74,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
 {
   CURLcode result;
   struct Curl_easy *data = conn->data;
-  unsigned char *path;
-  char *tmp;
+  unsigned char *path = NULL;
+  char *tmp = NULL;
   char *response;
   size_t len;
   bool have_chlg;
@@ -95,8 +95,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
   if(proxy) {
     digest = &data->state.proxydigest;
     allocuserpwd = &conn->allocptr.proxyuserpwd;
-    userp = conn->proxyuser;
-    passwdp = conn->proxypasswd;
+    userp = conn->http_proxy.user;
+    passwdp = conn->http_proxy.passwd;
     authp = &data->state.authproxy;
   }
   else {
@@ -140,12 +140,14 @@ CURLcode Curl_output_digest(struct connectdata *conn,
      http://www.fngtps.com/2006/09/http-authentication
   */
 
-  if(authp->iestyle && ((tmp = strchr((char *)uripath, '?')) != NULL)) {
-    size_t urilen = tmp - (char *)uripath;
-
-    path = (unsigned char *) aprintf("%.*s", urilen, uripath);
+  if(authp->iestyle) {
+    tmp = strchr((char *)uripath, '?');
+    if(tmp) {
+      size_t urilen = tmp - (char *)uripath;
+      path = (unsigned char *) aprintf("%.*s", urilen, uripath);
+    }
   }
-  else
+  if(!tmp)
     path = (unsigned char *) strdup((char *) uripath);
 
   if(!path)
diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c
index eb17ed4..51375e8 100644
--- a/lib/http_negotiate.c
+++ b/lib/http_negotiate.c
@@ -37,6 +37,7 @@
 CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
                               const char *header)
 {
+  CURLcode result;
   struct Curl_easy *data = conn->data;
   size_t len;
 
@@ -50,11 +51,11 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
   struct negotiatedata *neg_ctx;
 
   if(proxy) {
-    userp = conn->proxyuser;
-    passwdp = conn->proxypasswd;
+    userp = conn->http_proxy.user;
+    passwdp = conn->http_proxy.passwd;
     service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
               data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
-    host = conn->proxy.name;
+    host = conn->http_proxy.host.name;
     neg_ctx = &data->state.proxyneg;
   }
   else {
@@ -89,8 +90,13 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
   }
 
   /* Initilise the security context and decode our challenge */
-  return Curl_auth_decode_spnego_message(data, userp, passwdp, service, host,
-                                         header, neg_ctx);
+  result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
+                                           host, header, neg_ctx);
+
+  if(result)
+    Curl_auth_spnego_cleanup(neg_ctx);
+
+  return result;
 }
 
 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c
index e424040..21c77cd 100644
--- a/lib/http_ntlm.c
+++ b/lib/http_ntlm.c
@@ -136,8 +136,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
 
   if(proxy) {
     allocuserpwd = &conn->allocptr.proxyuserpwd;
-    userp = conn->proxyuser;
-    passwdp = conn->proxypasswd;
+    userp = conn->http_proxy.user;
+    passwdp = conn->http_proxy.passwd;
     ntlm = &conn->proxyntlm;
     authp = &conn->data->state.authproxy;
   }
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index 8f5e9b4..e0213f3 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -35,14 +35,50 @@
 #include "non-ascii.h"
 #include "connect.h"
 #include "curlx.h"
+#include "vtls/vtls.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "memdebug.h"
 
-CURLcode Curl_proxy_connect(struct connectdata *conn)
+/*
+ * Perform SSL initialization for HTTPS proxy.  Sets
+ * proxy_ssl_connected connection bit when complete.  Can be
+ * called multiple times.
+ */
+static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex)
+{
+#ifdef USE_SSL
+  CURLcode result = CURLE_OK;
+  DEBUGASSERT(conn->http_proxy.proxytype == CURLPROXY_HTTPS);
+  if(!conn->bits.proxy_ssl_connected[sockindex]) {
+    /* perform SSL initialization for this socket */
+    result =
+      Curl_ssl_connect_nonblocking(conn, sockindex,
+                                   &conn->bits.proxy_ssl_connected[sockindex]);
+    if(result)
+      conn->bits.close = TRUE; /* a failed connection is marked for closure to
+                                  prevent (bad) re-use or similar */
+  }
+  return result;
+#else
+  (void) conn;
+  (void) sockindex;
+  return CURLE_NOT_BUILT_IN;
+#endif
+}
+
+CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
 {
+  if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
+    const CURLcode result = https_proxy_connect(conn, sockindex);
+    if(result)
+      return result;
+    if(!conn->bits.proxy_ssl_connected[sockindex])
+      return result; /* wait for HTTPS proxy SSL initialization to complete */
+  }
+
   if(conn->bits.tunnel_proxy && conn->bits.httpproxy) {
 #ifndef CURL_DISABLE_PROXY
     /* for [protocol] tunneled through HTTP proxy */
@@ -68,15 +104,20 @@ CURLcode Curl_proxy_connect(struct connectdata *conn)
     memset(&http_proxy, 0, sizeof(http_proxy));
     conn->data->req.protop = &http_proxy;
     connkeep(conn, "HTTP proxy CONNECT");
-    if(conn->bits.conn_to_host)
+    if(sockindex == SECONDARYSOCKET)
+      hostname = conn->secondaryhostname;
+    else if(conn->bits.conn_to_host)
       hostname = conn->conn_to_host.name;
     else
       hostname = conn->host.name;
-    if(conn->bits.conn_to_port)
+
+    if(sockindex == SECONDARYSOCKET)
+      remote_port = conn->secondary_port;
+    else if(conn->bits.conn_to_port)
       remote_port = conn->conn_to_port;
     else
       remote_port = conn->remote_port;
-    result = Curl_proxyCONNECT(conn, FIRSTSOCKET, hostname,
+    result = Curl_proxyCONNECT(conn, sockindex, hostname,
                                remote_port, FALSE);
     conn->data->req.protop = prot_save;
     if(CURLE_OK != result)
@@ -113,7 +154,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
   curl_off_t cl=0;
   bool closeConnection = FALSE;
   bool chunked_encoding = FALSE;
-  long check;
+  time_t check;
 
 #define SELECT_OK      0
 #define SELECT_ERROR   1
@@ -161,7 +202,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
         char *host=(char *)"";
         const char *proxyconn="";
         const char *useragent="";
-        const char *http = (conn->proxytype == CURLPROXY_HTTP_1_0) ?
+        const char *http = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ?
           "1.0" : "1.1";
         bool ipv6_ip = conn->bits.ipv6_ip;
         char *hostheader;
@@ -244,7 +285,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
     }
 
     if(!blocking) {
-      if(0 == SOCKET_READABLE(tunnelsocket, 0))
+      if(!Curl_conn_data_pending(conn, sockindex))
         /* return so we'll be called again polling-style */
         return CURLE_OK;
       else {
@@ -263,13 +304,22 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
       char *ptr;
       char *line_start;
 
-      ptr=data->state.buffer;
+      ptr = data->state.buffer;
       line_start = ptr;
 
-      nread=0;
-      perline=0;
+      nread = 0;
+      perline = 0;
+
+      while(nread < BUFSIZE && keepon && !error) {
+        int writetype;
 
-      while((nread<BUFSIZE) && (keepon && !error)) {
+        if(Curl_pgrsUpdate(conn))
+          return CURLE_ABORTED_BY_CALLBACK;
+
+        if(ptr >= &data->state.buffer[BUFSIZE]) {
+          failf(data, "CONNECT response too large!");
+          return CURLE_RECV_ERROR;
+        }
 
         check = Curl_timeleft(data, NULL, TRUE);
         if(check <= 0) {
@@ -278,253 +328,233 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
           break;
         }
 
-        /* loop every second at least, less if the timeout is near */
-        switch (SOCKET_READABLE(tunnelsocket, check<1000L?check:1000)) {
-        case -1: /* select() error, stop reading */
-          error = SELECT_ERROR;
-          failf(data, "Proxy CONNECT aborted due to select/poll error");
+        /* Read one byte at a time to avoid a race condition. Wait at most one
+           second before looping to ensure continuous pgrsUpdates. */
+        result = Curl_read(conn, tunnelsocket, ptr, 1, &gotbytes);
+        if(result == CURLE_AGAIN) {
+          if(SOCKET_READABLE(tunnelsocket, check<1000L?check:1000) == -1) {
+            error = SELECT_ERROR;
+            failf(data, "Proxy CONNECT aborted due to select/poll error");
+            break;
+          }
+          continue;
+        }
+        else if(result) {
+          keepon = FALSE;
           break;
-        case 0: /* timeout */
+        }
+        else if(gotbytes <= 0) {
+          if(data->set.proxyauth && data->state.authproxy.avail) {
+            /* proxy auth was requested and there was proxy auth available,
+               then deem this as "mere" proxy disconnect */
+            conn->bits.proxy_connect_closed = TRUE;
+            infof(data, "Proxy CONNECT connection closed\n");
+          }
+          else {
+            error = SELECT_ERROR;
+            failf(data, "Proxy CONNECT aborted");
+          }
+          keepon = FALSE;
           break;
-        default:
-          DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1);
-          result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread,
-                             &gotbytes);
-          if(result==CURLE_AGAIN)
-            continue; /* go loop yourself */
-          else if(result)
-            keepon = FALSE;
-          else if(gotbytes <= 0) {
-            keepon = FALSE;
-            if(data->set.proxyauth && data->state.authproxy.avail) {
-              /* proxy auth was requested and there was proxy auth available,
-                 then deem this as "mere" proxy disconnect */
-              conn->bits.proxy_connect_closed = TRUE;
-              infof(data, "Proxy CONNECT connection closed\n");
-            }
-            else {
-              error = SELECT_ERROR;
-              failf(data, "Proxy CONNECT aborted");
+        }
+
+        /* We got a byte of data */
+        nread++;
+
+        if(keepon > TRUE) {
+          /* This means we are currently ignoring a response-body */
+
+          nread = 0; /* make next read start over in the read buffer */
+          ptr = data->state.buffer;
+          if(cl) {
+            /* A Content-Length based body: simply count down the counter
+               and make sure to break out of the loop when we're done! */
+            cl--;
+            if(cl <= 0) {
+              keepon = FALSE;
+              break;
             }
           }
           else {
-            /*
-             * We got a whole chunk of data, which can be anything from one
-             * byte to a set of lines and possibly just a piece of the last
-             * line.
-             */
-            int i;
-
-            nread += gotbytes;
-
-            if(keepon > TRUE) {
-              /* This means we are currently ignoring a response-body */
-
-              nread = 0; /* make next read start over in the read buffer */
-              ptr=data->state.buffer;
-              if(cl) {
-                /* A Content-Length based body: simply count down the counter
-                   and make sure to break out of the loop when we're done! */
-                cl -= gotbytes;
-                if(cl<=0) {
-                  keepon = FALSE;
-                  break;
-                }
+            /* chunked-encoded body, so we need to do the chunked dance
+               properly to know when the end of the body is reached */
+            CHUNKcode r;
+            ssize_t tookcareof = 0;
+
+            /* now parse the chunked piece of data so that we can
+               properly tell when the stream ends */
+            r = Curl_httpchunk_read(conn, ptr, 1, &tookcareof);
+            if(r == CHUNKE_STOP) {
+              /* we're done reading chunks! */
+              infof(data, "chunk reading DONE\n");
+              keepon = FALSE;
+              /* we did the full CONNECT treatment, go COMPLETE */
+              conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+            }
+          }
+          continue;
+        }
+
+        perline++; /* amount of bytes in this line so far */
+
+        /* if this is not the end of a header line then continue */
+        if(*ptr != 0x0a) {
+          ptr++;
+          continue;
+        }
+
+        /* convert from the network encoding */
+        result = Curl_convert_from_network(data, line_start, perline);
+        /* Curl_convert_from_network calls failf if unsuccessful */
+        if(result)
+          return result;
+
+        /* output debug if that is requested */
+        if(data->set.verbose)
+          Curl_debug(data, CURLINFO_HEADER_IN,
+                     line_start, (size_t)perline, conn);
+
+        /* send the header to the callback */
+        writetype = CLIENTWRITE_HEADER;
+        if(data->set.include_header)
+          writetype |= CLIENTWRITE_BODY;
+
+        result = Curl_client_write(conn, writetype, line_start, perline);
+
+        data->info.header_size += (long)perline;
+        data->req.headerbytecount += (long)perline;
+
+        if(result)
+          return result;
+
+        /* Newlines are CRLF, so the CR is ignored as the line isn't
+           really terminated until the LF comes. Treat a following CR
+           as end-of-headers as well.*/
+
+        if(('\r' == line_start[0]) ||
+           ('\n' == line_start[0])) {
+          /* end of response-headers from the proxy */
+          nread = 0; /* make next read start over in the read
+                        buffer */
+          ptr = data->state.buffer;
+          if((407 == k->httpcode) && !data->state.authproblem) {
+            /* If we get a 407 response code with content length
+               when we have no auth problem, we must ignore the
+               whole response-body */
+            keepon = 2;
+
+            if(cl) {
+              infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
+                    " bytes of response-body\n", cl);
+            }
+            else if(chunked_encoding) {
+              CHUNKcode r;
+
+              infof(data, "Ignore chunked response-body\n");
+
+              /* We set ignorebody true here since the chunked
+                 decoder function will acknowledge that. Pay
+                 attention so that this is cleared again when this
+                 function returns! */
+              k->ignorebody = TRUE;
+
+              if(line_start[1] == '\n') {
+                /* this can only be a LF if the letter at index 0
+                   was a CR */
+                line_start++;
               }
-              else {
-                /* chunked-encoded body, so we need to do the chunked dance
-                   properly to know when the end of the body is reached */
-                CHUNKcode r;
-                ssize_t tookcareof=0;
-
-                /* now parse the chunked piece of data so that we can
-                   properly tell when the stream ends */
-                r = Curl_httpchunk_read(conn, ptr, gotbytes, &tookcareof);
-                if(r == CHUNKE_STOP) {
-                  /* we're done reading chunks! */
-                  infof(data, "chunk reading DONE\n");
-                  keepon = FALSE;
-                  /* we did the full CONNECT treatment, go COMPLETE */
-                  conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
-                }
-                else
-                  infof(data, "Read %zd bytes of chunk, continue\n",
-                        tookcareof);
+
+              /* now parse the chunked piece of data so that we can
+                 properly tell when the stream ends */
+              r = Curl_httpchunk_read(conn, line_start + 1, 1, &gotbytes);
+              if(r == CHUNKE_STOP) {
+                /* we're done reading chunks! */
+                infof(data, "chunk reading DONE\n");
+                keepon = FALSE;
+                /* we did the full CONNECT treatment, go to
+                   COMPLETE */
+                conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
               }
             }
-            else
-              for(i = 0; i < gotbytes; ptr++, i++) {
-                perline++; /* amount of bytes in this line so far */
-                if(*ptr == 0x0a) {
-                  char letter;
-                  int writetype;
-
-                  /* convert from the network encoding */
-                  result = Curl_convert_from_network(data, line_start,
-                                                     perline);
-                  /* Curl_convert_from_network calls failf if unsuccessful */
-                  if(result)
-                    return result;
-
-                  /* output debug if that is requested */
-                  if(data->set.verbose)
-                    Curl_debug(data, CURLINFO_HEADER_IN,
-                               line_start, (size_t)perline, conn);
-
-                  /* send the header to the callback */
-                  writetype = CLIENTWRITE_HEADER;
-                  if(data->set.include_header)
-                    writetype |= CLIENTWRITE_BODY;
-
-                  result = Curl_client_write(conn, writetype, line_start,
-                                             perline);
-
-                  data->info.header_size += (long)perline;
-                  data->req.headerbytecount += (long)perline;
-
-                  if(result)
-                    return result;
-
-                  /* Newlines are CRLF, so the CR is ignored as the line isn't
-                     really terminated until the LF comes. Treat a following CR
-                     as end-of-headers as well.*/
-
-                  if(('\r' == line_start[0]) ||
-                     ('\n' == line_start[0])) {
-                    /* end of response-headers from the proxy */
-                    nread = 0; /* make next read start over in the read
-                                  buffer */
-                    ptr=data->state.buffer;
-                    if((407 == k->httpcode) && !data->state.authproblem) {
-                      /* If we get a 407 response code with content length
-                         when we have no auth problem, we must ignore the
-                         whole response-body */
-                      keepon = 2;
-
-                      if(cl) {
-                        infof(data, "Ignore %" CURL_FORMAT_CURL_OFF_T
-                              " bytes of response-body\n", cl);
-
-                        /* remove the remaining chunk of what we already
-                           read */
-                        cl -= (gotbytes - i);
-
-                        if(cl<=0)
-                          /* if the whole thing was already read, we are done!
-                           */
-                          keepon=FALSE;
-                      }
-                      else if(chunked_encoding) {
-                        CHUNKcode r;
-                        /* We set ignorebody true here since the chunked
-                           decoder function will acknowledge that. Pay
-                           attention so that this is cleared again when this
-                           function returns! */
-                        k->ignorebody = TRUE;
-                        infof(data, "%zd bytes of chunk left\n", gotbytes-i);
-
-                        if(line_start[1] == '\n') {
-                          /* this can only be a LF if the letter at index 0
-                             was a CR */
-                          line_start++;
-                          i++;
-                        }
-
-                        /* now parse the chunked piece of data so that we can
-                           properly tell when the stream ends */
-                        r = Curl_httpchunk_read(conn, line_start+1,
-                                                  gotbytes -i, &gotbytes);
-                        if(r == CHUNKE_STOP) {
-                          /* we're done reading chunks! */
-                          infof(data, "chunk reading DONE\n");
-                          keepon = FALSE;
-                          /* we did the full CONNECT treatment, go to
-                             COMPLETE */
-                          conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
-                        }
-                        else
-                          infof(data, "Read %zd bytes of chunk, continue\n",
-                                gotbytes);
-                      }
-                      else {
-                        /* without content-length or chunked encoding, we
-                           can't keep the connection alive since the close is
-                           the end signal so we bail out at once instead */
-                        keepon=FALSE;
-                      }
-                    }
-                    else {
-                      keepon = FALSE;
-                      if(200 == data->info.httpproxycode) {
-                        if(gotbytes - (i+1))
-                          failf(data, "Proxy CONNECT followed by %zd bytes "
-                                "of opaque data. Data ignored (known bug #39)",
-                                gotbytes - (i+1));
-                      }
-                    }
-                    /* we did the full CONNECT treatment, go to COMPLETE */
-                    conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
-                    break; /* breaks out of for-loop, not switch() */
-                  }
-
-                  /* keep a backup of the position we are about to blank */
-                  letter = line_start[perline];
-                  line_start[perline]=0; /* zero terminate the buffer */
-                  if((checkprefix("WWW-Authenticate:", line_start) &&
-                      (401 == k->httpcode)) ||
-                     (checkprefix("Proxy-authenticate:", line_start) &&
-                      (407 == k->httpcode))) {
-
-                    bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
-                    char *auth = Curl_copy_header_value(line_start);
-                    if(!auth)
-                      return CURLE_OUT_OF_MEMORY;
-
-                    result = Curl_http_input_auth(conn, proxy, auth);
-
-                    free(auth);
-
-                    if(result)
-                      return result;
-                  }
-                  else if(checkprefix("Content-Length:", line_start)) {
-                    cl = curlx_strtoofft(line_start +
-                                         strlen("Content-Length:"), NULL, 10);
-                  }
-                  else if(Curl_compareheader(line_start,
-                                             "Connection:", "close"))
-                    closeConnection = TRUE;
-                  else if(Curl_compareheader(line_start,
-                                             "Transfer-Encoding:",
-                                             "chunked")) {
-                    infof(data, "CONNECT responded chunked\n");
-                    chunked_encoding = TRUE;
-                    /* init our chunky engine */
-                    Curl_httpchunk_init(conn);
-                  }
-                  else if(Curl_compareheader(line_start,
-                                             "Proxy-Connection:", "close"))
-                    closeConnection = TRUE;
-                  else if(2 == sscanf(line_start, "HTTP/1.%d %d",
-                                      &subversion,
-                                      &k->httpcode)) {
-                    /* store the HTTP code from the proxy */
-                    data->info.httpproxycode = k->httpcode;
-                  }
-                  /* put back the letter we blanked out before */
-                  line_start[perline]= letter;
-
-                  perline=0; /* line starts over here */
-                  line_start = ptr+1; /* this skips the zero byte we wrote */
-                }
-              }
+            else {
+              /* without content-length or chunked encoding, we
+                 can't keep the connection alive since the close is
+                 the end signal so we bail out at once instead */
+              keepon = FALSE;
+            }
           }
-          break;
-        } /* switch */
-        if(Curl_pgrsUpdate(conn))
-          return CURLE_ABORTED_BY_CALLBACK;
+          else
+            keepon = FALSE;
+          /* we did the full CONNECT treatment, go to COMPLETE */
+          conn->tunnel_state[sockindex] = TUNNEL_COMPLETE;
+          continue;
+        }
+
+        line_start[perline] = 0; /* zero terminate the buffer */
+        if((checkprefix("WWW-Authenticate:", line_start) &&
+            (401 == k->httpcode)) ||
+           (checkprefix("Proxy-authenticate:", line_start) &&
+            (407 == k->httpcode))) {
+
+          bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
+          char *auth = Curl_copy_header_value(line_start);
+          if(!auth)
+            return CURLE_OUT_OF_MEMORY;
+
+          result = Curl_http_input_auth(conn, proxy, auth);
+
+          free(auth);
+
+          if(result)
+            return result;
+        }
+        else if(checkprefix("Content-Length:", line_start)) {
+          if(k->httpcode/100 == 2) {
+            /* A server MUST NOT send any Transfer-Encoding or
+               Content-Length header fields in a 2xx (Successful)
+               response to CONNECT. (RFC 7231 section 4.3.6) */
+            failf(data, "Content-Length: in %03d response",
+                  k->httpcode);
+            return CURLE_RECV_ERROR;
+          }
+
+          cl = curlx_strtoofft(line_start +
+                               strlen("Content-Length:"), NULL, 10);
+        }
+        else if(Curl_compareheader(line_start, "Connection:", "close"))
+          closeConnection = TRUE;
+        else if(Curl_compareheader(line_start,
+                                   "Transfer-Encoding:",
+                                   "chunked")) {
+          if(k->httpcode/100 == 2) {
+            /* A server MUST NOT send any Transfer-Encoding or
+               Content-Length header fields in a 2xx (Successful)
+               response to CONNECT. (RFC 7231 section 4.3.6) */
+            failf(data, "Transfer-Encoding: in %03d response", k->httpcode);
+            return CURLE_RECV_ERROR;
+          }
+          infof(data, "CONNECT responded chunked\n");
+          chunked_encoding = TRUE;
+          /* init our chunky engine */
+          Curl_httpchunk_init(conn);
+        }
+        else if(Curl_compareheader(line_start, "Proxy-Connection:", "close"))
+          closeConnection = TRUE;
+        else if(2 == sscanf(line_start, "HTTP/1.%d %d",
+                            &subversion,
+                            &k->httpcode)) {
+          /* store the HTTP code from the proxy */
+          data->info.httpproxycode = k->httpcode;
+        }
+
+        perline = 0; /* line starts over here */
+        ptr = data->state.buffer;
+        line_start = ptr;
       } /* while there's buffer left and loop is requested */
 
+      if(Curl_pgrsUpdate(conn))
+        return CURLE_ABORTED_BY_CALLBACK;
+
       if(error)
         return CURLE_RECV_ERROR;
 
@@ -538,8 +568,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
         if(conn->bits.close)
           /* the connection has been marked for closure, most likely in the
              Curl_http_auth_act() function and thus we can kill it at once
-             below
-          */
+             below */
           closeConnection = TRUE;
       }
 
@@ -600,7 +629,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
 
   data->state.authproxy.done = TRUE;
 
-  infof (data, "Proxy replied OK to CONNECT request\n");
+  infof(data, "Proxy replied OK to CONNECT request\n");
   data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */
   conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the
                                          document request  */
diff --git a/lib/http_proxy.h b/lib/http_proxy.h
index fd04330..d1f5a7c 100644
--- a/lib/http_proxy.h
+++ b/lib/http_proxy.h
@@ -32,11 +32,11 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
 /* Default proxy timeout in milliseconds */
 #define PROXY_TIMEOUT (3600*1000)
 
-CURLcode Curl_proxy_connect(struct connectdata *conn);
+CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex);
 
 #else
 #define Curl_proxyCONNECT(x,y,z,w,v) CURLE_NOT_BUILT_IN
-#define Curl_proxy_connect(x) CURLE_OK
+#define Curl_proxy_connect(x,y) CURLE_OK
 #endif
 
 #endif /* HEADER_CURL_HTTP_PROXY_H */
diff --git a/lib/if2ip.c b/lib/if2ip.c
index e6faa4b..d876615 100644
--- a/lib/if2ip.c
+++ b/lib/if2ip.c
@@ -68,7 +68,7 @@ unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
 #else
   if(sa->sa_family == AF_INET6) {
     const struct sockaddr_in6 * sa6 = (const struct sockaddr_in6 *)(void *) sa;
-    const unsigned char * b = sa6->sin6_addr.s6_addr;
+    const unsigned char *b = sa6->sin6_addr.s6_addr;
     unsigned short w = (unsigned short) ((b[0] << 8) | b[1]);
 
     switch(w & 0xFFC0) {
diff --git a/lib/imap.c b/lib/imap.c
index 4aa7dcc..78dc6fa 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -107,7 +107,7 @@ static CURLcode imap_perform_authenticate(struct connectdata *conn,
                                           const char *initresp);
 static CURLcode imap_continue_authenticate(struct connectdata *conn,
                                            const char *resp);
-static void imap_get_message(char *buffer, char** outptr);
+static void imap_get_message(char *buffer, char **outptr);
 
 /*
  * IMAP protocol handler.
@@ -390,10 +390,10 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
  *
  * Gets the authentication message from the response buffer.
  */
-static void imap_get_message(char *buffer, char** outptr)
+static void imap_get_message(char *buffer, char **outptr)
 {
   size_t len = 0;
-  char* message = NULL;
+  char *message = NULL;
 
   /* Find the start of the message */
   for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c
index 416005c..9afbdbb 100644
--- a/lib/inet_ntop.c
+++ b/lib/inet_ntop.c
@@ -182,12 +182,12 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
  */
 char *Curl_inet_ntop(int af, const void *src, char *buf, size_t size)
 {
-  switch (af) {
+  switch(af) {
   case AF_INET:
-    return inet_ntop4((const unsigned char*)src, buf, size);
+    return inet_ntop4((const unsigned char *)src, buf, size);
 #ifdef ENABLE_IPV6
   case AF_INET6:
-    return inet_ntop6((const unsigned char*)src, buf, size);
+    return inet_ntop6((const unsigned char *)src, buf, size);
 #endif
   default:
     SET_ERRNO(EAFNOSUPPORT);
diff --git a/lib/inet_pton.c b/lib/inet_pton.c
index cf8b88a..475f44a 100644
--- a/lib/inet_pton.c
+++ b/lib/inet_pton.c
@@ -65,7 +65,7 @@ static int      inet_pton6(const char *src, unsigned char *dst);
 int
 Curl_inet_pton(int af, const char *src, void *dst)
 {
-  switch (af) {
+  switch(af) {
   case AF_INET:
     return (inet_pton4(src, (unsigned char *)dst));
 #ifdef ENABLE_IPV6
@@ -103,7 +103,8 @@ inet_pton4(const char *src, unsigned char *dst)
   while((ch = *src++) != '\0') {
     const char *pch;
 
-    if((pch = strchr(digits, ch)) != NULL) {
+    pch = strchr(digits, ch);
+    if(pch) {
       unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
 
       if(saw_digit && *tp == 0)
@@ -169,7 +170,8 @@ inet_pton6(const char *src, unsigned char *dst)
   while((ch = *src++) != '\0') {
     const char *pch;
 
-    if((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+    pch = strchr((xdigits = xdigits_l), ch);
+    if(!pch)
       pch = strchr((xdigits = xdigits_u), ch);
     if(pch != NULL) {
       val <<= 4;
diff --git a/lib/krb5.c b/lib/krb5.c
index 5d5c003..067b0a5 100644
--- a/lib/krb5.c
+++ b/lib/krb5.c
@@ -121,7 +121,7 @@ krb5_encode(void *app_data, const void *from, int length, int level, void **to)
   /* NOTE that the cast is safe, neither of the krb5, gnu gss and heimdal
    * libraries modify the input buffer in gss_seal()
    */
-  dec.value = (void*)from;
+  dec.value = (void *)from;
   dec.length = length;
   maj = gss_seal(&min, *context,
                  level == PROT_PRIVATE,
diff --git a/lib/ldap.c b/lib/ldap.c
index 7dbc1b0..979ce7d 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -109,9 +109,9 @@ typedef struct {
 #undef LDAPURLDesc
 #define LDAPURLDesc             CURL_LDAPURLDesc
 
-static int  _ldap_url_parse (const struct connectdata *conn,
-                             LDAPURLDesc **ludp);
-static void _ldap_free_urldesc (LDAPURLDesc *ludp);
+static int  _ldap_url_parse(const struct connectdata *conn,
+                            LDAPURLDesc **ludp);
+static void _ldap_free_urldesc(LDAPURLDesc *ludp);
 
 #undef ldap_free_urldesc
 #define ldap_free_urldesc       _ldap_free_urldesc
@@ -119,11 +119,11 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp);
 
 #ifdef DEBUG_LDAP
   #define LDAP_TRACE(x)   do { \
-                            _ldap_trace ("%u: ", __LINE__); \
+                            _ldap_trace("%u: ", __LINE__); \
                             _ldap_trace x; \
                           } WHILE_FALSE
 
-  static void _ldap_trace (const char *fmt, ...);
+  static void _ldap_trace(const char *fmt, ...);
 #else
   #define LDAP_TRACE(x)   Curl_nop_stmt
 #endif
@@ -271,7 +271,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
     ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
 #else
     int ldap_option;
-    char* ldap_ca = data->set.str[STRING_SSL_CAFILE];
+    char *ldap_ca = conn->ssl_config.CAfile;
 #if defined(CURL_HAS_NOVELL_LDAPSDK)
     rc = ldapssl_client_init(NULL, NULL);
     if(rc != LDAP_SUCCESS) {
@@ -279,11 +279,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       result = CURLE_SSL_CERTPROBLEM;
       goto quit;
     }
-    if(data->set.ssl.verifypeer) {
+    if(conn->ssl_config.verifypeer) {
       /* Novell SDK supports DER or BASE64 files. */
       int cert_type = LDAPSSL_CERT_FILETYPE_B64;
-      if((data->set.str[STRING_CERT_TYPE]) &&
-         (strcasecompare(data->set.str[STRING_CERT_TYPE], "DER")))
+      if((data->set.ssl.cert_type) &&
+         (strcasecompare(data->set.ssl.cert_type, "DER")))
         cert_type = LDAPSSL_CERT_FILETYPE_DER;
       if(!ldap_ca) {
         failf(data, "LDAP local: ERROR %s CA cert not set!",
@@ -321,10 +321,10 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       goto quit;
     }
 #elif defined(LDAP_OPT_X_TLS)
-    if(data->set.ssl.verifypeer) {
+    if(conn->ssl_config.verifypeer) {
       /* OpenLDAP SDK supports BASE64 files. */
-      if((data->set.str[STRING_CERT_TYPE]) &&
-         (!strcasecompare(data->set.str[STRING_CERT_TYPE], "PEM"))) {
+      if((data->set.ssl.cert_type) &&
+         (!strcasecompare(data->set.ssl.cert_type, "PEM"))) {
         failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!");
         result = CURLE_SSL_CERTPROBLEM;
         goto quit;
@@ -655,7 +655,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
 quit:
   if(ldapmsg) {
     ldap_msgfree(ldapmsg);
-    LDAP_TRACE (("Received %d entries\n", num));
+    LDAP_TRACE(("Received %d entries\n", num));
   }
   if(rc == LDAP_SIZELIMIT_EXCEEDED)
     infof(data, "There are more than %d entries\n", num);
@@ -682,7 +682,7 @@ quit:
 }
 
 #ifdef DEBUG_LDAP
-static void _ldap_trace (const char *fmt, ...)
+static void _ldap_trace(const char *fmt, ...)
 {
   static int do_trace = -1;
   va_list args;
@@ -694,9 +694,9 @@ static void _ldap_trace (const char *fmt, ...)
   if(!do_trace)
     return;
 
-  va_start (args, fmt);
-  vfprintf (stderr, fmt, args);
-  va_end (args);
+  va_start(args, fmt);
+  vfprintf(stderr, fmt, args);
+  va_end(args);
 }
 #endif
 
@@ -705,7 +705,7 @@ static void _ldap_trace (const char *fmt, ...)
 /*
  * Return scope-value for a scope-string.
  */
-static int str2scope (const char *p)
+static int str2scope(const char *p)
 {
   if(strcasecompare(p, "one"))
     return LDAP_SCOPE_ONELEVEL;
@@ -799,7 +799,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
     char *unescaped;
     CURLcode result;
 
-    LDAP_TRACE (("DN '%s'\n", dn));
+    LDAP_TRACE(("DN '%s'\n", dn));
 
     /* Unescape the DN */
     result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE);
@@ -864,7 +864,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
       char *unescaped;
       CURLcode result;
 
-      LDAP_TRACE (("attr[%d] '%s'\n", i, attributes[i]));
+      LDAP_TRACE(("attr[%d] '%s'\n", i, attributes[i]));
 
       /* Unescape the attribute */
       result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
@@ -917,7 +917,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 
       goto quit;
     }
-    LDAP_TRACE (("scope %d\n", ludp->lud_scope));
+    LDAP_TRACE(("scope %d\n", ludp->lud_scope));
   }
 
   p = q;
@@ -934,7 +934,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
     char *unescaped;
     CURLcode result;
 
-    LDAP_TRACE (("filter '%s'\n", filter));
+    LDAP_TRACE(("filter '%s'\n", filter));
 
     /* Unescape the filter */
     result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE);
@@ -1009,7 +1009,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp)
     free(ludp->lud_attrs);
   }
 
-  free (ludp);
+  free(ludp);
 }
 #endif  /* !HAVE_LDAP_URL_PARSE */
 #endif  /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */
diff --git a/lib/md4.c b/lib/md4.c
index 60f73a2..1bdc9f3 100644
--- a/lib/md4.c
+++ b/lib/md4.c
@@ -213,7 +213,8 @@ static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
   unsigned long used, available;
 
   saved_lo = ctx->lo;
-  if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+  ctx->lo = (saved_lo + size) & 0x1fffffff;
+  if(ctx->lo < saved_lo)
     ctx->hi++;
   ctx->hi += (MD4_u32plus)size >> 29;
 
diff --git a/lib/md5.c b/lib/md5.c
index f818d32..f2dc16c 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -45,7 +45,7 @@ static void MD5_Init(MD5_CTX * ctx)
 }
 
 static void MD5_Update(MD5_CTX * ctx,
-                       const unsigned char * input,
+                       const unsigned char *input,
                        unsigned int inputLen)
 {
   md5_update(ctx, inputLen, input);
@@ -71,7 +71,7 @@ static void MD5_Init(MD5_CTX * ctx)
 }
 
 static void MD5_Update(MD5_CTX * ctx,
-                       const unsigned char * input,
+                       const unsigned char *input,
                        unsigned int inputLen)
 {
   gcry_md_write(*ctx, input, inputLen);
@@ -402,7 +402,8 @@ static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
   unsigned long used, available;
 
   saved_lo = ctx->lo;
-  if((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+  ctx->lo = (saved_lo + size) & 0x1fffffff;
+  if(ctx->lo < saved_lo)
     ctx->hi++;
   ctx->hi += (MD5_u32plus)size >> 29;
 
diff --git a/lib/memdebug.c b/lib/memdebug.c
index ccbf461..15e8661 100644
--- a/lib/memdebug.c
+++ b/lib/memdebug.c
@@ -90,7 +90,7 @@ struct memdebug {
   union {
     curl_off_t o;
     double d;
-    void * p;
+    void *p;
   } mem[1];
   /* I'm hoping this is the thing with the strictest alignment
    * requirements.  That also means we waste some space :-( */
diff --git a/lib/mprintf.c b/lib/mprintf.c
index 2c88aa8..e4270ab 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -92,7 +92,8 @@
 #  define mp_uintmax_t unsigned long
 #endif
 
-#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
+#define BUFFSIZE 326 /* buffer for long-to-str and float-to-str calcs, should
+                        fit negative DBL_MAX (317 letters) */
 #define MAX_PARAMETERS 128 /* lame static limit */
 
 #ifdef __AMIGA__
@@ -303,7 +304,6 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
           flags |= FLAGS_ALT;
           break;
         case '.':
-          flags |= FLAGS_PREC;
           if('*' == *fmt) {
             /* The precision is picked from a specified parameter */
 
@@ -502,7 +502,7 @@ static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
         (mp_intmax_t)va_arg(arglist, int);
     }
 
-    switch (vto[i].type) {
+    switch(vto[i].type) {
     case FORMAT_STRING:
       vto[i].data.str = va_arg(arglist, char *);
       break;
@@ -692,7 +692,7 @@ static int dprintf_formatf(
 
     is_alt = (p->flags & FLAGS_ALT) ? 1 : 0;
 
-    switch (p->type) {
+    switch(p->type) {
     case FORMAT_INT:
       num = p->data.num.as_unsigned;
       if(p->flags & FLAGS_CHAR) {
@@ -917,12 +917,25 @@ static int dprintf_formatf(
         *fptr = 0;
 
         if(width >= 0) {
+          if(width >= (long)sizeof(work))
+            width = sizeof(work)-1;
           /* RECURSIVE USAGE */
           len = curl_msnprintf(fptr, left, "%ld", width);
           fptr += len;
           left -= len;
         }
         if(prec >= 0) {
+          /* for each digit in the integer part, we can have one less
+             precision */
+          size_t maxprec = sizeof(work) - 2;
+          double val = p->data.dnum;
+          while(val >= 10.0) {
+            val /= 10;
+            maxprec--;
+          }
+
+          if(prec > (long)maxprec)
+            prec = (long)maxprec-1;
           /* RECURSIVE USAGE */
           len = curl_msnprintf(fptr, left, ".%ld", prec);
           fptr += len;
@@ -942,7 +955,9 @@ static int dprintf_formatf(
         /* NOTE NOTE NOTE!! Not all sprintf implementations return number of
            output characters */
         (sprintf)(work, formatbuf, p->data.dnum);
-
+#ifdef CURLDEBUG
+        assert(strlen(work) <= sizeof(work));
+#endif
         for(fptr=work; *fptr; fptr++)
           OUTCHAR(*fptr);
       }
diff --git a/lib/multi.c b/lib/multi.c
index 2432b15..950b600 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -42,6 +42,7 @@
 #include "multihandle.h"
 #include "pipeline.h"
 #include "sigpipe.h"
+#include "vtls/vtls.h"
 #include "connect.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -812,6 +813,11 @@ static int waitconnect_getsock(struct connectdata *conn,
   if(!numsocks)
     return GETSOCK_BLANK;
 
+#ifdef USE_SSL
+  if(CONNECT_FIRSTSOCKET_PROXY_SSL())
+    return Curl_ssl_getsock(conn, sock, numsocks);
+#endif
+
   for(i=0; i<2; i++) {
     if(conn->tempsock[i] != CURL_SOCKET_BAD) {
       sock[s] = conn->tempsock[i];
@@ -1300,7 +1306,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
   CURLMcode rc;
   CURLcode result = CURLE_OK;
   struct SingleRequest *k;
-  long timeout_ms;
+  time_t timeout_ms;
   int control;
 
   if(!GOOD_EASY_HANDLE(data))
@@ -1548,7 +1554,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         multistate(data, CURLM_STATE_CONNECT);
       }
       else if(!result) {
-        if(data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_COMPLETE) {
+        if((data->easy_conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
+           data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
+           (data->easy_conn->tunnel_state[FIRSTSOCKET] != TUNNEL_CONNECT)) {
           rc = CURLM_CALL_MULTI_PERFORM;
           /* initiate protocol connect phase */
           multistate(data, CURLM_STATE_SENDPROTOCONNECT);
@@ -1561,6 +1569,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       /* awaiting a completion of an asynch TCP connect */
       result = Curl_is_connected(data->easy_conn, FIRSTSOCKET, &connected);
       if(connected && !result) {
+#ifndef CURL_DISABLE_HTTP
+        if((data->easy_conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
+            !data->easy_conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
+            (data->easy_conn->tunnel_state[FIRSTSOCKET] == TUNNEL_CONNECT)) {
+          multistate(data, CURLM_STATE_WAITPROXYCONNECT);
+          break;
+        }
+#endif
         rc = CURLM_CALL_MULTI_PERFORM;
         multistate(data, data->easy_conn->bits.tunnel_proxy?
                    CURLM_STATE_WAITPROXYCONNECT:
@@ -2486,7 +2502,7 @@ static CURLMcode add_next_timeout(struct timeval now,
      timeout in *tv */
   for(e = list->head; e;) {
     struct curl_llist_element *n = e->next;
-    long diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
+    time_t diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
     if(diff <= 0)
       /* remove outdated entry */
       Curl_llist_remove(list, e, NULL);
@@ -2764,7 +2780,7 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
 
     if(Curl_splaycomparekeys(multi->timetree->key, now) > 0) {
       /* some time left before expiration */
-      *timeout_ms = curlx_tvdiff(multi->timetree->key, now);
+      *timeout_ms = (long)curlx_tvdiff(multi->timetree->key, now);
       if(!*timeout_ms)
         /*
          * Since we only provide millisecond resolution on the returned value
@@ -2871,7 +2887,7 @@ multi_addtimeout(struct curl_llist *timeoutlist,
     /* find the correct spot in the list */
     for(e = timeoutlist->head; e; e = e->next) {
       struct timeval *checktime = e->ptr;
-      long diff = curlx_tvdiff(*checktime, *timedup);
+      time_t diff = curlx_tvdiff(*checktime, *timedup);
       if(diff > 0)
         break;
       prev = e;
@@ -2898,7 +2914,7 @@ multi_addtimeout(struct curl_llist *timeoutlist,
  * The timeout will be added to a queue of timeouts if it defines a moment in
  * time that is later than the current head of queue.
  */
-void Curl_expire(struct Curl_easy *data, long milli)
+void Curl_expire(struct Curl_easy *data, time_t milli)
 {
   struct Curl_multi *multi = data->multi;
   struct timeval *nowp = &data->state.expiretime;
@@ -2911,7 +2927,7 @@ void Curl_expire(struct Curl_easy *data, long milli)
     return;
 
   set = Curl_tvnow();
-  set.tv_sec += milli/1000;
+  set.tv_sec += (long)(milli/1000);
   set.tv_usec += (milli%1000)*1000;
 
   if(set.tv_usec >= 1000000) {
@@ -2923,7 +2939,7 @@ void Curl_expire(struct Curl_easy *data, long milli)
     /* This means that the struct is added as a node in the splay tree.
        Compare if the new time is earlier, and only remove-old/add-new if it
        is. */
-    long diff = curlx_tvdiff(set, *nowp);
+    time_t diff = curlx_tvdiff(set, *nowp);
     if(diff > 0) {
       /* the new expire time was later so just add it to the queue
          and get out */
@@ -2961,14 +2977,14 @@ void Curl_expire(struct Curl_easy *data, long milli)
  * time-out period to expire.
  *
  */
-void Curl_expire_latest(struct Curl_easy *data, long milli)
+void Curl_expire_latest(struct Curl_easy *data, time_t milli)
 {
   struct timeval *expire = &data->state.expiretime;
 
   struct timeval set;
 
   set = Curl_tvnow();
-  set.tv_sec += milli / 1000;
+  set.tv_sec += (long)(milli / 1000);
   set.tv_usec += (milli % 1000) * 1000;
 
   if(set.tv_usec >= 1000000) {
@@ -2980,7 +2996,7 @@ void Curl_expire_latest(struct Curl_easy *data, long milli)
     /* This means that the struct is added as a node in the splay tree.
        Compare if the new time is earlier, and only remove-old/add-new if it
          is. */
-    long diff = curlx_tvdiff(set, *expire);
+    time_t diff = curlx_tvdiff(set, *expire);
     if(diff > 0)
       /* the new expire time was later than the top time, so just skip this */
       return;
diff --git a/lib/multihandle.h b/lib/multihandle.h
index c56b6ae..0b78de9 100644
--- a/lib/multihandle.h
+++ b/lib/multihandle.h
@@ -38,7 +38,9 @@ typedef enum {
   CURLM_STATE_CONNECT,      /* 2 - resolve/connect has been sent off */
   CURLM_STATE_WAITRESOLVE,  /* 3 - awaiting the resolve to finalize */
   CURLM_STATE_WAITCONNECT,  /* 4 - awaiting the TCP connect to finalize */
-  CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting proxy CONNECT to finalize */
+  CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting HTTPS proxy SSL initialization
+                                   to complete and/or proxy CONNECT to
+                                   finalize */
   CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */
   CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect
                                    phase */
diff --git a/lib/multiif.h b/lib/multiif.h
index eaff496..e5de1fc 100644
--- a/lib/multiif.h
+++ b/lib/multiif.h
@@ -25,9 +25,9 @@
 /*
  * Prototypes for library-wide functions provided by multi.c
  */
-void Curl_expire(struct Curl_easy *data, long milli);
+void Curl_expire(struct Curl_easy *data, time_t milli);
 void Curl_expire_clear(struct Curl_easy *data);
-void Curl_expire_latest(struct Curl_easy *data, long milli);
+void Curl_expire_latest(struct Curl_easy *data, time_t milli);
 bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
 void Curl_multi_handlePipeBreak(struct Curl_easy *data);
 
diff --git a/lib/non-ascii.c b/lib/non-ascii.c
index ed14618..2f5de4c 100644
--- a/lib/non-ascii.c
+++ b/lib/non-ascii.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -117,7 +117,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
     /* call iconv */
     input_ptr = output_ptr = buffer;
     in_bytes = out_bytes = length;
-    rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes,
+    rc = iconv(data->outbound_cd, (const char **)&input_ptr, &in_bytes,
                &output_ptr, &out_bytes);
     if((rc == ICONV_ERROR) || (in_bytes != 0)) {
       error = ERRNO;
diff --git a/lib/nwlib.c b/lib/nwlib.c
index 42b6aa0..290cbe3 100644
--- a/lib/nwlib.c
+++ b/lib/nwlib.c
@@ -184,7 +184,8 @@ int GetOrSetUpData(int id, libdata_t **appData,
      */
     NXLock(gLibLock);
 
-    if(!(app_data = (libdata_t *) get_app_data(id))) {
+    app_data = (libdata_t *) get_app_data(id);
+    if(!app_data) {
       app_data = malloc(sizeof(libdata_t));
 
       if(app_data) {
@@ -259,7 +260,8 @@ int GetOrSetUpData(int id, libdata_t **appData,
           err         = ENOMEM;
         }
 
-        if((err = NXKeySetValue(key, thread_data))) {
+        err = NXKeySetValue(key, thread_data);
+        if(err) {
           free(thread_data->twentybytes);
           free(thread_data);
           thread_data = (libthreaddata_t *) NULL;
@@ -303,14 +305,14 @@ void DisposeThreadData(void *data)
 /* For native CLib-based NLM seems we can do a bit more simple. */
 #include <nwthread.h>
 
-int main (void)
+int main(void)
 {
   /* initialize any globals here... */
 
   /* do this if any global initializing was done
   SynchronizeStart();
   */
-  ExitThread (TSR_THREAD, 0);
+  ExitThread(TSR_THREAD, 0);
   return 0;
 }
 
diff --git a/lib/nwos.c b/lib/nwos.c
index 385f9c8..c6c22cc 100644
--- a/lib/nwos.c
+++ b/lib/nwos.c
@@ -26,7 +26,7 @@
 
 #ifdef __NOVELL_LIBC__
 /* For native LibC-based NLM we need to do nothing. */
-int netware_init (void)
+int netware_init(void)
 {
   return 0;
 }
@@ -45,7 +45,7 @@ NETDB_DEFINE_CONTEXT
 #include <arpa/inet.h>
 NETINET_DEFINE_CONTEXT
 
-int netware_init (void)
+int netware_init(void)
 {
   int rc = 0;
   unsigned int myHandle = GetNLMHandle();
@@ -72,13 +72,13 @@ int netware_init (void)
 }
 
 /* dummy function to satisfy newer prelude */
-int __init_environment (void)
+int __init_environment(void)
 {
   return 0;
 }
 
 /* dummy function to satisfy newer prelude */
-int __deinit_environment (void)
+int __deinit_environment(void)
 {
   return 0;
 }
diff --git a/lib/pingpong.c b/lib/pingpong.c
index bf2c8fd..7a99357 100644
--- a/lib/pingpong.c
+++ b/lib/pingpong.c
@@ -44,12 +44,12 @@
 
 /* Returns timeout in ms. 0 or negative number means the timeout has already
    triggered */
-long Curl_pp_state_timeout(struct pingpong *pp)
+time_t Curl_pp_state_timeout(struct pingpong *pp)
 {
   struct connectdata *conn = pp->conn;
   struct Curl_easy *data=conn->data;
-  long timeout_ms; /* in milliseconds */
-  long timeout2_ms; /* in milliseconds */
+  time_t timeout_ms; /* in milliseconds */
+  time_t timeout2_ms; /* in milliseconds */
   long response_time= (data->set.server_response_timeout)?
     data->set.server_response_timeout: pp->response_time;
 
@@ -83,8 +83,8 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
   struct connectdata *conn = pp->conn;
   curl_socket_t sock = conn->sock[FIRSTSOCKET];
   int rc;
-  long interval_ms;
-  long timeout_ms = Curl_pp_state_timeout(pp);
+  time_t interval_ms;
+  time_t timeout_ms = Curl_pp_state_timeout(pp);
   struct Curl_easy *data=conn->data;
   CURLcode result = CURLE_OK;
 
@@ -101,7 +101,9 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
   else
     interval_ms = 0; /* immediate */
 
-  if(Curl_pp_moredata(pp))
+  if(Curl_ssl_data_pending(conn, 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))
diff --git a/lib/pingpong.h b/lib/pingpong.h
index 2f649d5..500100a 100644
--- a/lib/pingpong.h
+++ b/lib/pingpong.h
@@ -88,7 +88,7 @@ void Curl_pp_init(struct pingpong *pp);
 
 /* Returns timeout in ms. 0 or negative number means the timeout has already
    triggered */
-long Curl_pp_state_timeout(struct pingpong *pp);
+time_t Curl_pp_state_timeout(struct pingpong *pp);
 
 
 /***********************************************************************
diff --git a/lib/pop3.c b/lib/pop3.c
index 8486519..9bb691c 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -104,7 +104,7 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn);
 static CURLcode pop3_perform_auth(struct connectdata *conn, const char *mech,
                                   const char *initresp);
 static CURLcode pop3_continue_auth(struct connectdata *conn, const char *resp);
-static void pop3_get_message(char *buffer, char** outptr);
+static void pop3_get_message(char *buffer, char **outptr);
 
 /*
  * POP3 protocol handler.
@@ -290,10 +290,10 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
  *
  * Gets the authentication message from the response buffer.
  */
-static void pop3_get_message(char *buffer, char** outptr)
+static void pop3_get_message(char *buffer, char **outptr)
 {
   size_t len = 0;
-  char* message = NULL;
+  char *message = NULL;
 
   /* Find the start of the message */
   for(message = buffer + 2; *message == ' ' || *message == '\t'; message++)
@@ -1572,7 +1572,7 @@ CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread)
       if(prev) {
         /* If the partial match was the CRLF and dot then only write the CRLF
            as the server would have inserted the dot */
-        result = Curl_client_write(conn, CLIENTWRITE_BODY, (char*)POP3_EOB,
+        result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)POP3_EOB,
                                    strip_dot ? prev - 1 : prev);
 
         if(result)
diff --git a/lib/progress.c b/lib/progress.c
index 0f67ef2..60627b2 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -249,24 +249,26 @@ long Curl_pgrsLimitWaitTime(curl_off_t cursize,
                             struct timeval start,
                             struct timeval now)
 {
-    curl_off_t size = cursize - startsize;
-    long minimum, actual;
+  curl_off_t size = cursize - startsize;
+  time_t minimum;
+  time_t actual;
 
-    /* we don't have a starting point yet -- return 0 so it gets (re)set */
-    if(start.tv_sec == 0 && start.tv_usec == 0)
-        return 0;
+  /* we don't have a starting point yet -- return 0 so it gets (re)set */
+  if(start.tv_sec == 0 && start.tv_usec == 0)
+    return 0;
 
-    /* not enough data yet */
-    if(size < limit)
-      return -1;
+  /* not enough data yet */
+  if(size < limit)
+    return -1;
 
-    minimum = (long) (CURL_OFF_T_C(1000) * size / limit);
-    actual = Curl_tvdiff(now, start);
+  minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
+  actual = Curl_tvdiff(now, start);
 
-    if(actual < minimum)
-      return minimum - actual;
-    else
-      return 0;
+  if(actual < minimum)
+    /* this is a conversion on some systems (64bit time_t => 32bit long) */
+    return (long)(minimum - actual);
+  else
+    return 0;
 }
 
 void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size)
@@ -359,9 +361,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
   now = Curl_tvnow(); /* what time is it */
 
   /* The time spent so far (from the start) */
-  data->progress.timespent =
-    (double)(now.tv_sec - data->progress.start.tv_sec) +
-    (double)(now.tv_usec - data->progress.start.tv_usec)/1000000.0;
+  data->progress.timespent = curlx_tvdiff_secs(now, data->progress.start);
   timespent = (curl_off_t)data->progress.timespent;
 
   /* The average download speed this far */
@@ -375,7 +375,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
      (data->progress.timespent>0?data->progress.timespent:1));
 
   /* Calculations done at most once a second, unless end is reached */
-  if(data->progress.lastshow != (long)now.tv_sec) {
+  if(data->progress.lastshow != now.tv_sec) {
     shownow = TRUE;
 
     data->progress.lastshow = now.tv_sec;
@@ -402,7 +402,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
 
     /* first of all, we don't do this if there's no counted seconds yet */
     if(countindex) {
-      long span_ms;
+      time_t span_ms;
 
       /* Get the index position to compare with the 'nowindex' position.
          Get the oldest entry possible. While we have less than CURR_TIME
diff --git a/lib/rand.c b/lib/rand.c
new file mode 100644
index 0000000..a51951c
--- /dev/null
+++ b/lib/rand.c
@@ -0,0 +1,130 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <fcntl.h>
+
+#include <curl/curl.h>
+#include "vtls/vtls.h"
+#include "sendf.h"
+#include "rand.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
+{
+  unsigned int r;
+  CURLcode result = CURLE_OK;
+  static unsigned int randseed;
+  static bool seeded = FALSE;
+
+#ifdef CURLDEBUG
+  char *force_entropy = getenv("CURL_ENTROPY");
+  if(force_entropy) {
+    if(!seeded) {
+      size_t elen = strlen(force_entropy);
+      size_t clen = sizeof(randseed);
+      size_t min = elen < clen ? elen : clen;
+      memcpy((char *)&randseed, force_entropy, min);
+      seeded = TRUE;
+    }
+    else
+      randseed++;
+    *rnd = randseed;
+    return CURLE_OK;
+  }
+#endif
+
+  /* data may be NULL! */
+  result = Curl_ssl_random(data, (unsigned char *)rnd, sizeof(*rnd));
+  if(result != CURLE_NOT_BUILT_IN)
+    /* only if there is no random funtion in the TLS backend do the non crypto
+       version, otherwise return result */
+    return result;
+
+  /* ---- non-cryptographic version following ---- */
+
+#ifdef RANDOM_FILE
+  if(!seeded) {
+    /* if there's a random file to read a seed from, use it */
+    int fd = open(RANDOM_FILE, O_RDONLY);
+    if(fd > -1) {
+      /* read random data into the randseed variable */
+      ssize_t nread = read(fd, &randseed, sizeof(randseed));
+      if(nread == sizeof(randseed))
+        seeded = TRUE;
+      close(fd);
+    }
+  }
+#endif
+
+  if(!seeded) {
+    struct timeval now = curlx_tvnow();
+    infof(data, "WARNING: Using weak random seed\n");
+    randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
+    randseed = randseed * 1103515245 + 12345;
+    randseed = randseed * 1103515245 + 12345;
+    randseed = randseed * 1103515245 + 12345;
+    seeded = TRUE;
+  }
+
+  /* Return an unsigned 32-bit pseudo-random number. */
+  r = randseed = randseed * 1103515245 + 12345;
+  *rnd = (r << 16) | ((r >> 16) & 0xFFFF);
+  return CURLE_OK;
+}
+
+/*
+ * Curl_rand() stores 'num' number of random unsigned integers in the buffer
+ * 'rndptr' points to.
+ *
+ * If libcurl is built without TLS support or with a TLS backend that lacks a
+ * proper random API (Gskit, PolarSSL or mbedTLS), this function will use
+ * "weak" random.
+ *
+ * When built *with* TLS support and a backend that offers strong random, it
+ * will return error if it cannot provide strong random values.
+ *
+ * NOTE: 'data' may be passed in as NULL when coming from external API without
+ * easy handle!
+ *
+ */
+
+CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rndptr,
+                   unsigned int num)
+{
+  CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
+  unsigned int i;
+
+  assert(num > 0);
+
+  for(i = 0; i < num; i++) {
+    result = randit(data, rndptr++);
+    if(result)
+      return result;
+  }
+  return result;
+}
diff --git a/lib/strdup.h b/lib/rand.h
similarity index 59%
copy from lib/strdup.h
copy to lib/rand.h
index c74a3b7..0f89861 100644
--- a/lib/strdup.h
+++ b/lib/rand.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_STRDUP_H
-#define HEADER_CURL_STRDUP_H
+#ifndef HEADER_CURL_RAND_H
+#define HEADER_CURL_RAND_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -21,11 +21,23 @@
  * KIND, either express or implied.
  *
  ***************************************************************************/
-#include "curl_setup.h"
 
-#ifndef HAVE_STRDUP
-extern char *curlx_strdup(const char *str);
-#endif
-void *Curl_memdup(const void *src, size_t buffer_length);
+/*
+ * Curl_rand() stores 'num' number of random unsigned integers in the buffer
+ * 'rnd' points to.
+ *
+ * If libcurl is built without TLS support or with a TLS backend that lacks a
+ * proper random API (Gskit, PolarSSL or mbedTLS), this function will use
+ * "weak" random.
+ *
+ * When built *with* TLS support and a backend that offers strong random, it
+ * will return error if it cannot provide strong random values.
+ *
+ * NOTE: 'data' may be passed in as NULL when coming from external API without
+ * easy handle!
+ *
+ */
+CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rnd,
+                   unsigned int num);
 
-#endif /* HEADER_CURL_STRDUP_H */
+#endif /* HEADER_CURL_RAND_H */
diff --git a/lib/rtsp.c b/lib/rtsp.c
index d1bad19..65c6c3b 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -36,6 +36,7 @@
 #include "strcase.h"
 #include "select.h"
 #include "connect.h"
+#include "strdup.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -139,7 +140,7 @@ static CURLcode rtsp_setup_connection(struct connectdata *conn)
  * want to block the application forever while receiving a stream. Therefore,
  * we cannot assume that an RTSP socket is dead just because it is readable.
  *
- * Instead, if it is readable, run Curl_getconnectinfo() to peek at the socket
+ * Instead, if it is readable, run Curl_connalive() to peek at the socket
  * and distinguish between closed and data.
  */
 bool Curl_rtsp_connisdead(struct connectdata *check)
@@ -156,12 +157,9 @@ bool Curl_rtsp_connisdead(struct connectdata *check)
     /* socket is in an error state */
     ret_val = TRUE;
   }
-  else if((sval & CURL_CSELECT_IN) && check->data) {
-    /* readable with no error. could be closed or could be alive but we can
-       only check if we have a proper Curl_easy for the connection */
-    curl_socket_t connectinfo = Curl_getconnectinfo(check->data, &check);
-    if(connectinfo != CURL_SOCKET_BAD)
-      ret_val = FALSE;
+  else if(sval & CURL_CSELECT_IN) {
+    /* readable with no error. could still be closed */
+    ret_val = !Curl_connalive(check);
   }
 
   return ret_val;
@@ -488,7 +486,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
    * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
    * with basic and digest, it will be freed anyway by the next request
    */
-  Curl_safefree (conn->allocptr.userpwd);
+  Curl_safefree(conn->allocptr.userpwd);
   conn->allocptr.userpwd = NULL;
 
   if(result)
@@ -614,9 +612,9 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
 
   if(rtspc->rtp_buf) {
     /* There was some leftover data the last time. Merge buffers */
-    char *newptr = realloc(rtspc->rtp_buf, rtspc->rtp_bufsize + *nread);
+    char *newptr = Curl_saferealloc(rtspc->rtp_buf,
+                                    rtspc->rtp_bufsize + *nread);
     if(!newptr) {
-      Curl_safefree(rtspc->rtp_buf);
       rtspc->rtp_buf = NULL;
       rtspc->rtp_bufsize = 0;
       return CURLE_OUT_OF_MEMORY;
@@ -736,7 +734,7 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
   curl_write_callback writeit;
 
   if(len == 0) {
-    failf (data, "Cannot write a 0 size RTP packet.");
+    failf(data, "Cannot write a 0 size RTP packet.");
     return CURLE_WRITE_ERROR;
   }
 
@@ -744,12 +742,12 @@ CURLcode rtp_client_write(struct connectdata *conn, char *ptr, size_t len)
   wrote = writeit(ptr, 1, len, data->set.rtp_out);
 
   if(CURL_WRITEFUNC_PAUSE == wrote) {
-    failf (data, "Cannot pause RTP");
+    failf(data, "Cannot pause RTP");
     return CURLE_WRITE_ERROR;
   }
 
   if(wrote != len) {
-    failf (data, "Failed writing RTP data");
+    failf(data, "Failed writing RTP data");
     return CURLE_WRITE_ERROR;
   }
 
diff --git a/lib/security.c b/lib/security.c
index ff26066..4a8f444 100644
--- a/lib/security.c
+++ b/lib/security.c
@@ -62,7 +62,7 @@
 #include "sendf.h"
 #include "strcase.h"
 #include "warnless.h"
-
+#include "strdup.h"
 /* The last #include file should be: */
 #include "memdebug.h"
 
@@ -88,7 +88,8 @@ name_to_level(const char *name)
 
 /* Convert a protocol |level| to its char representation.
    We take an int to catch programming mistakes. */
-static char level_to_char(int level) {
+static char level_to_char(int level)
+{
   switch(level) {
   case PROT_CLEAR:
     return 'C';
@@ -202,7 +203,7 @@ static CURLcode read_data(struct connectdata *conn,
   if(len) {
     /* only realloc if there was a length */
     len = ntohl(len);
-    tmp = realloc(buf->data, len);
+    tmp = Curl_saferealloc(buf->data, len);
   }
   if(tmp == NULL)
     return CURLE_OUT_OF_MEMORY;
@@ -222,7 +223,7 @@ buffer_read(struct krb5buffer *buf, void *data, size_t len)
 {
   if(buf->size - buf->index < len)
     len = buf->size - buf->index;
-  memcpy(data, (char*)buf->data + buf->index, len);
+  memcpy(data, (char *)buf->data + buf->index, len);
   buf->index += len;
   return len;
 }
@@ -291,7 +292,7 @@ static void do_sec_send(struct connectdata *conn, curl_socket_t fd,
       prot_level = conn->command_prot;
   }
   bytes = conn->mech->encode(conn->app_data, from, length, prot_level,
-                             (void**)&buffer);
+                             (void **)&buffer);
   if(!buffer || bytes <= 0)
     return; /* error */
 
@@ -411,7 +412,7 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
 static int sec_set_protection_level(struct connectdata *conn)
 {
   int code;
-  char* pbsz;
+  char *pbsz;
   static unsigned int buffer_size = 1 << 20; /* 1048576 */
   enum protection_level level = conn->request_data_prot;
 
diff --git a/lib/select.c b/lib/select.c
index 26302d9..03af645 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -145,7 +145,7 @@ int Curl_wait_ms(int timeout_ms)
 int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
                       curl_socket_t readfd1,
                       curl_socket_t writefd, /* socket to write to */
-                      long timeout_ms)       /* milliseconds to wait */
+                      time_t timeout_ms)     /* milliseconds to wait */
 {
 #ifdef HAVE_POLL_FINE
   struct pollfd pfd[3];
diff --git a/lib/select.h b/lib/select.h
index 1d26f49..e247bd9 100644
--- a/lib/select.h
+++ b/lib/select.h
@@ -73,7 +73,7 @@ struct pollfd
 
 int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
                       curl_socket_t writefd,
-                      long timeout_ms);
+                      time_t timeout_ms);
 
 #define SOCKET_READABLE(x,z) \
   Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, z)
diff --git a/lib/sendf.c b/lib/sendf.c
index 2101797..7601697 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -122,6 +122,13 @@ static size_t convert_lineends(struct Curl_easy *data,
 #endif /* CURL_DO_LINEEND_CONV */
 
 #ifdef USE_RECV_BEFORE_SEND_WORKAROUND
+bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
+{
+  struct postponed_data * const psnd = &(conn->postponed[sockindex]);
+  return psnd->buffer && psnd->allocated_size &&
+         psnd->recv_size > psnd->recv_processed;
+}
+
 static void pre_receive_plain(struct connectdata *conn, int num)
 {
   const curl_socket_t sockfd = conn->sock[num];
@@ -201,6 +208,12 @@ static ssize_t get_pre_recved(struct connectdata *conn, int num, char *buf,
 }
 #else  /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
 /* Use "do-nothing" macros instead of functions when workaround not used */
+bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex)
+{
+  (void)conn;
+  (void)sockindex;
+  return false;
+}
 #define pre_receive_plain(c,n) do {} WHILE_FALSE
 #define get_pre_recved(c,n,b,l) 0
 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
@@ -488,7 +501,7 @@ static CURLcode pausewrite(struct Curl_easy *data,
  */
 CURLcode Curl_client_chop_write(struct connectdata *conn,
                                 int type,
-                                char * ptr,
+                                char *ptr,
                                 size_t len)
 {
   struct Curl_easy *data = conn->data;
@@ -571,7 +584,7 @@ CURLcode Curl_client_chop_write(struct connectdata *conn,
         return pausewrite(data, CLIENTWRITE_HEADER, ptr, len);
 
       if(wrote != chunklen) {
-        failf (data, "Failed writing header");
+        failf(data, "Failed writing header");
         return CURLE_WRITE_ERROR;
       }
     }
@@ -692,7 +705,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
     }
     /* If we come here, it means that there is no data to read from the buffer,
      * so we read from the socket */
-    bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof (char));
+    bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof(char));
     buffertofill = conn->master_buffer;
   }
   else {
@@ -796,7 +809,7 @@ int Curl_debug(struct Curl_easy *data, curl_infotype type,
     char buffer[160];
     const char *t=NULL;
     const char *w="Data";
-    switch (type) {
+    switch(type) {
     case CURLINFO_HEADER_IN:
       w = "Header";
       /* FALLTHROUGH */
diff --git a/lib/sendf.h b/lib/sendf.h
index a951a0b..fbe4f99 100644
--- a/lib/sendf.h
+++ b/lib/sendf.h
@@ -56,6 +56,8 @@ CURLcode Curl_client_chop_write(struct connectdata *conn, int type, char *ptr,
 CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
                            size_t len) WARN_UNUSED_RESULT;
 
+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,
                          char *buf,
diff --git a/lib/setup-os400.h b/lib/setup-os400.h
index e32b72f..a3c2a7b 100644
--- a/lib/setup-os400.h
+++ b/lib/setup-os400.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -41,18 +41,18 @@ typedef unsigned long   u_int32_t;
 #include <qsoasync.h>
 #include <gssapi.h>
 
-extern int      Curl_getaddrinfo_a(const char * nodename,
-                                   const char * servname,
-                                   const struct addrinfo * hints,
-                                   struct addrinfo * * res);
+extern int Curl_getaddrinfo_a(const char *nodename,
+                              const char *servname,
+                              const struct addrinfo *hints,
+                              struct addrinfo **res);
 #define getaddrinfo             Curl_getaddrinfo_a
 
 
-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,
-                                   int flags);
+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,
+                              int flags);
 #define getnameinfo             Curl_getnameinfo_a
 
 
@@ -79,7 +79,7 @@ extern int      Curl_gsk_secure_soc_init(gsk_handle my_session_handle);
 
 extern int      Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle,
                                                 GSK_BUF_ID bufID,
-                                                const char * buffer,
+                                                const char *buffer,
                                                 int bufSize);
 #define gsk_attribute_set_buffer        Curl_gsk_attribute_set_buffer_a
 
@@ -95,29 +95,29 @@ extern int      Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
 
 extern int      Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
                                                 GSK_CALLBACK_ID callBackID,
-                                                void * callBackAreaPtr);
+                                                void *callBackAreaPtr);
 #define gsk_attribute_set_callback      Curl_gsk_attribute_set_callback
 
 extern int      Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle,
                                                 GSK_BUF_ID bufID,
-                                                const char * * buffer,
-                                                int * bufSize);
+                                                const char **buffer,
+                                                int *bufSize);
 #define gsk_attribute_get_buffer        Curl_gsk_attribute_get_buffer_a
 
 extern int      Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle,
                                             GSK_ENUM_ID enumID,
-                                            GSK_ENUM_VALUE * enumValue);
+                                            GSK_ENUM_VALUE *enumValue);
 #define gsk_attribute_get_enum  Curl_gsk_attribute_get_enum
 
 extern int      Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
                                                      GSK_NUM_ID numID,
-                                                     int * numValue);
+                                                     int *numValue);
 #define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value
 
 extern int      Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
                                  GSK_CERT_ID certID,
-                                 const gsk_cert_data_elem * * certDataElem,
-                                 int * certDataElementCount);
+                                 const gsk_cert_data_elem **certDataElem,
+                                 int *certDataElementCount);
 #define gsk_attribute_get_cert_info     Curl_gsk_attribute_get_cert_info
 
 extern int      Curl_gsk_secure_soc_misc(gsk_handle my_session_handle,
@@ -125,13 +125,13 @@ extern int      Curl_gsk_secure_soc_misc(gsk_handle my_session_handle,
 #define gsk_secure_soc_misc     Curl_gsk_secure_soc_misc
 
 extern int      Curl_gsk_secure_soc_read(gsk_handle my_session_handle,
-                                         char * readBuffer,
-                                         int readBufSize, int * amtRead);
+                                         char *readBuffer,
+                                         int readBufSize, int *amtRead);
 #define gsk_secure_soc_read     Curl_gsk_secure_soc_read
 
 extern int      Curl_gsk_secure_soc_write(gsk_handle my_session_handle,
-                                          char * writeBuffer,
-                                          int writeBufSize, int * amtWritten);
+                                          char *writeBuffer,
+                                          int writeBufSize, int *amtWritten);
 #define gsk_secure_soc_write    Curl_gsk_secure_soc_write
 
 extern const char *     Curl_gsk_strerror_a(int gsk_return_value);
@@ -202,10 +202,10 @@ extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
 
 extern int Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen);
 extern int Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen);
-extern int Curl_os400_sendto(int sd, char * buffer, int buflen, int flags,
-            struct sockaddr * dstaddr, int addrlen);
-extern int Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
-                                struct sockaddr * fromaddr, int * addrlen);
+extern int Curl_os400_sendto(int sd, char *buffer, int buflen, int flags,
+                             struct sockaddr * dstaddr, int addrlen);
+extern int Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags,
+                               struct sockaddr *fromaddr, int *addrlen);
 
 #define connect                 Curl_os400_connect
 #define bind                    Curl_os400_bind
diff --git a/lib/setup-vms.h b/lib/setup-vms.h
index 4b78e0b..6c454ae 100644
--- a/lib/setup-vms.h
+++ b/lib/setup-vms.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -41,7 +41,7 @@
 #   endif
 #endif
 #include <stdlib.h>
-    char * decc$getenv(const char * __name);
+char *decc$getenv(const char *__name);
 #include <pwd.h>
 
 #include <string.h>
@@ -79,23 +79,24 @@
 #   if __INITIAL_POINTER_SIZE == 32
 /* Translate the path, but only if the path is a VMS file specification */
 /* The translation is usually only needed for older versions of VMS */
-static char * vms_translate_path(const char * path) {
-char * unix_path;
-char * test_str;
-
-    /* See if the result is in VMS format, if not, we are done */
-    /* Assume that this is a PATH, not just some data */
-    test_str = strpbrk(path, ":[<^");
-    if(test_str == NULL) {
-      return (char *)path;
-    }
-
-    unix_path = decc$translate_vms(path);
-
-    if((int)unix_path <= 0) {
-      /* We can not translate it, so return the original string */
-      return (char *)path;
-    }
+static char *vms_translate_path(const char *path)
+{
+  char *unix_path;
+  char *test_str;
+
+  /* See if the result is in VMS format, if not, we are done */
+  /* Assume that this is a PATH, not just some data */
+  test_str = strpbrk(path, ":[<^");
+  if(test_str == NULL) {
+    return (char *)path;
+  }
+
+  unix_path = decc$translate_vms(path);
+
+  if((int)unix_path <= 0) {
+    /* We can not translate it, so return the original string */
+    return (char *)path;
+  }
 }
 #   else
     /* VMS translate path is actually not needed on the current 64 bit */
@@ -111,74 +112,74 @@ char * test_str;
 #   endif
 #endif
 
-static char * vms_getenv(const char * envvar) {
+static char *vms_getenv(const char *envvar)
+{
+  char *result;
+  char *vms_path;
 
-char * result;
-char * vms_path;
-
-    /* first use the DECC getenv() function */
-    result = decc$getenv(envvar);
-    if(result == NULL) {
-      return result;
-    }
+  /* first use the DECC getenv() function */
+  result = decc$getenv(envvar);
+  if(result == NULL) {
+    return result;
+  }
 
-    vms_path = result;
-    result = vms_translate_path(vms_path);
+  vms_path = result;
+  result = vms_translate_path(vms_path);
 
-    /* note that if you backport this to use VAX C RTL, that the VAX C RTL */
-    /* may do a malloc(2048) for each call to getenv(), so you will need   */
-    /* to add a free(vms_path) */
-    /* Do not do a free() for DEC C RTL builds, which should be used for */
-    /* VMS 5.5-2 and later, even if using GCC */
+  /* note that if you backport this to use VAX C RTL, that the VAX C RTL */
+  /* may do a malloc(2048) for each call to getenv(), so you will need   */
+  /* to add a free(vms_path) */
+  /* Do not do a free() for DEC C RTL builds, which should be used for */
+  /* VMS 5.5-2 and later, even if using GCC */
 
-    return result;
+  return result;
 }
 
 
 static struct passwd vms_passwd_cache;
 
-static struct passwd * vms_getpwuid(uid_t uid) {
-
-struct passwd * my_passwd;
+static struct passwd * vms_getpwuid(uid_t uid)
+{
+  struct passwd * my_passwd;
 
 /* Hack needed to support 64 bit builds, decc_getpwnam is 32 bit only */
 #ifdef __DECC
 #   if __INITIAL_POINTER_SIZE
-__char_ptr32 unix_path;
+  __char_ptr32 unix_path;
 #   else
-char * unix_path;
+  char *unix_path;
 #   endif
 #else
-char * unix_path;
+  char *unix_path;
 #endif
 
-    my_passwd = decc_getpwuid(uid);
-    if(my_passwd == NULL) {
-      return my_passwd;
-    }
-
-    unix_path = vms_translate_path(my_passwd->pw_dir);
-
-    if((long)unix_path <= 0) {
-      /* We can not translate it, so return the original string */
-      return my_passwd;
-    }
-
-    /* If no changes needed just return it */
-    if(unix_path == my_passwd->pw_dir) {
-      return my_passwd;
-    }
-
-    /* Need to copy the structure returned */
-    /* Since curl is only using pw_dir, no need to fix up *
-    /* the pw_shell when running under Bash */
-    vms_passwd_cache.pw_name = my_passwd->pw_name;
-    vms_passwd_cache.pw_uid = my_passwd->pw_uid;
-    vms_passwd_cache.pw_gid = my_passwd->pw_uid;
-    vms_passwd_cache.pw_dir = unix_path;
-    vms_passwd_cache.pw_shell = my_passwd->pw_shell;
-
-    return &vms_passwd_cache;
+  my_passwd = decc_getpwuid(uid);
+  if(my_passwd == NULL) {
+    return my_passwd;
+  }
+
+  unix_path = vms_translate_path(my_passwd->pw_dir);
+
+  if((long)unix_path <= 0) {
+    /* We can not translate it, so return the original string */
+    return my_passwd;
+  }
+
+  /* If no changes needed just return it */
+  if(unix_path == my_passwd->pw_dir) {
+    return my_passwd;
+  }
+
+  /* Need to copy the structure returned */
+  /* Since curl is only using pw_dir, no need to fix up */
+  /* the pw_shell when running under Bash */
+  vms_passwd_cache.pw_name = my_passwd->pw_name;
+  vms_passwd_cache.pw_uid = my_passwd->pw_uid;
+  vms_passwd_cache.pw_gid = my_passwd->pw_uid;
+  vms_passwd_cache.pw_dir = unix_path;
+  vms_passwd_cache.pw_shell = my_passwd->pw_shell;
+
+  return &vms_passwd_cache;
 }
 
 #ifdef __DECC
diff --git a/lib/share.h b/lib/share.h
index e689ff2..c039a16 100644
--- a/lib/share.h
+++ b/lib/share.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -54,8 +54,8 @@ struct Curl_share {
   long sessionage;
 };
 
-CURLSHcode Curl_share_lock (struct Curl_easy *, curl_lock_data,
-                            curl_lock_access);
-CURLSHcode Curl_share_unlock (struct Curl_easy *, curl_lock_data);
+CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data,
+                           curl_lock_access);
+CURLSHcode Curl_share_unlock(struct Curl_easy *, curl_lock_data);
 
 #endif /* HEADER_CURL_SHARE_H */
diff --git a/lib/smb.c b/lib/smb.c
index 7cb0c96..f197fe1 100644
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2014, Bill Nagel <wnagel at tycoint.com>, Exacq Technologies
- * Copyright (C) 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 2016, Daniel Stenberg, <daniel at 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
@@ -308,8 +308,8 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg)
   if(smbc->got < sizeof(unsigned int))
     return CURLE_OK;
 
-  nbt_size = Curl_read16_be((unsigned char *)(buf + sizeof(unsigned short))) +
-             sizeof(unsigned int);
+  nbt_size = Curl_read16_be((const unsigned char *)(buf +
+             sizeof(unsigned short))) + sizeof(unsigned int);
   if(smbc->got < nbt_size)
     return CURLE_OK;
 
@@ -320,7 +320,7 @@ static CURLcode smb_recv_message(struct connectdata *conn, void **msg)
     if(nbt_size >= msg_size + sizeof(unsigned short)) {
       /* Add the byte count */
       msg_size += sizeof(unsigned short) +
-                  Curl_read16_le((unsigned char *)&buf[msg_size]);
+                  Curl_read16_le((const unsigned char *)&buf[msg_size]);
       if(nbt_size < msg_size)
         return CURLE_READ_ERROR;
     }
@@ -781,9 +781,9 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
       next_state = SMB_CLOSE;
       break;
     }
-    len = Curl_read16_le(((unsigned char *) msg) +
+    len = Curl_read16_le(((const unsigned char *) msg) +
                          sizeof(struct smb_header) + 11);
-    off = Curl_read16_le(((unsigned char *) msg) +
+    off = Curl_read16_le(((const unsigned char *) msg) +
                          sizeof(struct smb_header) + 13);
     if(len > 0) {
       if(off + sizeof(unsigned int) + len > smbc->got) {
@@ -812,7 +812,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
       next_state = SMB_CLOSE;
       break;
     }
-    len = Curl_read16_le(((unsigned char *) msg) +
+    len = Curl_read16_le(((const unsigned char *) msg) +
                          sizeof(struct smb_header) + 5);
     conn->data->req.bytecount += len;
     conn->data->req.offset += len;
diff --git a/lib/smtp.c b/lib/smtp.c
index a4fc2c2..ff8e80d 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -103,7 +103,7 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn);
 static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech,
                                   const char *initresp);
 static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp);
-static void smtp_get_message(char *buffer, char** outptr);
+static void smtp_get_message(char *buffer, char **outptr);
 
 /*
  * SMTP protocol handler.
@@ -278,10 +278,10 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
  *
  * Gets the authentication message from the response buffer.
  */
-static void smtp_get_message(char *buffer, char** outptr)
+static void smtp_get_message(char *buffer, char **outptr)
 {
   size_t len = 0;
-  char* message = NULL;
+  char *message = NULL;
 
   /* Find the start of the message */
   for(message = buffer + 4; *message == ' ' || *message == '\t'; message++)
diff --git a/lib/socks.c b/lib/socks.c
index 742d411..774fb20 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -57,7 +57,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
   ssize_t nread;
   ssize_t allread = 0;
   int result;
-  long timeleft;
+  time_t timeleft;
   *n = 0;
   for(;;) {
     timeleft = Curl_timeleft(conn->data, NULL, TRUE);
@@ -109,9 +109,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
                      const char *hostname,
                      int remote_port,
                      int sockindex,
-                     struct connectdata *conn,
-                     bool protocol4a)
+                     struct connectdata *conn)
 {
+  const bool protocol4a =
+    (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
 #define SOCKS4REQLEN 262
   unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
                                            id */
@@ -126,6 +127,10 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
     return CURLE_OPERATION_TIMEDOUT;
   }
 
+  if(conn->bits.httpproxy)
+    infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
+          protocol4a ? "a" : "", hostname, remote_port);
+
   (void)curlx_nonblock(sock, FALSE);
 
   infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
@@ -174,11 +179,11 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
       if(hp->ai_family == AF_INET) {
         struct sockaddr_in *saddr_in;
 
-        saddr_in = (struct sockaddr_in*)(void*)hp->ai_addr;
-        socksreq[4] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[0];
-        socksreq[5] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[1];
-        socksreq[6] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[2];
-        socksreq[7] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[3];
+        saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr;
+        socksreq[4] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[0];
+        socksreq[5] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[1];
+        socksreq[6] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[2];
+        socksreq[7] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[3];
 
         infof(data, "SOCKS4 connect to IPv4 %s (locally resolved)\n", buf);
       }
@@ -219,7 +224,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
     ssize_t written;
     ssize_t hostnamelen = 0;
     int packetsize = 9 +
-      (int)strlen((char*)socksreq + 8); /* size including NUL */
+      (int)strlen((char *)socksreq + 8); /* size including NUL */
 
     /* If SOCKS4a, set special invalid IP address 0.0.0.x */
     if(protocol4a) {
@@ -230,7 +235,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
       /* If still enough room in buffer, also append hostname */
       hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */
       if(packetsize + hostnamelen <= SOCKS4REQLEN)
-        strcpy((char*)socksreq + packetsize, hostname);
+        strcpy((char *)socksreq + packetsize, hostname);
       else
         hostnamelen = 0; /* Flag: hostname did not fit in buffer */
     }
@@ -376,11 +381,16 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
   CURLcode code;
   curl_socket_t sock = conn->sock[sockindex];
   struct Curl_easy *data = conn->data;
-  long timeout;
-  bool socks5_resolve_local = (conn->proxytype == CURLPROXY_SOCKS5)?TRUE:FALSE;
+  time_t timeout;
+  bool socks5_resolve_local =
+    (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
   const size_t hostname_len = strlen(hostname);
   ssize_t len = 0;
 
+  if(conn->bits.httpproxy)
+    infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
+          hostname, remote_port);
+
   /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
   if(!socks5_resolve_local && hostname_len > 255) {
     infof(conn->data, "SOCKS5: server resolving disabled for hostnames of "
@@ -605,9 +615,9 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
         struct sockaddr_in *saddr_in;
         socksreq[len++] = 1; /* ATYP: IPv4 = 1 */
 
-        saddr_in = (struct sockaddr_in*)(void*)hp->ai_addr;
+        saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr;
         for(i = 0; i < 4; i++) {
-          socksreq[len++] = ((unsigned char*)&saddr_in->sin_addr.s_addr)[i];
+          socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i];
         }
 
         infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", buf);
@@ -617,9 +627,10 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
         struct sockaddr_in6 *saddr_in6;
         socksreq[len++] = 4; /* ATYP: IPv6 = 4 */
 
-        saddr_in6 = (struct sockaddr_in6*)(void*)hp->ai_addr;
+        saddr_in6 = (struct sockaddr_in6 *)(void *)hp->ai_addr;
         for(i = 0; i < 16; i++) {
-          socksreq[len++] = ((unsigned char*)&saddr_in6->sin6_addr.s6_addr)[i];
+          socksreq[len++] =
+            ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i];
         }
 
         infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", buf);
diff --git a/lib/socks.h b/lib/socks.h
index a44ada6..348707e 100644
--- a/lib/socks.h
+++ b/lib/socks.h
@@ -25,7 +25,7 @@
 #include "curl_setup.h"
 
 #ifdef CURL_DISABLE_PROXY
-#define Curl_SOCKS4(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
+#define Curl_SOCKS4(a,b,c,d,e) CURLE_NOT_BUILT_IN
 #define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
 #else
 /*
@@ -49,8 +49,7 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
                      const char *hostname,
                      int remote_port,
                      int sockindex,
-                     struct connectdata *conn,
-                     bool protocol4a);
+                     struct connectdata *conn);
 
 /*
  * This function logs in to a SOCKS5 proxy and sends the specifics to the
diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c
index 369245a..54d0635 100644
--- a/lib/socks_gssapi.c
+++ b/lib/socks_gssapi.c
@@ -46,7 +46,7 @@ static gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
 static int check_gss_err(struct Curl_easy *data,
                          OM_uint32 major_status,
                          OM_uint32 minor_status,
-                         const char* function)
+                         const char *function)
 {
   if(GSS_ERROR(major_status)) {
     OM_uint32 maj_stat, min_stat;
@@ -65,7 +65,7 @@ static int check_gss_err(struct Curl_easy *data,
                                     &msg_ctx, &status_string);
       if(maj_stat == GSS_S_COMPLETE) {
         if(sizeof(buf) > len + status_string.length + 1) {
-          strcpy(buf+len, (char*) status_string.value);
+          strcpy(buf+len, (char *) status_string.value);
           len += status_string.length;
         }
         gss_release_buffer(&min_stat, &status_string);
@@ -86,7 +86,7 @@ static int check_gss_err(struct Curl_easy *data,
                                     &msg_ctx, &status_string);
       if(maj_stat == GSS_S_COMPLETE) {
         if(sizeof(buf) > len + status_string.length)
-          strcpy(buf+len, (char*) status_string.value);
+          strcpy(buf+len, (char *) status_string.value);
         gss_release_buffer(&min_stat, &status_string);
         break;
       }
@@ -123,6 +123,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
   unsigned char socksreq[4]; /* room for GSS-API exchange header only */
   const char *serviceptr = data->set.str[STRING_PROXY_SERVICE_NAME] ?
                            data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
+  const size_t serviceptr_length = strlen(serviceptr);
 
   /*   GSS-API request looks like
    * +----+------+-----+----------------+
@@ -134,22 +135,23 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
 
   /* prepare service name */
   if(strchr(serviceptr, '/')) {
-    service.value = malloc(strlen(serviceptr));
+    service.length = serviceptr_length;
+    service.value = malloc(service.length);
     if(!service.value)
       return CURLE_OUT_OF_MEMORY;
-    service.length = strlen(serviceptr);
     memcpy(service.value, serviceptr, service.length);
 
     gss_major_status = gss_import_name(&gss_minor_status, &service,
                                        (gss_OID) GSS_C_NULL_OID, &server);
   }
   else {
-    service.value = malloc(strlen(serviceptr) +strlen(conn->proxy.name)+2);
+    service.value = malloc(serviceptr_length +
+                           strlen(conn->socks_proxy.host.name)+2);
     if(!service.value)
       return CURLE_OUT_OF_MEMORY;
-    service.length = strlen(serviceptr) +strlen(conn->proxy.name)+1;
+    service.length = serviceptr_length + strlen(conn->socks_proxy.host.name)+1;
     snprintf(service.value, service.length+1, "%s@%s",
-             serviceptr, conn->proxy.name);
+             serviceptr, conn->socks_proxy.host.name);
 
     gss_major_status = gss_import_name(&gss_minor_status, &service,
                                        GSS_C_NT_HOSTBASED_SERVICE, &server);
@@ -290,9 +292,9 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
   gss_release_name(&gss_status, &server);
 
   /* Everything is good so far, user was authenticated! */
-  gss_major_status = gss_inquire_context (&gss_minor_status, gss_context,
-                                          &gss_client_name, NULL, NULL, NULL,
-                                          NULL, NULL, NULL);
+  gss_major_status = gss_inquire_context(&gss_minor_status, gss_context,
+                                         &gss_client_name, NULL, NULL, NULL,
+                                         NULL, NULL, NULL);
   if(check_gss_err(data, gss_major_status,
                    gss_minor_status, "gss_inquire_context")) {
     gss_delete_sec_context(&gss_status, &gss_context, NULL);
diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c
index 6053490..edc73ad 100644
--- a/lib/socks_sspi.c
+++ b/lib/socks_sspi.c
@@ -45,7 +45,7 @@
  */
 static int check_sspi_err(struct connectdata *conn,
                           SECURITY_STATUS status,
-                          const char* function)
+                          const char *function)
 {
   if(status != SEC_E_OK &&
      status != SEC_I_COMPLETE_AND_CONTINUE &&
@@ -86,6 +86,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
   unsigned char socksreq[4]; /* room for GSS-API exchange header only */
   const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
                         data->set.str[STRING_PROXY_SERVICE_NAME]  : "rcmd";
+  const size_t service_length = strlen(service);
 
   /*   GSS-API request looks like
    * +----+------+-----+----------------+
@@ -102,11 +103,13 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
       return CURLE_OUT_OF_MEMORY;
   }
   else {
-    service_name = malloc(strlen(service) + strlen(conn->proxy.name) + 2);
+    service_name = malloc(service_length +
+                          strlen(conn->socks_proxy.host.name) + 2);
     if(!service_name)
       return CURLE_OUT_OF_MEMORY;
-    snprintf(service_name, strlen(service) +strlen(conn->proxy.name)+2,
-             "%s/%s", service, conn->proxy.name);
+    snprintf(service_name, service_length +
+             strlen(conn->socks_proxy.host.name)+2, "%s/%s",
+             service, conn->socks_proxy.host.name);
   }
 
   input_desc.cBuffers = 1;
diff --git a/lib/speedcheck.c b/lib/speedcheck.c
index 13c34af..bc15d97 100644
--- a/lib/speedcheck.c
+++ b/lib/speedcheck.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -40,8 +40,8 @@ CURLcode Curl_speedcheck(struct Curl_easy *data,
      data->set.low_speed_time &&
      (Curl_tvlong(data->state.keeps_speed) != 0) &&
      (data->progress.current_speed < data->set.low_speed_limit)) {
-    long howlong = Curl_tvdiff(now, data->state.keeps_speed);
-    long nextcheck = (data->set.low_speed_time * 1000) - howlong;
+    time_t howlong = Curl_tvdiff(now, data->state.keeps_speed);
+    time_t nextcheck = (data->set.low_speed_time * 1000) - howlong;
 
     /* We are now below the "low speed limit". If we are below it
        for "low speed time" seconds we consider that enough reason
diff --git a/lib/ssh.c b/lib/ssh.c
index 43c8283..5ed036a 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -71,7 +71,7 @@
 #include "url.h"
 #include "speedcheck.h"
 #include "getinfo.h"
-
+#include "strdup.h"
 #include "strcase.h"
 #include "vtls/vtls.h"
 #include "connect.h"
@@ -239,7 +239,7 @@ kbd_callback(const char *name, int name_len, const char *instruction,
 
 static CURLcode sftp_libssh2_error_to_CURLE(int err)
 {
-  switch (err) {
+  switch(err) {
     case LIBSSH2_FX_OK:
       return CURLE_OK;
 
@@ -271,7 +271,7 @@ static CURLcode sftp_libssh2_error_to_CURLE(int err)
 
 static CURLcode libssh2_session_error_to_CURLE(int err)
 {
-  switch (err) {
+  switch(err) {
     /* Ordered by order of appearance in libssh2.h */
     case LIBSSH2_ERROR_NONE:
       return CURLE_OK;
@@ -676,7 +676,7 @@ static CURLcode ssh_check_fingerprint(struct connectdata *conn)
    * against a known fingerprint, if available.
    */
   if(pubkey_md5 && strlen(pubkey_md5) == 32) {
-    if(!fingerprint || strcmp(md5buffer, pubkey_md5)) {
+    if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) {
       if(fingerprint)
         failf(data,
             "Denied establishing ssh session: mismatch md5 fingerprint. "
@@ -782,14 +782,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           state(conn, SSH_AUTH_DONE);
           break;
         }
-        else if((err = libssh2_session_last_errno(sshc->ssh_session)) ==
-           LIBSSH2_ERROR_EAGAIN) {
-          rc = LIBSSH2_ERROR_EAGAIN;
-          break;
-        }
         else {
-          state(conn, SSH_SESSION_FREE);
-          sshc->actualcode = libssh2_session_error_to_CURLE(err);
+          err = libssh2_session_last_errno(sshc->ssh_session);
+          if(err == LIBSSH2_ERROR_EAGAIN)
+            rc = LIBSSH2_ERROR_EAGAIN;
+          else {
+            state(conn, SSH_SESSION_FREE);
+            sshc->actualcode = libssh2_session_error_to_CURLE(err);
+          }
           break;
         }
       }
@@ -874,7 +874,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           break;
         }
 
-        sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
+        sshc->passphrase = data->set.ssl.key_passwd;
         if(!sshc->passphrase)
           sshc->passphrase = "";
 
@@ -1987,12 +1987,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           break;
         }
       }
-      if((sshc->readdir_filename = malloc(PATH_MAX+1)) == NULL) {
+      sshc->readdir_filename = malloc(PATH_MAX+1);
+      if(!sshc->readdir_filename) {
         state(conn, SSH_SFTP_CLOSE);
         sshc->actualcode = CURLE_OUT_OF_MEMORY;
         break;
       }
-      if((sshc->readdir_longentry = malloc(PATH_MAX+1)) == NULL) {
+      sshc->readdir_longentry = malloc(PATH_MAX+1);
+      if(!sshc->readdir_longentry) {
         Curl_safefree(sshc->readdir_filename);
         state(conn, SSH_SFTP_CLOSE);
         sshc->actualcode = CURLE_OUT_OF_MEMORY;
@@ -2112,9 +2114,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
 
       /* get room for the filename and extra output */
       sshc->readdir_totalLen += 4 + sshc->readdir_len;
-      new_readdir_line = realloc(sshc->readdir_line, sshc->readdir_totalLen);
+      new_readdir_line = Curl_saferealloc(sshc->readdir_line,
+                                          sshc->readdir_totalLen);
       if(!new_readdir_line) {
-        Curl_safefree(sshc->readdir_line);
+        sshc->readdir_line = NULL;
         Curl_safefree(sshc->readdir_filename);
         Curl_safefree(sshc->readdir_longentry);
         state(conn, SSH_SFTP_CLOSE);
@@ -2651,7 +2654,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         else if(rc < 0) {
           infof(data, "Failed to disconnect from libssh2 agent\n");
         }
-        libssh2_agent_free (sshc->ssh_agent);
+        libssh2_agent_free(sshc->ssh_agent);
         sshc->ssh_agent = NULL;
 
         /* NB: there is no need to free identities, they are part of internal
@@ -2788,13 +2791,16 @@ static int ssh_getsock(struct connectdata *conn,
 static void ssh_block2waitfor(struct connectdata *conn, bool block)
 {
   struct ssh_conn *sshc = &conn->proto.sshc;
-  int dir;
-  if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) {
-    /* translate the libssh2 define bits into our own bit defines */
-    conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
-      ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
+  int dir = 0;
+  if(block) {
+    dir = libssh2_session_block_directions(sshc->ssh_session);
+    if(dir) {
+      /* translate the libssh2 define bits into our own bit defines */
+      conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
+        ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
+    }
   }
-  else
+  if(!dir)
     /* It didn't block or libssh2 didn't reveal in which direction, put back
        the original set */
     conn->waitfor = sshc->orig_waitfor;
@@ -2860,8 +2866,8 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
       if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
         fd_write = sock;
       /* wait for the socket to become ready */
-      Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
-                        left>1000?1000:left); /* ignore result */
+      (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
+                              left>1000?1000:left); /* ignore result */
     }
 #endif
 
@@ -3383,7 +3389,7 @@ get_pathname(const char **cpp, char **path)
 
 static const char *sftp_libssh2_strerror(int err)
 {
-  switch (err) {
+  switch(err) {
     case LIBSSH2_FX_NO_SUCH_FILE:
       return "No such file or directory";
 
diff --git a/lib/strcase.c b/lib/strcase.c
index 807689e..a750f7b 100644
--- a/lib/strcase.c
+++ b/lib/strcase.c
@@ -34,7 +34,7 @@ char Curl_raw_toupper(char in)
   if(in >= 'a' && in <= 'z')
     return (char)('A' + in - 'a');
 #else
-  switch (in) {
+  switch(in) {
   case 'a':
     return 'A';
   case 'b':
@@ -120,6 +120,16 @@ int Curl_strcasecompare(const char *first, const char *second)
   return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
 }
 
+int Curl_safe_strcasecompare(const char *first, const char *second)
+{
+  if(first && second)
+    /* both pointers point to something then compare them */
+    return Curl_strcasecompare(first, second);
+  else
+    /* if both pointers are NULL then treat them as equal */
+    return (NULL == first && NULL == second);
+}
+
 /*
  * @unittest: 1301
  */
diff --git a/lib/strcase.h b/lib/strcase.h
index bf057b1..ea2abc8 100644
--- a/lib/strcase.h
+++ b/lib/strcase.h
@@ -36,6 +36,7 @@
 #define strncasecompare(a,b,c) Curl_strncasecompare(a,b,c)
 
 int Curl_strcasecompare(const char *first, const char *second);
+int Curl_safe_strcasecompare(const char *first, const char *second);
 int Curl_strncasecompare(const char *first, const char *second, size_t max);
 
 char Curl_raw_toupper(char in);
diff --git a/lib/strdup.c b/lib/strdup.c
index 5a15c2b..136b693 100644
--- a/lib/strdup.c
+++ b/lib/strdup.c
@@ -75,3 +75,26 @@ void *Curl_memdup(const void *src, size_t length)
 
   return buffer;
 }
+
+/***************************************************************************
+ *
+ * Curl_saferealloc(ptr, size)
+ *
+ * Does a normal realloc(), but will free the data pointer if the realloc
+ * fails. If 'size' is zero, it will free the data and return a failure.
+ *
+ * This convenience function is provided and used to help us avoid a common
+ * mistake pattern when we could pass in a zero, catch the NULL return and end
+ * up free'ing the memory twice.
+ *
+ * Returns the new pointer or NULL on failure.
+ *
+ ***************************************************************************/
+void *Curl_saferealloc(void *ptr, size_t size)
+{
+  void *datap = realloc(ptr, size);
+  if(size && !datap)
+    /* only free 'ptr' if size was non-zero */
+    free(ptr);
+  return datap;
+}
diff --git a/lib/strdup.h b/lib/strdup.h
index c74a3b7..ae3d5d0 100644
--- a/lib/strdup.h
+++ b/lib/strdup.h
@@ -27,5 +27,6 @@
 extern char *curlx_strdup(const char *str);
 #endif
 void *Curl_memdup(const void *src, size_t buffer_length);
+void *Curl_saferealloc(void *ptr, size_t size);
 
 #endif /* HEADER_CURL_STRDUP_H */
diff --git a/lib/strerror.c b/lib/strerror.c
index db50c7d..7e5cde4 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -53,7 +53,7 @@ const char *
 curl_easy_strerror(CURLcode error)
 {
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-  switch (error) {
+  switch(error) {
   case CURLE_OK:
     return "No error";
 
@@ -348,7 +348,7 @@ const char *
 curl_multi_strerror(CURLMcode error)
 {
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-  switch (error) {
+  switch(error) {
   case CURLM_CALL_MULTI_PERFORM:
     return "Please call curl_multi_perform() soon";
 
@@ -393,7 +393,7 @@ const char *
 curl_share_strerror(CURLSHcode error)
 {
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-  switch (error) {
+  switch(error) {
   case CURLSHE_OK:
     return "No error";
 
@@ -435,7 +435,7 @@ get_winsock_error (int err, char *buf, size_t len)
   const char *p;
 
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
-  switch (err) {
+  switch(err) {
   case WSAEINTR:
     p = "Call interrupted";
     break;
@@ -609,7 +609,7 @@ get_winsock_error (int err, char *buf, size_t len)
   else
     p = "error";
 #endif
-  strncpy (buf, p, len);
+  strncpy(buf, p, len);
   buf [len-1] = '\0';
   return buf;
 }
@@ -715,10 +715,12 @@ const char *Curl_strerror(struct connectdata *conn, int err)
   buf[max] = '\0'; /* make sure the string is zero terminated */
 
   /* strip trailing '\r\n' or '\n'. */
-  if((p = strrchr(buf, '\n')) != NULL && (p - buf) >= 2)
-     *p = '\0';
-  if((p = strrchr(buf, '\r')) != NULL && (p - buf) >= 1)
-     *p = '\0';
+  p = strrchr(buf, '\n');
+  if(p && (p - buf) >= 2)
+    *p = '\0';
+  p = strrchr(buf, '\r');
+  if(p && (p - buf) >= 1)
+    *p = '\0';
 
   if(old_errno != ERRNO)
     SET_ERRNO(old_errno);
@@ -750,7 +752,7 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err)
 
   old_errno = ERRNO;
 
-  switch (err) {
+  switch(err) {
     case SEC_E_OK:
       txt = "No error";
       break;
@@ -1035,10 +1037,12 @@ const char *Curl_sspi_strerror (struct connectdata *conn, int err)
     if(msg_formatted) {
       msgbuf[sizeof(msgbuf)-1] = '\0';
       /* strip trailing '\r\n' or '\n' */
-      if((p = strrchr(msgbuf, '\n')) != NULL && (p - msgbuf) >= 2)
-         *p = '\0';
-      if((p = strrchr(msgbuf, '\r')) != NULL && (p - msgbuf) >= 1)
-         *p = '\0';
+      p = strrchr(msgbuf, '\n');
+      if(p && (p - msgbuf) >= 2)
+        *p = '\0';
+      p = strrchr(msgbuf, '\r');
+      if(p && (p - msgbuf) >= 1)
+        *p = '\0';
       msg = msgbuf;
     }
     if(msg)
diff --git a/lib/strtoofft.c b/lib/strtoofft.c
index 6d5d2d5..b854bf4 100644
--- a/lib/strtoofft.c
+++ b/lib/strtoofft.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -165,7 +165,7 @@ static int get_char(char c, int base)
     value = c - 'a' + 10;
   }
 #else
-  const char * cp;
+  const char *cp;
   int value;
 
   cp = memchr(valchars, c, 10 + 26 + 26);
diff --git a/lib/telnet.c b/lib/telnet.c
index c37242d..551af60 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -91,7 +91,7 @@
 
 #ifdef USE_WINSOCK
 typedef FARPROC WSOCK2_FUNC;
-static CURLcode check_wsock2 (struct Curl_easy *data);
+static CURLcode check_wsock2(struct Curl_easy *data);
 #endif
 
 static
@@ -935,7 +935,7 @@ static void suboption(struct connectdata *conn)
   struct TELNET *tn = (struct TELNET *)data->req.protop;
 
   printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2);
-  switch (CURL_SB_GET(tn)) {
+  switch(CURL_SB_GET(tn)) {
     case CURL_TELOPT_TTYPE:
       len = strlen(tn->subopt_ttype) + 4 + 2;
       snprintf((char *)temp, sizeof(temp),
@@ -1004,12 +1004,12 @@ static void sendsuboption(struct connectdata *conn, int option)
   ssize_t bytes_written;
   int err;
   unsigned short x, y;
-  unsigned char*uc1, *uc2;
+  unsigned char *uc1, *uc2;
 
   struct Curl_easy *data = conn->data;
   struct TELNET *tn = (struct TELNET *)data->req.protop;
 
-  switch (option) {
+  switch(option) {
   case CURL_TELOPT_NAWS:
     /* We prepare data to be sent */
     CURL_SB_CLEAR(tn);
@@ -1020,8 +1020,8 @@ static void sendsuboption(struct connectdata *conn, int option)
     /* Window size must be sent according to the 'network order' */
     x=htons(tn->subopt_wsx);
     y=htons(tn->subopt_wsy);
-    uc1 = (unsigned char*)&x;
-    uc2 = (unsigned char*)&y;
+    uc1 = (unsigned char *)&x;
+    uc2 = (unsigned char *)&y;
     CURL_SB_ACCUM(tn, uc1[0]);
     CURL_SB_ACCUM(tn, uc1[1]);
     CURL_SB_ACCUM(tn, uc2[0]);
@@ -1087,7 +1087,7 @@ CURLcode telrcv(struct connectdata *conn,
   while(count--) {
     c = inbuf[in];
 
-    switch (tn->telrcv_state) {
+    switch(tn->telrcv_state) {
     case CURL_TS_CR:
       tn->telrcv_state = CURL_TS_DATA;
       if(c == '\0') {
@@ -1111,7 +1111,7 @@ CURLcode telrcv(struct connectdata *conn,
     case CURL_TS_IAC:
     process_iac:
       DEBUGASSERT(startwrite < 0);
-      switch (c) {
+      switch(c) {
       case CURL_WILL:
         tn->telrcv_state = CURL_TS_WILL;
         break;
@@ -1241,7 +1241,7 @@ static CURLcode send_telnet_data(struct connectdata *conn,
       struct pollfd pfd[1];
       pfd[0].fd = conn->sock[FIRSTSOCKET];
       pfd[0].events = POLLOUT;
-      switch (Curl_poll(pfd, 1, -1)) {
+      switch(Curl_poll(pfd, 1, -1)) {
         case -1:                    /* error, abort writing */
         case 0:                     /* timeout (will never happen) */
           result = CURLE_SEND_ERROR;
@@ -1489,7 +1489,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
 
       events.lNetworkEvents = 0;
       if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) {
-        if((err = SOCKERRNO) != EINPROGRESS) {
+        err = SOCKERRNO;
+        if(err != EINPROGRESS) {
           infof(data, "WSAEnumNetworkEvents failed (%d)", err);
           keepon = FALSE;
           result = CURLE_READ_ERROR;
@@ -1576,7 +1577,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
   }
 
   while(keepon) {
-    switch (Curl_poll(pfd, poll_cnt, interval_ms)) {
+    switch(Curl_poll(pfd, poll_cnt, interval_ms)) {
     case -1:                    /* error, stop reading */
       keepon = FALSE;
       continue;
diff --git a/lib/tftp.c b/lib/tftp.c
index deee394..f2f8347 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -199,7 +199,7 @@ const struct Curl_handler Curl_handler_tftp = {
 static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
 {
   time_t maxtime, timeout;
-  long timeout_ms;
+  time_t timeout_ms;
   bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE;
 
   time(&state->start_time);
@@ -304,7 +304,7 @@ static unsigned short getrpacketblock(const tftp_packet_t *packet)
 
 static size_t Curl_strnlen(const char *string, size_t maxlen)
 {
-  const char *end = memchr (string, '\0', maxlen);
+  const char *end = memchr(string, '\0', maxlen);
   return end ? (size_t) (end - string) : maxlen;
 }
 
@@ -1356,7 +1356,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
 static CURLcode tftp_setup_connection(struct connectdata * conn)
 {
   struct Curl_easy *data = conn->data;
-  char * type;
+  char *type;
   char command;
 
   conn->socktype = SOCK_DGRAM;   /* UDP datagram based */
@@ -1372,7 +1372,7 @@ static CURLcode tftp_setup_connection(struct connectdata * conn)
     *type = 0;                   /* it was in the middle of the hostname */
     command = Curl_raw_toupper(type[6]);
 
-    switch (command) {
+    switch(command) {
     case 'A': /* ASCII mode */
     case 'N': /* NETASCII mode */
       data->set.prefer_ascii = TRUE;
diff --git a/lib/timeval.c b/lib/timeval.c
index 629f1c8..f3b207a 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -116,7 +116,7 @@ struct timeval curlx_tvnow(void)
  * Returns: the time difference in number of milliseconds. For large diffs it
  * returns 0x7fffffff on 32bit time_t systems.
  */
-long curlx_tvdiff(struct timeval newer, struct timeval older)
+time_t curlx_tvdiff(struct timeval newer, struct timeval older)
 {
 #if SIZEOF_TIME_T < 8
   /* for 32bit time_t systems, add a precaution to avoid overflow for really
@@ -126,7 +126,7 @@ long curlx_tvdiff(struct timeval newer, struct timeval older)
     return 0x7fffffff;
 #endif
   return (newer.tv_sec-older.tv_sec)*1000+
-    (long)(newer.tv_usec-older.tv_usec)/1000;
+    (time_t)(newer.tv_usec-older.tv_usec)/1000;
 }
 
 /*
@@ -144,7 +144,7 @@ double curlx_tvdiff_secs(struct timeval newer, struct timeval older)
 }
 
 /* return the number of seconds in the given input timeval struct */
-long Curl_tvlong(struct timeval t1)
+time_t Curl_tvlong(struct timeval t1)
 {
   return t1.tv_sec;
 }
diff --git a/lib/timeval.h b/lib/timeval.h
index 50c31a2..09f8b3a 100644
--- a/lib/timeval.h
+++ b/lib/timeval.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@ struct timeval curlx_tvnow(void);
  *
  * Returns: the time difference in number of milliseconds.
  */
-long curlx_tvdiff(struct timeval t1, struct timeval t2);
+time_t curlx_tvdiff(struct timeval t1, struct timeval t2);
 
 /*
  * Same as curlx_tvdiff but with full usec resolution.
@@ -46,7 +46,7 @@ long curlx_tvdiff(struct timeval t1, struct timeval t2);
  */
 double curlx_tvdiff_secs(struct timeval t1, struct timeval t2);
 
-long Curl_tvlong(struct timeval t1);
+time_t Curl_tvlong(struct timeval t1);
 
 /* These two defines below exist to provide the older API for library
    internals only. */
diff --git a/lib/transfer.c b/lib/transfer.c
index 6245ee4..750fb04 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -741,8 +741,8 @@ static CURLcode readwrite_data(struct Curl_easy *data,
              Make sure that ALL_CONTENT_ENCODINGS contains all the
              encodings handled here. */
 #ifdef HAVE_LIBZ
-          switch (conn->data->set.http_ce_skip ?
-                  IDENTITY : k->auto_decoding) {
+          switch(conn->data->set.http_ce_skip ?
+                 IDENTITY : k->auto_decoding) {
           case IDENTITY:
 #endif
             /* This is the default when the server sends no
@@ -775,9 +775,9 @@ static CURLcode readwrite_data(struct Curl_easy *data,
             break;
 
           default:
-            failf (data, "Unrecognized content encoding type. "
-                   "libcurl understands `identity', `deflate' and `gzip' "
-                   "content encodings.");
+            failf(data, "Unrecognized content encoding type. "
+                  "libcurl understands `identity', `deflate' and `gzip' "
+                  "content encodings.");
             result = CURLE_BAD_CONTENT_ENCODING;
             break;
           }
@@ -1137,7 +1137,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
 
       */
 
-      long ms = Curl_tvdiff(k->now, k->start100);
+      time_t ms = Curl_tvdiff(k->now, k->start100);
       if(ms >= data->set.expect_100_timeout) {
         /* we've waited long enough, continue anyway */
         k->exp100 = EXP100_SEND_DATA;
@@ -1296,7 +1296,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
   /* Init the SSL session ID cache here. We do it here since we want to do it
      after the *_setopt() calls (that could specify the size of the cache) but
      before any transfer takes place. */
-  result = Curl_ssl_initsessions(data, data->set.ssl.max_ssl_sessions);
+  result = Curl_ssl_initsessions(data, data->set.general_ssl.max_ssl_sessions);
   if(result)
     return result;
 
diff --git a/lib/url.c b/lib/url.c
index b997f41..7944d7b 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -92,6 +92,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
 #include "warnless.h"
 #include "non-ascii.h"
 #include "inet_pton.h"
+#include "getinfo.h"
 
 /* And now for the protocols */
 #include "ftp.h"
@@ -463,6 +464,7 @@ CURLcode Curl_close(struct Curl_easy *data)
   /* this destroys the channel and we cannot use it anymore after this */
   Curl_resolver_cleanup(data->state.resolver);
 
+  Curl_http2_cleanup_dependencies(data);
   Curl_convert_close(data);
 
   /* No longer a dirty share, if it exists */
@@ -525,9 +527,9 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
   set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
 
   /* Set the default size of the SSL session ID cache */
-  set->ssl.max_ssl_sessions = 5;
+  set->general_ssl.max_ssl_sessions = 5;
 
-  set->proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */
+  set->proxyport = 0;
   set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
   set->httpauth = CURLAUTH_BASIC;  /* defaults to basic */
   set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
@@ -539,14 +541,16 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
    * libcurl 7.10 introduced SSL verification *by default*! This needs to be
    * switched off unless wanted.
    */
-  set->ssl.verifypeer = TRUE;
-  set->ssl.verifyhost = TRUE;
+  set->ssl.primary.verifypeer = TRUE;
+  set->ssl.primary.verifyhost = TRUE;
 #ifdef USE_TLS_SRP
   set->ssl.authtype = CURL_TLSAUTH_NONE;
 #endif
   set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
                                                       type */
-  set->ssl.sessionid = TRUE; /* session ID caching enabled by default */
+  set->general_ssl.sessionid = TRUE; /* session ID caching enabled by
+                                        default */
+  set->proxy_ssl = set->ssl;
 
   set->new_file_perms = 0644;    /* Default permissions */
   set->new_directory_perms = 0755; /* Default permissions */
@@ -569,14 +573,17 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
 
   /* This is our preferred CA cert bundle/path since install time */
 #if defined(CURL_CA_BUNDLE)
-  result = setstropt(&set->str[STRING_SSL_CAFILE], CURL_CA_BUNDLE);
+  result = setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
   if(result)
     return result;
 #endif
 #if defined(CURL_CA_PATH)
-  result = setstropt(&set->str[STRING_SSL_CAPATH], CURL_CA_PATH);
+  result = setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
   if(result)
     return result;
+
+  result = setstropt(&set->str[STRING_SSL_CAPATH_PROXY],
+                     (char *) CURL_CA_PATH);
 #endif
 
   set->wildcardmatch  = FALSE;
@@ -646,6 +653,8 @@ CURLcode Curl_open(struct Curl_easy **curl)
 
     Curl_convert_init(data);
 
+    Curl_initinfo(data);
+
     /* most recent connection is not yet defined */
     data->state.lastconnect = NULL;
 
@@ -694,7 +703,12 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     break;
   case CURLOPT_SSL_CIPHER_LIST:
     /* set a list of cipher we want to use in the SSL connection */
-    result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST],
+    result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSL_CIPHER_LIST:
+    /* set a list of cipher we want to use in the SSL connection for proxy */
+    result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
                        va_arg(param, char *));
     break;
 
@@ -900,7 +914,18 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * implementations are lame.
      */
 #ifdef USE_SSL
-    data->set.ssl.version = va_arg(param, long);
+    data->set.ssl.primary.version = va_arg(param, long);
+#else
+    result = CURLE_UNKNOWN_OPTION;
+#endif
+    break;
+  case CURLOPT_PROXY_SSLVERSION:
+    /*
+     * Set explicit SSL version to try to connect with for proxy, as some SSL
+     * implementations are lame.
+     */
+#ifdef USE_SSL
+    data->set.proxy_ssl.primary.version = va_arg(param, long);
 #else
     result = CURLE_UNKNOWN_OPTION;
 #endif
@@ -1007,7 +1032,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
           (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
         result = CURLE_OUT_OF_MEMORY;
       else {
-        char * p;
+        char *p;
 
         (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
 
@@ -1434,18 +1459,30 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
 
   case CURLOPT_PROXY:
     /*
-     * Set proxy server:port to use as HTTP proxy.
+     * Set proxy server:port to use as proxy.
      *
-     * If the proxy is set to "" we explicitly say that we don't want to use a
-     * proxy (even though there might be environment variables saying so).
+     * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
+     * we explicitly say that we don't want to use a proxy
+     * (even though there might be environment variables saying so).
      *
      * Setting it to NULL, means no proxy but allows the environment variables
-     * to decide for us.
+     * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
      */
     result = setstropt(&data->set.str[STRING_PROXY],
                        va_arg(param, char *));
     break;
 
+  case CURLOPT_PRE_PROXY:
+    /*
+     * Set proxy server:port to use as SOCKS proxy.
+     *
+     * If the proxy is set to "" or NULL we explicitly say that we don't want
+     * to use the socks proxy.
+     */
+    result = setstropt(&data->set.str[STRING_PRE_PROXY],
+                       va_arg(param, char *));
+    break;
+
   case CURLOPT_PROXYTYPE:
     /*
      * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
@@ -1457,7 +1494,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     /*
      * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
      */
-    switch (va_arg(param, long)) {
+    switch(va_arg(param, long)) {
     case 0:
       data->set.proxy_transfer_mode = FALSE;
       break;
@@ -1910,35 +1947,70 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     /*
      * String that holds file name of the SSL certificate to use
      */
-    result = setstropt(&data->set.str[STRING_CERT],
+    result = setstropt(&data->set.str[STRING_CERT_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSLCERT:
+    /*
+     * String that holds file name of the SSL certificate to use for proxy
+     */
+    result = setstropt(&data->set.str[STRING_CERT_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_SSLCERTTYPE:
     /*
      * String that holds file type of the SSL certificate to use
      */
-    result = setstropt(&data->set.str[STRING_CERT_TYPE],
+    result = setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSLCERTTYPE:
+    /*
+     * String that holds file type of the SSL certificate to use for proxy
+     */
+    result = setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_SSLKEY:
     /*
      * String that holds file name of the SSL key to use
      */
-    result = setstropt(&data->set.str[STRING_KEY],
+    result = setstropt(&data->set.str[STRING_KEY_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSLKEY:
+    /*
+     * String that holds file name of the SSL key to use for proxy
+     */
+    result = setstropt(&data->set.str[STRING_KEY_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_SSLKEYTYPE:
     /*
      * String that holds file type of the SSL key to use
      */
-    result = setstropt(&data->set.str[STRING_KEY_TYPE],
+    result = setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_SSLKEYTYPE:
+    /*
+     * String that holds file type of the SSL key to use for proxy
+     */
+    result = setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_KEYPASSWD:
     /*
      * String that holds the SSL or SSH private key password.
      */
-    result = setstropt(&data->set.str[STRING_KEY_PASSWD],
+    result = setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_KEYPASSWD:
+    /*
+     * String that holds the SSL private key password for proxy.
+     */
+    result = setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_SSLENGINE:
@@ -2001,7 +2073,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     /*
      * Enable peer SSL verifying.
      */
-    data->set.ssl.verifypeer = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
+                                       TRUE : FALSE;
+    break;
+  case CURLOPT_PROXY_SSL_VERIFYPEER:
+    /*
+     * Enable peer SSL verifying for proxy.
+     */
+    data->set.proxy_ssl.primary.verifypeer =
+      (0 != va_arg(param, long))?TRUE:FALSE;
     break;
   case CURLOPT_SSL_VERIFYHOST:
     /*
@@ -2019,7 +2099,25 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
 
-    data->set.ssl.verifyhost = (0 != arg) ? TRUE : FALSE;
+    data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
+    break;
+  case CURLOPT_PROXY_SSL_VERIFYHOST:
+    /*
+     * Enable verification of the host name in the peer certificate for proxy
+     */
+    arg = va_arg(param, long);
+
+    /* Obviously people are not reading documentation and too many thought
+       this argument took a boolean when it wasn't and misused it. We thus ban
+       1 as a sensible input and we warn about its use. Then we only have the
+       2 action internally stored as TRUE. */
+
+    if(1 == arg) {
+      failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+    }
+
+    data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE;
     break;
   case CURLOPT_SSL_VERIFYSTATUS:
     /*
@@ -2030,7 +2128,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
       break;
     }
 
-    data->set.ssl.verifystatus = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
+                                         TRUE : FALSE;
     break;
   case CURLOPT_SSL_CTX_FUNCTION:
 #ifdef have_curlssl_ssl_ctx
@@ -2076,7 +2175,19 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * Set pinned public key for SSL connection.
      * Specify file name of the public key in DER format.
      */
-    result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+    result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
+                       va_arg(param, char *));
+#else
+    result = CURLE_NOT_BUILT_IN;
+#endif
+    break;
+  case CURLOPT_PROXY_PINNEDPUBLICKEY:
+#ifdef have_curlssl_pinnedpubkey /* only by supported backends */
+    /*
+     * Set pinned public key for SSL connection.
+     * Specify file name of the public key in DER format.
+     */
+    result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
                        va_arg(param, char *));
 #else
     result = CURLE_NOT_BUILT_IN;
@@ -2086,7 +2197,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     /*
      * Set CA info for SSL connection. Specify file name of the CA certificate
      */
-    result = setstropt(&data->set.str[STRING_SSL_CAFILE],
+    result = setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_CAINFO:
+    /*
+     * Set CA info SSL connection for proxy. Specify file name of the
+     * CA certificate
+     */
+    result = setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_CAPATH:
@@ -2096,7 +2215,16 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * certificates which have been prepared using openssl c_rehash utility.
      */
     /* This does not work on windows. */
-    result = setstropt(&data->set.str[STRING_SSL_CAPATH],
+    result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_CAPATH:
+    /*
+     * Set CA path info for SSL connection proxy. Specify directory name of the
+     * CA certificates which have been prepared using openssl c_rehash utility.
+     */
+    /* This does not work on windows. */
+    result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
                        va_arg(param, char *));
 #else
     result = CURLE_NOT_BUILT_IN;
@@ -2107,7 +2235,15 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * Set CRL file info for SSL connection. Specify file name of the CRL
      * to check certificates revocation
      */
-    result = setstropt(&data->set.str[STRING_SSL_CRLFILE],
+    result = setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
+                       va_arg(param, char *));
+    break;
+  case CURLOPT_PROXY_CRLFILE:
+    /*
+     * Set CRL file info for SSL connection for proxy. Specify file name of the
+     * CRL to check certificates revocation
+     */
+    result = setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
                        va_arg(param, char *));
     break;
   case CURLOPT_ISSUERCERT:
@@ -2115,7 +2251,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
      * Set Issuer certificate file
      * to check certificates issuer
      */
-    result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT],
+    result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
                        va_arg(param, char *));
     break;
   case CURLOPT_TELNETOPTIONS:
@@ -2196,7 +2332,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
       }
 #endif   /* CURL_DISABLE_HTTP */
       if(data->share->sslsession) {
-        data->set.ssl.max_ssl_sessions = data->share->max_ssl_sessions;
+        data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
         data->state.session = data->share->sslsession;
       }
       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
@@ -2231,8 +2367,14 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
 
   case CURLOPT_SSL_OPTIONS:
     arg = va_arg(param, long);
-    data->set.ssl_enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
-    data->set.ssl_no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
+    data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+    data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
+    break;
+
+  case CURLOPT_PROXY_SSL_OPTIONS:
+    arg = va_arg(param, long);
+    data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
+    data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
     break;
 
 #endif
@@ -2328,7 +2470,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     break;
 
   case CURLOPT_SSL_SESSIONID_CACHE:
-    data->set.ssl.sessionid = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    data->set.general_ssl.sessionid = (0 != va_arg(param, long)) ?
+                                      TRUE : FALSE;
     break;
 
 #ifdef USE_LIBSSH2
@@ -2595,23 +2738,43 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     break;
 #ifdef USE_TLS_SRP
   case CURLOPT_TLSAUTH_USERNAME:
-    result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME],
+    result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
                        va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
+    if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
       data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
     break;
+  case CURLOPT_PROXY_TLSAUTH_USERNAME:
+    result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
+                       va_arg(param, char *));
+    if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
+       !data->set.proxy_ssl.authtype)
+      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+    break;
   case CURLOPT_TLSAUTH_PASSWORD:
-    result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD],
+    result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
                        va_arg(param, char *));
-    if(data->set.str[STRING_TLSAUTH_USERNAME] && !data->set.ssl.authtype)
+    if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
       data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
     break;
+  case CURLOPT_PROXY_TLSAUTH_PASSWORD:
+    result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
+                       va_arg(param, char *));
+    if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
+       !data->set.proxy_ssl.authtype)
+      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+    break;
   case CURLOPT_TLSAUTH_TYPE:
     if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
       data->set.ssl.authtype = CURL_TLSAUTH_SRP;
     else
       data->set.ssl.authtype = CURL_TLSAUTH_NONE;
     break;
+  case CURLOPT_PROXY_TLSAUTH_TYPE:
+    if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
+      data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
+    else
+      data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
+    break;
 #endif
   case CURLOPT_DNS_SERVERS:
     result = Curl_set_dns_servers(data, va_arg(param, char *));
@@ -2678,9 +2841,11 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
     return CURLE_NOT_BUILT_IN;
 #else
     struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
-    if(dep && GOOD_EASY_HANDLE(dep)) {
-      data->set.stream_depends_on = dep;
-      data->set.stream_depends_e = (option == CURLOPT_STREAM_DEPENDS_E);
+    if(!dep || GOOD_EASY_HANDLE(dep)) {
+      if(data->set.stream_depends_on) {
+        Curl_http2_remove_child(data->set.stream_depends_on, data);
+      }
+      Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
     }
     break;
 #endif
@@ -2718,10 +2883,10 @@ static void conn_reset_postponed_data(struct connectdata *conn, int num)
 #endif /* DEBUGBUILD */
   }
   else {
-    DEBUGASSERT (psnd->allocated_size == 0);
-    DEBUGASSERT (psnd->recv_size == 0);
-    DEBUGASSERT (psnd->recv_processed == 0);
-    DEBUGASSERT (psnd->bindsock == CURL_SOCKET_BAD);
+    DEBUGASSERT(psnd->allocated_size == 0);
+    DEBUGASSERT(psnd->recv_size == 0);
+    DEBUGASSERT(psnd->recv_processed == 0);
+    DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD);
   }
 }
 
@@ -2768,8 +2933,10 @@ static void conn_free(struct connectdata *conn)
   Curl_safefree(conn->passwd);
   Curl_safefree(conn->oauth_bearer);
   Curl_safefree(conn->options);
-  Curl_safefree(conn->proxyuser);
-  Curl_safefree(conn->proxypasswd);
+  Curl_safefree(conn->http_proxy.user);
+  Curl_safefree(conn->socks_proxy.user);
+  Curl_safefree(conn->http_proxy.passwd);
+  Curl_safefree(conn->socks_proxy.passwd);
   Curl_safefree(conn->allocptr.proxyuserpwd);
   Curl_safefree(conn->allocptr.uagent);
   Curl_safefree(conn->allocptr.userpwd);
@@ -2783,7 +2950,9 @@ static void conn_free(struct connectdata *conn)
   Curl_safefree(conn->trailer);
   Curl_safefree(conn->host.rawalloc); /* host name buffer */
   Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
-  Curl_safefree(conn->proxy.rawalloc); /* proxy name buffer */
+  Curl_safefree(conn->secondaryhostname);
+  Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
+  Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
   Curl_safefree(conn->master_buffer);
 
   conn_reset_all_postponed_data(conn);
@@ -2795,7 +2964,12 @@ static void conn_free(struct connectdata *conn)
   conn->recv_pipe = NULL;
 
   Curl_safefree(conn->localdev);
-  Curl_free_ssl_config(&conn->ssl_config);
+  Curl_free_primary_ssl_config(&conn->ssl_config);
+  Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
+
+#ifdef USE_UNIX_SOCKETS
+  Curl_safefree(conn->unix_domain_socket);
+#endif
 
   free(conn); /* free all the connection oriented data */
 }
@@ -2856,6 +3030,8 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
   free_fixed_hostname(&conn->host);
   free_fixed_hostname(&conn->conn_to_host);
   free_fixed_hostname(&conn->proxy);
+  free_fixed_hostname(&conn->http_proxy.host);
+  free_fixed_hostname(&conn->socks_proxy.host);
 
   Curl_ssl_close(conn, FIRSTSOCKET);
 
@@ -3014,8 +3190,8 @@ Curl_oldest_idle_connection(struct Curl_easy *data)
   struct curl_hash_iterator iter;
   struct curl_llist_element *curr;
   struct curl_hash_element *he;
-  long highscore=-1;
-  long score;
+  time_t highscore=-1;
+  time_t score;
   struct timeval now;
   struct connectdata *conn_candidate = NULL;
   struct connectbundle *bundle;
@@ -3052,6 +3228,21 @@ Curl_oldest_idle_connection(struct Curl_easy *data)
   return conn_candidate;
 }
 
+static bool
+proxy_info_matches(const struct proxy_info* data,
+                   const struct proxy_info* needle)
+{
+  if((data->proxytype == needle->proxytype) &&
+     (data->port == needle->port) &&
+     Curl_safe_strcasecompare(data->host.name, needle->host.name) &&
+     Curl_safe_strcasecompare(data->user, needle->user) &&
+     Curl_safe_strcasecompare(data->passwd, needle->passwd))
+    return TRUE;
+
+  return FALSE;
+}
+
+
 /*
  * This function finds the connection in the connection
  * bundle that has been unused for the longest time.
@@ -3064,8 +3255,8 @@ find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
                                       struct connectbundle *bundle)
 {
   struct curl_llist_element *curr;
-  long highscore=-1;
-  long score;
+  time_t highscore=-1;
+  time_t score;
   struct timeval now;
   struct connectdata *conn_candidate = NULL;
   struct connectdata *conn;
@@ -3147,7 +3338,7 @@ static int call_disconnect_if_dead(struct connectdata *conn,
 static void prune_dead_connections(struct Curl_easy *data)
 {
   struct timeval now = Curl_tvnow();
-  long elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
+  time_t elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
 
   if(elapsed >= 1000L) {
     Curl_conncache_foreach(data->state.conn_cache, data,
@@ -3326,6 +3517,17 @@ ConnectionExists(struct Curl_easy *data,
         }
       }
 
+#ifdef USE_UNIX_SOCKETS
+      if(needle->unix_domain_socket) {
+        if(!check->unix_domain_socket)
+          continue;
+        if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
+          continue;
+      }
+      else if(check->unix_domain_socket)
+        continue;
+#endif
+
       if((needle->handler->flags&PROTOPT_SSL) !=
          (check->handler->flags&PROTOPT_SSL))
         /* don't do mixed SSL and non-SSL connections */
@@ -3334,23 +3536,12 @@ ConnectionExists(struct Curl_easy *data,
           /* except protocols that have been upgraded via TLS */
           continue;
 
-      if(needle->handler->flags&PROTOPT_SSL) {
-        if((data->set.ssl.verifypeer != check->verifypeer) ||
-           (data->set.ssl.verifyhost != check->verifyhost))
-          continue;
-      }
-
-      if(needle->bits.proxy != check->bits.proxy)
-        /* don't do mixed proxy and non-proxy connections */
+      if(needle->bits.httpproxy != check->bits.httpproxy ||
+         needle->bits.socksproxy != check->bits.socksproxy)
         continue;
 
-      if(needle->bits.proxy &&
-         (needle->proxytype != check->proxytype ||
-          needle->bits.httpproxy != check->bits.httpproxy ||
-          needle->bits.tunnel_proxy != check->bits.tunnel_proxy ||
-          !strcasecompare(needle->proxy.name, check->proxy.name) ||
-          needle->port != check->port))
-        /* don't mix connections that use different proxies */
+      if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy,
+                                                        &check->socks_proxy))
         continue;
 
       if(needle->bits.conn_to_host != check->bits.conn_to_host)
@@ -3363,6 +3554,33 @@ ConnectionExists(struct Curl_easy *data,
          * connections that don't use this feature */
         continue;
 
+      if(needle->bits.httpproxy) {
+        if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
+          continue;
+
+        if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
+          continue;
+
+        if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
+          /* use https proxy */
+          if(needle->handler->flags&PROTOPT_SSL) {
+            /* use double layer ssl */
+            if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
+                                        &check->proxy_ssl_config))
+              continue;
+            if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
+              continue;
+          }
+          else {
+            if(!Curl_ssl_config_matches(&needle->ssl_config,
+                                        &check->ssl_config))
+              continue;
+            if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
+              continue;
+          }
+        }
+      }
+
       if(!canPipeline && check->inuse)
         /* this request can't be pipelined but the checked connection is
            already in use so we skip it */
@@ -3382,9 +3600,8 @@ ConnectionExists(struct Curl_easy *data,
         */
         if((check->localport != needle->localport) ||
            (check->localportrange != needle->localportrange) ||
-           !check->localdev ||
-           !needle->localdev ||
-           strcmp(check->localdev, needle->localdev))
+           (needle->localdev &&
+            (!check->localdev || strcmp(check->localdev, needle->localdev))))
           continue;
       }
 
@@ -3399,10 +3616,11 @@ ConnectionExists(struct Curl_easy *data,
       }
 
       if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) ||
-         (needle->bits.httpproxy && needle->bits.tunnel_proxy)) {
+         needle->bits.tunnel_proxy) {
         /* The requested connection does not use a HTTP proxy or it uses SSL or
-           it is a non-SSL protocol tunneled over the same HTTP proxy name and
-           port number */
+           it is a non-SSL protocol tunneled or it is a non-SSL protocol which
+           is allowed to be upgraded via TLS */
+
         if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
             (get_protocol_family(check->handler->protocol) ==
              needle->handler->protocol && check->tls_upgraded)) &&
@@ -3463,12 +3681,13 @@ ConnectionExists(struct Curl_easy *data,
 
         /* Same for Proxy NTLM authentication */
         if(wantProxyNTLMhttp) {
-          /* Both check->proxyuser and check->proxypasswd can be NULL */
-          if(!check->proxyuser || !check->proxypasswd)
+          /* Both check->http_proxy.user and check->http_proxy.passwd can be
+           * NULL */
+          if(!check->http_proxy.user || !check->http_proxy.passwd)
             continue;
 
-          if(strcmp(needle->proxyuser, check->proxyuser) ||
-             strcmp(needle->proxypasswd, check->proxypasswd))
+          if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
+             strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
             continue;
         }
         else if(check->proxyntlm.state != NTLMSTATE_NONE) {
@@ -3572,51 +3791,48 @@ ConnectionExists(struct Curl_easy *data,
    Note: this function's sub-functions call failf()
 
 */
-CURLcode Curl_connected_proxy(struct connectdata *conn,
-                              int sockindex)
+CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex)
 {
-  if(!conn->bits.proxy || sockindex)
-    /* this magic only works for the primary socket as the secondary is used
-       for FTP only and it has FTP specific magic in ftp.c */
-    return CURLE_OK;
+  CURLcode result = CURLE_OK;
 
-  switch(conn->proxytype) {
+  if(conn->bits.socksproxy) {
 #ifndef CURL_DISABLE_PROXY
-  case CURLPROXY_SOCKS5:
-  case CURLPROXY_SOCKS5_HOSTNAME:
-    return Curl_SOCKS5(conn->proxyuser, conn->proxypasswd,
-                       conn->bits.conn_to_host ? conn->conn_to_host.name :
-                       conn->host.name,
-                       conn->bits.conn_to_port ? conn->conn_to_port :
-                       conn->remote_port,
-                       FIRSTSOCKET, conn);
-
-  case CURLPROXY_SOCKS4:
-    return Curl_SOCKS4(conn->proxyuser,
-                       conn->bits.conn_to_host ? conn->conn_to_host.name :
-                       conn->host.name,
-                       conn->bits.conn_to_port ? conn->conn_to_port :
-                       conn->remote_port,
-                       FIRSTSOCKET, conn, FALSE);
-
-  case CURLPROXY_SOCKS4A:
-    return Curl_SOCKS4(conn->proxyuser,
-                       conn->bits.conn_to_host ? conn->conn_to_host.name :
-                       conn->host.name,
-                       conn->bits.conn_to_port ? conn->conn_to_port :
-                       conn->remote_port,
-                       FIRSTSOCKET, conn, TRUE);
+    const char * const host = conn->bits.conn_to_host ?
+                              conn->conn_to_host.name :
+                              conn->bits.httpproxy ?
+                              conn->http_proxy.host.name :
+                              sockindex == SECONDARYSOCKET ?
+                              conn->secondaryhostname : conn->host.name;
+    const int port = conn->bits.conn_to_port ? conn->conn_to_port :
+                     conn->bits.httpproxy ?
+                     (int)conn->http_proxy.port :
+                     sockindex == SECONDARYSOCKET ?
+                      conn->secondary_port : conn->remote_port;
+    conn->bits.socksproxy_connecting = TRUE;
+    switch(conn->socks_proxy.proxytype) {
+    case CURLPROXY_SOCKS5:
+    case CURLPROXY_SOCKS5_HOSTNAME:
+      result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
+                         host, port, sockindex, conn);
+      break;
 
+    case CURLPROXY_SOCKS4:
+    case CURLPROXY_SOCKS4A:
+      result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
+                           conn);
+      break;
+
+    default:
+      failf(conn->data, "unknown proxytype option given");
+      result = CURLE_COULDNT_CONNECT;
+    } /* switch proxytype */
+    conn->bits.socksproxy_connecting = FALSE;
+#else
+  (void)sockindex;
 #endif /* CURL_DISABLE_PROXY */
-  case CURLPROXY_HTTP:
-  case CURLPROXY_HTTP_1_0:
-    /* do nothing here. handled later. */
-    break;
-  default:
-    break;
-  } /* switch proxytype */
+  }
 
-  return CURLE_OK;
+  return result;
 }
 
 /*
@@ -3627,7 +3843,9 @@ void Curl_verboseconnect(struct connectdata *conn)
 {
   if(conn->data->set.verbose)
     infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
-          conn->bits.proxy ? conn->proxy.dispname : conn->host.dispname,
+          conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
+          conn->bits.httpproxy ? conn->http_proxy.host.dispname :
+                             conn->host.dispname,
           conn->ip_addr_str, conn->port, conn->connection_id);
 }
 #endif
@@ -3717,10 +3935,14 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
 
   if(!conn->bits.protoconnstart) {
 
-    result = Curl_proxy_connect(conn);
+    result = Curl_proxy_connect(conn, 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 &&
        (conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE))
       /* when using an HTTP tunnel proxy, await complete tunnel establishment
@@ -3750,7 +3972,7 @@ CURLcode Curl_protocol_connect(struct connectdata *conn,
  */
 static bool is_ASCII_name(const char *hostname)
 {
-  const unsigned char *ch = (const unsigned char*)hostname;
+  const unsigned char *ch = (const unsigned char *)hostname;
 
   while(*ch) {
     if(*ch++ & 0x80)
@@ -3879,12 +4101,14 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->data = data; /* Setup the association between this connection
                         and the Curl_easy */
 
-  conn->proxytype = data->set.proxytype; /* type */
+  conn->http_proxy.proxytype = data->set.proxytype;
+  conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
 
 #ifdef CURL_DISABLE_PROXY
 
   conn->bits.proxy = FALSE;
   conn->bits.httpproxy = FALSE;
+  conn->bits.socksproxy = FALSE;
   conn->bits.proxy_user_passwd = FALSE;
   conn->bits.tunnel_proxy = FALSE;
 
@@ -3895,11 +4119,20 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->bits.proxy = (data->set.str[STRING_PROXY] &&
                       *data->set.str[STRING_PROXY]) ? TRUE : FALSE;
   conn->bits.httpproxy = (conn->bits.proxy &&
-                          (conn->proxytype == CURLPROXY_HTTP ||
-                           conn->proxytype == CURLPROXY_HTTP_1_0)) ?
-                          TRUE : FALSE;
-  conn->bits.proxy_user_passwd = (data->set.str[STRING_PROXYUSERNAME]) ?
-                                 TRUE : FALSE;
+                          (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
+                           conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
+                           conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
+                           TRUE : FALSE;
+  conn->bits.socksproxy = (conn->bits.proxy &&
+                           !conn->bits.httpproxy) ? TRUE : FALSE;
+
+  if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) {
+    conn->bits.proxy = TRUE;
+    conn->bits.socksproxy = TRUE;
+  }
+
+  conn->bits.proxy_user_passwd =
+    (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE;
   conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
 
 #endif /* CURL_DISABLE_PROXY */
@@ -3908,8 +4141,10 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
   conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
 
-  conn->verifypeer = data->set.ssl.verifypeer;
-  conn->verifyhost = data->set.ssl.verifyhost;
+  conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
+  conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
+  conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
+  conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
 
   conn->ip_version = data->set.ipver;
 
@@ -3924,7 +4159,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
      !conn->master_buffer) {
     /* Allocate master_buffer to be used for HTTP/1 pipelining */
-    conn->master_buffer = calloc(BUFSIZE, sizeof (char));
+    conn->master_buffer = calloc(BUFSIZE, sizeof(char));
     if(!conn->master_buffer)
       goto error;
   }
@@ -4065,33 +4300,38 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
      * the URL protocols specified in RFC 1738
      */
     if(path[0] != '/') {
-      /* the URL included a host name, we ignore host names in file:// URLs
-         as the standards don't define what to do with them */
-      char *ptr=strchr(path, '/');
-      if(ptr) {
-        /* there was a slash present
-
-           RFC1738 (section 3.1, page 5) says:
-
-           The rest of the locator consists of data specific to the scheme,
-           and is known as the "url-path". It supplies the details of how the
-           specified resource can be accessed. Note that the "/" between the
-           host (or port) and the url-path is NOT part of the url-path.
-
-           As most agents use file://localhost/foo to get '/foo' although the
-           slash preceding foo is a separator and not a slash for the path,
-           a URL as file://localhost//foo must be valid as well, to refer to
-           the same file with an absolute path.
-        */
+      /* the URL includes a host name, it must match "localhost" or
+         "127.0.0.1" to be valid */
+      char *ptr;
+      if(!checkprefix("localhost/", path) &&
+         !checkprefix("127.0.0.1/", path)) {
+        failf(data, "Valid host name with slash missing in URL");
+        return CURLE_URL_MALFORMAT;
+      }
+      ptr = &path[9]; /* now points to the slash after the host */
 
-        if(ptr[1] && ('/' == ptr[1]))
-          /* if there was two slashes, we skip the first one as that is then
-             used truly as a separator */
-          ptr++;
+      /* there was a host name and slash present
 
-        /* This cannot be made with strcpy, as the memory chunks overlap! */
-        memmove(path, ptr, strlen(ptr)+1);
-      }
+         RFC1738 (section 3.1, page 5) says:
+
+         The rest of the locator consists of data specific to the scheme,
+         and is known as the "url-path". It supplies the details of how the
+         specified resource can be accessed. Note that the "/" between the
+         host (or port) and the url-path is NOT part of the url-path.
+
+         As most agents use file://localhost/foo to get '/foo' although the
+         slash preceding foo is a separator and not a slash for the path,
+         a URL as file://localhost//foo must be valid as well, to refer to
+         the same file with an absolute path.
+      */
+
+      if('/' == ptr[1])
+        /* if there was two slashes, we skip the first one as that is then
+           used truly as a separator */
+        ptr++;
+
+      /* This cannot be made with strcpy, as the memory chunks overlap! */
+      memmove(path, ptr, strlen(ptr)+1);
     }
 
     protop = "file"; /* protocol string */
@@ -4473,7 +4713,7 @@ void Curl_free_request_state(struct Curl_easy *data)
 * Checks if the host is in the noproxy list. returns true if it matches
 * and therefore the proxy should NOT be used.
 ****************************************************************/
-static bool check_noproxy(const char* name, const char* no_proxy)
+static bool check_noproxy(const char *name, const char *no_proxy)
 {
   /* no_proxy=domain1.dom,host.domain2.dom
    *   (a comma-separated list of hosts which should
@@ -4482,7 +4722,7 @@ static bool check_noproxy(const char* name, const char* no_proxy)
    */
   size_t tok_start;
   size_t tok_end;
-  const char* separator = ", ";
+  const char *separator = ", ";
   size_t no_proxy_len;
   size_t namelen;
   char *endptr;
@@ -4636,7 +4876,8 @@ static char *detect_proxy(struct connectdata *conn)
  * that may exist registered to the same proxy host.
  */
 static CURLcode parse_proxy(struct Curl_easy *data,
-                            struct connectdata *conn, char *proxy)
+                            struct connectdata *conn, char *proxy,
+                            curl_proxytype proxytype)
 {
   char *prox_portno;
   char *endofprot;
@@ -4645,6 +4886,10 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   char *proxyptr;
   char *portptr;
   char *atsign;
+  long port = -1;
+  char *proxyuser = NULL;
+  char *proxypasswd = NULL;
+  bool sockstype;
 
   /* We do the proxy host string parsing here. We want the host name and the
    * port name. Accept a protocol:// prefix
@@ -4654,14 +4899,16 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   endofprot = strstr(proxy, "://");
   if(endofprot) {
     proxyptr = endofprot+3;
-    if(checkprefix("socks5h", proxy))
-      conn->proxytype = CURLPROXY_SOCKS5_HOSTNAME;
+    if(checkprefix("https", proxy))
+      proxytype = CURLPROXY_HTTPS;
+    else if(checkprefix("socks5h", proxy))
+      proxytype = CURLPROXY_SOCKS5_HOSTNAME;
     else if(checkprefix("socks5", proxy))
-      conn->proxytype = CURLPROXY_SOCKS5;
+      proxytype = CURLPROXY_SOCKS5;
     else if(checkprefix("socks4a", proxy))
-      conn->proxytype = CURLPROXY_SOCKS4A;
+      proxytype = CURLPROXY_SOCKS4A;
     else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
-      conn->proxytype = CURLPROXY_SOCKS4;
+      proxytype = CURLPROXY_SOCKS4;
     else if(checkprefix("http:", proxy))
       ; /* leave it as HTTP or HTTP/1.0 */
     else {
@@ -4673,54 +4920,28 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   else
     proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
 
+#ifndef HTTPS_PROXY_SUPPORT
+  if(proxytype == CURLPROXY_HTTPS) {
+    failf(data, "Unsupported proxy \'%s\'"
+                ", libcurl is built without the HTTPS-proxy support.", proxy);
+    return CURLE_NOT_BUILT_IN;
+  }
+#endif
+
+  sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
+              proxytype == CURLPROXY_SOCKS5 ||
+              proxytype == CURLPROXY_SOCKS4A ||
+              proxytype == CURLPROXY_SOCKS4;
+
   /* Is there a username and password given in this proxy url? */
   atsign = strchr(proxyptr, '@');
   if(atsign) {
-    char *proxyuser = NULL;
-    char *proxypasswd = NULL;
     CURLcode result =
       parse_login_details(proxyptr, atsign - proxyptr,
-                          &proxyuser, &proxypasswd, NULL);
-    if(!result) {
-      /* found user and password, rip them out.  note that we are
-         unescaping them, as there is otherwise no way to have a
-         username or password with reserved characters like ':' in
-         them. */
-      Curl_safefree(conn->proxyuser);
-      if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH)
-        result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL,
-                                FALSE);
-      else {
-        conn->proxyuser = strdup("");
-        if(!conn->proxyuser)
-          result = CURLE_OUT_OF_MEMORY;
-      }
-
-      if(!result) {
-        Curl_safefree(conn->proxypasswd);
-        if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
-          result = Curl_urldecode(data, proxypasswd, 0,
-                                  &conn->proxypasswd, NULL, FALSE);
-        else {
-          conn->proxypasswd = strdup("");
-          if(!conn->proxypasswd)
-            result = CURLE_OUT_OF_MEMORY;
-        }
-      }
-
-      if(!result) {
-        conn->bits.proxy_user_passwd = TRUE; /* enable it */
-        atsign++; /* the right side of the @-letter */
-
-        proxyptr = atsign; /* now use this instead */
-      }
-    }
-
-    free(proxyuser);
-    free(proxypasswd);
-
+                              &proxyuser, &proxypasswd, NULL);
     if(result)
       return result;
+    proxyptr = atsign + 1;
   }
 
   /* start scanning for port number at this point */
@@ -4757,7 +4978,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   prox_portno = strchr(portptr, ':');
   if(prox_portno) {
     char *endp = NULL;
-    long port = 0;
+
     *prox_portno = 0x0; /* cut off number from host name */
     prox_portno ++;
     /* now set the local port number */
@@ -4791,15 +5012,59 @@ static CURLcode parse_proxy(struct Curl_easy *data,
     if(data->set.proxyport)
       /* None given in the proxy string, then get the default one if it is
          given */
-      conn->port = data->set.proxyport;
+      port = data->set.proxyport;
+    else {
+      if(proxytype == CURLPROXY_HTTPS)
+        port = CURL_DEFAULT_HTTPS_PROXY_PORT;
+      else
+        port = CURL_DEFAULT_PROXY_PORT;
+    }
   }
 
-  /* now, clone the cleaned proxy host name */
-  conn->proxy.rawalloc = strdup(proxyptr);
-  conn->proxy.name = conn->proxy.rawalloc;
+  if(*proxyptr) {
+    struct proxy_info *proxyinfo =
+      sockstype ? &conn->socks_proxy : &conn->http_proxy;
+    proxyinfo->proxytype = proxytype;
 
-  if(!conn->proxy.rawalloc)
-    return CURLE_OUT_OF_MEMORY;
+    if(proxyuser) {
+      /* found user and password, rip them out.  note that we are unescaping
+         them, as there is otherwise no way to have a username or password
+         with reserved characters like ':' in them. */
+      Curl_safefree(proxyinfo->user);
+      proxyinfo->user = curl_easy_unescape(data, proxyuser, 0, NULL);
+
+      if(!proxyinfo->user)
+        return CURLE_OUT_OF_MEMORY;
+
+      Curl_safefree(proxyinfo->passwd);
+      if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
+        proxyinfo->passwd = curl_easy_unescape(data, proxypasswd, 0, NULL);
+      else
+        proxyinfo->passwd = strdup("");
+
+      if(!proxyinfo->passwd)
+        return CURLE_OUT_OF_MEMORY;
+
+      conn->bits.proxy_user_passwd = TRUE; /* enable it */
+    }
+
+    if(port >= 0) {
+      proxyinfo->port = port;
+      if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
+        conn->port = port;
+    }
+
+    /* now, clone the cleaned proxy host name */
+    Curl_safefree(proxyinfo->host.rawalloc);
+    proxyinfo->host.rawalloc = strdup(proxyptr);
+    proxyinfo->host.name = proxyinfo->host.rawalloc;
+
+    if(!proxyinfo->host.rawalloc)
+      return CURLE_OUT_OF_MEMORY;
+  }
+
+  Curl_safefree(proxyuser);
+  Curl_safefree(proxypasswd);
 
   return CURLE_OK;
 }
@@ -4825,10 +5090,11 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data,
     proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
   }
 
-  result = Curl_urldecode(data, proxyuser, 0, &conn->proxyuser, NULL, FALSE);
+  result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
+                          FALSE);
   if(!result)
-    result = Curl_urldecode(data, proxypasswd, 0, &conn->proxypasswd, NULL,
-                            FALSE);
+    result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
+                            NULL, FALSE);
   return result;
 }
 #endif /* CURL_DISABLE_PROXY */
@@ -5180,11 +5446,16 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
       *portptr = '\0'; /* cut off the name there */
       conn->remote_port = curlx_ultous(port);
     }
-    else
+    else {
+      if(rest[0]) {
+        failf(data, "Illegal port number");
+        return CURLE_URL_MALFORMAT;
+      }
       /* Browser behavior adaptation. If there's a colon with no digits after,
          just cut off the name there which makes us ignore the colon and just
          use the default port. Firefox and Chrome both do that. */
       *portptr = '\0';
+    }
   }
 
   /* only if remote_port was not already parsed off the URL we use the
@@ -5404,6 +5675,9 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data,
   int host_match = FALSE;
   int port_match = FALSE;
 
+  *host_result = NULL;
+  *port_result = -1;
+
   if(*ptr == ':') {
     /* an empty hostname always matches */
     host_match = TRUE;
@@ -5466,9 +5740,9 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
 {
   CURLcode result = CURLE_OK;
   char *host = NULL;
-  int port = 0;
+  int port = -1;
 
-  while(conn_to_host && !host) {
+  while(conn_to_host && !host && port == -1) {
     result = parse_connect_to_string(data, conn, conn_to_host->data,
                                      &host, &port);
     if(result)
@@ -5487,7 +5761,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
     else {
       /* no "connect to host" */
       conn->bits.conn_to_host = FALSE;
-      free(host);
+      Curl_safefree(host);
     }
 
     if(port >= 0) {
@@ -5498,6 +5772,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
     else {
       /* no "connect to port" */
       conn->bits.conn_to_port = FALSE;
+      port = -1;
     }
 
     conn_to_host = conn_to_host->next;
@@ -5514,7 +5789,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
                                bool *async)
 {
   CURLcode result=CURLE_OK;
-  long timeout_ms = Curl_timeleft(data, NULL, TRUE);
+  time_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
 
   /*************************************************************
    * Resolve the name of the server or proxy
@@ -5531,32 +5806,36 @@ static CURLcode resolve_server(struct Curl_easy *data,
     struct Curl_dns_entry *hostaddr;
 
 #ifdef USE_UNIX_SOCKETS
-    if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
+    if(conn->unix_domain_socket) {
       /* Unix domain sockets are local. The host gets ignored, just use the
        * specified domain socket address. Do not cache "DNS entries". There is
        * no DNS involved and we already have the filesystem path available */
-      const char *path = data->set.str[STRING_UNIX_SOCKET_PATH];
+      const char *path = conn->unix_domain_socket;
 
       hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
       if(!hostaddr)
         result = CURLE_OUT_OF_MEMORY;
-      else if((hostaddr->addr = Curl_unix2addr(path)) != NULL)
-        hostaddr->inuse++;
       else {
-        /* Long paths are not supported for now */
-        if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) {
-          failf(data, "Unix socket path too long: '%s'", path);
-          result = CURLE_COULDNT_RESOLVE_HOST;
+        int longpath=0;
+        hostaddr->addr = Curl_unix2addr(path, &longpath);
+        if(hostaddr->addr)
+          hostaddr->inuse++;
+        else {
+          /* Long paths are not supported for now */
+          if(longpath) {
+            failf(data, "Unix socket path too long: '%s'", path);
+            result = CURLE_COULDNT_RESOLVE_HOST;
+          }
+          else
+            result = CURLE_OUT_OF_MEMORY;
+          free(hostaddr);
+          hostaddr = NULL;
         }
-        else
-          result = CURLE_OUT_OF_MEMORY;
-        free(hostaddr);
-        hostaddr = NULL;
       }
     }
     else
 #endif
-    if(!conn->proxy.name || !*conn->proxy.name) {
+    if(!conn->bits.proxy) {
       struct hostname *connhost;
       if(conn->bits.conn_to_host)
         connhost = &conn->conn_to_host;
@@ -5588,8 +5867,11 @@ static CURLcode resolve_server(struct Curl_easy *data,
     else {
       /* This is a proxy that hasn't been resolved yet. */
 
+      struct hostname * const host = conn->bits.socksproxy ?
+        &conn->socks_proxy.host : &conn->http_proxy.host;
+
       /* resolve proxy */
-      rc = Curl_resolv_timeout(conn, conn->proxy.name, (int)conn->port,
+      rc = Curl_resolv_timeout(conn, host->name, (int)conn->port,
                                &hostaddr, timeout_ms);
 
       if(rc == CURLRESOLV_PENDING)
@@ -5599,7 +5881,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
         result = CURLE_OPERATION_TIMEDOUT;
 
       else if(!hostaddr) {
-        failf(data, "Couldn't resolve proxy '%s'", conn->proxy.dispname);
+        failf(data, "Couldn't resolve proxy '%s'", host->dispname);
         result = CURLE_COULDNT_RESOLVE_PROXY;
         /* don't return yet, we need to clean up the timeout first */
       }
@@ -5619,12 +5901,18 @@ static CURLcode resolve_server(struct Curl_easy *data,
 static void reuse_conn(struct connectdata *old_conn,
                        struct connectdata *conn)
 {
+  free_fixed_hostname(&old_conn->http_proxy.host);
+  free_fixed_hostname(&old_conn->socks_proxy.host);
   free_fixed_hostname(&old_conn->proxy);
+
+  free(old_conn->http_proxy.host.rawalloc);
+  free(old_conn->socks_proxy.host.rawalloc);
   free(old_conn->proxy.rawalloc);
 
   /* free the SSL config struct from this connection struct as this was
      allocated in vain and is targeted for destruction */
-  Curl_free_ssl_config(&old_conn->ssl_config);
+  Curl_free_primary_ssl_config(&old_conn->ssl_config);
+  Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
 
   conn->data = old_conn->data;
 
@@ -5644,12 +5932,18 @@ static void reuse_conn(struct connectdata *old_conn,
   conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
   if(conn->bits.proxy_user_passwd) {
     /* use the new proxy user name and proxy password though */
-    Curl_safefree(conn->proxyuser);
-    Curl_safefree(conn->proxypasswd);
-    conn->proxyuser = old_conn->proxyuser;
-    conn->proxypasswd = old_conn->proxypasswd;
-    old_conn->proxyuser = NULL;
-    old_conn->proxypasswd = NULL;
+    Curl_safefree(conn->http_proxy.user);
+    Curl_safefree(conn->socks_proxy.user);
+    Curl_safefree(conn->http_proxy.passwd);
+    Curl_safefree(conn->socks_proxy.passwd);
+    conn->http_proxy.user = old_conn->http_proxy.user;
+    conn->socks_proxy.user = old_conn->socks_proxy.user;
+    conn->http_proxy.passwd = old_conn->http_proxy.passwd;
+    conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
+    old_conn->http_proxy.user = NULL;
+    old_conn->socks_proxy.user = NULL;
+    old_conn->http_proxy.passwd = NULL;
+    old_conn->socks_proxy.passwd = NULL;
   }
 
   /* host can change, when doing keepalive with a proxy or if the case is
@@ -5675,8 +5969,10 @@ static void reuse_conn(struct connectdata *old_conn,
 
   Curl_safefree(old_conn->user);
   Curl_safefree(old_conn->passwd);
-  Curl_safefree(old_conn->proxyuser);
-  Curl_safefree(old_conn->proxypasswd);
+  Curl_safefree(old_conn->http_proxy.user);
+  Curl_safefree(old_conn->socks_proxy.user);
+  Curl_safefree(old_conn->http_proxy.passwd);
+  Curl_safefree(old_conn->socks_proxy.passwd);
   Curl_safefree(old_conn->localdev);
 
   Curl_llist_destroy(old_conn->send_pipe, NULL);
@@ -5686,6 +5982,10 @@ static void reuse_conn(struct connectdata *old_conn,
   old_conn->recv_pipe = NULL;
 
   Curl_safefree(old_conn->master_buffer);
+
+#ifdef USE_UNIX_SOCKETS
+  Curl_safefree(old_conn->unix_domain_socket);
+#endif
 }
 
 /**
@@ -5717,6 +6017,7 @@ static CURLcode create_conn(struct Curl_easy *data,
   char *options = NULL;
   bool reuse;
   char *proxy = NULL;
+  char *socksproxy = NULL;
   bool prot_missing = FALSE;
   bool connections_available = TRUE;
   bool force_reuse = FALSE;
@@ -5883,18 +6184,35 @@ static CURLcode create_conn(struct Curl_easy *data,
     }
   }
 
+  if(data->set.str[STRING_PRE_PROXY]) {
+    socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
+    /* if global socks proxy is set, this is it */
+    if(NULL == socksproxy) {
+      failf(data, "memory shortage");
+      result = CURLE_OUT_OF_MEMORY;
+      goto out;
+    }
+  }
+
   if(data->set.str[STRING_NOPROXY] &&
      check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) {
-    free(proxy);  /* proxy is in exception list */
-    proxy = NULL;
+    Curl_safefree(proxy);
+    Curl_safefree(socksproxy);
   }
-  else if(!proxy)
+  else if(!proxy && !socksproxy)
     proxy = detect_proxy(conn);
 
 #ifdef USE_UNIX_SOCKETS
-  if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) {
-    free(proxy);  /* Unix domain sockets cannot be proxied, so disable it */
-    proxy = NULL;
+  if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
+    if(proxy) {
+      free(proxy); /* Unix domain sockets cannot be proxied, so disable it */
+      proxy = NULL;
+    }
+    conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
+    if(conn->unix_domain_socket == NULL) {
+      result = CURLE_OUT_OF_MEMORY;
+      goto out;
+    }
   }
 #endif
 
@@ -5903,23 +6221,36 @@ static CURLcode create_conn(struct Curl_easy *data,
                      protocol doesn't work with network */
     proxy = NULL;
   }
+  if(socksproxy && (!*socksproxy ||
+                    (conn->handler->flags & PROTOPT_NONETWORK))) {
+    free(socksproxy);  /* Don't bother with an empty socks proxy string or if
+                          the protocol doesn't work with network */
+    socksproxy = NULL;
+  }
 
   /***********************************************************************
    * If this is supposed to use a proxy, we need to figure out the proxy host
    * name, proxy type and port number, so that we can re-use an existing
    * connection that may exist registered to the same proxy host.
    ***********************************************************************/
-  if(proxy) {
-    result = parse_proxy(data, conn, proxy);
-
-    free(proxy); /* parse_proxy copies the proxy string */
-    proxy = NULL;
+  if(proxy || socksproxy) {
+    if(proxy) {
+      result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
+      Curl_safefree(proxy); /* parse_proxy copies the proxy string */
+      if(result)
+        goto out;
+    }
 
-    if(result)
-      goto out;
+    if(socksproxy) {
+      result = parse_proxy(data, conn, socksproxy,
+                           conn->socks_proxy.proxytype);
+      /* parse_proxy copies the socks proxy string */
+      Curl_safefree(socksproxy);
+      if(result)
+        goto out;
+    }
 
-    if((conn->proxytype == CURLPROXY_HTTP) ||
-       (conn->proxytype == CURLPROXY_HTTP_1_0)) {
+    if(conn->http_proxy.host.rawalloc) {
 #ifdef CURL_DISABLE_HTTP
       /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
       result = CURLE_UNSUPPORTED_PROTOCOL;
@@ -5938,12 +6269,34 @@ static CURLcode create_conn(struct Curl_easy *data,
       conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
       conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
     }
-    conn->bits.proxy = TRUE;
+
+    if(conn->socks_proxy.host.rawalloc) {
+      if(!conn->http_proxy.host.rawalloc) {
+        /* once a socks proxy */
+        if(!conn->socks_proxy.user) {
+          conn->socks_proxy.user = conn->http_proxy.user;
+          conn->http_proxy.user = NULL;
+          Curl_safefree(conn->socks_proxy.passwd);
+          conn->socks_proxy.passwd = conn->http_proxy.passwd;
+          conn->http_proxy.passwd = NULL;
+        }
+      }
+      conn->bits.socksproxy = TRUE;
+    }
+    else
+      conn->bits.socksproxy = FALSE; /* not a socks proxy */
   }
   else {
+    conn->bits.socksproxy = FALSE;
+    conn->bits.httpproxy = FALSE;
+  }
+  conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
+
+  if(!conn->bits.proxy) {
     /* we aren't using the proxy after all... */
     conn->bits.proxy = FALSE;
     conn->bits.httpproxy = FALSE;
+    conn->bits.socksproxy = FALSE;
     conn->bits.proxy_user_passwd = FALSE;
     conn->bits.tunnel_proxy = FALSE;
   }
@@ -6079,20 +6432,51 @@ static CURLcode create_conn(struct Curl_easy *data,
      that will be freed as part of the Curl_easy struct, but all cloned
      copies will be separately allocated.
   */
-  data->set.ssl.CApath = data->set.str[STRING_SSL_CAPATH];
-  data->set.ssl.CAfile = data->set.str[STRING_SSL_CAFILE];
-  data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE];
-  data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT];
-  data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
-  data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
-  data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST];
-  data->set.ssl.clientcert = data->set.str[STRING_CERT];
+  data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
+  data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
+  data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
+  data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
+  data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
+  data->set.proxy_ssl.primary.random_file =
+    data->set.str[STRING_SSL_RANDOM_FILE];
+  data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
+  data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
+  data->set.ssl.primary.cipher_list =
+    data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
+  data->set.proxy_ssl.primary.cipher_list =
+    data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
+
+  data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
+  data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
+  data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
+  data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
+  data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
+  data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
+  data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
+  data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
+  data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
+  data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
+  data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
+  data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
+  data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
+  data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
+  data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
+  data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
 #ifdef USE_TLS_SRP
-  data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME];
-  data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD];
+  data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
+  data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
+  data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
+  data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
 #endif
 
-  if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) {
+  if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
+     &conn->ssl_config)) {
+    result = CURLE_OUT_OF_MEMORY;
+    goto out;
+  }
+
+  if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
+                                    &conn->proxy_ssl_config)) {
     result = CURLE_OUT_OF_MEMORY;
     goto out;
   }
@@ -6149,7 +6533,9 @@ static CURLcode create_conn(struct Curl_easy *data,
     infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
           conn->connection_id,
           conn->bits.proxy?"proxy":"host",
-          conn->proxy.name?conn->proxy.dispname:conn->host.dispname);
+          conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
+          conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
+                                       conn->host.dispname);
   }
   else {
     /* We have decided that we want a new connection. However, we may not
@@ -6280,6 +6666,7 @@ static CURLcode create_conn(struct Curl_easy *data,
   free(options);
   free(passwd);
   free(user);
+  free(socksproxy);
   free(proxy);
   return result;
 }
diff --git a/lib/url.h b/lib/url.h
index 90d9db3..f13c8e6 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -67,6 +67,8 @@ void Curl_getoff_all_pipelines(struct Curl_easy *data,
 void Curl_close_connections(struct Curl_easy *data);
 
 #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
+#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
+                                             specified */
 
 CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex);
 
@@ -76,5 +78,16 @@ CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex);
 void Curl_verboseconnect(struct connectdata *conn);
 #endif
 
+#define CONNECT_PROXY_SSL()\
+  (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
+  !conn->bits.proxy_ssl_connected[sockindex])
+
+#define CONNECT_FIRSTSOCKET_PROXY_SSL()\
+  (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
+  !conn->bits.proxy_ssl_connected[FIRSTSOCKET])
+
+#define CONNECT_SECONDARYSOCKET_PROXY_SSL()\
+  (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
+  !conn->bits.proxy_ssl_connected[SECONDARYSOCKET])
 
 #endif /* HEADER_CURL_URL_H */
diff --git a/lib/urldata.h b/lib/urldata.h
index 7c7bf1b..0271d26 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -316,6 +316,8 @@ struct ssl_connect_data {
 #elif defined(USE_GSKIT)
   gsk_handle handle;
   int iocport;
+  int localfd;
+  int remotefd;
 #elif defined(USE_AXTLS)
   SSL_CTX* ssl_ctx;
   SSL*     ssl;
@@ -341,28 +343,38 @@ struct ssl_connect_data {
 #endif
 };
 
-struct ssl_config_data {
+struct ssl_primary_config {
   long version;          /* what version the client wants to use */
-  long certverifyresult; /* result from the certificate verification */
-
   bool verifypeer;       /* set TRUE if this is desired */
   bool verifyhost;       /* set TRUE if CN/SAN must match hostname */
   bool verifystatus;     /* set TRUE if certificate status must be checked */
   char *CApath;          /* certificate dir (doesn't work on windows) */
   char *CAfile;          /* certificate to verify peer against */
-  const char *CRLfile;   /* CRL to check certificate revocation */
-  const char *issuercert;/* optional issuer certificate filename */
   char *clientcert;
   char *random_file;     /* path to file containing "random" data */
   char *egdsocket;       /* path to file containing the EGD daemon socket */
   char *cipher_list;     /* list of ciphers to use */
-  size_t max_ssl_sessions; /* SSL session id cache size */
+};
+
+struct ssl_config_data {
+  struct ssl_primary_config primary;
+  bool enable_beast; /* especially allow this flaw for interoperability's
+                        sake*/
+  bool no_revoke;    /* disable SSL certificate revocation checks */
+  long certverifyresult; /* result from the certificate verification */
+  char *CRLfile;   /* CRL to check certificate revocation */
+  char *issuercert;/* optional issuer certificate filename */
   curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
   void *fsslctxp;        /* parameter for call back */
-  bool sessionid;        /* cache session IDs or not */
   bool certinfo;         /* gather lots of certificate info */
   bool falsestart;
 
+  char *cert; /* client certificate file name */
+  char *cert_type; /* format for certificate (default: PEM)*/
+  char *key; /* private key file name */
+  char *key_type; /* format for private key (default: PEM) */
+  char *key_passwd; /* plain text private key password */
+
 #ifdef USE_TLS_SRP
   char *username; /* TLS username (for, e.g., SRP) */
   char *password; /* TLS password (for, e.g., SRP) */
@@ -370,6 +382,11 @@ struct ssl_config_data {
 #endif
 };
 
+struct ssl_general_config {
+  bool sessionid; /* cache session IDs or not */
+  size_t max_ssl_sessions; /* SSL session id cache size */
+};
+
 /* information stored about one single SSL session */
 struct curl_ssl_session {
   char *name;       /* host name for which this ID was used */
@@ -380,7 +397,7 @@ struct curl_ssl_session {
   long age;         /* just a number, the higher the more recent */
   int remote_port;  /* remote port */
   int conn_to_port; /* remote port for the connection (may be -1) */
-  struct ssl_config_data ssl_config; /* setup for this session */
+  struct ssl_primary_config ssl_config; /* setup for this session */
 };
 
 /* Struct used for Digest challenge-response authentication */
@@ -451,7 +468,7 @@ struct ntlmdata {
 #else
   unsigned int flags;
   unsigned char nonce[8];
-  void* target_info; /* TargetInfo received in the ntlm type-2 message */
+  void *target_info; /* TargetInfo received in the ntlm type-2 message */
   unsigned int target_info_len;
 #endif
 };
@@ -497,6 +514,7 @@ struct ConnectBits {
                         that overrides the port in the URL (remote port) */
   bool proxy; /* if set, this transfer is done through a proxy - any type */
   bool httpproxy;    /* if set, this transfer is done through a http proxy */
+  bool socksproxy;   /* if set, this transfer is done through a socks proxy */
   bool user_passwd;    /* do we use user+password for this connection? */
   bool proxy_user_passwd; /* user+password for the proxy? */
   bool ipv6_ip; /* we communicate with a remote site specified with pure IPv6
@@ -531,6 +549,7 @@ struct ConnectBits {
   bool ftp_use_eprt;  /* As set with CURLOPT_FTP_USE_EPRT, but if we find out
                          EPRT doesn't work we disable it for the forthcoming
                          requests */
+  bool ftp_use_data_ssl; /* Enabled SSL for the data connection */
   bool netrc;         /* name+password provided by netrc */
   bool userpwd_in_url; /* name+password found in url */
   bool stream_was_rewound; /* Indicates that the stream was rewound after a
@@ -547,6 +566,9 @@ struct ConnectBits {
   bool tcp_fastopen; /* use TCP Fast Open */
   bool tls_enable_npn;  /* TLS NPN extension? */
   bool tls_enable_alpn; /* TLS ALPN extension? */
+  bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy
+                                  is complete */
+  bool socksproxy_connecting; /* connecting through a socks proxy */
 };
 
 struct hostname {
@@ -732,7 +754,7 @@ struct SingleRequest {
  */
 
 struct Curl_handler {
-  const char * scheme;        /* URL scheme name. */
+  const char *scheme;        /* URL scheme name. */
 
   /* Complement to setup_connection_internals(). */
   CURLcode (*setup_connection)(struct connectdata *);
@@ -849,6 +871,14 @@ struct postponed_data {
 };
 #endif /* USE_RECV_BEFORE_SEND_WORKAROUND */
 
+struct proxy_info {
+  struct hostname host;
+  long port;
+  curl_proxytype proxytype; /* what kind of proxy that is in use */
+  char *user;    /* proxy user name string, allocated */
+  char *passwd;  /* proxy password string, allocated */
+};
+
 /*
  * The connectdata struct contains all fields and variables that should be
  * unique for an entire connection.
@@ -898,14 +928,20 @@ struct connectdata {
   int socktype;  /* SOCK_STREAM or SOCK_DGRAM */
 
   struct hostname host;
+  char *secondaryhostname; /* secondary socket host name (ftp) */
   struct hostname conn_to_host; /* the host to connect to. valid only if
                                    bits.conn_to_host is set */
   struct hostname proxy;
 
+  struct proxy_info socks_proxy;
+  struct proxy_info http_proxy;
+
   long port;       /* which port to use locally */
   int remote_port; /* the remote port, not the proxy port! */
   int conn_to_port; /* the remote port to connect to. valid only if
                        bits.conn_to_port is set */
+  unsigned short secondary_port; /* secondary socket remote port to connect to
+                                    (ftp) */
 
   /* 'primary_ip' and 'primary_port' get filled with peer's numerical
      ip address and port number whenever an outgoing connection is
@@ -930,10 +966,6 @@ struct connectdata {
 
   char *oauth_bearer; /* bearer token for OAuth 2.0, allocated */
 
-  char *proxyuser;    /* proxy user name string, allocated */
-  char *proxypasswd;  /* proxy password string, allocated */
-  curl_proxytype proxytype; /* what kind of proxy that is in use */
-
   int httpversion;        /* the HTTP version*10 reported by the server */
   int rtspversion;        /* the RTSP version*10 reported by the server */
 
@@ -951,7 +983,9 @@ struct connectdata {
   struct postponed_data postponed[2]; /* two buffers for two sockets */
 #endif /* USE_RECV_BEFORE_SEND_WORKAROUND */
   struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
-  struct ssl_config_data ssl_config;
+  struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */
+  struct ssl_primary_config ssl_config;
+  struct ssl_primary_config proxy_ssl_config;
   bool tls_upgraded;
 
   struct ConnectBits bits;    /* various state-flags for this connection */
@@ -962,8 +996,8 @@ struct connectdata {
   struct timeval connecttime;
   /* The two fields below get set in Curl_connecthost */
   int num_addr; /* number of addresses to try to connect to */
-  long timeoutms_per_addr; /* how long time in milliseconds to spend on
-                              trying to connect to each IP address */
+  time_t timeoutms_per_addr; /* how long time in milliseconds to spend on
+                                trying to connect to each IP address */
 
   const struct Curl_handler *handler; /* Connection's protocol handler */
   const struct Curl_handler *given;   /* The protocol first given */
@@ -1020,7 +1054,7 @@ struct connectdata {
                                    send on this pipeline */
   struct curl_llist *recv_pipe; /* List of handles waiting to read
                                    their responses on this pipeline */
-  char* master_buffer; /* The master buffer allocated on-demand;
+  char *master_buffer; /* The master buffer allocated on-demand;
                           used for pipelining. */
   size_t read_pos; /* Current read position in the master buffer */
   size_t buf_len; /* Length of the buffer?? */
@@ -1041,8 +1075,8 @@ struct connectdata {
   /* used for communication with Samba's winbind daemon helper ntlm_auth */
   curl_socket_t ntlm_auth_hlpr_socket;
   pid_t ntlm_auth_hlpr_pid;
-  char* challenge_header;
-  char* response_header;
+  char *challenge_header;
+  char *response_header;
 #endif
 #endif
 
@@ -1078,9 +1112,6 @@ struct connectdata {
   int socks5_gssapi_enctype;
 #endif
 
-  bool verifypeer;
-  bool verifyhost;
-
   /* When this connection is created, store the conditions for the local end
      bind. This is stored before the actual bind and before any connection is
      made and will serve the purpose of being used for comparison reasons so
@@ -1099,13 +1130,17 @@ struct connectdata {
   struct connectbundle *bundle; /* The bundle we are member of */
 
   int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
+
+#ifdef USE_UNIX_SOCKETS
+  char *unix_domain_socket;
+#endif
 };
 
 /* The end of connectdata. */
 
 /*
  * Struct to keep statistical and informational data.
- * All variables in this struct must be reset in Curl_initinfo().
+ * All variables in this struct must be initialized/reset in Curl_initinfo().
  */
 struct PureInfo {
   int httpcode;  /* Recent HTTP, FTP, RTSP or SMTP response code */
@@ -1139,6 +1174,9 @@ struct PureInfo {
   char conn_local_ip[MAX_IPADR_LEN];
   long conn_local_port;
 
+  const char *conn_scheme;
+  unsigned int conn_protocol;
+
   struct curl_certinfo certs; /* info about the certs, only populated in
                                  OpenSSL builds. Asked for with
                                  CURLOPT_CERTINFO / CURLINFO_CERTINFO */
@@ -1146,8 +1184,8 @@ struct PureInfo {
 
 
 struct Progress {
-  long lastshow; /* time() of the last displayed progress meter or NULL to
-                    force redraw at next call */
+  time_t lastshow; /* time() of the last displayed progress meter or NULL to
+                      force redraw at next call */
   curl_off_t size_dl; /* total expected size */
   curl_off_t size_ul; /* total expected size */
   curl_off_t downloaded; /* transferred so far */
@@ -1242,6 +1280,11 @@ struct auth {
                    be RFC compliant */
 };
 
+struct Curl_http2_dep {
+  struct Curl_http2_dep *next;
+  struct Curl_easy *data;
+};
+
 struct UrlState {
 
   /* Points to the connection cache */
@@ -1402,8 +1445,10 @@ struct DynamicStatic {
 struct Curl_multi;    /* declared and used only in multi.c */
 
 enum dupstring {
-  STRING_CERT,            /* client certificate file name */
-  STRING_CERT_TYPE,       /* format for certificate (default: PEM)*/
+  STRING_CERT_ORIG,       /* client certificate file name */
+  STRING_CERT_PROXY,      /* client certificate file name */
+  STRING_CERT_TYPE_ORIG,  /* format for certificate (default: PEM)*/
+  STRING_CERT_TYPE_PROXY, /* format for certificate (default: PEM)*/
   STRING_COOKIE,          /* HTTP cookie string to send */
   STRING_COOKIEJAR,       /* dump all cookies to this file */
   STRING_CUSTOMREQUEST,   /* HTTP/FTP/RTSP request/method to use */
@@ -1413,25 +1458,35 @@ enum dupstring {
   STRING_FTP_ACCOUNT,     /* ftp account data */
   STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */
   STRING_FTPPORT,         /* port to send with the FTP PORT command */
-  STRING_KEY,             /* private key file name */
-  STRING_KEY_PASSWD,      /* plain text private key password */
-  STRING_KEY_TYPE,        /* format for private key (default: PEM) */
+  STRING_KEY_ORIG,        /* private key file name */
+  STRING_KEY_PROXY,       /* private key file name */
+  STRING_KEY_PASSWD_ORIG, /* plain text private key password */
+  STRING_KEY_PASSWD_PROXY, /* plain text private key password */
+  STRING_KEY_TYPE_ORIG,   /* format for private key (default: PEM) */
+  STRING_KEY_TYPE_PROXY,  /* format for private key (default: PEM) */
   STRING_KRB_LEVEL,       /* krb security level */
   STRING_NETRC_FILE,      /* if not NULL, use this instead of trying to find
                              $HOME/.netrc */
   STRING_PROXY,           /* proxy to use */
+  STRING_PRE_PROXY,       /* pre socks proxy to use */
   STRING_SET_RANGE,       /* range, if used */
   STRING_SET_REFERER,     /* custom string for the HTTP referer field */
   STRING_SET_URL,         /* what original URL to work on */
-  STRING_SSL_CAPATH,      /* CA directory name (doesn't work on windows) */
-  STRING_SSL_CAFILE,      /* certificate file to verify peer against */
-  STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */
-  STRING_SSL_CIPHER_LIST, /* list of ciphers to use */
+  STRING_SSL_CAPATH_ORIG, /* CA directory name (doesn't work on windows) */
+  STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */
+  STRING_SSL_CAFILE_ORIG, /* certificate file to verify peer against */
+  STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */
+  STRING_SSL_PINNEDPUBLICKEY_ORIG, /* public key file to verify peer against */
+  STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */
+  STRING_SSL_CIPHER_LIST_ORIG, /* list of ciphers to use */
+  STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */
   STRING_SSL_EGDSOCKET,   /* path to file containing the EGD daemon socket */
   STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */
   STRING_USERAGENT,       /* User-Agent string */
-  STRING_SSL_CRLFILE,     /* crl file to check certificate */
-  STRING_SSL_ISSUERCERT,  /* issuer cert file to check certificate */
+  STRING_SSL_CRLFILE_ORIG, /* crl file to check certificate */
+  STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */
+  STRING_SSL_ISSUERCERT_ORIG, /* issuer cert file to check certificate */
+  STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */
   STRING_USERNAME,        /* <username>, if used */
   STRING_PASSWORD,        /* <password>, if used */
   STRING_OPTIONS,         /* <options>, if used */
@@ -1459,8 +1514,10 @@ enum dupstring {
   STRING_MAIL_AUTH,
 
 #ifdef USE_TLS_SRP
-  STRING_TLSAUTH_USERNAME,      /* TLS auth <username> */
-  STRING_TLSAUTH_PASSWORD,      /* TLS auth <password> */
+  STRING_TLSAUTH_USERNAME_ORIG,  /* TLS auth <username> */
+  STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth <username> */
+  STRING_TLSAUTH_PASSWORD_ORIG,  /* TLS auth <password> */
+  STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth <password> */
 #endif
   STRING_BEARER,                /* <bearer>, if used */
 #ifdef USE_UNIX_SOCKETS
@@ -1524,10 +1581,10 @@ struct UserDefined {
   curl_opensocket_callback fopensocket; /* function for checking/translating
                                            the address and opening the
                                            socket */
-  void* opensocket_client;
+  void *opensocket_client;
   curl_closesocket_callback fclosesocket; /* function for closing the
                                              socket */
-  void* closesocket_client;
+  void *closesocket_client;
 
   void *seek_client;    /* pointer to pass to the seek callback */
   /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */
@@ -1578,7 +1635,10 @@ struct UserDefined {
   long httpversion; /* when non-zero, a specific HTTP version requested to
                        be used in the library's request(s) */
   struct ssl_config_data ssl;  /* user defined SSL stuff */
+  struct ssl_config_data proxy_ssl;  /* user defined SSL stuff for proxy */
+  struct ssl_general_config general_ssl; /* general user defined SSL stuff */
   curl_proxytype proxytype; /* what kind of proxy that is in use */
+  curl_proxytype socks_proxytype; /* what kind of socks proxy that is in use */
   long dns_cache_timeout; /* DNS cache timeout */
   long buffer_size;      /* size of receive buffer to use */
   void *private_data; /* application-private data */
@@ -1642,9 +1702,6 @@ struct UserDefined {
   bool ftp_skip_ip;      /* skip the IP address the FTP server passes on to
                             us */
   bool connect_only;     /* make connection, let application use the socket */
-  bool ssl_enable_beast; /* especially allow this flaw for interoperability's
-                            sake*/
-  bool ssl_no_revoke;    /* disable SSL certificate revocation checks */
   long ssh_auth_types;   /* allowed SSH auth types */
   bool http_te_skip;     /* pass the raw body data to the user, even when
                             transfer-encoded (chunked, compressed) */
@@ -1695,6 +1752,8 @@ struct UserDefined {
   struct Curl_easy *stream_depends_on;
   bool stream_depends_e; /* set or don't set the Exclusive bit */
   int stream_weight;
+
+  struct Curl_http2_dep *stream_dependents;
 };
 
 struct Names {
diff --git a/lib/vauth/cleartext.c b/lib/vauth/cleartext.c
index 6df419a..a761ae7 100644
--- a/lib/vauth/cleartext.c
+++ b/lib/vauth/cleartext.c
@@ -66,16 +66,27 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
   char *plainauth;
   size_t ulen;
   size_t plen;
+  size_t plainlen;
 
+  *outlen = 0;
+  *outptr = NULL;
   ulen = strlen(userp);
   plen = strlen(passwdp);
 
-  plainauth = malloc(2 * ulen + plen + 2);
-  if(!plainauth) {
-    *outlen = 0;
-    *outptr = NULL;
+  /* Compute binary message length, checking for overflows. */
+  plainlen = 2 * ulen;
+  if(plainlen < ulen)
+    return CURLE_OUT_OF_MEMORY;
+  plainlen += plen;
+  if(plainlen < plen)
+    return CURLE_OUT_OF_MEMORY;
+  plainlen += 2;
+  if(plainlen < 2)
+    return CURLE_OUT_OF_MEMORY;
+
+  plainauth = malloc(plainlen);
+  if(!plainauth)
     return CURLE_OUT_OF_MEMORY;
-  }
 
   /* Calculate the reply */
   memcpy(plainauth, userp, ulen);
@@ -85,8 +96,7 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
   memcpy(plainauth + 2 * ulen + 2, passwdp, plen);
 
   /* Base64 encode the reply */
-  result = Curl_base64_encode(data, plainauth, 2 * ulen + plen + 2, outptr,
-                              outlen);
+  result = Curl_base64_encode(data, plainauth, plainlen, outptr, outlen);
   free(plainauth);
 
   return result;
diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c
index 0a11a30..7d9200a 100644
--- a/lib/vauth/digest.c
+++ b/lib/vauth/digest.c
@@ -40,6 +40,7 @@
 #include "strcase.h"
 #include "non-ascii.h" /* included for Curl_convert_... prototypes */
 #include "curl_printf.h"
+#include "rand.h"
 
 /* The last #include files should be: */
 #include "curl_memory.h"
@@ -59,7 +60,7 @@
    what ultimately goes over the network.
 */
 #define CURL_OUTPUT_DIGEST_CONV(a, b) \
-  result = Curl_convert_to_network(a, (char *)b, strlen((const char*)b)); \
+  result = Curl_convert_to_network(a, (char *)b, strlen((const char *)b)); \
   if(result) { \
     free(b); \
     return result; \
@@ -387,10 +388,9 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
     return CURLE_BAD_CONTENT_ENCODING;
 
   /* Generate 16 bytes of random data */
-  entropy[0] = Curl_rand(data);
-  entropy[1] = Curl_rand(data);
-  entropy[2] = Curl_rand(data);
-  entropy[3] = Curl_rand(data);
+  result = Curl_rand(data, &entropy[0], 4);
+  if(result)
+    return result;
 
   /* Convert the random data into a 32 byte hex string */
   snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x",
@@ -684,9 +684,12 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
     digest->nc = 1;
 
   if(!digest->cnonce) {
+    unsigned int rnd[4];
+    result = Curl_rand(data, &rnd[0], 4);
+    if(result)
+      return result;
     snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x",
-             Curl_rand(data), Curl_rand(data),
-             Curl_rand(data), Curl_rand(data));
+             rnd[0], rnd[1], rnd[2], rnd[3]);
 
     result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
                                 &cnonce, &cnonce_sz);
diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c
index 29526fc..b9ceb12 100644
--- a/lib/vauth/digest_sspi.c
+++ b/lib/vauth/digest_sspi.c
@@ -414,7 +414,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
       return CURLE_OUT_OF_MEMORY;
 
     /* Populate our identity domain */
-    if(Curl_override_sspi_http_realm((const char*) digest->input_token,
+    if(Curl_override_sspi_http_realm((const char *) digest->input_token,
                                      &identity))
       return CURLE_OUT_OF_MEMORY;
 
diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c
index b484a01..b4d345d 100644
--- a/lib/vauth/ntlm.c
+++ b/lib/vauth/ntlm.c
@@ -41,7 +41,7 @@
 #include "curl_gethostname.h"
 #include "curl_multibyte.h"
 #include "warnless.h"
-
+#include "rand.h"
 #include "vtls/vtls.h"
 
 #ifdef USE_NSS
@@ -558,8 +558,9 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
     unsigned int entropy[2];
     unsigned char ntlmv2hash[0x18];
 
-    entropy[0] = Curl_rand(data);
-    entropy[1] = Curl_rand(data);
+    result = Curl_rand(data, &entropy[0], 2);
+    if(result)
+      return result;
 
     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
     if(result)
@@ -598,8 +599,9 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
     unsigned int entropy[2];
 
     /* Need to create 8 bytes random data */
-    entropy[0] = Curl_rand(data);
-    entropy[1] = Curl_rand(data);
+    result = Curl_rand(data, &entropy[0], 2);
+    if(result)
+      return result;
 
     /* 8 bytes random data as challenge in lmresp */
     memcpy(lmresp, entropy, 8);
diff --git a/lib/vauth/spnego_sspi.c b/lib/vauth/spnego_sspi.c
index 672b43f..5fa95e2 100644
--- a/lib/vauth/spnego_sspi.c
+++ b/lib/vauth/spnego_sspi.c
@@ -264,7 +264,7 @@ CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data,
 
   /* Base64 encode the already generated response */
   result = Curl_base64_encode(data,
-                              (const char*) nego->output_token,
+                              (const char *) nego->output_token,
                               nego->output_token_length,
                               outptr, outlen);
 
diff --git a/lib/version.c b/lib/version.c
index a434a62..3d17768 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -324,6 +324,9 @@ static curl_version_info_data version_info = {
 #if defined(USE_LIBPSL)
   | CURL_VERSION_PSL
 #endif
+#if defined(HTTPS_PROXY_SUPPORT)
+  | CURL_VERSION_HTTPS_PROXY
+#endif
   ,
   NULL, /* ssl_version */
   0,    /* ssl_version_num, this is kept at zero */
diff --git a/lib/vtls/axtls.c b/lib/vtls/axtls.c
index 85b8bc4..ff4634e 100644
--- a/lib/vtls/axtls.c
+++ b/lib/vtls/axtls.c
@@ -65,7 +65,7 @@ int Curl_axtls_cleanup(void)
 
 static CURLcode map_error_to_curl(int axtls_err)
 {
-  switch (axtls_err) {
+  switch(axtls_err) {
   case SSL_ERROR_NOT_SUPPORTED:
   case SSL_ERROR_INVALID_VERSION:
   case -70:                       /* protocol version alert from server */
@@ -121,7 +121,7 @@ static Curl_send axtls_send;
 static void free_ssl_structs(struct ssl_connect_data *connssl)
 {
   if(connssl->ssl) {
-    ssl_free (connssl->ssl);
+    ssl_free(connssl->ssl);
     connssl->ssl = NULL;
   }
   if(connssl->ssl_ctx) {
@@ -158,7 +158,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
 
   /* axTLS only supports TLSv1 */
   /* check to see if we've been told to use an explicit SSL/TLS version */
-  switch(data->set.ssl.version) {
+  switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
     break;
@@ -183,17 +183,17 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
   conn->ssl[sockindex].ssl = NULL;
 
   /* Load the trusted CA cert bundle file */
-  if(data->set.ssl.CAfile) {
-    if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
-       != SSL_OK) {
+  if(SSL_CONN_CONFIG(CAfile)) {
+    if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT,
+                    SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) {
       infof(data, "error reading ca cert file %s \n",
-            data->set.ssl.CAfile);
-      if(data->set.ssl.verifypeer) {
+            SSL_CONN_CONFIG(CAfile));
+      if(SSL_CONN_CONFIG(verifypeer)) {
         return CURLE_SSL_CACERT_BADFILE;
       }
     }
     else
-      infof(data, "found certificates in %s\n", data->set.ssl.CAfile);
+      infof(data, "found certificates in %s\n", SSL_CONN_CONFIG(CAfile));
   }
 
   /* gtls.c tasks we're skipping for now:
@@ -205,15 +205,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
    */
 
   /* Load client certificate */
-  if(data->set.str[STRING_CERT]) {
+  if(SSL_SET_OPTION(cert)) {
     i=0;
     /* Instead of trying to analyze cert type here, let axTLS try them all. */
     while(cert_types[i] != 0) {
       ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
-                                    data->set.str[STRING_CERT], NULL);
+                                    SSL_SET_OPTION(cert), NULL);
       if(ssl_fcn_return == SSL_OK) {
         infof(data, "successfully read cert file %s \n",
-              data->set.str[STRING_CERT]);
+              SSL_SET_OPTION(cert));
         break;
       }
       i++;
@@ -221,7 +221,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
     /* Tried all cert types, none worked. */
     if(cert_types[i] == 0) {
       failf(data, "%s is not x509 or pkcs12 format",
-            data->set.str[STRING_CERT]);
+            SSL_SET_OPTION(cert));
       return CURLE_SSL_CERTPROBLEM;
     }
   }
@@ -229,15 +229,15 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
   /* Load client key.
      If a pkcs12 file successfully loaded a cert, then there's nothing to do
      because the key has already been loaded. */
-  if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) {
+  if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) {
     i=0;
     /* Instead of trying to analyze key type here, let axTLS try them all. */
     while(key_types[i] != 0) {
       ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
-                                    data->set.str[STRING_KEY], NULL);
+                                    SSL_SET_OPTION(key), NULL);
       if(ssl_fcn_return == SSL_OK) {
         infof(data, "successfully read key file %s \n",
-              data->set.str[STRING_KEY]);
+              SSL_SET_OPTION(key));
         break;
       }
       i++;
@@ -245,7 +245,7 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
     /* Tried all key types, none worked. */
     if(key_types[i] == 0) {
       failf(data, "Failure: %s is not a supported key file",
-            data->set.str[STRING_KEY]);
+            SSL_SET_OPTION(key));
       return CURLE_SSL_CONNECT_ERROR;
     }
   }
@@ -256,15 +256,16 @@ static CURLcode connect_prep(struct connectdata *conn, int sockindex)
    * 2) setting up callbacks.  these seem gnutls specific
    */
 
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     const uint8_t *ssl_sessionid;
     size_t ssl_idsize;
 
     /* In axTLS, handshaking happens inside ssl_client_new. */
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) {
+    if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize,
+                              sockindex)) {
       /* we got a session id, use it! */
-      infof (data, "SSL re-using session ID\n");
+      infof(data, "SSL re-using session ID\n");
       ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
                            ssl_sessionid, (uint8_t)ssl_idsize);
     }
@@ -291,13 +292,17 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
   const char *dns_altname;
   int8_t found_subject_alt_names = 0;
   int8_t found_subject_alt_name_matching_conn = 0;
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const char * const dispname = SSL_IS_PROXY() ?
+    conn->http_proxy.host.dispname : conn->host.dispname;
 
   /* Here, gtls.c gets the peer certificates and fails out depending on
    * settings in "data."  axTLS api doesn't have get cert chain fcn, so omit?
    */
 
   /* Verify server's certificate */
-  if(data->set.ssl.verifypeer) {
+  if(SSL_CONN_CONFIG(verifypeer)) {
     if(ssl_verify_cert(ssl) != SSL_OK) {
       Curl_axtls_close(conn, sockindex);
       failf(data, "server cert verify failed");
@@ -328,8 +333,8 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
     found_subject_alt_names = 1;
 
     infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
-          dns_altname, conn->host.name);
-    if(Curl_cert_hostcheck(dns_altname, conn->host.name)) {
+          dns_altname, hostname);
+    if(Curl_cert_hostcheck(dns_altname, hostname)) {
       found_subject_alt_name_matching_conn = 1;
       break;
     }
@@ -337,23 +342,21 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
 
   /* RFC2818 checks */
   if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
-    if(data->set.ssl.verifyhost) {
+    if(SSL_CONN_CONFIG(verifyhost)) {
       /* Break connection ! */
       Curl_axtls_close(conn, sockindex);
-      failf(data, "\tsubjectAltName(s) do not match %s\n",
-            conn->host.dispname);
+      failf(data, "\tsubjectAltName(s) do not match %s\n", dispname);
       return CURLE_PEER_FAILED_VERIFICATION;
     }
     else
-      infof(data, "\tsubjectAltName(s) do not match %s\n",
-            conn->host.dispname);
+      infof(data, "\tsubjectAltName(s) do not match %s\n", dispname);
   }
   else if(found_subject_alt_names == 0) {
     /* Per RFC2818, when no Subject Alt Names were available, examine the peer
        CN as a legacy fallback */
     peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
     if(peer_CN == NULL) {
-      if(data->set.ssl.verifyhost) {
+      if(SSL_CONN_CONFIG(verifyhost)) {
         Curl_axtls_close(conn, sockindex);
         failf(data, "unable to obtain common name from peer certificate");
         return CURLE_PEER_FAILED_VERIFICATION;
@@ -362,17 +365,17 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
         infof(data, "unable to obtain common name from peer certificate");
     }
     else {
-      if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
-        if(data->set.ssl.verifyhost) {
+      if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
+        if(SSL_CONN_CONFIG(verifyhost)) {
           /* Break connection ! */
           Curl_axtls_close(conn, sockindex);
           failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
-                peer_CN, conn->host.dispname);
+                peer_CN, dispname);
           return CURLE_PEER_FAILED_VERIFICATION;
         }
         else
           infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
-                peer_CN, conn->host.dispname);
+                peer_CN, dispname);
       }
     }
   }
@@ -383,13 +386,13 @@ static CURLcode connect_finish(struct connectdata *conn, int sockindex)
   conn->send[sockindex] = axtls_send;
 
   /* Put our freshly minted SSL session in cache */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     const uint8_t *ssl_sessionid = ssl_get_session_id_size(ssl);
     size_t ssl_idsize = ssl_get_session_id(ssl);
     Curl_ssl_sessionid_lock(conn);
-    if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize)
-       != CURLE_OK)
-      infof (data, "failed to add session to cache\n");
+    if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize,
+                             sockindex) != CURLE_OK)
+      infof(data, "failed to add session to cache\n");
     Curl_ssl_sessionid_unlock(conn);
   }
 
@@ -437,7 +440,7 @@ CURLcode Curl_axtls_connect_nonblocking(
         return CURLE_OK;
       }
     }
-    infof (conn->data, "handshake completed successfully\n");
+    infof(conn->data, "handshake completed successfully\n");
     conn->ssl[sockindex].connecting_state = ssl_connect_3;
   }
 
@@ -503,7 +506,7 @@ Curl_axtls_connect(struct connectdata *conn,
     /* TODO: avoid polling */
     Curl_wait_ms(10);
   }
-  infof (conn->data, "handshake completed successfully\n");
+  infof(conn->data, "handshake completed successfully\n");
 
   conn_step = connect_finish(conn, sockindex);
   if(conn_step != CURLE_OK) {
diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c
index 5d6dbfb..fc4dde4 100644
--- a/lib/vtls/cyassl.c
+++ b/lib/vtls/cyassl.c
@@ -149,7 +149,7 @@ cyassl_connect_step1(struct connectdata *conn,
     return CURLE_OK;
 
   /* check to see if we've been told to use an explicit SSL/TLS version */
-  switch(data->set.ssl.version) {
+  switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
 #if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
@@ -174,12 +174,15 @@ cyassl_connect_step1(struct connectdata *conn,
     req_method = TLSv1_2_client_method();
     use_sni(TRUE);
     break;
+  case CURL_SSLVERSION_TLSv1_3:
+    failf(data, "CyaSSL: TLS 1.3 is not yet supported");
+    return CURLE_SSL_CONNECT_ERROR;
   case CURL_SSLVERSION_SSLv3:
 #ifdef WOLFSSL_ALLOW_SSLV3
     req_method = SSLv3_client_method();
     use_sni(FALSE);
 #else
-    failf(data, "No support for SSLv3");
+    failf(data, "CyaSSL does not support SSLv3");
     return CURLE_NOT_BUILT_IN;
 #endif
     break;
@@ -205,7 +208,7 @@ cyassl_connect_step1(struct connectdata *conn,
     return CURLE_OUT_OF_MEMORY;
   }
 
-  switch(data->set.ssl.version) {
+  switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
 #if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
@@ -228,18 +231,18 @@ cyassl_connect_step1(struct connectdata *conn,
 
 #ifndef NO_FILESYSTEM
   /* load trusted cacert */
-  if(data->set.str[STRING_SSL_CAFILE]) {
+  if(SSL_CONN_CONFIG(CAfile)) {
     if(1 != SSL_CTX_load_verify_locations(conssl->ctx,
-                                          data->set.str[STRING_SSL_CAFILE],
-                                          data->set.str[STRING_SSL_CAPATH])) {
-      if(data->set.ssl.verifypeer) {
+                                      SSL_CONN_CONFIG(CAfile),
+                                      SSL_CONN_CONFIG(CApath))) {
+      if(SSL_CONN_CONFIG(verifypeer)) {
         /* Fail if we insist on successfully verifying the server. */
         failf(data, "error setting certificate verify locations:\n"
               "  CAfile: %s\n  CApath: %s",
-              data->set.str[STRING_SSL_CAFILE]?
-              data->set.str[STRING_SSL_CAFILE]: "none",
-              data->set.str[STRING_SSL_CAPATH]?
-              data->set.str[STRING_SSL_CAPATH] : "none");
+              SSL_CONN_CONFIG(CAfile)?
+              SSL_CONN_CONFIG(CAfile): "none",
+              SSL_CONN_CONFIG(CApath)?
+              SSL_CONN_CONFIG(CApath) : "none");
         return CURLE_SSL_CACERT_BADFILE;
       }
       else {
@@ -256,25 +259,25 @@ cyassl_connect_step1(struct connectdata *conn,
     infof(data,
           "  CAfile: %s\n"
           "  CApath: %s\n",
-          data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
+          SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
           "none",
-          data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
+          SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath):
           "none");
   }
 
   /* Load the client certificate, and private key */
-  if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) {
-    int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]);
+  if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
+    int file_type = do_file_type(SSL_SET_OPTION(cert_type));
 
-    if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT],
+    if(SSL_CTX_use_certificate_file(conssl->ctx, SSL_SET_OPTION(cert),
                                      file_type) != 1) {
       failf(data, "unable to use client certificate (no key or wrong pass"
             " phrase?)");
       return CURLE_SSL_CONNECT_ERROR;
     }
 
-    file_type = do_file_type(data->set.str[STRING_KEY_TYPE]);
-    if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY],
+    file_type = do_file_type(SSL_SET_OPTION(key_type));
+    if(SSL_CTX_use_PrivateKey_file(conssl->ctx, SSL_SET_OPTION(key),
                                     file_type) != 1) {
       failf(data, "unable to set private key");
       return CURLE_SSL_CONNECT_ERROR;
@@ -287,7 +290,8 @@ cyassl_connect_step1(struct connectdata *conn,
    * anyway. In the latter case the result of the verification is checked with
    * SSL_get_verify_result() below. */
   SSL_CTX_set_verify(conssl->ctx,
-                     data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
+                     SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER:
+                                                 SSL_VERIFY_NONE,
                      NULL);
 
 #ifdef HAVE_SNI
@@ -296,13 +300,15 @@ cyassl_connect_step1(struct connectdata *conn,
 #ifdef ENABLE_IPV6
     struct in6_addr addr6;
 #endif
-    size_t hostname_len = strlen(conn->host.name);
+    const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+      conn->host.name;
+    size_t hostname_len = strlen(hostname);
     if((hostname_len < USHRT_MAX) &&
-       (0 == Curl_inet_pton(AF_INET, conn->host.name, &addr4)) &&
+       (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) &&
 #ifdef ENABLE_IPV6
-       (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr6)) &&
+       (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
 #endif
-       (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, conn->host.name,
+       (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, hostname,
                           (unsigned short)hostname_len) != 1)) {
       infof(data, "WARNING: failed to configure server name indication (SNI) "
             "TLS extension\n");
@@ -331,7 +337,7 @@ cyassl_connect_step1(struct connectdata *conn,
     }
   }
 #ifdef NO_FILESYSTEM
-  else if(data->set.ssl.verifypeer) {
+  else if(SSL_CONN_CONFIG(verifypeer)) {
     failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built"
           " with \"no filesystem\". Either disable peer verification"
           " (insecure) or if you are building an application with libcurl you"
@@ -377,11 +383,11 @@ cyassl_connect_step1(struct connectdata *conn,
 #endif /* HAVE_ALPN */
 
   /* Check if there's a cached ID we can/should use here! */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     void *ssl_sessionid = NULL;
 
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
+    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
       /* we got a session id, use it! */
       if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
         Curl_ssl_sessionid_unlock(conn);
@@ -391,7 +397,7 @@ cyassl_connect_step1(struct connectdata *conn,
         return CURLE_SSL_CONNECT_ERROR;
       }
       /* Informational message */
-      infof (data, "SSL re-using session ID\n");
+      infof(data, "SSL re-using session ID\n");
     }
     Curl_ssl_sessionid_unlock(conn);
   }
@@ -414,13 +420,20 @@ cyassl_connect_step2(struct connectdata *conn,
   int ret = -1;
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data* conssl = &conn->ssl[sockindex];
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const char * const dispname = SSL_IS_PROXY() ?
+    conn->http_proxy.host.dispname : conn->host.dispname;
+  const char * const pinnedpubkey = SSL_IS_PROXY() ?
+                        data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+                        data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
 
   conn->recv[sockindex] = cyassl_recv;
   conn->send[sockindex] = cyassl_send;
 
   /* Enable RFC2818 checks */
-  if(data->set.ssl.verifyhost) {
-    ret = CyaSSL_check_domain_name(conssl->handle, conn->host.name);
+  if(SSL_CONN_CONFIG(verifyhost)) {
+    ret = CyaSSL_check_domain_name(conssl->handle, hostname);
     if(ret == SSL_FAILURE)
       return CURLE_OUT_OF_MEMORY;
   }
@@ -444,31 +457,31 @@ cyassl_connect_step2(struct connectdata *conn,
     else if(DOMAIN_NAME_MISMATCH == detail) {
 #if 1
       failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n",
-            conn->host.dispname);
+            dispname);
       return CURLE_PEER_FAILED_VERIFICATION;
 #else
       /* When the CyaSSL_check_domain_name() is used and you desire to continue
-       * on a DOMAIN_NAME_MISMATCH, i.e. 'data->set.ssl.verifyhost == 0',
+       * on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost == 0',
        * CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA error. The only
        * way to do this is currently to switch the CyaSSL_check_domain_name()
-       * in and out based on the 'data->set.ssl.verifyhost' value. */
-      if(data->set.ssl.verifyhost) {
+       * in and out based on the 'conn->ssl_config.verifyhost' value. */
+      if(SSL_CONN_CONFIG(verifyhost)) {
         failf(data,
               "\tsubject alt name(s) or common name do not match \"%s\"\n",
-              conn->host.dispname);
+              dispname);
         return CURLE_PEER_FAILED_VERIFICATION;
       }
       else {
         infof(data,
               "\tsubject alt name(s) and/or common name do not match \"%s\"\n",
-              conn->host.dispname);
+              dispname);
         return CURLE_OK;
       }
 #endif
     }
 #if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
     else if(ASN_NO_SIGNER_E == detail) {
-      if(data->set.ssl.verifypeer) {
+      if(SSL_CONN_CONFIG(verifypeer)) {
         failf(data, "\tCA signer not available for verification\n");
         return CURLE_SSL_CACERT_BADFILE;
       }
@@ -487,7 +500,7 @@ cyassl_connect_step2(struct connectdata *conn,
     }
   }
 
-  if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+  if(pinnedpubkey) {
 #ifdef KEEP_PEER_CERT
     X509 *x509;
     const char *x509_der;
@@ -509,7 +522,8 @@ cyassl_connect_step2(struct connectdata *conn,
     }
 
     memset(&x509_parsed, 0, sizeof x509_parsed);
-    Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len);
+    if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
+      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
 
     pubkey = &x509_parsed.subjectPublicKeyInfo;
     if(!pubkey->header || pubkey->end <= pubkey->header) {
@@ -518,7 +532,7 @@ cyassl_connect_step2(struct connectdata *conn,
     }
 
     result = Curl_pin_peer_pubkey(data,
-                                  data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+                                  pinnedpubkey,
                                   (const unsigned char *)pubkey->header,
                                   (size_t)(pubkey->end - pubkey->header));
     if(result) {
@@ -583,7 +597,7 @@ cyassl_connect_step3(struct connectdata *conn,
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     bool incache;
     SSL_SESSION *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
@@ -591,7 +605,8 @@ cyassl_connect_step3(struct connectdata *conn,
     our_ssl_sessionid = SSL_get_session(connssl->handle);
 
     Curl_ssl_sessionid_lock(conn);
-    incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
+    incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
+                                      sockindex));
     if(incache) {
       if(old_ssl_sessionid != our_ssl_sessionid) {
         infof(data, "old SSL session ID is stale, removing\n");
@@ -602,7 +617,7 @@ cyassl_connect_step3(struct connectdata *conn,
 
     if(!incache) {
       result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
-                                     0 /* unknown size */);
+                                     0 /* unknown size */, sockindex);
       if(result) {
         Curl_ssl_sessionid_unlock(conn);
         failf(data, "failed to store ssl session");
@@ -654,11 +669,11 @@ void Curl_cyassl_close(struct connectdata *conn, int sockindex)
 
   if(conssl->handle) {
     (void)SSL_shutdown(conssl->handle);
-    SSL_free (conssl->handle);
+    SSL_free(conssl->handle);
     conssl->handle = NULL;
   }
   if(conssl->ctx) {
-    SSL_CTX_free (conssl->ctx);
+    SSL_CTX_free(conssl->ctx);
     conssl->ctx = NULL;
   }
 }
@@ -740,7 +755,7 @@ int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
   if(connssl->handle) {
-    SSL_free (connssl->handle);
+    SSL_free(connssl->handle);
     connssl->handle = NULL;
   }
   return retval;
diff --git a/lib/vtls/darwinssl.c b/lib/vtls/darwinssl.c
index 66e74f1..a43e391 100644
--- a/lib/vtls/darwinssl.c
+++ b/lib/vtls/darwinssl.c
@@ -197,7 +197,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
 
   do {
     length = write(sock,
-                   (char*)dataPtr + bytesSent,
+                   (char *)dataPtr + bytesSent,
                    dataLen - bytesSent);
   } while((length > 0) &&
            ( (bytesSent += length) < dataLen) );
@@ -219,8 +219,9 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
   return ortn;
 }
 
-CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) {
-  switch (cipher) {
+CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher)
+{
+  switch(cipher) {
     /* SSL version 3.0 */
     case SSL_RSA_WITH_NULL_MD5:
       return "SSL_RSA_WITH_NULL_MD5";
@@ -364,7 +365,8 @@ CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) {
   return "SSL_NULL_WITH_NULL_NULL";
 }
 
-CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
+CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher)
+{
   switch(cipher) {
     /* TLS 1.0 with AES (RFC 3268) */
     case TLS_RSA_WITH_AES_128_CBC_SHA:
@@ -883,14 +885,18 @@ static OSStatus CopyIdentityWithLabel(char *label,
                                       SecIdentityRef *out_cert_and_key)
 {
   OSStatus status = errSecItemNotFound;
+  CFArrayRef keys_list;
+  CFIndex keys_list_count;
+  CFIndex i;
+  CFStringRef common_name;
 
 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
   /* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
      kSecClassIdentity was introduced in Lion. If both exist, let's use them
      to find the certificate. */
   if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) {
-    CFTypeRef keys[4];
-    CFTypeRef values[4];
+    CFTypeRef keys[5];
+    CFTypeRef values[5];
     CFDictionaryRef query_dict;
     CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
       kCFStringEncodingUTF8);
@@ -900,21 +906,53 @@ static OSStatus CopyIdentityWithLabel(char *label,
     keys[0] = kSecClass;
     values[1] = kCFBooleanTrue;    /* we want a reference */
     keys[1] = kSecReturnRef;
-    values[2] = kSecMatchLimitOne; /* one is enough, thanks */
+    values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the
+                                    * label matching below worked correctly */
     keys[2] = kSecMatchLimit;
     /* identity searches need a SecPolicyRef in order to work */
-    values[3] = SecPolicyCreateSSL(false, label_cf);
+    values[3] = SecPolicyCreateSSL(false, NULL);
     keys[3] = kSecMatchPolicy;
+    /* match the name of the certificate (doesn't work in macOS 10.12.1) */
+    values[4] = label_cf;
+    keys[4] = kSecAttrLabel;
     query_dict = CFDictionaryCreate(NULL, (const void **)keys,
-                                   (const void **)values, 4L,
-                                   &kCFCopyStringDictionaryKeyCallBacks,
-                                   &kCFTypeDictionaryValueCallBacks);
+                                    (const void **)values, 5L,
+                                    &kCFCopyStringDictionaryKeyCallBacks,
+                                    &kCFTypeDictionaryValueCallBacks);
     CFRelease(values[3]);
-    CFRelease(label_cf);
 
     /* Do we have a match? */
-    status = SecItemCopyMatching(query_dict, (CFTypeRef *)out_cert_and_key);
+    status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list);
+
+    /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity,
+     * we need to find the correct identity ourselves */
+    if(status == noErr) {
+      keys_list_count = CFArrayGetCount(keys_list);
+      *out_cert_and_key = NULL;
+      for(i=0; i<keys_list_count; i++) {
+        OSStatus err = noErr;
+        SecCertificateRef cert = NULL;
+        *out_cert_and_key =
+          (SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i);
+        err = SecIdentityCopyCertificate(*out_cert_and_key, &cert);
+        if(err == noErr) {
+          SecCertificateCopyCommonName(cert, &common_name);
+          if(CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
+            CFRelease(cert);
+            CFRelease(common_name);
+            status = noErr;
+            break;
+          }
+          CFRelease(common_name);
+        }
+        *out_cert_and_key = NULL;
+        status = 1;
+        CFRelease(cert);
+      }
+    }
+
     CFRelease(query_dict);
+    CFRelease(label_cf);
   }
   else {
 #if CURL_SUPPORT_MAC_10_6
@@ -1002,6 +1040,12 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   curl_socket_t sockfd = conn->sock[sockindex];
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+  const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+  char * const ssl_cert = SSL_SET_OPTION(cert);
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
 #ifdef ENABLE_IPV6
   struct in6_addr addr;
 #else
@@ -1052,40 +1096,46 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
   /* check to see if we've been told to use an explicit SSL/TLS version */
 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
   if(SSLSetProtocolVersionMax != NULL) {
-    switch(data->set.ssl.version) {
-      default:
-      case CURL_SSLVERSION_DEFAULT:
-      case CURL_SSLVERSION_TLSv1:
-        (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
-        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
-        break;
-      case CURL_SSLVERSION_TLSv1_0:
-        (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
-        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1);
-        break;
-      case CURL_SSLVERSION_TLSv1_1:
-        (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11);
-        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11);
-        break;
-      case CURL_SSLVERSION_TLSv1_2:
-        (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12);
-        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
-        break;
-      case CURL_SSLVERSION_SSLv3:
-        err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
-        if(err != noErr) {
-          failf(data, "Your version of the OS does not support SSLv3");
-          return CURLE_SSL_CONNECT_ERROR;
-        }
-        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
-        break;
-      case CURL_SSLVERSION_SSLv2:
-        err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
-        if(err != noErr) {
-          failf(data, "Your version of the OS does not support SSLv2");
-          return CURLE_SSL_CONNECT_ERROR;
-        }
-        (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2);
+    switch(conn->ssl_config.version) {
+    case CURL_SSLVERSION_DEFAULT:
+    case CURL_SSLVERSION_TLSv1:
+      (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
+      (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+      break;
+    case CURL_SSLVERSION_TLSv1_0:
+      (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
+      (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1);
+      break;
+    case CURL_SSLVERSION_TLSv1_1:
+      (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11);
+      (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11);
+      break;
+    case CURL_SSLVERSION_TLSv1_2:
+      (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12);
+      (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+      break;
+    case CURL_SSLVERSION_TLSv1_3:
+      failf(data, "DarwinSSL: TLS 1.3 is not yet supported");
+      return CURLE_SSL_CONNECT_ERROR;
+    case CURL_SSLVERSION_SSLv3:
+      err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
+      if(err != noErr) {
+        failf(data, "Your version of the OS does not support SSLv3");
+        return CURLE_SSL_CONNECT_ERROR;
+      }
+      (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
+      break;
+    case CURL_SSLVERSION_SSLv2:
+      err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
+      if(err != noErr) {
+        failf(data, "Your version of the OS does not support SSLv2");
+        return CURLE_SSL_CONNECT_ERROR;
+      }
+      (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2);
+      break;
+    default:
+      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+      return CURLE_SSL_CONNECT_ERROR;
     }
   }
   else {
@@ -1093,121 +1143,131 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
     (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                        kSSLProtocolAll,
                                        false);
-    switch (data->set.ssl.version) {
-      default:
-      case CURL_SSLVERSION_DEFAULT:
-      case CURL_SSLVERSION_TLSv1:
-        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kTLSProtocol1,
-                                           true);
-        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kTLSProtocol11,
-                                           true);
-        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kTLSProtocol12,
-                                           true);
-        break;
-      case CURL_SSLVERSION_TLSv1_0:
-        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kTLSProtocol1,
-                                           true);
-        break;
-      case CURL_SSLVERSION_TLSv1_1:
-        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kTLSProtocol11,
-                                           true);
-        break;
-      case CURL_SSLVERSION_TLSv1_2:
-        (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kTLSProtocol12,
-                                           true);
-        break;
-      case CURL_SSLVERSION_SSLv3:
-        err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kSSLProtocol3,
-                                           true);
-        if(err != noErr) {
-          failf(data, "Your version of the OS does not support SSLv3");
-          return CURLE_SSL_CONNECT_ERROR;
-        }
-        break;
-      case CURL_SSLVERSION_SSLv2:
-        err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                           kSSLProtocol2,
-                                           true);
-        if(err != noErr) {
-          failf(data, "Your version of the OS does not support SSLv2");
-          return CURLE_SSL_CONNECT_ERROR;
-        }
-        break;
-    }
-#endif  /* CURL_SUPPORT_MAC_10_8 */
-  }
-#else
-  (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
-  switch(data->set.ssl.version) {
-    default:
+    switch(conn->ssl_config.version) {
     case CURL_SSLVERSION_DEFAULT:
     case CURL_SSLVERSION_TLSv1:
+      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                         kTLSProtocol1,
+                                         true);
+      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                         kTLSProtocol11,
+                                         true);
+      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                         kTLSProtocol12,
+                                         true);
+      break;
     case CURL_SSLVERSION_TLSv1_0:
       (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
                                          kTLSProtocol1,
                                          true);
       break;
     case CURL_SSLVERSION_TLSv1_1:
-      failf(data, "Your version of the OS does not support TLSv1.1");
-      return CURLE_SSL_CONNECT_ERROR;
+      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                         kTLSProtocol11,
+                                         true);
+      break;
     case CURL_SSLVERSION_TLSv1_2:
-      failf(data, "Your version of the OS does not support TLSv1.2");
+      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                         kTLSProtocol12,
+                                         true);
+      break;
+    case CURL_SSLVERSION_TLSv1_3:
+      failf(data, "DarwinSSL: TLS 1.3 is not yet supported");
       return CURLE_SSL_CONNECT_ERROR;
-    case CURL_SSLVERSION_SSLv2:
+    case CURL_SSLVERSION_SSLv3:
       err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                         kSSLProtocol2,
+                                         kSSLProtocol3,
                                          true);
       if(err != noErr) {
-        failf(data, "Your version of the OS does not support SSLv2");
+        failf(data, "Your version of the OS does not support SSLv3");
         return CURLE_SSL_CONNECT_ERROR;
       }
       break;
-    case CURL_SSLVERSION_SSLv3:
+    case CURL_SSLVERSION_SSLv2:
       err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
-                                         kSSLProtocol3,
+                                         kSSLProtocol2,
                                          true);
       if(err != noErr) {
-        failf(data, "Your version of the OS does not support SSLv3");
+        failf(data, "Your version of the OS does not support SSLv2");
         return CURLE_SSL_CONNECT_ERROR;
       }
       break;
+    default:
+      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+#endif  /* CURL_SUPPORT_MAC_10_8 */
+  }
+#else
+  (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
+  switch(conn->ssl_config.version) {
+  case CURL_SSLVERSION_DEFAULT:
+  case CURL_SSLVERSION_TLSv1:
+  case CURL_SSLVERSION_TLSv1_0:
+    (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                       kTLSProtocol1,
+                                       true);
+    break;
+  case CURL_SSLVERSION_TLSv1_1:
+    failf(data, "Your version of the OS does not support TLSv1.1");
+    return CURLE_SSL_CONNECT_ERROR;
+  case CURL_SSLVERSION_TLSv1_2:
+    failf(data, "Your version of the OS does not support TLSv1.2");
+    return CURLE_SSL_CONNECT_ERROR;
+  case CURL_SSLVERSION_TLSv1_3:
+    failf(data, "Your version of the OS does not support TLSv1.3");
+    return CURLE_SSL_CONNECT_ERROR;
+  case CURL_SSLVERSION_SSLv2:
+    err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                       kSSLProtocol2,
+                                       true);
+    if(err != noErr) {
+      failf(data, "Your version of the OS does not support SSLv2");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+    break;
+  case CURL_SSLVERSION_SSLv3:
+    err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+                                       kSSLProtocol3,
+                                       true);
+    if(err != noErr) {
+      failf(data, "Your version of the OS does not support SSLv3");
+      return CURLE_SSL_CONNECT_ERROR;
+    }
+    break;
+  default:
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+    return CURLE_SSL_CONNECT_ERROR;
   }
 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
 
-  if(data->set.str[STRING_KEY]) {
+  if(SSL_SET_OPTION(key)) {
     infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
-                "Transport. The private key must be in the Keychain.\n");
+          "Transport. The private key must be in the Keychain.\n");
   }
 
-  if(data->set.str[STRING_CERT]) {
+  if(ssl_cert) {
     SecIdentityRef cert_and_key = NULL;
-    bool is_cert_file = is_file(data->set.str[STRING_CERT]);
+    bool is_cert_file = is_file(ssl_cert);
 
     /* User wants to authenticate with a client cert. Look for it:
        If we detect that this is a file on disk, then let's load it.
        Otherwise, assume that the user wants to use an identity loaded
        from the Keychain. */
     if(is_cert_file) {
-      if(!data->set.str[STRING_CERT_TYPE])
+      if(!SSL_SET_OPTION(cert_type))
         infof(data, "WARNING: SSL: Certificate type not set, assuming "
                     "PKCS#12 format.\n");
-      else if(strncmp(data->set.str[STRING_CERT_TYPE], "P12",
-        strlen(data->set.str[STRING_CERT_TYPE])) != 0)
+      else if(strncmp(SSL_SET_OPTION(cert_type), "P12",
+        strlen(SSL_SET_OPTION(cert_type))) != 0)
         infof(data, "WARNING: SSL: The Security framework only supports "
                     "loading identities that are in PKCS#12 format.\n");
 
-      err = CopyIdentityFromPKCS12File(data->set.str[STRING_CERT],
-        data->set.str[STRING_KEY_PASSWD], &cert_and_key);
+      err = CopyIdentityFromPKCS12File(ssl_cert,
+        SSL_SET_OPTION(key_passwd), &cert_and_key);
     }
     else
-      err = CopyIdentityWithLabel(data->set.str[STRING_CERT], &cert_and_key);
+      err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
 
     if(err == noErr) {
       SecCertificateRef cert = NULL;
@@ -1246,27 +1306,27 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
     }
     else {
       switch(err) {
-        case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
-          failf(data, "SSL: Incorrect password for the certificate \"%s\" "
-                      "and its private key.", data->set.str[STRING_CERT]);
-          break;
-        case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
-          failf(data, "SSL: Couldn't make sense of the data in the "
-                      "certificate \"%s\" and its private key.",
-                      data->set.str[STRING_CERT]);
-          break;
-        case -25260: /* errSecPassphraseRequired */
-          failf(data, "SSL The certificate \"%s\" requires a password.",
-                      data->set.str[STRING_CERT]);
-          break;
-        case errSecItemNotFound:
-          failf(data, "SSL: Can't find the certificate \"%s\" and its private "
-                      "key in the Keychain.", data->set.str[STRING_CERT]);
-          break;
-        default:
-          failf(data, "SSL: Can't load the certificate \"%s\" and its private "
-                      "key: OSStatus %d", data->set.str[STRING_CERT], err);
-          break;
+      case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
+        failf(data, "SSL: Incorrect password for the certificate \"%s\" "
+                    "and its private key.", ssl_cert);
+        break;
+      case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
+        failf(data, "SSL: Couldn't make sense of the data in the "
+                    "certificate \"%s\" and its private key.",
+                    ssl_cert);
+        break;
+      case -25260: /* errSecPassphraseRequired */
+        failf(data, "SSL The certificate \"%s\" requires a password.",
+                    ssl_cert);
+        break;
+      case errSecItemNotFound:
+        failf(data, "SSL: Can't find the certificate \"%s\" and its private "
+                    "key in the Keychain.", ssl_cert);
+        break;
+      default:
+        failf(data, "SSL: Can't load the certificate \"%s\" and its private "
+                    "key: OSStatus %d", ssl_cert, err);
+        break;
       }
       return CURLE_SSL_CERTPROBLEM;
     }
@@ -1297,8 +1357,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
 #else
   if(SSLSetSessionOption != NULL) {
 #endif /* CURL_BUILD_MAC */
-    bool break_on_auth = !data->set.ssl.verifypeer ||
-      data->set.str[STRING_SSL_CAFILE];
+    bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile;
     err = SSLSetSessionOption(connssl->ssl_ctx,
                               kSSLSessionOptionBreakOnServerAuth,
                               break_on_auth);
@@ -1310,7 +1369,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
   else {
 #if CURL_SUPPORT_MAC_10_8
     err = SSLSetEnableCertVerify(connssl->ssl_ctx,
-                                 data->set.ssl.verifypeer?true:false);
+                                 conn->ssl_config.verifypeer?true:false);
     if(err != noErr) {
       failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
       return CURLE_SSL_CONNECT_ERROR;
@@ -1319,22 +1378,21 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
   }
 #else
   err = SSLSetEnableCertVerify(connssl->ssl_ctx,
-                               data->set.ssl.verifypeer?true:false);
+                               conn->ssl_config.verifypeer?true:false);
   if(err != noErr) {
     failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
     return CURLE_SSL_CONNECT_ERROR;
   }
 #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
 
-  if(data->set.str[STRING_SSL_CAFILE]) {
-    bool is_cert_file = is_file(data->set.str[STRING_SSL_CAFILE]);
+  if(ssl_cafile) {
+    bool is_cert_file = is_file(ssl_cafile);
 
     if(!is_cert_file) {
-      failf(data, "SSL: can't load CA certificate file %s",
-            data->set.str[STRING_SSL_CAFILE]);
+      failf(data, "SSL: can't load CA certificate file %s", ssl_cafile);
       return CURLE_SSL_CACERT_BADFILE;
     }
-    if(!data->set.ssl.verifypeer) {
+    if(!verifypeer) {
       failf(data, "SSL: CA certificate set, but certificate verification "
             "is disabled");
       return CURLE_SSL_CONNECT_ERROR;
@@ -1344,22 +1402,22 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
   /* Configure hostname check. SNI is used if available.
    * Both hostname check and SNI require SSLSetPeerDomainName().
    * Also: the verifyhost setting influences SNI usage */
-  if(data->set.ssl.verifyhost) {
-    err = SSLSetPeerDomainName(connssl->ssl_ctx, conn->host.name,
-    strlen(conn->host.name));
+  if(conn->ssl_config.verifyhost) {
+    err = SSLSetPeerDomainName(connssl->ssl_ctx, hostname,
+    strlen(hostname));
 
     if(err != noErr) {
       infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n",
             err);
     }
 
-    if((Curl_inet_pton(AF_INET, conn->host.name, &addr))
+    if((Curl_inet_pton(AF_INET, hostname, &addr))
   #ifdef ENABLE_IPV6
-    || (Curl_inet_pton(AF_INET6, conn->host.name, &addr))
+    || (Curl_inet_pton(AF_INET6, hostname, &addr))
   #endif
        ) {
-         infof(data, "WARNING: using IP address, SNI is being disabled by "
-         "the OS.\n");
+      infof(data, "WARNING: using IP address, SNI is being disabled by "
+            "the OS.\n");
     }
   }
 
@@ -1382,7 +1440,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
         running in an affected version of OS X. */
       if(darwinver_maj == 12 && darwinver_min <= 3 &&
          all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
-           continue;
+        continue;
       }
 #endif /* CURL_BUILD_MAC */
       switch(all_ciphers[i]) {
@@ -1474,21 +1532,22 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
   /* We want to enable 1/n-1 when using a CBC cipher unless the user
      specifically doesn't want us doing that: */
   if(SSLSetSessionOption != NULL) {
+    /* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */
     SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
-                      !data->set.ssl_enable_beast);
+                      !data->set.ssl.enable_beast);
     SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart,
                       data->set.ssl.falsestart); /* false start support */
   }
 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
 
   /* Check if there's a cached ID we can/should use here! */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     char *ssl_sessionid;
     size_t ssl_sessionid_len;
 
     Curl_ssl_sessionid_lock(conn);
     if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
-                              &ssl_sessionid_len)) {
+                              &ssl_sessionid_len, sockindex)) {
       /* we got a session id, use it! */
       err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
       Curl_ssl_sessionid_unlock(conn);
@@ -1504,9 +1563,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
     else {
       CURLcode result;
       ssl_sessionid =
-        aprintf("%s:%d:%d:%s:%hu", data->set.str[STRING_SSL_CAFILE],
-                data->set.ssl.verifypeer, data->set.ssl.verifyhost,
-                conn->host.name, conn->remote_port);
+        aprintf("%s:%d:%d:%s:%hu", ssl_cafile,
+                verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
       ssl_sessionid_len = strlen(ssl_sessionid);
 
       err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
@@ -1516,7 +1574,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
         return CURLE_SSL_CONNECT_ERROR;
       }
 
-      result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len);
+      result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len,
+                                     sockindex);
       Curl_ssl_sessionid_unlock(conn);
       if(result) {
         failf(data, "failed to store ssl session");
@@ -1820,7 +1879,7 @@ static int verify_cert(const char *cafile, struct Curl_easy *data,
     return sslerr_to_curlerr(data, ret);
   }
 
-  switch (trust_eval) {
+  switch(trust_eval) {
     case kSecTrustResultUnspecified:
     case kSecTrustResultProceed:
       return CURLE_OK;
@@ -1842,6 +1901,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
   OSStatus err;
   SSLCipherSuite cipher;
   SSLProtocol protocol = 0;
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 
   DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
               || ssl_connect_2_reading == connssl->connecting_state
@@ -1851,7 +1912,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
   err = SSLHandshake(connssl->ssl_ctx);
 
   if(err != noErr) {
-    switch (err) {
+    switch(err) {
       case errSSLWouldBlock:  /* they're not done with us yet */
         connssl->connecting_state = connssl->ssl_direction ?
             ssl_connect_2_writing : ssl_connect_2_reading;
@@ -1860,8 +1921,8 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
       /* The below is errSSLServerAuthCompleted; it's not defined in
         Leopard's headers */
       case -9841:
-        if(data->set.str[STRING_SSL_CAFILE]) {
-          int res = verify_cert(data->set.str[STRING_SSL_CAFILE], data,
+        if(SSL_CONN_CONFIG(CAfile)) {
+          int res = verify_cert(SSL_CONN_CONFIG(CAfile), data,
                                 connssl->ssl_ctx);
           if(res != CURLE_OK)
             return res;
@@ -1930,7 +1991,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
         return CURLE_SSL_CONNECT_ERROR;
       default:
         failf(data, "Unknown SSL protocol error in connection to %s:%d",
-              conn->host.name, err);
+              hostname, err);
         return CURLE_SSL_CONNECT_ERROR;
     }
   }
@@ -1941,7 +2002,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
     /* Informational message */
     (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
     (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol);
-    switch (protocol) {
+    switch(protocol) {
       case kSSLProtocol2:
         infof(data, "SSL 2.0 connection using %s\n",
               SSLCipherNameForNumber(cipher));
@@ -2390,7 +2451,8 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
   (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
 }
 
-bool Curl_darwinssl_false_start(void) {
+bool Curl_darwinssl_false_start(void)
+{
 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
   if(SSLSetSessionOption != NULL)
     return TRUE;
@@ -2427,7 +2489,7 @@ static ssize_t darwinssl_send(struct connectdata *conn,
   if(connssl->ssl_write_buffered_length) {
     /* Write the buffered data: */
     err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed);
-    switch (err) {
+    switch(err) {
       case noErr:
         /* processed is always going to be 0 because we didn't write to
            the buffer, so return how much was written to the socket */
@@ -2447,7 +2509,7 @@ static ssize_t darwinssl_send(struct connectdata *conn,
     /* We've got new data to write: */
     err = SSLWrite(connssl->ssl_ctx, mem, len, &processed);
     if(err != noErr) {
-      switch (err) {
+      switch(err) {
         case errSSLWouldBlock:
           /* Data was buffered but not sent, we have to tell the caller
              to try sending again, and remember how much was buffered */
@@ -2476,7 +2538,7 @@ static ssize_t darwinssl_recv(struct connectdata *conn,
   OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed);
 
   if(err != noErr) {
-    switch (err) {
+    switch(err) {
       case errSSLWouldBlock:  /* return how much we read (if anything) */
         if(processed)
           return (ssize_t)processed;
diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
index 3b0cfd5..a0d462b 100644
--- a/lib/vtls/gskit.c
+++ b/lib/vtls/gskit.c
@@ -81,6 +81,10 @@
 #include "memdebug.h"
 
 
+/* Directions. */
+#define SOS_READ        0x01
+#define SOS_WRITE       0x02
+
 /* SSL version flags. */
 #define CURL_GSKPROTO_SSLV2     0
 #define CURL_GSKPROTO_SSLV2_MASK        (1 << CURL_GSKPROTO_SSLV2)
@@ -151,7 +155,7 @@ static const gskit_cipher  ciphertable[] = {
 static bool is_separator(char c)
 {
   /* Return whether character is a cipher list separator. */
-  switch (c) {
+  switch(c) {
   case ' ':
   case '\t':
   case ':':
@@ -167,7 +171,7 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc,
                              const char *procname, CURLcode defcode)
 {
   /* Process GSKit status and map it to a CURLcode. */
-  switch (rc) {
+  switch(rc) {
   case GSK_OK:
   case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
     return CURLE_OK;
@@ -190,7 +194,7 @@ static CURLcode gskit_status(struct Curl_easy *data, int rc,
   case GSK_OS400_ERROR_NOT_REGISTERED:
     break;
   case GSK_ERROR_IO:
-    switch (errno) {
+    switch(errno) {
     case ENOMEM:
       return CURLE_OUT_OF_MEMORY;
     default:
@@ -211,7 +215,7 @@ static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
 {
   int rc = gsk_attribute_set_enum(h, id, value);
 
-  switch (rc) {
+  switch(rc) {
   case GSK_OK:
     return CURLE_OK;
   case GSK_ERROR_IO:
@@ -233,7 +237,7 @@ static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
 {
   int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
 
-  switch (rc) {
+  switch(rc) {
   case GSK_OK:
     return CURLE_OK;
   case GSK_ERROR_IO:
@@ -255,7 +259,7 @@ static CURLcode set_numeric(struct Curl_easy *data,
 {
   int rc = gsk_attribute_set_numeric_value(h, id, value);
 
-  switch (rc) {
+  switch(rc) {
   case GSK_OK:
     return CURLE_OK;
   case GSK_ERROR_IO:
@@ -275,7 +279,7 @@ static CURLcode set_callback(struct Curl_easy *data,
 {
   int rc = gsk_attribute_set_callback(h, id, info);
 
-  switch (rc) {
+  switch(rc) {
   case GSK_OK:
     return CURLE_OK;
   case GSK_ERROR_IO:
@@ -289,10 +293,11 @@ static CURLcode set_callback(struct Curl_easy *data,
 }
 
 
-static CURLcode set_ciphers(struct Curl_easy *data,
+static CURLcode set_ciphers(struct connectdata *conn,
                                         gsk_handle h, unsigned int *protoflags)
 {
-  const char *cipherlist = data->set.str[STRING_SSL_CIPHER_LIST];
+  struct Curl_easy *data = conn->data;
+  const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
   const char *clp;
   const gskit_cipher *ctp;
   int i;
@@ -340,7 +345,7 @@ static CURLcode set_ciphers(struct Curl_easy *data,
       break;
     /* Search the cipher in our table. */
     for(ctp = ciphertable; ctp->name; ctp++)
-      if(strnequal(ctp->name, clp, l) && !ctp->name[l])
+      if(strncasecompare(ctp->name, clp, l) && !ctp->name[l])
         break;
     if(!ctp->name) {
       failf(data, "Unknown cipher %.*s", l, clp);
@@ -448,7 +453,7 @@ static CURLcode init_environment(struct Curl_easy *data,
   /* Creates the GSKit environment. */
 
   rc = gsk_environment_open(&h);
-  switch (rc) {
+  switch(rc) {
   case GSK_OK:
     break;
   case GSK_INSUFFICIENT_STORAGE:
@@ -500,17 +505,195 @@ static void close_async_handshake(struct ssl_connect_data *connssl)
   connssl->iocport = -1;
 }
 
+/* SSL over SSL
+ * Problems:
+ * 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To
+ *    pipe an SSL stream into another, it is therefore needed to have a pair
+ *    of such communicating sockets and handle the pipelining explicitly.
+ * 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot
+ *    be used to produce the pipeline.
+ * The solution is to simulate socketpair() for AF_INET with low-level API
+ *    listen(), bind() and connect().
+ */
+
+static int
+inetsocketpair(int sv[2])
+{
+  int lfd;      /* Listening socket. */
+  int sfd;      /* Server socket. */
+  int cfd;      /* Client socket. */
+  int len;
+  struct sockaddr_in addr1;
+  struct sockaddr_in addr2;
+
+  /* Create listening socket on a local dynamic port. */
+  lfd = socket(AF_INET, SOCK_STREAM, 0);
+  if(lfd < 0)
+    return -1;
+  memset((char *) &addr1, 0, sizeof addr1);
+  addr1.sin_family = AF_INET;
+  addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+  addr1.sin_port = 0;
+  if(bind(lfd, (struct sockaddr *) &addr1, sizeof addr1) ||
+     listen(lfd, 2) < 0) {
+    close(lfd);
+    return -1;
+  }
+
+  /* Get the allocated port. */
+  len = sizeof addr1;
+  if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) {
+    close(lfd);
+    return -1;
+  }
+
+  /* Create the client socket. */
+  cfd = socket(AF_INET, SOCK_STREAM, 0);
+  if(cfd < 0) {
+    close(lfd);
+    return -1;
+  }
+
+  /* Request unblocking connection to the listening socket. */
+  curlx_nonblock(cfd, TRUE);
+  if(connect(cfd, (struct sockaddr *) &addr1, sizeof addr1) < 0 &&
+     errno != EINPROGRESS) {
+    close(lfd);
+    close(cfd);
+    return -1;
+  }
+
+  /* Get the client dynamic port for intrusion check below. */
+  len = sizeof addr2;
+  if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) {
+    close(lfd);
+    close(cfd);
+    return -1;
+  }
+
+  /* Accept the incoming connection and get the server socket. */
+  curlx_nonblock(lfd, TRUE);
+  for(;;) {
+    len = sizeof addr1;
+    sfd = accept(lfd, (struct sockaddr *) &addr1, &len);
+    if(sfd < 0) {
+      close(lfd);
+      close(cfd);
+      return -1;
+    }
 
-static void close_one(struct ssl_connect_data *conn,
-                      struct Curl_easy *data)
+    /* Check for possible intrusion from an external process. */
+    if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr &&
+       addr1.sin_port == addr2.sin_port)
+      break;
+
+    /* Intrusion: reject incoming connection. */
+    close(sfd);
+  }
+
+  /* Done, return sockets and succeed. */
+  close(lfd);
+  curlx_nonblock(cfd, FALSE);
+  sv[0] = cfd;
+  sv[1] = sfd;
+  return 0;
+}
+
+static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
+                           int directions)
 {
-  if(conn->handle) {
-    gskit_status(data, gsk_secure_soc_close(&conn->handle),
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex];
+  fd_set fds_read;
+  fd_set fds_write;
+  int n;
+  int m;
+  int i;
+  int ret = 0;
+  struct timeval tv = {0, 0};
+  char buf[CURL_MAX_WRITE_SIZE];
+
+  if(!connssl->use || !connproxyssl->use)
+    return 0;   /* No SSL over SSL: OK. */
+
+  FD_ZERO(&fds_read);
+  FD_ZERO(&fds_write);
+  n = -1;
+  if(directions & SOS_READ) {
+    FD_SET(connssl->remotefd, &fds_write);
+    n = connssl->remotefd;
+  }
+  if(directions & SOS_WRITE) {
+    FD_SET(connssl->remotefd, &fds_read);
+    n = connssl->remotefd;
+    FD_SET(conn->sock[sockindex], &fds_write);
+    if(n < conn->sock[sockindex])
+      n = conn->sock[sockindex];
+  }
+  i = select(n + 1, &fds_read, &fds_write, NULL, &tv);
+  if(i < 0)
+    return -1;  /* Select error. */
+
+  if(FD_ISSET(connssl->remotefd, &fds_write)) {
+    /* Try getting data from HTTPS proxy and pipe it upstream. */
+    n = 0;
+    i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n);
+    switch(i) {
+    case GSK_OK:
+      if(n) {
+        i = write(connssl->remotefd, buf, n);
+        if(i < 0)
+          return -1;
+        ret = 1;
+      }
+      break;
+    case GSK_OS400_ERROR_TIMED_OUT:
+    case GSK_WOULD_BLOCK:
+      break;
+    default:
+      return -1;
+    }
+  }
+
+  if(FD_ISSET(connssl->remotefd, &fds_read) &&
+     FD_ISSET(conn->sock[sockindex], &fds_write)) {
+    /* Pipe data to HTTPS proxy. */
+    n = read(connssl->remotefd, buf, sizeof buf);
+    if(n < 0)
+      return -1;
+    if(n) {
+      i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m);
+      if(i != GSK_OK || n != m)
+        return -1;
+      ret = 1;
+    }
+  }
+
+  return ret;  /* OK */
+}
+
+
+static void close_one(struct ssl_connect_data *connssl,
+                      struct connectdata *conn, int sockindex)
+{
+  if(connssl->handle) {
+    gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle),
               "gsk_secure_soc_close()", 0);
-    conn->handle = (gsk_handle) NULL;
+    /* Last chance to drain output. */
+    while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
+      ;
+    connssl->handle = (gsk_handle) NULL;
+    if(connssl->localfd >= 0) {
+      close(connssl->localfd);
+      connssl->localfd = -1;
+    }
+    if(connssl->remotefd >= 0) {
+      close(connssl->remotefd);
+      connssl->remotefd = -1;
+    }
   }
-  if(conn->iocport >= 0)
-    close_async_handshake(conn);
+  if(connssl->iocport >= 0)
+    close_async_handshake(connssl);
 }
 
 
@@ -518,13 +701,18 @@ static ssize_t gskit_send(struct connectdata *conn, int sockindex,
                            const void *mem, size_t len, CURLcode *curlcode)
 {
   struct Curl_easy *data = conn->data;
-  CURLcode cc;
+  CURLcode cc = CURLE_SEND_ERROR;
   int written;
 
-  cc = gskit_status(data,
-                    gsk_secure_soc_write(conn->ssl[sockindex].handle,
-                                         (char *) mem, (int) len, &written),
-                    "gsk_secure_soc_write()", CURLE_SEND_ERROR);
+  if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
+    cc = gskit_status(data,
+                      gsk_secure_soc_write(conn->ssl[sockindex].handle,
+                                           (char *) mem, (int) len, &written),
+                      "gsk_secure_soc_write()", CURLE_SEND_ERROR);
+    if(cc == CURLE_OK)
+      if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0)
+        cc = CURLE_SEND_ERROR;
+  }
   if(cc != CURLE_OK) {
     *curlcode = cc;
     written = -1;
@@ -539,15 +727,23 @@ static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
   struct Curl_easy *data = conn->data;
   int buffsize;
   int nread;
-  CURLcode cc;
+  CURLcode cc = CURLE_RECV_ERROR;
 
-  buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
-  cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
-                                              buf, buffsize, &nread),
-                    "gsk_secure_soc_read()", CURLE_RECV_ERROR);
-  if(cc != CURLE_OK) {
+  if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
+    buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
+    cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
+                                                buf, buffsize, &nread),
+                      "gsk_secure_soc_read()", CURLE_RECV_ERROR);
+  }
+  switch(cc) {
+  case CURLE_OK:
+    break;
+  case CURLE_OPERATION_TIMEDOUT:
+    cc = CURLE_AGAIN;
+  default:
     *curlcode = cc;
     nread = -1;
+    break;
   }
   return (ssize_t) nread;
 }
@@ -560,18 +756,26 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
   gsk_handle envir;
   CURLcode result;
   int rc;
-  char *keyringfile;
-  char *keyringpwd;
-  char *keyringlabel;
-  char *sni;
+  const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
+  const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
+  const char * const keyringlabel = SSL_SET_OPTION(cert);
+  const long int ssl_version = SSL_CONN_CONFIG(version);
+  const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+  const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
+    conn->host.name;
+  const char *sni;
   unsigned int protoflags;
   long timeout;
   Qso_OverlappedIO_t commarea;
+  int sockpair[2];
+  static const int sobufsize = CURL_MAX_WRITE_SIZE;
 
   /* Create SSL environment, start (preferably asynchronous) handshake. */
 
   connssl->handle = (gsk_handle) NULL;
   connssl->iocport = -1;
+  connssl->localfd = -1;
+  connssl->remotefd = -1;
 
   /* GSKit supports two ways of specifying an SSL context: either by
    *  application identifier (that should have been defined at the system
@@ -586,9 +790,6 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
    *  application identifier mode is tried first, as recommended in IBM doc.
    */
 
-  keyringfile = data->set.str[STRING_SSL_CAFILE];
-  keyringpwd = data->set.str[STRING_KEY_PASSWD];
-  keyringlabel = data->set.str[STRING_CERT];
   envir = (gsk_handle) NULL;
 
   if(keyringlabel && *keyringlabel && !keyringpwd &&
@@ -613,19 +814,36 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
   if(result)
     return result;
 
+  /* Establish a pipelining socket pair for SSL over SSL. */
+  if(conn->proxy_ssl[sockindex].use) {
+    if(inetsocketpair(sockpair))
+      return CURLE_SSL_CONNECT_ERROR;
+    connssl->localfd = sockpair[0];
+    connssl->remotefd = sockpair[1];
+    setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF,
+               (void *) sobufsize, sizeof sobufsize);
+    setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF,
+               (void *) sobufsize, sizeof sobufsize);
+    setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF,
+               (void *) sobufsize, sizeof sobufsize);
+    setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF,
+               (void *) sobufsize, sizeof sobufsize);
+    curlx_nonblock(connssl->localfd, TRUE);
+    curlx_nonblock(connssl->remotefd, TRUE);
+  }
+
   /* Determine which SSL/TLS version should be enabled. */
-  protoflags = CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
-               CURL_GSKPROTO_TLSV12_MASK;
-  sni = conn->host.name;
-  switch (data->set.ssl.version) {
+  sni = hostname;
+  switch(ssl_version) {
   case CURL_SSLVERSION_SSLv2:
     protoflags = CURL_GSKPROTO_SSLV2_MASK;
-    sni = (char *) NULL;
+    sni = NULL;
     break;
   case CURL_SSLVERSION_SSLv3:
     protoflags = CURL_GSKPROTO_SSLV3_MASK;
-    sni = (char *) NULL;
+    sni = NULL;
     break;
+  case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
     protoflags = CURL_GSKPROTO_TLSV10_MASK |
                  CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
@@ -639,6 +857,12 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
   case CURL_SSLVERSION_TLSv1_2:
     protoflags = CURL_GSKPROTO_TLSV12_MASK;
     break;
+  case CURL_SSLVERSION_TLSv1_3:
+    failf(data, "GSKit: TLS 1.3 is not yet supported");
+    return CURLE_SSL_CONNECT_ERROR;
+  default:
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+    return CURLE_SSL_CONNECT_ERROR;
   }
 
   /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
@@ -661,9 +885,12 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
                            (timeout + 999) / 1000);
   }
   if(!result)
-    result = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]);
+    result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1);
   if(!result)
-    result = set_ciphers(data, connssl->handle, &protoflags);
+    result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0?
+                         connssl->localfd: conn->sock[sockindex]);
+  if(!result)
+    result = set_ciphers(conn, connssl->handle, &protoflags);
   if(!protoflags) {
     failf(data, "No SSL protocol/cipher combination enabled");
     result = CURLE_SSL_CIPHER;
@@ -706,7 +933,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
   }
   if(!result)
     result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
-                      data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL:
+                      verifypeer? GSK_SERVER_AUTH_FULL:
                       GSK_SERVER_AUTH_PASSTHRU, FALSE);
 
   if(!result) {
@@ -730,6 +957,10 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
     else if(errno != ENOBUFS)
       result = gskit_status(data, GSK_ERROR_IO,
                             "QsoCreateIOCompletionPort()", 0);
+    else if(conn->proxy_ssl[sockindex].use) {
+      /* Cannot pipeline while handshaking synchronously. */
+      result = CURLE_SSL_CONNECT_ERROR;
+    }
     else {
       /* No more completion port available. Use synchronous IO. */
       result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
@@ -742,7 +973,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
   }
 
   /* Error: rollback. */
-  close_one(connssl, data);
+  close_one(connssl, conn, sockindex);
   return result;
 }
 
@@ -765,7 +996,7 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
       timeout_ms = 0;
     stmv.tv_sec = timeout_ms / 1000;
     stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
-    switch (QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
+    switch(QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
     case 1:             /* Operation complete. */
       break;
     case -1:            /* An error occurred: handshake still in progress. */
@@ -822,7 +1053,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
     infof(data, "Server certificate:\n");
     p = cdev;
     for(i = 0; i++ < cdec; p++)
-      switch (p->cert_data_id) {
+      switch(p->cert_data_id) {
       case CERT_BODY_DER:
         cert = p->cert_data_p;
         certend = cert + cdev->cert_data_l;
@@ -865,14 +1096,14 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
   }
 
   /* Check pinned public key. */
-  ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+  ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+                         data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
   if(!result && ptr) {
     curl_X509certificate x509;
     curl_asn1Element *p;
 
-    if(!cert)
+    if(Curl_parseX509(&x509, cert, certend))
       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
-    Curl_parseX509(&x509, cert, certend);
     p = &x509.subjectPublicKeyInfo;
     result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header);
     if(result) {
@@ -913,6 +1144,11 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
       result = gskit_connect_step1(conn, sockindex);
   }
 
+  /* Handle handshake pipelining. */
+  if(!result)
+    if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
+      result = CURLE_SSL_CONNECT_ERROR;
+
   /* Step 2: check if handshake is over. */
   if(!result && connssl->connecting_state == ssl_connect_2) {
     /* check allowed time left */
@@ -927,12 +1163,17 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
       result = gskit_connect_step2(conn, sockindex, nonblocking);
   }
 
+  /* Handle handshake pipelining. */
+  if(!result)
+    if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
+      result = CURLE_SSL_CONNECT_ERROR;
+
   /* Step 3: gather certificate info, verify host. */
   if(!result && connssl->connecting_state == ssl_connect_3)
     result = gskit_connect_step3(conn, sockindex);
 
   if(result)
-    close_one(connssl, data);
+    close_one(connssl, conn, sockindex);
   else if(connssl->connecting_state == ssl_connect_done) {
     connssl->state = ssl_connection_complete;
     connssl->connecting_state = ssl_connect_1;
@@ -976,11 +1217,8 @@ CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
 
 void Curl_gskit_close(struct connectdata *conn, int sockindex)
 {
-  struct Curl_easy *data = conn->data;
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-
-  if(connssl->use)
-    close_one(connssl, data);
+  close_one(&conn->ssl[sockindex], conn, sockindex);
+  close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
 }
 
 
@@ -999,7 +1237,7 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
   if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
     return 0;
 
-  close_one(connssl, data);
+  close_one(connssl, conn, sockindex);
   rc = 0;
   what = SOCKET_READABLE(conn->sock[sockindex],
                          SSL_SHUTDOWN_TIMEOUT);
diff --git a/lib/vtls/gskit.h b/lib/vtls/gskit.h
index 41483cb..2297592 100644
--- a/lib/vtls/gskit.h
+++ b/lib/vtls/gskit.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at 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
@@ -41,6 +41,9 @@ int Curl_gskit_shutdown(struct connectdata *conn, int sockindex);
 size_t Curl_gskit_version(char *buffer, size_t size);
 int Curl_gskit_check_cxn(struct connectdata *cxn);
 
+/* Support HTTPS-proxy */
+/* TODO: add '#define HTTPS_PROXY_SUPPORT 1' and fix test #1014 (if need) */
+
 /* Set the API backend definition to GSKit */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT
 
@@ -64,7 +67,7 @@ int Curl_gskit_check_cxn(struct connectdata *cxn);
 #define curlssl_version Curl_gskit_version
 #define curlssl_check_cxn(x) Curl_gskit_check_cxn(x)
 #define curlssl_data_pending(x,y) 0
-#define curlssl_random(x,y,z) -1
+#define curlssl_random(x,y,z) (x=x, y=y, z=z, CURLE_NOT_BUILT_IN)
 
 #endif /* USE_GSKIT */
 
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index 5c87c7f..0e308cb 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -68,7 +68,7 @@
 #define GNUTLS_POINTER_TO_INT_CAST(p) ((int) (long) (p))
 #endif
 #ifndef GNUTLS_INT_TO_POINTER_CAST
-#define GNUTLS_INT_TO_POINTER_CAST(i) ((void*) (long) (i))
+#define GNUTLS_INT_TO_POINTER_CAST(i) ((void *) (long) (i))
 #endif
 
 /* Enable GnuTLS debugging by defining GTLSDEBUG */
@@ -171,6 +171,16 @@ static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
   return ret;
 }
 
+static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len)
+{
+  return gnutls_record_send((gnutls_session_t) s, buf, len);
+}
+
+static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
+{
+  return gnutls_record_recv((gnutls_session_t) s, buf, len);
+}
+
 /* Curl_gtls_init()
  *
  * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
@@ -225,14 +235,15 @@ static void showtime(struct Curl_easy *data,
   infof(data, "%s\n", data->state.buffer);
 }
 
-static gnutls_datum_t load_file (const char *file)
+static gnutls_datum_t load_file(const char *file)
 {
   FILE *f;
   gnutls_datum_t loaded_file = { NULL, 0 };
   long filelen;
   void *ptr;
 
-  if(!(f = fopen(file, "rb")))
+  f = fopen(file, "rb");
+  if(!f)
     return loaded_file;
   if(fseek(f, 0, SEEK_END) != 0
      || (filelen = ftell(f)) < 0
@@ -251,7 +262,8 @@ out:
   return loaded_file;
 }
 
-static void unload_file(gnutls_datum_t data) {
+static void unload_file(gnutls_datum_t data)
+{
   free(data.data);
 }
 
@@ -371,6 +383,9 @@ gtls_connect_step1(struct connectdata *conn,
   gnutls_session_t session;
   int rc;
   bool sni = TRUE; /* default is SNI enabled */
+  void *transport_ptr = NULL;
+  gnutls_push_func gnutls_transport_push = NULL;
+  gnutls_pull_func gnutls_transport_pull = NULL;
 #ifdef ENABLE_IPV6
   struct in6_addr addr;
 #else
@@ -397,10 +412,13 @@ gtls_connect_step1(struct connectdata *conn,
    requested in the priority string, so treat it specially
  */
 #define GNUTLS_SRP "+SRP"
-  const char* prioritylist;
+  const char *prioritylist;
   const char *err = NULL;
 #endif
 
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+
   if(conn->ssl[sockindex].state == ssl_connection_complete)
     /* to make us tolerant against being called more than once for the
        same connection */
@@ -409,12 +427,11 @@ gtls_connect_step1(struct connectdata *conn,
   if(!gtls_inited)
     Curl_gtls_init();
 
-  /* GnuTLS only supports SSLv3 and TLSv1 */
-  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+  if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
     failf(data, "GnuTLS does not support SSLv2");
     return CURLE_SSL_CONNECT_ERROR;
   }
-  else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
+  else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
     sni = FALSE; /* SSLv3 has no SNI */
 
   /* allocate a cred struct */
@@ -425,8 +442,8 @@ gtls_connect_step1(struct connectdata *conn,
   }
 
 #ifdef USE_TLS_SRP
-  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
-    infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
+  if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
+    infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
 
     rc = gnutls_srp_allocate_client_credentials(
            &conn->ssl[sockindex].srp_client_cred);
@@ -438,8 +455,8 @@ gtls_connect_step1(struct connectdata *conn,
 
     rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
                                            srp_client_cred,
-                                           data->set.ssl.username,
-                                           data->set.ssl.password);
+                                           SSL_SET_OPTION(username),
+                                           SSL_SET_OPTION(password));
     if(rc != GNUTLS_E_SUCCESS) {
       failf(data, "gnutls_srp_set_client_cred() failed: %s",
             gnutls_strerror(rc));
@@ -448,64 +465,64 @@ gtls_connect_step1(struct connectdata *conn,
   }
 #endif
 
-  if(data->set.ssl.CAfile) {
+  if(SSL_CONN_CONFIG(CAfile)) {
     /* set the trusted CA cert bundle file */
     gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
                                         GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
 
     rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
-                                                data->set.ssl.CAfile,
+                                                SSL_CONN_CONFIG(CAfile),
                                                 GNUTLS_X509_FMT_PEM);
     if(rc < 0) {
       infof(data, "error reading ca cert file %s (%s)\n",
-            data->set.ssl.CAfile, gnutls_strerror(rc));
-      if(data->set.ssl.verifypeer)
+            SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
+      if(SSL_CONN_CONFIG(verifypeer))
         return CURLE_SSL_CACERT_BADFILE;
     }
     else
-      infof(data, "found %d certificates in %s\n",
-            rc, data->set.ssl.CAfile);
+      infof(data, "found %d certificates in %s\n", rc,
+            SSL_CONN_CONFIG(CAfile));
   }
 
 #ifdef HAS_CAPATH
-  if(data->set.ssl.CApath) {
+  if(SSL_CONN_CONFIG(CApath)) {
     /* set the trusted CA cert directory */
     rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
-                                                data->set.ssl.CApath,
-                                                GNUTLS_X509_FMT_PEM);
+                                               SSL_CONN_CONFIG(CApath),
+                                               GNUTLS_X509_FMT_PEM);
     if(rc < 0) {
       infof(data, "error reading ca cert file %s (%s)\n",
-            data->set.ssl.CAfile, gnutls_strerror(rc));
-      if(data->set.ssl.verifypeer)
+            SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
+      if(SSL_CONN_CONFIG(verifypeer))
         return CURLE_SSL_CACERT_BADFILE;
     }
     else
       infof(data, "found %d certificates in %s\n",
-            rc, data->set.ssl.CApath);
+            rc, SSL_CONN_CONFIG(CApath));
   }
 #endif
 
 #ifdef CURL_CA_FALLBACK
   /* use system ca certificate store as fallback */
-  if(data->set.ssl.verifypeer &&
-     !(data->set.ssl.CAfile || data->set.ssl.CApath)) {
+  if(SSL_CONN_CONFIG(verifypeer) &&
+     !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
     gnutls_certificate_set_x509_system_trust(conn->ssl[sockindex].cred);
   }
 #endif
 
-  if(data->set.ssl.CRLfile) {
+  if(SSL_SET_OPTION(CRLfile)) {
     /* set the CRL list file */
     rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
-                                              data->set.ssl.CRLfile,
+                                              SSL_SET_OPTION(CRLfile),
                                               GNUTLS_X509_FMT_PEM);
     if(rc < 0) {
       failf(data, "error reading crl file %s (%s)",
-            data->set.ssl.CRLfile, gnutls_strerror(rc));
+            SSL_SET_OPTION(CRLfile), gnutls_strerror(rc));
       return CURLE_SSL_CRL_BADFILE;
     }
     else
       infof(data, "found %d CRL in %s\n",
-            rc, data->set.ssl.CRLfile);
+            rc, SSL_SET_OPTION(CRLfile));
   }
 
   /* Initialize TLS session as a client */
@@ -518,13 +535,13 @@ gtls_connect_step1(struct connectdata *conn,
   /* convenient assign */
   session = conn->ssl[sockindex].session;
 
-  if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
+  if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
 #ifdef ENABLE_IPV6
-     (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
+     (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
 #endif
      sni &&
-     (gnutls_server_name_set(session, GNUTLS_NAME_DNS, conn->host.name,
-                             strlen(conn->host.name)) < 0))
+     (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname,
+                             strlen(hostname)) < 0))
     infof(data, "WARNING: failed to configure server name indication (SNI) "
           "TLS extension\n");
 
@@ -545,13 +562,13 @@ gtls_connect_step1(struct connectdata *conn,
   if(rc != GNUTLS_E_SUCCESS)
     return CURLE_SSL_CONNECT_ERROR;
 
-  if(data->set.ssl.cipher_list != NULL) {
+  if(SSL_CONN_CONFIG(cipher_list) != NULL) {
     failf(data, "can't pass a custom cipher list to older GnuTLS"
           " versions");
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  switch (data->set.ssl.version) {
+  switch(SSL_CONN_CONFIG(version) {
     case CURL_SSLVERSION_SSLv3:
       protocol_priority[0] = GNUTLS_SSL3;
       break;
@@ -569,12 +586,16 @@ gtls_connect_step1(struct connectdata *conn,
       break;
     case CURL_SSLVERSION_TLSv1_2:
       protocol_priority[0] = GNUTLS_TLS1_2;
-    break;
-      case CURL_SSLVERSION_SSLv2:
-    default:
+      break;
+    case CURL_SSLVERSION_TLSv1_3:
+      failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+      return CURLE_SSL_CONNECT_ERROR;
+    case CURL_SSLVERSION_SSLv2:
       failf(data, "GnuTLS does not support SSLv2");
       return CURLE_SSL_CONNECT_ERROR;
-      break;
+    default:
+      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+      return CURLE_SSL_CONNECT_ERROR;
   }
   rc = gnutls_protocol_set_priority(session, protocol_priority);
   if(rc != GNUTLS_E_SUCCESS) {
@@ -586,7 +607,7 @@ gtls_connect_step1(struct connectdata *conn,
   /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
    * removed if a run-time error indicates that SRP is not supported by this
    * GnuTLS version */
-  switch (data->set.ssl.version) {
+  switch(SSL_CONN_CONFIG(version)) {
     case CURL_SSLVERSION_SSLv3:
       prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
       sni = false;
@@ -607,11 +628,15 @@ gtls_connect_step1(struct connectdata *conn,
       prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
                      "+VERS-TLS1.2:" GNUTLS_SRP;
       break;
+    case CURL_SSLVERSION_TLSv1_3:
+      failf(data, "GnuTLS: TLS 1.3 is not yet supported");
+      return CURLE_SSL_CONNECT_ERROR;
     case CURL_SSLVERSION_SSLv2:
-    default:
       failf(data, "GnuTLS does not support SSLv2");
       return CURLE_SSL_CONNECT_ERROR;
-      break;
+    default:
+      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+      return CURLE_SSL_CONNECT_ERROR;
   }
   rc = gnutls_priority_set_direct(session, prioritylist, &err);
   if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
@@ -661,8 +686,8 @@ gtls_connect_step1(struct connectdata *conn,
   }
 #endif
 
-  if(data->set.str[STRING_CERT]) {
-    if(data->set.str[STRING_KEY_PASSWD]) {
+  if(SSL_SET_OPTION(cert)) {
+    if(SSL_SET_OPTION(key_passwd)) {
 #if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
       const unsigned int supported_key_encryption_algorithms =
         GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
@@ -671,11 +696,11 @@ gtls_connect_step1(struct connectdata *conn,
         GNUTLS_PKCS_USE_PBES2_AES_256;
       rc = gnutls_certificate_set_x509_key_file2(
            conn->ssl[sockindex].cred,
-           data->set.str[STRING_CERT],
-           data->set.str[STRING_KEY] ?
-           data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
-           do_file_type(data->set.str[STRING_CERT_TYPE]),
-           data->set.str[STRING_KEY_PASSWD],
+           SSL_SET_OPTION(cert),
+           SSL_SET_OPTION(key) ?
+           SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
+           do_file_type(SSL_SET_OPTION(cert_type)),
+           SSL_SET_OPTION(key_passwd),
            supported_key_encryption_algorithms);
       if(rc != GNUTLS_E_SUCCESS) {
         failf(data,
@@ -689,15 +714,14 @@ gtls_connect_step1(struct connectdata *conn,
 #endif
     }
     else {
-      rc = gnutls_certificate_set_x509_key_file(
+      if(gnutls_certificate_set_x509_key_file(
            conn->ssl[sockindex].cred,
-           data->set.str[STRING_CERT],
-           data->set.str[STRING_KEY] ?
-           data->set.str[STRING_KEY] : data->set.str[STRING_CERT],
-           do_file_type(data->set.str[STRING_CERT_TYPE]) );
-      if(rc != GNUTLS_E_SUCCESS) {
-        failf(data, "error reading X.509 key or certificate file: %s",
-              gnutls_strerror(rc));
+           SSL_SET_OPTION(cert),
+           SSL_SET_OPTION(key) ?
+           SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
+           do_file_type(SSL_SET_OPTION(cert_type)) ) !=
+         GNUTLS_E_SUCCESS) {
+        failf(data, "error reading X.509 key or certificate file");
         return CURLE_SSL_CONNECT_ERROR;
       }
     }
@@ -705,7 +729,7 @@ gtls_connect_step1(struct connectdata *conn,
 
 #ifdef USE_TLS_SRP
   /* put the credentials to the current session */
-  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+  if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
     rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
                                 conn->ssl[sockindex].srp_client_cred);
     if(rc != GNUTLS_E_SUCCESS) {
@@ -724,19 +748,30 @@ gtls_connect_step1(struct connectdata *conn,
     }
   }
 
-  /* set the connection handle (file descriptor for the socket) */
-  gnutls_transport_set_ptr(session,
-                           GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]));
+  if(conn->proxy_ssl[sockindex].use) {
+    transport_ptr = conn->proxy_ssl[sockindex].session;
+    gnutls_transport_push = Curl_gtls_push_ssl;
+    gnutls_transport_pull = Curl_gtls_pull_ssl;
+  }
+  else {
+    /* file descriptor for the socket */
+    transport_ptr = GNUTLS_INT_TO_POINTER_CAST(conn->sock[sockindex]);
+    gnutls_transport_push = Curl_gtls_push;
+    gnutls_transport_pull = Curl_gtls_pull;
+  }
+
+  /* set the connection handle */
+  gnutls_transport_set_ptr(session, transport_ptr);
 
   /* register callback functions to send and receive data. */
-  gnutls_transport_set_push_function(session, Curl_gtls_push);
-  gnutls_transport_set_pull_function(session, Curl_gtls_pull);
+  gnutls_transport_set_push_function(session, gnutls_transport_push);
+  gnutls_transport_set_pull_function(session, gnutls_transport_pull);
 
   /* lowat must be set to zero when using custom push and pull functions. */
   gnutls_transport_set_lowat(session, 0);
 
 #ifdef HAS_OCSP
-  if(data->set.ssl.verifystatus) {
+  if(SSL_CONN_CONFIG(verifystatus)) {
     rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
     if(rc != GNUTLS_E_SUCCESS) {
       failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
@@ -747,17 +782,17 @@ gtls_connect_step1(struct connectdata *conn,
 
   /* This might be a reconnect, so we check for a session ID in the cache
      to speed up things */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     void *ssl_sessionid;
     size_t ssl_idsize;
 
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize)) {
+    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
       /* we got a session id, use it! */
       gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
 
       /* Informational message */
-      infof (data, "SSL re-using session ID\n");
+      infof(data, "SSL re-using session ID\n");
     }
     Curl_ssl_sessionid_unlock(conn);
   }
@@ -847,8 +882,9 @@ gtls_connect_step3(struct connectdata *conn,
   gnutls_datum_t proto;
 #endif
   CURLcode result = CURLE_OK;
-
   gnutls_protocol_t version = gnutls_protocol_get_version(session);
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 
   /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
   ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
@@ -866,13 +902,13 @@ gtls_connect_step3(struct connectdata *conn,
 
   chainp = gnutls_certificate_get_peers(session, &cert_list_size);
   if(!chainp) {
-    if(data->set.ssl.verifypeer ||
-       data->set.ssl.verifyhost ||
-       data->set.ssl.issuercert) {
+    if(SSL_CONN_CONFIG(verifypeer) ||
+       SSL_CONN_CONFIG(verifyhost) ||
+       SSL_SET_OPTION(issuercert)) {
 #ifdef USE_TLS_SRP
-      if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
-         && data->set.ssl.username != NULL
-         && !data->set.ssl.verifypeer
+      if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
+         && SSL_SET_OPTION(username) != NULL
+         && !SSL_CONN_CONFIG(verifypeer)
          && gnutls_cipher_get(session)) {
         /* no peer cert, but auth is ok if we have SRP user and cipher and no
            peer verify */
@@ -905,7 +941,7 @@ gtls_connect_step3(struct connectdata *conn,
     }
   }
 
-  if(data->set.ssl.verifypeer) {
+  if(SSL_CONN_CONFIG(verifypeer)) {
     /* This function will try to verify the peer's certificate and return its
        status (trusted, invalid etc.). The value of status should be one or
        more of the gnutls_certificate_status_t enumerated elements bitwise
@@ -921,10 +957,11 @@ gtls_connect_step3(struct connectdata *conn,
 
     /* verify_status is a bitmask of gnutls_certificate_status bits */
     if(verify_status & GNUTLS_CERT_INVALID) {
-      if(data->set.ssl.verifypeer) {
+      if(SSL_CONN_CONFIG(verifypeer)) {
         failf(data, "server certificate verification failed. CAfile: %s "
-              "CRLfile: %s", data->set.ssl.CAfile?data->set.ssl.CAfile:"none",
-              data->set.ssl.CRLfile?data->set.ssl.CRLfile:"none");
+              "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
+              "none",
+              SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
         return CURLE_SSL_CACERT;
       }
       else
@@ -937,7 +974,7 @@ gtls_connect_step3(struct connectdata *conn,
     infof(data, "\t server certificate verification SKIPPED\n");
 
 #ifdef HAS_OCSP
-  if(data->set.ssl.verifystatus) {
+  if(SSL_CONN_CONFIG(verifystatus)) {
     if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
       gnutls_datum_t status_request;
       gnutls_ocsp_resp_t ocsp_resp;
@@ -1049,21 +1086,21 @@ gtls_connect_step3(struct connectdata *conn,
        gnutls_x509_crt_t format */
     gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
 
-  if(data->set.ssl.issuercert) {
+  if(SSL_SET_OPTION(issuercert)) {
     gnutls_x509_crt_init(&x509_issuer);
-    issuerp = load_file(data->set.ssl.issuercert);
+    issuerp = load_file(SSL_SET_OPTION(issuercert));
     gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
     rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
     gnutls_x509_crt_deinit(x509_issuer);
     unload_file(issuerp);
     if(rc <= 0) {
       failf(data, "server certificate issuer check failed (IssuerCert: %s)",
-            data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
+            SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
       gnutls_x509_crt_deinit(x509_cert);
       return CURLE_SSL_ISSUER_ERROR;
     }
     infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
-          data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
+          SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
   }
 
   size=sizeof(certbuf);
@@ -1082,7 +1119,7 @@ gtls_connect_step3(struct connectdata *conn,
      in RFC2818 (HTTPS), which takes into account wildcards, and the subject
      alternative name PKIX extension. Returns non zero on success, and zero on
      failure. */
-  rc = gnutls_x509_crt_check_hostname(x509_cert, conn->host.name);
+  rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
 #if GNUTLS_VERSION_NUMBER < 0x030306
   /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
      addresses. */
@@ -1098,10 +1135,10 @@ gtls_connect_step3(struct connectdata *conn,
     int i;
     int ret = 0;
 
-    if(Curl_inet_pton(AF_INET, conn->host.name, addrbuf) > 0)
+    if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
       addrlen = 4;
 #ifdef ENABLE_IPV6
-    else if(Curl_inet_pton(AF_INET6, conn->host.name, addrbuf) > 0)
+    else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
       addrlen = 16;
 #endif
 
@@ -1126,15 +1163,18 @@ gtls_connect_step3(struct connectdata *conn,
   }
 #endif
   if(!rc) {
-    if(data->set.ssl.verifyhost) {
+    const char * const dispname = SSL_IS_PROXY() ?
+      conn->http_proxy.host.dispname : conn->host.dispname;
+
+    if(SSL_CONN_CONFIG(verifyhost)) {
       failf(data, "SSL: certificate subject name (%s) does not match "
-            "target host name '%s'", certbuf, conn->host.dispname);
+            "target host name '%s'", certbuf, dispname);
       gnutls_x509_crt_deinit(x509_cert);
       return CURLE_PEER_FAILED_VERIFICATION;
     }
     else
       infof(data, "\t common name: %s (does not match '%s')\n",
-            certbuf, conn->host.dispname);
+            certbuf, dispname);
   }
   else
     infof(data, "\t common name: %s (matched)\n", certbuf);
@@ -1143,7 +1183,7 @@ gtls_connect_step3(struct connectdata *conn,
   certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
 
   if(certclock == (time_t)-1) {
-    if(data->set.ssl.verifypeer) {
+    if(SSL_CONN_CONFIG(verifypeer)) {
       failf(data, "server cert expiration date verify failed");
       gnutls_x509_crt_deinit(x509_cert);
       return CURLE_SSL_CONNECT_ERROR;
@@ -1153,7 +1193,7 @@ gtls_connect_step3(struct connectdata *conn,
   }
   else {
     if(certclock < time(NULL)) {
-      if(data->set.ssl.verifypeer) {
+      if(SSL_CONN_CONFIG(verifypeer)) {
         failf(data, "server certificate expiration date has passed.");
         gnutls_x509_crt_deinit(x509_cert);
         return CURLE_PEER_FAILED_VERIFICATION;
@@ -1168,7 +1208,7 @@ gtls_connect_step3(struct connectdata *conn,
   certclock = gnutls_x509_crt_get_activation_time(x509_cert);
 
   if(certclock == (time_t)-1) {
-    if(data->set.ssl.verifypeer) {
+    if(SSL_CONN_CONFIG(verifypeer)) {
       failf(data, "server cert activation date verify failed");
       gnutls_x509_crt_deinit(x509_cert);
       return CURLE_SSL_CONNECT_ERROR;
@@ -1178,7 +1218,7 @@ gtls_connect_step3(struct connectdata *conn,
   }
   else {
     if(certclock > time(NULL)) {
-      if(data->set.ssl.verifypeer) {
+      if(SSL_CONN_CONFIG(verifypeer)) {
         failf(data, "server certificate not activated yet.");
         gnutls_x509_crt_deinit(x509_cert);
         return CURLE_PEER_FAILED_VERIFICATION;
@@ -1190,7 +1230,8 @@ gtls_connect_step3(struct connectdata *conn,
       infof(data, "\t server certificate activation date OK\n");
   }
 
-  ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+  ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+        data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
   if(ptr) {
     result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
     if(result != CURLE_OK) {
@@ -1270,7 +1311,7 @@ gtls_connect_step3(struct connectdata *conn,
   conn->recv[sockindex] = gtls_recv;
   conn->send[sockindex] = gtls_send;
 
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     /* we always unconditionally get the session id here, as even if we
        already got it from the cache and asked to use it in the connection, it
        might've been rejected and then a new one is in use now and we need to
@@ -1289,7 +1330,8 @@ gtls_connect_step3(struct connectdata *conn,
       gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
 
       Curl_ssl_sessionid_lock(conn);
-      incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
+      incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
+                                        sockindex));
       if(incache) {
         /* there was one before in the cache, so instead of risking that the
            previous one was rejected, we just kill that and store the new */
@@ -1297,7 +1339,8 @@ gtls_connect_step3(struct connectdata *conn,
       }
 
       /* store this session id */
-      result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
+      result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize,
+                                     sockindex);
       Curl_ssl_sessionid_unlock(conn);
       if(result) {
         free(connect_sessionid);
@@ -1332,7 +1375,7 @@ gtls_connect_common(struct connectdata *conn,
 
   /* Initiate the connection, if not already done */
   if(ssl_connect_1==connssl->connecting_state) {
-    rc = gtls_connect_step1 (conn, sockindex);
+    rc = gtls_connect_step1(conn, sockindex);
     if(rc)
       return rc;
   }
@@ -1379,6 +1422,20 @@ Curl_gtls_connect(struct connectdata *conn,
   return CURLE_OK;
 }
 
+bool Curl_gtls_data_pending(const struct connectdata *conn, int connindex)
+{
+  bool res = FALSE;
+  if(conn->ssl[connindex].session &&
+     0 != gnutls_record_check_pending(conn->ssl[connindex].session))
+    res = TRUE;
+
+  if(conn->proxy_ssl[connindex].session &&
+     0 != gnutls_record_check_pending(conn->proxy_ssl[connindex].session))
+    res = TRUE;
+
+  return res;
+}
+
 static ssize_t gtls_send(struct connectdata *conn,
                          int sockindex,
                          const void *mem,
@@ -1398,29 +1455,29 @@ static ssize_t gtls_send(struct connectdata *conn,
   return rc;
 }
 
-static void close_one(struct connectdata *conn,
-                      int idx)
+static void close_one(struct ssl_connect_data *ssl)
 {
-  if(conn->ssl[idx].session) {
-    gnutls_bye(conn->ssl[idx].session, GNUTLS_SHUT_RDWR);
-    gnutls_deinit(conn->ssl[idx].session);
-    conn->ssl[idx].session = NULL;
+  if(ssl->session) {
+    gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR);
+    gnutls_deinit(ssl->session);
+    ssl->session = NULL;
   }
-  if(conn->ssl[idx].cred) {
-    gnutls_certificate_free_credentials(conn->ssl[idx].cred);
-    conn->ssl[idx].cred = NULL;
+  if(ssl->cred) {
+    gnutls_certificate_free_credentials(ssl->cred);
+    ssl->cred = NULL;
   }
 #ifdef USE_TLS_SRP
-  if(conn->ssl[idx].srp_client_cred) {
-    gnutls_srp_free_client_credentials(conn->ssl[idx].srp_client_cred);
-    conn->ssl[idx].srp_client_cred = NULL;
+  if(ssl->srp_client_cred) {
+    gnutls_srp_free_client_credentials(ssl->srp_client_cred);
+    ssl->srp_client_cred = NULL;
   }
 #endif
 }
 
 void Curl_gtls_close(struct connectdata *conn, int sockindex)
 {
-  close_one(conn, sockindex);
+  close_one(&conn->ssl[sockindex]);
+  close_one(&conn->proxy_ssl[sockindex]);
 }
 
 /*
@@ -1486,8 +1543,8 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
   gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
 
 #ifdef USE_TLS_SRP
-  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP
-     && data->set.ssl.username != NULL)
+  if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
+     && SSL_SET_OPTION(username) != NULL)
     gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
 #endif
 
@@ -1597,7 +1654,7 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */
   gcry_md_hd_t MD5pw;
   gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
   gcry_md_write(MD5pw, tmp, tmplen);
-  memcpy(md5sum, gcry_md_read (MD5pw, 0), md5len);
+  memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
   gcry_md_close(MD5pw);
 #endif
 }
@@ -1616,7 +1673,7 @@ void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
   gcry_md_hd_t SHA256pw;
   gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
   gcry_md_write(SHA256pw, tmp, tmplen);
-  memcpy(sha256sum, gcry_md_read (SHA256pw, 0), sha256len);
+  memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
   gcry_md_close(SHA256pw);
 #endif
 }
diff --git a/lib/vtls/gtls.h b/lib/vtls/gtls.h
index e0a95a7..6531201 100644
--- a/lib/vtls/gtls.h
+++ b/lib/vtls/gtls.h
@@ -34,6 +34,8 @@ CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
 CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
                                        int sockindex,
                                        bool *done);
+bool Curl_gtls_data_pending(const struct connectdata *conn,
+                            int connindex);
 
  /* close a SSL connection */
 void Curl_gtls_close(struct connectdata *conn, int sockindex);
@@ -55,6 +57,9 @@ void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
 
 bool Curl_gtls_cert_status_request(void);
 
+/* Support HTTPS-proxy */
+#define HTTPS_PROXY_SUPPORT 1
+
 /* Set the API backend definition to GnuTLS */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS
 
@@ -81,7 +86,7 @@ bool Curl_gtls_cert_status_request(void);
 #define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
 #define curlssl_version Curl_gtls_version
 #define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
+#define curlssl_data_pending(x,y) Curl_gtls_data_pending(x,y)
 #define curlssl_random(x,y,z) Curl_gtls_random(x,y,z)
 #define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d)
 #define curlssl_sha256sum(a,b,c,d) Curl_gtls_sha256sum(a,b,c,d)
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index 24249dd..8bcaddd 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -31,11 +31,15 @@
 
 #ifdef USE_MBEDTLS
 
+#include <mbedtls/version.h>
+#if MBEDTLS_VERSION_NUMBER >= 0x02040000
 #include <mbedtls/net_sockets.h>
+#else
+#include <mbedtls/net.h>
+#endif
 #include <mbedtls/ssl.h>
 #include <mbedtls/certs.h>
 #include <mbedtls/x509.h>
-#include <mbedtls/version.h>
 
 #include <mbedtls/error.h>
 #include <mbedtls/entropy.h>
@@ -159,13 +163,20 @@ mbed_connect_step1(struct connectdata *conn,
 {
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
-
+  const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+  const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+  const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
+  char * const ssl_cert = SSL_SET_OPTION(cert);
+  const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
   int ret = -1;
   char errorbuf[128];
   errorbuf[0]=0;
 
   /* mbedTLS only supports SSLv3 and TLSv1 */
-  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+  if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
     failf(data, "mbedTLS does not support SSLv2");
     return CURLE_SSL_CONNECT_ERROR;
   }
@@ -201,34 +212,32 @@ mbed_connect_step1(struct connectdata *conn,
   /* Load the trusted CA */
   mbedtls_x509_crt_init(&connssl->cacert);
 
-  if(data->set.str[STRING_SSL_CAFILE]) {
-    ret = mbedtls_x509_crt_parse_file(&connssl->cacert,
-                                      data->set.str[STRING_SSL_CAFILE]);
+  if(ssl_cafile) {
+    ret = mbedtls_x509_crt_parse_file(&connssl->cacert, ssl_cafile);
 
     if(ret<0) {
 #ifdef MBEDTLS_ERROR_C
       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
 #endif /* MBEDTLS_ERROR_C */
       failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
-            data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);
+            ssl_cafile, -ret, errorbuf);
 
-      if(data->set.ssl.verifypeer)
+      if(verifypeer)
         return CURLE_SSL_CACERT_BADFILE;
     }
   }
 
-  if(data->set.str[STRING_SSL_CAPATH]) {
-    ret = mbedtls_x509_crt_parse_path(&connssl->cacert,
-                                      data->set.str[STRING_SSL_CAPATH]);
+  if(ssl_capath) {
+    ret = mbedtls_x509_crt_parse_path(&connssl->cacert, ssl_capath);
 
     if(ret<0) {
 #ifdef MBEDTLS_ERROR_C
       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
 #endif /* MBEDTLS_ERROR_C */
       failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
-            data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);
+            ssl_capath, -ret, errorbuf);
 
-      if(data->set.ssl.verifypeer)
+      if(verifypeer)
         return CURLE_SSL_CACERT_BADFILE;
     }
   }
@@ -236,16 +245,15 @@ mbed_connect_step1(struct connectdata *conn,
   /* Load the client certificate */
   mbedtls_x509_crt_init(&connssl->clicert);
 
-  if(data->set.str[STRING_CERT]) {
-    ret = mbedtls_x509_crt_parse_file(&connssl->clicert,
-                                      data->set.str[STRING_CERT]);
+  if(ssl_cert) {
+    ret = mbedtls_x509_crt_parse_file(&connssl->clicert, ssl_cert);
 
     if(ret) {
 #ifdef MBEDTLS_ERROR_C
       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
 #endif /* MBEDTLS_ERROR_C */
       failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
-            data->set.str[STRING_CERT], -ret, errorbuf);
+            ssl_cert, -ret, errorbuf);
 
       return CURLE_SSL_CERTPROBLEM;
     }
@@ -254,9 +262,9 @@ mbed_connect_step1(struct connectdata *conn,
   /* Load the client private key */
   mbedtls_pk_init(&connssl->pk);
 
-  if(data->set.str[STRING_KEY]) {
-    ret = mbedtls_pk_parse_keyfile(&connssl->pk, data->set.str[STRING_KEY],
-                                   data->set.str[STRING_KEY_PASSWD]);
+  if(SSL_SET_OPTION(key)) {
+    ret = mbedtls_pk_parse_keyfile(&connssl->pk, SSL_SET_OPTION(key),
+                                   SSL_SET_OPTION(key_passwd));
     if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA))
       ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
 
@@ -265,7 +273,7 @@ mbed_connect_step1(struct connectdata *conn,
       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
 #endif /* MBEDTLS_ERROR_C */
       failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
-            data->set.str[STRING_KEY], -ret, errorbuf);
+            SSL_SET_OPTION(key), -ret, errorbuf);
 
       return CURLE_SSL_CERTPROBLEM;
     }
@@ -274,23 +282,21 @@ mbed_connect_step1(struct connectdata *conn,
   /* Load the CRL */
   mbedtls_x509_crl_init(&connssl->crl);
 
-  if(data->set.str[STRING_SSL_CRLFILE]) {
-    ret = mbedtls_x509_crl_parse_file(&connssl->crl,
-                                      data->set.str[STRING_SSL_CRLFILE]);
+  if(ssl_crlfile) {
+    ret = mbedtls_x509_crl_parse_file(&connssl->crl, ssl_crlfile);
 
     if(ret) {
 #ifdef MBEDTLS_ERROR_C
       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
 #endif /* MBEDTLS_ERROR_C */
       failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
-            data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);
+            ssl_crlfile, -ret, errorbuf);
 
       return CURLE_SSL_CRL_BADFILE;
     }
   }
 
-  infof(data, "mbedTLS: Connecting to %s:%d\n",
-        conn->host.name, conn->remote_port);
+  infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port);
 
   mbedtls_ssl_config_init(&connssl->config);
 
@@ -312,7 +318,7 @@ mbed_connect_step1(struct connectdata *conn,
   mbedtls_ssl_conf_cert_profile(&connssl->config,
                                 &mbedtls_x509_crt_profile_fr);
 
-  switch(data->set.ssl.version) {
+  switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
     mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
@@ -347,8 +353,11 @@ mbed_connect_step1(struct connectdata *conn,
                                  MBEDTLS_SSL_MINOR_VERSION_3);
     infof(data, "mbedTLS: Set SSL version to TLS 1.2\n");
     break;
+  case CURL_SSLVERSION_TLSv1_3:
+    failf(data, "mbedTLS: TLS 1.3 is not yet supported");
+    return CURLE_SSL_CONNECT_ERROR;
   default:
-    failf(data, "mbedTLS: Unsupported SSL protocol version");
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
     return CURLE_SSL_CONNECT_ERROR;
   }
 
@@ -365,11 +374,11 @@ mbed_connect_step1(struct connectdata *conn,
                                 mbedtls_ssl_list_ciphersuites());
 
   /* Check if there's a cached ID we can/should use here! */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     void *old_session = NULL;
 
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) {
+    if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
       ret = mbedtls_ssl_set_session(&connssl->ssl, old_session);
       if(ret) {
         Curl_ssl_sessionid_unlock(conn);
@@ -385,11 +394,11 @@ mbed_connect_step1(struct connectdata *conn,
                             &connssl->cacert,
                             &connssl->crl);
 
-  if(data->set.str[STRING_KEY]) {
+  if(SSL_SET_OPTION(key)) {
     mbedtls_ssl_conf_own_cert(&connssl->config,
                               &connssl->clicert, &connssl->pk);
   }
-  if(mbedtls_ssl_set_hostname(&connssl->ssl, conn->host.name)) {
+  if(mbedtls_ssl_set_hostname(&connssl->ssl, hostname)) {
     /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
        the name to set in the SNI extension. So even if curl connects to a
        host specified as an IP address, this function must be used. */
@@ -443,9 +452,12 @@ mbed_connect_step2(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
   const mbedtls_x509_crt *peercert;
+  const char * const pinnedpubkey = SSL_IS_PROXY() ?
+        data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+        data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
 
 #ifdef HAS_ALPN
-  const char* next_protocol;
+  const char *next_protocol;
 #endif
 
   char errorbuf[128];
@@ -479,7 +491,7 @@ mbed_connect_step2(struct connectdata *conn,
 
   ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl);
 
-  if(ret && data->set.ssl.verifypeer) {
+  if(ret && SSL_CONN_CONFIG(verifypeer)) {
     if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
       failf(data, "Cert verify failed: BADCERT_EXPIRED");
 
@@ -514,7 +526,7 @@ mbed_connect_step2(struct connectdata *conn,
     free(buffer);
   }
 
-  if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+  if(pinnedpubkey) {
     int size;
     CURLcode result;
     mbedtls_x509_crt *p;
@@ -553,7 +565,7 @@ mbed_connect_step2(struct connectdata *conn,
 
     /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
     result = Curl_pin_peer_pubkey(data,
-                                  data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+                                  pinnedpubkey,
                                   &pubkey[PUB_DER_MAX_BYTES - size], size);
     if(result) {
       mbedtls_x509_crt_free(p);
@@ -606,7 +618,7 @@ mbed_connect_step3(struct connectdata *conn,
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     int ret;
     mbedtls_ssl_session *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
@@ -625,10 +637,10 @@ mbed_connect_step3(struct connectdata *conn,
 
     /* If there's already a matching session in the cache, delete it */
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL))
+    if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
       Curl_ssl_delsessionid(conn, old_ssl_sessionid);
 
-    retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0);
+    retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
     Curl_ssl_sessionid_unlock(conn);
     if(retcode) {
       free(our_ssl_sessionid);
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index dff1575..ba8d582 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -200,14 +200,14 @@ static const cipher_s cipherlist[] = {
 #endif
 };
 
-static const char* pem_library = "libnsspem.so";
-static SECMODModule* mod = NULL;
+static const char *pem_library = "libnsspem.so";
+static SECMODModule *mod = NULL;
 
 /* NSPR I/O layer we use to detect blocking direction during SSL handshake */
 static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
 static PRIOMethods nspr_io_methods;
 
-static const char* nss_error_to_name(PRErrorCode code)
+static const char *nss_error_to_name(PRErrorCode code)
 {
   const char *name = PR_ErrorToName(code);
   if(name)
@@ -254,7 +254,8 @@ static SECStatus set_ciphers(struct Curl_easy *data, PRFileDesc * model,
     while((*cipher) && (ISSPACE(*cipher)))
       ++cipher;
 
-    if((cipher_list = strchr(cipher, ','))) {
+    cipher_list = strchr(cipher, ',');
+    if(cipher_list) {
       *cipher_list++ = '\0';
     }
 
@@ -337,9 +338,8 @@ static int is_file(const char *filename)
  * should be later deallocated using free().  If the OOM failure occurs, we
  * return NULL, too.
  */
-static char* dup_nickname(struct Curl_easy *data, enum dupstring cert_kind)
+static char *dup_nickname(struct Curl_easy *data, const char *str)
 {
-  const char *str = data->set.str[cert_kind];
   const char *n;
 
   if(!is_file(str))
@@ -514,7 +514,7 @@ static CURLcode nss_cache_crl(SECItem *crl_der)
   return CURLE_OK;
 }
 
-static CURLcode nss_load_crl(const char* crlfilename)
+static CURLcode nss_load_crl(const char *crlfilename)
 {
   PRFileDesc *infile;
   PRFileInfo  info;
@@ -540,7 +540,7 @@ static CURLcode nss_load_crl(const char* crlfilename)
     goto fail;
 
   /* place a trailing zero right after the visible data */
-  body = (char*)filedata.data;
+  body = (char *)filedata.data;
   body[--filedata.len] = '\0';
 
   body = strstr(body, "-----BEGIN");
@@ -585,6 +585,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
   SECStatus status;
   CURLcode result;
   struct ssl_connect_data *ssl = conn->ssl;
+  struct Curl_easy *data = conn->data;
 
   (void)sockindex; /* unused */
 
@@ -602,8 +603,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
   SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
   PK11_IsPresent(slot);
 
-  status = PK11_Authenticate(slot, PR_TRUE,
-                             conn->data->set.str[STRING_KEY_PASSWD]);
+  status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd));
   PK11_FreeSlot(slot);
 
   return (SECSuccess == status) ? CURLE_OK : CURLE_SSL_CERTPROBLEM;
@@ -664,7 +664,7 @@ static CURLcode cert_stuff(struct connectdata *conn, int sockindex,
   return CURLE_OK;
 }
 
-static char * nss_get_password(PK11SlotInfo * slot, PRBool retry, void *arg)
+static char *nss_get_password(PK11SlotInfo *slot, PRBool retry, void *arg)
 {
   (void)slot; /* unused */
 
@@ -682,7 +682,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
   struct connectdata *conn = (struct connectdata *)arg;
 
 #ifdef SSL_ENABLE_OCSP_STAPLING
-  if(conn->data->set.ssl.verifystatus) {
+  if(SSL_CONN_CONFIG(verifystatus)) {
     SECStatus cacheResult;
 
     const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
@@ -708,7 +708,7 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
   }
 #endif
 
-  if(!conn->data->set.ssl.verifypeer) {
+  if(!SSL_CONN_CONFIG(verifypeer)) {
     infof(conn->data, "skipping SSL peer certificate verification\n");
     return SECSuccess;
   }
@@ -734,6 +734,11 @@ static void HandshakeCallback(PRFileDesc *sock, void *arg)
   if(SSL_GetNextProto(sock, &state, buf, &buflen, buflenmax) == SECSuccess) {
 
     switch(state) {
+#if NSSVERNUM >= 0x031a00 /* 3.26.0 */
+    /* used by NSS internally to implement 0-RTT */
+    case SSL_NEXT_PROTO_EARLY_VALUE:
+      /* fall through! */
+#endif
     case SSL_NEXT_PROTO_NO_SUPPORT:
     case SSL_NEXT_PROTO_NO_OVERLAP:
       infof(conn->data, "ALPN/NPN, server did not agree to a protocol\n");
@@ -928,9 +933,12 @@ static SECStatus BadCertHandler(void *arg, PRFileDesc *sock)
   CERTCertificate *cert;
 
   /* remember the cert verification result */
-  data->set.ssl.certverifyresult = err;
+  if(SSL_IS_PROXY())
+    data->set.proxy_ssl.certverifyresult = err;
+  else
+    data->set.ssl.certverifyresult = err;
 
-  if(err == SSL_ERROR_BAD_CERT_DOMAIN && !data->set.ssl.verifyhost)
+  if(err == SSL_ERROR_BAD_CERT_DOMAIN && !SSL_CONN_CONFIG(verifyhost))
     /* we are asked not to verify the host name */
     return SECSuccess;
 
@@ -1367,36 +1375,55 @@ Curl_nss_check_cxn(struct connectdata *conn)
   return -1;  /* connection status unknown */
 }
 
+static void nss_close(struct ssl_connect_data *connssl)
+{
+  /* before the cleanup, check whether we are using a client certificate */
+  const bool client_cert = (connssl->client_nickname != NULL)
+    || (connssl->obj_clicert != NULL);
+
+  free(connssl->client_nickname);
+  connssl->client_nickname = NULL;
+
+  /* destroy all NSS objects in order to avoid failure of NSS shutdown */
+  Curl_llist_destroy(connssl->obj_list, NULL);
+  connssl->obj_list = NULL;
+  connssl->obj_clicert = NULL;
+
+  if(connssl->handle) {
+    if(client_cert)
+      /* A server might require different authentication based on the
+       * particular path being requested by the client.  To support this
+       * scenario, we must ensure that a connection will never reuse the
+       * authentication data from a previous connection. */
+      SSL_InvalidateSession(connssl->handle);
+
+    PR_Close(connssl->handle);
+    connssl->handle = NULL;
+  }
+}
+
 /*
  * This function is called when an SSL connection is closed.
  */
 void Curl_nss_close(struct connectdata *conn, int sockindex)
 {
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
 
-  if(connssl->handle) {
+  if(connssl->handle || connssl_proxy->handle) {
     /* NSS closes the socket we previously handed to it, so we must mark it
        as closed to avoid double close */
     fake_sclose(conn->sock[sockindex]);
     conn->sock[sockindex] = CURL_SOCKET_BAD;
+  }
 
-    if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL))
-      /* A server might require different authentication based on the
-       * particular path being requested by the client.  To support this
-       * scenario, we must ensure that a connection will never reuse the
-       * authentication data from a previous connection. */
-      SSL_InvalidateSession(connssl->handle);
-
-    free(connssl->client_nickname);
-    connssl->client_nickname = NULL;
-    /* destroy all NSS objects in order to avoid failure of NSS shutdown */
-    Curl_llist_destroy(connssl->obj_list, NULL);
-    connssl->obj_list = NULL;
-    connssl->obj_clicert = NULL;
+  if(connssl->handle)
+    /* nss_close(connssl) will transitively close also connssl_proxy->handle
+       if both are used. Clear it to avoid a double close leading to crash. */
+    connssl_proxy->handle = NULL;
 
-    PR_Close(connssl->handle);
-    connssl->handle = NULL;
-  }
+  nss_close(connssl);
+  nss_close(connssl_proxy);
 }
 
 /* return true if NSS can provide error code (and possibly msg) for the
@@ -1437,8 +1464,8 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
                                          int sockindex)
 {
   struct Curl_easy *data = conn->data;
-  const char *cafile = data->set.ssl.CAfile;
-  const char *capath = data->set.ssl.CApath;
+  const char *cafile = SSL_CONN_CONFIG(CAfile);
+  const char *capath = SSL_CONN_CONFIG(CApath);
 
   if(cafile) {
     CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
@@ -1486,13 +1513,22 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
 }
 
 static CURLcode nss_init_sslver(SSLVersionRange *sslver,
-                                struct Curl_easy *data)
+                                struct Curl_easy *data,
+                                struct connectdata *conn)
 {
-  switch(data->set.ssl.version) {
-  default:
+  switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_DEFAULT:
+    /* map CURL_SSLVERSION_DEFAULT to NSS default */
+    if(SSL_VersionRangeGetDefault(ssl_variant_stream, sslver) != SECSuccess)
+      return CURLE_SSL_CONNECT_ERROR;
+    /* ... but make sure we use at least TLSv1.0 according to libcurl API */
+    if(sslver->min < SSL_LIBRARY_VERSION_TLS_1_0)
+      sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+    return CURLE_OK;
+
   case CURL_SSLVERSION_TLSv1:
     sslver->min = SSL_LIBRARY_VERSION_TLS_1_0;
+    /* TODO: set sslver->max to SSL_LIBRARY_VERSION_TLS_1_3 once stable */
 #ifdef SSL_LIBRARY_VERSION_TLS_1_2
     sslver->max = SSL_LIBRARY_VERSION_TLS_1_2;
 #elif defined SSL_LIBRARY_VERSION_TLS_1_1
@@ -1532,6 +1568,18 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver,
     return CURLE_OK;
 #endif
     break;
+
+  case CURL_SSLVERSION_TLSv1_3:
+#ifdef SSL_LIBRARY_VERSION_TLS_1_3
+    sslver->min = SSL_LIBRARY_VERSION_TLS_1_3;
+    sslver->max = SSL_LIBRARY_VERSION_TLS_1_3;
+    return CURLE_OK;
+#endif
+    break;
+
+  default:
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+    return CURLE_SSL_CONNECT_ERROR;
   }
 
   failf(data, "TLS minor version cannot be set");
@@ -1589,6 +1637,7 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
   curl_socket_t sockfd = conn->sock[sockindex];
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   CURLcode result;
+  bool second_layer = FALSE;
 
   SSLVersionRange sslver = {
     SSL_LIBRARY_VERSION_TLS_1_0,  /* min */
@@ -1647,18 +1696,18 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     goto error;
 
   /* do not use SSL cache if disabled or we are not going to verify peer */
-  ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ?
-    PR_FALSE : PR_TRUE;
+  ssl_no_cache = (data->set.general_ssl.sessionid
+                  && SSL_CONN_CONFIG(verifypeer)) ? PR_FALSE : PR_TRUE;
   if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
     goto error;
 
   /* enable/disable the requested SSL version(s) */
-  if(nss_init_sslver(&sslver, data) != CURLE_OK)
+  if(nss_init_sslver(&sslver, data, conn) != CURLE_OK)
     goto error;
   if(SSL_VersionRangeSet(model, &sslver) != SECSuccess)
     goto error;
 
-  ssl_cbc_random_iv = !data->set.ssl_enable_beast;
+  ssl_cbc_random_iv = !SSL_SET_OPTION(enable_beast);
 #ifdef SSL_CBC_RANDOM_IV
   /* unless the user explicitly asks to allow the protocol vulnerability, we
      use the work-around */
@@ -1670,14 +1719,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n");
 #endif
 
-  if(data->set.ssl.cipher_list) {
-    if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) {
+  if(SSL_CONN_CONFIG(cipher_list)) {
+    if(set_ciphers(data, model, SSL_CONN_CONFIG(cipher_list)) != SECSuccess) {
       result = CURLE_SSL_CIPHER;
       goto error;
     }
   }
 
-  if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost)
+  if(!SSL_CONN_CONFIG(verifypeer) && SSL_CONN_CONFIG(verifyhost))
     infof(data, "warning: ignoring value of ssl.verifyhost\n");
 
   /* bypass the default SSL_AuthCertificate() hook in case we do not want to
@@ -1685,14 +1734,19 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
   if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
     goto error;
 
-  data->set.ssl.certverifyresult=0; /* not checked yet */
+  /* not checked yet */
+  if(SSL_IS_PROXY())
+    data->set.proxy_ssl.certverifyresult = 0;
+  else
+    data->set.ssl.certverifyresult = 0;
+
   if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
     goto error;
 
   if(SSL_HandshakeCallback(model, HandshakeCallback, conn) != SECSuccess)
     goto error;
 
-  if(data->set.ssl.verifypeer) {
+  if(SSL_CONN_CONFIG(verifypeer)) {
     const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
     if(rv) {
       result = rv;
@@ -1700,24 +1754,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     }
   }
 
-  if(data->set.ssl.CRLfile) {
-    const CURLcode rv = nss_load_crl(data->set.ssl.CRLfile);
+  if(SSL_SET_OPTION(CRLfile)) {
+    const CURLcode rv = nss_load_crl(SSL_SET_OPTION(CRLfile));
     if(rv) {
       result = rv;
       goto error;
     }
-    infof(data, "  CRLfile: %s\n", data->set.ssl.CRLfile);
+    infof(data, "  CRLfile: %s\n", SSL_SET_OPTION(CRLfile));
   }
 
-  if(data->set.str[STRING_CERT]) {
-    char *nickname = dup_nickname(data, STRING_CERT);
+  if(SSL_SET_OPTION(cert)) {
+    char *nickname = dup_nickname(data, SSL_SET_OPTION(cert));
     if(nickname) {
       /* we are not going to use libnsspem.so to read the client cert */
       connssl->obj_clicert = NULL;
     }
     else {
-      CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
-                               data->set.str[STRING_KEY]);
+      CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert),
+                               SSL_SET_OPTION(key));
       if(rv) {
         /* failf() is already done in cert_stuff() */
         result = rv;
@@ -1737,15 +1791,24 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     goto error;
   }
 
-  /* wrap OS file descriptor by NSPR's file descriptor abstraction */
-  nspr_io = PR_ImportTCPSocket(sockfd);
-  if(!nspr_io)
-    goto error;
+  if(conn->proxy_ssl[sockindex].use) {
+    DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
+    DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
+    nspr_io = conn->proxy_ssl[sockindex].handle;
+    second_layer = TRUE;
+  }
+  else {
+    /* wrap OS file descriptor by NSPR's file descriptor abstraction */
+    nspr_io = PR_ImportTCPSocket(sockfd);
+    if(!nspr_io)
+      goto error;
+  }
 
   /* create our own NSPR I/O layer */
   nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods);
   if(!nspr_io_stub) {
-    PR_Close(nspr_io);
+    if(!second_layer)
+      PR_Close(nspr_io);
     goto error;
   }
 
@@ -1754,7 +1817,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
 
   /* push our new layer to the NSPR I/O stack */
   if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) {
-    PR_Close(nspr_io);
+    if(!second_layer)
+      PR_Close(nspr_io);
     PR_Close(nspr_io_stub);
     goto error;
   }
@@ -1762,7 +1826,8 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
   /* import our model socket onto the current I/O stack */
   connssl->handle = SSL_ImportFD(model, nspr_io);
   if(!connssl->handle) {
-    PR_Close(nspr_io);
+    if(!second_layer)
+      PR_Close(nspr_io);
     goto error;
   }
 
@@ -1770,12 +1835,12 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
   model = NULL;
 
   /* This is the password associated with the cert that we're using */
-  if(data->set.str[STRING_KEY_PASSWD]) {
-    SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
+  if(SSL_SET_OPTION(key_passwd)) {
+    SSL_SetPKCS11PinArg(connssl->handle, SSL_SET_OPTION(key_passwd));
   }
 
 #ifdef SSL_ENABLE_OCSP_STAPLING
-  if(data->set.ssl.verifystatus) {
+  if(SSL_CONN_CONFIG(verifystatus)) {
     if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
         != SECSuccess)
       goto error;
@@ -1835,11 +1900,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     goto error;
 
   /* propagate hostname to the TLS layer */
-  if(SSL_SetURL(connssl->handle, conn->host.name) != SECSuccess)
+  if(SSL_SetURL(connssl->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name :
+                conn->host.name) != SECSuccess)
     goto error;
 
   /* prevent NSS from re-using the session for a different hostname */
-  if(SSL_SetSockPeerID(connssl->handle, conn->host.name) != SECSuccess)
+  if(SSL_SetSockPeerID(connssl->handle, SSL_IS_PROXY() ?
+                       conn->http_proxy.host.name : conn->host.name)
+     != SECSuccess)
     goto error;
 
   return CURLE_OK;
@@ -1857,6 +1925,12 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
   struct Curl_easy *data = conn->data;
   CURLcode result = CURLE_SSL_CONNECT_ERROR;
   PRUint32 timeout;
+  long * const certverifyresult = SSL_IS_PROXY() ?
+    &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
+  const char * const pinnedpubkey = SSL_IS_PROXY() ?
+              data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+              data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+
 
   /* check timeout situation */
   const long time_left = Curl_timeleft(data, NULL, TRUE);
@@ -1872,9 +1946,9 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
     if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
       /* blocking direction is updated by nss_update_connecting_state() */
       return CURLE_AGAIN;
-    else if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
+    else if(*certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
       result = CURLE_PEER_FAILED_VERIFICATION;
-    else if(conn->data->set.ssl.certverifyresult!=0)
+    else if(*certverifyresult != 0)
       result = CURLE_SSL_CACERT;
     goto error;
   }
@@ -1883,11 +1957,11 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
   if(result)
     goto error;
 
-  if(data->set.str[STRING_SSL_ISSUERCERT]) {
+  if(SSL_SET_OPTION(issuercert)) {
     SECStatus ret = SECFailure;
-    char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT);
+    char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert));
     if(nickname) {
-      /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */
+      /* we support only nicknames in case of issuercert for now */
       ret = check_issuer_cert(connssl->handle, nickname);
       free(nickname);
     }
@@ -1902,7 +1976,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex)
     }
   }
 
-  result = cmp_peer_pubkey(connssl, data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
+  result = cmp_peer_pubkey(connssl, pinnedpubkey);
   if(result)
     /* status already printed */
     goto error;
@@ -2112,7 +2186,8 @@ bool Curl_nss_cert_status_request(void)
 #endif
 }
 
-bool Curl_nss_false_start(void) {
+bool Curl_nss_false_start(void)
+{
 #if NSSVERNUM >= 0x030f04 /* 3.15.4 */
   return TRUE;
 #else
diff --git a/lib/vtls/nssg.h b/lib/vtls/nssg.h
index ac67e6a..fd94003 100644
--- a/lib/vtls/nssg.h
+++ b/lib/vtls/nssg.h
@@ -65,6 +65,9 @@ bool Curl_nss_cert_status_request(void);
 
 bool Curl_nss_false_start(void);
 
+/* Support HTTPS-proxy */
+#define HTTPS_PROXY_SUPPORT 1
+
 /* Set the API backend definition to NSS */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_NSS
 
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index c040928..d92e713 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -176,39 +176,34 @@ static int passwd_callback(char *buf, int num, int encrypting,
 }
 
 /*
- * rand_enough() is a function that returns TRUE if we have seeded the random
- * engine properly. We use some preprocessor magic to provide a seed_enough()
- * macro to use, just to prevent a compiler warning on this function if we
- * pass in an argument that is never used.
+ * rand_enough() returns TRUE if we have seeded the random engine properly.
  */
-
-#ifdef HAVE_RAND_STATUS
-#define seed_enough(x) rand_enough()
 static bool rand_enough(void)
 {
   return (0 != RAND_status()) ? TRUE : FALSE;
 }
-#else
-#define seed_enough(x) rand_enough(x)
-static bool rand_enough(int nread)
-{
-  /* this is a very silly decision to make */
-  return (nread > 500) ? TRUE : FALSE;
-}
-#endif
 
-static int ossl_seed(struct Curl_easy *data)
+static CURLcode Curl_ossl_seed(struct Curl_easy *data)
 {
+  /* we have the "SSL is seeded" boolean static to prevent multiple
+     time-consuming seedings in vain */
+  static bool ssl_seeded = FALSE;
   char *buf = data->state.buffer; /* point to the big buffer */
   int nread=0;
 
-  /* Q: should we add support for a random file name as a libcurl option?
-     A: Yes, it is here */
+  if(ssl_seeded)
+    return CURLE_OK;
+
+  if(rand_enough()) {
+    /* OpenSSL 1.1.0+ will return here */
+    ssl_seeded = TRUE;
+    return CURLE_OK;
+  }
 
 #ifndef RANDOM_FILE
   /* if RANDOM_FILE isn't defined, we only perform this if an option tells
      us to! */
-  if(data->set.ssl.random_file)
+  if(data->set.str[STRING_SSL_RANDOM_FILE])
 #define RANDOM_FILE "" /* doesn't matter won't be used */
 #endif
   {
@@ -217,7 +212,7 @@ static int ossl_seed(struct Curl_easy *data)
                              data->set.str[STRING_SSL_RANDOM_FILE]:
                              RANDOM_FILE),
                             RAND_LOAD_LENGTH);
-    if(seed_enough(nread))
+    if(rand_enough())
       return nread;
   }
 
@@ -237,7 +232,7 @@ static int ossl_seed(struct Curl_easy *data)
                        data->set.str[STRING_SSL_EGDSOCKET]:EGD_SOCKET);
     if(-1 != ret) {
       nread += ret;
-      if(seed_enough(nread))
+      if(rand_enough())
         return nread;
     }
   }
@@ -248,9 +243,10 @@ static int ossl_seed(struct Curl_easy *data)
   do {
     unsigned char randb[64];
     int len = sizeof(randb);
-    RAND_bytes(randb, len);
+    if(!RAND_bytes(randb, len))
+      break;
     RAND_add(randb, len, (len >> 1));
-  } while(!RAND_status());
+  } while(!rand_enough());
 
   /* generates a default path for the random seed file */
   buf[0]=0; /* blank it first */
@@ -258,25 +254,12 @@ static int ossl_seed(struct Curl_easy *data)
   if(buf[0]) {
     /* we got a file name to try */
     nread += RAND_load_file(buf, RAND_LOAD_LENGTH);
-    if(seed_enough(nread))
+    if(rand_enough())
       return nread;
   }
 
   infof(data, "libcurl is now using a weak random seed!\n");
-  return nread;
-}
-
-static void Curl_ossl_seed(struct Curl_easy *data)
-{
-  /* we have the "SSL is seeded" boolean static to prevent multiple
-     time-consuming seedings in vain */
-  static bool ssl_seeded = FALSE;
-
-  if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
-     data->set.str[STRING_SSL_EGDSOCKET]) {
-    ossl_seed(data);
-    ssl_seeded = TRUE;
-  }
+  return CURLE_SSL_CONNECT_ERROR; /* confusing error code */
 }
 
 #ifndef SSL_FILETYPE_ENGINE
@@ -312,7 +295,7 @@ static int ssl_ui_reader(UI *ui, UI_STRING *uis)
   switch(UI_get_string_type(uis)) {
   case UIT_PROMPT:
   case UIT_VERIFY:
-    password = (const char*)UI_get0_user_data(ui);
+    password = (const char *)UI_get0_user_data(ui);
     if(password && (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) {
       UI_set_result(ui, uis, password);
       return 1;
@@ -348,7 +331,8 @@ int cert_stuff(struct connectdata *conn,
                char *cert_file,
                const char *cert_type,
                char *key_file,
-               const char *key_type)
+               const char *key_type,
+               char *key_passwd)
 {
   struct Curl_easy *data = conn->data;
 
@@ -359,10 +343,9 @@ int cert_stuff(struct connectdata *conn,
     X509 *x509;
     int cert_done = 0;
 
-    if(data->set.str[STRING_KEY_PASSWD]) {
+    if(key_passwd) {
       /* set the password in the callback userdata */
-      SSL_CTX_set_default_passwd_cb_userdata(ctx,
-                                             data->set.str[STRING_KEY_PASSWD]);
+      SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd);
       /* Set passwd callback: */
       SSL_CTX_set_default_passwd_cb(ctx, passwd_callback);
     }
@@ -473,7 +456,7 @@ int cert_stuff(struct connectdata *conn,
 
       PKCS12_PBE_add();
 
-      if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509,
+      if(!PKCS12_parse(p12, key_passwd, &pri, &x509,
                        &ca)) {
         failf(data,
               "could not parse PKCS12 file, check password, " OSSL_PACKAGE
@@ -571,7 +554,7 @@ int cert_stuff(struct connectdata *conn,
         EVP_PKEY *priv_key = NULL;
         if(data->state.engine) {
           UI_METHOD *ui_method =
-            UI_create_method((char *)"cURL user interface");
+            UI_create_method((char *)"curl user interface");
           if(!ui_method) {
             failf(data, "unable do create " OSSL_PACKAGE
                   " user-interface method");
@@ -585,7 +568,7 @@ int cert_stuff(struct connectdata *conn,
           priv_key = (EVP_PKEY *)
             ENGINE_load_private_key(data->state.engine, key_file,
                                     ui_method,
-                                    data->set.str[STRING_KEY_PASSWD]);
+                                    key_passwd);
           UI_destroy_method(ui_method);
           if(!priv_key) {
             failf(data, "failed to load private key from crypto engine");
@@ -916,27 +899,31 @@ struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
 }
 
 
-/*
- * This function is called when an SSL connection is closed.
- */
-void Curl_ossl_close(struct connectdata *conn, int sockindex)
+static void ossl_close(struct ssl_connect_data *connssl)
 {
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-
   if(connssl->handle) {
     (void)SSL_shutdown(connssl->handle);
     SSL_set_connect_state(connssl->handle);
 
-    SSL_free (connssl->handle);
+    SSL_free(connssl->handle);
     connssl->handle = NULL;
   }
   if(connssl->ctx) {
-    SSL_CTX_free (connssl->ctx);
+    SSL_CTX_free(connssl->ctx);
     connssl->ctx = NULL;
   }
 }
 
 /*
+ * This function is called when an SSL connection is closed.
+ */
+void Curl_ossl_close(struct connectdata *conn, int sockindex)
+{
+  ossl_close(&conn->ssl[sockindex]);
+  ossl_close(&conn->proxy_ssl[sockindex]);
+}
+
+/*
  * This function is called to shut down the SSL layer but keep the
  * socket open (CCC - Clear Command Channel)
  */
@@ -1031,7 +1018,7 @@ int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
 #endif
     }
 
-    SSL_free (connssl->handle);
+    SSL_free(connssl->handle);
     connssl->handle = NULL;
   }
   return retval;
@@ -1107,16 +1094,20 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
   CURLcode result = CURLE_OK;
   bool dNSName = FALSE; /* if a dNSName field exists in the cert */
   bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const char * const dispname = SSL_IS_PROXY() ?
+    conn->http_proxy.host.dispname : conn->host.dispname;
 
 #ifdef ENABLE_IPV6
   if(conn->bits.ipv6_ip &&
-     Curl_inet_pton(AF_INET6, conn->host.name, &addr)) {
+     Curl_inet_pton(AF_INET6, hostname, &addr)) {
     target = GEN_IPADD;
     addrlen = sizeof(struct in6_addr);
   }
   else
 #endif
-    if(Curl_inet_pton(AF_INET, conn->host.name, &addr)) {
+    if(Curl_inet_pton(AF_INET, hostname, &addr)) {
       target = GEN_IPADD;
       addrlen = sizeof(struct in_addr);
     }
@@ -1165,11 +1156,11 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
           if((altlen == strlen(altptr)) &&
              /* if this isn't true, there was an embedded zero in the name
                 string and we cannot match it. */
-             Curl_cert_hostcheck(altptr, conn->host.name)) {
+             Curl_cert_hostcheck(altptr, hostname)) {
             dnsmatched = TRUE;
             infof(data,
                   " subjectAltName: host \"%s\" matched cert's \"%s\"\n",
-                  conn->host.dispname, altptr);
+                  dispname, altptr);
           }
           break;
 
@@ -1180,7 +1171,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
             ipmatched = TRUE;
             infof(data,
                   " subjectAltName: host \"%s\" matched cert's IP address!\n",
-                  conn->host.dispname);
+                  dispname);
           }
           break;
         }
@@ -1196,9 +1187,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
     /* an alternative name matched */
     ;
   else if(dNSName || iPAddress) {
-    infof(data, " subjectAltName does not match %s\n", conn->host.dispname);
+    infof(data, " subjectAltName does not match %s\n", dispname);
     failf(data, "SSL: no alternative certificate subject name matches "
-          "target host name '%s'", conn->host.dispname);
+          "target host name '%s'", dispname);
     result = CURLE_PEER_FAILED_VERIFICATION;
   }
   else {
@@ -1272,9 +1263,9 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
             "SSL: unable to obtain common name from peer certificate");
       result = CURLE_PEER_FAILED_VERIFICATION;
     }
-    else if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
+    else if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
       failf(data, "SSL: certificate subject name '%s' does not match "
-            "target host name '%s'", peer_CN, conn->host.dispname);
+            "target host name '%s'", peer_CN, dispname);
       result = CURLE_PEER_FAILED_VERIFICATION;
     }
     else {
@@ -1425,7 +1416,7 @@ static const char *ssl_msg_type(int ssl_ver, int msg)
 {
 #ifdef SSL2_VERSION_MAJOR
   if(ssl_ver == SSL2_VERSION_MAJOR) {
-    switch (msg) {
+    switch(msg) {
       case SSL2_MT_ERROR:
         return "Error";
       case SSL2_MT_CLIENT_HELLO:
@@ -1449,7 +1440,7 @@ static const char *ssl_msg_type(int ssl_ver, int msg)
   else
 #endif
   if(ssl_ver == SSL3_VERSION_MAJOR) {
-    switch (msg) {
+    switch(msg) {
       case SSL3_MT_HELLO_REQUEST:
         return "Hello request";
       case SSL3_MT_CLIENT_HELLO:
@@ -1549,6 +1540,11 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
     verstr = "TLSv1.2";
     break;
 #endif
+#ifdef TLS1_3_VERSION
+  case TLS1_3_VERSION:
+    verstr = "TLSv1.3";
+    break;
+#endif
   case 0:
     break;
   default:
@@ -1571,7 +1567,7 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
     else
       tls_rt_name = "";
 
-    msg_type = *(char*)buf;
+    msg_type = *(char *)buf;
     msg_name = ssl_msg_type(ssl_ver, msg_type);
 
     txt_len = snprintf(ssl_buf, sizeof(ssl_buf), "%s (%s), %s, %s (%d):\n",
@@ -1677,6 +1673,10 @@ get_ssl_version_txt(SSL *ssl)
     return "";
 
   switch(SSL_version(ssl)) {
+#ifdef TLS1_3_VERSION
+  case TLS1_3_VERSION:
+    return "TLSv1.3";
+#endif
 #if OPENSSL_VERSION_NUMBER >= 0x1000100FL
   case TLS1_2_VERSION:
     return "TLSv1.2";
@@ -1711,23 +1711,39 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
   struct in_addr addr;
 #endif
 #endif
+  long * const certverifyresult = SSL_IS_PROXY() ?
+    &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
+  const long int ssl_version = SSL_CONN_CONFIG(version);
+#ifdef USE_TLS_SRP
+  const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype);
+#endif
+  char * const ssl_cert = SSL_SET_OPTION(cert);
+  const char * const ssl_cert_type = SSL_SET_OPTION(cert_type);
+  const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+  const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
+  const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
+  const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 
   DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
 
   /* Make funny stuff to get random input */
-  Curl_ossl_seed(data);
+  result = Curl_ossl_seed(data);
+  if(result)
+    return result;
 
-  data->set.ssl.certverifyresult = !X509_V_OK;
+  *certverifyresult = !X509_V_OK;
 
   /* check to see if we've been told to use an explicit SSL/TLS version */
 
-  switch(data->set.ssl.version) {
-  default:
+  switch(ssl_version) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
   case CURL_SSLVERSION_TLSv1_0:
   case CURL_SSLVERSION_TLSv1_1:
   case CURL_SSLVERSION_TLSv1_2:
+  case CURL_SSLVERSION_TLSv1_3:
     /* it will be handled later with the context options */
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
     !defined(LIBRESSL_VERSION_NUMBER)
@@ -1743,7 +1759,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
     return CURLE_NOT_BUILT_IN;
 #else
 #ifdef USE_TLS_SRP
-    if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
+    if(ssl_authtype == CURL_TLSAUTH_SRP)
       return CURLE_SSL_CONNECT_ERROR;
 #endif
     req_method = SSLv2_client_method();
@@ -1756,13 +1772,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
     return CURLE_NOT_BUILT_IN;
 #else
 #ifdef USE_TLS_SRP
-    if(data->set.ssl.authtype == CURL_TLSAUTH_SRP)
+    if(ssl_authtype == CURL_TLSAUTH_SRP)
       return CURLE_SSL_CONNECT_ERROR;
 #endif
     req_method = SSLv3_client_method();
     use_sni(FALSE);
     break;
 #endif
+  default:
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+    return CURLE_SSL_CONNECT_ERROR;
   }
 
   if(connssl->ctx)
@@ -1841,14 +1860,14 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
   /* unless the user explicitly ask to allow the protocol vulnerability we
      use the work-around */
-  if(!conn->data->set.ssl_enable_beast)
+  if(!SSL_SET_OPTION(enable_beast))
     ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
 #endif
 
-  switch(data->set.ssl.version) {
+  switch(ssl_version) {
   case CURL_SSLVERSION_SSLv3:
 #ifdef USE_TLS_SRP
-    if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
+    if(ssl_authtype == CURL_TLSAUTH_SRP) {
       infof(data, "Set version TLSv1.x for SRP authorisation\n");
     }
 #endif
@@ -1857,6 +1876,9 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 #if OPENSSL_VERSION_NUMBER >= 0x1000100FL
     ctx_options |= SSL_OP_NO_TLSv1_1;
     ctx_options |= SSL_OP_NO_TLSv1_2;
+#ifdef TLS1_3_VERSION
+    ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
 #endif
     break;
 
@@ -1872,38 +1894,75 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 #if OPENSSL_VERSION_NUMBER >= 0x1000100FL
     ctx_options |= SSL_OP_NO_TLSv1_1;
     ctx_options |= SSL_OP_NO_TLSv1_2;
+#ifdef TLS1_3_VERSION
+    ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
 #endif
     break;
 
-#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
   case CURL_SSLVERSION_TLSv1_1:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
     ctx_options |= SSL_OP_NO_SSLv2;
     ctx_options |= SSL_OP_NO_SSLv3;
     ctx_options |= SSL_OP_NO_TLSv1;
     ctx_options |= SSL_OP_NO_TLSv1_2;
+#ifdef TLS1_3_VERSION
+    ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
     break;
+#else
+    failf(data, OSSL_PACKAGE " was built without TLS 1.1 support");
+    return CURLE_NOT_BUILT_IN;
+#endif
 
   case CURL_SSLVERSION_TLSv1_2:
+#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
     ctx_options |= SSL_OP_NO_SSLv2;
     ctx_options |= SSL_OP_NO_SSLv3;
     ctx_options |= SSL_OP_NO_TLSv1;
     ctx_options |= SSL_OP_NO_TLSv1_1;
+#ifdef TLS1_3_VERSION
+    ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
     break;
+#else
+    failf(data, OSSL_PACKAGE " was built without TLS 1.2 support");
+    return CURLE_NOT_BUILT_IN;
+#endif
+
+  case CURL_SSLVERSION_TLSv1_3:
+#ifdef TLS1_3_VERSION
+    SSL_CTX_set_max_proto_version(connssl->ctx, TLS1_3_VERSION);
+    ctx_options |= SSL_OP_NO_SSLv2;
+    ctx_options |= SSL_OP_NO_SSLv3;
+    ctx_options |= SSL_OP_NO_TLSv1;
+    ctx_options |= SSL_OP_NO_TLSv1_1;
+    ctx_options |= SSL_OP_NO_TLSv1_2;
+    break;
+#else
+    failf(data, OSSL_PACKAGE " was built without TLS 1.3 support");
+    return CURLE_NOT_BUILT_IN;
 #endif
 
-#ifndef OPENSSL_NO_SSL2
   case CURL_SSLVERSION_SSLv2:
+#ifndef OPENSSL_NO_SSL2
     ctx_options |= SSL_OP_NO_SSLv3;
     ctx_options |= SSL_OP_NO_TLSv1;
 #if OPENSSL_VERSION_NUMBER >= 0x1000100FL
     ctx_options |= SSL_OP_NO_TLSv1_1;
     ctx_options |= SSL_OP_NO_TLSv1_2;
+#ifdef TLS1_3_VERSION
+    ctx_options |= SSL_OP_NO_TLSv1_3;
+#endif
 #endif
     break;
+#else
+    failf(data, OSSL_PACKAGE " was built without SSLv2 support");
+    return CURLE_NOT_BUILT_IN;
 #endif
 
   default:
-    failf(data, "Unsupported SSL protocol version");
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
     return CURLE_SSL_CONNECT_ERROR;
   }
 
@@ -1942,19 +2001,16 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
   }
 #endif
 
-  if(data->set.str[STRING_CERT] || data->set.str[STRING_CERT_TYPE]) {
-    if(!cert_stuff(conn,
-                   connssl->ctx,
-                   data->set.str[STRING_CERT],
-                   data->set.str[STRING_CERT_TYPE],
-                   data->set.str[STRING_KEY],
-                   data->set.str[STRING_KEY_TYPE])) {
+  if(ssl_cert || ssl_cert_type) {
+    if(!cert_stuff(conn, connssl->ctx, ssl_cert, ssl_cert_type,
+                   SSL_SET_OPTION(key), SSL_SET_OPTION(key_type),
+                   SSL_SET_OPTION(key_passwd))) {
       /* failf() is already done in cert_stuff() */
       return CURLE_SSL_CERTPROBLEM;
     }
   }
 
-  ciphers = data->set.str[STRING_SSL_CIPHER_LIST];
+  ciphers = SSL_CONN_CONFIG(cipher_list);
   if(!ciphers)
     ciphers = (char *)DEFAULT_CIPHER_SELECTION;
   if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) {
@@ -1964,18 +2020,20 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
   infof(data, "Cipher selection: %s\n", ciphers);
 
 #ifdef USE_TLS_SRP
-  if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
-    infof(data, "Using TLS-SRP username: %s\n", data->set.ssl.username);
+  if(ssl_authtype == CURL_TLSAUTH_SRP) {
+    char * const ssl_username = SSL_SET_OPTION(username);
+
+    infof(data, "Using TLS-SRP username: %s\n", ssl_username);
 
-    if(!SSL_CTX_set_srp_username(connssl->ctx, data->set.ssl.username)) {
+    if(!SSL_CTX_set_srp_username(connssl->ctx, ssl_username)) {
       failf(data, "Unable to set SRP user name");
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
-    if(!SSL_CTX_set_srp_password(connssl->ctx, data->set.ssl.password)) {
+    if(!SSL_CTX_set_srp_password(connssl->ctx, SSL_SET_OPTION(password))) {
       failf(data, "failed setting SRP password");
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
-    if(!data->set.str[STRING_SSL_CIPHER_LIST]) {
+    if(!SSL_CONN_CONFIG(cipher_list)) {
       infof(data, "Setting cipher list SRP\n");
 
       if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) {
@@ -1985,20 +2043,17 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
     }
   }
 #endif
-  if(data->set.str[STRING_SSL_CAFILE] || data->set.str[STRING_SSL_CAPATH]) {
+
+  if(ssl_cafile || ssl_capath) {
     /* tell SSL where to find CA certificates that are used to verify
        the servers certificate. */
-    if(!SSL_CTX_load_verify_locations(connssl->ctx,
-                                       data->set.str[STRING_SSL_CAFILE],
-                                       data->set.str[STRING_SSL_CAPATH])) {
-      if(data->set.ssl.verifypeer) {
+    if(!SSL_CTX_load_verify_locations(connssl->ctx, ssl_cafile, ssl_capath)) {
+      if(verifypeer) {
         /* Fail if we insist on successfully verifying the server. */
         failf(data, "error setting certificate verify locations:\n"
               "  CAfile: %s\n  CApath: %s",
-              data->set.str[STRING_SSL_CAFILE]?
-              data->set.str[STRING_SSL_CAFILE]: "none",
-              data->set.str[STRING_SSL_CAPATH]?
-              data->set.str[STRING_SSL_CAPATH] : "none");
+              ssl_cafile ? ssl_cafile : "none",
+              ssl_capath ? ssl_capath : "none");
         return CURLE_SSL_CACERT_BADFILE;
       }
       else {
@@ -2015,29 +2070,25 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
     infof(data,
           "  CAfile: %s\n"
           "  CApath: %s\n",
-          data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
-          "none",
-          data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
-          "none");
+          ssl_cafile ? ssl_cafile : "none",
+          ssl_capath ? ssl_capath : "none");
   }
 #ifdef CURL_CA_FALLBACK
-  else if(data->set.ssl.verifypeer) {
+  else if(verifypeer) {
     /* verfying the peer without any CA certificates won't
        work so use openssl's built in default as fallback */
     SSL_CTX_set_default_verify_paths(connssl->ctx);
   }
 #endif
 
-  if(data->set.str[STRING_SSL_CRLFILE]) {
+  if(ssl_crlfile) {
     /* tell SSL where to find CRL file that is used to check certificate
      * revocation */
     lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx),
                                  X509_LOOKUP_file());
     if(!lookup ||
-       (!X509_load_crl_file(lookup, data->set.str[STRING_SSL_CRLFILE],
-                            X509_FILETYPE_PEM)) ) {
-      failf(data, "error loading CRL file: %s",
-            data->set.str[STRING_SSL_CRLFILE]);
+       (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
+      failf(data, "error loading CRL file: %s", ssl_crlfile);
       return CURLE_SSL_CRL_BADFILE;
     }
     else {
@@ -2046,9 +2097,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
       X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
                            X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
     }
-    infof(data,
-          "  CRLfile: %s\n", data->set.str[STRING_SSL_CRLFILE] ?
-          data->set.str[STRING_SSL_CRLFILE]: "none");
+    infof(data, "  CRLfile: %s\n", ssl_crlfile);
   }
 
   /* Try building a chain using issuers in the trusted store first to avoid
@@ -2059,7 +2108,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
   https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
   */
 #if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS)
-  if(data->set.ssl.verifypeer) {
+  if(verifypeer) {
     X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
                          X509_V_FLAG_TRUSTED_FIRST);
   }
@@ -2070,8 +2119,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
    * anyway. In the latter case the result of the verification is checked with
    * SSL_get_verify_result() below. */
   SSL_CTX_set_verify(connssl->ctx,
-                     data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
-                     NULL);
+                     verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
 
   /* give application a chance to interfere with SSL set up. */
   if(data->set.ssl.fsslctx) {
@@ -2094,31 +2142,30 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 
 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
     !defined(OPENSSL_NO_OCSP)
-  if(data->set.ssl.verifystatus)
+  if(SSL_CONN_CONFIG(verifystatus))
     SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp);
 #endif
 
   SSL_set_connect_state(connssl->handle);
 
   connssl->server_cert = 0x0;
-
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
-  if((0 == Curl_inet_pton(AF_INET, conn->host.name, &addr)) &&
+  if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
 #ifdef ENABLE_IPV6
-     (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
+     (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
 #endif
      sni &&
-     !SSL_set_tlsext_host_name(connssl->handle, conn->host.name))
+     !SSL_set_tlsext_host_name(connssl->handle, hostname))
     infof(data, "WARNING: failed to configure server name indication (SNI) "
           "TLS extension\n");
 #endif
 
   /* Check if there's a cached ID we can/should use here! */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     void *ssl_sessionid = NULL;
 
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
+    if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
       /* we got a session id, use it! */
       if(!SSL_set_session(connssl->handle, ssl_sessionid)) {
         Curl_ssl_sessionid_unlock(conn);
@@ -2127,13 +2174,21 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
         return CURLE_SSL_CONNECT_ERROR;
       }
       /* Informational message */
-      infof (data, "SSL re-using session ID\n");
+      infof(data, "SSL re-using session ID\n");
     }
     Curl_ssl_sessionid_unlock(conn);
   }
 
-  /* pass the raw socket into the SSL layers */
-  if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
+  if(conn->proxy_ssl[sockindex].use) {
+    BIO *const bio = BIO_new(BIO_f_ssl());
+    DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
+    DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
+    DEBUGASSERT(bio != NULL);
+    BIO_set_ssl(bio, conn->proxy_ssl[sockindex].handle, FALSE);
+    SSL_set_bio(connssl->handle, bio, bio);
+  }
+  else if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
+    /* pass the raw socket into the SSL layers */
     failf(data, "SSL: SSL_set_fd failed: %s",
           ERR_error_string(ERR_get_error(), NULL));
     return CURLE_SSL_CONNECT_ERROR;
@@ -2149,9 +2204,11 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
   struct Curl_easy *data = conn->data;
   int err;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  long * const certverifyresult = SSL_IS_PROXY() ?
+    &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
   DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
-             || ssl_connect_2_reading == connssl->connecting_state
-             || ssl_connect_2_writing == connssl->connecting_state);
+              || ssl_connect_2_reading == connssl->connecting_state
+              || ssl_connect_2_writing == connssl->connecting_state);
 
   ERR_clear_error();
 
@@ -2198,7 +2255,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
 
         lerr = SSL_get_verify_result(connssl->handle);
         if(lerr != X509_V_OK) {
-          data->set.ssl.certverifyresult = lerr;
+          *certverifyresult = lerr;
           snprintf(error_buffer, sizeof(error_buffer),
                    "SSL certificate problem: %s",
                    X509_verify_cert_error_string(lerr));
@@ -2220,8 +2277,11 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
        * the SO_ERROR is also lost.
        */
       if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
+        const char * const hostname = SSL_IS_PROXY() ?
+          conn->http_proxy.host.name : conn->host.name;
+        const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
         failf(data, "Unknown SSL protocol error in connection to %s:%ld ",
-              conn->host.name, conn->remote_port);
+              hostname, port);
         return result;
       }
 
@@ -2245,7 +2305,7 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
      * negotiated
      */
     if(conn->bits.tls_enable_alpn) {
-      const unsigned char* neg_protocol;
+      const unsigned char *neg_protocol;
       unsigned int len;
       SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len);
       if(len != 0) {
@@ -2276,7 +2336,8 @@ static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
 {
   int i, ilen;
 
-  if((ilen = (int)len) < 0)
+  ilen = (int)len;
+  if(ilen < 0)
     return 1; /* buffer too big */
 
   i = i2t_ASN1_OBJECT(buf, ilen, a);
@@ -2698,6 +2759,8 @@ static CURLcode servercert(struct connectdata *conn,
   FILE *fp;
   char *buffer = data->state.buffer;
   const char *ptr;
+  long * const certverifyresult = SSL_IS_PROXY() ?
+    &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
   BIO *mem = BIO_new(BIO_s_mem());
 
   if(data->set.ssl.certinfo)
@@ -2713,7 +2776,7 @@ static CURLcode servercert(struct connectdata *conn,
     return CURLE_PEER_FAILED_VERIFICATION;
   }
 
-  infof(data, "Server certificate:\n");
+  infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server");
 
   rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
                          buffer, BUFSIZE);
@@ -2731,7 +2794,7 @@ static CURLcode servercert(struct connectdata *conn,
 
   BIO_free(mem);
 
-  if(data->set.ssl.verifyhost) {
+  if(SSL_CONN_CONFIG(verifyhost)) {
     result = verifyhost(conn, connssl->server_cert);
     if(result) {
       X509_free(connssl->server_cert);
@@ -2754,12 +2817,12 @@ static CURLcode servercert(struct connectdata *conn,
        deallocating the certificate. */
 
     /* e.g. match issuer name with provided issuer certificate */
-    if(data->set.str[STRING_SSL_ISSUERCERT]) {
-      fp = fopen(data->set.str[STRING_SSL_ISSUERCERT], FOPEN_READTEXT);
+    if(SSL_SET_OPTION(issuercert)) {
+      fp = fopen(SSL_SET_OPTION(issuercert), FOPEN_READTEXT);
       if(!fp) {
         if(strict)
           failf(data, "SSL: Unable to open issuer cert (%s)",
-                data->set.str[STRING_SSL_ISSUERCERT]);
+                SSL_SET_OPTION(issuercert));
         X509_free(connssl->server_cert);
         connssl->server_cert = NULL;
         return CURLE_SSL_ISSUER_ERROR;
@@ -2769,7 +2832,7 @@ static CURLcode servercert(struct connectdata *conn,
       if(!issuer) {
         if(strict)
           failf(data, "SSL: Unable to read issuer cert (%s)",
-                data->set.str[STRING_SSL_ISSUERCERT]);
+                SSL_SET_OPTION(issuercert));
         X509_free(connssl->server_cert);
         X509_free(issuer);
         fclose(fp);
@@ -2781,7 +2844,7 @@ static CURLcode servercert(struct connectdata *conn,
       if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) {
         if(strict)
           failf(data, "SSL: Certificate issuer check failed (%s)",
-                data->set.str[STRING_SSL_ISSUERCERT]);
+                SSL_SET_OPTION(issuercert));
         X509_free(connssl->server_cert);
         X509_free(issuer);
         connssl->server_cert = NULL;
@@ -2789,15 +2852,14 @@ static CURLcode servercert(struct connectdata *conn,
       }
 
       infof(data, " SSL certificate issuer check ok (%s)\n",
-            data->set.str[STRING_SSL_ISSUERCERT]);
+            SSL_SET_OPTION(issuercert));
       X509_free(issuer);
     }
 
-    lerr = data->set.ssl.certverifyresult =
-      SSL_get_verify_result(connssl->handle);
+    lerr = *certverifyresult = SSL_get_verify_result(connssl->handle);
 
-    if(data->set.ssl.certverifyresult != X509_V_OK) {
-      if(data->set.ssl.verifypeer) {
+    if(*certverifyresult != X509_V_OK) {
+      if(SSL_CONN_CONFIG(verifypeer)) {
         /* We probably never reach this, because SSL_connect() will fail
            and we return earlier if verifypeer is set? */
         if(strict)
@@ -2816,7 +2878,7 @@ static CURLcode servercert(struct connectdata *conn,
 
 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
     !defined(OPENSSL_NO_OCSP)
-  if(data->set.ssl.verifystatus) {
+  if(SSL_CONN_CONFIG(verifystatus)) {
     result = verifystatus(conn, connssl);
     if(result) {
       X509_free(connssl->server_cert);
@@ -2830,7 +2892,8 @@ static CURLcode servercert(struct connectdata *conn,
     /* when not strict, we don't bother about the verify cert problems */
     result = CURLE_OK;
 
-  ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
+  ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+                         data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
   if(!result && ptr) {
     result = pkp_pin_peer_pubkey(data, connssl->server_cert, ptr);
     if(result)
@@ -2852,7 +2915,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     bool incache;
     SSL_SESSION *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
@@ -2864,7 +2927,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
         regardless of its state. */
 
     Curl_ssl_sessionid_lock(conn);
-    incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
+    incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
+                                      sockindex));
     if(incache) {
       if(old_ssl_sessionid != our_ssl_sessionid) {
         infof(data, "old SSL session ID is stale, removing\n");
@@ -2875,7 +2939,7 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
 
     if(!incache) {
       result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
-                                      0 /* unknown size */);
+                                      0 /* unknown size */, sockindex);
       if(result) {
         Curl_ssl_sessionid_unlock(conn);
         failf(data, "failed to store ssl session");
@@ -2899,8 +2963,8 @@ static CURLcode ossl_connect_step3(struct connectdata *conn, int sockindex)
    * operations.
    */
 
-  result = servercert(conn, connssl,
-                      (data->set.ssl.verifypeer || data->set.ssl.verifyhost));
+  result = servercert(conn, connssl, (SSL_CONN_CONFIG(verifypeer) ||
+                                      SSL_CONN_CONFIG(verifyhost)));
 
   if(!result)
     connssl->connecting_state = ssl_connect_done;
@@ -2920,7 +2984,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   curl_socket_t sockfd = conn->sock[sockindex];
-  long timeout_ms;
+  time_t timeout_ms;
   int what;
 
   /* check if the connection has already been established */
@@ -3048,7 +3112,10 @@ bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex)
 {
   if(conn->ssl[connindex].handle)
     /* SSL is in use */
-    return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
+    return (0 != SSL_pending(conn->ssl[connindex].handle) ||
+           (conn->proxy_ssl[connindex].handle &&
+            0 != SSL_pending(conn->proxy_ssl[connindex].handle))) ?
+           TRUE : FALSE;
   else
     return FALSE;
 }
@@ -3093,8 +3160,18 @@ static ssize_t ossl_send(struct connectdata *conn,
       /*  A failure in the SSL library occurred, usually a protocol error.
           The OpenSSL error queue contains more information on the error. */
       sslerror = ERR_get_error();
-      failf(conn->data, "SSL_write() error: %s",
-            ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
+      if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL &&
+         ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET &&
+         conn->ssl[sockindex].state == ssl_connection_complete &&
+         conn->proxy_ssl[sockindex].state == ssl_connection_complete) {
+        char ver[120];
+        Curl_ossl_version(ver, 120);
+        failf(conn->data, "Error: %s does not support double SSL tunneling.",
+              ver);
+      }
+      else
+        failf(conn->data, "SSL_write() error: %s",
+              ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)));
       *curlcode = CURLE_SEND_ERROR;
       return -1;
     }
@@ -3178,7 +3255,7 @@ size_t Curl_ossl_version(char *buffer, size_t size)
         sub[0] = 'z';
       }
       else {
-        sub[0]=(char)(((ssleay_value>>4)&0xff) + 'a' -1);
+        sub[0] = (char) (minor_ver + 'a' - 1);
       }
     }
     else
@@ -3199,7 +3276,12 @@ int Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
                      size_t length)
 {
   if(data) {
-    Curl_ossl_seed(data); /* Initiate the seed if not already done */
+    if(Curl_ossl_seed(data)) /* Initiate the seed if not already done */
+      return 1; /* couldn't seed for some reason */
+  }
+  else {
+    if(!rand_enough())
+      return 1;
   }
   RAND_bytes(entropy, curlx_uztosi(length));
   return 0; /* 0 as in no problem */
diff --git a/lib/vtls/openssl.h b/lib/vtls/openssl.h
index ee18e71..cff1e90 100644
--- a/lib/vtls/openssl.h
+++ b/lib/vtls/openssl.h
@@ -79,6 +79,9 @@ void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
 
 bool Curl_ossl_cert_status_request(void);
 
+/* Support HTTPS-proxy */
+#define HTTPS_PROXY_SUPPORT 1
+
 /* Set the API backend definition to OpenSSL */
 #define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL
 
diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c
index 18b564e..4bba3e3 100644
--- a/lib/vtls/polarssl.c
+++ b/lib/vtls/polarssl.c
@@ -147,12 +147,16 @@ polarssl_connect_step1(struct connectdata *conn,
 {
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+  const char *capath = SSL_CONN_CONFIG(CApath);
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
+  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
   int ret = -1;
   char errorbuf[128];
   errorbuf[0]=0;
 
   /* PolarSSL only supports SSLv3 and TLSv1 */
-  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
+  if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
     failf(data, "PolarSSL does not support SSLv2");
     return CURLE_SSL_CONNECT_ERROR;
   }
@@ -180,30 +184,29 @@ polarssl_connect_step1(struct connectdata *conn,
   /* Load the trusted CA */
   memset(&connssl->cacert, 0, sizeof(x509_crt));
 
-  if(data->set.str[STRING_SSL_CAFILE]) {
+  if(SSL_CONN_CONFIG(CAfile)) {
     ret = x509_crt_parse_file(&connssl->cacert,
-                              data->set.str[STRING_SSL_CAFILE]);
+                              SSL_CONN_CONFIG(CAfile));
 
     if(ret<0) {
       error_strerror(ret, errorbuf, sizeof(errorbuf));
       failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s",
-            data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);
+            SSL_CONN_CONFIG(CAfile), -ret, errorbuf);
 
-      if(data->set.ssl.verifypeer)
+      if(SSL_CONN_CONFIG(verifypeer))
         return CURLE_SSL_CACERT_BADFILE;
     }
   }
 
-  if(data->set.str[STRING_SSL_CAPATH]) {
-    ret = x509_crt_parse_path(&connssl->cacert,
-                              data->set.str[STRING_SSL_CAPATH]);
+  if(capath) {
+    ret = x509_crt_parse_path(&connssl->cacert, capath);
 
     if(ret<0) {
       error_strerror(ret, errorbuf, sizeof(errorbuf));
       failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s",
-            data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);
+            capath, -ret, errorbuf);
 
-      if(data->set.ssl.verifypeer)
+      if(SSL_CONN_CONFIG(verifypeer))
         return CURLE_SSL_CACERT_BADFILE;
     }
   }
@@ -211,25 +214,25 @@ polarssl_connect_step1(struct connectdata *conn,
   /* Load the client certificate */
   memset(&connssl->clicert, 0, sizeof(x509_crt));
 
-  if(data->set.str[STRING_CERT]) {
+  if(SSL_SET_OPTION(cert)) {
     ret = x509_crt_parse_file(&connssl->clicert,
-                              data->set.str[STRING_CERT]);
+                              SSL_SET_OPTION(cert));
 
     if(ret) {
       error_strerror(ret, errorbuf, sizeof(errorbuf));
       failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s",
-            data->set.str[STRING_CERT], -ret, errorbuf);
+            SSL_SET_OPTION(cert), -ret, errorbuf);
 
       return CURLE_SSL_CERTPROBLEM;
     }
   }
 
   /* Load the client private key */
-  if(data->set.str[STRING_KEY]) {
+  if(SSL_SET_OPTION(key)) {
     pk_context pk;
     pk_init(&pk);
-    ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY],
-                           data->set.str[STRING_KEY_PASSWD]);
+    ret = pk_parse_keyfile(&pk, SSL_SET_OPTION(key),
+                           SSL_SET_OPTION(key_passwd));
     if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
       ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
     if(ret == 0)
@@ -241,7 +244,7 @@ polarssl_connect_step1(struct connectdata *conn,
     if(ret) {
       error_strerror(ret, errorbuf, sizeof(errorbuf));
       failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s",
-            data->set.str[STRING_KEY], -ret, errorbuf);
+            SSL_SET_OPTION(key), -ret, errorbuf);
 
       return CURLE_SSL_CERTPROBLEM;
     }
@@ -250,29 +253,27 @@ polarssl_connect_step1(struct connectdata *conn,
   /* Load the CRL */
   memset(&connssl->crl, 0, sizeof(x509_crl));
 
-  if(data->set.str[STRING_SSL_CRLFILE]) {
+  if(SSL_SET_OPTION(CRLfile)) {
     ret = x509_crl_parse_file(&connssl->crl,
-                              data->set.str[STRING_SSL_CRLFILE]);
+                              SSL_SET_OPTION(CRLfile));
 
     if(ret) {
       error_strerror(ret, errorbuf, sizeof(errorbuf));
       failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s",
-            data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);
+            SSL_SET_OPTION(CRLfile), -ret, errorbuf);
 
       return CURLE_SSL_CRL_BADFILE;
     }
   }
 
-  infof(data, "PolarSSL: Connecting to %s:%d\n",
-        conn->host.name, conn->remote_port);
+  infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port);
 
   if(ssl_init(&connssl->ssl)) {
     failf(data, "PolarSSL: ssl_init failed");
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  switch(data->set.ssl.version) {
-  default:
+  switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
     ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
@@ -306,6 +307,12 @@ polarssl_connect_step1(struct connectdata *conn,
                         SSL_MINOR_VERSION_3);
     infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n");
     break;
+  case CURL_SSLVERSION_TLSv1_3:
+    failf(data, "PolarSSL: TLS 1.3 is not yet supported");
+    return CURLE_SSL_CONNECT_ERROR;
+  default:
+    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+    return CURLE_SSL_CONNECT_ERROR;
   }
 
   ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
@@ -320,11 +327,11 @@ polarssl_connect_step1(struct connectdata *conn,
   ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
 
   /* Check if there's a cached ID we can/should use here! */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     void *old_session = NULL;
 
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) {
+    if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
       ret = ssl_set_session(&connssl->ssl, old_session);
       if(ret) {
         Curl_ssl_sessionid_unlock(conn);
@@ -339,12 +346,12 @@ polarssl_connect_step1(struct connectdata *conn,
   ssl_set_ca_chain(&connssl->ssl,
                    &connssl->cacert,
                    &connssl->crl,
-                   conn->host.name);
+                   hostname);
 
   ssl_set_own_cert_rsa(&connssl->ssl,
                        &connssl->clicert, &connssl->rsa);
 
-  if(ssl_set_hostname(&connssl->ssl, conn->host.name)) {
+  if(ssl_set_hostname(&connssl->ssl, hostname)) {
     /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name
        to set in the SNI extension. So even if curl connects to a host
        specified as an IP address, this function must be used. */
@@ -354,7 +361,7 @@ polarssl_connect_step1(struct connectdata *conn,
 
 #ifdef HAS_ALPN
   if(conn->bits.tls_enable_alpn) {
-    static const char* protocols[3];
+    static const char *protocols[3];
     int cur = 0;
 
 #ifdef USE_NGHTTP2
@@ -390,6 +397,10 @@ polarssl_connect_step2(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
   char buffer[1024];
+  const char * const pinnedpubkey = SSL_IS_PROXY() ?
+            data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+            data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+
 
   char errorbuf[128];
   errorbuf[0] = 0;
@@ -423,7 +434,7 @@ polarssl_connect_step2(struct connectdata *conn,
 
   ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
 
-  if(ret && data->set.ssl.verifypeer) {
+  if(ret && SSL_CONN_CONFIG(verifypeer)) {
     if(ret & BADCERT_EXPIRED)
       failf(data, "Cert verify failed: BADCERT_EXPIRED");
 
@@ -451,7 +462,7 @@ polarssl_connect_step2(struct connectdata *conn,
   }
 
   /* adapted from mbedtls.c */
-  if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
+  if(pinnedpubkey) {
     int size;
     CURLcode result;
     x509_crt *p;
@@ -493,7 +504,7 @@ polarssl_connect_step2(struct connectdata *conn,
 
     /* pk_write_pubkey_der writes data at the end of the buffer. */
     result = Curl_pin_peer_pubkey(data,
-                                  data->set.str[STRING_SSL_PINNEDPUBLICKEY],
+                                  pinnedpubkey,
                                   &pubkey[PUB_DER_MAX_BYTES - size], size);
     if(result) {
       x509_crt_free(p);
@@ -544,7 +555,7 @@ polarssl_connect_step3(struct connectdata *conn,
 
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     int ret;
     ssl_session *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
@@ -563,10 +574,10 @@ polarssl_connect_step3(struct connectdata *conn,
 
     /* If there's already a matching session in the cache, delete it */
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL))
+    if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
       Curl_ssl_delsessionid(conn, old_ssl_sessionid);
 
-    retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0);
+    retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
     Curl_ssl_sessionid_unlock(conn);
     if(retcode) {
       free(our_ssl_sessionid);
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index f731eeb..ac8b705 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -59,6 +59,7 @@
 #include "x509asn1.h"
 #include "curl_printf.h"
 #include "system_win32.h"
+#include "hostcheck.h"
 
  /* The last #include file should be: */
 #include "curl_memory.h"
@@ -123,9 +124,11 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
 #endif
   TCHAR *host_name;
   CURLcode result;
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 
   infof(data, "schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
-        conn->host.name, conn->remote_port);
+        hostname, conn->remote_port);
 
 #ifdef HAS_ALPN
   /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
@@ -142,9 +145,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
   connssl->cred = NULL;
 
   /* check for an existing re-usable credential handle */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL)) {
+    if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {
       connssl->cred = old_cred;
       infof(data, "schannel: re-using existing credential handle\n");
 
@@ -161,7 +164,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
     memset(&schannel_cred, 0, sizeof(schannel_cred));
     schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
 
-    if(data->set.ssl.verifypeer) {
+    if(conn->ssl_config.verifypeer) {
 #ifdef _WIN32_WCE
       /* certificate validation on CE doesn't seem to work right; we'll
          do it following a more manual process. */
@@ -170,13 +173,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
         SCH_CRED_IGNORE_REVOCATION_OFFLINE;
 #else
       schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
-      if(data->set.ssl_no_revoke)
+      /* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */
+      if(data->set.ssl.no_revoke)
         schannel_cred.dwFlags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
                                  SCH_CRED_IGNORE_REVOCATION_OFFLINE;
       else
         schannel_cred.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN;
 #endif
-      if(data->set.ssl_no_revoke)
+      if(data->set.ssl.no_revoke)
         infof(data, "schannel: disabled server certificate revocation "
                     "checks\n");
       else
@@ -189,15 +193,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
       infof(data, "schannel: disabled server certificate revocation checks\n");
     }
 
-    if(!data->set.ssl.verifyhost) {
+    if(!conn->ssl_config.verifyhost) {
       schannel_cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
       infof(data, "schannel: verifyhost setting prevents Schannel from "
             "comparing the supplied target name with the subject "
             "names in server certificates. Also disables SNI.\n");
     }
 
-    switch(data->set.ssl.version) {
-    default:
+    switch(conn->ssl_config.version) {
     case CURL_SSLVERSION_DEFAULT:
     case CURL_SSLVERSION_TLSv1:
       schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT |
@@ -213,12 +216,18 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
     case CURL_SSLVERSION_TLSv1_2:
       schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT;
       break;
+    case CURL_SSLVERSION_TLSv1_3:
+      failf(data, "Schannel: TLS 1.3 is not yet supported");
+      return CURLE_SSL_CONNECT_ERROR;
     case CURL_SSLVERSION_SSLv3:
       schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
       break;
     case CURL_SSLVERSION_SSLv2:
       schannel_cred.grbitEnabledProtocols = SP_PROT_SSL2_CLIENT;
       break;
+    default:
+      failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
+      return CURLE_SSL_CONNECT_ERROR;
     }
 
     /* allocate memory for the re-usable credential handle */
@@ -253,9 +262,9 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
   }
 
   /* Warn if SNI is disabled due to use of an IP address */
-  if(Curl_inet_pton(AF_INET, conn->host.name, &addr)
+  if(Curl_inet_pton(AF_INET, hostname, &addr)
 #ifdef ENABLE_IPV6
-     || Curl_inet_pton(AF_INET6, conn->host.name, &addr6)
+     || Curl_inet_pton(AF_INET6, hostname, &addr6)
 #endif
     ) {
     infof(data, "schannel: using IP address, SNI is not supported by OS.\n");
@@ -265,17 +274,17 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
   if(connssl->use_alpn) {
     int cur = 0;
     int list_start_index = 0;
-    unsigned int* extension_len = NULL;
+    unsigned int *extension_len = NULL;
     unsigned short* list_len = NULL;
 
     /* The first four bytes will be an unsigned int indicating number
        of bytes of data in the rest of the the buffer. */
-    extension_len = (unsigned int*)(&alpn_buffer[cur]);
+    extension_len = (unsigned int *)(&alpn_buffer[cur]);
     cur += sizeof(unsigned int);
 
     /* The next four bytes are an indicator that this buffer will contain
        ALPN data, as opposed to NPN, for example. */
-    *(unsigned int*)&alpn_buffer[cur] =
+    *(unsigned int *)&alpn_buffer[cur] =
       SecApplicationProtocolNegotiationExt_ALPN;
     cur += sizeof(unsigned int);
 
@@ -333,7 +342,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
   }
   memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt));
 
-  host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+  host_name = Curl_convert_UTF8_to_tchar(hostname);
   if(!host_name)
     return CURLE_OUT_OF_MEMORY;
 
@@ -406,11 +415,13 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
   TCHAR *host_name;
   CURLcode result;
   bool doread;
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 
   doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
 
   infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
-        conn->host.name, conn->remote_port);
+        hostname, conn->remote_port);
 
   if(!connssl->cred || !connssl->ctxt)
     return CURLE_SSL_CONNECT_ERROR;
@@ -506,7 +517,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
     memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer,
            connssl->encdata_offset);
 
-    host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+    host_name = Curl_convert_UTF8_to_tchar(hostname);
     if(!host_name)
       return CURLE_OUT_OF_MEMORY;
 
@@ -623,7 +634,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
 #ifdef _WIN32_WCE
   /* Windows CE doesn't do any server certificate validation.
      We have to do it manually. */
-  if(data->set.ssl.verifypeer)
+  if(conn->ssl_config.verifypeer)
     return verify_certificate(conn, sockindex);
 #endif
 
@@ -638,6 +649,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   SECURITY_STATUS sspi_status = SEC_E_OK;
   CERT_CONTEXT *ccert_context = NULL;
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 #ifdef HAS_ALPN
   SecPkgContext_ApplicationProtocol alpn_result;
 #endif
@@ -645,7 +658,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
 
   infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
-        conn->host.name, conn->remote_port);
+        hostname, conn->remote_port);
 
   if(!connssl->cred)
     return CURLE_SSL_CONNECT_ERROR;
@@ -701,12 +714,13 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
 #endif
 
   /* save the current session data for possible re-use */
-  if(conn->ssl_config.sessionid) {
+  if(data->set.general_ssl.sessionid) {
     bool incache;
     struct curl_schannel_cred *old_cred = NULL;
 
     Curl_ssl_sessionid_lock(conn);
-    incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL));
+    incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL,
+                                      sockindex));
     if(incache) {
       if(old_cred != connssl->cred) {
         infof(data, "schannel: old credential handle is stale, removing\n");
@@ -717,7 +731,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
     }
     if(!incache) {
       result = Curl_ssl_addsessionid(conn, (void *)connssl->cred,
-                                     sizeof(struct curl_schannel_cred));
+                                     sizeof(struct curl_schannel_cred),
+                                     sockindex);
       if(result) {
         Curl_ssl_sessionid_unlock(conn);
         failf(data, "schannel: failed to store credential handle");
@@ -769,7 +784,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   curl_socket_t sockfd = conn->sock[sockindex];
-  long timeout_ms;
+  time_t timeout_ms;
   int what;
 
   /* check if the connection has already been established */
@@ -957,7 +972,7 @@ schannel_send(struct connectdata *conn, int sockindex,
     /* send entire message or fail */
     while(len > (size_t)written) {
       ssize_t this_write;
-      long timeleft;
+      time_t timeleft;
       int what;
 
       this_write = 0;
@@ -1376,9 +1391,11 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
    */
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
+    conn->host.name;
 
   infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
-        conn->host.name, conn->remote_port);
+        hostname, conn->remote_port);
 
   if(connssl->cred && connssl->ctxt) {
     SecBufferDesc BuffDesc;
@@ -1400,7 +1417,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
       failf(data, "schannel: ApplyControlToken failure: %s",
             Curl_sspi_strerror(conn, sspi_status));
 
-    host_name = Curl_convert_UTF8_to_tchar(conn->host.name);
+    host_name = Curl_convert_UTF8_to_tchar(hostname);
     if(!host_name)
       return CURLE_OUT_OF_MEMORY;
 
@@ -1525,6 +1542,9 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
   CURLcode result = CURLE_OK;
   CERT_CONTEXT *pCertContextServer = NULL;
   const CERT_CHAIN_CONTEXT *pChainContext = NULL;
+  const char * const conn_hostname = SSL_IS_PROXY() ?
+    conn->http_proxy.host.name :
+    conn->host.name;
 
   status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
                                             SECPKG_ATTR_REMOTE_CERT_CONTEXT,
@@ -1546,7 +1566,7 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
                                 NULL,
                                 pCertContextServer->hCertStore,
                                 &ChainPara,
-                                (data->set.ssl_no_revoke ? 0 :
+                                (data->set.ssl.no_revoke ? 0 :
                                  CERT_CHAIN_REVOCATION_CHECK_CHAIN),
                                 NULL,
                                 &pChainContext)) {
@@ -1582,15 +1602,10 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
   }
 
   if(result == CURLE_OK) {
-    if(data->set.ssl.verifyhost) {
-      TCHAR cert_hostname_buff[128];
-      xcharp_u hostname;
-      xcharp_u cert_hostname;
+    if(conn->ssl_config.verifyhost) {
+      TCHAR cert_hostname_buff[256];
       DWORD len;
 
-      cert_hostname.const_tchar_ptr = cert_hostname_buff;
-      hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn->host.name);
-
       /* TODO: Fix this for certificates with multiple alternative names.
       Right now we're only asking for the first preferred alternative name.
       Instead we'd need to do all via CERT_NAME_SEARCH_ALL_NAMES_FLAG
@@ -1601,31 +1616,50 @@ static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
       */
       len = CertGetNameString(pCertContextServer,
                               CERT_NAME_DNS_TYPE,
-                              0,
+                              CERT_NAME_DISABLE_IE4_UTF8_FLAG,
                               NULL,
-                              cert_hostname.tchar_ptr,
-                              128);
-      if(len > 0 && *cert_hostname.tchar_ptr == '*') {
-        /* this is a wildcard cert.  try matching the last len - 1 chars */
-        int hostname_len = strlen(conn->host.name);
-        cert_hostname.tchar_ptr++;
-        if(_tcsicmp(cert_hostname.const_tchar_ptr,
-                    hostname.const_tchar_ptr + hostname_len - len + 2) != 0)
-          result = CURLE_PEER_FAILED_VERIFICATION;
+                              cert_hostname_buff,
+                              256);
+      if(len > 0) {
+        const char *cert_hostname;
+
+        /* Comparing the cert name and the connection hostname encoded as UTF-8
+         * is acceptable since both values are assumed to use ASCII
+         * (or some equivalent) encoding
+         */
+        cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname_buff);
+        if(!cert_hostname) {
+          result = CURLE_OUT_OF_MEMORY;
+        }
+        else{
+          int match_result;
+
+          match_result = Curl_cert_hostcheck(cert_hostname, conn->host.name);
+          if(match_result == CURL_HOST_MATCH) {
+            infof(data,
+                  "schannel: connection hostname (%s) validated "
+                  "against certificate name (%s)\n",
+                  conn->host.name,
+                  cert_hostname);
+            result = CURLE_OK;
+          }
+          else{
+            failf(data,
+                  "schannel: connection hostname (%s) "
+                  "does not match certificate name (%s)",
+                  conn->host.name,
+                  cert_hostname);
+            result = CURLE_PEER_FAILED_VERIFICATION;
+          }
+          Curl_unicodefree(cert_hostname);
+        }
       }
-      else if(len == 0 || _tcsicmp(hostname.const_tchar_ptr,
-                                   cert_hostname.const_tchar_ptr) != 0) {
+      else {
+        failf(data,
+              "schannel: CertGetNameString did not provide any "
+              "certificate name information");
         result = CURLE_PEER_FAILED_VERIFICATION;
       }
-      if(result == CURLE_PEER_FAILED_VERIFICATION) {
-        char *_cert_hostname;
-        _cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname.tchar_ptr);
-        failf(data, "schannel: CertGetNameString() certificate hostname "
-              "(%s) did not match connection (%s)",
-              _cert_hostname, conn->host.name);
-        Curl_unicodefree(_cert_hostname);
-      }
-      Curl_unicodefree(hostname.tchar_ptr);
     }
   }
 
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index 56a8823..b808e1c 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -65,6 +65,7 @@
 #include "url.h"
 #include "progress.h"
 #include "share.h"
+#include "multiif.h"
 #include "timeval.h"
 #include "curl_md5.h"
 #include "warnless.h"
@@ -80,94 +81,49 @@
                                  (data->share->specifier &             \
                                   (1<<CURL_LOCK_DATA_SSL_SESSION)))
 
-static bool safe_strequal(char* str1, char* str2)
-{
-  if(str1 && str2)
-    /* both pointers point to something then compare them */
-    return (0 != strcasecompare(str1, str2)) ? TRUE : FALSE;
-  else
-    /* if both pointers are NULL then treat them as equal */
-    return (!str1 && !str2) ? TRUE : FALSE;
-}
+#define CLONE_STRING(var)                    \
+  if(source->var) {                          \
+    dest->var = strdup(source->var);         \
+    if(!dest->var)                           \
+      return FALSE;                          \
+  }                                          \
+  else                                       \
+    dest->var = NULL;
 
 bool
-Curl_ssl_config_matches(struct ssl_config_data* data,
-                        struct ssl_config_data* needle)
+Curl_ssl_config_matches(struct ssl_primary_config* data,
+                        struct ssl_primary_config* needle)
 {
   if((data->version == needle->version) &&
      (data->verifypeer == needle->verifypeer) &&
      (data->verifyhost == needle->verifyhost) &&
-     safe_strequal(data->CApath, needle->CApath) &&
-     safe_strequal(data->CAfile, needle->CAfile) &&
-     safe_strequal(data->clientcert, needle->clientcert) &&
-     safe_strequal(data->cipher_list, needle->cipher_list))
+     Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
+     Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
+     Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
+     Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list))
     return TRUE;
 
   return FALSE;
 }
 
 bool
-Curl_clone_ssl_config(struct ssl_config_data *source,
-                      struct ssl_config_data *dest)
+Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
+                              struct ssl_primary_config *dest)
 {
-  dest->sessionid = source->sessionid;
   dest->verifyhost = source->verifyhost;
   dest->verifypeer = source->verifypeer;
   dest->version = source->version;
 
-  if(source->CAfile) {
-    dest->CAfile = strdup(source->CAfile);
-    if(!dest->CAfile)
-      return FALSE;
-  }
-  else
-    dest->CAfile = NULL;
-
-  if(source->CApath) {
-    dest->CApath = strdup(source->CApath);
-    if(!dest->CApath)
-      return FALSE;
-  }
-  else
-    dest->CApath = NULL;
-
-  if(source->cipher_list) {
-    dest->cipher_list = strdup(source->cipher_list);
-    if(!dest->cipher_list)
-      return FALSE;
-  }
-  else
-    dest->cipher_list = NULL;
-
-  if(source->egdsocket) {
-    dest->egdsocket = strdup(source->egdsocket);
-    if(!dest->egdsocket)
-      return FALSE;
-  }
-  else
-    dest->egdsocket = NULL;
-
-  if(source->random_file) {
-    dest->random_file = strdup(source->random_file);
-    if(!dest->random_file)
-      return FALSE;
-  }
-  else
-    dest->random_file = NULL;
-
-  if(source->clientcert) {
-    dest->clientcert = strdup(source->clientcert);
-    if(!dest->clientcert)
-      return FALSE;
-    dest->sessionid = FALSE;
-  }
-  else
-    dest->clientcert = NULL;
-
+  CLONE_STRING(CAfile);
+  CLONE_STRING(CApath);
+  CLONE_STRING(cipher_list);
+  CLONE_STRING(egdsocket);
+  CLONE_STRING(random_file);
+  CLONE_STRING(clientcert);
   return TRUE;
 }
 
-void Curl_free_ssl_config(struct ssl_config_data* sslc)
+void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
 {
   Curl_safefree(sslc->CAfile);
   Curl_safefree(sslc->CApath);
@@ -177,77 +133,6 @@ void Curl_free_ssl_config(struct ssl_config_data* sslc)
   Curl_safefree(sslc->clientcert);
 }
 
-
-/*
- * Curl_rand() returns a random unsigned integer, 32bit.
- *
- * This non-SSL function is put here only because this file is the only one
- * with knowledge of what the underlying SSL libraries provide in terms of
- * randomizers.
- *
- * NOTE: 'data' may be passed in as NULL when coming from external API without
- * easy handle!
- *
- */
-
-unsigned int Curl_rand(struct Curl_easy *data)
-{
-  unsigned int r = 0;
-  static unsigned int randseed;
-  static bool seeded = FALSE;
-
-#ifdef CURLDEBUG
-  char *force_entropy = getenv("CURL_ENTROPY");
-  if(force_entropy) {
-    if(!seeded) {
-      size_t elen = strlen(force_entropy);
-      size_t clen = sizeof(randseed);
-      size_t min = elen < clen ? elen : clen;
-      memcpy((char *)&randseed, force_entropy, min);
-      seeded = TRUE;
-    }
-    else
-      randseed++;
-    return randseed;
-  }
-#endif
-
-  /* data may be NULL! */
-  if(!Curl_ssl_random(data, (unsigned char *)&r, sizeof(r)))
-    return r;
-
-  /* If Curl_ssl_random() returns non-zero it couldn't offer randomness and we
-     instead perform a "best effort" */
-
-#ifdef RANDOM_FILE
-  if(!seeded) {
-    /* if there's a random file to read a seed from, use it */
-    int fd = open(RANDOM_FILE, O_RDONLY);
-    if(fd > -1) {
-      /* read random data into the randseed variable */
-      ssize_t nread = read(fd, &randseed, sizeof(randseed));
-      if(nread == sizeof(randseed))
-        seeded = TRUE;
-      close(fd);
-    }
-  }
-#endif
-
-  if(!seeded) {
-    struct timeval now = curlx_tvnow();
-    infof(data, "WARNING: Using weak random seed\n");
-    randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
-    randseed = randseed * 1103515245 + 12345;
-    randseed = randseed * 1103515245 + 12345;
-    randseed = randseed * 1103515245 + 12345;
-    seeded = TRUE;
-  }
-
-  /* Return an unsigned 32-bit pseudo-random number. */
-  r = randseed = randseed * 1103515245 + 12345;
-  return (r << 16) | ((r >> 16) & 0xFFFF);
-}
-
 int Curl_ssl_backend(void)
 {
   return (int)CURL_SSL_BACKEND;
@@ -288,19 +173,41 @@ void Curl_ssl_cleanup(void)
 static bool ssl_prefs_check(struct Curl_easy *data)
 {
   /* check for CURLOPT_SSLVERSION invalid parameter value */
-  if((data->set.ssl.version < 0)
-     || (data->set.ssl.version >= CURL_SSLVERSION_LAST)) {
+  if((data->set.ssl.primary.version < 0)
+     || (data->set.ssl.primary.version >= CURL_SSLVERSION_LAST)) {
     failf(data, "Unrecognized parameter value passed via CURLOPT_SSLVERSION");
     return FALSE;
   }
   return TRUE;
 }
 
+static CURLcode
+ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
+{
+  DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
+  if(ssl_connection_complete == conn->ssl[sockindex].state &&
+     !conn->proxy_ssl[sockindex].use) {
+#if defined(HTTPS_PROXY_SUPPORT)
+    conn->proxy_ssl[sockindex] = conn->ssl[sockindex];
+    memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
+#else
+    return CURLE_NOT_BUILT_IN;
+#endif
+  }
+  return CURLE_OK;
+}
+
 CURLcode
 Curl_ssl_connect(struct connectdata *conn, int sockindex)
 {
   CURLcode result;
 
+  if(conn->bits.proxy_ssl_connected[sockindex]) {
+    result = ssl_connect_init_proxy(conn, sockindex);
+    if(result)
+      return result;
+  }
+
   if(!ssl_prefs_check(conn->data))
     return CURLE_SSL_CONNECT_ERROR;
 
@@ -321,6 +228,11 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
                              bool *done)
 {
   CURLcode result;
+  if(conn->bits.proxy_ssl_connected[sockindex]) {
+    result = ssl_connect_init_proxy(conn, sockindex);
+    if(result)
+      return result;
+  }
 
   if(!ssl_prefs_check(conn->data))
     return CURLE_SSL_CONNECT_ERROR;
@@ -363,7 +275,8 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn)
  */
 bool Curl_ssl_getsessionid(struct connectdata *conn,
                            void **ssl_sessionid,
-                           size_t *idsize) /* set 0 if unknown */
+                           size_t *idsize, /* set 0 if unknown */
+                           int sockindex)
 {
   struct curl_ssl_session *check;
   struct Curl_easy *data = conn->data;
@@ -371,11 +284,18 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
   long *general_age;
   bool no_match = TRUE;
 
+  const bool isProxy = CONNECT_PROXY_SSL();
+  struct ssl_primary_config * const ssl_config = isProxy ?
+                                                 &conn->proxy_ssl_config :
+                                                 &conn->ssl_config;
+  const char * const name = isProxy ? conn->http_proxy.host.name :
+                                      conn->host.name;
+  int port = isProxy ? (int)conn->port : conn->remote_port;
   *ssl_sessionid = NULL;
 
-  DEBUGASSERT(conn->ssl_config.sessionid);
+  DEBUGASSERT(data->set.general_ssl.sessionid);
 
-  if(!conn->ssl_config.sessionid)
+  if(!data->set.general_ssl.sessionid)
     /* session ID re-use is disabled */
     return TRUE;
 
@@ -385,21 +305,21 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
   else
     general_age = &data->state.sessionage;
 
-  for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) {
+  for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
     check = &data->state.session[i];
     if(!check->sessionid)
       /* not session ID means blank entry */
       continue;
-    if(strcasecompare(conn->host.name, check->name) &&
+    if(strcasecompare(name, check->name) &&
        ((!conn->bits.conn_to_host && !check->conn_to_host) ||
         (conn->bits.conn_to_host && check->conn_to_host &&
          strcasecompare(conn->conn_to_host.name, check->conn_to_host))) &&
        ((!conn->bits.conn_to_port && check->conn_to_port == -1) ||
         (conn->bits.conn_to_port && check->conn_to_port != -1 &&
          conn->conn_to_port == check->conn_to_port)) &&
-       (conn->remote_port == check->remote_port) &&
+       (port == check->remote_port) &&
        strcasecompare(conn->handler->scheme, check->scheme) &&
-       Curl_ssl_config_matches(&conn->ssl_config, &check->ssl_config)) {
+       Curl_ssl_config_matches(ssl_config, &check->ssl_config)) {
       /* yes, we have a session ID! */
       (*general_age)++;          /* increase general age */
       check->age = *general_age; /* set this as used in this age */
@@ -428,7 +348,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
     session->sessionid = NULL;
     session->age = 0; /* fresh */
 
-    Curl_free_ssl_config(&session->ssl_config);
+    Curl_free_primary_ssl_config(&session->ssl_config);
 
     Curl_safefree(session->name);
     Curl_safefree(session->conn_to_host);
@@ -443,7 +363,7 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
   size_t i;
   struct Curl_easy *data=conn->data;
 
-  for(i = 0; i < data->set.ssl.max_ssl_sessions; i++) {
+  for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
     struct curl_ssl_session *check = &data->state.session[i];
 
     if(check->sessionid == ssl_sessionid) {
@@ -461,7 +381,8 @@ void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
  */
 CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
                                void *ssl_sessionid,
-                               size_t idsize)
+                               size_t idsize,
+                               int sockindex)
 {
   size_t i;
   struct Curl_easy *data=conn->data; /* the mother of all structs */
@@ -471,10 +392,14 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
   char *clone_conn_to_host;
   int conn_to_port;
   long *general_age;
+  const bool isProxy = CONNECT_PROXY_SSL();
+  struct ssl_primary_config * const ssl_config = isProxy ?
+                                           &conn->proxy_ssl_config :
+                                           &conn->ssl_config;
 
-  DEBUGASSERT(conn->ssl_config.sessionid);
+  DEBUGASSERT(data->set.general_ssl.sessionid);
 
-  clone_host = strdup(conn->host.name);
+  clone_host = strdup(isProxy ? conn->http_proxy.host.name : conn->host.name);
   if(!clone_host)
     return CURLE_OUT_OF_MEMORY; /* bail out */
 
@@ -505,14 +430,14 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
   }
 
   /* find an empty slot for us, or find the oldest */
-  for(i = 1; (i < data->set.ssl.max_ssl_sessions) &&
+  for(i = 1; (i < data->set.general_ssl.max_ssl_sessions) &&
         data->state.session[i].sessionid; i++) {
     if(data->state.session[i].age < oldest_age) {
       oldest_age = data->state.session[i].age;
       store = &data->state.session[i];
     }
   }
-  if(i == data->set.ssl.max_ssl_sessions)
+  if(i == data->set.general_ssl.max_ssl_sessions)
     /* cache is full, we must "kill" the oldest entry! */
     Curl_ssl_kill_session(store);
   else
@@ -528,10 +453,11 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
   store->name = clone_host;               /* clone host name */
   store->conn_to_host = clone_conn_to_host; /* clone connect to host name */
   store->conn_to_port = conn_to_port; /* connect to port number */
-  store->remote_port = conn->remote_port; /* port number */
+  /* port number */
+  store->remote_port = isProxy ? (int)conn->port : conn->remote_port;
   store->scheme = conn->handler->scheme;
 
-  if(!Curl_clone_ssl_config(&conn->ssl_config, &store->ssl_config)) {
+  if(!Curl_clone_primary_ssl_config(ssl_config, &store->ssl_config)) {
     store->sessionid = NULL; /* let caller free sessionid */
     free(clone_host);
     free(clone_conn_to_host);
@@ -547,7 +473,7 @@ void Curl_ssl_close_all(struct Curl_easy *data)
   size_t i;
   /* kill the session ID cache if not shared */
   if(data->state.session && !SSLSESSION_SHARED(data)) {
-    for(i = 0; i < data->set.ssl.max_ssl_sessions; i++)
+    for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++)
       /* the single-killer function handles empty table slots */
       Curl_ssl_kill_session(&data->state.session[i]);
 
@@ -558,6 +484,43 @@ void Curl_ssl_close_all(struct Curl_easy *data)
   curlssl_close_all(data);
 }
 
+#if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
+    defined(USE_DARWINSSL) || defined(USE_NSS)
+/* This function is for OpenSSL, GnuTLS, darwinssl, and schannel only. */
+int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
+                     int numsocks)
+{
+  struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
+
+  if(!numsocks)
+    return GETSOCK_BLANK;
+
+  if(connssl->connecting_state == ssl_connect_2_writing) {
+    /* write mode */
+    socks[0] = conn->sock[FIRSTSOCKET];
+    return GETSOCK_WRITESOCK(0);
+  }
+  else if(connssl->connecting_state == ssl_connect_2_reading) {
+    /* read mode */
+    socks[0] = conn->sock[FIRSTSOCKET];
+    return GETSOCK_READSOCK(0);
+  }
+
+  return GETSOCK_BLANK;
+}
+#else
+int Curl_ssl_getsock(struct connectdata *conn,
+                          curl_socket_t *socks,
+                          int numsocks)
+{
+  (void)conn;
+  (void)socks;
+  (void)numsocks;
+  return GETSOCK_BLANK;
+}
+/* USE_SSLEAY || USE_GNUTLS || USE_SCHANNEL || USE_DARWINSSL || USE_NSS */
+#endif
+
 void Curl_ssl_close(struct connectdata *conn, int sockindex)
 {
   DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
@@ -615,7 +578,7 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, size_t amount)
     return CURLE_OUT_OF_MEMORY;
 
   /* store the info in the SSL section */
-  data->set.ssl.max_ssl_sessions = amount;
+  data->set.general_ssl.max_ssl_sessions = amount;
   data->state.session = session;
   data->state.sessionage = 1; /* this is brand new */
   return CURLE_OK;
@@ -691,9 +654,9 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
                                     const char *value,
                                     size_t valuelen)
 {
-  struct curl_certinfo * ci = &data->info.certs;
-  char * output;
-  struct curl_slist * nl;
+  struct curl_certinfo *ci = &data->info.certs;
+  char *output;
+  struct curl_slist *nl;
   CURLcode result = CURLE_OK;
   size_t labellen = strlen(label);
   size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */
@@ -736,11 +699,16 @@ CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data,
   return Curl_ssl_push_certinfo_len(data, certnum, label, value, valuelen);
 }
 
-int Curl_ssl_random(struct Curl_easy *data,
-                     unsigned char *entropy,
-                     size_t length)
+CURLcode Curl_ssl_random(struct Curl_easy *data,
+                         unsigned char *entropy,
+                         size_t length)
 {
-  return curlssl_random(data, entropy, length);
+  int rc = curlssl_random(data, entropy, length);
+  if(rc) {
+    failf(data, "PRNG seeding failed");
+    return CURLE_FAILED_INIT; /* possibly weird return code */
+  }
+  return CURLE_OK;
 }
 
 /*
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index a41ecc3..2aabeda 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -50,13 +50,24 @@
 #define ALPN_HTTP_1_1_LENGTH 8
 #define ALPN_HTTP_1_1 "http/1.1"
 
-bool Curl_ssl_config_matches(struct ssl_config_data* data,
-                             struct ssl_config_data* needle);
-bool Curl_clone_ssl_config(struct ssl_config_data* source,
-                           struct ssl_config_data* dest);
-void Curl_free_ssl_config(struct ssl_config_data* sslc);
-
-unsigned int Curl_rand(struct Curl_easy *);
+/* set of helper macros for the backends to access the correct fields. For the
+   proxy or for the remote host - to properly support HTTPS proxy */
+
+#define SSL_IS_PROXY() (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \
+  ssl_connection_complete != conn->proxy_ssl[conn->sock[SECONDARYSOCKET] == \
+  CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state)
+#define SSL_SET_OPTION(var) (SSL_IS_PROXY() ? data->set.proxy_ssl.var : \
+                             data->set.ssl.var)
+#define SSL_CONN_CONFIG(var) (SSL_IS_PROXY() ?          \
+  conn->proxy_ssl_config.var : conn->ssl_config.var)
+
+bool Curl_ssl_config_matches(struct ssl_primary_config* data,
+                             struct ssl_primary_config* needle);
+bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
+                                   struct ssl_primary_config *dest);
+void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc);
+int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks,
+                     int numsocks);
 
 int Curl_ssl_backend(void);
 
@@ -87,12 +98,12 @@ int Curl_ssl_check_cxn(struct connectdata *conn);
 /* Certificate information list handling. */
 
 void Curl_ssl_free_certinfo(struct Curl_easy *data);
-CURLcode Curl_ssl_init_certinfo(struct Curl_easy * data, int num);
-CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy * data, int certnum,
-                                    const char * label, const char * value,
+CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num);
+CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, int certnum,
+                                    const char *label, const char *value,
                                     size_t valuelen);
-CURLcode Curl_ssl_push_certinfo(struct Curl_easy * data, int certnum,
-                                const char * label, const char * value);
+CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, int certnum,
+                                const char *label, const char *value);
 
 /* Functions to be used by SSL library adaptation functions */
 
@@ -116,7 +127,8 @@ void Curl_ssl_sessionid_unlock(struct connectdata *conn);
  */
 bool Curl_ssl_getsessionid(struct connectdata *conn,
                            void **ssl_sessionid,
-                           size_t *idsize); /* set 0 if unknown */
+                           size_t *idsize, /* set 0 if unknown */
+                           int sockindex);
 /* add a new session ID
  * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
  * Caller must ensure that it has properly shared ownership of this sessionid
@@ -124,7 +136,8 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
  */
 CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
                                void *ssl_sessionid,
-                               size_t idsize);
+                               size_t idsize,
+                               int sockindex);
 /* Kill a single session ID entry in the cache
  * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
  * This will call engine-specific curlssl_session_free function, which must
@@ -140,10 +153,9 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session);
  */
 void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid);
 
-/* get N random bytes into the buffer, return 0 if a find random is filled
-   in */
-int Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer,
-                    size_t length);
+/* get N random bytes into the buffer */
+CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer,
+                         size_t length);
 CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
                          size_t tmplen,
                          unsigned char *md5sum, /* output */
diff --git a/lib/x509asn1.c b/lib/x509asn1.c
index 74a511b..c4bc7c1 100644
--- a/lib/x509asn1.c
+++ b/lib/x509asn1.c
@@ -40,6 +40,9 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
+/* For overflow checks. */
+#define CURL_SIZE_T_MAX         ((size_t)-1)
+
 
 /* ASN.1 OIDs. */
 static const char       cnOID[] = "2.5.4.3";    /* Common name. */
@@ -105,8 +108,8 @@ static const curl_OID   OIDtable[] = {
  */
 
 
-const char * Curl_getASN1Element(curl_asn1Element * elem,
-                                 const char * beg, const char * end)
+const char *Curl_getASN1Element(curl_asn1Element *elem,
+                                const char *beg, const char *end)
 {
   unsigned char b;
   unsigned long len;
@@ -116,8 +119,8 @@ const char * Curl_getASN1Element(curl_asn1Element * elem,
      ending at `end'.
      Returns a pointer in source string after the parsed element, or NULL
      if an error occurs. */
-
-  if(beg >= end || !*beg)
+  if(!beg || !end || beg >= end || !*beg ||
+     (size_t)(end - beg) > CURL_ASN1_MAX)
     return (const char *) NULL;
 
   /* Process header byte. */
@@ -152,7 +155,7 @@ const char * Curl_getASN1Element(curl_asn1Element * elem,
     elem->end = beg;
     return beg + 1;
   }
-  else if(beg + b > end)
+  else if((unsigned)b > (size_t)(end - beg))
     return (const char *) NULL; /* Does not fit in source. */
   else {
     /* Get long length. */
@@ -163,16 +166,16 @@ const char * Curl_getASN1Element(curl_asn1Element * elem,
       len = (len << 8) | (unsigned char) *beg++;
     } while(--b);
   }
-  if((unsigned long) (end - beg) < len)
+  if(len > (size_t)(end - beg))
     return (const char *) NULL;  /* Element data does not fit in source. */
   elem->beg = beg;
   elem->end = beg + len;
   return elem->end;
 }
 
-static const curl_OID * searchOID(const char * oid)
+static const curl_OID * searchOID(const char *oid)
 {
-  const curl_OID * op;
+  const curl_OID *op;
 
   /* Search the null terminated OID or OID identifier in local table.
      Return the table entry pointer or NULL if not found. */
@@ -184,7 +187,7 @@ static const curl_OID * searchOID(const char * oid)
   return (const curl_OID *) NULL;
 }
 
-static const char * bool2str(const char * beg, const char * end)
+static const char *bool2str(const char *beg, const char *end)
 {
   /* Convert an ASN.1 Boolean value into its string representation.
      Return the dynamically allocated string, or NULL if source is not an
@@ -195,22 +198,24 @@ static const char * bool2str(const char * beg, const char * end)
   return strdup(*beg? "TRUE": "FALSE");
 }
 
-static const char * octet2str(const char * beg, const char * end)
+static const char *octet2str(const char *beg, const char *end)
 {
   size_t n = end - beg;
-  char * buf;
+  char *buf = NULL;
 
   /* Convert an ASN.1 octet string to a printable string.
      Return the dynamically allocated string, or NULL if an error occurs. */
 
-  buf = malloc(3 * n + 1);
-  if(buf)
-    for(n = 0; beg < end; n += 3)
-      snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
+  if(n <= (CURL_SIZE_T_MAX - 1) / 3) {
+    buf = malloc(3 * n + 1);
+    if(buf)
+      for(n = 0; beg < end; n += 3)
+        snprintf(buf + n, 4, "%02x:", *(const unsigned char *) beg++);
+  }
   return buf;
 }
 
-static const char * bit2str(const char * beg, const char * end)
+static const char *bit2str(const char *beg, const char *end)
 {
   /* Convert an ASN.1 bit string to a printable string.
      Return the dynamically allocated string, or NULL if an error occurs. */
@@ -220,7 +225,7 @@ static const char * bit2str(const char * beg, const char * end)
   return octet2str(beg, end);
 }
 
-static const char * int2str(const char * beg, const char * end)
+static const char *int2str(const char *beg, const char *end)
 {
   long val = 0;
   size_t n = end - beg;
@@ -246,14 +251,14 @@ static const char * int2str(const char * beg, const char * end)
 }
 
 static ssize_t
-utf8asn1str(char * * to, int type, const char * from, const char * end)
+utf8asn1str(char **to, int type, const char *from, const char *end)
 {
   size_t inlength = end - from;
   int size = 1;
   size_t outlength;
   int charsize;
   unsigned int wc;
-  char * buf;
+  char *buf;
 
   /* Perform a lazy conversion from an ASN.1 typed string to UTF8. Allocate the
      destination buffer dynamically. The allocation size will normally be too
@@ -262,7 +267,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
      string length. */
 
   *to = (char *) NULL;
-  switch (type) {
+  switch(type) {
   case CURL_ASN1_BMP_STRING:
     size = 2;
     break;
@@ -282,6 +287,8 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
 
   if(inlength % size)
     return -1;  /* Length inconsistent with character size. */
+  if(inlength / size > (CURL_SIZE_T_MAX - 1) / 4)
+    return -1;  /* Too big. */
   buf = malloc(4 * (inlength / size) + 1);
   if(!buf)
     return -1;  /* Not enough memory. */
@@ -295,7 +302,7 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
   else {
     for(outlength = 0; from < end;) {
       wc = 0;
-      switch (size) {
+      switch(size) {
       case 4:
         wc = (wc << 8) | *(const unsigned char *) from++;
         wc = (wc << 8) | *(const unsigned char *) from++;
@@ -335,9 +342,9 @@ utf8asn1str(char * * to, int type, const char * from, const char * end)
   return outlength;
 }
 
-static const char * string2str(int type, const char * beg, const char * end)
+static const char *string2str(int type, const char *beg, const char *end)
 {
-  char * buf;
+  char *buf;
 
   /* Convert an ASN.1 String into its UTF-8 string representation.
      Return the dynamically allocated string, or NULL if an error occurs. */
@@ -347,7 +354,7 @@ static const char * string2str(int type, const char * beg, const char * end)
   return buf;
 }
 
-static int encodeUint(char * buf, int n, unsigned int x)
+static int encodeUint(char *buf, int n, unsigned int x)
 {
   int i = 0;
   unsigned int y = x / 10;
@@ -367,7 +374,7 @@ static int encodeUint(char * buf, int n, unsigned int x)
   return i;
 }
 
-static int encodeOID(char * buf, int n, const char * beg, const char * end)
+static int encodeOID(char *buf, int n, const char *beg, const char *end)
 {
   int i = 0;
   unsigned int x;
@@ -406,9 +413,9 @@ static int encodeOID(char * buf, int n, const char * beg, const char * end)
   return i;
 }
 
-static const char * OID2str(const char * beg, const char * end, bool symbolic)
+static const char *OID2str(const char *beg, const char *end, bool symbolic)
 {
-  char * buf = (char *) NULL;
+  char *buf = (char *) NULL;
   const curl_OID * op;
   int n;
 
@@ -436,14 +443,14 @@ static const char * OID2str(const char * beg, const char * end, bool symbolic)
   return buf;
 }
 
-static const char * GTime2str(const char * beg, const char * end)
+static const char *GTime2str(const char *beg, const char *end)
 {
-  const char * tzp;
-  const char * fracp;
+  const char *tzp;
+  const char *fracp;
   char sec1, sec2;
   size_t fracl;
   size_t tzl;
-  const char * sep = "";
+  const char *sep = "";
 
   /* Convert an ASN.1 Generalized time to a printable string.
      Return the dynamically allocated string, or NULL if an error occurs. */
@@ -453,7 +460,7 @@ static const char * GTime2str(const char * beg, const char * end)
 
   /* Get seconds digits. */
   sec1 = '0';
-  switch (fracp - beg - 12) {
+  switch(fracp - beg - 12) {
   case 0:
     sec2 = '0';
     break;
@@ -499,11 +506,11 @@ static const char * GTime2str(const char * beg, const char * end)
                        sep, tzl, tzp);
 }
 
-static const char * UTime2str(const char * beg, const char * end)
+static const char *UTime2str(const char *beg, const char *end)
 {
-  const char * tzp;
+  const char *tzp;
   size_t tzl;
-  const char * sec;
+  const char *sec;
 
   /* Convert an ASN.1 UTC time to a printable string.
      Return the dynamically allocated string, or NULL if an error occurs. */
@@ -512,7 +519,7 @@ static const char * UTime2str(const char * beg, const char * end)
     ;
   /* Get the seconds. */
   sec = beg + 10;
-  switch (tzp - sec) {
+  switch(tzp - sec) {
   case 0:
     sec = "00";
   case 2:
@@ -538,7 +545,7 @@ static const char * UTime2str(const char * beg, const char * end)
                        tzl, tzp);
 }
 
-const char * Curl_ASN1tostr(curl_asn1Element * elem, int type)
+const char *Curl_ASN1tostr(curl_asn1Element *elem, int type)
 {
   /* Convert an ASN.1 element to a printable string.
      Return the dynamically allocated string, or NULL if an error occurs. */
@@ -549,7 +556,7 @@ const char * Curl_ASN1tostr(curl_asn1Element * elem, int type)
   if(!type)
     type = elem->tag;   /* Type not forced: use element tag as type. */
 
-  switch (type) {
+  switch(type) {
   case CURL_ASN1_BOOLEAN:
     return bool2str(elem->beg, elem->end);
   case CURL_ASN1_INTEGER:
@@ -581,17 +588,17 @@ const char * Curl_ASN1tostr(curl_asn1Element * elem, int type)
   return (const char *) NULL;   /* Unsupported. */
 }
 
-static ssize_t encodeDN(char * buf, size_t n, curl_asn1Element * dn)
+static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
 {
   curl_asn1Element rdn;
   curl_asn1Element atv;
   curl_asn1Element oid;
   curl_asn1Element value;
   size_t l = 0;
-  const char * p1;
-  const char * p2;
-  const char * p3;
-  const char * str;
+  const char *p1;
+  const char *p2;
+  const char *p3;
+  const char *str;
 
   /* ASCII encode distinguished name at `dn' into the `n'-byte buffer at `buf'.
      Return the total string length, even if larger than `n'. */
@@ -647,9 +654,9 @@ static ssize_t encodeDN(char * buf, size_t n, curl_asn1Element * dn)
   return l;
 }
 
-const char * Curl_DNtostr(curl_asn1Element * dn)
+const char *Curl_DNtostr(curl_asn1Element *dn)
 {
-  char * buf = (char *) NULL;
+  char *buf = (char *) NULL;
   ssize_t n = encodeDN(buf, 0, dn);
 
   /* Convert an ASN.1 distinguished name into a printable string.
@@ -669,12 +676,12 @@ const char * Curl_DNtostr(curl_asn1Element * dn)
  * X509 parser.
  */
 
-void Curl_parseX509(curl_X509certificate * cert,
-                    const char * beg, const char * end)
+int Curl_parseX509(curl_X509certificate *cert,
+                   const char *beg, const char *end)
 {
   curl_asn1Element elem;
   curl_asn1Element tbsCertificate;
-  const char * ccp;
+  const char *ccp;
   static const char defaultVersion = 0;  /* v1. */
 
   /* ASN.1 parse an X509 certificate into structure subfields.
@@ -686,7 +693,8 @@ void Curl_parseX509(curl_X509certificate * cert,
   cert->certificate.end = end;
 
   /* Get the sequence content. */
-  Curl_getASN1Element(&elem, beg, end);
+  if(!Curl_getASN1Element(&elem, beg, end))
+    return -1;  /* Invalid bounds/size. */
   beg = elem.beg;
   end = elem.end;
 
@@ -749,9 +757,10 @@ void Curl_parseX509(curl_X509certificate * cert,
   }
   if(elem.tag == 3)
     Curl_getASN1Element(&cert->extensions, elem.beg, elem.end);
+  return 0;
 }
 
-static size_t copySubstring(char * to, const char * from)
+static size_t copySubstring(char *to, const char *from)
 {
   size_t i;
 
@@ -768,8 +777,8 @@ static size_t copySubstring(char * to, const char * from)
   return i;
 }
 
-static const char * dumpAlgo(curl_asn1Element * param,
-                             const char * beg, const char * end)
+static const char *dumpAlgo(curl_asn1Element *param,
+                            const char *beg, const char *end)
 {
   curl_asn1Element oid;
 
@@ -784,10 +793,10 @@ static const char * dumpAlgo(curl_asn1Element * param,
   return OID2str(oid.beg, oid.end, TRUE);
 }
 
-static void do_pubkey_field(struct Curl_easy * data, int certnum,
-                            const char * label, curl_asn1Element * elem)
+static void do_pubkey_field(struct Curl_easy *data, int certnum,
+                            const char *label, curl_asn1Element *elem)
 {
-  const char * output;
+  const char *output;
 
   /* Generate a certificate information record for the public key. */
 
@@ -801,14 +810,14 @@ static void do_pubkey_field(struct Curl_easy * data, int certnum,
   }
 }
 
-static void do_pubkey(struct Curl_easy * data, int certnum,
-                      const char * algo, curl_asn1Element * param,
-                      curl_asn1Element * pubkey)
+static void do_pubkey(struct Curl_easy *data, int certnum,
+                      const char *algo, curl_asn1Element *param,
+                      curl_asn1Element *pubkey)
 {
   curl_asn1Element elem;
   curl_asn1Element pk;
-  const char * p;
-  const char * q;
+  const char *p;
+  const char *q;
   unsigned long len;
   unsigned int i;
 
@@ -865,18 +874,18 @@ static void do_pubkey(struct Curl_easy * data, int certnum,
 #endif
 }
 
-CURLcode Curl_extract_certinfo(struct connectdata * conn,
+CURLcode Curl_extract_certinfo(struct connectdata *conn,
                                int certnum,
-                               const char * beg,
-                               const char * end)
+                               const char *beg,
+                               const char *end)
 {
   curl_X509certificate cert;
-  struct Curl_easy * data = conn->data;
+  struct Curl_easy *data = conn->data;
   curl_asn1Element param;
-  const char * ccp;
-  char * cp1;
+  const char *ccp;
+  char *cp1;
   size_t cl1;
-  char * cp2;
+  char *cp2;
   CURLcode result;
   unsigned long version;
   size_t i;
@@ -889,7 +898,8 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
   /* Prepare the certificate information for curl_easy_getinfo(). */
 
   /* Extract the certificate ASN.1 elements. */
-  Curl_parseX509(&cert, beg, end);
+  if(Curl_parseX509(&cert, beg, end))
+    return CURLE_OUT_OF_MEMORY;
 
   /* Subject. */
   ccp = Curl_DNtostr(&cert.subject);
@@ -1029,12 +1039,12 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
 
 #if defined(USE_GSKIT)
 
-static const char * checkOID(const char * beg, const char * end,
-                             const char * oid)
+static const char *checkOID(const char *beg, const char *end,
+                            const char *oid)
 {
   curl_asn1Element e;
-  const char * ccp;
-  const char * p;
+  const char *ccp;
+  const char *p;
   bool matched;
 
   /* Check if first ASN.1 element at `beg' is the given OID.
@@ -1053,21 +1063,26 @@ static const char * checkOID(const char * beg, const char * end,
   return matched? ccp: (const char *) NULL;
 }
 
-CURLcode Curl_verifyhost(struct connectdata * conn,
-                         const char * beg, const char * end)
+CURLcode Curl_verifyhost(struct connectdata *conn,
+                         const char *beg, const char *end)
 {
-  struct Curl_easy * data = conn->data;
+  struct Curl_easy *data = conn->data;
   curl_X509certificate cert;
   curl_asn1Element dn;
   curl_asn1Element elem;
   curl_asn1Element ext;
   curl_asn1Element name;
-  const char * p;
-  const char * q;
-  char * dnsname;
+  const char *p;
+  const char *q;
+  char *dnsname;
   int matched = -1;
   size_t addrlen = (size_t) -1;
   ssize_t len;
+  const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
+                                                conn->host.name;
+  const char * const dispname = SSL_IS_PROXY()?
+                                  conn->http_proxy.host.dispname:
+                                  conn->host.dispname;
 #ifdef ENABLE_IPV6
   struct in6_addr addr;
 #else
@@ -1077,20 +1092,19 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
   /* Verify that connection server matches info in X509 certificate at
      `beg'..`end'. */
 
-  if(!data->set.ssl.verifyhost)
+  if(!SSL_CONN_CONFIG(verifyhost))
     return CURLE_OK;
 
-  if(!beg)
+  if(Curl_parseX509(&cert, beg, end))
     return CURLE_PEER_FAILED_VERIFICATION;
-  Curl_parseX509(&cert, beg, end);
 
   /* Get the server IP address. */
 #ifdef ENABLE_IPV6
-  if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, conn->host.name, &addr))
+  if(conn->bits.ipv6_ip && Curl_inet_pton(AF_INET6, hostname, &addr))
     addrlen = sizeof(struct in6_addr);
   else
 #endif
-  if(Curl_inet_pton(AF_INET, conn->host.name, &addr))
+  if(Curl_inet_pton(AF_INET, hostname, &addr))
     addrlen = sizeof(struct in_addr);
 
   /* Process extensions. */
@@ -1108,12 +1122,12 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
       /* Check all GeneralNames. */
       for(q = elem.beg; matched != 1 && q < elem.end;) {
         q = Curl_getASN1Element(&name, q, elem.end);
-        switch (name.tag) {
+        switch(name.tag) {
         case 2: /* DNS name. */
           len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
                             name.beg, name.end);
           if(len > 0 && (size_t)len == strlen(dnsname))
-            matched = Curl_cert_hostcheck(dnsname, conn->host.name);
+            matched = Curl_cert_hostcheck(dnsname, hostname);
           else
             matched = 0;
           free(dnsname);
@@ -1128,15 +1142,15 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
     }
   }
 
-  switch (matched) {
+  switch(matched) {
   case 1:
     /* an alternative name matched the server hostname */
-    infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname);
+    infof(data, "\t subjectAltName: %s matched\n", dispname);
     return CURLE_OK;
   case 0:
     /* an alternative name field existed, but didn't match and then
        we MUST fail */
-    infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname);
+    infof(data, "\t subjectAltName does not match %s\n", dispname);
     return CURLE_PEER_FAILED_VERIFICATION;
   }
 
@@ -1168,14 +1182,14 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
     }
     if(strlen(dnsname) != (size_t) len)         /* Nul byte in string ? */
       failf(data, "SSL: illegal cert name field");
-    else if(Curl_cert_hostcheck((const char *) dnsname, conn->host.name)) {
+    else if(Curl_cert_hostcheck((const char *) dnsname, hostname)) {
       infof(data, "\t common name: %s (matched)\n", dnsname);
       free(dnsname);
       return CURLE_OK;
     }
     else
       failf(data, "SSL: certificate subject name '%s' does not match "
-            "target host name '%s'", dnsname, conn->host.dispname);
+            "target host name '%s'", dnsname, dispname);
     free(dnsname);
   }
 
diff --git a/lib/x509asn1.h b/lib/x509asn1.h
index 0f2b930..ce40297 100644
--- a/lib/x509asn1.h
+++ b/lib/x509asn1.h
@@ -8,7 +8,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel at haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel at haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -34,6 +34,9 @@
  * Constants.
  */
 
+/* Largest supported ASN.1 structure. */
+#define CURL_ASN1_MAX                   ((size_t) 0x40000)      /* 256K */
+
 /* ASN.1 classes. */
 #define CURL_ASN1_UNIVERSAL             0
 #define CURL_ASN1_APPLICATION           1
@@ -117,16 +120,15 @@ typedef struct {
  * Prototypes.
  */
 
-const char * Curl_getASN1Element(curl_asn1Element * elem,
-                                 const char * beg, const char * end);
-const char * Curl_ASN1tostr(curl_asn1Element * elem, int type);
-const char * Curl_DNtostr(curl_asn1Element * dn);
-void Curl_parseX509(curl_X509certificate * cert,
-                    const char * beg, const char * end);
-CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum,
-                               const char * beg, const char * end);
-CURLcode Curl_verifyhost(struct connectdata * conn,
-                         const char * beg, const char * end);
-
+const char *Curl_getASN1Element(curl_asn1Element *elem,
+                                 const char *beg, const char *end);
+const char *Curl_ASN1tostr(curl_asn1Element *elem, int type);
+const char *Curl_DNtostr(curl_asn1Element *dn);
+int Curl_parseX509(curl_X509certificate *cert,
+                   const char *beg, const char *end);
+CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum,
+                               const char *beg, const char *end);
+CURLcode Curl_verifyhost(struct connectdata *conn,
+                         const char *beg, const char *end);
 #endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_CYASSL or USE_SCHANNEL */
 #endif /* HEADER_CURL_X509ASN1_H */

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f4a3290ae7ae096f8b92f7adfba7088e6918bc0b
commit f4a3290ae7ae096f8b92f7adfba7088e6918bc0b
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Feb 7 11:33:09 2017 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Feb 7 11:36:59 2017 -0500

    curl: Update script to get curl 7.52.1

diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index 22d1d8a..9cff7ca 100755
--- a/Utilities/Scripts/update-curl.bash
+++ b/Utilities/Scripts/update-curl.bash
@@ -8,7 +8,7 @@ readonly name="curl"
 readonly ownership="Curl Upstream <curl-library at cool.haxx.se>"
 readonly subtree="Utilities/cmcurl"
 readonly repo="https://github.com/curl/curl.git"
-readonly tag="curl-7_51_0"
+readonly tag="curl-7_52_1"
 readonly shortlog=false
 readonly paths="
   CMake/*

-----------------------------------------------------------------------

Summary of changes:
 Help/release/dev/update-curl.rst                   |    6 +
 Tests/CMakeTests/FileDownloadBadHashTest.cmake.in  |    2 +-
 Tests/CMakeTests/FileDownloadTest.cmake.in         |    2 +-
 Tests/CMakeTests/FileUploadTest.cmake.in           |    2 +-
 Tests/RunCMake/file/DOWNLOAD-hash-mismatch.cmake   |    2 +-
 Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake |    2 +-
 Tests/RunCMake/file/UPLOAD-unused-argument.cmake   |    2 +-
 Utilities/Scripts/update-curl.bash                 |    2 +-
 Utilities/cmcurl/CMake/OtherTests.cmake            |   25 +-
 Utilities/cmcurl/CMakeLists.txt                    |    8 +-
 Utilities/cmcurl/include/curl/curl.h               |   84 +-
 Utilities/cmcurl/include/curl/curlver.h            |    8 +-
 Utilities/cmcurl/include/curl/easy.h               |    4 +-
 Utilities/cmcurl/include/curl/stdcheaders.h        |    6 +-
 Utilities/cmcurl/include/curl/typecheck-gcc.h      |   55 +-
 Utilities/cmcurl/lib/Makefile.inc                  |    4 +-
 Utilities/cmcurl/lib/asyn-ares.c                   |    4 +-
 Utilities/cmcurl/lib/asyn-thread.c                 |   24 +-
 Utilities/cmcurl/lib/conncache.c                   |    6 +-
 Utilities/cmcurl/lib/connect.c                     |   98 ++-
 Utilities/cmcurl/lib/connect.h                     |   13 +-
 Utilities/cmcurl/lib/content_encoding.c            |   23 +-
 Utilities/cmcurl/lib/cookie.c                      |   10 +-
 Utilities/cmcurl/lib/curl_addrinfo.c               |   34 +-
 Utilities/cmcurl/lib/curl_addrinfo.h               |    2 +-
 Utilities/cmcurl/lib/curl_endian.c                 |   18 +-
 Utilities/cmcurl/lib/curl_endian.h                 |   18 +-
 Utilities/cmcurl/lib/curl_gethostname.c            |    8 +-
 Utilities/cmcurl/lib/curl_gssapi.c                 |    2 +-
 Utilities/cmcurl/lib/curl_hmac.h                   |   26 +-
 Utilities/cmcurl/lib/curl_ntlm_core.c              |    2 +-
 Utilities/cmcurl/lib/curl_ntlm_wb.c                |   13 +-
 Utilities/cmcurl/lib/curl_sasl.c                   |   20 +-
 Utilities/cmcurl/lib/curl_sec.h                    |   16 +-
 Utilities/cmcurl/lib/curl_setup.h                  |    4 +-
 Utilities/cmcurl/lib/curl_threads.c                |    5 +-
 Utilities/cmcurl/lib/curl_threads.h                |    5 +-
 Utilities/cmcurl/lib/easy.c                        |    2 +
 Utilities/cmcurl/lib/escape.c                      |    9 +-
 Utilities/cmcurl/lib/file.c                        |    2 +-
 Utilities/cmcurl/lib/formdata.c                    |   46 +-
 Utilities/cmcurl/lib/formdata.h                    |    2 +-
 Utilities/cmcurl/lib/ftp.c                         |  196 ++---
 Utilities/cmcurl/lib/ftp.h                         |    2 +-
 Utilities/cmcurl/lib/ftplistparser.c               |    8 +-
 Utilities/cmcurl/lib/getinfo.c                     |   29 +-
 Utilities/cmcurl/lib/hash.c                        |    6 +-
 Utilities/cmcurl/lib/hash.h                        |   15 +-
 Utilities/cmcurl/lib/hmac.c                        |   10 +-
 Utilities/cmcurl/lib/hostcheck.c                   |    9 +-
 Utilities/cmcurl/lib/hostip.c                      |    4 +-
 Utilities/cmcurl/lib/hostip.h                      |    8 +-
 Utilities/cmcurl/lib/hostip4.c                     |    2 +-
 Utilities/cmcurl/lib/http.c                        |   85 +-
 Utilities/cmcurl/lib/http2.c                       |  212 ++++-
 Utilities/cmcurl/lib/http2.h                       |    8 +
 Utilities/cmcurl/lib/http_chunks.c                 |   14 +-
 Utilities/cmcurl/lib/http_digest.c                 |   20 +-
 Utilities/cmcurl/lib/http_negotiate.c              |   16 +-
 Utilities/cmcurl/lib/http_ntlm.c                   |    4 +-
 Utilities/cmcurl/lib/http_proxy.c                  |  529 +++++------
 Utilities/cmcurl/lib/http_proxy.h                  |    4 +-
 Utilities/cmcurl/lib/if2ip.c                       |    2 +-
 Utilities/cmcurl/lib/imap.c                        |    6 +-
 Utilities/cmcurl/lib/inet_ntop.c                   |    6 +-
 Utilities/cmcurl/lib/inet_pton.c                   |    8 +-
 Utilities/cmcurl/lib/krb5.c                        |    2 +-
 Utilities/cmcurl/lib/ldap.c                        |   46 +-
 Utilities/cmcurl/lib/md4.c                         |    3 +-
 Utilities/cmcurl/lib/md5.c                         |    7 +-
 Utilities/cmcurl/lib/memdebug.c                    |    2 +-
 Utilities/cmcurl/lib/mprintf.c                     |   25 +-
 Utilities/cmcurl/lib/multi.c                       |   38 +-
 Utilities/cmcurl/lib/multihandle.h                 |    4 +-
 Utilities/cmcurl/lib/multiif.h                     |    4 +-
 Utilities/cmcurl/lib/non-ascii.c                   |    4 +-
 Utilities/cmcurl/lib/nwlib.c                       |   10 +-
 Utilities/cmcurl/lib/nwos.c                        |    8 +-
 Utilities/cmcurl/lib/pingpong.c                    |   14 +-
 Utilities/cmcurl/lib/pingpong.h                    |    2 +-
 Utilities/cmcurl/lib/pop3.c                        |    8 +-
 Utilities/cmcurl/lib/progress.c                    |   40 +-
 Utilities/cmcurl/lib/rand.c                        |  130 +++
 Utilities/cmcurl/lib/{easyif.h => rand.h}          |   26 +-
 Utilities/cmcurl/lib/rtsp.c                        |   24 +-
 Utilities/cmcurl/lib/security.c                    |   13 +-
 Utilities/cmcurl/lib/select.c                      |    2 +-
 Utilities/cmcurl/lib/select.h                      |    2 +-
 Utilities/cmcurl/lib/sendf.c                       |   21 +-
 Utilities/cmcurl/lib/sendf.h                       |    2 +
 Utilities/cmcurl/lib/setup-os400.h                 |   52 +-
 Utilities/cmcurl/lib/setup-vms.h                   |  139 +--
 Utilities/cmcurl/lib/share.h                       |    8 +-
 Utilities/cmcurl/lib/smb.c                         |   14 +-
 Utilities/cmcurl/lib/smtp.c                        |    6 +-
 Utilities/cmcurl/lib/socks.c                       |   43 +-
 Utilities/cmcurl/lib/socks.h                       |    5 +-
 Utilities/cmcurl/lib/socks_gssapi.c                |   24 +-
 Utilities/cmcurl/lib/socks_sspi.c                  |   11 +-
 Utilities/cmcurl/lib/speedcheck.c                  |    6 +-
 Utilities/cmcurl/lib/ssh.c                         |   58 +-
 Utilities/cmcurl/lib/strcase.c                     |   12 +-
 Utilities/cmcurl/lib/strcase.h                     |    1 +
 Utilities/cmcurl/lib/strdup.c                      |   23 +
 Utilities/cmcurl/lib/strdup.h                      |    1 +
 Utilities/cmcurl/lib/strerror.c                    |   32 +-
 Utilities/cmcurl/lib/strtoofft.c                   |    4 +-
 Utilities/cmcurl/lib/telnet.c                      |   23 +-
 Utilities/cmcurl/lib/tftp.c                        |    8 +-
 Utilities/cmcurl/lib/timeval.c                     |    6 +-
 Utilities/cmcurl/lib/timeval.h                     |    6 +-
 Utilities/cmcurl/lib/transfer.c                    |   14 +-
 Utilities/cmcurl/lib/url.c                         |  925 ++++++++++++++------
 Utilities/cmcurl/lib/url.h                         |   13 +
 Utilities/cmcurl/lib/urldata.h                     |  147 +++-
 Utilities/cmcurl/lib/vauth/cleartext.c             |   24 +-
 Utilities/cmcurl/lib/vauth/digest.c                |   17 +-
 Utilities/cmcurl/lib/vauth/digest_sspi.c           |    2 +-
 Utilities/cmcurl/lib/vauth/ntlm.c                  |   12 +-
 Utilities/cmcurl/lib/vauth/spnego_sspi.c           |    2 +-
 Utilities/cmcurl/lib/version.c                     |    3 +
 Utilities/cmcurl/lib/vtls/axtls.c                  |   81 +-
 Utilities/cmcurl/lib/vtls/cyassl.c                 |  105 ++-
 Utilities/cmcurl/lib/vtls/darwinssl.c              |  412 +++++----
 Utilities/cmcurl/lib/vtls/gskit.c                  |  354 ++++++--
 Utilities/cmcurl/lib/vtls/gskit.h                  |    7 +-
 Utilities/cmcurl/lib/vtls/gtls.c                   |  289 +++---
 Utilities/cmcurl/lib/vtls/gtls.h                   |    7 +-
 Utilities/cmcurl/lib/vtls/mbedtls.c                |   92 +-
 Utilities/cmcurl/lib/vtls/nss.c                    |  219 +++--
 Utilities/cmcurl/lib/vtls/nssg.h                   |    3 +
 Utilities/cmcurl/lib/vtls/openssl.c                |  398 +++++----
 Utilities/cmcurl/lib/vtls/openssl.h                |    3 +
 Utilities/cmcurl/lib/vtls/polarssl.c               |   81 +-
 Utilities/cmcurl/lib/vtls/schannel.c               |  144 +--
 Utilities/cmcurl/lib/vtls/vtls.c                   |  300 +++----
 Utilities/cmcurl/lib/vtls/vtls.h                   |   48 +-
 Utilities/cmcurl/lib/x509asn1.c                    |  194 ++--
 Utilities/cmcurl/lib/x509asn1.h                    |   26 +-
 139 files changed, 4145 insertions(+), 2525 deletions(-)
 create mode 100644 Help/release/dev/update-curl.rst
 create mode 100644 Utilities/cmcurl/lib/rand.c
 copy Utilities/cmcurl/lib/{easyif.h => rand.h} (59%)


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list