Преглед на файлове

Merge branch 'upstream-curl' into update-curl

* upstream-curl:
  curl 2019-05-22 (885ce314)
Brad King преди 6 години
родител
ревизия
a39138ef9a
променени са 100 файла, в които са добавени 3168 реда и са изтрити 1970 реда
  1. 50 2
      Utilities/cmcurl/CMake/CurlTests.c
  2. 2 2
      Utilities/cmcurl/CMake/FindGSS.cmake
  3. 50 17
      Utilities/cmcurl/CMake/OtherTests.cmake
  4. 39 27
      Utilities/cmcurl/CMakeLists.txt
  5. 1 1
      Utilities/cmcurl/COPYING
  6. 58 8
      Utilities/cmcurl/include/curl/curl.h
  7. 6 6
      Utilities/cmcurl/include/curl/curlver.h
  8. 5 9
      Utilities/cmcurl/include/curl/typecheck-gcc.h
  9. 5 2
      Utilities/cmcurl/include/curl/urlapi.h
  10. 10 9
      Utilities/cmcurl/lib/Makefile.inc
  11. 569 0
      Utilities/cmcurl/lib/altsvc.c
  12. 77 0
      Utilities/cmcurl/lib/altsvc.h
  13. 25 7
      Utilities/cmcurl/lib/amigaos.c
  14. 8 2
      Utilities/cmcurl/lib/amigaos.h
  15. 140 17
      Utilities/cmcurl/lib/asyn-ares.c
  16. 50 20
      Utilities/cmcurl/lib/asyn-thread.c
  17. 26 10
      Utilities/cmcurl/lib/asyn.h
  18. 20 13
      Utilities/cmcurl/lib/base64.c
  19. 22 16
      Utilities/cmcurl/lib/conncache.c
  20. 4 4
      Utilities/cmcurl/lib/conncache.h
  21. 67 47
      Utilities/cmcurl/lib/connect.c
  22. 1 8
      Utilities/cmcurl/lib/connect.h
  23. 129 73
      Utilities/cmcurl/lib/cookie.c
  24. 11 2
      Utilities/cmcurl/lib/cookie.h
  25. 16 16
      Utilities/cmcurl/lib/curl_addrinfo.c
  26. 5 8
      Utilities/cmcurl/lib/curl_addrinfo.h
  27. 8 2
      Utilities/cmcurl/lib/curl_config.h.cmake
  28. 5 5
      Utilities/cmcurl/lib/curl_endian.c
  29. 4 11
      Utilities/cmcurl/lib/curl_fnmatch.c
  30. 55 0
      Utilities/cmcurl/lib/curl_get_line.c
  31. 7 11
      Utilities/cmcurl/lib/curl_get_line.h
  32. 3 3
      Utilities/cmcurl/lib/curl_gssapi.c
  33. 1 15
      Utilities/cmcurl/lib/curl_gssapi.h
  34. 3 1
      Utilities/cmcurl/lib/curl_md4.h
  35. 5 5
      Utilities/cmcurl/lib/curl_md5.h
  36. 2 2
      Utilities/cmcurl/lib/curl_memory.h
  37. 6 6
      Utilities/cmcurl/lib/curl_multibyte.c
  38. 32 37
      Utilities/cmcurl/lib/curl_ntlm_core.c
  39. 1 3
      Utilities/cmcurl/lib/curl_ntlm_core.h
  40. 67 19
      Utilities/cmcurl/lib/curl_ntlm_wb.c
  41. 7 4
      Utilities/cmcurl/lib/curl_ntlm_wb.h
  42. 5 1
      Utilities/cmcurl/lib/curl_path.c
  43. 4 12
      Utilities/cmcurl/lib/curl_printf.h
  44. 5 4
      Utilities/cmcurl/lib/curl_rtmp.c
  45. 20 20
      Utilities/cmcurl/lib/curl_sasl.c
  46. 20 9
      Utilities/cmcurl/lib/curl_setup.h
  47. 5 6
      Utilities/cmcurl/lib/curlx.h
  48. 4 7
      Utilities/cmcurl/lib/dict.c
  49. 87 40
      Utilities/cmcurl/lib/doh.c
  50. 9 1
      Utilities/cmcurl/lib/doh.h
  51. 27 84
      Utilities/cmcurl/lib/easy.c
  52. 1 1
      Utilities/cmcurl/lib/escape.c
  53. 15 14
      Utilities/cmcurl/lib/file.c
  54. 3 2
      Utilities/cmcurl/lib/fileinfo.c
  55. 7 7
      Utilities/cmcurl/lib/formdata.c
  56. 10 1
      Utilities/cmcurl/lib/formdata.h
  57. 47 56
      Utilities/cmcurl/lib/ftp.c
  58. 1 2
      Utilities/cmcurl/lib/ftp.h
  59. 2 5
      Utilities/cmcurl/lib/ftplistparser.c
  60. 4 4
      Utilities/cmcurl/lib/getinfo.c
  61. 21 7
      Utilities/cmcurl/lib/gopher.c
  62. 4 4
      Utilities/cmcurl/lib/hostasyn.c
  63. 4 7
      Utilities/cmcurl/lib/hostcheck.c
  64. 56 97
      Utilities/cmcurl/lib/hostip.c
  65. 6 13
      Utilities/cmcurl/lib/hostip.h
  66. 2 2
      Utilities/cmcurl/lib/hostip4.c
  67. 8 6
      Utilities/cmcurl/lib/hostip6.c
  68. 318 174
      Utilities/cmcurl/lib/http.c
  69. 5 4
      Utilities/cmcurl/lib/http.h
  70. 60 16
      Utilities/cmcurl/lib/http2.c
  71. 5 2
      Utilities/cmcurl/lib/http2.h
  72. 3 2
      Utilities/cmcurl/lib/http_digest.c
  73. 6 6
      Utilities/cmcurl/lib/http_digest.h
  74. 107 25
      Utilities/cmcurl/lib/http_negotiate.c
  75. 4 4
      Utilities/cmcurl/lib/http_negotiate.h
  76. 24 16
      Utilities/cmcurl/lib/http_ntlm.c
  77. 5 5
      Utilities/cmcurl/lib/http_ntlm.h
  78. 2 2
      Utilities/cmcurl/lib/http_proxy.c
  79. 14 45
      Utilities/cmcurl/lib/if2ip.c
  80. 2 4
      Utilities/cmcurl/lib/if2ip.h
  81. 19 22
      Utilities/cmcurl/lib/imap.c
  82. 6 6
      Utilities/cmcurl/lib/inet_ntop.c
  83. 2 1
      Utilities/cmcurl/lib/inet_pton.c
  84. 13 9
      Utilities/cmcurl/lib/ldap.c
  85. 6 6
      Utilities/cmcurl/lib/libcurl.rc
  86. 60 54
      Utilities/cmcurl/lib/md4.c
  87. 84 90
      Utilities/cmcurl/lib/md5.c
  88. 69 85
      Utilities/cmcurl/lib/memdebug.c
  89. 59 64
      Utilities/cmcurl/lib/memdebug.h
  90. 9 85
      Utilities/cmcurl/lib/mime.c
  91. 24 3
      Utilities/cmcurl/lib/mime.h
  92. 1 1
      Utilities/cmcurl/lib/mprintf.c
  93. 197 296
      Utilities/cmcurl/lib/multi.c
  94. 14 34
      Utilities/cmcurl/lib/multihandle.h
  95. 16 17
      Utilities/cmcurl/lib/multiif.h
  96. 13 3
      Utilities/cmcurl/lib/netrc.c
  97. 10 1
      Utilities/cmcurl/lib/netrc.h
  98. 2 2
      Utilities/cmcurl/lib/non-ascii.c
  99. 4 9
      Utilities/cmcurl/lib/openldap.c
  100. 26 15
      Utilities/cmcurl/lib/parsedate.c

+ 50 - 2
Utilities/cmcurl/CMake/CurlTests.c

@@ -240,6 +240,7 @@ int main()
 #ifndef inet_ntoa_r
 #ifndef inet_ntoa_r
   func_type func;
   func_type func;
   func = (func_type)inet_ntoa_r;
   func = (func_type)inet_ntoa_r;
+  (void)func;
 #endif
 #endif
   return 0;
   return 0;
 }
 }
@@ -255,6 +256,7 @@ int main()
 #ifndef inet_ntoa_r
 #ifndef inet_ntoa_r
   func_type func;
   func_type func;
   func = (func_type)&inet_ntoa_r;
   func = (func_type)&inet_ntoa_r;
+  (void)func;
 #endif
 #endif
   return 0;
   return 0;
 }
 }
@@ -553,8 +555,8 @@ main() {
 #include <time.h>
 #include <time.h>
 int
 int
 main() {
 main() {
-  struct timespec ts = {0, 0}; 
-  clock_gettime(CLOCK_MONOTONIC, &ts); 
+  struct timespec ts = {0, 0};
+  clock_gettime(CLOCK_MONOTONIC, &ts);
   return 0;
   return 0;
 }
 }
 #endif
 #endif
@@ -565,3 +567,49 @@ main() {
   return 0;
   return 0;
 }
 }
 #endif
 #endif
+#ifdef HAVE_VARIADIC_MACROS_C99
+#define c99_vmacro3(first, ...) fun3(first, __VA_ARGS__)
+#define c99_vmacro2(first, ...) fun2(first, __VA_ARGS__)
+
+int fun3(int arg1, int arg2, int arg3);
+int fun2(int arg1, int arg2);
+
+int fun3(int arg1, int arg2, int arg3) {
+  return arg1 + arg2 + arg3;
+}
+int fun2(int arg1, int arg2) {
+  return arg1 + arg2;
+}
+
+int
+main() {
+  int res3 = c99_vmacro3(1, 2, 3);
+  int res2 = c99_vmacro2(1, 2);
+  (void)res3;
+  (void)res2;
+  return 0;
+}
+#endif
+#ifdef HAVE_VARIADIC_MACROS_GCC
+#define gcc_vmacro3(first, args...) fun3(first, args)
+#define gcc_vmacro2(first, args...) fun2(first, args)
+
+int fun3(int arg1, int arg2, int arg3);
+int fun2(int arg1, int arg2);
+
+int fun3(int arg1, int arg2, int arg3) {
+  return arg1 + arg2 + arg3;
+}
+int fun2(int arg1, int arg2) {
+  return arg1 + arg2;
+}
+
+int
+main() {
+  int res3 = gcc_vmacro3(1, 2, 3);
+  int res2 = gcc_vmacro2(1, 2);
+  (void)res3;
+  (void)res2;
+  return 0;
+}
+#endif

+ 2 - 2
Utilities/cmcurl/CMake/FindGSS.cmake

@@ -68,7 +68,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
       # should also work in an odd case when multiple directories are given
       # should also work in an odd case when multiple directories are given
       string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
       string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
       string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
       string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
-      string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1"_GSS_CFLAGS "${_GSS_CFLAGS}")
+      string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _GSS_CFLAGS "${_GSS_CFLAGS}")
 
 
       foreach(_flag ${_GSS_CFLAGS})
       foreach(_flag ${_GSS_CFLAGS})
         if(_flag MATCHES "^-I.*")
         if(_flag MATCHES "^-I.*")
@@ -91,7 +91,7 @@ if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approac
       # this script gives us libraries and link directories. Blah. We have to deal with it.
       # this script gives us libraries and link directories. Blah. We have to deal with it.
       string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
       string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
       string(REGEX REPLACE " +-(L|l)" ";-\\1" _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}")
+      string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
 
 
       foreach(_flag ${_GSS_LIB_FLAGS})
       foreach(_flag ${_GSS_LIB_FLAGS})
         if(_flag MATCHES "^-l.*")
         if(_flag MATCHES "^-l.*")

+ 50 - 17
Utilities/cmcurl/CMake/OtherTests.cmake

@@ -24,6 +24,8 @@ else()
   add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
   add_header_include(HAVE_SYS_SOCKET_H "sys/socket.h")
 endif()
 endif()
 
 
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+
 check_c_source_compiles("${_source_epilogue}
 check_c_source_compiles("${_source_epilogue}
 int main(void) {
 int main(void) {
     recv(0, 0, 0, 0);
     recv(0, 0, 0, 0);
@@ -177,23 +179,6 @@ int main(void) {
   return 0;
   return 0;
 }" HAVE_STRUCT_TIMEVAL)
 }" HAVE_STRUCT_TIMEVAL)
 
 
-
-include(CheckCSourceRuns)
-# See HAVE_POLL in CMakeLists.txt for why poll is disabled on macOS
-if(NOT APPLE)
-  set(CMAKE_REQUIRED_FLAGS)
-  if(HAVE_SYS_POLL_H)
-    set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
-  endif()
-  check_c_source_runs("
-    #ifdef HAVE_SYS_POLL_H
-    #  include <sys/poll.h>
-    #endif
-    int main(void) {
-      return poll((void *)0, 0, 10 /*ms*/);
-    }" HAVE_POLL_FINE)
-endif()
-
 set(HAVE_SIG_ATOMIC_T 1)
 set(HAVE_SIG_ATOMIC_T 1)
 set(CMAKE_REQUIRED_FLAGS)
 set(CMAKE_REQUIRED_FLAGS)
 if(HAVE_SIGNAL_H)
 if(HAVE_SIGNAL_H)
@@ -229,3 +214,51 @@ check_type_size("struct sockaddr_storage" SIZEOF_STRUCT_SOCKADDR_STORAGE)
 if(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
 if(HAVE_SIZEOF_STRUCT_SOCKADDR_STORAGE)
   set(HAVE_STRUCT_SOCKADDR_STORAGE 1)
   set(HAVE_STRUCT_SOCKADDR_STORAGE 1)
 endif()
 endif()
+
+unset(CMAKE_TRY_COMPILE_TARGET_TYPE)
+
+if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
+  # if not cross-compilation...
+  include(CheckCSourceRuns)
+  set(CMAKE_REQUIRED_FLAGS "")
+  if(HAVE_SYS_POLL_H)
+    set(CMAKE_REQUIRED_FLAGS "-DHAVE_SYS_POLL_H")
+  elseif(HAVE_POLL_H)
+    set(CMAKE_REQUIRED_FLAGS "-DHAVE_POLL_H")
+  endif()
+  check_c_source_runs("
+    #include <stdlib.h>
+    #include <sys/time.h>
+
+    #ifdef HAVE_SYS_POLL_H
+    #  include <sys/poll.h>
+    #elif  HAVE_POLL_H
+    #  include <poll.h>
+    #endif
+
+    int main(void)
+    {
+        if(0 != poll(0, 0, 10)) {
+          return 1; /* fail */
+        }
+        else {
+          /* detect the 10.12 poll() breakage */
+          struct timeval before, after;
+          int rc;
+          size_t us;
+
+          gettimeofday(&before, NULL);
+          rc = poll(NULL, 0, 500);
+          gettimeofday(&after, NULL);
+
+          us = (after.tv_sec - before.tv_sec) * 1000000 +
+            (after.tv_usec - before.tv_usec);
+
+          if(us < 400000) {
+            return 1;
+          }
+        }
+        return 0;
+    }" HAVE_POLL_FINE)
+endif()
+

+ 39 - 27
Utilities/cmcurl/CMakeLists.txt

@@ -90,7 +90,7 @@ endif()
 #                            | (__| |_| |  _ <| |___
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #                             \___|\___/|_| \_\_____|
 #
 #
-# Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+# Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
 #
 #
 # This software is licensed as described in the file COPYING, which
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
 # you should have received as part of this distribution. The terms
@@ -143,7 +143,6 @@ string(REGEX MATCH "#define LIBCURL_VERSION_NUM 0x[0-9a-fA-F]+"
   CURL_VERSION_NUM ${CURL_VERSION_H_CONTENTS})
   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?
 
 
 # Setup package meta-data
 # Setup package meta-data
 # SET(PACKAGE "curl")
 # SET(PACKAGE "curl")
@@ -158,7 +157,6 @@ endif()
 set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
 set(OPERATING_SYSTEM "${CMAKE_SYSTEM_NAME}")
 set(OS "\"${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(CURL_WERROR "Turn compiler warnings into errors" OFF)
@@ -193,11 +191,7 @@ endif()
 
 
 if(ENABLE_DEBUG)
 if(ENABLE_DEBUG)
   # DEBUGBUILD will be defined only for Debug builds
   # DEBUGBUILD will be defined only for Debug builds
-  if(NOT CMAKE_VERSION VERSION_LESS 3.0)
-    set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUGBUILD>)
-  else()
-    set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUGBUILD)
-  endif()
+  set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:DEBUGBUILD>)
   set(ENABLE_CURLDEBUG ON)
   set(ENABLE_CURLDEBUG ON)
 endif()
 endif()
 
 
@@ -393,10 +387,10 @@ if(WIN32)
 endif()
 endif()
 
 
 # check SSL libraries
 # check SSL libraries
-# TODO support GNUTLS, NSS, POLARSSL, AXTLS, CYASSL
+# TODO support GNUTLS, NSS, POLARSSL, CYASSL
 
 
 if(APPLE)
 if(APPLE)
-  option(CMAKE_USE_DARWINSSL "enable Apple OS native SSL/TLS" OFF)
+  option(CMAKE_USE_SECTRANSP "enable Apple OS native SSL/TLS" OFF)
 endif()
 endif()
 if(WIN32)
 if(WIN32)
   option(CMAKE_USE_WINSSL "enable Windows native SSL/TLS" OFF)
   option(CMAKE_USE_WINSSL "enable Windows native SSL/TLS" OFF)
@@ -406,13 +400,13 @@ endif()
 option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF)
 option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF)
 
 
 set(openssl_default ON)
 set(openssl_default ON)
-if(WIN32 OR CMAKE_USE_DARWINSSL OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS)
+if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS)
   set(openssl_default OFF)
   set(openssl_default OFF)
 endif()
 endif()
 
 
 count_true(enabled_ssl_options_count
 count_true(enabled_ssl_options_count
   CMAKE_USE_WINSSL
   CMAKE_USE_WINSSL
-  CMAKE_USE_DARWINSSL
+  CMAKE_USE_SECTRANSP
   CMAKE_USE_OPENSSL
   CMAKE_USE_OPENSSL
   CMAKE_USE_MBEDTLS
   CMAKE_USE_MBEDTLS
 )
 )
@@ -432,6 +426,10 @@ if(CURL_WINDOWS_SSPI)
 endif()
 endif()
 
 
 if(CMAKE_USE_DARWINSSL)
 if(CMAKE_USE_DARWINSSL)
+  message(FATAL_ERROR "The cmake option CMAKE_USE_DARWINSSL was renamed to CMAKE_USE_SECTRANSP.")
+endif()
+
+if(CMAKE_USE_SECTRANSP)
   find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation")
   find_library(COREFOUNDATION_FRAMEWORK "CoreFoundation")
   if(NOT COREFOUNDATION_FRAMEWORK)
   if(NOT COREFOUNDATION_FRAMEWORK)
       message(FATAL_ERROR "CoreFoundation framework not found")
       message(FATAL_ERROR "CoreFoundation framework not found")
@@ -443,7 +441,7 @@ if(CMAKE_USE_DARWINSSL)
   endif()
   endif()
 
 
   set(SSL_ENABLED ON)
   set(SSL_ENABLED ON)
-  set(USE_DARWINSSL ON)
+  set(USE_SECTRANSP ON)
   list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}")
   list(APPEND CURL_LIBS "${COREFOUNDATION_FRAMEWORK}" "${SECURITY_FRAMEWORK}")
 endif()
 endif()
 
 
@@ -578,6 +576,7 @@ if(NOT CURL_DISABLE_LDAP)
         list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB})
         list(APPEND CMAKE_REQUIRED_LIBRARIES ${CMAKE_LBER_LIB})
       endif()
       endif()
       check_c_source_compiles("${_SRC_STRING}" NOT_NEED_LBER_H)
       check_c_source_compiles("${_SRC_STRING}" NOT_NEED_LBER_H)
+      unset(CMAKE_REQUIRED_LIBRARIES)
 
 
       if(NOT_NEED_LBER_H)
       if(NOT_NEED_LBER_H)
         set(NEED_LBER_H OFF)
         set(NEED_LBER_H OFF)
@@ -685,6 +684,7 @@ if(CMAKE_USE_LIBSSH2)
     check_function_exists(libssh2_scp_send64        HAVE_LIBSSH2_SCP_SEND64)
     check_function_exists(libssh2_scp_send64        HAVE_LIBSSH2_SCP_SEND64)
     check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE)
     check_function_exists(libssh2_session_handshake HAVE_LIBSSH2_SESSION_HANDSHAKE)
     set(CMAKE_EXTRA_INCLUDE_FILES "")
     set(CMAKE_EXTRA_INCLUDE_FILES "")
+    unset(CMAKE_REQUIRED_LIBRARIES)
   endif()
   endif()
 endif()
 endif()
 
 
@@ -699,7 +699,7 @@ if(CMAKE_USE_GSSAPI)
 
 
     message(STATUS "Found ${GSS_FLAVOUR} GSSAPI version: \"${GSS_VERSION}\"")
     message(STATUS "Found ${GSS_FLAVOUR} GSSAPI version: \"${GSS_VERSION}\"")
 
 
-    list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIRECTORIES})
+    list(APPEND CMAKE_REQUIRED_INCLUDES ${GSS_INCLUDE_DIR})
     check_include_file_concat("gssapi/gssapi.h"  HAVE_GSSAPI_GSSAPI_H)
     check_include_file_concat("gssapi/gssapi.h"  HAVE_GSSAPI_GSSAPI_H)
     check_include_file_concat("gssapi/gssapi_generic.h" HAVE_GSSAPI_GSSAPI_GENERIC_H)
     check_include_file_concat("gssapi/gssapi_generic.h" HAVE_GSSAPI_GSSAPI_GENERIC_H)
     check_include_file_concat("gssapi/gssapi_krb5.h" HAVE_GSSAPI_GSSAPI_KRB5_H)
     check_include_file_concat("gssapi/gssapi_krb5.h" HAVE_GSSAPI_GSSAPI_KRB5_H)
@@ -732,10 +732,11 @@ if(CMAKE_USE_GSSAPI)
       if(NOT HAVE_GSS_C_NT_HOSTBASED_SERVICE)
       if(NOT HAVE_GSS_C_NT_HOSTBASED_SERVICE)
         set(HAVE_OLD_GSSMIT ON)
         set(HAVE_OLD_GSSMIT ON)
       endif()
       endif()
+      unset(CMAKE_REQUIRED_LIBRARIES)
 
 
     endif()
     endif()
 
 
-    include_directories(${GSS_INCLUDE_DIRECTORIES})
+    include_directories(${GSS_INCLUDE_DIR})
     link_directories(${GSS_LINK_DIRECTORIES})
     link_directories(${GSS_LINK_DIRECTORIES})
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_FLAGS}")
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GSS_COMPILER_FLAGS}")
     set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
     set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GSS_LINKER_FLAGS}")
@@ -942,12 +943,8 @@ endif()
 
 
 check_symbol_exists(basename      "${CURL_INCLUDES}" HAVE_BASENAME)
 check_symbol_exists(basename      "${CURL_INCLUDES}" HAVE_BASENAME)
 check_symbol_exists(socket        "${CURL_INCLUDES}" HAVE_SOCKET)
 check_symbol_exists(socket        "${CURL_INCLUDES}" HAVE_SOCKET)
-# poll on macOS is unreliable, it first did not exist, then was broken until
-# fixed in 10.9 only to break again in 10.12.
-if(NOT APPLE)
-  check_symbol_exists(poll        "${CURL_INCLUDES}" HAVE_POLL)
-endif()
 check_symbol_exists(select        "${CURL_INCLUDES}" HAVE_SELECT)
 check_symbol_exists(select        "${CURL_INCLUDES}" HAVE_SELECT)
+check_symbol_exists(poll          "${CURL_INCLUDES}" HAVE_POLL)
 check_symbol_exists(strdup        "${CURL_INCLUDES}" HAVE_STRDUP)
 check_symbol_exists(strdup        "${CURL_INCLUDES}" HAVE_STRDUP)
 check_symbol_exists(strstr        "${CURL_INCLUDES}" HAVE_STRSTR)
 check_symbol_exists(strstr        "${CURL_INCLUDES}" HAVE_STRSTR)
 check_symbol_exists(strtok_r      "${CURL_INCLUDES}" HAVE_STRTOK_R)
 check_symbol_exists(strtok_r      "${CURL_INCLUDES}" HAVE_STRTOK_R)
@@ -1003,6 +1000,8 @@ check_symbol_exists(freeifaddrs    "${CURL_INCLUDES}" HAVE_FREEIFADDRS)
 check_symbol_exists(pipe           "${CURL_INCLUDES}" HAVE_PIPE)
 check_symbol_exists(pipe           "${CURL_INCLUDES}" HAVE_PIPE)
 check_symbol_exists(ftruncate      "${CURL_INCLUDES}" HAVE_FTRUNCATE)
 check_symbol_exists(ftruncate      "${CURL_INCLUDES}" HAVE_FTRUNCATE)
 check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
 check_symbol_exists(getprotobyname "${CURL_INCLUDES}" HAVE_GETPROTOBYNAME)
+check_symbol_exists(getpeername    "${CURL_INCLUDES}" HAVE_GETPEERNAME)
+check_symbol_exists(getsockname    "${CURL_INCLUDES}" HAVE_GETSOCKNAME)
 check_symbol_exists(getrlimit      "${CURL_INCLUDES}" HAVE_GETRLIMIT)
 check_symbol_exists(getrlimit      "${CURL_INCLUDES}" HAVE_GETRLIMIT)
 check_symbol_exists(setlocale      "${CURL_INCLUDES}" HAVE_SETLOCALE)
 check_symbol_exists(setlocale      "${CURL_INCLUDES}" HAVE_SETLOCALE)
 check_symbol_exists(setmode        "${CURL_INCLUDES}" HAVE_SETMODE)
 check_symbol_exists(setmode        "${CURL_INCLUDES}" HAVE_SETMODE)
@@ -1086,6 +1085,8 @@ foreach(CURL_TEST
     HAVE_INET_NTOA_R_DECL_REENTRANT
     HAVE_INET_NTOA_R_DECL_REENTRANT
     HAVE_GETADDRINFO
     HAVE_GETADDRINFO
     HAVE_FILE_OFFSET_BITS
     HAVE_FILE_OFFSET_BITS
+    HAVE_VARIADIC_MACROS_C99
+    HAVE_VARIADIC_MACROS_GCC
     )
     )
   curl_internal_test(${CURL_TEST})
   curl_internal_test(${CURL_TEST})
 endforeach()
 endforeach()
@@ -1247,7 +1248,7 @@ if(CURL_WERROR)
 endif()
 endif()
 
 
 # Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it).
 # Ugly (but functional) way to include "Makefile.inc" by transforming it (= regenerate it).
-function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
+function(transform_makefile_inc INPUT_FILE OUTPUT_FILE)
   file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT)
   file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT)
   string(REPLACE "$(top_srcdir)"   "\${CURL_SOURCE_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
   string(REPLACE "$(top_srcdir)"   "\${CURL_SOURCE_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
   string(REPLACE "$(top_builddir)" "\${CURL_BINARY_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
   string(REPLACE "$(top_builddir)" "\${CURL_BINARY_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
@@ -1311,10 +1312,7 @@ endfunction()
 
 
 # Clear list and try to detect available features
 # Clear list and try to detect available features
 set(_items)
 set(_items)
-_add_if("WinSSL"        SSL_ENABLED AND USE_WINDOWS_SSPI)
-_add_if("OpenSSL"       SSL_ENABLED AND USE_OPENSSL)
-_add_if("DarwinSSL"     SSL_ENABLED AND USE_DARWINSSL)
-_add_if("mbedTLS"       SSL_ENABLED AND USE_MBEDTLS)
+_add_if("SSL"           SSL_ENABLED)
 _add_if("IPv6"          ENABLE_IPV6)
 _add_if("IPv6"          ENABLE_IPV6)
 _add_if("unix-sockets"  USE_UNIX_SOCKETS)
 _add_if("unix-sockets"  USE_UNIX_SOCKETS)
 _add_if("libz"          HAVE_LIBZ)
 _add_if("libz"          HAVE_LIBZ)
@@ -1332,7 +1330,7 @@ _add_if("Kerberos"      NOT CURL_DISABLE_CRYPTO_AUTH AND
                         (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
                         (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
 # NTLM support requires crypto function adaptions from various SSL libs
 # NTLM support requires crypto function adaptions from various SSL libs
 # TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
 # TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
-if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_DARWINSSL OR USE_MBEDTLS))
+if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_SECTRANSP OR USE_MBEDTLS))
   _add_if("NTLM"        1)
   _add_if("NTLM"        1)
   # TODO missing option (autoconf: --enable-ntlm-wb)
   # TODO missing option (autoconf: --enable-ntlm-wb)
   _add_if("NTLM_WB"     NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
   _add_if("NTLM_WB"     NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
@@ -1371,10 +1369,24 @@ _add_if("SCP"           USE_LIBSSH2)
 _add_if("SFTP"          USE_LIBSSH2)
 _add_if("SFTP"          USE_LIBSSH2)
 _add_if("RTSP"          NOT CURL_DISABLE_RTSP)
 _add_if("RTSP"          NOT CURL_DISABLE_RTSP)
 _add_if("RTMP"          USE_LIBRTMP)
 _add_if("RTMP"          USE_LIBRTMP)
-list(SORT _items)
+if(_items)
+  list(SORT _items)
+endif()
 string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}")
 string(REPLACE ";" " " SUPPORT_PROTOCOLS "${_items}")
 message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
 message(STATUS "Enabled protocols: ${SUPPORT_PROTOCOLS}")
 
 
+# Clear list and collect SSL backends
+set(_items)
+_add_if("WinSSL"           SSL_ENABLED AND USE_WINDOWS_SSPI)
+_add_if("OpenSSL"          SSL_ENABLED AND USE_OPENSSL)
+_add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
+_add_if("mbedTLS"          SSL_ENABLED AND USE_MBEDTLS)
+if(_items)
+  list(SORT _items)
+endif()
+string(REPLACE ";" " " SSL_BACKENDS "${_items}")
+message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}")
+
 # curl-config needs the following options to be set.
 # curl-config needs the following options to be set.
 set(CC                      "${CMAKE_C_COMPILER}")
 set(CC                      "${CMAKE_C_COMPILER}")
 # TODO probably put a -D... options here?
 # TODO probably put a -D... options here?

+ 1 - 1
Utilities/cmcurl/COPYING

@@ -1,6 +1,6 @@
 COPYRIGHT AND PERMISSION NOTICE
 COPYRIGHT AND PERMISSION NOTICE
 
 
-Copyright (c) 1996 - 2018, Daniel Stenberg, <[email protected]>, and many
+Copyright (c) 1996 - 2019, Daniel Stenberg, <[email protected]>, and many
 contributors, see the THANKS file.
 contributors, see the THANKS file.
 
 
 All rights reserved.
 All rights reserved.

+ 58 - 8
Utilities/cmcurl/include/curl/curl.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -91,6 +91,11 @@
 #include <support/SupportDefs.h>
 #include <support/SupportDefs.h>
 #endif
 #endif
 
 
+/* Compatibility for non-Clang compilers */
+#ifndef __has_declspec_attribute
+#  define __has_declspec_attribute(x) 0
+#endif
+
 #ifdef  __cplusplus
 #ifdef  __cplusplus
 extern "C" {
 extern "C" {
 #endif
 #endif
@@ -109,7 +114,9 @@ typedef void CURLSH;
 
 
 #ifdef CURL_STATICLIB
 #ifdef CURL_STATICLIB
 #  define CURL_EXTERN
 #  define CURL_EXTERN
-#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)
+#elif defined(WIN32) || defined(__SYMBIAN32__) || \
+     (__has_declspec_attribute(dllexport) && \
+      __has_declspec_attribute(dllimport))
 #  if defined(BUILDING_LIBCURL)
 #  if defined(BUILDING_LIBCURL)
 #    define CURL_EXTERN  __declspec(dllexport)
 #    define CURL_EXTERN  __declspec(dllexport)
 #  else
 #  else
@@ -144,8 +151,8 @@ typedef enum {
   CURLSSLBACKEND_POLARSSL = 6,
   CURLSSLBACKEND_POLARSSL = 6,
   CURLSSLBACKEND_WOLFSSL = 7,
   CURLSSLBACKEND_WOLFSSL = 7,
   CURLSSLBACKEND_SCHANNEL = 8,
   CURLSSLBACKEND_SCHANNEL = 8,
-  CURLSSLBACKEND_DARWINSSL = 9,
-  CURLSSLBACKEND_AXTLS = 10,
+  CURLSSLBACKEND_SECURETRANSPORT = 9,
+  CURLSSLBACKEND_AXTLS = 10, /* never used since 7.63.0 */
   CURLSSLBACKEND_MBEDTLS = 11,
   CURLSSLBACKEND_MBEDTLS = 11,
   CURLSSLBACKEND_MESALINK = 12
   CURLSSLBACKEND_MESALINK = 12
 } curl_sslbackend;
 } curl_sslbackend;
@@ -153,7 +160,10 @@ typedef enum {
 /* aliases for library clones and renames */
 /* aliases for library clones and renames */
 #define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL
 #define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL
 #define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL
 #define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL
+
+/* deprecated names: */
 #define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL
 #define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL
+#define CURLSSLBACKEND_DARWINSSL CURLSSLBACKEND_SECURETRANSPORT
 
 
 struct curl_httppost {
 struct curl_httppost {
   struct curl_httppost *next;       /* next entry in the list */
   struct curl_httppost *next;       /* next entry in the list */
@@ -280,7 +290,7 @@ typedef enum {
 struct curl_fileinfo {
 struct curl_fileinfo {
   char *filename;
   char *filename;
   curlfiletype filetype;
   curlfiletype filetype;
-  time_t time;
+  time_t time; /* always zero! */
   unsigned int perm;
   unsigned int perm;
   int uid;
   int uid;
   int gid;
   int gid;
@@ -355,11 +365,21 @@ typedef int (*curl_seek_callback)(void *instream,
    signal libcurl to pause sending data on the current transfer. */
    signal libcurl to pause sending data on the current transfer. */
 #define CURL_READFUNC_PAUSE 0x10000001
 #define CURL_READFUNC_PAUSE 0x10000001
 
 
+/* Return code for when the trailing headers' callback has terminated
+   without any errors*/
+#define CURL_TRAILERFUNC_OK 0
+/* Return code for when was an error in the trailing header's list and we
+  want to abort the request */
+#define CURL_TRAILERFUNC_ABORT 1
+
 typedef size_t (*curl_read_callback)(char *buffer,
 typedef size_t (*curl_read_callback)(char *buffer,
                                       size_t size,
                                       size_t size,
                                       size_t nitems,
                                       size_t nitems,
                                       void *instream);
                                       void *instream);
 
 
+typedef int (*curl_trailer_callback)(struct curl_slist **list,
+                                      void *userdata);
+
 typedef enum {
 typedef enum {
   CURLSOCKTYPE_IPCXN,  /* socket created for a specific IP connection */
   CURLSOCKTYPE_IPCXN,  /* socket created for a specific IP connection */
   CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
   CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
@@ -585,9 +605,6 @@ typedef enum {
   CURL_LAST /* never use! */
   CURL_LAST /* never use! */
 } CURLcode;
 } CURLcode;
 
 
-/* added in 7.62.0 */
-#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION
-
 #ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
 #ifndef CURL_NO_OLDIES /* define this to test if your app builds with all
                           the obsolete stuff removed! */
                           the obsolete stuff removed! */
 
 
@@ -602,6 +619,9 @@ typedef enum {
 #define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
 #define CURLOPT_ENCODING CURLOPT_ACCEPT_ENCODING
 #define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY
 #define CURLE_FTP_WEIRD_SERVER_REPLY CURLE_WEIRD_SERVER_REPLY
 
 
+/* The following were added in 7.62.0 */
+#define CURLE_SSL_CACERT CURLE_PEER_FAILED_VERIFICATION
+
 /* The following were added in 7.21.5, April 2011 */
 /* The following were added in 7.21.5, April 2011 */
 #define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
 #define CURLE_UNKNOWN_TELNET_OPTION CURLE_UNKNOWN_OPTION
 
 
@@ -861,6 +881,14 @@ typedef enum {
 #define CURLHEADER_UNIFIED  0
 #define CURLHEADER_UNIFIED  0
 #define CURLHEADER_SEPARATE (1<<0)
 #define CURLHEADER_SEPARATE (1<<0)
 
 
+/* CURLALTSVC_* are bits for the CURLOPT_ALTSVC_CTRL option */
+#define CURLALTSVC_IMMEDIATELY  (1<<0)
+#define CURLALTSVC_ALTUSED      (1<<1)
+#define CURLALTSVC_READONLYFILE (1<<2)
+#define CURLALTSVC_H1           (1<<3)
+#define CURLALTSVC_H2           (1<<4)
+#define CURLALTSVC_H3           (1<<5)
+
 /* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
 /* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */
 #define CURLPROTO_HTTP   (1<<0)
 #define CURLPROTO_HTTP   (1<<0)
 #define CURLPROTO_HTTPS  (1<<1)
 #define CURLPROTO_HTTPS  (1<<1)
@@ -1872,6 +1900,27 @@ typedef enum {
   /* Time in ms between connection upkeep calls for long-lived connections. */
   /* Time in ms between connection upkeep calls for long-lived connections. */
   CINIT(UPKEEP_INTERVAL_MS, LONG, 281),
   CINIT(UPKEEP_INTERVAL_MS, LONG, 281),
 
 
+  /* Specify URL using CURL URL API. */
+  CINIT(CURLU, OBJECTPOINT, 282),
+
+  /* add trailing data just after no more data is available */
+  CINIT(TRAILERFUNCTION, FUNCTIONPOINT, 283),
+
+  /* pointer to be passed to HTTP_TRAILER_FUNCTION */
+  CINIT(TRAILERDATA, OBJECTPOINT, 284),
+
+  /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */
+  CINIT(HTTP09_ALLOWED, LONG, 285),
+
+  /* alt-svc control bitmask */
+  CINIT(ALTSVC_CTRL, LONG, 286),
+
+  /* alt-svc cache file name to possibly read from/write to */
+  CINIT(ALTSVC, STRINGPOINT, 287),
+
+  /* maximum age of a connection to consider it for reuse (in seconds) */
+  CINIT(MAXAGE_CONN, LONG, 288),
+
   CURLOPT_LASTENTRY /* the last unused */
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 } CURLoption;
 
 
@@ -2734,6 +2783,7 @@ typedef struct {
 #define CURL_VERSION_HTTPS_PROXY  (1<<21) /* HTTPS-proxy support built-in */
 #define CURL_VERSION_HTTPS_PROXY  (1<<21) /* HTTPS-proxy support built-in */
 #define CURL_VERSION_MULTI_SSL    (1<<22) /* Multiple SSL backends available */
 #define CURL_VERSION_MULTI_SSL    (1<<22) /* Multiple SSL backends available */
 #define CURL_VERSION_BROTLI       (1<<23) /* Brotli features are present. */
 #define CURL_VERSION_BROTLI       (1<<23) /* Brotli features are present. */
+#define CURL_VERSION_ALTSVC       (1<<24) /* Alt-Svc handling built-in */
 
 
  /*
  /*
  * NAME curl_version_info()
  * NAME curl_version_info()

+ 6 - 6
Utilities/cmcurl/include/curl/curlver.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -26,16 +26,16 @@
    a script at release-time. This was made its own header file in 7.11.2 */
    a script at release-time. This was made its own header file in 7.11.2 */
 
 
 /* This is the global package copyright */
 /* This is the global package copyright */
-#define LIBCURL_COPYRIGHT "1996 - 2018 Daniel Stenberg, <[email protected]>."
+#define LIBCURL_COPYRIGHT "1996 - 2019 Daniel Stenberg, <[email protected]>."
 
 
 /* This is the version number of the libcurl package from which this header
 /* This is the version number of the libcurl package from which this header
    file origins: */
    file origins: */
-#define LIBCURL_VERSION "7.62.0"
+#define LIBCURL_VERSION "7.65.0"
 
 
 /* The numeric version number is also available "in parts" by using these
 /* The numeric version number is also available "in parts" by using these
    defines: */
    defines: */
 #define LIBCURL_VERSION_MAJOR 7
 #define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 62
+#define LIBCURL_VERSION_MINOR 65
 #define LIBCURL_VERSION_PATCH 0
 #define LIBCURL_VERSION_PATCH 0
 
 
 /* This is the numeric version of the libcurl version number, meant for easier
 /* This is the numeric version of the libcurl version number, meant for easier
@@ -57,7 +57,7 @@
    CURL_VERSION_BITS() macro since curl's own configure script greps for it
    CURL_VERSION_BITS() macro since curl's own configure script greps for it
    and needs it to contain the full number.
    and needs it to contain the full number.
 */
 */
-#define LIBCURL_VERSION_NUM 0x073E00
+#define LIBCURL_VERSION_NUM 0x074100
 
 
 /*
 /*
  * This is the date and time when the full source package was created. The
  * This is the date and time when the full source package was created. The
@@ -70,7 +70,7 @@
  */
  */
 #define LIBCURL_TIMESTAMP "[unreleased]"
 #define LIBCURL_TIMESTAMP "[unreleased]"
 
 
-#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
+#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
 #define CURL_AT_LEAST_VERSION(x,y,z) \
 #define CURL_AT_LEAST_VERSION(x,y,z) \
   (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
   (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
 
 

+ 5 - 9
Utilities/cmcurl/include/curl/typecheck-gcc.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -113,7 +113,6 @@ __extension__ ({                                                              \
 })
 })
 
 
 /* wraps curl_easy_getinfo() with typechecking */
 /* wraps curl_easy_getinfo() with typechecking */
-/* FIXME: don't allow const pointers */
 #define curl_easy_getinfo(handle, info, arg)                                  \
 #define curl_easy_getinfo(handle, info, arg)                                  \
 __extension__ ({                                                              \
 __extension__ ({                                                              \
   __typeof__(info) _curl_info = info;                                         \
   __typeof__(info) _curl_info = info;                                         \
@@ -146,9 +145,8 @@ __extension__ ({                                                              \
   curl_easy_getinfo(handle, _curl_info, arg);                                 \
   curl_easy_getinfo(handle, _curl_info, arg);                                 \
 })
 })
 
 
-/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
- * for now just make sure that the functions are called with three
- * arguments
+/*
+ * For now, just make sure that the functions are called with three arguments
  */
  */
 #define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
 #define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
 #define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
 #define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
@@ -256,6 +254,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
 #define _curl_is_string_option(option)                                        \
 #define _curl_is_string_option(option)                                        \
   ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET ||                                \
   ((option) == CURLOPT_ABSTRACT_UNIX_SOCKET ||                                \
    (option) == CURLOPT_ACCEPT_ENCODING ||                                     \
    (option) == CURLOPT_ACCEPT_ENCODING ||                                     \
+   (option) == CURLOPT_ALTSVC ||                                              \
    (option) == CURLOPT_CAINFO ||                                              \
    (option) == CURLOPT_CAINFO ||                                              \
    (option) == CURLOPT_CAPATH ||                                              \
    (option) == CURLOPT_CAPATH ||                                              \
    (option) == CURLOPT_COOKIE ||                                              \
    (option) == CURLOPT_COOKIE ||                                              \
@@ -363,6 +362,7 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
    (option) == CURLOPT_SSL_CTX_DATA ||                                        \
    (option) == CURLOPT_SSL_CTX_DATA ||                                        \
    (option) == CURLOPT_WRITEDATA ||                                           \
    (option) == CURLOPT_WRITEDATA ||                                           \
    (option) == CURLOPT_RESOLVER_START_DATA ||                                 \
    (option) == CURLOPT_RESOLVER_START_DATA ||                                 \
+   (option) == CURLOPT_CURLU ||                                               \
    0)
    0)
 
 
 /* evaluates to true if option takes a POST data argument (void* or char*) */
 /* evaluates to true if option takes a POST data argument (void* or char*) */
@@ -504,10 +504,6 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_off_t,
    _curl_is_arr((expr), char) ||                                              \
    _curl_is_arr((expr), char) ||                                              \
    _curl_is_arr((expr), unsigned char))
    _curl_is_arr((expr), unsigned char))
 
 
-/* FIXME: the whole callback checking is messy...
- * The idea is to tolerate char vs. void and const vs. not const
- * pointers in arguments at least
- */
 /* helper: __builtin_types_compatible_p distinguishes between functions and
 /* helper: __builtin_types_compatible_p distinguishes between functions and
  * function pointers, hide it */
  * function pointers, hide it */
 #define _curl_callback_compatible(func, type)                                 \
 #define _curl_callback_compatible(func, type)                                 \

+ 5 - 2
Utilities/cmcurl/include/curl/urlapi.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2018 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,8 @@
  *
  *
  ***************************************************************************/
  ***************************************************************************/
 
 
+#include "curl.h"
+
 #ifdef  __cplusplus
 #ifdef  __cplusplus
 extern "C" {
 extern "C" {
 #endif
 #endif
@@ -58,7 +60,8 @@ typedef enum {
   CURLUPART_PORT,
   CURLUPART_PORT,
   CURLUPART_PATH,
   CURLUPART_PATH,
   CURLUPART_QUERY,
   CURLUPART_QUERY,
-  CURLUPART_FRAGMENT
+  CURLUPART_FRAGMENT,
+  CURLUPART_ZONEID /* added in 7.65.0 */
 } CURLUPart;
 } CURLUPart;
 
 
 #define CURLU_DEFAULT_PORT (1<<0)       /* return default port number */
 #define CURLU_DEFAULT_PORT (1<<0)       /* return default port number */

+ 10 - 9
Utilities/cmcurl/lib/Makefile.inc

@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #                             \___|\___/|_| \_\_____|
 #
 #
-# Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+# Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
 #
 #
 # This software is licensed as described in the file COPYING, which
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
 # you should have received as part of this distribution. The terms
@@ -28,13 +28,13 @@ LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c         \
 LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h
 LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h
 
 
 LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c     \
 LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c     \
-  vtls/polarssl.c vtls/polarssl_threadlock.c vtls/axtls.c               \
+  vtls/polarssl.c vtls/polarssl_threadlock.c                            \
   vtls/cyassl.c vtls/schannel.c vtls/schannel_verify.c                  \
   vtls/cyassl.c vtls/schannel.c vtls/schannel_verify.c                  \
-  vtls/darwinssl.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c
+  vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c vtls/mesalink.c
 
 
 LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h                \
 LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h                \
-  vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h vtls/axtls.h   \
-  vtls/cyassl.h vtls/schannel.h vtls/darwinssl.h vtls/gskit.h           \
+  vtls/nssg.h vtls/polarssl.h vtls/polarssl_threadlock.h                \
+  vtls/cyassl.h vtls/schannel.h vtls/sectransp.h vtls/gskit.h           \
   vtls/mbedtls.h vtls/mesalink.h
   vtls/mbedtls.h vtls/mesalink.h
 
 
 LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
 LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
@@ -52,10 +52,10 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
   openldap.c curl_gethostname.c gopher.c idn_win32.c                    \
   openldap.c curl_gethostname.c gopher.c idn_win32.c                    \
   http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c      \
   http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c      \
   http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.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          \
+  curl_multibyte.c hostcheck.c conncache.c dotdot.c                     \
   x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.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 psl.c  \
   mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c  \
-  doh.c urlapi.c
+  doh.c urlapi.c curl_get_line.c altsvc.c
 
 
 LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
 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         \
   formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h         \
@@ -72,10 +72,11 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
   curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h           \
   curl_gethostname.h gopher.h http_proxy.h non-ascii.h asyn.h           \
   http_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h             \
   http_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h             \
   curl_sasl.h curl_multibyte.h hostcheck.h conncache.h                  \
   curl_sasl.h curl_multibyte.h hostcheck.h conncache.h                  \
-  curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h       \
+  curl_setup_once.h multihandle.h setup-vms.h dotdot.h                  \
   x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.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_printf.h system_win32.h rand.h mime.h curl_sha256.h setopt.h     \
-  curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h
+  curl_path.h curl_ctype.h curl_range.h psl.h doh.h urlapi-int.h        \
+  curl_get_line.h altsvc.h
 
 
 LIB_RCFILES = libcurl.rc
 LIB_RCFILES = libcurl.rc
 
 

+ 569 - 0
Utilities/cmcurl/lib/altsvc.c

@@ -0,0 +1,569 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2019, Daniel Stenberg, <[email protected]>, 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.
+ *
+ ***************************************************************************/
+/*
+ * The Alt-Svc: header is defined in RFC 7838:
+ * https://tools.ietf.org/html/rfc7838
+ */
+#include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC)
+#include <curl/curl.h>
+#include "urldata.h"
+#include "altsvc.h"
+#include "curl_get_line.h"
+#include "strcase.h"
+#include "parsedate.h"
+#include "sendf.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"
+
+#define MAX_ALTSVC_LINE 4095
+#define MAX_ALTSVC_DATELENSTR "64"
+#define MAX_ALTSVC_DATELEN 64
+#define MAX_ALTSVC_HOSTLENSTR "512"
+#define MAX_ALTSVC_HOSTLEN 512
+#define MAX_ALTSVC_ALPNLENSTR "10"
+#define MAX_ALTSVC_ALPNLEN 10
+
+static enum alpnid alpn2alpnid(char *name)
+{
+  if(strcasecompare(name, "h1"))
+    return ALPN_h1;
+  if(strcasecompare(name, "h2"))
+    return ALPN_h2;
+  if(strcasecompare(name, "h2c"))
+    return ALPN_h2c;
+  if(strcasecompare(name, "h3"))
+    return ALPN_h3;
+  return ALPN_none; /* unknown, probably rubbish input */
+}
+
+/* Given the ALPN ID, return the name */
+const char *Curl_alpnid2str(enum alpnid id)
+{
+  switch(id) {
+  case ALPN_h1:
+    return "h1";
+  case ALPN_h2:
+    return "h2";
+  case ALPN_h2c:
+    return "h2c";
+  case ALPN_h3:
+    return "h3";
+  default:
+    return ""; /* bad */
+  }
+}
+
+
+static void altsvc_free(struct altsvc *as)
+{
+  free(as->srchost);
+  free(as->dsthost);
+  free(as);
+}
+
+static struct altsvc *altsvc_createid(const char *srchost,
+                                      const char *dsthost,
+                                      enum alpnid srcalpnid,
+                                      enum alpnid dstalpnid,
+                                      unsigned int srcport,
+                                      unsigned int dstport)
+{
+  struct altsvc *as = calloc(sizeof(struct altsvc), 1);
+  if(!as)
+    return NULL;
+
+  as->srchost = strdup(srchost);
+  if(!as->srchost)
+    goto error;
+  as->dsthost = strdup(dsthost);
+  if(!as->dsthost)
+    goto error;
+
+  as->srcalpnid = srcalpnid;
+  as->dstalpnid = dstalpnid;
+  as->srcport = curlx_ultous(srcport);
+  as->dstport = curlx_ultous(dstport);
+
+  return as;
+  error:
+  altsvc_free(as);
+  return NULL;
+}
+
+static struct altsvc *altsvc_create(char *srchost,
+                                    char *dsthost,
+                                    char *srcalpn,
+                                    char *dstalpn,
+                                    unsigned int srcport,
+                                    unsigned int dstport)
+{
+  enum alpnid dstalpnid = alpn2alpnid(dstalpn);
+  enum alpnid srcalpnid = alpn2alpnid(srcalpn);
+  if(!srcalpnid || !dstalpnid)
+    return NULL;
+  return altsvc_createid(srchost, dsthost, srcalpnid, dstalpnid,
+                         srcport, dstport);
+}
+
+/* only returns SERIOUS errors */
+static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
+{
+  /* Example line:
+     h2 example.com 443 h3 shiny.example.com 8443 "20191231 10:00:00" 1
+   */
+  char srchost[MAX_ALTSVC_HOSTLEN + 1];
+  char dsthost[MAX_ALTSVC_HOSTLEN + 1];
+  char srcalpn[MAX_ALTSVC_ALPNLEN + 1];
+  char dstalpn[MAX_ALTSVC_ALPNLEN + 1];
+  char date[MAX_ALTSVC_DATELEN + 1];
+  unsigned int srcport;
+  unsigned int dstport;
+  unsigned int prio;
+  unsigned int persist;
+  int rc;
+
+  rc = sscanf(line,
+              "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
+              "%" MAX_ALTSVC_ALPNLENSTR "s %" MAX_ALTSVC_HOSTLENSTR "s %u "
+              "\"%" MAX_ALTSVC_DATELENSTR "[^\"]\" %u %u",
+              srcalpn, srchost, &srcport,
+              dstalpn, dsthost, &dstport,
+              date, &persist, &prio);
+  if(9 == rc) {
+    struct altsvc *as;
+    time_t expires = curl_getdate(date, NULL);
+    as = altsvc_create(srchost, dsthost, srcalpn, dstalpn, srcport, dstport);
+    if(as) {
+      as->expires = expires;
+      as->prio = prio;
+      as->persist = persist ? 1 : 0;
+      Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
+      asi->num++; /* one more entry */
+    }
+  }
+
+  return CURLE_OK;
+}
+
+/*
+ * Load alt-svc entries from the given file. The text based line-oriented file
+ * format is documented here:
+ * https://github.com/curl/curl/wiki/QUIC-implementation
+ *
+ * This function only returns error on major problems that prevents alt-svc
+ * handling to work completely. It will ignore individual syntactical errors
+ * etc.
+ */
+static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file)
+{
+  CURLcode result = CURLE_OK;
+  char *line = NULL;
+  FILE *fp = fopen(file, FOPEN_READTEXT);
+  if(fp) {
+    line = malloc(MAX_ALTSVC_LINE);
+    if(!line)
+      goto fail;
+    while(Curl_get_line(line, MAX_ALTSVC_LINE, fp)) {
+      char *lineptr = line;
+      while(*lineptr && ISBLANK(*lineptr))
+        lineptr++;
+      if(*lineptr == '#')
+        /* skip commented lines */
+        continue;
+
+      altsvc_add(asi, lineptr);
+    }
+    free(line); /* free the line buffer */
+    fclose(fp);
+  }
+  return result;
+
+  fail:
+  free(line);
+  fclose(fp);
+  return CURLE_OUT_OF_MEMORY;
+}
+
+/*
+ * Write this single altsvc entry to a single output line
+ */
+
+static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
+{
+  struct tm stamp;
+  CURLcode result = Curl_gmtime(as->expires, &stamp);
+  if(result)
+    return result;
+
+  fprintf(fp,
+          "%s %s %u "
+          "%s %s %u "
+          "\"%d%02d%02d "
+          "%02d:%02d:%02d\" "
+          "%u %d\n",
+          Curl_alpnid2str(as->srcalpnid), as->srchost, as->srcport,
+          Curl_alpnid2str(as->dstalpnid), as->dsthost, as->dstport,
+          stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
+          stamp.tm_hour, stamp.tm_min, stamp.tm_sec,
+          as->persist, as->prio);
+  return CURLE_OK;
+}
+
+/* ---- library-wide functions below ---- */
+
+/*
+ * Curl_altsvc_init() creates a new altsvc cache.
+ * It returns the new instance or NULL if something goes wrong.
+ */
+struct altsvcinfo *Curl_altsvc_init(void)
+{
+  struct altsvcinfo *asi = calloc(sizeof(struct altsvcinfo), 1);
+  if(!asi)
+    return NULL;
+  Curl_llist_init(&asi->list, NULL);
+
+  /* set default behavior */
+  asi->flags = CURLALTSVC_H1
+#ifdef USE_NGHTTP2
+    | CURLALTSVC_H2
+#endif
+#ifdef USE_HTTP3
+    | CURLALTSVC_H3
+#endif
+    ;
+  return asi;
+}
+
+/*
+ * Curl_altsvc_load() loads alt-svc from file.
+ */
+CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file)
+{
+  CURLcode result;
+  DEBUGASSERT(asi);
+  result = altsvc_load(asi, file);
+  return result;
+}
+
+/*
+ * Curl_altsvc_ctrl() passes on the external bitmask.
+ */
+CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl)
+{
+  DEBUGASSERT(asi);
+  if(!ctrl)
+    /* unexpected */
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+  asi->flags = ctrl;
+  return CURLE_OK;
+}
+
+/*
+ * Curl_altsvc_cleanup() frees an altsvc cache instance and all associated
+ * resources.
+ */
+void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
+{
+  struct curl_llist_element *e;
+  struct curl_llist_element *n;
+  if(altsvc) {
+    for(e = altsvc->list.head; e; e = n) {
+      struct altsvc *as = e->ptr;
+      n = e->next;
+      altsvc_free(as);
+    }
+    free(altsvc);
+  }
+}
+
+/*
+ * Curl_altsvc_save() writes the altsvc cache to a file.
+ */
+CURLcode Curl_altsvc_save(struct altsvcinfo *altsvc, const char *file)
+{
+  struct curl_llist_element *e;
+  struct curl_llist_element *n;
+  CURLcode result = CURLE_OK;
+  FILE *out;
+
+  if(!altsvc)
+    /* no cache activated */
+    return CURLE_OK;
+
+  if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file[0])
+    /* marked as read-only or zero length file name */
+    return CURLE_OK;
+  out = fopen(file, FOPEN_WRITETEXT);
+  if(!out)
+    return CURLE_WRITE_ERROR;
+  fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n"
+        "# This file was generated by libcurl! Edit at your own risk.\n",
+        out);
+  for(e = altsvc->list.head; e; e = n) {
+    struct altsvc *as = e->ptr;
+    n = e->next;
+    result = altsvc_out(as, out);
+    if(result)
+      break;
+  }
+  fclose(out);
+  return result;
+}
+
+static CURLcode getalnum(const char **ptr, char *alpnbuf, size_t buflen)
+{
+  size_t len;
+  const char *protop;
+  const char *p = *ptr;
+  while(*p && ISBLANK(*p))
+    p++;
+  protop = p;
+  while(*p && ISALNUM(*p))
+    p++;
+  len = p - protop;
+
+  if(!len || (len >= buflen))
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+  memcpy(alpnbuf, protop, len);
+  alpnbuf[len] = 0;
+  *ptr = p;
+  return CURLE_OK;
+}
+
+/* altsvc_flush() removes all alternatives for this source origin from the
+   list */
+static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
+                         const char *srchost, unsigned short srcport)
+{
+  struct curl_llist_element *e;
+  struct curl_llist_element *n;
+  for(e = asi->list.head; e; e = n) {
+    struct altsvc *as = e->ptr;
+    n = e->next;
+    if((srcalpnid == as->srcalpnid) &&
+       (srcport == as->srcport) &&
+       strcasecompare(srchost, as->srchost)) {
+      Curl_llist_remove(&asi->list, e, NULL);
+      altsvc_free(as);
+      asi->num--;
+    }
+  }
+}
+
+#ifdef DEBUGBUILD
+/* to play well with debug builds, we can *set* a fixed time this will
+   return */
+static time_t debugtime(void *unused)
+{
+  char *timestr = getenv("CURL_TIME");
+  (void)unused;
+  if(timestr) {
+    unsigned long val = strtol(timestr, NULL, 10);
+    return (time_t)val;
+  }
+  return time(NULL);
+}
+#define time(x) debugtime(x)
+#endif
+
+/*
+ * Curl_altsvc_parse() takes an incoming alt-svc response header and stores
+ * the data correctly in the cache.
+ *
+ * 'value' points to the header *value*. That's contents to the right of the
+ * header name.
+ */
+CURLcode Curl_altsvc_parse(struct Curl_easy *data,
+                           struct altsvcinfo *asi, const char *value,
+                           enum alpnid srcalpnid, const char *srchost,
+                           unsigned short srcport)
+{
+  const char *p = value;
+  size_t len;
+  enum alpnid dstalpnid = srcalpnid; /* the same by default */
+  char namebuf[MAX_ALTSVC_HOSTLEN] = "";
+  char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
+  struct altsvc *as;
+  unsigned short dstport = srcport; /* the same by default */
+  const char *semip;
+  time_t maxage = 24 * 3600; /* default is 24 hours */
+  bool persist = FALSE;
+  CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
+  if(result)
+    return result;
+
+  DEBUGASSERT(asi);
+
+  /* Flush all cached alternatives for this source origin, if any */
+  altsvc_flush(asi, srcalpnid, srchost, srcport);
+
+  /* "clear" is a magic keyword */
+  if(strcasecompare(alpnbuf, "clear")) {
+    return CURLE_OK;
+  }
+
+  /* The 'ma' and 'persist' flags are annoyingly meant for all alternatives
+     but are set after the list on the line. Scan for the semicolons and get
+     those fields first! */
+  semip = p;
+  do {
+    semip = strchr(semip, ';');
+    if(semip) {
+      char option[32];
+      unsigned long num;
+      char *end_ptr;
+      semip++; /* pass the semicolon */
+      result = getalnum(&semip, option, sizeof(option));
+      if(result)
+        break;
+      while(*semip && ISBLANK(*semip))
+        semip++;
+      if(*semip != '=')
+        continue;
+      semip++;
+      num = strtoul(semip, &end_ptr, 10);
+      if(num < ULONG_MAX) {
+        if(strcasecompare("ma", option))
+          maxage = num;
+        else if(strcasecompare("persist", option) && (num == 1))
+          persist = TRUE;
+      }
+      semip = end_ptr;
+    }
+  } while(semip);
+
+  do {
+    if(*p == '=') {
+      /* [protocol]="[host][:port]" */
+      dstalpnid = alpn2alpnid(alpnbuf);
+      if(!dstalpnid) {
+        infof(data, "Unknown alt-svc protocol \"%s\", ignoring...\n", alpnbuf);
+        return CURLE_OK;
+      }
+      p++;
+      if(*p == '\"') {
+        const char *dsthost;
+        p++;
+        if(*p != ':') {
+          /* host name starts here */
+          const char *hostp = p;
+          while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
+            p++;
+          len = p - hostp;
+          if(!len || (len >= MAX_ALTSVC_HOSTLEN))
+            return CURLE_BAD_FUNCTION_ARGUMENT;
+          memcpy(namebuf, hostp, len);
+          namebuf[len] = 0;
+          dsthost = namebuf;
+        }
+        else {
+          /* no destination name, use source host */
+          dsthost = srchost;
+        }
+        if(*p == ':') {
+          /* a port number */
+          char *end_ptr;
+          unsigned long port = strtoul(++p, &end_ptr, 10);
+          if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
+            infof(data, "Unknown alt-svc port number, ignoring...\n");
+            return CURLE_OK;
+          }
+          p = end_ptr;
+          dstport = curlx_ultous(port);
+        }
+        if(*p++ != '\"')
+          return CURLE_BAD_FUNCTION_ARGUMENT;
+        as = altsvc_createid(srchost, dsthost,
+                             srcalpnid, dstalpnid,
+                             srcport, dstport);
+        if(as) {
+          /* The expires time also needs to take the Age: value (if any) into
+             account. [See RFC 7838 section 3.1] */
+          as->expires = maxage + time(NULL);
+          as->persist = persist;
+          Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
+          asi->num++; /* one more entry */
+          infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
+                Curl_alpnid2str(dstalpnid));
+        }
+      }
+      /* after the double quote there can be a comma if there's another
+         string or a semicolon if no more */
+      if(*p == ',') {
+        /* comma means another alternative is presented */
+        p++;
+        result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
+        if(result)
+          /* failed to parse, but since we already did at least one host we
+             return OK */
+          return CURLE_OK;
+      }
+    }
+  } while(*p && (*p != ';') && (*p != '\n') && (*p != '\r'));
+
+  return CURLE_OK;
+}
+
+/*
+ * Return TRUE on a match
+ */
+bool Curl_altsvc_lookup(struct altsvcinfo *asi,
+                        enum alpnid srcalpnid, const char *srchost,
+                        int srcport,
+                        enum alpnid *dstalpnid, const char **dsthost,
+                        int *dstport)
+{
+  struct curl_llist_element *e;
+  struct curl_llist_element *n;
+  time_t now = time(NULL);
+  DEBUGASSERT(asi);
+  DEBUGASSERT(srchost);
+  DEBUGASSERT(dsthost);
+
+  for(e = asi->list.head; e; e = n) {
+    struct altsvc *as = e->ptr;
+    n = e->next;
+    if(as->expires < now) {
+      /* an expired entry, remove */
+      altsvc_free(as);
+      continue;
+    }
+    if((as->srcalpnid == srcalpnid) &&
+       strcasecompare(as->srchost, srchost) &&
+       as->srcport == srcport) {
+      /* match */
+      *dstalpnid = as->dstalpnid;
+      *dsthost = as->dsthost;
+      *dstport = as->dstport;
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */

+ 77 - 0
Utilities/cmcurl/lib/altsvc.h

@@ -0,0 +1,77 @@
+#ifndef HEADER_CURL_ALTSVC_H
+#define HEADER_CURL_ALTSVC_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2019, Daniel Stenberg, <[email protected]>, 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"
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC)
+#include <curl/curl.h>
+#include "llist.h"
+
+enum alpnid {
+  ALPN_none,
+  ALPN_h1,
+  ALPN_h2,
+  ALPN_h2c,
+  ALPN_h3
+};
+
+struct altsvc {
+  char *srchost;
+  char *dsthost;
+  unsigned short srcport;
+  unsigned short dstport;
+  enum alpnid srcalpnid;
+  enum alpnid dstalpnid;
+  time_t expires;
+  bool persist;
+  int prio;
+  struct curl_llist_element node;
+};
+
+struct altsvcinfo {
+  char *filename;
+  struct curl_llist list; /* list of entries */
+  size_t num; /* number of alt-svc entries */
+  long flags; /* the publicly set bitmask */
+};
+
+const char *Curl_alpnid2str(enum alpnid id);
+struct altsvcinfo *Curl_altsvc_init(void);
+CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file);
+CURLcode Curl_altsvc_save(struct altsvcinfo *asi, const char *file);
+CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl);
+void Curl_altsvc_cleanup(struct altsvcinfo *altsvc);
+CURLcode Curl_altsvc_parse(struct Curl_easy *data,
+                           struct altsvcinfo *altsvc, const char *value,
+                           enum alpnid srcalpn, const char *srchost,
+                           unsigned short srcport);
+bool Curl_altsvc_lookup(struct altsvcinfo *asi,
+                        enum alpnid srcalpnid, const char *srchost,
+                        int srcport,
+                        enum alpnid *dstalpnid, const char **dsthost,
+                        int *dstport);
+#else
+/* disabled */
+#define Curl_altsvc_save(a,b)
+#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */
+#endif /* HEADER_CURL_ALTSVC_H */

+ 25 - 7
Utilities/cmcurl/lib/amigaos.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -22,17 +22,26 @@
 
 
 #include "curl_setup.h"
 #include "curl_setup.h"
 
 
-#if defined(__AMIGA__) && !defined(__ixemul__)
-
-#include <amitcp/socketbasetags.h>
+#ifdef __AMIGA__
+#  include "amigaos.h"
+#  if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL)
+#    include <amitcp/socketbasetags.h>
+#  endif
+#  ifdef __libnix__
+#    include <stabs.h>
+#  endif
+#endif
 
 
-#include "amigaos.h"
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
 
 
+#ifdef __AMIGA__
+#if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL)
 struct Library *SocketBase = NULL;
 struct Library *SocketBase = NULL;
 extern int errno, h_errno;
 extern int errno, h_errno;
 
 
 #ifdef __libnix__
 #ifdef __libnix__
-#include <stabs.h>
 void __request(const char *msg);
 void __request(const char *msg);
 #else
 #else
 # define __request(msg)       Printf(msg "\n\a")
 # define __request(msg)       Printf(msg "\n\a")
@@ -74,4 +83,13 @@ bool Curl_amiga_init()
 ADD2EXIT(Curl_amiga_cleanup, -50);
 ADD2EXIT(Curl_amiga_cleanup, -50);
 #endif
 #endif
 
 
-#endif /* __AMIGA__ && ! __ixemul__ */
+#endif /* HAVE_PROTO_BSDSOCKET_H */
+
+#ifdef USE_AMISSL
+void Curl_amiga_X509_free(X509 *a)
+{
+  X509_free(a);
+}
+#endif /* USE_AMISSL */
+#endif /* __AMIGA__ */
+

+ 8 - 2
Utilities/cmcurl/lib/amigaos.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -23,7 +23,7 @@
  ***************************************************************************/
  ***************************************************************************/
 #include "curl_setup.h"
 #include "curl_setup.h"
 
 
-#if defined(__AMIGA__) && !defined(__ixemul__)
+#if defined(__AMIGA__) && defined(HAVE_BSDSOCKET_H) && !defined(USE_AMISSL)
 
 
 bool Curl_amiga_init();
 bool Curl_amiga_init();
 void Curl_amiga_cleanup();
 void Curl_amiga_cleanup();
@@ -35,4 +35,10 @@ void Curl_amiga_cleanup();
 
 
 #endif
 #endif
 
 
+#ifdef USE_AMISSL
+#include <openssl/x509v3.h>
+void Curl_amiga_X509_free(X509 *a);
+#endif /* USE_AMISSL */
+
 #endif /* HEADER_CURL_AMIGAOS_H */
 #endif /* HEADER_CURL_AMIGAOS_H */
+

+ 140 - 17
Utilities/cmcurl/lib/asyn-ares.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -68,7 +68,7 @@
 #include "progress.h"
 #include "progress.h"
 
 
 #  if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
 #  if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
-     (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
+     (defined(WIN32) || defined(__SYMBIAN32__))
 #    define CARES_STATICLIB
 #    define CARES_STATICLIB
 #  endif
 #  endif
 #  include <ares.h>
 #  include <ares.h>
@@ -89,8 +89,20 @@ struct ResolverResults {
   int num_pending; /* number of ares_gethostbyname() requests */
   int num_pending; /* number of ares_gethostbyname() requests */
   Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */
   Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */
   int last_status;
   int last_status;
+  struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
 };
 };
 
 
+/* How long we are willing to wait for additional parallel responses after
+   obtaining a "definitive" one.
+
+   This is intended to equal the c-ares default timeout.  cURL always uses that
+   default value.  Unfortunately, c-ares doesn't expose its default timeout in
+   its API, but it is officially documented as 5 seconds.
+
+   See query_completed_cb() for an explanation of how this is used.
+ */
+#define HAPPY_EYEBALLS_DNS_TIMEOUT 5000
+
 /*
 /*
  * Curl_resolver_global_init() - the generic low-level asynchronous name
  * Curl_resolver_global_init() - the generic low-level asynchronous name
  * resolve API.  Called from curl_global_init() to initialize global resolver
  * resolve API.  Called from curl_global_init() to initialize global resolver
@@ -119,6 +131,17 @@ void Curl_resolver_global_cleanup(void)
 #endif
 #endif
 }
 }
 
 
+
+static void Curl_ares_sock_state_cb(void *data, ares_socket_t socket_fd,
+                                    int readable, int writable)
+{
+  struct Curl_easy *easy = data;
+  if(!readable && !writable) {
+    DEBUGASSERT(easy);
+    Curl_multi_closed(easy, socket_fd);
+  }
+}
+
 /*
 /*
  * Curl_resolver_init()
  * Curl_resolver_init()
  *
  *
@@ -126,9 +149,14 @@ void Curl_resolver_global_cleanup(void)
  * URL-state specific environment ('resolver' member of the UrlState
  * URL-state specific environment ('resolver' member of the UrlState
  * structure).  Fills the passed pointer by the initialized ares_channel.
  * structure).  Fills the passed pointer by the initialized ares_channel.
  */
  */
-CURLcode Curl_resolver_init(void **resolver)
+CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
 {
 {
-  int status = ares_init((ares_channel*)resolver);
+  int status;
+  struct ares_options options;
+  int optmask = ARES_OPT_SOCK_STATE_CB;
+  options.sock_state_cb = Curl_ares_sock_state_cb;
+  options.sock_state_cb_data = easy;
+  status = ares_init_options((ares_channel*)resolver, &options, optmask);
   if(status != ARES_SUCCESS) {
   if(status != ARES_SUCCESS) {
     if(status == ARES_ENOMEM)
     if(status == ARES_ENOMEM)
       return CURLE_OUT_OF_MEMORY;
       return CURLE_OUT_OF_MEMORY;
@@ -159,12 +187,15 @@ void Curl_resolver_cleanup(void *resolver)
  * environment ('resolver' member of the UrlState structure).  Duplicates the
  * environment ('resolver' member of the UrlState structure).  Duplicates the
  * 'from' ares channel and passes the resulting channel to the 'to' pointer.
  * 'from' ares channel and passes the resulting channel to the 'to' pointer.
  */
  */
-int Curl_resolver_duphandle(void **to, void *from)
+CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
 {
 {
-  /* Clone the ares channel for the new handle */
-  if(ARES_SUCCESS != ares_dup((ares_channel*)to, (ares_channel)from))
-    return CURLE_FAILED_INIT;
-  return CURLE_OK;
+  (void)from;
+  /*
+   * it would be better to call ares_dup instead, but right now
+   * it is not possible to set 'sock_state_cb_data' outside of
+   * ares_init_options
+   */
+  return Curl_resolver_init(easy, to);
 }
 }
 
 
 static void destroy_async_data(struct Curl_async *async);
 static void destroy_async_data(struct Curl_async *async);
@@ -179,6 +210,17 @@ void Curl_resolver_cancel(struct connectdata *conn)
   destroy_async_data(&conn->async);
   destroy_async_data(&conn->async);
 }
 }
 
 
+/*
+ * We're equivalent to Curl_resolver_cancel() for the c-ares resolver.  We
+ * never block.
+ */
+void Curl_resolver_kill(struct connectdata *conn)
+{
+  /* We don't need to check the resolver state because we can be called safely
+     at any time and we always do the same thing. */
+  Curl_resolver_cancel(conn);
+}
+
 /*
 /*
  * destroy_async_data() cleans up async resolver data.
  * destroy_async_data() cleans up async resolver data.
  */
  */
@@ -289,9 +331,9 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
     /* move through the descriptors and ask for processing on them */
     /* move through the descriptors and ask for processing on them */
     for(i = 0; i < num; i++)
     for(i = 0; i < num; i++)
       ares_process_fd((ares_channel)data->state.resolver,
       ares_process_fd((ares_channel)data->state.resolver,
-                      pfd[i].revents & (POLLRDNORM|POLLIN)?
+                      (pfd[i].revents & (POLLRDNORM|POLLIN))?
                       pfd[i].fd:ARES_SOCKET_BAD,
                       pfd[i].fd:ARES_SOCKET_BAD,
-                      pfd[i].revents & (POLLWRNORM|POLLOUT)?
+                      (pfd[i].revents & (POLLWRNORM|POLLOUT))?
                       pfd[i].fd:ARES_SOCKET_BAD);
                       pfd[i].fd:ARES_SOCKET_BAD);
   }
   }
   return nfds;
   return nfds;
@@ -317,6 +359,29 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
 
 
   waitperform(conn, 0);
   waitperform(conn, 0);
 
 
+  /* Now that we've checked for any last minute results above, see if there are
+     any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer
+     expires. */
+  if(res
+     && res->num_pending
+     /* This is only set to non-zero if the timer was started. */
+     && (res->happy_eyeballs_dns_time.tv_sec
+         || res->happy_eyeballs_dns_time.tv_usec)
+     && (Curl_timediff(Curl_now(), res->happy_eyeballs_dns_time)
+         >= HAPPY_EYEBALLS_DNS_TIMEOUT)) {
+    /* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer
+       running. */
+    memset(
+      &res->happy_eyeballs_dns_time, 0, sizeof(res->happy_eyeballs_dns_time));
+
+    /* Cancel the raw c-ares request, which will fire query_completed_cb() with
+       ARES_ECANCELLED synchronously for all pending responses.  This will
+       leave us with res->num_pending == 0, which is perfect for the next
+       block. */
+    ares_cancel((ares_channel)data->state.resolver);
+    DEBUGASSERT(res->num_pending == 0);
+  }
+
   if(res && !res->num_pending) {
   if(res && !res->num_pending) {
     if(dns) {
     if(dns) {
       (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
       (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
@@ -342,13 +407,13 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
 /*
 /*
  * Curl_resolver_wait_resolv()
  * Curl_resolver_wait_resolv()
  *
  *
- * waits for a resolve to finish. This function should be avoided since using
+ * Waits for a resolve to finish. This function should be avoided since using
  * this risk getting the multi interface to "hang".
  * this risk getting the multi interface to "hang".
  *
  *
  * If 'entry' is non-NULL, make it point to the resolved dns entry
  * If 'entry' is non-NULL, make it point to the resolved dns entry
  *
  *
- * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
- * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
  */
  */
 CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
 CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                    struct Curl_dns_entry **entry)
                                    struct Curl_dns_entry **entry)
@@ -425,9 +490,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
 
 
   if(result)
   if(result)
     /* close the connection, since we can't return failure here without
     /* close the connection, since we can't return failure here without
-       cleaning up this connection properly.
-       TODO: remove this action from here, it is not a name resolver decision.
-    */
+       cleaning up this connection properly. */
     connclose(conn, "c-ares resolve failed");
     connclose(conn, "c-ares resolve failed");
 
 
   return result;
   return result;
@@ -487,6 +550,66 @@ static void query_completed_cb(void *arg,  /* (struct connectdata *) */
     /* A successful result overwrites any previous error */
     /* A successful result overwrites any previous error */
     if(res->last_status != ARES_SUCCESS)
     if(res->last_status != ARES_SUCCESS)
       res->last_status = status;
       res->last_status = status;
+
+    /* If there are responses still pending, we presume they must be the
+       complementary IPv4 or IPv6 lookups that we started in parallel in
+       Curl_resolver_getaddrinfo() (for Happy Eyeballs).  If we've got a
+       "definitive" response from one of a set of parallel queries, we need to
+       think about how long we're willing to wait for more responses. */
+    if(res->num_pending
+       /* Only these c-ares status values count as "definitive" for these
+          purposes.  For example, ARES_ENODATA is what we expect when there is
+          no IPv6 entry for a domain name, and that's not a reason to get more
+          aggressive in our timeouts for the other response.  Other errors are
+          either a result of bad input (which should affect all parallel
+          requests), local or network conditions, non-definitive server
+          responses, or us cancelling the request. */
+       && (status == ARES_SUCCESS || status == ARES_ENOTFOUND)) {
+      /* Right now, there can only be up to two parallel queries, so don't
+         bother handling any other cases. */
+      DEBUGASSERT(res->num_pending == 1);
+
+      /* It's possible that one of these parallel queries could succeed
+         quickly, but the other could always fail or timeout (when we're
+         talking to a pool of DNS servers that can only successfully resolve
+         IPv4 address, for example).
+
+         It's also possible that the other request could always just take
+         longer because it needs more time or only the second DNS server can
+         fulfill it successfully.  But, to align with the philosophy of Happy
+         Eyeballs, we don't want to wait _too_ long or users will think
+         requests are slow when IPv6 lookups don't actually work (but IPv4 ones
+         do).
+
+         So, now that we have a usable answer (some IPv4 addresses, some IPv6
+         addresses, or "no such domain"), we start a timeout for the remaining
+         pending responses.  Even though it is typical that this resolved
+         request came back quickly, that needn't be the case.  It might be that
+         this completing request didn't get a result from the first DNS server
+         or even the first round of the whole DNS server pool.  So it could
+         already be quite some time after we issued the DNS queries in the
+         first place.  Without modifying c-ares, we can't know exactly where in
+         its retry cycle we are.  We could guess based on how much time has
+         gone by, but it doesn't really matter.  Happy Eyeballs tells us that,
+         given usable information in hand, we simply don't want to wait "too
+         much longer" after we get a result.
+
+         We simply wait an additional amount of time equal to the default
+         c-ares query timeout.  That is enough time for a typical parallel
+         response to arrive without being "too long".  Even on a network
+         where one of the two types of queries is failing or timing out
+         constantly, this will usually mean we wait a total of the default
+         c-ares timeout (5 seconds) plus the round trip time for the successful
+         request, which seems bearable.  The downside is that c-ares might race
+         with us to issue one more retry just before we give up, but it seems
+         better to "waste" that request instead of trying to guess the perfect
+         timeout to prevent it.  After all, we don't even know where in the
+         c-ares retry cycle each request is.
+      */
+      res->happy_eyeballs_dns_time = Curl_now();
+      Curl_expire(
+        conn->data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS);
+    }
   }
   }
 }
 }
 
 

+ 50 - 20
Utilities/cmcurl/lib/asyn-thread.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -108,8 +108,9 @@ void Curl_resolver_global_cleanup(void)
  * URL-state specific environment ('resolver' member of the UrlState
  * URL-state specific environment ('resolver' member of the UrlState
  * structure).
  * structure).
  */
  */
-CURLcode Curl_resolver_init(void **resolver)
+CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver)
 {
 {
+  (void)easy;
   *resolver = calloc(1, sizeof(struct resdata));
   *resolver = calloc(1, sizeof(struct resdata));
   if(!*resolver)
   if(!*resolver)
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;
@@ -132,10 +133,10 @@ void Curl_resolver_cleanup(void *resolver)
  * Called from curl_easy_duphandle() to duplicate resolver URL state-specific
  * Called from curl_easy_duphandle() to duplicate resolver URL state-specific
  * environment ('resolver' member of the UrlState structure).
  * environment ('resolver' member of the UrlState structure).
  */
  */
-int Curl_resolver_duphandle(void **to, void *from)
+CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, void *from)
 {
 {
   (void)from;
   (void)from;
-  return Curl_resolver_init(to);
+  return Curl_resolver_init(easy, to);
 }
 }
 
 
 static void destroy_async_data(struct Curl_async *);
 static void destroy_async_data(struct Curl_async *);
@@ -276,7 +277,7 @@ static unsigned int CURL_STDCALL getaddrinfo_thread(void *arg)
   char service[12];
   char service[12];
   int rc;
   int rc;
 
 
-  snprintf(service, sizeof(service), "%d", tsd->port);
+  msnprintf(service, sizeof(service), "%d", tsd->port);
 
 
   rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
   rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
 
 
@@ -460,23 +461,15 @@ static CURLcode resolver_error(struct connectdata *conn)
   return result;
   return result;
 }
 }
 
 
-/*
- * Curl_resolver_wait_resolv()
- *
- * waits for a resolve to finish. This function should be avoided since using
- * this risk getting the multi interface to "hang".
- *
- * If 'entry' is non-NULL, make it point to the resolved dns entry
- *
- * This is the version for resolves-in-a-thread.
- */
-CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
-                                   struct Curl_dns_entry **entry)
+static CURLcode thread_wait_resolv(struct connectdata *conn,
+                                   struct Curl_dns_entry **entry,
+                                   bool report)
 {
 {
   struct thread_data   *td = (struct thread_data*) conn->async.os_specific;
   struct thread_data   *td = (struct thread_data*) conn->async.os_specific;
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
 
 
   DEBUGASSERT(conn && td);
   DEBUGASSERT(conn && td);
+  DEBUGASSERT(td->thread_hnd != curl_thread_t_null);
 
 
   /* wait for the thread to resolve the name */
   /* wait for the thread to resolve the name */
   if(Curl_thread_join(&td->thread_hnd)) {
   if(Curl_thread_join(&td->thread_hnd)) {
@@ -491,18 +484,55 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
   if(entry)
   if(entry)
     *entry = conn->async.dns;
     *entry = conn->async.dns;
 
 
-  if(!conn->async.dns)
+  if(!conn->async.dns && report)
     /* a name was not resolved, report error */
     /* a name was not resolved, report error */
     result = resolver_error(conn);
     result = resolver_error(conn);
 
 
   destroy_async_data(&conn->async);
   destroy_async_data(&conn->async);
 
 
-  if(!conn->async.dns)
+  if(!conn->async.dns && report)
     connclose(conn, "asynch resolve failed");
     connclose(conn, "asynch resolve failed");
 
 
   return result;
   return result;
 }
 }
 
 
+
+/*
+ * Until we gain a way to signal the resolver threads to stop early, we must
+ * simply wait for them and ignore their results.
+ */
+void Curl_resolver_kill(struct connectdata *conn)
+{
+  struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+
+  /* If we're still resolving, we must wait for the threads to fully clean up,
+     unfortunately.  Otherwise, we can simply cancel to clean up any resolver
+     data. */
+  if(td && td->thread_hnd != curl_thread_t_null)
+    (void)thread_wait_resolv(conn, NULL, FALSE);
+  else
+    Curl_resolver_cancel(conn);
+}
+
+/*
+ * Curl_resolver_wait_resolv()
+ *
+ * Waits for a resolve to finish. This function should be avoided since using
+ * this risk getting the multi interface to "hang".
+ *
+ * If 'entry' is non-NULL, make it point to the resolved dns entry
+ *
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
+ *
+ * This is the version for resolves-in-a-thread.
+ */
+CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
+                                   struct Curl_dns_entry **entry)
+{
+  return thread_wait_resolv(conn, entry, TRUE);
+}
+
 /*
 /*
  * Curl_resolver_is_resolved() is called repeatedly to check if a previous
  * Curl_resolver_is_resolved() is called repeatedly to check if a previous
  * name resolve request has completed. It should also make sure to time-out if
  * name resolve request has completed. It should also make sure to time-out if
@@ -678,7 +708,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
   hints.ai_family = pf;
   hints.ai_family = pf;
   hints.ai_socktype = conn->socktype;
   hints.ai_socktype = conn->socktype;
 
 
-  snprintf(sbuf, sizeof(sbuf), "%d", port);
+  msnprintf(sbuf, sizeof(sbuf), "%d", port);
 
 
   reslv->start = Curl_now();
   reslv->start = Curl_now();
   /* fire up a new resolver thread! */
   /* fire up a new resolver thread! */

+ 26 - 10
Utilities/cmcurl/lib/asyn.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -60,7 +60,7 @@ void Curl_resolver_global_cleanup(void);
  * Returning anything else than CURLE_OK fails curl_easy_init() with the
  * Returning anything else than CURLE_OK fails curl_easy_init() with the
  * correspondent code.
  * correspondent code.
  */
  */
-CURLcode Curl_resolver_init(void **resolver);
+CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver);
 
 
 /*
 /*
  * Curl_resolver_cleanup()
  * Curl_resolver_cleanup()
@@ -79,17 +79,33 @@ void Curl_resolver_cleanup(void *resolver);
  * pointer.  Returning anything else than CURLE_OK causes failed
  * pointer.  Returning anything else than CURLE_OK causes failed
  * curl_easy_duphandle() call.
  * curl_easy_duphandle() call.
  */
  */
-int Curl_resolver_duphandle(void **to, void *from);
+CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to,
+                                 void *from);
 
 
 /*
 /*
  * Curl_resolver_cancel().
  * Curl_resolver_cancel().
  *
  *
  * It is called from inside other functions to cancel currently performing
  * It is called from inside other functions to cancel currently performing
  * resolver request. Should also free any temporary resources allocated to
  * resolver request. Should also free any temporary resources allocated to
- * perform a request.
+ * perform a request.  This never waits for resolver threads to complete.
+ *
+ * It is safe to call this when conn is in any state.
  */
  */
 void Curl_resolver_cancel(struct connectdata *conn);
 void Curl_resolver_cancel(struct connectdata *conn);
 
 
+/*
+ * Curl_resolver_kill().
+ *
+ * This acts like Curl_resolver_cancel() except it will block until any threads
+ * associated with the resolver are complete.  This never blocks for resolvers
+ * that do not use threads.  This is intended to be the "last chance" function
+ * that cleans up an in-progress resolver completely (before its owner is about
+ * to die).
+ *
+ * It is safe to call this when conn is in any state.
+ */
+void Curl_resolver_kill(struct connectdata *conn);
+
 /* Curl_resolver_getsock()
 /* Curl_resolver_getsock()
  *
  *
  * This function is called from the multi_getsock() function.  'sock' is a
  * This function is called from the multi_getsock() function.  'sock' is a
@@ -116,14 +132,13 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
 /*
 /*
  * Curl_resolver_wait_resolv()
  * Curl_resolver_wait_resolv()
  *
  *
- * waits for a resolve to finish. This function should be avoided since using
+ * Waits for a resolve to finish. This function should be avoided since using
  * this risk getting the multi interface to "hang".
  * this risk getting the multi interface to "hang".
  *
  *
  * If 'entry' is non-NULL, make it point to the resolved dns entry
  * If 'entry' is non-NULL, make it point to the resolved dns entry
  *
  *
- * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
- * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
-
+ * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
+ * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
  */
  */
 CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
 CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                    struct Curl_dns_entry **dnsentry);
                                    struct Curl_dns_entry **dnsentry);
@@ -147,11 +162,12 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
 #ifndef CURLRES_ASYNCH
 #ifndef CURLRES_ASYNCH
 /* convert these functions if an asynch resolver isn't used */
 /* convert these functions if an asynch resolver isn't used */
 #define Curl_resolver_cancel(x) Curl_nop_stmt
 #define Curl_resolver_cancel(x) Curl_nop_stmt
+#define Curl_resolver_kill(x) Curl_nop_stmt
 #define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
 #define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
 #define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
 #define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
 #define Curl_resolver_getsock(x,y,z) 0
 #define Curl_resolver_getsock(x,y,z) 0
-#define Curl_resolver_duphandle(x,y) CURLE_OK
-#define Curl_resolver_init(x) CURLE_OK
+#define Curl_resolver_duphandle(x,y,z) CURLE_OK
+#define Curl_resolver_init(x,y) CURLE_OK
 #define Curl_resolver_global_init() CURLE_OK
 #define Curl_resolver_global_init() CURLE_OK
 #define Curl_resolver_global_cleanup() Curl_nop_stmt
 #define Curl_resolver_global_cleanup() Curl_nop_stmt
 #define Curl_resolver_cleanup(x) Curl_nop_stmt
 #define Curl_resolver_cleanup(x) Curl_nop_stmt

+ 20 - 13
Utilities/cmcurl/lib/base64.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -23,6 +23,11 @@
 /* Base64 encoding/decoding */
 /* Base64 encoding/decoding */
 
 
 #include "curl_setup.h"
 #include "curl_setup.h"
+
+#if !defined(CURL_DISABLE_HTTP_AUTH) || defined(USE_LIBSSH2) || \
+  defined(USE_LIBSSH) || !defined(CURL_DISABLE_LDAP) || \
+  !defined(CURL_DISABLE_DOH) || defined(USE_SSL)
+
 #include "urldata.h" /* for the Curl_easy definition */
 #include "urldata.h" /* for the Curl_easy definition */
 #include "warnless.h"
 #include "warnless.h"
 #include "curl_base64.h"
 #include "curl_base64.h"
@@ -233,24 +238,24 @@ static CURLcode base64_encode(const char *table64,
 
 
     switch(inputparts) {
     switch(inputparts) {
     case 1: /* only one byte read */
     case 1: /* only one byte read */
-      snprintf(output, 5, "%c%c==",
-               table64[obuf[0]],
-               table64[obuf[1]]);
+      msnprintf(output, 5, "%c%c==",
+                table64[obuf[0]],
+                table64[obuf[1]]);
       break;
       break;
 
 
     case 2: /* two bytes read */
     case 2: /* two bytes read */
-      snprintf(output, 5, "%c%c%c=",
-               table64[obuf[0]],
-               table64[obuf[1]],
-               table64[obuf[2]]);
+      msnprintf(output, 5, "%c%c%c=",
+                table64[obuf[0]],
+                table64[obuf[1]],
+                table64[obuf[2]]);
       break;
       break;
 
 
     default:
     default:
-      snprintf(output, 5, "%c%c%c%c",
-               table64[obuf[0]],
-               table64[obuf[1]],
-               table64[obuf[2]],
-               table64[obuf[3]]);
+      msnprintf(output, 5, "%c%c%c%c",
+                table64[obuf[0]],
+                table64[obuf[1]],
+                table64[obuf[2]],
+                table64[obuf[3]]);
       break;
       break;
     }
     }
     output += 4;
     output += 4;
@@ -317,3 +322,5 @@ CURLcode Curl_base64url_encode(struct Curl_easy *data,
 {
 {
   return base64_encode(base64url, data, inputbuff, insize, outptr, outlen);
   return base64_encode(base64url, data, inputbuff, insize, outptr, outlen);
 }
 }
+
+#endif /* no users so disabled */

+ 22 - 16
Utilities/cmcurl/lib/conncache.c

@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
  * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <[email protected]>
  * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <[email protected]>
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -175,12 +175,12 @@ static void hashkey(struct connectdata *conn, char *buf,
   DEBUGASSERT(len > 32);
   DEBUGASSERT(len > 32);
 
 
   /* put the number first so that the hostname gets cut off if too long */
   /* put the number first so that the hostname gets cut off if too long */
-  snprintf(buf, len, "%ld%s", conn->port, hostname);
+  msnprintf(buf, len, "%ld%s", conn->port, hostname);
 }
 }
 
 
-void Curl_conncache_unlock(struct connectdata *conn)
+void Curl_conncache_unlock(struct Curl_easy *data)
 {
 {
-  CONN_UNLOCK(conn->data);
+  CONN_UNLOCK(data);
 }
 }
 
 
 /* Returns number of connections currently held in the connection cache.
 /* Returns number of connections currently held in the connection cache.
@@ -302,9 +302,14 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
   return result;
   return result;
 }
 }
 
 
-void Curl_conncache_remove_conn(struct connectdata *conn, bool lock)
+/*
+ * Removes the connectdata object from the connection cache *and* clears the
+ * ->data pointer association. Pass TRUE/FALSE in the 'lock' argument
+ * depending on if the parent function already holds the lock or not.
+ */
+void Curl_conncache_remove_conn(struct Curl_easy *data,
+                                struct connectdata *conn, bool lock)
 {
 {
-  struct Curl_easy *data = conn->data;
   struct connectbundle *bundle = conn->bundle;
   struct connectbundle *bundle = conn->bundle;
   struct conncache *connc = data->state.conn_cache;
   struct conncache *connc = data->state.conn_cache;
 
 
@@ -323,6 +328,7 @@ void Curl_conncache_remove_conn(struct connectdata *conn, bool lock)
       DEBUGF(infof(data, "The cache now contains %zu members\n",
       DEBUGF(infof(data, "The cache now contains %zu members\n",
                    connc->num_conn));
                    connc->num_conn));
     }
     }
+    conn->data = NULL; /* clear the association */
     if(lock) {
     if(lock) {
       CONN_UNLOCK(data);
       CONN_UNLOCK(data);
     }
     }
@@ -386,8 +392,8 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
    NOTE: no locking is done here as this is presumably only done when cleaning
    NOTE: no locking is done here as this is presumably only done when cleaning
    up a cache!
    up a cache!
 */
 */
-struct connectdata *
-Curl_conncache_find_first_connection(struct conncache *connc)
+static struct connectdata *
+conncache_find_first_connection(struct conncache *connc)
 {
 {
   struct curl_hash_iterator iter;
   struct curl_hash_iterator iter;
   struct curl_hash_element *he;
   struct curl_hash_element *he;
@@ -427,6 +433,8 @@ bool Curl_conncache_return_conn(struct connectdata *conn)
     data->multi->maxconnects;
     data->multi->maxconnects;
   struct connectdata *conn_candidate = NULL;
   struct connectdata *conn_candidate = NULL;
 
 
+  conn->data = NULL; /* no owner anymore */
+  conn->lastused = Curl_now(); /* it was used up until now */
   if(maxconnects > 0 &&
   if(maxconnects > 0 &&
      Curl_conncache_size(data) > maxconnects) {
      Curl_conncache_size(data) > maxconnects) {
     infof(data, "Connection cache is full, closing the oldest one.\n");
     infof(data, "Connection cache is full, closing the oldest one.\n");
@@ -470,9 +478,9 @@ Curl_conncache_extract_bundle(struct Curl_easy *data,
   while(curr) {
   while(curr) {
     conn = curr->ptr;
     conn = curr->ptr;
 
 
-    if(!CONN_INUSE(conn)) {
+    if(!CONN_INUSE(conn) && !conn->data) {
       /* Set higher score for the age passed since the connection was used */
       /* Set higher score for the age passed since the connection was used */
-      score = Curl_timediff(now, conn->now);
+      score = Curl_timediff(now, conn->lastused);
 
 
       if(score > highscore) {
       if(score > highscore) {
         highscore = score;
         highscore = score;
@@ -528,9 +536,9 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
     while(curr) {
     while(curr) {
       conn = curr->ptr;
       conn = curr->ptr;
 
 
-      if(!CONN_INUSE(conn)) {
+      if(!CONN_INUSE(conn) && !conn->data) {
         /* Set higher score for the age passed since the connection was used */
         /* Set higher score for the age passed since the connection was used */
-        score = Curl_timediff(now, conn->now);
+        score = Curl_timediff(now, conn->lastused);
 
 
         if(score > highscore) {
         if(score > highscore) {
           highscore = score;
           highscore = score;
@@ -560,20 +568,18 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
 {
 {
   struct connectdata *conn;
   struct connectdata *conn;
 
 
-  conn = Curl_conncache_find_first_connection(connc);
+  conn = conncache_find_first_connection(connc);
   while(conn) {
   while(conn) {
     SIGPIPE_VARIABLE(pipe_st);
     SIGPIPE_VARIABLE(pipe_st);
     conn->data = connc->closure_handle;
     conn->data = connc->closure_handle;
 
 
     sigpipe_ignore(conn->data, &pipe_st);
     sigpipe_ignore(conn->data, &pipe_st);
-    conn->data->easy_conn = NULL; /* clear the easy handle's connection
-                                     pointer */
     /* This will remove the connection from the cache */
     /* This will remove the connection from the cache */
     connclose(conn, "kill all");
     connclose(conn, "kill all");
     (void)Curl_disconnect(connc->closure_handle, conn, FALSE);
     (void)Curl_disconnect(connc->closure_handle, conn, FALSE);
     sigpipe_restore(&pipe_st);
     sigpipe_restore(&pipe_st);
 
 
-    conn = Curl_conncache_find_first_connection(connc);
+    conn = conncache_find_first_connection(connc);
   }
   }
 
 
   if(connc->closure_handle) {
   if(connc->closure_handle) {

+ 4 - 4
Utilities/cmcurl/lib/conncache.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 2015 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2015 - 2019, Daniel Stenberg, <[email protected]>, et al.
  * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <[email protected]>
  * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <[email protected]>
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
@@ -40,7 +40,6 @@ struct conncache {
 
 
 #define BUNDLE_NO_MULTIUSE -1
 #define BUNDLE_NO_MULTIUSE -1
 #define BUNDLE_UNKNOWN     0  /* initial value */
 #define BUNDLE_UNKNOWN     0  /* initial value */
-#define BUNDLE_PIPELINING  1
 #define BUNDLE_MULTIPLEX   2
 #define BUNDLE_MULTIPLEX   2
 
 
 struct connectbundle {
 struct connectbundle {
@@ -56,7 +55,7 @@ void Curl_conncache_destroy(struct conncache *connc);
 /* return the correct bundle, to a host or a proxy */
 /* return the correct bundle, to a host or a proxy */
 struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
 struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
                                                  struct conncache *connc);
                                                  struct conncache *connc);
-void Curl_conncache_unlock(struct connectdata *conn);
+void Curl_conncache_unlock(struct Curl_easy *data);
 /* returns number of connections currently held in the connection cache */
 /* returns number of connections currently held in the connection cache */
 size_t Curl_conncache_size(struct Curl_easy *data);
 size_t Curl_conncache_size(struct Curl_easy *data);
 size_t Curl_conncache_bundle_size(struct connectdata *conn);
 size_t Curl_conncache_bundle_size(struct connectdata *conn);
@@ -64,7 +63,8 @@ size_t Curl_conncache_bundle_size(struct connectdata *conn);
 bool Curl_conncache_return_conn(struct connectdata *conn);
 bool Curl_conncache_return_conn(struct connectdata *conn);
 CURLcode Curl_conncache_add_conn(struct conncache *connc,
 CURLcode Curl_conncache_add_conn(struct conncache *connc,
                                  struct connectdata *conn) WARN_UNUSED_RESULT;
                                  struct connectdata *conn) WARN_UNUSED_RESULT;
-void Curl_conncache_remove_conn(struct connectdata *conn,
+void Curl_conncache_remove_conn(struct Curl_easy *data,
+                                struct connectdata *conn,
                                 bool lock);
                                 bool lock);
 bool Curl_conncache_foreach(struct Curl_easy *data,
 bool Curl_conncache_foreach(struct Curl_easy *data,
                             struct conncache *connc,
                             struct conncache *connc,

+ 67 - 47
Utilities/cmcurl/lib/connect.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -357,7 +357,7 @@ static CURLcode bindlocal(struct connectdata *conn,
         conn->ip_version = CURL_IPRESOLVE_V6;
         conn->ip_version = CURL_IPRESOLVE_V6;
 #endif
 #endif
 
 
-      rc = Curl_resolv(conn, dev, 0, &h);
+      rc = Curl_resolv(conn, dev, 0, FALSE, &h);
       if(rc == CURLRESOLV_PENDING)
       if(rc == CURLRESOLV_PENDING)
         (void)Curl_resolver_wait_resolv(conn, &h);
         (void)Curl_resolver_wait_resolv(conn, &h);
       conn->ip_version = ipver;
       conn->ip_version = ipver;
@@ -446,9 +446,10 @@ static CURLcode bindlocal(struct connectdata *conn,
       curl_socklen_t size = sizeof(add);
       curl_socklen_t size = sizeof(add);
       memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
       memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
       if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
       if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
+        char buffer[STRERROR_LEN];
         data->state.os_errno = error = SOCKERRNO;
         data->state.os_errno = error = SOCKERRNO;
         failf(data, "getsockname() failed with errno %d: %s",
         failf(data, "getsockname() failed with errno %d: %s",
-              error, Curl_strerror(conn, error));
+              error, Curl_strerror(error, buffer, sizeof(buffer)));
         return CURLE_INTERFACE_FAILED;
         return CURLE_INTERFACE_FAILED;
       }
       }
       infof(data, "Local port: %hu\n", port);
       infof(data, "Local port: %hu\n", port);
@@ -470,10 +471,12 @@ static CURLcode bindlocal(struct connectdata *conn,
     else
     else
       break;
       break;
   }
   }
-
-  data->state.os_errno = error = SOCKERRNO;
-  failf(data, "bind failed with errno %d: %s",
-        error, Curl_strerror(conn, error));
+  {
+    char buffer[STRERROR_LEN];
+    data->state.os_errno = error = SOCKERRNO;
+    failf(data, "bind failed with errno %d: %s",
+          error, Curl_strerror(error, buffer, sizeof(buffer)));
+  }
 
 
   return CURLE_INTERFACE_FAILED;
   return CURLE_INTERFACE_FAILED;
 }
 }
@@ -522,7 +525,7 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
     err = 0;
     err = 0;
   }
   }
 #endif
 #endif
-#ifdef __minix
+#if defined(EBADIOCTL) && defined(__minix)
   /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
   /* Minix 3.1.x doesn't support getsockopt on UDP sockets */
   if(EBADIOCTL == err) {
   if(EBADIOCTL == err) {
     SET_SOCKERRNO(0);
     SET_SOCKERRNO(0);
@@ -617,12 +620,14 @@ void Curl_persistconninfo(struct connectdata *conn)
   conn->data->info.conn_local_port = conn->local_port;
   conn->data->info.conn_local_port = conn->local_port;
 }
 }
 
 
+UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
+                             long *port);
+
 /* retrieves ip address and port from a sockaddr structure.
 /* retrieves ip address and port from a sockaddr structure.
    note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
    note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
-bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
-                         long *port)
+UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
+                             long *port)
 {
 {
-  unsigned short us_port;
   struct sockaddr_in *si = NULL;
   struct sockaddr_in *si = NULL;
 #ifdef ENABLE_IPV6
 #ifdef ENABLE_IPV6
   struct sockaddr_in6 *si6 = NULL;
   struct sockaddr_in6 *si6 = NULL;
@@ -636,7 +641,7 @@ bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
       si = (struct sockaddr_in *)(void *) sa;
       si = (struct sockaddr_in *)(void *) sa;
       if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
       if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
                         addr, MAX_IPADR_LEN)) {
                         addr, MAX_IPADR_LEN)) {
-        us_port = ntohs(si->sin_port);
+        unsigned short us_port = ntohs(si->sin_port);
         *port = us_port;
         *port = us_port;
         return TRUE;
         return TRUE;
       }
       }
@@ -646,7 +651,7 @@ bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
       si6 = (struct sockaddr_in6 *)(void *) sa;
       si6 = (struct sockaddr_in6 *)(void *) sa;
       if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
       if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
                         addr, MAX_IPADR_LEN)) {
                         addr, MAX_IPADR_LEN)) {
-        us_port = ntohs(si6->sin6_port);
+        unsigned short us_port = ntohs(si6->sin6_port);
         *port = us_port;
         *port = us_port;
         return TRUE;
         return TRUE;
       }
       }
@@ -655,7 +660,7 @@ bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
     case AF_UNIX:
     case AF_UNIX:
       su = (struct sockaddr_un*)sa;
       su = (struct sockaddr_un*)sa;
-      snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
+      msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
       *port = 0;
       *port = 0;
       return TRUE;
       return TRUE;
 #endif
 #endif
@@ -673,49 +678,57 @@ bool Curl_getaddressinfo(struct sockaddr *sa, char *addr,
    connection */
    connection */
 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
 {
 {
-  curl_socklen_t len;
-  struct Curl_sockaddr_storage ssrem;
-  struct Curl_sockaddr_storage ssloc;
-  struct Curl_easy *data = conn->data;
-
   if(conn->socktype == SOCK_DGRAM)
   if(conn->socktype == SOCK_DGRAM)
     /* there's no connection! */
     /* there's no connection! */
     return;
     return;
 
 
+#if defined(HAVE_GETPEERNAME) || defined(HAVE_GETSOCKNAME)
   if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
   if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
+    struct Curl_easy *data = conn->data;
+    char buffer[STRERROR_LEN];
+    struct Curl_sockaddr_storage ssrem;
+    struct Curl_sockaddr_storage ssloc;
+    curl_socklen_t len;
+#ifdef HAVE_GETPEERNAME
     len = sizeof(struct Curl_sockaddr_storage);
     len = sizeof(struct Curl_sockaddr_storage);
     if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
     if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
       int error = SOCKERRNO;
       int error = SOCKERRNO;
       failf(data, "getpeername() failed with errno %d: %s",
       failf(data, "getpeername() failed with errno %d: %s",
-            error, Curl_strerror(conn, error));
+            error, Curl_strerror(error, buffer, sizeof(buffer)));
       return;
       return;
     }
     }
-
+#endif
+#ifdef HAVE_GETSOCKNAME
     len = sizeof(struct Curl_sockaddr_storage);
     len = sizeof(struct Curl_sockaddr_storage);
     memset(&ssloc, 0, sizeof(ssloc));
     memset(&ssloc, 0, sizeof(ssloc));
     if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
     if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
       int error = SOCKERRNO;
       int error = SOCKERRNO;
       failf(data, "getsockname() failed with errno %d: %s",
       failf(data, "getsockname() failed with errno %d: %s",
-            error, Curl_strerror(conn, error));
+            error, Curl_strerror(error, buffer, sizeof(buffer)));
       return;
       return;
     }
     }
-
-    if(!Curl_getaddressinfo((struct sockaddr*)&ssrem,
-                            conn->primary_ip, &conn->primary_port)) {
+#endif
+#ifdef HAVE_GETPEERNAME
+    if(!getaddressinfo((struct sockaddr*)&ssrem,
+                       conn->primary_ip, &conn->primary_port)) {
       failf(data, "ssrem inet_ntop() failed with errno %d: %s",
       failf(data, "ssrem inet_ntop() failed with errno %d: %s",
-            errno, Curl_strerror(conn, errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       return;
       return;
     }
     }
     memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
     memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
-
-    if(!Curl_getaddressinfo((struct sockaddr*)&ssloc,
-                            conn->local_ip, &conn->local_port)) {
+#endif
+#ifdef HAVE_GETSOCKNAME
+    if(!getaddressinfo((struct sockaddr*)&ssloc,
+                       conn->local_ip, &conn->local_port)) {
       failf(data, "ssloc inet_ntop() failed with errno %d: %s",
       failf(data, "ssloc inet_ntop() failed with errno %d: %s",
-            errno, Curl_strerror(conn, errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       return;
       return;
     }
     }
-
+#endif
   }
   }
+#else /* !HAVE_GETSOCKNAME && !HAVE_GETPEERNAME */
+  (void)sockfd; /* unused */
+#endif
 
 
   /* persist connection info in session handle */
   /* persist connection info in session handle */
   Curl_persistconninfo(conn);
   Curl_persistconninfo(conn);
@@ -836,9 +849,11 @@ CURLcode Curl_is_connected(struct connectdata *conn,
       if(conn->tempaddr[i]) {
       if(conn->tempaddr[i]) {
         CURLcode status;
         CURLcode status;
         char ipaddress[MAX_IPADR_LEN];
         char ipaddress[MAX_IPADR_LEN];
+        char buffer[STRERROR_LEN];
         Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
         Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
         infof(data, "connect to %s port %ld failed: %s\n",
         infof(data, "connect to %s port %ld failed: %s\n",
-              ipaddress, conn->port, Curl_strerror(conn, error));
+              ipaddress, conn->port,
+              Curl_strerror(error, buffer, sizeof(buffer)));
 
 
         conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
         conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
                                    allow : allow / 2;
                                    allow : allow / 2;
@@ -854,8 +869,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
 
 
   if(result) {
   if(result) {
     /* no more addresses to try */
     /* no more addresses to try */
-
     const char *hostname;
     const char *hostname;
+    char buffer[STRERROR_LEN];
 
 
     /* if the first address family runs out of addresses to try before
     /* if the first address family runs out of addresses to try before
        the happy eyeball timeout, go ahead and try the next family now */
        the happy eyeball timeout, go ahead and try the next family now */
@@ -875,13 +890,14 @@ CURLcode Curl_is_connected(struct connectdata *conn,
       hostname = conn->host.name;
       hostname = conn->host.name;
 
 
     failf(data, "Failed to connect to %s port %ld: %s",
     failf(data, "Failed to connect to %s port %ld: %s",
-        hostname, conn->port, Curl_strerror(conn, error));
+          hostname, conn->port,
+          Curl_strerror(error, buffer, sizeof(buffer)));
   }
   }
 
 
   return result;
   return result;
 }
 }
 
 
-void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
+static void tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
 {
 {
 #if defined(TCP_NODELAY)
 #if defined(TCP_NODELAY)
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -889,6 +905,7 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
 #endif
 #endif
   curl_socklen_t onoff = (curl_socklen_t) 1;
   curl_socklen_t onoff = (curl_socklen_t) 1;
   int level = IPPROTO_TCP;
   int level = IPPROTO_TCP;
+  char buffer[STRERROR_LEN];
 
 
 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
   (void) conn;
   (void) conn;
@@ -897,7 +914,7 @@ void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
   if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
   if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
                 sizeof(onoff)) < 0)
                 sizeof(onoff)) < 0)
     infof(data, "Could not set TCP_NODELAY: %s\n",
     infof(data, "Could not set TCP_NODELAY: %s\n",
-          Curl_strerror(conn, SOCKERRNO));
+          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
   else
   else
     infof(data, "TCP_NODELAY set\n");
     infof(data, "TCP_NODELAY set\n");
 #else
 #else
@@ -917,9 +934,11 @@ static void nosigpipe(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
   int onoff = 1;
   int onoff = 1;
   if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
   if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
-                sizeof(onoff)) < 0)
+                sizeof(onoff)) < 0) {
+    char buffer[STRERROR_LEN];
     infof(data, "Could not set SO_NOSIGPIPE: %s\n",
     infof(data, "Could not set SO_NOSIGPIPE: %s\n",
-          Curl_strerror(conn, SOCKERRNO));
+          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
+  }
 }
 }
 #else
 #else
 #define nosigpipe(x,y) Curl_nop_stmt
 #define nosigpipe(x,y) Curl_nop_stmt
@@ -995,6 +1014,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
 #ifdef TCP_FASTOPEN_CONNECT
 #ifdef TCP_FASTOPEN_CONNECT
   int optval = 1;
   int optval = 1;
 #endif
 #endif
+  char buffer[STRERROR_LEN];
 
 
   *sockp = CURL_SOCKET_BAD;
   *sockp = CURL_SOCKET_BAD;
 
 
@@ -1006,15 +1026,15 @@ static CURLcode singleipconnect(struct connectdata *conn,
     return CURLE_OK;
     return CURLE_OK;
 
 
   /* store remote address and port used in this connection attempt */
   /* store remote address and port used in this connection attempt */
-  if(!Curl_getaddressinfo((struct sockaddr*)&addr.sa_addr,
-                          ipaddress, &port)) {
+  if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
+                     ipaddress, &port)) {
     /* malformed address or bug in inet_ntop, try next address */
     /* malformed address or bug in inet_ntop, try next address */
     failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
     failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
-          errno, Curl_strerror(conn, errno));
+          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     Curl_closesocket(conn, sockfd);
     Curl_closesocket(conn, sockfd);
     return CURLE_OK;
     return CURLE_OK;
   }
   }
-  infof(data, "  Trying %s...\n", ipaddress);
+  infof(data, "  Trying %s:%ld...\n", ipaddress, port);
 
 
 #ifdef ENABLE_IPV6
 #ifdef ENABLE_IPV6
   is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
   is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
@@ -1023,7 +1043,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
   is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
   is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
 #endif
 #endif
   if(is_tcp && data->set.tcp_nodelay)
   if(is_tcp && data->set.tcp_nodelay)
-    Curl_tcpnodelay(conn, sockfd);
+    tcpnodelay(conn, sockfd);
 
 
   nosigpipe(conn, sockfd);
   nosigpipe(conn, sockfd);
 
 
@@ -1146,7 +1166,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
     default:
     default:
       /* unknown error, fallthrough and try another address! */
       /* unknown error, fallthrough and try another address! */
       infof(data, "Immediate connect fail for %s: %s\n",
       infof(data, "Immediate connect fail for %s: %s\n",
-            ipaddress, Curl_strerror(conn, error));
+            ipaddress, Curl_strerror(error, buffer, sizeof(buffer)));
       data->state.os_errno = error;
       data->state.os_errno = error;
 
 
       /* connect failed */
       /* connect failed */
@@ -1314,7 +1334,7 @@ int Curl_closesocket(struct connectdata *conn,
       conn->sock_accepted[SECONDARYSOCKET] = FALSE;
       conn->sock_accepted[SECONDARYSOCKET] = FALSE;
     else {
     else {
       int rc;
       int rc;
-      Curl_multi_closed(conn, sock);
+      Curl_multi_closed(conn->data, sock);
       Curl_set_in_callback(conn->data, true);
       Curl_set_in_callback(conn->data, true);
       rc = conn->fclosesocket(conn->closesocket_client, sock);
       rc = conn->fclosesocket(conn->closesocket_client, sock);
       Curl_set_in_callback(conn->data, false);
       Curl_set_in_callback(conn->data, false);
@@ -1324,7 +1344,7 @@ int Curl_closesocket(struct connectdata *conn,
 
 
   if(conn)
   if(conn)
     /* tell the multi-socket code about this */
     /* tell the multi-socket code about this */
-    Curl_multi_closed(conn, sock);
+    Curl_multi_closed(conn->data, sock);
 
 
   sclose(sock);
   sclose(sock);
 
 
@@ -1420,7 +1440,7 @@ void Curl_conncontrol(struct connectdata *conn,
   if((ctrl == CONNCTRL_STREAM) &&
   if((ctrl == CONNCTRL_STREAM) &&
      (conn->handler->flags & PROTOPT_STREAM))
      (conn->handler->flags & PROTOPT_STREAM))
     DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
     DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
-  else if(closeit != conn->bits.close) {
+  else if((bit)closeit != conn->bits.close) {
     DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
     DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
                  closeit?"closure":"keep alive", reason));
                  closeit?"closure":"keep alive", reason));
     conn->bits.close = closeit; /* the only place in the source code that
     conn->bits.close = closeit; /* the only place in the source code that

+ 1 - 8
Utilities/cmcurl/lib/connect.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -75,11 +75,6 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
 void Curl_persistconninfo(struct connectdata *conn);
 void Curl_persistconninfo(struct connectdata *conn);
 int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
 int Curl_closesocket(struct connectdata *conn, curl_socket_t sock);
 
 
-/*
- * Get presentation format IP address and port from a sockaddr.
- */
-bool Curl_getaddressinfo(struct sockaddr *sa, char *addr, long *port);
-
 /*
 /*
  * The Curl_sockaddr_ex structure is basically libcurl's external API
  * The Curl_sockaddr_ex structure is basically libcurl's external API
  * curl_sockaddr structure with enough space available to directly hold any
  * curl_sockaddr structure with enough space available to directly hold any
@@ -111,8 +106,6 @@ CURLcode Curl_socket(struct connectdata *conn,
                      struct Curl_sockaddr_ex *addr,
                      struct Curl_sockaddr_ex *addr,
                      curl_socket_t *sockfd);
                      curl_socket_t *sockfd);
 
 
-void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd);
-
 /*
 /*
  * Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
  * Curl_conncontrol() marks the end of a connection/stream. The 'closeit'
  * argument specifies if it is the end of a connection or a stream.
  * argument specifies if it is the end of a connection or a stream.

+ 129 - 73
Utilities/cmcurl/lib/cookie.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -93,6 +93,7 @@ Example set of cookies:
 #include "share.h"
 #include "share.h"
 #include "strtoofft.h"
 #include "strtoofft.h"
 #include "strcase.h"
 #include "strcase.h"
+#include "curl_get_line.h"
 #include "curl_memrchr.h"
 #include "curl_memrchr.h"
 #include "inet_pton.h"
 #include "inet_pton.h"
 
 
@@ -223,7 +224,7 @@ static bool pathmatch(const char *cookie_path, const char *request_uri)
     goto pathmatched;
     goto pathmatched;
   }
   }
 
 
-  /* here, cookie_path_len < url_path_len */
+  /* here, cookie_path_len < uri_path_len */
   if(uri_path[cookie_path_len] == '/') {
   if(uri_path[cookie_path_len] == '/') {
     ret = TRUE;
     ret = TRUE;
     goto pathmatched;
     goto pathmatched;
@@ -433,9 +434,10 @@ Curl_cookie_add(struct Curl_easy *data,
                 bool noexpire, /* if TRUE, skip remove_expired() */
                 bool noexpire, /* if TRUE, skip remove_expired() */
                 char *lineptr,   /* first character of the line */
                 char *lineptr,   /* first character of the line */
                 const char *domain, /* default domain */
                 const char *domain, /* default domain */
-                const char *path)   /* full path used when this cookie is set,
+                const char *path,   /* full path used when this cookie is set,
                                        used to get default path for the cookie
                                        used to get default path for the cookie
                                        unless set */
                                        unless set */
+                bool secure)  /* TRUE if connection is over secure origin */
 {
 {
   struct Cookie *clist;
   struct Cookie *clist;
   struct Cookie *co;
   struct Cookie *co;
@@ -527,6 +529,19 @@ Curl_cookie_add(struct Curl_easy *data,
         while(*whatptr && ISBLANK(*whatptr))
         while(*whatptr && ISBLANK(*whatptr))
           whatptr++;
           whatptr++;
 
 
+        /*
+         * Check if we have a reserved prefix set before anything else, as we
+         * otherwise have to test for the prefix in both the cookie name and
+         * "the rest". Prefixes must start with '__' and end with a '-', so
+         * only test for names where that can possibly be true.
+         */
+        if(nlen > 3 && name[0] == '_' && name[1] == '_') {
+          if(strncasecompare("__Secure-", name, 9))
+            co->prefix |= COOKIE_PREFIX__SECURE;
+          else if(strncasecompare("__Host-", name, 7))
+            co->prefix |= COOKIE_PREFIX__HOST;
+        }
+
         if(!co->name) {
         if(!co->name) {
           /* The very first name/value pair is the actual cookie name */
           /* The very first name/value pair is the actual cookie name */
           if(!sep) {
           if(!sep) {
@@ -546,8 +561,20 @@ Curl_cookie_add(struct Curl_easy *data,
           /* this was a "<name>=" with no content, and we must allow
           /* this was a "<name>=" with no content, and we must allow
              'secure' and 'httponly' specified this weirdly */
              'secure' and 'httponly' specified this weirdly */
           done = TRUE;
           done = TRUE;
-          if(strcasecompare("secure", name))
-            co->secure = TRUE;
+          /*
+           * secure cookies are only allowed to be set when the connection is
+           * using a secure protocol, or when the cookie is being set by
+           * reading from file
+           */
+          if(strcasecompare("secure", name)) {
+            if(secure || !c->running) {
+              co->secure = TRUE;
+            }
+            else {
+              badcookie = TRUE;
+              break;
+            }
+          }
           else if(strcasecompare("httponly", name))
           else if(strcasecompare("httponly", name))
             co->httponly = TRUE;
             co->httponly = TRUE;
           else if(sep)
           else if(sep)
@@ -675,7 +702,10 @@ Curl_cookie_add(struct Curl_easy *data,
         /* overflow, used max value */
         /* overflow, used max value */
         co->expires = CURL_OFF_T_MAX;
         co->expires = CURL_OFF_T_MAX;
       else if(!offt) {
       else if(!offt) {
-        if(CURL_OFF_T_MAX - now < co->expires)
+        if(!co->expires)
+          /* already expired */
+          co->expires = 1;
+        else if(CURL_OFF_T_MAX - now < co->expires)
           /* would overflow */
           /* would overflow */
           co->expires = CURL_OFF_T_MAX;
           co->expires = CURL_OFF_T_MAX;
         else
         else
@@ -828,7 +858,13 @@ Curl_cookie_add(struct Curl_easy *data,
         fields++; /* add a field and fall down to secure */
         fields++; /* add a field and fall down to secure */
         /* FALLTHROUGH */
         /* FALLTHROUGH */
       case 3:
       case 3:
-        co->secure = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
+        co->secure = FALSE;
+        if(strcasecompare(ptr, "TRUE")) {
+          if(secure || c->running)
+            co->secure = TRUE;
+          else
+            badcookie = TRUE;
+        }
         break;
         break;
       case 4:
       case 4:
         if(curlx_strtoofft(ptr, NULL, 10, &co->expires))
         if(curlx_strtoofft(ptr, NULL, 10, &co->expires))
@@ -838,6 +874,13 @@ Curl_cookie_add(struct Curl_easy *data,
         co->name = strdup(ptr);
         co->name = strdup(ptr);
         if(!co->name)
         if(!co->name)
           badcookie = TRUE;
           badcookie = TRUE;
+        else {
+          /* For Netscape file format cookies we check prefix on the name */
+          if(strncasecompare("__Secure-", co->name, 9))
+            co->prefix |= COOKIE_PREFIX__SECURE;
+          else if(strncasecompare("__Host-", co->name, 7))
+            co->prefix |= COOKIE_PREFIX__HOST;
+        }
         break;
         break;
       case 6:
       case 6:
         co->value = strdup(ptr);
         co->value = strdup(ptr);
@@ -866,6 +909,26 @@ Curl_cookie_add(struct Curl_easy *data,
 
 
   }
   }
 
 
+  if(co->prefix & COOKIE_PREFIX__SECURE) {
+    /* The __Secure- prefix only requires that the cookie be set secure */
+    if(!co->secure) {
+      freecookie(co);
+      return NULL;
+    }
+  }
+  if(co->prefix & COOKIE_PREFIX__HOST) {
+    /*
+     * The __Host- prefix requires the cookie to be secure, have a "/" path
+     * and not have a domain set.
+     */
+    if(co->secure && co->path && strcmp(co->path, "/") == 0 && !co->tailmatch)
+      ;
+    else {
+      freecookie(co);
+      return NULL;
+    }
+  }
+
   if(!c->running &&    /* read from a file */
   if(!c->running &&    /* read from a file */
      c->newsession &&  /* clean session cookies */
      c->newsession &&  /* clean session cookies */
      !co->expires) {   /* this is a session cookie since it doesn't expire! */
      !co->expires) {   /* this is a session cookie since it doesn't expire! */
@@ -926,9 +989,31 @@ Curl_cookie_add(struct Curl_easy *data,
         /* the domains were identical */
         /* the domains were identical */
 
 
         if(clist->spath && co->spath) {
         if(clist->spath && co->spath) {
-          if(strcasecompare(clist->spath, co->spath)) {
-            replace_old = TRUE;
+          if(clist->secure && !co->secure && !secure) {
+            size_t cllen;
+            const char *sep;
+
+            /*
+             * A non-secure cookie may not overlay an existing secure cookie.
+             * For an existing cookie "a" with path "/login", refuse a new
+             * cookie "a" with for example path "/login/en", while the path
+             * "/loginhelper" is ok.
+             */
+
+            sep = strchr(clist->spath + 1, '/');
+
+            if(sep)
+              cllen = sep - clist->spath;
+            else
+              cllen = strlen(clist->spath);
+
+            if(strncasecompare(clist->spath, co->spath, cllen)) {
+              freecookie(co);
+              return NULL;
+            }
           }
           }
+          else if(strcasecompare(clist->spath, co->spath))
+            replace_old = TRUE;
           else
           else
             replace_old = FALSE;
             replace_old = FALSE;
         }
         }
@@ -1003,33 +1088,6 @@ Curl_cookie_add(struct Curl_easy *data,
   return co;
   return co;
 }
 }
 
 
-/*
- * get_line() makes sure to only return complete whole lines that fit in 'len'
- * bytes and end with a newline.
- */
-static char *get_line(char *buf, int len, FILE *input)
-{
-  bool partial = FALSE;
-  while(1) {
-    char *b = fgets(buf, len, input);
-    if(b) {
-      size_t rlen = strlen(b);
-      if(rlen && (b[rlen-1] == '\n')) {
-        if(partial) {
-          partial = FALSE;
-          continue;
-        }
-        return b;
-      }
-      /* read a partial, discard the next piece that ends with newline */
-      partial = TRUE;
-    }
-    else
-      break;
-  }
-  return NULL;
-}
-
 
 
 /*****************************************************************************
 /*****************************************************************************
  *
  *
@@ -1087,7 +1145,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
     line = malloc(MAX_COOKIE_LINE);
     line = malloc(MAX_COOKIE_LINE);
     if(!line)
     if(!line)
       goto fail;
       goto fail;
-    while(get_line(line, MAX_COOKIE_LINE, fp)) {
+    while(Curl_get_line(line, MAX_COOKIE_LINE, fp)) {
       if(checkprefix("Set-Cookie:", line)) {
       if(checkprefix("Set-Cookie:", line)) {
         /* This is a cookie line, get it! */
         /* This is a cookie line, get it! */
         lineptr = &line[11];
         lineptr = &line[11];
@@ -1100,7 +1158,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
       while(*lineptr && ISBLANK(*lineptr))
       while(*lineptr && ISBLANK(*lineptr))
         lineptr++;
         lineptr++;
 
 
-      Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL);
+      Curl_cookie_add(data, c, headerline, TRUE, lineptr, NULL, NULL, TRUE);
     }
     }
     free(line); /* free the line buffer */
     free(line); /* free the line buffer */
     remove_expired(c); /* run this once, not on every cookie */
     remove_expired(c); /* run this once, not on every cookie */
@@ -1451,27 +1509,14 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
   struct Cookie *co;
   struct Cookie *co;
   FILE *out;
   FILE *out;
   bool use_stdout = FALSE;
   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
-       destination file */
+  if(!c)
+    /* no cookie engine alive */
     return 0;
     return 0;
 
 
   /* at first, remove expired cookies */
   /* at first, remove expired cookies */
   remove_expired(c);
   remove_expired(c);
 
 
-  /* make sure we still have cookies after expiration */
-  if(0 == c->numcookies)
-    return 0;
-
-  array = malloc(sizeof(struct Cookie *) * c->numcookies);
-  if(!array)
-    return 1;
-
   if(!strcmp("-", dumphere)) {
   if(!strcmp("-", dumphere)) {
     /* use stdout */
     /* use stdout */
     out = stdout;
     out = stdout;
@@ -1480,7 +1525,6 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
   else {
   else {
     out = fopen(dumphere, FOPEN_WRITETEXT);
     out = fopen(dumphere, FOPEN_WRITETEXT);
     if(!out) {
     if(!out) {
-      free(array);
       return 1; /* failure */
       return 1; /* failure */
     }
     }
   }
   }
@@ -1490,32 +1534,44 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
         "# This file was generated by libcurl! Edit at your own risk.\n\n",
         "# This file was generated by libcurl! Edit at your own risk.\n\n",
         out);
         out);
 
 
-  j = 0;
-  for(i = 0; i < COOKIE_HASH_SIZE; i++) {
-    for(co = c->cookies[i]; co; co = co->next) {
-      if(!co->domain)
-        continue;
-      array[j++] = co;
-    }
-  }
-
-  qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct);
+  if(c->numcookies) {
+    unsigned int i;
+    unsigned int j;
+    struct Cookie **array;
 
 
-  for(i = 0; i < j; i++) {
-    format_ptr = get_netscape_format(array[i]);
-    if(format_ptr == NULL) {
-      fprintf(out, "#\n# Fatal libcurl error\n");
-      free(array);
+    array = malloc(sizeof(struct Cookie *) * c->numcookies);
+    if(!array) {
       if(!use_stdout)
       if(!use_stdout)
         fclose(out);
         fclose(out);
       return 1;
       return 1;
     }
     }
-    fprintf(out, "%s\n", format_ptr);
-    free(format_ptr);
-  }
 
 
-  free(array);
+    j = 0;
+    for(i = 0; i < COOKIE_HASH_SIZE; i++) {
+      for(co = c->cookies[i]; co; co = co->next) {
+        if(!co->domain)
+          continue;
+        array[j++] = co;
+      }
+    }
+
+    qsort(array, c->numcookies, sizeof(struct Cookie *), cookie_sort_ct);
 
 
+    for(i = 0; i < j; i++) {
+      char *format_ptr = get_netscape_format(array[i]);
+      if(format_ptr == NULL) {
+        fprintf(out, "#\n# Fatal libcurl error\n");
+        free(array);
+        if(!use_stdout)
+          fclose(out);
+        return 1;
+      }
+      fprintf(out, "%s\n", format_ptr);
+      free(format_ptr);
+    }
+
+    free(array);
+  }
   if(!use_stdout)
   if(!use_stdout)
     fclose(out);
     fclose(out);
 
 

+ 11 - 2
Utilities/cmcurl/lib/cookie.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -44,8 +44,16 @@ struct Cookie {
   bool livecookie;   /* updated from a server, not a stored file */
   bool livecookie;   /* updated from a server, not a stored file */
   bool httponly;     /* true if the httponly directive is present */
   bool httponly;     /* true if the httponly directive is present */
   int creationtime;  /* time when the cookie was written */
   int creationtime;  /* time when the cookie was written */
+  unsigned char prefix; /* bitmap fields indicating which prefix are set */
 };
 };
 
 
+/*
+ * Available cookie prefixes, as defined in
+ * draft-ietf-httpbis-rfc6265bis-02
+ */
+#define COOKIE_PREFIX__SECURE (1<<0)
+#define COOKIE_PREFIX__HOST (1<<1)
+
 #define COOKIE_HASH_SIZE 256
 #define COOKIE_HASH_SIZE 256
 
 
 struct CookieInfo {
 struct CookieInfo {
@@ -85,7 +93,8 @@ struct Curl_easy;
 struct Cookie *Curl_cookie_add(struct Curl_easy *data,
 struct Cookie *Curl_cookie_add(struct Curl_easy *data,
                                struct CookieInfo *, bool header, bool noexpiry,
                                struct CookieInfo *, bool header, bool noexpiry,
                                char *lineptr,
                                char *lineptr,
-                               const char *domain, const char *path);
+                               const char *domain, const char *path,
+                               bool secure);
 
 
 struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
 struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *,
                                    const char *, bool);
                                    const char *, bool);

+ 16 - 16
Utilities/cmcurl/lib/curl_addrinfo.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -539,7 +539,7 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) &&  \
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) &&  \
   defined(HAVE_FREEADDRINFO)
   defined(HAVE_FREEADDRINFO)
 /*
 /*
- * curl_dofreeaddrinfo()
+ * curl_dbg_freeaddrinfo()
  *
  *
  * This is strictly for memory tracing and are using the same style as the
  * This is 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
  * family otherwise present in memdebug.c. I put these ones here since they
@@ -547,23 +547,23 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
  */
  */
 
 
 void
 void
-curl_dofreeaddrinfo(struct addrinfo *freethis,
-                    int line, const char *source)
+curl_dbg_freeaddrinfo(struct addrinfo *freethis,
+                      int line, const char *source)
 {
 {
+  curl_dbg_log("ADDR %s:%d freeaddrinfo(%p)\n",
+               source, line, (void *)freethis);
 #ifdef USE_LWIPSOCK
 #ifdef USE_LWIPSOCK
   lwip_freeaddrinfo(freethis);
   lwip_freeaddrinfo(freethis);
 #else
 #else
   (freeaddrinfo)(freethis);
   (freeaddrinfo)(freethis);
 #endif
 #endif
-  curl_memlog("ADDR %s:%d freeaddrinfo(%p)\n",
-              source, line, (void *)freethis);
 }
 }
 #endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */
 #endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */
 
 
 
 
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
 /*
 /*
- * curl_dogetaddrinfo()
+ * curl_dbg_getaddrinfo()
  *
  *
  * This is strictly for memory tracing and are using the same style as the
  * This is 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
  * family otherwise present in memdebug.c. I put these ones here since they
@@ -571,11 +571,11 @@ curl_dofreeaddrinfo(struct addrinfo *freethis,
  */
  */
 
 
 int
 int
-curl_dogetaddrinfo(const char *hostname,
-                   const char *service,
-                   const struct addrinfo *hints,
-                   struct addrinfo **result,
-                   int line, const char *source)
+curl_dbg_getaddrinfo(const char *hostname,
+                    const char *service,
+                    const struct addrinfo *hints,
+                    struct addrinfo **result,
+                    int line, const char *source)
 {
 {
 #ifdef USE_LWIPSOCK
 #ifdef USE_LWIPSOCK
   int res = lwip_getaddrinfo(hostname, service, hints, result);
   int res = lwip_getaddrinfo(hostname, service, hints, result);
@@ -584,11 +584,11 @@ curl_dogetaddrinfo(const char *hostname,
 #endif
 #endif
   if(0 == res)
   if(0 == res)
     /* success */
     /* success */
-    curl_memlog("ADDR %s:%d getaddrinfo() = %p\n",
-                source, line, (void *)*result);
+    curl_dbg_log("ADDR %s:%d getaddrinfo() = %p\n",
+                 source, line, (void *)*result);
   else
   else
-    curl_memlog("ADDR %s:%d getaddrinfo() failed\n",
-                source, line);
+    curl_dbg_log("ADDR %s:%d getaddrinfo() failed\n",
+                 source, line);
   return res;
   return res;
 }
 }
 #endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */
 #endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */

+ 5 - 8
Utilities/cmcurl/lib/curl_addrinfo.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -86,17 +86,14 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract);
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
     defined(HAVE_FREEADDRINFO)
     defined(HAVE_FREEADDRINFO)
 void
 void
-curl_dofreeaddrinfo(struct addrinfo *freethis,
-                    int line, const char *source);
+curl_dbg_freeaddrinfo(struct addrinfo *freethis, int line, const char *source);
 #endif
 #endif
 
 
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO)
 int
 int
-curl_dogetaddrinfo(const char *hostname,
-                   const char *service,
-                   const struct addrinfo *hints,
-                   struct addrinfo **result,
-                   int line, const char *source);
+curl_dbg_getaddrinfo(const char *hostname, const char *service,
+                     const struct addrinfo *hints, struct addrinfo **result,
+                     int line, const char *source);
 #endif
 #endif
 
 
 #ifdef HAVE_GETADDRINFO
 #ifdef HAVE_GETADDRINFO

+ 8 - 2
Utilities/cmcurl/lib/curl_config.h.cmake

@@ -226,6 +226,12 @@
 /* Define to 1 if you have the `getprotobyname' function. */
 /* Define to 1 if you have the `getprotobyname' function. */
 #cmakedefine HAVE_GETPROTOBYNAME 1
 #cmakedefine HAVE_GETPROTOBYNAME 1
 
 
+/* Define to 1 if you have the `getpeername' function. */
+#cmakedefine HAVE_GETPEERNAME 1
+
+/* Define to 1 if you have the `getsockname' function. */
+#cmakedefine HAVE_GETSOCKNAME 1
+
 /* Define to 1 if you have the `getpwuid' function. */
 /* Define to 1 if you have the `getpwuid' function. */
 #cmakedefine HAVE_GETPWUID 1
 #cmakedefine HAVE_GETPWUID 1
 
 
@@ -930,8 +936,8 @@
 /* if PolarSSL is enabled */
 /* if PolarSSL is enabled */
 #cmakedefine USE_POLARSSL 1
 #cmakedefine USE_POLARSSL 1
 
 
-/* if DarwinSSL is enabled */
-#cmakedefine USE_DARWINSSL 1
+/* if Secure Transport is enabled */
+#cmakedefine USE_SECTRANSP 1
 
 
 /* if mbedTLS is enabled */
 /* if mbedTLS is enabled */
 #cmakedefine USE_MBEDTLS 1
 #cmakedefine USE_MBEDTLS 1

+ 5 - 5
Utilities/cmcurl/lib/curl_endian.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -82,7 +82,7 @@ unsigned short Curl_read16_be(const unsigned char *buf)
 }
 }
 
 
 /*
 /*
- * Curl_write32_le()
+ * write32_le()
  *
  *
  * This function converts a 32-bit integer from the native endian format,
  * This function converts a 32-bit integer from the native endian format,
  * to little endian format ready for sending down the wire.
  * to little endian format ready for sending down the wire.
@@ -92,7 +92,7 @@ unsigned short Curl_read16_be(const unsigned char *buf)
  * value    [in]     - The 32-bit integer value.
  * value    [in]     - The 32-bit integer value.
  * buffer   [in]     - A pointer to the output buffer.
  * buffer   [in]     - A pointer to the output buffer.
  */
  */
-void Curl_write32_le(const int value, unsigned char *buffer)
+static void write32_le(const int value, unsigned char *buffer)
 {
 {
   buffer[0] = (char)(value & 0x000000FF);
   buffer[0] = (char)(value & 0x000000FF);
   buffer[1] = (char)((value & 0x0000FF00) >> 8);
   buffer[1] = (char)((value & 0x0000FF00) >> 8);
@@ -118,7 +118,7 @@ void Curl_write64_le(const long long value, unsigned char *buffer)
 void Curl_write64_le(const __int64 value, unsigned char *buffer)
 void Curl_write64_le(const __int64 value, unsigned char *buffer)
 #endif
 #endif
 {
 {
-  Curl_write32_le((int)value, buffer);
-  Curl_write32_le((int)(value >> 32), buffer + 4);
+  write32_le((int)value, buffer);
+  write32_le((int)(value >> 32), buffer + 4);
 }
 }
 #endif /* CURL_SIZEOF_CURL_OFF_T > 4 */
 #endif /* CURL_SIZEOF_CURL_OFF_T > 4 */

+ 4 - 11
Utilities/cmcurl/lib/curl_fnmatch.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
  ***************************************************************************/
  ***************************************************************************/
 
 
 #include "curl_setup.h"
 #include "curl_setup.h"
-
+#ifndef CURL_DISABLE_FTP
 #include <curl/curl.h>
 #include <curl/curl.h>
 
 
 #include "curl_fnmatch.h"
 #include "curl_fnmatch.h"
@@ -32,15 +32,6 @@
 
 
 #ifndef HAVE_FNMATCH
 #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_CHARSET_LEN (sizeof(char) * 256)
 #define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
 #define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
 
 
@@ -394,3 +385,5 @@ int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
 }
 }
 
 
 #endif
 #endif
+
+#endif /* if FTP is disabled */

+ 55 - 0
Utilities/cmcurl/lib/curl_get_line.c

@@ -0,0 +1,55 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, 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_get_line.h"
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+/*
+ * get_line() makes sure to only return complete whole lines that fit in 'len'
+ * bytes and end with a newline.
+ */
+char *Curl_get_line(char *buf, int len, FILE *input)
+{
+  bool partial = FALSE;
+  while(1) {
+    char *b = fgets(buf, len, input);
+    if(b) {
+      size_t rlen = strlen(b);
+      if(rlen && (b[rlen-1] == '\n')) {
+        if(partial) {
+          partial = FALSE;
+          continue;
+        }
+        return b;
+      }
+      /* read a partial, discard the next piece that ends with newline */
+      partial = TRUE;
+    }
+    else
+      break;
+  }
+  return NULL;
+}

+ 7 - 11
Utilities/cmcurl/lib/vtls/axtls.h → Utilities/cmcurl/lib/curl_get_line.h

@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_AXTLS_H
-#define HEADER_CURL_AXTLS_H
+#ifndef HEADER_CURL_GET_LINE_H
+#define HEADER_CURL_GET_LINE_H
 /***************************************************************************
 /***************************************************************************
  *                                  _   _ ____  _
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
  *  Project                     ___| | | |  _ \| |
@@ -7,8 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 2010, DirecTV, Contact: Eric Hu <[email protected]>
- * Copyright (C) 2010 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -23,11 +22,8 @@
  *
  *
  ***************************************************************************/
  ***************************************************************************/
 
 
-#ifdef USE_AXTLS
-#include "curl/curl.h"
-#include "urldata.h"
+/* get_line() makes sure to only return complete whole lines that fit in 'len'
+ * bytes and end with a newline. */
+char *Curl_get_line(char *buf, int len, FILE *input);
 
 
-extern const struct Curl_ssl Curl_ssl_axtls;
-
-#endif /* USE_AXTLS */
-#endif /* HEADER_CURL_AXTLS_H */
+#endif /* HEADER_CURL_GET_LINE_H */

+ 3 - 3
Utilities/cmcurl/lib/curl_gssapi.c

@@ -97,9 +97,9 @@ static size_t display_gss_error(OM_uint32 status, int type,
                                   &msg_ctx,
                                   &msg_ctx,
                                   &status_string);
                                   &status_string);
     if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) {
     if(GSS_LOG_BUFFER_LEN > len + status_string.length + 3) {
-      len += snprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
-                      "%.*s. ", (int)status_string.length,
-                      (char *)status_string.value);
+      len += msnprintf(buf + len, GSS_LOG_BUFFER_LEN - len,
+                       "%.*s. ", (int)status_string.length,
+                       (char *)status_string.value);
     }
     }
     gss_release_buffer(&min_stat, &status_string);
     gss_release_buffer(&min_stat, &status_string);
   } while(!GSS_ERROR(maj_stat) && msg_ctx != 0);
   } while(!GSS_ERROR(maj_stat) && msg_ctx != 0);

+ 1 - 15
Utilities/cmcurl/lib/curl_gssapi.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 2011 - 2015, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2011 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -26,19 +26,6 @@
 #include "urldata.h"
 #include "urldata.h"
 
 
 #ifdef HAVE_GSSAPI
 #ifdef HAVE_GSSAPI
-
-#ifdef HAVE_GSSGNU
-#  include <gss.h>
-#elif defined HAVE_GSSMIT
-   /* MIT style */
-#  include <gssapi/gssapi.h>
-#  include <gssapi/gssapi_generic.h>
-#  include <gssapi/gssapi_krb5.h>
-#else
-   /* Heimdal-style */
-#  include <gssapi.h>
-#endif
-
 extern gss_OID_desc Curl_spnego_mech_oid;
 extern gss_OID_desc Curl_spnego_mech_oid;
 extern gss_OID_desc Curl_krb5_mech_oid;
 extern gss_OID_desc Curl_krb5_mech_oid;
 
 
@@ -71,5 +58,4 @@ void Curl_gss_log_error(struct Curl_easy *data, const char *prefix,
 #define GSSAUTH_P_PRIVACY   4
 #define GSSAUTH_P_PRIVACY   4
 
 
 #endif /* HAVE_GSSAPI */
 #endif /* HAVE_GSSAPI */
-
 #endif /* HEADER_CURL_GSSAPI_H */
 #endif /* HEADER_CURL_GSSAPI_H */

+ 3 - 1
Utilities/cmcurl/lib/curl_md4.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -25,11 +25,13 @@
 #include "curl_setup.h"
 #include "curl_setup.h"
 
 
 #if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
 #if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
+    (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || \
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
 
 
 void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len);
 void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len);
 
 
 #endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
 #endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
+    (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) ||
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
 
 
 #endif /* HEADER_CURL_MD4_H */
 #endif /* HEADER_CURL_MD4_H */

+ 5 - 5
Utilities/cmcurl/lib/curl_md5.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -53,10 +53,10 @@ void Curl_md5it(unsigned char *output,
                 const unsigned char *input);
                 const unsigned char *input);
 
 
 MD5_context * Curl_MD5_init(const MD5_params *md5params);
 MD5_context * Curl_MD5_init(const MD5_params *md5params);
-int Curl_MD5_update(MD5_context *context,
-                    const unsigned char *data,
-                    unsigned int len);
-int Curl_MD5_final(MD5_context *context, unsigned char *result);
+CURLcode Curl_MD5_update(MD5_context *context,
+                         const unsigned char *data,
+                         unsigned int len);
+CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result);
 
 
 #endif
 #endif
 
 

+ 2 - 2
Utilities/cmcurl/lib/curl_memory.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -39,7 +39,7 @@
  *
  *
  * File lib/strdup.c is an exception, given that it provides a strdup
  * File lib/strdup.c is an exception, given that it provides a strdup
  * clone implementation while using malloc. Extra care needed inside
  * clone implementation while using malloc. Extra care needed inside
- * this one. TODO: revisit this paragraph and related code.
+ * this one.
  *
  *
  * The need for curl_memory.h inclusion is due to libcurl's feature
  * The need for curl_memory.h inclusion is due to libcurl's feature
  * of allowing library user to provide memory replacement functions,
  * of allowing library user to provide memory replacement functions,

+ 6 - 6
Utilities/cmcurl/lib/curl_multibyte.c

@@ -64,13 +64,13 @@ char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w)
   char *str_utf8 = NULL;
   char *str_utf8 = NULL;
 
 
   if(str_w) {
   if(str_w) {
-    int str_utf8_len = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, NULL,
-                                           0, NULL, NULL);
-    if(str_utf8_len > 0) {
-      str_utf8 = malloc(str_utf8_len * sizeof(wchar_t));
+    int bytes = WideCharToMultiByte(CP_UTF8, 0, str_w, -1,
+                                    NULL, 0, NULL, NULL);
+    if(bytes > 0) {
+      str_utf8 = malloc(bytes);
       if(str_utf8) {
       if(str_utf8) {
-        if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, str_utf8_len,
-                               NULL, FALSE) == 0) {
+        if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, bytes,
+                               NULL, NULL) == 0) {
           free(str_utf8);
           free(str_utf8);
           return NULL;
           return NULL;
         }
         }

+ 32 - 37
Utilities/cmcurl/lib/curl_ntlm_core.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -38,7 +38,7 @@
    3. USE_GNUTLS
    3. USE_GNUTLS
    4. USE_NSS
    4. USE_NSS
    5. USE_MBEDTLS
    5. USE_MBEDTLS
-   6. USE_DARWINSSL
+   6. USE_SECTRANSP
    7. USE_OS400CRYPTO
    7. USE_OS400CRYPTO
    8. USE_WIN32_CRYPTO
    8. USE_WIN32_CRYPTO
 
 
@@ -54,23 +54,15 @@
 
 
 #ifdef USE_OPENSSL
 #ifdef USE_OPENSSL
 
 
-#  ifdef USE_OPENSSL
-#    include <openssl/des.h>
-#    ifndef OPENSSL_NO_MD4
-#      include <openssl/md4.h>
-#    endif
-#    include <openssl/md5.h>
-#    include <openssl/ssl.h>
-#    include <openssl/rand.h>
+#  include <openssl/des.h>
+#  ifndef OPENSSL_NO_MD4
+#    include <openssl/md4.h>
 #  else
 #  else
-#    include <des.h>
-#    ifndef OPENSSL_NO_MD4
-#      include <md4.h>
-#    endif
-#    include <md5.h>
-#    include <ssl.h>
-#    include <rand.h>
+#    include "curl_md4.h"
 #  endif
 #  endif
+#  include <openssl/md5.h>
+#  include <openssl/ssl.h>
+#  include <openssl/rand.h>
 #  if (OPENSSL_VERSION_NUMBER < 0x00907001L)
 #  if (OPENSSL_VERSION_NUMBER < 0x00907001L)
 #    define DES_key_schedule des_key_schedule
 #    define DES_key_schedule des_key_schedule
 #    define DES_cblock des_cblock
 #    define DES_cblock des_cblock
@@ -111,7 +103,7 @@
 #    include "curl_md4.h"
 #    include "curl_md4.h"
 #  endif
 #  endif
 
 
-#elif defined(USE_DARWINSSL)
+#elif defined(USE_SECTRANSP)
 
 
 #  include <CommonCrypto/CommonCryptor.h>
 #  include <CommonCrypto/CommonCryptor.h>
 #  include <CommonCrypto/CommonDigest.h>
 #  include <CommonCrypto/CommonDigest.h>
@@ -300,7 +292,7 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out,
   return mbedtls_des_crypt_ecb(&ctx, in, out) == 0;
   return mbedtls_des_crypt_ecb(&ctx, in, out) == 0;
 }
 }
 
 
-#elif defined(USE_DARWINSSL)
+#elif defined(USE_SECTRANSP)
 
 
 static bool encrypt_des(const unsigned char *in, unsigned char *out,
 static bool encrypt_des(const unsigned char *in, unsigned char *out,
                         const unsigned char *key_56)
                         const unsigned char *key_56)
@@ -447,7 +439,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
   setup_des_key(keys + 14, &des);
   setup_des_key(keys + 14, &des);
   gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
   gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
   gcry_cipher_close(des);
   gcry_cipher_close(des);
-#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \
+#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
   || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
   || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
   encrypt_des(plaintext, results, keys);
   encrypt_des(plaintext, results, keys);
   encrypt_des(plaintext, results + 8, keys + 7);
   encrypt_des(plaintext, results + 8, keys + 7);
@@ -511,7 +503,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
     setup_des_key(pw + 7, &des);
     setup_des_key(pw + 7, &des);
     gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
     gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
     gcry_cipher_close(des);
     gcry_cipher_close(des);
-#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \
+#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_SECTRANSP) \
   || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
   || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
     encrypt_des(magic, lmbuffer, pw);
     encrypt_des(magic, lmbuffer, pw);
     encrypt_des(magic, lmbuffer + 8, pw + 7);
     encrypt_des(magic, lmbuffer + 8, pw + 7);
@@ -578,10 +570,14 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
   {
   {
     /* Create NT hashed password. */
     /* Create NT hashed password. */
 #ifdef USE_OPENSSL
 #ifdef USE_OPENSSL
+#if !defined(OPENSSL_NO_MD4)
     MD4_CTX MD4pw;
     MD4_CTX MD4pw;
     MD4_Init(&MD4pw);
     MD4_Init(&MD4pw);
     MD4_Update(&MD4pw, pw, 2 * len);
     MD4_Update(&MD4pw, pw, 2 * len);
     MD4_Final(ntbuffer, &MD4pw);
     MD4_Final(ntbuffer, &MD4pw);
+#else
+    Curl_md4it(ntbuffer, pw, 2 * len);
+#endif
 #elif defined(USE_GNUTLS_NETTLE)
 #elif defined(USE_GNUTLS_NETTLE)
     struct md4_ctx MD4pw;
     struct md4_ctx MD4pw;
     md4_init(&MD4pw);
     md4_init(&MD4pw);
@@ -601,7 +597,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
 #else
 #else
     Curl_md4it(ntbuffer, pw, 2 * len);
     Curl_md4it(ntbuffer, pw, 2 * len);
 #endif
 #endif
-#elif defined(USE_DARWINSSL)
+#elif defined(USE_SECTRANSP)
     (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
     (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
 #elif defined(USE_OS400CRYPTO)
 #elif defined(USE_OS400CRYPTO)
     Curl_md4it(ntbuffer, pw, 2 * len);
     Curl_md4it(ntbuffer, pw, 2 * len);
@@ -631,9 +627,9 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
 #if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI)
 #if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI)
 
 
 /* This returns the HMAC MD5 digest */
 /* This returns the HMAC MD5 digest */
-CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
-                       const unsigned char *data, unsigned int datalen,
-                       unsigned char *output)
+static CURLcode hmac_md5(const unsigned char *key, unsigned int keylen,
+                         const unsigned char *data, unsigned int datalen,
+                         unsigned char *output)
 {
 {
   HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen);
   HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen);
 
 
@@ -678,9 +674,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
   ascii_uppercase_to_unicode_le(identity, user, userlen);
   ascii_uppercase_to_unicode_le(identity, user, userlen);
   ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
   ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
 
 
-  result = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len),
-                         ntlmv2hash);
-
+  result = hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len),
+                    ntlmv2hash);
   free(identity);
   free(identity);
 
 
   return result;
   return result;
@@ -753,12 +748,12 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;
 
 
   /* Create the BLOB structure */
   /* Create the BLOB structure */
-  snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
-           "%c%c%c%c"   /* NTLMv2_BLOB_SIGNATURE */
-           "%c%c%c%c",  /* Reserved = 0 */
-           NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
-           NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
-           0, 0, 0, 0);
+  msnprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
+            "%c%c%c%c"   /* NTLMv2_BLOB_SIGNATURE */
+            "%c%c%c%c",  /* Reserved = 0 */
+            NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
+            NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3],
+            0, 0, 0, 0);
 
 
   Curl_write64_le(tw, ptr + 24);
   Curl_write64_le(tw, ptr + 24);
   memcpy(ptr + 32, challenge_client, 8);
   memcpy(ptr + 32, challenge_client, 8);
@@ -766,8 +761,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
 
 
   /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
   /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
   memcpy(ptr + 8, &ntlm->nonce[0], 8);
   memcpy(ptr + 8, &ntlm->nonce[0], 8);
-  result = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8,
-                         NTLMv2_BLOB_LEN + 8, hmac_output);
+  result = hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8,
+                    NTLMv2_BLOB_LEN + 8, hmac_output);
   if(result) {
   if(result) {
     free(ptr);
     free(ptr);
     return result;
     return result;
@@ -809,7 +804,7 @@ CURLcode  Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
   memcpy(&data[0], challenge_server, 8);
   memcpy(&data[0], challenge_server, 8);
   memcpy(&data[8], challenge_client, 8);
   memcpy(&data[8], challenge_client, 8);
 
 
-  result = Curl_hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output);
+  result = hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output);
   if(result)
   if(result)
     return result;
     return result;
 
 

+ 1 - 3
Utilities/cmcurl/lib/curl_ntlm_core.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -43,9 +43,7 @@
 
 
 /* Define USE_NTRESPONSES in order to make the type-3 message include
 /* Define USE_NTRESPONSES in order to make the type-3 message include
  * the NT response message. */
  * the NT response message. */
-#if !defined(USE_OPENSSL) || !defined(OPENSSL_NO_MD4)
 #define USE_NTRESPONSES
 #define USE_NTRESPONSES
-#endif
 
 
 /* Define USE_NTLM2SESSION in order to make the type-3 message include the
 /* Define USE_NTLM2SESSION in order to make the type-3 message include the
    NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a
    NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a

+ 67 - 19
Utilities/cmcurl/lib/curl_ntlm_wb.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -53,6 +53,8 @@
 #include "url.h"
 #include "url.h"
 #include "strerror.h"
 #include "strerror.h"
 #include "strdup.h"
 #include "strdup.h"
+#include "strcase.h"
+
 /* The last 3 #include files should be in this order */
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "curl_memory.h"
@@ -74,7 +76,7 @@
 #  define sclose_nolog(x)  close((x))
 #  define sclose_nolog(x)  close((x))
 #endif
 #endif
 
 
-void Curl_ntlm_wb_cleanup(struct connectdata *conn)
+void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn)
 {
 {
   if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
   if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
     sclose(conn->ntlm_auth_hlpr_socket);
     sclose(conn->ntlm_auth_hlpr_socket);
@@ -124,6 +126,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
   struct passwd pw, *pw_res;
   struct passwd pw, *pw_res;
   char pwbuf[1024];
   char pwbuf[1024];
 #endif
 #endif
+  char buffer[STRERROR_LEN];
 
 
   /* Return if communication with ntlm_auth already set up */
   /* Return if communication with ntlm_auth already set up */
   if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
   if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
@@ -179,13 +182,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
 
 
   if(access(ntlm_auth, X_OK) != 0) {
   if(access(ntlm_auth, X_OK) != 0) {
     failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s",
     failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s",
-          ntlm_auth, errno, Curl_strerror(conn, errno));
+          ntlm_auth, errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     goto done;
     goto done;
   }
   }
 
 
   if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
   if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
     failf(conn->data, "Could not open socket pair. errno %d: %s",
     failf(conn->data, "Could not open socket pair. errno %d: %s",
-          errno, Curl_strerror(conn, errno));
+          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     goto done;
     goto done;
   }
   }
 
 
@@ -194,7 +197,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
     sclose(sockfds[0]);
     sclose(sockfds[0]);
     sclose(sockfds[1]);
     sclose(sockfds[1]);
     failf(conn->data, "Could not fork. errno %d: %s",
     failf(conn->data, "Could not fork. errno %d: %s",
-          errno, Curl_strerror(conn, errno));
+          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     goto done;
     goto done;
   }
   }
   else if(!child_pid) {
   else if(!child_pid) {
@@ -206,13 +209,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
     sclose_nolog(sockfds[0]);
     sclose_nolog(sockfds[0]);
     if(dup2(sockfds[1], STDIN_FILENO) == -1) {
     if(dup2(sockfds[1], STDIN_FILENO) == -1) {
       failf(conn->data, "Could not redirect child stdin. errno %d: %s",
       failf(conn->data, "Could not redirect child stdin. errno %d: %s",
-            errno, Curl_strerror(conn, errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       exit(1);
       exit(1);
     }
     }
 
 
     if(dup2(sockfds[1], STDOUT_FILENO) == -1) {
     if(dup2(sockfds[1], STDOUT_FILENO) == -1) {
       failf(conn->data, "Could not redirect child stdout. errno %d: %s",
       failf(conn->data, "Could not redirect child stdout. errno %d: %s",
-            errno, Curl_strerror(conn, errno));
+            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       exit(1);
       exit(1);
     }
     }
 
 
@@ -232,7 +235,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
 
 
     sclose_nolog(sockfds[1]);
     sclose_nolog(sockfds[1]);
     failf(conn->data, "Could not execl(). errno %d: %s",
     failf(conn->data, "Could not execl(). errno %d: %s",
-          errno, Curl_strerror(conn, errno));
+          errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     exit(1);
     exit(1);
   }
   }
 
 
@@ -332,6 +335,48 @@ done:
   return CURLE_REMOTE_ACCESS_DENIED;
   return CURLE_REMOTE_ACCESS_DENIED;
 }
 }
 
 
+CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
+                            bool proxy,
+                            const char *header)
+{
+  curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
+
+  if(!checkprefix("NTLM", header))
+    return CURLE_BAD_CONTENT_ENCODING;
+
+  header += strlen("NTLM");
+  while(*header && ISSPACE(*header))
+    header++;
+
+  if(*header) {
+    conn->challenge_header = strdup(header);
+    if(!conn->challenge_header)
+      return CURLE_OUT_OF_MEMORY;
+
+    *state = NTLMSTATE_TYPE2; /* We got a type-2 message */
+  }
+  else {
+    if(*state == NTLMSTATE_LAST) {
+      infof(conn->data, "NTLM auth restarted\n");
+      Curl_http_auth_cleanup_ntlm_wb(conn);
+    }
+    else if(*state == NTLMSTATE_TYPE3) {
+      infof(conn->data, "NTLM handshake rejected\n");
+      Curl_http_auth_cleanup_ntlm_wb(conn);
+      *state = NTLMSTATE_NONE;
+      return CURLE_REMOTE_ACCESS_DENIED;
+    }
+    else if(*state >= NTLMSTATE_TYPE1) {
+      infof(conn->data, "NTLM handshake failure (internal error)\n");
+      return CURLE_REMOTE_ACCESS_DENIED;
+    }
+
+    *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
+  }
+
+  return CURLE_OK;
+}
+
 /*
 /*
  * This is for creating ntlm header output by delegating challenge/response
  * This is for creating ntlm header output by delegating challenge/response
  * to Samba's winbind daemon helper ntlm_auth.
  * to Samba's winbind daemon helper ntlm_auth.
@@ -344,8 +389,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   char **allocuserpwd;
   char **allocuserpwd;
   /* point to the name and password for this */
   /* point to the name and password for this */
   const char *userp;
   const char *userp;
-  /* point to the correct struct with this */
-  struct ntlmdata *ntlm;
+  curlntlm *state;
   struct auth *authp;
   struct auth *authp;
 
 
   CURLcode res = CURLE_OK;
   CURLcode res = CURLE_OK;
@@ -357,13 +401,13 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   if(proxy) {
   if(proxy) {
     allocuserpwd = &conn->allocptr.proxyuserpwd;
     allocuserpwd = &conn->allocptr.proxyuserpwd;
     userp = conn->http_proxy.user;
     userp = conn->http_proxy.user;
-    ntlm = &conn->proxyntlm;
+    state = &conn->proxy_ntlm_state;
     authp = &conn->data->state.authproxy;
     authp = &conn->data->state.authproxy;
   }
   }
   else {
   else {
     allocuserpwd = &conn->allocptr.userpwd;
     allocuserpwd = &conn->allocptr.userpwd;
     userp = conn->user;
     userp = conn->user;
-    ntlm = &conn->ntlm;
+    state = &conn->http_ntlm_state;
     authp = &conn->data->state.authhost;
     authp = &conn->data->state.authhost;
   }
   }
   authp->done = FALSE;
   authp->done = FALSE;
@@ -372,7 +416,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   if(!userp)
   if(!userp)
     userp = "";
     userp = "";
 
 
-  switch(ntlm->state) {
+  switch(*state) {
   case NTLMSTATE_TYPE1:
   case NTLMSTATE_TYPE1:
   default:
   default:
     /* Use Samba's 'winbind' daemon to support NTLM authentication,
     /* Use Samba's 'winbind' daemon to support NTLM authentication,
@@ -391,7 +435,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
     res = ntlm_wb_init(conn, userp);
     res = ntlm_wb_init(conn, userp);
     if(res)
     if(res)
       return res;
       return res;
-    res = ntlm_wb_response(conn, "YR\n", ntlm->state);
+    res = ntlm_wb_response(conn, "YR\n", *state);
     if(res)
     if(res)
       return res;
       return res;
 
 
@@ -405,11 +449,12 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
       return CURLE_OUT_OF_MEMORY;
       return CURLE_OUT_OF_MEMORY;
     conn->response_header = NULL;
     conn->response_header = NULL;
     break;
     break;
+
   case NTLMSTATE_TYPE2:
   case NTLMSTATE_TYPE2:
     input = aprintf("TT %s\n", conn->challenge_header);
     input = aprintf("TT %s\n", conn->challenge_header);
     if(!input)
     if(!input)
       return CURLE_OUT_OF_MEMORY;
       return CURLE_OUT_OF_MEMORY;
-    res = ntlm_wb_response(conn, input, ntlm->state);
+    res = ntlm_wb_response(conn, input, *state);
     free(input);
     free(input);
     input = NULL;
     input = NULL;
     if(res)
     if(res)
@@ -420,17 +465,20 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
                             proxy ? "Proxy-" : "",
                             proxy ? "Proxy-" : "",
                             conn->response_header);
                             conn->response_header);
     DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
     DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
-    ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
+    *state = NTLMSTATE_TYPE3; /* we sent a type-3 */
     authp->done = TRUE;
     authp->done = TRUE;
-    Curl_ntlm_wb_cleanup(conn);
+    Curl_http_auth_cleanup_ntlm_wb(conn);
     if(!*allocuserpwd)
     if(!*allocuserpwd)
       return CURLE_OUT_OF_MEMORY;
       return CURLE_OUT_OF_MEMORY;
     break;
     break;
+
   case NTLMSTATE_TYPE3:
   case NTLMSTATE_TYPE3:
     /* connection is already authenticated,
     /* connection is already authenticated,
      * don't send a header in future requests */
      * don't send a header in future requests */
-    free(*allocuserpwd);
-    *allocuserpwd = NULL;
+    *state = NTLMSTATE_LAST;
+    /* FALLTHROUGH */
+  case NTLMSTATE_LAST:
+    Curl_safefree(*allocuserpwd);
     authp->done = TRUE;
     authp->done = TRUE;
     break;
     break;
   }
   }

+ 7 - 4
Utilities/cmcurl/lib/curl_ntlm_wb.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -27,11 +27,14 @@
 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
     defined(NTLM_WB_ENABLED)
     defined(NTLM_WB_ENABLED)
 
 
-/* this is for creating ntlm header output by delegating challenge/response
-   to Samba's winbind daemon helper ntlm_auth */
+/* this is for ntlm header input */
+CURLcode Curl_input_ntlm_wb(struct connectdata *conn, bool proxy,
+                            const char *header);
+
+/* this is for creating ntlm header output */
 CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy);
 CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy);
 
 
-void Curl_ntlm_wb_cleanup(struct connectdata *conn);
+void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn);
 
 
 #endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */
 #endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */
 
 

+ 5 - 1
Utilities/cmcurl/lib/curl_path.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,8 @@
 
 
 #include "curl_setup.h"
 #include "curl_setup.h"
 
 
+#if defined(USE_SSH)
+
 #include <curl/curl.h>
 #include <curl/curl.h>
 #include "curl_memory.h"
 #include "curl_memory.h"
 #include "curl_path.h"
 #include "curl_path.h"
@@ -193,3 +195,5 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir)
   Curl_safefree(*path);
   Curl_safefree(*path);
   return CURLE_QUOTE_ERROR;
   return CURLE_QUOTE_ERROR;
 }
 }
+
+#endif /* if SSH is used */

+ 4 - 12
Utilities/cmcurl/lib/curl_printf.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@
 
 
 # undef printf
 # undef printf
 # undef fprintf
 # undef fprintf
-# undef snprintf
+# undef msnprintf
 # undef vprintf
 # undef vprintf
 # undef vfprintf
 # undef vfprintf
 # undef vsnprintf
 # undef vsnprintf
@@ -39,18 +39,10 @@
 # undef vaprintf
 # undef vaprintf
 # define printf curl_mprintf
 # define printf curl_mprintf
 # define fprintf curl_mfprintf
 # define fprintf curl_mfprintf
-# define snprintf curl_msnprintf
+# define msnprintf curl_msnprintf
 # define vprintf curl_mvprintf
 # define vprintf curl_mvprintf
 # define vfprintf curl_mvfprintf
 # define vfprintf curl_mvfprintf
-# define vsnprintf curl_mvsnprintf
+# define mvsnprintf curl_mvsnprintf
 # define aprintf curl_maprintf
 # define aprintf curl_maprintf
 # define vaprintf curl_mvaprintf
 # define vaprintf curl_mvaprintf
-
-/* We define away the sprintf functions unconditonally since we don't want
-   internal code to be using them, intentionally or by mistake!*/
-# undef sprintf
-# undef vsprintf
-# define sprintf sprintf_was_used
-# define vsprintf vsprintf_was_used
-
 #endif /* HEADER_CURL_PRINTF_H */
 #endif /* HEADER_CURL_PRINTF_H */

+ 5 - 4
Utilities/cmcurl/lib/curl_rtmp.c

@@ -5,7 +5,7 @@
  *                | (__| |_| |  _ <| |___
  *                | (__| |_| |  _ <| |___
  *                 \___|\___/|_| \_\_____|
  *                 \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 2012 - 2015, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <[email protected]>, et al.
  * Copyright (C) 2010, Howard Chu, <[email protected]>
  * Copyright (C) 2010, Howard Chu, <[email protected]>
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
@@ -239,17 +239,18 @@ static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
 
 
 static CURLcode rtmp_do(struct connectdata *conn, bool *done)
 static CURLcode rtmp_do(struct connectdata *conn, bool *done)
 {
 {
+  struct Curl_easy *data = conn->data;
   RTMP *r = conn->proto.generic;
   RTMP *r = conn->proto.generic;
 
 
   if(!RTMP_ConnectStream(r, 0))
   if(!RTMP_ConnectStream(r, 0))
     return CURLE_FAILED_INIT;
     return CURLE_FAILED_INIT;
 
 
   if(conn->data->set.upload) {
   if(conn->data->set.upload) {
-    Curl_pgrsSetUploadSize(conn->data, conn->data->state.infilesize);
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+    Curl_pgrsSetUploadSize(data, data->state.infilesize);
+    Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
   }
   }
   else
   else
-    Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
   *done = TRUE;
   *done = TRUE;
   return CURLE_OK;
   return CURLE_OK;
 }
 }

+ 20 - 20
Utilities/cmcurl/lib/curl_sasl.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2012 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -31,6 +31,9 @@
 
 
 #include "curl_setup.h"
 #include "curl_setup.h"
 
 
+#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \
+  !defined(CURL_DISABLE_POP3)
+
 #include <curl/curl.h>
 #include <curl/curl.h>
 #include "urldata.h"
 #include "urldata.h"
 
 
@@ -83,14 +86,14 @@ void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
 #if defined(USE_KERBEROS5)
 #if defined(USE_KERBEROS5)
   /* Cleanup the gssapi structure */
   /* Cleanup the gssapi structure */
   if(authused == SASL_MECH_GSSAPI) {
   if(authused == SASL_MECH_GSSAPI) {
-    Curl_auth_gssapi_cleanup(&conn->krb5);
+    Curl_auth_cleanup_gssapi(&conn->krb5);
   }
   }
 #endif
 #endif
 
 
 #if defined(USE_NTLM)
 #if defined(USE_NTLM)
   /* Cleanup the NTLM structure */
   /* Cleanup the NTLM structure */
   if(authused == SASL_MECH_NTLM) {
   if(authused == SASL_MECH_NTLM) {
-    Curl_auth_ntlm_cleanup(&conn->ntlm);
+    Curl_auth_cleanup_ntlm(&conn->ntlm);
   }
   }
 #endif
 #endif
 
 
@@ -290,7 +293,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
 #if defined(USE_KERBEROS5)
 #if defined(USE_KERBEROS5)
     if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() &&
     if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() &&
        Curl_auth_user_contains_domain(conn->user)) {
        Curl_auth_user_contains_domain(conn->user)) {
-      sasl->mutual_auth = FALSE; /* TODO: Calculate mutual authentication */
+      sasl->mutual_auth = FALSE;
       mech = SASL_MECH_STRING_GSSAPI;
       mech = SASL_MECH_STRING_GSSAPI;
       state1 = SASL_GSSAPI;
       state1 = SASL_GSSAPI;
       state2 = SASL_GSSAPI_TOKEN;
       state2 = SASL_GSSAPI_TOKEN;
@@ -300,8 +303,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
         result = Curl_auth_create_gssapi_user_message(data, conn->user,
         result = Curl_auth_create_gssapi_user_message(data, conn->user,
                                                       conn->passwd,
                                                       conn->passwd,
                                                       service,
                                                       service,
-                                                      data->easy_conn->
-                                                            host.name,
+                                                      data->conn->host.name,
                                                       sasl->mutual_auth,
                                                       sasl->mutual_auth,
                                                       NULL, &conn->krb5,
                                                       NULL, &conn->krb5,
                                                       &resp, &len);
                                                       &resp, &len);
@@ -358,10 +360,9 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
       sasl->authused = SASL_MECH_XOAUTH2;
       sasl->authused = SASL_MECH_XOAUTH2;
 
 
       if(force_ir || data->set.sasl_ir)
       if(force_ir || data->set.sasl_ir)
-        result = Curl_auth_create_oauth_bearer_message(data, conn->user,
-                                                       NULL, 0,
-                                                       conn->oauth_bearer,
-                                                       &resp, &len);
+        result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
+                                                        conn->oauth_bearer,
+                                                        &resp, &len);
     }
     }
     else if(enabledmechs & SASL_MECH_PLAIN) {
     else if(enabledmechs & SASL_MECH_PLAIN) {
       mech = SASL_MECH_STRING_PLAIN;
       mech = SASL_MECH_STRING_PLAIN;
@@ -369,8 +370,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
       sasl->authused = SASL_MECH_PLAIN;
       sasl->authused = SASL_MECH_PLAIN;
 
 
       if(force_ir || data->set.sasl_ir)
       if(force_ir || data->set.sasl_ir)
-        result = Curl_auth_create_plain_message(data, conn->user, conn->passwd,
-                                                &resp, &len);
+        result = Curl_auth_create_plain_message(data, NULL, conn->user,
+                                                conn->passwd, &resp, &len);
     }
     }
     else if(enabledmechs & SASL_MECH_LOGIN) {
     else if(enabledmechs & SASL_MECH_LOGIN) {
       mech = SASL_MECH_STRING_LOGIN;
       mech = SASL_MECH_STRING_LOGIN;
@@ -452,9 +453,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
     *progress = SASL_DONE;
     *progress = SASL_DONE;
     return result;
     return result;
   case SASL_PLAIN:
   case SASL_PLAIN:
-    result = Curl_auth_create_plain_message(data, conn->user, conn->passwd,
-                                            &resp,
-                                            &len);
+    result = Curl_auth_create_plain_message(data, NULL, conn->user,
+                                            conn->passwd, &resp, &len);
     break;
     break;
   case SASL_LOGIN:
   case SASL_LOGIN:
     result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
     result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
@@ -517,7 +517,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
     result = Curl_auth_create_gssapi_user_message(data, conn->user,
     result = Curl_auth_create_gssapi_user_message(data, conn->user,
                                                   conn->passwd,
                                                   conn->passwd,
                                                   service,
                                                   service,
-                                                  data->easy_conn->host.name,
+                                                  data->conn->host.name,
                                                   sasl->mutual_auth, NULL,
                                                   sasl->mutual_auth, NULL,
                                                   &conn->krb5,
                                                   &conn->krb5,
                                                   &resp, &len);
                                                   &resp, &len);
@@ -563,10 +563,9 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
       newstate = SASL_OAUTH2_RESP;
       newstate = SASL_OAUTH2_RESP;
     }
     }
     else
     else
-      result = Curl_auth_create_oauth_bearer_message(data, conn->user,
-                                                     NULL, 0,
-                                                     conn->oauth_bearer,
-                                                     &resp, &len);
+      result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
+                                                      conn->oauth_bearer,
+                                                      &resp, &len);
     break;
     break;
 
 
   case SASL_OAUTH2_RESP:
   case SASL_OAUTH2_RESP:
@@ -627,3 +626,4 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
 
 
   return result;
   return result;
 }
 }
+#endif /* protocols are enabled that use SASL */

+ 20 - 9
Utilities/cmcurl/lib/curl_setup.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -314,11 +314,12 @@
 #endif
 #endif
 
 
 #ifdef __AMIGA__
 #ifdef __AMIGA__
-#  ifndef __ixemul__
-#    include <exec/types.h>
-#    include <exec/execbase.h>
-#    include <proto/exec.h>
-#    include <proto/dos.h>
+#  include <exec/types.h>
+#  include <exec/execbase.h>
+#  include <proto/exec.h>
+#  include <proto/dos.h>
+#  ifdef HAVE_PROTO_BSDSOCKET_H
+#    include <proto/bsdsocket.h> /* ensure bsdsocket.library use */
 #    define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
 #    define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0)
 #  endif
 #  endif
 #endif
 #endif
@@ -661,9 +662,9 @@ int netware_init(void);
 #define LIBIDN_REQUIRED_VERSION "0.4.1"
 #define LIBIDN_REQUIRED_VERSION "0.4.1"
 
 
 #if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
 #if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \
-    defined(USE_POLARSSL) || defined(USE_AXTLS) || defined(USE_MBEDTLS) || \
+    defined(USE_POLARSSL) || defined(USE_MBEDTLS) || \
     defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
     defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
-    defined(USE_DARWINSSL) || defined(USE_GSKIT) || defined(USE_MESALINK)
+    defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK)
 #define USE_SSL    /* SSL support has been enabled */
 #define USE_SSL    /* SSL support has been enabled */
 #endif
 #endif
 
 
@@ -682,7 +683,7 @@ int netware_init(void);
 /* Single point where USE_NTLM definition might be defined */
 /* Single point where USE_NTLM definition might be defined */
 #if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
 #if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
 #if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
 #if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
-    defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \
+    defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
     defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
     defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
     defined(USE_MBEDTLS)
     defined(USE_MBEDTLS)
 
 
@@ -700,6 +701,10 @@ int netware_init(void);
 #error "No longer supported. Set CURLOPT_CAINFO at runtime instead."
 #error "No longer supported. Set CURLOPT_CAINFO at runtime instead."
 #endif
 #endif
 
 
+#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) || defined(USE_WOLFSSH)
+#define USE_SSH
+#endif
+
 /*
 /*
  * Provide a mechanism to silence picky compilers, such as gcc 4.6+.
  * Provide a mechanism to silence picky compilers, such as gcc 4.6+.
  * Parameters should of course normally not be unused, but for example when
  * Parameters should of course normally not be unused, but for example when
@@ -831,4 +836,10 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
                size_t buflen, struct passwd **result);
                size_t buflen, struct passwd **result);
 #endif
 #endif
 
 
+#ifdef DEBUGBUILD
+#define UNITTEST
+#else
+#define UNITTEST static
+#endif
+
 #endif /* HEADER_CURL_SETUP_H */
 #endif /* HEADER_CURL_SETUP_H */

+ 5 - 6
Utilities/cmcurl/lib/curlx.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -81,22 +81,21 @@
 # undef printf
 # undef printf
 # undef fprintf
 # undef fprintf
 # undef sprintf
 # undef sprintf
-# undef snprintf
+# undef msnprintf
 # undef vprintf
 # undef vprintf
 # undef vfprintf
 # undef vfprintf
 # undef vsprintf
 # undef vsprintf
-# undef vsnprintf
+# undef mvsnprintf
 # undef aprintf
 # undef aprintf
 # undef vaprintf
 # undef vaprintf
 
 
 # define printf curlx_mprintf
 # define printf curlx_mprintf
 # define fprintf curlx_mfprintf
 # define fprintf curlx_mfprintf
 # define sprintf curlx_msprintf
 # define sprintf curlx_msprintf
-# define snprintf curlx_msnprintf
+# define msnprintf curlx_msnprintf
 # define vprintf curlx_mvprintf
 # define vprintf curlx_mvprintf
 # define vfprintf curlx_mvfprintf
 # define vfprintf curlx_mvfprintf
-# define vsprintf curlx_mvsprintf
-# define vsnprintf curlx_mvsnprintf
+# define mvsnprintf curlx_mvsnprintf
 # define aprintf curlx_maprintf
 # define aprintf curlx_maprintf
 # define vaprintf curlx_mvaprintf
 # define vaprintf curlx_mvaprintf
 #endif /* ENABLE_CURLX_PRINTF */
 #endif /* ENABLE_CURLX_PRINTF */

+ 4 - 7
Utilities/cmcurl/lib/dict.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -137,7 +137,6 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
 
 
   char *path = data->state.up.path;
   char *path = data->state.up.path;
-  curl_off_t *bytecount = &data->req.bytecount;
 
 
   *done = TRUE; /* unconditionally */
   *done = TRUE; /* unconditionally */
 
 
@@ -200,8 +199,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
       failf(data, "Failed sending DICT request");
       failf(data, "Failed sending DICT request");
       return result;
       return result;
     }
     }
-    Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-                        -1, NULL); /* no upload */
+    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); /* no upload */
   }
   }
   else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
   else if(strncasecompare(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
           strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
           strncasecompare(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
@@ -247,8 +245,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
       failf(data, "Failed sending DICT request");
       failf(data, "Failed sending DICT request");
       return result;
       return result;
     }
     }
-    Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-                        -1, NULL); /* no upload */
+    Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
   }
   }
   else {
   else {
 
 
@@ -270,7 +267,7 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
         return result;
         return result;
       }
       }
 
 
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, -1, NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
     }
     }
   }
   }
 
 

+ 87 - 40
Utilities/cmcurl/lib/doh.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2018 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -22,17 +22,19 @@
 
 
 #include "curl_setup.h"
 #include "curl_setup.h"
 
 
+#ifndef CURL_DISABLE_DOH
+
 #include "urldata.h"
 #include "urldata.h"
 #include "curl_addrinfo.h"
 #include "curl_addrinfo.h"
 #include "doh.h"
 #include "doh.h"
 
 
-#ifdef USE_NGHTTP2
 #include "sendf.h"
 #include "sendf.h"
 #include "multiif.h"
 #include "multiif.h"
 #include "url.h"
 #include "url.h"
 #include "share.h"
 #include "share.h"
 #include "curl_base64.h"
 #include "curl_base64.h"
 #include "connect.h"
 #include "connect.h"
+#include "strdup.h"
 /* The last 3 #include files should be in this order */
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "curl_memory.h"
@@ -143,8 +145,8 @@ doh_write_cb(void *contents, size_t size, size_t nmemb, void *userp)
     /* suspiciously much for us */
     /* suspiciously much for us */
     return 0;
     return 0;
 
 
-  mem->memory = realloc(mem->memory, mem->size + realsize);
-  if(mem->memory == NULL)
+  mem->memory = Curl_saferealloc(mem->memory, mem->size + realsize);
+  if(!mem->memory)
     /* out of memory! */
     /* out of memory! */
     return 0;
     return 0;
 
 
@@ -160,7 +162,7 @@ static int Curl_doh_done(struct Curl_easy *doh, CURLcode result)
   struct Curl_easy *data = doh->set.dohfor;
   struct Curl_easy *data = doh->set.dohfor;
   /* so one of the DOH request done for the 'data' transfer is now complete! */
   /* so one of the DOH request done for the 'data' transfer is now complete! */
   data->req.doh.pending--;
   data->req.doh.pending--;
-  infof(data, "a DOH request is completed, %d to go\n", data->req.doh.pending);
+  infof(data, "a DOH request is completed, %u to go\n", data->req.doh.pending);
   if(result)
   if(result)
     infof(data, "DOH request %s\n", curl_easy_strerror(result));
     infof(data, "DOH request %s\n", curl_easy_strerror(result));
 
 
@@ -173,8 +175,12 @@ static int Curl_doh_done(struct Curl_easy *doh, CURLcode result)
   return 0;
   return 0;
 }
 }
 
 
-#define ERROR_CHECK_SETOPT(x,y) result = curl_easy_setopt(doh, x, y);   \
-  if(result) goto error
+#define ERROR_CHECK_SETOPT(x,y) \
+do {                                      \
+  result = curl_easy_setopt(doh, x, y);   \
+  if(result)                              \
+    goto error;                           \
+} WHILE_FALSE
 
 
 static CURLcode dohprobe(struct Curl_easy *data,
 static CURLcode dohprobe(struct Curl_easy *data,
                          struct dnsprobe *p, DNStype dnstype,
                          struct dnsprobe *p, DNStype dnstype,
@@ -234,13 +240,76 @@ static CURLcode dohprobe(struct Curl_easy *data,
       ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->dohlen);
       ERROR_CHECK_SETOPT(CURLOPT_POSTFIELDSIZE, (long)p->dohlen);
     }
     }
     ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
     ERROR_CHECK_SETOPT(CURLOPT_HTTPHEADER, headers);
+#ifdef USE_NGHTTP2
     ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
     ERROR_CHECK_SETOPT(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
+#endif
 #ifndef CURLDEBUG
 #ifndef CURLDEBUG
     /* enforce HTTPS if not debug */
     /* enforce HTTPS if not debug */
     ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
     ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
 #endif
 #endif
     ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
     ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms);
-    ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
+    if(data->set.verbose)
+      ERROR_CHECK_SETOPT(CURLOPT_VERBOSE, 1L);
+    if(data->set.no_signal)
+      ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L);
+
+    /* Inherit *some* SSL options from the user's transfer. This is a
+       best-guess as to which options are needed for compatibility. #3661 */
+    if(data->set.ssl.falsestart)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_FALSESTART, 1L);
+    if(data->set.ssl.primary.verifyhost)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, 2L);
+    if(data->set.proxy_ssl.primary.verifyhost)
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYHOST, 2L);
+    if(data->set.ssl.primary.verifypeer)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, 1L);
+    if(data->set.proxy_ssl.primary.verifypeer)
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_VERIFYPEER, 1L);
+    if(data->set.ssl.primary.verifystatus)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, 1L);
+    if(data->set.str[STRING_SSL_CAFILE_ORIG]) {
+      ERROR_CHECK_SETOPT(CURLOPT_CAINFO,
+        data->set.str[STRING_SSL_CAFILE_ORIG]);
+    }
+    if(data->set.str[STRING_SSL_CAFILE_PROXY]) {
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAINFO,
+        data->set.str[STRING_SSL_CAFILE_PROXY]);
+    }
+    if(data->set.str[STRING_SSL_CAPATH_ORIG]) {
+      ERROR_CHECK_SETOPT(CURLOPT_CAPATH,
+        data->set.str[STRING_SSL_CAPATH_ORIG]);
+    }
+    if(data->set.str[STRING_SSL_CAPATH_PROXY]) {
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH,
+        data->set.str[STRING_SSL_CAPATH_PROXY]);
+    }
+    if(data->set.str[STRING_SSL_CRLFILE_ORIG]) {
+      ERROR_CHECK_SETOPT(CURLOPT_CRLFILE,
+        data->set.str[STRING_SSL_CRLFILE_ORIG]);
+    }
+    if(data->set.str[STRING_SSL_CRLFILE_PROXY]) {
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_CRLFILE,
+        data->set.str[STRING_SSL_CRLFILE_PROXY]);
+    }
+    if(data->set.ssl.certinfo)
+      ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L);
+    if(data->set.str[STRING_SSL_RANDOM_FILE]) {
+      ERROR_CHECK_SETOPT(CURLOPT_RANDOM_FILE,
+        data->set.str[STRING_SSL_RANDOM_FILE]);
+    }
+    if(data->set.str[STRING_SSL_EGDSOCKET]) {
+      ERROR_CHECK_SETOPT(CURLOPT_EGDSOCKET,
+        data->set.str[STRING_SSL_EGDSOCKET]);
+    }
+    if(data->set.ssl.no_revoke)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
+    if(data->set.proxy_ssl.no_revoke)
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
+    if(data->set.ssl.fsslctx)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
+    if(data->set.ssl.fsslctxp)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_DATA, data->set.ssl.fsslctxp);
+
     doh->set.fmultidone = Curl_doh_done;
     doh->set.fmultidone = Curl_doh_done;
     doh->set.dohfor = data; /* identify for which transfer this is done */
     doh->set.dohfor = data; /* identify for which transfer this is done */
     p->easy = doh;
     p->easy = doh;
@@ -515,7 +584,6 @@ UNITTEST DOHcode doh_decode(unsigned char *doh,
   unsigned short qdcount;
   unsigned short qdcount;
   unsigned short ancount;
   unsigned short ancount;
   unsigned short type = 0;
   unsigned short type = 0;
-  unsigned short class;
   unsigned short rdlength;
   unsigned short rdlength;
   unsigned short nscount;
   unsigned short nscount;
   unsigned short arcount;
   unsigned short arcount;
@@ -524,7 +592,7 @@ UNITTEST DOHcode doh_decode(unsigned char *doh,
 
 
   if(dohlen < 12)
   if(dohlen < 12)
     return DOH_TOO_SMALL_BUFFER; /* too small */
     return DOH_TOO_SMALL_BUFFER; /* too small */
-  if(doh[0] || doh[1])
+  if(!doh || doh[0] || doh[1])
     return DOH_DNS_BAD_ID; /* bad ID */
     return DOH_DNS_BAD_ID; /* bad ID */
   rcode = doh[3] & 0x0f;
   rcode = doh[3] & 0x0f;
   if(rcode)
   if(rcode)
@@ -543,6 +611,7 @@ UNITTEST DOHcode doh_decode(unsigned char *doh,
 
 
   ancount = get16bit(doh, 6);
   ancount = get16bit(doh, 6);
   while(ancount) {
   while(ancount) {
+    unsigned short class;
     unsigned int ttl;
     unsigned int ttl;
 
 
     rc = skipqname(doh, dohlen, &index);
     rc = skipqname(doh, dohlen, &index);
@@ -660,13 +729,13 @@ static void showdoh(struct Curl_easy *data,
       char buffer[128];
       char buffer[128];
       char *ptr;
       char *ptr;
       size_t len;
       size_t len;
-      snprintf(buffer, 128, "DOH AAAA: ");
+      msnprintf(buffer, 128, "DOH AAAA: ");
       ptr = &buffer[10];
       ptr = &buffer[10];
       len = 118;
       len = 118;
       for(j = 0; j < 16; j += 2) {
       for(j = 0; j < 16; j += 2) {
         size_t l;
         size_t l;
-        snprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j],
-                 d->addr[i].ip.v6[j + 1]);
+        msnprintf(ptr, len, "%s%02x%02x", j?":":"", d->addr[i].ip.v6[j],
+                  d->addr[i].ip.v6[j + 1]);
         l = strlen(ptr);
         l = strlen(ptr);
         len -= l;
         len -= l;
         ptr += l;
         ptr += l;
@@ -827,8 +896,6 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
     DOHcode rc;
     DOHcode rc;
     DOHcode rc2;
     DOHcode rc2;
     struct dohentry de;
     struct dohentry de;
-    struct Curl_dns_entry *dns;
-    struct Curl_addrinfo *ai;
     /* remove DOH handles from multi handle and close them */
     /* remove DOH handles from multi handle and close them */
     curl_multi_remove_handle(data->multi, data->req.doh.probe[0].easy);
     curl_multi_remove_handle(data->multi, data->req.doh.probe[0].easy);
     Curl_close(data->req.doh.probe[0].easy);
     Curl_close(data->req.doh.probe[0].easy);
@@ -853,11 +920,14 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
                      &de);
                      &de);
     free(data->req.doh.probe[1].serverdoh.memory);
     free(data->req.doh.probe[1].serverdoh.memory);
     if(rc2) {
     if(rc2) {
-      infof(data, "DOG: %s type %s for %s\n", doh_strerror(rc2),
+      infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc2),
             type2name(data->req.doh.probe[1].dnstype),
             type2name(data->req.doh.probe[1].dnstype),
             data->req.doh.host);
             data->req.doh.host);
     }
     }
     if(!rc || !rc2) {
     if(!rc || !rc2) {
+      struct Curl_dns_entry *dns;
+      struct Curl_addrinfo *ai;
+
       infof(data, "DOH Host name: %s\n", data->req.doh.host);
       infof(data, "DOH Host name: %s\n", data->req.doh.host);
       showdoh(data, &de);
       showdoh(data, &de);
 
 
@@ -894,27 +964,4 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
   return CURLE_OK;
   return CURLE_OK;
 }
 }
 
 
-#else /* !USE_NGHTTP2 */
-/*
- */
-Curl_addrinfo *Curl_doh(struct connectdata *conn,
-                        const char *hostname,
-                        int port,
-                        int *waitp)
-{
-  (void)conn;
-  (void)hostname;
-  (void)port;
-  (void)waitp;
-  return NULL;
-}
-
-CURLcode Curl_doh_is_resolved(struct connectdata *conn,
-                              struct Curl_dns_entry **dnsp)
-{
-  (void)conn;
-  (void)dnsp;
-  return CURLE_NOT_BUILT_IN;
-}
-
-#endif /* USE_NGHTTP2 */
+#endif /* CURL_DISABLE_DOH */

+ 9 - 1
Utilities/cmcurl/lib/doh.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2018 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -25,6 +25,8 @@
 #include "urldata.h"
 #include "urldata.h"
 #include "curl_addrinfo.h"
 #include "curl_addrinfo.h"
 
 
+#ifndef CURL_DISABLE_DOH
+
 /*
 /*
  * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name
  * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name
  * and returns a 'Curl_addrinfo *' with the address information.
  * and returns a 'Curl_addrinfo *' with the address information.
@@ -102,4 +104,10 @@ DOHcode doh_decode(unsigned char *doh,
                    struct dohentry *d);
                    struct dohentry *d);
 void de_cleanup(struct dohentry *d);
 void de_cleanup(struct dohentry *d);
 #endif
 #endif
+
+#else /* if DOH is disabled */
+#define Curl_doh(a,b,c,d) NULL
+#define Curl_doh_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
+#endif
+
 #endif /* HEADER_CURL_DOH_H */
 #endif /* HEADER_CURL_DOH_H */

+ 27 - 84
Utilities/cmcurl/lib/easy.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -75,6 +75,7 @@
 #include "ssh.h"
 #include "ssh.h"
 #include "setopt.h"
 #include "setopt.h"
 #include "http_digest.h"
 #include "http_digest.h"
+#include "system_win32.h"
 
 
 /* The last 3 #include files should be in this order */
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_printf.h"
@@ -83,70 +84,6 @@
 
 
 void Curl_version_init(void);
 void Curl_version_init(void);
 
 
-/* win32_cleanup() is for win32 socket cleanup functionality, the opposite
-   of win32_init() */
-static void win32_cleanup(void)
-{
-#ifdef USE_WINSOCK
-  WSACleanup();
-#endif
-#ifdef USE_WINDOWS_SSPI
-  Curl_sspi_global_cleanup();
-#endif
-}
-
-/* win32_init() performs win32 socket initialization to properly setup the
-   stack to allow networking */
-static CURLcode win32_init(void)
-{
-#ifdef USE_WINSOCK
-  WORD wVersionRequested;
-  WSADATA wsaData;
-  int res;
-
-#if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
-  Error IPV6_requires_winsock2
-#endif
-
-  wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
-
-  res = WSAStartup(wVersionRequested, &wsaData);
-
-  if(res != 0)
-    /* Tell the user that we couldn't find a usable */
-    /* winsock.dll.     */
-    return CURLE_FAILED_INIT;
-
-  /* Confirm that the Windows Sockets DLL supports what we need.*/
-  /* Note that if the DLL supports versions greater */
-  /* than wVersionRequested, it will still return */
-  /* wVersionRequested in wVersion. wHighVersion contains the */
-  /* highest supported version. */
-
-  if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
-     HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) {
-    /* Tell the user that we couldn't find a usable */
-
-    /* winsock.dll. */
-    WSACleanup();
-    return CURLE_FAILED_INIT;
-  }
-  /* The Windows Sockets DLL is acceptable. Proceed. */
-#elif defined(USE_LWIPSOCK)
-  lwip_init();
-#endif
-
-#ifdef USE_WINDOWS_SSPI
-  {
-    CURLcode result = Curl_sspi_global_init();
-    if(result)
-      return result;
-  }
-#endif
-
-  return CURLE_OK;
-}
-
 /* true globals -- for curl_global_init() and curl_global_cleanup() */
 /* true globals -- for curl_global_init() and curl_global_cleanup() */
 static unsigned int  initialized;
 static unsigned int  initialized;
 static long          init_flags;
 static long          init_flags;
@@ -223,11 +160,12 @@ static CURLcode global_init(long flags, bool memoryfuncs)
     return CURLE_FAILED_INIT;
     return CURLE_FAILED_INIT;
   }
   }
 
 
-  if(flags & CURL_GLOBAL_WIN32)
-    if(win32_init()) {
-      DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
-      return CURLE_FAILED_INIT;
-    }
+#ifdef WIN32
+  if(Curl_win32_init(flags)) {
+    DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
+    return CURLE_FAILED_INIT;
+  }
+#endif
 
 
 #ifdef __AMIGA__
 #ifdef __AMIGA__
   if(!Curl_amiga_init()) {
   if(!Curl_amiga_init()) {
@@ -327,12 +265,12 @@ void curl_global_cleanup(void)
   if(--initialized)
   if(--initialized)
     return;
     return;
 
 
-  Curl_global_host_cache_dtor();
   Curl_ssl_cleanup();
   Curl_ssl_cleanup();
   Curl_resolver_global_cleanup();
   Curl_resolver_global_cleanup();
 
 
-  if(init_flags & CURL_GLOBAL_WIN32)
-    win32_cleanup();
+#ifdef WIN32
+  Curl_win32_cleanup(init_flags);
+#endif
 
 
   Curl_amiga_cleanup();
   Curl_amiga_cleanup();
 
 
@@ -489,8 +427,8 @@ static int events_socket(struct Curl_easy *easy,      /* easy handle */
            mask. Convert from libcurl bitmask to the poll one. */
            mask. Convert from libcurl bitmask to the poll one. */
         m->socket.events = socketcb2poll(what);
         m->socket.events = socketcb2poll(what);
         infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s,
         infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s,
-              what&CURL_POLL_IN?"IN":"",
-              what&CURL_POLL_OUT?"OUT":"");
+              (what&CURL_POLL_IN)?"IN":"",
+              (what&CURL_POLL_OUT)?"OUT":"");
       }
       }
       break;
       break;
     }
     }
@@ -513,8 +451,8 @@ static int events_socket(struct Curl_easy *easy,      /* easy handle */
         m->socket.revents = 0;
         m->socket.revents = 0;
         ev->list = m;
         ev->list = m;
         infof(easy, "socket cb: socket %d ADDED as %s%s\n", s,
         infof(easy, "socket cb: socket %d ADDED as %s%s\n", s,
-              what&CURL_POLL_IN?"IN":"",
-              what&CURL_POLL_OUT?"OUT":"");
+              (what&CURL_POLL_IN)?"IN":"",
+              (what&CURL_POLL_OUT)?"OUT":"");
       }
       }
       else
       else
         return CURLE_OUT_OF_MEMORY;
         return CURLE_OUT_OF_MEMORY;
@@ -621,7 +559,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
       return CURLE_RECV_ERROR;
       return CURLE_RECV_ERROR;
 
 
     if(mcode)
     if(mcode)
-      return CURLE_URL_MALFORMAT; /* TODO: return a proper error! */
+      return CURLE_URL_MALFORMAT;
 
 
     /* we don't really care about the "msgs_in_queue" value returned in the
     /* we don't really care about the "msgs_in_queue" value returned in the
        second argument */
        second argument */
@@ -664,12 +602,12 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
 
 
   while(!done && !mcode) {
   while(!done && !mcode) {
     int still_running = 0;
     int still_running = 0;
-    int rc;
+    bool gotsocket = FALSE;
 
 
-    mcode = curl_multi_wait(multi, NULL, 0, 1000, &rc);
+    mcode = Curl_multi_wait(multi, NULL, 0, 1000, NULL, &gotsocket);
 
 
     if(!mcode) {
     if(!mcode) {
-      if(!rc) {
+      if(!gotsocket) {
         long sleep_ms;
         long sleep_ms;
 
 
         /* If it returns without any filedescriptor instantly, we need to
         /* If it returns without any filedescriptor instantly, we need to
@@ -688,6 +626,7 @@ static CURLcode easy_transfer(struct Curl_multi *multi)
 
 
     /* only read 'still_running' if curl_multi_perform() return OK */
     /* only read 'still_running' if curl_multi_perform() return OK */
     if(!mcode && !still_running) {
     if(!mcode && !still_running) {
+      int rc;
       CURLMsg *msg = curl_multi_info_read(multi, &rc);
       CURLMsg *msg = curl_multi_info_read(multi, &rc);
       if(msg) {
       if(msg) {
         result = msg->data.result;
         result = msg->data.result;
@@ -966,7 +905,8 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
   }
   }
 
 
   /* Clone the resolver handle, if present, for the new handle */
   /* Clone the resolver handle, if present, for the new handle */
-  if(Curl_resolver_duphandle(&outcurl->state.resolver,
+  if(Curl_resolver_duphandle(outcurl,
+                             &outcurl->state.resolver,
                              data->state.resolver))
                              data->state.resolver))
     goto fail;
     goto fail;
 
 
@@ -1021,7 +961,10 @@ void curl_easy_reset(struct Curl_easy *data)
   /* zero out authentication data: */
   /* zero out authentication data: */
   memset(&data->state.authhost, 0, sizeof(struct auth));
   memset(&data->state.authhost, 0, sizeof(struct auth));
   memset(&data->state.authproxy, 0, sizeof(struct auth));
   memset(&data->state.authproxy, 0, sizeof(struct auth));
-  Curl_digest_cleanup(data);
+
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+  Curl_http_auth_cleanup_digest(data);
+#endif
 }
 }
 
 
 /*
 /*
@@ -1058,7 +1001,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
     unsigned int i;
     unsigned int i;
     unsigned int count = data->state.tempcount;
     unsigned int count = data->state.tempcount;
     struct tempbuf writebuf[3]; /* there can only be three */
     struct tempbuf writebuf[3]; /* there can only be three */
-    struct connectdata *conn = data->easy_conn;
+    struct connectdata *conn = data->conn;
     struct Curl_easy *saved_data = NULL;
     struct Curl_easy *saved_data = NULL;
 
 
     /* copy the structs to allow for immediate re-pausing */
     /* copy the structs to allow for immediate re-pausing */

+ 1 - 1
Utilities/cmcurl/lib/escape.c

@@ -122,7 +122,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char *string,
         return NULL;
         return NULL;
       }
       }
 
 
-      snprintf(&ns[strindex], 4, "%%%02X", in);
+      msnprintf(&ns[strindex], 4, "%%%02X", in);
 
 
       strindex += 3;
       strindex += 3;
     }
     }

+ 15 - 14
Utilities/cmcurl/lib/file.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -311,7 +311,7 @@ static CURLcode file_upload(struct connectdata *conn)
     if(result)
     if(result)
       break;
       break;
 
 
-    if(readcount <= 0)  /* fix questionable compare error. curlvms */
+    if(!readcount)
       break;
       break;
 
 
     nread = readcount;
     nread = readcount;
@@ -417,8 +417,9 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
     struct tm buffer;
     struct tm buffer;
     const struct tm *tm = &buffer;
     const struct tm *tm = &buffer;
     char header[80];
     char header[80];
-    snprintf(header, sizeof(header),
-             "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size);
+    msnprintf(header, sizeof(header),
+              "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n",
+              expected_size);
     result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
     result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
     if(result)
     if(result)
       return result;
       return result;
@@ -434,16 +435,16 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
       return result;
       return result;
 
 
     /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
     /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
-    snprintf(header, sizeof(header),
-             "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
-             Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
-             tm->tm_mday,
-             Curl_month[tm->tm_mon],
-             tm->tm_year + 1900,
-             tm->tm_hour,
-             tm->tm_min,
-             tm->tm_sec,
-             data->set.opt_no_body ? "": "\r\n");
+    msnprintf(header, sizeof(header),
+              "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n%s",
+              Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+              tm->tm_mday,
+              Curl_month[tm->tm_mon],
+              tm->tm_year + 1900,
+              tm->tm_hour,
+              tm->tm_min,
+              tm->tm_sec,
+              data->set.opt_no_body ? "": "\r\n");
     result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
     result = Curl_client_write(conn, CLIENTWRITE_HEADER, header, 0);
     if(result)
     if(result)
       return result;
       return result;

+ 3 - 2
Utilities/cmcurl/lib/fileinfo.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 2010 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2010 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
  ***************************************************************************/
  ***************************************************************************/
 
 
 #include "curl_setup.h"
 #include "curl_setup.h"
-
+#ifndef CURL_DISABLE_FTP
 #include "strdup.h"
 #include "strdup.h"
 #include "fileinfo.h"
 #include "fileinfo.h"
 #include "curl_memory.h"
 #include "curl_memory.h"
@@ -41,3 +41,4 @@ void Curl_fileinfo_cleanup(struct fileinfo *finfo)
   Curl_safefree(finfo->info.b_data);
   Curl_safefree(finfo->info.b_data);
   free(finfo);
   free(finfo);
 }
 }
+#endif

+ 7 - 7
Utilities/cmcurl/lib/formdata.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -24,14 +24,14 @@
 
 
 #include <curl/curl.h>
 #include <curl/curl.h>
 
 
-#ifndef CURL_DISABLE_HTTP
+#include "formdata.h"
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)
 
 
 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
 #include <libgen.h>
 #include <libgen.h>
 #endif
 #endif
 
 
 #include "urldata.h" /* for struct Curl_easy */
 #include "urldata.h" /* for struct Curl_easy */
-#include "formdata.h"
 #include "mime.h"
 #include "mime.h"
 #include "non-ascii.h"
 #include "non-ascii.h"
 #include "vtls/vtls.h"
 #include "vtls/vtls.h"
@@ -569,7 +569,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
       if(((form->flags & HTTPPOST_FILENAME) ||
       if(((form->flags & HTTPPOST_FILENAME) ||
           (form->flags & HTTPPOST_BUFFER)) &&
           (form->flags & HTTPPOST_BUFFER)) &&
          !form->contenttype) {
          !form->contenttype) {
-        char *f = form->flags & HTTPPOST_BUFFER?
+        char *f = (form->flags & HTTPPOST_BUFFER)?
           form->showfilename : form->value;
           form->showfilename : form->value;
         char const *type;
         char const *type;
         type = Curl_mime_contenttype(f);
         type = Curl_mime_contenttype(f);
@@ -921,7 +921,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
   return result;
   return result;
 }
 }
 
 
-#else  /* CURL_DISABLE_HTTP */
+#else
+/* if disabled */
 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
                           struct curl_httppost **last_post,
                           struct curl_httppost **last_post,
                           ...)
                           ...)
@@ -946,5 +947,4 @@ void curl_formfree(struct curl_httppost *form)
   /* does nothing HTTP is disabled */
   /* does nothing HTTP is disabled */
 }
 }
 
 
-
-#endif  /* !defined(CURL_DISABLE_HTTP) */
+#endif  /* if disabled */

+ 10 - 1
Utilities/cmcurl/lib/formdata.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,10 @@
  *
  *
  ***************************************************************************/
  ***************************************************************************/
 
 
+#include "curl_setup.h"
+
+#ifndef CURL_DISABLE_MIME
+
 /* used by FormAdd for temporary storage */
 /* used by FormAdd for temporary storage */
 typedef struct FormInfo {
 typedef struct FormInfo {
   char *name;
   char *name;
@@ -47,5 +51,10 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
                           curl_mimepart *,
                           curl_mimepart *,
                           struct curl_httppost *post,
                           struct curl_httppost *post,
                           curl_read_callback fread_func);
                           curl_read_callback fread_func);
+#else
+/* disabled */
+#define Curl_getformdata(a,b,c,d) CURLE_NOT_BUILT_IN
+#endif
+
 
 
 #endif /* HEADER_CURL_FORMDATA_H */
 #endif /* HEADER_CURL_FORMDATA_H */

+ 47 - 56
Utilities/cmcurl/lib/ftp.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -448,7 +448,6 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
 static CURLcode InitiateTransfer(struct connectdata *conn)
 static CURLcode InitiateTransfer(struct connectdata *conn)
 {
 {
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
-  struct FTP *ftp = data->req.protop;
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
 
 
   if(conn->bits.ftp_use_data_ssl) {
   if(conn->bits.ftp_use_data_ssl) {
@@ -461,24 +460,19 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
   }
   }
 
 
   if(conn->proto.ftpc.state_saved == FTP_STOR) {
   if(conn->proto.ftpc.state_saved == FTP_STOR) {
-    *(ftp->bytecountp) = 0;
-
     /* When we know we're uploading a specified file, we can get the file
     /* When we know we're uploading a specified file, we can get the file
        size prior to the actual upload. */
        size prior to the actual upload. */
-
     Curl_pgrsSetUploadSize(data, data->state.infilesize);
     Curl_pgrsSetUploadSize(data, data->state.infilesize);
 
 
     /* set the SO_SNDBUF for the secondary socket for those who need it */
     /* set the SO_SNDBUF for the secondary socket for those who need it */
     Curl_sndbufset(conn->sock[SECONDARYSOCKET]);
     Curl_sndbufset(conn->sock[SECONDARYSOCKET]);
 
 
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
-                        SECONDARYSOCKET, ftp->bytecountp);
+    Curl_setup_transfer(data, -1, -1, FALSE, SECONDARYSOCKET);
   }
   }
   else {
   else {
     /* FTP download: */
     /* FTP download: */
-    Curl_setup_transfer(conn, SECONDARYSOCKET,
-                        conn->proto.ftpc.retr_size_saved, FALSE,
-                        ftp->bytecountp, -1, NULL); /* no upload here */
+    Curl_setup_transfer(data, SECONDARYSOCKET,
+                        conn->proto.ftpc.retr_size_saved, FALSE, -1);
   }
   }
 
 
   conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
   conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
@@ -578,7 +572,6 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
 
 
 #if defined(HAVE_GSSAPI)
 #if defined(HAVE_GSSAPI)
   /* handle the security-oriented responses 6xx ***/
   /* handle the security-oriented responses 6xx ***/
-  /* FIXME: some errorchecking perhaps... ***/
   switch(code) {
   switch(code) {
   case 631:
   case 631:
     code = Curl_sec_read_msg(conn, buf, PROT_SAFE);
     code = Curl_sec_read_msg(conn, buf, PROT_SAFE);
@@ -655,7 +648,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
 
 
   while(!*ftpcode && !result) {
   while(!*ftpcode && !result) {
     /* check and reset timeout value every lap */
     /* check and reset timeout value every lap */
-    time_t timeout = Curl_pp_state_timeout(pp); /* timeout in milliseconds */
+    time_t timeout = Curl_pp_state_timeout(pp, FALSE);
     time_t interval_ms;
     time_t interval_ms;
 
 
     if(timeout <= 0) {
     if(timeout <= 0) {
@@ -955,7 +948,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   unsigned short port_max = 0;
   unsigned short port_max = 0;
   unsigned short port;
   unsigned short port;
   bool possibly_non_local = TRUE;
   bool possibly_non_local = TRUE;
-
+  char buffer[STRERROR_LEN];
   char *addr = NULL;
   char *addr = NULL;
 
 
   /* Step 1, figure out what is requested,
   /* Step 1, figure out what is requested,
@@ -1064,11 +1057,10 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   if(!host) {
   if(!host) {
     /* not an interface and not a host name, get default by extracting
     /* not an interface and not a host name, get default by extracting
        the IP from the control connection */
        the IP from the control connection */
-
     sslen = sizeof(ss);
     sslen = sizeof(ss);
     if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
     if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
       failf(data, "getsockname() failed: %s",
       failf(data, "getsockname() failed: %s",
-          Curl_strerror(conn, SOCKERRNO) );
+            Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
       free(addr);
       free(addr);
       return CURLE_FTP_PORT_FAILED;
       return CURLE_FTP_PORT_FAILED;
     }
     }
@@ -1087,7 +1079,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   }
   }
 
 
   /* resolv ip/host to ip */
   /* resolv ip/host to ip */
-  rc = Curl_resolv(conn, host, 0, &h);
+  rc = Curl_resolv(conn, host, 0, FALSE, &h);
   if(rc == CURLRESOLV_PENDING)
   if(rc == CURLRESOLV_PENDING)
     (void)Curl_resolver_wait_resolv(conn, &h);
     (void)Curl_resolver_wait_resolv(conn, &h);
   if(h) {
   if(h) {
@@ -1121,7 +1113,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
     break;
     break;
   }
   }
   if(!ai) {
   if(!ai) {
-    failf(data, "socket failure: %s", Curl_strerror(conn, error));
+    failf(data, "socket failure: %s",
+          Curl_strerror(error, buffer, sizeof(buffer)));
     return CURLE_FTP_PORT_FAILED;
     return CURLE_FTP_PORT_FAILED;
   }
   }
 
 
@@ -1145,14 +1138,13 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
         /* The requested bind address is not local.  Use the address used for
         /* The requested bind address is not local.  Use the address used for
          * the control connection instead and restart the port loop
          * the control connection instead and restart the port loop
          */
          */
-
         infof(data, "bind(port=%hu) on non-local address failed: %s\n", port,
         infof(data, "bind(port=%hu) on non-local address failed: %s\n", port,
-              Curl_strerror(conn, error) );
+              Curl_strerror(error, buffer, sizeof(buffer)));
 
 
         sslen = sizeof(ss);
         sslen = sizeof(ss);
         if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
         if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
           failf(data, "getsockname() failed: %s",
           failf(data, "getsockname() failed: %s",
-                Curl_strerror(conn, SOCKERRNO) );
+                Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
           Curl_closesocket(conn, portsock);
           Curl_closesocket(conn, portsock);
           return CURLE_FTP_PORT_FAILED;
           return CURLE_FTP_PORT_FAILED;
         }
         }
@@ -1162,7 +1154,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
       }
       }
       if(error != EADDRINUSE && error != EACCES) {
       if(error != EADDRINUSE && error != EACCES) {
         failf(data, "bind(port=%hu) failed: %s", port,
         failf(data, "bind(port=%hu) failed: %s", port,
-              Curl_strerror(conn, error) );
+              Curl_strerror(error, buffer, sizeof(buffer)));
         Curl_closesocket(conn, portsock);
         Curl_closesocket(conn, portsock);
         return CURLE_FTP_PORT_FAILED;
         return CURLE_FTP_PORT_FAILED;
       }
       }
@@ -1185,7 +1177,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   sslen = sizeof(ss);
   sslen = sizeof(ss);
   if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
   if(getsockname(portsock, (struct sockaddr *)sa, &sslen)) {
     failf(data, "getsockname() failed: %s",
     failf(data, "getsockname() failed: %s",
-          Curl_strerror(conn, SOCKERRNO) );
+          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
     Curl_closesocket(conn, portsock);
     Curl_closesocket(conn, portsock);
     return CURLE_FTP_PORT_FAILED;
     return CURLE_FTP_PORT_FAILED;
   }
   }
@@ -1193,7 +1185,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   /* step 4, listen on the socket */
   /* step 4, listen on the socket */
 
 
   if(listen(portsock, 1)) {
   if(listen(portsock, 1)) {
-    failf(data, "socket failure: %s", Curl_strerror(conn, SOCKERRNO));
+    failf(data, "socket failure: %s",
+          Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
     Curl_closesocket(conn, portsock);
     Curl_closesocket(conn, portsock);
     return CURLE_FTP_PORT_FAILED;
     return CURLE_FTP_PORT_FAILED;
   }
   }
@@ -1272,7 +1265,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
         source++;
         source++;
       }
       }
       *dest = 0;
       *dest = 0;
-      snprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
+      msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
 
 
       result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
       result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
       if(result) {
       if(result) {
@@ -1658,7 +1651,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
         infof(data, "File already completely uploaded\n");
         infof(data, "File already completely uploaded\n");
 
 
         /* no data to transfer */
         /* no data to transfer */
-        Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+        Curl_setup_transfer(data, -1, -1, FALSE, -1);
 
 
         /* Set ->transfer so that we won't get any error in
         /* Set ->transfer so that we won't get any error in
          * ftp_done() because we didn't transfer anything! */
          * ftp_done() because we didn't transfer anything! */
@@ -1940,7 +1933,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
      */
      */
     const char * const host_name = conn->bits.socksproxy ?
     const char * const host_name = conn->bits.socksproxy ?
       conn->socks_proxy.host.name : conn->http_proxy.host.name;
       conn->socks_proxy.host.name : conn->http_proxy.host.name;
-    rc = Curl_resolv(conn, host_name, (int)conn->port, &addr);
+    rc = Curl_resolv(conn, host_name, (int)conn->port, FALSE, &addr);
     if(rc == CURLRESOLV_PENDING)
     if(rc == CURLRESOLV_PENDING)
       /* BLOCKING, ignores the return code but 'addr' will be NULL in
       /* BLOCKING, ignores the return code but 'addr' will be NULL in
          case of failure */
          case of failure */
@@ -1956,7 +1949,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
   }
   }
   else {
   else {
     /* normal, direct, ftp connection */
     /* normal, direct, ftp connection */
-    rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr);
+    rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr);
     if(rc == CURLRESOLV_PENDING)
     if(rc == CURLRESOLV_PENDING)
       /* BLOCKING */
       /* BLOCKING */
       (void)Curl_resolver_wait_resolv(conn, &addr);
       (void)Curl_resolver_wait_resolv(conn, &addr);
@@ -2061,9 +2054,9 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
         char timebuf[24];
         char timebuf[24];
         time_t secs = time(NULL);
         time_t secs = time(NULL);
 
 
-        snprintf(timebuf, sizeof(timebuf),
-                 "%04d%02d%02d %02d:%02d:%02d GMT",
-                 year, month, day, hour, minute, second);
+        msnprintf(timebuf, sizeof(timebuf),
+                  "%04d%02d%02d %02d:%02d:%02d GMT",
+                  year, month, day, hour, minute, second);
         /* now, convert this into a time() value: */
         /* now, convert this into a time() value: */
         data->info.filetime = curl_getdate(timebuf, &secs);
         data->info.filetime = curl_getdate(timebuf, &secs);
       }
       }
@@ -2086,15 +2079,15 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
           return result;
           return result;
 
 
         /* format: "Tue, 15 Nov 1994 12:45:26" */
         /* format: "Tue, 15 Nov 1994 12:45:26" */
-        snprintf(headerbuf, sizeof(headerbuf),
-                 "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
-                 Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
-                 tm->tm_mday,
-                 Curl_month[tm->tm_mon],
-                 tm->tm_year + 1900,
-                 tm->tm_hour,
-                 tm->tm_min,
-                 tm->tm_sec);
+        msnprintf(headerbuf, sizeof(headerbuf),
+                  "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+                  Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+                  tm->tm_mday,
+                  Curl_month[tm->tm_mon],
+                  tm->tm_year + 1900,
+                  tm->tm_hour,
+                  tm->tm_min,
+                  tm->tm_sec);
         result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0);
         result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0);
         if(result)
         if(result)
           return result;
           return result;
@@ -2230,7 +2223,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
 
 
     if(ftp->downloadsize == 0) {
     if(ftp->downloadsize == 0) {
       /* no data to transfer */
       /* no data to transfer */
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, -1, -1, FALSE, -1);
       infof(data, "File already completely downloaded\n");
       infof(data, "File already completely downloaded\n");
 
 
       /* Set ->transfer so that we won't get any error in ftp_done()
       /* Set ->transfer so that we won't get any error in ftp_done()
@@ -2276,8 +2269,8 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
 #ifdef CURL_FTP_HTTPSTYLE_HEAD
 #ifdef CURL_FTP_HTTPSTYLE_HEAD
     if(-1 != filesize) {
     if(-1 != filesize) {
       char clbuf[128];
       char clbuf[128];
-      snprintf(clbuf, sizeof(clbuf),
-               "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
+      msnprintf(clbuf, sizeof(clbuf),
+                "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
       result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0);
       result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0);
       if(result)
       if(result)
         return result;
         return result;
@@ -3054,7 +3047,7 @@ static CURLcode ftp_multi_statemach(struct connectdata *conn,
                                     bool *done)
                                     bool *done)
 {
 {
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
-  CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE);
+  CURLcode result = Curl_pp_statemach(&ftpc->pp, FALSE, FALSE);
 
 
   /* Check for the state outside of the Curl_socket_check() return code checks
   /* Check for the state outside of the Curl_socket_check() return code checks
      since at times we are in fact already in this state when this function
      since at times we are in fact already in this state when this function
@@ -3071,7 +3064,7 @@ static CURLcode ftp_block_statemach(struct connectdata *conn)
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
 
 
   while(ftpc->state != FTP_STOP) {
   while(ftpc->state != FTP_STOP) {
-    result = Curl_pp_statemach(pp, TRUE);
+    result = Curl_pp_statemach(pp, TRUE, TRUE /* disconnecting */);
     if(result)
     if(result)
       break;
       break;
   }
   }
@@ -3308,33 +3301,33 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
     ;
     ;
   else if(data->set.upload) {
   else if(data->set.upload) {
     if((-1 != data->state.infilesize) &&
     if((-1 != data->state.infilesize) &&
-       (data->state.infilesize != *ftp->bytecountp) &&
+       (data->state.infilesize != data->req.writebytecount) &&
        !data->set.crlf &&
        !data->set.crlf &&
        (ftp->transfer == FTPTRANSFER_BODY)) {
        (ftp->transfer == FTPTRANSFER_BODY)) {
       failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
       failf(data, "Uploaded unaligned file size (%" CURL_FORMAT_CURL_OFF_T
             " out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
             " out of %" CURL_FORMAT_CURL_OFF_T " bytes)",
-            *ftp->bytecountp, data->state.infilesize);
+            data->req.bytecount, data->state.infilesize);
       result = CURLE_PARTIAL_FILE;
       result = CURLE_PARTIAL_FILE;
     }
     }
   }
   }
   else {
   else {
     if((-1 != data->req.size) &&
     if((-1 != data->req.size) &&
-       (data->req.size != *ftp->bytecountp) &&
+       (data->req.size != data->req.bytecount) &&
 #ifdef CURL_DO_LINEEND_CONV
 #ifdef CURL_DO_LINEEND_CONV
        /* Most FTP servers don't adjust their file SIZE response for CRLFs, so
        /* Most FTP servers don't adjust their file SIZE response for CRLFs, so
         * we'll check to see if the discrepancy can be explained by the number
         * we'll check to see if the discrepancy can be explained by the number
         * of CRLFs we've changed to LFs.
         * of CRLFs we've changed to LFs.
         */
         */
        ((data->req.size + data->state.crlf_conversions) !=
        ((data->req.size + data->state.crlf_conversions) !=
-        *ftp->bytecountp) &&
+        data->req.bytecount) &&
 #endif /* CURL_DO_LINEEND_CONV */
 #endif /* CURL_DO_LINEEND_CONV */
-       (data->req.maxdownload != *ftp->bytecountp)) {
+       (data->req.maxdownload != data->req.bytecount)) {
       failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T
       failf(data, "Received only partial file: %" CURL_FORMAT_CURL_OFF_T
-            " bytes", *ftp->bytecountp);
+            " bytes", data->req.bytecount);
       result = CURLE_PARTIAL_FILE;
       result = CURLE_PARTIAL_FILE;
     }
     }
     else if(!ftpc->dont_check &&
     else if(!ftpc->dont_check &&
-            !*ftp->bytecountp &&
+            !data->req.bytecount &&
             (data->req.size>0)) {
             (data->req.size>0)) {
       failf(data, "No data was received!");
       failf(data, "No data was received!");
       result = CURLE_FTP_COULDNT_RETR_FILE;
       result = CURLE_FTP_COULDNT_RETR_FILE;
@@ -3496,7 +3489,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
   if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
   if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
     if(Curl_connect_ongoing(conn)) {
     if(Curl_connect_ongoing(conn)) {
       /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
       /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
-         aren't used so we blank their arguments. TODO: make this nicer */
+         aren't used so we blank their arguments. */
       result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
       result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
 
 
       return result;
       return result;
@@ -3629,7 +3622,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
   if(!result && (ftp->transfer != FTPTRANSFER_BODY))
   if(!result && (ftp->transfer != FTPTRANSFER_BODY))
     /* no data to transfer. FIX: it feels like a kludge to have this here
     /* no data to transfer. FIX: it feels like a kludge to have this here
        too! */
        too! */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(data, -1, -1, FALSE, -1);
 
 
   if(!ftpc->wait_data_conn) {
   if(!ftpc->wait_data_conn) {
     /* no waiting for the data connection so this is now complete */
     /* no waiting for the data connection so this is now complete */
@@ -4309,7 +4302,7 @@ static CURLcode ftp_dophase_done(struct connectdata *conn,
 
 
   if(ftp->transfer != FTPTRANSFER_BODY)
   if(ftp->transfer != FTPTRANSFER_BODY)
     /* no data to transfer */
     /* no data to transfer */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
   else if(!connected)
   else if(!connected)
     /* since we didn't connect now, we want do_more to get called */
     /* since we didn't connect now, we want do_more to get called */
     conn->bits.do_more = TRUE;
     conn->bits.do_more = TRUE;
@@ -4396,7 +4389,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;
 
 
   ftp->path = &data->state.up.path[1]; /* don't include the initial slash */
   ftp->path = &data->state.up.path[1]; /* don't include the initial slash */
-  data->state.slash_removed = TRUE; /* we've skipped the slash */
 
 
   /* FTP URLs support an extension like ";type=<typecode>" that
   /* FTP URLs support an extension like ";type=<typecode>" that
    * we'll try to get now! */
    * we'll try to get now! */
@@ -4429,7 +4421,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
   }
   }
 
 
   /* get some initial data into the ftp struct */
   /* get some initial data into the ftp struct */
-  ftp->bytecountp = &conn->data->req.bytecount;
   ftp->transfer = FTPTRANSFER_BODY;
   ftp->transfer = FTPTRANSFER_BODY;
   ftp->downloadsize = 0;
   ftp->downloadsize = 0;
 
 

+ 1 - 2
Utilities/cmcurl/lib/ftp.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -102,7 +102,6 @@ typedef enum {
    perhaps the Curl_easy is changed between the times the connection is
    perhaps the Curl_easy is changed between the times the connection is
    used. */
    used. */
 struct FTP {
 struct FTP {
-  curl_off_t *bytecountp;
   char *user;    /* user name string */
   char *user;    /* user name string */
   char *passwd;  /* password string */
   char *passwd;  /* password string */
   char *path;    /* points to the urlpieces struct field */
   char *path;    /* points to the urlpieces struct field */

+ 2 - 5
Utilities/cmcurl/lib/ftplistparser.c

@@ -405,7 +405,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
             parser->state.UNIX.main = PL_UNIX_FILETYPE;
             parser->state.UNIX.main = PL_UNIX_FILETYPE;
             /* start FSM again not considering size of directory */
             /* start FSM again not considering size of directory */
             finfo->b_used = 0;
             finfo->b_used = 0;
-            i--;
+            continue;
           }
           }
           break;
           break;
         case PL_UNIX_TOTALSIZE_READING:
         case PL_UNIX_TOTALSIZE_READING:
@@ -914,10 +914,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
       case PL_WINNT_DIRORSIZE:
       case PL_WINNT_DIRORSIZE:
         switch(parser->state.NT.sub.dirorsize) {
         switch(parser->state.NT.sub.dirorsize) {
         case PL_WINNT_DIRORSIZE_PRESPACE:
         case PL_WINNT_DIRORSIZE_PRESPACE:
-          if(c == ' ') {
-
-          }
-          else {
+          if(c != ' ') {
             parser->item_offset = finfo->b_used - 1;
             parser->item_offset = finfo->b_used - 1;
             parser->item_length = 1;
             parser->item_length = 1;
             parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;
             parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;

+ 4 - 4
Utilities/cmcurl/lib/getinfo.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -163,10 +163,10 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
       *param_longp = (long)data->info.filetime;
       *param_longp = (long)data->info.filetime;
     break;
     break;
   case CURLINFO_HEADER_SIZE:
   case CURLINFO_HEADER_SIZE:
-    *param_longp = data->info.header_size;
+    *param_longp = (long)data->info.header_size;
     break;
     break;
   case CURLINFO_REQUEST_SIZE:
   case CURLINFO_REQUEST_SIZE:
-    *param_longp = data->info.request_size;
+    *param_longp = (long)data->info.request_size;
     break;
     break;
   case CURLINFO_SSL_VERIFYRESULT:
   case CURLINFO_SSL_VERIFYRESULT:
     *param_longp = data->set.ssl.certverifyresult;
     *param_longp = data->set.ssl.certverifyresult;
@@ -390,7 +390,7 @@ static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
                                           param_slistp;
                                           param_slistp;
       struct curl_tlssessioninfo *tsi = &data->tsi;
       struct curl_tlssessioninfo *tsi = &data->tsi;
 #ifdef USE_SSL
 #ifdef USE_SSL
-      struct connectdata *conn = data->easy_conn;
+      struct connectdata *conn = data->conn;
 #endif
 #endif
 
 
       *tsip = tsi;
       *tsip = tsi;

+ 21 - 7
Utilities/cmcurl/lib/gopher.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -31,9 +31,11 @@
 #include "progress.h"
 #include "progress.h"
 #include "gopher.h"
 #include "gopher.h"
 #include "select.h"
 #include "select.h"
+#include "strdup.h"
 #include "url.h"
 #include "url.h"
 #include "escape.h"
 #include "escape.h"
 #include "warnless.h"
 #include "warnless.h"
+#include "curl_printf.h"
 #include "curl_memory.h"
 #include "curl_memory.h"
 /* The last #include file should be: */
 /* The last #include file should be: */
 #include "memdebug.h"
 #include "memdebug.h"
@@ -76,9 +78,9 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
-
-  curl_off_t *bytecount = &data->req.bytecount;
+  char *gopherpath;
   char *path = data->state.up.path;
   char *path = data->state.up.path;
+  char *query = data->state.up.query;
   char *sel = NULL;
   char *sel = NULL;
   char *sel_org = NULL;
   char *sel_org = NULL;
   ssize_t amount, k;
   ssize_t amount, k;
@@ -86,20 +88,33 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
 
 
   *done = TRUE; /* unconditionally */
   *done = TRUE; /* unconditionally */
 
 
+  /* path is guaranteed non-NULL */
+  DEBUGASSERT(path);
+
+  if(query)
+    gopherpath = aprintf("%s?%s", path, query);
+  else
+    gopherpath = strdup(path);
+
+  if(!gopherpath)
+    return CURLE_OUT_OF_MEMORY;
+
   /* Create selector. Degenerate cases: / and /1 => convert to "" */
   /* Create selector. Degenerate cases: / and /1 => convert to "" */
-  if(strlen(path) <= 2) {
+  if(strlen(gopherpath) <= 2) {
     sel = (char *)"";
     sel = (char *)"";
     len = strlen(sel);
     len = strlen(sel);
+    free(gopherpath);
   }
   }
   else {
   else {
     char *newp;
     char *newp;
 
 
     /* Otherwise, drop / and the first character (i.e., item type) ... */
     /* Otherwise, drop / and the first character (i.e., item type) ... */
-    newp = path;
+    newp = gopherpath;
     newp += 2;
     newp += 2;
 
 
     /* ... and finally unescape */
     /* ... and finally unescape */
     result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
     result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
+    free(gopherpath);
     if(result)
     if(result)
       return result;
       return result;
     sel_org = sel;
     sel_org = sel;
@@ -153,8 +168,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
   if(result)
   if(result)
     return result;
     return result;
 
 
-  Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-                      -1, NULL); /* no upload */
+  Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
   return CURLE_OK;
   return CURLE_OK;
 }
 }
 #endif /*CURL_DISABLE_GOPHER*/
 #endif /*CURL_DISABLE_GOPHER*/

+ 4 - 4
Utilities/cmcurl/lib/hostasyn.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -85,14 +85,14 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
       dns = Curl_cache_addr(data, ai,
       dns = Curl_cache_addr(data, ai,
                             conn->async.hostname,
                             conn->async.hostname,
                             conn->async.port);
                             conn->async.port);
+      if(data->share)
+        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
+
       if(!dns) {
       if(!dns) {
         /* failed to store, cleanup and return error */
         /* failed to store, cleanup and return error */
         Curl_freeaddrinfo(ai);
         Curl_freeaddrinfo(ai);
         result = CURLE_OUT_OF_MEMORY;
         result = CURLE_OUT_OF_MEMORY;
       }
       }
-
-      if(data->share)
-        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
     }
     }
     else {
     else {
       result = CURLE_OUT_OF_MEMORY;
       result = CURLE_OUT_OF_MEMORY;

+ 4 - 7
Utilities/cmcurl/lib/hostcheck.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -23,7 +23,6 @@
 #include "curl_setup.h"
 #include "curl_setup.h"
 
 
 #if defined(USE_OPENSSL)                                \
 #if defined(USE_OPENSSL)                                \
-  || defined(USE_AXTLS)                                 \
   || defined(USE_GSKIT)                                 \
   || defined(USE_GSKIT)                                 \
   || defined(USE_SCHANNEL)
   || defined(USE_SCHANNEL)
 /* these backends use functions from this file */
 /* these backends use functions from this file */
@@ -128,16 +127,14 @@ static int hostmatch(char *hostname, char *pattern)
 
 
 int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
 int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
 {
 {
-  char *matchp;
-  char *hostp;
   int res = 0;
   int res = 0;
   if(!match_pattern || !*match_pattern ||
   if(!match_pattern || !*match_pattern ||
       !hostname || !*hostname) /* sanity check */
       !hostname || !*hostname) /* sanity check */
     ;
     ;
   else {
   else {
-    matchp = strdup(match_pattern);
+    char *matchp = strdup(match_pattern);
     if(matchp) {
     if(matchp) {
-      hostp = strdup(hostname);
+      char *hostp = strdup(hostname);
       if(hostp) {
       if(hostp) {
         if(hostmatch(hostp, matchp) == CURL_HOST_MATCH)
         if(hostmatch(hostp, matchp) == CURL_HOST_MATCH)
           res = 1;
           res = 1;
@@ -150,4 +147,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
   return res;
   return res;
 }
 }
 
 
-#endif /* OPENSSL, AXTLS, GSKIT or schannel+wince */
+#endif /* OPENSSL, GSKIT or schannel+wince */

+ 56 - 97
Utilities/cmcurl/lib/hostip.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -73,6 +73,8 @@
 #define USE_ALARM_TIMEOUT
 #define USE_ALARM_TIMEOUT
 #endif
 #endif
 
 
+#define MAX_HOSTCACHE_LEN (255 + 7) /* max FQDN + colon + port number + zero */
+
 /*
 /*
  * hostip.c explained
  * hostip.c explained
  * ==================
  * ==================
@@ -112,42 +114,8 @@
  * CURLRES_* defines based on the config*.h and curl_setup.h defines.
  * CURLRES_* defines based on the config*.h and curl_setup.h defines.
  */
  */
 
 
-/* These two symbols are for the global DNS cache */
-static struct curl_hash hostname_cache;
-static int host_cache_initialized;
-
 static void freednsentry(void *freethis);
 static void freednsentry(void *freethis);
 
 
-/*
- * Curl_global_host_cache_init() initializes and sets up a global DNS cache.
- * Global DNS cache is general badness. Do not use. This will be removed in
- * a future version. Use the share interface instead!
- *
- * Returns a struct curl_hash pointer on success, NULL on failure.
- */
-struct curl_hash *Curl_global_host_cache_init(void)
-{
-  int rc = 0;
-  if(!host_cache_initialized) {
-    rc = Curl_hash_init(&hostname_cache, 7, Curl_hash_str,
-                        Curl_str_key_compare, freednsentry);
-    if(!rc)
-      host_cache_initialized = 1;
-  }
-  return rc?NULL:&hostname_cache;
-}
-
-/*
- * Destroy and cleanup the global DNS cache
- */
-void Curl_global_host_cache_dtor(void)
-{
-  if(host_cache_initialized) {
-    Curl_hash_destroy(&hostname_cache);
-    host_cache_initialized = 0;
-  }
-}
-
 /*
 /*
  * Return # of addresses in a Curl_addrinfo struct
  * Return # of addresses in a Curl_addrinfo struct
  */
  */
@@ -198,23 +166,19 @@ Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
 }
 }
 
 
 /*
 /*
- * Return a hostcache id string for the provided host + port, to be used by
- * the DNS caching.
+ * Create a hostcache id string for the provided host + port, to be used by
+ * the DNS caching. Without alloc.
  */
  */
-static char *
-create_hostcache_id(const char *name, int port)
+static void
+create_hostcache_id(const char *name, int port, char *ptr, size_t buflen)
 {
 {
-  /* create and return the new allocated entry */
-  char *id = aprintf("%s:%d", name, port);
-  char *ptr = id;
-  if(ptr) {
-    /* lower case the name part */
-    while(*ptr && (*ptr != ':')) {
-      *ptr = (char)TOLOWER(*ptr);
-      ptr++;
-    }
-  }
-  return id;
+  size_t len = strlen(name);
+  if(len > (buflen - 7))
+    len = buflen - 7;
+  /* store and lower case the name */
+  while(len--)
+    *ptr++ = (char)TOLOWER(*name++);
+  msnprintf(ptr, 7, ":%u", port);
 }
 }
 
 
 struct hostcache_prune_data {
 struct hostcache_prune_data {
@@ -296,22 +260,27 @@ fetch_addr(struct connectdata *conn,
                 const char *hostname,
                 const char *hostname,
                 int port)
                 int port)
 {
 {
-  char *entry_id = NULL;
   struct Curl_dns_entry *dns = NULL;
   struct Curl_dns_entry *dns = NULL;
   size_t entry_len;
   size_t entry_len;
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
+  char entry_id[MAX_HOSTCACHE_LEN];
 
 
   /* Create an entry id, based upon the hostname and port */
   /* Create an entry id, based upon the hostname and port */
-  entry_id = create_hostcache_id(hostname, port);
-  /* If we can't create the entry id, fail */
-  if(!entry_id)
-    return dns;
-
+  create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
   entry_len = strlen(entry_id);
   entry_len = strlen(entry_id);
 
 
   /* See if its already in our dns cache */
   /* See if its already in our dns cache */
   dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
   dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
 
 
+  /* No entry found in cache, check if we might have a wildcard entry */
+  if(!dns && data->change.wildcard_resolve) {
+    create_hostcache_id("*", port, entry_id, sizeof(entry_id));
+    entry_len = strlen(entry_id);
+
+    /* See if it's already in our dns cache */
+    dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
+  }
+
   if(dns && (data->set.dns_cache_timeout != -1)) {
   if(dns && (data->set.dns_cache_timeout != -1)) {
     /* See whether the returned entry is stale. Done before we release lock */
     /* See whether the returned entry is stale. Done before we release lock */
     struct hostcache_prune_data user;
     struct hostcache_prune_data user;
@@ -326,9 +295,6 @@ fetch_addr(struct connectdata *conn,
     }
     }
   }
   }
 
 
-  /* free the allocated entry_id again */
-  free(entry_id);
-
   return dns;
   return dns;
 }
 }
 
 
@@ -368,6 +334,9 @@ Curl_fetch_addr(struct connectdata *conn,
   return dns;
   return dns;
 }
 }
 
 
+#ifndef CURL_DISABLE_SHUFFLE_DNS
+UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
+                                    Curl_addrinfo **addr);
 /*
 /*
  * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
  * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
  * struct by re-linking its linked list.
  * struct by re-linking its linked list.
@@ -380,7 +349,8 @@ Curl_fetch_addr(struct connectdata *conn,
  *
  *
  * @unittest: 1608
  * @unittest: 1608
  */
  */
-CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr)
+UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
+                                    Curl_addrinfo **addr)
 {
 {
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
   const int num_addrs = Curl_num_addresses(*addr);
   const int num_addrs = Curl_num_addresses(*addr);
@@ -431,6 +401,7 @@ CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr)
   }
   }
   return result;
   return result;
 }
 }
+#endif
 
 
 /*
 /*
  * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
  * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
@@ -447,32 +418,30 @@ Curl_cache_addr(struct Curl_easy *data,
                 const char *hostname,
                 const char *hostname,
                 int port)
                 int port)
 {
 {
-  char *entry_id;
+  char entry_id[MAX_HOSTCACHE_LEN];
   size_t entry_len;
   size_t entry_len;
   struct Curl_dns_entry *dns;
   struct Curl_dns_entry *dns;
   struct Curl_dns_entry *dns2;
   struct Curl_dns_entry *dns2;
 
 
+#ifndef CURL_DISABLE_SHUFFLE_DNS
   /* shuffle addresses if requested */
   /* shuffle addresses if requested */
   if(data->set.dns_shuffle_addresses) {
   if(data->set.dns_shuffle_addresses) {
     CURLcode result = Curl_shuffle_addr(data, &addr);
     CURLcode result = Curl_shuffle_addr(data, &addr);
     if(result)
     if(result)
       return NULL;
       return NULL;
   }
   }
-
-  /* Create an entry id, based upon the hostname and port */
-  entry_id = create_hostcache_id(hostname, port);
-  /* If we can't create the entry id, fail */
-  if(!entry_id)
-    return NULL;
-  entry_len = strlen(entry_id);
+#endif
 
 
   /* Create a new cache entry */
   /* Create a new cache entry */
   dns = calloc(1, sizeof(struct Curl_dns_entry));
   dns = calloc(1, sizeof(struct Curl_dns_entry));
   if(!dns) {
   if(!dns) {
-    free(entry_id);
     return NULL;
     return NULL;
   }
   }
 
 
+  /* Create an entry id, based upon the hostname and port */
+  create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
+  entry_len = strlen(entry_id);
+
   dns->inuse = 1;   /* the cache has the first reference */
   dns->inuse = 1;   /* the cache has the first reference */
   dns->addr = addr; /* this is the address(es) */
   dns->addr = addr; /* this is the address(es) */
   time(&dns->timestamp);
   time(&dns->timestamp);
@@ -484,16 +453,11 @@ Curl_cache_addr(struct Curl_easy *data,
                        (void *)dns);
                        (void *)dns);
   if(!dns2) {
   if(!dns2) {
     free(dns);
     free(dns);
-    free(entry_id);
     return NULL;
     return NULL;
   }
   }
 
 
   dns = dns2;
   dns = dns2;
   dns->inuse++;         /* mark entry as in-use */
   dns->inuse++;         /* mark entry as in-use */
-
-  /* free the allocated entry_id */
-  free(entry_id);
-
   return dns;
   return dns;
 }
 }
 
 
@@ -521,6 +485,7 @@ Curl_cache_addr(struct Curl_easy *data,
 int Curl_resolv(struct connectdata *conn,
 int Curl_resolv(struct connectdata *conn,
                 const char *hostname,
                 const char *hostname,
                 int port,
                 int port,
+                bool allowDOH,
                 struct Curl_dns_entry **entry)
                 struct Curl_dns_entry **entry)
 {
 {
   struct Curl_dns_entry *dns = NULL;
   struct Curl_dns_entry *dns = NULL;
@@ -548,7 +513,7 @@ int Curl_resolv(struct connectdata *conn,
     /* The entry was not in the cache. Resolve it to IP address */
     /* The entry was not in the cache. Resolve it to IP address */
 
 
     Curl_addrinfo *addr;
     Curl_addrinfo *addr;
-    int respwait;
+    int respwait = 0;
 
 
     /* Check what IP specifics the app has requested and if we can provide it.
     /* Check what IP specifics the app has requested and if we can provide it.
      * If not, bail out. */
      * If not, bail out. */
@@ -566,7 +531,7 @@ int Curl_resolv(struct connectdata *conn,
         return CURLRESOLV_ERROR;
         return CURLRESOLV_ERROR;
     }
     }
 
 
-    if(data->set.doh) {
+    if(allowDOH && data->set.doh) {
       addr = Curl_doh(conn, hostname, port, &respwait);
       addr = Curl_doh(conn, hostname, port, &respwait);
     }
     }
     else {
     else {
@@ -692,7 +657,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
 
 
   if(!timeout)
   if(!timeout)
     /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
     /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
-    return Curl_resolv(conn, hostname, port, entry);
+    return Curl_resolv(conn, hostname, port, TRUE, entry);
 
 
   if(timeout < 1000) {
   if(timeout < 1000) {
     /* The alarm() function only provides integer second resolution, so if
     /* The alarm() function only provides integer second resolution, so if
@@ -754,7 +719,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
   /* Perform the actual name resolution. This might be interrupted by an
   /* Perform the actual name resolution. This might be interrupted by an
    * alarm if it takes too long.
    * alarm if it takes too long.
    */
    */
-  rc = Curl_resolv(conn, hostname, port, entry);
+  rc = Curl_resolv(conn, hostname, port, TRUE, entry);
 
 
 #ifdef USE_ALARM_TIMEOUT
 #ifdef USE_ALARM_TIMEOUT
 clean_up:
 clean_up:
@@ -872,11 +837,14 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
   char hostname[256];
   char hostname[256];
   int port = 0;
   int port = 0;
 
 
+  /* Default is no wildcard found */
+  data->change.wildcard_resolve = false;
+
   for(hostp = data->change.resolve; hostp; hostp = hostp->next) {
   for(hostp = data->change.resolve; hostp; hostp = hostp->next) {
+    char entry_id[MAX_HOSTCACHE_LEN];
     if(!hostp->data)
     if(!hostp->data)
       continue;
       continue;
     if(hostp->data[0] == '-') {
     if(hostp->data[0] == '-') {
-      char *entry_id;
       size_t entry_len;
       size_t entry_len;
 
 
       if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) {
       if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) {
@@ -886,12 +854,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       }
       }
 
 
       /* Create an entry id, based upon the hostname and port */
       /* Create an entry id, based upon the hostname and port */
-      entry_id = create_hostcache_id(hostname, port);
-      /* If we can't create the entry id, fail */
-      if(!entry_id) {
-        return CURLE_OUT_OF_MEMORY;
-      }
-
+      create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
       entry_len = strlen(entry_id);
       entry_len = strlen(entry_id);
 
 
       if(data->share)
       if(data->share)
@@ -902,14 +865,10 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
 
 
       if(data->share)
       if(data->share)
         Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
         Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
-
-      /* free the allocated entry_id again */
-      free(entry_id);
     }
     }
     else {
     else {
       struct Curl_dns_entry *dns;
       struct Curl_dns_entry *dns;
       Curl_addrinfo *head = NULL, *tail = NULL;
       Curl_addrinfo *head = NULL, *tail = NULL;
-      char *entry_id;
       size_t entry_len;
       size_t entry_len;
       char address[64];
       char address[64];
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -1005,12 +964,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       }
       }
 
 
       /* Create an entry id, based upon the hostname and port */
       /* Create an entry id, based upon the hostname and port */
-      entry_id = create_hostcache_id(hostname, port);
-      /* If we can't create the entry id, fail */
-      if(!entry_id) {
-        Curl_freeaddrinfo(head);
-        return CURLE_OUT_OF_MEMORY;
-      }
+      create_hostcache_id(hostname, port, entry_id, sizeof(entry_id));
       entry_len = strlen(entry_id);
       entry_len = strlen(entry_id);
 
 
       if(data->share)
       if(data->share)
@@ -1031,8 +985,6 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
 
 
         Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
         Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
       }
       }
-      /* free the allocated entry_id again */
-      free(entry_id);
 
 
       /* put this new host in the cache */
       /* put this new host in the cache */
       dns = Curl_cache_addr(data, head, hostname, port);
       dns = Curl_cache_addr(data, head, hostname, port);
@@ -1052,6 +1004,13 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
       }
       }
       infof(data, "Added %s:%d:%s to DNS cache\n",
       infof(data, "Added %s:%d:%s to DNS cache\n",
             hostname, port, addresses);
             hostname, port, addresses);
+
+      /* Wildcard hostname */
+      if(hostname[0] == '*' && hostname[1] == '\0') {
+        infof(data, "RESOLVE %s:%d is wildcard, enabling wildcard checks\n",
+              hostname, port);
+        data->change.wildcard_resolve = true;
+      }
     }
     }
   }
   }
   data->change.resolve = NULL; /* dealt with now */
   data->change.resolve = NULL; /* dealt with now */

+ 6 - 13
Utilities/cmcurl/lib/hostip.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -83,8 +83,11 @@ struct Curl_dns_entry {
 #define CURLRESOLV_ERROR    -1
 #define CURLRESOLV_ERROR    -1
 #define CURLRESOLV_RESOLVED  0
 #define CURLRESOLV_RESOLVED  0
 #define CURLRESOLV_PENDING   1
 #define CURLRESOLV_PENDING   1
-int Curl_resolv(struct connectdata *conn, const char *hostname,
-                int port, struct Curl_dns_entry **dnsentry);
+int Curl_resolv(struct connectdata *conn,
+                const char *hostname,
+                int port,
+                bool allowDOH,
+                struct Curl_dns_entry **dnsentry);
 int Curl_resolv_timeout(struct connectdata *conn, const char *hostname,
 int Curl_resolv_timeout(struct connectdata *conn, const char *hostname,
                         int port, struct Curl_dns_entry **dnsentry,
                         int port, struct Curl_dns_entry **dnsentry,
                         time_t timeoutms);
                         time_t timeoutms);
@@ -178,16 +181,6 @@ Curl_fetch_addr(struct connectdata *conn,
                 const char *hostname,
                 const char *hostname,
                 int port);
                 int port);
 
 
-/*
- * Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
- * struct by re-linking its linked list.
- *
- * The addr argument should be the address of a pointer to the head node of a
- * `Curl_addrinfo` list and it will be modified to point to the new head after
- * shuffling.
- */
-CURLcode Curl_shuffle_addr(struct Curl_easy *data, Curl_addrinfo **addr);
-
 /*
 /*
  * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
  * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache.
  *
  *

+ 2 - 2
Utilities/cmcurl/lib/hostip4.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -145,7 +145,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
     hints.ai_family = PF_INET;
     hints.ai_family = PF_INET;
     hints.ai_socktype = SOCK_STREAM;
     hints.ai_socktype = SOCK_STREAM;
     if(port) {
     if(port) {
-      snprintf(sbuf, sizeof(sbuf), "%d", port);
+      msnprintf(sbuf, sizeof(sbuf), "%d", port);
       sbufptr = sbuf;
       sbufptr = sbuf;
     }
     }
 
 

+ 8 - 6
Utilities/cmcurl/lib/hostip6.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -101,14 +101,16 @@ static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
 {
 {
   printf("dump_addrinfo:\n");
   printf("dump_addrinfo:\n");
   for(; ai; ai = ai->ai_next) {
   for(; ai; ai = ai->ai_next) {
-    char  buf[INET6_ADDRSTRLEN];
-
+    char buf[INET6_ADDRSTRLEN];
     printf("    fam %2d, CNAME %s, ",
     printf("    fam %2d, CNAME %s, ",
            ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
            ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
     if(Curl_printable_address(ai, buf, sizeof(buf)))
     if(Curl_printable_address(ai, buf, sizeof(buf)))
       printf("%s\n", buf);
       printf("%s\n", buf);
-    else
-      printf("failed; %s\n", Curl_strerror(conn, SOCKERRNO));
+    else {
+      char buffer[STRERROR_LEN];
+      printf("failed; %s\n",
+             Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
+    }
   }
   }
 }
 }
 #else
 #else
@@ -178,7 +180,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
 #endif
 #endif
 
 
   if(port) {
   if(port) {
-    snprintf(sbuf, sizeof(sbuf), "%d", port);
+    msnprintf(sbuf, sizeof(sbuf), "%d", port);
     sbufptr = sbuf;
     sbufptr = sbuf;
   }
   }
 
 

+ 318 - 174
Utilities/cmcurl/lib/http.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -73,10 +73,10 @@
 #include "http_proxy.h"
 #include "http_proxy.h"
 #include "warnless.h"
 #include "warnless.h"
 #include "non-ascii.h"
 #include "non-ascii.h"
-#include "pipeline.h"
 #include "http2.h"
 #include "http2.h"
 #include "connect.h"
 #include "connect.h"
 #include "strdup.h"
 #include "strdup.h"
+#include "altsvc.h"
 
 
 /* The last 3 #include files should be in this order */
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_printf.h"
@@ -92,7 +92,9 @@ static int http_getsock_do(struct connectdata *conn,
                            int numsocks);
                            int numsocks);
 static int http_should_fail(struct connectdata *conn);
 static int http_should_fail(struct connectdata *conn);
 
 
+#ifndef CURL_DISABLE_PROXY
 static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
 static CURLcode add_haproxy_protocol_header(struct connectdata *conn);
+#endif
 
 
 #ifdef USE_SSL
 #ifdef USE_SSL
 static CURLcode https_connecting(struct connectdata *conn, bool *done);
 static CURLcode https_connecting(struct connectdata *conn, bool *done);
@@ -102,13 +104,14 @@ static int https_getsock(struct connectdata *conn,
 #else
 #else
 #define https_connecting(x,y) CURLE_COULDNT_CONNECT
 #define https_connecting(x,y) CURLE_COULDNT_CONNECT
 #endif
 #endif
+static CURLcode http_setup_conn(struct connectdata *conn);
 
 
 /*
 /*
  * HTTP handler interface.
  * HTTP handler interface.
  */
  */
 const struct Curl_handler Curl_handler_http = {
 const struct Curl_handler Curl_handler_http = {
   "HTTP",                               /* scheme */
   "HTTP",                               /* scheme */
-  Curl_http_setup_conn,                 /* setup_connection */
+  http_setup_conn,                      /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
   ZERO_NULL,                            /* do_more */
@@ -133,7 +136,7 @@ const struct Curl_handler Curl_handler_http = {
  */
  */
 const struct Curl_handler Curl_handler_https = {
 const struct Curl_handler Curl_handler_https = {
   "HTTPS",                              /* scheme */
   "HTTPS",                              /* scheme */
-  Curl_http_setup_conn,                 /* setup_connection */
+  http_setup_conn,                      /* setup_connection */
   Curl_http,                            /* do_it */
   Curl_http,                            /* do_it */
   Curl_http_done,                       /* done */
   Curl_http_done,                       /* done */
   ZERO_NULL,                            /* do_more */
   ZERO_NULL,                            /* do_more */
@@ -153,7 +156,7 @@ const struct Curl_handler Curl_handler_https = {
 };
 };
 #endif
 #endif
 
 
-CURLcode Curl_http_setup_conn(struct connectdata *conn)
+static CURLcode http_setup_conn(struct connectdata *conn)
 {
 {
   /* allocate the HTTP-specific struct for the Curl_easy, only to survive
   /* allocate the HTTP-specific struct for the Curl_easy, only to survive
      during this request */
      during this request */
@@ -175,7 +178,7 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
   return CURLE_OK;
   return CURLE_OK;
 }
 }
 
 
-
+#ifndef CURL_DISABLE_PROXY
 /*
 /*
  * checkProxyHeaders() checks the linked list of custom proxy headers
  * checkProxyHeaders() checks the linked list of custom proxy headers
  * if proxy headers are not available, then it will lookup into http header
  * if proxy headers are not available, then it will lookup into http header
@@ -202,6 +205,10 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
 
 
   return NULL;
   return NULL;
 }
 }
+#else
+/* disabled */
+#define Curl_checkProxyheaders(x,y) NULL
+#endif
 
 
 /*
 /*
  * Strip off leading and trailing whitespace from the value in the
  * Strip off leading and trailing whitespace from the value in the
@@ -256,6 +263,7 @@ char *Curl_copy_header_value(const char *header)
   return value;
   return value;
 }
 }
 
 
+#ifndef CURL_DISABLE_HTTP_AUTH
 /*
 /*
  * http_output_basic() sets up an Authorization: header (or the proxy version)
  * http_output_basic() sets up an Authorization: header (or the proxy version)
  * for HTTP Basic authentication.
  * for HTTP Basic authentication.
@@ -337,6 +345,8 @@ static CURLcode http_output_bearer(struct connectdata *conn)
   return result;
   return result;
 }
 }
 
 
+#endif
+
 /* pickoneauth() selects the most favourable authentication method from the
 /* pickoneauth() selects the most favourable authentication method from the
  * ones available and the ones we want.
  * ones available and the ones we want.
  *
  *
@@ -415,7 +425,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
     break;
     break;
   }
   }
 
 
-  bytessent = http->writebytecount;
+  bytessent = data->req.writebytecount;
 
 
   if(conn->bits.authneg) {
   if(conn->bits.authneg) {
     /* This is a state where we are known to be negotiating and we don't send
     /* This is a state where we are known to be negotiating and we don't send
@@ -456,8 +466,8 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
        (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
        (data->state.authproxy.picked == CURLAUTH_NTLM_WB) ||
        (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
        (data->state.authhost.picked == CURLAUTH_NTLM_WB)) {
       if(((expectsend - bytessent) < 2000) ||
       if(((expectsend - bytessent) < 2000) ||
-         (conn->ntlm.state != NTLMSTATE_NONE) ||
-         (conn->proxyntlm.state != NTLMSTATE_NONE)) {
+         (conn->http_ntlm_state != NTLMSTATE_NONE) ||
+         (conn->proxy_ntlm_state != NTLMSTATE_NONE)) {
         /* The NTLM-negotiation has started *OR* there is just a little (<2K)
         /* The NTLM-negotiation has started *OR* there is just a little (<2K)
            data left to send, keep on sending. */
            data left to send, keep on sending. */
 
 
@@ -479,8 +489,36 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
             (curl_off_t)(expectsend - bytessent));
             (curl_off_t)(expectsend - bytessent));
     }
     }
 #endif
 #endif
+#if defined(USE_SPNEGO)
+    /* There is still data left to send */
+    if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) ||
+       (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) {
+      if(((expectsend - bytessent) < 2000) ||
+         (conn->http_negotiate_state != GSS_AUTHNONE) ||
+         (conn->proxy_negotiate_state != GSS_AUTHNONE)) {
+        /* The NEGOTIATE-negotiation has started *OR*
+        there is just a little (<2K) data left to send, keep on sending. */
+
+        /* rewind data when completely done sending! */
+        if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
+          conn->bits.rewindaftersend = TRUE;
+          infof(data, "Rewind stream after send\n");
+        }
+
+        return CURLE_OK;
+      }
 
 
-    /* This is not NTLM or many bytes left to send: close */
+      if(conn->bits.close)
+        /* this is already marked to get closed */
+        return CURLE_OK;
+
+      infof(data, "NEGOTIATE send, close instead of sending %"
+        CURL_FORMAT_CURL_OFF_T " bytes\n",
+        (curl_off_t)(expectsend - bytessent));
+    }
+#endif
+
+    /* This is not NEGOTIATE/NTLM or many bytes left to send: close */
     streamclose(conn, "Mid-auth HTTP and much data left to send");
     streamclose(conn, "Mid-auth HTTP and much data left to send");
     data->req.size = 0; /* don't download any more than 0 bytes */
     data->req.size = 0; /* don't download any more than 0 bytes */
 
 
@@ -526,6 +564,12 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
     pickhost = pickoneauth(&data->state.authhost, authmask);
     pickhost = pickoneauth(&data->state.authhost, authmask);
     if(!pickhost)
     if(!pickhost)
       data->state.authproblem = TRUE;
       data->state.authproblem = TRUE;
+    if(data->state.authhost.picked == CURLAUTH_NTLM &&
+       conn->httpversion > 11) {
+      infof(data, "Forcing HTTP/1.1 for NTLM");
+      connclose(conn, "Force HTTP/1.1 connection");
+      conn->data->set.httpversion = CURL_HTTP_VERSION_1_1;
+    }
   }
   }
   if(conn->bits.proxy_user_passwd &&
   if(conn->bits.proxy_user_passwd &&
      ((data->req.httpcode == 407) ||
      ((data->req.httpcode == 407) ||
@@ -576,6 +620,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
   return result;
   return result;
 }
 }
 
 
+#ifndef CURL_DISABLE_HTTP_AUTH
 /*
 /*
  * Output the correct authentication header depending on the auth type
  * Output the correct authentication header depending on the auth type
  * and whether or not it is to a proxy.
  * and whether or not it is to a proxy.
@@ -592,10 +637,6 @@ output_auth_headers(struct connectdata *conn,
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO)
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO)
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
 #endif
 #endif
-#ifdef USE_SPNEGO
-  struct negotiatedata *negdata = proxy ?
-    &data->state.proxyneg : &data->state.negotiate;
-#endif
 
 
 #ifdef CURL_DISABLE_CRYPTO_AUTH
 #ifdef CURL_DISABLE_CRYPTO_AUTH
   (void)request;
   (void)request;
@@ -603,15 +644,11 @@ output_auth_headers(struct connectdata *conn,
 #endif
 #endif
 
 
 #ifdef USE_SPNEGO
 #ifdef USE_SPNEGO
-  negdata->state = GSS_AUTHNONE;
-  if((authstatus->picked == CURLAUTH_NEGOTIATE) &&
-     negdata->context && !GSS_ERROR(negdata->status)) {
+  if((authstatus->picked == CURLAUTH_NEGOTIATE)) {
     auth = "Negotiate";
     auth = "Negotiate";
     result = Curl_output_negotiate(conn, proxy);
     result = Curl_output_negotiate(conn, proxy);
     if(result)
     if(result)
       return result;
       return result;
-    authstatus->done = TRUE;
-    negdata->state = GSS_AUTHSENT;
   }
   }
   else
   else
 #endif
 #endif
@@ -697,7 +734,7 @@ output_auth_headers(struct connectdata *conn,
  *
  *
  * @param conn all information about the current connection
  * @param conn all information about the current connection
  * @param request pointer to the request keyword
  * @param request pointer to the request keyword
- * @param path pointer to the requested path
+ * @param path pointer to the requested path; should include query part
  * @param proxytunnel boolean if this is the request setting up a "proxy
  * @param proxytunnel boolean if this is the request setting up a "proxy
  * tunnel"
  * tunnel"
  *
  *
@@ -744,7 +781,7 @@ Curl_http_output_auth(struct connectdata *conn,
 #ifndef CURL_DISABLE_PROXY
 #ifndef CURL_DISABLE_PROXY
   /* Send proxy authentication header if needed */
   /* Send proxy authentication header if needed */
   if(conn->bits.httpproxy &&
   if(conn->bits.httpproxy &&
-      (conn->bits.tunnel_proxy == proxytunnel)) {
+     (conn->bits.tunnel_proxy == (bit)proxytunnel)) {
     result = output_auth_headers(conn, authproxy, request, path, TRUE);
     result = output_auth_headers(conn, authproxy, request, path, TRUE);
     if(result)
     if(result)
       return result;
       return result;
@@ -772,6 +809,22 @@ Curl_http_output_auth(struct connectdata *conn,
   return result;
   return result;
 }
 }
 
 
+#else
+/* when disabled */
+CURLcode
+Curl_http_output_auth(struct connectdata *conn,
+                      const char *request,
+                      const char *path,
+                      bool proxytunnel)
+{
+  (void)conn;
+  (void)request;
+  (void)path;
+  (void)proxytunnel;
+  return CURLE_OK;
+}
+#endif
+
 /*
 /*
  * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
  * Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
  * headers. They are dealt with both in the transfer.c main loop and in the
  * headers. They are dealt with both in the transfer.c main loop and in the
@@ -787,8 +840,8 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
 
 
 #ifdef USE_SPNEGO
 #ifdef USE_SPNEGO
-  struct negotiatedata *negdata = proxy?
-    &data->state.proxyneg:&data->state.negotiate;
+  curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state :
+                                    &conn->http_negotiate_state;
 #endif
 #endif
   unsigned long *availp;
   unsigned long *availp;
   struct auth *authp;
   struct auth *authp;
@@ -827,21 +880,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
         authp->avail |= CURLAUTH_NEGOTIATE;
         authp->avail |= CURLAUTH_NEGOTIATE;
 
 
         if(authp->picked == CURLAUTH_NEGOTIATE) {
         if(authp->picked == CURLAUTH_NEGOTIATE) {
-          if(negdata->state == GSS_AUTHSENT ||
-             negdata->state == GSS_AUTHNONE) {
-            CURLcode result = Curl_input_negotiate(conn, proxy, auth);
-            if(!result) {
-              DEBUGASSERT(!data->req.newurl);
-              data->req.newurl = strdup(data->change.url);
-              if(!data->req.newurl)
-                return CURLE_OUT_OF_MEMORY;
-              data->state.authproblem = FALSE;
-              /* we received a GSS auth token and we dealt with it fine */
-              negdata->state = GSS_AUTHRECV;
-            }
-            else
-              data->state.authproblem = TRUE;
+          CURLcode result = Curl_input_negotiate(conn, proxy, auth);
+          if(!result) {
+            DEBUGASSERT(!data->req.newurl);
+            data->req.newurl = strdup(data->change.url);
+            if(!data->req.newurl)
+              return CURLE_OUT_OF_MEMORY;
+            data->state.authproblem = FALSE;
+            /* we received a GSS auth token and we dealt with it fine */
+            *negstate = GSS_AUTHRECV;
           }
           }
+          else
+            data->state.authproblem = TRUE;
         }
         }
       }
       }
     }
     }
@@ -869,19 +919,10 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
                 *availp |= CURLAUTH_NTLM_WB;
                 *availp |= CURLAUTH_NTLM_WB;
                 authp->avail |= CURLAUTH_NTLM_WB;
                 authp->avail |= CURLAUTH_NTLM_WB;
 
 
-                /* Get the challenge-message which will be passed to
-                 * ntlm_auth for generating the type 3 message later */
-                while(*auth && ISSPACE(*auth))
-                  auth++;
-                if(checkprefix("NTLM", auth)) {
-                  auth += strlen("NTLM");
-                  while(*auth && ISSPACE(*auth))
-                    auth++;
-                  if(*auth) {
-                    conn->challenge_header = strdup(auth);
-                    if(!conn->challenge_header)
-                      return CURLE_OUT_OF_MEMORY;
-                  }
+                result = Curl_input_ntlm_wb(conn, proxy, auth);
+                if(result) {
+                  infof(data, "Authentication problem. Ignoring this.\n");
+                  data->state.authproblem = TRUE;
                 }
                 }
               }
               }
 #endif
 #endif
@@ -1111,14 +1152,13 @@ void Curl_add_buffer_free(Curl_send_buffer **inp)
 CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
 CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
                               struct connectdata *conn,
                               struct connectdata *conn,
 
 
-                               /* add the number of sent bytes to this
-                                  counter */
-                              long *bytes_written,
+                              /* add the number of sent bytes to this
+                                 counter */
+                              curl_off_t *bytes_written,
 
 
-                               /* how much of the buffer contains body data */
+                              /* how much of the buffer contains body data */
                               size_t included_body_bytes,
                               size_t included_body_bytes,
                               int socketindex)
                               int socketindex)
-
 {
 {
   ssize_t amount;
   ssize_t amount;
   CURLcode result;
   CURLcode result;
@@ -1214,7 +1254,8 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
     if(http) {
     if(http) {
       /* if we sent a piece of the body here, up the byte counter for it
       /* if we sent a piece of the body here, up the byte counter for it
          accordingly */
          accordingly */
-      http->writebytecount += bodylen;
+      data->req.writebytecount += bodylen;
+      Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
 
 
       if((size_t)amount != size) {
       if((size_t)amount != size) {
         /* The whole request could not be sent in one system call. We must
         /* The whole request could not be sent in one system call. We must
@@ -1255,7 +1296,6 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
            This needs FIXing.
            This needs FIXing.
         */
         */
         return CURLE_SEND_ERROR;
         return CURLE_SEND_ERROR;
-      Curl_pipeline_leave_write(conn);
     }
     }
   }
   }
   Curl_add_buffer_free(&in);
   Curl_add_buffer_free(&in);
@@ -1432,12 +1472,14 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
     /* nothing else to do except wait right now - we're not done here. */
     /* nothing else to do except wait right now - we're not done here. */
     return CURLE_OK;
     return CURLE_OK;
 
 
+#ifndef CURL_DISABLE_PROXY
   if(conn->data->set.haproxyprotocol) {
   if(conn->data->set.haproxyprotocol) {
     /* add HAProxy PROXY protocol header */
     /* add HAProxy PROXY protocol header */
     result = add_haproxy_protocol_header(conn);
     result = add_haproxy_protocol_header(conn);
     if(result)
     if(result)
       return result;
       return result;
   }
   }
+#endif
 
 
   if(conn->given->protocol & CURLPROTO_HTTPS) {
   if(conn->given->protocol & CURLPROTO_HTTPS) {
     /* perform SSL initialization */
     /* perform SSL initialization */
@@ -1464,6 +1506,7 @@ static int http_getsock_do(struct connectdata *conn,
   return GETSOCK_WRITESOCK(0);
   return GETSOCK_WRITESOCK(0);
 }
 }
 
 
+#ifndef CURL_DISABLE_PROXY
 static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
 static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
 {
 {
   char proxy_header[128];
   char proxy_header[128];
@@ -1479,14 +1522,14 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
     strcpy(tcp_version, "TCP4");
     strcpy(tcp_version, "TCP4");
   }
   }
 
 
-  snprintf(proxy_header,
-           sizeof(proxy_header),
-           "PROXY %s %s %s %li %li\r\n",
-           tcp_version,
-           conn->data->info.conn_local_ip,
-           conn->data->info.conn_primary_ip,
-           conn->data->info.conn_local_port,
-           conn->data->info.conn_primary_port);
+  msnprintf(proxy_header,
+            sizeof(proxy_header),
+            "PROXY %s %s %s %li %li\r\n",
+            tcp_version,
+            conn->data->info.conn_local_ip,
+            conn->data->info.conn_primary_ip,
+            conn->data->info.conn_local_port,
+            conn->data->info.conn_primary_port);
 
 
   req_buffer = Curl_add_buffer_init();
   req_buffer = Curl_add_buffer_init();
   if(!req_buffer)
   if(!req_buffer)
@@ -1504,6 +1547,7 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
 
 
   return result;
   return result;
 }
 }
+#endif
 
 
 #ifdef USE_SSL
 #ifdef USE_SSL
 static CURLcode https_connecting(struct connectdata *conn, bool *done)
 static CURLcode https_connecting(struct connectdata *conn, bool *done)
@@ -1547,20 +1591,6 @@ CURLcode Curl_http_done(struct connectdata *conn,
 
 
   Curl_unencode_cleanup(conn);
   Curl_unencode_cleanup(conn);
 
 
-#ifdef USE_SPNEGO
-  if(data->state.proxyneg.state == GSS_AUTHSENT ||
-     data->state.negotiate.state == GSS_AUTHSENT) {
-    /* add forbid re-use if http-code != 401/407 as a WA only needed for
-     * 401/407 that signal auth failure (empty) otherwise state will be RECV
-     * with current code.
-     * Do not close CONNECT_ONLY connections. */
-    if((data->req.httpcode != 401) && (data->req.httpcode != 407) &&
-       !data->set.connect_only)
-      streamclose(conn, "Negotiate transfer completed");
-    Curl_cleanup_negotiate(data);
-  }
-#endif
-
   /* set the proper values (possibly modified on POST) */
   /* set the proper values (possibly modified on POST) */
   conn->seek_func = data->set.seek_func; /* restore */
   conn->seek_func = data->set.seek_func; /* restore */
   conn->seek_client = data->set.seek_client; /* restore */
   conn->seek_client = data->set.seek_client; /* restore */
@@ -1576,16 +1606,6 @@ CURLcode Curl_http_done(struct connectdata *conn,
 
 
   Curl_mime_cleanpart(&http->form);
   Curl_mime_cleanpart(&http->form);
 
 
-  switch(data->set.httpreq) {
-  case HTTPREQ_PUT:
-  case HTTPREQ_POST_FORM:
-  case HTTPREQ_POST_MIME:
-    data->req.bytecount = http->readbytecount + http->writebytecount;
-    break;
-  default:
-    break;
-  }
-
   if(status)
   if(status)
     return status;
     return status;
 
 
@@ -1593,7 +1613,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
                       entire operation is complete */
                       entire operation is complete */
      !conn->bits.retry &&
      !conn->bits.retry &&
      !data->set.connect_only &&
      !data->set.connect_only &&
-     (http->readbytecount +
+     (data->req.bytecount +
       data->req.headerbytecount -
       data->req.headerbytecount -
       data->req.deductheadercount) <= 0) {
       data->req.deductheadercount) <= 0) {
     /* If this connection isn't simply closed to be retried, AND nothing was
     /* If this connection isn't simply closed to be retried, AND nothing was
@@ -1676,6 +1696,50 @@ enum proxy_use {
   HEADER_CONNECT  /* sending CONNECT to a proxy */
   HEADER_CONNECT  /* sending CONNECT to a proxy */
 };
 };
 
 
+/* used to compile the provided trailers into one buffer
+   will return an error code if one of the headers is
+   not formatted correctly */
+CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
+                                    Curl_send_buffer *buffer,
+                                    struct Curl_easy *handle)
+{
+  char *ptr = NULL;
+  CURLcode result = CURLE_OK;
+  const char *endofline_native = NULL;
+  const char *endofline_network = NULL;
+
+  if(
+#ifdef CURL_DO_LINEEND_CONV
+     (handle->set.prefer_ascii) ||
+#endif
+     (handle->set.crlf)) {
+    /* \n will become \r\n later on */
+    endofline_native  = "\n";
+    endofline_network = "\x0a";
+  }
+  else {
+    endofline_native  = "\r\n";
+    endofline_network = "\x0d\x0a";
+  }
+
+  while(trailers) {
+    /* only add correctly formatted trailers */
+    ptr = strchr(trailers->data, ':');
+    if(ptr && *(ptr + 1) == ' ') {
+      result = Curl_add_bufferf(&buffer, "%s%s", trailers->data,
+                                endofline_native);
+      if(result)
+        return result;
+    }
+    else
+      infof(handle, "Malformatted trailing header ! Skipping trailer.");
+    trailers = trailers->next;
+  }
+  result = Curl_add_buffer(&buffer, endofline_network,
+                           strlen(endofline_network));
+  return result;
+}
+
 CURLcode Curl_add_custom_headers(struct connectdata *conn,
 CURLcode Curl_add_custom_headers(struct connectdata *conn,
                                  bool is_connect,
                                  bool is_connect,
                                  Curl_send_buffer *req_buffer)
                                  Curl_send_buffer *req_buffer)
@@ -1737,9 +1801,16 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
           }
           }
           else {
           else {
             if(*(--ptr) == ';') {
             if(*(--ptr) == ';') {
-              /* send no-value custom header if terminated by semicolon */
-              *ptr = ':';
-              semicolonp = ptr;
+              /* copy the source */
+              semicolonp = strdup(headers->data);
+              if(!semicolonp) {
+                Curl_add_buffer_free(&req_buffer);
+                return CURLE_OUT_OF_MEMORY;
+              }
+              /* put a colon where the semicolon is */
+              semicolonp[ptr - headers->data] = ':';
+              /* point at the colon */
+              optr = &semicolonp [ptr - headers->data];
             }
             }
           }
           }
           ptr = optr;
           ptr = optr;
@@ -1755,35 +1826,37 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
         if(*ptr || semicolonp) {
         if(*ptr || semicolonp) {
           /* only send this if the contents was non-blank or done special */
           /* only send this if the contents was non-blank or done special */
           CURLcode result = CURLE_OK;
           CURLcode result = CURLE_OK;
+          char *compare = semicolonp ? semicolonp : headers->data;
 
 
           if(conn->allocptr.host &&
           if(conn->allocptr.host &&
              /* a Host: header was sent already, don't pass on any custom Host:
              /* a Host: header was sent already, don't pass on any custom Host:
                 header as that will produce *two* in the same request! */
                 header as that will produce *two* in the same request! */
-             checkprefix("Host:", headers->data))
+             checkprefix("Host:", compare))
             ;
             ;
           else if(data->set.httpreq == HTTPREQ_POST_FORM &&
           else if(data->set.httpreq == HTTPREQ_POST_FORM &&
                   /* this header (extended by formdata.c) is sent later */
                   /* this header (extended by formdata.c) is sent later */
-                  checkprefix("Content-Type:", headers->data))
+                  checkprefix("Content-Type:", compare))
             ;
             ;
           else if(data->set.httpreq == HTTPREQ_POST_MIME &&
           else if(data->set.httpreq == HTTPREQ_POST_MIME &&
                   /* this header is sent later */
                   /* this header is sent later */
-                  checkprefix("Content-Type:", headers->data))
+                  checkprefix("Content-Type:", compare))
             ;
             ;
           else if(conn->bits.authneg &&
           else if(conn->bits.authneg &&
                   /* while doing auth neg, don't allow the custom length since
                   /* while doing auth neg, don't allow the custom length since
                      we will force length zero then */
                      we will force length zero then */
-                  checkprefix("Content-Length:", headers->data))
+                  checkprefix("Content-Length:", compare))
             ;
             ;
           else if(conn->allocptr.te &&
           else if(conn->allocptr.te &&
                   /* when asking for Transfer-Encoding, don't pass on a custom
                   /* when asking for Transfer-Encoding, don't pass on a custom
                      Connection: */
                      Connection: */
-                  checkprefix("Connection:", headers->data))
+                  checkprefix("Connection:", compare))
             ;
             ;
           else if((conn->httpversion == 20) &&
           else if((conn->httpversion == 20) &&
-                  checkprefix("Transfer-Encoding:", headers->data))
+                  checkprefix("Transfer-Encoding:", compare))
             /* HTTP/2 doesn't support chunked requests */
             /* HTTP/2 doesn't support chunked requests */
             ;
             ;
-          else if(checkprefix("Authorization:", headers->data) &&
+          else if((checkprefix("Authorization:", compare) ||
+                   checkprefix("Cookie:", compare)) &&
                   /* be careful of sending this potentially sensitive header to
                   /* be careful of sending this potentially sensitive header to
                      other hosts */
                      other hosts */
                   (data->state.this_is_a_follow &&
                   (data->state.this_is_a_follow &&
@@ -1792,10 +1865,10 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
                    !strcasecompare(data->state.first_host, conn->host.name)))
                    !strcasecompare(data->state.first_host, conn->host.name)))
             ;
             ;
           else {
           else {
-            result = Curl_add_bufferf(&req_buffer, "%s\r\n", headers->data);
+            result = Curl_add_bufferf(&req_buffer, "%s\r\n", compare);
           }
           }
           if(semicolonp)
           if(semicolonp)
-            *semicolonp = ';'; /* put back the semicolon */
+            free(semicolonp);
           if(result)
           if(result)
             return result;
             return result;
         }
         }
@@ -1807,6 +1880,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
   return CURLE_OK;
   return CURLE_OK;
 }
 }
 
 
+#ifndef CURL_DISABLE_PARSEDATE
 CURLcode Curl_add_timecondition(struct Curl_easy *data,
 CURLcode Curl_add_timecondition(struct Curl_easy *data,
                                 Curl_send_buffer *req_buffer)
                                 Curl_send_buffer *req_buffer)
 {
 {
@@ -1850,21 +1924,31 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
    */
    */
 
 
   /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
   /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
-  snprintf(datestr, sizeof(datestr),
-           "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
-           condp,
-           Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
-           tm->tm_mday,
-           Curl_month[tm->tm_mon],
-           tm->tm_year + 1900,
-           tm->tm_hour,
-           tm->tm_min,
-           tm->tm_sec);
+  msnprintf(datestr, sizeof(datestr),
+            "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+            condp,
+            Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
+            tm->tm_mday,
+            Curl_month[tm->tm_mon],
+            tm->tm_year + 1900,
+            tm->tm_hour,
+            tm->tm_min,
+            tm->tm_sec);
 
 
   result = Curl_add_buffer(&req_buffer, datestr, strlen(datestr));
   result = Curl_add_buffer(&req_buffer, datestr, strlen(datestr));
 
 
   return result;
   return result;
 }
 }
+#else
+/* disabled */
+CURLcode Curl_add_timecondition(struct Curl_easy *data,
+                                Curl_send_buffer *req_buffer)
+{
+  (void)data;
+  (void)req_buffer;
+  return CURLE_OK;
+}
+#endif
 
 
 /*
 /*
  * Curl_http() gets called from the generic multi_do() function when a HTTP
  * Curl_http() gets called from the generic multi_do() function when a HTTP
@@ -1916,6 +2000,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
 #ifdef USE_NGHTTP2
 #ifdef USE_NGHTTP2
       if(conn->data->set.httpversion ==
       if(conn->data->set.httpversion ==
          CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
          CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
+        if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
+          /* We don't support HTTP/2 proxies yet. Also it's debatable whether
+             or not this setting should apply to HTTP/2 proxies. */
+          infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
+          break;
+        }
+
         DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
         DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
         conn->httpversion = 20;
         conn->httpversion = 20;
 
 
@@ -1947,7 +2038,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
 
 
     data->state.first_remote_port = conn->remote_port;
     data->state.first_remote_port = conn->remote_port;
   }
   }
-  http->writebytecount = http->readbytecount = 0;
 
 
   if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
   if((conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) &&
      data->set.upload) {
      data->set.upload) {
@@ -1995,11 +2085,21 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   }
   }
 
 
   /* setup the authentication headers */
   /* setup the authentication headers */
-  result = Curl_http_output_auth(conn, request, path, FALSE);
-  if(result)
-    return result;
+  {
+    char *pq = NULL;
+    if(query && *query) {
+      pq = aprintf("%s?%s", path, query);
+      if(!pq)
+        return CURLE_OUT_OF_MEMORY;
+    }
+    result = Curl_http_output_auth(conn, request, (pq ? pq : path), FALSE);
+    free(pq);
+    if(result)
+      return result;
+  }
 
 
-  if((data->state.authhost.multipass || data->state.authproxy.multipass) &&
+  if(((data->state.authhost.multipass && !data->state.authhost.done)
+      || (data->state.authproxy.multipass && !data->state.authproxy.done)) &&
      (httpreq != HTTPREQ_GET) &&
      (httpreq != HTTPREQ_GET) &&
      (httpreq != HTTPREQ_HEAD)) {
      (httpreq != HTTPREQ_HEAD)) {
     /* Auth is required and we are not authenticated yet. Make a PUT or POST
     /* Auth is required and we are not authenticated yet. Make a PUT or POST
@@ -2084,6 +2184,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
     http->sendit = NULL;
     http->sendit = NULL;
   }
   }
 
 
+#ifndef CURL_DISABLE_MIME
   if(http->sendit) {
   if(http->sendit) {
     const char *cthdr = Curl_checkheaders(conn, "Content-Type");
     const char *cthdr = Curl_checkheaders(conn, "Content-Type");
 
 
@@ -2108,6 +2209,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       return result;
       return result;
     http->postsize = Curl_mime_size(http->sendit);
     http->postsize = Curl_mime_size(http->sendit);
   }
   }
+#endif
 
 
   ptr = Curl_checkheaders(conn, "Transfer-Encoding");
   ptr = Curl_checkheaders(conn, "Transfer-Encoding");
   if(ptr) {
   if(ptr) {
@@ -2293,8 +2395,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
           if(!*data->state.up.path && path[strlen(path) - 1] != '/') {
           if(!*data->state.up.path && path[strlen(path) - 1] != '/') {
             *p++ = '/';
             *p++ = '/';
           }
           }
-          snprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
-                   data->set.prefer_ascii ? 'a' : 'i');
+          msnprintf(p, sizeof(ftp_typecode) - 1, ";type=%c",
+                    data->set.prefer_ascii ? 'a' : 'i');
         }
         }
       }
       }
       if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
       if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
@@ -2635,9 +2737,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       failf(data, "Failed sending PUT request");
       failf(data, "Failed sending PUT request");
     else
     else
       /* prepare for transfer */
       /* prepare for transfer */
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
-                          &http->readbytecount, postsize?FIRSTSOCKET:-1,
-                          postsize?&http->writebytecount:NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
+                          postsize?FIRSTSOCKET:-1);
     if(result)
     if(result)
       return result;
       return result;
     break;
     break;
@@ -2657,12 +2758,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
         failf(data, "Failed sending POST request");
         failf(data, "Failed sending POST request");
       else
       else
         /* setup variables for the upcoming transfer */
         /* setup variables for the upcoming transfer */
-        Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
-                            -1, NULL);
+        Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE, -1);
       break;
       break;
     }
     }
 
 
-    postsize = http->postsize;
+    data->state.infilesize = postsize = http->postsize;
 
 
     /* We only set Content-Length and allow a custom Content-Length if
     /* We only set Content-Length and allow a custom Content-Length if
        we don't upload data chunked, as RFC2616 forbids us to set both
        we don't upload data chunked, as RFC2616 forbids us to set both
@@ -2678,6 +2778,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
         return result;
         return result;
     }
     }
 
 
+#ifndef CURL_DISABLE_MIME
     /* Output mime-generated headers. */
     /* Output mime-generated headers. */
     {
     {
       struct curl_slist *hdr;
       struct curl_slist *hdr;
@@ -2688,6 +2789,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
           return result;
           return result;
       }
       }
     }
     }
+#endif
 
 
     /* For really small posts we don't use Expect: headers at all, and for
     /* For really small posts we don't use Expect: headers at all, and for
        the somewhat bigger ones we allow the app to disable it. Just make
        the somewhat bigger ones we allow the app to disable it. Just make
@@ -2726,9 +2828,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       failf(data, "Failed sending POST request");
       failf(data, "Failed sending POST request");
     else
     else
       /* prepare for transfer */
       /* prepare for transfer */
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
-                          &http->readbytecount, postsize?FIRSTSOCKET:-1,
-                          postsize?&http->writebytecount:NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
+                          postsize?FIRSTSOCKET:-1);
     if(result)
     if(result)
       return result;
       return result;
 
 
@@ -2882,9 +2983,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
     if(result)
     if(result)
       failf(data, "Failed sending HTTP POST request");
       failf(data, "Failed sending HTTP POST request");
     else
     else
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
-                          &http->readbytecount, http->postdata?FIRSTSOCKET:-1,
-                          http->postdata?&http->writebytecount:NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
+                          http->postdata?FIRSTSOCKET:-1);
     break;
     break;
 
 
   default:
   default:
@@ -2900,33 +3000,30 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       failf(data, "Failed sending HTTP request");
       failf(data, "Failed sending HTTP request");
     else
     else
       /* HTTP GET/HEAD download: */
       /* HTTP GET/HEAD download: */
-      Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
-                          http->postdata?FIRSTSOCKET:-1,
-                          http->postdata?&http->writebytecount:NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, -1, TRUE,
+                          http->postdata?FIRSTSOCKET:-1);
   }
   }
   if(result)
   if(result)
     return result;
     return result;
 
 
-  if(http->writebytecount) {
+  if(data->req.writebytecount) {
     /* if a request-body has been sent off, we make sure this progress is noted
     /* if a request-body has been sent off, we make sure this progress is noted
        properly */
        properly */
-    Curl_pgrsSetUploadCounter(data, http->writebytecount);
+    Curl_pgrsSetUploadCounter(data, data->req.writebytecount);
     if(Curl_pgrsUpdate(conn))
     if(Curl_pgrsUpdate(conn))
       result = CURLE_ABORTED_BY_CALLBACK;
       result = CURLE_ABORTED_BY_CALLBACK;
 
 
-    if(http->writebytecount >= postsize) {
+    if(data->req.writebytecount >= postsize) {
       /* already sent the entire request body, mark the "upload" as
       /* already sent the entire request body, mark the "upload" as
          complete */
          complete */
       infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
       infof(data, "upload completely sent off: %" CURL_FORMAT_CURL_OFF_T
             " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
             " out of %" CURL_FORMAT_CURL_OFF_T " bytes\n",
-            http->writebytecount, postsize);
+            data->req.writebytecount, postsize);
       data->req.upload_done = TRUE;
       data->req.upload_done = TRUE;
       data->req.keepon &= ~KEEP_SEND; /* we're done writing */
       data->req.keepon &= ~KEEP_SEND; /* we're done writing */
       data->req.exp100 = EXP100_SEND_DATA; /* already sent */
       data->req.exp100 = EXP100_SEND_DATA; /* already sent */
       Curl_expire_done(data, EXPIRE_100_TIMEOUT);
       Curl_expire_done(data, EXPIRE_100_TIMEOUT);
     }
     }
-    else
-      data->req.writebytecount = http->writebytecount;
   }
   }
 
 
   if((conn->httpversion == 20) && data->req.upload_chunky)
   if((conn->httpversion == 20) && data->req.upload_chunky)
@@ -3161,6 +3258,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
           k->header = FALSE;
           k->header = FALSE;
           k->badheader = HEADER_ALLBAD;
           k->badheader = HEADER_ALLBAD;
           streamclose(conn, "bad HTTP: No end-of-message indicator");
           streamclose(conn, "bad HTTP: No end-of-message indicator");
+          if(!data->set.http09_allowed) {
+            failf(data, "Received HTTP/0.9 when not allowed\n");
+            return CURLE_UNSUPPORTED_PROTOCOL;
+          }
           break;
           break;
         }
         }
       }
       }
@@ -3194,6 +3295,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
       if(st == STATUS_BAD) {
       if(st == STATUS_BAD) {
         streamclose(conn, "bad HTTP: No end-of-message indicator");
         streamclose(conn, "bad HTTP: No end-of-message indicator");
         /* this is not the beginning of a protocol first header line */
         /* this is not the beginning of a protocol first header line */
+        if(!data->set.http09_allowed) {
+          failf(data, "Received HTTP/0.9 when not allowed\n");
+          return CURLE_UNSUPPORTED_PROTOCOL;
+        }
         k->header = FALSE;
         k->header = FALSE;
         if(*nread)
         if(*nread)
           /* since there's more, this is a partial bad header */
           /* since there's more, this is a partial bad header */
@@ -3306,14 +3411,31 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
 #if defined(USE_NTLM)
 #if defined(USE_NTLM)
       if(conn->bits.close &&
       if(conn->bits.close &&
          (((data->req.httpcode == 401) &&
          (((data->req.httpcode == 401) &&
-           (conn->ntlm.state == NTLMSTATE_TYPE2)) ||
+           (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
           ((data->req.httpcode == 407) &&
           ((data->req.httpcode == 407) &&
-           (conn->proxyntlm.state == NTLMSTATE_TYPE2)))) {
+           (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
         infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
         infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
         data->state.authproblem = TRUE;
         data->state.authproblem = TRUE;
       }
       }
 #endif
 #endif
-
+#if defined(USE_SPNEGO)
+      if(conn->bits.close &&
+        (((data->req.httpcode == 401) &&
+          (conn->http_negotiate_state == GSS_AUTHRECV)) ||
+         ((data->req.httpcode == 407) &&
+          (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
+        infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
+        data->state.authproblem = TRUE;
+      }
+      if((conn->http_negotiate_state == GSS_AUTHDONE) &&
+         (data->req.httpcode != 401)) {
+        conn->http_negotiate_state = GSS_AUTHSUCC;
+      }
+      if((conn->proxy_negotiate_state == GSS_AUTHDONE) &&
+         (data->req.httpcode != 407)) {
+        conn->proxy_negotiate_state = GSS_AUTHSUCC;
+      }
+#endif
       /*
       /*
        * When all the headers have been parsed, see if we should give
        * When all the headers have been parsed, see if we should give
        * up and return an error.
        * up and return an error.
@@ -3549,6 +3671,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
             if(conn->httpversion != 20)
             if(conn->httpversion != 20)
               infof(data, "Lying server, not serving HTTP/2\n");
               infof(data, "Lying server, not serving HTTP/2\n");
           }
           }
+          if(conn->httpversion < 20) {
+            conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
+            infof(data, "Mark bundle as not supporting multiuse\n");
+          }
         }
         }
         else if(!nc) {
         else if(!nc) {
           /* this is the real world, not a Nirvana
           /* this is the real world, not a Nirvana
@@ -3586,7 +3712,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
           conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
           conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
         }
         }
         else {
         else {
-          /* TODO: do we care about the other cases here? */
           nc = 0;
           nc = 0;
         }
         }
       }
       }
@@ -3639,26 +3764,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         }
         }
         else if(conn->httpversion >= 11 &&
         else if(conn->httpversion >= 11 &&
                 !conn->bits.close) {
                 !conn->bits.close) {
-          /* If HTTP version is >= 1.1 and connection is persistent
-             server supports pipelining. */
+          /* If HTTP version is >= 1.1 and connection is persistent */
           DEBUGF(infof(data,
           DEBUGF(infof(data,
-                       "HTTP 1.1 or later with persistent connection, "
-                       "pipelining supported\n"));
-          /* Activate pipelining if needed */
-          if(conn->bundle) {
-            if(!Curl_pipeline_site_blacklisted(data, conn))
-              conn->bundle->multiuse = BUNDLE_PIPELINING;
-          }
+                       "HTTP 1.1 or later with persistent connection\n"));
         }
         }
 
 
         switch(k->httpcode) {
         switch(k->httpcode) {
-        case 204:
-          /* (quote from RFC2616, section 10.2.5): The server has
-           * fulfilled the request but does not need to return an
-           * entity-body ... The 204 response MUST NOT include a
-           * message-body, and thus is always terminated by the first
-           * empty line after the header fields. */
-          /* FALLTHROUGH */
         case 304:
         case 304:
           /* (quote from RFC2616, section 10.3.5): The 304 response
           /* (quote from RFC2616, section 10.3.5): The 304 response
            * MUST NOT contain a message-body, and thus is always
            * MUST NOT contain a message-body, and thus is always
@@ -3666,6 +3777,13 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
            * fields.  */
            * fields.  */
           if(data->set.timecondition)
           if(data->set.timecondition)
             data->info.timecond = TRUE;
             data->info.timecond = TRUE;
+          /* FALLTHROUGH */
+        case 204:
+          /* (quote from RFC2616, section 10.2.5): The server has
+           * fulfilled the request but does not need to return an
+           * entity-body ... The 204 response MUST NOT include a
+           * message-body, and thus is always terminated by the first
+           * empty line after the header fields. */
           k->size = 0;
           k->size = 0;
           k->maxdownload = 0;
           k->maxdownload = 0;
           k->ignorecl = TRUE; /* ignore Content-Length headers */
           k->ignorecl = TRUE; /* ignore Content-Length headers */
@@ -3733,19 +3851,6 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         data->info.contenttype = contenttype;
         data->info.contenttype = contenttype;
       }
       }
     }
     }
-    else if(checkprefix("Server:", k->p)) {
-      if(conn->httpversion < 20) {
-        /* only do this for non-h2 servers */
-        char *server_name = Curl_copy_header_value(k->p);
-
-        /* Turn off pipelining if the server version is blacklisted  */
-        if(conn->bundle && (conn->bundle->multiuse == BUNDLE_PIPELINING)) {
-          if(Curl_pipeline_server_blacklisted(data, server_name))
-            conn->bundle->multiuse = BUNDLE_NO_MULTIUSE;
-        }
-        free(server_name);
-      }
-    }
     else if((conn->httpversion == 10) &&
     else if((conn->httpversion == 10) &&
             conn->bits.httpproxy &&
             conn->bits.httpproxy &&
             Curl_compareheader(k->p,
             Curl_compareheader(k->p,
@@ -3859,7 +3964,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
                          here, or else use real peer host name. */
                          here, or else use real peer host name. */
                       conn->allocptr.cookiehost?
                       conn->allocptr.cookiehost?
                       conn->allocptr.cookiehost:conn->host.name,
                       conn->allocptr.cookiehost:conn->host.name,
-                      data->state.up.path);
+                      data->state.up.path,
+                      (conn->handler->protocol&CURLPROTO_HTTPS)?
+                      TRUE:FALSE);
       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
     }
     }
 #endif
 #endif
@@ -3888,6 +3995,22 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
       if(result)
       if(result)
         return result;
         return result;
     }
     }
+  #ifdef USE_SPNEGO
+    else if(checkprefix("Persistent-Auth", k->p)) {
+      struct negotiatedata *negdata = &conn->negotiate;
+      struct auth *authp = &data->state.authhost;
+      if(authp->picked == CURLAUTH_NEGOTIATE) {
+        char *persistentauth = Curl_copy_header_value(k->p);
+        if(!persistentauth)
+          return CURLE_OUT_OF_MEMORY;
+        negdata->noauthpersist = checkprefix("false", persistentauth);
+        negdata->havenoauthpersist = TRUE;
+        infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
+          negdata->noauthpersist, persistentauth);
+        free(persistentauth);
+      }
+    }
+  #endif
     else if((k->httpcode >= 300 && k->httpcode < 400) &&
     else if((k->httpcode >= 300 && k->httpcode < 400) &&
             checkprefix("Location:", k->p) &&
             checkprefix("Location:", k->p) &&
             !data->req.location) {
             !data->req.location) {
@@ -3915,6 +4038,27 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         }
         }
       }
       }
     }
     }
+#ifdef USE_ALTSVC
+    /* If enabled, the header is incoming and this is over HTTPS */
+    else if(data->asi && checkprefix("Alt-Svc:", k->p) &&
+            ((conn->handler->flags & PROTOPT_SSL) ||
+#ifdef CURLDEBUG
+             /* allow debug builds to circumvent the HTTPS restriction */
+             getenv("CURL_ALTSVC_HTTP")
+#else
+             0
+#endif
+              )) {
+      /* the ALPN of the current request */
+      enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
+      result = Curl_altsvc_parse(data, data->asi,
+                                 &k->p[ strlen("Alt-Svc:") ],
+                                 id, conn->host.name,
+                                 curlx_uitous(conn->remote_port));
+      if(result)
+        return result;
+    }
+#endif
     else if(conn->handler->protocol & CURLPROTO_RTSP) {
     else if(conn->handler->protocol & CURLPROTO_RTSP) {
       result = Curl_rtsp_parseheader(conn, k->p);
       result = Curl_rtsp_parseheader(conn, k->p);
       if(result)
       if(result)

+ 5 - 4
Utilities/cmcurl/lib/http.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -65,7 +65,7 @@ CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr,
                          size_t size) WARN_UNUSED_RESULT;
                          size_t size) WARN_UNUSED_RESULT;
 CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
 CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
                               struct connectdata *conn,
                               struct connectdata *conn,
-                              long *bytes_written,
+                              curl_off_t *bytes_written,
                               size_t included_body_bytes,
                               size_t included_body_bytes,
                               int socketindex);
                               int socketindex);
 
 
@@ -74,6 +74,9 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
 CURLcode Curl_add_custom_headers(struct connectdata *conn,
 CURLcode Curl_add_custom_headers(struct connectdata *conn,
                                  bool is_connect,
                                  bool is_connect,
                                  Curl_send_buffer *req_buffer);
                                  Curl_send_buffer *req_buffer);
+CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
+                                    Curl_send_buffer *buffer,
+                                    struct Curl_easy *handle);
 
 
 /* protocol-specific functions set up to be called by the main engine */
 /* protocol-specific functions set up to be called by the main engine */
 CURLcode Curl_http(struct connectdata *conn, bool *done);
 CURLcode Curl_http(struct connectdata *conn, bool *done);
@@ -136,8 +139,6 @@ struct HTTP {
 
 
   const char *p_pragma;      /* Pragma: string */
   const char *p_pragma;      /* Pragma: string */
   const char *p_accept;      /* Accept: string */
   const char *p_accept;      /* Accept: string */
-  curl_off_t readbytecount;
-  curl_off_t writebytecount;
 
 
   /* For FORM posting */
   /* For FORM posting */
   curl_mimepart form;
   curl_mimepart form;

+ 60 - 16
Utilities/cmcurl/lib/http2.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -111,8 +111,6 @@ static int http2_perform_getsock(const struct connectdata *conn,
   int bitmap = GETSOCK_BLANK;
   int bitmap = GETSOCK_BLANK;
   (void)numsocks;
   (void)numsocks;
 
 
-  /* TODO We should check underlying socket state if it is SSL socket
-     because of renegotiation. */
   sock[0] = conn->sock[FIRSTSOCKET];
   sock[0] = conn->sock[FIRSTSOCKET];
 
 
   /* in a HTTP/2 connection we can basically always get a frame so we should
   /* in a HTTP/2 connection we can basically always get a frame so we should
@@ -350,14 +348,14 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
 int Curl_http2_ver(char *p, size_t len)
 int Curl_http2_ver(char *p, size_t len)
 {
 {
   nghttp2_info *h2 = nghttp2_version(0);
   nghttp2_info *h2 = nghttp2_version(0);
-  return snprintf(p, len, " nghttp2/%s", h2->version_str);
+  return msnprintf(p, len, " nghttp2/%s", h2->version_str);
 }
 }
 
 
 /* HTTP/2 error code to name based on the Error Code Registry.
 /* HTTP/2 error code to name based on the Error Code Registry.
 https://tools.ietf.org/html/rfc7540#page-77
 https://tools.ietf.org/html/rfc7540#page-77
 nghttp2_error_code enums are identical.
 nghttp2_error_code enums are identical.
 */
 */
-const char *Curl_http2_strerror(uint32_t err)
+static const char *http2_strerror(uint32_t err)
 {
 {
 #ifndef NGHTTP2_HAS_HTTP2_STRERROR
 #ifndef NGHTTP2_HAS_HTTP2_STRERROR
   const char *str[] = {
   const char *str[] = {
@@ -618,6 +616,18 @@ static int push_promise(struct Curl_easy *data,
   return rv;
   return rv;
 }
 }
 
 
+/*
+ * multi_connchanged() is called to tell that there is a connection in
+ * this multi handle that has changed state (multiplexing become possible, the
+ * number of allowed streams changed or similar), and a subsequent use of this
+ * multi handle should move CONNECT_PEND handles back to CONNECT to have them
+ * retry.
+ */
+static void multi_connchanged(struct Curl_multi *multi)
+{
+  multi->recheckstate = TRUE;
+}
+
 static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
 static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
                          void *userp)
                          void *userp)
 {
 {
@@ -650,7 +660,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
         infof(conn->data,
         infof(conn->data,
               "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n",
               "Connection state changed (MAX_CONCURRENT_STREAMS == %u)!\n",
               httpc->settings.max_concurrent_streams);
               httpc->settings.max_concurrent_streams);
-        Curl_multi_connchanged(conn->data->multi);
+        multi_connchanged(conn->data->multi);
       }
       }
     }
     }
     return 0;
     return 0;
@@ -800,7 +810,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
     H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
     H2BUGF(infof(data_s, "NGHTTP2_ERR_PAUSE - %zu bytes out of buffer"
                  ", stream %u\n",
                  ", stream %u\n",
                  len - nread, stream_id));
                  len - nread, stream_id));
-    data_s->easy_conn->proto.httpc.pause_stream_id = stream_id;
+    data_s->conn->proto.httpc.pause_stream_id = stream_id;
 
 
     return NGHTTP2_ERR_PAUSE;
     return NGHTTP2_ERR_PAUSE;
   }
   }
@@ -808,7 +818,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
   /* pause execution of nghttp2 if we received data for another handle
   /* pause execution of nghttp2 if we received data for another handle
      in order to process them first. */
      in order to process them first. */
   if(conn->data != data_s) {
   if(conn->data != data_s) {
-    data_s->easy_conn->proto.httpc.pause_stream_id = stream_id;
+    data_s->conn->proto.httpc.pause_stream_id = stream_id;
 
 
     return NGHTTP2_ERR_PAUSE;
     return NGHTTP2_ERR_PAUSE;
   }
   }
@@ -837,7 +847,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
       return 0;
       return 0;
     }
     }
     H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
     H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
-                 Curl_http2_strerror(error_code), error_code, stream_id));
+                 http2_strerror(error_code), error_code, stream_id));
     stream = data_s->req.protop;
     stream = data_s->req.protop;
     if(!stream)
     if(!stream)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
       return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -854,6 +864,10 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id,
             stream_id);
             stream_id);
       DEBUGASSERT(0);
       DEBUGASSERT(0);
     }
     }
+    if(stream_id == httpc->pause_stream_id) {
+      H2BUGF(infof(data_s, "Stopped the pause stream!\n"));
+      httpc->pause_stream_id = 0;
+    }
     H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
     H2BUGF(infof(data_s, "Removed stream %u hash!\n", stream_id));
     stream->stream_id = 0; /* cleared */
     stream->stream_id = 0; /* cleared */
   }
   }
@@ -953,6 +967,28 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
   if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
   if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
     char *h;
     char *h;
 
 
+    if(!strcmp(":authority", (const char *)name)) {
+      /* pseudo headers are lower case */
+      int rc = 0;
+      char *check = aprintf("%s:%d", conn->host.name, conn->remote_port);
+      if(!check)
+        /* no memory */
+        return NGHTTP2_ERR_CALLBACK_FAILURE;
+      if(!Curl_strcasecompare(check, (const char *)value)) {
+        /* This is push is not for the same authority that was asked for in
+         * the URL. RFC 7540 section 8.2 says: "A client MUST treat a
+         * PUSH_PROMISE for which the server is not authoritative as a stream
+         * error of type PROTOCOL_ERROR."
+         */
+        (void)nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
+                                        stream_id, NGHTTP2_PROTOCOL_ERROR);
+        rc = NGHTTP2_ERR_CALLBACK_FAILURE;
+      }
+      free(check);
+      if(rc)
+        return rc;
+    }
+
     if(!stream->push_headers) {
     if(!stream->push_headers) {
       stream->push_headers_alloc = 10;
       stream->push_headers_alloc = 10;
       stream->push_headers = malloc(stream->push_headers_alloc *
       stream->push_headers = malloc(stream->push_headers_alloc *
@@ -1193,7 +1229,7 @@ void Curl_http2_done(struct connectdata *conn, bool premature)
 /*
 /*
  * Initialize nghttp2 for a Curl connection
  * Initialize nghttp2 for a Curl connection
  */
  */
-CURLcode Curl_http2_init(struct connectdata *conn)
+static CURLcode http2_init(struct connectdata *conn)
 {
 {
   if(!conn->proto.httpc.h2) {
   if(!conn->proto.httpc.h2) {
     int rc;
     int rc;
@@ -1427,7 +1463,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
   }
   }
   else if(httpc->error_code != NGHTTP2_NO_ERROR) {
   else if(httpc->error_code != NGHTTP2_NO_ERROR) {
     failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
     failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
-          stream->stream_id, Curl_http2_strerror(httpc->error_code),
+          stream->stream_id, http2_strerror(httpc->error_code),
           httpc->error_code);
           httpc->error_code);
     *err = CURLE_HTTP2_STREAM;
     *err = CURLE_HTTP2_STREAM;
     return -1;
     return -1;
@@ -1809,9 +1845,9 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
                           const void *mem, size_t len, CURLcode *err)
                           const void *mem, size_t len, CURLcode *err)
 {
 {
   /*
   /*
-   * BIG TODO: Currently, we send request in this function, but this
-   * function is also used to send request body. It would be nice to
-   * add dedicated function for request.
+   * Currently, we send request in this function, but this function is also
+   * used to send request body. It would be nice to add dedicated function for
+   * request.
    */
    */
   int rv;
   int rv;
   struct http_conn *httpc = &conn->proto.httpc;
   struct http_conn *httpc = &conn->proto.httpc;
@@ -2137,7 +2173,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
   else
   else
     conn->handler = &Curl_handler_http2;
     conn->handler = &Curl_handler_http2;
 
 
-  result = Curl_http2_init(conn);
+  result = http2_init(conn);
   if(result) {
   if(result) {
     Curl_add_buffer_free(&stream->header_recvbuf);
     Curl_add_buffer_free(&stream->header_recvbuf);
     return result;
     return result;
@@ -2159,7 +2195,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
   conn->bundle->multiuse = BUNDLE_MULTIPLEX;
   conn->bundle->multiuse = BUNDLE_MULTIPLEX;
 
 
   infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n");
   infof(conn->data, "Connection state changed (HTTP/2 confirmed)\n");
-  Curl_multi_connchanged(conn->data->multi);
+  multi_connchanged(conn->data->multi);
 
 
   return CURLE_OK;
   return CURLE_OK;
 }
 }
@@ -2367,6 +2403,14 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
     Curl_http2_remove_child(data->set.stream_depends_on, data);
     Curl_http2_remove_child(data->set.stream_depends_on, data);
 }
 }
 
 
+/* Only call this function for a transfer that already got a HTTP/2
+   CURLE_HTTP2_STREAM error! */
+bool Curl_h2_http_1_1_error(struct connectdata *conn)
+{
+  struct http_conn *httpc = &conn->proto.httpc;
+  return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED);
+}
+
 #else /* !USE_NGHTTP2 */
 #else /* !USE_NGHTTP2 */
 
 
 /* Satisfy external references even if http2 is not compiled in. */
 /* Satisfy external references even if http2 is not compiled in. */

+ 5 - 2
Utilities/cmcurl/lib/http2.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -59,8 +59,10 @@ CURLcode Curl_http2_add_child(struct Curl_easy *parent,
 void Curl_http2_remove_child(struct Curl_easy *parent,
 void Curl_http2_remove_child(struct Curl_easy *parent,
                              struct Curl_easy *child);
                              struct Curl_easy *child);
 void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
 void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
+
+/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */
+bool Curl_h2_http_1_1_error(struct connectdata *conn);
 #else /* USE_NGHTTP2 */
 #else /* USE_NGHTTP2 */
-#define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
 #define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL
@@ -74,6 +76,7 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
 #define Curl_http2_add_child(x, y, z)
 #define Curl_http2_add_child(x, y, z)
 #define Curl_http2_remove_child(x, y)
 #define Curl_http2_remove_child(x, y)
 #define Curl_http2_cleanup_dependencies(x)
 #define Curl_http2_cleanup_dependencies(x)
+#define Curl_h2_http_1_1_error(x) 0
 #endif
 #endif
 
 
 #endif /* HEADER_CURL_HTTP2_H */
 #endif /* HEADER_CURL_HTTP2_H */

+ 3 - 2
Utilities/cmcurl/lib/http_digest.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -28,6 +28,7 @@
 #include "strcase.h"
 #include "strcase.h"
 #include "vauth/vauth.h"
 #include "vauth/vauth.h"
 #include "http_digest.h"
 #include "http_digest.h"
+
 /* The last 3 #include files should be in this order */
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "curl_memory.h"
@@ -171,7 +172,7 @@ CURLcode Curl_output_digest(struct connectdata *conn,
   return CURLE_OK;
   return CURLE_OK;
 }
 }
 
 
-void Curl_digest_cleanup(struct Curl_easy *data)
+void Curl_http_auth_cleanup_digest(struct Curl_easy *data)
 {
 {
   Curl_auth_digest_cleanup(&data->state.digest);
   Curl_auth_digest_cleanup(&data->state.digest);
   Curl_auth_digest_cleanup(&data->state.proxydigest);
   Curl_auth_digest_cleanup(&data->state.proxydigest);

+ 6 - 6
Utilities/cmcurl/lib/http_digest.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -23,6 +23,8 @@
  ***************************************************************************/
  ***************************************************************************/
 #include "curl_setup.h"
 #include "curl_setup.h"
 
 
+#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
+
 /* this is for digest header input */
 /* this is for digest header input */
 CURLcode Curl_input_digest(struct connectdata *conn,
 CURLcode Curl_input_digest(struct connectdata *conn,
                            bool proxy, const char *header);
                            bool proxy, const char *header);
@@ -33,10 +35,8 @@ CURLcode Curl_output_digest(struct connectdata *conn,
                             const unsigned char *request,
                             const unsigned char *request,
                             const unsigned char *uripath);
                             const unsigned char *uripath);
 
 
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
-void Curl_digest_cleanup(struct Curl_easy *data);
-#else
-#define Curl_digest_cleanup(x) Curl_nop_stmt
-#endif
+void Curl_http_auth_cleanup_digest(struct Curl_easy *data);
+
+#endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_CRYPTO_AUTH */
 
 
 #endif /* HEADER_CURL_HTTP_DIGEST_H */
 #endif /* HEADER_CURL_HTTP_DIGEST_H */

+ 107 - 25
Utilities/cmcurl/lib/http_negotiate.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -49,6 +49,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
 
 
   /* Point to the correct struct with this */
   /* Point to the correct struct with this */
   struct negotiatedata *neg_ctx;
   struct negotiatedata *neg_ctx;
+  curlnegotiate state;
 
 
   if(proxy) {
   if(proxy) {
     userp = conn->http_proxy.user;
     userp = conn->http_proxy.user;
@@ -56,7 +57,8 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
     service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
               data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
               data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
     host = conn->http_proxy.host.name;
     host = conn->http_proxy.host.name;
-    neg_ctx = &data->state.proxyneg;
+    neg_ctx = &conn->proxyneg;
+    state = conn->proxy_negotiate_state;
   }
   }
   else {
   else {
     userp = conn->user;
     userp = conn->user;
@@ -64,7 +66,8 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     service = data->set.str[STRING_SERVICE_NAME] ?
     service = data->set.str[STRING_SERVICE_NAME] ?
               data->set.str[STRING_SERVICE_NAME] : "HTTP";
               data->set.str[STRING_SERVICE_NAME] : "HTTP";
     host = conn->host.name;
     host = conn->host.name;
-    neg_ctx = &data->state.negotiate;
+    neg_ctx = &conn->negotiate;
+    state = conn->http_negotiate_state;
   }
   }
 
 
   /* Not set means empty */
   /* Not set means empty */
@@ -80,59 +83,138 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     header++;
     header++;
 
 
   len = strlen(header);
   len = strlen(header);
+  neg_ctx->havenegdata = len != 0;
   if(!len) {
   if(!len) {
-    /* Is this the first call in a new negotiation? */
-    if(neg_ctx->context) {
-      /* The server rejected our authentication and hasn't suppled any more
+    if(state == GSS_AUTHSUCC) {
+      infof(conn->data, "Negotiate auth restarted\n");
+      Curl_http_auth_cleanup_negotiate(conn);
+    }
+    else if(state != GSS_AUTHNONE) {
+      /* The server rejected our authentication and hasn't supplied any more
       negotiation mechanisms */
       negotiation mechanisms */
+      Curl_http_auth_cleanup_negotiate(conn);
       return CURLE_LOGIN_DENIED;
       return CURLE_LOGIN_DENIED;
     }
     }
   }
   }
 
 
+  /* Supports SSL channel binding for Windows ISS extended protection */
+#if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS)
+  neg_ctx->sslContext = conn->sslContext;
+#endif
+
   /* Initialize the security context and decode our challenge */
   /* Initialize the security context and decode our challenge */
   result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
   result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
                                            host, header, neg_ctx);
                                            host, header, neg_ctx);
 
 
   if(result)
   if(result)
-    Curl_auth_spnego_cleanup(neg_ctx);
+    Curl_http_auth_cleanup_negotiate(conn);
 
 
   return result;
   return result;
 }
 }
 
 
 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
 {
 {
-  struct negotiatedata *neg_ctx = proxy ? &conn->data->state.proxyneg :
-    &conn->data->state.negotiate;
+  struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg :
+    &conn->negotiate;
+  struct auth *authp = proxy ? &conn->data->state.authproxy :
+    &conn->data->state.authhost;
+  curlnegotiate *state = proxy ? &conn->proxy_negotiate_state :
+                                 &conn->http_negotiate_state;
   char *base64 = NULL;
   char *base64 = NULL;
   size_t len = 0;
   size_t len = 0;
   char *userp;
   char *userp;
   CURLcode result;
   CURLcode result;
 
 
-  result = Curl_auth_create_spnego_message(conn->data, neg_ctx, &base64, &len);
-  if(result)
-    return result;
+  authp->done = FALSE;
 
 
-  userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
-                  base64);
+  if(*state == GSS_AUTHRECV) {
+    if(neg_ctx->havenegdata) {
+      neg_ctx->havemultiplerequests = TRUE;
+    }
+  }
+  else if(*state == GSS_AUTHSUCC) {
+    if(!neg_ctx->havenoauthpersist) {
+      neg_ctx->noauthpersist = !neg_ctx->havemultiplerequests;
+    }
+  }
 
 
-  if(proxy) {
-    Curl_safefree(conn->allocptr.proxyuserpwd);
-    conn->allocptr.proxyuserpwd = userp;
+  if(neg_ctx->noauthpersist ||
+    (*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) {
+
+    if(neg_ctx->noauthpersist && *state == GSS_AUTHSUCC) {
+      infof(conn->data, "Curl_output_negotiate, "
+       "no persistent authentication: cleanup existing context");
+      Curl_http_auth_cleanup_negotiate(conn);
+    }
+    if(!neg_ctx->context) {
+      result = Curl_input_negotiate(conn, proxy, "Negotiate");
+      if(result == CURLE_LOGIN_DENIED) {
+        /* negotiate auth failed, let's continue unauthenticated to stay
+         * compatible with the behavior before curl-7_64_0-158-g6c6035532 */
+        conn->data->state.authproblem = TRUE;
+        return CURLE_OK;
+      }
+      else if(result)
+        return result;
+    }
+
+    result = Curl_auth_create_spnego_message(conn->data,
+      neg_ctx, &base64, &len);
+    if(result)
+      return result;
+
+    userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
+      base64);
+
+    if(proxy) {
+      Curl_safefree(conn->allocptr.proxyuserpwd);
+      conn->allocptr.proxyuserpwd = userp;
+    }
+    else {
+      Curl_safefree(conn->allocptr.userpwd);
+      conn->allocptr.userpwd = userp;
+    }
+
+    free(base64);
+
+    if(userp == NULL) {
+      return CURLE_OUT_OF_MEMORY;
+    }
+
+    *state = GSS_AUTHSENT;
+  #ifdef HAVE_GSSAPI
+    if(neg_ctx->status == GSS_S_COMPLETE ||
+       neg_ctx->status == GSS_S_CONTINUE_NEEDED) {
+      *state = GSS_AUTHDONE;
+    }
+  #else
+  #ifdef USE_WINDOWS_SSPI
+    if(neg_ctx->status == SEC_E_OK ||
+       neg_ctx->status == SEC_I_CONTINUE_NEEDED) {
+      *state = GSS_AUTHDONE;
+    }
+  #endif
+  #endif
   }
   }
-  else {
-    Curl_safefree(conn->allocptr.userpwd);
-    conn->allocptr.userpwd = userp;
+
+  if(*state == GSS_AUTHDONE || *state == GSS_AUTHSUCC) {
+    /* connection is already authenticated,
+     * don't send a header in future requests */
+    authp->done = TRUE;
   }
   }
 
 
-  free(base64);
+  neg_ctx->havenegdata = FALSE;
 
 
-  return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
+  return CURLE_OK;
 }
 }
 
 
-void Curl_cleanup_negotiate(struct Curl_easy *data)
+void Curl_http_auth_cleanup_negotiate(struct connectdata *conn)
 {
 {
-  Curl_auth_spnego_cleanup(&data->state.negotiate);
-  Curl_auth_spnego_cleanup(&data->state.proxyneg);
+  conn->http_negotiate_state = GSS_AUTHNONE;
+  conn->proxy_negotiate_state = GSS_AUTHNONE;
+
+  Curl_auth_cleanup_spnego(&conn->negotiate);
+  Curl_auth_cleanup_spnego(&conn->proxyneg);
 }
 }
 
 
 #endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
 #endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */

+ 4 - 4
Utilities/cmcurl/lib/http_negotiate.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
  *
  *
  ***************************************************************************/
  ***************************************************************************/
 
 
-#ifdef USE_SPNEGO
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
 
 
 /* this is for Negotiate header input */
 /* this is for Negotiate header input */
 CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
 CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
@@ -31,8 +31,8 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
 /* this is for creating Negotiate header output */
 /* this is for creating Negotiate header output */
 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
 
 
-void Curl_cleanup_negotiate(struct Curl_easy *data);
+void Curl_http_auth_cleanup_negotiate(struct connectdata *conn);
 
 
-#endif /* USE_SPNEGO */
+#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
 
 
 #endif /* HEADER_CURL_HTTP_NEGOTIATE_H */
 #endif /* HEADER_CURL_HTTP_NEGOTIATE_H */

+ 24 - 16
Utilities/cmcurl/lib/http_ntlm.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -68,9 +68,11 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
 {
 {
   /* point to the correct struct with this */
   /* point to the correct struct with this */
   struct ntlmdata *ntlm;
   struct ntlmdata *ntlm;
+  curlntlm *state;
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
 
 
   ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
   ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
+  state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
 
 
   if(checkprefix("NTLM", header)) {
   if(checkprefix("NTLM", header)) {
     header += strlen("NTLM");
     header += strlen("NTLM");
@@ -83,25 +85,25 @@ CURLcode Curl_input_ntlm(struct connectdata *conn,
       if(result)
       if(result)
         return result;
         return result;
 
 
-      ntlm->state = NTLMSTATE_TYPE2; /* We got a type-2 message */
+      *state = NTLMSTATE_TYPE2; /* We got a type-2 message */
     }
     }
     else {
     else {
-      if(ntlm->state == NTLMSTATE_LAST) {
+      if(*state == NTLMSTATE_LAST) {
         infof(conn->data, "NTLM auth restarted\n");
         infof(conn->data, "NTLM auth restarted\n");
-        Curl_http_ntlm_cleanup(conn);
+        Curl_http_auth_cleanup_ntlm(conn);
       }
       }
-      else if(ntlm->state == NTLMSTATE_TYPE3) {
+      else if(*state == NTLMSTATE_TYPE3) {
         infof(conn->data, "NTLM handshake rejected\n");
         infof(conn->data, "NTLM handshake rejected\n");
-        Curl_http_ntlm_cleanup(conn);
-        ntlm->state = NTLMSTATE_NONE;
+        Curl_http_auth_cleanup_ntlm(conn);
+        *state = NTLMSTATE_NONE;
         return CURLE_REMOTE_ACCESS_DENIED;
         return CURLE_REMOTE_ACCESS_DENIED;
       }
       }
-      else if(ntlm->state >= NTLMSTATE_TYPE1) {
+      else if(*state >= NTLMSTATE_TYPE1) {
         infof(conn->data, "NTLM handshake failure (internal error)\n");
         infof(conn->data, "NTLM handshake failure (internal error)\n");
         return CURLE_REMOTE_ACCESS_DENIED;
         return CURLE_REMOTE_ACCESS_DENIED;
       }
       }
 
 
-      ntlm->state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
+      *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
     }
     }
   }
   }
 
 
@@ -129,6 +131,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
 
 
   /* point to the correct struct with this */
   /* point to the correct struct with this */
   struct ntlmdata *ntlm;
   struct ntlmdata *ntlm;
+  curlntlm *state;
   struct auth *authp;
   struct auth *authp;
 
 
   DEBUGASSERT(conn);
   DEBUGASSERT(conn);
@@ -147,6 +150,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
               conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
               conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
     hostname = conn->http_proxy.host.name;
     hostname = conn->http_proxy.host.name;
     ntlm = &conn->proxyntlm;
     ntlm = &conn->proxyntlm;
+    state = &conn->proxy_ntlm_state;
     authp = &conn->data->state.authproxy;
     authp = &conn->data->state.authproxy;
   }
   }
   else {
   else {
@@ -157,6 +161,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
               conn->data->set.str[STRING_SERVICE_NAME] : "HTTP";
               conn->data->set.str[STRING_SERVICE_NAME] : "HTTP";
     hostname = conn->host.name;
     hostname = conn->host.name;
     ntlm = &conn->ntlm;
     ntlm = &conn->ntlm;
+    state = &conn->http_ntlm_state;
     authp = &conn->data->state.authhost;
     authp = &conn->data->state.authhost;
   }
   }
   authp->done = FALSE;
   authp->done = FALSE;
@@ -175,9 +180,12 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
     if(s_hSecDll == NULL)
     if(s_hSecDll == NULL)
       return err;
       return err;
   }
   }
+#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
+  ntlm->sslContext = conn->sslContext;
+#endif
 #endif
 #endif
 
 
-  switch(ntlm->state) {
+  switch(*state) {
   case NTLMSTATE_TYPE1:
   case NTLMSTATE_TYPE1:
   default: /* for the weird cases we (re)start here */
   default: /* for the weird cases we (re)start here */
     /* Create a type-1 message */
     /* Create a type-1 message */
@@ -219,7 +227,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
 
 
       DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
       DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
 
 
-      ntlm->state = NTLMSTATE_TYPE3; /* we send a type-3 */
+      *state = NTLMSTATE_TYPE3; /* we send a type-3 */
       authp->done = TRUE;
       authp->done = TRUE;
     }
     }
     break;
     break;
@@ -227,7 +235,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
   case NTLMSTATE_TYPE3:
   case NTLMSTATE_TYPE3:
     /* connection is already authenticated,
     /* connection is already authenticated,
      * don't send a header in future requests */
      * don't send a header in future requests */
-    ntlm->state = NTLMSTATE_LAST;
+    *state = NTLMSTATE_LAST;
     /* FALLTHROUGH */
     /* FALLTHROUGH */
   case NTLMSTATE_LAST:
   case NTLMSTATE_LAST:
     Curl_safefree(*allocuserpwd);
     Curl_safefree(*allocuserpwd);
@@ -238,13 +246,13 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
   return CURLE_OK;
   return CURLE_OK;
 }
 }
 
 
-void Curl_http_ntlm_cleanup(struct connectdata *conn)
+void Curl_http_auth_cleanup_ntlm(struct connectdata *conn)
 {
 {
-  Curl_auth_ntlm_cleanup(&conn->ntlm);
-  Curl_auth_ntlm_cleanup(&conn->proxyntlm);
+  Curl_auth_cleanup_ntlm(&conn->ntlm);
+  Curl_auth_cleanup_ntlm(&conn->proxyntlm);
 
 
 #if defined(NTLM_WB_ENABLED)
 #if defined(NTLM_WB_ENABLED)
-  Curl_ntlm_wb_cleanup(conn);
+  Curl_http_auth_cleanup_ntlm_wb(conn);
 #endif
 #endif
 }
 }
 
 

+ 5 - 5
Utilities/cmcurl/lib/http_ntlm.h

@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_NTLM_H
-#define HEADER_CURL_NTLM_H
+#ifndef HEADER_CURL_HTTP_NTLM_H
+#define HEADER_CURL_HTTP_NTLM_H
 /***************************************************************************
 /***************************************************************************
  *                                  _   _ ____  _
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
  *  Project                     ___| | | |  _ \| |
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -33,8 +33,8 @@ CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy,
 /* this is for creating ntlm header output */
 /* this is for creating ntlm header output */
 CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
 CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
 
 
-void Curl_http_ntlm_cleanup(struct connectdata *conn);
+void Curl_http_auth_cleanup_ntlm(struct connectdata *conn);
 
 
 #endif /* !CURL_DISABLE_HTTP && USE_NTLM */
 #endif /* !CURL_DISABLE_HTTP && USE_NTLM */
 
 
-#endif /* HEADER_CURL_NTLM_H */
+#endif /* HEADER_CURL_HTTP_NTLM_H */

+ 2 - 2
Utilities/cmcurl/lib/http_proxy.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -643,7 +643,7 @@ static CURLcode CONNECT(struct connectdata *conn,
 
 
 void Curl_connect_free(struct Curl_easy *data)
 void Curl_connect_free(struct Curl_easy *data)
 {
 {
-  struct connectdata *conn = data->easy_conn;
+  struct connectdata *conn = data->conn;
   struct http_connect_state *s = conn->connect_state;
   struct http_connect_state *s = conn->connect_state;
   if(s) {
   if(s) {
     free(s);
     free(s);

+ 14 - 45
Utilities/cmcurl/lib/if2ip.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -96,26 +96,8 @@ unsigned int Curl_ipv6_scope(const struct sockaddr *sa)
 
 
 #if defined(HAVE_GETIFADDRS)
 #if defined(HAVE_GETIFADDRS)
 
 
-bool Curl_if_is_interface_name(const char *interf)
-{
-  bool result = FALSE;
-
-  struct ifaddrs *iface, *head;
-
-  if(getifaddrs(&head) >= 0) {
-    for(iface = head; iface != NULL; iface = iface->ifa_next) {
-      if(strcasecompare(iface->ifa_name, interf)) {
-        result = TRUE;
-        break;
-      }
-    }
-    freeifaddrs(head);
-  }
-  return result;
-}
-
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
-                          unsigned int remote_scope_id, const char *interf,
+                          unsigned int local_scope_id, const char *interf,
                           char *buf, int buf_size)
                           char *buf, int buf_size)
 {
 {
   struct ifaddrs *iface, *head;
   struct ifaddrs *iface, *head;
@@ -127,7 +109,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 
 
 #if !defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) || \
 #if !defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) || \
     !defined(ENABLE_IPV6)
     !defined(ENABLE_IPV6)
-  (void) remote_scope_id;
+  (void) local_scope_id;
 #endif
 #endif
 
 
   if(getifaddrs(&head) >= 0) {
   if(getifaddrs(&head) >= 0) {
@@ -141,7 +123,9 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
             char ipstr[64];
             char ipstr[64];
 #ifdef ENABLE_IPV6
 #ifdef ENABLE_IPV6
             if(af == AF_INET6) {
             if(af == AF_INET6) {
+#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
               unsigned int scopeid = 0;
               unsigned int scopeid = 0;
+#endif
               unsigned int ifscope = Curl_ipv6_scope(iface->ifa_addr);
               unsigned int ifscope = Curl_ipv6_scope(iface->ifa_addr);
 
 
               if(ifscope != remote_scope) {
               if(ifscope != remote_scope) {
@@ -161,15 +145,16 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
                             ->sin6_scope_id;
                             ->sin6_scope_id;
 
 
               /* If given, scope id should match. */
               /* If given, scope id should match. */
-              if(remote_scope_id && scopeid != remote_scope_id) {
+              if(local_scope_id && scopeid != local_scope_id) {
                 if(res == IF2IP_NOT_FOUND)
                 if(res == IF2IP_NOT_FOUND)
                   res = IF2IP_AF_NOT_SUPPORTED;
                   res = IF2IP_AF_NOT_SUPPORTED;
 
 
                 continue;
                 continue;
               }
               }
-#endif
+
               if(scopeid)
               if(scopeid)
-                snprintf(scope, sizeof(scope), "%%%u", scopeid);
+                  msnprintf(scope, sizeof(scope), "%%%u", scopeid);
+#endif
             }
             }
             else
             else
 #endif
 #endif
@@ -177,7 +162,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
                   &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
                   &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
             res = IF2IP_FOUND;
             res = IF2IP_FOUND;
             ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
             ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
-            snprintf(buf, buf_size, "%s%s", ip, scope);
+            msnprintf(buf, buf_size, "%s%s", ip, scope);
             break;
             break;
           }
           }
         }
         }
@@ -196,17 +181,8 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 
 
 #elif defined(HAVE_IOCTL_SIOCGIFADDR)
 #elif defined(HAVE_IOCTL_SIOCGIFADDR)
 
 
-bool Curl_if_is_interface_name(const char *interf)
-{
-  /* This is here just to support the old interfaces */
-  char buf[256];
-
-  return (Curl_if2ip(AF_INET, 0 /* unused */, 0, interf, buf, sizeof(buf)) ==
-          IF2IP_NOT_FOUND) ? FALSE : TRUE;
-}
-
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
-                          unsigned int remote_scope_id, const char *interf,
+                          unsigned int local_scope_id, const char *interf,
                           char *buf, int buf_size)
                           char *buf, int buf_size)
 {
 {
   struct ifreq req;
   struct ifreq req;
@@ -216,7 +192,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
   size_t len;
   size_t len;
 
 
   (void)remote_scope;
   (void)remote_scope;
-  (void)remote_scope_id;
+  (void)local_scope_id;
 
 
   if(!interf || (af != AF_INET))
   if(!interf || (af != AF_INET))
     return IF2IP_NOT_FOUND;
     return IF2IP_NOT_FOUND;
@@ -251,20 +227,13 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 
 
 #else
 #else
 
 
-bool Curl_if_is_interface_name(const char *interf)
-{
-  (void) interf;
-
-  return FALSE;
-}
-
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
-                          unsigned int remote_scope_id, const char *interf,
+                          unsigned int local_scope_id, const char *interf,
                           char *buf, int buf_size)
                           char *buf, int buf_size)
 {
 {
     (void) af;
     (void) af;
     (void) remote_scope;
     (void) remote_scope;
-    (void) remote_scope_id;
+    (void) local_scope_id;
     (void) interf;
     (void) interf;
     (void) buf;
     (void) buf;
     (void) buf_size;
     (void) buf_size;

+ 2 - 4
Utilities/cmcurl/lib/if2ip.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -32,8 +32,6 @@
 
 
 unsigned int Curl_ipv6_scope(const struct sockaddr *sa);
 unsigned int Curl_ipv6_scope(const struct sockaddr *sa);
 
 
-bool Curl_if_is_interface_name(const char *interf);
-
 typedef enum {
 typedef enum {
   IF2IP_NOT_FOUND = 0, /* Interface not found */
   IF2IP_NOT_FOUND = 0, /* Interface not found */
   IF2IP_AF_NOT_SUPPORTED = 1, /* Int. exists but has no address for this af */
   IF2IP_AF_NOT_SUPPORTED = 1, /* Int. exists but has no address for this af */
@@ -41,7 +39,7 @@ typedef enum {
 } if2ip_result_t;
 } if2ip_result_t;
 
 
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
-                          unsigned int remote_scope_id, const char *interf,
+                          unsigned int local_scope_id, const char *interf,
                           char *buf, int buf_size);
                           char *buf, int buf_size);
 
 
 #ifdef __INTERIX
 #ifdef __INTERIX

+ 19 - 22
Utilities/cmcurl/lib/imap.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -28,6 +28,7 @@
  * RFC4959 IMAP Extension for SASL Initial Client Response
  * RFC4959 IMAP Extension for SASL Initial Client Response
  * RFC5092 IMAP URL Scheme
  * RFC5092 IMAP URL Scheme
  * RFC6749 OAuth 2.0 Authorization Framework
  * RFC6749 OAuth 2.0 Authorization Framework
+ * RFC8314 Use of TLS for Email Submission and Access
  * Draft   LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
  * Draft   LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
  *
  *
  ***************************************************************************/
  ***************************************************************************/
@@ -316,7 +317,7 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len,
      a space and optionally some text as per RFC-3501 for the AUTHENTICATE and
      a space and optionally some text as per RFC-3501 for the AUTHENTICATE and
      APPEND commands and as outlined in Section 4. Examples of RFC-4959 but
      APPEND commands and as outlined in Section 4. Examples of RFC-4959 but
      some e-mail servers ignore this and only send a single + instead. */
      some e-mail servers ignore this and only send a single + instead. */
-  if(imap && !imap->custom && ((len == 3 && !memcmp("+", line, 1)) ||
+  if(imap && !imap->custom && ((len == 3 && line[0] == '+') ||
      (len >= 2 && !memcmp("+ ", line, 2)))) {
      (len >= 2 && !memcmp("+ ", line, 2)))) {
     switch(imapc->state) {
     switch(imapc->state) {
       /* States which are interested in continuation responses */
       /* States which are interested in continuation responses */
@@ -1042,7 +1043,7 @@ static CURLcode imap_state_listsearch_resp(struct connectdata *conn,
     line[len] = '\0';
     line[len] = '\0';
   }
   }
   else if(imapcode != IMAP_RESP_OK)
   else if(imapcode != IMAP_RESP_OK)
-    result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */
+    result = CURLE_QUOTE_ERROR;
   else
   else
     /* End of DO phase */
     /* End of DO phase */
     state(conn, IMAP_STOP);
     state(conn, IMAP_STOP);
@@ -1114,7 +1115,7 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
   if(imapcode != '*') {
   if(imapcode != '*') {
     Curl_pgrsSetDownloadSize(data, -1);
     Curl_pgrsSetDownloadSize(data, -1);
     state(conn, IMAP_STOP);
     state(conn, IMAP_STOP);
-    return CURLE_REMOTE_FILE_NOT_FOUND; /* TODO: Fix error code */
+    return CURLE_REMOTE_FILE_NOT_FOUND;
   }
   }
 
 
   /* Something like this is received "* 1 FETCH (BODY[TEXT] {2021}\r" so parse
   /* Something like this is received "* 1 FETCH (BODY[TEXT] {2021}\r" so parse
@@ -1177,11 +1178,11 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode,
 
 
     if(data->req.bytecount == size)
     if(data->req.bytecount == size)
       /* The entire data is already transferred! */
       /* The entire data is already transferred! */
-      Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, -1, -1, FALSE, -1);
     else {
     else {
       /* IMAP download */
       /* IMAP download */
       data->req.maxdownload = size;
       data->req.maxdownload = size;
-      Curl_setup_transfer(conn, FIRSTSOCKET, size, FALSE, NULL, -1, NULL);
+      Curl_setup_transfer(data, FIRSTSOCKET, size, FALSE, -1);
     }
     }
   }
   }
   else {
   else {
@@ -1231,7 +1232,7 @@ static CURLcode imap_state_append_resp(struct connectdata *conn, int imapcode,
     Curl_pgrsSetUploadSize(data, data->state.infilesize);
     Curl_pgrsSetUploadSize(data, data->state.infilesize);
 
 
     /* IMAP upload */
     /* IMAP upload */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
+    Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
 
 
     /* End of DO phase */
     /* End of DO phase */
     state(conn, IMAP_STOP);
     state(conn, IMAP_STOP);
@@ -1362,19 +1363,20 @@ static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done)
       return result;
       return result;
   }
   }
 
 
-  result = Curl_pp_statemach(&imapc->pp, FALSE);
+  result = Curl_pp_statemach(&imapc->pp, FALSE, FALSE);
   *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
   *done = (imapc->state == IMAP_STOP) ? TRUE : FALSE;
 
 
   return result;
   return result;
 }
 }
 
 
-static CURLcode imap_block_statemach(struct connectdata *conn)
+static CURLcode imap_block_statemach(struct connectdata *conn,
+                                     bool disconnecting)
 {
 {
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
   struct imap_conn *imapc = &conn->proto.imapc;
   struct imap_conn *imapc = &conn->proto.imapc;
 
 
   while(imapc->state != IMAP_STOP && !result)
   while(imapc->state != IMAP_STOP && !result)
-    result = Curl_pp_statemach(&imapc->pp, TRUE);
+    result = Curl_pp_statemach(&imapc->pp, TRUE, disconnecting);
 
 
   return result;
   return result;
 }
 }
@@ -1490,14 +1492,9 @@ static CURLcode imap_done(struct connectdata *conn, CURLcode status,
         state(conn, IMAP_APPEND_FINAL);
         state(conn, IMAP_APPEND_FINAL);
     }
     }
 
 
-    /* Run the state-machine
-
-       TODO: when the multi interface is used, this _really_ should be using
-       the imap_multi_statemach function but we have no general support for
-       non-blocking DONE operations!
-    */
+    /* Run the state-machine */
     if(!result)
     if(!result)
-      result = imap_block_statemach(conn);
+      result = imap_block_statemach(conn, FALSE);
   }
   }
 
 
   /* Cleanup our per-request based variables */
   /* Cleanup our per-request based variables */
@@ -1635,7 +1632,7 @@ static CURLcode imap_disconnect(struct connectdata *conn, bool dead_connection)
      point! */
      point! */
   if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart)
   if(!dead_connection && imapc->pp.conn && imapc->pp.conn->bits.protoconnstart)
     if(!imap_perform_logout(conn))
     if(!imap_perform_logout(conn))
-      (void)imap_block_statemach(conn); /* ignore errors on LOGOUT */
+      (void)imap_block_statemach(conn, TRUE); /* ignore errors on LOGOUT */
 
 
   /* Disconnect from the server */
   /* Disconnect from the server */
   Curl_pp_disconnect(&imapc->pp);
   Curl_pp_disconnect(&imapc->pp);
@@ -1659,7 +1656,7 @@ static CURLcode imap_dophase_done(struct connectdata *conn, bool connected)
 
 
   if(imap->transfer != FTPTRANSFER_BODY)
   if(imap->transfer != FTPTRANSFER_BODY)
     /* no data to transfer */
     /* no data to transfer */
-    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+    Curl_setup_transfer(conn->data, -1, -1, FALSE, -1);
 
 
   return CURLE_OK;
   return CURLE_OK;
 }
 }
@@ -1749,8 +1746,8 @@ static CURLcode imap_sendf(struct connectdata *conn, const char *fmt, ...)
   imapc->cmdid = (imapc->cmdid + 1) % 1000;
   imapc->cmdid = (imapc->cmdid + 1) % 1000;
 
 
   /* Calculate the tag based on the connection ID and command ID */
   /* Calculate the tag based on the connection ID and command ID */
-  snprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
-           'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
+  msnprintf(imapc->resptag, sizeof(imapc->resptag), "%c%03d",
+            'A' + curlx_sltosi(conn->connection_id % 26), imapc->cmdid);
 
 
   /* Prefix the format with the tag */
   /* Prefix the format with the tag */
   taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
   taggedfmt = aprintf("%s %s", imapc->resptag, fmt);
@@ -1793,7 +1790,7 @@ static char *imap_atom(const char *str, bool escape_only)
     return NULL;
     return NULL;
 
 
   /* Look for "atom-specials", counting the backslash and quote characters as
   /* Look for "atom-specials", counting the backslash and quote characters as
-     these will need escapping */
+     these will need escaping */
   p1 = str;
   p1 = str;
   while(*p1) {
   while(*p1) {
     if(*p1 == '\\')
     if(*p1 == '\\')

+ 6 - 6
Utilities/cmcurl/lib/inet_ntop.c

@@ -55,11 +55,11 @@ static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
   DEBUGASSERT(size >= 16);
   DEBUGASSERT(size >= 16);
 
 
   tmp[0] = '\0';
   tmp[0] = '\0';
-  (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
-                 ((int)((unsigned char)src[0])) & 0xff,
-                 ((int)((unsigned char)src[1])) & 0xff,
-                 ((int)((unsigned char)src[2])) & 0xff,
-                 ((int)((unsigned char)src[3])) & 0xff);
+  (void)msnprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
+                  ((int)((unsigned char)src[0])) & 0xff,
+                  ((int)((unsigned char)src[1])) & 0xff,
+                  ((int)((unsigned char)src[2])) & 0xff,
+                  ((int)((unsigned char)src[3])) & 0xff);
 
 
   len = strlen(tmp);
   len = strlen(tmp);
   if(len == 0 || len >= size) {
   if(len == 0 || len >= size) {
@@ -148,7 +148,7 @@ static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
       tp += strlen(tp);
       tp += strlen(tp);
       break;
       break;
     }
     }
-    tp += snprintf(tp, 5, "%lx", words[i]);
+    tp += msnprintf(tp, 5, "%lx", words[i]);
   }
   }
 
 
   /* Was it a trailing run of 0x00's?
   /* Was it a trailing run of 0x00's?

+ 2 - 1
Utilities/cmcurl/lib/inet_pton.c

@@ -153,7 +153,7 @@ inet_pton6(const char *src, unsigned char *dst)
   static const char xdigits_l[] = "0123456789abcdef",
   static const char xdigits_l[] = "0123456789abcdef",
     xdigits_u[] = "0123456789ABCDEF";
     xdigits_u[] = "0123456789ABCDEF";
   unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
   unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
-  const char *xdigits, *curtok;
+  const char *curtok;
   int ch, saw_xdigit;
   int ch, saw_xdigit;
   size_t val;
   size_t val;
 
 
@@ -168,6 +168,7 @@ inet_pton6(const char *src, unsigned char *dst)
   saw_xdigit = 0;
   saw_xdigit = 0;
   val = 0;
   val = 0;
   while((ch = *src++) != '\0') {
   while((ch = *src++) != '\0') {
+    const char *xdigits;
     const char *pch;
     const char *pch;
 
 
     pch = strchr((xdigits = xdigits_l), ch);
     pch = strchr((xdigits = xdigits_l), ch);

+ 13 - 9
Utilities/cmcurl/lib/ldap.c

@@ -5,7 +5,7 @@
  *                | (__| |_| |  _ <| |___
  *                | (__| |_| |  _ <| |___
  *                 \___|\___/|_| \_\_____|
  *                 \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -744,7 +744,7 @@ quit:
 #endif
 #endif
 
 
   /* no data to transfer */
   /* no data to transfer */
-  Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+  Curl_setup_transfer(data, -1, -1, FALSE, -1);
   connclose(conn, "LDAP connection always disable re-use");
   connclose(conn, "LDAP connection always disable re-use");
 
 
   return result;
   return result;
@@ -839,6 +839,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 {
 {
   int rc = LDAP_SUCCESS;
   int rc = LDAP_SUCCESS;
   char *path;
   char *path;
+  char *query;
   char *p;
   char *p;
   char *q;
   char *q;
   size_t i;
   size_t i;
@@ -846,7 +847,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
   if(!conn->data ||
   if(!conn->data ||
      !conn->data->state.up.path ||
      !conn->data->state.up.path ||
      conn->data->state.up.path[0] != '/' ||
      conn->data->state.up.path[0] != '/' ||
-     !strcasecompare("LDAP", conn->data->state.up.scheme))
+     !strncasecompare("LDAP", conn->data->state.up.scheme, 4))
     return LDAP_INVALID_SYNTAX;
     return LDAP_INVALID_SYNTAX;
 
 
   ludp->lud_scope = LDAP_SCOPE_BASE;
   ludp->lud_scope = LDAP_SCOPE_BASE;
@@ -858,11 +859,14 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
   if(!path)
   if(!path)
     return LDAP_NO_MEMORY;
     return LDAP_NO_MEMORY;
 
 
-  /* Parse the DN (Distinguished Name) */
-  q = strchr(p, '?');
-  if(q)
-    *q++ = '\0';
+  /* Duplicate the query */
+  q = query = strdup(conn->data->state.up.query);
+  if(!query) {
+    free(path);
+    return LDAP_NO_MEMORY;
+  }
 
 
+  /* Parse the DN (Distinguished Name) */
   if(*p) {
   if(*p) {
     char *dn = p;
     char *dn = p;
     char *unescaped;
     char *unescaped;
@@ -1039,6 +1043,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 
 
 quit:
 quit:
   free(path);
   free(path);
+  free(query);
 
 
   return rc;
   return rc;
 }
 }
@@ -1064,8 +1069,6 @@ static int _ldap_url_parse(const struct connectdata *conn,
 
 
 static void _ldap_free_urldesc(LDAPURLDesc *ludp)
 static void _ldap_free_urldesc(LDAPURLDesc *ludp)
 {
 {
-  size_t i;
-
   if(!ludp)
   if(!ludp)
     return;
     return;
 
 
@@ -1073,6 +1076,7 @@ static void _ldap_free_urldesc(LDAPURLDesc *ludp)
   free(ludp->lud_filter);
   free(ludp->lud_filter);
 
 
   if(ludp->lud_attrs) {
   if(ludp->lud_attrs) {
+    size_t i;
     for(i = 0; i < ludp->lud_attrs_dups; i++)
     for(i = 0; i < ludp->lud_attrs_dups; i++)
       free(ludp->lud_attrs[i]);
       free(ludp->lud_attrs[i]);
     free(ludp->lud_attrs);
     free(ludp->lud_attrs);

+ 6 - 6
Utilities/cmcurl/lib/libcurl.rc

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -22,22 +22,22 @@
 #include <winver.h>
 #include <winver.h>
 #include "../include/curl/curlver.h"
 #include "../include/curl/curlver.h"
 
 
-LANGUAGE  0x09,0x01
+LANGUAGE  0, 0
 
 
 #define RC_VERSION  LIBCURL_VERSION_MAJOR, LIBCURL_VERSION_MINOR, LIBCURL_VERSION_PATCH, 0
 #define RC_VERSION  LIBCURL_VERSION_MAJOR, LIBCURL_VERSION_MINOR, LIBCURL_VERSION_PATCH, 0
 
 
 VS_VERSION_INFO VERSIONINFO
 VS_VERSION_INFO VERSIONINFO
   FILEVERSION     RC_VERSION
   FILEVERSION     RC_VERSION
   PRODUCTVERSION  RC_VERSION
   PRODUCTVERSION  RC_VERSION
-  FILEFLAGSMASK   0x3fL
+  FILEFLAGSMASK   VS_FFI_FILEFLAGSMASK
 #if defined(DEBUGBUILD) || defined(_DEBUG)
 #if defined(DEBUGBUILD) || defined(_DEBUG)
-  FILEFLAGS 1
+  FILEFLAGS VS_FF_DEBUG
 #else
 #else
-  FILEFLAGS 0
+  FILEFLAGS 0L
 #endif
 #endif
   FILEOS      VOS__WINDOWS32
   FILEOS      VOS__WINDOWS32
   FILETYPE    VFT_DLL
   FILETYPE    VFT_DLL
-  FILESUBTYPE 0x0L
+  FILESUBTYPE 0L
 
 
 BEGIN
 BEGIN
   BLOCK "StringFileInfo"
   BLOCK "StringFileInfo"

+ 60 - 54
Utilities/cmcurl/lib/md4.c

@@ -1,4 +1,5 @@
 /*
 /*
+ * !checksrc! disable COPYRIGHT
  * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
  * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
  * MD4 Message-Digest Algorithm (RFC 1320).
  * MD4 Message-Digest Algorithm (RFC 1320).
  *
  *
@@ -37,9 +38,11 @@
 
 
 #include "curl_setup.h"
 #include "curl_setup.h"
 
 
-/* The NSS, OS/400 and sometimes mbed TLS crypto libraries do not provide the
- * MD4 hash algorithm, so we have a local implementation of it */
+/* The NSS, OS/400, and when not included, OpenSSL and mbed TLS crypto
+ * libraries do not provide the MD4 hash algorithm, so we use this
+ * implementation of it */
 #if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
 #if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
+    (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) || \
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
 
 
 #include "curl_md4.h"
 #include "curl_md4.h"
@@ -112,7 +115,6 @@ static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
 {
 {
   const unsigned char *ptr;
   const unsigned char *ptr;
   MD4_u32plus a, b, c, d;
   MD4_u32plus a, b, c, d;
-  MD4_u32plus saved_a, saved_b, saved_c, saved_d;
 
 
   ptr = (const unsigned char *)data;
   ptr = (const unsigned char *)data;
 
 
@@ -122,6 +124,8 @@ static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
   d = ctx->d;
   d = ctx->d;
 
 
   do {
   do {
+    MD4_u32plus saved_a, saved_b, saved_c, saved_d;
+
     saved_a = a;
     saved_a = a;
     saved_b = b;
     saved_b = b;
     saved_c = c;
     saved_c = c;
@@ -129,59 +133,59 @@ static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
 
 
 /* Round 1 */
 /* Round 1 */
     STEP(F, a, b, c, d, SET(0), 3)
     STEP(F, a, b, c, d, SET(0), 3)
-      STEP(F, d, a, b, c, SET(1), 7)
-      STEP(F, c, d, a, b, SET(2), 11)
-      STEP(F, b, c, d, a, SET(3), 19)
-      STEP(F, a, b, c, d, SET(4), 3)
-      STEP(F, d, a, b, c, SET(5), 7)
-      STEP(F, c, d, a, b, SET(6), 11)
-      STEP(F, b, c, d, a, SET(7), 19)
-      STEP(F, a, b, c, d, SET(8), 3)
-      STEP(F, d, a, b, c, SET(9), 7)
-      STEP(F, c, d, a, b, SET(10), 11)
-      STEP(F, b, c, d, a, SET(11), 19)
-      STEP(F, a, b, c, d, SET(12), 3)
-      STEP(F, d, a, b, c, SET(13), 7)
-      STEP(F, c, d, a, b, SET(14), 11)
-      STEP(F, b, c, d, a, SET(15), 19)
+    STEP(F, d, a, b, c, SET(1), 7)
+    STEP(F, c, d, a, b, SET(2), 11)
+    STEP(F, b, c, d, a, SET(3), 19)
+    STEP(F, a, b, c, d, SET(4), 3)
+    STEP(F, d, a, b, c, SET(5), 7)
+    STEP(F, c, d, a, b, SET(6), 11)
+    STEP(F, b, c, d, a, SET(7), 19)
+    STEP(F, a, b, c, d, SET(8), 3)
+    STEP(F, d, a, b, c, SET(9), 7)
+    STEP(F, c, d, a, b, SET(10), 11)
+    STEP(F, b, c, d, a, SET(11), 19)
+    STEP(F, a, b, c, d, SET(12), 3)
+    STEP(F, d, a, b, c, SET(13), 7)
+    STEP(F, c, d, a, b, SET(14), 11)
+    STEP(F, b, c, d, a, SET(15), 19)
 
 
 /* Round 2 */
 /* Round 2 */
-      STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3)
-      STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5)
-      STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9)
-      STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13)
-      STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3)
-      STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5)
-      STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9)
-      STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13)
-      STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3)
-      STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5)
-      STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9)
-      STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13)
-      STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3)
-      STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5)
-      STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9)
-      STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13)
+    STEP(G, a, b, c, d, GET(0) + 0x5a827999, 3)
+    STEP(G, d, a, b, c, GET(4) + 0x5a827999, 5)
+    STEP(G, c, d, a, b, GET(8) + 0x5a827999, 9)
+    STEP(G, b, c, d, a, GET(12) + 0x5a827999, 13)
+    STEP(G, a, b, c, d, GET(1) + 0x5a827999, 3)
+    STEP(G, d, a, b, c, GET(5) + 0x5a827999, 5)
+    STEP(G, c, d, a, b, GET(9) + 0x5a827999, 9)
+    STEP(G, b, c, d, a, GET(13) + 0x5a827999, 13)
+    STEP(G, a, b, c, d, GET(2) + 0x5a827999, 3)
+    STEP(G, d, a, b, c, GET(6) + 0x5a827999, 5)
+    STEP(G, c, d, a, b, GET(10) + 0x5a827999, 9)
+    STEP(G, b, c, d, a, GET(14) + 0x5a827999, 13)
+    STEP(G, a, b, c, d, GET(3) + 0x5a827999, 3)
+    STEP(G, d, a, b, c, GET(7) + 0x5a827999, 5)
+    STEP(G, c, d, a, b, GET(11) + 0x5a827999, 9)
+    STEP(G, b, c, d, a, GET(15) + 0x5a827999, 13)
 
 
 /* Round 3 */
 /* Round 3 */
-      STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3)
-      STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9)
-      STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11)
-      STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15)
-      STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3)
-      STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9)
-      STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11)
-      STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15)
-      STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3)
-      STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9)
-      STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11)
-      STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15)
-      STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3)
-      STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9)
-      STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11)
-      STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15)
-
-      a += saved_a;
+    STEP(H, a, b, c, d, GET(0) + 0x6ed9eba1, 3)
+    STEP(H, d, a, b, c, GET(8) + 0x6ed9eba1, 9)
+    STEP(H, c, d, a, b, GET(4) + 0x6ed9eba1, 11)
+    STEP(H, b, c, d, a, GET(12) + 0x6ed9eba1, 15)
+    STEP(H, a, b, c, d, GET(2) + 0x6ed9eba1, 3)
+    STEP(H, d, a, b, c, GET(10) + 0x6ed9eba1, 9)
+    STEP(H, c, d, a, b, GET(6) + 0x6ed9eba1, 11)
+    STEP(H, b, c, d, a, GET(14) + 0x6ed9eba1, 15)
+    STEP(H, a, b, c, d, GET(1) + 0x6ed9eba1, 3)
+    STEP(H, d, a, b, c, GET(9) + 0x6ed9eba1, 9)
+    STEP(H, c, d, a, b, GET(5) + 0x6ed9eba1, 11)
+    STEP(H, b, c, d, a, GET(13) + 0x6ed9eba1, 15)
+    STEP(H, a, b, c, d, GET(3) + 0x6ed9eba1, 3)
+    STEP(H, d, a, b, c, GET(11) + 0x6ed9eba1, 9)
+    STEP(H, c, d, a, b, GET(7) + 0x6ed9eba1, 11)
+    STEP(H, b, c, d, a, GET(15) + 0x6ed9eba1, 15)
+
+    a += saved_a;
     b += saved_b;
     b += saved_b;
     c += saved_c;
     c += saved_c;
     d += saved_d;
     d += saved_d;
@@ -211,7 +215,7 @@ static void MD4_Init(MD4_CTX *ctx)
 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
 {
 {
   MD4_u32plus saved_lo;
   MD4_u32plus saved_lo;
-  unsigned long used, available;
+  unsigned long used;
 
 
   saved_lo = ctx->lo;
   saved_lo = ctx->lo;
   ctx->lo = (saved_lo + size) & 0x1fffffff;
   ctx->lo = (saved_lo + size) & 0x1fffffff;
@@ -222,7 +226,7 @@ static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
   used = saved_lo & 0x3f;
   used = saved_lo & 0x3f;
 
 
   if(used) {
   if(used) {
-    available = 64 - used;
+    unsigned long available = 64 - used;
 
 
     if(size < available) {
     if(size < available) {
       memcpy(&ctx->buffer[used], data, size);
       memcpy(&ctx->buffer[used], data, size);
@@ -303,5 +307,7 @@ void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
   MD4_Update(&ctx, input, curlx_uztoui(len));
   MD4_Update(&ctx, input, curlx_uztoui(len));
   MD4_Final(output, &ctx);
   MD4_Final(output, &ctx);
 }
 }
+
 #endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
 #endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
+    (defined(USE_OPENSSL) && defined(OPENSSL_NO_MD4)) ||
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
     (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */

+ 84 - 90
Utilities/cmcurl/lib/md5.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -39,19 +39,19 @@
 
 
 typedef struct md5_ctx MD5_CTX;
 typedef struct md5_ctx MD5_CTX;
 
 
-static void MD5_Init(MD5_CTX * ctx)
+static void MD5_Init(MD5_CTX *ctx)
 {
 {
   md5_init(ctx);
   md5_init(ctx);
 }
 }
 
 
-static void MD5_Update(MD5_CTX * ctx,
+static void MD5_Update(MD5_CTX *ctx,
                        const unsigned char *input,
                        const unsigned char *input,
                        unsigned int inputLen)
                        unsigned int inputLen)
 {
 {
   md5_update(ctx, inputLen, input);
   md5_update(ctx, inputLen, input);
 }
 }
 
 
-static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
 {
 {
   md5_digest(ctx, 16, digest);
   md5_digest(ctx, 16, digest);
 }
 }
@@ -65,25 +65,25 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
 
 
 typedef gcry_md_hd_t MD5_CTX;
 typedef gcry_md_hd_t MD5_CTX;
 
 
-static void MD5_Init(MD5_CTX * ctx)
+static void MD5_Init(MD5_CTX *ctx)
 {
 {
   gcry_md_open(ctx, GCRY_MD_MD5, 0);
   gcry_md_open(ctx, GCRY_MD_MD5, 0);
 }
 }
 
 
-static void MD5_Update(MD5_CTX * ctx,
+static void MD5_Update(MD5_CTX *ctx,
                        const unsigned char *input,
                        const unsigned char *input,
                        unsigned int inputLen)
                        unsigned int inputLen)
 {
 {
   gcry_md_write(*ctx, input, inputLen);
   gcry_md_write(*ctx, input, inputLen);
 }
 }
 
 
-static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
+static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
 {
 {
   memcpy(digest, gcry_md_read(*ctx, 0), 16);
   memcpy(digest, gcry_md_read(*ctx, 0), 16);
   gcry_md_close(*ctx);
   gcry_md_close(*ctx);
 }
 }
 
 
-#elif defined(USE_OPENSSL)
+#elif defined(USE_OPENSSL) && !defined(USE_AMISSL)
 /* When OpenSSL is available we use the MD5-function from OpenSSL */
 /* When OpenSSL is available we use the MD5-function from OpenSSL */
 #include <openssl/md5.h>
 #include <openssl/md5.h>
 #include "curl_memory.h"
 #include "curl_memory.h"
@@ -124,7 +124,7 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
   CC_MD5_Final(digest, ctx);
   CC_MD5_Final(digest, ctx);
 }
 }
 
 
-#elif defined(_WIN32) && !defined(CURL_WINDOWS_APP)
+#elif defined(WIN32) && !defined(CURL_WINDOWS_APP)
 
 
 #include <wincrypt.h>
 #include <wincrypt.h>
 #include "curl_memory.h"
 #include "curl_memory.h"
@@ -163,13 +163,6 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
     CryptReleaseContext(ctx->hCryptProv, 0);
     CryptReleaseContext(ctx->hCryptProv, 0);
 }
 }
 
 
-#elif defined(USE_AXTLS)
-#include <axTLS/config.h>
-#include <axTLS/os_int.h>
-#include <axTLS/crypto.h>
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
 #else
 #else
 /* When no other crypto library is available we use this code segment */
 /* When no other crypto library is available we use this code segment */
 /*
 /*
@@ -282,7 +275,6 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
 {
 {
   const unsigned char *ptr;
   const unsigned char *ptr;
   MD5_u32plus a, b, c, d;
   MD5_u32plus a, b, c, d;
-  MD5_u32plus saved_a, saved_b, saved_c, saved_d;
 
 
   ptr = (const unsigned char *)data;
   ptr = (const unsigned char *)data;
 
 
@@ -292,6 +284,8 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
   d = ctx->d;
   d = ctx->d;
 
 
   do {
   do {
+    MD5_u32plus saved_a, saved_b, saved_c, saved_d;
+
     saved_a = a;
     saved_a = a;
     saved_b = b;
     saved_b = b;
     saved_c = c;
     saved_c = c;
@@ -299,77 +293,77 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
 
 
 /* Round 1 */
 /* Round 1 */
     STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
     STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
-      STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
-      STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
-      STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
-      STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
-      STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
-      STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
-      STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
-      STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
-      STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
-      STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
-      STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
-      STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
-      STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
-      STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
-      STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
+    STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
+    STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
+    STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
+    STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
+    STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
+    STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
+    STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
+    STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
+    STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
+    STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
+    STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
+    STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
+    STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
+    STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
+    STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
 
 
 /* Round 2 */
 /* Round 2 */
-      STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
-      STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
-      STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
-      STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
-      STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
-      STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
-      STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
-      STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
-      STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
-      STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
-      STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
-      STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
-      STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
-      STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
-      STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
-      STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
+    STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
+    STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
+    STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
+    STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
+    STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
+    STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
+    STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
+    STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
+    STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
+    STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
+    STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
+    STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
+    STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
+    STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
+    STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
+    STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
 
 
 /* Round 3 */
 /* Round 3 */
-      STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
-      STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
-      STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
-      STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
-      STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
-      STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
-      STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
-      STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
-      STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
-      STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
-      STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
-      STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
-      STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
-      STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
-      STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
-      STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
+    STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
+    STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
+    STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
+    STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
+    STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
+    STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
+    STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
+    STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
+    STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
+    STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
+    STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
+    STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
+    STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
+    STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
+    STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
+    STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
 
 
 /* Round 4 */
 /* Round 4 */
-      STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
-      STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
-      STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
-      STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
-      STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
-      STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
-      STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
-      STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
-      STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
-      STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
-      STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
-      STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
-      STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
-      STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
-      STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
-      STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
-
-      a += saved_a;
+    STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
+    STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
+    STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
+    STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
+    STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
+    STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
+    STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
+    STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
+    STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
+    STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
+    STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
+    STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
+    STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
+    STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
+    STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
+    STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
+
+    a += saved_a;
     b += saved_b;
     b += saved_b;
     c += saved_c;
     c += saved_c;
     d += saved_d;
     d += saved_d;
@@ -399,7 +393,7 @@ static void MD5_Init(MD5_CTX *ctx)
 static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
 static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
 {
 {
   MD5_u32plus saved_lo;
   MD5_u32plus saved_lo;
-  unsigned long used, available;
+  unsigned long used;
 
 
   saved_lo = ctx->lo;
   saved_lo = ctx->lo;
   ctx->lo = (saved_lo + size) & 0x1fffffff;
   ctx->lo = (saved_lo + size) & 0x1fffffff;
@@ -410,7 +404,7 @@ static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
   used = saved_lo & 0x3f;
   used = saved_lo & 0x3f;
 
 
   if(used) {
   if(used) {
-    available = 64 - used;
+    unsigned long available = 64 - used;
 
 
     if(size < available) {
     if(size < available) {
       memcpy(&ctx->buffer[used], data, size);
       memcpy(&ctx->buffer[used], data, size);
@@ -552,23 +546,23 @@ MD5_context *Curl_MD5_init(const MD5_params *md5params)
   return ctxt;
   return ctxt;
 }
 }
 
 
-int Curl_MD5_update(MD5_context *context,
-                    const unsigned char *data,
-                    unsigned int len)
+CURLcode Curl_MD5_update(MD5_context *context,
+                         const unsigned char *data,
+                         unsigned int len)
 {
 {
   (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len);
   (*context->md5_hash->md5_update_func)(context->md5_hashctx, data, len);
 
 
-  return 0;
+  return CURLE_OK;
 }
 }
 
 
-int Curl_MD5_final(MD5_context *context, unsigned char *result)
+CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result)
 {
 {
   (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
   (*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
 
 
   free(context->md5_hashctx);
   free(context->md5_hashctx);
   free(context);
   free(context);
 
 
-  return 0;
+  return CURLE_OK;
 }
 }
 
 
 #endif /* CURL_DISABLE_CRYPTO_AUTH */
 #endif /* CURL_DISABLE_CRYPTO_AUTH */

+ 69 - 85
Utilities/cmcurl/lib/memdebug.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -100,30 +100,29 @@ struct memdebug {
  * Don't use these with multithreaded test programs!
  * Don't use these with multithreaded test programs!
  */
  */
 
 
-#define logfile curl_debuglogfile
-FILE *curl_debuglogfile = NULL;
+FILE *curl_dbg_logfile = NULL;
 static bool memlimit = FALSE; /* enable memory limit */
 static bool memlimit = FALSE; /* enable memory limit */
 static long memsize = 0;  /* set number of mallocs allowed */
 static long memsize = 0;  /* set number of mallocs allowed */
 
 
 /* this sets the log file name */
 /* this sets the log file name */
-void curl_memdebug(const char *logname)
+void curl_dbg_memdebug(const char *logname)
 {
 {
-  if(!logfile) {
+  if(!curl_dbg_logfile) {
     if(logname && *logname)
     if(logname && *logname)
-      logfile = fopen(logname, FOPEN_WRITETEXT);
+      curl_dbg_logfile = fopen(logname, FOPEN_WRITETEXT);
     else
     else
-      logfile = stderr;
+      curl_dbg_logfile = stderr;
 #ifdef MEMDEBUG_LOG_SYNC
 #ifdef MEMDEBUG_LOG_SYNC
     /* Flush the log file after every line so the log isn't lost in a crash */
     /* Flush the log file after every line so the log isn't lost in a crash */
-    if(logfile)
-      setbuf(logfile, (char *)NULL);
+    if(curl_dbg_logfile)
+      setbuf(curl_dbg_logfile, (char *)NULL);
 #endif
 #endif
   }
   }
 }
 }
 
 
 /* This function sets the number of malloc() calls that should return
 /* This function sets the number of malloc() calls that should return
    successfully! */
    successfully! */
-void curl_memlimit(long limit)
+void curl_dbg_memlimit(long limit)
 {
 {
   if(!memlimit) {
   if(!memlimit) {
     memlimit = TRUE;
     memlimit = TRUE;
@@ -140,12 +139,12 @@ static bool countcheck(const char *func, int line, const char *source)
     if(!memsize) {
     if(!memsize) {
       if(source) {
       if(source) {
         /* log to file */
         /* log to file */
-        curl_memlog("LIMIT %s:%d %s reached memlimit\n",
-                    source, line, func);
+        curl_dbg_log("LIMIT %s:%d %s reached memlimit\n",
+                     source, line, func);
         /* log to stderr also */
         /* log to stderr also */
         fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
         fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
                 source, line, func);
                 source, line, func);
-        fflush(logfile); /* because it might crash now */
+        fflush(curl_dbg_logfile); /* because it might crash now */
       }
       }
       errno = ENOMEM;
       errno = ENOMEM;
       return TRUE; /* RETURN ERROR! */
       return TRUE; /* RETURN ERROR! */
@@ -159,7 +158,7 @@ static bool countcheck(const char *func, int line, const char *source)
   return FALSE; /* allow this */
   return FALSE; /* allow this */
 }
 }
 
 
-void *curl_domalloc(size_t wantedsize, int line, const char *source)
+void *curl_dbg_malloc(size_t wantedsize, int line, const char *source)
 {
 {
   struct memdebug *mem;
   struct memdebug *mem;
   size_t size;
   size_t size;
@@ -180,15 +179,15 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source)
   }
   }
 
 
   if(source)
   if(source)
-    curl_memlog("MEM %s:%d malloc(%zu) = %p\n",
-                source, line, wantedsize,
-                mem ? (void *)mem->mem : (void *)0);
+    curl_dbg_log("MEM %s:%d malloc(%zu) = %p\n",
+                 source, line, wantedsize,
+                 mem ? (void *)mem->mem : (void *)0);
 
 
   return (mem ? mem->mem : NULL);
   return (mem ? mem->mem : NULL);
 }
 }
 
 
-void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
-                    int line, const char *source)
+void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size,
+                      int line, const char *source)
 {
 {
   struct memdebug *mem;
   struct memdebug *mem;
   size_t size, user_size;
   size_t size, user_size;
@@ -208,14 +207,14 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
     mem->size = user_size;
     mem->size = user_size;
 
 
   if(source)
   if(source)
-    curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n",
-                source, line, wanted_elements, wanted_size,
-                mem ? (void *)mem->mem : (void *)0);
+    curl_dbg_log("MEM %s:%d calloc(%zu,%zu) = %p\n",
+                 source, line, wanted_elements, wanted_size,
+                 mem ? (void *)mem->mem : (void *)0);
 
 
   return (mem ? mem->mem : NULL);
   return (mem ? mem->mem : NULL);
 }
 }
 
 
-char *curl_dostrdup(const char *str, int line, const char *source)
+char *curl_dbg_strdup(const char *str, int line, const char *source)
 {
 {
   char *mem;
   char *mem;
   size_t len;
   size_t len;
@@ -227,19 +226,19 @@ char *curl_dostrdup(const char *str, int line, const char *source)
 
 
   len = strlen(str) + 1;
   len = strlen(str) + 1;
 
 
-  mem = curl_domalloc(len, 0, NULL); /* NULL prevents logging */
+  mem = curl_dbg_malloc(len, 0, NULL); /* NULL prevents logging */
   if(mem)
   if(mem)
     memcpy(mem, str, len);
     memcpy(mem, str, len);
 
 
   if(source)
   if(source)
-    curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n",
-                source, line, (const void *)str, len, (const void *)mem);
+    curl_dbg_log("MEM %s:%d strdup(%p) (%zu) = %p\n",
+                 source, line, (const void *)str, len, (const void *)mem);
 
 
   return mem;
   return mem;
 }
 }
 
 
 #if defined(WIN32) && defined(UNICODE)
 #if defined(WIN32) && defined(UNICODE)
-wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
+wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, const char *source)
 {
 {
   wchar_t *mem;
   wchar_t *mem;
   size_t wsiz, bsiz;
   size_t wsiz, bsiz;
@@ -252,12 +251,12 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
   wsiz = wcslen(str) + 1;
   wsiz = wcslen(str) + 1;
   bsiz = wsiz * sizeof(wchar_t);
   bsiz = wsiz * sizeof(wchar_t);
 
 
-  mem = curl_domalloc(bsiz, 0, NULL); /* NULL prevents logging */
+  mem = curl_dbg_malloc(bsiz, 0, NULL); /* NULL prevents logging */
   if(mem)
   if(mem)
     memcpy(mem, str, bsiz);
     memcpy(mem, str, bsiz);
 
 
   if(source)
   if(source)
-    curl_memlog("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
+    curl_dbg_log("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
                 source, line, (void *)str, bsiz, (void *)mem);
                 source, line, (void *)str, bsiz, (void *)mem);
 
 
   return mem;
   return mem;
@@ -266,8 +265,8 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
 
 
 /* We provide a realloc() that accepts a NULL as pointer, which then
 /* We provide a realloc() that accepts a NULL as pointer, which then
    performs a malloc(). In order to work with ares. */
    performs a malloc(). In order to work with ares. */
-void *curl_dorealloc(void *ptr, size_t wantedsize,
-                     int line, const char *source)
+void *curl_dbg_realloc(void *ptr, size_t wantedsize,
+                      int line, const char *source)
 {
 {
   struct memdebug *mem = NULL;
   struct memdebug *mem = NULL;
 
 
@@ -293,7 +292,7 @@ void *curl_dorealloc(void *ptr, size_t wantedsize,
 
 
   mem = (Curl_crealloc)(mem, size);
   mem = (Curl_crealloc)(mem, size);
   if(source)
   if(source)
-    curl_memlog("MEM %s:%d realloc(%p, %zu) = %p\n",
+    curl_dbg_log("MEM %s:%d realloc(%p, %zu) = %p\n",
                 source, line, (void *)ptr, wantedsize,
                 source, line, (void *)ptr, wantedsize,
                 mem ? (void *)mem->mem : (void *)0);
                 mem ? (void *)mem->mem : (void *)0);
 
 
@@ -305,11 +304,10 @@ void *curl_dorealloc(void *ptr, size_t wantedsize,
   return NULL;
   return NULL;
 }
 }
 
 
-void curl_dofree(void *ptr, int line, const char *source)
+void curl_dbg_free(void *ptr, int line, const char *source)
 {
 {
-  struct memdebug *mem;
-
   if(ptr) {
   if(ptr) {
+    struct memdebug *mem;
 
 
 #ifdef __INTEL_COMPILER
 #ifdef __INTEL_COMPILER
 #  pragma warning(push)
 #  pragma warning(push)
@@ -331,11 +329,11 @@ void curl_dofree(void *ptr, int line, const char *source)
   }
   }
 
 
   if(source)
   if(source)
-    curl_memlog("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
+    curl_dbg_log("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
 }
 }
 
 
-curl_socket_t curl_socket(int domain, int type, int protocol,
-                          int line, const char *source)
+curl_socket_t curl_dbg_socket(int domain, int type, int protocol,
+                             int line, const char *source)
 {
 {
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
     "FD %s:%d socket() = %d\n" :
     "FD %s:%d socket() = %d\n" :
@@ -351,44 +349,44 @@ curl_socket_t curl_socket(int domain, int type, int protocol,
   sockfd = socket(domain, type, protocol);
   sockfd = socket(domain, type, protocol);
 
 
   if(source && (sockfd != CURL_SOCKET_BAD))
   if(source && (sockfd != CURL_SOCKET_BAD))
-    curl_memlog(fmt, source, line, sockfd);
+    curl_dbg_log(fmt, source, line, sockfd);
 
 
   return sockfd;
   return sockfd;
 }
 }
 
 
-SEND_TYPE_RETV curl_dosend(SEND_TYPE_ARG1 sockfd,
-                           SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf,
-                           SEND_TYPE_ARG3 len, SEND_TYPE_ARG4 flags, int line,
-                           const char *source)
+SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd,
+                            SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf,
+                            SEND_TYPE_ARG3 len, SEND_TYPE_ARG4 flags, int line,
+                            const char *source)
 {
 {
   SEND_TYPE_RETV rc;
   SEND_TYPE_RETV rc;
   if(countcheck("send", line, source))
   if(countcheck("send", line, source))
     return -1;
     return -1;
   rc = send(sockfd, buf, len, flags);
   rc = send(sockfd, buf, len, flags);
   if(source)
   if(source)
-    curl_memlog("SEND %s:%d send(%lu) = %ld\n",
+    curl_dbg_log("SEND %s:%d send(%lu) = %ld\n",
                 source, line, (unsigned long)len, (long)rc);
                 source, line, (unsigned long)len, (long)rc);
   return rc;
   return rc;
 }
 }
 
 
-RECV_TYPE_RETV curl_dorecv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf,
-                           RECV_TYPE_ARG3 len, RECV_TYPE_ARG4 flags, int line,
-                           const char *source)
+RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf,
+                            RECV_TYPE_ARG3 len, RECV_TYPE_ARG4 flags, int line,
+                            const char *source)
 {
 {
   RECV_TYPE_RETV rc;
   RECV_TYPE_RETV rc;
   if(countcheck("recv", line, source))
   if(countcheck("recv", line, source))
     return -1;
     return -1;
   rc = recv(sockfd, buf, len, flags);
   rc = recv(sockfd, buf, len, flags);
   if(source)
   if(source)
-    curl_memlog("RECV %s:%d recv(%lu) = %ld\n",
+    curl_dbg_log("RECV %s:%d recv(%lu) = %ld\n",
                 source, line, (unsigned long)len, (long)rc);
                 source, line, (unsigned long)len, (long)rc);
   return rc;
   return rc;
 }
 }
 
 
 #ifdef HAVE_SOCKETPAIR
 #ifdef HAVE_SOCKETPAIR
-int curl_socketpair(int domain, int type, int protocol,
-                    curl_socket_t socket_vector[2],
-                    int line, const char *source)
+int curl_dbg_socketpair(int domain, int type, int protocol,
+                       curl_socket_t socket_vector[2],
+                       int line, const char *source)
 {
 {
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
     "FD %s:%d socketpair() = %d %d\n" :
     "FD %s:%d socketpair() = %d %d\n" :
@@ -399,14 +397,14 @@ int curl_socketpair(int domain, int type, int protocol,
   int res = socketpair(domain, type, protocol, socket_vector);
   int res = socketpair(domain, type, protocol, socket_vector);
 
 
   if(source && (0 == res))
   if(source && (0 == res))
-    curl_memlog(fmt, source, line, socket_vector[0], socket_vector[1]);
+    curl_dbg_log(fmt, source, line, socket_vector[0], socket_vector[1]);
 
 
   return res;
   return res;
 }
 }
 #endif
 #endif
 
 
-curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
-                          int line, const char *source)
+curl_socket_t curl_dbg_accept(curl_socket_t s, void *saddr, void *saddrlen,
+                             int line, const char *source)
 {
 {
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
     "FD %s:%d accept() = %d\n" :
     "FD %s:%d accept() = %d\n" :
@@ -420,13 +418,13 @@ curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
   curl_socket_t sockfd = accept(s, addr, addrlen);
   curl_socket_t sockfd = accept(s, addr, addrlen);
 
 
   if(source && (sockfd != CURL_SOCKET_BAD))
   if(source && (sockfd != CURL_SOCKET_BAD))
-    curl_memlog(fmt, source, line, sockfd);
+    curl_dbg_log(fmt, source, line, sockfd);
 
 
   return sockfd;
   return sockfd;
 }
 }
 
 
 /* separate function to allow libcurl to mark a "faked" close */
 /* separate function to allow libcurl to mark a "faked" close */
-void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source)
+void curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source)
 {
 {
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
   const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
     "FD %s:%d sclose(%d)\n":
     "FD %s:%d sclose(%d)\n":
@@ -435,54 +433,40 @@ void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source)
     "FD %s:%d sclose(%zd)\n";
     "FD %s:%d sclose(%zd)\n";
 
 
   if(source)
   if(source)
-    curl_memlog(fmt, source, line, sockfd);
+    curl_dbg_log(fmt, source, line, sockfd);
 }
 }
 
 
 /* this is our own defined way to close sockets on *ALL* platforms */
 /* this is our own defined way to close sockets on *ALL* platforms */
-int curl_sclose(curl_socket_t sockfd, int line, const char *source)
+int curl_dbg_sclose(curl_socket_t sockfd, int line, const char *source)
 {
 {
   int res = sclose(sockfd);
   int res = sclose(sockfd);
-  curl_mark_sclose(sockfd, line, source);
+  curl_dbg_mark_sclose(sockfd, line, source);
   return res;
   return res;
 }
 }
 
 
-FILE *curl_fopen(const char *file, const char *mode,
-                 int line, const char *source)
+FILE *curl_dbg_fopen(const char *file, const char *mode,
+                    int line, const char *source)
 {
 {
   FILE *res = fopen(file, mode);
   FILE *res = fopen(file, mode);
 
 
   if(source)
   if(source)
-    curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
+    curl_dbg_log("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
                 source, line, file, mode, (void *)res);
                 source, line, file, mode, (void *)res);
 
 
   return res;
   return res;
 }
 }
 
 
-#ifdef HAVE_FDOPEN
-FILE *curl_fdopen(int filedes, const char *mode,
-                  int line, const char *source)
-{
-  FILE *res = fdopen(filedes, mode);
-
-  if(source)
-    curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
-                source, line, filedes, mode, (void *)res);
-
-  return res;
-}
-#endif
-
-int curl_fclose(FILE *file, int line, const char *source)
+int curl_dbg_fclose(FILE *file, int line, const char *source)
 {
 {
   int res;
   int res;
 
 
   DEBUGASSERT(file != NULL);
   DEBUGASSERT(file != NULL);
 
 
-  res = fclose(file);
-
   if(source)
   if(source)
-    curl_memlog("FILE %s:%d fclose(%p)\n",
-                source, line, (void *)file);
+    curl_dbg_log("FILE %s:%d fclose(%p)\n",
+                 source, line, (void *)file);
+
+  res = fclose(file);
 
 
   return res;
   return res;
 }
 }
@@ -490,13 +474,13 @@ int curl_fclose(FILE *file, int line, const char *source)
 #define LOGLINE_BUFSIZE  1024
 #define LOGLINE_BUFSIZE  1024
 
 
 /* this does the writing to the memory tracking log file */
 /* this does the writing to the memory tracking log file */
-void curl_memlog(const char *format, ...)
+void curl_dbg_log(const char *format, ...)
 {
 {
   char *buf;
   char *buf;
   int nchars;
   int nchars;
   va_list ap;
   va_list ap;
 
 
-  if(!logfile)
+  if(!curl_dbg_logfile)
     return;
     return;
 
 
   buf = (Curl_cmalloc)(LOGLINE_BUFSIZE);
   buf = (Curl_cmalloc)(LOGLINE_BUFSIZE);
@@ -504,14 +488,14 @@ void curl_memlog(const char *format, ...)
     return;
     return;
 
 
   va_start(ap, format);
   va_start(ap, format);
-  nchars = vsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
+  nchars = mvsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
   va_end(ap);
   va_end(ap);
 
 
   if(nchars > LOGLINE_BUFSIZE - 1)
   if(nchars > LOGLINE_BUFSIZE - 1)
     nchars = LOGLINE_BUFSIZE - 1;
     nchars = LOGLINE_BUFSIZE - 1;
 
 
   if(nchars > 0)
   if(nchars > 0)
-    fwrite(buf, 1, (size_t)nchars, logfile);
+    fwrite(buf, 1, (size_t)nchars, curl_dbg_logfile);
 
 
   (Curl_cfree)(buf);
   (Curl_cfree)(buf);
 }
 }

+ 59 - 64
Utilities/cmcurl/lib/memdebug.h

@@ -8,7 +8,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -30,97 +30,92 @@
 
 
 #define CURL_MT_LOGFNAME_BUFSIZE 512
 #define CURL_MT_LOGFNAME_BUFSIZE 512
 
 
-#define logfile curl_debuglogfile
-
-extern FILE *logfile;
+extern FILE *curl_dbg_logfile;
 
 
 /* memory functions */
 /* memory functions */
-CURL_EXTERN void *curl_domalloc(size_t size, int line, const char *source);
-CURL_EXTERN void *curl_docalloc(size_t elements, size_t size, int line,
-                                const char *source);
-CURL_EXTERN void *curl_dorealloc(void *ptr, size_t size, int line,
-                                 const char *source);
-CURL_EXTERN void curl_dofree(void *ptr, int line, const char *source);
-CURL_EXTERN char *curl_dostrdup(const char *str, int line, const char *source);
-#if defined(WIN32) && defined(UNICODE)
-CURL_EXTERN wchar_t *curl_dowcsdup(const wchar_t *str, int line,
+CURL_EXTERN void *curl_dbg_malloc(size_t size, int line, const char *source);
+CURL_EXTERN void *curl_dbg_calloc(size_t elements, size_t size, int line,
+                                  const char *source);
+CURL_EXTERN void *curl_dbg_realloc(void *ptr, size_t size, int line,
                                    const char *source);
                                    const char *source);
+CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source);
+CURL_EXTERN char *curl_dbg_strdup(const char *str, int line, const char *src);
+#if defined(WIN32) && defined(UNICODE)
+CURL_EXTERN wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line,
+                                     const char *source);
 #endif
 #endif
 
 
-CURL_EXTERN void curl_memdebug(const char *logname);
-CURL_EXTERN void curl_memlimit(long limit);
-CURL_EXTERN void curl_memlog(const char *format, ...);
+CURL_EXTERN void curl_dbg_memdebug(const char *logname);
+CURL_EXTERN void curl_dbg_memlimit(long limit);
+CURL_EXTERN void curl_dbg_log(const char *format, ...);
 
 
 /* file descriptor manipulators */
 /* file descriptor manipulators */
-CURL_EXTERN curl_socket_t curl_socket(int domain, int type, int protocol,
-                                      int line, const char *source);
-CURL_EXTERN void curl_mark_sclose(curl_socket_t sockfd,
-                                  int line, const char *source);
-CURL_EXTERN int curl_sclose(curl_socket_t sockfd,
-                            int line, const char *source);
-CURL_EXTERN curl_socket_t curl_accept(curl_socket_t s, void *a, void *alen,
+CURL_EXTERN curl_socket_t curl_dbg_socket(int domain, int type, int protocol,
+                                          int line, const char *source);
+CURL_EXTERN void curl_dbg_mark_sclose(curl_socket_t sockfd,
                                       int line, const char *source);
                                       int line, const char *source);
-#ifdef HAVE_SOCKETPAIR
-CURL_EXTERN int curl_socketpair(int domain, int type, int protocol,
-                                curl_socket_t socket_vector[2],
+CURL_EXTERN int curl_dbg_sclose(curl_socket_t sockfd,
                                 int line, const char *source);
                                 int line, const char *source);
+CURL_EXTERN curl_socket_t curl_dbg_accept(curl_socket_t s, void *a, void *alen,
+                                          int line, const char *source);
+#ifdef HAVE_SOCKETPAIR
+CURL_EXTERN int curl_dbg_socketpair(int domain, int type, int protocol,
+                                    curl_socket_t socket_vector[2],
+                                    int line, const char *source);
 #endif
 #endif
 
 
 /* send/receive sockets */
 /* send/receive sockets */
-CURL_EXTERN SEND_TYPE_RETV curl_dosend(SEND_TYPE_ARG1 sockfd,
-                                       SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf,
-                                       SEND_TYPE_ARG3 len,
-                                       SEND_TYPE_ARG4 flags, int line,
-                                       const char *source);
-CURL_EXTERN RECV_TYPE_RETV curl_dorecv(RECV_TYPE_ARG1 sockfd,
-                                       RECV_TYPE_ARG2 buf, RECV_TYPE_ARG3 len,
-                                       RECV_TYPE_ARG4 flags, int line,
-                                       const char *source);
+CURL_EXTERN SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd,
+                                         SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf,
+                                         SEND_TYPE_ARG3 len,
+                                         SEND_TYPE_ARG4 flags, int line,
+                                         const char *source);
+CURL_EXTERN RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd,
+                                         RECV_TYPE_ARG2 buf,
+                                         RECV_TYPE_ARG3 len,
+                                         RECV_TYPE_ARG4 flags, int line,
+                                         const char *source);
 
 
 /* FILE functions */
 /* FILE functions */
-CURL_EXTERN FILE *curl_fopen(const char *file, const char *mode, int line,
-                             const char *source);
-#ifdef HAVE_FDOPEN
-CURL_EXTERN FILE *curl_fdopen(int filedes, const char *mode, int line,
-                              const char *source);
-#endif
-CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
+CURL_EXTERN FILE *curl_dbg_fopen(const char *file, const char *mode, int line,
+                                 const char *source);
+CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source);
 
 
 #ifndef MEMDEBUG_NODEFINES
 #ifndef MEMDEBUG_NODEFINES
 
 
 /* Set this symbol on the command-line, recompile all lib-sources */
 /* Set this symbol on the command-line, recompile all lib-sources */
 #undef strdup
 #undef strdup
-#define strdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
-#define malloc(size) curl_domalloc(size, __LINE__, __FILE__)
-#define calloc(nbelem,size) curl_docalloc(nbelem, size, __LINE__, __FILE__)
-#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__)
-#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__)
-#define send(a,b,c,d) curl_dosend(a,b,c,d, __LINE__, __FILE__)
-#define recv(a,b,c,d) curl_dorecv(a,b,c,d, __LINE__, __FILE__)
+#define strdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__)
+#define malloc(size) curl_dbg_malloc(size, __LINE__, __FILE__)
+#define calloc(nbelem,size) curl_dbg_calloc(nbelem, size, __LINE__, __FILE__)
+#define realloc(ptr,size) curl_dbg_realloc(ptr, size, __LINE__, __FILE__)
+#define free(ptr) curl_dbg_free(ptr, __LINE__, __FILE__)
+#define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__)
+#define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__)
 
 
 #ifdef WIN32
 #ifdef WIN32
 #  ifdef UNICODE
 #  ifdef UNICODE
 #    undef wcsdup
 #    undef wcsdup
-#    define wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+#    define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
 #    undef _wcsdup
 #    undef _wcsdup
-#    define _wcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+#    define _wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
 #    undef _tcsdup
 #    undef _tcsdup
-#    define _tcsdup(ptr) curl_dowcsdup(ptr, __LINE__, __FILE__)
+#    define _tcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__)
 #  else
 #  else
 #    undef _tcsdup
 #    undef _tcsdup
-#    define _tcsdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
+#    define _tcsdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__)
 #  endif
 #  endif
 #endif
 #endif
 
 
 #undef socket
 #undef socket
 #define socket(domain,type,protocol)\
 #define socket(domain,type,protocol)\
- curl_socket(domain, type, protocol, __LINE__, __FILE__)
+ curl_dbg_socket(domain, type, protocol, __LINE__, __FILE__)
 #undef accept /* for those with accept as a macro */
 #undef accept /* for those with accept as a macro */
 #define accept(sock,addr,len)\
 #define accept(sock,addr,len)\
- curl_accept(sock, addr, len, __LINE__, __FILE__)
+ curl_dbg_accept(sock, addr, len, __LINE__, __FILE__)
 #ifdef HAVE_SOCKETPAIR
 #ifdef HAVE_SOCKETPAIR
 #define socketpair(domain,type,protocol,socket_vector)\
 #define socketpair(domain,type,protocol,socket_vector)\
- curl_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__)
+ curl_dbg_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__)
 #endif
 #endif
 
 
 #ifdef HAVE_GETADDRINFO
 #ifdef HAVE_GETADDRINFO
@@ -129,31 +124,31 @@ CURL_EXTERN int curl_fclose(FILE *file, int line, const char *source);
    our macro as for other platforms. Instead, we redefine the new name they
    our macro as for other platforms. Instead, we redefine the new name they
    define getaddrinfo to become! */
    define getaddrinfo to become! */
 #define ogetaddrinfo(host,serv,hint,res) \
 #define ogetaddrinfo(host,serv,hint,res) \
-  curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
+  curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
 #else
 #else
 #undef getaddrinfo
 #undef getaddrinfo
 #define getaddrinfo(host,serv,hint,res) \
 #define getaddrinfo(host,serv,hint,res) \
-  curl_dogetaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
+  curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__)
 #endif
 #endif
 #endif /* HAVE_GETADDRINFO */
 #endif /* HAVE_GETADDRINFO */
 
 
 #ifdef HAVE_FREEADDRINFO
 #ifdef HAVE_FREEADDRINFO
 #undef freeaddrinfo
 #undef freeaddrinfo
 #define freeaddrinfo(data) \
 #define freeaddrinfo(data) \
-  curl_dofreeaddrinfo(data, __LINE__, __FILE__)
+  curl_dbg_freeaddrinfo(data, __LINE__, __FILE__)
 #endif /* HAVE_FREEADDRINFO */
 #endif /* HAVE_FREEADDRINFO */
 
 
 /* sclose is probably already defined, redefine it! */
 /* sclose is probably already defined, redefine it! */
 #undef sclose
 #undef sclose
-#define sclose(sockfd) curl_sclose(sockfd,__LINE__,__FILE__)
+#define sclose(sockfd) curl_dbg_sclose(sockfd,__LINE__,__FILE__)
 
 
-#define fake_sclose(sockfd) curl_mark_sclose(sockfd,__LINE__,__FILE__)
+#define fake_sclose(sockfd) curl_dbg_mark_sclose(sockfd,__LINE__,__FILE__)
 
 
 #undef fopen
 #undef fopen
-#define fopen(file,mode) curl_fopen(file,mode,__LINE__,__FILE__)
+#define fopen(file,mode) curl_dbg_fopen(file,mode,__LINE__,__FILE__)
 #undef fdopen
 #undef fdopen
-#define fdopen(file,mode) curl_fdopen(file,mode,__LINE__,__FILE__)
-#define fclose(file) curl_fclose(file,__LINE__,__FILE__)
+#define fdopen(file,mode) curl_dbg_fdopen(file,mode,__LINE__,__FILE__)
+#define fclose(file) curl_dbg_fclose(file,__LINE__,__FILE__)
 
 
 #endif /* MEMDEBUG_NODEFINES */
 #endif /* MEMDEBUG_NODEFINES */
 
 

+ 9 - 85
Utilities/cmcurl/lib/mime.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -29,8 +29,8 @@
 #include "urldata.h"
 #include "urldata.h"
 #include "sendf.h"
 #include "sendf.h"
 
 
-#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
-    !defined(CURL_DISABLE_IMAP)
+#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
+  !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
 
 
 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
 #if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
 #include <libgen.h>
 #include <libgen.h>
@@ -821,8 +821,10 @@ static size_t readback_part(curl_mimepart *part,
     struct curl_slist *hdr = (struct curl_slist *) part->state.ptr;
     struct curl_slist *hdr = (struct curl_slist *) part->state.ptr;
     switch(part->state.state) {
     switch(part->state.state) {
     case MIMESTATE_BEGIN:
     case MIMESTATE_BEGIN:
-      mimesetstate(&part->state, part->flags & MIME_BODY_ONLY? MIMESTATE_BODY:
-                                 MIMESTATE_CURLHEADERS, part->curlheaders);
+      mimesetstate(&part->state,
+                   (part->flags & MIME_BODY_ONLY)?
+                     MIMESTATE_BODY: MIMESTATE_CURLHEADERS,
+                   part->curlheaders);
       break;
       break;
     case MIMESTATE_USERHEADERS:
     case MIMESTATE_USERHEADERS:
       if(!hdr) {
       if(!hdr) {
@@ -1122,8 +1124,6 @@ void curl_mime_free(curl_mime *mime)
       Curl_mime_cleanpart(part);
       Curl_mime_cleanpart(part);
       free(part);
       free(part);
     }
     }
-
-    free(mime->boundary);
     free(mime);
     free(mime);
   }
   }
 }
 }
@@ -1220,18 +1220,10 @@ curl_mime *curl_mime_init(struct Curl_easy *easy)
     mime->firstpart = NULL;
     mime->firstpart = NULL;
     mime->lastpart = NULL;
     mime->lastpart = NULL;
 
 
-    /* Get a part boundary. */
-    mime->boundary = malloc(24 + MIME_RAND_BOUNDARY_CHARS + 1);
-    if(!mime->boundary) {
-      free(mime);
-      return NULL;
-    }
-
     memset(mime->boundary, '-', 24);
     memset(mime->boundary, '-', 24);
-    if(Curl_rand_hex(easy, (unsigned char *) mime->boundary + 24,
+    if(Curl_rand_hex(easy, (unsigned char *) &mime->boundary[24],
                      MIME_RAND_BOUNDARY_CHARS + 1)) {
                      MIME_RAND_BOUNDARY_CHARS + 1)) {
       /* failed to get random separator, bail out */
       /* failed to get random separator, bail out */
-      free(mime->boundary);
       free(mime);
       free(mime);
       return NULL;
       return NULL;
     }
     }
@@ -1909,72 +1901,4 @@ CURLcode curl_mime_headers(curl_mimepart *part,
   return CURLE_NOT_BUILT_IN;
   return CURLE_NOT_BUILT_IN;
 }
 }
 
 
-void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
-{
-  (void) part;
-  (void) easy;
-}
-
-void Curl_mime_cleanpart(curl_mimepart *part)
-{
-  (void) part;
-}
-
-CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src)
-{
-  (void) dst;
-  (void) src;
-  return CURLE_OK;    /* Nothing to duplicate: always succeed. */
-}
-
-CURLcode Curl_mime_set_subparts(curl_mimepart *part,
-                                curl_mime *subparts, int take_ownership)
-{
-  (void) part;
-  (void) subparts;
-  (void) take_ownership;
-  return CURLE_NOT_BUILT_IN;
-}
-
-CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
-                                   const char *contenttype,
-                                   const char *disposition,
-                                   enum mimestrategy strategy)
-{
-  (void) part;
-  (void) contenttype;
-  (void) disposition;
-  (void) strategy;
-  return CURLE_NOT_BUILT_IN;
-}
-
-curl_off_t Curl_mime_size(curl_mimepart *part)
-{
-  (void) part;
-  return (curl_off_t) -1;
-}
-
-size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
-{
-  (void) buffer;
-  (void) size;
-  (void) nitems;
-  (void) instream;
-  return 0;
-}
-
-CURLcode Curl_mime_rewind(curl_mimepart *part)
-{
-  (void) part;
-  return CURLE_NOT_BUILT_IN;
-}
-
-/* VARARGS2 */
-CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
-{
-  (void) slp;
-  (void) fmt;
-  return CURLE_NOT_BUILT_IN;
-}
-
-#endif /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
+#endif /* if disabled */

+ 24 - 3
Utilities/cmcurl/lib/mime.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,8 @@
  *
  *
  ***************************************************************************/
  ***************************************************************************/
 
 
+#include "curl_setup.h"
+
 #define MIME_RAND_BOUNDARY_CHARS        16  /* Nb. of random boundary chars. */
 #define MIME_RAND_BOUNDARY_CHARS        16  /* Nb. of random boundary chars. */
 #define MAX_ENCODED_LINE_LENGTH         76  /* Maximum encoded line length. */
 #define MAX_ENCODED_LINE_LENGTH         76  /* Maximum encoded line length. */
 #define ENCODING_BUFFER_SIZE            256 /* Encoding temp buffers size. */
 #define ENCODING_BUFFER_SIZE            256 /* Encoding temp buffers size. */
@@ -69,7 +71,7 @@ enum mimestrategy {
 typedef struct {
 typedef struct {
   const char *   name;          /* Encoding name. */
   const char *   name;          /* Encoding name. */
   size_t         (*encodefunc)(char *buffer, size_t size, bool ateof,
   size_t         (*encodefunc)(char *buffer, size_t size, bool ateof,
-                             curl_mimepart *part);  /* Encoded read. */
+                               curl_mimepart *part);  /* Encoded read. */
   curl_off_t     (*sizefunc)(curl_mimepart *part);  /* Encoded size. */
   curl_off_t     (*sizefunc)(curl_mimepart *part);  /* Encoded size. */
 }  mime_encoder;
 }  mime_encoder;
 
 
@@ -88,13 +90,16 @@ typedef struct {
   size_t offset;              /* State-dependent offset. */
   size_t offset;              /* State-dependent offset. */
 }  mime_state;
 }  mime_state;
 
 
+/* minimum buffer size for the boundary string */
+#define MIME_BOUNDARY_LEN (24 + MIME_RAND_BOUNDARY_CHARS + 1)
+
 /* A mime multipart. */
 /* A mime multipart. */
 struct curl_mime_s {
 struct curl_mime_s {
   struct Curl_easy *easy;          /* The associated easy handle. */
   struct Curl_easy *easy;          /* The associated easy handle. */
   curl_mimepart *parent;           /* Parent part. */
   curl_mimepart *parent;           /* Parent part. */
   curl_mimepart *firstpart;        /* First part. */
   curl_mimepart *firstpart;        /* First part. */
   curl_mimepart *lastpart;         /* Last part. */
   curl_mimepart *lastpart;         /* Last part. */
-  char *boundary;                  /* The part boundary. */
+  char boundary[MIME_BOUNDARY_LEN]; /* The part boundary. */
   mime_state state;                /* Current readback state. */
   mime_state state;                /* Current readback state. */
 };
 };
 
 
@@ -122,6 +127,8 @@ struct curl_mimepart_s {
   mime_encoder_state encstate;     /* Data encoder state. */
   mime_encoder_state encstate;     /* Data encoder state. */
 };
 };
 
 
+#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
+  !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
 
 
 /* Prototypes. */
 /* Prototypes. */
 void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy);
 void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy);
@@ -140,4 +147,18 @@ CURLcode Curl_mime_rewind(curl_mimepart *part);
 CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
 CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
 const char *Curl_mime_contenttype(const char *filename);
 const char *Curl_mime_contenttype(const char *filename);
 
 
+#else
+/* if disabled */
+#define Curl_mime_initpart(x,y)
+#define Curl_mime_cleanpart(x)
+#define Curl_mime_duppart(x,y) CURLE_OK /* Nothing to duplicate. Succeed */
+#define Curl_mime_set_subparts(a,b,c) CURLE_NOT_BUILT_IN
+#define Curl_mime_prepare_headers(a,b,c,d) CURLE_NOT_BUILT_IN
+#define Curl_mime_size(x) (curl_off_t) -1
+#define Curl_mime_read NULL
+#define Curl_mime_rewind(x) ((void)x, CURLE_NOT_BUILT_IN)
+#define Curl_mime_add_header(x,y,...) CURLE_NOT_BUILT_IN
+#endif
+
+
 #endif /* HEADER_CURL_MIME_H */
 #endif /* HEADER_CURL_MIME_H */

+ 1 - 1
Utilities/cmcurl/lib/mprintf.c

@@ -835,7 +835,7 @@ static int dprintf_formatf(
           while(width-- > 0)
           while(width-- > 0)
             OUTCHAR(' ');
             OUTCHAR(' ');
 
 
-        while((len-- > 0) && *str)
+        for(; len && *str; len--)
           OUTCHAR(*str++);
           OUTCHAR(*str++);
         if(p->flags&FLAGS_LEFT)
         if(p->flags&FLAGS_LEFT)
           while(width-- > 0)
           while(width-- > 0)

Файловите разлики са ограничени, защото са твърде много
+ 197 - 296
Utilities/cmcurl/lib/multi.c


+ 14 - 34
Utilities/cmcurl/lib/multihandle.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -46,18 +46,16 @@ typedef enum {
   CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */
   CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */
   CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect
   CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect
                                    phase */
                                    phase */
-  CURLM_STATE_WAITDO,       /* 8 - wait for our turn to send the request */
-  CURLM_STATE_DO,           /* 9 - start send off the request (part 1) */
-  CURLM_STATE_DOING,        /* 10 - sending off the request (part 1) */
-  CURLM_STATE_DO_MORE,      /* 11 - send off the request (part 2) */
-  CURLM_STATE_DO_DONE,      /* 12 - done sending off request */
-  CURLM_STATE_WAITPERFORM,  /* 13 - wait for our turn to read the response */
-  CURLM_STATE_PERFORM,      /* 14 - transfer data */
-  CURLM_STATE_TOOFAST,      /* 15 - wait because limit-rate exceeded */
-  CURLM_STATE_DONE,         /* 16 - post data transfer operation */
-  CURLM_STATE_COMPLETED,    /* 17 - operation complete */
-  CURLM_STATE_MSGSENT,      /* 18 - the operation complete message is sent */
-  CURLM_STATE_LAST          /* 19 - not a true state, never use this */
+  CURLM_STATE_DO,           /* 8 - start send off the request (part 1) */
+  CURLM_STATE_DOING,        /* 9 - sending off the request (part 1) */
+  CURLM_STATE_DO_MORE,      /* 10 - send off the request (part 2) */
+  CURLM_STATE_DO_DONE,      /* 11 - done sending off request */
+  CURLM_STATE_PERFORM,      /* 12 - transfer data */
+  CURLM_STATE_TOOFAST,      /* 13 - wait because limit-rate exceeded */
+  CURLM_STATE_DONE,         /* 14 - post data transfer operation */
+  CURLM_STATE_COMPLETED,    /* 15 - operation complete */
+  CURLM_STATE_MSGSENT,      /* 16 - the operation complete message is sent */
+  CURLM_STATE_LAST          /* 17 - not a true state, never use this */
 } CURLMstate;
 } CURLMstate;
 
 
 /* we support N sockets per easy handle. Set the corresponding bit to what
 /* we support N sockets per easy handle. Set the corresponding bit to what
@@ -66,7 +64,7 @@ typedef enum {
 #define GETSOCK_READABLE (0x00ff)
 #define GETSOCK_READABLE (0x00ff)
 #define GETSOCK_WRITABLE (0xff00)
 #define GETSOCK_WRITABLE (0xff00)
 
 
-#define CURLPIPE_ANY (CURLPIPE_HTTP1 | CURLPIPE_MULTIPLEX)
+#define CURLPIPE_ANY (CURLPIPE_MULTIPLEX)
 
 
 /* This is the struct known as CURLM on the outside */
 /* This is the struct known as CURLM on the outside */
 struct Curl_multi {
 struct Curl_multi {
@@ -112,8 +110,8 @@ struct Curl_multi {
      same actual socket) */
      same actual socket) */
   struct curl_hash sockhash;
   struct curl_hash sockhash;
 
 
-  /* pipelining wanted bits (CURLPIPE*) */
-  long pipelining;
+  /* multiplexing wanted */
+  bool multiplexing;
 
 
   bool recheckstate; /* see Curl_multi_connchanged */
   bool recheckstate; /* see Curl_multi_connchanged */
 
 
@@ -129,24 +127,6 @@ struct Curl_multi {
   long max_total_connections; /* if >0, a fixed limit of the maximum number
   long max_total_connections; /* if >0, a fixed limit of the maximum number
                                  of connections in total */
                                  of connections in total */
 
 
-  long max_pipeline_length; /* if >0, maximum number of requests in a
-                               pipeline */
-
-  long content_length_penalty_size; /* a connection with a
-                                       content-length bigger than
-                                       this is not considered
-                                       for pipelining */
-
-  long chunk_length_penalty_size; /* a connection with a chunk length
-                                     bigger than this is not
-                                     considered for pipelining */
-
-  struct curl_llist pipelining_site_bl; /* List of sites that are blacklisted
-                                           from pipelining */
-
-  struct curl_llist pipelining_server_bl; /* List of server types that are
-                                             blacklisted from pipelining */
-
   /* timer callback and user data pointer for the *socket() API */
   /* timer callback and user data pointer for the *socket() API */
   curl_multi_timer_callback timer_cb;
   curl_multi_timer_callback timer_cb;
   void *timer_userp;
   void *timer_userp;

+ 16 - 17
Utilities/cmcurl/lib/multiif.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -30,8 +30,10 @@ void Curl_updatesocket(struct Curl_easy *data);
 void Curl_expire(struct Curl_easy *data, time_t milli, expire_id);
 void Curl_expire(struct Curl_easy *data, time_t milli, expire_id);
 void Curl_expire_clear(struct Curl_easy *data);
 void Curl_expire_clear(struct Curl_easy *data);
 void Curl_expire_done(struct Curl_easy *data, expire_id id);
 void Curl_expire_done(struct Curl_easy *data, expire_id id);
-bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
-void Curl_multi_handlePipeBreak(struct Curl_easy *data);
+void Curl_detach_connnection(struct Curl_easy *data);
+void Curl_attach_connnection(struct Curl_easy *data,
+                             struct connectdata *conn);
+bool Curl_multiplex_wanted(const struct Curl_multi *multi);
 void Curl_set_in_callback(struct Curl_easy *data, bool value);
 void Curl_set_in_callback(struct Curl_easy *data, bool value);
 bool Curl_is_in_callback(struct Curl_easy *easy);
 bool Curl_is_in_callback(struct Curl_easy *easy);
 
 
@@ -62,22 +64,11 @@ void Curl_multi_dump(struct Curl_multi *multi);
 /* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
 /* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */
 size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
 size_t Curl_multi_max_host_connections(struct Curl_multi *multi);
 
 
-/* Return the value of the CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE option */
-curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi);
-
-/* Return the value of the CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE option */
-curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi);
-
-/* Return the value of the CURLMOPT_PIPELINING_SITE_BL option */
-struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi);
-
-/* Return the value of the CURLMOPT_PIPELINING_SERVER_BL option */
-struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi);
-
 /* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
 /* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */
 size_t Curl_multi_max_total_connections(struct Curl_multi *multi);
 size_t Curl_multi_max_total_connections(struct Curl_multi *multi);
 
 
-void Curl_multi_connchanged(struct Curl_multi *multi);
+void Curl_multiuse_state(struct connectdata *conn,
+                         int bundlestate); /* use BUNDLE_* defines */
 
 
 /*
 /*
  * Curl_multi_closed()
  * Curl_multi_closed()
@@ -89,7 +80,7 @@ void Curl_multi_connchanged(struct Curl_multi *multi);
  * socket again and it gets the same file descriptor number.
  * socket again and it gets the same file descriptor number.
  */
  */
 
 
-void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);
+void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s);
 
 
 /*
 /*
  * Add a handle and move it into PERFORM state at once. For pushed streams.
  * Add a handle and move it into PERFORM state at once. For pushed streams.
@@ -97,4 +88,12 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s);
 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
 CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
                                  struct Curl_easy *data,
                                  struct Curl_easy *data,
                                  struct connectdata *conn);
                                  struct connectdata *conn);
+
+CURLMcode Curl_multi_wait(struct Curl_multi *multi,
+                          struct curl_waitfd extra_fds[],
+                          unsigned int extra_nfds,
+                          int timeout_ms,
+                          int *ret,
+                          bool *gotsocket); /* if any socket was checked */
+
 #endif /* HEADER_CURL_MULTIIF_H */
 #endif /* HEADER_CURL_MULTIIF_H */

+ 13 - 3
Utilities/cmcurl/lib/netrc.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -21,6 +21,7 @@
  ***************************************************************************/
  ***************************************************************************/
 
 
 #include "curl_setup.h"
 #include "curl_setup.h"
+#ifndef CURL_DISABLE_NETRC
 
 
 #ifdef HAVE_PWD_H
 #ifdef HAVE_PWD_H
 #include <pwd.h>
 #include <pwd.h>
@@ -53,6 +54,8 @@ enum host_lookup_state {
 int Curl_parsenetrc(const char *host,
 int Curl_parsenetrc(const char *host,
                     char **loginp,
                     char **loginp,
                     char **passwordp,
                     char **passwordp,
+                    bool *login_changed,
+                    bool *password_changed,
                     char *netrcfile)
                     char *netrcfile)
 {
 {
   FILE *file;
   FILE *file;
@@ -164,7 +167,7 @@ int Curl_parsenetrc(const char *host,
             if(specific_login) {
             if(specific_login) {
               state_our_login = strcasecompare(login, tok);
               state_our_login = strcasecompare(login, tok);
             }
             }
-            else {
+            else if(!login || strcmp(login, tok)) {
               if(login_alloc) {
               if(login_alloc) {
                 free(login);
                 free(login);
                 login_alloc = FALSE;
                 login_alloc = FALSE;
@@ -179,7 +182,8 @@ int Curl_parsenetrc(const char *host,
             state_login = 0;
             state_login = 0;
           }
           }
           else if(state_password) {
           else if(state_password) {
-            if(state_our_login || !specific_login) {
+            if((state_our_login || !specific_login)
+                && (!password || strcmp(password, tok))) {
               if(password_alloc) {
               if(password_alloc) {
                 free(password);
                 free(password);
                 password_alloc = FALSE;
                 password_alloc = FALSE;
@@ -211,15 +215,19 @@ int Curl_parsenetrc(const char *host,
 
 
     out:
     out:
     if(!retcode) {
     if(!retcode) {
+      *login_changed = FALSE;
+      *password_changed = FALSE;
       if(login_alloc) {
       if(login_alloc) {
         if(*loginp)
         if(*loginp)
           free(*loginp);
           free(*loginp);
         *loginp = login;
         *loginp = login;
+        *login_changed = TRUE;
       }
       }
       if(password_alloc) {
       if(password_alloc) {
         if(*passwordp)
         if(*passwordp)
           free(*passwordp);
           free(*passwordp);
         *passwordp = password;
         *passwordp = password;
+        *password_changed = TRUE;
       }
       }
     }
     }
     else {
     else {
@@ -233,3 +241,5 @@ int Curl_parsenetrc(const char *host,
 
 
   return retcode;
   return retcode;
 }
 }
+
+#endif

+ 10 - 1
Utilities/cmcurl/lib/netrc.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -22,15 +22,24 @@
  *
  *
  ***************************************************************************/
  ***************************************************************************/
 
 
+#include "curl_setup.h"
+#ifndef CURL_DISABLE_NETRC
+
 /* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
 /* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */
 int Curl_parsenetrc(const char *host,
 int Curl_parsenetrc(const char *host,
                     char **loginp,
                     char **loginp,
                     char **passwordp,
                     char **passwordp,
+                    bool *login_changed,
+                    bool *password_changed,
                     char *filename);
                     char *filename);
   /* Assume: (*passwordp)[0]=0, host[0] != 0.
   /* Assume: (*passwordp)[0]=0, host[0] != 0.
    * If (*loginp)[0] = 0, search for login and password within a machine
    * If (*loginp)[0] = 0, search for login and password within a machine
    * section in the netrc.
    * section in the netrc.
    * If (*loginp)[0] != 0, search for password within machine and login.
    * If (*loginp)[0] != 0, search for password within machine and login.
    */
    */
+#else
+/* disabled */
+#define Curl_parsenetrc(a,b,c,d,e,f) 1
+#endif
 
 
 #endif /* HEADER_CURL_NETRC_H */
 #endif /* HEADER_CURL_NETRC_H */

+ 2 - 2
Utilities/cmcurl/lib/non-ascii.c

@@ -78,7 +78,7 @@ CURLcode Curl_convert_clone(struct Curl_easy *data,
 
 
 /*
 /*
  * Curl_convert_to_network() is an internal function for performing ASCII
  * Curl_convert_to_network() is an internal function for performing ASCII
- * conversions on non-ASCII platforms. It convers the buffer _in place_.
+ * conversions on non-ASCII platforms. It converts the buffer _in place_.
  */
  */
 CURLcode Curl_convert_to_network(struct Curl_easy *data,
 CURLcode Curl_convert_to_network(struct Curl_easy *data,
                                  char *buffer, size_t length)
                                  char *buffer, size_t length)
@@ -144,7 +144,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
 
 
 /*
 /*
  * Curl_convert_from_network() is an internal function for performing ASCII
  * Curl_convert_from_network() is an internal function for performing ASCII
- * conversions on non-ASCII platforms. It convers the buffer _in place_.
+ * conversions on non-ASCII platforms. It converts the buffer _in place_.
  */
  */
 CURLcode Curl_convert_from_network(struct Curl_easy *data,
 CURLcode Curl_convert_from_network(struct Curl_easy *data,
                                    char *buffer, size_t length)
                                    char *buffer, size_t length)

+ 4 - 9
Utilities/cmcurl/lib/openldap.c

@@ -6,7 +6,7 @@
  *                 \___|\___/|_| \_\_____|
  *                 \___|\___/|_| \_\_____|
  *
  *
  * Copyright (C) 2010, Howard Chu, <[email protected]>
  * Copyright (C) 2010, Howard Chu, <[email protected]>
- * Copyright (C) 2011 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2011 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -196,9 +196,6 @@ static CURLcode ldap_setup_connection(struct connectdata *conn)
   li->proto = proto;
   li->proto = proto;
   conn->proto.generic = li;
   conn->proto.generic = li;
   connkeep(conn, "OpenLDAP default");
   connkeep(conn, "OpenLDAP default");
-  /* TODO:
-   * - provide option to choose SASL Binds instead of Simple
-   */
   return CURLE_OK;
   return CURLE_OK;
 }
 }
 
 
@@ -220,8 +217,8 @@ static CURLcode ldap_connect(struct connectdata *conn, bool *done)
   ptr = hosturl + 4;
   ptr = hosturl + 4;
   if(conn->handler->flags & PROTOPT_SSL)
   if(conn->handler->flags & PROTOPT_SSL)
     *ptr++ = 's';
     *ptr++ = 's';
-  snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
-           conn->host.name, conn->remote_port);
+  msnprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
+            conn->host.name, conn->remote_port);
 
 
 #ifdef CURL_OPENLDAP_DEBUG
 #ifdef CURL_OPENLDAP_DEBUG
   static int do_trace = 0;
   static int do_trace = 0;
@@ -414,7 +411,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;
   lr->msgid = msgid;
   lr->msgid = msgid;
   data->req.protop = lr;
   data->req.protop = lr;
-  Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
+  Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
   *done = TRUE;
   *done = TRUE;
   return CURLE_OK;
   return CURLE_OK;
 }
 }
@@ -510,8 +507,6 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
     lr->nument++;
     lr->nument++;
     rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv);
     rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv);
     if(rc < 0) {
     if(rc < 0) {
-      /* TODO: verify that this is really how this return code should be
-         handled */
       *err = CURLE_RECV_ERROR;
       *err = CURLE_RECV_ERROR;
       return -1;
       return -1;
     }
     }

+ 26 - 15
Utilities/cmcurl/lib/parsedate.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
  *
  *
  * This software is licensed as described in the file COPYING, which
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
  * you should have received as part of this distribution. The terms
@@ -82,20 +82,6 @@
 #include "warnless.h"
 #include "warnless.h"
 #include "parsedate.h"
 #include "parsedate.h"
 
 
-const char * const Curl_wkday[] =
-{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
-static const char * const weekday[] =
-{ "Monday", "Tuesday", "Wednesday", "Thursday",
-  "Friday", "Saturday", "Sunday" };
-const char * const Curl_month[]=
-{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
-struct tzinfo {
-  char name[5];
-  int offset; /* +/- in minutes */
-};
-
 /*
 /*
  * parsedate()
  * parsedate()
  *
  *
@@ -114,6 +100,22 @@ static int parsedate(const char *date, time_t *output);
 #define PARSEDATE_LATER  1
 #define PARSEDATE_LATER  1
 #define PARSEDATE_SOONER 2
 #define PARSEDATE_SOONER 2
 
 
+#ifndef CURL_DISABLE_PARSEDATE
+
+const char * const Curl_wkday[] =
+{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
+static const char * const weekday[] =
+{ "Monday", "Tuesday", "Wednesday", "Thursday",
+  "Friday", "Saturday", "Sunday" };
+const char * const Curl_month[]=
+{ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+struct tzinfo {
+  char name[5];
+  int offset; /* +/- in minutes */
+};
+
 /* Here's a bunch of frequently used time zone names. These were supported
 /* Here's a bunch of frequently used time zone names. These were supported
    by the old getdate parser. */
    by the old getdate parser. */
 #define tDAYZONE -60       /* offset for daylight savings time */
 #define tDAYZONE -60       /* offset for daylight savings time */
@@ -555,6 +557,15 @@ static int parsedate(const char *date, time_t *output)
 
 
   return PARSEDATE_OK;
   return PARSEDATE_OK;
 }
 }
+#else
+/* disabled */
+static int parsedate(const char *date, time_t *output)
+{
+  (void)date;
+  *output = 0;
+  return PARSEDATE_OK; /* a lie */
+}
+#endif
 
 
 time_t curl_getdate(const char *p, const time_t *now)
 time_t curl_getdate(const char *p, const time_t *now)
 {
 {

Някои файлове не бяха показани, защото твърде много файлове са промени