From 18812a9c3d395b368d8f3d85394b346472c8e858 Mon Sep 17 00:00:00 2001
From: Curl Upstream <curl-library@cool.haxx.se>
Date: Tue, 4 Sep 2018 23:49:50 +0200
Subject: curl 2018-09-04 (432eb5f5)

Code extracted from:

    https://github.com/curl/curl.git

at commit 432eb5f5c254ee8383b2522ce597c9219877923e (curl-7_61_1).
---
 CMake/CurlSymbolHiding.cmake       |  92 ++++-----
 CMake/CurlTests.c                  |  30 +--
 CMake/FindCARES.cmake              |  38 ++--
 CMake/FindGSS.cmake                | 410 ++++++++++++++++++-------------------
 CMake/FindLibSSH2.cmake            |  14 +-
 CMake/FindNGHTTP2.cmake            |   2 +-
 CMake/Macros.cmake                 |  62 ++----
 CMake/OtherTests.cmake             |  61 +++---
 CMake/Platforms/WindowsCache.cmake |   7 +-
 CMake/Utilities.cmake              |  41 +---
 CMake/cmake_uninstall.cmake.in     |  18 +-
 CMake/curl-config.cmake            |  59 ------
 CMake/curl-config.cmake.in         |  64 ++++++
 CMakeLists.txt                     | 285 +++++++++++++-------------
 include/curl/curl.h                |  22 +-
 include/curl/curlver.h             |   8 +-
 include/curl/system.h              |  20 +-
 include/curl/typecheck-gcc.h       |   2 +-
 lib/CMakeLists.txt                 |  36 ++--
 lib/Makefile.inc                   |   4 +-
 lib/asyn-ares.c                    |  37 ++--
 lib/asyn-thread.c                  |  14 +-
 lib/base64.c                       |   3 +-
 lib/conncache.c                    |  62 +++---
 lib/conncache.h                    |   4 +-
 lib/connect.c                      |  12 +-
 lib/content_encoding.c             |  40 ++--
 lib/cookie.c                       | 130 +++++++-----
 lib/cookie.h                       |   4 +-
 lib/curl_addrinfo.c                |   3 +-
 lib/curl_config.h.cmake            |   6 +
 lib/curl_fnmatch.c                 |  43 +++-
 lib/curl_ntlm_core.c               |   5 +-
 lib/curl_sasl.c                    |   3 +-
 lib/curl_setup.h                   |  15 +-
 lib/curl_threads.c                 |   3 +-
 lib/dict.c                         |  10 +-
 lib/easy.c                         |  34 ++-
 lib/escape.c                       |   6 +-
 lib/file.c                         |  12 +-
 lib/formdata.c                     |  16 +-
 lib/ftp.c                          |  16 +-
 lib/getinfo.c                      |  22 ++
 lib/gopher.c                       |  11 +-
 lib/hash.c                         |  11 +-
 lib/hmac.c                         |   4 +-
 lib/hostasyn.c                     |   4 +-
 lib/hostip.c                       |  38 ++--
 lib/hostip6.c                      |  35 +---
 lib/http.c                         | 226 +++++++++++++-------
 lib/http2.c                        | 211 +++++++++----------
 lib/http2.h                        |   4 +-
 lib/http_ntlm.c                    |   2 +-
 lib/http_proxy.c                   |   7 +-
 lib/imap.c                         |  16 +-
 lib/inet_ntop.c                    |   2 +-
 lib/ldap.c                         |   9 -
 lib/md5.c                          |  40 ++--
 lib/memdebug.h                     |   9 +-
 lib/mime.c                         |  53 +++--
 lib/multi.c                        | 207 +++++++++++--------
 lib/multihandle.h                  |   8 +-
 lib/netrc.c                        |   4 +-
 lib/pingpong.c                     |  10 +-
 lib/pipeline.c                     |   9 +-
 lib/pop3.c                         |   4 +-
 lib/progress.c                     |  39 ++--
 lib/progress.h                     |  13 --
 lib/psl.c                          | 111 ++++++++++
 lib/psl.h                          |  47 +++++
 lib/rand.c                         |   2 +-
 lib/rtsp.c                         |   6 +-
 lib/security.c                     |   4 +-
 lib/select.c                       |   8 +-
 lib/sendf.c                        |  48 +----
 lib/sendf.h                        |   5 +-
 lib/setopt.c                       |  43 +++-
 lib/sha256.c                       |  19 +-
 lib/share.c                        |  11 +-
 lib/share.h                        |   6 +-
 lib/smb.c                          | 105 +++++-----
 lib/smb.h                          |   1 +
 lib/smtp.c                         |   5 +-
 lib/socks.c                        |  14 +-
 lib/splay.c                        |   3 +-
 lib/ssh-libssh.c                   |  64 +++---
 lib/ssh.c                          |  45 ++--
 lib/ssh.h                          |   4 +-
 lib/strcase.h                      |   1 -
 lib/system_win32.c                 |  15 +-
 lib/telnet.c                       |  59 +++---
 lib/tftp.c                         |  27 +--
 lib/transfer.c                     |  86 +++++---
 lib/transfer.h                     |   4 +-
 lib/url.c                          | 219 ++++++++++----------
 lib/url.h                          |   3 +-
 lib/urldata.h                      |  49 +++--
 lib/vauth/digest.c                 |   6 +-
 lib/version.c                      |   2 +-
 lib/vtls/axtls.c                   |   5 +
 lib/vtls/cyassl.c                  |   4 +-
 lib/vtls/darwinssl.c               |  79 ++++++-
 lib/vtls/gskit.c                   |  32 +--
 lib/vtls/nss.c                     |  11 +-
 lib/vtls/openssl.c                 | 126 ++++++++----
 lib/vtls/schannel.c                | 205 ++++++++++++++++++-
 lib/vtls/schannel.h                |  34 +++
 lib/vtls/schannel_verify.c         |  18 +-
 lib/vtls/vtls.c                    |  13 +-
 lib/vtls/vtls.h                    |   5 +-
 lib/warnless.h                     |   3 +
 lib/x509asn1.c                     | 130 ++++++------
 112 files changed, 2573 insertions(+), 1865 deletions(-)
 delete mode 100644 CMake/curl-config.cmake
 create mode 100644 CMake/curl-config.cmake.in
 create mode 100644 lib/psl.c
 create mode 100644 lib/psl.h

diff --git a/CMake/CurlSymbolHiding.cmake b/CMake/CurlSymbolHiding.cmake
index 9f7d296..15ba46e 100644
--- a/CMake/CurlSymbolHiding.cmake
+++ b/CMake/CurlSymbolHiding.cmake
@@ -4,57 +4,57 @@ option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide al
 mark_as_advanced(CURL_HIDDEN_SYMBOLS)
 
 if(CURL_HIDDEN_SYMBOLS)
-    set(SUPPORTS_SYMBOL_HIDING FALSE)
+  set(SUPPORTS_SYMBOL_HIDING FALSE)
 
-    if(CMAKE_C_COMPILER_ID MATCHES "Clang")
-        set(SUPPORTS_SYMBOL_HIDING TRUE)
-        set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
-        set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
-    elseif(CMAKE_COMPILER_IS_GNUCC)
-        if(NOT CMAKE_VERSION VERSION_LESS 2.8.10)
-            set(GCC_VERSION ${CMAKE_C_COMPILER_VERSION})
-        else()
-            execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
-                            OUTPUT_VARIABLE GCC_VERSION)
-        endif()
-        if(NOT GCC_VERSION VERSION_LESS 3.4)
-            # note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact
-            set(SUPPORTS_SYMBOL_HIDING TRUE)
-            set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
-            set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
-        endif()
-    elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0)
-        set(SUPPORTS_SYMBOL_HIDING TRUE)
-        set(_SYMBOL_EXTERN "__global")
-        set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden")
-    elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0)
-        # note: this should probably just check for version 9.1.045 but I'm not 100% sure
-        #       so let's to it the same way autotools do.
-        set(SUPPORTS_SYMBOL_HIDING TRUE)
-        set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
-        set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
-        check_c_source_compiles("#include <stdio.h>
-            int main (void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug)
-        if(NOT _no_bug)
-            set(SUPPORTS_SYMBOL_HIDING FALSE)
-            set(_SYMBOL_EXTERN "")
-            set(_CFLAG_SYMBOLS_HIDE "")
-        endif()
-    elseif(MSVC)
-        set(SUPPORTS_SYMBOL_HIDING TRUE)
+  if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+    set(SUPPORTS_SYMBOL_HIDING TRUE)
+    set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
+    set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
+  elseif(CMAKE_COMPILER_IS_GNUCC)
+    if(NOT CMAKE_VERSION VERSION_LESS 2.8.10)
+      set(GCC_VERSION ${CMAKE_C_COMPILER_VERSION})
+    else()
+      execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
+                      OUTPUT_VARIABLE GCC_VERSION)
+    endif()
+    if(NOT GCC_VERSION VERSION_LESS 3.4)
+      # note: this is considered buggy prior to 4.0 but the autotools don't care, so let's ignore that fact
+      set(SUPPORTS_SYMBOL_HIDING TRUE)
+      set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
+      set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
     endif()
+  elseif(CMAKE_C_COMPILER_ID MATCHES "SunPro" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.0)
+    set(SUPPORTS_SYMBOL_HIDING TRUE)
+    set(_SYMBOL_EXTERN "__global")
+    set(_CFLAG_SYMBOLS_HIDE "-xldscope=hidden")
+  elseif(CMAKE_C_COMPILER_ID MATCHES "Intel" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.0)
+    # note: this should probably just check for version 9.1.045 but I'm not 100% sure
+    #       so let's to it the same way autotools do.
+    set(SUPPORTS_SYMBOL_HIDING TRUE)
+    set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
+    set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
+    check_c_source_compiles("#include <stdio.h>
+        int main (void) { printf(\"icc fvisibility bug test\"); return 0; }" _no_bug)
+    if(NOT _no_bug)
+      set(SUPPORTS_SYMBOL_HIDING FALSE)
+      set(_SYMBOL_EXTERN "")
+      set(_CFLAG_SYMBOLS_HIDE "")
+    endif()
+  elseif(MSVC)
+    set(SUPPORTS_SYMBOL_HIDING TRUE)
+  endif()
 
-    set(HIDES_CURL_PRIVATE_SYMBOLS ${SUPPORTS_SYMBOL_HIDING})
+  set(HIDES_CURL_PRIVATE_SYMBOLS ${SUPPORTS_SYMBOL_HIDING})
 elseif(MSVC)
-    if(NOT CMAKE_VERSION VERSION_LESS 3.7)
-        set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) #present since 3.4.3 but broken
-        set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
-    else()
-        message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.")
-        set(HIDES_CURL_PRIVATE_SYMBOLS TRUE)
-    endif()
-elseif()
+  if(NOT CMAKE_VERSION VERSION_LESS 3.7)
+    set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) #present since 3.4.3 but broken
     set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
+  else()
+    message(WARNING "Hiding private symbols regardless CURL_HIDDEN_SYMBOLS being disabled.")
+    set(HIDES_CURL_PRIVATE_SYMBOLS TRUE)
+  endif()
+elseif()
+  set(HIDES_CURL_PRIVATE_SYMBOLS FALSE)
 endif()
 
 set(CURL_CFLAG_SYMBOLS_HIDE ${_CFLAG_SYMBOLS_HIDE})
diff --git a/CMake/CurlTests.c b/CMake/CurlTests.c
index bc36c8e..ab244ac 100644
--- a/CMake/CurlTests.c
+++ b/CMake/CurlTests.c
@@ -507,30 +507,30 @@ main ()
 #ifdef HAVE_GLIBC_STRERROR_R
 #include <string.h>
 #include <errno.h>
+
+void check(char c) {}
+
 int
 main () {
-  char buffer[1024]; /* big enough to play with */
-  char *string =
-    strerror_r(EACCES, buffer, sizeof(buffer));
-    /* this should've returned a string */
-    if(!string || !string[0])
-      return 99;
-    return 0;
+  char buffer[1024];
+  /* This will not compile if strerror_r does not return a char* */
+  check(strerror_r(EACCES, buffer, sizeof(buffer))[0]);
+  return 0;
 }
 #endif
 #ifdef HAVE_POSIX_STRERROR_R
 #include <string.h>
 #include <errno.h>
+
+/* float, because a pointer can't be implicitly cast to float */
+void check(float f) {}
+
 int
 main () {
-  char buffer[1024]; /* big enough to play with */
-  int error =
-    strerror_r(EACCES, buffer, sizeof(buffer));
-    /* This should've returned zero, and written an error string in the
-       buffer.*/
-    if(!buffer[0] || error)
-      return 99;
-    return 0;
+  char buffer[1024];
+  /* This will not compile if strerror_r does not return an int */
+  check(strerror_r(EACCES, buffer, sizeof(buffer)));
+  return 0;
 }
 #endif
 #ifdef HAVE_FSETXATTR_6
diff --git a/CMake/FindCARES.cmake b/CMake/FindCARES.cmake
index c4ab5f1..723044a 100644
--- a/CMake/FindCARES.cmake
+++ b/CMake/FindCARES.cmake
@@ -7,36 +7,36 @@
 # also defined, but not for general use are
 # CARES_LIBRARY, where to find the c-ares library.
 
-FIND_PATH(CARES_INCLUDE_DIR ares.h
+find_path(CARES_INCLUDE_DIR ares.h
   /usr/local/include
   /usr/include
   )
 
-SET(CARES_NAMES ${CARES_NAMES} cares)
-FIND_LIBRARY(CARES_LIBRARY
+set(CARES_NAMES ${CARES_NAMES} cares)
+find_library(CARES_LIBRARY
   NAMES ${CARES_NAMES}
   PATHS /usr/lib /usr/local/lib
   )
 
-IF (CARES_LIBRARY AND CARES_INCLUDE_DIR)
-  SET(CARES_LIBRARIES ${CARES_LIBRARY})
-  SET(CARES_FOUND "YES")
-ELSE (CARES_LIBRARY AND CARES_INCLUDE_DIR)
-  SET(CARES_FOUND "NO")
-ENDIF (CARES_LIBRARY AND CARES_INCLUDE_DIR)
+if(CARES_LIBRARY AND CARES_INCLUDE_DIR)
+  set(CARES_LIBRARIES ${CARES_LIBRARY})
+  set(CARES_FOUND "YES")
+else()
+  set(CARES_FOUND "NO")
+endif()
 
 
-IF (CARES_FOUND)
-  IF (NOT CARES_FIND_QUIETLY)
-    MESSAGE(STATUS "Found c-ares: ${CARES_LIBRARIES}")
-  ENDIF (NOT CARES_FIND_QUIETLY)
-ELSE (CARES_FOUND)
-  IF (CARES_FIND_REQUIRED)
-    MESSAGE(FATAL_ERROR "Could not find c-ares library")
-  ENDIF (CARES_FIND_REQUIRED)
-ENDIF (CARES_FOUND)
+if(CARES_FOUND)
+  if(NOT CARES_FIND_QUIETLY)
+    message(STATUS "Found c-ares: ${CARES_LIBRARIES}")
+  endif()
+else()
+  if(CARES_FIND_REQUIRED)
+    message(FATAL_ERROR "Could not find c-ares library")
+  endif()
+endif()
 
-MARK_AS_ADVANCED(
+mark_as_advanced(
   CARES_LIBRARY
   CARES_INCLUDE_DIR
   )
diff --git a/CMake/FindGSS.cmake b/CMake/FindGSS.cmake
index 60dcb73..7a637fc 100644
--- a/CMake/FindGSS.cmake
+++ b/CMake/FindGSS.cmake
@@ -28,211 +28,209 @@ set(_GSS_ROOT_HINTS
 
 # try to find library using system pkg-config if user didn't specify root dir
 if(NOT GSS_ROOT_DIR AND NOT "$ENV{GSS_ROOT_DIR}")
-    if(UNIX)
-        find_package(PkgConfig QUIET)
-        pkg_search_module(_GSS_PKG ${_MIT_MODNAME} ${_HEIMDAL_MODNAME})
-        list(APPEND _GSS_ROOT_HINTS "${_GSS_PKG_PREFIX}")
-    elseif(WIN32)
-        list(APPEND _GSS_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]")
-    endif()
+  if(UNIX)
+    find_package(PkgConfig QUIET)
+    pkg_search_module(_GSS_PKG ${_MIT_MODNAME} ${_HEIMDAL_MODNAME})
+    list(APPEND _GSS_ROOT_HINTS "${_GSS_PKG_PREFIX}")
+  elseif(WIN32)
+    list(APPEND _GSS_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]")
+  endif()
 endif()
 
 if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approach.
-    find_file(_GSS_CONFIGURE_SCRIPT
-        NAMES
-            "krb5-config"
-        HINTS
-            ${_GSS_ROOT_HINTS}
-        PATH_SUFFIXES
-            bin
-        NO_CMAKE_PATH
-        NO_CMAKE_ENVIRONMENT_PATH
+  find_file(_GSS_CONFIGURE_SCRIPT
+      NAMES
+          "krb5-config"
+      HINTS
+          ${_GSS_ROOT_HINTS}
+      PATH_SUFFIXES
+          bin
+      NO_CMAKE_PATH
+      NO_CMAKE_ENVIRONMENT_PATH
+  )
+
+  # if not found in user-supplied directories, maybe system knows better
+  find_file(_GSS_CONFIGURE_SCRIPT
+      NAMES
+          "krb5-config"
+      PATH_SUFFIXES
+          bin
+  )
+
+  if(_GSS_CONFIGURE_SCRIPT)
+    execute_process(
+          COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi"
+          OUTPUT_VARIABLE _GSS_CFLAGS
+          RESULT_VARIABLE _GSS_CONFIGURE_FAILED
+      )
+    message(STATUS "CFLAGS: ${_GSS_CFLAGS}")
+    if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
+      # should also work in an odd case when multiple directories are given
+      string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
+      string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
+      string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1"_GSS_CFLAGS "${_GSS_CFLAGS}")
+
+      foreach(_flag ${_GSS_CFLAGS})
+        if(_flag MATCHES "^-I.*")
+          string(REGEX REPLACE "^-I" "" _val "${_flag}")
+          list(APPEND _GSS_INCLUDE_DIR "${_val}")
+        else()
+          list(APPEND _GSS_COMPILER_FLAGS "${_flag}")
+        endif()
+      endforeach()
+    endif()
+
+    execute_process(
+        COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi"
+        OUTPUT_VARIABLE _GSS_LIB_FLAGS
+        RESULT_VARIABLE _GSS_CONFIGURE_FAILED
     )
+    message(STATUS "LDFLAGS: ${_GSS_LIB_FLAGS}")
+
+    if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
+      # this script gives us libraries and link directories. Blah. We have to deal with it.
+      string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
+      string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
+      string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1"_GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
+
+      foreach(_flag ${_GSS_LIB_FLAGS})
+        if(_flag MATCHES "^-l.*")
+          string(REGEX REPLACE "^-l" "" _val "${_flag}")
+          list(APPEND _GSS_LIBRARIES "${_val}")
+        elseif(_flag MATCHES "^-L.*")
+          string(REGEX REPLACE "^-L" "" _val "${_flag}")
+          list(APPEND _GSS_LINK_DIRECTORIES "${_val}")
+        else()
+          list(APPEND _GSS_LINKER_FLAGS "${_flag}")
+        endif()
+      endforeach()
+    endif()
 
-    # if not found in user-supplied directories, maybe system knows better
-    find_file(_GSS_CONFIGURE_SCRIPT
-        NAMES
-            "krb5-config"
-        PATH_SUFFIXES
-            bin
+    execute_process(
+        COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version"
+        OUTPUT_VARIABLE _GSS_VERSION
+        RESULT_VARIABLE _GSS_CONFIGURE_FAILED
     )
 
-    if(_GSS_CONFIGURE_SCRIPT)
-        execute_process(
-            COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi"
-            OUTPUT_VARIABLE _GSS_CFLAGS
-            RESULT_VARIABLE _GSS_CONFIGURE_FAILED
-        )
-message(STATUS "CFLAGS: ${_GSS_CFLAGS}")
-        if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
-            # should also work in an odd case when multiple directories are given
-            string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
-            string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
-            string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1"_GSS_CFLAGS "${_GSS_CFLAGS}")
-
-            foreach(_flag ${_GSS_CFLAGS})
-                if(_flag MATCHES "^-I.*")
-                    string(REGEX REPLACE "^-I" "" _val "${_flag}")
-                    list(APPEND _GSS_INCLUDE_DIR "${_val}")
-                else()
-                    list(APPEND _GSS_COMPILER_FLAGS "${_flag}")
-                endif()
-            endforeach()
-        endif()
+    # older versions may not have the "--version" parameter. In this case we just don't care.
+    if(_GSS_CONFIGURE_FAILED)
+      set(_GSS_VERSION 0)
+    endif()
 
-        execute_process(
-            COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi"
-            OUTPUT_VARIABLE _GSS_LIB_FLAGS
-            RESULT_VARIABLE _GSS_CONFIGURE_FAILED
-        )
-message(STATUS "LDFLAGS: ${_GSS_LIB_FLAGS}")
-        if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
-            # this script gives us libraries and link directories. Blah. We have to deal with it.
-            string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
-            string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
-            string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1"_GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
-
-            foreach(_flag ${_GSS_LIB_FLAGS})
-                if(_flag MATCHES "^-l.*")
-                    string(REGEX REPLACE "^-l" "" _val "${_flag}")
-                    list(APPEND _GSS_LIBRARIES "${_val}")
-                elseif(_flag MATCHES "^-L.*")
-                    string(REGEX REPLACE "^-L" "" _val "${_flag}")
-                    list(APPEND _GSS_LINK_DIRECTORIES "${_val}")
-                else()
-                    list(APPEND _GSS_LINKER_FLAGS "${_flag}")
-                endif()
-            endforeach()
-        endif()
+    execute_process(
+        COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor"
+        OUTPUT_VARIABLE _GSS_VENDOR
+        RESULT_VARIABLE _GSS_CONFIGURE_FAILED
+    )
 
+    # older versions may not have the "--vendor" parameter. In this case we just don't care.
+    if(_GSS_CONFIGURE_FAILED)
+      set(GSS_FLAVOUR "Heimdal") # most probably, shouldn't really matter
+    else()
+      if(_GSS_VENDOR MATCHES ".*H|heimdal.*")
+        set(GSS_FLAVOUR "Heimdal")
+      else()
+        set(GSS_FLAVOUR "MIT")
+      endif()
+    endif()
 
-        execute_process(
-            COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version"
-            OUTPUT_VARIABLE _GSS_VERSION
-            RESULT_VARIABLE _GSS_CONFIGURE_FAILED
-        )
+  else() # either there is no config script or we are on platform that doesn't provide one (Windows?)
 
-        # older versions may not have the "--version" parameter. In this case we just don't care.
-        if(_GSS_CONFIGURE_FAILED)
-            set(_GSS_VERSION 0)
-        endif()
+    find_path(_GSS_INCLUDE_DIR
+        NAMES
+            "gssapi/gssapi.h"
+        HINTS
+            ${_GSS_ROOT_HINTS}
+        PATH_SUFFIXES
+            include
+            inc
+    )
 
+    if(_GSS_INCLUDE_DIR) #jay, we've found something
+      set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIR}")
+      check_include_files( "gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _GSS_HAVE_MIT_HEADERS)
 
-        execute_process(
-            COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor"
-            OUTPUT_VARIABLE _GSS_VENDOR
-            RESULT_VARIABLE _GSS_CONFIGURE_FAILED
-        )
+      if(_GSS_HAVE_MIT_HEADERS)
+        set(GSS_FLAVOUR "MIT")
+      else()
+        # prevent compiling the header - just check if we can include it
+        set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__")
+        check_include_file( "roken.h" _GSS_HAVE_ROKEN_H)
+
+        check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H)
+        if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H)
+          set(GSS_FLAVOUR "Heimdal")
+        endif()
+        set(CMAKE_REQUIRED_DEFINITIONS "")
+      endif()
+    else()
+      # I'm not convienced if this is the right way but this is what autotools do at the moment
+      find_path(_GSS_INCLUDE_DIR
+          NAMES
+              "gssapi.h"
+          HINTS
+              ${_GSS_ROOT_HINTS}
+          PATH_SUFFIXES
+              include
+              inc
+      )
+
+      if(_GSS_INCLUDE_DIR)
+        set(GSS_FLAVOUR "Heimdal")
+      endif()
+    endif()
+
+    # if we have headers, check if we can link libraries
+    if(GSS_FLAVOUR)
+      set(_GSS_LIBDIR_SUFFIXES "")
+      set(_GSS_LIBDIR_HINTS ${_GSS_ROOT_HINTS})
+      get_filename_component(_GSS_CALCULATED_POTENTIAL_ROOT "${_GSS_INCLUDE_DIR}" PATH)
+      list(APPEND _GSS_LIBDIR_HINTS ${_GSS_CALCULATED_POTENTIAL_ROOT})
 
-        # older versions may not have the "--vendor" parameter. In this case we just don't care.
-        if(_GSS_CONFIGURE_FAILED)
-            set(GSS_FLAVOUR "Heimdal") # most probably, shouldn't really matter
+      if(WIN32)
+        if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+          list(APPEND _GSS_LIBDIR_SUFFIXES "lib/AMD64")
+          if(GSS_FLAVOUR STREQUAL "MIT")
+            set(_GSS_LIBNAME "gssapi64")
+          else()
+            set(_GSS_LIBNAME "libgssapi")
+          endif()
         else()
-            if(_GSS_VENDOR MATCHES ".*H|heimdal.*")
-                set(GSS_FLAVOUR "Heimdal")
-            else()
-                set(GSS_FLAVOUR "MIT")
-            endif()
+          list(APPEND _GSS_LIBDIR_SUFFIXES "lib/i386")
+          if(GSS_FLAVOUR STREQUAL "MIT")
+            set(_GSS_LIBNAME "gssapi32")
+          else()
+            set(_GSS_LIBNAME "libgssapi")
+          endif()
         endif()
-
-    else() # either there is no config script or we are on platform that doesn't provide one (Windows?)
-
-        find_path(_GSS_INCLUDE_DIR
-            NAMES
-                "gssapi/gssapi.h"
-            HINTS
-                ${_GSS_ROOT_HINTS}
-            PATH_SUFFIXES
-                include
-                inc
-        )
-
-        if(_GSS_INCLUDE_DIR) #jay, we've found something
-            set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIR}")
-            check_include_files( "gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _GSS_HAVE_MIT_HEADERS)
-
-            if(_GSS_HAVE_MIT_HEADERS)
-                set(GSS_FLAVOUR "MIT")
-            else()
-                # prevent compiling the header - just check if we can include it
-                set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__")
-                check_include_file( "roken.h" _GSS_HAVE_ROKEN_H)
-
-                check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H)
-                if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H)
-                    set(GSS_FLAVOUR "Heimdal")
-                endif()
-                set(CMAKE_REQUIRED_DEFINITIONS "")
-            endif()
+      else()
+        list(APPEND _GSS_LIBDIR_SUFFIXES "lib;lib64") # those suffixes are not checked for HINTS
+        if(GSS_FLAVOUR STREQUAL "MIT")
+          set(_GSS_LIBNAME "gssapi_krb5")
         else()
-            # I'm not convienced if this is the right way but this is what autotools do at the moment
-            find_path(_GSS_INCLUDE_DIR
-                NAMES
-                    "gssapi.h"
-                HINTS
-                    ${_GSS_ROOT_HINTS}
-                PATH_SUFFIXES
-                    include
-                    inc
-            )
-
-            if(_GSS_INCLUDE_DIR)
-                set(GSS_FLAVOUR "Heimdal")
-            endif()
+          set(_GSS_LIBNAME "gssapi")
         endif()
+      endif()
 
-        # if we have headers, check if we can link libraries
-        if(GSS_FLAVOUR)
-            set(_GSS_LIBDIR_SUFFIXES "")
-            set(_GSS_LIBDIR_HINTS ${_GSS_ROOT_HINTS})
-            get_filename_component(_GSS_CALCULATED_POTENTIAL_ROOT "${_GSS_INCLUDE_DIR}" PATH)
-            list(APPEND _GSS_LIBDIR_HINTS ${_GSS_CALCULATED_POTENTIAL_ROOT})
-
-            if(WIN32)
-                if(CMAKE_SIZEOF_VOID_P EQUAL 8)
-                    list(APPEND _GSS_LIBDIR_SUFFIXES "lib/AMD64")
-                    if(GSS_FLAVOUR STREQUAL "MIT")
-                        set(_GSS_LIBNAME "gssapi64")
-                    else()
-                        set(_GSS_LIBNAME "libgssapi")
-                    endif()
-                else()
-                    list(APPEND _GSS_LIBDIR_SUFFIXES "lib/i386")
-                    if(GSS_FLAVOUR STREQUAL "MIT")
-                        set(_GSS_LIBNAME "gssapi32")
-                    else()
-                        set(_GSS_LIBNAME "libgssapi")
-                    endif()
-                endif()
-            else()
-                list(APPEND _GSS_LIBDIR_SUFFIXES "lib;lib64") # those suffixes are not checked for HINTS
-                if(GSS_FLAVOUR STREQUAL "MIT")
-                    set(_GSS_LIBNAME "gssapi_krb5")
-                else()
-                    set(_GSS_LIBNAME "gssapi")
-                endif()
-            endif()
-
-            find_library(_GSS_LIBRARIES
-                NAMES
-                    ${_GSS_LIBNAME}
-                HINTS
-                    ${_GSS_LIBDIR_HINTS}
-                PATH_SUFFIXES
-                    ${_GSS_LIBDIR_SUFFIXES}
-            )
-
-        endif()
+      find_library(_GSS_LIBRARIES
+          NAMES
+              ${_GSS_LIBNAME}
+          HINTS
+              ${_GSS_LIBDIR_HINTS}
+          PATH_SUFFIXES
+              ${_GSS_LIBDIR_SUFFIXES}
+      )
 
     endif()
+  endif()
 else()
-    if(_GSS_PKG_${_MIT_MODNAME}_VERSION)
-        set(GSS_FLAVOUR "MIT")
-        set(_GSS_VERSION _GSS_PKG_${_MIT_MODNAME}_VERSION)
-    else()
-        set(GSS_FLAVOUR "Heimdal")
-        set(_GSS_VERSION _GSS_PKG_${_MIT_HEIMDAL}_VERSION)
-    endif()
+  if(_GSS_PKG_${_MIT_MODNAME}_VERSION)
+    set(GSS_FLAVOUR "MIT")
+    set(_GSS_VERSION _GSS_PKG_${_MIT_MODNAME}_VERSION)
+  else()
+    set(GSS_FLAVOUR "Heimdal")
+    set(_GSS_VERSION _GSS_PKG_${_MIT_HEIMDAL}_VERSION)
+  endif()
 endif()
 
 set(GSS_INCLUDE_DIR ${_GSS_INCLUDE_DIR})
@@ -243,36 +241,34 @@ set(GSS_COMPILER_FLAGS ${_GSS_COMPILER_FLAGS})
 set(GSS_VERSION ${_GSS_VERSION})
 
 if(GSS_FLAVOUR)
+  if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal")
+    if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+      set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest")
+    else()
+      set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest")
+    endif()
 
-    if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal")
-        if(CMAKE_SIZEOF_VOID_P EQUAL 8)
-            set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest")
-        else()
-            set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest")
-        endif()
-
-        if(EXISTS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}")
-            file(STRINGS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" heimdal_version_str
-                 REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$")
+    if(EXISTS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}")
+      file(STRINGS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" heimdal_version_str
+           REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$")
 
-            string(REGEX MATCH "[0-9]\\.[^\"]+"
-                   GSS_VERSION "${heimdal_version_str}")
-        endif()
+      string(REGEX MATCH "[0-9]\\.[^\"]+"
+             GSS_VERSION "${heimdal_version_str}")
+    endif()
 
-        if(NOT GSS_VERSION)
-            set(GSS_VERSION "Heimdal Unknown")
-        endif()
-    elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT")
-        get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE)
-        if(WIN32 AND _MIT_VERSION)
-            set(GSS_VERSION "${_MIT_VERSION}")
-        else()
-            set(GSS_VERSION "MIT Unknown")
-        endif()
+    if(NOT GSS_VERSION)
+      set(GSS_VERSION "Heimdal Unknown")
     endif()
+  elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT")
+    get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE)
+    if(WIN32 AND _MIT_VERSION)
+      set(GSS_VERSION "${_MIT_VERSION}")
+    else()
+      set(GSS_VERSION "MIT Unknown")
+    endif()
+  endif()
 endif()
 
-
 include(FindPackageHandleStandardArgs)
 
 set(_GSS_REQUIRED_VARS GSS_LIBRARIES GSS_FLAVOUR)
diff --git a/CMake/FindLibSSH2.cmake b/CMake/FindLibSSH2.cmake
index 12a7c61..84822db 100644
--- a/CMake/FindLibSSH2.cmake
+++ b/CMake/FindLibSSH2.cmake
@@ -5,14 +5,14 @@
 # LIBSSH2_INCLUDE_DIR - the libssh2 include directory
 # LIBSSH2_LIBRARY - the libssh2 library name
 
-if (LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
+if(LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
   set(LibSSH2_FIND_QUIETLY TRUE)
-endif (LIBSSH2_INCLUDE_DIR AND LIBSSH2_LIBRARY)
+endif()
 
-FIND_PATH(LIBSSH2_INCLUDE_DIR libssh2.h
+find_path(LIBSSH2_INCLUDE_DIR libssh2.h
 )
 
-FIND_LIBRARY(LIBSSH2_LIBRARY NAMES ssh2
+find_library(LIBSSH2_LIBRARY NAMES ssh2
 )
 
 if(LIBSSH2_INCLUDE_DIR)
@@ -27,9 +27,9 @@ if(LIBSSH2_INCLUDE_DIR)
   string(REGEX REPLACE "^0(.+)" "\\1" LIBSSH2_VERSION_PATCH "${LIBSSH2_VERSION_PATCH}")
 
   set(LIBSSH2_VERSION "${LIBSSH2_VERSION_MAJOR}.${LIBSSH2_VERSION_MINOR}.${LIBSSH2_VERSION_PATCH}")
-endif(LIBSSH2_INCLUDE_DIR)
+endif()
 
 include(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibSSH2 DEFAULT_MSG LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY )
+find_package_handle_standard_args(LibSSH2 DEFAULT_MSG LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY )
 
-MARK_AS_ADVANCED(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY LIBSSH2_VERSION_MAJOR LIBSSH2_VERSION_MINOR LIBSSH2_VERSION_PATCH LIBSSH2_VERSION)
+mark_as_advanced(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY LIBSSH2_VERSION_MAJOR LIBSSH2_VERSION_MINOR LIBSSH2_VERSION_PATCH LIBSSH2_VERSION)
diff --git a/CMake/FindNGHTTP2.cmake b/CMake/FindNGHTTP2.cmake
index 4e566cf..348b961 100644
--- a/CMake/FindNGHTTP2.cmake
+++ b/CMake/FindNGHTTP2.cmake
@@ -14,5 +14,5 @@ find_package_handle_standard_args(NGHTTP2
       "Could NOT find NGHTTP2"
 )
 
-set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR} )
+set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR})
 set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY})
diff --git a/CMake/Macros.cmake b/CMake/Macros.cmake
index 82aadca..7f71345 100644
--- a/CMake/Macros.cmake
+++ b/CMake/Macros.cmake
@@ -5,35 +5,35 @@
 # multiple times with a sequence of possibly dependent libraries in
 # order of least-to-most-dependent.  Some libraries depend on others
 # to link correctly.
-macro(CHECK_LIBRARY_EXISTS_CONCAT LIBRARY SYMBOL VARIABLE)
+macro(check_library_exists_concat LIBRARY SYMBOL VARIABLE)
   check_library_exists("${LIBRARY};${CURL_LIBS}" ${SYMBOL} "${CMAKE_LIBRARY_PATH}"
     ${VARIABLE})
   if(${VARIABLE})
     set(CURL_LIBS ${LIBRARY} ${CURL_LIBS})
-  endif(${VARIABLE})
-endmacro(CHECK_LIBRARY_EXISTS_CONCAT)
+  endif()
+endmacro()
 
 # Check if header file exists and add it to the list.
 # This macro is intended to be called multiple times with a sequence of
 # possibly dependent header files.  Some headers depend on others to be
 # compiled correctly.
-macro(CHECK_INCLUDE_FILE_CONCAT FILE VARIABLE)
+macro(check_include_file_concat FILE VARIABLE)
   check_include_files("${CURL_INCLUDES};${FILE}" ${VARIABLE})
   if(${VARIABLE})
     set(CURL_INCLUDES ${CURL_INCLUDES} ${FILE})
     set(CURL_TEST_DEFINES "${CURL_TEST_DEFINES} -D${VARIABLE}")
-  endif(${VARIABLE})
-endmacro(CHECK_INCLUDE_FILE_CONCAT)
+  endif()
+endmacro()
 
 # For other curl specific tests, use this macro.
-macro(CURL_INTERNAL_TEST CURL_TEST)
+macro(curl_internal_test CURL_TEST)
   if(NOT DEFINED "${CURL_TEST}")
     set(MACRO_CHECK_FUNCTION_DEFINITIONS
       "-D${CURL_TEST} ${CURL_TEST_DEFINES} ${CMAKE_REQUIRED_FLAGS}")
     if(CMAKE_REQUIRED_LIBRARIES)
       set(CURL_TEST_ADD_LIBRARIES
         "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
-    endif(CMAKE_REQUIRED_LIBRARIES)
+    endif()
 
     message(STATUS "Performing Curl Test ${CURL_TEST}")
     try_compile(${CURL_TEST}
@@ -48,53 +48,17 @@ macro(CURL_INTERNAL_TEST CURL_TEST)
       file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
         "Performing Curl Test ${CURL_TEST} passed with the following output:\n"
         "${OUTPUT}\n")
-    else(${CURL_TEST})
+    else()
       message(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
       set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
       file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
         "Performing Curl Test ${CURL_TEST} failed with the following output:\n"
         "${OUTPUT}\n")
-    endif(${CURL_TEST})
-  endif()
-endmacro(CURL_INTERNAL_TEST)
-
-macro(CURL_INTERNAL_TEST_RUN CURL_TEST)
-  if(NOT DEFINED "${CURL_TEST}_COMPILE")
-    set(MACRO_CHECK_FUNCTION_DEFINITIONS
-      "-D${CURL_TEST} ${CMAKE_REQUIRED_FLAGS}")
-    if(CMAKE_REQUIRED_LIBRARIES)
-      set(CURL_TEST_ADD_LIBRARIES
-        "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
-    endif(CMAKE_REQUIRED_LIBRARIES)
-
-    message(STATUS "Performing Curl Test ${CURL_TEST}")
-    try_run(${CURL_TEST} ${CURL_TEST}_COMPILE
-      ${CMAKE_BINARY_DIR}
-      ${CMAKE_CURRENT_SOURCE_DIR}/CMake/CurlTests.c
-      CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
-      "${CURL_TEST_ADD_LIBRARIES}"
-      OUTPUT_VARIABLE OUTPUT)
-    if(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
-      set(${CURL_TEST} 1 CACHE INTERNAL "Curl test ${FUNCTION}")
-      message(STATUS "Performing Curl Test ${CURL_TEST} - Success")
-    else(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
-      message(STATUS "Performing Curl Test ${CURL_TEST} - Failed")
-      set(${CURL_TEST} "" CACHE INTERNAL "Curl test ${FUNCTION}")
-      file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
-        "Performing Curl Test ${CURL_TEST} failed with the following output:\n"
-        "${OUTPUT}")
-      if(${CURL_TEST}_COMPILE)
-        file(APPEND
-          "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
-          "There was a problem running this test\n")
-      endif(${CURL_TEST}_COMPILE)
-      file(APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log"
-        "\n\n")
-    endif(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
+    endif()
   endif()
-endmacro(CURL_INTERNAL_TEST_RUN)
+endmacro()
 
-macro(CURL_NROFF_CHECK)
+macro(curl_nroff_check)
   find_program(NROFF NAMES gnroff nroff)
   if(NROFF)
     # Need a way to write to stdin, this will do
@@ -121,4 +85,4 @@ macro(CURL_NROFF_CHECK)
   else()
     message(WARNING "Found no *nroff program")
   endif()
-endmacro(CURL_NROFF_CHECK)
+endmacro()
diff --git a/CMake/OtherTests.cmake b/CMake/OtherTests.cmake
index 989f04e..ce6d3e1 100644
--- a/CMake/OtherTests.cmake
+++ b/CMake/OtherTests.cmake
@@ -5,8 +5,8 @@ set(_source_epilogue "#undef inline")
 macro(add_header_include check header)
   if(${check})
     set(_source_epilogue "${_source_epilogue}\n#include <${header}>")
-  endif(${check})
-endmacro(add_header_include)
+  endif()
+endmacro()
 
 set(signature_call_conv)
 if(HAVE_WINDOWS_H)
@@ -19,10 +19,10 @@ if(HAVE_WINDOWS_H)
   if(HAVE_LIBWS2_32)
     set(CMAKE_REQUIRED_LIBRARIES ws2_32)
   endif()
-else(HAVE_WINDOWS_H)
+else()
   add_header_include(HAVE_SYS_TYPES_H "sys/types.h")
   add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
-endif(HAVE_WINDOWS_H)
+endif()
 
 check_c_source_compiles("${_source_epilogue}
 int main(void) {
@@ -64,13 +64,13 @@ if(curl_cv_recv)
                   set(RECV_TYPE_RETV "${recv_retv}")
                   set(HAVE_RECV 1)
                   set(curl_cv_func_recv_done 1)
-                endif(curl_cv_func_recv_test)
-              endif(NOT curl_cv_func_recv_done)
-            endforeach(recv_arg4)
-          endforeach(recv_arg3)
-        endforeach(recv_arg2)
-      endforeach(recv_arg1)
-    endforeach(recv_retv)
+                endif()
+              endif()
+            endforeach()
+          endforeach()
+        endforeach()
+      endforeach()
+    endforeach()
   else()
     string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG1 "${curl_cv_func_recv_args}")
     string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*$" "\\1" RECV_TYPE_ARG2 "${curl_cv_func_recv_args}")
@@ -81,10 +81,10 @@ if(curl_cv_recv)
 
   if("${curl_cv_func_recv_args}" STREQUAL "unknown")
     message(FATAL_ERROR "Cannot find proper types to use for recv args")
-  endif("${curl_cv_func_recv_args}" STREQUAL "unknown")
-else(curl_cv_recv)
+  endif()
+else()
   message(FATAL_ERROR "Unable to link function recv")
-endif(curl_cv_recv)
+endif()
 set(curl_cv_func_recv_args "${curl_cv_func_recv_args}" CACHE INTERNAL "Arguments for recv")
 set(HAVE_RECV 1)
 
@@ -130,13 +130,13 @@ if(curl_cv_send)
                   set(SEND_TYPE_RETV "${send_retv}")
                   set(HAVE_SEND 1)
                   set(curl_cv_func_send_done 1)
-                endif(curl_cv_func_send_test)
-              endif(NOT curl_cv_func_send_done)
-            endforeach(send_arg4)
-          endforeach(send_arg3)
-        endforeach(send_arg2)
-      endforeach(send_arg1)
-    endforeach(send_retv)
+                endif()
+              endif()
+            endforeach()
+          endforeach()
+        endforeach()
+      endforeach()
+    endforeach()
   else()
     string(REGEX REPLACE "^([^,]*),[^,]*,[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG1 "${curl_cv_func_send_args}")
     string(REGEX REPLACE "^[^,]*,([^,]*),[^,]*,[^,]*,[^,]*,[^,]*$" "\\1" SEND_TYPE_ARG2 "${curl_cv_func_send_args}")
@@ -148,11 +148,11 @@ if(curl_cv_send)
 
   if("${curl_cv_func_send_args}" STREQUAL "unknown")
     message(FATAL_ERROR "Cannot find proper types to use for send args")
-  endif("${curl_cv_func_send_args}" STREQUAL "unknown")
+  endif()
   set(SEND_QUAL_ARG2 "const")
-else(curl_cv_send)
+else()
   message(FATAL_ERROR "Unable to link function send")
-endif(curl_cv_send)
+endif()
 set(curl_cv_func_send_args "${curl_cv_func_send_args}" CACHE INTERNAL "Arguments for send")
 set(HAVE_SEND 1)
 
@@ -184,7 +184,7 @@ 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)
+  endif()
   check_c_source_runs("
     #ifdef HAVE_SYS_POLL_H
     #  include <sys/poll.h>
@@ -199,7 +199,7 @@ set(CMAKE_REQUIRED_FLAGS)
 if(HAVE_SIGNAL_H)
   set(CMAKE_REQUIRED_FLAGS "-DHAVE_SIGNAL_H")
   set(CMAKE_EXTRA_INCLUDE_FILES "signal.h")
-endif(HAVE_SIGNAL_H)
+endif()
 check_type_size("sig_atomic_t" SIZEOF_SIG_ATOMIC_T)
 if(HAVE_SIZEOF_SIG_ATOMIC_T)
   check_c_source_compiles("
@@ -213,8 +213,8 @@ if(HAVE_SIZEOF_SIG_ATOMIC_T)
     }" HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
   if(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
     set(HAVE_SIG_ATOMIC_T_VOLATILE 1)
-  endif(NOT HAVE_SIG_ATOMIC_T_NOT_VOLATILE)
-endif(HAVE_SIZEOF_SIG_ATOMIC_T)
+  endif()
+endif()
 
 if(HAVE_WINDOWS_H)
   set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h)
@@ -222,11 +222,10 @@ else()
   set(CMAKE_EXTRA_INCLUDE_FILES)
   if(HAVE_SYS_SOCKET_H)
     set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h)
-  endif(HAVE_SYS_SOCKET_H)
+  endif()
 endif()
 
 check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE)
 if(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
   set(HAVE_STRUCT_SOCKADDR_STORAGE 1)
-endif(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
-
+endif()
diff --git a/CMake/Platforms/WindowsCache.cmake b/CMake/Platforms/WindowsCache.cmake
index 6fc2991..cafaec2 100644
--- a/CMake/Platforms/WindowsCache.cmake
+++ b/CMake/Platforms/WindowsCache.cmake
@@ -118,8 +118,7 @@ if(NOT UNIX)
 
     set(HAVE_SIGACTION 0)
     set(HAVE_MACRO_SIGSETJMP 0)
-  else(WIN32)
+  else()
     message("This file should be included on Windows platform only")
-  endif(WIN32)
-endif(NOT UNIX)
-
+  endif()
+endif()
diff --git a/CMake/Utilities.cmake b/CMake/Utilities.cmake
index 005b166..5cb1d44 100644
--- a/CMake/Utilities.cmake
+++ b/CMake/Utilities.cmake
@@ -1,44 +1,13 @@
 # File containing various utilities
 
-# Converts a CMake list to a string containing elements separated by spaces
-function(TO_LIST_SPACES _LIST_NAME OUTPUT_VAR)
-  set(NEW_LIST_SPACE)
-  foreach(ITEM ${${_LIST_NAME}})
-    set(NEW_LIST_SPACE "${NEW_LIST_SPACE} ${ITEM}")
-  endforeach()
-  string(STRIP ${NEW_LIST_SPACE} NEW_LIST_SPACE)
-  set(${OUTPUT_VAR} "${NEW_LIST_SPACE}" PARENT_SCOPE)
-endfunction()
-
-# Appends a lis of item to a string which is a space-separated list, if they don't already exist.
-function(LIST_SPACES_APPEND_ONCE LIST_NAME)
-  string(REPLACE " " ";" _LIST ${${LIST_NAME}})
-  list(APPEND _LIST ${ARGN})
-  list(REMOVE_DUPLICATES _LIST)
-  to_list_spaces(_LIST NEW_LIST_SPACE)
-  set(${LIST_NAME} "${NEW_LIST_SPACE}" PARENT_SCOPE)
-endfunction()
-
-# Convenience function that does the same as LIST(FIND ...) but with a TRUE/FALSE return value.
-# Ex: IN_STR_LIST(MY_LIST "Searched item" WAS_FOUND)
-function(IN_STR_LIST LIST_NAME ITEM_SEARCHED RETVAL)
-  list(FIND ${LIST_NAME} ${ITEM_SEARCHED} FIND_POS)
-  if(${FIND_POS} EQUAL -1)
-    set(${RETVAL} FALSE PARENT_SCOPE)
-  else()
-    set(${RETVAL} TRUE PARENT_SCOPE)
-  endif()
-endfunction()
-
 # Returns a list of arguments that evaluate to true
-function(collect_true output_var output_count_var)
-  set(${output_var})
+function(count_true output_count_var)
+  set(lst)
   foreach(option_var IN LISTS ARGN)
     if(${option_var})
-      list(APPEND ${output_var} ${option_var})
+      list(APPEND lst ${option_var})
     endif()
   endforeach()
-  set(${output_var} ${${output_var}} PARENT_SCOPE)
-  list(LENGTH ${output_var} ${output_count_var})
-  set(${output_count_var} ${${output_count_var}} PARENT_SCOPE)
+  list(LENGTH lst lst_len)
+  set(${output_count_var} ${lst_len} PARENT_SCOPE)
 endfunction()
diff --git a/CMake/cmake_uninstall.cmake.in b/CMake/cmake_uninstall.cmake.in
index d00a516..db8e536 100644
--- a/CMake/cmake_uninstall.cmake.in
+++ b/CMake/cmake_uninstall.cmake.in
@@ -1,11 +1,11 @@
 if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
   message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
-endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+endif()
 
-if (NOT DEFINED CMAKE_INSTALL_PREFIX)
-  set (CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@")
-endif ()
- message(${CMAKE_INSTALL_PREFIX})
+if(NOT DEFINED CMAKE_INSTALL_PREFIX)
+  set(CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@")
+endif()
+message(${CMAKE_INSTALL_PREFIX})
 
 file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
 string(REGEX REPLACE "\n" ";" files "${files}")
@@ -19,8 +19,8 @@ foreach(file ${files})
       )
     if(NOT "${rm_retval}" STREQUAL 0)
       message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
-    endif(NOT "${rm_retval}" STREQUAL 0)
-  else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+    endif()
+  else()
     message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
-  endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
-endforeach(file)
+  endif()
+endforeach()
diff --git a/CMake/curl-config.cmake b/CMake/curl-config.cmake
deleted file mode 100644
index 119332c..0000000
--- a/CMake/curl-config.cmake
+++ /dev/null
@@ -1,59 +0,0 @@
-
-get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
-
-if(NOT CURL_FIND_COMPONENTS)
-    set(CURL_FIND_COMPONENTS curl libcurl)
-    if(CURL_FIND_REQUIRED)
-        set(CURL_FIND_REQUIRED_curl TRUE)
-        set(CURL_FIND_REQUIRED_libcurl TRUE)
-    endif()
-endif()
-
-set(_curl_missing_components)
-foreach(_comp ${CURL_FIND_COMPONENTS})
-    if(EXISTS "${_DIR}/${_comp}-target.cmake")
-        include("${_DIR}/${_comp}-target.cmake")
-        set(CURL_${_comp}_FOUND TRUE)
-    else()
-        set(CURL_${_comp}_FOUND FALSE)
-        if(CURL_FIND_REQUIRED_${_comp})
-            set(CURL_FOUND FALSE)
-            list(APPEND _curl_missing_components ${_comp})
-        endif()
-    endif()
-endforeach()
-
-if(_curl_missing_components)
-    set(CURL_NOT_FOUND_MESSAGE "Following required components not found: " ${_curl_missing_components})
-else()
-    if(TARGET CURL::libcurl)
-        string(TOUPPER "${CMAKE_BUILD_TYPE}" _curl_current_config)
-        if(NOT _curl_current_config)
-            set(_curl_current_config "NOCONFIG")
-        endif()
-        get_target_property(_curl_configurations CURL::libcurl IMPORTED_CONFIGURATIONS)
-        list(FIND _curl_configurations "${_curl_current_config}" _i)
-        if(_i LESS 0)
-            set(_curl_config "RELEASE")
-            list(FIND _curl_configurations "${_curl_current_config}" _i)
-            if(_i LESS 0)
-                set(_curl_config "NOCONFIG")
-                list(FIND _curl_configurations "${_curl_current_config}" _i)
-            endif()
-        endif()
-
-        if(_i LESS 0)
-            set(_curl_current_config "") # let CMake pick config at random
-        else()
-	    set(_curl_current_config "_${_curl_current_config}")
-        endif()
-
-        get_target_property(CURL_INCLUDE_DIRS CURL::libcurl INTERFACE_INCLUDE_DIRECTORIES)
-        get_target_property(CURL_LIBRARIES CURL::libcurl "LOCATION${_curl_current_config}")
-        set(_curl_current_config)
-        set(_curl_configurations)
-        set(_i)
-    endif()
-endif()
-
-unset(_curl_missing_components)
diff --git a/CMake/curl-config.cmake.in b/CMake/curl-config.cmake.in
new file mode 100644
index 0000000..73e04c6
--- /dev/null
+++ b/CMake/curl-config.cmake.in
@@ -0,0 +1,64 @@
+
+get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
+
+if(NOT CURL_FIND_COMPONENTS)
+  set(CURL_FIND_COMPONENTS curl libcurl)
+  if(CURL_FIND_REQUIRED)
+    set(CURL_FIND_REQUIRED_curl TRUE)
+    set(CURL_FIND_REQUIRED_libcurl TRUE)
+  endif()
+endif()
+
+include(CMakeFindDependencyMacro)
+if(CURL_FIND_REQUIRED_libcurl)
+    find_dependency(OpenSSL "@OPENSSL_VERSION_MAJOR@")
+endif()
+
+set(_curl_missing_components)
+foreach(_comp ${CURL_FIND_COMPONENTS})
+  if(EXISTS "${_DIR}/${_comp}-target.cmake")
+    include("${_DIR}/${_comp}-target.cmake")
+    set(CURL_${_comp}_FOUND TRUE)
+  else()
+    set(CURL_${_comp}_FOUND FALSE)
+    if(CURL_FIND_REQUIRED_${_comp})
+      set(CURL_FOUND FALSE)
+      list(APPEND _curl_missing_components ${_comp})
+    endif()
+  endif()
+endforeach()
+
+if(_curl_missing_components)
+  set(CURL_NOT_FOUND_MESSAGE "Following required components not found: " ${_curl_missing_components})
+else()
+  if(TARGET CURL::libcurl)
+    string(TOUPPER "${CMAKE_BUILD_TYPE}" _curl_current_config)
+    if(NOT _curl_current_config)
+      set(_curl_current_config "NOCONFIG")
+    endif()
+    get_target_property(_curl_configurations CURL::libcurl IMPORTED_CONFIGURATIONS)
+    list(FIND _curl_configurations "${_curl_current_config}" _i)
+    if(_i LESS 0)
+      set(_curl_config "RELEASE")
+      list(FIND _curl_configurations "${_curl_current_config}" _i)
+      if(_i LESS 0)
+        set(_curl_config "NOCONFIG")
+        list(FIND _curl_configurations "${_curl_current_config}" _i)
+      endif()
+    endif()
+
+    if(_i LESS 0)
+      set(_curl_current_config "") # let CMake pick config at random
+    else()
+      set(_curl_current_config "_${_curl_current_config}")
+    endif()
+
+    get_target_property(CURL_INCLUDE_DIRS CURL::libcurl INTERFACE_INCLUDE_DIRECTORIES)
+    get_target_property(CURL_LIBRARIES CURL::libcurl "LOCATION${_curl_current_config}")
+    set(_curl_current_config)
+    set(_curl_configurations)
+    set(_i)
+  endif()
+endif()
+
+unset(_curl_missing_components)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bf25b1f..e6dbb73 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,24 +38,24 @@
 # 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.12 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.4 FATAL_ERROR)
 set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
 include(Utilities)
 include(Macros)
 include(CMakeDependentOption)
 include(CheckCCompilerFlag)
 
-project( CURL C )
+project(CURL C)
 
 message(WARNING "the curl cmake build system is poorly maintained. Be aware")
 
-file (READ ${CURL_SOURCE_DIR}/include/curl/curlver.h CURL_VERSION_H_CONTENTS)
-string (REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*"
+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]+"
+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})
+string(REGEX REPLACE "[^0]+0x" "" CURL_VERSION_NUM ${CURL_VERSION_NUM})
 
 include_regular_expression("^.*$")    # Sukender: Is it necessary?
 
@@ -71,19 +71,19 @@ set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
 set(OS "\"${CMAKE_SYSTEM_NAME}\"")
 
 include_directories(${PROJECT_BINARY_DIR}/include/curl)
-include_directories( ${CURL_SOURCE_DIR}/include )
+include_directories(${CURL_SOURCE_DIR}/include)
 
 option(CURL_WERROR "Turn compiler warnings into errors" OFF)
 option(PICKY_COMPILER "Enable picky compiler options" ON)
 option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
-option(CURL_STATICLIB "Set to ON to build libcurl with static linking." OFF)
+option(BUILD_SHARED_LIBS "Build shared libraries" ON)
 option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
 if(WIN32)
   option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF)
   option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when building against modern SDKs while still requiring compatibility with older Windows versions, such as Windows XP, Windows Server 2003 etc." ON)
 endif()
 
-CMAKE_DEPENDENT_OPTION(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup"
+cmake_dependent_option(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded DNS lookup"
         ON "NOT ENABLE_ARES"
         OFF)
 
@@ -91,19 +91,19 @@ option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF)
 option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" OFF)
 
 if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
-  if (PICKY_COMPILER)
-    foreach (_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers)
+  if(PICKY_COMPILER)
+    foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits -Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered -Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wvla -Wdouble-promotion -Wno-system-headers)
       # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
       # test result in.
-      CHECK_C_COMPILER_FLAG(${_CCOPT} OPT${_CCOPT})
+      check_c_compiler_flag(${_CCOPT} OPT${_CCOPT})
       if(OPT${_CCOPT})
         set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}")
       endif()
     endforeach()
-  endif(PICKY_COMPILER)
-endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
+  endif()
+endif()
 
-if (ENABLE_DEBUG)
+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>)
@@ -113,12 +113,14 @@ if (ENABLE_DEBUG)
   set(ENABLE_CURLDEBUG ON)
 endif()
 
-if (ENABLE_CURLDEBUG)
+if(ENABLE_CURLDEBUG)
   set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS CURLDEBUG)
 endif()
 
 # For debug libs and exes, add "-d" postfix
-set(CMAKE_DEBUG_POSTFIX "-d" CACHE STRING "Set debug library postfix")
+if(NOT DEFINED CMAKE_DEBUG_POSTFIX)
+  set(CMAKE_DEBUG_POSTFIX "-d")
+endif()
 
 # initialize CURL_LIBS
 set(CURL_LIBS "")
@@ -126,7 +128,7 @@ set(CURL_LIBS "")
 if(ENABLE_ARES)
   set(USE_ARES 1)
   find_package(CARES REQUIRED)
-  list(APPEND CURL_LIBS ${CARES_LIBRARY} )
+  list(APPEND CURL_LIBS ${CARES_LIBRARY})
   set(CURL_LIBS ${CURL_LIBS} ${CARES_LIBRARY})
 endif()
 
@@ -203,10 +205,10 @@ if(ENABLE_IPV6 AND NOT WIN32)
   endif()
 endif()
 
-CURL_NROFF_CHECK()
+curl_nroff_check()
 find_package(Perl)
 
-CMAKE_DEPENDENT_OPTION(ENABLE_MANUAL "to provide the built-in manual"
+cmake_dependent_option(ENABLE_MANUAL "to provide the built-in manual"
     ON "NROFF_USEFUL;PERL_FOUND"
     OFF)
 
@@ -230,28 +232,28 @@ endif()
 # Disable warnings on Borland to avoid changing 3rd party code.
 if(BORLAND)
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-")
-endif(BORLAND)
+endif()
 
 # 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)
+endif()
 
 # Include all the necessary files for macros
-include (CheckFunctionExists)
-include (CheckIncludeFile)
-include (CheckIncludeFiles)
-include (CheckLibraryExists)
-include (CheckSymbolExists)
-include (CheckTypeSize)
-include (CheckCSourceCompiles)
-include (CMakeDependentOption)
+include(CheckFunctionExists)
+include(CheckIncludeFile)
+include(CheckIncludeFiles)
+include(CheckLibraryExists)
+include(CheckSymbolExists)
+include(CheckTypeSize)
+include(CheckCSourceCompiles)
+include(CMakeDependentOption)
 
 # 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)
+endif()
 
 if(ENABLE_THREADED_RESOLVER)
   find_package(Threads REQUIRED)
@@ -274,11 +276,11 @@ 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)
+endif()
 
 if(NOT NOT_NEED_LIBNSL)
   check_library_exists_concat("nsl"    gethostbyname  HAVE_LIBNSL)
-endif(NOT NOT_NEED_LIBNSL)
+endif()
 
 check_function_exists(gethostname HAVE_GETHOSTNAME)
 
@@ -307,14 +309,14 @@ if(WIN32 OR CMAKE_USE_DARWINSSL OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS)
 endif()
 option(CMAKE_USE_OPENSSL "Use OpenSSL code. Experimental" ${openssl_default})
 
-collect_true(enabled_ssl_options enabled_ssl_options_count
+count_true(enabled_ssl_options_count
   CMAKE_USE_WINSSL
   CMAKE_USE_DARWINSSL
   CMAKE_USE_OPENSSL
   CMAKE_USE_MBEDTLS
 )
-if(enabled_ssl_options_count GREATER 1)
-  message(FATAL_ERROR "Multiple SSL options specified: ${enabled_ssl_options}. Please pick at most one and disable the rest.")
+if(enabled_ssl_options_count GREATER "1")
+  set(CURL_WITH_MULTI_SSL ON)
 endif()
 
 if(CMAKE_USE_WINSSL)
@@ -350,11 +352,10 @@ if(CMAKE_USE_OPENSSL)
   set(USE_OPENSSL ON)
   set(HAVE_LIBCRYPTO ON)
   set(HAVE_LIBSSL ON)
-  list(APPEND CURL_LIBS ${OPENSSL_LIBRARIES})
-  include_directories(${OPENSSL_INCLUDE_DIR})
+  list(APPEND CURL_LIBS OpenSSL::SSL OpenSSL::Crypto)
+
   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/rsa.h"    HAVE_OPENSSL_RSA_H)
@@ -474,7 +475,6 @@ if(NOT CURL_DISABLE_LDAP)
       endif()
     endif()
   endif()
-
 endif()
 
 # No ldap, no ldaps.
@@ -554,9 +554,8 @@ if(CMAKE_USE_LIBSSH2)
     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)
+  endif()
+endif()
 
 option(CMAKE_USE_GSSAPI "Use GSSAPI implementation (right now only Heimdal is supported with CMake build)" OFF)
 mark_as_advanced(CMAKE_USE_GSSAPI)
@@ -625,7 +624,6 @@ else()
   unset(USE_UNIX_SOCKETS CACHE)
 endif()
 
-
 #
 # CA handling
 #
@@ -637,67 +635,66 @@ set(CURL_CA_PATH "auto" CACHE STRING
     "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
 
 if("${CURL_CA_BUNDLE}" STREQUAL "")
-    message(FATAL_ERROR "Invalid value of CURL_CA_BUNDLE. Use 'none', 'auto' or file path.")
+  message(FATAL_ERROR "Invalid value of CURL_CA_BUNDLE. Use 'none', 'auto' or file path.")
 elseif("${CURL_CA_BUNDLE}" STREQUAL "none")
-    unset(CURL_CA_BUNDLE CACHE)
+  unset(CURL_CA_BUNDLE CACHE)
 elseif("${CURL_CA_BUNDLE}" STREQUAL "auto")
-    unset(CURL_CA_BUNDLE CACHE)
-    set(CURL_CA_BUNDLE_AUTODETECT TRUE)
+  unset(CURL_CA_BUNDLE CACHE)
+  set(CURL_CA_BUNDLE_AUTODETECT TRUE)
 else()
-    set(CURL_CA_BUNDLE_SET TRUE)
+  set(CURL_CA_BUNDLE_SET TRUE)
 endif()
 
 if("${CURL_CA_PATH}" STREQUAL "")
-    message(FATAL_ERROR "Invalid value of CURL_CA_PATH. Use 'none', 'auto' or directory path.")
+  message(FATAL_ERROR "Invalid value of CURL_CA_PATH. Use 'none', 'auto' or directory path.")
 elseif("${CURL_CA_PATH}" STREQUAL "none")
-    unset(CURL_CA_PATH CACHE)
+  unset(CURL_CA_PATH CACHE)
 elseif("${CURL_CA_PATH}" STREQUAL "auto")
-    unset(CURL_CA_PATH CACHE)
-    set(CURL_CA_PATH_AUTODETECT TRUE)
+  unset(CURL_CA_PATH CACHE)
+  set(CURL_CA_PATH_AUTODETECT TRUE)
 else()
-    set(CURL_CA_PATH_SET TRUE)
+  set(CURL_CA_PATH_SET TRUE)
 endif()
 
 if(CURL_CA_BUNDLE_SET AND CURL_CA_PATH_AUTODETECT)
-    # Skip autodetection of unset CA path because CA bundle is set explicitly
+  # Skip autodetection of unset CA path because CA bundle is set explicitly
 elseif(CURL_CA_PATH_SET AND CURL_CA_BUNDLE_AUTODETECT)
-    # Skip autodetection of unset CA bundle because CA path is set explicitly
+  # Skip autodetection of unset CA bundle because CA path is set explicitly
 elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT)
-    # first try autodetecting a CA bundle, then a CA path
-
-    if(CURL_CA_BUNDLE_AUTODETECT)
-        set(SEARCH_CA_BUNDLE_PATHS
-            /etc/ssl/certs/ca-certificates.crt
-            /etc/pki/tls/certs/ca-bundle.crt
-            /usr/share/ssl/certs/ca-bundle.crt
-            /usr/local/share/certs/ca-root-nss.crt
-            /etc/ssl/cert.pem)
-
-        foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS})
-            if(EXISTS "${SEARCH_CA_BUNDLE_PATH}")
-                message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}")
-                set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}")
-                set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
-                break()
-            endif()
-        endforeach()
-    endif()
+  # first try autodetecting a CA bundle, then a CA path
+
+  if(CURL_CA_BUNDLE_AUTODETECT)
+    set(SEARCH_CA_BUNDLE_PATHS
+        /etc/ssl/certs/ca-certificates.crt
+        /etc/pki/tls/certs/ca-bundle.crt
+        /usr/share/ssl/certs/ca-bundle.crt
+        /usr/local/share/certs/ca-root-nss.crt
+        /etc/ssl/cert.pem)
+
+    foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS})
+      if(EXISTS "${SEARCH_CA_BUNDLE_PATH}")
+        message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}")
+        set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}")
+        set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
+        break()
+      endif()
+    endforeach()
+  endif()
 
-    if(CURL_CA_PATH_AUTODETECT AND (NOT CURL_CA_PATH_SET))
-        if(EXISTS "/etc/ssl/certs")
-            set(CURL_CA_PATH "/etc/ssl/certs")
-            set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
-        endif()
+  if(CURL_CA_PATH_AUTODETECT AND (NOT CURL_CA_PATH_SET))
+    if(EXISTS "/etc/ssl/certs")
+      set(CURL_CA_PATH "/etc/ssl/certs")
+      set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
     endif()
+  endif()
 endif()
 
 if(CURL_CA_PATH_SET AND NOT USE_OPENSSL AND NOT USE_MBEDTLS)
-    message(FATAL_ERROR
-            "CA path only supported by OpenSSL, GnuTLS or mbed TLS. "
-            "Set CURL_CA_PATH=none or enable one of those TLS backends.")
+  message(FATAL_ERROR
+          "CA path only supported by OpenSSL, GnuTLS or mbed TLS. "
+          "Set CURL_CA_PATH=none or enable one of those TLS backends.")
 endif()
 
-
 # Check for header files
 if(NOT UNIX)
   check_include_file_concat("windows.h"      HAVE_WINDOWS_H)
@@ -707,7 +704,7 @@ if(NOT UNIX)
   if(NOT CURL_WINDOWS_SSPI AND USE_OPENSSL)
     set(CURL_LIBS ${CURL_LIBS} "crypt32")
   endif()
-endif(NOT UNIX)
+endif()
 
 check_include_file_concat("stdio.h"          HAVE_STDIO_H)
 check_include_file_concat("inttypes.h"       HAVE_INTTYPES_H)
@@ -790,17 +787,17 @@ check_type_size("time_t"  SIZEOF_TIME_T)
 if(NOT HAVE_SIZEOF_SSIZE_T)
   if(SIZEOF_LONG EQUAL SIZEOF_SIZE_T)
     set(ssize_t long)
-  endif(SIZEOF_LONG EQUAL SIZEOF_SIZE_T)
+  endif()
   if(NOT ssize_t AND SIZEOF___INT64 EQUAL SIZEOF_SIZE_T)
     set(ssize_t __int64)
-  endif(NOT ssize_t AND SIZEOF___INT64 EQUAL SIZEOF_SIZE_T)
-endif(NOT HAVE_SIZEOF_SSIZE_T)
+  endif()
+endif()
 # off_t is sized later, after the HAVE_FILE_OFFSET_BITS test
 
 if(HAVE_SIZEOF_LONG_LONG)
   set(HAVE_LONGLONG 1)
   set(HAVE_LL 1)
-endif(HAVE_SIZEOF_LONG_LONG)
+endif()
 
 find_file(RANDOM_FILE urandom /dev)
 mark_as_advanced(RANDOM_FILE)
@@ -832,7 +829,7 @@ 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)
+endif()
 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)
@@ -848,6 +845,7 @@ 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(getpwuid_r    "${CURL_INCLUDES}" HAVE_GETPWUID_R)
 check_symbol_exists(geteuid       "${CURL_INCLUDES}" HAVE_GETEUID)
 check_symbol_exists(utime         "${CURL_INCLUDES}" HAVE_UTIME)
 check_symbol_exists(gmtime_r      "${CURL_INCLUDES}" HAVE_GMTIME_R)
@@ -860,7 +858,7 @@ 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)
+endif()
 check_symbol_exists(uname          "${CURL_INCLUDES}" HAVE_UNAME)
 check_symbol_exists(strtoll        "${CURL_INCLUDES}" HAVE_STRTOLL)
 check_symbol_exists(_strtoi64      "${CURL_INCLUDES}" HAVE__STRTOI64)
@@ -894,35 +892,35 @@ if(WIN32)
     add_definitions(-D_WIN32_WINNT=0x0501)
   endif()
 else()
-    check_function_exists(inet_pton HAVE_INET_PTON)
+  check_function_exists(inet_pton HAVE_INET_PTON)
 endif()
 
 check_symbol_exists(fsetxattr "${CURL_INCLUDES}" HAVE_FSETXATTR)
 if(HAVE_FSETXATTR)
   foreach(CURL_TEST HAVE_FSETXATTR_5 HAVE_FSETXATTR_6)
-    curl_internal_test_run(${CURL_TEST})
-  endforeach(CURL_TEST)
-endif(HAVE_FSETXATTR)
+    curl_internal_test(${CURL_TEST})
+  endforeach()
+endif()
 
 # 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)
+endif()
 
 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)
+    endif()
+  endif()
+endif()
 
 # 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)
+endif()
 
 # Do curl specific tests
 foreach(CURL_TEST
@@ -960,12 +958,12 @@ foreach(CURL_TEST
     HAVE_FILE_OFFSET_BITS
     )
   curl_internal_test(${CURL_TEST})
-endforeach(CURL_TEST)
+endforeach()
 
 if(HAVE_FILE_OFFSET_BITS)
   set(_FILE_OFFSET_BITS 64)
   set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
-endif(HAVE_FILE_OFFSET_BITS)
+endif()
 check_type_size("off_t"  SIZEOF_OFF_T)
 
 # include this header to get the type
@@ -980,8 +978,8 @@ foreach(CURL_TEST
     HAVE_GLIBC_STRERROR_R
     HAVE_POSIX_STRERROR_R
     )
-  curl_internal_test_run(${CURL_TEST})
-endforeach(CURL_TEST)
+  curl_internal_test(${CURL_TEST})
+endforeach()
 
 # Check for reentrant
 foreach(CURL_TEST
@@ -995,9 +993,9 @@ foreach(CURL_TEST
   if(NOT ${CURL_TEST})
     if(${CURL_TEST}_REENTRANT)
       set(NEED_REENTRANT 1)
-    endif(${CURL_TEST}_REENTRANT)
-  endif(NOT ${CURL_TEST})
-endforeach(CURL_TEST)
+    endif()
+  endif()
+endforeach()
 
 if(NEED_REENTRANT)
   foreach(CURL_TEST
@@ -1010,32 +1008,32 @@ if(NEED_REENTRANT)
     set(${CURL_TEST} 0)
     if(${CURL_TEST}_REENTRANT)
       set(${CURL_TEST} 1)
-    endif(${CURL_TEST}_REENTRANT)
-  endforeach(CURL_TEST)
-endif(NEED_REENTRANT)
+    endif()
+  endforeach()
+endif()
 
 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)
+endif()
 
 # Some other minor tests
 
 if(NOT HAVE_IN_ADDR_T)
   set(in_addr_t "unsigned long")
-endif(NOT HAVE_IN_ADDR_T)
+endif()
 
 # Fix libz / zlib.h
 
 if(NOT CURL_SPECIAL_LIBZ)
   if(NOT HAVE_LIBZ)
     set(HAVE_ZLIB_H 0)
-  endif(NOT HAVE_LIBZ)
+  endif()
 
   if(NOT HAVE_ZLIB_H)
     set(HAVE_LIBZ 0)
-  endif(NOT HAVE_ZLIB_H)
-endif(NOT CURL_SPECIAL_LIBZ)
+  endif()
+endif()
 
 # Check for nonblocking
 set(HAVE_DISABLED_NONBLOCKING 1)
@@ -1044,16 +1042,13 @@ if(HAVE_FIONBIO 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)
+endif()
 
 if(RETSIGTYPE_TEST)
   set(RETSIGTYPE void)
-else(RETSIGTYPE_TEST)
+else()
   set(RETSIGTYPE int)
-endif(RETSIGTYPE_TEST)
+endif()
 
 if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
   include(CheckCCompilerFlag)
@@ -1063,13 +1058,13 @@ if(CMAKE_COMPILER_IS_GNUCC AND APPLE)
     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)
+    else()
       set(MPRINTF_COMPILE_FLAGS "-Wno-long-double")
-    endif(MPRINTF_COMPILE_FLAGS)
+    endif()
     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)
+  endif()
+endif()
 
 if(HAVE_SOCKLEN_T)
   set(CURL_TYPEOF_CURL_SOCKLEN_T "socklen_t")
@@ -1104,19 +1099,25 @@ include(CMake/OtherTests.cmake)
 
 add_definitions(-DHAVE_CONFIG_H)
 
-# For windows, all compilers used by cmake should support large files
+# For Windows, all compilers used by CMake should support large files
 if(WIN32)
   set(USE_WIN32_LARGE_FILES ON)
-endif(WIN32)
+
+  # Use the manifest embedded in the Windows Resource
+  set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DCURL_EMBED_MANIFEST")
+endif()
 
 if(MSVC)
+  # Disable default manifest added by CMake
+  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
+
   add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
   if(CMAKE_C_FLAGS MATCHES "/W[0-4]")
     string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
-  else(CMAKE_C_FLAGS MATCHES "/W[0-4]")
+  else()
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
-  endif(CMAKE_C_FLAGS MATCHES "/W[0-4]")
-endif(MSVC)
+  endif()
+endif()
 
 if(CURL_WERROR)
   if(MSVC_VERSION)
@@ -1125,7 +1126,7 @@ if(CURL_WERROR)
     # this assumes clang or gcc style options
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
   endif()
-endif(CURL_WERROR)
+endif()
 
 # Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it).
 function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
@@ -1144,9 +1145,9 @@ function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
 endfunction()
 
 if(WIN32 AND NOT CYGWIN)
-    set(CURL_INSTALL_CMAKE_DIR CMake)
+  set(CURL_INSTALL_CMAKE_DIR CMake)
 else()
-    set(CURL_INSTALL_CMAKE_DIR lib/cmake/curl)
+  set(CURL_INSTALL_CMAKE_DIR lib/cmake/curl)
 endif()
 
 if(USE_MANUAL)
@@ -1246,11 +1247,12 @@ set(CONFIGURE_OPTIONS       "")
 # TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB?
 set(CPPFLAG_CURL_STATICLIB  "")
 set(CURLVERSION             "${CURL_VERSION}")
-set(ENABLE_SHARED           "yes")
-if(CURL_STATICLIB)
-  set(ENABLE_STATIC         "yes")
-else()
+if(BUILD_SHARED_LIBS)
+  set(ENABLE_SHARED         "yes")
   set(ENABLE_STATIC         "no")
+else()
+  set(ENABLE_SHARED         "no")
+  set(ENABLE_STATIC         "yes")
 endif()
 set(exec_prefix             "\${prefix}")
 set(includedir              "\${prefix}/include")
@@ -1274,6 +1276,9 @@ set(REQUIRE_LIB_DEPS        "no")
 set(VERSIONNUM              "${CURL_VERSION_NUM}")
 
 # Finally generate a "curl-config" matching this config
+# Use:
+# * ENABLE_SHARED
+# * ENABLE_STATIC
 configure_file("${CURL_SOURCE_DIR}/curl-config.in"
                "${CURL_BINARY_DIR}/curl-config" @ONLY)
 install(FILES "${CURL_BINARY_DIR}/curl-config"
@@ -1307,9 +1312,9 @@ write_basic_package_version_file(
     COMPATIBILITY SameMajorVersion
 )
 
-configure_file(CMake/curl-config.cmake
+configure_file(CMake/curl-config.cmake.in
         "${PROJECT_BINARY_DIR}/curl-config.cmake"
-        COPYONLY
+        @ONLY
 )
 
 install(
diff --git a/include/curl/curl.h b/include/curl/curl.h
index 3fd4ca8..067b34d 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -691,6 +691,7 @@ typedef enum {
  * 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_BEARER       - HTTP Bearer token authentication
  * CURLAUTH_ONLY         - Use together with a single other type to force no
  *                         authentication or just that single type
  * CURLAUTH_ANY          - All fine types set
@@ -708,6 +709,7 @@ typedef enum {
 #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_BEARER       (((unsigned long)1)<<6)
 #define CURLAUTH_ONLY         (((unsigned long)1)<<31)
 #define CURLAUTH_ANY          (~CURLAUTH_DIGEST_IE)
 #define CURLAUTH_ANYSAFE      (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE))
@@ -1847,6 +1849,13 @@ typedef enum {
   /* shuffle addresses before use when DNS returns multiple */
   CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275),
 
+  /* Specify which TLS 1.3 ciphers suites to use */
+  CINIT(TLS13_CIPHERS, STRINGPOINT, 276),
+  CINIT(PROXY_TLS13_CIPHERS, STRINGPOINT, 277),
+
+  /* Disallow specifying username/login in URL. */
+  CINIT(DISALLOW_USERNAME_IN_URL, LONG, 278),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
@@ -2527,7 +2536,17 @@ typedef enum {
   CURLINFO_SCHEME           = CURLINFO_STRING + 49,
   /* Fill in new entries below here! */
 
-  CURLINFO_LASTONE          = 49
+  /* Preferably these would be defined conditionally based on the
+     sizeof curl_off_t being 64-bits */
+  CURLINFO_TOTAL_TIME_T     = CURLINFO_OFF_T + 50,
+  CURLINFO_NAMELOOKUP_TIME_T = CURLINFO_OFF_T + 51,
+  CURLINFO_CONNECT_TIME_T   = CURLINFO_OFF_T + 52,
+  CURLINFO_PRETRANSFER_TIME_T = CURLINFO_OFF_T + 53,
+  CURLINFO_STARTTRANSFER_TIME_T = CURLINFO_OFF_T + 54,
+  CURLINFO_REDIRECT_TIME_T  = CURLINFO_OFF_T + 55,
+  CURLINFO_APPCONNECT_TIME_T = CURLINFO_OFF_T + 56,
+
+  CURLINFO_LASTONE          = 56
 } CURLINFO;
 
 /* CURLINFO_RESPONSE_CODE is the new name for the option previously known as
@@ -2570,6 +2589,7 @@ typedef enum {
   CURL_LOCK_DATA_DNS,
   CURL_LOCK_DATA_SSL_SESSION,
   CURL_LOCK_DATA_CONNECT,
+  CURL_LOCK_DATA_PSL,
   CURL_LOCK_DATA_LAST
 } curl_lock_data;
 
diff --git a/include/curl/curlver.h b/include/curl/curlver.h
index 26f2371..12b2f9f 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.60.0-DEV"
+#define LIBCURL_VERSION "7.61.1-DEV"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 60
-#define LIBCURL_VERSION_PATCH 0
+#define LIBCURL_VERSION_MINOR 61
+#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 0x073C00
+#define LIBCURL_VERSION_NUM 0x073D01
 
 /*
  * This is the date and time when the full source package was created. The
diff --git a/include/curl/system.h b/include/curl/system.h
index eac4cfe..a54fd58 100644
--- a/include/curl/system.h
+++ b/include/curl/system.h
@@ -320,6 +320,24 @@
 #  define CURL_PULL_SYS_TYPES_H      1
 #  define CURL_PULL_SYS_SOCKET_H     1
 
+#elif defined(__xlc__) /* IBM xlc compiler */
+#  if !defined(_LP64)
+#    define CURL_TYPEOF_CURL_OFF_T     long long
+#    define CURL_FORMAT_CURL_OFF_T     "lld"
+#    define CURL_FORMAT_CURL_OFF_TU    "llu"
+#    define CURL_SUFFIX_CURL_OFF_T     LL
+#    define CURL_SUFFIX_CURL_OFF_TU    ULL
+#  else
+#    define CURL_TYPEOF_CURL_OFF_T     long
+#    define CURL_FORMAT_CURL_OFF_T     "ld"
+#    define CURL_FORMAT_CURL_OFF_TU    "lu"
+#    define CURL_SUFFIX_CURL_OFF_T     L
+#    define CURL_SUFFIX_CURL_OFF_TU    UL
+#  endif
+#  define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
+#  define CURL_PULL_SYS_TYPES_H      1
+#  define CURL_PULL_SYS_SOCKET_H     1
+
 /* ===================================== */
 /*    KEEP MSVC THE PENULTIMATE ENTRY    */
 /* ===================================== */
@@ -344,7 +362,7 @@
 /*    KEEP GENERIC GCC THE LAST ENTRY    */
 /* ===================================== */
 
-#elif defined(__GNUC__)
+#elif defined(__GNUC__) && !defined(_SCO_DS)
 #  if !defined(__LP64__) &&                                             \
   (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) ||      \
    defined(__ppc__) || defined(__powerpc__) || defined(__arm__) ||      \
diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h
index 3a0f253..a6f6386 100644
--- a/include/curl/typecheck-gcc.h
+++ b/include/curl/typecheck-gcc.h
@@ -428,7 +428,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
  * == or whatsoever.
  */
 
-/* XXX: should evaluate to true iff expr is a pointer */
+/* XXX: should evaluate to true if expr is a pointer */
 #define _curl_is_any_ptr(expr)                                                \
   (sizeof(expr) == sizeof(void *))
 
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 1fabdba..87cbe81 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -1,5 +1,13 @@
 set(LIB_NAME libcurl)
 
+if(BUILD_SHARED_LIBS)
+  set(CURL_STATICLIB NO)
+else()
+  set(CURL_STATICLIB YES)
+endif()
+
+# Use:
+# * CURL_STATICLIB
 configure_file(curl_config.h.cmake
   ${CMAKE_CURRENT_BINARY_DIR}/curl_config.h)
 
@@ -59,28 +67,23 @@ if(USE_ARES)
   include_directories(${CARES_INCLUDE_DIR})
 endif()
 
-if(CURL_STATICLIB)
-  # Static lib
-  set(CURL_USER_DEFINED_DYNAMIC_OR_STATIC STATIC)
-else()
-  # DLL / so dynamic lib
-  set(CURL_USER_DEFINED_DYNAMIC_OR_STATIC SHARED)
-endif()
-
 add_library(
   ${LIB_NAME}
-  ${CURL_USER_DEFINED_DYNAMIC_OR_STATIC}
   ${HHEADERS} ${CSOURCES}
   )
 
-if(MSVC AND CURL_STATICLIB)
+if(MSVC AND NOT BUILD_SHARED_LIBS)
   set_target_properties(${LIB_NAME} PROPERTIES STATIC_LIBRARY_FLAGS ${CMAKE_EXE_LINKER_FLAGS})
 endif()
 
+if(NOT BUILD_SHARED_LIBS)
+    set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB)
+endif()
+
 target_link_libraries(${LIB_NAME} ${CURL_LIBS})
 
 if(WIN32)
-  add_definitions( -D_USRDLL )
+  add_definitions(-D_USRDLL)
 endif()
 
 set_target_properties(${LIB_NAME} PROPERTIES COMPILE_DEFINITIONS BUILDING_LIBCURL)
@@ -95,21 +98,14 @@ set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
 set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "")
 
 if(WIN32)
-  if(NOT CURL_STATICLIB)
+  if(BUILD_SHARED_LIBS)
     # Add "_imp" as a suffix before the extension to avoid conflicting with the statically linked "libcurl.lib"
     set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib")
-
-    set_target_properties (${LIB_NAME} PROPERTIES
-       DEBUG_POSTFIX "-d"
-       # Note: no postfix for release variants, let user choose what style of release he wants
-       # MINSIZEREL_POSTFIX "-z"
-       # RELWITHDEBINFO_POSTFIX "-g"
-       )
   endif()
 endif()
 
 target_include_directories(${LIB_NAME} INTERFACE
-	$<INSTALL_INTERFACE:include>)
+  $<INSTALL_INTERFACE:include>)
 
 install(TARGETS ${LIB_NAME}
   EXPORT libcurl-target
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index 61c2341..76ca6d0 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -54,7 +54,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.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      \
-  mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c
+  mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c
 
 LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
   formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h         \
@@ -74,7 +74,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.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 rand.h mime.h curl_sha256.h setopt.h     \
-  curl_path.h curl_ctype.h curl_range.h
+  curl_path.h curl_ctype.h curl_range.h psl.h
 
 LIB_RCFILES = libcurl.rc
 
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index aa581a4..5cfb260 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -312,22 +312,25 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
     conn->async.os_specific;
   CURLcode result = CURLE_OK;
 
-  *dns = NULL;
+  if(dns)
+    *dns = NULL;
 
   waitperform(conn, 0);
 
   if(res && !res->num_pending) {
-    (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
-    /* temp_ai ownership is moved to the connection, so we need not free-up
-       them */
-    res->temp_ai = NULL;
+    if(dns) {
+      (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
+      /* temp_ai ownership is moved to the connection, so we need not free-up
+         them */
+      res->temp_ai = NULL;
+    }
     if(!conn->async.dns) {
       failf(data, "Could not resolve: %s (%s)",
             conn->async.hostname, ares_strerror(conn->async.status));
       result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
         CURLE_COULDNT_RESOLVE_HOST;
     }
-    else
+    else if(dns)
       *dns = conn->async.dns;
 
     destroy_async_data(&conn->async);
@@ -390,7 +393,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
       timeout_ms = 1000;
 
     waitperform(conn, timeout_ms);
-    result = Curl_resolver_is_resolved(conn, &temp_entry);
+    result = Curl_resolver_is_resolved(conn, entry?&temp_entry:NULL);
 
     if(result || conn->async.done)
       break;
@@ -472,17 +475,19 @@ static void query_completed_cb(void *arg,  /* (struct connectdata *) */
     return;
 
   res = (struct ResolverResults *)conn->async.os_specific;
-  res->num_pending--;
+  if(res) {
+    res->num_pending--;
 
-  if(CURL_ASYNC_SUCCESS == status) {
-    Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
-    if(ai) {
-      compound_results(res, ai);
+    if(CURL_ASYNC_SUCCESS == status) {
+      Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
+      if(ai) {
+        compound_results(res, ai);
+      }
     }
+    /* A successful result overwrites any previous error */
+    if(res->last_status != ARES_SUCCESS)
+      res->last_status = status;
   }
-  /* A successful result overwrites any previous error */
-  if(res->last_status != ARES_SUCCESS)
-    res->last_status = status;
 }
 
 /*
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index b11fab2..2a59294 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -182,8 +182,6 @@ static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn)
   return &(((struct thread_data *)conn->async.os_specific)->tsd);
 }
 
-#define CONN_THREAD_SYNC_DATA(conn) &(((conn)->async.os_specific)->tsd);
-
 /* Destroy resolver thread synchronization data */
 static
 void destroy_thread_sync_data(struct thread_sync_data * tsd)
@@ -481,8 +479,10 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
   DEBUGASSERT(conn && td);
 
   /* wait for the thread to resolve the name */
-  if(Curl_thread_join(&td->thread_hnd))
-    result = getaddrinfo_complete(conn);
+  if(Curl_thread_join(&td->thread_hnd)) {
+    if(entry)
+      result = getaddrinfo_complete(conn);
+  }
   else
     DEBUGASSERT(0);
 
@@ -572,10 +572,10 @@ int Curl_resolver_getsock(struct connectdata *conn,
   (void)socks;
   (void)numsocks;
   ms = Curl_timediff(Curl_now(), reslv->start);
-  if(ms < 10)
-    milli = ms/3;
+  if(ms < 3)
+    milli = 0;
   else if(ms <= 50)
-    milli = 10;
+    milli = ms/3;
   else if(ms <= 250)
     milli = 50;
   else
diff --git a/lib/base64.c b/lib/base64.c
index 204a227..6370e4c 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -49,13 +49,12 @@ static size_t decodeQuantum(unsigned char *dest, const char *src)
   unsigned long i, x = 0;
 
   for(i = 0, s = src; i < 4; i++, s++) {
-    unsigned long v = 0;
-
     if(*s == '=') {
       x = (x << 6);
       padding++;
     }
     else {
+      unsigned long v = 0;
       p = base64;
 
       while(*p && (*p != *s)) {
diff --git a/lib/conncache.c b/lib/conncache.c
index b8f5444..6fbf3b1 100644
--- a/lib/conncache.c
+++ b/lib/conncache.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <linus@haxx.se>
- * Copyright (C) 2012 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -63,10 +63,9 @@
 
 static void conn_llist_dtor(void *user, void *element)
 {
-  struct connectdata *data = element;
+  struct connectdata *conn = element;
   (void)user;
-
-  data->bundle = NULL;
+  conn->bundle = NULL;
 }
 
 static CURLcode bundle_create(struct Curl_easy *data,
@@ -96,14 +95,13 @@ static void bundle_destroy(struct connectbundle *cb_ptr)
 }
 
 /* Add a connection to a bundle */
-static CURLcode bundle_add_conn(struct connectbundle *cb_ptr,
-                                struct connectdata *conn)
+static void bundle_add_conn(struct connectbundle *cb_ptr,
+                            struct connectdata *conn)
 {
   Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn,
                          &conn->bundle_node);
   conn->bundle = cb_ptr;
   cb_ptr->num_connections++;
-  return CURLE_OK;
 }
 
 /* Remove a connection from a bundle */
@@ -263,7 +261,7 @@ static void conncache_remove_bundle(struct conncache *connc,
 CURLcode Curl_conncache_add_conn(struct conncache *connc,
                                  struct connectdata *conn)
 {
-  CURLcode result;
+  CURLcode result = CURLE_OK;
   struct connectbundle *bundle;
   struct connectbundle *new_bundle = NULL;
   struct Curl_easy *data = conn->data;
@@ -290,19 +288,13 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
     bundle = new_bundle;
   }
 
-  result = bundle_add_conn(bundle, conn);
-  if(result) {
-    if(new_bundle)
-      conncache_remove_bundle(data->state.conn_cache, new_bundle);
-    goto unlock;
-  }
-
+  bundle_add_conn(bundle, conn);
   conn->connection_id = connc->next_connection_id++;
   connc->num_conn++;
 
   DEBUGF(infof(conn->data, "Added connection %ld. "
-               "The cache now contains %" CURL_FORMAT_CURL_OFF_TU " members\n",
-               conn->connection_id, (curl_off_t) connc->num_conn));
+               "The cache now contains %zu members\n",
+               conn->connection_id, connc->num_conn));
 
   unlock:
   CONN_UNLOCK(data);
@@ -320,7 +312,7 @@ void Curl_conncache_remove_conn(struct connectdata *conn, bool lock)
      due to a failed connection attempt, before being added to a bundle */
   if(bundle) {
     if(lock) {
-      CONN_LOCK(conn->data);
+      CONN_LOCK(data);
     }
     bundle_remove_conn(bundle, conn);
     if(bundle->num_connections == 0)
@@ -328,12 +320,11 @@ void Curl_conncache_remove_conn(struct connectdata *conn, bool lock)
     conn->bundle = NULL; /* removed from it */
     if(connc) {
       connc->num_conn--;
-      DEBUGF(infof(conn->data, "The cache now contains %"
-                   CURL_FORMAT_CURL_OFF_TU " members\n",
-                   (curl_off_t) connc->num_conn));
+      DEBUGF(infof(data, "The cache now contains %zu members\n",
+                   connc->num_conn));
     }
     if(lock) {
-      CONN_UNLOCK(conn->data);
+      CONN_UNLOCK(data);
     }
   }
 }
@@ -441,18 +432,11 @@ bool Curl_conncache_return_conn(struct connectdata *conn)
     infof(data, "Connection cache is full, closing the oldest one.\n");
 
     conn_candidate = Curl_conncache_extract_oldest(data);
-
     if(conn_candidate) {
-      /* Set the connection's owner correctly */
-      conn_candidate->data = data;
-
       /* the winner gets the honour of being disconnected */
-      (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
+      (void)Curl_disconnect(data, conn_candidate, /* dead_connection */ FALSE);
     }
   }
-  CONN_LOCK(data);
-  conn->inuse = FALSE; /* Mark the connection unused */
-  CONN_UNLOCK(data);
 
   return (conn_candidate == conn) ? FALSE : TRUE;
 
@@ -486,7 +470,7 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
   while(curr) {
     conn = curr->ptr;
 
-    if(!conn->inuse) {
+    if(!CONN_INUSE(conn)) {
       /* Set higher score for the age passed since the connection was used */
       score = Curl_timediff(now, conn->now);
 
@@ -501,9 +485,9 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
     /* remove it to prevent another thread from nicking it */
     bundle_remove_conn(bundle, conn_candidate);
     data->state.conn_cache->num_conn--;
-    DEBUGF(infof(data, "The cache now contains %"
-                 CURL_FORMAT_CURL_OFF_TU " members\n",
-                 (curl_off_t) data->state.conn_cache->num_conn));
+    DEBUGF(infof(data, "The cache now contains %zu members\n",
+                 data->state.conn_cache->num_conn));
+    conn_candidate->data = data; /* associate! */
   }
 
   return conn_candidate;
@@ -544,7 +528,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
     while(curr) {
       conn = curr->ptr;
 
-      if(!conn->inuse) {
+      if(!CONN_INUSE(conn)) {
         /* Set higher score for the age passed since the connection was used */
         score = Curl_timediff(now, conn->now);
 
@@ -563,9 +547,9 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
     /* remove it to prevent another thread from nicking it */
     bundle_remove_conn(bundle_candidate, conn_candidate);
     connc->num_conn--;
-    DEBUGF(infof(data, "The cache now contains %"
-                 CURL_FORMAT_CURL_OFF_TU " members\n",
-                 (curl_off_t) connc->num_conn));
+    DEBUGF(infof(data, "The cache now contains %zu members\n",
+                 connc->num_conn));
+    conn_candidate->data = data; /* associate! */
   }
   CONN_UNLOCK(data);
 
@@ -586,7 +570,7 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
                                      pointer */
     /* This will remove the connection from the cache */
     connclose(conn, "kill all");
-    (void)Curl_disconnect(conn, FALSE);
+    (void)Curl_disconnect(connc->closure_handle, conn, FALSE);
     sigpipe_restore(&pipe_st);
 
     conn = Curl_conncache_find_first_connection(connc);
diff --git a/lib/conncache.h b/lib/conncache.h
index d8ad80f..eedd7a8 100644
--- a/lib/conncache.h
+++ b/lib/conncache.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2015 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2015 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <linus@haxx.se>
  *
  * This software is licensed as described in the file COPYING, which
@@ -63,7 +63,7 @@ size_t Curl_conncache_bundle_size(struct connectdata *conn);
 
 bool Curl_conncache_return_conn(struct connectdata *conn);
 CURLcode Curl_conncache_add_conn(struct conncache *connc,
-                                 struct connectdata *conn);
+                                 struct connectdata *conn) WARN_UNUSED_RESULT;
 void Curl_conncache_remove_conn(struct connectdata *conn,
                                 bool lock);
 bool Curl_conncache_foreach(struct Curl_easy *data,
diff --git a/lib/connect.c b/lib/connect.c
index 1a27ae1..41f2202 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -1237,8 +1237,6 @@ static int conn_is_conn(struct connectdata *conn, void *param)
 curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
                                   struct connectdata **connp)
 {
-  curl_socket_t sockfd;
-
   DEBUGASSERT(data);
 
   /* this works for an easy handle:
@@ -1261,15 +1259,15 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
       return CURL_SOCKET_BAD;
     }
 
-    if(connp)
+    if(connp) {
       /* only store this if the caller cares for it */
       *connp = c;
-    sockfd = c->sock[FIRSTSOCKET];
+      c->data = data;
+    }
+    return c->sock[FIRSTSOCKET];
   }
   else
     return CURL_SOCKET_BAD;
-
-  return sockfd;
 }
 
 /*
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index 7c979ef..6d47537 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -71,13 +71,13 @@
 #define RESERVED     0xE0 /* bits 5..7: reserved */
 
 typedef enum {
-  ZLIB_UNINIT,          /* uninitialized */
-  ZLIB_INIT,            /* initialized */
-  ZLIB_INFLATING,       /* Inflating started. */
-  ZLIB_GZIP_HEADER,     /* reading gzip header */
-  ZLIB_GZIP_TRAILER,    /* reading gzip trailer */
-  ZLIB_GZIP_INFLATING,  /* inflating gzip stream */
-  ZLIB_INIT_GZIP        /* initialized in transparent gzip mode */
+  ZLIB_UNINIT,               /* uninitialized */
+  ZLIB_INIT,                 /* initialized */
+  ZLIB_INFLATING,            /* inflating started. */
+  ZLIB_EXTERNAL_TRAILER,     /* reading external trailer */
+  ZLIB_GZIP_HEADER,          /* reading gzip header */
+  ZLIB_GZIP_INFLATING,       /* inflating gzip stream */
+  ZLIB_INIT_GZIP             /* initialized in transparent gzip mode */
 } zlibInitState;
 
 /* Writer parameters. */
@@ -150,8 +150,8 @@ static CURLcode process_trailer(struct connectdata *conn, zlib_params *zp)
   if(result || !zp->trailerlen)
     result = exit_zlib(conn, z, &zp->zlib_init, result);
   else {
-    /* Only occurs for gzip with zlib < 1.2.0.4. */
-    zp->zlib_init = ZLIB_GZIP_TRAILER;
+    /* Only occurs for gzip with zlib < 1.2.0.4 or raw deflate. */
+    zp->zlib_init = ZLIB_EXTERNAL_TRAILER;
   }
   return result;
 }
@@ -163,7 +163,6 @@ static CURLcode inflate_stream(struct connectdata *conn,
   z_stream *z = &zp->z;         /* zlib state structure */
   uInt nread = z->avail_in;
   Bytef *orig_in = z->next_in;
-  int status;                   /* zlib status */
   bool done = FALSE;
   CURLcode result = CURLE_OK;   /* Curl_client_write status */
   char *decomp;                 /* Put the decompressed data here. */
@@ -184,13 +183,20 @@ static CURLcode inflate_stream(struct connectdata *conn,
   /* because the buffer size is fixed, iteratively decompress and transfer to
      the client via downstream_write function. */
   while(!done) {
+    int status;                   /* zlib status */
     done = TRUE;
 
     /* (re)set buffer for decompressed output for every iteration */
     z->next_out = (Bytef *) decomp;
     z->avail_out = DSIZ;
 
+#ifdef Z_BLOCK
+    /* Z_BLOCK is only available in zlib ver. >= 1.2.0.5 */
     status = inflate(z, Z_BLOCK);
+#else
+    /* fallback for zlib ver. < 1.2.0.5 */
+    status = inflate(z, Z_SYNC_FLUSH);
+#endif
 
     /* Flush output data if some. */
     if(z->avail_out != DSIZ) {
@@ -227,6 +233,7 @@ static CURLcode inflate_stream(struct connectdata *conn,
           z->next_in = orig_in;
           z->avail_in = nread;
           zp->zlib_init = ZLIB_INFLATING;
+          zp->trailerlen = 4; /* Tolerate up to 4 unknown trailer bytes. */
           done = FALSE;
           break;
         }
@@ -281,6 +288,9 @@ static CURLcode deflate_unencode_write(struct connectdata *conn,
   z->next_in = (Bytef *) buf;
   z->avail_in = (uInt) nbytes;
 
+  if(zp->zlib_init == ZLIB_EXTERNAL_TRAILER)
+    return process_trailer(conn, zp);
+
   /* Now uncompress the data */
   return inflate_stream(conn, writer, ZLIB_INFLATING);
 }
@@ -526,7 +536,7 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
   }
   break;
 
-  case ZLIB_GZIP_TRAILER:
+  case ZLIB_EXTERNAL_TRAILER:
     z->next_in = (Bytef *) buf;
     z->avail_in = (uInt) nbytes;
     return process_trailer(conn, zp);
@@ -755,7 +765,6 @@ char *Curl_all_content_encodings(void)
   const content_encoding * const *cep;
   const content_encoding *ce;
   char *ace;
-  char *p;
 
   for(cep = encodings; *cep; cep++) {
     ce = *cep;
@@ -768,7 +777,7 @@ char *Curl_all_content_encodings(void)
 
   ace = malloc(len);
   if(ace) {
-    p = ace;
+    char *p = ace;
     for(cep = encodings; *cep; cep++) {
       ce = *cep;
       if(!strcasecompare(ce->name, CONTENT_ENCODING_DEFAULT)) {
@@ -915,10 +924,9 @@ void Curl_unencode_cleanup(struct connectdata *conn)
 static const content_encoding *find_encoding(const char *name, size_t len)
 {
   const content_encoding * const *cep;
-  const content_encoding *ce;
 
   for(cep = encodings; *cep; cep++) {
-    ce = *cep;
+    const content_encoding *ce = *cep;
     if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
        (ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
       return ce;
diff --git a/lib/cookie.c b/lib/cookie.c
index 2c028b3..da49c2a 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -40,7 +40,7 @@ struct Cookie *Curl_cookie_add(struct Curl_easy *data,
         received from a server.
 
         The function need to replace previously stored lines that this new
-        line superceeds.
+        line supersedes.
 
         It may remove lines that are expired.
 
@@ -84,12 +84,9 @@ Example set of cookies:
 
 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
 
-#ifdef USE_LIBPSL
-# include <libpsl.h>
-#endif
-
 #include "urldata.h"
 #include "cookie.h"
+#include "psl.h"
 #include "strtok.h"
 #include "sendf.h"
 #include "slist.h"
@@ -253,9 +250,9 @@ static const char *get_top_domain(const char * const domain, size_t *outlen)
   len = strlen(domain);
   last = memrchr(domain, '.', len);
   if(last) {
-    first = memrchr(domain, '.', (size_t) (last - domain));
+    first = memrchr(domain, '.', (last - domain));
     if(first)
-      len -= (size_t) (++first - domain);
+      len -= (++first - domain);
   }
 
   if(outlen)
@@ -379,13 +376,13 @@ static void strstore(char **str, const char *newstr)
  */
 static void remove_expired(struct CookieInfo *cookies)
 {
-  struct Cookie *co, *nx, *pv;
+  struct Cookie *co, *nx;
   curl_off_t now = (curl_off_t)time(NULL);
   unsigned int i;
 
   for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+    struct Cookie *pv = NULL;
     co = cookies->cookies[i];
-    pv = NULL;
     while(co) {
       nx = co->next;
       if(co->expires && co->expires < now) {
@@ -406,6 +403,12 @@ static void remove_expired(struct CookieInfo *cookies)
   }
 }
 
+/* Make sure domain contains a dot or is localhost. */
+static bool bad_domain(const char *domain)
+{
+  return !strchr(domain, '.') && !strcasecompare(domain, "localhost");
+}
+
 /****************************************************************************
  *
  * Curl_cookie_add()
@@ -442,10 +445,6 @@ Curl_cookie_add(struct Curl_easy *data,
   bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
   size_t myhash;
 
-#ifdef USE_LIBPSL
-  const psl_ctx_t *psl;
-#endif
-
 #ifdef CURL_DISABLE_VERBOSE_STRINGS
   (void)data;
 #endif
@@ -497,7 +496,7 @@ Curl_cookie_add(struct Curl_easy *data,
              name + contents. Chrome and Firefox support 4095 or 4096 bytes
              combo. */
           freecookie(co);
-          infof(data, "oversized cookie dropped, name/val %d + %d bytes\n",
+          infof(data, "oversized cookie dropped, name/val %zu + %zu bytes\n",
                 nlen, len);
           return NULL;
         }
@@ -585,13 +584,8 @@ Curl_cookie_add(struct Curl_easy *data,
            * TLD or otherwise "protected" suffix. To reduce risk, we require a
            * dot OR the exact host name being "localhost".
            */
-          {
-            const char *dotp;
-            /* check for more dots */
-            dotp = strchr(whatptr, '.');
-            if(!dotp && !strcasecompare("localhost", whatptr))
-              domain = ":";
-          }
+          if(bad_domain(whatptr))
+            domain = ":";
 #endif
 
           is_ip = isip(domain ? domain : whatptr);
@@ -723,9 +717,9 @@ Curl_cookie_add(struct Curl_easy *data,
       if(!queryp)
         endslash = strrchr(path, '/');
       else
-        endslash = memrchr(path, '/', (size_t)(queryp - path));
+        endslash = memrchr(path, '/', (queryp - path));
       if(endslash) {
-        size_t pathlen = (size_t)(endslash-path + 1); /* include end slash */
+        size_t pathlen = (endslash-path + 1); /* include end slash */
         co->path = malloc(pathlen + 1); /* one extra for the zero byte */
         if(co->path) {
           memcpy(co->path, path, pathlen);
@@ -880,9 +874,10 @@ Curl_cookie_add(struct Curl_easy *data,
   }
 
   co->livecookie = c->running;
+  co->creationtime = ++c->lastct;
 
   /* now, we have parsed the incoming line, we must now check if this
-     superceeds an already existing cookie, which it may if the previous have
+     supersedes an already existing cookie, which it may if the previous have
      the same domain and path as this */
 
   /* at first, remove expired cookies */
@@ -890,14 +885,21 @@ Curl_cookie_add(struct Curl_easy *data,
     remove_expired(c);
 
 #ifdef USE_LIBPSL
-  /* Check if the domain is a Public Suffix and if yes, ignore the cookie.
-     This needs a libpsl compiled with builtin data. */
+  /* Check if the domain is a Public Suffix and if yes, ignore the cookie. */
   if(domain && co->domain && !isip(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);
+    const psl_ctx_t *psl = Curl_psl_use(data);
+    int acceptable;
+
+    if(psl) {
+      acceptable = psl_is_cookie_domain_acceptable(psl, domain, co->domain);
+      Curl_psl_release(data);
+    }
+    else
+      acceptable = !bad_domain(domain);
+
+    if(!acceptable) {
+      infof(data, "cookie '%s' dropped, domain '%s' must not "
+                  "set cookies for '%s'\n", co->name, domain, co->domain);
       freecookie(co);
       return NULL;
     }
@@ -951,6 +953,9 @@ Curl_cookie_add(struct Curl_easy *data,
       if(replace_old) {
         co->next = clist->next; /* get the next-pointer first */
 
+        /* when replacing, creationtime is kept from old */
+        co->creationtime = clist->creationtime;
+
         /* then free all the old pointers */
         free(clist->name);
         free(clist->value);
@@ -1140,12 +1145,24 @@ static int cookie_sort(const void *p1, const void *p2)
   if(l1 != l2)
     return (l2 > l1) ? 1 : -1 ;  /* avoid size_t <=> int conversions */
 
-  /* 3 - compare cookie names */
-  if(c1->name && c2->name)
-    return strcmp(c1->name, c2->name);
+  /* 3 - compare cookie name lengths */
+  l1 = c1->name ? strlen(c1->name) : 0;
+  l2 = c2->name ? strlen(c2->name) : 0;
 
-  /* sorry, can't be more deterministic */
-  return 0;
+  if(l1 != l2)
+    return (l2 > l1) ? 1 : -1;
+
+  /* 4 - compare cookie creation time */
+  return (c2->creationtime > c1->creationtime) ? 1 : -1;
+}
+
+/* sort cookies only according to creation time */
+static int cookie_sort_ct(const void *p1, const void *p2)
+{
+  struct Cookie *c1 = *(struct Cookie **)p1;
+  struct Cookie *c2 = *(struct Cookie **)p2;
+
+  return (c2->creationtime > c1->creationtime) ? 1 : -1;
 }
 
 #define CLONE(field)                     \
@@ -1174,6 +1191,7 @@ static struct Cookie *dup_cookie(struct Cookie *src)
     d->secure = src->secure;
     d->livecookie = src->livecookie;
     d->httponly = src->httponly;
+    d->creationtime = src->creationtime;
   }
   return d;
 
@@ -1384,9 +1402,8 @@ void Curl_cookie_clearsess(struct CookieInfo *cookies)
  ****************************************************************************/
 void Curl_cookie_cleanup(struct CookieInfo *c)
 {
-  unsigned int i;
-
   if(c) {
+    unsigned int i;
     free(c->filename);
     for(i = 0; i < COOKIE_HASH_SIZE; i++)
       Curl_cookie_freelist(c->cookies[i]);
@@ -1439,6 +1456,8 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
   bool use_stdout = FALSE;
   char *format_ptr;
   unsigned int i;
+  unsigned int j;
+  struct Cookie **array;
 
   if((NULL == c) || (0 == c->numcookies))
     /* If there are no known cookies, we don't write or even create any
@@ -1452,6 +1471,10 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
   if(0 == c->numcookies)
     return 0;
 
+  array = malloc(sizeof(struct Cookie *) * c->numcookies);
+  if(!array)
+    return 1;
+
   if(!strcmp("-", dumphere)) {
     /* use stdout */
     out = stdout;
@@ -1459,8 +1482,10 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
   }
   else {
     out = fopen(dumphere, FOPEN_WRITETEXT);
-    if(!out)
+    if(!out) {
+      free(array);
       return 1; /* failure */
+    }
   }
 
   fputs("# Netscape HTTP Cookie File\n"
@@ -1468,22 +1493,33 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
         "# This file was generated by libcurl! Edit at your own risk.\n\n",
         out);
 
+  j = 0;
   for(i = 0; i < COOKIE_HASH_SIZE; i++) {
     for(co = c->cookies[i]; co; co = co->next) {
       if(!co->domain)
         continue;
-      format_ptr = get_netscape_format(co);
-      if(format_ptr == NULL) {
-        fprintf(out, "#\n# Fatal libcurl error\n");
-        if(!use_stdout)
-          fclose(out);
-        return 1;
+      array[j++] = co;
+    }
+  }
+
+  qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct);
+
+  for(i = 0; i < j; i++) {
+    format_ptr = get_netscape_format(array[i]);
+    if(format_ptr == NULL) {
+      fprintf(out, "#\n# Fatal libcurl error\n");
+      if(!use_stdout) {
+        free(array);
+        fclose(out);
       }
-      fprintf(out, "%s\n", format_ptr);
-      free(format_ptr);
+      return 1;
     }
+    fprintf(out, "%s\n", format_ptr);
+    free(format_ptr);
   }
 
+  free(array);
+
   if(!use_stdout)
     fclose(out);
 
diff --git a/lib/cookie.h b/lib/cookie.h
index 79b5928..a9f90ca 100644
--- a/lib/cookie.h
+++ b/lib/cookie.h
@@ -34,7 +34,7 @@ struct Cookie {
   char *domain;      /* domain = <this> */
   curl_off_t expires;  /* expires = <this> */
   char *expirestr;   /* the plain text version */
-  bool tailmatch;    /* weather we do tail-matchning of the domain name */
+  bool tailmatch;    /* whether we do tail-matching of the domain name */
 
   /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */
   char *version;     /* Version = <value> */
@@ -43,6 +43,7 @@ struct Cookie {
   bool secure;       /* whether the 'secure' keyword was used */
   bool livecookie;   /* updated from a server, not a stored file */
   bool httponly;     /* true if the httponly directive is present */
+  int creationtime;  /* time when the cookie was written */
 };
 
 #define COOKIE_HASH_SIZE 256
@@ -55,6 +56,7 @@ struct CookieInfo {
   bool running;    /* state info, for cookie adding information */
   long numcookies; /* number of cookies in the "jar" */
   bool newsession; /* new session, discard session cookies on load */
+  int lastct;      /* last creation-time used in the jar */
 };
 
 /* This is the maximum line length we accept for a cookie line. RFC 2109
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c
index 55d5a39..fd49679 100644
--- a/lib/curl_addrinfo.c
+++ b/lib/curl_addrinfo.c
@@ -536,7 +536,8 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
 }
 #endif
 
-#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO)
+#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) &&  \
+  defined(HAVE_FREEADDRINFO)
 /*
  * curl_dofreeaddrinfo()
  *
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index 4b12083..ab0094b 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -235,6 +235,9 @@
 /* Define to 1 if you have the `getpwuid' function. */
 #cmakedefine HAVE_GETPWUID 1
 
+/* Define to 1 if you have the `getpwuid_r' function. */
+#cmakedefine HAVE_GETPWUID_R 1
+
 /* Define to 1 if you have the `getrlimit' function. */
 #cmakedefine HAVE_GETRLIMIT 1
 
@@ -963,6 +966,9 @@
 /* to enable Windows SSL  */
 #cmakedefine USE_SCHANNEL 1
 
+/* enable multiple SSL backends */
+#cmakedefine CURL_WITH_MULTI_SSL 1
+
 /* Define to 1 if using yaSSL in OpenSSL compatibility mode. */
 #cmakedefine USE_YASSLEMUL 1
 
diff --git a/lib/curl_fnmatch.c b/lib/curl_fnmatch.c
index 0179a4f..fbfd85c 100644
--- a/lib/curl_fnmatch.c
+++ b/lib/curl_fnmatch.c
@@ -30,6 +30,17 @@
 /* The last #include file should be: */
 #include "memdebug.h"
 
+#ifndef HAVE_FNMATCH
+
+/*
+ * TODO:
+ *
+ * Make this function match POSIX. Test 1307 includes a set of test patterns
+ * that returns different results with a POSIX fnmatch() than with this
+ * implementation and this is considered a bug where POSIX is the guiding
+ * light.
+ */
+
 #define CURLFNM_CHARSET_LEN (sizeof(char) * 256)
 #define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
 
@@ -334,9 +345,9 @@ static int loop(const unsigned char *pattern, const unsigned char *string,
         s++;
         break;
       }
+      /* Syntax error in set; mismatch! */
+      return CURL_FNMATCH_NOMATCH;
 
-      /* Syntax error in set: this must be taken as a regular character. */
-      /* FALLTHROUGH */
     default:
       if(*p++ != *s++)
         return CURL_FNMATCH_NOMATCH;
@@ -355,5 +366,31 @@ int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
   if(!pattern || !string) {
     return CURL_FNMATCH_FAIL;
   }
-  return loop((unsigned char *)pattern, (unsigned char *)string, 5);
+  return loop((unsigned char *)pattern, (unsigned char *)string, 2);
+}
+#else
+#include <fnmatch.h>
+/*
+ * @unittest: 1307
+ */
+int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
+{
+  int rc;
+  (void)ptr; /* the argument is specified by the curl_fnmatch_callback
+                prototype, but not used by Curl_fnmatch() */
+  if(!pattern || !string) {
+    return CURL_FNMATCH_FAIL;
+  }
+  rc = fnmatch(pattern, string, 0);
+  switch(rc) {
+  case 0:
+    return CURL_FNMATCH_MATCH;
+  case FNM_NOMATCH:
+    return CURL_FNMATCH_NOMATCH;
+  default:
+    return CURL_FNMATCH_FAIL;
+  }
+  /* not reached */
 }
+
+#endif
diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c
index e27cab3..922e85a 100644
--- a/lib/curl_ntlm_core.c
+++ b/lib/curl_ntlm_core.c
@@ -557,8 +557,11 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
                                    unsigned char *ntbuffer /* 21 bytes */)
 {
   size_t len = strlen(password);
-  unsigned char *pw = len ? malloc(len * 2) : strdup("");
+  unsigned char *pw;
   CURLcode result;
+  if(len > SIZE_T_MAX/2) /* avoid integer overflow */
+    return CURLE_OUT_OF_MEMORY;
+  pw = len ? malloc(len * 2) : strdup("");
   if(!pw)
     return CURLE_OUT_OF_MEMORY;
 
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index e54e487..354bc54 100644
--- a/lib/curl_sasl.c
+++ b/lib/curl_sasl.c
@@ -146,7 +146,6 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
                                          const char *value, size_t len)
 {
   CURLcode result = CURLE_OK;
-  unsigned int mechbit;
   size_t mechlen;
 
   if(!len)
@@ -160,7 +159,7 @@ CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
   if(!strncmp(value, "*", len))
     sasl->prefmech = SASL_AUTH_DEFAULT;
   else {
-    mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
+    unsigned int mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
     if(mechbit && mechlen == len)
       sasl->prefmech |= mechbit;
     else
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index 5593a3b..2498987 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -217,7 +217,7 @@
 
 /*
  * Use getaddrinfo to resolve the IPv4 address literal. If the current network
- * interface doesn’t support IPv4, but supports IPv6, NAT64, and DNS64,
+ * interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
  * performing this task will result in a synthesized IPv6 address.
  */
 #ifdef  __APPLE__
@@ -242,6 +242,7 @@
 #  if defined(_UNICODE) && !defined(UNICODE)
 #    define UNICODE
 #  endif
+#  include <winerror.h>
 #  include <windows.h>
 #  ifdef HAVE_WINSOCK2_H
 #    include <winsock2.h>
@@ -800,4 +801,16 @@ endings either CRLF or LF so 't' is appropriate.
 #define CURL_SA_FAMILY_T unsigned short
 #endif
 
+/* Some convenience macros to get the larger/smaller value out of two given.
+   We prefix with CURL to prevent name collisions. */
+#define CURLMAX(x,y) ((x)>(y)?(x):(y))
+#define CURLMIN(x,y) ((x)<(y)?(x):(y))
+
+/* Some versions of the Android SDK is missing the declaration */
+#if defined(HAVE_GETPWUID_R) && defined(HAVE_DECL_GETPWUID_R_MISSING)
+struct passwd;
+int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
+               size_t buflen, struct passwd **result);
+#endif
+
 #endif /* HEADER_CURL_SETUP_H */
diff --git a/lib/curl_threads.c b/lib/curl_threads.c
index c1624a9..b8f0cd3 100644
--- a/lib/curl_threads.c
+++ b/lib/curl_threads.c
@@ -108,7 +108,8 @@ curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *),
 #ifdef _WIN32_WCE
   t = CreateThread(NULL, 0, func, arg, 0, NULL);
 #else
-  t = (curl_thread_t)_beginthreadex(NULL, 0, func, arg, 0, NULL);
+  uintptr_t thread_handle = _beginthreadex(NULL, 0, func, arg, 0, NULL);
+  t = (curl_thread_t)thread_handle;
 #endif
   if((t == 0) || (t == LongToHandle(-1L))) {
 #ifdef _WIN32_WCE
diff --git a/lib/dict.c b/lib/dict.c
index 4fc8552..408d57b 100644
--- a/lib/dict.c
+++ b/lib/dict.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -95,17 +95,17 @@ static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
 {
   char *newp = NULL;
   char *dictp;
-  char *ptr;
   size_t len;
-  char ch;
-  int olen = 0;
 
   CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
   if(!newp || result)
     return NULL;
 
-  dictp = malloc(((size_t)len)*2 + 1); /* add one for terminating zero */
+  dictp = malloc(len*2 + 1); /* add one for terminating zero */
   if(dictp) {
+    char *ptr;
+    char ch;
+    int olen = 0;
     /* According to RFC2229 section 2.2, these letters need to be escaped with
        \[letter] */
     for(ptr = newp;
diff --git a/lib/easy.c b/lib/easy.c
index 6b91435..027d0be 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -113,7 +113,7 @@ static CURLcode win32_init(void)
   res = WSAStartup(wVersionRequested, &wsaData);
 
   if(res != 0)
-    /* Tell the user that we couldn't find a useable */
+    /* Tell the user that we couldn't find a usable */
     /* winsock.dll.     */
     return CURLE_FAILED_INIT;
 
@@ -125,7 +125,7 @@ static CURLcode win32_init(void)
 
   if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
      HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) {
-    /* Tell the user that we couldn't find a useable */
+    /* Tell the user that we couldn't find a usable */
 
     /* winsock.dll. */
     WSACleanup();
@@ -661,38 +661,27 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
   bool done = FALSE;
   CURLMcode mcode = CURLM_OK;
   CURLcode result = CURLE_OK;
-  struct curltime before;
-  int without_fds = 0;  /* count number of consecutive returns from
-                           curl_multi_wait() without any filedescriptors */
 
   while(!done && !mcode) {
     int still_running = 0;
     int rc;
 
-    before = Curl_now();
     mcode = curl_multi_wait(multi, NULL, 0, 1000, &rc);
 
     if(!mcode) {
       if(!rc) {
-        struct curltime after = Curl_now();
+        long sleep_ms;
 
         /* If it returns without any filedescriptor instantly, we need to
            avoid busy-looping during periods where it has nothing particular
            to wait for */
-        if(Curl_timediff(after, before) <= 10) {
-          without_fds++;
-          if(without_fds > 2) {
-            int sleep_ms = without_fds < 10 ? (1 << (without_fds - 1)) : 1000;
-            Curl_wait_ms(sleep_ms);
-          }
+        curl_multi_timeout(multi, &sleep_ms);
+        if(sleep_ms) {
+          if(sleep_ms > 1000)
+            sleep_ms = 1000;
+          Curl_wait_ms((int)sleep_ms);
         }
-        else
-          /* it wasn't "instant", restart counter */
-          without_fds = 0;
       }
-      else
-        /* got file descriptor, restart counter */
-        without_fds = 0;
 
       mcode = curl_multi_perform(multi, &still_running);
     }
@@ -969,6 +958,13 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
     outcurl->change.referer_alloc = TRUE;
   }
 
+  /* Reinitialize an SSL engine for the new handle
+   * note: the engine name has already been copied by dupset */
+  if(outcurl->set.str[STRING_SSL_ENGINE]) {
+    if(Curl_ssl_set_engine(outcurl, outcurl->set.str[STRING_SSL_ENGINE]))
+      goto fail;
+  }
+
   /* Clone the resolver handle, if present, for the new handle */
   if(Curl_resolver_duphandle(&outcurl->state.resolver,
                              data->state.resolver))
diff --git a/lib/escape.c b/lib/escape.c
index b7e2d32..10774f0 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -82,7 +82,6 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
   size_t alloc;
   char *ns;
   char *testing_ptr = NULL;
-  unsigned char in; /* we need to treat the characters unsigned */
   size_t newlen;
   size_t strindex = 0;
   size_t length;
@@ -100,7 +99,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
 
   length = alloc-1;
   while(length--) {
-    in = *string;
+    unsigned char in = *string; /* we need to treat the characters unsigned */
 
     if(Curl_isunreserved(in))
       /* just copy this */
@@ -150,7 +149,6 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
 {
   size_t alloc = (length?length:strlen(string)) + 1;
   char *ns = malloc(alloc);
-  unsigned char in;
   size_t strindex = 0;
   unsigned long hex;
   CURLcode result;
@@ -159,7 +157,7 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
     return CURLE_OUT_OF_MEMORY;
 
   while(--alloc > 0) {
-    in = *string;
+    unsigned char in = *string;
     if(('%' == in) && (alloc > 2) &&
        ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
       /* this is two hexadecimal digits following a '%' */
diff --git a/lib/file.c b/lib/file.c
index db04cc2..e50e988 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -256,8 +256,6 @@ static CURLcode file_upload(struct connectdata *conn)
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
   char *buf = data->state.buffer;
-  size_t nread;
-  size_t nwrite;
   curl_off_t bytecount = 0;
   struct_stat file_stat;
   const char *buf2;
@@ -306,7 +304,9 @@ static CURLcode file_upload(struct connectdata *conn)
   }
 
   while(!result) {
-    int readcount;
+    size_t nread;
+    size_t nwrite;
+    size_t readcount;
     result = Curl_fillreadbuffer(conn, (int)data->set.buffer_size, &readcount);
     if(result)
       break;
@@ -314,7 +314,7 @@ static CURLcode file_upload(struct connectdata *conn)
     if(readcount <= 0)  /* fix questionable compare error. curlvms */
       break;
 
-    nread = (size_t)readcount;
+    nread = readcount;
 
     /*skip bytes before resume point*/
     if(data->state.resume_from) {
@@ -378,7 +378,6 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
   curl_off_t expected_size = 0;
   bool size_known;
   bool fstated = FALSE;
-  ssize_t nread;
   struct Curl_easy *data = conn->data;
   char *buf = data->state.buffer;
   curl_off_t bytecount = 0;
@@ -461,7 +460,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
     return result;
 
   /* Adjust the start offset in case we want to get the N last bytes
-   * of the stream iff the filesize could be determined */
+   * of the stream if the filesize could be determined */
   if(data->state.resume_from < 0) {
     if(!fstated) {
       failf(data, "Can't get the size of file.");
@@ -502,6 +501,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
   Curl_pgrsTime(data, TIMER_STARTTRANSFER);
 
   while(!result) {
+    ssize_t nread;
     /* Don't fill a whole buffer if we want less than all data */
     size_t bytestoread;
 
diff --git a/lib/formdata.c b/lib/formdata.c
index f912410..202d930 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -39,16 +39,13 @@
 #include "sendf.h"
 #include "strdup.h"
 #include "rand.h"
+#include "warnless.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "memdebug.h"
 
 
-/* What kind of Content-Type to use on un-specified files with unrecognized
-   extensions. */
-#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
-
 #define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
 #define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
 #define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
@@ -305,7 +302,8 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
        * Set the contents property.
        */
     case CURLFORM_PTRCONTENTS:
-      current_form->flags |= HTTPPOST_PTRCONTENTS; /* fall through */
+      current_form->flags |= HTTPPOST_PTRCONTENTS;
+      /* FALLTHROUGH */
     case CURLFORM_COPYCONTENTS:
       if(current_form->value)
         return_value = CURL_FORMADD_OPTION_TWICE;
@@ -725,7 +723,7 @@ int curl_formget(struct curl_httppost *form, void *arg,
 
   while(!result) {
     char buffer[8192];
-    size_t nread = Curl_mime_read(buffer, 1, sizeof buffer, &toppart);
+    size_t nread = Curl_mime_read(buffer, 1, sizeof(buffer), &toppart);
 
     if(!nread)
       break;
@@ -812,7 +810,6 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
 {
   CURLcode result = CURLE_OK;
   curl_mime *form = NULL;
-  curl_mime *multipart;
   curl_mimepart *part;
   struct curl_httppost *file;
 
@@ -831,7 +828,7 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
   /* Process each top part. */
   for(; !result && post; post = post->next) {
     /* If we have more than a file here, create a mime subpart and fill it. */
-    multipart = form;
+    curl_mime *multipart = form;
     if(post->more) {
       part = curl_mime_addpart(form);
       if(!part)
@@ -883,7 +880,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
                compatibility: use of "-" pseudo file name should be avoided. */
             result = curl_mime_data_cb(part, (curl_off_t) -1,
                                        (curl_read_callback) fread,
-                                       (curl_seek_callback) fseek,
+                                       CURLX_FUNCTION_CAST(curl_seek_callback,
+                                                           fseek),
                                        NULL, (void *) stdin);
           }
           else
diff --git a/lib/ftp.c b/lib/ftp.c
index 4e074a1..7dbf080 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -239,8 +239,8 @@ static void close_secondarysocket(struct connectdata *conn)
 
 static void freedirs(struct ftp_conn *ftpc)
 {
-  int i;
   if(ftpc->dirs) {
+    int i;
     for(i = 0; i < ftpc->dirdepth; i++) {
       free(ftpc->dirs[i]);
       ftpc->dirs[i] = NULL;
@@ -637,8 +637,6 @@ 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];
-  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;
@@ -657,7 +655,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
 
   while(!*ftpcode && !result) {
     /* check and reset timeout value every lap */
-    timeout = Curl_pp_state_timeout(pp);
+    time_t timeout = Curl_pp_state_timeout(pp); /* timeout in milliseconds */
+    time_t interval_ms;
 
     if(timeout <= 0) {
       failf(data, "FTP response timeout");
@@ -1589,7 +1588,6 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
   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)) {
@@ -1605,6 +1603,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
     /* 3. pass file-size number of bytes in the source file */
     /* 4. lower the infilesize counter */
     /* => transfer as usual */
+    int seekerr = CURL_SEEKFUNC_OK;
 
     if(data->state.resume_from < 0) {
       /* Got no given size to start from, figure it out */
@@ -2782,7 +2781,6 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
         char *ptr = &data->state.buffer[4];  /* start on the first letter */
         const size_t buf_size = data->set.buffer_size;
         char *dir;
-        char *store;
         bool entry_extracted = FALSE;
 
         dir = malloc(nread + 1);
@@ -2805,6 +2803,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
 
         if('\"' == *ptr) {
           /* it started good */
+          char *store;
           ptr++;
           for(store = dir; *ptr;) {
             if('\"' == *ptr) {
@@ -3992,8 +3991,7 @@ CURLcode Curl_ftpsend(struct connectdata *conn, const char *cmd)
       break;
 
     if(conn->data->set.verbose)
-      Curl_debug(conn->data, CURLINFO_HEADER_OUT,
-                 sptr, (size_t)bytes_written, conn);
+      Curl_debug(conn->data, CURLINFO_HEADER_OUT, sptr, (size_t)bytes_written);
 
     if(bytes_written != (ssize_t)write_len) {
       write_len -= bytes_written;
@@ -4384,7 +4382,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
 {
   struct Curl_easy *data = conn->data;
   char *type;
-  char command;
   struct FTP *ftp;
 
   conn->data->req.protop = ftp = malloc(sizeof(struct FTP));
@@ -4402,6 +4399,7 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
     type = strstr(conn->host.rawalloc, ";type=");
 
   if(type) {
+    char command;
     *type = 0;                     /* it was in the middle of the hostname */
     command = Curl_raw_toupper(type[6]);
     conn->bits.type_set = TRUE;
diff --git a/lib/getinfo.c b/lib/getinfo.c
index d280eeb..14b4562 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -281,6 +281,28 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
     *param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
       data->progress.size_ul:-1;
     break;
+  case CURLINFO_TOTAL_TIME_T:
+    *param_offt = data->progress.timespent;
+    break;
+  case CURLINFO_NAMELOOKUP_TIME_T:
+    *param_offt = data->progress.t_nslookup;
+    break;
+  case CURLINFO_CONNECT_TIME_T:
+    *param_offt = data->progress.t_connect;
+    break;
+  case CURLINFO_APPCONNECT_TIME_T:
+    *param_offt = data->progress.t_appconnect;
+    break;
+  case CURLINFO_PRETRANSFER_TIME_T:
+    *param_offt = data->progress.t_pretransfer;
+    break;
+  case CURLINFO_STARTTRANSFER_TIME_T:
+    *param_offt = data->progress.t_starttransfer;
+    break;
+  case CURLINFO_REDIRECT_TIME_T:
+    *param_offt = data->progress.t_redirect;
+    break;
+
   default:
     return CURLE_UNKNOWN_OPTION;
   }
diff --git a/lib/gopher.c b/lib/gopher.c
index b7c31b6..3ecee9b 100644
--- a/lib/gopher.c
+++ b/lib/gopher.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -89,22 +89,15 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
   /* Create selector. Degenerate cases: / and /1 => convert to "" */
   if(strlen(path) <= 2) {
     sel = (char *)"";
-    len = (int)strlen(sel);
+    len = strlen(sel);
   }
   else {
     char *newp;
-    size_t j, i;
 
     /* Otherwise, drop / and the first character (i.e., item type) ... */
     newp = path;
     newp += 2;
 
-    /* ... then turn ? into TAB for search servers, Veronica, etc. ... */
-    j = strlen(newp);
-    for(i = 0; i<j; i++)
-      if(newp[i] == '?')
-        newp[i] = '\x09';
-
     /* ... and finally unescape */
     result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
     if(result)
diff --git a/lib/hash.c b/lib/hash.c
index 15a128f..421d68f 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -60,8 +60,6 @@ Curl_hash_init(struct curl_hash *h,
                comp_function comparator,
                curl_hash_dtor dtor)
 {
-  int i;
-
   if(!slots || !hfunc || !comparator ||!dtor) {
     return 1; /* failure */
   }
@@ -74,6 +72,7 @@ Curl_hash_init(struct curl_hash *h,
 
   h->table = malloc(slots * sizeof(struct curl_llist));
   if(h->table) {
+    int i;
     for(i = 0; i < slots; ++i)
       Curl_llist_init(&h->table[i], (curl_llist_dtor) hash_element_dtor);
     return 0; /* fine */
@@ -140,11 +139,10 @@ 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)
 {
   struct curl_llist_element *le;
-  struct curl_hash_element  *he;
   struct curl_llist *l = FETCH_LIST(h, key, key_len);
 
   for(le = l->head; le; le = le->next) {
-    he = le->ptr;
+    struct curl_hash_element *he = le->ptr;
     if(h->comp_func(he->key, he->key_len, key, key_len)) {
       Curl_llist_remove(l, le, (void *) h);
       --h->size;
@@ -162,13 +160,12 @@ void *
 Curl_hash_pick(struct curl_hash *h, void *key, size_t key_len)
 {
   struct curl_llist_element *le;
-  struct curl_hash_element  *he;
   struct curl_llist *l;
 
   if(h) {
     l = FETCH_LIST(h, key, key_len);
     for(le = l->head; le; le = le->next) {
-      he = le->ptr;
+      struct curl_hash_element *he = le->ptr;
       if(h->comp_func(he->key, he->key_len, key, key_len)) {
         return he->ptr;
       }
@@ -291,7 +288,6 @@ void Curl_hash_start_iterate(struct curl_hash *hash,
 struct curl_hash_element *
 Curl_hash_next_element(struct curl_hash_iterator *iter)
 {
-  int i;
   struct curl_hash *h = iter->hash;
 
   /* Get the next element in the current list, if any */
@@ -300,6 +296,7 @@ Curl_hash_next_element(struct curl_hash_iterator *iter)
 
   /* If we have reached the end of the list, find the next one */
   if(!iter->current_element) {
+    int i;
     for(i = iter->slot_index; i < h->slots; i++) {
       if(h->table[i].head) {
         iter->current_element = h->table[i].head;
diff --git a/lib/hmac.c b/lib/hmac.c
index dae9505..bf49ebe 100644
--- a/lib/hmac.c
+++ b/lib/hmac.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -58,7 +58,7 @@ Curl_HMAC_init(const HMAC_params * hashparams,
   unsigned char b;
 
   /* Create HMAC context. */
-  i = sizeof *ctxt + 2 * hashparams->hmac_ctxtsize +
+  i = sizeof(*ctxt) + 2 * hashparams->hmac_ctxtsize +
     hashparams->hmac_resultlen;
   ctxt = malloc(i);
 
diff --git a/lib/hostasyn.c b/lib/hostasyn.c
index 7b6e856..e7b399e 100644
--- a/lib/hostasyn.c
+++ b/lib/hostasyn.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -131,7 +131,7 @@ CURLcode Curl_async_resolved(struct connectdata *conn,
   if(result)
     /* We're not allowed to return failure with memory left allocated
        in the connectdata struct, free those here */
-    Curl_disconnect(conn, FALSE); /* close the connection */
+    Curl_disconnect(conn->data, conn, TRUE); /* close the connection */
 
   return result;
 }
diff --git a/lib/hostip.c b/lib/hostip.c
index c2f9def..bc20f71 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -907,7 +907,9 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       char *entry_id;
       size_t entry_len;
       char address[64];
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
       char *addresses = NULL;
+#endif
       char *addr_begin;
       char *addr_end;
       char *port_ptr;
@@ -930,7 +932,9 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
         goto err;
 
       port = (int)tmp_port;
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
       addresses = end_ptr + 1;
+#endif
 
       while(*end_ptr) {
         size_t alen;
@@ -1010,24 +1014,28 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       /* See if its already in our dns cache */
       dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
 
+      if(dns) {
+        infof(data, "RESOLVE %s:%d is - old addresses discarded!\n",
+                hostname, port);
+        /* delete old entry entry, there are two reasons for this
+         1. old entry may have different addresses.
+         2. even if entry with correct addresses is already in the cache,
+            but if it is close to expire, then by the time next http
+            request is made, it can get expired and pruned because old
+            entry is not necessarily marked as added by CURLOPT_RESOLVE. */
+
+        Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
+      }
       /* free the allocated entry_id again */
       free(entry_id);
 
-      if(!dns) {
-        /* if not in the cache already, put this host in the cache */
-        dns = Curl_cache_addr(data, head, hostname, port);
-        if(dns) {
-          dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */
-          /* release the returned reference; the cache itself will keep the
-           * entry alive: */
-          dns->inuse--;
-        }
-      }
-      else {
-        /* this is a duplicate, free it again */
-        infof(data, "RESOLVE %s:%d is already cached, %s not stored!\n",
-              hostname, port, addresses);
-        Curl_freeaddrinfo(head);
+      /* put this new host in the cache */
+      dns = Curl_cache_addr(data, head, hostname, port);
+      if(dns) {
+        dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */
+        /* release the returned reference; the cache itself will keep the
+         * entry alive: */
+            dns->inuse--;
       }
 
       if(data->share)
diff --git a/lib/hostip6.c b/lib/hostip6.c
index 7c9988f..3bf47b4 100644
--- a/lib/hostip6.c
+++ b/lib/hostip6.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -59,39 +59,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
-/* These are strictly for memory tracing and are using the same style as the
- * family otherwise present in memdebug.c. I put these ones here since they
- * require a bunch of structs I didn't want to include in memdebug.c
- */
-
-/*
- * For CURLRES_ARS, this should be written using ares_gethostbyaddr()
- * (ignoring the fact c-ares doesn't return 'serv').
- */
-
-int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
-                       GETNAMEINFO_TYPE_ARG2 salen,
-                       char *host, GETNAMEINFO_TYPE_ARG46 hostlen,
-                       char *serv, GETNAMEINFO_TYPE_ARG46 servlen,
-                       GETNAMEINFO_TYPE_ARG7 flags,
-                       int line, const char *source)
-{
-  int res = (getnameinfo)(sa, salen,
-                          host, hostlen,
-                          serv, servlen,
-                          flags);
-  if(0 == res)
-    /* success */
-    curl_memlog("GETNAME %s:%d getnameinfo()\n",
-                source, line);
-  else
-    curl_memlog("GETNAME %s:%d getnameinfo() failed = %d\n",
-                source, line, res);
-  return res;
-}
-#endif /* defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) */
-
 /*
  * Curl_ipv6works() returns TRUE if IPv6 seems to work.
  */
diff --git a/lib/http.c b/lib/http.c
index ff1d681..e727ed8 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -158,18 +158,20 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
   /* allocate the HTTP-specific struct for the Curl_easy, only to survive
      during this request */
   struct HTTP *http;
-  DEBUGASSERT(conn->data->req.protop == NULL);
+  struct Curl_easy *data = conn->data;
+  DEBUGASSERT(data->req.protop == NULL);
 
   http = calloc(1, sizeof(struct HTTP));
   if(!http)
     return CURLE_OUT_OF_MEMORY;
 
   Curl_mime_initpart(&http->form, conn->data);
-  conn->data->req.protop = http;
-
-  Curl_http2_setup_conn(conn);
-  Curl_http2_setup_req(conn->data);
+  data->req.protop = http;
 
+  if(!CONN_INUSE(conn))
+    /* if not alredy multi-using, setup connection details */
+    Curl_http2_setup_conn(conn);
+  Curl_http2_setup_req(data);
   return CURLE_OK;
 }
 
@@ -310,22 +312,49 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
   return result;
 }
 
+/*
+ * http_output_bearer() sets up an Authorization: header
+ * for HTTP Bearer authentication.
+ *
+ * Returns CURLcode.
+ */
+static CURLcode http_output_bearer(struct connectdata *conn)
+{
+  char **userp;
+  CURLcode result = CURLE_OK;
+
+  userp = &conn->allocptr.userpwd;
+  free(*userp);
+  *userp = aprintf("Authorization: Bearer %s\r\n",
+                   conn->oauth_bearer);
+
+  if(!*userp) {
+    result = CURLE_OUT_OF_MEMORY;
+    goto fail;
+  }
+
+  fail:
+  return result;
+}
+
 /* pickoneauth() selects the most favourable authentication method from the
  * ones available and the ones we want.
  *
  * return TRUE if one was picked
  */
-static bool pickoneauth(struct auth *pick)
+static bool pickoneauth(struct auth *pick, unsigned long mask)
 {
   bool picked;
   /* only deal with authentication we want */
-  unsigned long avail = pick->avail & pick->want;
+  unsigned long avail = pick->avail & pick->want & mask;
   picked = TRUE;
 
   /* The order of these checks is highly relevant, as this will be the order
      of preference in case of the existence of multiple accepted types. */
   if(avail & CURLAUTH_NEGOTIATE)
     pick->picked = CURLAUTH_NEGOTIATE;
+  else if(avail & CURLAUTH_BEARER)
+    pick->picked = CURLAUTH_BEARER;
   else if(avail & CURLAUTH_DIGEST)
     pick->picked = CURLAUTH_DIGEST;
   else if(avail & CURLAUTH_NTLM)
@@ -479,6 +508,10 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
   bool pickhost = FALSE;
   bool pickproxy = FALSE;
   CURLcode result = CURLE_OK;
+  unsigned long authmask = ~0ul;
+
+  if(!conn->oauth_bearer)
+    authmask &= (unsigned long)~CURLAUTH_BEARER;
 
   if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
     /* this is a transient response code, ignore */
@@ -487,17 +520,18 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
   if(data->state.authproblem)
     return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
 
-  if(conn->bits.user_passwd &&
+  if((conn->bits.user_passwd || conn->oauth_bearer) &&
      ((data->req.httpcode == 401) ||
       (conn->bits.authneg && data->req.httpcode < 300))) {
-    pickhost = pickoneauth(&data->state.authhost);
+    pickhost = pickoneauth(&data->state.authhost, authmask);
     if(!pickhost)
       data->state.authproblem = TRUE;
   }
   if(conn->bits.proxy_user_passwd &&
      ((data->req.httpcode == 407) ||
       (conn->bits.authneg && data->req.httpcode < 300))) {
-    pickproxy = pickoneauth(&data->state.authproxy);
+    pickproxy = pickoneauth(&data->state.authproxy,
+                            authmask & ~CURLAUTH_BEARER);
     if(!pickproxy)
       data->state.authproblem = TRUE;
   }
@@ -628,6 +662,20 @@ output_auth_headers(struct connectdata *conn,
        functions work that way */
     authstatus->done = TRUE;
   }
+  if(authstatus->picked == CURLAUTH_BEARER) {
+    /* Bearer */
+    if((!proxy && conn->oauth_bearer &&
+        !Curl_checkheaders(conn, "Authorization:"))) {
+      auth = "Bearer";
+      result = http_output_bearer(conn);
+      if(result)
+        return result;
+    }
+
+    /* NOTE: this function should set 'done' TRUE, as the other auth
+       functions work that way */
+    authstatus->done = TRUE;
+  }
 
   if(auth) {
     infof(data, "%s auth using %s with user '%s'\n",
@@ -674,7 +722,7 @@ Curl_http_output_auth(struct connectdata *conn,
   authproxy = &data->state.authproxy;
 
   if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
-     conn->bits.user_passwd)
+     conn->bits.user_passwd || conn->oauth_bearer)
     /* continue please */;
   else {
     authhost->done = TRUE;
@@ -883,6 +931,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
               data->state.authproblem = TRUE;
             }
           }
+          else
+            if(checkprefix("Bearer", auth)) {
+              *availp |= CURLAUTH_BEARER;
+              authp->avail |= CURLAUTH_BEARER;
+              if(authp->picked == CURLAUTH_BEARER) {
+                /* We asked for Bearer authentication but got a 40X back
+                  anyway, which basically means our token isn't valid. */
+                authp->avail = CURLAUTH_NONE;
+                infof(data, "Authentication problem. Ignoring this.\n");
+                data->state.authproblem = TRUE;
+              }
+            }
 
     /* there may be multiple methods on one line, so keep reading */
     while(*auth && *auth != ',') /* read up to the next comma */
@@ -1063,7 +1123,8 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
   CURLcode result;
   char *ptr;
   size_t size;
-  struct HTTP *http = conn->data->req.protop;
+  struct Curl_easy *data = conn->data;
+  struct HTTP *http = data->req.protop;
   size_t sendsize;
   curl_socket_t sockfd;
   size_t headersize;
@@ -1083,7 +1144,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
 
   DEBUGASSERT(size > included_body_bytes);
 
-  result = Curl_convert_to_network(conn->data, ptr, headersize);
+  result = Curl_convert_to_network(data, ptr, headersize);
   /* Curl_convert_to_network calls failf if unsuccessful */
   if(result) {
     /* conversion failed, free memory and return to the caller */
@@ -1108,8 +1169,14 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
        must copy the data to the uploadbuffer first, since that is the buffer
        we will be using if this send is retried later.
     */
-    memcpy(conn->data->state.uploadbuffer, ptr, sendsize);
-    ptr = conn->data->state.uploadbuffer;
+    result = Curl_get_upload_buffer(data);
+    if(result) {
+      /* malloc failed, free memory and return to the caller */
+      Curl_add_buffer_free(in);
+      return result;
+    }
+    memcpy(data->state.ulbuf, ptr, sendsize);
+    ptr = data->state.ulbuf;
   }
   else
     sendsize = size;
@@ -1126,14 +1193,14 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
     size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount;
     size_t bodylen = amount - headlen;
 
-    if(conn->data->set.verbose) {
+    if(data->set.verbose) {
       /* this data _may_ contain binary stuff */
-      Curl_debug(conn->data, CURLINFO_HEADER_OUT, ptr, headlen, conn);
+      Curl_debug(data, CURLINFO_HEADER_OUT, ptr, headlen);
       if(bodylen) {
         /* there was body data sent beyond the initial header part, pass that
            on to the debug callback too */
-        Curl_debug(conn->data, CURLINFO_DATA_OUT,
-                   ptr + headlen, bodylen, conn);
+        Curl_debug(data, CURLINFO_DATA_OUT,
+                   ptr + headlen, bodylen);
       }
     }
 
@@ -1157,14 +1224,14 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
         ptr = in->buffer + amount;
 
         /* backup the currently set pointers */
-        http->backup.fread_func = conn->data->state.fread_func;
-        http->backup.fread_in = conn->data->state.in;
+        http->backup.fread_func = data->state.fread_func;
+        http->backup.fread_in = data->state.in;
         http->backup.postdata = http->postdata;
         http->backup.postsize = http->postsize;
 
         /* set the new pointers for the request-sending */
-        conn->data->state.fread_func = (curl_read_callback)readmoredata;
-        conn->data->state.in = (void *)conn;
+        data->state.fread_func = (curl_read_callback)readmoredata;
+        data->state.in = (void *)conn;
         http->postdata = ptr;
         http->postsize = (curl_off_t)size;
 
@@ -1223,7 +1290,6 @@ CURLcode Curl_add_bufferf(Curl_send_buffer *in, const char *fmt, ...)
 CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
 {
   char *new_rb;
-  size_t new_size;
 
   if(~size < in->size_used) {
     /* If resulting used size of send buffer would wrap size_t, cleanup
@@ -1236,10 +1302,10 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
 
   if(!in->buffer ||
      ((in->size_used + size) > (in->size_max - 1))) {
-
     /* If current buffer size isn't enough to hold the result, use a
        buffer size that doubles the required size. If this new size
        would wrap size_t, then just use the largest possible one */
+    size_t new_size;
 
     if((size > (size_t)-1 / 2) || (in->size_used > (size_t)-1 / 2) ||
        (~(size * 2) < (in->size_used * 2)))
@@ -1406,7 +1472,7 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
   }
 
   snprintf(proxy_header,
-           sizeof proxy_header,
+           sizeof(proxy_header),
            "PROXY %s %s %s %li %li\r\n",
            tcp_version,
            conn->data->info.conn_local_ip,
@@ -1574,7 +1640,6 @@ static CURLcode expect100(struct Curl_easy *data,
                           Curl_send_buffer *req_buffer)
 {
   CURLcode result = CURLE_OK;
-  const char *ptr;
   data->state.expect100header = FALSE; /* default to false unless it is set
                                           to TRUE below */
   if(use_http_1_1plus(data, conn) &&
@@ -1582,7 +1647,7 @@ static CURLcode expect100(struct Curl_easy *data,
     /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
        Expect: 100-continue to the headers which actually speeds up post
        operations (as there is one packet coming back from the web server) */
-    ptr = Curl_checkheaders(conn, "Expect");
+    const char *ptr = Curl_checkheaders(conn, "Expect");
     if(ptr) {
       data->state.expect100header =
         Curl_compareheader(ptr, "Expect:", "100-continue");
@@ -1819,7 +1884,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   const char *httpstring;
   Curl_send_buffer *req_buffer;
   curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
-  int seekerr = CURL_SEEKFUNC_CANTSEEK;
 
   /* Always consider the DO phase done after this function call, even if there
      may be parts of the request that is not yet sent, since we can deal with
@@ -1863,6 +1927,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   }
 
   http = data->req.protop;
+  DEBUGASSERT(http);
 
   if(!data->state.this_is_a_follow) {
     /* Free to avoid leaking memory on multiple requests*/
@@ -2088,7 +2153,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
     else {
       /* If the host begins with '[', we start searching for the port after
          the bracket has been closed */
-      int startsearch = 0;
       if(*cookiehost == '[') {
         char *closingbracket;
         /* since the 'cookiehost' is an allocated memory area that will be
@@ -2099,6 +2163,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
           *closingbracket = 0;
       }
       else {
+        int startsearch = 0;
         char *colon = strchr(cookiehost + startsearch, ':');
         if(colon)
           *colon = 0; /* The host must not include an embedded port number */
@@ -2244,6 +2309,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
 
       /* Now, let's read off the proper amount of bytes from the
          input. */
+      int seekerr = CURL_SEEKFUNC_CANTSEEK;
       if(conn->seek_func) {
         Curl_set_in_callback(data, true);
         seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
@@ -2828,6 +2894,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       data->req.exp100 = EXP100_SEND_DATA; /* already sent */
       Curl_expire_done(data, EXPIRE_100_TIMEOUT);
     }
+    else
+      data->req.writebytecount = http->writebytecount;
   }
 
   if((conn->httpversion == 20) && data->req.upload_chunky)
@@ -2838,17 +2906,32 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   return result;
 }
 
+typedef enum {
+  STATUS_UNKNOWN, /* not enough data to tell yet */
+  STATUS_DONE, /* a status line was read */
+  STATUS_BAD /* not a status line */
+} statusline;
+
+
+/* Check a string for a prefix. Check no more than 'len' bytes */
+static bool checkprefixmax(const char *prefix, const char *buffer, size_t len)
+{
+  size_t ch = CURLMIN(strlen(prefix), len);
+  return curl_strnequal(prefix, buffer, ch);
+}
+
 /*
  * checkhttpprefix()
  *
  * Returns TRUE if member of the list matches prefix of string
  */
-static bool
+static statusline
 checkhttpprefix(struct Curl_easy *data,
-                const char *s)
+                const char *s, size_t len)
 {
   struct curl_slist *head = data->set.http200aliases;
-  bool rc = FALSE;
+  statusline rc = STATUS_BAD;
+  statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
 #ifdef CURL_DOES_CONVERSIONS
   /* convert from the network encoding using a scratch area */
   char *scratch = strdup(s);
@@ -2865,15 +2948,15 @@ checkhttpprefix(struct Curl_easy *data,
 #endif /* CURL_DOES_CONVERSIONS */
 
   while(head) {
-    if(checkprefix(head->data, s)) {
-      rc = TRUE;
+    if(checkprefixmax(head->data, s, len)) {
+      rc = onmatch;
       break;
     }
     head = head->next;
   }
 
-  if(!rc && (checkprefix("HTTP/", s)))
-    rc = TRUE;
+  if((rc != STATUS_DONE) && (checkprefixmax("HTTP/", s, len)))
+    rc = onmatch;
 
 #ifdef CURL_DOES_CONVERSIONS
   free(scratch);
@@ -2882,11 +2965,12 @@ checkhttpprefix(struct Curl_easy *data,
 }
 
 #ifndef CURL_DISABLE_RTSP
-static bool
+static statusline
 checkrtspprefix(struct Curl_easy *data,
-                const char *s)
+                const char *s, size_t len)
 {
-  bool result = FALSE;
+  statusline result = STATUS_BAD;
+  statusline onmatch = len >= 5? STATUS_DONE : STATUS_UNKNOWN;
 
 #ifdef CURL_DOES_CONVERSIONS
   /* convert from the network encoding using a scratch area */
@@ -2899,30 +2983,31 @@ checkrtspprefix(struct Curl_easy *data,
     /* Curl_convert_from_network calls failf if unsuccessful */
     result = FALSE; /* can't return CURLE_foobar so return FALSE */
   }
-  else
-    result = checkprefix("RTSP/", scratch)? TRUE: FALSE;
+  else if(checkprefixmax("RTSP/", scratch, len))
+    result = onmatch;
   free(scratch);
 #else
   (void)data; /* unused */
-  result = checkprefix("RTSP/", s)? TRUE: FALSE;
+  if(checkprefixmax("RTSP/", s, len))
+    result = onmatch;
 #endif /* CURL_DOES_CONVERSIONS */
 
   return result;
 }
 #endif /* CURL_DISABLE_RTSP */
 
-static bool
+static statusline
 checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
-                 const char *s)
+                 const char *s, size_t len)
 {
 #ifndef CURL_DISABLE_RTSP
   if(conn->handler->protocol & CURLPROTO_RTSP)
-    return checkrtspprefix(data, s);
+    return checkrtspprefix(data, s, len);
 #else
   (void)conn;
 #endif /* CURL_DISABLE_RTSP */
 
-  return checkhttpprefix(data, s);
+  return checkhttpprefix(data, s, len);
 }
 
 /*
@@ -2939,7 +3024,7 @@ 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, "Rejected %zd bytes header (max is %d)!", newsize,
+    failf(data, "Rejected %zu bytes header (max is %d)!", newsize,
           CURL_MAX_HTTP_HEADER);
     return CURLE_OUT_OF_MEMORY;
   }
@@ -3036,12 +3121,15 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
       if(result)
         return result;
 
-      if(!k->headerline && (k->hbuflen>5)) {
-        /* make a first check that this looks like a protocol header */
-        if(!checkprotoprefix(data, conn, data->state.headerbuff)) {
+      if(!k->headerline) {
+        /* check if this looks like a protocol header */
+        statusline st = checkprotoprefix(data, conn, data->state.headerbuff,
+                                         k->hbuflen);
+        if(st == STATUS_BAD) {
           /* this is not the beginning of a protocol first header line */
           k->header = FALSE;
           k->badheader = HEADER_ALLBAD;
+          streamclose(conn, "bad HTTP: No end-of-message indicator");
           break;
         }
       }
@@ -3070,8 +3158,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
 
     if(!k->headerline) {
       /* the first read header */
-      if((k->hbuflen>5) &&
-         !checkprotoprefix(data, conn, data->state.headerbuff)) {
+      statusline st = checkprotoprefix(data, conn, data->state.headerbuff,
+                                       k->hbuflen);
+      if(st == STATUS_BAD) {
+        streamclose(conn, "bad HTTP: No end-of-message indicator");
         /* this is not the beginning of a protocol first header line */
         k->header = FALSE;
         if(*nread)
@@ -3354,7 +3444,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
 
         if(data->set.verbose)
           Curl_debug(data, CURLINFO_HEADER_IN,
-                     k->str_start, headerlen, conn);
+                     k->str_start, headerlen);
         break;          /* exit header line loop */
       }
 
@@ -3440,7 +3530,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
              compare header line against list of aliases
           */
           if(!nc) {
-            if(checkhttpprefix(data, k->p)) {
+            if(checkhttpprefix(data, k->p, k->hbuflen) == STATUS_DONE) {
               nc = 1;
               k->httpcode = 200;
               conn->httpversion = 10;
@@ -3487,21 +3577,18 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
          * depending on how authentication is working.  Other codes
          * are definitely errors, so give up here.
          */
-        if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
+        if(data->state.resume_from && data->set.httpreq == HTTPREQ_GET &&
+             k->httpcode == 416) {
+          /* "Requested Range Not Satisfiable", just proceed and
+             pretend this is no error */
+          k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
+        }
+        else if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
            ((k->httpcode != 401) || !conn->bits.user_passwd) &&
            ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
-
-          if(data->state.resume_from &&
-             (data->set.httpreq == HTTPREQ_GET) &&
-             (k->httpcode == 416)) {
-            /* "Requested Range Not Satisfiable", just proceed and
-               pretend this is no error */
-          }
-          else {
-            /* serious error, go home! */
-            print_http_error(data);
-            return CURLE_HTTP_RETURNED_ERROR;
-          }
+          /* serious error, go home! */
+          print_http_error(data);
+          return CURLE_HTTP_RETURNED_ERROR;
         }
 
         if(conn->httpversion == 10) {
@@ -3812,8 +3899,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
       writetype |= CLIENTWRITE_BODY;
 
     if(data->set.verbose)
-      Curl_debug(data, CURLINFO_HEADER_IN,
-                 k->p, (size_t)k->hbuflen, conn);
+      Curl_debug(data, CURLINFO_HEADER_IN, k->p, (size_t)k->hbuflen);
 
     result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
     if(result)
diff --git a/lib/http2.c b/lib/http2.c
index da001df..d769193 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -42,7 +42,6 @@
 #include "memdebug.h"
 
 #define H2_BUFSIZE 32768
-#define MIN(x,y) ((x)<(y)?(x):(y))
 
 #if (NGHTTP2_VERSION_NUM < 0x010000)
 #error too old nghttp2 version, upgrade!
@@ -154,6 +153,11 @@ static void http2_stream_free(struct HTTP *http)
   }
 }
 
+/*
+ * Disconnects *a* connection used for HTTP/2. It might be an old one from the
+ * connection cache and not the "main" one. Don't touch the easy handle!
+ */
+
 static CURLcode http2_disconnect(struct connectdata *conn,
                                  bool dead_connection)
 {
@@ -164,8 +168,6 @@ static CURLcode http2_disconnect(struct connectdata *conn,
 
   nghttp2_session_del(c->h2);
   Curl_safefree(c->inbuf);
-  http2_stream_free(conn->data->req.protop);
-  conn->data->state.drain = 0;
 
   H2BUGF(infof(conn->data, "HTTP/2 DISCONNECT done\n"));
 
@@ -345,7 +347,7 @@ const char *Curl_http2_strerror(uint32_t err)
     "INADEQUATE_SECURITY",  /* 0xC */
     "HTTP_1_1_REQUIRED"     /* 0xD */
   };
-  return (err < sizeof str / sizeof str[0]) ? str[err] : "unknown";
+  return (err < sizeof(str) / sizeof(str[0])) ? str[err] : "unknown";
 #else
   return nghttp2_http2_strerror(err);
 #endif
@@ -368,6 +370,10 @@ static ssize_t send_callback(nghttp2_session *h2,
   (void)h2;
   (void)flags;
 
+  if(!c->send_underlying)
+    /* called before setup properly! */
+    return NGHTTP2_ERR_CALLBACK_FAILURE;
+
   written = ((Curl_send*)c->send_underlying)(conn, FIRSTSOCKET,
                                              data, length, &result);
 
@@ -441,6 +447,28 @@ char *curl_pushheader_byname(struct curl_pushheaders *h, const char *header)
   return NULL;
 }
 
+/*
+ * This specific transfer on this connection has been "drained".
+ */
+static void drained_transfer(struct Curl_easy *data,
+                             struct http_conn *httpc)
+{
+  DEBUGASSERT(httpc->drain_total >= data->state.drain);
+  httpc->drain_total -= data->state.drain;
+  data->state.drain = 0;
+}
+
+/*
+ * Mark this transfer to get "drained".
+ */
+static void drain_this(struct Curl_easy *data,
+                       struct http_conn *httpc)
+{
+  data->state.drain++;
+  httpc->drain_total++;
+  DEBUGASSERT(httpc->drain_total >= data->state.drain);
+}
+
 static struct Curl_easy *duphandle(struct Curl_easy *data)
 {
   struct Curl_easy *second = curl_easy_duphandle(data);
@@ -520,6 +548,7 @@ static int push_promise(struct Curl_easy *data,
     if(rv) {
       /* denied, kill off the new handle again */
       http2_stream_free(newhandle->req.protop);
+      newhandle->req.protop = NULL;
       (void)Curl_close(newhandle);
       goto fail;
     }
@@ -535,14 +564,22 @@ static int push_promise(struct Curl_easy *data,
     if(rc) {
       infof(data, "failed to add handle to multi\n");
       http2_stream_free(newhandle->req.protop);
+      newhandle->req.protop = NULL;
       Curl_close(newhandle);
       rv = 1;
       goto fail;
     }
 
     httpc = &conn->proto.httpc;
-    nghttp2_session_set_stream_user_data(httpc->h2,
-                                         frame->promised_stream_id, newhandle);
+    rv = nghttp2_session_set_stream_user_data(httpc->h2,
+                                              frame->promised_stream_id,
+                                              newhandle);
+    if(rv) {
+      infof(data, "failed to set user_data for stream %d\n",
+            frame->promised_stream_id);
+      DEBUGASSERT(0);
+      goto fail;
+    }
   }
   else {
     H2BUGF(infof(data, "Got PUSH_PROMISE, ignore it!\n"));
@@ -581,7 +618,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
       if(max_conn != httpc->settings.max_concurrent_streams) {
         /* only signal change if the value actually changed */
         infof(conn->data,
-              "Connection state changed (MAX_CONCURRENT_STREAMS == %d)!\n",
+              "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n",
               httpc->settings.max_concurrent_streams);
         Curl_multi_connchanged(conn->data->multi);
       }
@@ -640,7 +677,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
     Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
 
     left = stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
-    ncopy = MIN(stream->len, left);
+    ncopy = CURLMIN(stream->len, left);
 
     memcpy(&stream->mem[stream->memlen],
            stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
@@ -653,8 +690,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
     stream->len -= ncopy;
     stream->memlen += ncopy;
 
-    data_s->state.drain++;
-    httpc->drain_total++;
+    drain_this(data_s, httpc);
     {
       /* get the pointer from userp again since it was re-assigned above */
       struct connectdata *conn_s = (struct connectdata *)userp;
@@ -683,25 +719,6 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
   return 0;
 }
 
-static int on_invalid_frame_recv(nghttp2_session *session,
-                                 const nghttp2_frame *frame,
-                                 int lib_error_code, void *userp)
-{
-  struct Curl_easy *data_s = NULL;
-  (void)userp;
-#if !defined(DEBUG_HTTP2) || defined(CURL_DISABLE_VERBOSE_STRINGS)
-  (void)lib_error_code;
-#endif
-
-  data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
-  if(data_s) {
-    H2BUGF(infof(data_s,
-                 "on_invalid_frame_recv() was called, error=%d:%s\n",
-                 lib_error_code, nghttp2_strerror(lib_error_code)));
-  }
-  return 0;
-}
-
 static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
                               int32_t stream_id,
                               const uint8_t *data, size_t len, void *userp)
@@ -727,14 +744,13 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
   if(!stream)
     return NGHTTP2_ERR_CALLBACK_FAILURE;
 
-  nread = MIN(stream->len, len);
+  nread = CURLMIN(stream->len, len);
   memcpy(&stream->mem[stream->memlen], data, nread);
 
   stream->len -= nread;
   stream->memlen += nread;
 
-  data_s->state.drain++;
-  conn->proto.httpc.drain_total++;
+  drain_this(data_s, &conn->proto.httpc);
 
   /* if we receive data for another handle, wake that up */
   if(conn->data != data_s)
@@ -768,58 +784,13 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
   return 0;
 }
 
-static int before_frame_send(nghttp2_session *session,
-                             const nghttp2_frame *frame,
-                             void *userp)
-{
-  struct Curl_easy *data_s;
-  (void)userp;
-
-  data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
-  if(data_s) {
-    H2BUGF(infof(data_s, "before_frame_send() was called\n"));
-  }
-
-  return 0;
-}
-static int on_frame_send(nghttp2_session *session,
-                         const nghttp2_frame *frame,
-                         void *userp)
-{
-  struct Curl_easy *data_s;
-  (void)userp;
-
-  data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
-  if(data_s) {
-    H2BUGF(infof(data_s, "on_frame_send() was called, length = %zd\n",
-                 frame->hd.length));
-  }
-  return 0;
-}
-static int on_frame_not_send(nghttp2_session *session,
-                             const nghttp2_frame *frame,
-                             int lib_error_code, void *userp)
-{
-  struct Curl_easy *data_s;
-  (void)userp;
-#if !defined(DEBUG_HTTP2) || defined(CURL_DISABLE_VERBOSE_STRINGS)
-  (void)lib_error_code;
-#endif
-
-  data_s = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
-  if(data_s) {
-    H2BUGF(infof(data_s,
-                 "on_frame_not_send() was called, lib_error_code = %d\n",
-                 lib_error_code));
-  }
-  return 0;
-}
 static int on_stream_close(nghttp2_session *session, int32_t stream_id,
                            uint32_t error_code, void *userp)
 {
   struct Curl_easy *data_s;
   struct HTTP *stream;
   struct connectdata *conn = (struct connectdata *)userp;
+  int rv;
   (void)session;
   (void)stream_id;
 
@@ -840,14 +811,19 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
       return NGHTTP2_ERR_CALLBACK_FAILURE;
 
     stream->closed = TRUE;
-    data_s->state.drain++;
     httpc = &conn->proto.httpc;
-    httpc->drain_total++;
+    drain_this(data_s, httpc);
     httpc->error_code = error_code;
 
     /* remove the entry from the hash as the stream is now gone */
-    nghttp2_session_set_stream_user_data(session, stream_id, 0);
+    rv = nghttp2_session_set_stream_user_data(session, stream_id, 0);
+    if(rv) {
+      infof(data_s, "http/2: failed to clear user_data for stream %d!\n",
+            stream_id);
+      DEBUGASSERT(0);
+    }
     H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
+    stream->stream_id = 0; /* cleared */
   }
   return 0;
 }
@@ -1052,7 +1028,7 @@ static ssize_t data_source_read_callback(nghttp2_session *session,
   else
     return NGHTTP2_ERR_INVALID_ARGUMENT;
 
-  nread = MIN(stream->upload_len, length);
+  nread = CURLMIN(stream->upload_len, length);
   if(nread > 0) {
     memcpy(buf, stream->upload_mem, nread);
     stream->upload_mem += nread;
@@ -1109,6 +1085,12 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
   struct HTTP *http = data->req.protop;
   struct http_conn *httpc = &conn->proto.httpc;
 
+  if(!httpc->h2) /* not HTTP/2 ? */
+    return;
+
+  if(data->state.drain)
+    drained_transfer(data, httpc);
+
   if(http->header_recvbuf) {
     Curl_add_buffer_free(http->header_recvbuf);
     http->header_recvbuf = NULL; /* clear the pointer */
@@ -1126,15 +1108,24 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
 
   if(premature) {
     /* RST_STREAM */
-    nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE, http->stream_id,
-                              NGHTTP2_STREAM_CLOSED);
+    if(!nghttp2_submit_rst_stream(httpc->h2, NGHTTP2_FLAG_NONE,
+                                  http->stream_id, NGHTTP2_STREAM_CLOSED))
+      (void)nghttp2_session_send(httpc->h2);
+
     if(http->stream_id == httpc->pause_stream_id) {
       infof(data, "stopped the pause stream!\n");
       httpc->pause_stream_id = 0;
     }
   }
-  if(http->stream_id) {
-    nghttp2_session_set_stream_user_data(httpc->h2, http->stream_id, 0);
+  /* -1 means unassigned and 0 means cleared */
+  if(http->stream_id > 0) {
+    int rv = nghttp2_session_set_stream_user_data(httpc->h2,
+                                                  http->stream_id, 0);
+    if(rv) {
+      infof(data, "http/2: failed to clear user_data for stream %d!\n",
+            http->stream_id);
+      DEBUGASSERT(0);
+    }
     http->stream_id = 0;
   }
 }
@@ -1164,21 +1155,9 @@ CURLcode Curl_http2_init(struct connectdata *conn)
     /* nghttp2_on_frame_recv_callback */
     nghttp2_session_callbacks_set_on_frame_recv_callback
       (callbacks, on_frame_recv);
-    /* nghttp2_on_invalid_frame_recv_callback */
-    nghttp2_session_callbacks_set_on_invalid_frame_recv_callback
-      (callbacks, on_invalid_frame_recv);
     /* nghttp2_on_data_chunk_recv_callback */
     nghttp2_session_callbacks_set_on_data_chunk_recv_callback
       (callbacks, on_data_chunk_recv);
-    /* nghttp2_before_frame_send_callback */
-    nghttp2_session_callbacks_set_before_frame_send_callback
-      (callbacks, before_frame_send);
-    /* nghttp2_on_frame_send_callback */
-    nghttp2_session_callbacks_set_on_frame_send_callback
-      (callbacks, on_frame_send);
-    /* nghttp2_on_frame_not_send_callback */
-    nghttp2_session_callbacks_set_on_frame_not_send_callback
-      (callbacks, on_frame_not_send);
     /* nghttp2_on_stream_close_callback */
     nghttp2_session_callbacks_set_on_stream_close_callback
       (callbacks, on_stream_close);
@@ -1280,7 +1259,7 @@ static int h2_process_pending_input(struct connectdata *conn,
   if(rv < 0) {
     failf(data,
           "h2_process_pending_input: nghttp2_session_mem_recv() returned "
-          "%d:%s\n", rv, nghttp2_strerror((int)rv));
+          "%zd:%s\n", rv, nghttp2_strerror((int)rv));
     *err = CURLE_RECV_ERROR;
     return -1;
   }
@@ -1352,7 +1331,6 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
   return result;
 }
 
-
 static ssize_t http2_handle_stream_close(struct connectdata *conn,
                                          struct Curl_easy *data,
                                          struct HTTP *stream, CURLcode *err)
@@ -1365,9 +1343,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
     httpc->pause_stream_id = 0;
   }
 
-  DEBUGASSERT(httpc->drain_total >= data->state.drain);
-  httpc->drain_total -= data->state.drain;
-  data->state.drain = 0;
+  drained_transfer(data, httpc);
 
   if(httpc->pause_stream_id == 0) {
     if(h2_process_pending_input(conn, httpc, err) != 0) {
@@ -1388,7 +1364,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
     return -1;
   }
   else if(httpc->error_code != NGHTTP2_NO_ERROR) {
-    failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)",
+    failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
           stream->stream_id, Curl_http2_strerror(httpc->error_code),
           httpc->error_code);
     *err = CURLE_HTTP2_STREAM;
@@ -1396,7 +1372,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
   }
 
   if(!stream->bodystarted) {
-    failf(data, "HTTP/2 stream %u was closed cleanly, but before getting "
+    failf(data, "HTTP/2 stream %d was closed cleanly, but before getting "
           " all response header fields, treated as error",
           stream->stream_id);
     *err = CURLE_HTTP2_STREAM;
@@ -1510,7 +1486,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
     /* If there is body data pending for this stream to return, do that */
     size_t left =
       stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
-    size_t ncopy = MIN(len, left);
+    size_t ncopy = CURLMIN(len, left);
     memcpy(mem, stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
            ncopy);
     stream->nread_header_recvbuf += ncopy;
@@ -1546,13 +1522,13 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
   }
   else if(stream->pausedata) {
     DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
-    nread = MIN(len, stream->pauselen);
+    nread = CURLMIN(len, stream->pauselen);
     memcpy(mem, stream->pausedata, nread);
 
     stream->pausedata += nread;
     stream->pauselen -= nread;
 
-    infof(data, "%zu data bytes written\n", nread);
+    infof(data, "%zd data bytes written\n", nread);
     if(stream->pauselen == 0) {
       H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
       DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
@@ -1635,7 +1611,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
     rv = nghttp2_session_mem_recv(httpc->h2, (const uint8_t *)inbuf, nread);
 
     if(nghttp2_is_fatal((int)rv)) {
-      failf(data, "nghttp2_session_mem_recv() returned %d:%s\n",
+      failf(data, "nghttp2_session_mem_recv() returned %zd:%s\n",
             rv, nghttp2_strerror((int)rv));
       *err = CURLE_RECV_ERROR;
       return -1;
@@ -1678,9 +1654,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
                    stream->stream_id));
     }
     else if(!stream->closed) {
-      DEBUGASSERT(httpc->drain_total >= data->state.drain);
-      httpc->drain_total -= data->state.drain;
-      data->state.drain = 0; /* this stream is hereby drained */
+      drained_transfer(data, httpc);
     }
 
     return retlen;
@@ -2040,7 +2014,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
   }
 
   infof(conn->data, "Using Stream ID: %x (easy handle %p)\n",
-        stream_id, conn->data);
+        stream_id, (void *)conn->data);
   stream->stream_id = stream_id;
 
   /* this does not call h2_session_send() since there can not have been any
@@ -2154,9 +2128,14 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
       return CURLE_HTTP2;
     }
 
-    nghttp2_session_set_stream_user_data(httpc->h2,
-                                         stream->stream_id,
-                                         conn->data);
+    rv = nghttp2_session_set_stream_user_data(httpc->h2,
+                                              stream->stream_id,
+                                              data);
+    if(rv) {
+      infof(data, "http/2: failed to set user_data for stream %d!\n",
+            stream->stream_id);
+      DEBUGASSERT(0);
+    }
   }
   else {
     populate_settings(conn, httpc);
diff --git a/lib/http2.h b/lib/http2.h
index f597c80..21cd9b8 100644
--- a/lib/http2.h
+++ b/lib/http2.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -65,7 +65,7 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
 #define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL
-#define Curl_http2_setup_conn(x)
+#define Curl_http2_setup_conn(x) Curl_nop_stmt
 #define Curl_http2_setup_req(x)
 #define Curl_http2_init_state(x)
 #define Curl_http2_init_userset(x)
diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c
index fd5540b..a9b33f9 100644
--- a/lib/http_ntlm.c
+++ b/lib/http_ntlm.c
@@ -228,7 +228,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
     /* connection is already authenticated,
      * don't send a header in future requests */
     ntlm->state = NTLMSTATE_LAST;
-    /* fall-through */
+    /* FALLTHROUGH */
   case NTLMSTATE_LAST:
     Curl_safefree(*allocuserpwd);
     authp->done = TRUE;
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index e10a488..c8c445b 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -188,12 +188,10 @@ static CURLcode CONNECT(struct connectdata *conn,
   struct SingleRequest *k = &data->req;
   CURLcode result;
   curl_socket_t tunnelsocket = conn->sock[sockindex];
-  timediff_t check;
   struct http_connect_state *s = conn->connect_state;
 
 #define SELECT_OK      0
 #define SELECT_ERROR   1
-#define SELECT_TIMEOUT 2
 
   if(Curl_connect_complete(conn))
     return CURLE_OK; /* CONNECT is already completed */
@@ -201,12 +199,13 @@ static CURLcode CONNECT(struct connectdata *conn,
   conn->bits.proxy_connect_closed = FALSE;
 
   do {
+    timediff_t check;
     if(TUNNEL_INIT == s->tunnel_state) {
       /* BEGIN CONNECT PHASE */
       char *host_port;
       Curl_send_buffer *req_buffer;
 
-      infof(data, "Establish HTTP proxy tunnel to %s:%hu\n",
+      infof(data, "Establish HTTP proxy tunnel to %s:%d\n",
             hostname, remote_port);
 
         /* This only happens if we've looped here due to authentication
@@ -419,7 +418,7 @@ static CURLcode CONNECT(struct connectdata *conn,
         /* output debug if that is requested */
         if(data->set.verbose)
           Curl_debug(data, CURLINFO_HEADER_IN,
-                     s->line_start, (size_t)s->perline, conn);
+                     s->line_start, (size_t)s->perline);
 
         if(!data->set.suppress_connect_headers) {
           /* send the header to the callback */
diff --git a/lib/imap.c b/lib/imap.c
index cf278a2..942fe7d 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -609,7 +609,6 @@ static CURLcode imap_perform_list(struct connectdata *conn)
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
   struct IMAP *imap = data->req.protop;
-  char *mailbox;
 
   if(imap->custom)
     /* Send the custom request */
@@ -617,7 +616,8 @@ static CURLcode imap_perform_list(struct connectdata *conn)
                         imap->custom_params ? imap->custom_params : "");
   else {
     /* Make sure the mailbox is in the correct atom format if necessary */
-    mailbox = imap->mailbox ? imap_atom(imap->mailbox, true) : strdup("");
+    char *mailbox = imap->mailbox ? imap_atom(imap->mailbox, true)
+                                  : strdup("");
     if(!mailbox)
       return CURLE_OUT_OF_MEMORY;
 
@@ -854,7 +854,6 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct imap_conn *imapc = &conn->proto.imapc;
   const char *line = data->state.buffer;
-  size_t wordlen;
 
   (void)instate; /* no use for this yet */
 
@@ -864,6 +863,7 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn,
 
     /* Loop through the data line */
     for(;;) {
+      size_t wordlen;
       while(*line &&
             (*line == ' ' || *line == '\t' ||
               *line == '\r' || *line == '\n')) {
@@ -1046,12 +1046,12 @@ static CURLcode imap_state_select_resp(struct connectdata *conn, int imapcode,
   struct IMAP *imap = conn->data->req.protop;
   struct imap_conn *imapc = &conn->proto.imapc;
   const char *line = data->state.buffer;
-  char tmp[20];
 
   (void)instate; /* no use for this yet */
 
   if(imapcode == '*') {
     /* See if this is an UIDVALIDITY response */
+    char tmp[20];
     if(sscanf(line + 2, "OK [UIDVALIDITY %19[0123456789]]", tmp) == 1) {
       Curl_safefree(imapc->mailbox_uidvalidity);
       imapc->mailbox_uidvalidity = strdup(tmp);
@@ -1119,7 +1119,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
   }
 
   if(parsed) {
-    infof(data, "Found %" CURL_FORMAT_CURL_OFF_TU " bytes to download\n",
+    infof(data, "Found %" CURL_FORMAT_CURL_OFF_T " bytes to download\n",
           size);
     Curl_pgrsSetDownloadSize(data, size);
 
@@ -1144,10 +1144,8 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
 
       data->req.bytecount += chunk;
 
-      infof(data, "Written %" CURL_FORMAT_CURL_OFF_TU
-            " bytes, %" CURL_FORMAT_CURL_OFF_TU
-            " bytes are left for transfer\n", (curl_off_t)chunk,
-            size - chunk);
+      infof(data, "Written %zu bytes, %" CURL_FORMAT_CURL_OFF_TU
+            " bytes are left for transfer\n", chunk, size - chunk);
 
       /* Have we used the entire cache or just part of it?*/
       if(pp->cache_size > chunk) {
diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c
index fb91a50..ac5d2d4 100644
--- a/lib/inet_ntop.c
+++ b/lib/inet_ntop.c
@@ -49,7 +49,7 @@
  */
 static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
 {
-  char tmp[sizeof "255.255.255.255"];
+  char tmp[sizeof("255.255.255.255")];
   size_t len;
 
   DEBUGASSERT(size >= 16);
diff --git a/lib/ldap.c b/lib/ldap.c
index 89047bc..4d8f4fa 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -54,15 +54,6 @@
 # endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */
 #endif
 
-/* These are macros in both <wincrypt.h> (in above <winldap.h>) and typedefs
- * in BoringSSL's <openssl/x509.h>
- */
-#ifdef HAVE_BORINGSSL
-# undef X509_NAME
-# undef X509_CERT_PAIR
-# undef X509_EXTENSIONS
-#endif
-
 #include "urldata.h"
 #include <curl/curl.h>
 #include "sendf.h"
diff --git a/lib/md5.c b/lib/md5.c
index 3096602..b819d39 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -484,29 +484,35 @@ static void MD5_Final(unsigned char *result, MD5_CTX *ctx)
 
 #endif /* CRYPTO LIBS */
 
-/* Disable this picky gcc-8 compiler warning */
-#if defined(__GNUC__) && (__GNUC__ >= 8)
-#pragma GCC diagnostic ignored "-Wcast-function-type"
-#endif
-
 const HMAC_params Curl_HMAC_MD5[] = {
   {
-    (HMAC_hinit_func) MD5_Init,           /* Hash initialization function. */
-    (HMAC_hupdate_func) MD5_Update,       /* Hash update function. */
-    (HMAC_hfinal_func) MD5_Final,         /* Hash computation end function. */
-    sizeof(MD5_CTX),                      /* Size of hash context structure. */
-    64,                                   /* Maximum key length. */
-    16                                    /* Result size. */
+    /* Hash initialization function. */
+    CURLX_FUNCTION_CAST(HMAC_hinit_func, MD5_Init),
+    /* Hash update function. */
+    CURLX_FUNCTION_CAST(HMAC_hupdate_func, MD5_Update),
+    /* Hash computation end function. */
+    CURLX_FUNCTION_CAST(HMAC_hfinal_func, MD5_Final),
+    /* Size of hash context structure. */
+    sizeof(MD5_CTX),
+    /* Maximum key length. */
+    64,
+    /* Result size. */
+    16
   }
 };
 
 const MD5_params Curl_DIGEST_MD5[] = {
   {
-    (Curl_MD5_init_func) MD5_Init,      /* Digest initialization function */
-    (Curl_MD5_update_func) MD5_Update,  /* Digest update function */
-    (Curl_MD5_final_func) MD5_Final,    /* Digest computation end function */
-    sizeof(MD5_CTX),                    /* Size of digest context struct */
-    16                                  /* Result size */
+    /* Digest initialization function */
+    CURLX_FUNCTION_CAST(Curl_MD5_init_func, MD5_Init),
+    /* Digest update function */
+    CURLX_FUNCTION_CAST(Curl_MD5_update_func, MD5_Update),
+    /* Digest computation end function */
+    CURLX_FUNCTION_CAST(Curl_MD5_final_func, MD5_Final),
+    /* Size of digest context struct */
+    sizeof(MD5_CTX),
+    /* Result size */
+    16
   }
 };
 
@@ -527,7 +533,7 @@ MD5_context *Curl_MD5_init(const MD5_params *md5params)
   MD5_context *ctxt;
 
   /* Create MD5 context */
-  ctxt = malloc(sizeof *ctxt);
+  ctxt = malloc(sizeof(*ctxt));
 
   if(!ctxt)
     return ctxt;
diff --git a/lib/memdebug.h b/lib/memdebug.h
index 6fb8b68..233de65 100644
--- a/lib/memdebug.h
+++ b/lib/memdebug.h
@@ -8,7 +8,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -137,13 +137,6 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
 #endif
 #endif /* HAVE_GETADDRINFO */
 
-#ifdef HAVE_GETNAMEINFO
-#undef getnameinfo
-#define getnameinfo(sa,salen,host,hostlen,serv,servlen,flags) \
-  curl_dogetnameinfo(sa, salen, host, hostlen, serv, servlen, flags, \
-                     __LINE__, __FILE__)
-#endif /* HAVE_GETNAMEINFO */
-
 #ifdef HAVE_FREEADDRINFO
 #undef freeaddrinfo
 #define freeaddrinfo(data) \
diff --git a/lib/mime.c b/lib/mime.c
index 4c0d2eeb..ca492d1 100644
--- a/lib/mime.c
+++ b/lib/mime.c
@@ -505,9 +505,6 @@ static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
   mime_encoder_state *st = &part->encstate;
   char *ptr = buffer;
   size_t cursize = 0;
-  int i;
-  size_t len;
-  size_t consumed;
   int softlinebreak;
   char buf[4];
 
@@ -516,9 +513,9 @@ static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
      character constants that can be interpreted as non-ascii on some
      platforms. Preserve ASCII encoding on output too. */
   while(st->bufbeg < st->bufend) {
-    len = 1;
-    consumed = 1;
-    i = st->buf[st->bufbeg];
+    size_t len = 1;
+    size_t consumed = 1;
+    int i = st->buf[st->bufbeg];
     buf[0] = (char) i;
     buf[1] = aschex[(i >> 4) & 0xF];
     buf[2] = aschex[i & 0xF];
@@ -787,10 +784,10 @@ static size_t read_encoded_part_content(curl_mimepart *part,
       st->bufbeg = 0;
       st->bufend = len;
     }
-    if(st->bufend >= sizeof st->buf)
+    if(st->bufend >= sizeof(st->buf))
       return cursize? cursize: READ_ERROR;    /* Buffer full. */
     sz = read_part_content(part, st->buf + st->bufend,
-                           sizeof st->buf - st->bufend);
+                           sizeof(st->buf) - st->bufend);
     switch(sz) {
     case 0:
       ateof = TRUE;
@@ -813,8 +810,6 @@ static size_t readback_part(curl_mimepart *part,
                             char *buffer, size_t bufsize)
 {
   size_t cursize = 0;
-  size_t sz;
-  struct curl_slist *hdr;
 #ifdef CURL_DOES_CONVERSIONS
   char *convbuf = buffer;
 #endif
@@ -822,8 +817,8 @@ static size_t readback_part(curl_mimepart *part,
   /* Readback from part. */
 
   while(bufsize) {
-    sz = 0;
-    hdr = (struct curl_slist *) part->state.ptr;
+    size_t sz = 0;
+    struct curl_slist *hdr = (struct curl_slist *) part->state.ptr;
     switch(part->state.state) {
     case MIMESTATE_BEGIN:
       mimesetstate(&part->state, part->flags & MIME_BODY_ONLY? MIMESTATE_BODY:
@@ -918,8 +913,6 @@ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
 {
   curl_mime *mime = (curl_mime *) instream;
   size_t cursize = 0;
-  size_t sz;
-  curl_mimepart *part;
 #ifdef CURL_DOES_CONVERSIONS
   char *convbuf = buffer;
 #endif
@@ -927,8 +920,8 @@ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
   (void) size;   /* Always 1. */
 
   while(nitems) {
-    sz = 0;
-    part = mime->state.ptr;
+    size_t sz = 0;
+    curl_mimepart *part = mime->state.ptr;
     switch(mime->state.state) {
     case MIMESTATE_BEGIN:
     case MIMESTATE_BODY:
@@ -1044,7 +1037,6 @@ static int mime_subparts_seek(void *instream, curl_off_t offset, int whence)
   curl_mime *mime = (curl_mime *) instream;
   curl_mimepart *part;
   int result = CURL_SEEKFUNC_OK;
-  int res;
 
   if(whence != SEEK_SET || offset)
     return CURL_SEEKFUNC_CANTSEEK;    /* Only support full rewind. */
@@ -1053,7 +1045,7 @@ static int mime_subparts_seek(void *instream, curl_off_t offset, int whence)
    return CURL_SEEKFUNC_OK;           /* Already rewound. */
 
   for(part = mime->firstpart; part; part = part->nextpart) {
-    res = mime_part_rewind(part);
+    int res = mime_part_rewind(part);
     if(res != CURL_SEEKFUNC_OK)
       result = res;
   }
@@ -1220,7 +1212,7 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
 {
   curl_mime *mime;
 
-  mime = (curl_mime *) malloc(sizeof *mime);
+  mime = (curl_mime *) malloc(sizeof(*mime));
 
   if(mime) {
     mime->easy = easy;
@@ -1236,8 +1228,13 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
     }
 
     memset(mime->boundary, '-', 24);
-    Curl_rand_hex(easy, (unsigned char *) mime->boundary + 24,
-                  MIME_RAND_BOUNDARY_CHARS + 1);
+    if(Curl_rand_hex(easy, (unsigned char *) mime->boundary + 24,
+                     MIME_RAND_BOUNDARY_CHARS + 1)) {
+      /* failed to get random separator, bail out */
+      free(mime->boundary);
+      free(mime);
+      return NULL;
+    }
     mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL);
   }
 
@@ -1247,7 +1244,7 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
 /* Initialize a mime part. */
 void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
 {
-  memset((char *) part, 0, sizeof *part);
+  memset((char *) part, 0, sizeof(*part));
   part->easy = easy;
   mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
 }
@@ -1260,7 +1257,7 @@ curl_mimepart *curl_mime_addpart(curl_mime *mime)
   if(!mime)
     return NULL;
 
-  part = (curl_mimepart *) malloc(sizeof *part);
+  part = (curl_mimepart *) malloc(sizeof(*part));
 
   if(part) {
     Curl_mime_initpart(part, mime->easy);
@@ -1349,7 +1346,6 @@ CURLcode curl_mime_data(curl_mimepart *part,
 CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
 {
   CURLcode result = CURLE_OK;
-  char *base;
 
   if(!part)
     return CURLE_BAD_FUNCTION_ARGUMENT;
@@ -1357,6 +1353,7 @@ CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
   cleanup_part_content(part);
 
   if(filename) {
+    char *base;
     struct_stat sbuf;
 
     if(stat(filename, &sbuf) || access(filename, R_OK))
@@ -1564,7 +1561,6 @@ static size_t slist_size(struct curl_slist *s,
 static curl_off_t multipart_size(curl_mime *mime)
 {
   curl_off_t size;
-  curl_off_t sz;
   size_t boundarysize;
   curl_mimepart *part;
 
@@ -1575,7 +1571,7 @@ static curl_off_t multipart_size(curl_mime *mime)
   size = boundarysize;  /* Final boundary - CRLF after headers. */
 
   for(part = mime->firstpart; part; part = part->nextpart) {
-    sz = Curl_mime_size(part);
+    curl_off_t sz = Curl_mime_size(part);
 
     if(sz < 0)
       size = sz;
@@ -1643,8 +1639,6 @@ static CURLcode add_content_type(struct curl_slist **slp,
 
 const char *Curl_mime_contenttype(const char *filename)
 {
-  unsigned int i;
-
   /*
    * If no content type was specified, we scan through a few well-known
    * extensions and pick the first we match!
@@ -1669,8 +1663,9 @@ const char *Curl_mime_contenttype(const char *filename)
   if(filename) {
     size_t len1 = strlen(filename);
     const char *nameend = filename + len1;
+    unsigned int i;
 
-    for(i = 0; i < sizeof ctts / sizeof ctts[0]; i++) {
+    for(i = 0; i < sizeof(ctts) / sizeof(ctts[0]); i++) {
       size_t len2 = strlen(ctts[i].extension);
 
       if(len1 >= len2 && strcasecompare(nameend - len2, ctts[i].extension))
diff --git a/lib/multi.c b/lib/multi.c
index f852846..0caf943 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -31,6 +31,7 @@
 #include "progress.h"
 #include "easyif.h"
 #include "share.h"
+#include "psl.h"
 #include "multiif.h"
 #include "sendf.h"
 #include "timeval.h"
@@ -68,8 +69,8 @@
 #define GOOD_MULTI_HANDLE(x) \
   ((x) && (x)->type == CURL_MULTI_HANDLE)
 
-static void singlesocket(struct Curl_multi *multi,
-                         struct Curl_easy *data);
+static CURLMcode singlesocket(struct Curl_multi *multi,
+                              struct Curl_easy *data);
 static int update_timer(struct Curl_multi *multi);
 
 static CURLMcode add_next_timeout(struct curltime now,
@@ -106,6 +107,16 @@ static const char * const statename[]={
 /* function pointer called once when switching TO a state */
 typedef void (*init_multistate_func)(struct Curl_easy *data);
 
+static void Curl_init_completed(struct Curl_easy *data)
+{
+  /* this is a completed transfer */
+
+  /* Important: reset the conn pointer so that we don't point to memory
+     that could be freed anytime */
+  data->easy_conn = NULL;
+  Curl_expire_clear(data); /* stop all timers */
+}
+
 /* always use this function to change state, to make debugging easier */
 static void mstate(struct Curl_easy *data, CURLMstate state
 #ifdef DEBUGBUILD
@@ -115,17 +126,25 @@ static void mstate(struct Curl_easy *data, CURLMstate state
 {
   CURLMstate oldstate = data->mstate;
   static const init_multistate_func finit[CURLM_STATE_LAST] = {
-    NULL,
-    NULL,
+    NULL,              /* INIT */
+    NULL,              /* CONNECT_PEND */
     Curl_init_CONNECT, /* CONNECT */
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    Curl_connect_free /* DO */
-    /* the rest is NULL too */
+    NULL,              /* WAITRESOLVE */
+    NULL,              /* WAITCONNECT */
+    NULL,              /* WAITPROXYCONNECT */
+    NULL,              /* SENDPROTOCONNECT */
+    NULL,              /* PROTOCONNECT */
+    NULL,              /* WAITDO */
+    Curl_connect_free, /* DO */
+    NULL,              /* DOING */
+    NULL,              /* DO_MORE */
+    NULL,              /* DO_DONE */
+    NULL,              /* WAITPERFORM */
+    NULL,              /* PERFORM */
+    NULL,              /* TOOFAST */
+    NULL,              /* DONE */
+    Curl_init_completed, /* COMPLETED */
+    NULL               /* MSGSENT */
   };
 
 #if defined(DEBUGBUILD) && defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -409,6 +428,14 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
   else
     data->state.conn_cache = &multi->conn_cache;
 
+#ifdef USE_LIBPSL
+  /* Do the same for PSL. */
+  if(data->share && (data->share->specifier & (1 << CURL_LOCK_DATA_PSL)))
+    data->psl = &data->share->psl;
+  else
+    data->psl = &multi->psl;
+#endif
+
   /* This adds the new entry at the 'end' of the doubly-linked circular
      list of Curl_easy structs to try and maintain a FIFO queue so
      the pipelined requests are in order. */
@@ -449,7 +476,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
      happens if the lastcall time is set to the same time when the handle is
      removed as when the next handle is added, as then the check in
      update_timer() that prevents calling the application multiple times with
-     the same timer infor will not trigger and then the new handle's timeout
+     the same timer info will not trigger and then the new handle's timeout
      will not be notified to the app.
 
      The work-around is thus simply to clear the 'lastcall' variable to force
@@ -506,6 +533,11 @@ static CURLcode multi_done(struct connectdata **connp,
     /* Stop if multi_done() has already been called */
     return CURLE_OK;
 
+  if(data->mstate == CURLM_STATE_WAITRESOLVE) {
+    /* still waiting for the resolve to complete */
+    (void)Curl_resolver_wait_resolv(conn, NULL);
+  }
+
   Curl_getoff_all_pipelines(data, conn);
 
   /* Cleanup possible redirect junk */
@@ -546,7 +578,7 @@ static CURLcode multi_done(struct connectdata **connp,
   if(conn->send_pipe.size || conn->recv_pipe.size) {
     /* Stop if pipeline is not empty . */
     data->easy_conn = NULL;
-    DEBUGF(infof(data, "Connection still in use %d/%d, "
+    DEBUGF(infof(data, "Connection still in use %zu/%zu, "
                  "no more multi_done now!\n",
                  conn->send_pipe.size, conn->recv_pipe.size));
     return CURLE_OK;
@@ -560,6 +592,7 @@ static CURLcode multi_done(struct connectdata **connp,
     conn->dns_entry = NULL;
   }
   Curl_hostcache_prune(data);
+  Curl_safefree(data->state.ulbuf);
 
   /* if the transfer was completed in a paused state there can be buffered
      data left to free */
@@ -590,7 +623,7 @@ static CURLcode multi_done(struct connectdata **connp,
 #endif
      ) || conn->bits.close
        || (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
-    CURLcode res2 = Curl_disconnect(conn, premature); /* close connection */
+    CURLcode res2 = Curl_disconnect(data, conn, premature);
 
     /* If we had an error already, make sure we return that one. But
        if we got a new error, return that. */
@@ -608,7 +641,7 @@ static CURLcode multi_done(struct connectdata **connp,
              conn->bits.conn_to_host ? conn->conn_to_host.dispname :
              conn->host.dispname);
 
-    /* the connection is no longer in use */
+    /* the connection is no longer in use by this transfer */
     if(Curl_conncache_return_conn(conn)) {
       /* remember the most recently used connection */
       data->state.lastconnect = conn;
@@ -698,6 +731,11 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
       Curl_getoff_all_pipelines(data, data->easy_conn);
   }
 
+  if(data->connect_queue.ptr)
+    /* the handle was in the pending list waiting for an available connection,
+       so go ahead and remove it */
+    Curl_llist_remove(&multi->pending, &data->connect_queue, NULL);
+
   if(data->dns.hostcachetype == HCACHE_MULTI) {
     /* stop using the multi handle's DNS cache, *after* the possible
        multi_done() call above */
@@ -727,6 +765,12 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
     data->easy_conn = NULL;
   }
 
+#ifdef USE_LIBPSL
+  /* Remove the PSL association. */
+  if(data->psl == &multi->psl)
+    data->psl = NULL;
+#endif
+
   data->multi = NULL; /* clear the association to this multi handle */
 
   /* make sure there's no pending message in the queue sent from this easy
@@ -831,12 +875,10 @@ static int multi_getsock(struct Curl_easy *data,
                                                   of sockets */
                          int numsocks)
 {
-  /* If the pipe broke, or if there's no connection left for this easy handle,
-     then we MUST bail out now with no bitmask set. The no connection case can
-     happen when this is called from curl_multi_remove_handle() =>
-     singlesocket() => multi_getsock().
+  /* The no connection case can happen when this is called from
+     curl_multi_remove_handle() => singlesocket() => multi_getsock().
   */
-  if(data->state.pipe_broke || !data->easy_conn)
+  if(!data->easy_conn)
     return 0;
 
   if(data->mstate > CURLM_STATE_CONNECT &&
@@ -902,7 +944,6 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
   struct Curl_easy *data;
   int this_max_fd = -1;
   curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
-  int bitmap;
   int i;
   (void)exc_fd_set; /* not used */
 
@@ -914,7 +955,7 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
 
   data = multi->easyp;
   while(data) {
-    bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
+    int bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
 
     for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
       curl_socket_t s = CURL_SOCKET_BAD;
@@ -1068,8 +1109,6 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
     int pollrc;
     /* wait... */
     pollrc = Curl_poll(ufds, nfds, timeout_ms);
-    DEBUGF(infof(data, "Curl_poll(%d ds, %d ms) == %d\n",
-                 nfds, timeout_ms, pollrc));
 
     if(pollrc > 0) {
       retcode = pollrc;
@@ -1312,24 +1351,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
     bool stream_error = FALSE;
     rc = CURLM_OK;
 
-    /* Handle the case when the pipe breaks, i.e., the connection
-       we're using gets cleaned up and we're left with nothing. */
-    if(data->state.pipe_broke) {
-      infof(data, "Pipe broke: handle %p, url = %s\n",
-            (void *)data, data->state.path);
-
-      if(data->mstate < CURLM_STATE_COMPLETED) {
-        /* Head back to the CONNECT state */
-        multistate(data, CURLM_STATE_CONNECT);
-        rc = CURLM_CALL_MULTI_PERFORM;
-        result = CURLE_OK;
-      }
-
-      data->state.pipe_broke = FALSE;
-      data->easy_conn = NULL;
-      continue;
-    }
-
     if(!data->easy_conn &&
        data->mstate > CURLM_STATE_CONNECT &&
        data->mstate < CURLM_STATE_DONE) {
@@ -1555,6 +1576,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
           multistate(data, CURLM_STATE_SENDPROTOCONNECT);
         }
       }
+      else if(result)
+        stream_error = TRUE;
       break;
 #endif
 
@@ -1909,6 +1932,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
         if(!ret)
           retry = (newurl)?TRUE:FALSE;
+        else if(!result)
+          result = ret;
 
         if(retry) {
           /* if we are to retry, set the result to OK and consider the
@@ -2040,16 +2065,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       break;
 
     case CURLM_STATE_COMPLETED:
-      /* this is a completed transfer, it is likely to still be connected */
-
-      /* This node should be delinked from the list now and we should post
-         an information message that we are complete. */
-
-      /* Important: reset the conn pointer so that we don't point to memory
-         that could be freed anytime */
-      data->easy_conn = NULL;
-
-      Curl_expire_clear(data); /* stop all timers */
       break;
 
     case CURLM_STATE_MSGSENT:
@@ -2071,8 +2086,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         /* NOTE: no attempt to disconnect connections must be made
            in the case blocks above - cleanup happens only here */
 
-        data->state.pipe_broke = FALSE;
-
         /* Check if we can move pending requests to send pipe */
         process_pending_handles(multi); /* connection */
 
@@ -2087,7 +2100,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
             /* Don't attempt to send data over a connection that timed out */
             bool dead_connection = result == CURLE_OPERATION_TIMEDOUT;
             /* disconnect properly */
-            Curl_disconnect(data->easy_conn, dead_connection);
+            Curl_disconnect(data, data->easy_conn, dead_connection);
 
             /* This is where we make sure that the easy_conn pointer is reset.
                We don't have to do this in every case block above where a
@@ -2101,6 +2114,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         }
 
         multistate(data, CURLM_STATE_COMPLETED);
+        rc = CURLM_CALL_MULTI_PERFORM;
       }
       /* if there's still a connection to use, call the progress function */
       else if(data->easy_conn && Curl_pgrsUpdate(data->easy_conn)) {
@@ -2125,14 +2139,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
       msg->extmsg.data.result = result;
 
       rc = multi_addmsg(multi, msg);
-
+      DEBUGASSERT(!data->easy_conn);
       multistate(data, CURLM_STATE_MSGSENT);
     }
   } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE));
 
   data->result = result;
-
-
   return rc;
 }
 
@@ -2220,6 +2232,11 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
       data->state.conn_cache = NULL;
       data->multi = NULL; /* clear the association */
 
+#ifdef USE_LIBPSL
+      if(data->psl == &multi->psl)
+        data->psl = NULL;
+#endif
+
       data = nextdata;
     }
 
@@ -2232,6 +2249,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
     Curl_llist_destroy(&multi->pending, NULL);
 
     Curl_hash_destroy(&multi->hostcache);
+    Curl_psl_destroy(&multi->psl);
 
     /* Free the blacklists by setting them to NULL */
     Curl_pipeline_set_site_blacklist(NULL, &multi->pipelining_site_bl);
@@ -2286,8 +2304,8 @@ CURLMsg *curl_multi_info_read(struct Curl_multi *multi, int *msgs_in_queue)
  * and if we have a different state in any of those sockets from last time we
  * call the callback accordingly.
  */
-static void singlesocket(struct Curl_multi *multi,
-                         struct Curl_easy *data)
+static CURLMcode singlesocket(struct Curl_multi *multi,
+                              struct Curl_easy *data)
 {
   curl_socket_t socks[MAX_SOCKSPEREASYHANDLE];
   int i;
@@ -2334,7 +2352,7 @@ static void singlesocket(struct Curl_multi *multi,
       entry = sh_addentry(&multi->sockhash, s, data);
       if(!entry)
         /* fatal */
-        return;
+        return CURLM_OUT_OF_MEMORY;
     }
 
     /* we know (entry != NULL) at this point, see the logic above */
@@ -2422,6 +2440,7 @@ static void singlesocket(struct Curl_multi *multi,
 
   memcpy(data->sockets, socks, num*sizeof(curl_socket_t));
   data->numsocks = num;
+  return CURLM_OK;
 }
 
 void Curl_updatesocket(struct Curl_easy *data)
@@ -2442,20 +2461,23 @@ void Curl_updatesocket(struct Curl_easy *data)
 
 void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
 {
-  struct Curl_multi *multi = conn->data->multi;
-  if(multi) {
-    /* this is set if this connection is part of a handle that is added to
-       a multi handle, and only then this is necessary */
-    struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
-
-    if(entry) {
-      if(multi->socket_cb)
-        multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
-                         multi->socket_userp,
-                         entry->socketp);
+  if(conn->data) {
+    /* if there's still an easy handle associated with this connection */
+    struct Curl_multi *multi = conn->data->multi;
+    if(multi) {
+      /* this is set if this connection is part of a handle that is added to
+         a multi handle, and only then this is necessary */
+      struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
+
+      if(entry) {
+        if(multi->socket_cb)
+          multi->socket_cb(conn->data, s, CURL_POLL_REMOVE,
+                           multi->socket_userp,
+                           entry->socketp);
 
-      /* now remove it from the socket hash */
-      sh_delentry(&multi->sockhash, s);
+        /* now remove it from the socket hash */
+        sh_delentry(&multi->sockhash, s);
+      }
     }
   }
 }
@@ -2535,8 +2557,8 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
        and callbacks */
     if(result != CURLM_BAD_HANDLE) {
       data = multi->easyp;
-      while(data) {
-        singlesocket(multi, data);
+      while(data && !result) {
+        result = singlesocket(multi, data);
         data = data->next;
       }
     }
@@ -2590,10 +2612,13 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
         /* clear the bitmask only if not locked */
         data->easy_conn->cselect_bits = 0;
 
-      if(CURLM_OK >= result)
+      if(CURLM_OK >= result) {
         /* get the socket(s) and check if the state has been changed since
            last */
-        singlesocket(multi, data);
+        result = singlesocket(multi, data);
+        if(result)
+          return result;
+      }
 
       /* Now we fall-through and do the timer-based stuff, since we don't want
          to force the user to have to deal with timeouts as long as at least
@@ -2627,10 +2652,13 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
       result = multi_runsingle(multi, now, data);
       sigpipe_restore(&pipe_st);
 
-      if(CURLM_OK >= result)
+      if(CURLM_OK >= result) {
         /* get the socket(s) and check if the state has been changed since
            last */
-        singlesocket(multi, data);
+        result = singlesocket(multi, data);
+        if(result)
+          return result;
+      }
     }
 
     /* Check if there's one (more) expired timer to deal with! This function
@@ -2924,7 +2952,6 @@ void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id)
 {
   struct Curl_multi *multi = data->multi;
   struct curltime *nowp = &data->state.expiretime;
-  int rc;
   struct curltime set;
 
   /* this is only interesting while there is still an associated multi struct
@@ -2955,6 +2982,7 @@ void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id)
        Compare if the new time is earlier, and only remove-old/add-new if it
        is. */
     timediff_t diff = Curl_timediff(set, *nowp);
+    int rc;
 
     if(diff > 0) {
       /* The current splay tree entry is sooner than this new expiry time.
@@ -3000,7 +3028,6 @@ void Curl_expire_clear(struct Curl_easy *data)
 {
   struct Curl_multi *multi = data->multi;
   struct curltime *nowp = &data->state.expiretime;
-  int rc;
 
   /* this is only interesting while there is still an associated multi struct
      remaining! */
@@ -3011,6 +3038,7 @@ void Curl_expire_clear(struct Curl_easy *data)
     /* Since this is an cleared time, we must remove the previous entry from
        the splay tree */
     struct curl_llist *list = &data->state.timeoutlist;
+    int rc;
 
     rc = Curl_splayremovebyaddr(multi->timetree,
                                 &data->state.timenode,
@@ -3100,12 +3128,15 @@ static void process_pending_handles(struct Curl_multi *multi)
   }
 }
 
-void Curl_set_in_callback(struct Curl_easy *easy, bool value)
+void Curl_set_in_callback(struct Curl_easy *data, bool value)
 {
-  if(easy->multi_easy)
-    easy->multi_easy->in_callback = value;
-  else if(easy->multi)
-      easy->multi->in_callback = value;
+  /* might get called when there is no data pointer! */
+  if(data) {
+    if(data->multi_easy)
+      data->multi_easy->in_callback = value;
+    else if(data->multi)
+      data->multi->in_callback = value;
+  }
 }
 
 bool Curl_is_in_callback(struct Curl_easy *easy)
diff --git a/lib/multihandle.h b/lib/multihandle.h
index 1a5017f..ea2bf35 100644
--- a/lib/multihandle.h
+++ b/lib/multihandle.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,6 +23,7 @@
  ***************************************************************************/
 
 #include "conncache.h"
+#include "psl.h"
 
 struct Curl_message {
   struct curl_llist_element list;
@@ -97,6 +98,11 @@ struct Curl_multi {
   /* Hostname cache */
   struct curl_hash hostcache;
 
+#ifdef USE_LIBPSL
+  /* PSL cache. */
+  struct PslCache psl;
+#endif
+
   /* timetree points to the splay-tree of time nodes to figure out expire
      times of all currently set timers */
   struct Curl_tree *timetree;
diff --git a/lib/netrc.c b/lib/netrc.c
index dbcc59a..a407bda 100644
--- a/lib/netrc.c
+++ b/lib/netrc.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -115,7 +115,7 @@ int Curl_parsenetrc(const char *host,
     char *tok;
     char *tok_buf;
     bool done = FALSE;
-    char netrcbuffer[256];
+    char netrcbuffer[4096];
     int  netrcbuffsize = (int)sizeof(netrcbuffer);
 
     while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
diff --git a/lib/pingpong.c b/lib/pingpong.c
index ad370ee..2e93d20 100644
--- a/lib/pingpong.c
+++ b/lib/pingpong.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -49,7 +49,6 @@ time_t Curl_pp_state_timeout(struct pingpong *pp)
   struct connectdata *conn = pp->conn;
   struct Curl_easy *data = conn->data;
   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;
 
@@ -65,7 +64,7 @@ time_t Curl_pp_state_timeout(struct pingpong *pp)
 
   if(data->set.timeout) {
     /* if timeout is requested, find out how much remaining time we have */
-    timeout2_ms = data->set.timeout - /* timeout time */
+    time_t timeout2_ms = data->set.timeout - /* timeout time */
       Curl_timediff(Curl_now(), conn->now); /* spent time */
 
     /* pick the lowest number */
@@ -222,8 +221,7 @@ CURLcode Curl_pp_vsendf(struct pingpong *pp,
   }
 
   if(conn->data->set.verbose)
-    Curl_debug(conn->data, CURLINFO_HEADER_OUT,
-               s, (size_t)bytes_written, conn);
+    Curl_debug(conn->data, CURLINFO_HEADER_OUT, s, (size_t)bytes_written);
 
   if(bytes_written != (ssize_t)write_len) {
     /* the whole chunk was not sent, keep it around and adjust sizes */
@@ -371,7 +369,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
 #endif
             if(data->set.verbose)
               Curl_debug(data, CURLINFO_HEADER_IN,
-                         pp->linestart_resp, (size_t)perline, conn);
+                         pp->linestart_resp, (size_t)perline);
 
           /*
            * We pass all response-lines to the callback function registered
diff --git a/lib/pipeline.c b/lib/pipeline.c
index 4d41b04..8de3bab 100644
--- a/lib/pipeline.c
+++ b/lib/pipeline.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2013, Linus Nielsen Feltzing, <linus@haxx.se>
- * Copyright (C) 2013 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2013 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -82,7 +82,8 @@ bool Curl_pipeline_penalized(struct Curl_easy *data,
       penalized = TRUE;
 
     infof(data, "Conn: %ld (%p) Receive pipe weight: (%"
-          CURL_FORMAT_CURL_OFF_T "/%zu), penalized: %s\n",
+          CURL_FORMAT_CURL_OFF_T "/%" CURL_FORMAT_CURL_OFF_T
+          "), penalized: %s\n",
           conn->connection_id, (void *)conn, recv_size,
           conn->chunk.datasize, penalized?"TRUE":"FALSE");
     return penalized;
@@ -109,8 +110,8 @@ CURLcode Curl_add_handle_to_pipeline(struct Curl_easy *handle,
   pipeline = &conn->send_pipe;
 
   result = addHandleToPipeline(handle, pipeline);
-
-  if(pipeline == &conn->send_pipe && sendhead != conn->send_pipe.head) {
+  if((conn->bundle->multiuse == BUNDLE_PIPELINING) &&
+     (pipeline == &conn->send_pipe && sendhead != conn->send_pipe.head)) {
     /* this is a new one as head, expire it */
     Curl_pipeline_leave_write(conn); /* not in use yet */
     Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
diff --git a/lib/pop3.c b/lib/pop3.c
index 78f6afe..cd994f6 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -613,7 +613,6 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
   struct pop3_conn *pop3c = &conn->proto.pop3c;
   const char *line = data->state.buffer;
   size_t len = strlen(line);
-  size_t i;
 
   (void)instate; /* no use for this yet */
 
@@ -625,6 +624,7 @@ static CURLcode pop3_state_servergreet_resp(struct connectdata *conn,
     /* Does the server support APOP authentication? */
     if(len >= 4 && line[len - 2] == '>') {
       /* Look for the APOP timestamp */
+      size_t i;
       for(i = 3; i < len - 2; ++i) {
         if(line[i] == '<') {
           /* Calculate the length of the timestamp */
@@ -664,7 +664,6 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
   struct pop3_conn *pop3c = &conn->proto.pop3c;
   const char *line = data->state.buffer;
   size_t len = strlen(line);
-  size_t wordlen;
 
   (void)instate; /* no use for this yet */
 
@@ -689,6 +688,7 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
       /* Loop through the data line */
       for(;;) {
         size_t llen;
+        size_t wordlen;
         unsigned int mechbit;
 
         while(len &&
diff --git a/lib/progress.c b/lib/progress.c
index f59faa3..a94668d 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -35,22 +35,22 @@
    byte) */
 static void time2str(char *r, curl_off_t seconds)
 {
-  curl_off_t d, h, m, s;
+  curl_off_t h;
   if(seconds <= 0) {
     strcpy(r, "--:--:--");
     return;
   }
   h = seconds / CURL_OFF_T_C(3600);
   if(h <= CURL_OFF_T_C(99)) {
-    m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60);
-    s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60));
+    curl_off_t m = (seconds - (h*CURL_OFF_T_C(3600))) / CURL_OFF_T_C(60);
+    curl_off_t s = (seconds - (h*CURL_OFF_T_C(3600))) - (m*CURL_OFF_T_C(60));
     snprintf(r, 9, "%2" CURL_FORMAT_CURL_OFF_T ":%02" CURL_FORMAT_CURL_OFF_T
              ":%02" CURL_FORMAT_CURL_OFF_T, h, m, s);
   }
   else {
     /* this equals to more than 99 hours, switch to a more suitable output
        format to fit within the limits. */
-    d = seconds / CURL_OFF_T_C(86400);
+    curl_off_t d = seconds / CURL_OFF_T_C(86400);
     h = (seconds - (d*CURL_OFF_T_C(86400))) / CURL_OFF_T_C(3600);
     if(d <= CURL_OFF_T_C(999))
       snprintf(r, 9, "%3" CURL_FORMAT_CURL_OFF_T
@@ -369,25 +369,10 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size)
 int Curl_pgrsUpdate(struct connectdata *conn)
 {
   struct curltime now;
-  int result;
-  char max5[6][10];
-  curl_off_t dlpercen = 0;
-  curl_off_t ulpercen = 0;
-  curl_off_t total_percen = 0;
-  curl_off_t total_transfer;
-  curl_off_t total_expected_transfer;
   curl_off_t timespent;
   curl_off_t timespent_ms; /* milliseconds */
   struct Curl_easy *data = conn->data;
   int nowindex = data->progress.speeder_c% CURR_TIME;
-  int checkindex;
-  int countindex; /* amount of seconds stored in the speeder array */
-  char time_left[10];
-  char time_total[10];
-  char time_spent[10];
-  curl_off_t ulestimate = 0;
-  curl_off_t dlestimate = 0;
-  curl_off_t total_estimate;
   bool shownow = FALSE;
   curl_off_t dl = data->progress.downloaded;
   curl_off_t ul = data->progress.uploaded;
@@ -413,6 +398,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
 
   /* Calculations done at most once a second, unless end is reached */
   if(data->progress.lastshow != now.tv_sec) {
+    int countindex; /* amount of seconds stored in the speeder array */
     shownow = TRUE;
 
     data->progress.lastshow = now.tv_sec;
@@ -438,6 +424,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
 
     /* first of all, we don't do this if there's no counted seconds yet */
     if(countindex) {
+      int checkindex;
       timediff_t span_ms;
 
       /* Get the index position to compare with the 'nowindex' position.
@@ -477,8 +464,21 @@ int Curl_pgrsUpdate(struct connectdata *conn)
 
   if(!(data->progress.flags & PGRS_HIDE)) {
     /* progress meter has not been shut off */
+    char max5[6][10];
+    curl_off_t dlpercen = 0;
+    curl_off_t ulpercen = 0;
+    curl_off_t total_percen = 0;
+    curl_off_t total_transfer;
+    curl_off_t total_expected_transfer;
+    char time_left[10];
+    char time_total[10];
+    char time_spent[10];
+    curl_off_t ulestimate = 0;
+    curl_off_t dlestimate = 0;
+    curl_off_t total_estimate;
 
     if(data->set.fxferinfo) {
+      int result;
       /* There's a callback set, call that */
       Curl_set_in_callback(data, true);
       result = data->set.fxferinfo(data->set.progress_client,
@@ -492,6 +492,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
       return result;
     }
     if(data->set.fprogress) {
+      int result;
       /* The older deprecated callback is set, call that */
       Curl_set_in_callback(data, true);
       result = data->set.fprogress(data->set.progress_client,
diff --git a/lib/progress.h b/lib/progress.h
index 2baa925..92dbcbd 100644
--- a/lib/progress.h
+++ b/lib/progress.h
@@ -56,23 +56,10 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
                                   struct curltime start,
                                   struct curltime now);
 
-/* Don't show progress for sizes smaller than: */
-#define LEAST_SIZE_PROGRESS BUFSIZE
-
-#define PROGRESS_DOWNLOAD (1<<0)
-#define PROGRESS_UPLOAD   (1<<1)
-#define PROGRESS_DOWN_AND_UP (PROGRESS_UPLOAD | PROGRESS_DOWNLOAD)
-
-#define PGRS_SHOW_DL (1<<0)
-#define PGRS_SHOW_UL (1<<1)
-#define PGRS_DONE_DL (1<<2)
-#define PGRS_DONE_UL (1<<3)
 #define PGRS_HIDE    (1<<4)
 #define PGRS_UL_SIZE_KNOWN (1<<5)
 #define PGRS_DL_SIZE_KNOWN (1<<6)
-
 #define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */
 
-
 #endif /* HEADER_CURL_PROGRESS_H */
 
diff --git a/lib/psl.c b/lib/psl.c
new file mode 100644
index 0000000..568baff
--- /dev/null
+++ b/lib/psl.c
@@ -0,0 +1,111 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#include <curl/curl.h>
+
+#ifdef USE_LIBPSL
+
+#include "psl.h"
+#include "share.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+void Curl_psl_destroy(struct PslCache *pslcache)
+{
+  if(pslcache->psl) {
+    if(pslcache->dynamic)
+      psl_free((psl_ctx_t *) pslcache->psl);
+    pslcache->psl = NULL;
+    pslcache->dynamic = FALSE;
+  }
+}
+
+static time_t now_seconds(void)
+{
+  struct curltime now = Curl_now();
+
+  return now.tv_sec;
+}
+
+const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy)
+{
+  struct PslCache *pslcache = easy->psl;
+  const psl_ctx_t *psl;
+  time_t now;
+
+  if(!pslcache)
+    return NULL;
+
+  Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SHARED);
+  now = now_seconds();
+  if(!pslcache->psl || pslcache->expires <= now) {
+    /* Let a chance to other threads to do the job: avoids deadlock. */
+    Curl_share_unlock(easy, CURL_LOCK_DATA_PSL);
+
+    /* Update cache: this needs an exclusive lock. */
+    Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SINGLE);
+
+    /* Recheck in case another thread did the job. */
+    now = now_seconds();
+    if(!pslcache->psl || pslcache->expires <= now) {
+      bool dynamic = FALSE;
+      time_t expires = TIME_T_MAX;
+
+#if defined(PSL_VERSION_NUMBER) && PSL_VERSION_NUMBER >= 0x001000
+      psl = psl_latest(NULL);
+      dynamic = psl != NULL;
+      /* Take care of possible time computation overflow. */
+      expires = now < TIME_T_MAX - PSL_TTL? now + PSL_TTL: TIME_T_MAX;
+
+      /* Only get the built-in PSL if we do not already have the "latest". */
+      if(!psl && !pslcache->dynamic)
+#endif
+
+        psl = psl_builtin();
+
+      if(psl) {
+        Curl_psl_destroy(pslcache);
+        pslcache->psl = psl;
+        pslcache->dynamic = dynamic;
+        pslcache->expires = expires;
+      }
+    }
+    Curl_share_unlock(easy, CURL_LOCK_DATA_PSL);  /* Release exclusive lock. */
+    Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SHARED);
+  }
+  psl = pslcache->psl;
+  if(!psl)
+    Curl_share_unlock(easy, CURL_LOCK_DATA_PSL);
+  return psl;
+}
+
+void Curl_psl_release(struct Curl_easy *easy)
+{
+  Curl_share_unlock(easy, CURL_LOCK_DATA_PSL);
+}
+
+#endif /* USE_LIBPSL */
diff --git a/lib/psl.h b/lib/psl.h
new file mode 100644
index 0000000..e9f99d0
--- /dev/null
+++ b/lib/psl.h
@@ -0,0 +1,47 @@
+#ifndef HEADER_PSL_H
+#define HEADER_PSL_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#ifdef USE_LIBPSL
+#include <libpsl.h>
+
+#define PSL_TTL (72 * 3600)     /* PSL time to live before a refresh. */
+
+struct PslCache {
+  const psl_ctx_t *psl; /* The PSL. */
+  time_t expires; /* Time this PSL life expires. */
+  bool dynamic; /* PSL should be released when no longer needed. */
+};
+
+const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy);
+void Curl_psl_release(struct Curl_easy *easy);
+void Curl_psl_destroy(struct PslCache *pslcache);
+
+#else
+
+#define Curl_psl_use(easy) NULL
+#define Curl_psl_release(easy)
+#define Curl_psl_destroy(pslcache)
+
+#endif /* USE_LIBPSL */
+#endif /* HEADER_PSL_H */
diff --git a/lib/rand.c b/lib/rand.c
index 0769ed1..1dc2504 100644
--- a/lib/rand.c
+++ b/lib/rand.c
@@ -158,7 +158,7 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
   DEBUGASSERT(num > 1);
 
 #ifdef __clang_analyzer__
-  /* This silences a scan-build warning about accesssing this buffer with
+  /* This silences a scan-build warning about accessing this buffer with
      uninitialized memory. */
   memset(buffer, 0, sizeof(buffer));
 #endif
diff --git a/lib/rtsp.c b/lib/rtsp.c
index 41f3000..182ee29 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -218,8 +218,6 @@ static CURLcode rtsp_done(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct RTSP *rtsp = data->req.protop;
   CURLcode httpStatus;
-  long CSeq_sent;
-  long CSeq_recv;
 
   /* Bypass HTTP empty-reply checks on receive */
   if(data->set.rtspreq == RTSPREQ_RECEIVE)
@@ -229,8 +227,8 @@ static CURLcode rtsp_done(struct connectdata *conn,
 
   if(rtsp) {
     /* Check the sequence numbers */
-    CSeq_sent = rtsp->CSeq_sent;
-    CSeq_recv = rtsp->CSeq_recv;
+    long CSeq_sent = rtsp->CSeq_sent;
+    long CSeq_recv = rtsp->CSeq_recv;
     if((data->set.rtspreq != RTSPREQ_RECEIVE) && (CSeq_sent != CSeq_recv)) {
       failf(data,
             "The CSeq of this request %ld did not match the response %ld",
diff --git a/lib/security.c b/lib/security.c
index d171985..4034115 100644
--- a/lib/security.c
+++ b/lib/security.c
@@ -390,7 +390,7 @@ int Curl_sec_read_msg(struct connectdata *conn, char *buffer,
 
   if(conn->data->set.verbose) {
     buf[decoded_len] = '\n';
-    Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1, conn);
+    Curl_debug(conn->data, CURLINFO_HEADER_IN, buf, decoded_len + 1);
   }
 
   buf[decoded_len] = '\0';
@@ -488,7 +488,7 @@ static CURLcode choose_mech(struct connectdata *conn)
 
   tmp_allocation = realloc(conn->app_data, mech->size);
   if(tmp_allocation == NULL) {
-    failf(data, "Failed realloc of size %u", mech->size);
+    failf(data, "Failed realloc of size %zu", mech->size);
     mech = NULL;
     return CURLE_OUT_OF_MEMORY;
   }
diff --git a/lib/select.c b/lib/select.c
index 28390a4..8cd9eb2 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -80,7 +80,6 @@ int Curl_wait_ms(int timeout_ms)
 #endif
   struct curltime initial_tv;
   int pending_ms;
-  int error;
 #endif
   int r = 0;
 
@@ -98,6 +97,7 @@ int Curl_wait_ms(int timeout_ms)
   pending_ms = timeout_ms;
   initial_tv = Curl_now();
   do {
+    int error;
 #if defined(HAVE_POLL_FINE)
     r = poll(NULL, 0, pending_ms);
 #else
@@ -160,7 +160,6 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
 #endif
   struct curltime initial_tv = {0, 0};
   int pending_ms = 0;
-  int error;
   int r;
   int ret;
 
@@ -210,6 +209,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
   }
 
   do {
+    int error;
     if(timeout_ms < 0)
       pending_ms = -1;
     else if(!timeout_ms)
@@ -291,6 +291,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
 
   do {
+    int error;
     if(timeout_ms > 0) {
       pending_tv.tv_sec = pending_ms / 1000;
       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
@@ -402,7 +403,6 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
   bool fds_none = TRUE;
   unsigned int i;
   int pending_ms = 0;
-  int error;
   int r;
 
   if(ufds) {
@@ -431,6 +431,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
 #ifdef HAVE_POLL_FINE
 
   do {
+    int error;
     if(timeout_ms < 0)
       pending_ms = -1;
     else if(!timeout_ms)
@@ -502,6 +503,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
 
   do {
+    int error;
     if(timeout_ms > 0) {
       pending_tv.tv_sec = pending_ms / 1000;
       pending_tv.tv_usec = (pending_ms % 1000) * 1000;
diff --git a/lib/sendf.c b/lib/sendf.c
index 27c0ccc..d3c10b3 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -240,7 +240,7 @@ void Curl_infof(struct Curl_easy *data, const char *fmt, ...)
     vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
     va_end(ap);
     len = strlen(print_buffer);
-    Curl_debug(data, CURLINFO_TEXT, print_buffer, len, NULL);
+    Curl_debug(data, CURLINFO_TEXT, print_buffer, len);
   }
 }
 
@@ -265,7 +265,7 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
     if(data->set.verbose) {
       error[len] = '\n';
       error[++len] = '\0';
-      Curl_debug(data, CURLINFO_TEXT, error, len, NULL);
+      Curl_debug(data, CURLINFO_TEXT, error, len);
     }
     va_end(ap);
   }
@@ -300,7 +300,7 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
       break;
 
     if(data->set.verbose)
-      Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written, conn);
+      Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written);
 
     if((size_t)bytes_written != write_len) {
       /* if not all was written at once, we must advance the pointer, decrease
@@ -762,8 +762,8 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
 }
 
 /* return 0 on success */
-static int showit(struct Curl_easy *data, curl_infotype type,
-                  char *ptr, size_t size)
+int Curl_debug(struct Curl_easy *data, curl_infotype type,
+               char *ptr, size_t size)
 {
   static const char s_infotype[CURLINFO_END][3] = {
     "* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
@@ -834,41 +834,3 @@ static int showit(struct Curl_easy *data, curl_infotype type,
 #endif
   return rc;
 }
-
-int Curl_debug(struct Curl_easy *data, curl_infotype type,
-               char *ptr, size_t size,
-               struct connectdata *conn)
-{
-  int rc;
-  if(data->set.printhost && conn && conn->host.dispname) {
-    char buffer[160];
-    const char *t = NULL;
-    const char *w = "Data";
-    switch(type) {
-    case CURLINFO_HEADER_IN:
-      w = "Header";
-      /* FALLTHROUGH */
-    case CURLINFO_DATA_IN:
-      t = "from";
-      break;
-    case CURLINFO_HEADER_OUT:
-      w = "Header";
-      /* FALLTHROUGH */
-    case CURLINFO_DATA_OUT:
-      t = "to";
-      break;
-    default:
-      break;
-    }
-
-    if(t) {
-      snprintf(buffer, sizeof(buffer), "[%s %s %s]", w, t,
-               conn->host.dispname);
-      rc = showit(data, CURLINFO_TEXT, buffer, strlen(buffer));
-      if(rc)
-        return rc;
-    }
-  }
-  rc = showit(data, type, ptr, size);
-  return rc;
-}
diff --git a/lib/sendf.h b/lib/sendf.h
index 7c9134d..7627fe6 100644
--- a/lib/sendf.h
+++ b/lib/sendf.h
@@ -84,9 +84,8 @@ CURLcode Curl_write_plain(struct connectdata *conn,
                           ssize_t *written);
 
 /* the function used to output verbose information */
-int Curl_debug(struct Curl_easy *handle, curl_infotype type,
-               char *data, size_t size,
-               struct connectdata *conn);
+int Curl_debug(struct Curl_easy *data, curl_infotype type,
+               char *ptr, size_t size);
 
 
 #endif /* HEADER_CURL_SENDF_H */
diff --git a/lib/setopt.c b/lib/setopt.c
index af53ee3..5c5f4b3 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -142,6 +142,25 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
                             va_arg(param, char *));
     break;
 
+  case CURLOPT_TLS13_CIPHERS:
+    if(Curl_ssl_tls13_ciphersuites()) {
+      /* set preferred list of TLS 1.3 cipher suites */
+      result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_ORIG],
+                              va_arg(param, char *));
+    }
+    else
+      return CURLE_NOT_BUILT_IN;
+    break;
+  case CURLOPT_PROXY_TLS13_CIPHERS:
+    if(Curl_ssl_tls13_ciphersuites()) {
+      /* set preferred list of TLS 1.3 cipher suites for proxy */
+      result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_PROXY],
+                              va_arg(param, char *));
+    }
+    else
+      return CURLE_NOT_BUILT_IN;
+    break;
+
   case CURLOPT_RANDOM_FILE:
     /*
      * This is the path name to a file that contains random data to seed
@@ -1584,14 +1603,19 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
      * String that holds the SSL crypto engine.
      */
     argptr = va_arg(param, char *);
-    if(argptr && argptr[0])
-      result = Curl_ssl_set_engine(data, argptr);
+    if(argptr && argptr[0]) {
+      result = Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], argptr);
+      if(!result) {
+        result = Curl_ssl_set_engine(data, argptr);
+      }
+    }
     break;
 
   case CURLOPT_SSLENGINE_DEFAULT:
     /*
      * flag to set engine as default.
      */
+    Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], NULL);
     result = Curl_ssl_set_engine_default(data);
     break;
   case CURLOPT_CRLF:
@@ -1942,6 +1966,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
       if(data->share->sslsession == data->state.session)
         data->state.session = NULL;
 
+#ifdef USE_LIBPSL
+      if(data->psl == &data->share->psl)
+        data->psl = data->multi? &data->multi->psl: NULL;
+#endif
+
       data->share->dirty--;
 
       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
@@ -1973,8 +2002,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
         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);
+#ifdef USE_LIBPSL
+      if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL))
+        data->psl = &data->share->psl;
+#endif
 
+      Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
     }
     /* check for host cache not needed,
      * it will be done by curl_easy_perform */
@@ -2562,6 +2595,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
   case CURLOPT_DNS_SHUFFLE_ADDRESSES:
     data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE;
     break;
+  case CURLOPT_DISALLOW_USERNAME_IN_URL:
+    data->set.disallow_username_in_url =
+      (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
   default:
     /* unknown tag and its companion, just ignore: */
     result = CURLE_UNKNOWN_OPTION;
diff --git a/lib/sha256.c b/lib/sha256.c
index 55716c6..f9287af 100644
--- a/lib/sha256.c
+++ b/lib/sha256.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Florin Petriuc, <petriuc.florin@gmail.com>
+ * Copyright (C) 1998 - 2018, Florin Petriuc, <petriuc.florin@gmail.com>
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -123,15 +123,11 @@ static const unsigned long K[64] = {
 #define Sigma1(x)   (S(x, 6) ^ S(x, 11) ^ S(x, 25))
 #define Gamma0(x)   (S(x, 7) ^ S(x, 18) ^ R(x, 3))
 #define Gamma1(x)   (S(x, 17) ^ S(x, 19) ^ R(x, 10))
-#ifndef MIN
-#define MIN(x, y)   (((x) < (y)) ? (x) : (y))
-#endif
 /* compress 512-bits */
 static int sha256_compress(struct sha256_state *md,
                            unsigned char *buf)
 {
-  unsigned long S[8], W[64], t0, t1;
-  unsigned long t;
+  unsigned long S[8], W[64];
   int i;
   /* copy state into S */
   for(i = 0; i < 8; i++) {
@@ -146,12 +142,13 @@ static int sha256_compress(struct sha256_state *md,
       W[i - 16];
   }
   /* Compress */
-#define RND(a,b,c,d,e,f,g,h,i)                    \
-  t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
-  t1 = Sigma0(a) + Maj(a, b, c);                  \
-  d += t0;                                        \
+#define RND(a,b,c,d,e,f,g,h,i)                                  \
+  unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
+  unsigned long t1 = Sigma0(a) + Maj(a, b, c);                  \
+  d += t0;                                                      \
   h = t0 + t1;
   for(i = 0; i < 64; ++i) {
+    unsigned long t;
     RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
     t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
     S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
@@ -200,7 +197,7 @@ static int SHA256_Update(struct sha256_state *md,
       inlen -= block_size;
     }
     else {
-      n = MIN(inlen, (block_size - md->curlen));
+      n = CURLMIN(inlen, (block_size - md->curlen));
       memcpy(md->buf + md->curlen, in, n);
       md->curlen += n;
       in += n;
diff --git a/lib/share.c b/lib/share.c
index 870b191..3d51086 100644
--- a/lib/share.c
+++ b/lib/share.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -25,6 +25,7 @@
 #include <curl/curl.h>
 #include "urldata.h"
 #include "share.h"
+#include "psl.h"
 #include "vtls/vtls.h"
 #include "curl_memory.h"
 
@@ -106,6 +107,12 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
         res = CURLSHE_NOMEM;
       break;
 
+    case CURL_LOCK_DATA_PSL:
+#ifndef USE_LIBPSL
+      res = CURLSHE_NOT_BUILT_IN;
+#endif
+      break;
+
     default:
       res = CURLSHE_BAD_OPTION;
     }
@@ -205,6 +212,8 @@ curl_share_cleanup(struct Curl_share *share)
   }
 #endif
 
+  Curl_psl_destroy(&share->psl);
+
   if(share->unlockfunc)
     share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata);
   free(share);
diff --git a/lib/share.h b/lib/share.h
index 4b13406..a7dea41 100644
--- a/lib/share.h
+++ b/lib/share.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -25,6 +25,7 @@
 #include "curl_setup.h"
 #include <curl/curl.h>
 #include "cookie.h"
+#include "psl.h"
 #include "urldata.h"
 #include "conncache.h"
 
@@ -49,6 +50,9 @@ struct Curl_share {
 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
   struct CookieInfo *cookies;
 #endif
+#ifdef USE_LIBPSL
+  struct PslCache psl;
+#endif
 
   struct curl_ssl_session *sslsession;
   size_t max_ssl_sessions;
diff --git a/lib/smb.c b/lib/smb.c
index 9ac6150..e4b18fc 100644
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -59,6 +59,7 @@
 static CURLcode smb_setup_connection(struct connectdata *conn);
 static CURLcode smb_connect(struct connectdata *conn, bool *done);
 static CURLcode smb_connection_state(struct connectdata *conn, bool *done);
+static CURLcode smb_do(struct connectdata *conn, bool *done);
 static CURLcode smb_request_state(struct connectdata *conn, bool *done);
 static CURLcode smb_done(struct connectdata *conn, CURLcode status,
                          bool premature);
@@ -73,7 +74,7 @@ static CURLcode smb_parse_url_path(struct connectdata *conn);
 const struct Curl_handler Curl_handler_smb = {
   "SMB",                                /* scheme */
   smb_setup_connection,                 /* setup_connection */
-  ZERO_NULL,                            /* do_it */
+  smb_do,                               /* do_it */
   smb_done,                             /* done */
   ZERO_NULL,                            /* do_more */
   smb_connect,                          /* connect_it */
@@ -98,7 +99,7 @@ const struct Curl_handler Curl_handler_smb = {
 const struct Curl_handler Curl_handler_smbs = {
   "SMBS",                               /* scheme */
   smb_setup_connection,                 /* setup_connection */
-  ZERO_NULL,                            /* do_it */
+  smb_do,                               /* do_it */
   smb_done,                             /* done */
   ZERO_NULL,                            /* do_more */
   smb_connect,                          /* connect_it */
@@ -173,7 +174,6 @@ enum smb_req_state {
 /* SMB request data */
 struct smb_request {
   enum smb_req_state state;
-  char *share;
   char *path;
   unsigned short tid; /* Even if we connect to the same tree as another */
   unsigned short fid; /* request, the tid will be different */
@@ -182,7 +182,7 @@ struct smb_request {
 
 static void conn_state(struct connectdata *conn, enum smb_conn_state newstate)
 {
-  struct smb_conn *smb = &conn->proto.smbc;
+  struct smb_conn *smbc = &conn->proto.smbc;
 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
   /* For debug purposes */
   static const char * const names[] = {
@@ -194,12 +194,12 @@ static void conn_state(struct connectdata *conn, enum smb_conn_state newstate)
     /* LAST */
   };
 
-  if(smb->state != newstate)
+  if(smbc->state != newstate)
     infof(conn->data, "SMB conn %p state change from %s to %s\n",
-          (void *)smb, names[smb->state], names[newstate]);
+          (void *)smbc, names[smbc->state], names[newstate]);
 #endif
 
-  smb->state = newstate;
+  smbc->state = newstate;
 }
 
 static void request_state(struct connectdata *conn,
@@ -228,6 +228,8 @@ static void request_state(struct connectdata *conn,
   req->state = newstate;
 }
 
+/* this should setup things in the connection, not in the easy
+   handle */
 static CURLcode smb_setup_connection(struct connectdata *conn)
 {
   struct smb_request *req;
@@ -253,7 +255,6 @@ static CURLcode smb_connect(struct connectdata *conn, bool *done)
     return CURLE_LOGIN_DENIED;
 
   /* Initialize the connection state */
-  memset(smbc, 0, sizeof(*smbc));
   smbc->state = SMB_CONNECTING;
   smbc->recv_buf = malloc(MAX_MESSAGE_SIZE);
   if(!smbc->recv_buf)
@@ -366,7 +367,7 @@ static CURLcode smb_send(struct connectdata *conn, ssize_t len,
   ssize_t bytes_written;
   CURLcode result;
 
-  result = Curl_write(conn, FIRSTSOCKET, conn->data->state.uploadbuffer,
+  result = Curl_write(conn, FIRSTSOCKET, conn->data->state.ulbuf,
                       len, &bytes_written);
   if(result)
     return result;
@@ -392,7 +393,7 @@ static CURLcode smb_flush(struct connectdata *conn)
     return CURLE_OK;
 
   result = Curl_write(conn, FIRSTSOCKET,
-                      conn->data->state.uploadbuffer + smbc->sent,
+                      conn->data->state.ulbuf + smbc->sent,
                       len, &bytes_written);
   if(result)
     return result;
@@ -408,9 +409,12 @@ static CURLcode smb_flush(struct connectdata *conn)
 static CURLcode smb_send_message(struct connectdata *conn, unsigned char cmd,
                                  const void *msg, size_t msg_len)
 {
-  smb_format_message(conn, (struct smb_header *)conn->data->state.uploadbuffer,
+  CURLcode result = Curl_get_upload_buffer(conn->data);
+  if(result)
+    return result;
+  smb_format_message(conn, (struct smb_header *)conn->data->state.ulbuf,
                      cmd, msg_len);
-  memcpy(conn->data->state.uploadbuffer + sizeof(struct smb_header),
+  memcpy(conn->data->state.ulbuf + sizeof(struct smb_header),
          msg, msg_len);
 
   return smb_send(conn, sizeof(struct smb_header) + msg_len, 0);
@@ -475,11 +479,11 @@ static CURLcode smb_send_setup(struct connectdata *conn)
 
 static CURLcode smb_send_tree_connect(struct connectdata *conn)
 {
-  struct smb_request *req = conn->data->req.protop;
   struct smb_tree_connect msg;
+  struct smb_conn *smbc = &conn->proto.smbc;
   char *p = msg.bytes;
 
-  size_t byte_count = strlen(conn->host.name) + strlen(req->share);
+  size_t byte_count = strlen(conn->host.name) + strlen(smbc->share);
   byte_count += strlen(SERVICENAME) + 5; /* 2 nulls and 3 backslashes */
   if(byte_count > sizeof(msg.bytes))
     return CURLE_FILESIZE_EXCEEDED;
@@ -491,7 +495,7 @@ static CURLcode smb_send_tree_connect(struct connectdata *conn)
   MSGCAT("\\\\");
   MSGCAT(conn->host.name);
   MSGCAT("\\");
-  MSGCATNULL(req->share);
+  MSGCATNULL(smbc->share);
   MSGCATNULL(SERVICENAME); /* Match any type of service */
   byte_count = p - msg.bytes;
   msg.byte_count = smb_swap16((unsigned short)byte_count);
@@ -571,11 +575,15 @@ static CURLcode smb_send_read(struct connectdata *conn)
 
 static CURLcode smb_send_write(struct connectdata *conn)
 {
-  struct smb_write *msg = (struct smb_write *)conn->data->state.uploadbuffer;
+  struct smb_write *msg;
   struct smb_request *req = conn->data->req.protop;
   curl_off_t offset = conn->data->req.offset;
-
   curl_off_t upload_size = conn->data->req.size - conn->data->req.bytecount;
+  CURLcode result = Curl_get_upload_buffer(conn->data);
+  if(result)
+    return result;
+  msg = (struct smb_write *)conn->data->state.ulbuf;
+
   if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */
     upload_size = MAX_PAYLOAD_SIZE - 1;
 
@@ -602,9 +610,9 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
 
   /* Check if there is data in the transfer buffer */
   if(!smbc->send_size && smbc->upload_size) {
-    int nread = smbc->upload_size > UPLOAD_BUFSIZE ? UPLOAD_BUFSIZE :
-      (int) smbc->upload_size;
-    conn->data->req.upload_fromhere = conn->data->state.uploadbuffer;
+    size_t nread = smbc->upload_size > UPLOAD_BUFSIZE ? UPLOAD_BUFSIZE :
+      smbc->upload_size;
+    conn->data->req.upload_fromhere = conn->data->state.ulbuf;
     result = Curl_fillreadbuffer(conn, nread, &nread);
     if(result && result != CURLE_AGAIN)
       return result;
@@ -910,55 +918,52 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
 static CURLcode smb_done(struct connectdata *conn, CURLcode status,
                          bool premature)
 {
-  struct smb_request *req = conn->data->req.protop;
-
   (void) premature;
-
-  Curl_safefree(req->share);
   Curl_safefree(conn->data->req.protop);
-
   return status;
 }
 
 static CURLcode smb_disconnect(struct connectdata *conn, bool dead)
 {
   struct smb_conn *smbc = &conn->proto.smbc;
-  struct smb_request *req = conn->data->req.protop;
-
   (void) dead;
-
+  Curl_safefree(smbc->share);
   Curl_safefree(smbc->domain);
   Curl_safefree(smbc->recv_buf);
-
-  /* smb_done is not always called, so cleanup the request */
-  if(req) {
-    Curl_safefree(req->share);
-  }
-
   return CURLE_OK;
 }
 
 static int smb_getsock(struct connectdata *conn, curl_socket_t *socks,
                        int numsocks)
 {
-  struct smb_conn *smbc = &conn->proto.smbc;
-
   if(!numsocks)
     return GETSOCK_BLANK;
 
   socks[0] = conn->sock[FIRSTSOCKET];
+  return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
+}
 
-  if(smbc->send_size || smbc->upload_size)
-    return GETSOCK_WRITESOCK(0);
+static CURLcode smb_do(struct connectdata *conn, bool *done)
+{
+  struct smb_conn *smbc = &conn->proto.smbc;
+  struct smb_request *req = conn->data->req.protop;
 
-  return GETSOCK_READSOCK(0);
+  *done = FALSE;
+  if(smbc->share) {
+    req->path = strchr(smbc->share, '\0');
+    if(req->path) {
+      req->path++;
+      return CURLE_OK;
+    }
+  }
+  return CURLE_URL_MALFORMAT;
 }
 
 static CURLcode smb_parse_url_path(struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
-  struct smb_request *req = data->req.protop;
+  struct smb_conn *smbc = &conn->proto.smbc;
   char *path;
   char *slash;
 
@@ -968,35 +973,29 @@ static CURLcode smb_parse_url_path(struct connectdata *conn)
     return result;
 
   /* Parse the path for the share */
-  req->share = strdup((*path == '/' || *path == '\\') ? path + 1 : path);
-  if(!req->share) {
-    free(path);
-
+  smbc->share = strdup((*path == '/' || *path == '\\') ? path + 1 : path);
+  free(path);
+  if(!smbc->share)
     return CURLE_OUT_OF_MEMORY;
-  }
 
-  slash = strchr(req->share, '/');
+  slash = strchr(smbc->share, '/');
   if(!slash)
-    slash = strchr(req->share, '\\');
+    slash = strchr(smbc->share, '\\');
 
   /* The share must be present */
   if(!slash) {
-    free(path);
-
+    Curl_safefree(smbc->share);
     return CURLE_URL_MALFORMAT;
   }
 
   /* Parse the path for the file path converting any forward slashes into
      backslashes */
   *slash++ = 0;
-  req->path = slash;
+
   for(; *slash; slash++) {
     if(*slash == '/')
       *slash = '\\';
   }
-
-  free(path);
-
   return CURLE_OK;
 }
 
diff --git a/lib/smb.h b/lib/smb.h
index c3ee7ae..9ce6b56 100644
--- a/lib/smb.h
+++ b/lib/smb.h
@@ -35,6 +35,7 @@ struct smb_conn {
   enum smb_conn_state state;
   char *user;
   char *domain;
+  char *share;
   unsigned char challenge[8];
   unsigned int session_key;
   unsigned short uid;
diff --git a/lib/smtp.c b/lib/smtp.c
index 3f3b45a..ecf10a4 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -704,7 +704,6 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
   struct smtp_conn *smtpc = &conn->proto.smtpc;
   const char *line = data->state.buffer;
   size_t len = strlen(line);
-  size_t wordlen;
 
   (void)instate; /* no use for this yet */
 
@@ -739,6 +738,7 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
       /* Loop through the data line */
       for(;;) {
         size_t llen;
+        size_t wordlen;
         unsigned int mechbit;
 
         while(len &&
@@ -1563,13 +1563,14 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
   if(!scratch || data->set.crlf) {
     oldscratch = scratch;
 
-    scratch = newscratch = malloc(2 * data->set.buffer_size);
+    scratch = newscratch = malloc(2 * UPLOAD_BUFSIZE);
     if(!newscratch) {
       failf(data, "Failed to alloc scratch buffer!");
 
       return CURLE_OUT_OF_MEMORY;
     }
   }
+  DEBUGASSERT(UPLOAD_BUFSIZE >= nread);
 
   /* Have we already sent part of the EOB? */
   eob_sent = smtp->eob;
diff --git a/lib/socks.c b/lib/socks.c
index ac4270e..81f3eda 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -57,10 +57,9 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
   ssize_t nread;
   ssize_t allread = 0;
   int result;
-  timediff_t timeleft;
   *n = 0;
   for(;;) {
-    timeleft = Curl_timeleft(conn->data, NULL, TRUE);
+    timediff_t timeleft = Curl_timeleft(conn->data, NULL, TRUE);
     if(timeleft < 0) {
       /* we already got the timeout */
       result = CURLE_OPERATION_TIMEDOUT;
@@ -116,7 +115,6 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
 #define SOCKS4REQLEN 262
   unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
                                            id */
-  int result;
   CURLcode code;
   curl_socket_t sock = conn->sock[sockindex];
   struct Curl_easy *data = conn->data;
@@ -220,11 +218,12 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
    * Make connection
    */
   {
+    int result;
     ssize_t actualread;
     ssize_t written;
     ssize_t hostnamelen = 0;
-    int packetsize = 9 +
-      (int)strlen((char *)socksreq + 8); /* size including NUL */
+    ssize_t packetsize = 9 +
+      strlen((char *)socksreq + 8); /* size including NUL */
 
     /* If SOCKS4a, set special invalid IP address 0.0.0.x */
     if(protocol4a) {
@@ -617,11 +616,11 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
     if(dns)
       hp = dns->addr;
     if(hp) {
-      int i;
       char buf[64];
       Curl_printable_address(hp, buf, sizeof(buf));
 
       if(hp->ai_family == AF_INET) {
+        int i;
         struct sockaddr_in *saddr_in;
         socksreq[len++] = 1; /* ATYP: IPv4 = 1 */
 
@@ -634,6 +633,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
       }
 #ifdef ENABLE_IPV6
       else if(hp->ai_family == AF_INET6) {
+        int i;
         struct sockaddr_in6 *saddr_in6;
         socksreq[len++] = 4; /* ATYP: IPv6 = 4 */
 
diff --git a/lib/splay.c b/lib/splay.c
index 69af446..c54a63b 100644
--- a/lib/splay.c
+++ b/lib/splay.c
@@ -41,7 +41,6 @@ struct Curl_tree *Curl_splay(struct curltime i,
                              struct Curl_tree *t)
 {
   struct Curl_tree N, *l, *r, *y;
-  long comp;
 
   if(t == NULL)
     return t;
@@ -49,7 +48,7 @@ struct Curl_tree *Curl_splay(struct curltime i,
   l = r = &N;
 
   for(;;) {
-    comp = compare(i, t->key);
+    long comp = compare(i, t->key);
     if(comp < 0) {
       if(t->smaller == NULL)
         break;
diff --git a/lib/ssh-libssh.c b/lib/ssh-libssh.c
index 34ef490..7d59089 100644
--- a/lib/ssh-libssh.c
+++ b/lib/ssh-libssh.c
@@ -204,11 +204,21 @@ static CURLcode sftp_error_to_CURLE(int err)
   return CURLE_SSH;
 }
 
+#ifndef DEBUGBUILD
+#define state(x,y) mystate(x,y)
+#else
+#define state(x,y) mystate(x,y, __LINE__)
+#endif
+
 /*
  * SSH State machine related code
  */
 /* This is the ONLY way to change SSH state! */
-static void state(struct connectdata *conn, sshstate nowstate)
+static void mystate(struct connectdata *conn, sshstate nowstate
+#ifdef DEBUGBUILD
+                    , int lineno
+#endif
+  )
 {
   struct ssh_conn *sshc = &conn->proto.sshc;
 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -278,8 +288,9 @@ static void state(struct connectdata *conn, sshstate nowstate)
 
 
   if(sshc->state != nowstate) {
-    infof(conn->data, "SSH %p state change from %s to %s\n",
-          (void *) sshc, names[sshc->state], names[nowstate]);
+    infof(conn->data, "SSH %p state change from %s to %s (line %d)\n",
+          (void *) sshc, names[sshc->state], names[nowstate],
+          lineno);
   }
 #endif
 
@@ -418,7 +429,7 @@ cleanup:
 }
 
 #define MOVE_TO_ERROR_STATE(_r) { \
-  state(conn, SSH_SESSION_FREE); \
+  state(conn, SSH_SESSION_DISCONNECT); \
   sshc->actualcode = _r; \
   rc = SSH_ERROR; \
   break; \
@@ -486,7 +497,7 @@ restart:
       if(rc < 0)
         return SSH_ERROR;
 
-    /* fallthrough */
+    /* FALLTHROUGH */
     case 1:
       sshc->kbd_state = 1;
 
@@ -561,7 +572,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
       ssh_set_blocking(sshc->ssh_session, 0);
 
       state(conn, SSH_S_STARTUP);
-      /* fall-through */
+      /* FALLTHROUGH */
 
     case SSH_S_STARTUP:
       rc = ssh_connect(sshc->ssh_session);
@@ -575,7 +586,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
 
       state(conn, SSH_HOSTKEY);
 
-      /* fall-through */
+      /* FALLTHROUGH */
     case SSH_HOSTKEY:
 
       rc = myssh_is_known(conn);
@@ -584,7 +595,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
       }
 
       state(conn, SSH_AUTHLIST);
-      /* fall through */
+      /* FALLTHROUGH */
     case SSH_AUTHLIST:{
         sshc->authed = FALSE;
 
@@ -607,6 +618,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
         sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
         if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
           state(conn, SSH_AUTH_PKEY_INIT);
+          infof(data, "Authentication using SSH public key file\n");
         }
         else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
           state(conn, SSH_AUTH_GSSAPI);
@@ -651,6 +663,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
         if(rc != SSH_OK) {
           failf(data, "Could not load private key file %s",
                 data->set.str[STRING_SSH_PRIVATE_KEY]);
+          MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
           break;
         }
 
@@ -659,8 +672,6 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
 
       }
       else {
-        infof(data, "Authentication using SSH public key file\n");
-
         rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL,
                                          data->set.ssl.key_passwd);
         if(rc == SSH_AUTH_AGAIN) {
@@ -748,7 +759,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
         MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
       }
       state(conn, SSH_AUTH_PASS);
-      /* fall through */
+      /* FALLTHROUGH */
 
     case SSH_AUTH_PASS:
       rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd);
@@ -812,7 +823,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
         break;
       }
       state(conn, SSH_SFTP_REALPATH);
-      /* fall through */
+      /* FALLTHROUGH */
     case SSH_SFTP_REALPATH:
       /*
        * Get the "home" directory
@@ -1279,7 +1290,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
       if(sshc->readdir_attrs) {
         sshc->readdir_filename = sshc->readdir_attrs->name;
         sshc->readdir_longentry = sshc->readdir_attrs->longname;
-        sshc->readdir_len = (int)strlen(sshc->readdir_filename);
+        sshc->readdir_len = strlen(sshc->readdir_filename);
 
         if(data->set.ftp_list_only) {
           char *tmpLine;
@@ -1306,11 +1317,11 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
           if(data->set.verbose) {
             Curl_debug(data, CURLINFO_DATA_OUT,
                        (char *)sshc->readdir_filename,
-                       sshc->readdir_len, conn);
+                       sshc->readdir_len);
           }
         }
         else {
-          sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
+          sshc->readdir_currLen = strlen(sshc->readdir_longentry);
           sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
           sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
           if(!sshc->readdir_line) {
@@ -1371,12 +1382,12 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
         if(sshc->readdir_filename == NULL)
           sshc->readdir_len = 0;
         else
-          sshc->readdir_len = (int)strlen(sshc->readdir_tmp);
+          sshc->readdir_len = strlen(sshc->readdir_tmp);
         sshc->readdir_longentry = NULL;
         sshc->readdir_filename = sshc->readdir_tmp;
       }
       else {
-        sshc->readdir_len = (int)strlen(sshc->readdir_link_attrs->name);
+        sshc->readdir_len = strlen(sshc->readdir_link_attrs->name);
         sshc->readdir_filename = sshc->readdir_link_attrs->name;
         sshc->readdir_longentry = sshc->readdir_link_attrs->longname;
       }
@@ -1408,7 +1419,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
       sshc->readdir_longentry = NULL;
 
       state(conn, SSH_SFTP_READDIR_BOTTOM);
-      /* fall through */
+      /* FALLTHROUGH */
     case SSH_SFTP_READDIR_BOTTOM:
       sshc->readdir_currLen += snprintf(sshc->readdir_line +
                                         sshc->readdir_currLen,
@@ -1423,7 +1434,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
         /* output debug output if that is requested */
         if(data->set.verbose) {
           Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
-                     sshc->readdir_currLen, conn);
+                     sshc->readdir_currLen);
         }
         data->req.bytecount += sshc->readdir_currLen;
       }
@@ -1740,7 +1751,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
         MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
       }
       state(conn, SSH_SCP_DOWNLOAD);
-      /* fall through */
+      /* FALLTHROUGH */
 
     case SSH_SCP_DOWNLOAD:{
         curl_off_t bytecount;
@@ -1805,7 +1816,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
       ssh_set_blocking(sshc->ssh_session, 0);
 
       state(conn, SSH_SESSION_DISCONNECT);
-      /* fall through */
+      /* FALLTHROUGH */
 
     case SSH_SESSION_DISCONNECT:
       /* during weird times when we've been prematurely aborted, the channel
@@ -1822,7 +1833,7 @@ static CURLcode myssh_statemach_act(struct connectdata *conn, bool *block)
       conn->data->state.most_recent_ftp_entrypath = NULL;
 
       state(conn, SSH_SESSION_FREE);
-      /* fall through */
+      /* FALLTHROUGH */
     case SSH_SESSION_FREE:
       if(sshc->ssh_session) {
         ssh_free(sshc->ssh_session);
@@ -2379,7 +2390,8 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
     /* Post quote commands are executed after the SFTP_CLOSE state to avoid
        errors that could happen due to open file handles during POSTQUOTE
        operation */
-    if(!status && !premature && conn->data->set.postquote) {
+    if(!status && !premature && conn->data->set.postquote &&
+       !conn->bits.retry) {
       sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
       state(conn, SSH_SFTP_CLOSE);
     }
@@ -2437,7 +2449,7 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
         return -1;
       }
 
-      /* fall-through */
+      /* FALLTHROUGH */
     case 1:
       conn->proto.sshc.sftp_recv_state = 1;
 
@@ -2500,8 +2512,8 @@ static void sftp_quote(struct connectdata *conn)
       return;
     }
     if(data->set.verbose) {
-      Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4, conn);
-      Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
+      Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
+      Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
     }
     /* this sends an FTP-like "header" to the header callback so that the
        current directory can be read very similar to how it is read when
diff --git a/lib/ssh.c b/lib/ssh.c
index bf7bd54..a4b2ca4 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -659,7 +659,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       libssh2_session_set_blocking(sshc->ssh_session, 0);
 
       state(conn, SSH_S_STARTUP);
-      /* fall-through */
+      /* FALLTHROUGH */
 
     case SSH_S_STARTUP:
       rc = libssh2_session_startup(sshc->ssh_session, (int)sock);
@@ -675,7 +675,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
 
       state(conn, SSH_HOSTKEY);
 
-      /* fall-through */
+      /* FALLTHROUGH */
     case SSH_HOSTKEY:
       /*
        * Before we authenticate we should check the hostkey's fingerprint
@@ -1175,8 +1175,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           break;
         }
         if(data->set.verbose) {
-          Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn);
-          Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
+          Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4);
+          Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
         }
         /* this sends an FTP-like "header" to the header callback so that the
            current directory can be read very similar to how it is read when
@@ -1933,17 +1933,17 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       break;
 
     case SSH_SFTP_READDIR:
-      sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle,
-                                                  sshc->readdir_filename,
-                                                  PATH_MAX,
-                                                  sshc->readdir_longentry,
-                                                  PATH_MAX,
-                                                  &sshc->readdir_attrs);
-      if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
-        rc = LIBSSH2_ERROR_EAGAIN;
+      rc = libssh2_sftp_readdir_ex(sshc->sftp_handle,
+                                   sshc->readdir_filename,
+                                   PATH_MAX,
+                                   sshc->readdir_longentry,
+                                   PATH_MAX,
+                                   &sshc->readdir_attrs);
+      if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
-      if(sshc->readdir_len > 0) {
+      if(rc > 0) {
+        sshc->readdir_len = (size_t) rc;
         sshc->readdir_filename[sshc->readdir_len] = '\0';
 
         if(data->set.ftp_list_only) {
@@ -1970,11 +1970,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           /* output debug output if that is requested */
           if(data->set.verbose) {
             Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename,
-                       sshc->readdir_len, conn);
+                       sshc->readdir_len);
           }
         }
         else {
-          sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
+          sshc->readdir_currLen = strlen(sshc->readdir_longentry);
           sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
           sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
           if(!sshc->readdir_line) {
@@ -2008,13 +2008,13 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
           break;
         }
       }
-      else if(sshc->readdir_len == 0) {
+      else if(rc == 0) {
         Curl_safefree(sshc->readdir_filename);
         Curl_safefree(sshc->readdir_longentry);
         state(conn, SSH_SFTP_READDIR_DONE);
         break;
       }
-      else if(sshc->readdir_len <= 0) {
+      else if(rc < 0) {
         err = sftp_libssh2_last_error(sshc->sftp_session);
         result = sftp_libssh2_error_to_CURLE(err);
         sshc->actualcode = result?result:CURLE_SSH;
@@ -2029,16 +2029,16 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
       break;
 
     case SSH_SFTP_READDIR_LINK:
-      sshc->readdir_len =
+      rc =
         libssh2_sftp_symlink_ex(sshc->sftp_session,
                                 sshc->readdir_linkPath,
                                 curlx_uztoui(strlen(sshc->readdir_linkPath)),
                                 sshc->readdir_filename,
                                 PATH_MAX, LIBSSH2_SFTP_READLINK);
-      if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
-        rc = LIBSSH2_ERROR_EAGAIN;
+      if(rc == LIBSSH2_ERROR_EAGAIN) {
         break;
       }
+      sshc->readdir_len = (size_t) rc;
       Curl_safefree(sshc->readdir_linkPath);
 
       /* get room for the filename and extra output */
@@ -2079,7 +2079,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
         /* output debug output if that is requested */
         if(data->set.verbose) {
           Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
-                     sshc->readdir_currLen, conn);
+                     sshc->readdir_currLen);
         }
         data->req.bytecount += sshc->readdir_currLen;
       }
@@ -3219,7 +3219,8 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
     /* Post quote commands are executed after the SFTP_CLOSE state to avoid
        errors that could happen due to open file handles during POSTQUOTE
        operation */
-    if(!status && !premature && conn->data->set.postquote) {
+    if(!status && !premature && conn->data->set.postquote &&
+       !conn->bits.retry) {
       sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
       state(conn, SSH_SFTP_CLOSE);
     }
diff --git a/lib/ssh.h b/lib/ssh.h
index 1c13550..0620aac 100644
--- a/lib/ssh.h
+++ b/lib/ssh.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -131,7 +131,7 @@ struct ssh_conn {
                                  quote command fails) */
   char *homedir;              /* when doing SFTP we figure out home dir in the
                                  connect phase */
-  int readdir_len, readdir_totalLen, readdir_currLen;
+  size_t readdir_len, readdir_totalLen, readdir_currLen;
   char *readdir_line;
   char *readdir_linkPath;
   /* end of READDIR stuff */
diff --git a/lib/strcase.h b/lib/strcase.h
index ea2abc8..6fee384 100644
--- a/lib/strcase.h
+++ b/lib/strcase.h
@@ -46,6 +46,5 @@ char Curl_raw_toupper(char in);
 #define checkprefix(a,b)    curl_strnequal(a,b,strlen(a))
 
 void Curl_strntoupper(char *dest, const char *src, size_t n);
-char Curl_raw_toupper(char in);
 
 #endif /* HEADER_CURL_STRCASE_H */
diff --git a/lib/system_win32.c b/lib/system_win32.c
index cfbbf32..6b8004e 100644
--- a/lib/system_win32.c
+++ b/lib/system_win32.c
@@ -26,6 +26,7 @@
 
 #include <curl/curl.h>
 #include "system_win32.h"
+#include "warnless.h"
 
 /* The last #include files should be: */
 #include "curl_memory.h"
@@ -134,8 +135,9 @@ bool Curl_verify_windows_version(const unsigned int majorVersion,
       break;
 
     case VERSION_LESS_THAN_EQUAL:
-      if(osver.dwMajorVersion <= majorVersion &&
-         osver.dwMinorVersion <= minorVersion)
+      if(osver.dwMajorVersion < majorVersion ||
+        (osver.dwMajorVersion == majorVersion &&
+         osver.dwMinorVersion <= minorVersion))
         matched = TRUE;
       break;
 
@@ -146,8 +148,9 @@ bool Curl_verify_windows_version(const unsigned int majorVersion,
       break;
 
     case VERSION_GREATER_THAN_EQUAL:
-      if(osver.dwMajorVersion >= majorVersion &&
-         osver.dwMinorVersion >= minorVersion)
+      if(osver.dwMajorVersion > majorVersion ||
+        (osver.dwMajorVersion == majorVersion &&
+         osver.dwMinorVersion >= minorVersion))
         matched = TRUE;
       break;
 
@@ -278,7 +281,9 @@ HMODULE Curl_load_library(LPCTSTR filename)
 
   /* Attempt to find LoadLibraryEx() which is only available on Windows 2000
      and above */
-  pLoadLibraryEx = (LOADLIBRARYEX_FN) GetProcAddress(hKernel32, LOADLIBARYEX);
+  pLoadLibraryEx =
+    CURLX_FUNCTION_CAST(LOADLIBRARYEX_FN,
+                        (GetProcAddress(hKernel32, LOADLIBARYEX)));
 
   /* Detect if there's already a path in the filename and load the library if
      there is. Note: Both back slashes and forward slashes have been supported
diff --git a/lib/telnet.c b/lib/telnet.c
index d71c8e0..05fe744 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -52,10 +52,6 @@
 #include "connect.h"
 #include "progress.h"
 #include "system_win32.h"
-
-#define  TELOPTS
-#define  TELCMDS
-
 #include "arpa_telnet.h"
 #include "select.h"
 #include "strcase.h"
@@ -74,10 +70,10 @@
     x->subend = x->subpointer;                          \
     CURL_SB_CLEAR(x);                                   \
   } WHILE_FALSE
-#define CURL_SB_ACCUM(x,c)                                   \
-  do {                                                       \
-    if(x->subpointer < (x->subbuffer + sizeof x->subbuffer)) \
-      *x->subpointer++ = (c);                                \
+#define CURL_SB_ACCUM(x,c)                                      \
+  do {                                                          \
+    if(x->subpointer < (x->subbuffer + sizeof(x->subbuffer)))   \
+      *x->subpointer++ = (c);                                   \
   } WHILE_FALSE
 
 #define  CURL_SB_GET(x) ((*x->subpointer++)&0xff)
@@ -92,6 +88,7 @@
 #endif
 
 #ifdef USE_WINSOCK
+typedef WSAEVENT (WINAPI *WSOCK2_EVENT)(void);
 typedef FARPROC WSOCK2_FUNC;
 static CURLcode check_wsock2(struct Curl_easy *data);
 #endif
@@ -109,8 +106,10 @@ static void printoption(struct Curl_easy *data,
 
 static void negotiate(struct connectdata *);
 static void send_negotiation(struct connectdata *, int cmd, int option);
-static void set_local_option(struct connectdata *, int cmd, int option);
-static void set_remote_option(struct connectdata *, int cmd, int option);
+static void set_local_option(struct connectdata *conn,
+                             int option, int newstate);
+static void set_remote_option(struct connectdata *conn,
+                              int option, int newstate);
 
 static void printsub(struct Curl_easy *data,
                      int direction, unsigned char *pointer,
@@ -311,9 +310,6 @@ static void negotiate(struct connectdata *conn)
 static void printoption(struct Curl_easy *data,
                         const char *direction, int cmd, int option)
 {
-  const char *fmt;
-  const char *opt;
-
   if(data->set.verbose) {
     if(cmd == CURL_IAC) {
       if(CURL_TELCMD_OK(option))
@@ -322,9 +318,12 @@ static void printoption(struct Curl_easy *data,
         infof(data, "%s IAC %d\n", direction, option);
     }
     else {
-      fmt = (cmd == CURL_WILL) ? "WILL" : (cmd == CURL_WONT) ? "WONT" :
-        (cmd == CURL_DO) ? "DO" : (cmd == CURL_DONT) ? "DONT" : 0;
+      const char *fmt = (cmd == CURL_WILL) ? "WILL" :
+                        (cmd == CURL_WONT) ? "WONT" :
+                        (cmd == CURL_DO) ? "DO" :
+                        (cmd == CURL_DONT) ? "DONT" : 0;
       if(fmt) {
+        const char *opt;
         if(CURL_TELOPT_OK(option))
           opt = CURL_TELOPT(option);
         else if(option == CURL_TELOPT_EXOPL)
@@ -348,7 +347,6 @@ static void send_negotiation(struct connectdata *conn, int cmd, int option)
 {
    unsigned char buf[3];
    ssize_t bytes_written;
-   int err;
    struct Curl_easy *data = conn->data;
 
    buf[0] = CURL_IAC;
@@ -357,7 +355,7 @@ static void send_negotiation(struct connectdata *conn, int cmd, int option)
 
    bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3);
    if(bytes_written < 0) {
-     err = SOCKERRNO;
+     int err = SOCKERRNO;
      failf(data,"Sending data failed (%d)",err);
    }
 
@@ -710,9 +708,8 @@ static void printsub(struct Curl_easy *data,
                      unsigned char *pointer,    /* where suboption data is */
                      size_t length)             /* length of suboption data */
 {
-  unsigned int i = 0;
-
   if(data->set.verbose) {
+    unsigned int i = 0;
     if(direction) {
       infof(data, "%s IAC SB ", (direction == '<')? "RCVD":"SENT");
       if(length >= 3) {
@@ -764,7 +761,7 @@ static void printsub(struct Curl_easy *data,
     switch(pointer[0]) {
     case CURL_TELOPT_NAWS:
       if(length > 4)
-        infof(data, "Width: %hu ; Height: %hu", (pointer[1]<<8) | pointer[2],
+        infof(data, "Width: %d ; Height: %d", (pointer[1]<<8) | pointer[2],
               (pointer[3]<<8) | pointer[4]);
       break;
     default:
@@ -928,7 +925,6 @@ static void suboption(struct connectdata *conn)
   unsigned char temp[2048];
   ssize_t bytes_written;
   size_t len;
-  size_t tmplen;
   int err;
   char varname[128] = "";
   char varval[128] = "";
@@ -968,7 +964,7 @@ static void suboption(struct connectdata *conn)
       len = 4;
 
       for(v = tn->telnet_vars; v; v = v->next) {
-        tmplen = (strlen(v->data) + 1);
+        size_t tmplen = (strlen(v->data) + 1);
         /* Add the variable only if it fits */
         if(len + tmplen < (int)sizeof(temp)-6) {
           if(sscanf(v->data, "%127[^,],%127s", varname, varval)) {
@@ -1017,7 +1013,7 @@ static void sendsuboption(struct connectdata *conn, int option)
     CURL_SB_ACCUM(tn, CURL_IAC);
     CURL_SB_ACCUM(tn, CURL_SB);
     CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS);
-    /* We must deal either with litte or big endian processors */
+    /* We must deal either with little or big endian processors */
     /* Window size must be sent according to the 'network order' */
     x = htons(tn->subopt_wsx);
     y = htons(tn->subopt_wsy);
@@ -1223,7 +1219,7 @@ CURLcode telrcv(struct connectdata *conn,
 static CURLcode send_telnet_data(struct connectdata *conn,
                                  char *buffer, ssize_t nread)
 {
-  ssize_t escapes, i, j, outlen;
+  ssize_t escapes, i, outlen;
   unsigned char *outbuf = NULL;
   CURLcode result = CURLE_OK;
   ssize_t bytes_written, total_written;
@@ -1238,6 +1234,7 @@ static CURLcode send_telnet_data(struct connectdata *conn,
   if(outlen == nread)
     outbuf = (unsigned char *)buffer;
   else {
+    ssize_t j;
     outbuf = malloc(nread + escapes + 1);
     if(!outbuf)
       return CURLE_OUT_OF_MEMORY;
@@ -1306,7 +1303,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
 #ifdef USE_WINSOCK
   HMODULE wsock2;
   WSOCK2_FUNC close_event_func;
-  WSOCK2_FUNC create_event_func;
+  WSOCK2_EVENT create_event_func;
   WSOCK2_FUNC event_select_func;
   WSOCK2_FUNC enum_netevents_func;
   WSAEVENT event_handle;
@@ -1315,7 +1312,6 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
   HANDLE objs[2];
   DWORD  obj_count;
   DWORD  wait_timeout;
-  DWORD waitret;
   DWORD readfile_read;
   int err;
 #else
@@ -1361,7 +1357,9 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
   }
 
   /* Grab a pointer to WSACreateEvent */
-  create_event_func = GetProcAddress(wsock2, "WSACreateEvent");
+  create_event_func =
+    CURLX_FUNCTION_CAST(WSOCK2_EVENT,
+                        (GetProcAddress(wsock2, "WSACreateEvent")));
   if(create_event_func == NULL) {
     failf(data, "failed to find WSACreateEvent function (%u)", GetLastError());
     FreeLibrary(wsock2);
@@ -1438,7 +1436,8 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
   /* Keep on listening and act on events */
   while(keepon) {
     const DWORD buf_size = (DWORD)data->set.buffer_size;
-    waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout);
+    DWORD waitret = WaitForMultipleObjects(obj_count, objs,
+                                           FALSE, wait_timeout);
     switch(waitret) {
     case WAIT_TIMEOUT:
     {
@@ -1607,7 +1606,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
     case 0:                     /* timeout */
       pfd[0].revents = 0;
       pfd[1].revents = 0;
-      /* fall through */
+      /* FALLTHROUGH */
     default:                    /* read! */
       if(pfd[0].revents & POLLIN) {
         /* read data from network */
diff --git a/lib/tftp.c b/lib/tftp.c
index b32960f..e5bc80b 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -451,7 +451,6 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
   ssize_t senddata;
   const char *mode = "octet";
   char *filename;
-  char buf[64];
   struct Curl_easy *data = state->conn->data;
   CURLcode result = CURLE_OK;
 
@@ -504,6 +503,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
 
     /* optional addition of TFTP options */
     if(!data->set.tftp_no_options) {
+      char buf[64];
       /* add tsize option */
       if(data->set.upload && (data->state.infilesize != -1))
         snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
@@ -710,10 +710,9 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
 {
   struct Curl_easy *data = state->conn->data;
   ssize_t sbytes;
-  int rblock;
   CURLcode result = CURLE_OK;
   struct SingleRequest *k = &data->req;
-  int cb; /* Bytes currently read */
+  size_t cb; /* Bytes currently read */
 
   switch(event) {
 
@@ -721,7 +720,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
   case TFTP_EVENT_OACK:
     if(event == TFTP_EVENT_ACK) {
       /* Ack the packet */
-      rblock = getrpacketblock(&state->rpacket);
+      int rblock = getrpacketblock(&state->rpacket);
 
       if(rblock != state->block &&
          /* There's a bug in tftpd-hpa that causes it to send us an ack for
@@ -766,7 +765,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
     state->retries = 0;
     setpacketevent(&state->spacket, TFTP_EVENT_DATA);
     setpacketblock(&state->spacket, state->block);
-    if(state->block > 1 && state->sbytes < (int)state->blksize) {
+    if(state->block > 1 && state->sbytes < state->blksize) {
       state->state = TFTP_STATE_FIN;
       return CURLE_OK;
     }
@@ -782,7 +781,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
                                    &cb);
       if(result)
         return result;
-      state->sbytes += cb;
+      state->sbytes += (int)cb;
       state->conn->data->req.upload_fromhere += cb;
     } while(state->sbytes < state->blksize && cb != 0);
 
@@ -969,7 +968,7 @@ static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
 static CURLcode tftp_connect(struct connectdata *conn, bool *done)
 {
   tftp_state_data_t *state;
-  int blksize, rc;
+  int blksize;
 
   blksize = TFTP_BLKSIZE_DEFAULT;
 
@@ -1028,8 +1027,8 @@ static CURLcode tftp_connect(struct connectdata *conn, bool *done)
      * assume uses the same IP version and thus hopefully this works for both
      * IPv4 and IPv6...
      */
-    rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
-              conn->ip_addr->ai_addrlen);
+    int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
+                  conn->ip_addr->ai_addrlen);
     if(rc) {
       failf(conn->data, "bind() failed; %s",
             Curl_strerror(conn, SOCKERRNO));
@@ -1148,8 +1147,11 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
     case TFTP_EVENT_ERROR:
     {
       unsigned short error = getrpacketblock(&state->rpacket);
+      char *str = (char *)state->rpacket.data + 4;
+      size_t strn = state->rbytes - 4;
       state->error = (tftp_error_t)error;
-      infof(data, "%s\n", (const char *)state->rpacket.data + 4);
+      if(Curl_strnlen(str, strn) < strn)
+        infof(data, "TFTP error: %s\n", str);
       break;
     }
     case TFTP_EVENT_ACK:
@@ -1221,7 +1223,6 @@ static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
  **********************************************************/
 static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
 {
-  int                   rc;
   tftp_event_t          event;
   CURLcode              result = CURLE_OK;
   struct Curl_easy  *data = conn->data;
@@ -1245,7 +1246,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
   }
   else {
     /* no timeouts to handle, check our socket */
-    rc = SOCKET_READABLE(state->sockfd, 0);
+    int rc = SOCKET_READABLE(state->sockfd, 0);
 
     if(rc == -1) {
       /* bail out */
@@ -1368,7 +1369,6 @@ static CURLcode tftp_setup_connection(struct connectdata * conn)
 {
   struct Curl_easy *data = conn->data;
   char *type;
-  char command;
 
   conn->socktype = SOCK_DGRAM;   /* UDP datagram based */
 
@@ -1380,6 +1380,7 @@ static CURLcode tftp_setup_connection(struct connectdata * conn)
     type = strstr(conn->host.rawalloc, ";mode=");
 
   if(type) {
+    char command;
     *type = 0;                   /* it was in the middle of the hostname */
     command = Curl_raw_toupper(type[6]);
 
diff --git a/lib/transfer.c b/lib/transfer.c
index 131f2dc..7159d5c 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -106,15 +106,26 @@ char *Curl_checkheaders(const struct connectdata *conn,
 }
 #endif
 
+CURLcode Curl_get_upload_buffer(struct Curl_easy *data)
+{
+  if(!data->state.ulbuf) {
+    data->state.ulbuf = malloc(data->set.upload_buffer_size);
+    if(!data->state.ulbuf)
+      return CURLE_OUT_OF_MEMORY;
+  }
+  return CURLE_OK;
+}
+
 /*
  * This function will call the read callback to fill our buffer with data
  * to upload.
  */
-CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
+CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
+                             size_t *nreadp)
 {
   struct Curl_easy *data = conn->data;
-  size_t buffersize = (size_t)bytes;
-  int nread;
+  size_t buffersize = bytes;
+  size_t nread;
 #ifdef CURL_DOES_CONVERSIONS
   bool sending_http_headers = FALSE;
 
@@ -134,11 +145,9 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
     data->req.upload_fromhere += (8 + 2); /* 32bit hex + CRLF */
   }
 
-  /* this function returns a size_t, so we typecast to int to prevent warnings
-     with picky compilers */
   Curl_set_in_callback(data, true);
-  nread = (int)data->state.fread_func(data->req.upload_fromhere, 1,
-                                      buffersize, data->state.in);
+  nread = data->state.fread_func(data->req.upload_fromhere, 1,
+                                 buffersize, data->state.in);
   Curl_set_in_callback(data, false);
 
   if(nread == CURL_READFUNC_ABORT) {
@@ -167,7 +176,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
 
     return CURLE_OK; /* nothing was read */
   }
-  else if((size_t)nread > buffersize) {
+  else if(nread > buffersize) {
     /* the read function returned a too large value */
     *nreadp = 0;
     failf(data, "read function returned funny value");
@@ -226,13 +235,13 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
 #ifdef CURL_DOES_CONVERSIONS
     {
       CURLcode result;
-      int length;
+      size_t length;
       if(data->set.prefer_ascii)
         /* translate the protocol and data */
         length = nread;
       else
         /* just translate the protocol portion */
-        length = (int)strlen(hexbuffer);
+        length = strlen(hexbuffer);
       result = Curl_convert_to_network(data, data->req.upload_fromhere,
                                        length);
       /* Curl_convert_to_network calls failf if unsuccessful */
@@ -247,7 +256,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp)
       infof(data, "Signaling end of chunked upload via terminating chunk.\n");
     }
 
-    nread += (int)strlen(endofline_native); /* for the added end of line */
+    nread += strlen(endofline_native); /* for the added end of line */
   }
 #ifdef CURL_DOES_CONVERSIONS
   else if((data->set.prefer_ascii) && (!sending_http_headers)) {
@@ -444,7 +453,6 @@ static CURLcode readwrite_data(struct Curl_easy *data,
   CURLcode result = CURLE_OK;
   ssize_t nread; /* number of bytes read */
   size_t excess = 0; /* excess bytes read */
-  bool is_empty_data = FALSE;
   bool readmore = FALSE; /* used by RTP to signal for more data */
   int maxloops = 100;
 
@@ -454,6 +462,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
   /* This is where we loop until we have read everything there is to
      read or we get a CURLE_AGAIN */
   do {
+    bool is_empty_data = FALSE;
     size_t buffersize = data->set.buffer_size;
     size_t bytestoread = buffersize;
 
@@ -660,14 +669,14 @@ static CURLcode readwrite_data(struct Curl_easy *data,
       if(data->set.verbose) {
         if(k->badheader) {
           Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff,
-                     (size_t)k->hbuflen, conn);
+                     (size_t)k->hbuflen);
           if(k->badheader == HEADER_PARTHEADER)
             Curl_debug(data, CURLINFO_DATA_IN,
-                       k->str, (size_t)nread, conn);
+                       k->str, (size_t)nread);
         }
         else
           Curl_debug(data, CURLINFO_DATA_IN,
-                     k->str, (size_t)nread, conn);
+                     k->str, (size_t)nread);
       }
 
 #ifndef CURL_DISABLE_HTTP
@@ -797,7 +806,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
                                            nread);
             }
           }
-          else
+          else if(!k->ignorebody)
             result = Curl_unencode_write(conn, k->writer_stack, k->str, nread);
         }
         k->badheader = HEADER_NORMAL; /* taken care of now */
@@ -869,6 +878,26 @@ static CURLcode done_sending(struct connectdata *conn,
   return CURLE_OK;
 }
 
+#ifdef WIN32
+#ifndef SIO_IDEAL_SEND_BACKLOG_QUERY
+#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B
+#endif
+
+static void win_update_buffer_size(curl_socket_t sockfd)
+{
+  int result;
+  ULONG ideal;
+  DWORD ideallen;
+  result = WSAIoctl(sockfd, SIO_IDEAL_SEND_BACKLOG_QUERY, 0, 0,
+                    &ideal, sizeof(ideal), &ideallen, 0, 0);
+  if(result == 0) {
+    setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,
+               (const char *)&ideal, sizeof(ideal));
+  }
+}
+#else
+#define win_update_buffer_size(x)
+#endif
 
 /*
  * Send data to upload to the server, when the socket is writable.
@@ -894,13 +923,16 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
     /* only read more data if there's no upload data already
        present in the upload buffer */
     if(0 == k->upload_present) {
+      result = Curl_get_upload_buffer(data);
+      if(result)
+        return result;
       /* init the "upload from here" pointer */
-      k->upload_fromhere = data->state.uploadbuffer;
+      k->upload_fromhere = data->state.ulbuf;
 
       if(!k->upload_done) {
         /* HTTP pollution, this should be written nicer to become more
            protocol agnostic. */
-        int fillcount;
+        size_t fillcount;
         struct HTTP *http = k->protop;
 
         if((k->exp100 == EXP100_SENDING_REQUEST) &&
@@ -931,7 +963,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
         if(result)
           return result;
 
-        nread = (ssize_t)fillcount;
+        nread = fillcount;
       }
       else
         nread = 0; /* we're done uploading/reading */
@@ -959,7 +991,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
          (data->set.crlf))) {
         /* Do we need to allocate a scratch buffer? */
         if(!data->state.scratch) {
-          data->state.scratch = malloc(2 * data->set.buffer_size);
+          data->state.scratch = malloc(2 * UPLOAD_BUFSIZE);
           if(!data->state.scratch) {
             failf(data, "Failed to alloc scratch buffer!");
 
@@ -1020,14 +1052,15 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
                         k->upload_fromhere, /* buffer pointer */
                         k->upload_present,  /* buffer size */
                         &bytes_written);    /* actually sent */
-
     if(result)
       return result;
 
+    win_update_buffer_size(conn->writesockfd);
+
     if(data->set.verbose)
       /* show the data before we change the pointer upload_fromhere */
       Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere,
-                 (size_t)bytes_written, conn);
+                 (size_t)bytes_written);
 
     k->writebytecount += bytes_written;
 
@@ -1050,7 +1083,10 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
     }
     else {
       /* we've uploaded that buffer now */
-      k->upload_fromhere = data->state.uploadbuffer;
+      result = Curl_get_upload_buffer(data);
+      if(result)
+        return result;
+      k->upload_fromhere = data->state.ulbuf;
       k->upload_present = 0; /* no more bytes left */
 
       if(k->upload_done) {
@@ -1482,7 +1518,7 @@ static size_t strlen_url(const char *url, bool relative)
     switch(*ptr) {
     case '?':
       left = FALSE;
-      /* fall through */
+      /* FALLTHROUGH */
     default:
       if(urlchar_needs_escaping(*ptr))
         newlen += 2;
@@ -1527,7 +1563,7 @@ static void strcpy_url(char *output, const char *url, bool relative)
     switch(*iptr) {
     case '?':
       left = FALSE;
-      /* fall through */
+      /* FALLTHROUGH */
     default:
       if(urlchar_needs_escaping(*iptr)) {
         snprintf(optr, 4, "%%%02x", *iptr);
diff --git a/lib/transfer.h b/lib/transfer.h
index 9ba398d..9263e5b 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -51,9 +51,11 @@ int Curl_single_getsock(const struct connectdata *conn,
                         curl_socket_t *socks,
                         int numsocks);
 CURLcode Curl_readrewind(struct connectdata *conn);
-CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp);
+CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
+                             size_t *nreadp);
 CURLcode Curl_retry_request(struct connectdata *conn, char **url);
 bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc);
+CURLcode Curl_get_upload_buffer(struct Curl_easy *data);
 
 /* This sets up a forthcoming transfer */
 void
diff --git a/lib/url.c b/lib/url.c
index 701f83a..f159008 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -127,7 +127,6 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
 
 static void conn_free(struct connectdata *conn);
 static void free_fixed_hostname(struct hostname *host);
-static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
 static CURLcode parse_url_login(struct Curl_easy *data,
                                 struct connectdata *conn,
                                 char **userptr, char **passwdptr,
@@ -368,11 +367,9 @@ CURLcode Curl_close(struct Curl_easy *data)
 
   Curl_safefree(data->state.buffer);
   Curl_safefree(data->state.headerbuff);
-
+  Curl_safefree(data->state.ulbuf);
   Curl_flush_cookies(data, 1);
-
   Curl_digest_cleanup(data);
-
   Curl_safefree(data->info.contenttype);
   Curl_safefree(data->info.wouldredirect);
 
@@ -535,6 +532,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
   set->expect_100_timeout = 1000L; /* Wait for a second by default. */
   set->sep_headers = TRUE; /* separated header lists by default */
   set->buffer_size = READBUFFER_SIZE;
+  set->upload_buffer_size = UPLOAD_BUFSIZE;
   set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
 
   Curl_http2_init_userset(set);
@@ -734,20 +732,23 @@ static void conn_free(struct connectdata *conn)
  * primary connection, like when freeing room in the connection cache or
  * killing of a dead old connection.
  *
+ * A connection needs an easy handle when closing down. We support this passed
+ * in separately since the connection to get closed here is often already
+ * disassociated from an easy handle.
+ *
  * This function MUST NOT reset state in the Curl_easy struct if that
  * isn't strictly bound to the life-time of *this* particular connection.
  *
  */
 
-CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
+CURLcode Curl_disconnect(struct Curl_easy *data,
+                         struct connectdata *conn, bool dead_connection)
 {
-  struct Curl_easy *data;
   if(!conn)
     return CURLE_OK; /* this is closed and fine already */
-  data = conn->data;
 
   if(!data) {
-    DEBUGF(fprintf(stderr, "DISCONNECT without easy handle, ignoring\n"));
+    DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n"));
     return CURLE_OK;
   }
 
@@ -755,13 +756,12 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
    * If this connection isn't marked to force-close, leave it open if there
    * are other users of it
    */
-  if(!conn->bits.close &&
-     (conn->send_pipe.size + conn->recv_pipe.size)) {
-    DEBUGF(infof(data, "Curl_disconnect, usecounter: %d\n",
-                 conn->send_pipe.size + conn->recv_pipe.size));
+  if(CONN_INUSE(conn) && !dead_connection) {
+    DEBUGF(infof(data, "Curl_disconnect when inuse: %zu\n", CONN_INUSE(conn)));
     return CURLE_OK;
   }
 
+  conn->data = data;
   if(conn->dns_entry != NULL) {
     Curl_resolv_unlock(data, conn->dns_entry);
     conn->dns_entry = NULL;
@@ -787,16 +787,12 @@ CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
   free_fixed_hostname(&conn->http_proxy.host);
   free_fixed_hostname(&conn->socks_proxy.host);
 
+  DEBUGASSERT(conn->data == data);
+  /* this assumes that the pointer is still there after the connection was
+     detected from the cache */
   Curl_ssl_close(conn, FIRSTSOCKET);
 
-  /* Indicate to all handles on the pipe that we're dead */
-  if(Curl_pipeline_wanted(data->multi, CURLPIPE_ANY)) {
-    signalPipeClose(&conn->send_pipe, TRUE);
-    signalPipeClose(&conn->recv_pipe, TRUE);
-  }
-
   conn_free(conn);
-
   return CURLE_OK;
 }
 
@@ -848,6 +844,7 @@ static int IsPipeliningPossible(const struct Curl_easy *handle,
   return avail;
 }
 
+/* Returns non-zero if a handle was removed */
 int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
                                   struct curl_llist *pipeline)
 {
@@ -884,6 +881,16 @@ static void Curl_printPipeline(struct curl_llist *pipeline)
 static struct Curl_easy* gethandleathead(struct curl_llist *pipeline)
 {
   struct curl_llist_element *curr = pipeline->head;
+#ifdef DEBUGBUILD
+  {
+    struct curl_llist_element *p = pipeline->head;
+    while(p) {
+      struct Curl_easy *e = p->ptr;
+      DEBUGASSERT(GOOD_EASY_HANDLE(e));
+      p = p->next;
+    }
+  }
+#endif
   if(curr) {
     return (struct Curl_easy *) curr->ptr;
   }
@@ -896,41 +903,22 @@ static struct Curl_easy* gethandleathead(struct curl_llist *pipeline)
 void Curl_getoff_all_pipelines(struct Curl_easy *data,
                                struct connectdata *conn)
 {
-  bool recv_head = (conn->readchannel_inuse &&
-                    Curl_recvpipe_head(data, conn));
-  bool send_head = (conn->writechannel_inuse &&
-                    Curl_sendpipe_head(data, conn));
-
-  if(Curl_removeHandleFromPipeline(data, &conn->recv_pipe) && recv_head)
-    Curl_pipeline_leave_read(conn);
-  if(Curl_removeHandleFromPipeline(data, &conn->send_pipe) && send_head)
-    Curl_pipeline_leave_write(conn);
-}
-
-static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke)
-{
-  struct curl_llist_element *curr;
-
-  if(!pipeline)
+  if(!conn->bundle)
     return;
+  if(conn->bundle->multiuse == BUNDLE_PIPELINING) {
+    bool recv_head = (conn->readchannel_inuse &&
+                      Curl_recvpipe_head(data, conn));
+    bool send_head = (conn->writechannel_inuse &&
+                      Curl_sendpipe_head(data, conn));
 
-  curr = pipeline->head;
-  while(curr) {
-    struct curl_llist_element *next = curr->next;
-    struct Curl_easy *data = (struct Curl_easy *) curr->ptr;
-
-#ifdef DEBUGBUILD /* debug-only code */
-    if(data->magic != CURLEASY_MAGIC_NUMBER) {
-      /* MAJOR BADNESS */
-      infof(data, "signalPipeClose() found BAAD easy handle\n");
-    }
-#endif
-
-    if(pipe_broke)
-      data->state.pipe_broke = TRUE;
-    Curl_multi_handlePipeBreak(data);
-    Curl_llist_remove(pipeline, curr, NULL);
-    curr = next;
+    if(Curl_removeHandleFromPipeline(data, &conn->recv_pipe) && recv_head)
+      Curl_pipeline_leave_read(conn);
+    if(Curl_removeHandleFromPipeline(data, &conn->send_pipe) && send_head)
+      Curl_pipeline_leave_write(conn);
+  }
+  else {
+    (void)Curl_removeHandleFromPipeline(data, &conn->recv_pipe);
+    (void)Curl_removeHandleFromPipeline(data, &conn->send_pipe);
   }
 }
 
@@ -959,12 +947,13 @@ static bool extract_if_dead(struct connectdata *conn,
                             struct Curl_easy *data)
 {
   size_t pipeLen = conn->send_pipe.size + conn->recv_pipe.size;
-  if(!pipeLen && !conn->inuse) {
+  if(!pipeLen && !CONN_INUSE(conn)) {
     /* The check for a dead socket makes sense only if there are no
        handles in pipeline and the connection isn't already marked in
        use */
     bool dead;
 
+    conn->data = data;
     if(conn->handler->connection_check) {
       /* The protocol has a special method for checking the state of the
          connection. Use it to check if the connection is dead. */
@@ -979,9 +968,9 @@ static bool extract_if_dead(struct connectdata *conn,
     }
 
     if(dead) {
-      conn->data = data;
       infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
       Curl_conncache_remove_conn(conn, FALSE);
+      conn->data = NULL; /* detach */
       return TRUE;
     }
   }
@@ -1025,7 +1014,7 @@ static void prune_dead_connections(struct Curl_easy *data)
     while(Curl_conncache_foreach(data, data->state.conn_cache, &prune,
                                  call_extract_if_dead)) {
       /* disconnect it */
-      (void)Curl_disconnect(prune.extracted, /* dead_connection */TRUE);
+      (void)Curl_disconnect(data, prune.extracted, /* dead_connection */TRUE);
     }
     data->state.conn_cache->last_cleanup = now;
   }
@@ -1139,7 +1128,7 @@ ConnectionExists(struct Curl_easy *data,
 
       if(extract_if_dead(check, data)) {
         /* disconnect it */
-        (void)Curl_disconnect(check, /* dead_connection */TRUE);
+        (void)Curl_disconnect(data, check, /* dead_connection */TRUE);
         continue;
       }
 
@@ -1267,12 +1256,12 @@ ConnectionExists(struct Curl_easy *data,
         }
       }
 
-      if(!canpipe && check->inuse)
+      if(!canpipe && CONN_INUSE(check))
         /* this request can't be pipelined but the checked connection is
            already in use so we skip it */
         continue;
 
-      if((check->inuse) && (check->data->multi != needle->data->multi))
+      if(CONN_INUSE(check) && (check->data->multi != needle->data->multi))
         /* this could be subject for pipeline/multiplex use, but only
            if they belong to the same multi handle */
         continue;
@@ -1464,7 +1453,7 @@ ConnectionExists(struct Curl_easy *data,
 
   if(chosen) {
     /* mark it as used before releasing the lock */
-    chosen->inuse = TRUE;
+    chosen->data = data; /* own it! */
     Curl_conncache_unlock(needle);
     *usethis = chosen;
     return TRUE; /* yes, we found one to use! */
@@ -1554,7 +1543,11 @@ int Curl_protocol_getsock(struct connectdata *conn,
 {
   if(conn->handler->proto_getsock)
     return conn->handler->proto_getsock(conn, socks, numsocks);
-  return GETSOCK_BLANK;
+  /* Backup getsock logic. Since there is a live socket in use, we must wait
+     for it or it will be removed from watching when the multi_socket API is
+     used. */
+  socks[0] = conn->sock[FIRSTSOCKET];
+  return GETSOCK_READSOCK(0) | GETSOCK_WRITESOCK(0);
 }
 
 int Curl_doing_getsock(struct connectdata *conn,
@@ -1999,7 +1992,6 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
   char *fragment;
   char *path = data->state.path;
   char *query;
-  int i;
   int rc;
   const char *protop = "";
   CURLcode result;
@@ -2051,6 +2043,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
     ; /* do nothing */
   }
   else { /* check for a scheme */
+    int i;
     for(i = 0; i < 16 && data->change.url[i]; ++i) {
       if(data->change.url[i] == '/')
         break;
@@ -2203,7 +2196,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
       size_t s = strlen(slashbuf);
       protop = protobuf;
       if(s != 2) {
-        infof(data, "Unwillingly accepted illegal URL using %d slash%s!\n",
+        infof(data, "Unwillingly accepted illegal URL using %zu slash%s!\n",
               s, s>1?"es":"");
 
         if(data->change.url_alloc)
@@ -2449,7 +2442,7 @@ static CURLcode setup_range(struct Curl_easy *data)
       free(s->range);
 
     if(s->resume_from)
-      s->range = aprintf("%" CURL_FORMAT_CURL_OFF_TU "-", s->resume_from);
+      s->range = aprintf("%" CURL_FORMAT_CURL_OFF_T "-", s->resume_from);
     else
       s->range = strdup(data->set.str[STRING_SET_RANGE]);
 
@@ -2481,18 +2474,6 @@ static CURLcode setup_connection_internals(struct connectdata *conn)
 {
   const struct Curl_handler * p;
   CURLcode result;
-  struct Curl_easy *data = conn->data;
-
-  /* in some case in the multi state-machine, we go back to the CONNECT state
-     and then a second (or third or...) call to this function will be made
-     without doing a DISCONNECT or DONE in between (since the connection is
-     yet in place) and therefore this function needs to first make sure
-     there's no lingering previous data allocated. */
-  Curl_free_request_state(data);
-
-  memset(&data->req, 0, sizeof(struct SingleRequest));
-  data->req.maxdownload = -1;
-
   conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
 
   /* Perform setup complement if some. */
@@ -2539,14 +2520,13 @@ static bool check_noproxy(const char *name, const char *no_proxy)
    *   not be proxied, or an asterisk to override
    *   all proxy variables)
    */
-  size_t tok_start;
-  size_t tok_end;
-  const char *separator = ", ";
-  size_t no_proxy_len;
-  size_t namelen;
-  char *endptr;
-
   if(no_proxy && no_proxy[0]) {
+    size_t tok_start;
+    size_t tok_end;
+    const char *separator = ", ";
+    size_t no_proxy_len;
+    size_t namelen;
+    char *endptr;
     if(strcasecompare("*", no_proxy)) {
       return TRUE;
     }
@@ -3166,6 +3146,13 @@ static CURLcode parse_url_login(struct Curl_easy *data,
   if(userp) {
     char *newname;
 
+    if(data->set.disallow_username_in_url) {
+      failf(data, "Option DISALLOW_USERNAME_IN_URL is set "
+                  "and url contains username.");
+      result = CURLE_LOGIN_DENIED;
+      goto out;
+    }
+
     /* We have a user in the URL */
     conn->bits.userpwd_in_url = TRUE;
     conn->bits.user_passwd = TRUE; /* enable user+password */
@@ -3982,6 +3969,7 @@ static void reuse_conn(struct connectdata *old_conn,
 
   Curl_safefree(old_conn->user);
   Curl_safefree(old_conn->passwd);
+  Curl_safefree(old_conn->options);
   Curl_safefree(old_conn->http_proxy.user);
   Curl_safefree(old_conn->socks_proxy.user);
   Curl_safefree(old_conn->http_proxy.passwd);
@@ -4297,7 +4285,9 @@ static CURLcode create_conn(struct Curl_easy *data,
       conn->data = data;
       conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
 
-      Curl_conncache_add_conn(data->state.conn_cache, conn);
+      result = Curl_conncache_add_conn(data->state.conn_cache, conn);
+      if(result)
+        goto out;
 
       /*
        * Setup whatever necessary for a resumed transfer
@@ -4343,6 +4333,10 @@ static CURLcode create_conn(struct Curl_easy *data,
     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.primary.cipher_list13 =
+    data->set.str[STRING_SSL_CIPHER13_LIST_ORIG];
+  data->set.proxy_ssl.primary.cipher_list13 =
+    data->set.str[STRING_SSL_CIPHER13_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];
@@ -4468,13 +4462,11 @@ static CURLcode create_conn(struct Curl_easy *data,
         conn_candidate = Curl_conncache_extract_bundle(data, bundle);
         Curl_conncache_unlock(conn);
 
-        if(conn_candidate) {
-          /* Set the connection's owner correctly, then kill it */
-          conn_candidate->data = data;
-          (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
-        }
+        if(conn_candidate)
+          (void)Curl_disconnect(data, conn_candidate,
+                                /* dead_connection */ FALSE);
         else {
-          infof(data, "No more connections allowed to host: %d\n",
+          infof(data, "No more connections allowed to host: %zu\n",
                 max_host_connections);
           connections_available = FALSE;
         }
@@ -4491,12 +4483,9 @@ static CURLcode create_conn(struct Curl_easy *data,
 
       /* The cache is full. Let's see if we can kill a connection. */
       conn_candidate = Curl_conncache_extract_oldest(data);
-
-      if(conn_candidate) {
-        /* Set the connection's owner correctly, then kill it */
-        conn_candidate->data = data;
-        (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
-      }
+      if(conn_candidate)
+        (void)Curl_disconnect(data, conn_candidate,
+                              /* dead_connection */ FALSE);
       else {
         infof(data, "No connections available in cache\n");
         connections_available = FALSE;
@@ -4513,14 +4502,13 @@ static CURLcode create_conn(struct Curl_easy *data,
       goto out;
     }
     else {
-      /* Mark the connection as used, before we add it */
-      conn->inuse = TRUE;
-
       /*
        * This is a brand new connection, so let's store it in the connection
        * cache of ours!
        */
-      Curl_conncache_add_conn(data->state.conn_cache, conn);
+      result = Curl_conncache_add_conn(data->state.conn_cache, conn);
+      if(result)
+        goto out;
     }
 
 #if defined(USE_NTLM)
@@ -4656,12 +4644,16 @@ CURLcode Curl_connect(struct Curl_easy *data,
 
   *asyncp = FALSE; /* assume synchronous resolves by default */
 
+  /* init the single-transfer specific data */
+  Curl_free_request_state(data);
+  memset(&data->req, 0, sizeof(struct SingleRequest));
+  data->req.maxdownload = -1;
+
   /* call the stuff that needs to be called */
   result = create_conn(data, in_connect, asyncp);
 
   if(!result) {
-    /* no error */
-    if((*in_connect)->send_pipe.size || (*in_connect)->recv_pipe.size)
+    if(CONN_INUSE(*in_connect))
       /* pipelining */
       *protocol_done = TRUE;
     else if(!*asyncp) {
@@ -4676,12 +4668,11 @@ CURLcode Curl_connect(struct Curl_easy *data,
     *in_connect = NULL;
     return result;
   }
-
-  if(result && *in_connect) {
-    /* We're not allowed to return failure with memory left allocated
-       in the connectdata struct, free those here */
-    Curl_disconnect(*in_connect, FALSE); /* close the connection */
-    *in_connect = NULL;           /* return a NULL */
+  else if(result && *in_connect) {
+    /* We're not allowed to return failure with memory left allocated in the
+       connectdata struct, free those here */
+    Curl_disconnect(data, *in_connect, TRUE);
+    *in_connect = NULL; /* return a NULL */
   }
 
   return result;
@@ -4701,16 +4692,18 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
 {
   struct SingleRequest *k = &data->req;
 
-  conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
-                                 use */
+  if(conn) {
+    conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
+                                   use */
+    /* if the protocol used doesn't support wildcards, switch it off */
+    if(data->state.wildcardmatch &&
+       !(conn->handler->flags & PROTOPT_WILDCARD))
+      data->state.wildcardmatch = FALSE;
+  }
 
   data->state.done = FALSE; /* *_done() is not called yet */
   data->state.expect100header = FALSE;
 
-  /* if the protocol used doesn't support wildcards, switch it off */
-  if(data->state.wildcardmatch &&
-     !(conn->handler->flags & PROTOPT_WILDCARD))
-    data->state.wildcardmatch = FALSE;
 
   if(data->set.opt_no_body)
     /* in HTTP lingo, no body means using the HEAD request... */
diff --git a/lib/url.h b/lib/url.h
index a70bd54..ef3ebf0 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -39,7 +39,8 @@ void Curl_freeset(struct Curl_easy * data);
 CURLcode Curl_close(struct Curl_easy *data); /* opposite of curl_open() */
 CURLcode Curl_connect(struct Curl_easy *, struct connectdata **,
                       bool *async, bool *protocol_connect);
-CURLcode Curl_disconnect(struct connectdata *, bool dead_connection);
+CURLcode Curl_disconnect(struct Curl_easy *data,
+                         struct connectdata *, bool dead_connection);
 CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
 CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
 CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done);
diff --git a/lib/urldata.h b/lib/urldata.h
index 7fae00f..67db3b2 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -80,6 +80,7 @@
 #define RESP_TIMEOUT (1800*1000)
 
 #include "cookie.h"
+#include "psl.h"
 #include "formdata.h"
 
 #ifdef HAVE_NETINET_IN_H
@@ -142,8 +143,13 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
 #endif /* HAVE_LIBSSH2_H */
 
 /* The upload buffer size, should not be smaller than CURL_MAX_WRITE_SIZE, as
-   it needs to hold a full buffer as could be sent in a write callback */
-#define UPLOAD_BUFSIZE CURL_MAX_WRITE_SIZE
+   it needs to hold a full buffer as could be sent in a write callback.
+
+   The size was 16KB for many years but was bumped to 64KB because it makes
+   libcurl able to do significantly faster uploads in some circumstances. Even
+   larger buffers can help further, but this is deemed a fair memory/speed
+   compromise. */
+#define UPLOAD_BUFSIZE 65536
 
 /* The "master buffer" is for HTTP pipelining */
 #define MASTERBUF_SIZE 16384
@@ -156,11 +162,6 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
 #define GOOD_EASY_HANDLE(x) \
   ((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))
 
-/* Some convenience macros to get the larger/smaller value out of two given.
-   We prefix with CURL to prevent name collisions. */
-#define CURLMAX(x,y) ((x)>(y)?(x):(y))
-#define CURLMIN(x,y) ((x)<(y)?(x):(y))
-
 #ifdef HAVE_GSSAPI
 /* Types needed for krb5-ftp connections */
 struct krb5buffer {
@@ -226,6 +227,7 @@ struct ssl_primary_config {
   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 */
+  char *cipher_list13;   /* list of TLS 1.3 cipher suites to use */
 };
 
 struct ssl_config_data {
@@ -779,11 +781,12 @@ struct connectdata {
   curl_closesocket_callback fclosesocket; /* function closing the socket(s) */
   void *closesocket_client;
 
-  bool inuse; /* This is a marker for the connection cache logic. If this is
-                 TRUE this handle is being used by one or more easy handles
-                 and can only used by any other easy handle without careful
-                 consideration (== only for pipelining/multiplexing) and it
-                 cannot be used by another multi handle! */
+  /* This is used by the connection cache logic. If this returns TRUE, this
+     handle is being used by one or more easy handles and can only used by any
+     other easy handle without careful consideration (== only for
+     pipelining/multiplexing) and it cannot be used by another multi
+     handle! */
+#define CONN_INUSE(c) ((c)->send_pipe.size + (c)->recv_pipe.size)
 
   /**** Fields set when inited and not modified again */
   long connection_id; /* Contains a unique number to make it easier to
@@ -1222,7 +1225,7 @@ struct UrlState {
   size_t headersize;   /* size of the allocation */
 
   char *buffer; /* download buffer */
-  char uploadbuffer[UPLOAD_BUFSIZE + 1]; /* upload buffer */
+  char *ulbuf; /* alloced upload buffer or NULL */
   curl_off_t current_speed;  /* the ProgressShow() function sets this,
                                 bytes / second */
   bool this_is_a_follow; /* this is a followed Location: request */
@@ -1265,7 +1268,7 @@ struct UrlState {
   void *resolver; /* resolver state, if it is used in the URL state -
                      ares_channel f.e. */
 
-#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
+#if defined(USE_OPENSSL)
   /* void instead of ENGINE to avoid bleeding OpenSSL into this header */
   void *engine;
 #endif /* USE_OPENSSL */
@@ -1284,9 +1287,6 @@ struct UrlState {
                             involved in this request */
   bool expect100header;  /* TRUE if we added Expect: 100-continue */
 
-  bool pipe_broke; /* TRUE if the connection we were pipelined on broke
-                      and we need to restart from the beginning */
-
 #if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \
     !defined(__SYMBIAN32__)
 /* do FTP line-end conversions on most platforms */
@@ -1346,7 +1346,7 @@ struct DynamicStatic {
   char *url;        /* work URL, copied from UserDefined */
   bool url_alloc;   /* URL string is malloc()'ed */
   char *referer;    /* referer string */
-  bool referer_alloc; /* referer sting is malloc()ed */
+  bool referer_alloc; /* referer string is malloc()ed */
   struct curl_slist *cookielist; /* list of cookie files set by
                                     curl_easy_setopt(COOKIEFILE) calls */
   struct curl_slist *resolve; /* set to point to the set.resolve list when
@@ -1400,6 +1400,8 @@ enum dupstring {
   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_CIPHER13_LIST_ORIG, /* list of TLS 1.3 ciphers to use */
+  STRING_SSL_CIPHER13_LIST_PROXY, /* list of TLS 1.3 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 */
@@ -1407,6 +1409,7 @@ enum dupstring {
   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_SSL_ENGINE,      /* name of ssl engine */
   STRING_USERNAME,        /* <username>, if used */
   STRING_PASSWORD,        /* <password>, if used */
   STRING_OPTIONS,         /* <options>, if used */
@@ -1559,6 +1562,8 @@ struct UserDefined {
   curl_proxytype proxytype; /* what kind of proxy that is in use */
   long dns_cache_timeout; /* DNS cache timeout */
   long buffer_size;      /* size of receive buffer to use */
+  long upload_buffer_size; /* size of upload buffer to use,
+                              keep it >= CURL_MAX_WRITE_SIZE */
   void *private_data; /* application-private data */
 
   struct curl_slist *http200aliases; /* linked list of aliases for http200 */
@@ -1581,8 +1586,6 @@ struct UserDefined {
 /* Here follows boolean settings that define how to behave during
    this session. They are STATIC, set by libcurl users or at least initially
    and they don't change during operations. */
-
-  bool printhost;        /* printing host name in debug info */
   bool get_filetime;     /* get the time and get of the remote file */
   bool tunnel_thru_httpproxy; /* use CONNECT through a HTTP proxy */
   bool prefer_ascii;     /* ASCII rather than binary */
@@ -1676,7 +1679,7 @@ struct UserDefined {
   bool stream_depends_e; /* set or don't set the Exclusive bit */
   int stream_weight;
 
-  bool haproxyprotocol; /* whether to send HAProxy PROXY protocol header */
+  bool haproxyprotocol; /* whether to send HAProxy PROXY protocol v1 header */
 
   struct Curl_http2_dep *stream_dependents;
 
@@ -1685,6 +1688,7 @@ struct UserDefined {
   curl_resolver_start_callback resolver_start; /* optional callback called
                                                   before resolver start */
   void *resolver_start_client; /* pointer to pass to resolver start callback */
+  bool disallow_username_in_url; /* disallow username in url */
 };
 
 struct Names {
@@ -1736,6 +1740,9 @@ struct Curl_easy {
                                     struct to which this "belongs" when used
                                     by the easy interface */
   struct Curl_share *share;    /* Share, handles global variable mutexing */
+#ifdef USE_LIBPSL
+  struct PslCache *psl;        /* The associated PSL cache. */
+#endif
   struct SingleRequest req;    /* Request-specific data */
   struct UserDefined set;      /* values set by the libcurl user */
   struct DynamicStatic change; /* possibly modified userdefined data */
diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c
index 131d9da..cc6f169 100644
--- a/lib/vauth/digest.c
+++ b/lib/vauth/digest.c
@@ -158,7 +158,7 @@ static void auth_digest_sha256_to_ascii(unsigned char *source, /* 32 bytes */
 /* Perform quoted-string escaping as described in RFC2616 and its errata */
 static char *auth_digest_string_quoted(const char *source)
 {
-  char *dest, *d;
+  char *dest;
   const char *s = source;
   size_t n = 1; /* null terminator */
 
@@ -173,8 +173,8 @@ static char *auth_digest_string_quoted(const char *source)
 
   dest = malloc(n);
   if(dest) {
+    char *d = dest;
     s = source;
-    d = dest;
     while(*s) {
       if(*s == '"' || *s == '\\') {
         *d++ = '\\';
@@ -696,7 +696,6 @@ static CURLcode _Curl_auth_create_digest_http_message(
   unsigned char ha1[65];    /* 64 digits and 1 zero byte */
   unsigned char ha2[65];    /* 64 digits and 1 zero byte */
   char userh[65];
-  char cnoncebuf[33];
   char *cnonce = NULL;
   size_t cnonce_sz = 0;
   char *userp_quoted;
@@ -707,6 +706,7 @@ static CURLcode _Curl_auth_create_digest_http_message(
     digest->nc = 1;
 
   if(!digest->cnonce) {
+    char cnoncebuf[33];
     result = Curl_rand_hex(data, (unsigned char *)cnoncebuf,
                            sizeof(cnoncebuf));
     if(result)
diff --git a/lib/version.c b/lib/version.c
index 5b0d05a..05c2cd8 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -445,7 +445,7 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
 
 #ifdef HAVE_BROTLI
   version_info.brotli_ver_num = BrotliDecoderVersion();
-  brotli_version(brotli_buffer, sizeof brotli_buffer);
+  brotli_version(brotli_buffer, sizeof(brotli_buffer));
   version_info.brotli_version = brotli_buffer;
 #endif
 
diff --git a/lib/vtls/axtls.c b/lib/vtls/axtls.c
index 5ed898b..b262392 100644
--- a/lib/vtls/axtls.c
+++ b/lib/vtls/axtls.c
@@ -29,6 +29,11 @@
 #include "curl_setup.h"
 
 #ifdef USE_AXTLS
+
+#error axTLS support has been disabled in curl due to doubts about quality,
+#error user dedication and a lack of use/testing. We urge users to consider
+#error using a more established TLS backend instead.
+
 #include <axTLS/config.h>
 #include <axTLS/ssl.h>
 #include "axtls.h"
diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c
index 20ce460..e10398a 100644
--- a/lib/vtls/cyassl.c
+++ b/lib/vtls/cyassl.c
@@ -569,7 +569,7 @@ cyassl_connect_step2(struct connectdata *conn,
       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
     }
 
-    memset(&x509_parsed, 0, sizeof x509_parsed);
+    memset(&x509_parsed, 0, sizeof(x509_parsed));
     if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
 
@@ -968,6 +968,8 @@ static CURLcode Curl_cyassl_random(struct Curl_easy *data,
     return CURLE_FAILED_INIT;
   if(RNG_GenerateBlock(&rng, entropy, (unsigned)length))
     return CURLE_FAILED_INIT;
+  if(FreeRng(&rng))
+    return CURLE_FAILED_INIT;
   return CURLE_OK;
 }
 
diff --git a/lib/vtls/darwinssl.c b/lib/vtls/darwinssl.c
index 45fe49d..1aea0dc 100644
--- a/lib/vtls/darwinssl.c
+++ b/lib/vtls/darwinssl.c
@@ -1252,14 +1252,13 @@ static CURLcode darwinssl_version_from_curl(SSLProtocol *darwinver,
       return CURLE_OK;
     case CURL_SSLVERSION_TLSv1_3:
       /* TLS 1.3 support first appeared in iOS 11 and macOS 10.13 */
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
-      /* We can assume __builtin_available() will always work in the
-         10.13/11.0 SDK: */
+#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
       if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
         *darwinver = kTLSProtocol13;
         return CURLE_OK;
       }
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
+#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
+          HAVE_BUILTIN_AVAILABLE == 1 */
       break;
   }
   return CURLE_SSL_CONNECT_ERROR;
@@ -1278,7 +1277,7 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
   /* macOS 10.5-10.7 supported TLS 1.0 only.
      macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2.
      macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
   if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
     max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3;
   }
@@ -1287,7 +1286,8 @@ set_ssl_version_min_max(struct connectdata *conn, int sockindex)
   }
 #else
   max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
+#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
+          HAVE_BUILTIN_AVAILABLE == 1 */
 
   switch(ssl_version) {
     case CURL_SSLVERSION_DEFAULT:
@@ -1430,7 +1430,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
     case CURL_SSLVERSION_DEFAULT:
     case CURL_SSLVERSION_TLSv1:
       (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1);
-#if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
+#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
       if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
         (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol13);
       }
@@ -1439,7 +1439,8 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
       }
 #else
       (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12);
-#endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
+#endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
+          HAVE_BUILTIN_AVAILABLE == 1 */
       break;
     case CURL_SSLVERSION_TLSv1_0:
     case CURL_SSLVERSION_TLSv1_1:
@@ -1572,6 +1573,35 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
   }
 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
 
+#if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
+  if(conn->bits.tls_enable_alpn) {
+    if(__builtin_available(macOS 10.13.4, iOS 11, *)) {
+      CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
+                                                       &kCFTypeArrayCallBacks);
+
+#ifdef USE_NGHTTP2
+      if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
+         (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
+        CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID));
+        infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+      }
+#endif
+
+      CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1));
+      infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
+
+      /* expects length prefixed preference ordered list of protocols in wire
+       * format
+       */
+      err = SSLSetALPNProtocols(BACKEND->ssl_ctx, alpnArr);
+      if(err != noErr)
+        infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n",
+              err);
+      CFRelease(alpnArr);
+    }
+  }
+#endif
+
   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");
@@ -2466,6 +2496,39 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
         break;
     }
 
+#if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
+    if(conn->bits.tls_enable_alpn) {
+      if(__builtin_available(macOS 10.13.4, iOS 11, *)) {
+        CFArrayRef alpnArr = NULL;
+        CFStringRef chosenProtocol = NULL;
+        err = SSLCopyALPNProtocols(BACKEND->ssl_ctx, &alpnArr);
+
+        if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1)
+          chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0);
+
+#ifdef USE_NGHTTP2
+        if(chosenProtocol &&
+           !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID),
+                            0)) {
+          conn->negnpn = CURL_HTTP_VERSION_2;
+        }
+        else
+#endif
+        if(chosenProtocol &&
+           !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
+          conn->negnpn = CURL_HTTP_VERSION_1_1;
+        }
+        else
+          infof(data, "ALPN, server did not agree to a protocol\n");
+
+        /* chosenProtocol is a reference to the string within alpnArr
+           and doesn't need to be freed separately */
+        if(alpnArr)
+          CFRelease(alpnArr);
+      }
+    }
+#endif
+
     return CURLE_OK;
   }
 }
diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
index b0856cd..a0b4960 100644
--- a/lib/vtls/gskit.c
+++ b/lib/vtls/gskit.c
@@ -328,7 +328,7 @@ static CURLcode set_ciphers(struct connectdata *conn,
      GSKit tokens are always shorter than their cipher names, allocated buffers
      will always be large enough to accommodate the result. */
   l = strlen(cipherlist) + 1;
-  memset((char *) ciphers, 0, sizeof ciphers);
+  memset((char *) ciphers, 0, sizeof(ciphers));
   for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
     ciphers[i].buf = malloc(l);
     if(!ciphers[i].buf) {
@@ -536,18 +536,18 @@ inetsocketpair(int sv[2])
   lfd = socket(AF_INET, SOCK_STREAM, 0);
   if(lfd < 0)
     return -1;
-  memset((char *) &addr1, 0, sizeof addr1);
+  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) ||
+  if(bind(lfd, (struct sockaddr *) &addr1, sizeof(addr1)) ||
      listen(lfd, 2) < 0) {
     close(lfd);
     return -1;
   }
 
   /* Get the allocated port. */
-  len = sizeof addr1;
+  len = sizeof(addr1);
   if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) {
     close(lfd);
     return -1;
@@ -562,7 +562,7 @@ inetsocketpair(int sv[2])
 
   /* Request unblocking connection to the listening socket. */
   curlx_nonblock(cfd, TRUE);
-  if(connect(cfd, (struct sockaddr *) &addr1, sizeof addr1) < 0 &&
+  if(connect(cfd, (struct sockaddr *) &addr1, sizeof(addr1)) < 0 &&
      errno != EINPROGRESS) {
     close(lfd);
     close(cfd);
@@ -570,7 +570,7 @@ inetsocketpair(int sv[2])
   }
 
   /* Get the client dynamic port for intrusion check below. */
-  len = sizeof addr2;
+  len = sizeof(addr2);
   if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) {
     close(lfd);
     close(cfd);
@@ -580,7 +580,7 @@ inetsocketpair(int sv[2])
   /* Accept the incoming connection and get the server socket. */
   curlx_nonblock(lfd, TRUE);
   for(;;) {
-    len = sizeof addr1;
+    len = sizeof(addr1);
     sfd = accept(lfd, (struct sockaddr *) &addr1, &len);
     if(sfd < 0) {
       close(lfd);
@@ -644,7 +644,7 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
     /* Try getting data from HTTPS proxy and pipe it upstream. */
     n = 0;
     i = gsk_secure_soc_read(connproxyssl->backend->handle,
-                            buf, sizeof buf, &n);
+                            buf, sizeof(buf), &n);
     switch(i) {
     case GSK_OK:
       if(n) {
@@ -665,7 +665,7 @@ static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
   if(FD_ISSET(BACKEND->remotefd, &fds_read) &&
      FD_ISSET(conn->sock[sockindex], &fds_write)) {
     /* Pipe data to HTTPS proxy. */
-    n = read(BACKEND->remotefd, buf, sizeof buf);
+    n = read(BACKEND->remotefd, buf, sizeof(buf));
     if(n < 0)
       return -1;
     if(n) {
@@ -864,13 +864,13 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
     BACKEND->localfd = sockpair[0];
     BACKEND->remotefd = sockpair[1];
     setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
-               (void *) sobufsize, sizeof sobufsize);
+               (void *) sobufsize, sizeof(sobufsize));
     setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
-               (void *) sobufsize, sizeof sobufsize);
+               (void *) sobufsize, sizeof(sobufsize));
     setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
-               (void *) sobufsize, sizeof sobufsize);
+               (void *) sobufsize, sizeof(sobufsize));
     setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
-               (void *) sobufsize, sizeof sobufsize);
+               (void *) sobufsize, sizeof(sobufsize));
     curlx_nonblock(BACKEND->localfd, TRUE);
     curlx_nonblock(BACKEND->remotefd, TRUE);
   }
@@ -977,7 +977,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
 
   if(!result) {
     /* Start handshake. Try asynchronous first. */
-    memset(&commarea, 0, sizeof commarea);
+    memset(&commarea, 0, sizeof(commarea));
     BACKEND->iocport = QsoCreateIOCompletionPort();
     if(BACKEND->iocport != -1) {
       result = gskit_status(data,
@@ -1333,11 +1333,11 @@ static int Curl_gskit_check_cxn(struct connectdata *cxn)
     return 0; /* connection has been closed */
 
   err = 0;
-  errlen = sizeof err;
+  errlen = sizeof(err);
 
   if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
                  (unsigned char *) &err, &errlen) ||
-     errlen != sizeof err || err)
+     errlen != sizeof(err) || err)
     return 0; /* connection has been closed */
 
   return -1;  /* connection status unknown */
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index 7cd450c..89f8183 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -394,7 +394,7 @@ static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
 /* wrap 'ptr' as list node and tail-insert into 'list' */
 static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr)
 {
-  struct ptr_list_wrap *wrap = malloc(sizeof *wrap);
+  struct ptr_list_wrap *wrap = malloc(sizeof(*wrap));
   if(!wrap)
     return CURLE_OUT_OF_MEMORY;
 
@@ -914,11 +914,11 @@ static CURLcode display_conn_info(struct connectdata *conn, PRFileDesc *sock)
   PRTime now;
   int i;
 
-  if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
-     SECSuccess && channel.length == sizeof channel &&
+  if(SSL_GetChannelInfo(sock, &channel, sizeof(channel)) ==
+     SECSuccess && channel.length == sizeof(channel) &&
      channel.cipherSuite) {
     if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
-                              &suite, sizeof suite) == SECSuccess) {
+                              &suite, sizeof(suite)) == SECSuccess) {
       infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
     }
   }
@@ -1345,7 +1345,8 @@ static CURLcode nss_init(struct Curl_easy *data)
       return CURLE_OUT_OF_MEMORY;
 
     /* the default methods just call down to the lower I/O layer */
-    memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(), sizeof nspr_io_methods);
+    memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(),
+           sizeof(nspr_io_methods));
 
     /* override certain methods in the table by our wrappers */
     nspr_io_methods.recv  = nspr_io_recv;
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index f6a4bd3..a487f55 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -50,9 +50,6 @@
 #include "hostcheck.h"
 #include "curl_printf.h"
 #include <openssl/ssl.h>
-#ifdef HAVE_OPENSSL_ENGINE_H
-#include <openssl/engine.h>
-#endif
 #include <openssl/rand.h>
 #include <openssl/x509v3.h>
 #ifndef OPENSSL_NO_DSA
@@ -72,6 +69,12 @@
 #include <openssl/ocsp.h>
 #endif
 
+#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && /* 1.0.0 or later */     \
+  !defined(OPENSSL_NO_ENGINE)
+#define USE_OPENSSL_ENGINE
+#include <openssl/engine.h>
+#endif
+
 #include "warnless.h"
 #include "non-ascii.h" /* for Curl_convert_from_utf8 prototype */
 
@@ -83,7 +86,7 @@
 #error "OPENSSL_VERSION_NUMBER not defined"
 #endif
 
-#if defined(HAVE_OPENSSL_ENGINE_H)
+#ifdef USE_OPENSSL_ENGINE
 #include <openssl/ui.h>
 #endif
 
@@ -166,6 +169,17 @@ static unsigned long OpenSSL_version_num(void)
 #define HAVE_KEYLOG_CALLBACK
 #endif
 
+/* Whether SSL_CTX_set_ciphersuites is available.
+ * OpenSSL: supported since 1.1.1 (commit a53b5be6a05)
+ * BoringSSL: no
+ * LibreSSL: no
+ */
+#if ((OPENSSL_VERSION_NUMBER >= 0x10101000L) && \
+     !defined(LIBRESSL_VERSION_NUMBER) &&       \
+     !defined(OPENSSL_IS_BORINGSSL))
+#define HAVE_SSL_CTX_SET_CIPHERSUITES
+#endif
+
 #if defined(LIBRESSL_VERSION_NUMBER)
 #define OSSL_PACKAGE "LibreSSL"
 #elif defined(OPENSSL_IS_BORINGSSL)
@@ -504,7 +518,7 @@ static int do_file_type(const char *type)
   return -1;
 }
 
-#if defined(HAVE_OPENSSL_ENGINE_H)
+#ifdef USE_OPENSSL_ENGINE
 /*
  * Supply default password to the engine user interface conversation.
  * The password is passed by OpenSSL engine from ENGINE_load_private_key()
@@ -544,8 +558,20 @@ static int ssl_ui_writer(UI *ui, UI_STRING *uis)
   }
   return (UI_method_get_writer(UI_OpenSSL()))(ui, uis);
 }
+
+/*
+ * Check if a given string is a PKCS#11 URI
+ */
+static bool is_pkcs11_uri(const char *string)
+{
+  return (string && strncasecompare(string, "pkcs11:", 7));
+}
+
 #endif
 
+static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
+                                     const char *engine);
+
 static
 int cert_stuff(struct connectdata *conn,
                SSL_CTX* ctx,
@@ -606,8 +632,18 @@ int cert_stuff(struct connectdata *conn,
       }
       break;
     case SSL_FILETYPE_ENGINE:
-#if defined(HAVE_OPENSSL_ENGINE_H) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
+#if defined(USE_OPENSSL_ENGINE) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME)
       {
+        /* Implicitly use pkcs11 engine if none was provided and the
+         * cert_file is a PKCS#11 URI */
+        if(!data->state.engine) {
+          if(is_pkcs11_uri(cert_file)) {
+            if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) {
+              return 0;
+            }
+          }
+        }
+
         if(data->state.engine) {
           const char *cmd_name = "LOAD_CERT_CTRL";
           struct {
@@ -781,9 +817,20 @@ int cert_stuff(struct connectdata *conn,
       }
       break;
     case SSL_FILETYPE_ENGINE:
-#ifdef HAVE_OPENSSL_ENGINE_H
+#ifdef USE_OPENSSL_ENGINE
       {                         /* XXXX still needs some work */
         EVP_PKEY *priv_key = NULL;
+
+        /* Implicitly use pkcs11 engine if none was provided and the
+         * key_file is a PKCS#11 URI */
+        if(!data->state.engine) {
+          if(is_pkcs11_uri(key_file)) {
+            if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) {
+              return 0;
+            }
+          }
+        }
+
         if(data->state.engine) {
           UI_METHOD *ui_method =
             UI_create_method((char *)"curl user interface");
@@ -1088,7 +1135,7 @@ static int Curl_ossl_check_cxn(struct connectdata *conn)
 static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
                                      const char *engine)
 {
-#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
+#ifdef USE_OPENSSL_ENGINE
   ENGINE *e;
 
 #if OPENSSL_VERSION_NUMBER >= 0x00909000L
@@ -1133,7 +1180,7 @@ static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
  */
 static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
 {
-#ifdef HAVE_OPENSSL_ENGINE_H
+#ifdef USE_OPENSSL_ENGINE
   if(data->state.engine) {
     if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) {
       infof(data, "set default crypto engine '%s'\n",
@@ -1156,7 +1203,7 @@ static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
 static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
 {
   struct curl_slist *list = NULL;
-#if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
+#ifdef USE_OPENSSL_ENGINE
   struct curl_slist *beg;
   ENGINE *e;
 
@@ -1312,7 +1359,7 @@ static void Curl_ossl_session_free(void *ptr)
  */
 static void Curl_ossl_close_all(struct Curl_easy *data)
 {
-#ifdef HAVE_OPENSSL_ENGINE_H
+#ifdef USE_OPENSSL_ENGINE
   if(data->state.engine) {
     ENGINE_finish(data->state.engine);
     ENGINE_free(data->state.engine);
@@ -1922,7 +1969,15 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
     }
     else
 #endif
-    {
+    if(content_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
+      msg_type = *(char *)buf;
+      msg_name = "Change cipher spec";
+    }
+    else if(content_type == SSL3_RT_ALERT) {
+      msg_type = (((char *)buf)[0] << 8) + ((char *)buf)[1];
+      msg_name = SSL_alert_desc_string_long(msg_type);
+    }
+    else {
       msg_type = *(char *)buf;
       msg_name = ssl_msg_type(ssl_ver, msg_type);
     }
@@ -1931,12 +1986,12 @@ static void ssl_tls_trace(int direction, int ssl_ver, int content_type,
                        verstr, direction?"OUT":"IN",
                        tls_rt_name, msg_name, msg_type);
     if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) {
-      Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len, NULL);
+      Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len);
     }
   }
 
   Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT :
-             CURLINFO_SSL_DATA_IN, (char *)buf, len, NULL);
+             CURLINFO_SSL_DATA_IN, (char *)buf, len);
   (void) ssl;
 }
 #endif
@@ -2064,10 +2119,6 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
   long ssl_version = SSL_CONN_CONFIG(version);
   long ssl_version_max = SSL_CONN_CONFIG(version_max);
 
-  if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
-    ssl_version_max = ssl_version << 16;
-  }
-
   switch(ssl_version) {
     case CURL_SSLVERSION_TLSv1_3:
 #ifdef TLS1_3_VERSION
@@ -2099,8 +2150,7 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
 #endif
       /* FALLTHROUGH */
     case CURL_SSLVERSION_TLSv1_0:
-      *ctx_options |= SSL_OP_NO_SSLv2;
-      *ctx_options |= SSL_OP_NO_SSLv3;
+    case CURL_SSLVERSION_TLSv1:
       break;
   }
 
@@ -2116,12 +2166,12 @@ set_ssl_version_min_max(long *ctx_options, struct connectdata *conn,
 #endif
       /* FALLTHROUGH */
     case CURL_SSLVERSION_MAX_TLSv1_2:
-    case CURL_SSLVERSION_MAX_DEFAULT:
 #ifdef TLS1_3_VERSION
       *ctx_options |= SSL_OP_NO_TLSv1_3;
 #endif
       break;
     case CURL_SSLVERSION_MAX_TLSv1_3:
+    case CURL_SSLVERSION_MAX_DEFAULT:
 #ifdef TLS1_3_VERSION
       break;
 #else
@@ -2305,11 +2355,6 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 
   switch(ssl_version) {
   case CURL_SSLVERSION_SSLv3:
-#ifdef USE_TLS_SRP
-    if(ssl_authtype == CURL_TLSAUTH_SRP) {
-      infof(data, "Set version TLSv1.x for SRP authorisation\n");
-    }
-#endif
     ctx_options |= SSL_OP_NO_SSLv2;
     ctx_options |= SSL_OP_NO_TLSv1;
 #if OPENSSL_VERSION_NUMBER >= 0x1000100FL
@@ -2323,21 +2368,20 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
-    ctx_options |= SSL_OP_NO_SSLv2;
-    ctx_options |= SSL_OP_NO_SSLv3;
-    break;
-
   case CURL_SSLVERSION_TLSv1_0:
   case CURL_SSLVERSION_TLSv1_1:
   case CURL_SSLVERSION_TLSv1_2:
   case CURL_SSLVERSION_TLSv1_3:
+    /* asking for any TLS version as the minimum, means no SSL versions
+       allowed */
+    ctx_options |= SSL_OP_NO_SSLv2;
+    ctx_options |= SSL_OP_NO_SSLv3;
     result = set_ssl_version_min_max(&ctx_options, conn, sockindex);
     if(result != CURLE_OK)
        return result;
     break;
 
   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
@@ -2348,10 +2392,6 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
 #endif
 #endif
     break;
-#else
-    failf(data, OSSL_PACKAGE " was built without SSLv2 support");
-    return CURLE_NOT_BUILT_IN;
-#endif
 
   default:
     failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
@@ -2414,6 +2454,19 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
     infof(data, "Cipher selection: %s\n", ciphers);
   }
 
+#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
+  {
+    char *ciphers13 = SSL_CONN_CONFIG(cipher_list13);
+    if(ciphers13) {
+      if(!SSL_CTX_set_ciphersuites(BACKEND->ctx, ciphers13)) {
+        failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers);
+        return CURLE_SSL_CIPHER;
+      }
+      infof(data, "TLS 1.3 cipher selection: %s\n", ciphers13);
+    }
+  }
+#endif
+
 #ifdef USE_TLS_SRP
   if(ssl_authtype == CURL_TLSAUTH_SRP) {
     char * const ssl_username = SSL_SET_OPTION(username);
@@ -3754,6 +3807,9 @@ const struct Curl_ssl Curl_ssl_openssl = {
   SSLSUPP_CERTINFO |
   SSLSUPP_PINNEDPUBKEY |
   SSLSUPP_SSL_CTX |
+#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
+  SSLSUPP_TLS13_CIPHERSUITES |
+#endif
   SSLSUPP_HTTPS_PROXY,
 
   sizeof(struct ssl_backend_data),
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index 2cfd5c1..8f6c301 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -90,11 +90,17 @@
 #endif
 #endif
 
+#if defined(CryptStringToBinary) && defined(CRYPT_STRING_HEX)
+#define HAS_CLIENT_CERT_PATH
+#endif
+
+#ifdef HAS_CLIENT_CERT_PATH
 #ifdef UNICODE
 #define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_W
 #else
 #define CURL_CERT_STORE_PROV_SYSTEM CERT_STORE_PROV_SYSTEM_A
 #endif
+#endif
 
 #ifndef SP_PROT_SSL2_CLIENT
 #define SP_PROT_SSL2_CLIENT             0x00000008
@@ -199,6 +205,155 @@ set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
   return CURLE_OK;
 }
 
+/*longest is 26, buffer is slightly bigger*/
+#define LONGEST_ALG_ID 32
+#define CIPHEROPTION(X) \
+if(strcmp(#X, tmp) == 0) \
+  return X
+
+static int
+get_alg_id_by_name(char *name)
+{
+  char tmp[LONGEST_ALG_ID] = { 0 };
+  char *nameEnd = strchr(name, ':');
+  size_t n = nameEnd ? min((size_t)(nameEnd - name), LONGEST_ALG_ID - 1) : \
+    min(strlen(name), LONGEST_ALG_ID - 1);
+  strncpy(tmp, name, n);
+  tmp[n] = 0;
+  CIPHEROPTION(CALG_MD2);
+  CIPHEROPTION(CALG_MD4);
+  CIPHEROPTION(CALG_MD5);
+  CIPHEROPTION(CALG_SHA);
+  CIPHEROPTION(CALG_SHA1);
+  CIPHEROPTION(CALG_MAC);
+  CIPHEROPTION(CALG_RSA_SIGN);
+  CIPHEROPTION(CALG_DSS_SIGN);
+/*ifdefs for the options that are defined conditionally in wincrypt.h*/
+#ifdef CALG_NO_SIGN
+  CIPHEROPTION(CALG_NO_SIGN);
+#endif
+  CIPHEROPTION(CALG_RSA_KEYX);
+  CIPHEROPTION(CALG_DES);
+#ifdef CALG_3DES_112
+  CIPHEROPTION(CALG_3DES_112);
+#endif
+  CIPHEROPTION(CALG_3DES);
+  CIPHEROPTION(CALG_DESX);
+  CIPHEROPTION(CALG_RC2);
+  CIPHEROPTION(CALG_RC4);
+  CIPHEROPTION(CALG_SEAL);
+#ifdef CALG_DH_SF
+  CIPHEROPTION(CALG_DH_SF);
+#endif
+  CIPHEROPTION(CALG_DH_EPHEM);
+#ifdef CALG_AGREEDKEY_ANY
+  CIPHEROPTION(CALG_AGREEDKEY_ANY);
+#endif
+#ifdef CALG_HUGHES_MD5
+  CIPHEROPTION(CALG_HUGHES_MD5);
+#endif
+  CIPHEROPTION(CALG_SKIPJACK);
+#ifdef CALG_TEK
+  CIPHEROPTION(CALG_TEK);
+#endif
+  CIPHEROPTION(CALG_CYLINK_MEK);
+  CIPHEROPTION(CALG_SSL3_SHAMD5);
+#ifdef CALG_SSL3_MASTER
+  CIPHEROPTION(CALG_SSL3_MASTER);
+#endif
+#ifdef CALG_SCHANNEL_MASTER_HASH
+  CIPHEROPTION(CALG_SCHANNEL_MASTER_HASH);
+#endif
+#ifdef CALG_SCHANNEL_MAC_KEY
+  CIPHEROPTION(CALG_SCHANNEL_MAC_KEY);
+#endif
+#ifdef CALG_SCHANNEL_ENC_KEY
+  CIPHEROPTION(CALG_SCHANNEL_ENC_KEY);
+#endif
+#ifdef CALG_PCT1_MASTER
+  CIPHEROPTION(CALG_PCT1_MASTER);
+#endif
+#ifdef CALG_SSL2_MASTER
+  CIPHEROPTION(CALG_SSL2_MASTER);
+#endif
+#ifdef CALG_TLS1_MASTER
+  CIPHEROPTION(CALG_TLS1_MASTER);
+#endif
+#ifdef CALG_RC5
+  CIPHEROPTION(CALG_RC5);
+#endif
+#ifdef CALG_HMAC
+  CIPHEROPTION(CALG_HMAC);
+#endif
+#if !defined(__W32API_MAJOR_VERSION) || \
+    !defined(__W32API_MINOR_VERSION) || \
+    defined(__MINGW64_VERSION_MAJOR) || \
+    (__W32API_MAJOR_VERSION > 5)     || \
+    ((__W32API_MAJOR_VERSION == 5) && (__W32API_MINOR_VERSION > 0))
+  /* CALG_TLS1PRF has a syntax error in MinGW's w32api up to version 5.0,
+     see https://osdn.net/projects/mingw/ticket/38391 */
+  CIPHEROPTION(CALG_TLS1PRF);
+#endif
+#ifdef CALG_HASH_REPLACE_OWF
+  CIPHEROPTION(CALG_HASH_REPLACE_OWF);
+#endif
+#ifdef CALG_AES_128
+  CIPHEROPTION(CALG_AES_128);
+#endif
+#ifdef CALG_AES_192
+  CIPHEROPTION(CALG_AES_192);
+#endif
+#ifdef CALG_AES_256
+  CIPHEROPTION(CALG_AES_256);
+#endif
+#ifdef CALG_AES
+  CIPHEROPTION(CALG_AES);
+#endif
+#ifdef CALG_SHA_256
+  CIPHEROPTION(CALG_SHA_256);
+#endif
+#ifdef CALG_SHA_384
+  CIPHEROPTION(CALG_SHA_384);
+#endif
+#ifdef CALG_SHA_512
+  CIPHEROPTION(CALG_SHA_512);
+#endif
+#ifdef CALG_ECDH
+  CIPHEROPTION(CALG_ECDH);
+#endif
+#ifdef CALG_ECMQV
+  CIPHEROPTION(CALG_ECMQV);
+#endif
+#ifdef CALG_ECDSA
+  CIPHEROPTION(CALG_ECDSA);
+#endif
+  return 0;
+}
+
+static CURLcode
+set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers)
+{
+  char *startCur = ciphers;
+  int algCount = 0;
+  static ALG_ID algIds[45]; /*There are 45 listed in the MS headers*/
+  while(startCur && (0 != *startCur) && (algCount < 45)) {
+    long alg = strtol(startCur, 0, 0);
+    if(!alg)
+      alg = get_alg_id_by_name(startCur);
+    if(alg)
+      algIds[algCount++] = alg;
+    else
+      return CURLE_SSL_CIPHER;
+    startCur = strchr(startCur, ':');
+    if(startCur)
+      startCur++;
+  }
+    schannel_cred->palgSupportedAlgs = algIds;
+  schannel_cred->cSupportedAlgs = algCount;
+  return CURLE_OK;
+}
+
+#ifdef HAS_CLIENT_CERT_PATH
 static CURLcode
 get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
                   TCHAR **thumbprint)
@@ -248,6 +403,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
 
   return CURLE_OK;
 }
+#endif
 
 static CURLcode
 schannel_connect_step1(struct connectdata *conn, int sockindex)
@@ -299,10 +455,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
 #endif
 
 #ifdef _WIN32_WCE
+#ifdef HAS_MANUAL_VERIFY_API
   /* certificate validation on CE doesn't seem to work right; we'll
    * do it following a more manual process. */
   BACKEND->use_manual_cred_validation = true;
 #else
+#error "compiler too old to support requisite manual cert verify for Win CE"
+#endif
+#else
+#ifdef HAS_MANUAL_VERIFY_API
   if(SSL_CONN_CONFIG(CAfile)) {
     if(Curl_verify_windows_version(6, 1, PLATFORM_WINNT,
                                    VERSION_GREATER_THAN_EQUAL)) {
@@ -316,6 +477,12 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
   }
   else
     BACKEND->use_manual_cred_validation = false;
+#else
+  if(SSL_CONN_CONFIG(CAfile)) {
+    failf(data, "schannel: CA cert support not built in");
+    return CURLE_NOT_BUILT_IN;
+  }
+#endif
 #endif
 
   BACKEND->cred = NULL;
@@ -341,9 +508,11 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
     schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
 
     if(conn->ssl_config.verifypeer) {
+#ifdef HAS_MANUAL_VERIFY_API
       if(BACKEND->use_manual_cred_validation)
         schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION;
       else
+#endif
         schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION;
 
       /* TODO s/data->set.ssl.no_revoke/SSL_SET_OPTION(no_revoke)/g */
@@ -401,6 +570,16 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
       return CURLE_SSL_CONNECT_ERROR;
     }
 
+    if(SSL_CONN_CONFIG(cipher_list)) {
+      result = set_ssl_ciphers(&schannel_cred, SSL_CONN_CONFIG(cipher_list));
+      if(CURLE_OK != result) {
+        failf(data, "Unable to set ciphers to passed via SSL_CONN_CONFIG");
+        return result;
+      }
+    }
+
+
+#ifdef HAS_CLIENT_CERT_PATH
     /* client certificate */
     if(data->set.ssl.cert) {
       DWORD cert_store_name;
@@ -417,14 +596,21 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
       result = get_cert_location(cert_path, &cert_store_name,
                                  &cert_store_path, &cert_thumbprint_str);
       if(result != CURLE_OK) {
+        failf(data, "schannel: Failed to get certificate location for %s",
+              cert_path);
         Curl_unicodefree(cert_path);
         return result;
       }
 
-      cert_store = CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0,
-                                 (HCRYPTPROV)NULL,
-                                 cert_store_name, cert_store_path);
+      cert_store =
+        CertOpenStore(CURL_CERT_STORE_PROV_SYSTEM, 0,
+                      (HCRYPTPROV)NULL,
+                      CERT_STORE_OPEN_EXISTING_FLAG | cert_store_name,
+                      cert_store_path);
       if(!cert_store) {
+        failf(data, "schannel: Failed to open cert store %x %s, "
+              "last error is %x",
+              cert_store_name, cert_store_path, GetLastError());
         Curl_unicodefree(cert_path);
         return CURLE_SSL_CONNECT_ERROR;
       }
@@ -453,6 +639,12 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
 
       CertCloseStore(cert_store, 0);
     }
+#else
+    if(data->set.ssl.cert) {
+      failf(data, "schannel: client cert support not built in");
+      return CURLE_NOT_BUILT_IN;
+    }
+#endif
 
     /* allocate memory for the re-usable credential handle */
     BACKEND->cred = (struct curl_schannel_cred *)
@@ -877,9 +1069,11 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
     }
   }
 
+#ifdef HAS_MANUAL_VERIFY_API
   if(conn->ssl_config.verifypeer && BACKEND->use_manual_cred_validation) {
     return verify_certificate(conn, sockindex);
   }
+#endif
 
   return CURLE_OK;
 }
@@ -1819,7 +2013,7 @@ static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
 
     x509_der = (const char *)pCertContextServer->pbCertEncoded;
     x509_der_len = pCertContextServer->cbCertEncoded;
-    memset(&x509_parsed, 0, sizeof x509_parsed);
+    memset(&x509_parsed, 0, sizeof(x509_parsed));
     if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
       break;
 
@@ -1870,7 +2064,8 @@ static void Curl_schannel_checksum(const unsigned char *input,
     if(!CryptCreateHash(hProv, algId, 0, 0, &hHash))
       break; /* failed */
 
-    if(!CryptHashData(hHash, (const BYTE*)input, (DWORD)inputlen, 0))
+    /* workaround for original MinGW, should be (const BYTE*) */
+    if(!CryptHashData(hHash, (BYTE*)input, (DWORD)inputlen, 0))
       break; /* failed */
 
     /* get hash size */
diff --git a/lib/vtls/schannel.h b/lib/vtls/schannel.h
index 4476900..51417af 100644
--- a/lib/vtls/schannel.h
+++ b/lib/vtls/schannel.h
@@ -32,12 +32,44 @@
 
 #include "urldata.h"
 
+/* <wincrypt.h> has been included via the above <schnlsp.h>.
+ * Or in case of ldap.c, it was included via <winldap.h>.
+ * And since <wincrypt.h> has this:
+ *   #define X509_NAME  ((LPCSTR) 7)
+ *
+ * And in BoringSSL's <openssl/base.h> there is:
+ *  typedef struct X509_name_st X509_NAME;
+ *  etc.
+ *
+ * this wil cause all kinds of C-preprocessing paste errors in
+ * BoringSSL's <openssl/x509.h>: So just undefine those defines here
+ * (and only here).
+ */
+#if defined(HAVE_BORINGSSL) || defined(OPENSSL_IS_BORINGSSL)
+# undef X509_NAME
+# undef X509_CERT_PAIR
+# undef X509_EXTENSIONS
+#endif
+
 extern const struct Curl_ssl Curl_ssl_schannel;
 
 CURLcode verify_certificate(struct connectdata *conn, int sockindex);
 
 /* structs to expose only in schannel.c and schannel_verify.c */
 #ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS
+
+#ifdef __MINGW32__
+#include <_mingw.h>
+#ifdef __MINGW64_VERSION_MAJOR
+#define HAS_MANUAL_VERIFY_API
+#endif
+#else
+#include <wincrypt.h>
+#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN
+#define HAS_MANUAL_VERIFY_API
+#endif
+#endif
+
 struct curl_schannel_cred {
   CredHandle cred_handle;
   TimeStamp time_stamp;
@@ -66,7 +98,9 @@ struct ssl_backend_data {
   bool recv_sspi_close_notify; /* true if connection closed by close_notify */
   bool recv_connection_closed; /* true if connection closed, regardless how */
   bool use_alpn; /* true if ALPN is used for this connection */
+#ifdef HAS_MANUAL_VERIFY_API
   bool use_manual_cred_validation; /* true if manual cred validation is used */
+#endif
 };
 #endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */
 
diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c
index db187dd..5a7092a 100644
--- a/lib/vtls/schannel_verify.c
+++ b/lib/vtls/schannel_verify.c
@@ -30,14 +30,15 @@
 #include "curl_setup.h"
 
 #ifdef USE_SCHANNEL
-
-#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
-
 #ifndef USE_WINDOWS_SSPI
 #  error "Can't compile SCHANNEL support without SSPI."
 #endif
 
+#define EXPOSE_SCHANNEL_INTERNAL_STRUCTS
 #include "schannel.h"
+
+#ifdef HAS_MANUAL_VERIFY_API
+
 #include "vtls.h"
 #include "sendf.h"
 #include "strerror.h"
@@ -53,7 +54,7 @@
 #define BACKEND connssl->backend
 
 #define MAX_CAFILE_SIZE 1048576 /* 1 MiB */
-#define BEGIN_CERT "-----BEGIN CERTIFICATE-----\n"
+#define BEGIN_CERT "-----BEGIN CERTIFICATE-----"
 #define END_CERT "\n-----END CERTIFICATE-----"
 
 typedef struct {
@@ -71,6 +72,10 @@ typedef struct {
   HCERTSTORE hExclusiveTrustedPeople;
 } CERT_CHAIN_ENGINE_CONFIG_WIN7, *PCERT_CHAIN_ENGINE_CONFIG_WIN7;
 
+static int is_cr_or_lf(char c)
+{
+  return c == '\r' || c == '\n';
+}
 
 static CURLcode add_certs_to_store(HCERTSTORE trust_store,
                                    const char *ca_file,
@@ -177,7 +182,7 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
   current_ca_file_ptr = ca_file_buffer;
   while(more_certs && *current_ca_file_ptr != '\0') {
     char *begin_cert_ptr = strstr(current_ca_file_ptr, BEGIN_CERT);
-    if(!begin_cert_ptr) {
+    if(!begin_cert_ptr || !is_cr_or_lf(begin_cert_ptr[strlen(BEGIN_CERT)])) {
       more_certs = 0;
     }
     else {
@@ -209,7 +214,7 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
                              NULL,
                              NULL,
                              NULL,
-                             &cert_context)) {
+                             (const void **)&cert_context)) {
 
           failf(data,
                 "schannel: failed to extract certificate from CA file "
@@ -548,4 +553,5 @@ CURLcode verify_certificate(struct connectdata *conn, int sockindex)
   return result;
 }
 
+#endif /* HAS_MANUAL_VERIFY_API */
 #endif /* USE_SCHANNEL */
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index ee5bc7a..b61c640 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -96,7 +96,8 @@ Curl_ssl_config_matches(struct ssl_primary_config* data,
      Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
      Curl_safe_strcasecompare(data->random_file, needle->random_file) &&
      Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
-     Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list))
+     Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list) &&
+     Curl_safe_strcasecompare(data->cipher_list13, needle->cipher_list13))
     return TRUE;
 
   return FALSE;
@@ -119,6 +120,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
   CLONE_STRING(random_file);
   CLONE_STRING(egdsocket);
   CLONE_STRING(cipher_list);
+  CLONE_STRING(cipher_list13);
 
   return TRUE;
 }
@@ -131,6 +133,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
   Curl_safefree(sslc->random_file);
   Curl_safefree(sslc->egdsocket);
   Curl_safefree(sslc->cipher_list);
+  Curl_safefree(sslc->cipher_list13);
 }
 
 #ifdef USE_SSL
@@ -980,6 +983,14 @@ bool Curl_ssl_false_start(void)
 }
 
 /*
+ * Check whether the SSL backend supports setting TLS 1.3 cipher suites
+ */
+bool Curl_ssl_tls13_ciphersuites(void)
+{
+  return Curl_ssl->supports & SSLSUPP_TLS13_CIPHERSUITES;
+}
+
+/*
  * Default implementations for unsupported functions.
  */
 
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index e7b87c4..40f9d74 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -31,6 +31,7 @@ struct ssl_connect_data;
 #define SSLSUPP_PINNEDPUBKEY (1<<2) /* supports CURLOPT_PINNEDPUBLICKEY */
 #define SSLSUPP_SSL_CTX      (1<<3) /* supports CURLOPT_SSL_CTX */
 #define SSLSUPP_HTTPS_PROXY  (1<<4) /* supports access via HTTPS proxies */
+#define SSLSUPP_TLS13_CIPHERSUITES (1<<5) /* supports TLS 1.3 ciphersuites */
 
 struct Curl_ssl {
   /*
@@ -93,6 +94,7 @@ CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
 CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
 struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
 bool Curl_none_false_start(void);
+bool Curl_ssl_tls13_ciphersuites(void);
 CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
                           unsigned char *md5sum, size_t md5len);
 
@@ -246,7 +248,7 @@ bool Curl_ssl_false_start(void);
 
 #define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
 
-#else
+#else /* if not USE_SSL */
 
 /* When SSL support is not present, just define away these function calls */
 #define Curl_ssl_init() 1
@@ -270,6 +272,7 @@ bool Curl_ssl_false_start(void);
 #define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN)
 #define Curl_ssl_cert_status_request() FALSE
 #define Curl_ssl_false_start() FALSE
+#define Curl_ssl_tls13_ciphersuites() FALSE
 #endif
 
 #endif /* HEADER_CURL_VTLS_H */
diff --git a/lib/warnless.h b/lib/warnless.h
index f6a2d74..284ea1e 100644
--- a/lib/warnless.h
+++ b/lib/warnless.h
@@ -26,6 +26,9 @@
 #include <curl/curl.h> /* for curl_socket_t */
 #endif
 
+#define CURLX_FUNCTION_CAST(target_type, func) \
+  (target_type)(void (*) (void))(func)
+
 unsigned short curlx_ultous(unsigned long ulnum);
 
 unsigned char curlx_ultouc(unsigned long ulnum);
diff --git a/lib/x509asn1.c b/lib/x509asn1.c
index bba2023..72a0b4a 100644
--- a/lib/x509asn1.c
+++ b/lib/x509asn1.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -40,10 +40,6 @@
 #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. */
 static const char       sanOID[] = "2.5.29.17"; /* Subject alternative name. */
@@ -108,8 +104,8 @@ static const curl_OID   OIDtable[] = {
  */
 
 
-const char *Curl_getASN1Element(curl_asn1Element *elem,
-                                const char *beg, const char *end)
+static const char *getASN1Element(curl_asn1Element *elem,
+                                  const char *beg, const char *end)
 {
   unsigned char b;
   unsigned long len;
@@ -146,7 +142,7 @@ const char *Curl_getASN1Element(curl_asn1Element *elem,
       return (const char *) NULL;
     elem->beg = beg;
     while(beg < end && *beg) {
-      beg = Curl_getASN1Element(&lelem, beg, end);
+      beg = getASN1Element(&lelem, beg, end);
       if(!beg)
         return (const char *) NULL;
     }
@@ -206,7 +202,7 @@ static const char *octet2str(const char *beg, const char *end)
   /* Convert an ASN.1 octet string to a printable string.
      Return the dynamically allocated string, or NULL if an error occurs. */
 
-  if(n <= (CURL_SIZE_T_MAX - 1) / 3) {
+  if(n <= (SIZE_T_MAX - 1) / 3) {
     buf = malloc(3 * n + 1);
     if(buf)
       for(n = 0; beg < end; n += 3)
@@ -287,7 +283,7 @@ 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)
+  if(inlength / size > (SIZE_T_MAX - 1) / 4)
     return -1;  /* Too big. */
   buf = malloc(4 * (inlength / size) + 1);
   if(!buf)
@@ -306,10 +302,10 @@ utf8asn1str(char **to, int type, const char *from, const char *end)
       case 4:
         wc = (wc << 8) | *(const unsigned char *) from++;
         wc = (wc << 8) | *(const unsigned char *) from++;
-        /* fallthrough */
+        /* FALLTHROUGH */
       case 2:
         wc = (wc << 8) | *(const unsigned char *) from++;
-        /* fallthrough */
+        /* FALLTHROUGH */
       default: /* case 1: */
         wc = (wc << 8) | *(const unsigned char *) from++;
       }
@@ -546,7 +542,7 @@ static const char *UTime2str(const char *beg, const char *end)
                        tzl, tzp);
 }
 
-const char *Curl_ASN1tostr(curl_asn1Element *elem, int type)
+static const char *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. */
@@ -605,12 +601,12 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
      Return the total string length, even if larger than `n'. */
 
   for(p1 = dn->beg; p1 < dn->end;) {
-    p1 = Curl_getASN1Element(&rdn, p1, dn->end);
+    p1 = getASN1Element(&rdn, p1, dn->end);
     for(p2 = rdn.beg; p2 < rdn.end;) {
-      p2 = Curl_getASN1Element(&atv, p2, rdn.end);
-      p3 = Curl_getASN1Element(&oid, atv.beg, atv.end);
-      Curl_getASN1Element(&value, p3, atv.end);
-      str = Curl_ASN1tostr(&oid, 0);
+      p2 = getASN1Element(&atv, p2, rdn.end);
+      p3 = getASN1Element(&oid, atv.beg, atv.end);
+      getASN1Element(&value, p3, atv.end);
+      str = ASN1tostr(&oid, 0);
       if(!str)
         return -1;
 
@@ -640,7 +636,7 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
       l++;
 
       /* Generate value. */
-      str = Curl_ASN1tostr(&value, 0);
+      str = ASN1tostr(&value, 0);
       if(!str)
         return -1;
       for(p3 = str; *p3; p3++) {
@@ -655,7 +651,7 @@ static ssize_t encodeDN(char *buf, size_t n, curl_asn1Element *dn)
   return l;
 }
 
-const char *Curl_DNtostr(curl_asn1Element *dn)
+static const char *DNtostr(curl_asn1Element *dn)
 {
   char *buf = (char *) NULL;
   ssize_t n = encodeDN(buf, 0, dn);
@@ -694,17 +690,17 @@ int Curl_parseX509(curl_X509certificate *cert,
   cert->certificate.end = end;
 
   /* Get the sequence content. */
-  if(!Curl_getASN1Element(&elem, beg, end))
+  if(!getASN1Element(&elem, beg, end))
     return -1;  /* Invalid bounds/size. */
   beg = elem.beg;
   end = elem.end;
 
   /* Get tbsCertificate. */
-  beg = Curl_getASN1Element(&tbsCertificate, beg, end);
+  beg = getASN1Element(&tbsCertificate, beg, end);
   /* Skip the signatureAlgorithm. */
-  beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
+  beg = getASN1Element(&cert->signatureAlgorithm, beg, end);
   /* Get the signatureValue. */
-  Curl_getASN1Element(&cert->signature, beg, end);
+  getASN1Element(&cert->signature, beg, end);
 
   /* Parse TBSCertificate. */
   beg = tbsCertificate.beg;
@@ -712,29 +708,29 @@ int Curl_parseX509(curl_X509certificate *cert,
   /* Get optional version, get serialNumber. */
   cert->version.header = NULL;
   cert->version.beg = &defaultVersion;
-  cert->version.end = &defaultVersion + sizeof defaultVersion;;
-  beg = Curl_getASN1Element(&elem, beg, end);
+  cert->version.end = &defaultVersion + sizeof(defaultVersion);
+  beg = getASN1Element(&elem, beg, end);
   if(elem.tag == 0) {
-    Curl_getASN1Element(&cert->version, elem.beg, elem.end);
-    beg = Curl_getASN1Element(&elem, beg, end);
+    getASN1Element(&cert->version, elem.beg, elem.end);
+    beg = getASN1Element(&elem, beg, end);
   }
   cert->serialNumber = elem;
   /* Get signature algorithm. */
-  beg = Curl_getASN1Element(&cert->signatureAlgorithm, beg, end);
+  beg = getASN1Element(&cert->signatureAlgorithm, beg, end);
   /* Get issuer. */
-  beg = Curl_getASN1Element(&cert->issuer, beg, end);
+  beg = getASN1Element(&cert->issuer, beg, end);
   /* Get notBefore and notAfter. */
-  beg = Curl_getASN1Element(&elem, beg, end);
-  ccp = Curl_getASN1Element(&cert->notBefore, elem.beg, elem.end);
-  Curl_getASN1Element(&cert->notAfter, ccp, elem.end);
+  beg = getASN1Element(&elem, beg, end);
+  ccp = getASN1Element(&cert->notBefore, elem.beg, elem.end);
+  getASN1Element(&cert->notAfter, ccp, elem.end);
   /* Get subject. */
-  beg = Curl_getASN1Element(&cert->subject, beg, end);
+  beg = getASN1Element(&cert->subject, beg, end);
   /* Get subjectPublicKeyAlgorithm and subjectPublicKey. */
-  beg = Curl_getASN1Element(&cert->subjectPublicKeyInfo, beg, end);
-  ccp = Curl_getASN1Element(&cert->subjectPublicKeyAlgorithm,
+  beg = getASN1Element(&cert->subjectPublicKeyInfo, beg, end);
+  ccp = getASN1Element(&cert->subjectPublicKeyAlgorithm,
                             cert->subjectPublicKeyInfo.beg,
                             cert->subjectPublicKeyInfo.end);
-  Curl_getASN1Element(&cert->subjectPublicKey, ccp,
+  getASN1Element(&cert->subjectPublicKey, ccp,
                       cert->subjectPublicKeyInfo.end);
   /* Get optional issuerUiqueID, subjectUniqueID and extensions. */
   cert->issuerUniqueID.tag = cert->subjectUniqueID.tag = 0;
@@ -745,19 +741,19 @@ int Curl_parseX509(curl_X509certificate *cert,
   cert->extensions.header = NULL;
   cert->extensions.beg = cert->extensions.end = "";
   if(beg < end)
-    beg = Curl_getASN1Element(&elem, beg, end);
+    beg = getASN1Element(&elem, beg, end);
   if(elem.tag == 1) {
     cert->issuerUniqueID = elem;
     if(beg < end)
-      beg = Curl_getASN1Element(&elem, beg, end);
+      beg = getASN1Element(&elem, beg, end);
   }
   if(elem.tag == 2) {
     cert->subjectUniqueID = elem;
     if(beg < end)
-      beg = Curl_getASN1Element(&elem, beg, end);
+      beg = getASN1Element(&elem, beg, end);
   }
   if(elem.tag == 3)
-    Curl_getASN1Element(&cert->extensions, elem.beg, elem.end);
+    getASN1Element(&cert->extensions, elem.beg, elem.end);
   return 0;
 }
 
@@ -785,12 +781,12 @@ static const char *dumpAlgo(curl_asn1Element *param,
 
   /* Get algorithm parameters and return algorithm name. */
 
-  beg = Curl_getASN1Element(&oid, beg, end);
+  beg = getASN1Element(&oid, beg, end);
   param->header = NULL;
   param->tag = 0;
   param->beg = param->end = end;
   if(beg < end)
-    Curl_getASN1Element(param, beg, end);
+    getASN1Element(param, beg, end);
   return OID2str(oid.beg, oid.end, TRUE);
 }
 
@@ -801,7 +797,7 @@ static void do_pubkey_field(struct Curl_easy *data, int certnum,
 
   /* Generate a certificate information record for the public key. */
 
-  output = Curl_ASN1tostr(elem, 0);
+  output = ASN1tostr(elem, 0);
   if(output) {
     if(data->set.ssl.certinfo)
       Curl_ssl_push_certinfo(data, certnum, label, output);
@@ -825,10 +821,10 @@ static void do_pubkey(struct Curl_easy *data, int certnum,
   /* Generate all information records for the public key. */
 
   /* Get the public key (single element). */
-  Curl_getASN1Element(&pk, pubkey->beg + 1, pubkey->end);
+  getASN1Element(&pk, pubkey->beg + 1, pubkey->end);
 
   if(strcasecompare(algo, "rsaEncryption")) {
-    p = Curl_getASN1Element(&elem, pk.beg, pk.end);
+    p = getASN1Element(&elem, pk.beg, pk.end);
     /* Compute key length. */
     for(q = elem.beg; !*q && q < elem.end; q++)
       ;
@@ -849,22 +845,22 @@ static void do_pubkey(struct Curl_easy *data, int certnum,
     }
     /* Generate coefficients. */
     do_pubkey_field(data, certnum, "rsa(n)", &elem);
-    Curl_getASN1Element(&elem, p, pk.end);
+    getASN1Element(&elem, p, pk.end);
     do_pubkey_field(data, certnum, "rsa(e)", &elem);
   }
   else if(strcasecompare(algo, "dsa")) {
-    p = Curl_getASN1Element(&elem, param->beg, param->end);
+    p = getASN1Element(&elem, param->beg, param->end);
     do_pubkey_field(data, certnum, "dsa(p)", &elem);
-    p = Curl_getASN1Element(&elem, p, param->end);
+    p = getASN1Element(&elem, p, param->end);
     do_pubkey_field(data, certnum, "dsa(q)", &elem);
-    Curl_getASN1Element(&elem, p, param->end);
+    getASN1Element(&elem, p, param->end);
     do_pubkey_field(data, certnum, "dsa(g)", &elem);
     do_pubkey_field(data, certnum, "dsa(pub_key)", &pk);
   }
   else if(strcasecompare(algo, "dhpublicnumber")) {
-    p = Curl_getASN1Element(&elem, param->beg, param->end);
+    p = getASN1Element(&elem, param->beg, param->end);
     do_pubkey_field(data, certnum, "dh(p)", &elem);
-    Curl_getASN1Element(&elem, param->beg, param->end);
+    getASN1Element(&elem, param->beg, param->end);
     do_pubkey_field(data, certnum, "dh(g)", &elem);
     do_pubkey_field(data, certnum, "dh(pub_key)", &pk);
   }
@@ -903,7 +899,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
     return CURLE_OUT_OF_MEMORY;
 
   /* Subject. */
-  ccp = Curl_DNtostr(&cert.subject);
+  ccp = DNtostr(&cert.subject);
   if(!ccp)
     return CURLE_OUT_OF_MEMORY;
   if(data->set.ssl.certinfo)
@@ -913,7 +909,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
   free((char *) ccp);
 
   /* Issuer. */
-  ccp = Curl_DNtostr(&cert.issuer);
+  ccp = DNtostr(&cert.issuer);
   if(!ccp)
     return CURLE_OUT_OF_MEMORY;
   if(data->set.ssl.certinfo)
@@ -937,7 +933,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
     infof(data, "   Version: %lu (0x%lx)\n", version + 1, version);
 
   /* Serial number. */
-  ccp = Curl_ASN1tostr(&cert.serialNumber, 0);
+  ccp = ASN1tostr(&cert.serialNumber, 0);
   if(!ccp)
     return CURLE_OUT_OF_MEMORY;
   if(data->set.ssl.certinfo)
@@ -958,7 +954,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
   free((char *) ccp);
 
   /* Start Date. */
-  ccp = Curl_ASN1tostr(&cert.notBefore, 0);
+  ccp = ASN1tostr(&cert.notBefore, 0);
   if(!ccp)
     return CURLE_OUT_OF_MEMORY;
   if(data->set.ssl.certinfo)
@@ -968,7 +964,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
   free((char *) ccp);
 
   /* Expire Date. */
-  ccp = Curl_ASN1tostr(&cert.notAfter, 0);
+  ccp = ASN1tostr(&cert.notAfter, 0);
   if(!ccp)
     return CURLE_OUT_OF_MEMORY;
   if(data->set.ssl.certinfo)
@@ -992,7 +988,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
 /* TODO: extensions. */
 
   /* Signature. */
-  ccp = Curl_ASN1tostr(&cert.signature, 0);
+  ccp = ASN1tostr(&cert.signature, 0);
   if(!ccp)
     return CURLE_OUT_OF_MEMORY;
   if(data->set.ssl.certinfo)
@@ -1051,7 +1047,7 @@ static const char *checkOID(const char *beg, const char *end,
   /* Check if first ASN.1 element at `beg' is the given OID.
      Return a pointer in the source after the OID if found, else NULL. */
 
-  ccp = Curl_getASN1Element(&e, beg, end);
+  ccp = getASN1Element(&e, beg, end);
   if(!ccp || e.tag != CURL_ASN1_OBJECT_IDENTIFIER)
     return (const char *) NULL;
 
@@ -1110,19 +1106,19 @@ CURLcode Curl_verifyhost(struct connectdata *conn,
 
   /* Process extensions. */
   for(p = cert.extensions.beg; p < cert.extensions.end && matched != 1;) {
-    p = Curl_getASN1Element(&ext, p, cert.extensions.end);
+    p = getASN1Element(&ext, p, cert.extensions.end);
     /* Check if extension is a subjectAlternativeName. */
     ext.beg = checkOID(ext.beg, ext.end, sanOID);
     if(ext.beg) {
-      ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
+      ext.beg = getASN1Element(&elem, ext.beg, ext.end);
       /* Skip critical if present. */
       if(elem.tag == CURL_ASN1_BOOLEAN)
-        ext.beg = Curl_getASN1Element(&elem, ext.beg, ext.end);
+        ext.beg = getASN1Element(&elem, ext.beg, ext.end);
       /* Parse the octet string contents: is a single sequence. */
-      Curl_getASN1Element(&elem, elem.beg, elem.end);
+      getASN1Element(&elem, elem.beg, elem.end);
       /* Check all GeneralNames. */
       for(q = elem.beg; matched != 1 && q < elem.end;) {
-        q = Curl_getASN1Element(&name, q, elem.end);
+        q = getASN1Element(&name, q, elem.end);
         switch(name.tag) {
         case 2: /* DNS name. */
           len = utf8asn1str(&dnsname, CURL_ASN1_IA5_STRING,
@@ -1162,9 +1158,9 @@ CURLcode Curl_verifyhost(struct connectdata *conn,
   /* we have to look to the last occurrence of a commonName in the
      distinguished one to get the most significant one. */
   while(q < cert.subject.end) {
-    q = Curl_getASN1Element(&dn, q, cert.subject.end);
+    q = getASN1Element(&dn, q, cert.subject.end);
     for(p = dn.beg; p < dn.end;) {
-      p = Curl_getASN1Element(&elem, p, dn.end);
+      p = getASN1Element(&elem, p, dn.end);
       /* We have a DN's AttributeTypeAndValue: check it in case it's a CN. */
       elem.beg = checkOID(elem.beg, elem.end, cnOID);
       if(elem.beg)
@@ -1173,7 +1169,7 @@ CURLcode Curl_verifyhost(struct connectdata *conn,
   }
 
   /* Check the CN if found. */
-  if(!Curl_getASN1Element(&elem, name.beg, name.end))
+  if(!getASN1Element(&elem, name.beg, name.end))
     failf(data, "SSL: unable to obtain common name from peer certificate");
   else {
     len = utf8asn1str(&dnsname, elem.tag, elem.beg, elem.end);
-- 
cgit v0.12