Просмотр исходного кода

Merge branch 'upstream-curl' into update-curl

* upstream-curl:
  curl 2020-06-23 (e9db32a0)
Brad King 5 лет назад
Родитель
Сommit
0ef8fa5000
100 измененных файлов с 3074 добавлено и 1823 удалено
  1. 21 0
      Utilities/cmcurl/CMake/CMakeConfigurableFile.in
  2. 21 0
      Utilities/cmcurl/CMake/CurlSymbolHiding.cmake
  3. 21 0
      Utilities/cmcurl/CMake/FindBearSSL.cmake
  4. 21 0
      Utilities/cmcurl/CMake/FindBrotli.cmake
  5. 21 0
      Utilities/cmcurl/CMake/FindCARES.cmake
  6. 21 0
      Utilities/cmcurl/CMake/FindGSS.cmake
  7. 21 0
      Utilities/cmcurl/CMake/FindLibSSH2.cmake
  8. 21 0
      Utilities/cmcurl/CMake/FindMbedTLS.cmake
  9. 21 0
      Utilities/cmcurl/CMake/FindNGHTTP2.cmake
  10. 76 0
      Utilities/cmcurl/CMake/FindNGHTTP3.cmake
  11. 113 0
      Utilities/cmcurl/CMake/FindNGTCP2.cmake
  12. 21 0
      Utilities/cmcurl/CMake/FindNSS.cmake
  13. 68 0
      Utilities/cmcurl/CMake/FindQUICHE.cmake
  14. 34 0
      Utilities/cmcurl/CMake/FindWolfSSL.cmake
  15. 21 0
      Utilities/cmcurl/CMake/Macros.cmake
  16. 27 0
      Utilities/cmcurl/CMake/OtherTests.cmake
  17. 21 0
      Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake
  18. 21 0
      Utilities/cmcurl/CMake/Utilities.cmake
  19. 21 0
      Utilities/cmcurl/CMake/cmake_uninstall.cmake.in
  20. 21 0
      Utilities/cmcurl/CMake/curl-config.cmake.in
  21. 119 21
      Utilities/cmcurl/CMakeLists.txt
  22. 40 10
      Utilities/cmcurl/include/curl/curl.h
  23. 4 4
      Utilities/cmcurl/include/curl/curlver.h
  24. 12 1
      Utilities/cmcurl/include/curl/easy.h
  25. 2 4
      Utilities/cmcurl/include/curl/multi.h
  26. 5 4
      Utilities/cmcurl/include/curl/typecheck-gcc.h
  27. 27 1
      Utilities/cmcurl/lib/CMakeLists.txt
  28. 50 55
      Utilities/cmcurl/lib/Makefile.inc
  29. 10 9
      Utilities/cmcurl/lib/altsvc.c
  30. 0 1
      Utilities/cmcurl/lib/altsvc.h
  31. 30 27
      Utilities/cmcurl/lib/asyn-ares.c
  32. 25 18
      Utilities/cmcurl/lib/asyn-thread.c
  33. 5 5
      Utilities/cmcurl/lib/asyn.h
  34. 51 49
      Utilities/cmcurl/lib/conncache.c
  35. 4 5
      Utilities/cmcurl/lib/conncache.h
  36. 153 144
      Utilities/cmcurl/lib/connect.c
  37. 2 2
      Utilities/cmcurl/lib/connect.h
  38. 66 64
      Utilities/cmcurl/lib/content_encoding.c
  39. 13 13
      Utilities/cmcurl/lib/content_encoding.h
  40. 9 10
      Utilities/cmcurl/lib/cookie.c
  41. 37 66
      Utilities/cmcurl/lib/curl_addrinfo.c
  42. 9 10
      Utilities/cmcurl/lib/curl_addrinfo.h
  43. 48 3
      Utilities/cmcurl/lib/curl_config.h.cmake
  44. 13 15
      Utilities/cmcurl/lib/curl_hmac.h
  45. 10 10
      Utilities/cmcurl/lib/curl_md5.h
  46. 84 15
      Utilities/cmcurl/lib/curl_multibyte.c
  47. 21 28
      Utilities/cmcurl/lib/curl_multibyte.h
  48. 11 8
      Utilities/cmcurl/lib/curl_ntlm_core.c
  49. 5 1
      Utilities/cmcurl/lib/curl_ntlm_core.h
  50. 29 38
      Utilities/cmcurl/lib/curl_ntlm_wb.c
  51. 14 4
      Utilities/cmcurl/lib/curl_sasl.c
  52. 25 58
      Utilities/cmcurl/lib/curl_setup.h
  53. 3 1
      Utilities/cmcurl/lib/curl_setup_once.h
  54. 8 8
      Utilities/cmcurl/lib/curl_sspi.c
  55. 2 2
      Utilities/cmcurl/lib/curl_threads.c
  56. 11 1
      Utilities/cmcurl/lib/curlx.h
  57. 3 1
      Utilities/cmcurl/lib/dict.c
  58. 61 96
      Utilities/cmcurl/lib/doh.c
  59. 10 15
      Utilities/cmcurl/lib/doh.h
  60. 227 0
      Utilities/cmcurl/lib/dynbuf.c
  61. 63 0
      Utilities/cmcurl/lib/dynbuf.h
  62. 74 38
      Utilities/cmcurl/lib/easy.c
  63. 1 1
      Utilities/cmcurl/lib/easyif.h
  64. 23 33
      Utilities/cmcurl/lib/escape.c
  65. 2 4
      Utilities/cmcurl/lib/file.c
  66. 12 16
      Utilities/cmcurl/lib/formdata.c
  67. 3 3
      Utilities/cmcurl/lib/formdata.h
  68. 40 24
      Utilities/cmcurl/lib/ftp.c
  69. 0 1
      Utilities/cmcurl/lib/ftp.h
  70. 81 7
      Utilities/cmcurl/lib/getinfo.c
  71. 18 5
      Utilities/cmcurl/lib/gopher.c
  72. 9 8
      Utilities/cmcurl/lib/hmac.c
  73. 5 5
      Utilities/cmcurl/lib/hostasyn.c
  74. 59 41
      Utilities/cmcurl/lib/hostip.c
  75. 11 11
      Utilities/cmcurl/lib/hostip.h
  76. 8 8
      Utilities/cmcurl/lib/hostip4.c
  77. 9 13
      Utilities/cmcurl/lib/hostip6.c
  78. 201 277
      Utilities/cmcurl/lib/http.c
  79. 13 35
      Utilities/cmcurl/lib/http.h
  80. 78 105
      Utilities/cmcurl/lib/http2.c
  81. 1 1
      Utilities/cmcurl/lib/http2.h
  82. 17 32
      Utilities/cmcurl/lib/http_chunks.c
  83. 7 3
      Utilities/cmcurl/lib/http_digest.c
  84. 1 1
      Utilities/cmcurl/lib/http_digest.h
  85. 12 7
      Utilities/cmcurl/lib/http_negotiate.c
  86. 4 2
      Utilities/cmcurl/lib/http_negotiate.h
  87. 10 4
      Utilities/cmcurl/lib/http_ntlm.c
  88. 4 2
      Utilities/cmcurl/lib/http_ntlm.h
  89. 79 94
      Utilities/cmcurl/lib/http_proxy.c
  90. 2 1
      Utilities/cmcurl/lib/http_proxy.h
  91. 5 5
      Utilities/cmcurl/lib/idn_win32.c
  92. 6 6
      Utilities/cmcurl/lib/if2ip.c
  93. 3 3
      Utilities/cmcurl/lib/imap.c
  94. 30 30
      Utilities/cmcurl/lib/ldap.c
  95. 14 7
      Utilities/cmcurl/lib/md4.c
  96. 14 12
      Utilities/cmcurl/lib/md5.c
  97. 2 2
      Utilities/cmcurl/lib/memdebug.c
  98. 213 65
      Utilities/cmcurl/lib/mime.c
  99. 27 21
      Utilities/cmcurl/lib/mime.h
  100. 22 63
      Utilities/cmcurl/lib/mprintf.c

+ 21 - 0
Utilities/cmcurl/CMake/CMakeConfigurableFile.in

@@ -1 +1,22 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
 @CMAKE_CONFIGURABLE_FILE_CONTENT@
 @CMAKE_CONFIGURABLE_FILE_CONTENT@

+ 21 - 0
Utilities/cmcurl/CMake/CurlSymbolHiding.cmake

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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(CheckCSourceCompiles)
 include(CheckCSourceCompiles)
 
 
 option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON)
 option(CURL_HIDDEN_SYMBOLS "Set to ON to hide libcurl internal symbols (=hide all symbols that aren't officially external)." ON)

+ 21 - 0
Utilities/cmcurl/CMake/FindBearSSL.cmake

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
 find_path(BEARSSL_INCLUDE_DIRS bearssl.h)
 find_path(BEARSSL_INCLUDE_DIRS bearssl.h)
 
 
 find_library(BEARSSL_LIBRARY bearssl)
 find_library(BEARSSL_LIBRARY bearssl)

+ 21 - 0
Utilities/cmcurl/CMake/FindBrotli.cmake

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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(FindPackageHandleStandardArgs)
 include(FindPackageHandleStandardArgs)
 
 
 find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")
 find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")

+ 21 - 0
Utilities/cmcurl/CMake/FindCARES.cmake

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
 # - Find c-ares
 # - Find c-ares
 # Find the c-ares includes and library
 # Find the c-ares includes and library
 # This module defines
 # This module defines

+ 21 - 0
Utilities/cmcurl/CMake/FindGSS.cmake

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
 # - Try to find the GSS Kerberos library
 # - Try to find the GSS Kerberos library
 # Once done this will define
 # Once done this will define
 #
 #

+ 21 - 0
Utilities/cmcurl/CMake/FindLibSSH2.cmake

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
 # - Try to find the libssh2 library
 # - Try to find the libssh2 library
 # Once done this will define
 # Once done this will define
 #
 #

+ 21 - 0
Utilities/cmcurl/CMake/FindMbedTLS.cmake

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
 find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h)
 find_path(MBEDTLS_INCLUDE_DIRS mbedtls/ssl.h)
 
 
 find_library(MBEDTLS_LIBRARY mbedtls)
 find_library(MBEDTLS_LIBRARY mbedtls)

+ 21 - 0
Utilities/cmcurl/CMake/FindNGHTTP2.cmake

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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(FindPackageHandleStandardArgs)
 include(FindPackageHandleStandardArgs)
 
 
 find_path(NGHTTP2_INCLUDE_DIR "nghttp2/nghttp2.h")
 find_path(NGHTTP2_INCLUDE_DIR "nghttp2/nghttp2.h")

+ 76 - 0
Utilities/cmcurl/CMake/FindNGHTTP3.cmake

@@ -0,0 +1,76 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
+
+#[=======================================================================[.rst:
+FindNGHTTP3
+----------
+
+Find the nghttp3 library
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+``NGHTTP3_FOUND``
+  System has nghttp3
+``NGHTTP3_INCLUDE_DIRS``
+  The nghttp3 include directories.
+``NGHTTP3_LIBRARIES``
+  The libraries needed to use nghttp3
+``NGHTTP3_VERSION``
+  version of nghttp3.
+#]=======================================================================]
+
+if(UNIX)
+  find_package(PkgConfig QUIET)
+  pkg_search_module(PC_NGHTTP3 libnghttp3)
+endif()
+
+find_path(NGHTTP3_INCLUDE_DIR nghttp3/nghttp3.h
+  HINTS
+    ${PC_NGHTTP3_INCLUDEDIR}
+    ${PC_NGHTTP3_INCLUDE_DIRS}
+)
+
+find_library(NGHTTP3_LIBRARY NAMES nghttp3
+  HINTS
+    ${PC_NGHTTP3_LIBDIR}
+    ${PC_NGHTTP3_LIBRARY_DIRS}
+)
+
+if(PC_NGHTTP3_VERSION)
+  set(NGHTTP3_VERSION ${PC_NGHTTP3_VERSION})
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(NGHTTP3
+  REQUIRED_VARS
+    NGHTTP3_LIBRARY
+    NGHTTP3_INCLUDE_DIR
+  VERSION_VAR NGHTTP3_VERSION
+)
+
+if(NGHTTP3_FOUND)
+  set(NGHTTP3_LIBRARIES    ${NGHTTP3_LIBRARY})
+  set(NGHTTP3_INCLUDE_DIRS ${NGHTTP3_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(NGHTTP3_INCLUDE_DIRS NGHTTP3_LIBRARIES)

+ 113 - 0
Utilities/cmcurl/CMake/FindNGTCP2.cmake

@@ -0,0 +1,113 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
+
+#[=======================================================================[.rst:
+FindNGTCP2
+----------
+
+Find the ngtcp2 library
+
+This module accepts optional COMPONENTS to control the crypto library (these are
+mutually exclusive)::
+
+  OpenSSL:  Use libngtcp2_crypto_openssl
+  GnuTLS:   Use libngtcp2_crypto_gnutls
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+``NGTCP2_FOUND``
+  System has ngtcp2
+``NGTCP2_INCLUDE_DIRS``
+  The ngtcp2 include directories.
+``NGTCP2_LIBRARIES``
+  The libraries needed to use ngtcp2
+``NGTCP2_VERSION``
+  version of ngtcp2.
+#]=======================================================================]
+
+if(UNIX)
+  find_package(PkgConfig QUIET)
+  pkg_search_module(PC_NGTCP2 libngtcp2)
+endif()
+
+find_path(NGTCP2_INCLUDE_DIR ngtcp2/ngtcp2.h
+  HINTS
+    ${PC_NGTCP2_INCLUDEDIR}
+    ${PC_NGTCP2_INCLUDE_DIRS}
+)
+
+find_library(NGTCP2_LIBRARY NAMES ngtcp2
+  HINTS
+    ${PC_NGTCP2_LIBDIR}
+    ${PC_NGTCP2_LIBRARY_DIRS}
+)
+
+if(PC_NGTCP2_VERSION)
+  set(NGTCP2_VERSION ${PC_NGTCP2_VERSION})
+endif()
+
+if(NGTCP2_FIND_COMPONENTS)
+  set(NGTCP2_CRYPTO_BACKEND "")
+  foreach(component IN LISTS NGTCP2_FIND_COMPONENTS)
+    if(component MATCHES "^(OpenSSL|GnuTLS)")
+      if(NGTCP2_CRYPTO_BACKEND)
+        message(FATAL_ERROR "NGTCP2: Only one crypto library can be selected")
+      endif()
+      set(NGTCP2_CRYPTO_BACKEND ${component})
+    endif()
+  endforeach()
+
+  if(NGTCP2_CRYPTO_BACKEND)
+    string(TOLOWER "ngtcp2_crypto_${NGTCP2_CRYPTO_BACKEND}" _crypto_library)
+    if(UNIX)
+      pkg_search_module(PC_${_crypto_library} lib${_crypto_library})
+    endif()
+    find_library(${_crypto_library}_LIBRARY
+      NAMES
+        ${_crypto_library}
+      HINTS
+        ${PC_${_crypto_library}_LIBDIR}
+        ${PC_${_crypto_library}_LIBRARY_DIRS}
+    )
+    if(${_crypto_library}_LIBRARY)
+      set(NGTCP2_${NGTCP2_CRYPTO_BACKEND}_FOUND TRUE)
+      set(NGTCP2_CRYPTO_LIBRARY ${${_crypto_library}_LIBRARY})
+    endif()
+  endif()
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(NGTCP2
+  REQUIRED_VARS
+    NGTCP2_LIBRARY
+    NGTCP2_INCLUDE_DIR
+  VERSION_VAR NGTCP2_VERSION
+  HANDLE_COMPONENTS
+)
+
+if(NGTCP2_FOUND)
+  set(NGTCP2_LIBRARIES    ${NGTCP2_LIBRARY} ${NGTCP2_CRYPTO_LIBRARY})
+  set(NGTCP2_INCLUDE_DIRS ${NGTCP2_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(NGTCP2_INCLUDE_DIRS NGTCP2_LIBRARIES)

+ 21 - 0
Utilities/cmcurl/CMake/FindNSS.cmake

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
 if(UNIX)
 if(UNIX)
   find_package(PkgConfig QUIET)
   find_package(PkgConfig QUIET)
   pkg_search_module(PC_NSS nss)
   pkg_search_module(PC_NSS nss)

+ 68 - 0
Utilities/cmcurl/CMake/FindQUICHE.cmake

@@ -0,0 +1,68 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
+
+#[=======================================================================[.rst:
+FindQUICHE
+----------
+
+Find the quiche library
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+``QUICHE_FOUND``
+  System has quiche
+``QUICHE_INCLUDE_DIRS``
+  The quiche include directories.
+``QUICHE_LIBRARIES``
+  The libraries needed to use quiche
+#]=======================================================================]
+if(UNIX)
+  find_package(PkgConfig QUIET)
+  pkg_search_module(PC_QUICHE quiche)
+endif()
+
+find_path(QUICHE_INCLUDE_DIR quiche.h
+  HINTS
+    ${PC_QUICHE_INCLUDEDIR}
+    ${PC_QUICHE_INCLUDE_DIRS}
+)
+
+find_library(QUICHE_LIBRARY NAMES quiche
+  HINTS
+    ${PC_QUICHE_LIBDIR}
+    ${PC_QUICHE_LIBRARY_DIRS}
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(QUICHE
+  REQUIRED_VARS
+    QUICHE_LIBRARY
+    QUICHE_INCLUDE_DIR
+)
+
+if(QUICHE_FOUND)
+  set(QUICHE_LIBRARIES    ${QUICHE_LIBRARY})
+  set(QUICHE_INCLUDE_DIRS ${QUICHE_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(QUICHE_INCLUDE_DIRS QUICHE_LIBRARIES)

+ 34 - 0
Utilities/cmcurl/CMake/FindWolfSSL.cmake

@@ -0,0 +1,34 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
+find_path(WolfSSL_INCLUDE_DIR NAMES wolfssl/ssl.h)
+find_library(WolfSSL_LIBRARY NAMES wolfssl)
+mark_as_advanced(WolfSSL_INCLUDE_DIR WolfSSL_LIBRARY)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(WolfSSL
+  REQUIRED_VARS WolfSSL_INCLUDE_DIR WolfSSL_LIBRARY
+  )
+
+if(WolfSSL_FOUND)
+  set(WolfSSL_INCLUDE_DIRS ${WolfSSL_INCLUDE_DIR})
+  set(WolfSSL_LIBRARIES ${WolfSSL_LIBRARY})
+endif()

+ 21 - 0
Utilities/cmcurl/CMake/Macros.cmake

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
 #File defines convenience macros for available feature testing
 #File defines convenience macros for available feature testing
 
 
 # This macro checks if the symbol exists in the library and if it
 # This macro checks if the symbol exists in the library and if it

+ 27 - 0
Utilities/cmcurl/CMake/OtherTests.cmake

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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(CheckCSourceCompiles)
 include(CheckCSourceCompiles)
 # The begin of the sources (macros and includes)
 # The begin of the sources (macros and includes)
 set(_source_epilogue "#undef inline")
 set(_source_epilogue "#undef inline")
@@ -49,6 +70,9 @@ if(curl_cv_recv)
                 unset(curl_cv_func_recv_test CACHE)
                 unset(curl_cv_func_recv_test CACHE)
                 check_c_source_compiles("
                 check_c_source_compiles("
                   ${_source_epilogue}
                   ${_source_epilogue}
+                  #ifdef WINSOCK_API_LINKAGE
+                  WINSOCK_API_LINKAGE
+                  #endif
                   extern ${recv_retv} ${signature_call_conv}
                   extern ${recv_retv} ${signature_call_conv}
                   recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4});
                   recv(${recv_arg1}, ${recv_arg2}, ${recv_arg3}, ${recv_arg4});
                   int main(void) {
                   int main(void) {
@@ -122,6 +146,9 @@ if(curl_cv_send)
                 unset(curl_cv_func_send_test CACHE)
                 unset(curl_cv_func_send_test CACHE)
                 check_c_source_compiles("
                 check_c_source_compiles("
                   ${_source_epilogue}
                   ${_source_epilogue}
+                  #ifdef WINSOCK_API_LINKAGE
+                  WINSOCK_API_LINKAGE
+                  #endif
                   extern ${send_retv} ${signature_call_conv}
                   extern ${send_retv} ${signature_call_conv}
                   send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4});
                   send(${send_arg1}, ${send_arg2}, ${send_arg3}, ${send_arg4});
                   int main(void) {
                   int main(void) {

+ 21 - 0
Utilities/cmcurl/CMake/Platforms/WindowsCache.cmake

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
 if(NOT UNIX)
 if(NOT UNIX)
   if(WIN32)
   if(WIN32)
     set(HAVE_LIBDL 0)
     set(HAVE_LIBDL 0)

+ 21 - 0
Utilities/cmcurl/CMake/Utilities.cmake

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
 # File containing various utilities
 # File containing various utilities
 
 
 # Returns a list of arguments that evaluate to true
 # Returns a list of arguments that evaluate to true

+ 21 - 0
Utilities/cmcurl/CMake/cmake_uninstall.cmake.in

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
 if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
 if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
   message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
   message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
 endif()
 endif()

+ 21 - 0
Utilities/cmcurl/CMake/curl-config.cmake.in

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
 @PACKAGE_INIT@
 @PACKAGE_INIT@
 
 
 include(CMakeFindDependencyMacro)
 include(CMakeFindDependencyMacro)

+ 119 - 21
Utilities/cmcurl/CMakeLists.txt

@@ -118,7 +118,6 @@ endif()
 # The output .so file lacks the soname number which we currently have within the lib/Makefile.am file
 # The output .so file lacks the soname number which we currently have within the lib/Makefile.am file
 # Add full (4 or 5 libs) SSL support
 # Add full (4 or 5 libs) SSL support
 # Add INSTALL target (EXTRA_DIST variables in Makefile.am may be moved to Makefile.inc so that CMake/CPack is aware of what's to include).
 # Add INSTALL target (EXTRA_DIST variables in Makefile.am may be moved to Makefile.inc so that CMake/CPack is aware of what's to include).
-# Add CTests(?)
 # Check on all possible platforms
 # Check on all possible platforms
 # Test with as many configurations possible (With or without any option)
 # Test with as many configurations possible (With or without any option)
 # Create scripts that help keeping the CMake build system up to date (to reduce maintenance). According to Tetetest:
 # Create scripts that help keeping the CMake build system up to date (to reduce maintenance). According to Tetetest:
@@ -274,6 +273,8 @@ option(CURL_DISABLE_SMTP "to disable SMTP" OFF)
 mark_as_advanced(CURL_DISABLE_SMTP)
 mark_as_advanced(CURL_DISABLE_SMTP)
 option(CURL_DISABLE_GOPHER "to disable Gopher" OFF)
 option(CURL_DISABLE_GOPHER "to disable Gopher" OFF)
 mark_as_advanced(CURL_DISABLE_GOPHER)
 mark_as_advanced(CURL_DISABLE_GOPHER)
+option(CURL_ENABLE_MQTT "to enable MQTT" OFF)
+mark_as_advanced(CURL_ENABLE_MQTT)
 
 
 if(HTTP_ONLY)
 if(HTTP_ONLY)
   set(CURL_DISABLE_FTP ON)
   set(CURL_DISABLE_FTP ON)
@@ -323,10 +324,6 @@ cmake_dependent_option(ENABLE_MANUAL "to provide the built-in manual"
     ON "NROFF_USEFUL;PERL_FOUND"
     ON "NROFF_USEFUL;PERL_FOUND"
     OFF)
     OFF)
 
 
-if(NOT PERL_FOUND)
-  message(STATUS "Perl not found, testing disabled.")
-  set(BUILD_TESTING OFF)
-endif()
 if(ENABLE_MANUAL)
 if(ENABLE_MANUAL)
   set(USE_MANUAL ON)
   set(USE_MANUAL ON)
 endif()
 endif()
@@ -337,6 +334,7 @@ set(CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS}")
 set(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS})
 set(CMAKE_REQUIRED_FLAGS ${CMAKE_ANSI_CFLAGS})
 
 
 if(CURL_STATIC_CRT)
 if(CURL_STATIC_CRT)
+  set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
   set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
   set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
   set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
   set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
 endif()
 endif()
@@ -411,7 +409,7 @@ if(WIN32)
 endif()
 endif()
 
 
 # check SSL libraries
 # check SSL libraries
-# TODO support GnuTLS and WolfSSL
+# TODO support GnuTLS
 
 
 if(APPLE)
 if(APPLE)
   option(CMAKE_USE_SECTRANSP "enable Apple OS native SSL/TLS" OFF)
   option(CMAKE_USE_SECTRANSP "enable Apple OS native SSL/TLS" OFF)
@@ -424,9 +422,10 @@ endif()
 option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF)
 option(CMAKE_USE_MBEDTLS "Enable mbedTLS for SSL/TLS" OFF)
 option(CMAKE_USE_BEARSSL "Enable BearSSL for SSL/TLS" OFF)
 option(CMAKE_USE_BEARSSL "Enable BearSSL for SSL/TLS" OFF)
 option(CMAKE_USE_NSS "Enable NSS for SSL/TLS" OFF)
 option(CMAKE_USE_NSS "Enable NSS for SSL/TLS" OFF)
+option(CMAKE_USE_WOLFSSL "enable wolfSSL for SSL/TLS" OFF)
 
 
 set(openssl_default ON)
 set(openssl_default ON)
-if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS OR CMAKE_USE_NSS)
+if(WIN32 OR CMAKE_USE_SECTRANSP OR CMAKE_USE_WINSSL OR CMAKE_USE_MBEDTLS OR CMAKE_USE_NSS OR CMAKE_USE_WOLFSSL)
   set(openssl_default OFF)
   set(openssl_default OFF)
 endif()
 endif()
 
 
@@ -437,6 +436,7 @@ count_true(enabled_ssl_options_count
   CMAKE_USE_MBEDTLS
   CMAKE_USE_MBEDTLS
   CMAKE_USE_BEARSSL
   CMAKE_USE_BEARSSL
   CMAKE_USE_NSS
   CMAKE_USE_NSS
+  CMAKE_USE_WOLFSSL
 )
 )
 if(enabled_ssl_options_count GREATER "1")
 if(enabled_ssl_options_count GREATER "1")
   set(CURL_WITH_MULTI_SSL ON)
   set(CURL_WITH_MULTI_SSL ON)
@@ -523,6 +523,14 @@ if(CMAKE_USE_BEARSSL)
   include_directories(${BEARSSL_INCLUDE_DIRS})
   include_directories(${BEARSSL_INCLUDE_DIRS})
 endif()
 endif()
 
 
+if(CMAKE_USE_WOLFSSL)
+  find_package(WolfSSL REQUIRED)
+  set(SSL_ENABLED ON)
+  set(USE_WOLFSSL ON)
+  list(APPEND CURL_LIBS ${WolfSSL_LIBRARIES})
+  include_directories(${WolfSSL_INCLUDE_DIRS})
+endif()
+
 if(CMAKE_USE_NSS)
 if(CMAKE_USE_NSS)
   find_package(NSS REQUIRED)
   find_package(NSS REQUIRED)
   include_directories(${NSS_INCLUDE_DIRS})
   include_directories(${NSS_INCLUDE_DIRS})
@@ -543,6 +551,56 @@ if(USE_NGHTTP2)
   list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES})
   list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES})
 endif()
 endif()
 
 
+function(CheckQuicSupportInOpenSSL)
+  # Be sure that the OpenSSL library actually supports QUIC.
+  cmake_push_check_state()
+  set(CMAKE_REQUIRED_INCLUDES   "${OPENSSL_INCLUDE_DIR}")
+  set(CMAKE_REQUIRED_LIBRARIES  "${OPENSSL_LIBRARIES}")
+  check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
+  if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD)
+    message(FATAL_ERROR "QUIC support is missing in OpenSSL/boringssl. Try setting -DOPENSSL_ROOT_DIR")
+  endif()
+  cmake_pop_check_state()
+endfunction()
+
+option(USE_NGTCP2 "Use ngtcp2 and nghttp3 libraries for HTTP/3 support" OFF)
+if(USE_NGTCP2)
+  if(USE_OPENSSL)
+    find_package(NGTCP2 REQUIRED OpenSSL)
+    CheckQuicSupportInOpenSSL()
+  elseif(USE_GNUTLS)
+    # TODO add GnuTLS support as vtls library.
+    find_package(NGTCP2 REQUIRED GnuTLS)
+  else()
+    message(FATAL_ERROR "ngtcp2 requires OpenSSL or GnuTLS")
+  endif()
+  set(USE_NGTCP2 ON)
+  include_directories(${NGTCP2_INCLUDE_DIRS})
+  list(APPEND CURL_LIBS ${NGTCP2_LIBRARIES})
+
+  find_package(NGHTTP3 REQUIRED)
+  set(USE_NGHTTP3 ON)
+  include_directories(${NGHTTP3_INCLUDE_DIRS})
+  list(APPEND CURL_LIBS ${NGHTTP3_LIBRARIES})
+endif()
+
+option(USE_QUICHE "Use quiche library for HTTP/3 support" OFF)
+if(USE_QUICHE)
+  if(USE_NGTCP2)
+    message(FATAL_ERROR "Only one HTTP/3 backend can be selected!")
+  endif()
+  find_package(QUICHE REQUIRED)
+  CheckQuicSupportInOpenSSL()
+  set(USE_QUICHE ON)
+  include_directories(${QUICHE_INCLUDE_DIRS})
+  list(APPEND CURL_LIBS ${QUICHE_LIBRARIES})
+  cmake_push_check_state()
+  set(CMAKE_REQUIRED_INCLUDES   "${QUICHE_INCLUDE_DIRS}")
+  set(CMAKE_REQUIRED_LIBRARIES  "${QUICHE_LIBRARIES}")
+  check_symbol_exists(quiche_conn_set_qlog_fd "quiche.h" HAVE_QUICHE_CONN_SET_QLOG_FD)
+  cmake_pop_check_state()
+endif()
+
 if(WIN32)
 if(WIN32)
   set(USE_WIN32_CRYPTO ON)
   set(USE_WIN32_CRYPTO ON)
 endif()
 endif()
@@ -744,6 +802,20 @@ if(CMAKE_USE_LIBSSH2)
   endif()
   endif()
 endif()
 endif()
 
 
+# libssh
+option(CMAKE_USE_LIBSSH "Use libSSH" OFF)
+mark_as_advanced(CMAKE_USE_LIBSSH)
+if(NOT HAVE_LIBSSH2 AND CMAKE_USE_LIBSSH)
+  find_package(libssh CONFIG)
+  if(libssh_FOUND)
+    message(STATUS "Found libssh ${libssh_VERSION}")
+    # Use imported target for include and library paths.
+    list(APPEND CURL_LIBS ssh)
+    set(USE_LIBSSH ON)
+    set(HAVE_LIBSSH_LIBSSH_H 1)
+  endif()
+endif()
+
 option(CMAKE_USE_GSSAPI "Use GSSAPI implementation (right now only Heimdal is supported with CMake build)" OFF)
 option(CMAKE_USE_GSSAPI "Use GSSAPI implementation (right now only Heimdal is supported with CMake build)" OFF)
 mark_as_advanced(CMAKE_USE_GSSAPI)
 mark_as_advanced(CMAKE_USE_GSSAPI)
 
 
@@ -812,6 +884,8 @@ else()
   unset(USE_UNIX_SOCKETS CACHE)
   unset(USE_UNIX_SOCKETS CACHE)
 endif()
 endif()
 
 
+option(ENABLE_ALT_SVC "Enable alt-svc support" OFF)
+set(USE_ALTSVC ${ENABLE_ALT_SVC})
 
 
 if(0) # This code not needed for building within CMake.
 if(0) # This code not needed for building within CMake.
 #
 #
@@ -882,7 +956,7 @@ elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT)
 endif()
 endif()
 
 
 if(CURL_CA_PATH_SET AND NOT USE_OPENSSL AND NOT USE_MBEDTLS)
 if(CURL_CA_PATH_SET AND NOT USE_OPENSSL AND NOT USE_MBEDTLS)
-  message(FATAL_ERROR
+  message(STATUS
           "CA path only supported by OpenSSL, GnuTLS or mbed TLS. "
           "CA path only supported by OpenSSL, GnuTLS or mbed TLS. "
           "Set CURL_CA_PATH=none or enable one of those TLS backends.")
           "Set CURL_CA_PATH=none or enable one of those TLS backends.")
 endif()
 endif()
@@ -926,7 +1000,6 @@ check_include_file_concat("arpa/inet.h"      HAVE_ARPA_INET_H)
 check_include_file_concat("arpa/tftp.h"      HAVE_ARPA_TFTP_H)
 check_include_file_concat("arpa/tftp.h"      HAVE_ARPA_TFTP_H)
 check_include_file_concat("assert.h"         HAVE_ASSERT_H)
 check_include_file_concat("assert.h"         HAVE_ASSERT_H)
 check_include_file_concat("crypto.h"         HAVE_CRYPTO_H)
 check_include_file_concat("crypto.h"         HAVE_CRYPTO_H)
-check_include_file_concat("des.h"            HAVE_DES_H)
 check_include_file_concat("err.h"            HAVE_ERR_H)
 check_include_file_concat("err.h"            HAVE_ERR_H)
 check_include_file_concat("errno.h"          HAVE_ERRNO_H)
 check_include_file_concat("errno.h"          HAVE_ERRNO_H)
 check_include_file_concat("fcntl.h"          HAVE_FCNTL_H)
 check_include_file_concat("fcntl.h"          HAVE_FCNTL_H)
@@ -1314,7 +1387,7 @@ function(transform_makefile_inc INPUT_FILE OUTPUT_FILE)
   string(REGEX REPLACE "\\$\\(([a-zA-Z_][a-zA-Z0-9_]*)\\)" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})    # Replace $() with ${}
   string(REGEX REPLACE "\\$\\(([a-zA-Z_][a-zA-Z0-9_]*)\\)" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})    # Replace $() with ${}
   string(REGEX REPLACE "@([a-zA-Z_][a-zA-Z0-9_]*)@" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})    # Replace @@ with ${}, even if that may not be read by CMake scripts.
   string(REGEX REPLACE "@([a-zA-Z_][a-zA-Z0-9_]*)@" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})    # Replace @@ with ${}, even if that may not be read by CMake scripts.
   file(WRITE ${OUTPUT_FILE} ${MAKEFILE_INC_TEXT})
   file(WRITE ${OUTPUT_FILE} ${MAKEFILE_INC_TEXT})
-
+  set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${INPUT_FILE}")
 endfunction()
 endfunction()
 
 
 if(0) # This code not needed for building within CMake.
 if(0) # This code not needed for building within CMake.
@@ -1350,8 +1423,10 @@ install(FILES COPYING DESTINATION ${CMAKE_DOC_DIR}/cmcurl)
 #-----------------------------------------------------------------------------
 #-----------------------------------------------------------------------------
 
 
 if(0) # This code not needed for building within CMake.
 if(0) # This code not needed for building within CMake.
-include(CTest)
-if(BUILD_TESTING)
+option(BUILD_TESTING "Build tests" "${PERL_FOUND}")
+if(NOT PERL_FOUND)
+  message(STATUS "Perl not found, testing disabled.")
+elseif(BUILD_TESTING)
   add_subdirectory(tests)
   add_subdirectory(tests)
 endif()
 endif()
 
 
@@ -1385,6 +1460,7 @@ _add_if("Largefile"     (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND
 # TODO SSP1 (WinSSL) check is missing
 # TODO SSP1 (WinSSL) check is missing
 _add_if("SSPI"          USE_WINDOWS_SSPI)
 _add_if("SSPI"          USE_WINDOWS_SSPI)
 _add_if("GSS-API"       HAVE_GSSAPI)
 _add_if("GSS-API"       HAVE_GSSAPI)
+_add_if("alt-svc"       ENABLE_ALT_SVC)
 # TODO SSP1 missing for SPNEGO
 # TODO SSP1 missing for SPNEGO
 _add_if("SPNEGO"        NOT CURL_DISABLE_CRYPTO_AUTH AND
 _add_if("SPNEGO"        NOT CURL_DISABLE_CRYPTO_AUTH AND
                         (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
                         (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
@@ -1399,6 +1475,8 @@ _add_if("NTLM_WB"     use_ntlm AND NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
 _add_if("TLS-SRP"       USE_TLS_SRP)
 _add_if("TLS-SRP"       USE_TLS_SRP)
 # TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header
 # TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header
 _add_if("HTTP2"         USE_NGHTTP2)
 _add_if("HTTP2"         USE_NGHTTP2)
+_add_if("HTTP3"         USE_NGTCP2 OR USE_QUICHE)
+_add_if("MultiSSL"      CURL_WITH_MULTI_SSL)
 _add_if("HTTPS-proxy"   SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS OR USE_NSS))
 _add_if("HTTPS-proxy"   SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS OR USE_NSS))
 string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
 string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
 message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
 message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
@@ -1428,10 +1506,11 @@ _add_if("SMB"           NOT CURL_DISABLE_SMB AND use_ntlm)
 _add_if("SMBS"          NOT CURL_DISABLE_SMB AND SSL_ENABLED AND use_ntlm)
 _add_if("SMBS"          NOT CURL_DISABLE_SMB AND SSL_ENABLED AND use_ntlm)
 _add_if("SMTP"          NOT CURL_DISABLE_SMTP)
 _add_if("SMTP"          NOT CURL_DISABLE_SMTP)
 _add_if("SMTPS"         NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
 _add_if("SMTPS"         NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
-_add_if("SCP"           USE_LIBSSH2)
-_add_if("SFTP"          USE_LIBSSH2)
+_add_if("SCP"           USE_LIBSSH2 OR USE_LIBSSH)
+_add_if("SFTP"          USE_LIBSSH2 OR USE_LIBSSH)
 _add_if("RTSP"          NOT CURL_DISABLE_RTSP)
 _add_if("RTSP"          NOT CURL_DISABLE_RTSP)
 _add_if("RTMP"          USE_LIBRTMP)
 _add_if("RTMP"          USE_LIBRTMP)
+_add_if("MQTT"          CURL_ENABLE_MQTT)
 if(_items)
 if(_items)
   list(SORT _items)
   list(SORT _items)
 endif()
 endif()
@@ -1446,6 +1525,7 @@ _add_if("Secure Transport" SSL_ENABLED AND USE_SECTRANSP)
 _add_if("mbedTLS"          SSL_ENABLED AND USE_MBEDTLS)
 _add_if("mbedTLS"          SSL_ENABLED AND USE_MBEDTLS)
 _add_if("BearSSL"          SSL_ENABLED AND USE_BEARSSL)
 _add_if("BearSSL"          SSL_ENABLED AND USE_BEARSSL)
 _add_if("NSS"              SSL_ENABLED AND USE_NSS)
 _add_if("NSS"              SSL_ENABLED AND USE_NSS)
+_add_if("wolfSSL"          SSL_ENABLED AND USE_WOLFSSL)
 if(_items)
 if(_items)
   list(SORT _items)
   list(SORT _items)
 endif()
 endif()
@@ -1459,25 +1539,43 @@ set(CONFIGURE_OPTIONS       "")
 # TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB?
 # TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB?
 set(CPPFLAG_CURL_STATICLIB  "")
 set(CPPFLAG_CURL_STATICLIB  "")
 set(CURLVERSION             "${CURL_VERSION}")
 set(CURLVERSION             "${CURL_VERSION}")
-if(BUILD_SHARED_LIBS)
-  set(ENABLE_SHARED         "yes")
-  set(ENABLE_STATIC         "no")
-else()
-  set(ENABLE_SHARED         "no")
-  set(ENABLE_STATIC         "yes")
-endif()
 set(exec_prefix             "\${prefix}")
 set(exec_prefix             "\${prefix}")
 set(includedir              "\${prefix}/include")
 set(includedir              "\${prefix}/include")
 set(LDFLAGS                 "${CMAKE_SHARED_LINKER_FLAGS}")
 set(LDFLAGS                 "${CMAKE_SHARED_LINKER_FLAGS}")
 set(LIBCURL_LIBS            "")
 set(LIBCURL_LIBS            "")
 set(libdir                  "${CMAKE_INSTALL_PREFIX}/lib")
 set(libdir                  "${CMAKE_INSTALL_PREFIX}/lib")
 foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS})
 foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS})
+  if(TARGET "${_lib}")
+    set(_libname "${_lib}")
+    get_target_property(_libtype "${_libname}" TYPE)
+    if(_libtype STREQUAL INTERFACE_LIBRARY)
+      # Interface libraries can occur when an external project embeds curl and
+      # defined targets such as ZLIB::ZLIB by themselves. Ignore these as
+      # reading the LOCATION property will error out. Assume the user won't need
+      # this information in the .pc file.
+      continue()
+    endif()
+    get_target_property(_lib "${_libname}" LOCATION)
+    if(NOT _lib)
+      message(WARNING "Bad lib in library list: ${_libname}")
+      continue()
+    endif()
+  endif()
   if(_lib MATCHES ".*/.*" OR _lib MATCHES "^-")
   if(_lib MATCHES ".*/.*" OR _lib MATCHES "^-")
     set(LIBCURL_LIBS          "${LIBCURL_LIBS} ${_lib}")
     set(LIBCURL_LIBS          "${LIBCURL_LIBS} ${_lib}")
   else()
   else()
     set(LIBCURL_LIBS          "${LIBCURL_LIBS} -l${_lib}")
     set(LIBCURL_LIBS          "${LIBCURL_LIBS} -l${_lib}")
   endif()
   endif()
 endforeach()
 endforeach()
+if(BUILD_SHARED_LIBS)
+  set(ENABLE_SHARED         "yes")
+  set(ENABLE_STATIC         "no")
+  set(LIBCURL_NO_SHARED     "")
+else()
+  set(ENABLE_SHARED         "no")
+  set(ENABLE_STATIC         "yes")
+  set(LIBCURL_NO_SHARED     "${LIBCURL_LIBS}")
+endif()
 # "a" (Linux) or "lib" (Windows)
 # "a" (Linux) or "lib" (Windows)
 string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
 string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
 set(prefix                  "${CMAKE_INSTALL_PREFIX}")
 set(prefix                  "${CMAKE_INSTALL_PREFIX}")

+ 40 - 10
Utilities/cmcurl/include/curl/curl.h

@@ -833,6 +833,15 @@ typedef enum {
    if possible. The OpenSSL backend has this ability. */
    if possible. The OpenSSL backend has this ability. */
 #define CURLSSLOPT_NO_PARTIALCHAIN (1<<2)
 #define CURLSSLOPT_NO_PARTIALCHAIN (1<<2)
 
 
+/* - REVOKE_BEST_EFFORT tells libcurl to ignore certificate revocation offline
+   checks and ignore missing revocation list for those SSL backends where such
+   behavior is present. */
+#define CURLSSLOPT_REVOKE_BEST_EFFORT (1<<3)
+
+/* - CURLSSLOPT_NATIVE_CA tells libcurl to use standard certificate store of
+   operating system. Currently implemented under MS-Windows. */
+#define CURLSSLOPT_NATIVE_CA (1<<4)
+
 /* The default connection attempt delay in milliseconds for happy eyeballs.
 /* The default connection attempt delay in milliseconds for happy eyeballs.
    CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
    CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
    this value, keep them in sync. */
    this value, keep them in sync. */
@@ -932,6 +941,7 @@ typedef enum {
 #define CURLPROTO_GOPHER (1<<25)
 #define CURLPROTO_GOPHER (1<<25)
 #define CURLPROTO_SMB    (1<<26)
 #define CURLPROTO_SMB    (1<<26)
 #define CURLPROTO_SMBS   (1<<27)
 #define CURLPROTO_SMBS   (1<<27)
+#define CURLPROTO_MQTT   (1<<28)
 #define CURLPROTO_ALL    (~0) /* enable everything */
 #define CURLPROTO_ALL    (~0) /* enable everything */
 
 
 /* long may be 32 or 64 bits, but we should never depend on anything else
 /* long may be 32 or 64 bits, but we should never depend on anything else
@@ -940,6 +950,7 @@ typedef enum {
 #define CURLOPTTYPE_OBJECTPOINT   10000
 #define CURLOPTTYPE_OBJECTPOINT   10000
 #define CURLOPTTYPE_FUNCTIONPOINT 20000
 #define CURLOPTTYPE_FUNCTIONPOINT 20000
 #define CURLOPTTYPE_OFF_T         30000
 #define CURLOPTTYPE_OFF_T         30000
+#define CURLOPTTYPE_BLOB          40000
 
 
 /* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the
 /* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the
    string options from the header file */
    string options from the header file */
@@ -1949,6 +1960,17 @@ typedef enum {
   /* allow RCPT TO command to fail for some recipients */
   /* allow RCPT TO command to fail for some recipients */
   CURLOPT(CURLOPT_MAIL_RCPT_ALLLOWFAILS, CURLOPTTYPE_LONG, 290),
   CURLOPT(CURLOPT_MAIL_RCPT_ALLLOWFAILS, CURLOPTTYPE_LONG, 290),
 
 
+  /* the private SSL-certificate as a "blob" */
+  CURLOPT(CURLOPT_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 291),
+  CURLOPT(CURLOPT_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 292),
+  CURLOPT(CURLOPT_PROXY_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 293),
+  CURLOPT(CURLOPT_PROXY_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 294),
+  CURLOPT(CURLOPT_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 295),
+
+  /* Issuer certificate for proxy */
+  CURLOPT(CURLOPT_PROXY_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 296),
+  CURLOPT(CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 297),
+
   CURLOPT_LASTENTRY /* the last unused */
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 } CURLoption;
 
 
@@ -2105,8 +2127,8 @@ CURL_EXTERN int curl_strequal(const char *s1, const char *s2);
 CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n);
 CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n);
 
 
 /* Mime/form handling support. */
 /* Mime/form handling support. */
-typedef struct curl_mime_s      curl_mime;      /* Mime context. */
-typedef struct curl_mimepart_s  curl_mimepart;  /* Mime part context. */
+typedef struct curl_mime      curl_mime;      /* Mime context. */
+typedef struct curl_mimepart  curl_mimepart;  /* Mime part context. */
 
 
 /*
 /*
  * NAME curl_mime_init()
  * NAME curl_mime_init()
@@ -2428,7 +2450,7 @@ CURL_EXTERN CURLcode curl_global_init(long flags);
  * initialize libcurl and set user defined memory management callback
  * initialize libcurl and set user defined memory management callback
  * functions.  Users can implement memory management routines to check for
  * functions.  Users can implement memory management routines to check for
  * memory leaks, check for mis-use of the curl library etc.  User registered
  * memory leaks, check for mis-use of the curl library etc.  User registered
- * callback routines with be invoked by this library instead of the system
+ * callback routines will be invoked by this library instead of the system
  * memory management routines like malloc, free etc.
  * memory management routines like malloc, free etc.
  */
  */
 CURL_EXTERN CURLcode curl_global_init_mem(long flags,
 CURL_EXTERN CURLcode curl_global_init_mem(long flags,
@@ -2480,10 +2502,11 @@ struct curl_slist {
  * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE.
  * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE.
  */
  */
 
 
-typedef struct {
+struct curl_ssl_backend {
   curl_sslbackend id;
   curl_sslbackend id;
   const char *name;
   const char *name;
-} curl_ssl_backend;
+};
+typedef struct curl_ssl_backend curl_ssl_backend;
 
 
 typedef enum {
 typedef enum {
   CURLSSLSET_OK = 0,
   CURLSSLSET_OK = 0,
@@ -2724,6 +2747,7 @@ typedef enum {
   CURLVERSION_FOURTH,
   CURLVERSION_FOURTH,
   CURLVERSION_FIFTH,
   CURLVERSION_FIFTH,
   CURLVERSION_SIXTH,
   CURLVERSION_SIXTH,
+  CURLVERSION_SEVENTH,
   CURLVERSION_LAST /* never actually use this */
   CURLVERSION_LAST /* never actually use this */
 } CURLversion;
 } CURLversion;
 
 
@@ -2732,9 +2756,9 @@ typedef enum {
    meant to be a built-in version number for what kind of struct the caller
    meant to be a built-in version number for what kind of struct the caller
    expects. If the struct ever changes, we redefine the NOW to another enum
    expects. If the struct ever changes, we redefine the NOW to another enum
    from above. */
    from above. */
-#define CURLVERSION_NOW CURLVERSION_SIXTH
+#define CURLVERSION_NOW CURLVERSION_SEVENTH
 
 
-typedef struct {
+struct curl_version_info_data {
   CURLversion age;          /* age of the returned struct */
   CURLversion age;          /* age of the returned struct */
   const char *version;      /* LIBCURL_VERSION */
   const char *version;      /* LIBCURL_VERSION */
   unsigned int version_num; /* LIBCURL_VERSION_NUM */
   unsigned int version_num; /* LIBCURL_VERSION_NUM */
@@ -2771,7 +2795,15 @@ typedef struct {
   const char *nghttp2_version; /* human readable string. */
   const char *nghttp2_version; /* human readable string. */
   const char *quic_version;    /* human readable quic (+ HTTP/3) library +
   const char *quic_version;    /* human readable quic (+ HTTP/3) library +
                                   version or NULL */
                                   version or NULL */
-} curl_version_info_data;
+
+  /* These fields were added in CURLVERSION_SEVENTH */
+  const char *cainfo;          /* the built-in default CURLOPT_CAINFO, might
+                                  be NULL */
+  const char *capath;          /* the built-in default CURLOPT_CAPATH, might
+                                  be NULL */
+
+};
+typedef struct curl_version_info_data curl_version_info_data;
 
 
 #define CURL_VERSION_IPV6         (1<<0)  /* IPv6-enabled */
 #define CURL_VERSION_IPV6         (1<<0)  /* IPv6-enabled */
 #define CURL_VERSION_KERBEROS4    (1<<1)  /* Kerberos V4 auth is supported
 #define CURL_VERSION_KERBEROS4    (1<<1)  /* Kerberos V4 auth is supported
@@ -2805,8 +2837,6 @@ typedef struct {
 #define CURL_VERSION_ALTSVC       (1<<24) /* Alt-Svc handling built-in */
 #define CURL_VERSION_ALTSVC       (1<<24) /* Alt-Svc handling built-in */
 #define CURL_VERSION_HTTP3        (1<<25) /* HTTP3 support built-in */
 #define CURL_VERSION_HTTP3        (1<<25) /* HTTP3 support built-in */
 
 
-#define CURL_VERSION_ESNI         (1<<26) /* ESNI support */
-
  /*
  /*
  * NAME curl_version_info()
  * NAME curl_version_info()
  *
  *

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

@@ -30,16 +30,16 @@
 
 
 /* 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.69.0"
+#define LIBCURL_VERSION "7.71.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 69
+#define LIBCURL_VERSION_MINOR 71
 #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
-   parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
+   parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
    always follow this syntax:
    always follow this syntax:
 
 
          0xXXYYZZ
          0xXXYYZZ
@@ -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 0x074500
+#define LIBCURL_VERSION_NUM 0x074700
 
 
 /*
 /*
  * 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

+ 12 - 1
Utilities/cmcurl/include/curl/easy.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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,17 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
+/* Flag bits in the curl_blob struct: */
+#define CURL_BLOB_COPY   1 /* tell libcurl to copy the data */
+#define CURL_BLOB_NOCOPY 0 /* tell libcurl to NOT copy the data */
+
+struct curl_blob {
+  void *data;
+  size_t len;
+  unsigned int flags; /* bit 0 is defined, the rest are reserved and should be
+                         left zeroes */
+};
+
 CURL_EXTERN CURL *curl_easy_init(void);
 CURL_EXTERN CURL *curl_easy_init(void);
 CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
 CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
 CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
 CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);

+ 2 - 4
Utilities/cmcurl/include/curl/multi.h

@@ -377,12 +377,10 @@ typedef enum {
      will not be considered for pipelining */
      will not be considered for pipelining */
   CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10),
   CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10),
 
 
-  /* a list of site names(+port) that are blacklisted from
-     pipelining */
+  /* a list of site names(+port) that are blocked from pipelining */
   CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11),
   CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11),
 
 
-  /* a list of server types that are blacklisted from
-     pipelining */
+  /* a list of server types that are blocked from pipelining */
   CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12),
   CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12),
 
 
   /* maximum number of open connections in total */
   /* maximum number of open connections in total */

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

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -248,7 +248,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
   (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
   (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
 
 
 #define curlcheck_off_t_option(option)          \
 #define curlcheck_off_t_option(option)          \
-  ((option) > CURLOPTTYPE_OFF_T)
+  (((option) > CURLOPTTYPE_OFF_T) && ((option) < CURLOPTTYPE_BLOB))
 
 
 /* evaluates to true if option takes a char* argument */
 /* evaluates to true if option takes a char* argument */
 #define curlcheck_string_option(option)                                       \
 #define curlcheck_string_option(option)                                       \
@@ -392,8 +392,9 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
 /* groups of curl_easy_getinfo infos that take the same type of argument */
 /* groups of curl_easy_getinfo infos that take the same type of argument */
 
 
 /* evaluates to true if info expects a pointer to char * argument */
 /* evaluates to true if info expects a pointer to char * argument */
-#define curlcheck_string_info(info)                     \
-  (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
+#define curlcheck_string_info(info)                             \
+  (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG &&        \
+   (info) != CURLINFO_PRIVATE)
 
 
 /* evaluates to true if info expects a pointer to long argument */
 /* evaluates to true if info expects a pointer to long argument */
 #define curlcheck_long_info(info)                       \
 #define curlcheck_long_info(info)                       \

+ 27 - 1
Utilities/cmcurl/lib/CMakeLists.txt

@@ -1,3 +1,24 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, 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.
+#
+###########################################################################
 set(LIB_NAME cmcurl)
 set(LIB_NAME cmcurl)
 
 
 if(BUILD_SHARED_LIBS)
 if(BUILD_SHARED_LIBS)
@@ -96,6 +117,11 @@ add_library(
   ${CMAKE_CURL_SSL_DLLS}
   ${CMAKE_CURL_SSL_DLLS}
   )
   )
 
 
+add_library(
+  ${PROJECT_NAME}::${LIB_NAME}
+  ALIAS ${LIB_NAME}
+  )
+
 if(NOT BUILD_SHARED_LIBS)
 if(NOT BUILD_SHARED_LIBS)
     set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB)
     set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB)
 endif()
 endif()
@@ -146,7 +172,7 @@ install(TARGETS ${LIB_NAME}
 
 
 export(TARGETS ${LIB_NAME}
 export(TARGETS ${LIB_NAME}
        APPEND FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
        APPEND FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
-       NAMESPACE CURL::
+       NAMESPACE ${PROJECT_NAME}::
 )
 )
 
 
 endif()
 endif()

+ 50 - 55
Utilities/cmcurl/lib/Makefile.inc

@@ -20,71 +20,66 @@
 #
 #
 ###########################################################################
 ###########################################################################
 
 
-LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c vauth/cram.c         \
-  vauth/digest.c vauth/digest_sspi.c vauth/krb5_gssapi.c                \
-  vauth/krb5_sspi.c vauth/ntlm.c vauth/ntlm_sspi.c vauth/oauth2.c       \
-  vauth/spnego_gssapi.c vauth/spnego_sspi.c
+LIB_VAUTH_CFILES = vauth/cleartext.c vauth/cram.c vauth/digest.c             \
+  vauth/digest_sspi.c vauth/krb5_gssapi.c vauth/krb5_sspi.c vauth/ntlm.c     \
+  vauth/ntlm_sspi.c vauth/oauth2.c vauth/spnego_gssapi.c vauth/spnego_sspi.c \
+  vauth/vauth.c
 
 
-LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h
+LIB_VAUTH_HFILES = vauth/digest.h vauth/ntlm.h vauth/vauth.h
 
 
-LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c     \
-  vtls/mbedtls_threadlock.c vtls/wolfssl.c vtls/schannel.c              \
-  vtls/schannel_verify.c vtls/sectransp.c vtls/gskit.c vtls/mbedtls.c   \
-  vtls/mesalink.c vtls/bearssl.c
+LIB_VTLS_CFILES = vtls/bearssl.c vtls/gskit.c vtls/gtls.c vtls/keylog.c  \
+  vtls/mbedtls.c vtls/mbedtls_threadlock.c vtls/mesalink.c vtls/nss.c    \
+  vtls/openssl.c vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c \
+  vtls/vtls.c vtls/wolfssl.c
 
 
-LIB_VTLS_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h vtls/nssg.h    \
-  vtls/mbedtls_threadlock.h vtls/wolfssl.h vtls/schannel.h              \
-  vtls/sectransp.h vtls/gskit.h vtls/mbedtls.h vtls/mesalink.h          \
-  vtls/bearssl.h
+LIB_VTLS_HFILES = vtls/bearssl.h vtls/gskit.h vtls/gtls.h vtls/keylog.h      \
+  vtls/mbedtls.h vtls/mbedtls_threadlock.h vtls/mesalink.h vtls/nssg.h       \
+  vtls/openssl.h vtls/schannel.h vtls/sectransp.h vtls/vtls.h vtls/wolfssl.h
 
 
-LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c
+LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c vquic/vquic.c
 
 
-LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h
+LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h vquic/vquic.h
 
 
-LIB_VSSH_CFILES = vssh/libssh2.c vssh/libssh.c vssh/wolfssh.c
+LIB_VSSH_CFILES = vssh/libssh.c vssh/libssh2.c vssh/wolfssh.c
 
 
 LIB_VSSH_HFILES = vssh/ssh.h
 LIB_VSSH_HFILES = vssh/ssh.h
 
 
-LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c formdata.c   \
-  cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c       \
-  ldap.c version.c getenv.c escape.c mprintf.c telnet.c netrc.c         \
-  getinfo.c transfer.c strcase.c easy.c security.c curl_fnmatch.c       \
-  fileinfo.c ftplistparser.c wildcard.c krb5.c memdebug.c http_chunks.c \
-  strtok.c connect.c llist.c hash.c multi.c content_encoding.c share.c  \
-  http_digest.c md4.c md5.c http_negotiate.c inet_pton.c strtoofft.c    \
-  strerror.c amigaos.c hostasyn.c hostip4.c hostip6.c hostsyn.c         \
-  inet_ntop.c parsedate.c select.c tftp.c splay.c strdup.c socks.c      \
-  curl_addrinfo.c socks_gssapi.c socks_sspi.c                           \
-  curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c    \
-  pingpong.c rtsp.c curl_threads.c warnless.c hmac.c curl_rtmp.c        \
-  openldap.c curl_gethostname.c gopher.c idn_win32.c                    \
-  http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c      \
-  http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.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      \
-  mime.c sha256.c setopt.c curl_path.c curl_ctype.c curl_range.c psl.c  \
-  doh.c urlapi.c curl_get_line.c altsvc.c socketpair.c rename.c
+LIB_CFILES = altsvc.c amigaos.c asyn-ares.c asyn-thread.c base64.c            \
+  conncache.c connect.c content_encoding.c cookie.c curl_addrinfo.c           \
+  curl_ctype.c curl_des.c curl_endian.c curl_fnmatch.c curl_get_line.c        \
+  curl_gethostname.c curl_gssapi.c curl_memrchr.c curl_multibyte.c            \
+  curl_ntlm_core.c curl_ntlm_wb.c curl_path.c curl_range.c curl_rtmp.c        \
+  curl_sasl.c curl_sspi.c curl_threads.c dict.c dotdot.c easy.c escape.c      \
+  file.c fileinfo.c formdata.c ftp.c url.c ftplistparser.c getenv.c getinfo.c \
+  gopher.c hash.c hmac.c hostasyn.c hostcheck.c hostip.c hostip4.c hostip6.c  \
+  hostsyn.c http.c http2.c http_chunks.c http_digest.c http_negotiate.c       \
+  http_ntlm.c http_proxy.c idn_win32.c if2ip.c imap.c inet_ntop.c inet_pton.c \
+  krb5.c ldap.c llist.c md4.c md5.c memdebug.c mime.c mprintf.c mqtt.c        \
+  multi.c netrc.c non-ascii.c nonblock.c openldap.c parsedate.c pingpong.c    \
+  pop3.c progress.c psl.c doh.c rand.c rename.c rtsp.c security.c select.c    \
+  sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c socketpair.c socks.c \
+  socks_gssapi.c socks_sspi.c speedcheck.c splay.c strcase.c strdup.c         \
+  strerror.c strtok.c strtoofft.c system_win32.c telnet.c tftp.c timeval.c    \
+  transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c dynbuf.c
 
 
-LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h progress.h \
-  formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h if2ip.h         \
-  speedcheck.h urldata.h curl_ldap.h escape.h telnet.h getinfo.h        \
-  strcase.h curl_sec.h memdebug.h http_chunks.h curl_fnmatch.h          \
-  wildcard.h fileinfo.h ftplistparser.h strtok.h connect.h llist.h      \
-  hash.h content_encoding.h share.h curl_md4.h curl_md5.h http_digest.h \
-  http_negotiate.h inet_pton.h amigaos.h strtoofft.h strerror.h         \
-  inet_ntop.h curlx.h curl_memory.h curl_setup.h transfer.h select.h    \
-  easyif.h multiif.h parsedate.h tftp.h sockaddr.h splay.h strdup.h     \
-  socks.h curl_base64.h curl_addrinfo.h curl_sspi.h                     \
-  slist.h nonblock.h curl_memrchr.h imap.h pop3.h smtp.h pingpong.h     \
-  rtsp.h curl_threads.h warnless.h curl_hmac.h curl_rtmp.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             \
-  curl_sasl.h curl_multibyte.h hostcheck.h conncache.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           \
-  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_get_line.h altsvc.h quic.h socketpair.h rename.h
+LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h    \
+  content_encoding.h cookie.h curl_addrinfo.h curl_base64.h curl_ctype.h      \
+  curl_des.h curl_endian.h curl_fnmatch.h curl_get_line.h curl_gethostname.h  \
+  curl_gssapi.h curl_hmac.h curl_ldap.h curl_md4.h curl_md5.h curl_memory.h   \
+  curl_memrchr.h curl_multibyte.h curl_ntlm_core.h curl_ntlm_wb.h curl_path.h \
+  curl_printf.h curl_range.h curl_rtmp.h curl_sasl.h curl_sec.h curl_setup.h  \
+  curl_setup_once.h curl_sha256.h curl_sspi.h curl_threads.h curlx.h dict.h   \
+  dotdot.h easyif.h escape.h file.h fileinfo.h formdata.h ftp.h url.h         \
+  ftplistparser.h getinfo.h gopher.h hash.h hostcheck.h hostip.h http.h       \
+  http2.h http_chunks.h http_digest.h http_negotiate.h http_ntlm.h            \
+  http_proxy.h if2ip.h imap.h inet_ntop.h inet_pton.h llist.h memdebug.h      \
+  mime.h mqtt.h multihandle.h multiif.h netrc.h non-ascii.h nonblock.h        \
+  parsedate.h pingpong.h pop3.h progress.h psl.h doh.h quic.h rand.h rename.h \
+  rtsp.h select.h sendf.h setopt.h setup-vms.h share.h sigpipe.h slist.h      \
+  smb.h smtp.h sockaddr.h socketpair.h socks.h speedcheck.h splay.h strcase.h \
+  strdup.h strerror.h strtok.h strtoofft.h system_win32.h telnet.h tftp.h     \
+  timeval.h transfer.h urlapi-int.h urldata.h warnless.h wildcard.h           \
+  x509asn1.h dynbuf.h
 
 
 LIB_RCFILES = libcurl.rc
 LIB_RCFILES = libcurl.rc
 
 

+ 10 - 9
Utilities/cmcurl/lib/altsvc.c

@@ -50,8 +50,10 @@
 #define MAX_ALTSVC_ALPNLENSTR "10"
 #define MAX_ALTSVC_ALPNLENSTR "10"
 #define MAX_ALTSVC_ALPNLEN 10
 #define MAX_ALTSVC_ALPNLEN 10
 
 
-#if (defined(USE_QUICHE) || defined(USE_NGTCP2)) && !defined(UNITTESTS)
-#define H3VERSION "h3-27"
+#if defined(USE_QUICHE) && !defined(UNITTESTS)
+#define H3VERSION "h3-29"
+#elif defined(USE_NGTCP2) && !defined(UNITTESTS)
+#define H3VERSION "h3-29"
 #else
 #else
 #define H3VERSION "h3"
 #define H3VERSION "h3"
 #endif
 #endif
@@ -167,7 +169,6 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
       as->prio = prio;
       as->prio = prio;
       as->persist = persist ? 1 : 0;
       as->persist = persist ? 1 : 0;
       Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
       Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
-      asi->num++; /* one more entry */
     }
     }
   }
   }
 
 
@@ -408,7 +409,6 @@ static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
        strcasecompare(srchost, as->src.host)) {
        strcasecompare(srchost, as->src.host)) {
       Curl_llist_remove(&asi->list, e, NULL);
       Curl_llist_remove(&asi->list, e, NULL);
       altsvc_free(as);
       altsvc_free(as);
-      asi->num--;
     }
     }
   }
   }
 }
 }
@@ -429,6 +429,8 @@ static time_t debugtime(void *unused)
 #define time(x) debugtime(x)
 #define time(x) debugtime(x)
 #endif
 #endif
 
 
+#define ISNEWLINE(x) (((x) == '\n') || (x) == '\r')
+
 /*
 /*
  * Curl_altsvc_parse() takes an incoming alt-svc response header and stores
  * Curl_altsvc_parse() takes an incoming alt-svc response header and stores
  * the data correctly in the cache.
  * the data correctly in the cache.
@@ -474,7 +476,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
       dstalpnid = alpn2alpnid(alpnbuf);
       dstalpnid = alpn2alpnid(alpnbuf);
       p++;
       p++;
       if(*p == '\"') {
       if(*p == '\"') {
-        const char *dsthost;
+        const char *dsthost = "";
         const char *value_ptr;
         const char *value_ptr;
         char option[32];
         char option[32];
         unsigned long num;
         unsigned long num;
@@ -518,12 +520,12 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
         /* Handle the optional 'ma' and 'persist' flags. Unknown flags
         /* Handle the optional 'ma' and 'persist' flags. Unknown flags
            are skipped. */
            are skipped. */
         for(;;) {
         for(;;) {
-          while(*p && ISBLANK(*p) && *p != ';' && *p != ',')
+          while(ISBLANK(*p))
             p++;
             p++;
-          if(!*p || *p == ',')
+          if(*p != ';')
             break;
             break;
           p++; /* pass the semicolon */
           p++; /* pass the semicolon */
-          if(!*p)
+          if(!*p || ISNEWLINE(*p))
             break;
             break;
           result = getalnum(&p, option, sizeof(option));
           result = getalnum(&p, option, sizeof(option));
           if(result) {
           if(result) {
@@ -573,7 +575,6 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
             as->expires = maxage + time(NULL);
             as->expires = maxage + time(NULL);
             as->persist = persist;
             as->persist = persist;
             Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
             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,
             infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
                   Curl_alpnid2str(dstalpnid));
                   Curl_alpnid2str(dstalpnid));
           }
           }

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

@@ -52,7 +52,6 @@ struct altsvc {
 struct altsvcinfo {
 struct altsvcinfo {
   char *filename;
   char *filename;
   struct curl_llist list; /* list of entries */
   struct curl_llist list; /* list of entries */
-  size_t num; /* number of alt-svc entries */
   long flags; /* the publicly set bitmask */
   long flags; /* the publicly set bitmask */
 };
 };
 
 

+ 30 - 27
Utilities/cmcurl/lib/asyn-ares.c

@@ -87,7 +87,8 @@
 
 
 struct ResolverResults {
 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 */
+  struct 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 */
   struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
 };
 };
@@ -285,7 +286,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
  * return number of sockets it worked on
  * return number of sockets it worked on
  */
  */
 
 
-static int waitperform(struct connectdata *conn, int timeout_ms)
+static int waitperform(struct connectdata *conn, timediff_t timeout_ms)
 {
 {
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
   int nfds;
   int nfds;
@@ -352,8 +353,8 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
     conn->async.os_specific;
     conn->async.os_specific;
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
 
 
-  if(dns)
-    *dns = NULL;
+  DEBUGASSERT(dns);
+  *dns = NULL;
 
 
   waitperform(conn, 0);
   waitperform(conn, 0);
 
 
@@ -381,19 +382,18 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
   }
   }
 
 
   if(res && !res->num_pending) {
   if(res && !res->num_pending) {
-    if(dns) {
-      (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
-      /* temp_ai ownership is moved to the connection, so we need not free-up
-         them */
-      res->temp_ai = NULL;
-    }
+    (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
+    /* temp_ai ownership is moved to the connection, so we need not free-up
+       them */
+    res->temp_ai = NULL;
+
     if(!conn->async.dns) {
     if(!conn->async.dns) {
       failf(data, "Could not resolve: %s (%s)",
       failf(data, "Could not resolve: %s (%s)",
             conn->async.hostname, ares_strerror(conn->async.status));
             conn->async.hostname, ares_strerror(conn->async.status));
       result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
       result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
         CURLE_COULDNT_RESOLVE_HOST;
         CURLE_COULDNT_RESOLVE_HOST;
     }
     }
-    else if(dns)
+    else
       *dns = conn->async.dns;
       *dns = conn->async.dns;
 
 
     destroy_async_data(&conn->async);
     destroy_async_data(&conn->async);
@@ -408,7 +408,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
  * 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
+ * 'entry' MUST be non-NULL.
  *
  *
  * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
  * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
  * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
  * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
@@ -420,10 +420,9 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
   timediff_t timeout;
   timediff_t timeout;
   struct curltime now = Curl_now();
   struct curltime now = Curl_now();
-  struct Curl_dns_entry *temp_entry;
 
 
-  if(entry)
-    *entry = NULL; /* clear on entry */
+  DEBUGASSERT(entry);
+  *entry = NULL; /* clear on entry */
 
 
   timeout = Curl_timeleft(data, &now, TRUE);
   timeout = Curl_timeleft(data, &now, TRUE);
   if(timeout < 0) {
   if(timeout < 0) {
@@ -438,9 +437,13 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
   while(!result) {
   while(!result) {
     struct timeval *tvp, tv, store;
     struct timeval *tvp, tv, store;
     int itimeout;
     int itimeout;
-    int timeout_ms;
+    timediff_t timeout_ms;
 
 
-    itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;
+#if TIMEDIFF_T_MAX > INT_MAX
+    itimeout = (timeout > INT_MAX) ? INT_MAX : (int)timeout;
+#else
+    itimeout = (int)timeout;
+#endif
 
 
     store.tv_sec = itimeout/1000;
     store.tv_sec = itimeout/1000;
     store.tv_usec = (itimeout%1000)*1000;
     store.tv_usec = (itimeout%1000)*1000;
@@ -451,12 +454,12 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
        second is left, otherwise just use 1000ms to make sure the progress
        second is left, otherwise just use 1000ms to make sure the progress
        callback gets called frequent enough */
        callback gets called frequent enough */
     if(!tvp->tv_sec)
     if(!tvp->tv_sec)
-      timeout_ms = (int)(tvp->tv_usec/1000);
+      timeout_ms = (timediff_t)(tvp->tv_usec/1000);
     else
     else
       timeout_ms = 1000;
       timeout_ms = 1000;
 
 
     waitperform(conn, timeout_ms);
     waitperform(conn, timeout_ms);
-    result = Curl_resolver_is_resolved(conn, entry?&temp_entry:NULL);
+    result = Curl_resolver_is_resolved(conn, entry);
 
 
     if(result || conn->async.done)
     if(result || conn->async.done)
       break;
       break;
@@ -471,7 +474,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
       else if(timediff > timeout)
       else if(timediff > timeout)
         timeout = -1;
         timeout = -1;
       else
       else
-        timeout -= (long)timediff;
+        timeout -= timediff;
       now = now2; /* for next loop */
       now = now2; /* for next loop */
     }
     }
     if(timeout < 0)
     if(timeout < 0)
@@ -496,9 +499,9 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
 
 
 /* Connects results to the list */
 /* Connects results to the list */
 static void compound_results(struct ResolverResults *res,
 static void compound_results(struct ResolverResults *res,
-                             Curl_addrinfo *ai)
+                             struct Curl_addrinfo *ai)
 {
 {
-  Curl_addrinfo *ai_tail;
+  struct Curl_addrinfo *ai_tail;
   if(!ai)
   if(!ai)
     return;
     return;
   ai_tail = ai;
   ai_tail = ai;
@@ -540,7 +543,7 @@ static void query_completed_cb(void *arg,  /* (struct connectdata *) */
     res->num_pending--;
     res->num_pending--;
 
 
     if(CURL_ASYNC_SUCCESS == status) {
     if(CURL_ASYNC_SUCCESS == status) {
-      Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
+      struct Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
       if(ai) {
       if(ai) {
         compound_results(res, ai);
         compound_results(res, ai);
       }
       }
@@ -619,10 +622,10 @@ static void query_completed_cb(void *arg,  /* (struct connectdata *) */
  * memory we need to free after use. That memory *MUST* be freed with
  * memory we need to free after use. That memory *MUST* be freed with
  * Curl_freeaddrinfo(), nothing else.
  * Curl_freeaddrinfo(), nothing else.
  */
  */
-Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
-                                         const char *hostname,
-                                         int port,
-                                         int *waitp)
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+                                                const char *hostname,
+                                                int port,
+                                                int *waitp)
 {
 {
   char *bufp;
   char *bufp;
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;

+ 25 - 18
Utilities/cmcurl/lib/asyn-thread.c

@@ -158,7 +158,7 @@ static bool init_resolve_thread(struct connectdata *conn,
 
 
 /* Data for synchronization between resolver thread and its parent */
 /* Data for synchronization between resolver thread and its parent */
 struct thread_sync_data {
 struct thread_sync_data {
-  curl_mutex_t * mtx;
+  curl_mutex_t *mtx;
   int done;
   int done;
 
 
   char *hostname;        /* hostname to resolve, Curl_async.hostname
   char *hostname;        /* hostname to resolve, Curl_async.hostname
@@ -169,7 +169,7 @@ struct thread_sync_data {
   curl_socket_t sock_pair[2]; /* socket pair */
   curl_socket_t sock_pair[2]; /* socket pair */
 #endif
 #endif
   int sock_error;
   int sock_error;
-  Curl_addrinfo *res;
+  struct Curl_addrinfo *res;
 #ifdef HAVE_GETADDRINFO
 #ifdef HAVE_GETADDRINFO
   struct addrinfo hints;
   struct addrinfo hints;
 #endif
 #endif
@@ -179,7 +179,7 @@ struct thread_sync_data {
 struct thread_data {
 struct thread_data {
   curl_thread_t thread_hnd;
   curl_thread_t thread_hnd;
   unsigned int poll_interval;
   unsigned int poll_interval;
-  time_t interval_end;
+  timediff_t interval_end;
   struct thread_sync_data tsd;
   struct thread_sync_data tsd;
 };
 };
 
 
@@ -190,7 +190,7 @@ static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn)
 
 
 /* Destroy resolver thread synchronization data */
 /* Destroy resolver thread synchronization data */
 static
 static
-void destroy_thread_sync_data(struct thread_sync_data * tsd)
+void destroy_thread_sync_data(struct thread_sync_data *tsd)
 {
 {
   if(tsd->mtx) {
   if(tsd->mtx) {
     Curl_mutex_destroy(tsd->mtx);
     Curl_mutex_destroy(tsd->mtx);
@@ -216,7 +216,7 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
 
 
 /* Initialize resolver thread synchronization data */
 /* Initialize resolver thread synchronization data */
 static
 static
-int init_thread_sync_data(struct thread_data * td,
+int init_thread_sync_data(struct thread_data *td,
                            const char *hostname,
                            const char *hostname,
                            int port,
                            int port,
                            const struct addrinfo *hints)
                            const struct addrinfo *hints)
@@ -494,11 +494,14 @@ static CURLcode resolver_error(struct connectdata *conn)
   const char *host_or_proxy;
   const char *host_or_proxy;
   CURLcode result;
   CURLcode result;
 
 
+#ifndef CURL_DISABLE_PROXY
   if(conn->bits.httpproxy) {
   if(conn->bits.httpproxy) {
     host_or_proxy = "proxy";
     host_or_proxy = "proxy";
     result = CURLE_COULDNT_RESOLVE_PROXY;
     result = CURLE_COULDNT_RESOLVE_PROXY;
   }
   }
-  else {
+  else
+#endif
+  {
     host_or_proxy = "host";
     host_or_proxy = "host";
     result = CURLE_COULDNT_RESOLVE_HOST;
     result = CURLE_COULDNT_RESOLVE_HOST;
   }
   }
@@ -509,6 +512,9 @@ static CURLcode resolver_error(struct connectdata *conn)
   return result;
   return result;
 }
 }
 
 
+/*
+ * 'entry' may be NULL and then no data is returned
+ */
 static CURLcode thread_wait_resolv(struct connectdata *conn,
 static CURLcode thread_wait_resolv(struct connectdata *conn,
                                    struct Curl_dns_entry **entry,
                                    struct Curl_dns_entry **entry,
                                    bool report)
                                    bool report)
@@ -593,6 +599,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
   struct thread_data   *td = (struct thread_data*) conn->async.os_specific;
   struct thread_data   *td = (struct thread_data*) conn->async.os_specific;
   int done = 0;
   int done = 0;
 
 
+  DEBUGASSERT(entry);
   *entry = NULL;
   *entry = NULL;
 
 
   if(!td) {
   if(!td) {
@@ -618,8 +625,8 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
   else {
   else {
     /* poll for name lookup done with exponential backoff up to 250ms */
     /* poll for name lookup done with exponential backoff up to 250ms */
     /* should be fine even if this converts to 32 bit */
     /* should be fine even if this converts to 32 bit */
-    time_t elapsed = (time_t)Curl_timediff(Curl_now(),
-                                           data->progress.t_startsingle);
+    timediff_t elapsed = Curl_timediff(Curl_now(),
+                                       data->progress.t_startsingle);
     if(elapsed < 0)
     if(elapsed < 0)
       elapsed = 0;
       elapsed = 0;
 
 
@@ -644,7 +651,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
                           curl_socket_t *socks)
                           curl_socket_t *socks)
 {
 {
   int ret_val = 0;
   int ret_val = 0;
-  time_t milli;
+  timediff_t milli;
   timediff_t ms;
   timediff_t ms;
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
   struct resdata *reslv = (struct resdata *)data->state.resolver;
   struct resdata *reslv = (struct resdata *)data->state.resolver;
@@ -668,7 +675,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
     if(ms < 3)
     if(ms < 3)
       milli = 0;
       milli = 0;
     else if(ms <= 50)
     else if(ms <= 50)
-      milli = (time_t)ms/3;
+      milli = ms/3;
     else if(ms <= 250)
     else if(ms <= 250)
       milli = 50;
       milli = 50;
     else
     else
@@ -686,10 +693,10 @@ int Curl_resolver_getsock(struct connectdata *conn,
 /*
 /*
  * Curl_getaddrinfo() - for platforms without getaddrinfo
  * Curl_getaddrinfo() - for platforms without getaddrinfo
  */
  */
-Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
-                                         const char *hostname,
-                                         int port,
-                                         int *waitp)
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+                                                const char *hostname,
+                                                int port,
+                                                int *waitp)
 {
 {
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
   struct resdata *reslv = (struct resdata *)data->state.resolver;
   struct resdata *reslv = (struct resdata *)data->state.resolver;
@@ -714,10 +721,10 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
 /*
 /*
  * Curl_resolver_getaddrinfo() - for getaddrinfo
  * Curl_resolver_getaddrinfo() - for getaddrinfo
  */
  */
-Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
-                                         const char *hostname,
-                                         int port,
-                                         int *waitp)
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+                                                const char *hostname,
+                                                int port,
+                                                int *waitp)
 {
 {
   struct addrinfo hints;
   struct addrinfo hints;
   int pf = PF_INET;
   int pf = PF_INET;

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

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -153,10 +153,10 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
  * Each resolver backend must of course make sure to return data in the
  * Each resolver backend must of course make sure to return data in the
  * correct format to comply with this.
  * correct format to comply with this.
  */
  */
-Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
-                                         const char *hostname,
-                                         int port,
-                                         int *waitp);
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+                                                const char *hostname,
+                                                int port,
+                                                int *waitp);
 
 
 #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 */

+ 51 - 49
Utilities/cmcurl/lib/conncache.c

@@ -49,53 +49,51 @@ static void conn_llist_dtor(void *user, void *element)
   conn->bundle = NULL;
   conn->bundle = NULL;
 }
 }
 
 
-static CURLcode bundle_create(struct Curl_easy *data,
-                              struct connectbundle **cb_ptr)
+static CURLcode bundle_create(struct connectbundle **bundlep)
 {
 {
-  (void)data;
-  DEBUGASSERT(*cb_ptr == NULL);
-  *cb_ptr = malloc(sizeof(struct connectbundle));
-  if(!*cb_ptr)
+  DEBUGASSERT(*bundlep == NULL);
+  *bundlep = malloc(sizeof(struct connectbundle));
+  if(!*bundlep)
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;
 
 
-  (*cb_ptr)->num_connections = 0;
-  (*cb_ptr)->multiuse = BUNDLE_UNKNOWN;
+  (*bundlep)->num_connections = 0;
+  (*bundlep)->multiuse = BUNDLE_UNKNOWN;
 
 
-  Curl_llist_init(&(*cb_ptr)->conn_list, (curl_llist_dtor) conn_llist_dtor);
+  Curl_llist_init(&(*bundlep)->conn_list, (curl_llist_dtor) conn_llist_dtor);
   return CURLE_OK;
   return CURLE_OK;
 }
 }
 
 
-static void bundle_destroy(struct connectbundle *cb_ptr)
+static void bundle_destroy(struct connectbundle *bundle)
 {
 {
-  if(!cb_ptr)
+  if(!bundle)
     return;
     return;
 
 
-  Curl_llist_destroy(&cb_ptr->conn_list, NULL);
+  Curl_llist_destroy(&bundle->conn_list, NULL);
 
 
-  free(cb_ptr);
+  free(bundle);
 }
 }
 
 
 /* Add a connection to a bundle */
 /* Add a connection to a bundle */
-static void bundle_add_conn(struct connectbundle *cb_ptr,
+static void bundle_add_conn(struct connectbundle *bundle,
                             struct connectdata *conn)
                             struct connectdata *conn)
 {
 {
-  Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn,
+  Curl_llist_insert_next(&bundle->conn_list, bundle->conn_list.tail, conn,
                          &conn->bundle_node);
                          &conn->bundle_node);
-  conn->bundle = cb_ptr;
-  cb_ptr->num_connections++;
+  conn->bundle = bundle;
+  bundle->num_connections++;
 }
 }
 
 
 /* Remove a connection from a bundle */
 /* Remove a connection from a bundle */
-static int bundle_remove_conn(struct connectbundle *cb_ptr,
+static int bundle_remove_conn(struct connectbundle *bundle,
                               struct connectdata *conn)
                               struct connectdata *conn)
 {
 {
   struct curl_llist_element *curr;
   struct curl_llist_element *curr;
 
 
-  curr = cb_ptr->conn_list.head;
+  curr = bundle->conn_list.head;
   while(curr) {
   while(curr) {
     if(curr->ptr == conn) {
     if(curr->ptr == conn) {
-      Curl_llist_remove(&cb_ptr->conn_list, curr, NULL);
-      cb_ptr->num_connections--;
+      Curl_llist_remove(&bundle->conn_list, curr, NULL);
+      bundle->num_connections--;
       conn->bundle = NULL;
       conn->bundle = NULL;
       return 1; /* we removed a handle */
       return 1; /* we removed a handle */
     }
     }
@@ -145,12 +143,15 @@ static void hashkey(struct connectdata *conn, char *buf,
   const char *hostname;
   const char *hostname;
   long port = conn->remote_port;
   long port = conn->remote_port;
 
 
+#ifndef CURL_DISABLE_PROXY
   if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
   if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
     hostname = conn->http_proxy.host.name;
     hostname = conn->http_proxy.host.name;
     port = conn->port;
     port = conn->port;
   }
   }
-  else if(conn->bits.conn_to_host)
-    hostname = conn->conn_to_host.name;
+  else
+#endif
+    if(conn->bits.conn_to_host)
+      hostname = conn->conn_to_host.name;
   else
   else
     hostname = conn->host.name;
     hostname = conn->host.name;
 
 
@@ -162,20 +163,15 @@ static void hashkey(struct connectdata *conn, char *buf,
   msnprintf(buf, len, "%ld%s", port, hostname);
   msnprintf(buf, len, "%ld%s", port, hostname);
 }
 }
 
 
-void Curl_conncache_unlock(struct Curl_easy *data)
-{
-  CONN_UNLOCK(data);
-}
-
 /* Returns number of connections currently held in the connection cache.
 /* Returns number of connections currently held in the connection cache.
    Locks/unlocks the cache itself!
    Locks/unlocks the cache itself!
 */
 */
 size_t Curl_conncache_size(struct Curl_easy *data)
 size_t Curl_conncache_size(struct Curl_easy *data)
 {
 {
   size_t num;
   size_t num;
-  CONN_LOCK(data);
+  CONNCACHE_LOCK(data);
   num = data->state.conn_cache->num_conn;
   num = data->state.conn_cache->num_conn;
-  CONN_UNLOCK(data);
+  CONNCACHE_UNLOCK(data);
   return num;
   return num;
 }
 }
 
 
@@ -188,7 +184,7 @@ struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
                                                  const char **hostp)
                                                  const char **hostp)
 {
 {
   struct connectbundle *bundle = NULL;
   struct connectbundle *bundle = NULL;
-  CONN_LOCK(conn->data);
+  CONNCACHE_LOCK(conn->data);
   if(connc) {
   if(connc) {
     char key[HASHKEY_SIZE];
     char key[HASHKEY_SIZE];
     hashkey(conn, key, sizeof(key), hostp);
     hashkey(conn, key, sizeof(key), hostp);
@@ -235,8 +231,7 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
                                  struct connectdata *conn)
                                  struct connectdata *conn)
 {
 {
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
-  struct connectbundle *bundle;
-  struct connectbundle *new_bundle = NULL;
+  struct connectbundle *bundle = NULL;
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
 
 
   /* *find_bundle() locks the connection cache */
   /* *find_bundle() locks the connection cache */
@@ -245,20 +240,19 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
     int rc;
     int rc;
     char key[HASHKEY_SIZE];
     char key[HASHKEY_SIZE];
 
 
-    result = bundle_create(data, &new_bundle);
+    result = bundle_create(&bundle);
     if(result) {
     if(result) {
       goto unlock;
       goto unlock;
     }
     }
 
 
     hashkey(conn, key, sizeof(key), NULL);
     hashkey(conn, key, sizeof(key), NULL);
-    rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle);
+    rc = conncache_add_bundle(data->state.conn_cache, key, bundle);
 
 
     if(!rc) {
     if(!rc) {
-      bundle_destroy(new_bundle);
+      bundle_destroy(bundle);
       result = CURLE_OUT_OF_MEMORY;
       result = CURLE_OUT_OF_MEMORY;
       goto unlock;
       goto unlock;
     }
     }
-    bundle = new_bundle;
   }
   }
 
 
   bundle_add_conn(bundle, conn);
   bundle_add_conn(bundle, conn);
@@ -270,15 +264,17 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
                conn->connection_id, connc->num_conn));
                conn->connection_id, connc->num_conn));
 
 
   unlock:
   unlock:
-  CONN_UNLOCK(data);
+  CONNCACHE_UNLOCK(data);
 
 
   return result;
   return result;
 }
 }
 
 
 /*
 /*
- * 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.
+ * Removes the connectdata object from the connection cache, but does *not*
+ * clear the conn->data association. The transfer still owns this connection.
+ *
+ * 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,
 void Curl_conncache_remove_conn(struct Curl_easy *data,
                                 struct connectdata *conn, bool lock)
                                 struct connectdata *conn, bool lock)
@@ -290,7 +286,7 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
      due to a failed connection attempt, before being added to a bundle */
      due to a failed connection attempt, before being added to a bundle */
   if(bundle) {
   if(bundle) {
     if(lock) {
     if(lock) {
-      CONN_LOCK(data);
+      CONNCACHE_LOCK(data);
     }
     }
     bundle_remove_conn(bundle, conn);
     bundle_remove_conn(bundle, conn);
     if(bundle->num_connections == 0)
     if(bundle->num_connections == 0)
@@ -301,9 +297,8 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
       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);
+      CONNCACHE_UNLOCK(data);
     }
     }
   }
   }
 }
 }
@@ -332,7 +327,7 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
   if(!connc)
   if(!connc)
     return FALSE;
     return FALSE;
 
 
-  CONN_LOCK(data);
+  CONNCACHE_LOCK(data);
   Curl_hash_start_iterate(&connc->hash, &iter);
   Curl_hash_start_iterate(&connc->hash, &iter);
 
 
   he = Curl_hash_next_element(&iter);
   he = Curl_hash_next_element(&iter);
@@ -350,12 +345,12 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
       curr = curr->next;
       curr = curr->next;
 
 
       if(1 == func(conn, param)) {
       if(1 == func(conn, param)) {
-        CONN_UNLOCK(data);
+        CONNCACHE_UNLOCK(data);
         return TRUE;
         return TRUE;
       }
       }
     }
     }
   }
   }
-  CONN_UNLOCK(data);
+  CONNCACHE_UNLOCK(data);
   return FALSE;
   return FALSE;
 }
 }
 
 
@@ -494,7 +489,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
 
 
   now = Curl_now();
   now = Curl_now();
 
 
-  CONN_LOCK(data);
+  CONNCACHE_LOCK(data);
   Curl_hash_start_iterate(&connc->hash, &iter);
   Curl_hash_start_iterate(&connc->hash, &iter);
 
 
   he = Curl_hash_next_element(&iter);
   he = Curl_hash_next_element(&iter);
@@ -531,7 +526,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
                  connc->num_conn));
                  connc->num_conn));
     conn_candidate->data = data; /* associate! */
     conn_candidate->data = data; /* associate! */
   }
   }
-  CONN_UNLOCK(data);
+  CONNCACHE_UNLOCK(data);
 
 
   return conn_candidate;
   return conn_candidate;
 }
 }
@@ -539,6 +534,11 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
 void Curl_conncache_close_all_connections(struct conncache *connc)
 void Curl_conncache_close_all_connections(struct conncache *connc)
 {
 {
   struct connectdata *conn;
   struct connectdata *conn;
+  char buffer[READBUFFER_MIN + 1];
+  if(!connc->closure_handle)
+    return;
+  connc->closure_handle->state.buffer = buffer;
+  connc->closure_handle->set.buffer_size = READBUFFER_MIN;
 
 
   conn = conncache_find_first_connection(connc);
   conn = conncache_find_first_connection(connc);
   while(conn) {
   while(conn) {
@@ -548,12 +548,14 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
     sigpipe_ignore(conn->data, &pipe_st);
     sigpipe_ignore(conn->data, &pipe_st);
     /* This will remove the connection from the cache */
     /* This will remove the connection from the cache */
     connclose(conn, "kill all");
     connclose(conn, "kill all");
+    Curl_conncache_remove_conn(conn->data, conn, TRUE);
     (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 = conncache_find_first_connection(connc);
     conn = conncache_find_first_connection(connc);
   }
   }
 
 
+  connc->closure_handle->state.buffer = NULL;
   if(connc->closure_handle) {
   if(connc->closure_handle) {
     SIGPIPE_VARIABLE(pipe_st);
     SIGPIPE_VARIABLE(pipe_st);
     sigpipe_ignore(connc->closure_handle, &pipe_st);
     sigpipe_ignore(connc->closure_handle, &pipe_st);

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

@@ -45,21 +45,21 @@ struct conncache {
 #ifdef CURLDEBUG
 #ifdef CURLDEBUG
 /* the debug versions of these macros make extra certain that the lock is
 /* the debug versions of these macros make extra certain that the lock is
    never doubly locked or unlocked */
    never doubly locked or unlocked */
-#define CONN_LOCK(x) if((x)->share) {                                   \
+#define CONNCACHE_LOCK(x) if((x)->share) {                              \
     Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \
     Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \
     DEBUGASSERT(!(x)->state.conncache_lock);                            \
     DEBUGASSERT(!(x)->state.conncache_lock);                            \
     (x)->state.conncache_lock = TRUE;                                   \
     (x)->state.conncache_lock = TRUE;                                   \
   }
   }
 
 
-#define CONN_UNLOCK(x) if((x)->share) {                                 \
+#define CONNCACHE_UNLOCK(x) if((x)->share) {                            \
     DEBUGASSERT((x)->state.conncache_lock);                             \
     DEBUGASSERT((x)->state.conncache_lock);                             \
     (x)->state.conncache_lock = FALSE;                                  \
     (x)->state.conncache_lock = FALSE;                                  \
     Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT);                     \
     Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT);                     \
   }
   }
 #else
 #else
-#define CONN_LOCK(x) if((x)->share)                                     \
+#define CONNCACHE_LOCK(x) if((x)->share)                                \
     Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
     Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
-#define CONN_UNLOCK(x) if((x)->share)                   \
+#define CONNCACHE_UNLOCK(x) if((x)->share)              \
     Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
     Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
 #endif
 #endif
 
 
@@ -77,7 +77,6 @@ void Curl_conncache_destroy(struct conncache *connc);
 struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
 struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
                                                  struct conncache *connc,
                                                  struct conncache *connc,
                                                  const char **hostp);
                                                  const char **hostp);
-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);
 
 

+ 153 - 144
Utilities/cmcurl/lib/connect.c

@@ -166,12 +166,13 @@ tcpkeepalive(struct Curl_easy *data,
 
 
 static CURLcode
 static CURLcode
 singleipconnect(struct connectdata *conn,
 singleipconnect(struct connectdata *conn,
-                const Curl_addrinfo *ai, /* start connecting to this */
-                int sockindex);          /* 0 or 1 among the temp ones */
+                const struct Curl_addrinfo *ai, /* start connecting to this */
+                int tempindex);          /* 0 or 1 among the temp ones */
 
 
 /*
 /*
  * Curl_timeleft() returns the amount of milliseconds left allowed for the
  * Curl_timeleft() returns the amount of milliseconds left allowed for the
- * transfer/connection. If the value is negative, the timeout time has already
+ * transfer/connection. If the value is 0, there's no timeout (ie there's
+ * infinite time left). If the value is negative, the timeout time has already
  * elapsed.
  * elapsed.
  *
  *
  * The start time is stored in progress.t_startsingle - as set with
  * The start time is stored in progress.t_startsingle - as set with
@@ -555,13 +556,27 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
   return rc;
   return rc;
 }
 }
 
 
-/* Used within the multi interface. Try next IP address, return TRUE if no
+/* update tempaddr[tempindex] (to the next entry), makes sure to stick
+   to the correct family */
+static struct Curl_addrinfo *ainext(struct connectdata *conn,
+                                    int tempindex,
+                                    bool next) /* use next entry? */
+{
+  struct Curl_addrinfo *ai = conn->tempaddr[tempindex];
+  if(ai && next)
+    ai = ai->ai_next;
+  while(ai && (ai->ai_family != conn->tempfamily[tempindex]))
+    ai = ai->ai_next;
+  conn->tempaddr[tempindex] = ai;
+  return ai;
+}
+
+/* Used within the multi interface. Try next IP address, returns error if no
    more address exists or error */
    more address exists or error */
 static CURLcode trynextip(struct connectdata *conn,
 static CURLcode trynextip(struct connectdata *conn,
                           int sockindex,
                           int sockindex,
                           int tempindex)
                           int tempindex)
 {
 {
-  const int other = tempindex ^ 1;
   CURLcode result = CURLE_COULDNT_CONNECT;
   CURLcode result = CURLE_COULDNT_CONNECT;
 
 
   /* First clean up after the failed socket.
   /* First clean up after the failed socket.
@@ -572,38 +587,15 @@ static CURLcode trynextip(struct connectdata *conn,
   conn->tempsock[tempindex] = CURL_SOCKET_BAD;
   conn->tempsock[tempindex] = CURL_SOCKET_BAD;
 
 
   if(sockindex == FIRSTSOCKET) {
   if(sockindex == FIRSTSOCKET) {
-    Curl_addrinfo *ai = NULL;
-    int family = AF_UNSPEC;
-
-    if(conn->tempaddr[tempindex]) {
-      /* find next address in the same protocol family */
-      family = conn->tempaddr[tempindex]->ai_family;
-      ai = conn->tempaddr[tempindex]->ai_next;
-    }
-#ifdef ENABLE_IPV6
-    else if(conn->tempaddr[0]) {
-      /* happy eyeballs - try the other protocol family */
-      int firstfamily = conn->tempaddr[0]->ai_family;
-      family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
-      ai = conn->tempaddr[0]->ai_next;
-    }
-#endif
+    struct Curl_addrinfo *ai = conn->tempaddr[tempindex];
 
 
     while(ai) {
     while(ai) {
-      if(conn->tempaddr[other]) {
-        /* we can safely skip addresses of the other protocol family */
-        while(ai && ai->ai_family != family)
-          ai = ai->ai_next;
-      }
-
       if(ai) {
       if(ai) {
         result = singleipconnect(conn, ai, tempindex);
         result = singleipconnect(conn, ai, tempindex);
         if(result == CURLE_COULDNT_CONNECT) {
         if(result == CURLE_COULDNT_CONNECT) {
-          ai = ai->ai_next;
+          ai = ainext(conn, tempindex, TRUE);
           continue;
           continue;
         }
         }
-
-        conn->tempaddr[tempindex] = ai;
       }
       }
       break;
       break;
     }
     }
@@ -688,58 +680,56 @@ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen,
    connection */
    connection */
 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
 {
 {
-  if(conn->transport != TRNSPRT_TCP)
-    /* there's no TCP connection! */
-    return;
-
+  if(conn->transport == TRNSPRT_TCP) {
 #if defined(HAVE_GETPEERNAME) || defined(HAVE_GETSOCKNAME)
 #if defined(HAVE_GETPEERNAME) || defined(HAVE_GETSOCKNAME)
-  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 plen;
-    curl_socklen_t slen;
+    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 plen;
+      curl_socklen_t slen;
 #ifdef HAVE_GETPEERNAME
 #ifdef HAVE_GETPEERNAME
-    plen = sizeof(struct Curl_sockaddr_storage);
-    if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) {
-      int error = SOCKERRNO;
-      failf(data, "getpeername() failed with errno %d: %s",
-            error, Curl_strerror(error, buffer, sizeof(buffer)));
-      return;
-    }
+      plen = sizeof(struct Curl_sockaddr_storage);
+      if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) {
+        int error = SOCKERRNO;
+        failf(data, "getpeername() failed with errno %d: %s",
+              error, Curl_strerror(error, buffer, sizeof(buffer)));
+        return;
+      }
 #endif
 #endif
 #ifdef HAVE_GETSOCKNAME
 #ifdef HAVE_GETSOCKNAME
-    slen = sizeof(struct Curl_sockaddr_storage);
-    memset(&ssloc, 0, sizeof(ssloc));
-    if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) {
-      int error = SOCKERRNO;
-      failf(data, "getsockname() failed with errno %d: %s",
-            error, Curl_strerror(error, buffer, sizeof(buffer)));
-      return;
-    }
+      slen = sizeof(struct Curl_sockaddr_storage);
+      memset(&ssloc, 0, sizeof(ssloc));
+      if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) {
+        int error = SOCKERRNO;
+        failf(data, "getsockname() failed with errno %d: %s",
+              error, Curl_strerror(error, buffer, sizeof(buffer)));
+        return;
+      }
 #endif
 #endif
 #ifdef HAVE_GETPEERNAME
 #ifdef HAVE_GETPEERNAME
-    if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
-                         conn->primary_ip, &conn->primary_port)) {
-      failf(data, "ssrem inet_ntop() failed with errno %d: %s",
-            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
-      return;
-    }
-    memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
+      if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
+                           conn->primary_ip, &conn->primary_port)) {
+        failf(data, "ssrem inet_ntop() failed with errno %d: %s",
+              errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+        return;
+      }
+      memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
 #endif
 #endif
 #ifdef HAVE_GETSOCKNAME
 #ifdef HAVE_GETSOCKNAME
-    if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
-                         conn->local_ip, &conn->local_port)) {
-      failf(data, "ssloc inet_ntop() failed with errno %d: %s",
-            errno, Curl_strerror(errno, buffer, sizeof(buffer)));
-      return;
-    }
+      if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
+                           conn->local_ip, &conn->local_port)) {
+        failf(data, "ssloc inet_ntop() failed with errno %d: %s",
+              errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+        return;
+      }
 #endif
 #endif
-  }
+    }
 #else /* !HAVE_GETSOCKNAME && !HAVE_GETPEERNAME */
 #else /* !HAVE_GETSOCKNAME && !HAVE_GETPEERNAME */
-  (void)sockfd; /* unused */
+    (void)sockfd; /* unused */
 #endif
 #endif
+  } /* end of TCP-only section */
 
 
   /* persist connection info in session handle */
   /* persist connection info in session handle */
   Curl_persistconninfo(conn);
   Curl_persistconninfo(conn);
@@ -757,8 +747,8 @@ static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
 {
 {
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
 
 
-  if(conn->bits.socksproxy) {
 #ifndef CURL_DISABLE_PROXY
 #ifndef CURL_DISABLE_PROXY
+  if(conn->bits.socksproxy) {
     /* for the secondary socket (FTP), use the "connect to host"
     /* for the secondary socket (FTP), use the "connect to host"
      * but ignore the "connect to port" (use the secondary port)
      * but ignore the "connect to port" (use the secondary port)
      */
      */
@@ -791,11 +781,12 @@ static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
       failf(conn->data, "unknown proxytype option given");
       failf(conn->data, "unknown proxytype option given");
       result = CURLE_COULDNT_CONNECT;
       result = CURLE_COULDNT_CONNECT;
     } /* switch proxytype */
     } /* switch proxytype */
-#else
-  (void)sockindex;
-#endif /* CURL_DISABLE_PROXY */
   }
   }
   else
   else
+#else
+    (void)conn;
+    (void)sockindex;
+#endif /* CURL_DISABLE_PROXY */
     *done = TRUE; /* no SOCKS proxy, so consider us connected */
     *done = TRUE; /* no SOCKS proxy, so consider us connected */
 
 
   return result;
   return result;
@@ -816,6 +807,7 @@ static void post_SOCKS(struct connectdata *conn,
     Curl_pgrsTime(conn->data, TIMER_CONNECT); /* connect done */
     Curl_pgrsTime(conn->data, TIMER_CONNECT); /* connect done */
   Curl_updateconninfo(conn, conn->sock[sockindex]);
   Curl_updateconninfo(conn, conn->sock[sockindex]);
   Curl_verboseconnect(conn);
   Curl_verboseconnect(conn);
+  conn->data->info.numconnects++; /* to track the number of connections made */
 }
 }
 
 
 /*
 /*
@@ -831,8 +823,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
   timediff_t allow;
   timediff_t allow;
   int error = 0;
   int error = 0;
   struct curltime now;
   struct curltime now;
-  int rc;
-  int i;
+  int rc = 0;
+  unsigned int i;
 
 
   DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
   DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
 
 
@@ -867,47 +859,50 @@ CURLcode Curl_is_connected(struct connectdata *conn,
     const int other = i ^ 1;
     const int other = i ^ 1;
     if(conn->tempsock[i] == CURL_SOCKET_BAD)
     if(conn->tempsock[i] == CURL_SOCKET_BAD)
       continue;
       continue;
-
+    error = 0;
 #ifdef ENABLE_QUIC
 #ifdef ENABLE_QUIC
     if(conn->transport == TRNSPRT_QUIC) {
     if(conn->transport == TRNSPRT_QUIC) {
       result = Curl_quic_is_connected(conn, i, connected);
       result = Curl_quic_is_connected(conn, i, connected);
-      if(result) {
-        error = SOCKERRNO;
-        goto error;
-      }
-      if(*connected) {
+      if(!result && *connected) {
         /* use this socket from now on */
         /* use this socket from now on */
         conn->sock[sockindex] = conn->tempsock[i];
         conn->sock[sockindex] = conn->tempsock[i];
         conn->ip_addr = conn->tempaddr[i];
         conn->ip_addr = conn->tempaddr[i];
         conn->tempsock[i] = CURL_SOCKET_BAD;
         conn->tempsock[i] = CURL_SOCKET_BAD;
+        post_SOCKS(conn, sockindex, connected);
         connkeep(conn, "HTTP/3 default");
         connkeep(conn, "HTTP/3 default");
+        return CURLE_OK;
       }
       }
-      return result;
+      if(result)
+        error = SOCKERRNO;
     }
     }
+    else
 #endif
 #endif
-
+    {
 #ifdef mpeix
 #ifdef mpeix
-    /* Call this function once now, and ignore the results. We do this to
-       "clear" the error state on the socket so that we can later read it
-       reliably. This is reported necessary on the MPE/iX operating system. */
-    (void)verifyconnect(conn->tempsock[i], NULL);
+      /* Call this function once now, and ignore the results. We do this to
+         "clear" the error state on the socket so that we can later read it
+         reliably. This is reported necessary on the MPE/iX operating
+         system. */
+      (void)verifyconnect(conn->tempsock[i], NULL);
 #endif
 #endif
 
 
-    /* check socket for connect */
-    rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
+      /* check socket for connect */
+      rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
+    }
 
 
     if(rc == 0) { /* no connection yet */
     if(rc == 0) { /* no connection yet */
-      error = 0;
-      if(Curl_timediff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
+      if(Curl_timediff(now, conn->connecttime) >=
+         conn->timeoutms_per_addr[i]) {
         infof(data, "After %" CURL_FORMAT_TIMEDIFF_T
         infof(data, "After %" CURL_FORMAT_TIMEDIFF_T
-              "ms connect time, move on!\n", conn->timeoutms_per_addr);
+              "ms connect time, move on!\n", conn->timeoutms_per_addr[i]);
         error = ETIMEDOUT;
         error = ETIMEDOUT;
       }
       }
 
 
       /* should we try another protocol family? */
       /* should we try another protocol family? */
-      if(i == 0 && conn->tempaddr[1] == NULL &&
+      if(i == 0 && !conn->bits.parallel_connect &&
          (Curl_timediff(now, conn->connecttime) >=
          (Curl_timediff(now, conn->connecttime) >=
           data->set.happy_eyeballs_timeout)) {
           data->set.happy_eyeballs_timeout)) {
+        conn->bits.parallel_connect = TRUE; /* starting now */
         trynextip(conn, sockindex, 1);
         trynextip(conn, sockindex, 1);
       }
       }
     }
     }
@@ -944,9 +939,6 @@ CURLcode Curl_is_connected(struct connectdata *conn,
     else if(rc & CURL_CSELECT_ERR)
     else if(rc & CURL_CSELECT_ERR)
       (void)verifyconnect(conn->tempsock[i], &error);
       (void)verifyconnect(conn->tempsock[i], &error);
 
 
-#ifdef ENABLE_QUIC
-    error:
-#endif
     /*
     /*
      * The connection failed here, we should attempt to connect to the "next
      * The connection failed here, we should attempt to connect to the "next
      * address" for the given host. But first remember the latest error.
      * address" for the given host. But first remember the latest error.
@@ -959,15 +951,16 @@ CURLcode Curl_is_connected(struct connectdata *conn,
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
         char ipaddress[MAX_IPADR_LEN];
         char ipaddress[MAX_IPADR_LEN];
         char buffer[STRERROR_LEN];
         char buffer[STRERROR_LEN];
-        Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
-#endif
+        Curl_printable_address(conn->tempaddr[i], ipaddress,
+                               sizeof(ipaddress));
         infof(data, "connect to %s port %ld failed: %s\n",
         infof(data, "connect to %s port %ld failed: %s\n",
               ipaddress, conn->port,
               ipaddress, conn->port,
               Curl_strerror(error, buffer, sizeof(buffer)));
               Curl_strerror(error, buffer, sizeof(buffer)));
+#endif
 
 
-        conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
+        conn->timeoutms_per_addr[i] = conn->tempaddr[i]->ai_next == NULL ?
           allow : allow / 2;
           allow : allow / 2;
-
+        ainext(conn, i, TRUE);
         status = trynextip(conn, sockindex, i);
         status = trynextip(conn, sockindex, i);
         if((status != CURLE_COULDNT_CONNECT) ||
         if((status != CURLE_COULDNT_CONNECT) ||
            conn->tempsock[other] == CURL_SOCKET_BAD)
            conn->tempsock[other] == CURL_SOCKET_BAD)
@@ -977,25 +970,28 @@ CURLcode Curl_is_connected(struct connectdata *conn,
     }
     }
   }
   }
 
 
-  if(result) {
+  if(result &&
+     (conn->tempsock[0] == CURL_SOCKET_BAD) &&
+     (conn->tempsock[1] == CURL_SOCKET_BAD)) {
     /* no more addresses to try */
     /* no more addresses to try */
     const char *hostname;
     const char *hostname;
     char buffer[STRERROR_LEN];
     char buffer[STRERROR_LEN];
 
 
-    /* if the first address family runs out of addresses to try before
-       the happy eyeball timeout, go ahead and try the next family now */
-    if(conn->tempaddr[1] == NULL) {
-      result = trynextip(conn, sockindex, 1);
-      if(!result)
-        return result;
-    }
+    /* if the first address family runs out of addresses to try before the
+       happy eyeball timeout, go ahead and try the next family now */
+    result = trynextip(conn, sockindex, 1);
+    if(!result)
+      return result;
 
 
+#ifndef CURL_DISABLE_PROXY
     if(conn->bits.socksproxy)
     if(conn->bits.socksproxy)
       hostname = conn->socks_proxy.host.name;
       hostname = conn->socks_proxy.host.name;
     else if(conn->bits.httpproxy)
     else if(conn->bits.httpproxy)
       hostname = conn->http_proxy.host.name;
       hostname = conn->http_proxy.host.name;
-    else if(conn->bits.conn_to_host)
-      hostname = conn->conn_to_host.name;
+    else
+#endif
+      if(conn->bits.conn_to_host)
+        hostname = conn->conn_to_host.name;
     else
     else
       hostname = conn->host.name;
       hostname = conn->host.name;
 
 
@@ -1003,6 +999,9 @@ CURLcode Curl_is_connected(struct connectdata *conn,
           hostname, conn->port,
           hostname, conn->port,
           Curl_strerror(error, buffer, sizeof(buffer)));
           Curl_strerror(error, buffer, sizeof(buffer)));
 
 
+    Curl_quic_disconnect(conn, 0);
+    Curl_quic_disconnect(conn, 1);
+
 #ifdef WSAETIMEDOUT
 #ifdef WSAETIMEDOUT
     if(WSAETIMEDOUT == data->state.os_errno)
     if(WSAETIMEDOUT == data->state.os_errno)
       result = CURLE_OPERATION_TIMEDOUT;
       result = CURLE_OPERATION_TIMEDOUT;
@@ -1011,6 +1010,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
       result = CURLE_OPERATION_TIMEDOUT;
       result = CURLE_OPERATION_TIMEDOUT;
 #endif
 #endif
   }
   }
+  else
+    result = CURLE_OK; /* still trying */
 
 
   return result;
   return result;
 }
 }
@@ -1112,8 +1113,8 @@ void Curl_sndbufset(curl_socket_t sockfd)
  * having connected.
  * having connected.
  */
  */
 static CURLcode singleipconnect(struct connectdata *conn,
 static CURLcode singleipconnect(struct connectdata *conn,
-                                const Curl_addrinfo *ai,
-                                int sockindex)
+                                const struct Curl_addrinfo *ai,
+                                int tempindex)
 {
 {
   struct Curl_sockaddr_ex addr;
   struct Curl_sockaddr_ex addr;
   int rc = -1;
   int rc = -1;
@@ -1129,15 +1130,12 @@ static CURLcode singleipconnect(struct connectdata *conn,
   int optval = 1;
   int optval = 1;
 #endif
 #endif
   char buffer[STRERROR_LEN];
   char buffer[STRERROR_LEN];
-  curl_socket_t *sockp = &conn->tempsock[sockindex];
+  curl_socket_t *sockp = &conn->tempsock[tempindex];
   *sockp = CURL_SOCKET_BAD;
   *sockp = CURL_SOCKET_BAD;
 
 
   result = Curl_socket(conn, ai, &addr, &sockfd);
   result = Curl_socket(conn, ai, &addr, &sockfd);
   if(result)
   if(result)
-    /* Failed to create the socket, but still return OK since we signal the
-       lack of socket as well. This allows the parent function to keep looping
-       over alternative addresses/socket families etc. */
-    return CURLE_OK;
+    return result;
 
 
   /* store remote address and port used in this connection attempt */
   /* store remote address and port used in this connection attempt */
   if(!Curl_addr2string((struct sockaddr*)&addr.sa_addr, addr.addrlen,
   if(!Curl_addr2string((struct sockaddr*)&addr.sa_addr, addr.addrlen,
@@ -1205,8 +1203,10 @@ static CURLcode singleipconnect(struct connectdata *conn,
   (void)curlx_nonblock(sockfd, TRUE);
   (void)curlx_nonblock(sockfd, TRUE);
 
 
   conn->connecttime = Curl_now();
   conn->connecttime = Curl_now();
-  if(conn->num_addr > 1)
-    Curl_expire(data, conn->timeoutms_per_addr, EXPIRE_DNS_PER_NAME);
+  if(conn->num_addr > 1) {
+    Curl_expire(data, conn->timeoutms_per_addr[0], EXPIRE_DNS_PER_NAME);
+    Curl_expire(data, conn->timeoutms_per_addr[1], EXPIRE_DNS_PER_NAME2);
+  }
 
 
   /* Connect TCP and QUIC sockets */
   /* Connect TCP and QUIC sockets */
   if(!isconnected && (conn->transport != TRNSPRT_UDP)) {
   if(!isconnected && (conn->transport != TRNSPRT_UDP)) {
@@ -1257,7 +1257,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
     else if(conn->transport == TRNSPRT_QUIC) {
     else if(conn->transport == TRNSPRT_QUIC) {
       /* pass in 'sockfd' separately since it hasn't been put into the
       /* pass in 'sockfd' separately since it hasn't been put into the
          tempsock array at this point */
          tempsock array at this point */
-      result = Curl_quic_connect(conn, sockfd, sockindex,
+      result = Curl_quic_connect(conn, sockfd, tempindex,
                                  &addr.sa_addr, addr.addrlen);
                                  &addr.sa_addr, addr.addrlen);
       if(result)
       if(result)
         error = SOCKERRNO;
         error = SOCKERRNO;
@@ -1315,7 +1315,7 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
   struct curltime before = Curl_now();
   struct curltime before = Curl_now();
   CURLcode result = CURLE_COULDNT_CONNECT;
   CURLcode result = CURLE_COULDNT_CONNECT;
-
+  int i;
   timediff_t timeout_ms = Curl_timeleft(data, &before, TRUE);
   timediff_t timeout_ms = Curl_timeleft(data, &before, TRUE);
 
 
   if(timeout_ms < 0) {
   if(timeout_ms < 0) {
@@ -1325,30 +1325,37 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
   }
   }
 
 
   conn->num_addr = Curl_num_addresses(remotehost->addr);
   conn->num_addr = Curl_num_addresses(remotehost->addr);
-  conn->tempaddr[0] = remotehost->addr;
-  conn->tempaddr[1] = NULL;
-  conn->tempsock[0] = CURL_SOCKET_BAD;
-  conn->tempsock[1] = CURL_SOCKET_BAD;
+  conn->tempaddr[0] = conn->tempaddr[1] = remotehost->addr;
+  conn->tempsock[0] = conn->tempsock[1] = CURL_SOCKET_BAD;
 
 
   /* Max time for the next connection attempt */
   /* Max time for the next connection attempt */
-  conn->timeoutms_per_addr =
+  conn->timeoutms_per_addr[0] =
     conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
     conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
-
-  /* start connecting to first IP */
-  while(conn->tempaddr[0]) {
-    result = singleipconnect(conn, conn->tempaddr[0], 0);
-    if(!result)
-      break;
-    conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
+  conn->timeoutms_per_addr[1] =
+    conn->tempaddr[1]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
+
+  conn->tempfamily[0] = conn->tempaddr[0]?
+    conn->tempaddr[0]->ai_family:0;
+  conn->tempfamily[1] = conn->tempfamily[0] == AF_INET6 ?
+    AF_INET : AF_INET6;
+  ainext(conn, 1, FALSE); /* assigns conn->tempaddr[1] accordingly */
+
+  DEBUGF(infof(data, "family0 == %s, family1 == %s\n",
+               conn->tempfamily[0] == AF_INET ? "v4" : "v6",
+               conn->tempfamily[1] == AF_INET ? "v4" : "v6"));
+
+  /* get through the list in family order in case of quick failures */
+  for(i = 0; (i < 2) && result; i++) {
+    while(conn->tempaddr[i]) {
+      result = singleipconnect(conn, conn->tempaddr[i], i);
+      if(!result)
+        break;
+      ainext(conn, i, TRUE);
+    }
   }
   }
-
-  if(conn->tempsock[0] == CURL_SOCKET_BAD) {
-    if(!result)
-      result = CURLE_COULDNT_CONNECT;
+  if(result)
     return result;
     return result;
-  }
 
 
-  data->info.numconnects++; /* to track the number of connections made */
   Curl_expire(conn->data, data->set.happy_eyeballs_timeout,
   Curl_expire(conn->data, data->set.happy_eyeballs_timeout,
               EXPIRE_HAPPY_EYEBALLS);
               EXPIRE_HAPPY_EYEBALLS);
 
 
@@ -1448,11 +1455,11 @@ int Curl_closesocket(struct connectdata *conn,
                       curl_socket_t sock)
                       curl_socket_t sock)
 {
 {
   if(conn && conn->fclosesocket) {
   if(conn && conn->fclosesocket) {
-    if((sock == conn->sock[SECONDARYSOCKET]) && conn->sock_accepted)
+    if((sock == conn->sock[SECONDARYSOCKET]) && conn->bits.sock_accepted)
       /* if this socket matches the second socket, and that was created with
       /* if this socket matches the second socket, and that was created with
          accept, then we MUST NOT call the callback but clear the accepted
          accept, then we MUST NOT call the callback but clear the accepted
          status */
          status */
-      conn->sock_accepted = FALSE;
+      conn->bits.sock_accepted = FALSE;
     else {
     else {
       int rc;
       int rc;
       Curl_multi_closed(conn->data, sock);
       Curl_multi_closed(conn->data, sock);
@@ -1482,7 +1489,7 @@ int Curl_closesocket(struct connectdata *conn,
  *
  *
  */
  */
 CURLcode Curl_socket(struct connectdata *conn,
 CURLcode Curl_socket(struct connectdata *conn,
-                     const Curl_addrinfo *ai,
+                     const struct Curl_addrinfo *ai,
                      struct Curl_sockaddr_ex *addr,
                      struct Curl_sockaddr_ex *addr,
                      curl_socket_t *sockfd)
                      curl_socket_t *sockfd)
 {
 {
@@ -1564,6 +1571,7 @@ void Curl_conncontrol(struct connectdata *conn,
   /* close if a connection, or a stream that isn't multiplexed */
   /* close if a connection, or a stream that isn't multiplexed */
   bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
   bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
     ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
     ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
+  DEBUGASSERT(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));
@@ -1579,6 +1587,7 @@ void Curl_conncontrol(struct connectdata *conn,
 bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
 bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
 {
 {
   int readable;
   int readable;
+  DEBUGASSERT(conn);
 
 
   if(Curl_ssl_data_pending(conn, sockindex) ||
   if(Curl_ssl_data_pending(conn, sockindex) ||
      Curl_recv_has_postponed_data(conn, sockindex))
      Curl_recv_has_postponed_data(conn, sockindex))

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

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -105,7 +105,7 @@ struct Curl_sockaddr_ex {
  *
  *
  */
  */
 CURLcode Curl_socket(struct connectdata *conn,
 CURLcode Curl_socket(struct connectdata *conn,
-                     const Curl_addrinfo *ai,
+                     const struct Curl_addrinfo *ai,
                      struct Curl_sockaddr_ex *addr,
                      struct Curl_sockaddr_ex *addr,
                      curl_socket_t *sockfd);
                      curl_socket_t *sockfd);
 
 

+ 66 - 64
Utilities/cmcurl/lib/content_encoding.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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,11 +81,11 @@ typedef enum {
 } zlibInitState;
 } zlibInitState;
 
 
 /* Writer parameters. */
 /* Writer parameters. */
-typedef struct {
+struct zlib_params {
   zlibInitState zlib_init;   /* zlib init state */
   zlibInitState zlib_init;   /* zlib init state */
   uInt trailerlen;           /* Remaining trailer byte count. */
   uInt trailerlen;           /* Remaining trailer byte count. */
   z_stream z;                /* State structure for zlib. */
   z_stream z;                /* State structure for zlib. */
-}  zlib_params;
+};
 
 
 
 
 static voidpf
 static voidpf
@@ -133,7 +133,8 @@ exit_zlib(struct connectdata *conn,
   return result;
   return result;
 }
 }
 
 
-static CURLcode process_trailer(struct connectdata *conn, zlib_params *zp)
+static CURLcode process_trailer(struct connectdata *conn,
+                                struct zlib_params *zp)
 {
 {
   z_stream *z = &zp->z;
   z_stream *z = &zp->z;
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
@@ -157,9 +158,10 @@ static CURLcode process_trailer(struct connectdata *conn, zlib_params *zp)
 }
 }
 
 
 static CURLcode inflate_stream(struct connectdata *conn,
 static CURLcode inflate_stream(struct connectdata *conn,
-                               contenc_writer *writer, zlibInitState started)
+                               struct contenc_writer *writer,
+                               zlibInitState started)
 {
 {
-  zlib_params *zp = (zlib_params *) &writer->params;
+  struct zlib_params *zp = (struct zlib_params *) &writer->params;
   z_stream *z = &zp->z;         /* zlib state structure */
   z_stream *z = &zp->z;         /* zlib state structure */
   uInt nread = z->avail_in;
   uInt nread = z->avail_in;
   Bytef *orig_in = z->next_in;
   Bytef *orig_in = z->next_in;
@@ -259,9 +261,9 @@ static CURLcode inflate_stream(struct connectdata *conn,
 
 
 /* Deflate handler. */
 /* Deflate handler. */
 static CURLcode deflate_init_writer(struct connectdata *conn,
 static CURLcode deflate_init_writer(struct connectdata *conn,
-                                    contenc_writer *writer)
+                                    struct contenc_writer *writer)
 {
 {
-  zlib_params *zp = (zlib_params *) &writer->params;
+  struct zlib_params *zp = (struct zlib_params *) &writer->params;
   z_stream *z = &zp->z;     /* zlib state structure */
   z_stream *z = &zp->z;     /* zlib state structure */
 
 
   if(!writer->downstream)
   if(!writer->downstream)
@@ -278,10 +280,10 @@ static CURLcode deflate_init_writer(struct connectdata *conn,
 }
 }
 
 
 static CURLcode deflate_unencode_write(struct connectdata *conn,
 static CURLcode deflate_unencode_write(struct connectdata *conn,
-                                       contenc_writer *writer,
+                                       struct contenc_writer *writer,
                                        const char *buf, size_t nbytes)
                                        const char *buf, size_t nbytes)
 {
 {
-  zlib_params *zp = (zlib_params *) &writer->params;
+  struct zlib_params *zp = (struct zlib_params *) &writer->params;
   z_stream *z = &zp->z;     /* zlib state structure */
   z_stream *z = &zp->z;     /* zlib state structure */
 
 
   /* Set the compressed input when this function is called */
   /* Set the compressed input when this function is called */
@@ -296,29 +298,29 @@ static CURLcode deflate_unencode_write(struct connectdata *conn,
 }
 }
 
 
 static void deflate_close_writer(struct connectdata *conn,
 static void deflate_close_writer(struct connectdata *conn,
-                                 contenc_writer *writer)
+                                 struct contenc_writer *writer)
 {
 {
-  zlib_params *zp = (zlib_params *) &writer->params;
+  struct zlib_params *zp = (struct zlib_params *) &writer->params;
   z_stream *z = &zp->z;     /* zlib state structure */
   z_stream *z = &zp->z;     /* zlib state structure */
 
 
   exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
   exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
 }
 }
 
 
-static const content_encoding deflate_encoding = {
+static const struct content_encoding deflate_encoding = {
   "deflate",
   "deflate",
   NULL,
   NULL,
   deflate_init_writer,
   deflate_init_writer,
   deflate_unencode_write,
   deflate_unencode_write,
   deflate_close_writer,
   deflate_close_writer,
-  sizeof(zlib_params)
+  sizeof(struct zlib_params)
 };
 };
 
 
 
 
 /* Gzip handler. */
 /* Gzip handler. */
 static CURLcode gzip_init_writer(struct connectdata *conn,
 static CURLcode gzip_init_writer(struct connectdata *conn,
-                                 contenc_writer *writer)
+                                 struct contenc_writer *writer)
 {
 {
-  zlib_params *zp = (zlib_params *) &writer->params;
+  struct zlib_params *zp = (struct zlib_params *) &writer->params;
   z_stream *z = &zp->z;     /* zlib state structure */
   z_stream *z = &zp->z;     /* zlib state structure */
 
 
   if(!writer->downstream)
   if(!writer->downstream)
@@ -432,10 +434,10 @@ static enum {
 #endif
 #endif
 
 
 static CURLcode gzip_unencode_write(struct connectdata *conn,
 static CURLcode gzip_unencode_write(struct connectdata *conn,
-                                    contenc_writer *writer,
+                                    struct contenc_writer *writer,
                                     const char *buf, size_t nbytes)
                                     const char *buf, size_t nbytes)
 {
 {
-  zlib_params *zp = (zlib_params *) &writer->params;
+  struct zlib_params *zp = (struct zlib_params *) &writer->params;
   z_stream *z = &zp->z;     /* zlib state structure */
   z_stream *z = &zp->z;     /* zlib state structure */
 
 
   if(zp->zlib_init == ZLIB_INIT_GZIP) {
   if(zp->zlib_init == ZLIB_INIT_GZIP) {
@@ -560,33 +562,31 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
 }
 }
 
 
 static void gzip_close_writer(struct connectdata *conn,
 static void gzip_close_writer(struct connectdata *conn,
-                              contenc_writer *writer)
+                              struct contenc_writer *writer)
 {
 {
-  zlib_params *zp = (zlib_params *) &writer->params;
+  struct zlib_params *zp = (struct zlib_params *) &writer->params;
   z_stream *z = &zp->z;     /* zlib state structure */
   z_stream *z = &zp->z;     /* zlib state structure */
 
 
   exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
   exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
 }
 }
 
 
-static const content_encoding gzip_encoding = {
+static const struct content_encoding gzip_encoding = {
   "gzip",
   "gzip",
   "x-gzip",
   "x-gzip",
   gzip_init_writer,
   gzip_init_writer,
   gzip_unencode_write,
   gzip_unencode_write,
   gzip_close_writer,
   gzip_close_writer,
-  sizeof(zlib_params)
+  sizeof(struct zlib_params)
 };
 };
 
 
 #endif /* HAVE_LIBZ */
 #endif /* HAVE_LIBZ */
 
 
 
 
 #ifdef HAVE_BROTLI
 #ifdef HAVE_BROTLI
-
 /* Writer parameters. */
 /* Writer parameters. */
-typedef struct {
+struct brotli_params {
   BrotliDecoderState *br;    /* State structure for brotli. */
   BrotliDecoderState *br;    /* State structure for brotli. */
-}  brotli_params;
-
+};
 
 
 static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
 static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
 {
 {
@@ -627,10 +627,9 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
 }
 }
 
 
 static CURLcode brotli_init_writer(struct connectdata *conn,
 static CURLcode brotli_init_writer(struct connectdata *conn,
-                                   contenc_writer *writer)
+                                   struct contenc_writer *writer)
 {
 {
-  brotli_params *bp = (brotli_params *) &writer->params;
-
+  struct brotli_params *bp = (struct brotli_params *) &writer->params;
   (void) conn;
   (void) conn;
 
 
   if(!writer->downstream)
   if(!writer->downstream)
@@ -641,10 +640,10 @@ static CURLcode brotli_init_writer(struct connectdata *conn,
 }
 }
 
 
 static CURLcode brotli_unencode_write(struct connectdata *conn,
 static CURLcode brotli_unencode_write(struct connectdata *conn,
-                                      contenc_writer *writer,
+                                      struct contenc_writer *writer,
                                       const char *buf, size_t nbytes)
                                       const char *buf, size_t nbytes)
 {
 {
-  brotli_params *bp = (brotli_params *) &writer->params;
+  struct brotli_params *bp = (struct brotli_params *) &writer->params;
   const uint8_t *src = (const uint8_t *) buf;
   const uint8_t *src = (const uint8_t *) buf;
   char *decomp;
   char *decomp;
   uint8_t *dst;
   uint8_t *dst;
@@ -689,10 +688,9 @@ static CURLcode brotli_unencode_write(struct connectdata *conn,
 }
 }
 
 
 static void brotli_close_writer(struct connectdata *conn,
 static void brotli_close_writer(struct connectdata *conn,
-                                contenc_writer *writer)
+                                struct contenc_writer *writer)
 {
 {
-  brotli_params *bp = (brotli_params *) &writer->params;
-
+  struct brotli_params *bp = (struct brotli_params *) &writer->params;
   (void) conn;
   (void) conn;
 
 
   if(bp->br) {
   if(bp->br) {
@@ -701,40 +699,40 @@ static void brotli_close_writer(struct connectdata *conn,
   }
   }
 }
 }
 
 
-static const content_encoding brotli_encoding = {
+static const struct content_encoding brotli_encoding = {
   "br",
   "br",
   NULL,
   NULL,
   brotli_init_writer,
   brotli_init_writer,
   brotli_unencode_write,
   brotli_unencode_write,
   brotli_close_writer,
   brotli_close_writer,
-  sizeof(brotli_params)
+  sizeof(struct brotli_params)
 };
 };
 #endif
 #endif
 
 
 
 
 /* Identity handler. */
 /* Identity handler. */
 static CURLcode identity_init_writer(struct connectdata *conn,
 static CURLcode identity_init_writer(struct connectdata *conn,
-                                     contenc_writer *writer)
+                                     struct contenc_writer *writer)
 {
 {
   (void) conn;
   (void) conn;
   return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
   return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
 }
 }
 
 
 static CURLcode identity_unencode_write(struct connectdata *conn,
 static CURLcode identity_unencode_write(struct connectdata *conn,
-                                        contenc_writer *writer,
+                                        struct contenc_writer *writer,
                                         const char *buf, size_t nbytes)
                                         const char *buf, size_t nbytes)
 {
 {
   return Curl_unencode_write(conn, writer->downstream, buf, nbytes);
   return Curl_unencode_write(conn, writer->downstream, buf, nbytes);
 }
 }
 
 
 static void identity_close_writer(struct connectdata *conn,
 static void identity_close_writer(struct connectdata *conn,
-                                  contenc_writer *writer)
+                                  struct contenc_writer *writer)
 {
 {
   (void) conn;
   (void) conn;
   (void) writer;
   (void) writer;
 }
 }
 
 
-static const content_encoding identity_encoding = {
+static const struct content_encoding identity_encoding = {
   "identity",
   "identity",
   "none",
   "none",
   identity_init_writer,
   identity_init_writer,
@@ -745,7 +743,7 @@ static const content_encoding identity_encoding = {
 
 
 
 
 /* supported content encodings table. */
 /* supported content encodings table. */
-static const content_encoding * const encodings[] = {
+static const struct content_encoding * const encodings[] = {
   &identity_encoding,
   &identity_encoding,
 #ifdef HAVE_LIBZ
 #ifdef HAVE_LIBZ
   &deflate_encoding,
   &deflate_encoding,
@@ -762,8 +760,8 @@ static const content_encoding * const encodings[] = {
 char *Curl_all_content_encodings(void)
 char *Curl_all_content_encodings(void)
 {
 {
   size_t len = 0;
   size_t len = 0;
-  const content_encoding * const *cep;
-  const content_encoding *ce;
+  const struct content_encoding * const *cep;
+  const struct content_encoding *ce;
   char *ace;
   char *ace;
 
 
   for(cep = encodings; *cep; cep++) {
   for(cep = encodings; *cep; cep++) {
@@ -796,14 +794,14 @@ char *Curl_all_content_encodings(void)
 
 
 /* Real client writer: no downstream. */
 /* Real client writer: no downstream. */
 static CURLcode client_init_writer(struct connectdata *conn,
 static CURLcode client_init_writer(struct connectdata *conn,
-                                   contenc_writer *writer)
+                                   struct contenc_writer *writer)
 {
 {
   (void) conn;
   (void) conn;
   return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK;
   return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK;
 }
 }
 
 
 static CURLcode client_unencode_write(struct connectdata *conn,
 static CURLcode client_unencode_write(struct connectdata *conn,
-                                      contenc_writer *writer,
+                                      struct contenc_writer *writer,
                                       const char *buf, size_t nbytes)
                                       const char *buf, size_t nbytes)
 {
 {
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
@@ -818,13 +816,13 @@ static CURLcode client_unencode_write(struct connectdata *conn,
 }
 }
 
 
 static void client_close_writer(struct connectdata *conn,
 static void client_close_writer(struct connectdata *conn,
-                                contenc_writer *writer)
+                                struct contenc_writer *writer)
 {
 {
   (void) conn;
   (void) conn;
   (void) writer;
   (void) writer;
 }
 }
 
 
-static const content_encoding client_encoding = {
+static const struct content_encoding client_encoding = {
   NULL,
   NULL,
   NULL,
   NULL,
   client_init_writer,
   client_init_writer,
@@ -836,14 +834,14 @@ static const content_encoding client_encoding = {
 
 
 /* Deferred error dummy writer. */
 /* Deferred error dummy writer. */
 static CURLcode error_init_writer(struct connectdata *conn,
 static CURLcode error_init_writer(struct connectdata *conn,
-                                  contenc_writer *writer)
+                                  struct contenc_writer *writer)
 {
 {
   (void) conn;
   (void) conn;
   return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
   return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
 }
 }
 
 
 static CURLcode error_unencode_write(struct connectdata *conn,
 static CURLcode error_unencode_write(struct connectdata *conn,
-                                     contenc_writer *writer,
+                                     struct contenc_writer *writer,
                                      const char *buf, size_t nbytes)
                                      const char *buf, size_t nbytes)
 {
 {
   char *all = Curl_all_content_encodings();
   char *all = Curl_all_content_encodings();
@@ -861,13 +859,13 @@ static CURLcode error_unencode_write(struct connectdata *conn,
 }
 }
 
 
 static void error_close_writer(struct connectdata *conn,
 static void error_close_writer(struct connectdata *conn,
-                               contenc_writer *writer)
+                               struct contenc_writer *writer)
 {
 {
   (void) conn;
   (void) conn;
   (void) writer;
   (void) writer;
 }
 }
 
 
-static const content_encoding error_encoding = {
+static const struct content_encoding error_encoding = {
   NULL,
   NULL,
   NULL,
   NULL,
   error_init_writer,
   error_init_writer,
@@ -877,12 +875,13 @@ static const content_encoding error_encoding = {
 };
 };
 
 
 /* Create an unencoding writer stage using the given handler. */
 /* Create an unencoding writer stage using the given handler. */
-static contenc_writer *new_unencoding_writer(struct connectdata *conn,
-                                             const content_encoding *handler,
-                                             contenc_writer *downstream)
+static struct contenc_writer *
+new_unencoding_writer(struct connectdata *conn,
+                      const struct content_encoding *handler,
+                      struct contenc_writer *downstream)
 {
 {
-  size_t sz = offsetof(contenc_writer, params) + handler->paramsize;
-  contenc_writer *writer = (contenc_writer *) calloc(1, sz);
+  size_t sz = offsetof(struct contenc_writer, params) + handler->paramsize;
+  struct contenc_writer *writer = (struct contenc_writer *)calloc(1, sz);
 
 
   if(writer) {
   if(writer) {
     writer->handler = handler;
     writer->handler = handler;
@@ -897,7 +896,8 @@ static contenc_writer *new_unencoding_writer(struct connectdata *conn,
 }
 }
 
 
 /* Write data using an unencoding writer stack. */
 /* Write data using an unencoding writer stack. */
-CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer,
+CURLcode Curl_unencode_write(struct connectdata *conn,
+                             struct contenc_writer *writer,
                              const char *buf, size_t nbytes)
                              const char *buf, size_t nbytes)
 {
 {
   if(!nbytes)
   if(!nbytes)
@@ -910,7 +910,7 @@ void Curl_unencode_cleanup(struct connectdata *conn)
 {
 {
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
   struct SingleRequest *k = &data->req;
   struct SingleRequest *k = &data->req;
-  contenc_writer *writer = k->writer_stack;
+  struct contenc_writer *writer = k->writer_stack;
 
 
   while(writer) {
   while(writer) {
     k->writer_stack = writer->downstream;
     k->writer_stack = writer->downstream;
@@ -921,12 +921,13 @@ void Curl_unencode_cleanup(struct connectdata *conn)
 }
 }
 
 
 /* Find the content encoding by name. */
 /* Find the content encoding by name. */
-static const content_encoding *find_encoding(const char *name, size_t len)
+static const struct content_encoding *find_encoding(const char *name,
+                                                    size_t len)
 {
 {
-  const content_encoding * const *cep;
+  const struct content_encoding * const *cep;
 
 
   for(cep = encodings; *cep; cep++) {
   for(cep = encodings; *cep; cep++) {
-    const content_encoding *ce = *cep;
+    const struct content_encoding *ce = *cep;
     if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
     if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
        (ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
        (ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
       return ce;
       return ce;
@@ -962,8 +963,8 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
       Curl_httpchunk_init(conn);   /* init our chunky engine. */
       Curl_httpchunk_init(conn);   /* init our chunky engine. */
     }
     }
     else if(namelen) {
     else if(namelen) {
-      const content_encoding *encoding = find_encoding(name, namelen);
-      contenc_writer *writer;
+      const struct content_encoding *encoding = find_encoding(name, namelen);
+      struct contenc_writer *writer;
 
 
       if(!k->writer_stack) {
       if(!k->writer_stack) {
         k->writer_stack = new_unencoding_writer(conn, &client_encoding, NULL);
         k->writer_stack = new_unencoding_writer(conn, &client_encoding, NULL);
@@ -997,7 +998,8 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
   return CURLE_NOT_BUILT_IN;
   return CURLE_NOT_BUILT_IN;
 }
 }
 
 
-CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer,
+CURLcode Curl_unencode_write(struct connectdata *conn,
+                             struct contenc_writer *writer,
                              const char *buf, size_t nbytes)
                              const char *buf, size_t nbytes)
 {
 {
   (void) conn;
   (void) conn;

+ 13 - 13
Utilities/cmcurl/lib/content_encoding.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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,31 +23,31 @@
  ***************************************************************************/
  ***************************************************************************/
 #include "curl_setup.h"
 #include "curl_setup.h"
 
 
-/* Decoding writer. */
-typedef struct contenc_writer_s contenc_writer;
-typedef struct content_encoding_s content_encoding;
-
-struct contenc_writer_s {
-  const content_encoding *handler;  /* Encoding handler. */
-  contenc_writer *downstream;  /* Downstream writer. */
+struct contenc_writer {
+  const struct content_encoding *handler;  /* Encoding handler. */
+  struct contenc_writer *downstream;  /* Downstream writer. */
   void *params;  /* Encoding-specific storage (variable length). */
   void *params;  /* Encoding-specific storage (variable length). */
 };
 };
 
 
 /* Content encoding writer. */
 /* Content encoding writer. */
-struct content_encoding_s {
+struct content_encoding {
   const char *name;        /* Encoding name. */
   const char *name;        /* Encoding name. */
   const char *alias;       /* Encoding name alias. */
   const char *alias;       /* Encoding name alias. */
-  CURLcode (*init_writer)(struct connectdata *conn, contenc_writer *writer);
-  CURLcode (*unencode_write)(struct connectdata *conn, contenc_writer *writer,
+  CURLcode (*init_writer)(struct connectdata *conn,
+                          struct contenc_writer *writer);
+  CURLcode (*unencode_write)(struct connectdata *conn,
+                             struct contenc_writer *writer,
                              const char *buf, size_t nbytes);
                              const char *buf, size_t nbytes);
-  void (*close_writer)(struct connectdata *conn, contenc_writer *writer);
+  void (*close_writer)(struct connectdata *conn,
+                       struct contenc_writer *writer);
   size_t paramsize;
   size_t paramsize;
 };
 };
 
 
 
 
 CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
 CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
                                      const char *enclist, int maybechunked);
                                      const char *enclist, int maybechunked);
-CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer,
+CURLcode Curl_unencode_write(struct connectdata *conn,
+                             struct contenc_writer *writer,
                              const char *buf, size_t nbytes);
                              const char *buf, size_t nbytes);
 void Curl_unencode_cleanup(struct connectdata *conn);
 void Curl_unencode_cleanup(struct connectdata *conn);
 char *Curl_all_content_encodings(void);
 char *Curl_all_content_encodings(void);

+ 9 - 10
Utilities/cmcurl/lib/cookie.c

@@ -245,18 +245,17 @@ pathmatched:
  */
  */
 static const char *get_top_domain(const char * const domain, size_t *outlen)
 static const char *get_top_domain(const char * const domain, size_t *outlen)
 {
 {
-  size_t len;
+  size_t len = 0;
   const char *first = NULL, *last;
   const char *first = NULL, *last;
 
 
-  if(!domain)
-    return NULL;
-
-  len = strlen(domain);
-  last = memrchr(domain, '.', len);
-  if(last) {
-    first = memrchr(domain, '.', (last - domain));
-    if(first)
-      len -= (++first - domain);
+  if(domain) {
+    len = strlen(domain);
+    last = memrchr(domain, '.', len);
+    if(last) {
+      first = memrchr(domain, '.', (last - domain));
+      if(first)
+        len -= (++first - domain);
+    }
   }
   }
 
 
   if(outlen)
   if(outlen)

+ 37 - 66
Utilities/cmcurl/lib/curl_addrinfo.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -50,10 +50,6 @@
 #  define in_addr_t unsigned long
 #  define in_addr_t unsigned long
 #endif
 #endif
 
 
-#if defined(WIN32) && defined(USE_UNIX_SOCKETS)
-#include <afunix.h>
-#endif
-
 #include <stddef.h>
 #include <stddef.h>
 
 
 #include "curl_addrinfo.h"
 #include "curl_addrinfo.h"
@@ -82,16 +78,13 @@
 #endif
 #endif
 
 
 void
 void
-Curl_freeaddrinfo(Curl_addrinfo *cahead)
+Curl_freeaddrinfo(struct Curl_addrinfo *cahead)
 {
 {
-  Curl_addrinfo *vqualifier canext;
-  Curl_addrinfo *ca;
+  struct Curl_addrinfo *vqualifier canext;
+  struct Curl_addrinfo *ca;
 
 
-  for(ca = cahead; ca != NULL; ca = canext) {
-    free(ca->ai_addr);
-    free(ca->ai_canonname);
+  for(ca = cahead; ca; ca = canext) {
     canext = ca->ai_next;
     canext = ca->ai_next;
-
     free(ca);
     free(ca);
   }
   }
 }
 }
@@ -116,13 +109,13 @@ int
 Curl_getaddrinfo_ex(const char *nodename,
 Curl_getaddrinfo_ex(const char *nodename,
                     const char *servname,
                     const char *servname,
                     const struct addrinfo *hints,
                     const struct addrinfo *hints,
-                    Curl_addrinfo **result)
+                    struct Curl_addrinfo **result)
 {
 {
   const struct addrinfo *ai;
   const struct addrinfo *ai;
   struct addrinfo *aihead;
   struct addrinfo *aihead;
-  Curl_addrinfo *cafirst = NULL;
-  Curl_addrinfo *calast = NULL;
-  Curl_addrinfo *ca;
+  struct Curl_addrinfo *cafirst = NULL;
+  struct Curl_addrinfo *calast = NULL;
+  struct Curl_addrinfo *ca;
   size_t ss_size;
   size_t ss_size;
   int error;
   int error;
 
 
@@ -135,7 +128,7 @@ Curl_getaddrinfo_ex(const char *nodename,
   /* traverse the addrinfo list */
   /* traverse the addrinfo list */
 
 
   for(ai = aihead; ai != NULL; ai = ai->ai_next) {
   for(ai = aihead; ai != NULL; ai = ai->ai_next) {
-
+    size_t namelen = ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0;
     /* ignore elements with unsupported address family, */
     /* ignore elements with unsupported address family, */
     /* settle family-specific sockaddr structure size.  */
     /* settle family-specific sockaddr structure size.  */
     if(ai->ai_family == AF_INET)
     if(ai->ai_family == AF_INET)
@@ -155,7 +148,7 @@ Curl_getaddrinfo_ex(const char *nodename,
     if((size_t)ai->ai_addrlen < ss_size)
     if((size_t)ai->ai_addrlen < ss_size)
       continue;
       continue;
 
 
-    ca = malloc(sizeof(Curl_addrinfo));
+    ca = malloc(sizeof(struct Curl_addrinfo) + ss_size + namelen);
     if(!ca) {
     if(!ca) {
       error = EAI_MEMORY;
       error = EAI_MEMORY;
       break;
       break;
@@ -173,22 +166,12 @@ Curl_getaddrinfo_ex(const char *nodename,
     ca->ai_canonname = NULL;
     ca->ai_canonname = NULL;
     ca->ai_next      = NULL;
     ca->ai_next      = NULL;
 
 
-    ca->ai_addr = malloc(ss_size);
-    if(!ca->ai_addr) {
-      error = EAI_MEMORY;
-      free(ca);
-      break;
-    }
+    ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
     memcpy(ca->ai_addr, ai->ai_addr, ss_size);
     memcpy(ca->ai_addr, ai->ai_addr, ss_size);
 
 
-    if(ai->ai_canonname != NULL) {
-      ca->ai_canonname = strdup(ai->ai_canonname);
-      if(!ca->ai_canonname) {
-        error = EAI_MEMORY;
-        free(ca->ai_addr);
-        free(ca);
-        break;
-      }
+    if(namelen) {
+      ca->ai_canonname = (void *)((char *)ca->ai_addr + ss_size);
+      memcpy(ca->ai_canonname, ai->ai_canonname, namelen);
     }
     }
 
 
     /* if the return list is empty, this becomes the first element */
     /* if the return list is empty, this becomes the first element */
@@ -256,7 +239,6 @@ Curl_getaddrinfo_ex(const char *nodename,
  *       struct sockaddr      *ai_addr;
  *       struct sockaddr      *ai_addr;
  *       struct Curl_addrinfo *ai_next;
  *       struct Curl_addrinfo *ai_next;
  *     };
  *     };
- *     typedef struct Curl_addrinfo Curl_addrinfo;
  *
  *
  *   hostent defined in <netdb.h>
  *   hostent defined in <netdb.h>
  *
  *
@@ -273,12 +255,12 @@ Curl_getaddrinfo_ex(const char *nodename,
  *     #define h_addr  h_addr_list[0]
  *     #define h_addr  h_addr_list[0]
  */
  */
 
 
-Curl_addrinfo *
+struct Curl_addrinfo *
 Curl_he2ai(const struct hostent *he, int port)
 Curl_he2ai(const struct hostent *he, int port)
 {
 {
-  Curl_addrinfo *ai;
-  Curl_addrinfo *prevai = NULL;
-  Curl_addrinfo *firstai = NULL;
+  struct Curl_addrinfo *ai;
+  struct Curl_addrinfo *prevai = NULL;
+  struct Curl_addrinfo *firstai = NULL;
   struct sockaddr_in *addr;
   struct sockaddr_in *addr;
 #ifdef ENABLE_IPV6
 #ifdef ENABLE_IPV6
   struct sockaddr_in6 *addr6;
   struct sockaddr_in6 *addr6;
@@ -294,8 +276,8 @@ Curl_he2ai(const struct hostent *he, int port)
   DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL));
   DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL));
 
 
   for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) {
   for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) {
-
     size_t ss_size;
     size_t ss_size;
+    size_t namelen = strlen(he->h_name) + 1; /* include zero termination */
 #ifdef ENABLE_IPV6
 #ifdef ENABLE_IPV6
     if(he->h_addrtype == AF_INET6)
     if(he->h_addrtype == AF_INET6)
       ss_size = sizeof(struct sockaddr_in6);
       ss_size = sizeof(struct sockaddr_in6);
@@ -303,24 +285,17 @@ Curl_he2ai(const struct hostent *he, int port)
 #endif
 #endif
       ss_size = sizeof(struct sockaddr_in);
       ss_size = sizeof(struct sockaddr_in);
 
 
-    ai = calloc(1, sizeof(Curl_addrinfo));
+    /* allocate memory to told the struct, the address and the name */
+    ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + namelen);
     if(!ai) {
     if(!ai) {
       result = CURLE_OUT_OF_MEMORY;
       result = CURLE_OUT_OF_MEMORY;
       break;
       break;
     }
     }
-    ai->ai_canonname = strdup(he->h_name);
-    if(!ai->ai_canonname) {
-      result = CURLE_OUT_OF_MEMORY;
-      free(ai);
-      break;
-    }
-    ai->ai_addr = calloc(1, ss_size);
-    if(!ai->ai_addr) {
-      result = CURLE_OUT_OF_MEMORY;
-      free(ai->ai_canonname);
-      free(ai);
-      break;
-    }
+    /* put the address after the struct */
+    ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
+    /* then put the name after the address */
+    ai->ai_canonname = (char *)ai->ai_addr + ss_size;
+    memcpy(ai->ai_canonname, he->h_name, namelen);
 
 
     if(!firstai)
     if(!firstai)
       /* store the pointer we want to return from this function */
       /* store the pointer we want to return from this function */
@@ -393,10 +368,10 @@ struct namebuff {
  * given address/host
  * given address/host
  */
  */
 
 
-Curl_addrinfo *
+struct Curl_addrinfo *
 Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
 Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
 {
 {
-  Curl_addrinfo *ai;
+  struct Curl_addrinfo *ai;
 
 
 #if defined(__VMS) && \
 #if defined(__VMS) && \
     defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
     defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
@@ -469,7 +444,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
  * Given an IPv4 or IPv6 dotted string address, this converts it to a proper
  * Given an IPv4 or IPv6 dotted string address, this converts it to a proper
  * allocated Curl_addrinfo struct and returns it.
  * allocated Curl_addrinfo struct and returns it.
  */
  */
-Curl_addrinfo *Curl_str2addr(char *address, int port)
+struct Curl_addrinfo *Curl_str2addr(char *address, int port)
 {
 {
   struct in_addr in;
   struct in_addr in;
   if(Curl_inet_pton(AF_INET, address, &in) > 0)
   if(Curl_inet_pton(AF_INET, address, &in) > 0)
@@ -492,22 +467,19 @@ Curl_addrinfo *Curl_str2addr(char *address, int port)
  * struct initialized with this path.
  * struct initialized with this path.
  * Set '*longpath' to TRUE if the error is a too long path.
  * Set '*longpath' to TRUE if the error is a too long path.
  */
  */
-Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
+struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath,
+                                     bool abstract)
 {
 {
-  Curl_addrinfo *ai;
+  struct Curl_addrinfo *ai;
   struct sockaddr_un *sa_un;
   struct sockaddr_un *sa_un;
   size_t path_len;
   size_t path_len;
 
 
   *longpath = FALSE;
   *longpath = FALSE;
 
 
-  ai = calloc(1, sizeof(Curl_addrinfo));
+  ai = calloc(1, sizeof(struct Curl_addrinfo) + sizeof(struct sockaddr_un));
   if(!ai)
   if(!ai)
     return NULL;
     return NULL;
-  ai->ai_addr = calloc(1, sizeof(struct sockaddr_un));
-  if(!ai->ai_addr) {
-    free(ai);
-    return NULL;
-  }
+  ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
 
 
   sa_un = (void *) ai->ai_addr;
   sa_un = (void *) ai->ai_addr;
   sa_un->sun_family = AF_UNIX;
   sa_un->sun_family = AF_UNIX;
@@ -515,7 +487,6 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
   /* sun_path must be able to store the NUL-terminated path */
   /* sun_path must be able to store the NUL-terminated path */
   path_len = strlen(path) + 1;
   path_len = strlen(path) + 1;
   if(path_len > sizeof(sa_un->sun_path)) {
   if(path_len > sizeof(sa_un->sun_path)) {
-    free(ai->ai_addr);
     free(ai);
     free(ai);
     *longpath = TRUE;
     *longpath = TRUE;
     return NULL;
     return NULL;
@@ -598,9 +569,9 @@ curl_dbg_getaddrinfo(const char *hostname,
  * Work-arounds the sin6_port is always zero bug on iOS 9.3.2 and Mac OS X
  * Work-arounds the sin6_port is always zero bug on iOS 9.3.2 and Mac OS X
  * 10.11.5.
  * 10.11.5.
  */
  */
-void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port)
+void Curl_addrinfo_set_port(struct Curl_addrinfo *addrinfo, int port)
 {
 {
-  Curl_addrinfo *ca;
+  struct Curl_addrinfo *ca;
   struct sockaddr_in *addr;
   struct sockaddr_in *addr;
 #ifdef ENABLE_IPV6
 #ifdef ENABLE_IPV6
   struct sockaddr_in6 *addr6;
   struct sockaddr_in6 *addr6;

+ 9 - 10
Utilities/cmcurl/lib/curl_addrinfo.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -40,7 +40,6 @@
 #  include <stdlib.h>
 #  include <stdlib.h>
 #endif
 #endif
 
 
-
 /*
 /*
  * Curl_addrinfo is our internal struct definition that we use to allow
  * Curl_addrinfo is our internal struct definition that we use to allow
  * consistent internal handling of this data. We use this even when the
  * consistent internal handling of this data. We use this even when the
@@ -58,29 +57,29 @@ struct Curl_addrinfo {
   struct sockaddr      *ai_addr;
   struct sockaddr      *ai_addr;
   struct Curl_addrinfo *ai_next;
   struct Curl_addrinfo *ai_next;
 };
 };
-typedef struct Curl_addrinfo Curl_addrinfo;
 
 
 void
 void
-Curl_freeaddrinfo(Curl_addrinfo *cahead);
+Curl_freeaddrinfo(struct Curl_addrinfo *cahead);
 
 
 #ifdef HAVE_GETADDRINFO
 #ifdef HAVE_GETADDRINFO
 int
 int
 Curl_getaddrinfo_ex(const char *nodename,
 Curl_getaddrinfo_ex(const char *nodename,
                     const char *servname,
                     const char *servname,
                     const struct addrinfo *hints,
                     const struct addrinfo *hints,
-                    Curl_addrinfo **result);
+                    struct Curl_addrinfo **result);
 #endif
 #endif
 
 
-Curl_addrinfo *
+struct Curl_addrinfo *
 Curl_he2ai(const struct hostent *he, int port);
 Curl_he2ai(const struct hostent *he, int port);
 
 
-Curl_addrinfo *
+struct Curl_addrinfo *
 Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
 Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
 
 
-Curl_addrinfo *Curl_str2addr(char *dotted, int port);
+struct Curl_addrinfo *Curl_str2addr(char *dotted, int port);
 
 
 #ifdef USE_UNIX_SOCKETS
 #ifdef USE_UNIX_SOCKETS
-Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract);
+struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath,
+                                     bool abstract);
 #endif
 #endif
 
 
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
 #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
@@ -98,7 +97,7 @@ curl_dbg_getaddrinfo(const char *hostname, const char *service,
 
 
 #ifdef HAVE_GETADDRINFO
 #ifdef HAVE_GETADDRINFO
 #ifdef USE_RESOLVE_ON_IPS
 #ifdef USE_RESOLVE_ON_IPS
-void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port);
+void Curl_addrinfo_set_port(struct Curl_addrinfo *addrinfo, int port);
 #else
 #else
 #define Curl_addrinfo_set_port(x,y)
 #define Curl_addrinfo_set_port(x,y)
 #endif
 #endif

+ 48 - 3
Utilities/cmcurl/lib/curl_config.h.cmake

@@ -1,3 +1,24 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2020, 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.
+ *
+ ***************************************************************************/
 /* lib/curl_config.h.in.  Generated somehow by cmake.  */
 /* lib/curl_config.h.in.  Generated somehow by cmake.  */
 
 
 #include <cm3p/kwiml/abi.h>
 #include <cm3p/kwiml/abi.h>
@@ -35,6 +56,9 @@
 /* to disable LDAPS */
 /* to disable LDAPS */
 #cmakedefine CURL_DISABLE_LDAPS 1
 #cmakedefine CURL_DISABLE_LDAPS 1
 
 
+/* to enable MQTT */
+#undef CURL_ENABLE_MQTT
+
 /* to disable POP3 */
 /* to disable POP3 */
 #cmakedefine CURL_DISABLE_POP3 1
 #cmakedefine CURL_DISABLE_POP3 1
 
 
@@ -138,9 +162,6 @@
 /* Define to 1 if you have the <crypto.h> header file. */
 /* Define to 1 if you have the <crypto.h> header file. */
 #cmakedefine HAVE_CRYPTO_H 1
 #cmakedefine HAVE_CRYPTO_H 1
 
 
-/* Define to 1 if you have the <des.h> header file. */
-#cmakedefine HAVE_DES_H 1
-
 /* Define to 1 if you have the <dlfcn.h> header file. */
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #cmakedefine HAVE_DLFCN_H 1
 #cmakedefine HAVE_DLFCN_H 1
 
 
@@ -400,6 +421,9 @@
 /* Define to 1 if you have the <libssh2.h> header file. */
 /* Define to 1 if you have the <libssh2.h> header file. */
 #cmakedefine HAVE_LIBSSH2_H 1
 #cmakedefine HAVE_LIBSSH2_H 1
 
 
+/* Define to 1 if you have the <libssh/libssh.h> header file. */
+#cmakedefine HAVE_LIBSSH_LIBSSH_H 1
+
 /* if zlib is available */
 /* if zlib is available */
 #cmakedefine HAVE_LIBZ 1
 #cmakedefine HAVE_LIBZ 1
 
 
@@ -948,6 +972,12 @@ ${SIZEOF_TIME_T_CODE}
 /* if BearSSL is enabled */
 /* if BearSSL is enabled */
 #cmakedefine USE_BEARSSL 1
 #cmakedefine USE_BEARSSL 1
 
 
+/* if WolfSSL is enabled */
+#cmakedefine USE_WOLFSSL 1
+
+/* if libSSH is in use */
+#cmakedefine USE_LIBSSH 1
+
 /* if libSSH2 is in use */
 /* if libSSH2 is in use */
 #cmakedefine USE_LIBSSH2 1
 #cmakedefine USE_LIBSSH2 1
 
 
@@ -969,9 +999,24 @@ ${SIZEOF_TIME_T_CODE}
 /* to enable NGHTTP2  */
 /* to enable NGHTTP2  */
 #cmakedefine USE_NGHTTP2 1
 #cmakedefine USE_NGHTTP2 1
 
 
+/* to enable NGTCP2 */
+#cmakedefine USE_NGTCP2 1
+
+/* to enable NGHTTP3  */
+#cmakedefine USE_NGHTTP3 1
+
+/* to enable quiche */
+#cmakedefine USE_QUICHE 1
+
+/* Define to 1 if you have the quiche_conn_set_qlog_fd function. */
+#cmakedefine HAVE_QUICHE_CONN_SET_QLOG_FD 1
+
 /* if Unix domain sockets are enabled  */
 /* if Unix domain sockets are enabled  */
 #cmakedefine USE_UNIX_SOCKETS
 #cmakedefine USE_UNIX_SOCKETS
 
 
+/* to enable alt-svc */
+#cmakedefine USE_ALTSVC 1
+
 /* to enable SSPI support */
 /* to enable SSPI support */
 #cmakedefine USE_WINDOWS_SSPI 1
 #cmakedefine USE_WINDOWS_SSPI 1
 
 

+ 13 - 15
Utilities/cmcurl/lib/curl_hmac.h

@@ -34,37 +34,35 @@ typedef void    (* HMAC_hfinal_func)(unsigned char *result, void *context);
 
 
 
 
 /* Per-hash function HMAC parameters. */
 /* Per-hash function HMAC parameters. */
-
-typedef struct {
-  HMAC_hinit_func       hmac_hinit;     /* Initialize context procedure. */
+struct HMAC_params {
+  HMAC_hinit_func
+  hmac_hinit;     /* Initialize context procedure. */
   HMAC_hupdate_func     hmac_hupdate;   /* Update context with data. */
   HMAC_hupdate_func     hmac_hupdate;   /* Update context with data. */
   HMAC_hfinal_func      hmac_hfinal;    /* Get final result procedure. */
   HMAC_hfinal_func      hmac_hfinal;    /* Get final result procedure. */
   unsigned int          hmac_ctxtsize;  /* Context structure size. */
   unsigned int          hmac_ctxtsize;  /* Context structure size. */
   unsigned int          hmac_maxkeylen; /* Maximum key length (bytes). */
   unsigned int          hmac_maxkeylen; /* Maximum key length (bytes). */
   unsigned int          hmac_resultlen; /* Result length (bytes). */
   unsigned int          hmac_resultlen; /* Result length (bytes). */
-} HMAC_params;
+};
 
 
 
 
 /* HMAC computation context. */
 /* HMAC computation context. */
-
-typedef struct {
-  const HMAC_params *hmac_hash; /* Hash function definition. */
+struct HMAC_context {
+  const struct HMAC_params *hmac_hash; /* Hash function definition. */
   void *hmac_hashctxt1;         /* Hash function context 1. */
   void *hmac_hashctxt1;         /* Hash function context 1. */
   void *hmac_hashctxt2;         /* Hash function context 2. */
   void *hmac_hashctxt2;         /* Hash function context 2. */
-} HMAC_context;
+};
 
 
 
 
 /* Prototypes. */
 /* Prototypes. */
-
-HMAC_context * Curl_HMAC_init(const HMAC_params *hashparams,
-                              const unsigned char *key,
-                              unsigned int keylen);
-int Curl_HMAC_update(HMAC_context *context,
+struct HMAC_context *Curl_HMAC_init(const struct HMAC_params *hashparams,
+                                    const unsigned char *key,
+                                    unsigned int keylen);
+int Curl_HMAC_update(struct HMAC_context *context,
                      const unsigned char *data,
                      const unsigned char *data,
                      unsigned int len);
                      unsigned int len);
-int Curl_HMAC_final(HMAC_context *context, unsigned char *result);
+int Curl_HMAC_final(struct HMAC_context *context, unsigned char *result);
 
 
-CURLcode Curl_hmacit(const HMAC_params *hashparams,
+CURLcode Curl_hmacit(const struct HMAC_params *hashparams,
                      const unsigned char *key, const size_t keylen,
                      const unsigned char *key, const size_t keylen,
                      const unsigned char *data, const size_t datalen,
                      const unsigned char *data, const size_t datalen,
                      unsigned char *output);
                      unsigned char *output);

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

@@ -33,30 +33,30 @@ typedef void (* Curl_MD5_update_func)(void *context,
                                       unsigned int len);
                                       unsigned int len);
 typedef void (* Curl_MD5_final_func)(unsigned char *result, void *context);
 typedef void (* Curl_MD5_final_func)(unsigned char *result, void *context);
 
 
-typedef struct {
+struct MD5_params {
   Curl_MD5_init_func     md5_init_func;   /* Initialize context procedure */
   Curl_MD5_init_func     md5_init_func;   /* Initialize context procedure */
   Curl_MD5_update_func   md5_update_func; /* Update context with data */
   Curl_MD5_update_func   md5_update_func; /* Update context with data */
   Curl_MD5_final_func    md5_final_func;  /* Get final result procedure */
   Curl_MD5_final_func    md5_final_func;  /* Get final result procedure */
   unsigned int           md5_ctxtsize;  /* Context structure size */
   unsigned int           md5_ctxtsize;  /* Context structure size */
   unsigned int           md5_resultlen; /* Result length (bytes) */
   unsigned int           md5_resultlen; /* Result length (bytes) */
-} MD5_params;
+};
 
 
-typedef struct {
-  const MD5_params      *md5_hash;      /* Hash function definition */
+struct MD5_context {
+  const struct MD5_params *md5_hash;    /* Hash function definition */
   void                  *md5_hashctx;   /* Hash function context */
   void                  *md5_hashctx;   /* Hash function context */
-} MD5_context;
+};
 
 
-extern const MD5_params Curl_DIGEST_MD5[1];
-extern const HMAC_params Curl_HMAC_MD5[1];
+extern const struct MD5_params Curl_DIGEST_MD5[1];
+extern const struct HMAC_params Curl_HMAC_MD5[1];
 
 
 void Curl_md5it(unsigned char *output, const unsigned char *input,
 void Curl_md5it(unsigned char *output, const unsigned char *input,
                 const size_t len);
                 const size_t len);
 
 
-MD5_context * Curl_MD5_init(const MD5_params *md5params);
-CURLcode Curl_MD5_update(MD5_context *context,
+struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params);
+CURLcode Curl_MD5_update(struct MD5_context *context,
                          const unsigned char *data,
                          const unsigned char *data,
                          unsigned int len);
                          unsigned int len);
-CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result);
+CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result);
 
 
 #endif
 #endif
 
 

+ 84 - 15
Utilities/cmcurl/lib/curl_multibyte.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -20,24 +20,21 @@
  *
  *
  ***************************************************************************/
  ***************************************************************************/
 
 
-#include "curl_setup.h"
-
-#include <curl/curl.h>
+/*
+ * This file is 'mem-include-scan' clean. See test 1132.
+ */
 
 
-#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \
-                                defined(USE_WIN32_LDAP)) && defined(UNICODE))
+#include "curl_setup.h"
 
 
- /*
-  * MultiByte conversions using Windows kernel32 library.
-  */
+#if defined(WIN32)
 
 
 #include "curl_multibyte.h"
 #include "curl_multibyte.h"
-#include "curl_memory.h"
 
 
-/* The last #include file should be: */
-#include "memdebug.h"
+/*
+ * MultiByte conversions using Windows kernel32 library.
+ */
 
 
-wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8)
+wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8)
 {
 {
   wchar_t *str_w = NULL;
   wchar_t *str_w = NULL;
 
 
@@ -59,7 +56,7 @@ wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8)
   return str_w;
   return str_w;
 }
 }
 
 
-char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w)
+char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w)
 {
 {
   char *str_utf8 = NULL;
   char *str_utf8 = NULL;
 
 
@@ -81,4 +78,76 @@ char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w)
   return str_utf8;
   return str_utf8;
 }
 }
 
 
-#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */
+#endif /* WIN32 */
+
+#if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES)
+
+FILE *curlx_win32_fopen(const char *filename, const char *mode)
+{
+#ifdef _UNICODE
+  FILE *result = NULL;
+  wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename);
+  wchar_t *mode_w = curlx_convert_UTF8_to_wchar(mode);
+  if(filename_w && mode_w)
+    result = _wfopen(filename_w, mode_w);
+  free(filename_w);
+  free(mode_w);
+  if(result)
+    return result;
+#endif
+
+  return (fopen)(filename, mode);
+}
+
+int curlx_win32_stat(const char *path, struct_stat *buffer)
+{
+  int result = -1;
+#ifdef _UNICODE
+  wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
+#endif /* _UNICODE */
+
+#if defined(USE_WIN32_SMALL_FILES)
+#if defined(_UNICODE)
+  if(path_w)
+    result = _wstat(path_w, buffer);
+  else
+#endif /* _UNICODE */
+    result = _stat(path, buffer);
+#else /* USE_WIN32_SMALL_FILES */
+#if defined(_UNICODE)
+  if(path_w)
+    result = _wstati64(path_w, buffer);
+  else
+#endif /* _UNICODE */
+    result = _stati64(path, buffer);
+#endif /* USE_WIN32_SMALL_FILES */
+
+#ifdef _UNICODE
+  free(path_w);
+#endif
+
+  return result;
+}
+
+int curlx_win32_access(const char *path, int mode)
+{
+    int result = -1;
+#ifdef _UNICODE
+    wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
+#endif /* _UNICODE */
+
+#if defined(_UNICODE)
+    if(path_w)
+        result = _waccess(path_w, mode);
+    else
+#endif /* _UNICODE */
+        result = _access(path, mode);
+
+#ifdef _UNICODE
+    free(path_w);
+#endif
+
+    return result;
+}
+
+#endif /* USE_WIN32_LARGE_FILES || USE_WIN32_SMALL_FILES */

+ 21 - 28
Utilities/cmcurl/lib/curl_multibyte.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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,48 +23,43 @@
  ***************************************************************************/
  ***************************************************************************/
 #include "curl_setup.h"
 #include "curl_setup.h"
 
 
-#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \
-                                defined(USE_WIN32_LDAP)) && defined(UNICODE))
+#if defined(WIN32)
 
 
  /*
  /*
   * MultiByte conversions using Windows kernel32 library.
   * MultiByte conversions using Windows kernel32 library.
   */
   */
 
 
-wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8);
-char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w);
+wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8);
+char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
 
 
-#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */
-
-
-#if defined(USE_WIN32_IDN) || defined(USE_WINDOWS_SSPI) || \
-    defined(USE_WIN32_LDAP)
+#endif /* WIN32 */
 
 
 /*
 /*
- * Macros Curl_convert_UTF8_to_tchar(), Curl_convert_tchar_to_UTF8()
- * and Curl_unicodefree() main purpose is to minimize the number of
+ * Macros curlx_convert_UTF8_to_tchar(), curlx_convert_tchar_to_UTF8()
+ * and curlx_unicodefree() main purpose is to minimize the number of
  * preprocessor conditional directives needed by code using these
  * preprocessor conditional directives needed by code using these
  * to differentiate UNICODE from non-UNICODE builds.
  * to differentiate UNICODE from non-UNICODE builds.
  *
  *
- * When building with UNICODE defined, this two macros
- * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8()
+ * When building with UNICODE defined, these two macros
+ * curlx_convert_UTF8_to_tchar() and curlx_convert_tchar_to_UTF8()
  * return a pointer to a newly allocated memory area holding result.
  * return a pointer to a newly allocated memory area holding result.
  * When the result is no longer needed, allocated memory is intended
  * When the result is no longer needed, allocated memory is intended
- * to be free'ed with Curl_unicodefree().
+ * to be free'ed with curlx_unicodefree().
  *
  *
  * When building without UNICODE defined, this macros
  * When building without UNICODE defined, this macros
- * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8()
- * return the pointer received as argument. Curl_unicodefree() does
+ * curlx_convert_UTF8_to_tchar() and curlx_convert_tchar_to_UTF8()
+ * return the pointer received as argument. curlx_unicodefree() does
  * no actual free'ing of this pointer it is simply set to NULL.
  * no actual free'ing of this pointer it is simply set to NULL.
  */
  */
 
 
-#ifdef UNICODE
+#if defined(UNICODE) && defined(WIN32)
 
 
-#define Curl_convert_UTF8_to_tchar(ptr) Curl_convert_UTF8_to_wchar((ptr))
-#define Curl_convert_tchar_to_UTF8(ptr) Curl_convert_wchar_to_UTF8((ptr))
-#define Curl_unicodefree(ptr)                           \
+#define curlx_convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr))
+#define curlx_convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr))
+#define curlx_unicodefree(ptr)                          \
   do {                                                  \
   do {                                                  \
     if(ptr) {                                           \
     if(ptr) {                                           \
-      free(ptr);                                        \
+      (free)(ptr);                                        \
       (ptr) = NULL;                                     \
       (ptr) = NULL;                                     \
     }                                                   \
     }                                                   \
   } while(0)
   } while(0)
@@ -78,9 +73,9 @@ typedef union {
 
 
 #else
 #else
 
 
-#define Curl_convert_UTF8_to_tchar(ptr) (ptr)
-#define Curl_convert_tchar_to_UTF8(ptr) (ptr)
-#define Curl_unicodefree(ptr) \
+#define curlx_convert_UTF8_to_tchar(ptr) (ptr)
+#define curlx_convert_tchar_to_UTF8(ptr) (ptr)
+#define curlx_unicodefree(ptr) \
   do {(ptr) = NULL;} while(0)
   do {(ptr) = NULL;} while(0)
 
 
 typedef union {
 typedef union {
@@ -90,8 +85,6 @@ typedef union {
   const unsigned char *const_tbyte_ptr;
   const unsigned char *const_tbyte_ptr;
 } xcharp_u;
 } xcharp_u;
 
 
-#endif /* UNICODE */
-
-#endif /* USE_WIN32_IDN || USE_WINDOWS_SSPI || USE_WIN32_LDAP */
+#endif /* UNICODE && WIN32 */
 
 
 #endif /* HEADER_CURL_MULTIBYTE_H */
 #endif /* HEADER_CURL_MULTIBYTE_H */

+ 11 - 8
Utilities/cmcurl/lib/curl_ntlm_core.c

@@ -52,13 +52,18 @@
 
 
 #if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
 #if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
 
 
-#ifdef USE_OPENSSL
+#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
+
+#ifdef USE_WOLFSSL
+#include <wolfssl/options.h>
+#endif
 
 
 #  include <openssl/des.h>
 #  include <openssl/des.h>
 #  include <openssl/md5.h>
 #  include <openssl/md5.h>
 #  include <openssl/ssl.h>
 #  include <openssl/ssl.h>
 #  include <openssl/rand.h>
 #  include <openssl/rand.h>
-#  if (OPENSSL_VERSION_NUMBER < 0x00907001L)
+#  if (defined(OPENSSL_VERSION_NUMBER) && \
+       (OPENSSL_VERSION_NUMBER < 0x00907001L)) && !defined(USE_WOLFSSL)
 #    define DES_key_schedule des_key_schedule
 #    define DES_key_schedule des_key_schedule
 #    define DES_cblock des_cblock
 #    define DES_cblock des_cblock
 #    define DES_set_odd_parity des_set_odd_parity
 #    define DES_set_odd_parity des_set_odd_parity
@@ -78,14 +83,12 @@
 #elif defined(USE_GNUTLS)
 #elif defined(USE_GNUTLS)
 
 
 #  include <gcrypt.h>
 #  include <gcrypt.h>
-#  define MD5_DIGEST_LENGTH 16
 
 
 #elif defined(USE_NSS)
 #elif defined(USE_NSS)
 
 
 #  include <nss.h>
 #  include <nss.h>
 #  include <pk11pub.h>
 #  include <pk11pub.h>
 #  include <hasht.h>
 #  include <hasht.h>
-#  define MD5_DIGEST_LENGTH MD5_LENGTH
 
 
 #elif defined(USE_MBEDTLS)
 #elif defined(USE_MBEDTLS)
 
 
@@ -138,7 +141,7 @@ static void extend_key_56_to_64(const unsigned char *key_56, char *key)
   key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
   key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
 }
 }
 
 
-#ifdef USE_OPENSSL
+#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
 /*
 /*
  * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.  The
  * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.  The
  * key schedule ks is also set.
  * key schedule ks is also set.
@@ -342,7 +345,7 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out,
 
 
   /* Acquire the crypto provider */
   /* Acquire the crypto provider */
   if(!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL,
   if(!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL,
-                          CRYPT_VERIFYCONTEXT))
+                          CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
     return FALSE;
     return FALSE;
 
 
   /* Setup the key blob structure */
   /* Setup the key blob structure */
@@ -387,7 +390,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
                             const unsigned char *plaintext,
                             const unsigned char *plaintext,
                             unsigned char *results)
                             unsigned char *results)
 {
 {
-#ifdef USE_OPENSSL
+#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
   DES_key_schedule ks;
   DES_key_schedule ks;
 
 
   setup_des_key(keys, DESKEY(ks));
   setup_des_key(keys, DESKEY(ks));
@@ -462,7 +465,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
   {
   {
     /* Create LanManager hashed password. */
     /* Create LanManager hashed password. */
 
 
-#ifdef USE_OPENSSL
+#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
     DES_key_schedule ks;
     DES_key_schedule ks;
 
 
     setup_des_key(pw, DESKEY(ks));
     setup_des_key(pw, DESKEY(ks));

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

@@ -29,6 +29,7 @@
 /* If NSS is the first available SSL backend (see order in curl_ntlm_core.c)
 /* If NSS is the first available SSL backend (see order in curl_ntlm_core.c)
    then it must be initialized to be used by NTLM. */
    then it must be initialized to be used by NTLM. */
 #if !defined(USE_OPENSSL) && \
 #if !defined(USE_OPENSSL) && \
+    !defined(USE_WOLFSSL) && \
     !defined(USE_GNUTLS_NETTLE) && \
     !defined(USE_GNUTLS_NETTLE) && \
     !defined(USE_GNUTLS) && \
     !defined(USE_GNUTLS) && \
     defined(USE_NSS)
     defined(USE_NSS)
@@ -37,7 +38,10 @@
 
 
 #if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
 #if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
 
 
-#ifdef USE_OPENSSL
+#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
+#ifdef USE_WOLFSSL
+#  include <wolfssl/options.h>
+#endif
 #  include <openssl/ssl.h>
 #  include <openssl/ssl.h>
 #endif
 #endif
 
 

+ 29 - 38
Utilities/cmcurl/lib/curl_ntlm_wb.c

@@ -261,15 +261,11 @@ done:
 static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
 static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
                                  const char *input, curlntlm state)
                                  const char *input, curlntlm state)
 {
 {
-  char *buf = malloc(NTLM_BUFSIZE);
   size_t len_in = strlen(input), len_out = 0;
   size_t len_in = strlen(input), len_out = 0;
-
-#if defined(CURL_DISABLE_VERBOSE_STRINGS)
-  (void) data;
-#endif
-
-  if(!buf)
-    return CURLE_OUT_OF_MEMORY;
+  struct dynbuf b;
+  char *ptr = NULL;
+  unsigned char *buf = (unsigned char *)data->state.buffer;
+  Curl_dyn_init(&b, MAX_NTLM_WB_RESPONSE);
 
 
   while(len_in > 0) {
   while(len_in > 0) {
     ssize_t written = swrite(ntlm->ntlm_auth_hlpr_socket, input, len_in);
     ssize_t written = swrite(ntlm->ntlm_auth_hlpr_socket, input, len_in);
@@ -285,10 +281,8 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
   }
   }
   /* Read one line */
   /* Read one line */
   while(1) {
   while(1) {
-    ssize_t size;
-    char *newbuf;
-
-    size = sread(ntlm->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE);
+    ssize_t size =
+      sread(ntlm->ntlm_auth_hlpr_socket, buf, data->set.buffer_size);
     if(size == -1) {
     if(size == -1) {
       if(errno == EINTR)
       if(errno == EINTR)
         continue;
         continue;
@@ -297,48 +291,41 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
     else if(size == 0)
     else if(size == 0)
       goto done;
       goto done;
 
 
-    len_out += size;
-    if(buf[len_out - 1] == '\n') {
-      buf[len_out - 1] = '\0';
-      break;
-    }
+    if(Curl_dyn_addn(&b, buf, size))
+      goto done;
 
 
-    if(len_out > MAX_NTLM_WB_RESPONSE) {
-      failf(data, "too large ntlm_wb response!");
-      free(buf);
-      return CURLE_OUT_OF_MEMORY;
+    len_out = Curl_dyn_len(&b);
+    ptr = Curl_dyn_ptr(&b);
+    if(len_out && ptr[len_out - 1] == '\n') {
+      ptr[len_out - 1] = '\0';
+      break; /* done! */
     }
     }
-
-    newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE);
-    if(!newbuf)
-      return CURLE_OUT_OF_MEMORY;
-
-    buf = newbuf;
+    /* loop */
   }
   }
 
 
   /* Samba/winbind installed but not configured */
   /* Samba/winbind installed but not configured */
   if(state == NTLMSTATE_TYPE1 &&
   if(state == NTLMSTATE_TYPE1 &&
      len_out == 3 &&
      len_out == 3 &&
-     buf[0] == 'P' && buf[1] == 'W')
+     ptr[0] == 'P' && ptr[1] == 'W')
     goto done;
     goto done;
   /* invalid response */
   /* invalid response */
   if(len_out < 4)
   if(len_out < 4)
     goto done;
     goto done;
   if(state == NTLMSTATE_TYPE1 &&
   if(state == NTLMSTATE_TYPE1 &&
-     (buf[0]!='Y' || buf[1]!='R' || buf[2]!=' '))
+     (ptr[0]!='Y' || ptr[1]!='R' || ptr[2]!=' '))
     goto done;
     goto done;
   if(state == NTLMSTATE_TYPE2 &&
   if(state == NTLMSTATE_TYPE2 &&
-     (buf[0]!='K' || buf[1]!='K' || buf[2]!=' ') &&
-     (buf[0]!='A' || buf[1]!='F' || buf[2]!=' '))
+     (ptr[0]!='K' || ptr[1]!='K' || ptr[2]!=' ') &&
+     (ptr[0]!='A' || ptr[1]!='F' || ptr[2]!=' '))
     goto done;
     goto done;
 
 
-  ntlm->response = aprintf("%.*s", len_out - 4, buf + 3);
-  free(buf);
+  ntlm->response = strdup(ptr + 3);
+  Curl_dyn_free(&b);
   if(!ntlm->response)
   if(!ntlm->response)
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;
   return CURLE_OK;
   return CURLE_OK;
 done:
 done:
-  free(buf);
+  Curl_dyn_free(&b);
   return CURLE_REMOTE_ACCESS_DENIED;
   return CURLE_REMOTE_ACCESS_DENIED;
 }
 }
 
 
@@ -389,8 +376,7 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
  * 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.
  */
  */
-CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
-                              bool proxy)
+CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
 {
 {
   /* point to the address of the pointer that holds the string to send to the
   /* point to the address of the pointer that holds the string to send to the
      server, which is for a plain host or for a HTTP proxy */
      server, which is for a plain host or for a HTTP proxy */
@@ -400,6 +386,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   struct ntlmdata *ntlm;
   struct ntlmdata *ntlm;
   curlntlm *state;
   curlntlm *state;
   struct auth *authp;
   struct auth *authp;
+  struct Curl_easy *data = conn->data;
 
 
   CURLcode res = CURLE_OK;
   CURLcode res = CURLE_OK;
 
 
@@ -407,14 +394,18 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   DEBUGASSERT(conn->data);
   DEBUGASSERT(conn->data);
 
 
   if(proxy) {
   if(proxy) {
-    allocuserpwd = &conn->allocptr.proxyuserpwd;
+#ifndef CURL_DISABLE_PROXY
+    allocuserpwd = &data->state.aptr.proxyuserpwd;
     userp = conn->http_proxy.user;
     userp = conn->http_proxy.user;
     ntlm = &conn->proxyntlm;
     ntlm = &conn->proxyntlm;
     state = &conn->proxy_ntlm_state;
     state = &conn->proxy_ntlm_state;
     authp = &conn->data->state.authproxy;
     authp = &conn->data->state.authproxy;
+#else
+    return CURLE_NOT_BUILT_IN;
+#endif
   }
   }
   else {
   else {
-    allocuserpwd = &conn->allocptr.userpwd;
+    allocuserpwd = &data->state.aptr.userpwd;
     userp = conn->user;
     userp = conn->user;
     ntlm = &conn->ntlm;
     ntlm = &conn->ntlm;
     state = &conn->http_ntlm_state;
     state = &conn->http_ntlm_state;

+ 14 - 4
Utilities/cmcurl/lib/curl_sasl.c

@@ -264,9 +264,14 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
   size_t len = 0;
   size_t len = 0;
   saslstate state1 = SASL_STOP;
   saslstate state1 = SASL_STOP;
   saslstate state2 = SASL_FINAL;
   saslstate state2 = SASL_FINAL;
+#ifndef CURL_DISABLE_PROXY
   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
     conn->host.name;
     conn->host.name;
   const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
   const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
+#else
+  const char * const hostname = conn->host.name;
+  const long int port = conn->remote_port;
+#endif
 #if defined(USE_KERBEROS5) || defined(USE_NTLM)
 #if defined(USE_KERBEROS5) || defined(USE_NTLM)
   const char *service = data->set.str[STRING_SERVICE_NAME] ?
   const char *service = data->set.str[STRING_SERVICE_NAME] ?
     data->set.str[STRING_SERVICE_NAME] :
     data->set.str[STRING_SERVICE_NAME] :
@@ -417,18 +422,23 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
   saslstate newstate = SASL_FINAL;
   saslstate newstate = SASL_FINAL;
   char *resp = NULL;
   char *resp = NULL;
+#ifndef CURL_DISABLE_PROXY
   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
     conn->host.name;
     conn->host.name;
   const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
   const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
+#else
+  const char * const hostname = conn->host.name;
+  const long int port = conn->remote_port;
+#endif
 #if !defined(CURL_DISABLE_CRYPTO_AUTH)
 #if !defined(CURL_DISABLE_CRYPTO_AUTH)
   char *chlg = NULL;
   char *chlg = NULL;
   size_t chlglen = 0;
   size_t chlglen = 0;
 #endif
 #endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
-    defined(USE_NTLM)
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) ||     \
+  defined(USE_NTLM)
   const char *service = data->set.str[STRING_SERVICE_NAME] ?
   const char *service = data->set.str[STRING_SERVICE_NAME] ?
-                        data->set.str[STRING_SERVICE_NAME] :
-                        sasl->params->service;
+    data->set.str[STRING_SERVICE_NAME] :
+    sasl->params->service;
   char *serverdata;
   char *serverdata;
 #endif
 #endif
   size_t len = 0;
   size_t len = 0;

+ 25 - 58
Utilities/cmcurl/lib/curl_setup.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -235,64 +235,20 @@
 #endif
 #endif
 
 
 /*
 /*
- * Use getaddrinfo to resolve the IPv4 address literal. If the current network
- * interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
- * performing this task will result in a synthesized IPv6 address.
- */
-#ifdef  __APPLE__
-#define USE_RESOLVE_ON_IPS 1
-#endif
-
-/*
- * Include header files for windows builds before redefining anything.
- * Use this preprocessor block only to include or exclude windows.h,
- * winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs
- * to any other further and independent block.  Under Cygwin things work
- * just as under linux (e.g. <sys/socket.h>) and the winsock headers should
- * never be included when __CYGWIN__ is defined.  configure script takes
- * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK_H, HAVE_WINSOCK2_H,
- * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined.
+ * Windows setup file includes some system headers.
  */
  */
 
 
 #ifdef HAVE_WINDOWS_H
 #ifdef HAVE_WINDOWS_H
-#  if defined(UNICODE) && !defined(_UNICODE)
-#    define _UNICODE
-#  endif
-#  if defined(_UNICODE) && !defined(UNICODE)
-#    define UNICODE
-#  endif
-#  include <winerror.h>
-#  include <windows.h>
-#  ifdef HAVE_WINSOCK2_H
-#    include <winsock2.h>
-#    ifdef HAVE_WS2TCPIP_H
-#      include <ws2tcpip.h>
-#    endif
-#  else
-#    ifdef HAVE_WINSOCK_H
-#      include <winsock.h>
-#    endif
-#  endif
-#  include <tchar.h>
-#  ifdef UNICODE
-     typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str);
-#  endif
+#  include "setup-win32.h"
 #endif
 #endif
 
 
 /*
 /*
- * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else
- * define USE_WINSOCK to 1 if we have and use WINSOCK  API, else
- * undefine USE_WINSOCK.
+ * Use getaddrinfo to resolve the IPv4 address literal. If the current network
+ * interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64,
+ * performing this task will result in a synthesized IPv6 address.
  */
  */
-
-#undef USE_WINSOCK
-
-#ifdef HAVE_WINSOCK2_H
-#  define USE_WINSOCK 2
-#else
-#  ifdef HAVE_WINSOCK_H
-#    define USE_WINSOCK 1
-#  endif
+#ifdef  __APPLE__
+#define USE_RESOLVE_ON_IPS 1
 #endif
 #endif
 
 
 #ifdef USE_LWIPSOCK
 #ifdef USE_LWIPSOCK
@@ -390,9 +346,14 @@
 #  undef  fstat
 #  undef  fstat
 #  define fstat(fdes,stp)            _fstati64(fdes, stp)
 #  define fstat(fdes,stp)            _fstati64(fdes, stp)
 #  undef  stat
 #  undef  stat
-#  define stat(fname,stp)            _stati64(fname, stp)
+#  define stat(fname,stp)            curlx_win32_stat(fname, stp)
 #  define struct_stat                struct _stati64
 #  define struct_stat                struct _stati64
 #  define LSEEK_ERROR                (__int64)-1
 #  define LSEEK_ERROR                (__int64)-1
+#  define fopen(fname,mode)          curlx_win32_fopen(fname, mode)
+#  define access(fname,mode)         curlx_win32_access(fname, mode)
+   int curlx_win32_stat(const char *path, struct_stat *buffer);
+   FILE *curlx_win32_fopen(const char *filename, const char *mode);
+   int curlx_win32_access(const char *path, int mode);
 #endif
 #endif
 
 
 /*
 /*
@@ -407,8 +368,13 @@
 #    undef  lseek
 #    undef  lseek
 #    define lseek(fdes,offset,whence)  _lseek(fdes, (long)offset, whence)
 #    define lseek(fdes,offset,whence)  _lseek(fdes, (long)offset, whence)
 #    define fstat(fdes,stp)            _fstat(fdes, stp)
 #    define fstat(fdes,stp)            _fstat(fdes, stp)
-#    define stat(fname,stp)            _stat(fname, stp)
+#    define stat(fname,stp)            curlx_win32_stat(fname, stp)
 #    define struct_stat                struct _stat
 #    define struct_stat                struct _stat
+#    define fopen(fname,mode)          curlx_win32_fopen(fname, mode)
+#    define access(fname,mode)         curlx_win32_access(fname, mode)
+     int curlx_win32_stat(const char *path, struct_stat *buffer);
+     FILE *curlx_win32_fopen(const char *filename, const char *mode);
+     int curlx_win32_access(const char *path, int mode);
 #  endif
 #  endif
 #  define LSEEK_ERROR                (long)-1
 #  define LSEEK_ERROR                (long)-1
 #endif
 #endif
@@ -686,10 +652,11 @@ 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) || \
-    defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
-    defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
-    defined(USE_MBEDTLS)
+#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) ||                \
+  defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) ||  \
+  defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) ||              \
+  defined(USE_MBEDTLS) ||                                               \
+  (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_SET_ODD_PARITY))
 
 
 #define USE_NTLM
 #define USE_NTLM
 
 

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

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -481,6 +481,8 @@ typedef int sig_atomic_t;
 
 
 #ifdef __VMS
 #ifdef __VMS
 #define argv_item_t  __char_ptr32
 #define argv_item_t  __char_ptr32
+#elif defined(_UNICODE)
+#define argv_item_t wchar_t *
 #else
 #else
 #define argv_item_t  char *
 #define argv_item_t  char *
 #endif
 #endif

+ 8 - 8
Utilities/cmcurl/lib/curl_sspi.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -151,7 +151,7 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
   /* Initialize the identity */
   /* Initialize the identity */
   memset(identity, 0, sizeof(*identity));
   memset(identity, 0, sizeof(*identity));
 
 
-  useranddomain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)userp);
+  useranddomain.tchar_ptr = curlx_convert_UTF8_to_tchar((char *)userp);
   if(!useranddomain.tchar_ptr)
   if(!useranddomain.tchar_ptr)
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;
 
 
@@ -173,7 +173,7 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
   /* Setup the identity's user and length */
   /* Setup the identity's user and length */
   dup_user.tchar_ptr = _tcsdup(user.tchar_ptr);
   dup_user.tchar_ptr = _tcsdup(user.tchar_ptr);
   if(!dup_user.tchar_ptr) {
   if(!dup_user.tchar_ptr) {
-    Curl_unicodefree(useranddomain.tchar_ptr);
+    curlx_unicodefree(useranddomain.tchar_ptr);
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;
   }
   }
   identity->User = dup_user.tbyte_ptr;
   identity->User = dup_user.tbyte_ptr;
@@ -183,7 +183,7 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
   /* Setup the identity's domain and length */
   /* Setup the identity's domain and length */
   dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1));
   dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1));
   if(!dup_domain.tchar_ptr) {
   if(!dup_domain.tchar_ptr) {
-    Curl_unicodefree(useranddomain.tchar_ptr);
+    curlx_unicodefree(useranddomain.tchar_ptr);
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;
   }
   }
   _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen);
   _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen);
@@ -192,22 +192,22 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
   identity->DomainLength = curlx_uztoul(domlen);
   identity->DomainLength = curlx_uztoul(domlen);
   dup_domain.tchar_ptr = NULL;
   dup_domain.tchar_ptr = NULL;
 
 
-  Curl_unicodefree(useranddomain.tchar_ptr);
+  curlx_unicodefree(useranddomain.tchar_ptr);
 
 
   /* Setup the identity's password and length */
   /* Setup the identity's password and length */
-  passwd.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)passwdp);
+  passwd.tchar_ptr = curlx_convert_UTF8_to_tchar((char *)passwdp);
   if(!passwd.tchar_ptr)
   if(!passwd.tchar_ptr)
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;
   dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr);
   dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr);
   if(!dup_passwd.tchar_ptr) {
   if(!dup_passwd.tchar_ptr) {
-    Curl_unicodefree(passwd.tchar_ptr);
+    curlx_unicodefree(passwd.tchar_ptr);
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;
   }
   }
   identity->Password = dup_passwd.tbyte_ptr;
   identity->Password = dup_passwd.tbyte_ptr;
   identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr));
   identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr));
   dup_passwd.tchar_ptr = NULL;
   dup_passwd.tchar_ptr = NULL;
 
 
-  Curl_unicodefree(passwd.tchar_ptr);
+  curlx_unicodefree(passwd.tchar_ptr);
 
 
   /* Setup the identity's flags */
   /* Setup the identity's flags */
   identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY;
   identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY;

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

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -48,7 +48,7 @@ struct curl_actual_call {
 
 
 static void *curl_thread_create_thunk(void *arg)
 static void *curl_thread_create_thunk(void *arg)
 {
 {
-  struct curl_actual_call * ac = arg;
+  struct curl_actual_call *ac = arg;
   unsigned int (*func)(void *) = ac->func;
   unsigned int (*func)(void *) = ac->func;
   void *real_arg = ac->arg;
   void *real_arg = ac->arg;
 
 

+ 11 - 1
Utilities/cmcurl/lib/curlx.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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,16 @@
   curlx_uztosi()
   curlx_uztosi()
 */
 */
 
 
+#include "curl_multibyte.h"
+/* "curl_multibyte.h" provides these functions and macros:
+
+  curlx_convert_UTF8_to_wchar()
+  curlx_convert_wchar_to_UTF8()
+  curlx_convert_UTF8_to_tchar()
+  curlx_convert_tchar_to_UTF8()
+  curlx_unicodefree()
+*/
+
 /* Now setup curlx_ * names for the functions that are to become curlx_ and
 /* Now setup curlx_ * names for the functions that are to become curlx_ and
    be removed from a future libcurl official API:
    be removed from a future libcurl official API:
    curlx_getenv
    curlx_getenv

+ 3 - 1
Utilities/cmcurl/lib/dict.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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,6 +46,8 @@
 
 
 #ifdef HAVE_SYS_SELECT_H
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #include <sys/select.h>
+#elif defined(HAVE_UNISTD_H)
+#include <unistd.h>
 #endif
 #endif
 
 
 #include "urldata.h"
 #include "urldata.h"

+ 61 - 96
Utilities/cmcurl/lib/doh.c

@@ -35,13 +35,13 @@
 #include "curl_base64.h"
 #include "curl_base64.h"
 #include "connect.h"
 #include "connect.h"
 #include "strdup.h"
 #include "strdup.h"
+#include "dynbuf.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"
 #include "memdebug.h"
 #include "memdebug.h"
 
 
 #define DNS_CLASS_IN 0x01
 #define DNS_CLASS_IN 0x01
-#define DOH_MAX_RESPONSE_SIZE 3000 /* bytes */
 
 
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
 static const char * const errors[]={
 static const char * const errors[]={
@@ -174,23 +174,14 @@ UNITTEST DOHcode doh_encode(const char *host,
 }
 }
 
 
 static size_t
 static size_t
-doh_write_cb(void *contents, size_t size, size_t nmemb, void *userp)
+doh_write_cb(const void *contents, size_t size, size_t nmemb, void *userp)
 {
 {
   size_t realsize = size * nmemb;
   size_t realsize = size * nmemb;
-  struct dohresponse *mem = (struct dohresponse *)userp;
+  struct dynbuf *mem = (struct dynbuf *)userp;
 
 
-  if((mem->size + realsize) > DOH_MAX_RESPONSE_SIZE)
-    /* suspiciously much for us */
+  if(Curl_dyn_addn(mem, contents, realsize))
     return 0;
     return 0;
 
 
-  mem->memory = Curl_saferealloc(mem->memory, mem->size + realsize);
-  if(!mem->memory)
-    /* out of memory! */
-    return 0;
-
-  memcpy(&(mem->memory[mem->size]), contents, realsize);
-  mem->size += realsize;
-
   return realsize;
   return realsize;
 }
 }
 
 
@@ -238,10 +229,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
   }
   }
 
 
   p->dnstype = dnstype;
   p->dnstype = dnstype;
-  p->serverdoh.memory = NULL;
-  /* the memory will be grown as needed by realloc in the doh_write_cb
-     function */
-  p->serverdoh.size = 0;
+  Curl_dyn_init(&p->serverdoh, DYN_DOH_RESPONSE);
 
 
   /* Note: this is code for sending the DoH request with GET but there's still
   /* Note: this is code for sending the DoH request with GET but there's still
      no logic that actually enables this. We should either add that ability or
      no logic that actually enables this. We should either add that ability or
@@ -272,7 +260,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
   if(!result) {
   if(!result) {
     /* pass in the struct pointer via a local variable to please coverity and
     /* pass in the struct pointer via a local variable to please coverity and
        the gcc typecheck helpers */
        the gcc typecheck helpers */
-    struct dohresponse *resp = &p->serverdoh;
+    struct dynbuf *resp = &p->serverdoh;
     ERROR_CHECK_SETOPT(CURLOPT_URL, url);
     ERROR_CHECK_SETOPT(CURLOPT_URL, url);
     ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
     ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
     ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, resp);
     ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, resp);
@@ -318,6 +306,9 @@ static CURLcode dohprobe(struct Curl_easy *data,
     }
     }
     if(data->set.proxy_ssl.no_revoke)
     if(data->set.proxy_ssl.no_revoke)
       ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
       ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
+    else if(data->set.proxy_ssl.revoke_best_effort)
+      ERROR_CHECK_SETOPT(CURLOPT_PROXY_SSL_OPTIONS,
+                         CURLSSLOPT_REVOKE_BEST_EFFORT);
     if(data->set.str[STRING_SSL_CAPATH_PROXY]) {
     if(data->set.str[STRING_SSL_CAPATH_PROXY]) {
       ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH,
       ERROR_CHECK_SETOPT(CURLOPT_PROXY_CAPATH,
         data->set.str[STRING_SSL_CAPATH_PROXY]);
         data->set.str[STRING_SSL_CAPATH_PROXY]);
@@ -351,6 +342,8 @@ static CURLcode dohprobe(struct Curl_easy *data,
     }
     }
     if(data->set.ssl.no_revoke)
     if(data->set.ssl.no_revoke)
       ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
       ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
+    else if(data->set.ssl.revoke_best_effort)
+      ERROR_CHECK_SETOPT(CURLOPT_SSL_OPTIONS, CURLSSLOPT_REVOKE_BEST_EFFORT);
     if(data->set.ssl.fsslctx)
     if(data->set.ssl.fsslctx)
       ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
       ERROR_CHECK_SETOPT(CURLOPT_SSL_CTX_FUNCTION, data->set.ssl.fsslctx);
     if(data->set.ssl.fsslctxp)
     if(data->set.ssl.fsslctxp)
@@ -380,10 +373,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
  * 'Curl_addrinfo *' with the address information.
  * 'Curl_addrinfo *' with the address information.
  */
  */
 
 
-Curl_addrinfo *Curl_doh(struct connectdata *conn,
-                        const char *hostname,
-                        int port,
-                        int *waitp)
+struct Curl_addrinfo *Curl_doh(struct connectdata *conn,
+                               const char *hostname,
+                               int port,
+                               int *waitp)
 {
 {
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
@@ -396,6 +389,7 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
   /* start clean, consider allocating this struct on demand */
   /* start clean, consider allocating this struct on demand */
   memset(&data->req.doh, 0, sizeof(struct dohdata));
   memset(&data->req.doh, 0, sizeof(struct dohdata));
 
 
+  conn->bits.doh = TRUE;
   data->req.doh.host = hostname;
   data->req.doh.host = hostname;
   data->req.doh.port = port;
   data->req.doh.port = port;
   data->req.doh.headers =
   data->req.doh.headers =
@@ -434,7 +428,7 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
   return NULL;
   return NULL;
 }
 }
 
 
-static DOHcode skipqname(unsigned char *doh, size_t dohlen,
+static DOHcode skipqname(const unsigned char *doh, size_t dohlen,
                          unsigned int *indexp)
                          unsigned int *indexp)
 {
 {
   unsigned char length;
   unsigned char length;
@@ -458,12 +452,12 @@ static DOHcode skipqname(unsigned char *doh, size_t dohlen,
   return DOH_OK;
   return DOH_OK;
 }
 }
 
 
-static unsigned short get16bit(unsigned char *doh, int index)
+static unsigned short get16bit(const unsigned char *doh, int index)
 {
 {
   return (unsigned short)((doh[index] << 8) | doh[index + 1]);
   return (unsigned short)((doh[index] << 8) | doh[index + 1]);
 }
 }
 
 
-static unsigned int get32bit(unsigned char *doh, int index)
+static unsigned int get32bit(const unsigned char *doh, int index)
 {
 {
    /* make clang and gcc optimize this to bswap by incrementing
    /* make clang and gcc optimize this to bswap by incrementing
       the pointer first. */
       the pointer first. */
@@ -475,7 +469,7 @@ static unsigned int get32bit(unsigned char *doh, int index)
   return ( (unsigned)doh[0] << 24) | (doh[1] << 16) |(doh[2] << 8) | doh[3];
   return ( (unsigned)doh[0] << 24) | (doh[1] << 16) |(doh[2] << 8) | doh[3];
 }
 }
 
 
-static DOHcode store_a(unsigned char *doh, int index, struct dohentry *d)
+static DOHcode store_a(const unsigned char *doh, int index, struct dohentry *d)
 {
 {
   /* silently ignore addresses over the limit */
   /* silently ignore addresses over the limit */
   if(d->numaddr < DOH_MAX_ADDR) {
   if(d->numaddr < DOH_MAX_ADDR) {
@@ -487,7 +481,9 @@ static DOHcode store_a(unsigned char *doh, int index, struct dohentry *d)
   return DOH_OK;
   return DOH_OK;
 }
 }
 
 
-static DOHcode store_aaaa(unsigned char *doh, int index, struct dohentry *d)
+static DOHcode store_aaaa(const unsigned char *doh,
+                          int index,
+                          struct dohentry *d)
 {
 {
   /* silently ignore addresses over the limit */
   /* silently ignore addresses over the limit */
   if(d->numaddr < DOH_MAX_ADDR) {
   if(d->numaddr < DOH_MAX_ADDR) {
@@ -499,38 +495,12 @@ static DOHcode store_aaaa(unsigned char *doh, int index, struct dohentry *d)
   return DOH_OK;
   return DOH_OK;
 }
 }
 
 
-static DOHcode cnameappend(struct cnamestore *c,
-                           unsigned char *src,
-                           size_t len)
-{
-  if(!c->alloc) {
-    c->allocsize = len + 1;
-    c->alloc = malloc(c->allocsize);
-    if(!c->alloc)
-      return DOH_OUT_OF_MEM;
-  }
-  else if(c->allocsize < (c->allocsize + len + 1)) {
-    char *ptr;
-    c->allocsize += len + 1;
-    ptr = realloc(c->alloc, c->allocsize);
-    if(!ptr) {
-      free(c->alloc);
-      return DOH_OUT_OF_MEM;
-    }
-    c->alloc = ptr;
-  }
-  memcpy(&c->alloc[c->len], src, len);
-  c->len += len;
-  c->alloc[c->len] = 0; /* keep it zero terminated */
-  return DOH_OK;
-}
-
-static DOHcode store_cname(unsigned char *doh,
+static DOHcode store_cname(const unsigned char *doh,
                            size_t dohlen,
                            size_t dohlen,
                            unsigned int index,
                            unsigned int index,
                            struct dohentry *d)
                            struct dohentry *d)
 {
 {
-  struct cnamestore *c;
+  struct dynbuf *c;
   unsigned int loop = 128; /* a valid DNS name can never loop this much */
   unsigned int loop = 128; /* a valid DNS name can never loop this much */
   unsigned char length;
   unsigned char length;
 
 
@@ -559,18 +529,15 @@ static DOHcode store_cname(unsigned char *doh,
       index++;
       index++;
 
 
     if(length) {
     if(length) {
-      DOHcode rc;
-      if(c->len) {
-        rc = cnameappend(c, (unsigned char *)".", 1);
-        if(rc)
-          return rc;
+      if(Curl_dyn_len(c)) {
+        if(Curl_dyn_add(c, "."))
+          return DOH_OUT_OF_MEM;
       }
       }
       if((index + length) > dohlen)
       if((index + length) > dohlen)
         return DOH_DNS_BAD_LABEL;
         return DOH_DNS_BAD_LABEL;
 
 
-      rc = cnameappend(c, &doh[index], length);
-      if(rc)
-        return rc;
+      if(Curl_dyn_addn(c, &doh[index], length))
+        return DOH_OUT_OF_MEM;
       index += length;
       index += length;
     }
     }
   } while(length && --loop);
   } while(length && --loop);
@@ -580,7 +547,7 @@ static DOHcode store_cname(unsigned char *doh,
   return DOH_OK;
   return DOH_OK;
 }
 }
 
 
-static DOHcode rdata(unsigned char *doh,
+static DOHcode rdata(const unsigned char *doh,
                      size_t dohlen,
                      size_t dohlen,
                      unsigned short rdlength,
                      unsigned short rdlength,
                      unsigned short type,
                      unsigned short type,
@@ -623,14 +590,17 @@ static DOHcode rdata(unsigned char *doh,
   return DOH_OK;
   return DOH_OK;
 }
 }
 
 
-static void init_dohentry(struct dohentry *de)
+UNITTEST void de_init(struct dohentry *de)
 {
 {
+  int i;
   memset(de, 0, sizeof(*de));
   memset(de, 0, sizeof(*de));
   de->ttl = INT_MAX;
   de->ttl = INT_MAX;
+  for(i = 0; i < DOH_MAX_CNAME; i++)
+    Curl_dyn_init(&de->cname[i], DYN_DOH_CNAME);
 }
 }
 
 
 
 
-UNITTEST DOHcode doh_decode(unsigned char *doh,
+UNITTEST DOHcode doh_decode(const unsigned char *doh,
                             size_t dohlen,
                             size_t dohlen,
                             DNStype dnstype,
                             DNStype dnstype,
                             struct dohentry *d)
                             struct dohentry *d)
@@ -770,12 +740,12 @@ UNITTEST DOHcode doh_decode(unsigned char *doh,
 
 
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
 static void showdoh(struct Curl_easy *data,
 static void showdoh(struct Curl_easy *data,
-                    struct dohentry *d)
+                    const struct dohentry *d)
 {
 {
   int i;
   int i;
   infof(data, "TTL: %u seconds\n", d->ttl);
   infof(data, "TTL: %u seconds\n", d->ttl);
   for(i = 0; i < d->numaddr; i++) {
   for(i = 0; i < d->numaddr; i++) {
-    struct dohaddr *a = &d->addr[i];
+    const struct dohaddr *a = &d->addr[i];
     if(a->type == DNS_TYPE_A) {
     if(a->type == DNS_TYPE_A) {
       infof(data, "DOH A: %u.%u.%u.%u\n",
       infof(data, "DOH A: %u.%u.%u.%u\n",
             a->ip.v4[0], a->ip.v4[1],
             a->ip.v4[0], a->ip.v4[1],
@@ -801,7 +771,7 @@ static void showdoh(struct Curl_easy *data,
     }
     }
   }
   }
   for(i = 0; i < d->numcname; i++) {
   for(i = 0; i < d->numcname; i++) {
-    infof(data, "CNAME: %s\n", d->cname[i].alloc);
+    infof(data, "CNAME: %s\n", Curl_dyn_ptr(&d->cname[i]));
   }
   }
 }
 }
 #else
 #else
@@ -821,18 +791,19 @@ static void showdoh(struct Curl_easy *data,
  * must be an associated call later to Curl_freeaddrinfo().
  * must be an associated call later to Curl_freeaddrinfo().
  */
  */
 
 
-static Curl_addrinfo *
+static struct Curl_addrinfo *
 doh2ai(const struct dohentry *de, const char *hostname, int port)
 doh2ai(const struct dohentry *de, const char *hostname, int port)
 {
 {
-  Curl_addrinfo *ai;
-  Curl_addrinfo *prevai = NULL;
-  Curl_addrinfo *firstai = NULL;
+  struct Curl_addrinfo *ai;
+  struct Curl_addrinfo *prevai = NULL;
+  struct Curl_addrinfo *firstai = NULL;
   struct sockaddr_in *addr;
   struct sockaddr_in *addr;
 #ifdef ENABLE_IPV6
 #ifdef ENABLE_IPV6
   struct sockaddr_in6 *addr6;
   struct sockaddr_in6 *addr6;
 #endif
 #endif
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
   int i;
   int i;
+  size_t hostlen = strlen(hostname) + 1; /* include zero terminator */
 
 
   if(!de)
   if(!de)
     /* no input == no output! */
     /* no input == no output! */
@@ -855,24 +826,14 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
       addrtype = AF_INET;
       addrtype = AF_INET;
     }
     }
 
 
-    ai = calloc(1, sizeof(Curl_addrinfo));
+    ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen);
     if(!ai) {
     if(!ai) {
       result = CURLE_OUT_OF_MEMORY;
       result = CURLE_OUT_OF_MEMORY;
       break;
       break;
     }
     }
-    ai->ai_canonname = strdup(hostname);
-    if(!ai->ai_canonname) {
-      result = CURLE_OUT_OF_MEMORY;
-      free(ai);
-      break;
-    }
-    ai->ai_addr = calloc(1, ss_size);
-    if(!ai->ai_addr) {
-      result = CURLE_OUT_OF_MEMORY;
-      free(ai->ai_canonname);
-      free(ai);
-      break;
-    }
+    ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
+    ai->ai_canonname = (void *)((char *)ai->ai_addr + ss_size);
+    memcpy(ai->ai_canonname, hostname, hostlen);
 
 
     if(!firstai)
     if(!firstai)
       /* store the pointer we want to return from this function */
       /* store the pointer we want to return from this function */
@@ -934,7 +895,7 @@ UNITTEST void de_cleanup(struct dohentry *d)
 {
 {
   int i = 0;
   int i = 0;
   for(i = 0; i < d->numcname; i++) {
   for(i = 0; i < d->numcname; i++) {
-    free(d->cname[i].alloc);
+    Curl_dyn_free(&d->cname[i]);
   }
   }
 }
 }
 
 
@@ -952,7 +913,9 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
       CURLE_COULDNT_RESOLVE_HOST;
       CURLE_COULDNT_RESOLVE_HOST;
   }
   }
   else if(!data->req.doh.pending) {
   else if(!data->req.doh.pending) {
-    DOHcode rc[DOH_PROBE_SLOTS];
+    DOHcode rc[DOH_PROBE_SLOTS] = {
+      DOH_OK, DOH_OK
+    };
     struct dohentry de;
     struct dohentry de;
     int slot;
     int slot;
     /* remove DOH handles from multi handle and close them */
     /* remove DOH handles from multi handle and close them */
@@ -961,17 +924,19 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
       Curl_close(&data->req.doh.probe[slot].easy);
       Curl_close(&data->req.doh.probe[slot].easy);
     }
     }
     /* parse the responses, create the struct and return it! */
     /* parse the responses, create the struct and return it! */
-    init_dohentry(&de);
+    de_init(&de);
     for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
     for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
-      rc[slot] = doh_decode(data->req.doh.probe[slot].serverdoh.memory,
-                            data->req.doh.probe[slot].serverdoh.size,
-                            data->req.doh.probe[slot].dnstype,
+      struct dnsprobe *p = &data->req.doh.probe[slot];
+      if(!p->dnstype)
+        continue;
+      rc[slot] = doh_decode(Curl_dyn_uptr(&p->serverdoh),
+                            Curl_dyn_len(&p->serverdoh),
+                            p->dnstype,
                             &de);
                             &de);
-      Curl_safefree(data->req.doh.probe[slot].serverdoh.memory);
+      Curl_dyn_free(&p->serverdoh);
       if(rc[slot]) {
       if(rc[slot]) {
         infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]),
         infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]),
-              type2name(data->req.doh.probe[slot].dnstype),
-              data->req.doh.host);
+              type2name(p->dnstype), data->req.doh.host);
       }
       }
     } /* next slot */
     } /* next slot */
 
 

+ 10 - 15
Utilities/cmcurl/lib/doh.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 2018 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 2018 - 2020, 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,10 +32,10 @@
  * and returns a 'Curl_addrinfo *' with the address information.
  * and returns a 'Curl_addrinfo *' with the address information.
  */
  */
 
 
-Curl_addrinfo *Curl_doh(struct connectdata *conn,
-                        const char *hostname,
-                        int port,
-                        int *waitp);
+struct Curl_addrinfo *Curl_doh(struct connectdata *conn,
+                               const char *hostname,
+                               int port,
+                               int *waitp);
 
 
 CURLcode Curl_doh_is_resolved(struct connectdata *conn,
 CURLcode Curl_doh_is_resolved(struct connectdata *conn,
                               struct Curl_dns_entry **dns);
                               struct Curl_dns_entry **dns);
@@ -70,12 +70,6 @@ typedef enum {
 #define DOH_MAX_ADDR 24
 #define DOH_MAX_ADDR 24
 #define DOH_MAX_CNAME 4
 #define DOH_MAX_CNAME 4
 
 
-struct cnamestore {
-  size_t len;       /* length of cname */
-  char *alloc;      /* allocated pointer */
-  size_t allocsize; /* allocated size */
-};
-
 struct dohaddr {
 struct dohaddr {
   int type;
   int type;
   union {
   union {
@@ -85,11 +79,11 @@ struct dohaddr {
 };
 };
 
 
 struct dohentry {
 struct dohentry {
-  unsigned int ttl;
-  int numaddr;
+  struct dynbuf cname[DOH_MAX_CNAME];
   struct dohaddr addr[DOH_MAX_ADDR];
   struct dohaddr addr[DOH_MAX_ADDR];
+  int numaddr;
+  unsigned int ttl;
   int numcname;
   int numcname;
-  struct cnamestore cname[DOH_MAX_CNAME];
 };
 };
 
 
 
 
@@ -99,10 +93,11 @@ DOHcode doh_encode(const char *host,
                    unsigned char *dnsp, /* buffer */
                    unsigned char *dnsp, /* buffer */
                    size_t len,  /* buffer size */
                    size_t len,  /* buffer size */
                    size_t *olen); /* output length */
                    size_t *olen); /* output length */
-DOHcode doh_decode(unsigned char *doh,
+DOHcode doh_decode(const unsigned char *doh,
                    size_t dohlen,
                    size_t dohlen,
                    DNStype dnstype,
                    DNStype dnstype,
                    struct dohentry *d);
                    struct dohentry *d);
+void de_init(struct dohentry *d);
 void de_cleanup(struct dohentry *d);
 void de_cleanup(struct dohentry *d);
 #endif
 #endif
 
 

+ 227 - 0
Utilities/cmcurl/lib/dynbuf.c

@@ -0,0 +1,227 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2020, 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 "strdup.h"
+#include "dynbuf.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define MIN_FIRST_ALLOC 32
+
+#define DYNINIT 0xbee51da /* random pattern */
+
+/*
+ * Init a dynbuf struct.
+ */
+void Curl_dyn_init(struct dynbuf *s, size_t toobig)
+{
+  DEBUGASSERT(s);
+  DEBUGASSERT(toobig);
+  s->bufr = NULL;
+  s->leng = 0;
+  s->allc = 0;
+  s->toobig = toobig;
+#ifdef DEBUGBUILD
+  s->init = DYNINIT;
+#endif
+}
+
+/*
+ * free the buffer and re-init the necessary fields. It doesn't touch the
+ * 'init' field and thus this buffer can be reused to add data to again.
+ */
+void Curl_dyn_free(struct dynbuf *s)
+{
+  DEBUGASSERT(s);
+  Curl_safefree(s->bufr);
+  s->leng = s->allc = 0;
+}
+
+/*
+ * Store/append an chunk of memory to the dynbuf.
+ */
+static CURLcode dyn_nappend(struct dynbuf *s,
+                            const unsigned char *mem, size_t len)
+{
+  size_t indx = s->leng;
+  size_t a = s->allc;
+  size_t fit = len + indx + 1; /* new string + old string + zero byte */
+
+  /* try to detect if there's rubbish in the struct */
+  DEBUGASSERT(s->init == DYNINIT);
+  DEBUGASSERT(s->toobig);
+  DEBUGASSERT(indx < s->toobig);
+  DEBUGASSERT(!s->leng || s->bufr);
+
+  if(fit > s->toobig) {
+    Curl_dyn_free(s);
+    return CURLE_OUT_OF_MEMORY;
+  }
+  else if(!a) {
+    DEBUGASSERT(!indx);
+    /* first invoke */
+    if(fit < MIN_FIRST_ALLOC)
+      a = MIN_FIRST_ALLOC;
+    else
+      a = fit;
+  }
+  else {
+    while(a < fit)
+      a *= 2;
+  }
+
+  if(a != s->allc) {
+    s->bufr = Curl_saferealloc(s->bufr, a);
+    if(!s->bufr) {
+      s->leng = s->allc = 0;
+      return CURLE_OUT_OF_MEMORY;
+    }
+    s->allc = a;
+  }
+
+  if(len)
+    memcpy(&s->bufr[indx], mem, len);
+  s->leng = indx + len;
+  s->bufr[s->leng] = 0;
+  return CURLE_OK;
+}
+
+/*
+ * Clears the string, keeps the allocation. This can also be called on a
+ * buffer that already was freed.
+ */
+void Curl_dyn_reset(struct dynbuf *s)
+{
+  DEBUGASSERT(s);
+  DEBUGASSERT(s->init == DYNINIT);
+  DEBUGASSERT(!s->leng || s->bufr);
+  if(s->leng)
+    s->bufr[0] = 0;
+  s->leng = 0;
+}
+
+#ifdef USE_NGTCP2
+/*
+ * Specify the size of the tail to keep (number of bytes from the end of the
+ * buffer). The rest will be dropped.
+ */
+CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail)
+{
+  DEBUGASSERT(s);
+  DEBUGASSERT(s->init == DYNINIT);
+  DEBUGASSERT(!s->leng || s->bufr);
+  if(trail > s->leng)
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+  else if(trail == s->leng)
+    return CURLE_OK;
+  else if(!trail) {
+    Curl_dyn_reset(s);
+  }
+  else {
+    memmove(&s->bufr[0], &s->bufr[s->leng - trail], trail);
+    s->leng = trail;
+  }
+  return CURLE_OK;
+
+}
+#endif
+
+/*
+ * Appends a buffer with length.
+ */
+CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
+{
+  DEBUGASSERT(s);
+  DEBUGASSERT(s->init == DYNINIT);
+  DEBUGASSERT(!s->leng || s->bufr);
+  return dyn_nappend(s, mem, len);
+}
+
+/*
+ * Append a zero terminated string at the end.
+ */
+CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
+{
+  size_t n = strlen(str);
+  DEBUGASSERT(s);
+  DEBUGASSERT(s->init == DYNINIT);
+  DEBUGASSERT(!s->leng || s->bufr);
+  return dyn_nappend(s, (unsigned char *)str, n);
+}
+
+/*
+ * Append a string printf()-style
+ */
+CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
+{
+  char *str;
+  va_list ap;
+  va_start(ap, fmt);
+  str = vaprintf(fmt, ap); /* this allocs a new string to append */
+  va_end(ap);
+
+  if(str) {
+    CURLcode result = dyn_nappend(s, (unsigned char *)str, strlen(str));
+    free(str);
+    return result;
+  }
+  /* If we failed, we cleanup the whole buffer and return error */
+  Curl_dyn_free(s);
+  return CURLE_OUT_OF_MEMORY;
+}
+
+/*
+ * Returns a pointer to the buffer.
+ */
+char *Curl_dyn_ptr(const struct dynbuf *s)
+{
+  DEBUGASSERT(s);
+  DEBUGASSERT(s->init == DYNINIT);
+  DEBUGASSERT(!s->leng || s->bufr);
+  return s->bufr;
+}
+
+/*
+ * Returns an unsigned pointer to the buffer.
+ */
+unsigned char *Curl_dyn_uptr(const struct dynbuf *s)
+{
+  DEBUGASSERT(s);
+  DEBUGASSERT(s->init == DYNINIT);
+  DEBUGASSERT(!s->leng || s->bufr);
+  return (unsigned char *)s->bufr;
+}
+
+/*
+ * Returns the length of the buffer.
+ */
+size_t Curl_dyn_len(const struct dynbuf *s)
+{
+  DEBUGASSERT(s);
+  DEBUGASSERT(s->init == DYNINIT);
+  DEBUGASSERT(!s->leng || s->bufr);
+  return s->leng;
+}

+ 63 - 0
Utilities/cmcurl/lib/dynbuf.h

@@ -0,0 +1,63 @@
+#ifndef HEADER_CURL_DYNBUF_H
+#define HEADER_CURL_DYNBUF_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2020, 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.
+ *
+ ***************************************************************************/
+
+struct dynbuf {
+  char *bufr;    /* point to a zero terminated allocated buffer */
+  size_t leng;   /* number of bytes *EXCLUDING* the zero terminator */
+  size_t allc;   /* size of the current allocation */
+  size_t toobig; /* size limit for the buffer */
+#ifdef DEBUGBUILD
+  int init;     /* detect API usage mistakes */
+#endif
+};
+
+void Curl_dyn_init(struct dynbuf *s, size_t toobig);
+void Curl_dyn_free(struct dynbuf *s);
+CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
+  WARN_UNUSED_RESULT;
+CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
+  WARN_UNUSED_RESULT;
+CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
+  WARN_UNUSED_RESULT;
+void Curl_dyn_reset(struct dynbuf *s);
+CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail);
+char *Curl_dyn_ptr(const struct dynbuf *s);
+unsigned char *Curl_dyn_uptr(const struct dynbuf *s);
+size_t Curl_dyn_len(const struct dynbuf *s);
+
+/* Dynamic buffer max sizes */
+#define DYN_DOH_RESPONSE    3000
+#define DYN_DOH_CNAME       256
+#define DYN_PAUSE_BUFFER    (64 * 1024 * 1024)
+#define DYN_HAXPROXY        2048
+#define DYN_HTTP_REQUEST    (128*1024)
+#define DYN_H2_HEADERS      (128*1024)
+#define DYN_H2_TRAILER      4096
+#define DYN_APRINTF         8000000
+#define DYN_RTSP_REQ_HEADER (64*1024)
+#define DYN_TRAILERS        (64*1024)
+#define DYN_PROXY_CONNECT_HEADERS 16384
+#define DYN_QLOG_NAME       1024
+#define DYN_H1_TRAILER      DYN_H2_TRAILER
+#endif

+ 74 - 38
Utilities/cmcurl/lib/easy.c

@@ -77,14 +77,13 @@
 #include "http_digest.h"
 #include "http_digest.h"
 #include "system_win32.h"
 #include "system_win32.h"
 #include "http2.h"
 #include "http2.h"
+#include "dynbuf.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"
 #include "memdebug.h"
 #include "memdebug.h"
 
 
-void Curl_version_init(void);
-
 /* 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;
@@ -201,8 +200,6 @@ static CURLcode global_init(long flags, bool memoryfuncs)
 
 
   init_flags = flags;
   init_flags = flags;
 
 
-  Curl_version_init();
-
   return CURLE_OK;
   return CURLE_OK;
 
 
   fail:
   fail:
@@ -513,7 +510,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
     before = Curl_now();
     before = Curl_now();
 
 
     /* wait for activity or timeout */
     /* wait for activity or timeout */
-    pollrc = Curl_poll(fds, numfds, (int)ev->ms);
+    pollrc = Curl_poll(fds, numfds, ev->ms);
 
 
     after = Curl_now();
     after = Curl_now();
 
 
@@ -684,6 +681,7 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
   mcode = curl_multi_add_handle(multi, data);
   mcode = curl_multi_add_handle(multi, data);
   if(mcode) {
   if(mcode) {
     curl_multi_cleanup(multi);
     curl_multi_cleanup(multi);
+    data->multi_easy = NULL;
     if(mcode == CURLM_OUT_OF_MEMORY)
     if(mcode == CURLM_OUT_OF_MEMORY)
       return CURLE_OUT_OF_MEMORY;
       return CURLE_OUT_OF_MEMORY;
     return CURLE_FAILED_INIT;
     return CURLE_FAILED_INIT;
@@ -766,6 +764,7 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
 {
 {
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
   enum dupstring i;
   enum dupstring i;
+  enum dupblob j;
 
 
   /* Copy src->set into dst->set first, then deal with the strings
   /* Copy src->set into dst->set first, then deal with the strings
      afterwards */
      afterwards */
@@ -782,6 +781,16 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
       return result;
       return result;
   }
   }
 
 
+  /* clear all blob pointers first */
+  memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *));
+  /* duplicate all blobs */
+  for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
+    result = Curl_setblobopt(&dst->set.blobs[j], src->set.blobs[j]);
+    /* Curl_setstropt return CURLE_BAD_FUNCTION_ARGUMENT with blob */
+    if(result)
+      return result;
+  }
+
   /* duplicate memory areas pointed to */
   /* duplicate memory areas pointed to */
   i = STRING_COPYPOSTFIELDS;
   i = STRING_COPYPOSTFIELDS;
   if(src->set.postfieldsize && src->set.str[i]) {
   if(src->set.postfieldsize && src->set.str[i]) {
@@ -820,19 +829,13 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
    * the likeliness of us forgetting to init a buffer here in the future.
    * the likeliness of us forgetting to init a buffer here in the future.
    */
    */
   outcurl->set.buffer_size = data->set.buffer_size;
   outcurl->set.buffer_size = data->set.buffer_size;
-  outcurl->state.buffer = malloc(outcurl->set.buffer_size + 1);
-  if(!outcurl->state.buffer)
-    goto fail;
-
-  outcurl->state.headerbuff = malloc(HEADERSIZE);
-  if(!outcurl->state.headerbuff)
-    goto fail;
-  outcurl->state.headersize = HEADERSIZE;
 
 
   /* copy all userdefined values */
   /* copy all userdefined values */
   if(dupset(outcurl, data))
   if(dupset(outcurl, data))
     goto fail;
     goto fail;
 
 
+  Curl_dyn_init(&outcurl->state.headerb, CURL_MAX_HTTP_HEADER);
+
   /* the connection cache is setup on demand */
   /* the connection cache is setup on demand */
   outcurl->state.conn_cache = NULL;
   outcurl->state.conn_cache = NULL;
 
 
@@ -887,6 +890,28 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
                              data->state.resolver))
                              data->state.resolver))
     goto fail;
     goto fail;
 
 
+#ifdef USE_ARES
+  {
+    CURLcode rc;
+
+    rc = Curl_set_dns_servers(outcurl, data->set.str[STRING_DNS_SERVERS]);
+    if(rc && rc != CURLE_NOT_BUILT_IN)
+      goto fail;
+
+    rc = Curl_set_dns_interface(outcurl, data->set.str[STRING_DNS_INTERFACE]);
+    if(rc && rc != CURLE_NOT_BUILT_IN)
+      goto fail;
+
+    rc = Curl_set_dns_local_ip4(outcurl, data->set.str[STRING_DNS_LOCAL_IP4]);
+    if(rc && rc != CURLE_NOT_BUILT_IN)
+      goto fail;
+
+    rc = Curl_set_dns_local_ip6(outcurl, data->set.str[STRING_DNS_LOCAL_IP6]);
+    if(rc && rc != CURLE_NOT_BUILT_IN)
+      goto fail;
+  }
+#endif /* USE_ARES */
+
   Curl_convert_setup(outcurl);
   Curl_convert_setup(outcurl);
 
 
   Curl_initinfo(outcurl);
   Curl_initinfo(outcurl);
@@ -903,7 +928,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
     curl_slist_free_all(outcurl->change.cookielist);
     curl_slist_free_all(outcurl->change.cookielist);
     outcurl->change.cookielist = NULL;
     outcurl->change.cookielist = NULL;
     Curl_safefree(outcurl->state.buffer);
     Curl_safefree(outcurl->state.buffer);
-    Curl_safefree(outcurl->state.headerbuff);
+    Curl_dyn_free(&outcurl->state.headerb);
     Curl_safefree(outcurl->change.url);
     Curl_safefree(outcurl->change.url);
     Curl_safefree(outcurl->change.referer);
     Curl_safefree(outcurl->change.referer);
     Curl_freeset(outcurl);
     Curl_freeset(outcurl);
@@ -919,8 +944,6 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
  */
  */
 void curl_easy_reset(struct Curl_easy *data)
 void curl_easy_reset(struct Curl_easy *data)
 {
 {
-  long old_buffer_size = data->set.buffer_size;
-
   Curl_free_request_state(data);
   Curl_free_request_state(data);
 
 
   /* zero out UserDefined data: */
   /* zero out UserDefined data: */
@@ -944,18 +967,6 @@ void curl_easy_reset(struct Curl_easy *data)
 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
   Curl_http_auth_cleanup_digest(data);
   Curl_http_auth_cleanup_digest(data);
 #endif
 #endif
-
-  /* resize receive buffer */
-  if(old_buffer_size != data->set.buffer_size) {
-    char *newbuff = realloc(data->state.buffer, data->set.buffer_size + 1);
-    if(!newbuff) {
-      DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
-      /* nothing we can do here except use the old size */
-      data->set.buffer_size = old_buffer_size;
-    }
-    else
-      data->state.buffer = newbuff;
-  }
 }
 }
 
 
 /*
 /*
@@ -973,16 +984,37 @@ void curl_easy_reset(struct Curl_easy *data)
  */
  */
 CURLcode curl_easy_pause(struct Curl_easy *data, int action)
 CURLcode curl_easy_pause(struct Curl_easy *data, int action)
 {
 {
-  struct SingleRequest *k = &data->req;
+  struct SingleRequest *k;
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
+  int oldstate;
+  int newstate;
 
 
-  /* first switch off both pause bits */
-  int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
+  if(!GOOD_EASY_HANDLE(data) || !data->conn)
+    /* crazy input, don't continue */
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  k = &data->req;
+  oldstate = k->keepon & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
 
 
-  /* set the new desired pause bits */
-  newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) |
+  /* first switch off both pause bits then set the new pause bits */
+  newstate = (k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) |
+    ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) |
     ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0);
     ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0);
 
 
+  if((newstate & (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE)) == oldstate) {
+    /* Not changing any pause state, return */
+    DEBUGF(infof(data, "pause: no change, early return\n"));
+    return CURLE_OK;
+  }
+
+  /* Unpause parts in active mime tree. */
+  if((k->keepon & ~newstate & KEEP_SEND_PAUSE) &&
+     (data->mstate == CURLM_STATE_PERFORM ||
+      data->mstate == CURLM_STATE_TOOFAST) &&
+     data->state.fread_func == (curl_read_callback) Curl_mime_read) {
+    Curl_mime_unpause(data->state.in);
+  }
+
   /* put it back in the keepon */
   /* put it back in the keepon */
   k->keepon = newstate;
   k->keepon = newstate;
 
 
@@ -1001,7 +1033,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
       /* copy the structs to allow for immediate re-pausing */
       /* copy the structs to allow for immediate re-pausing */
       for(i = 0; i < data->state.tempcount; i++) {
       for(i = 0; i < data->state.tempcount; i++) {
         writebuf[i] = data->state.tempwrite[i];
         writebuf[i] = data->state.tempwrite[i];
-        data->state.tempwrite[i].buf = NULL;
+        Curl_dyn_init(&data->state.tempwrite[i].b, DYN_PAUSE_BUFFER);
       }
       }
       data->state.tempcount = 0;
       data->state.tempcount = 0;
 
 
@@ -1015,9 +1047,10 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
         /* even if one function returns error, this loops through and frees
         /* even if one function returns error, this loops through and frees
            all buffers */
            all buffers */
         if(!result)
         if(!result)
-          result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf,
-                                     writebuf[i].len);
-        free(writebuf[i].buf);
+          result = Curl_client_write(conn, writebuf[i].type,
+                                     Curl_dyn_ptr(&writebuf[i].b),
+                                     Curl_dyn_len(&writebuf[i].b));
+        Curl_dyn_free(&writebuf[i].b);
       }
       }
 
 
       /* recover previous owner of the connection */
       /* recover previous owner of the connection */
@@ -1033,8 +1066,11 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
      to have this handle checked soon */
      to have this handle checked soon */
   if((newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
   if((newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
      (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) {
      (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) {
-    data->state.drain++;
     Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
     Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
+
+    /* force a recv/send check of this connection, as the data might've been
+       read off the socket already */
+    data->conn->cselect_bits = CURL_CSELECT_IN | CURL_CSELECT_OUT;
     if(data->multi)
     if(data->multi)
       Curl_update_timer(data->multi);
       Curl_update_timer(data->multi);
   }
   }

+ 1 - 1
Utilities/cmcurl/lib/easyif.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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 - 33
Utilities/cmcurl/lib/escape.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -79,57 +79,42 @@ char *curl_unescape(const char *string, int length)
 char *curl_easy_escape(struct Curl_easy *data, const char *string,
 char *curl_easy_escape(struct Curl_easy *data, const char *string,
                        int inlength)
                        int inlength)
 {
 {
-  size_t alloc;
-  char *ns;
-  char *testing_ptr = NULL;
-  size_t newlen;
-  size_t strindex = 0;
   size_t length;
   size_t length;
   CURLcode result;
   CURLcode result;
+  struct dynbuf d;
 
 
   if(inlength < 0)
   if(inlength < 0)
     return NULL;
     return NULL;
 
 
-  alloc = (inlength?(size_t)inlength:strlen(string)) + 1;
-  newlen = alloc;
-
-  ns = malloc(alloc);
-  if(!ns)
-    return NULL;
+  Curl_dyn_init(&d, CURL_MAX_INPUT_LENGTH);
 
 
-  length = alloc-1;
+  length = (inlength?(size_t)inlength:strlen(string));
   while(length--) {
   while(length--) {
     unsigned char in = *string; /* we need to treat the characters unsigned */
     unsigned char in = *string; /* we need to treat the characters unsigned */
 
 
-    if(Curl_isunreserved(in))
-      /* just copy this */
-      ns[strindex++] = in;
+    if(Curl_isunreserved(in)) {
+      /* append this */
+      if(Curl_dyn_addn(&d, &in, 1))
+        return NULL;
+    }
     else {
     else {
       /* encode it */
       /* encode it */
-      newlen += 2; /* the size grows with two, since this'll become a %XX */
-      if(newlen > alloc) {
-        alloc *= 2;
-        testing_ptr = Curl_saferealloc(ns, alloc);
-        if(!testing_ptr)
-          return NULL;
-        ns = testing_ptr;
-      }
-
+      char encoded[4];
       result = Curl_convert_to_network(data, (char *)&in, 1);
       result = Curl_convert_to_network(data, (char *)&in, 1);
       if(result) {
       if(result) {
         /* Curl_convert_to_network calls failf if unsuccessful */
         /* Curl_convert_to_network calls failf if unsuccessful */
-        free(ns);
+        Curl_dyn_free(&d);
         return NULL;
         return NULL;
       }
       }
 
 
-      msnprintf(&ns[strindex], 4, "%%%02X", in);
-
-      strindex += 3;
+      msnprintf(encoded, sizeof(encoded), "%%%02X", in);
+      if(Curl_dyn_add(&d, encoded))
+        return NULL;
     }
     }
     string++;
     string++;
   }
   }
-  ns[strindex] = 0; /* terminate it */
-  return ns;
+
+  return Curl_dyn_ptr(&d);
 }
 }
 
 
 /*
 /*
@@ -149,12 +134,17 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
                         char **ostring, size_t *olen,
                         char **ostring, size_t *olen,
                         bool reject_ctrl)
                         bool reject_ctrl)
 {
 {
-  size_t alloc = (length?length:strlen(string)) + 1;
-  char *ns = malloc(alloc);
+  size_t alloc;
+  char *ns;
   size_t strindex = 0;
   size_t strindex = 0;
   unsigned long hex;
   unsigned long hex;
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
 
 
+  DEBUGASSERT(string);
+
+  alloc = (length?length:strlen(string)) + 1;
+  ns = malloc(alloc);
+
   if(!ns)
   if(!ns)
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;
 
 

+ 2 - 4
Utilities/cmcurl/lib/file.c

@@ -136,7 +136,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
   struct Curl_easy *data = conn->data;
   struct Curl_easy *data = conn->data;
   char *real_path;
   char *real_path;
   struct FILEPROTO *file = data->req.protop;
   struct FILEPROTO *file = data->req.protop;
-  int fd = -1;
+  int fd;
 #ifdef DOS_FILESYSTEM
 #ifdef DOS_FILESYSTEM
   size_t i;
   size_t i;
   char *actual_path;
   char *actual_path;
@@ -181,9 +181,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
       return CURLE_URL_MALFORMAT;
       return CURLE_URL_MALFORMAT;
     }
     }
 
 
-  if(strncmp("\\\\", actual_path, 2))
-    /* refuse to open path that starts with two backslashes */
-    fd = open_readonly(actual_path, O_RDONLY|O_BINARY);
+  fd = open_readonly(actual_path, O_RDONLY|O_BINARY);
   file->path = actual_path;
   file->path = actual_path;
 #else
 #else
   if(memchr(real_path, 0, real_path_len)) {
   if(memchr(real_path, 0, real_path_len)) {

+ 12 - 16
Utilities/cmcurl/lib/formdata.c

@@ -123,11 +123,11 @@ AddHttpPost(char *name, size_t namelength,
  * parent_form_info is NULL.
  * parent_form_info is NULL.
  *
  *
  ***************************************************************************/
  ***************************************************************************/
-static FormInfo * AddFormInfo(char *value,
-                              char *contenttype,
-                              FormInfo *parent_form_info)
+static struct FormInfo *AddFormInfo(char *value,
+                                    char *contenttype,
+                                    struct FormInfo *parent_form_info)
 {
 {
-  FormInfo *form_info;
+  struct FormInfo *form_info;
   form_info = calloc(1, sizeof(struct FormInfo));
   form_info = calloc(1, sizeof(struct FormInfo));
   if(form_info) {
   if(form_info) {
     if(value)
     if(value)
@@ -204,7 +204,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
                      struct curl_httppost **last_post,
                      struct curl_httppost **last_post,
                      va_list params)
                      va_list params)
 {
 {
-  FormInfo *first_form, *current_form, *form = NULL;
+  struct FormInfo *first_form, *current_form, *form = NULL;
   CURLFORMcode return_value = CURL_FORMADD_OK;
   CURLFORMcode return_value = CURL_FORMADD_OK;
   const char *prevtype = NULL;
   const char *prevtype = NULL;
   struct curl_httppost *post = NULL;
   struct curl_httppost *post = NULL;
@@ -521,7 +521,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
   if(CURL_FORMADD_OK != return_value) {
   if(CURL_FORMADD_OK != return_value) {
     /* On error, free allocated fields for all nodes of the FormInfo linked
     /* On error, free allocated fields for all nodes of the FormInfo linked
        list without deallocating nodes. List nodes are deallocated later on */
        list without deallocating nodes. List nodes are deallocated later on */
-    FormInfo *ptr;
+    struct FormInfo *ptr;
     for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
     for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
       if(ptr->name_alloc) {
       if(ptr->name_alloc) {
         Curl_safefree(ptr->name);
         Curl_safefree(ptr->name);
@@ -650,7 +650,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
       /* On error, free allocated fields for nodes of the FormInfo linked
       /* On error, free allocated fields for nodes of the FormInfo linked
          list which are not already owned by the httppost linked list
          list which are not already owned by the httppost linked list
          without deallocating nodes. List nodes are deallocated later on */
          without deallocating nodes. List nodes are deallocated later on */
-      FormInfo *ptr;
+      struct FormInfo *ptr;
       for(ptr = form; ptr != NULL; ptr = ptr->more) {
       for(ptr = form; ptr != NULL; ptr = ptr->more) {
         if(ptr->name_alloc) {
         if(ptr->name_alloc) {
           Curl_safefree(ptr->name);
           Curl_safefree(ptr->name);
@@ -676,7 +676,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
      fields given that these have either been deallocated or are owned
      fields given that these have either been deallocated or are owned
      now by the httppost linked list */
      now by the httppost linked list */
   while(first_form) {
   while(first_form) {
-    FormInfo *ptr = first_form->more;
+    struct FormInfo *ptr = first_form->more;
     free(first_form);
     free(first_form);
     first_form = ptr;
     first_form = ptr;
   }
   }
@@ -728,14 +728,10 @@ int curl_formget(struct curl_httppost *form, void *arg,
     if(!nread)
     if(!nread)
       break;
       break;
 
 
-    switch(nread) {
-    default:
-      if(append(arg, buffer, nread) != nread)
-        result = CURLE_READ_ERROR;
-      break;
-    case CURL_READFUNC_ABORT:
-    case CURL_READFUNC_PAUSE:
-      break;
+    if(nread > sizeof(buffer) || append(arg, buffer, nread) != nread) {
+      result = CURLE_READ_ERROR;
+      if(nread == CURL_READFUNC_ABORT)
+        result = CURLE_ABORTED_BY_CALLBACK;
     }
     }
   }
   }
 
 

+ 3 - 3
Utilities/cmcurl/lib/formdata.h

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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,7 +27,7 @@
 #ifndef CURL_DISABLE_MIME
 #ifndef CURL_DISABLE_MIME
 
 
 /* used by FormAdd for temporary storage */
 /* used by FormAdd for temporary storage */
-typedef struct FormInfo {
+struct FormInfo {
   char *name;
   char *name;
   bool name_alloc;
   bool name_alloc;
   size_t namelength;
   size_t namelength;
@@ -45,7 +45,7 @@ typedef struct FormInfo {
   char *userp;        /* pointer for the read callback */
   char *userp;        /* pointer for the read callback */
   struct curl_slist *contentheader;
   struct curl_slist *contentheader;
   struct FormInfo *more;
   struct FormInfo *more;
-} FormInfo;
+};
 
 
 CURLcode Curl_getformdata(struct Curl_easy *data,
 CURLcode Curl_getformdata(struct Curl_easy *data,
                           curl_mimepart *,
                           curl_mimepart *,

+ 40 - 24
Utilities/cmcurl/lib/ftp.c

@@ -113,7 +113,7 @@ static CURLcode ftp_parse_url_path(struct connectdata *conn);
 static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done);
 static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done);
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
 static void ftp_pasv_verbose(struct connectdata *conn,
 static void ftp_pasv_verbose(struct connectdata *conn,
-                             Curl_addrinfo *ai,
+                             struct Curl_addrinfo *ai,
                              char *newhost, /* ascii version */
                              char *newhost, /* ascii version */
                              int port);
                              int port);
 #endif
 #endif
@@ -136,7 +136,7 @@ static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks);
 static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks);
 static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks);
 static CURLcode ftp_doing(struct connectdata *conn,
 static CURLcode ftp_doing(struct connectdata *conn,
                           bool *dophase_done);
                           bool *dophase_done);
-static CURLcode ftp_setup_connection(struct connectdata * conn);
+static CURLcode ftp_setup_connection(struct connectdata *conn);
 
 
 static CURLcode init_wc_data(struct connectdata *conn);
 static CURLcode init_wc_data(struct connectdata *conn);
 static CURLcode wc_statemach(struct connectdata *conn);
 static CURLcode wc_statemach(struct connectdata *conn);
@@ -221,6 +221,9 @@ static void close_secondarysocket(struct connectdata *conn)
     conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
     conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
   }
   }
   conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
   conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
+#ifndef CURL_DISABLE_PROXY
+  conn->bits.proxy_ssl_connected[SECONDARYSOCKET] = FALSE;
+#endif
 }
 }
 
 
 /*
 /*
@@ -291,7 +294,7 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
 
 
   conn->sock[SECONDARYSOCKET] = s;
   conn->sock[SECONDARYSOCKET] = s;
   (void)curlx_nonblock(s, TRUE); /* enable non-blocking */
   (void)curlx_nonblock(s, TRUE); /* enable non-blocking */
-  conn->sock_accepted = TRUE;
+  conn->bits.sock_accepted = TRUE;
 
 
   if(data->set.fsockopt) {
   if(data->set.fsockopt) {
     int error = 0;
     int error = 0;
@@ -334,7 +337,7 @@ static timediff_t ftp_timeleft_accept(struct Curl_easy *data)
   now = Curl_now();
   now = Curl_now();
 
 
   /* check if the generic timeout possibly is set shorter */
   /* check if the generic timeout possibly is set shorter */
-  other =  Curl_timeleft(data, &now, FALSE);
+  other = Curl_timeleft(data, &now, FALSE);
   if(other && (other < timeout_ms))
   if(other && (other < timeout_ms))
     /* note that this also works fine for when other happens to be negative
     /* note that this also works fine for when other happens to be negative
        due to it already having elapsed */
        due to it already having elapsed */
@@ -386,7 +389,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
   if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
   if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
     /* Data connection could not be established, let's return */
     /* Data connection could not be established, let's return */
     infof(data, "There is negative response in cache while serv connect\n");
     infof(data, "There is negative response in cache while serv connect\n");
-    Curl_GetFTPResponse(&nread, conn, &ftpcode);
+    (void)Curl_GetFTPResponse(&nread, conn, &ftpcode);
     return CURLE_FTP_ACCEPT_FAILED;
     return CURLE_FTP_ACCEPT_FAILED;
   }
   }
 
 
@@ -408,7 +411,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
     }
     }
     else if(result & CURL_CSELECT_IN) {
     else if(result & CURL_CSELECT_IN) {
       infof(data, "Ctrl conn has data while waiting for data conn\n");
       infof(data, "Ctrl conn has data while waiting for data conn\n");
-      Curl_GetFTPResponse(&nread, conn, &ftpcode);
+      (void)Curl_GetFTPResponse(&nread, conn, &ftpcode);
 
 
       if(ftpcode/100 > 3)
       if(ftpcode/100 > 3)
         return CURLE_FTP_ACCEPT_FAILED;
         return CURLE_FTP_ACCEPT_FAILED;
@@ -632,8 +635,8 @@ 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, FALSE);
-    time_t interval_ms;
+    timediff_t timeout = Curl_pp_state_timeout(pp, FALSE);
+    timediff_t interval_ms;
 
 
     if(timeout <= 0) {
     if(timeout <= 0) {
       failf(data, "FTP response timeout");
       failf(data, "FTP response timeout");
@@ -815,6 +818,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)
 
 
   if(FTP_STOP == ftpc->state) {
   if(FTP_STOP == ftpc->state) {
     int bits = GETSOCK_READSOCK(0);
     int bits = GETSOCK_READSOCK(0);
+    bool any = FALSE;
 
 
     /* if stopped and still in this state, then we're also waiting for a
     /* if stopped and still in this state, then we're also waiting for a
        connect on the secondary connection */
        connect on the secondary connection */
@@ -829,10 +833,11 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)
         if(conn->tempsock[i] != CURL_SOCKET_BAD) {
         if(conn->tempsock[i] != CURL_SOCKET_BAD) {
           socks[s] = conn->tempsock[i];
           socks[s] = conn->tempsock[i];
           bits |= GETSOCK_WRITESOCK(s++);
           bits |= GETSOCK_WRITESOCK(s++);
+          any = TRUE;
         }
         }
       }
       }
     }
     }
-    else {
+    if(!any) {
       socks[1] = conn->sock[SECONDARYSOCKET];
       socks[1] = conn->sock[SECONDARYSOCKET];
       bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1);
       bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1);
     }
     }
@@ -913,7 +918,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   char myhost[MAX_IPADR_LEN + 1] = "";
   char myhost[MAX_IPADR_LEN + 1] = "";
 
 
   struct Curl_sockaddr_storage ss;
   struct Curl_sockaddr_storage ss;
-  Curl_addrinfo *res, *ai;
+  struct Curl_addrinfo *res, *ai;
   curl_socklen_t sslen;
   curl_socklen_t sslen;
   char hbuf[NI_MAXHOST];
   char hbuf[NI_MAXHOST];
   struct sockaddr *sa = (struct sockaddr *)&ss;
   struct sockaddr *sa = (struct sockaddr *)&ss;
@@ -1293,7 +1298,7 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn)
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
   /*
   /*
-    Here's the excecutive summary on what to do:
+    Here's the executive summary on what to do:
 
 
     PASV is RFC959, expect:
     PASV is RFC959, expect:
     227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
     227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
@@ -1759,7 +1764,11 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
 {
 {
   CURLcode result = CURLE_OK;
   CURLcode result = CURLE_OK;
 
 
-  if(conn->bits.ipv6 && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)) {
+  if(conn->bits.ipv6
+#ifndef CURL_DISABLE_PROXY
+     && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)
+#endif
+    ) {
     /* We can't disable EPSV when doing IPv6, so this is instead a fail */
     /* We can't disable EPSV when doing IPv6, so this is instead a fail */
     failf(conn->data, "Failed EPSV attempt, exiting\n");
     failf(conn->data, "Failed EPSV attempt, exiting\n");
     return CURLE_WEIRD_SERVER_REPLY;
     return CURLE_WEIRD_SERVER_REPLY;
@@ -1784,9 +1793,10 @@ static char *control_address(struct connectdata *conn)
      If a proxy tunnel is used, returns the original host name instead, because
      If a proxy tunnel is used, returns the original host name instead, because
      the effective control connection address is the proxy address,
      the effective control connection address is the proxy address,
      not the ftp host. */
      not the ftp host. */
+#ifndef CURL_DISABLE_PROXY
   if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
   if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
     return conn->host.name;
     return conn->host.name;
-
+#endif
   return conn->ip_addr_str;
   return conn->ip_addr_str;
 }
 }
 
 
@@ -1903,6 +1913,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
     return CURLE_FTP_WEIRD_PASV_REPLY;
     return CURLE_FTP_WEIRD_PASV_REPLY;
   }
   }
 
 
+#ifndef CURL_DISABLE_PROXY
   if(conn->bits.proxy) {
   if(conn->bits.proxy) {
     /*
     /*
      * This connection uses a proxy and we need to connect to the proxy again
      * This connection uses a proxy and we need to connect to the proxy again
@@ -1925,7 +1936,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
       return CURLE_COULDNT_RESOLVE_PROXY;
       return CURLE_COULDNT_RESOLVE_PROXY;
     }
     }
   }
   }
-  else {
+  else
+#endif
+  {
     /* normal, direct, ftp connection */
     /* normal, direct, ftp connection */
     rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr);
     rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr);
     if(rc == CURLRESOLV_PENDING)
     if(rc == CURLRESOLV_PENDING)
@@ -2634,9 +2647,12 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
 #endif
 #endif
 
 
       if(data->set.use_ssl &&
       if(data->set.use_ssl &&
-         (!conn->ssl[FIRSTSOCKET].use ||
-          (conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
-           !conn->proxy_ssl[FIRSTSOCKET].use))) {
+         (!conn->ssl[FIRSTSOCKET].use
+#ifndef CURL_DISABLE_PROXY
+          || (conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
+              !conn->proxy_ssl[FIRSTSOCKET].use)
+#endif
+           )) {
         /* We don't have a SSL/TLS connection yet, but FTPS is
         /* We don't have a SSL/TLS connection yet, but FTPS is
            requested. Try a FTPS connection now */
            requested. Try a FTPS connection now */
 
 
@@ -3231,9 +3247,9 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
     }
     }
 
 
     if(conn->ssl[SECONDARYSOCKET].use) {
     if(conn->ssl[SECONDARYSOCKET].use) {
-      /* The secondary socket is using SSL so we must close down that part
-         first before we close the socket for real */
-      Curl_ssl_close(conn, SECONDARYSOCKET);
+      /* The secondary socket used SSL so we must close down that part first
+         before we close the socket for real */
+      result = Curl_ssl_shutdown(conn, SECONDARYSOCKET);
 
 
       /* Note that we keep "use" set to TRUE since that (next) connection is
       /* Note that we keep "use" set to TRUE since that (next) connection is
          still requested to use SSL */
          still requested to use SSL */
@@ -3249,7 +3265,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
      * data has been transferred. This happens when doing through NATs etc that
      * data has been transferred. This happens when doing through NATs etc that
      * abandon old silent connections.
      * abandon old silent connections.
      */
      */
-    long old_time = pp->response_time;
+    timediff_t old_time = pp->response_time;
 
 
     pp->response_time = 60*1000; /* give it only a minute for now */
     pp->response_time = 60*1000; /* give it only a minute for now */
     pp->response = Curl_now(); /* timeout relative now */
     pp->response = Curl_now(); /* timeout relative now */
@@ -3442,7 +3458,7 @@ static CURLcode ftp_nb_type(struct connectdata *conn,
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
 static void
 static void
 ftp_pasv_verbose(struct connectdata *conn,
 ftp_pasv_verbose(struct connectdata *conn,
-                 Curl_addrinfo *ai,
+                 struct Curl_addrinfo *ai,
                  char *newhost, /* ascii version */
                  char *newhost, /* ascii version */
                  int port)
                  int port)
 {
 {
@@ -3500,6 +3516,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
     }
     }
   }
   }
 
 
+#ifndef CURL_DISABLE_PROXY
   result = Curl_proxy_connect(conn, SECONDARYSOCKET);
   result = Curl_proxy_connect(conn, SECONDARYSOCKET);
   if(result)
   if(result)
     return result;
     return result;
@@ -3510,7 +3527,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
   if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
   if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
      Curl_connect_ongoing(conn))
      Curl_connect_ongoing(conn))
     return result;
     return result;
-
+#endif
 
 
   if(ftpc->state) {
   if(ftpc->state) {
     /* already in a state so skip the initial commands.
     /* already in a state so skip the initial commands.
@@ -4338,7 +4355,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
     char command;
     char command;
     *type = 0;                     /* it was in the middle of the hostname */
     *type = 0;                     /* it was in the middle of the hostname */
     command = Curl_raw_toupper(type[6]);
     command = Curl_raw_toupper(type[6]);
-    conn->bits.type_set = TRUE;
 
 
     switch(command) {
     switch(command) {
     case 'A': /* ASCII mode */
     case 'A': /* ASCII mode */

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

@@ -150,7 +150,6 @@ struct ftp_conn {
      connection to */
      connection to */
   char *newhost;          /* this is the pair to connect the DATA... */
   char *newhost;          /* this is the pair to connect the DATA... */
   unsigned short newport; /* connection to */
   unsigned short newport; /* connection to */
-
 };
 };
 
 
 #define DEFAULT_ACCEPT_TIMEOUT   60000 /* milliseconds == one minute */
 #define DEFAULT_ACCEPT_TIMEOUT   60000 /* milliseconds == one minute */

+ 81 - 7
Utilities/cmcurl/lib/getinfo.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -147,6 +147,33 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
     long          *to_long;
     long          *to_long;
   } lptr;
   } lptr;
 
 
+#ifdef DEBUGBUILD
+  char *timestr = getenv("CURL_TIME");
+  if(timestr) {
+    unsigned long val = strtol(timestr, NULL, 10);
+    switch(info) {
+    case CURLINFO_LOCAL_PORT:
+      *param_longp = (long)val;
+      return CURLE_OK;
+    default:
+      break;
+    }
+  }
+  /* use another variable for this to allow different values */
+  timestr = getenv("CURL_DEBUG_SIZE");
+  if(timestr) {
+    unsigned long val = strtol(timestr, NULL, 10);
+    switch(info) {
+    case CURLINFO_HEADER_SIZE:
+    case CURLINFO_REQUEST_SIZE:
+      *param_longp = (long)val;
+      return CURLE_OK;
+    default:
+      break;
+    }
+  }
+#endif
+
   switch(info) {
   switch(info) {
   case CURLINFO_RESPONSE_CODE:
   case CURLINFO_RESPONSE_CODE:
     *param_longp = data->info.httpcode;
     *param_longp = data->info.httpcode;
@@ -171,9 +198,11 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
   case CURLINFO_SSL_VERIFYRESULT:
   case CURLINFO_SSL_VERIFYRESULT:
     *param_longp = data->set.ssl.certverifyresult;
     *param_longp = data->set.ssl.certverifyresult;
     break;
     break;
+#ifndef CURL_DISABLE_PROXY
   case CURLINFO_PROXY_SSL_VERIFYRESULT:
   case CURLINFO_PROXY_SSL_VERIFYRESULT:
     *param_longp = data->set.proxy_ssl.certverifyresult;
     *param_longp = data->set.proxy_ssl.certverifyresult;
     break;
     break;
+#endif
   case CURLINFO_REDIRECT_COUNT:
   case CURLINFO_REDIRECT_COUNT:
     *param_longp = data->set.followlocation;
     *param_longp = data->set.followlocation;
     break;
     break;
@@ -212,8 +241,11 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
     *param_longp = data->info.conn_local_port;
     *param_longp = data->info.conn_local_port;
     break;
     break;
   case CURLINFO_CONDITION_UNMET:
   case CURLINFO_CONDITION_UNMET:
-    /* return if the condition prevented the document to get transferred */
-    *param_longp = data->info.timecond ? 1L : 0L;
+    if(data->info.httpcode == 304)
+      *param_longp = 1L;
+    else
+      /* return if the condition prevented the document to get transferred */
+      *param_longp = data->info.timecond ? 1L : 0L;
     break;
     break;
   case CURLINFO_RTSP_CLIENT_CSEQ:
   case CURLINFO_RTSP_CLIENT_CSEQ:
     *param_longp = data->state.rtsp_next_client_CSeq;
     *param_longp = data->state.rtsp_next_client_CSeq;
@@ -258,6 +290,27 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
 static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
 static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
                              curl_off_t *param_offt)
                              curl_off_t *param_offt)
 {
 {
+#ifdef DEBUGBUILD
+  char *timestr = getenv("CURL_TIME");
+  if(timestr) {
+    unsigned long val = strtol(timestr, NULL, 10);
+    switch(info) {
+    case CURLINFO_TOTAL_TIME_T:
+    case CURLINFO_NAMELOOKUP_TIME_T:
+    case CURLINFO_CONNECT_TIME_T:
+    case CURLINFO_APPCONNECT_TIME_T:
+    case CURLINFO_PRETRANSFER_TIME_T:
+    case CURLINFO_STARTTRANSFER_TIME_T:
+    case CURLINFO_REDIRECT_TIME_T:
+    case CURLINFO_SPEED_DOWNLOAD_T:
+    case CURLINFO_SPEED_UPLOAD_T:
+      *param_offt = (curl_off_t)val;
+      return CURLE_OK;
+    default:
+      break;
+    }
+  }
+#endif
   switch(info) {
   switch(info) {
   case CURLINFO_FILETIME_T:
   case CURLINFO_FILETIME_T:
     *param_offt = (curl_off_t)data->info.filetime;
     *param_offt = (curl_off_t)data->info.filetime;
@@ -269,7 +322,7 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
     *param_offt = data->progress.downloaded;
     *param_offt = data->progress.downloaded;
     break;
     break;
   case CURLINFO_SPEED_DOWNLOAD_T:
   case CURLINFO_SPEED_DOWNLOAD_T:
-    *param_offt =  data->progress.dlspeed;
+    *param_offt = data->progress.dlspeed;
     break;
     break;
   case CURLINFO_SPEED_UPLOAD_T:
   case CURLINFO_SPEED_UPLOAD_T:
     *param_offt = data->progress.ulspeed;
     *param_offt = data->progress.ulspeed;
@@ -282,7 +335,7 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
     *param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
     *param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
       data->progress.size_ul:-1;
       data->progress.size_ul:-1;
     break;
     break;
-  case CURLINFO_TOTAL_TIME_T:
+   case CURLINFO_TOTAL_TIME_T:
     *param_offt = data->progress.timespent;
     *param_offt = data->progress.timespent;
     break;
     break;
   case CURLINFO_NAMELOOKUP_TIME_T:
   case CURLINFO_NAMELOOKUP_TIME_T:
@@ -316,6 +369,27 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
 static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
 static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
                                double *param_doublep)
                                double *param_doublep)
 {
 {
+#ifdef DEBUGBUILD
+  char *timestr = getenv("CURL_TIME");
+  if(timestr) {
+    unsigned long val = strtol(timestr, NULL, 10);
+    switch(info) {
+    case CURLINFO_TOTAL_TIME:
+    case CURLINFO_NAMELOOKUP_TIME:
+    case CURLINFO_CONNECT_TIME:
+    case CURLINFO_APPCONNECT_TIME:
+    case CURLINFO_PRETRANSFER_TIME:
+    case CURLINFO_STARTTRANSFER_TIME:
+    case CURLINFO_REDIRECT_TIME:
+    case CURLINFO_SPEED_DOWNLOAD:
+    case CURLINFO_SPEED_UPLOAD:
+      *param_doublep = (double)val;
+      return CURLE_OK;
+    default:
+      break;
+    }
+  }
+#endif
   switch(info) {
   switch(info) {
   case CURLINFO_TOTAL_TIME:
   case CURLINFO_TOTAL_TIME:
     *param_doublep = DOUBLE_SECS(data->progress.timespent);
     *param_doublep = DOUBLE_SECS(data->progress.timespent);
@@ -336,13 +410,13 @@ static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
     *param_doublep = DOUBLE_SECS(data->progress.t_starttransfer);
     *param_doublep = DOUBLE_SECS(data->progress.t_starttransfer);
     break;
     break;
   case CURLINFO_SIZE_UPLOAD:
   case CURLINFO_SIZE_UPLOAD:
-    *param_doublep =  (double)data->progress.uploaded;
+    *param_doublep = (double)data->progress.uploaded;
     break;
     break;
   case CURLINFO_SIZE_DOWNLOAD:
   case CURLINFO_SIZE_DOWNLOAD:
     *param_doublep = (double)data->progress.downloaded;
     *param_doublep = (double)data->progress.downloaded;
     break;
     break;
   case CURLINFO_SPEED_DOWNLOAD:
   case CURLINFO_SPEED_DOWNLOAD:
-    *param_doublep =  (double)data->progress.dlspeed;
+    *param_doublep = (double)data->progress.dlspeed;
     break;
     break;
   case CURLINFO_SPEED_UPLOAD:
   case CURLINFO_SPEED_UPLOAD:
     *param_doublep = (double)data->progress.ulspeed;
     *param_doublep = (double)data->progress.ulspeed;

+ 18 - 5
Utilities/cmcurl/lib/gopher.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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 <curl/curl.h>
 #include <curl/curl.h>
 #include "transfer.h"
 #include "transfer.h"
 #include "sendf.h"
 #include "sendf.h"
+#include "connect.h"
 #include "progress.h"
 #include "progress.h"
 #include "gopher.h"
 #include "gopher.h"
 #include "select.h"
 #include "select.h"
@@ -83,8 +84,10 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
   char *query = data->state.up.query;
   char *query = data->state.up.query;
   char *sel = NULL;
   char *sel = NULL;
   char *sel_org = NULL;
   char *sel_org = NULL;
+  timediff_t timeout_ms;
   ssize_t amount, k;
   ssize_t amount, k;
   size_t len;
   size_t len;
+  int what;
 
 
   *done = TRUE; /* unconditionally */
   *done = TRUE; /* unconditionally */
 
 
@@ -139,19 +142,29 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
     else
     else
       break;
       break;
 
 
+    timeout_ms = Curl_timeleft(conn->data, NULL, FALSE);
+    if(timeout_ms < 0) {
+      result = CURLE_OPERATION_TIMEDOUT;
+      break;
+    }
+    if(!timeout_ms)
+      timeout_ms = TIMEDIFF_T_MAX;
+
     /* Don't busyloop. The entire loop thing is a work-around as it causes a
     /* Don't busyloop. The entire loop thing is a work-around as it causes a
        BLOCKING behavior which is a NO-NO. This function should rather be
        BLOCKING behavior which is a NO-NO. This function should rather be
        split up in a do and a doing piece where the pieces that aren't
        split up in a do and a doing piece where the pieces that aren't
        possible to send now will be sent in the doing function repeatedly
        possible to send now will be sent in the doing function repeatedly
        until the entire request is sent.
        until the entire request is sent.
-
-       Wait a while for the socket to be writable. Note that this doesn't
-       acknowledge the timeout.
     */
     */
-    if(SOCKET_WRITABLE(sockfd, 100) < 0) {
+    what = SOCKET_WRITABLE(sockfd, timeout_ms);
+    if(what < 0) {
       result = CURLE_SEND_ERROR;
       result = CURLE_SEND_ERROR;
       break;
       break;
     }
     }
+    else if(!what) {
+      result = CURLE_OPERATION_TIMEDOUT;
+      break;
+    }
   }
   }
 
 
   free(sel_org);
   free(sel_org);

+ 9 - 8
Utilities/cmcurl/lib/hmac.c

@@ -48,13 +48,13 @@ static const unsigned char hmac_opad = 0x5C;
 
 
 
 
 
 
-HMAC_context *
-Curl_HMAC_init(const HMAC_params * hashparams,
+struct HMAC_context *
+Curl_HMAC_init(const struct HMAC_params *hashparams,
                const unsigned char *key,
                const unsigned char *key,
                unsigned int keylen)
                unsigned int keylen)
 {
 {
   size_t i;
   size_t i;
-  HMAC_context *ctxt;
+  struct HMAC_context *ctxt;
   unsigned char *hkey;
   unsigned char *hkey;
   unsigned char b;
   unsigned char b;
 
 
@@ -101,7 +101,7 @@ Curl_HMAC_init(const HMAC_params * hashparams,
   return ctxt;
   return ctxt;
 }
 }
 
 
-int Curl_HMAC_update(HMAC_context * ctxt,
+int Curl_HMAC_update(struct HMAC_context *ctxt,
                      const unsigned char *data,
                      const unsigned char *data,
                      unsigned int len)
                      unsigned int len)
 {
 {
@@ -111,9 +111,9 @@ int Curl_HMAC_update(HMAC_context * ctxt,
 }
 }
 
 
 
 
-int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result)
+int Curl_HMAC_final(struct HMAC_context *ctxt, unsigned char *result)
 {
 {
-  const HMAC_params * hashparams = ctxt->hmac_hash;
+  const struct HMAC_params *hashparams = ctxt->hmac_hash;
 
 
   /* Do not get result if called with a null parameter: only release
   /* Do not get result if called with a null parameter: only release
      storage. */
      storage. */
@@ -147,12 +147,13 @@ int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result)
  *
  *
  * Returns CURLE_OK on success.
  * Returns CURLE_OK on success.
  */
  */
-CURLcode Curl_hmacit(const HMAC_params *hashparams,
+CURLcode Curl_hmacit(const struct HMAC_params *hashparams,
                      const unsigned char *key, const size_t keylen,
                      const unsigned char *key, const size_t keylen,
                      const unsigned char *data, const size_t datalen,
                      const unsigned char *data, const size_t datalen,
                      unsigned char *output)
                      unsigned char *output)
 {
 {
-  HMAC_context *ctxt = Curl_HMAC_init(hashparams, key, curlx_uztoui(keylen));
+  struct HMAC_context *ctxt =
+    Curl_HMAC_init(hashparams, key, curlx_uztoui(keylen));
 
 
   if(!ctxt)
   if(!ctxt)
     return CURLE_OUT_OF_MEMORY;
     return CURLE_OUT_OF_MEMORY;

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

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -117,10 +117,10 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
  * name resolve layers (selected at build-time). They all take this same set
  * name resolve layers (selected at build-time). They all take this same set
  * of arguments
  * of arguments
  */
  */
-Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
-                                const char *hostname,
-                                int port,
-                                int *waitp)
+struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+                                       const char *hostname,
+                                       int port,
+                                       int *waitp)
 {
 {
   return Curl_resolver_getaddrinfo(conn, hostname, port, waitp);
   return Curl_resolver_getaddrinfo(conn, hostname, port, waitp);
 }
 }

+ 59 - 41
Utilities/cmcurl/lib/hostip.c

@@ -120,7 +120,7 @@ static void freednsentry(void *freethis);
 /*
 /*
  * Return # of addresses in a Curl_addrinfo struct
  * Return # of addresses in a Curl_addrinfo struct
  */
  */
-int Curl_num_addresses(const Curl_addrinfo *addr)
+int Curl_num_addresses(const struct Curl_addrinfo *addr)
 {
 {
   int i = 0;
   int i = 0;
   while(addr) {
   while(addr) {
@@ -131,39 +131,36 @@ int Curl_num_addresses(const Curl_addrinfo *addr)
 }
 }
 
 
 /*
 /*
- * Curl_printable_address() returns a printable version of the 1st address
+ * Curl_printable_address() stores a printable version of the 1st address
  * given in the 'ai' argument. The result will be stored in the buf that is
  * given in the 'ai' argument. The result will be stored in the buf that is
  * bufsize bytes big.
  * bufsize bytes big.
  *
  *
- * If the conversion fails, it returns NULL.
+ * If the conversion fails, the target buffer is empty.
  */
  */
-const char *
-Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
+void Curl_printable_address(const struct Curl_addrinfo *ai, char *buf,
+                            size_t bufsize)
 {
 {
-  const struct sockaddr_in *sa4;
-  const struct in_addr *ipaddr4;
-#ifdef ENABLE_IPV6
-  const struct sockaddr_in6 *sa6;
-  const struct in6_addr *ipaddr6;
-#endif
+  DEBUGASSERT(bufsize);
+  buf[0] = 0;
 
 
   switch(ai->ai_family) {
   switch(ai->ai_family) {
-    case AF_INET:
-      sa4 = (const void *)ai->ai_addr;
-      ipaddr4 = &sa4->sin_addr;
-      return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf,
-                            bufsize);
+  case AF_INET: {
+    const struct sockaddr_in *sa4 = (const void *)ai->ai_addr;
+    const struct in_addr *ipaddr4 = &sa4->sin_addr;
+    (void)Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, bufsize);
+    break;
+  }
 #ifdef ENABLE_IPV6
 #ifdef ENABLE_IPV6
-    case AF_INET6:
-      sa6 = (const void *)ai->ai_addr;
-      ipaddr6 = &sa6->sin6_addr;
-      return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf,
-                            bufsize);
+  case AF_INET6: {
+    const struct sockaddr_in6 *sa6 = (const void *)ai->ai_addr;
+    const struct in6_addr *ipaddr6 = &sa6->sin6_addr;
+    (void)Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf, bufsize);
+    break;
+  }
 #endif
 #endif
-    default:
-      break;
+  default:
+    break;
   }
   }
-  return NULL;
 }
 }
 
 
 /*
 /*
@@ -337,7 +334,7 @@ Curl_fetch_addr(struct connectdata *conn,
 
 
 #ifndef CURL_DISABLE_SHUFFLE_DNS
 #ifndef CURL_DISABLE_SHUFFLE_DNS
 UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
 UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
-                                    Curl_addrinfo **addr);
+                                    struct 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.
@@ -351,13 +348,13 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
  * @unittest: 1608
  * @unittest: 1608
  */
  */
 UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
 UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
-                                    Curl_addrinfo **addr)
+                                    struct 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);
 
 
   if(num_addrs > 1) {
   if(num_addrs > 1) {
-    Curl_addrinfo **nodes;
+    struct Curl_addrinfo **nodes;
     infof(data, "Shuffling %i addresses", num_addrs);
     infof(data, "Shuffling %i addresses", num_addrs);
 
 
     nodes = malloc(num_addrs*sizeof(*nodes));
     nodes = malloc(num_addrs*sizeof(*nodes));
@@ -376,7 +373,7 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
       if(rnd) {
       if(rnd) {
         /* Fisher-Yates shuffle */
         /* Fisher-Yates shuffle */
         if(Curl_rand(data, (unsigned char *)rnd, rnd_size) == CURLE_OK) {
         if(Curl_rand(data, (unsigned char *)rnd, rnd_size) == CURLE_OK) {
-          Curl_addrinfo *swap_tmp;
+          struct Curl_addrinfo *swap_tmp;
           for(i = num_addrs - 1; i > 0; i--) {
           for(i = num_addrs - 1; i > 0; i--) {
             swap_tmp = nodes[rnd[i] % (i + 1)];
             swap_tmp = nodes[rnd[i] % (i + 1)];
             nodes[rnd[i] % (i + 1)] = nodes[i];
             nodes[rnd[i] % (i + 1)] = nodes[i];
@@ -415,7 +412,7 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
  */
  */
 struct Curl_dns_entry *
 struct Curl_dns_entry *
 Curl_cache_addr(struct Curl_easy *data,
 Curl_cache_addr(struct Curl_easy *data,
-                Curl_addrinfo *addr,
+                struct Curl_addrinfo *addr,
                 const char *hostname,
                 const char *hostname,
                 int port)
                 int port)
 {
 {
@@ -495,6 +492,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
   enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
   enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
 
 
   *entry = NULL;
   *entry = NULL;
+  conn->bits.doh = FALSE; /* default is not */
 
 
   if(data->share)
   if(data->share)
     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
     Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
@@ -513,11 +511,13 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
   if(!dns) {
   if(!dns) {
     /* 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 = NULL;
+    struct Curl_addrinfo *addr = NULL;
     int respwait = 0;
     int respwait = 0;
-#ifndef USE_RESOLVE_ON_IPS
     struct in_addr in;
     struct in_addr in;
+#ifndef USE_RESOLVE_ON_IPS
+    const
 #endif
 #endif
+      bool ipnum = FALSE;
 
 
     /* notify the resolver start callback */
     /* notify the resolver start callback */
     if(data->set.resolver_start) {
     if(data->set.resolver_start) {
@@ -544,6 +544,22 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
         addr = Curl_ip2addr(AF_INET6, &in6, hostname, port);
         addr = Curl_ip2addr(AF_INET6, &in6, hostname, port);
     }
     }
 #endif /* ENABLE_IPV6 */
 #endif /* ENABLE_IPV6 */
+
+#else /* if USE_RESOLVE_ON_IPS */
+    /* First check if this is an IPv4 address string */
+    if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
+      /* This is a dotted IP address 123.123.123.123-style */
+      ipnum = TRUE;
+#ifdef ENABLE_IPV6
+    else {
+      struct in6_addr in6;
+      /* check if this is an IPv6 address string */
+      if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0)
+        /* This is an IPv6 address literal */
+        ipnum = TRUE;
+    }
+#endif /* ENABLE_IPV6 */
+
 #endif /* !USE_RESOLVE_ON_IPS */
 #endif /* !USE_RESOLVE_ON_IPS */
 
 
     if(!addr) {
     if(!addr) {
@@ -552,7 +568,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
       if(!Curl_ipvalid(conn))
       if(!Curl_ipvalid(conn))
         return CURLRESOLV_ERROR;
         return CURLRESOLV_ERROR;
 
 
-      if(allowDOH && data->set.doh) {
+      if(allowDOH && data->set.doh && !ipnum) {
         addr = Curl_doh(conn, hostname, port, &respwait);
         addr = Curl_doh(conn, hostname, port, &respwait);
       }
       }
       else {
       else {
@@ -890,7 +906,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
     }
     }
     else {
     else {
       struct Curl_dns_entry *dns;
       struct Curl_dns_entry *dns;
-      Curl_addrinfo *head = NULL, *tail = NULL;
+      struct Curl_addrinfo *head = NULL, *tail = NULL;
       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)
@@ -924,7 +940,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
 
 
       while(*end_ptr) {
       while(*end_ptr) {
         size_t alen;
         size_t alen;
-        Curl_addrinfo *ai;
+        struct Curl_addrinfo *ai;
 
 
         addr_begin = end_ptr + 1;
         addr_begin = end_ptr + 1;
         addr_end = strchr(addr_begin, ',');
         addr_end = strchr(addr_begin, ',');
@@ -1047,7 +1063,7 @@ CURLcode Curl_resolv_check(struct connectdata *conn,
   (void)dns;
   (void)dns;
 #endif
 #endif
 
 
-  if(conn->data->set.doh)
+  if(conn->bits.doh)
     return Curl_doh_is_resolved(conn, dns);
     return Curl_doh_is_resolved(conn, dns);
   return Curl_resolver_is_resolved(conn, dns);
   return Curl_resolver_is_resolved(conn, dns);
 }
 }
@@ -1056,7 +1072,7 @@ int Curl_resolv_getsock(struct connectdata *conn,
                         curl_socket_t *socks)
                         curl_socket_t *socks)
 {
 {
 #ifdef CURLRES_ASYNCH
 #ifdef CURLRES_ASYNCH
-  if(conn->data->set.doh)
+  if(conn->bits.doh)
     /* nothing to wait for during DOH resolve, those handles have their own
     /* nothing to wait for during DOH resolve, those handles have their own
        sockets */
        sockets */
     return GETSOCK_BLANK;
     return GETSOCK_BLANK;
@@ -1085,10 +1101,12 @@ CURLcode Curl_once_resolved(struct connectdata *conn,
 
 
   result = Curl_setup_conn(conn, protocol_done);
   result = Curl_setup_conn(conn, protocol_done);
 
 
-  if(result)
-    /* We're not allowed to return failure with memory left allocated
-       in the connectdata struct, free those here */
-    Curl_disconnect(conn->data, conn, TRUE); /* close the connection */
-
+  if(result) {
+    struct Curl_easy *data = conn->data;
+    DEBUGASSERT(data);
+    Curl_detach_connnection(data);
+    Curl_conncache_remove_conn(data, conn, TRUE);
+    Curl_disconnect(data, conn, TRUE);
+  }
   return result;
   return result;
 }
 }

+ 11 - 11
Utilities/cmcurl/lib/hostip.h

@@ -64,7 +64,7 @@ struct connectdata;
 struct curl_hash *Curl_global_host_cache_init(void);
 struct curl_hash *Curl_global_host_cache_init(void);
 
 
 struct Curl_dns_entry {
 struct Curl_dns_entry {
-  Curl_addrinfo *addr;
+  struct Curl_addrinfo *addr;
   /* timestamp == 0 -- CURLOPT_RESOLVE entry, doesn't timeout */
   /* timestamp == 0 -- CURLOPT_RESOLVE entry, doesn't timeout */
   time_t timestamp;
   time_t timestamp;
   /* use-counter, use Curl_resolv_unlock to release reference */
   /* use-counter, use Curl_resolv_unlock to release reference */
@@ -117,10 +117,10 @@ bool Curl_ipvalid(struct connectdata *conn);
  * name resolve layers (selected at build-time). They all take this same set
  * name resolve layers (selected at build-time). They all take this same set
  * of arguments
  * of arguments
  */
  */
-Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
-                                const char *hostname,
-                                int port,
-                                int *waitp);
+struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+                                       const char *hostname,
+                                       int port,
+                                       int *waitp);
 
 
 
 
 /* unlock a previously resolved dns entry */
 /* unlock a previously resolved dns entry */
@@ -134,7 +134,7 @@ int Curl_mk_dnscache(struct curl_hash *hash);
 void Curl_hostcache_prune(struct Curl_easy *data);
 void Curl_hostcache_prune(struct Curl_easy *data);
 
 
 /* Return # of addresses in a Curl_addrinfo struct */
 /* Return # of addresses in a Curl_addrinfo struct */
-int Curl_num_addresses(const Curl_addrinfo *addr);
+int Curl_num_addresses(const struct Curl_addrinfo *addr);
 
 
 #if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
 #if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
 int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
 int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
@@ -146,7 +146,7 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
 #endif
 #endif
 
 
 /* IPv4 threadsafe resolve function used for synch and asynch builds */
 /* IPv4 threadsafe resolve function used for synch and asynch builds */
-Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
+struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
 
 
 CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect);
 CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect);
 
 
@@ -158,15 +158,15 @@ CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect);
  */
  */
 CURLcode Curl_addrinfo_callback(struct connectdata *conn,
 CURLcode Curl_addrinfo_callback(struct connectdata *conn,
                                 int status,
                                 int status,
-                                Curl_addrinfo *ai);
+                                struct Curl_addrinfo *ai);
 
 
 /*
 /*
  * Curl_printable_address() returns a printable version of the 1st address
  * Curl_printable_address() returns a printable version of the 1st address
  * given in the 'ip' argument. The result will be stored in the buf that is
  * given in the 'ip' argument. The result will be stored in the buf that is
  * bufsize bytes big.
  * bufsize bytes big.
  */
  */
-const char *Curl_printable_address(const Curl_addrinfo *ip,
-                                   char *buf, size_t bufsize);
+void Curl_printable_address(const struct Curl_addrinfo *ip,
+                            char *buf, size_t bufsize);
 
 
 /*
 /*
  * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
  * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
@@ -187,7 +187,7 @@ Curl_fetch_addr(struct connectdata *conn,
  * Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
  * Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
  */
  */
 struct Curl_dns_entry *
 struct Curl_dns_entry *
-Curl_cache_addr(struct Curl_easy *data, Curl_addrinfo *addr,
+Curl_cache_addr(struct Curl_easy *data, struct Curl_addrinfo *addr,
                 const char *hostname, int port);
                 const char *hostname, int port);
 
 
 #ifndef INADDR_NONE
 #ifndef INADDR_NONE

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

@@ -88,12 +88,12 @@ bool Curl_ipvalid(struct connectdata *conn)
  * flavours have thread-safe versions of the plain gethostbyname() etc.
  * flavours have thread-safe versions of the plain gethostbyname() etc.
  *
  *
  */
  */
-Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
-                                const char *hostname,
-                                int port,
-                                int *waitp)
+struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+                                       const char *hostname,
+                                       int port,
+                                       int *waitp)
 {
 {
-  Curl_addrinfo *ai = NULL;
+  struct Curl_addrinfo *ai = NULL;
 
 
 #ifdef CURL_DISABLE_VERBOSE_STRINGS
 #ifdef CURL_DISABLE_VERBOSE_STRINGS
   (void)conn;
   (void)conn;
@@ -119,13 +119,13 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
  * implying that only threadsafe code and function calls may be used.
  * implying that only threadsafe code and function calls may be used.
  *
  *
  */
  */
-Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
-                                   int port)
+struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
+                                          int port)
 {
 {
 #if !defined(HAVE_GETADDRINFO_THREADSAFE) && defined(HAVE_GETHOSTBYNAME_R_3)
 #if !defined(HAVE_GETADDRINFO_THREADSAFE) && defined(HAVE_GETHOSTBYNAME_R_3)
   int res;
   int res;
 #endif
 #endif
-  Curl_addrinfo *ai = NULL;
+  struct Curl_addrinfo *ai = NULL;
   struct hostent *h = NULL;
   struct hostent *h = NULL;
   struct hostent *buf = NULL;
   struct hostent *buf = NULL;
 
 

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

@@ -103,20 +103,16 @@ bool Curl_ipvalid(struct connectdata *conn)
 #if defined(CURLRES_SYNCH)
 #if defined(CURLRES_SYNCH)
 
 
 #ifdef DEBUG_ADDRINFO
 #ifdef DEBUG_ADDRINFO
-static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
+static void dump_addrinfo(struct connectdata *conn,
+                          const struct 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)))
-      printf("%s\n", buf);
-    else {
-      char buffer[STRERROR_LEN];
-      printf("failed; %s\n",
-             Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
-    }
+    Curl_printable_address(ai, buf, sizeof(buf));
+    printf("%s\n", buf);
   }
   }
 }
 }
 #else
 #else
@@ -132,13 +128,13 @@ static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
  * memory we need to free after use. That memory *MUST* be freed with
  * memory we need to free after use. That memory *MUST* be freed with
  * Curl_freeaddrinfo(), nothing else.
  * Curl_freeaddrinfo(), nothing else.
  */
  */
-Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
-                                const char *hostname,
-                                int port,
-                                int *waitp)
+struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+                                       const char *hostname,
+                                       int port,
+                                       int *waitp)
 {
 {
   struct addrinfo hints;
   struct addrinfo hints;
-  Curl_addrinfo *res;
+  struct Curl_addrinfo *res;
   int error;
   int error;
   char sbuf[12];
   char sbuf[12];
   char *sbufptr = NULL;
   char *sbufptr = NULL;

Разница между файлами не показана из-за своего большого размера
+ 201 - 277
Utilities/cmcurl/lib/http.c


+ 13 - 35
Utilities/cmcurl/lib/http.h

@@ -44,38 +44,19 @@ char *Curl_copy_header_value(const char *header);
 
 
 char *Curl_checkProxyheaders(const struct connectdata *conn,
 char *Curl_checkProxyheaders(const struct connectdata *conn,
                              const char *thisheader);
                              const char *thisheader);
-/* ------------------------------------------------------------------------- */
-/*
- * The add_buffer series of functions are used to build one large memory chunk
- * from repeated function invokes. Used so that the entire HTTP request can
- * be sent in one go.
- */
-struct Curl_send_buffer {
-  char *buffer;
-  size_t size_max;
-  size_t size_used;
-};
-typedef struct Curl_send_buffer Curl_send_buffer;
-
-Curl_send_buffer *Curl_add_buffer_init(void);
-void Curl_add_buffer_free(Curl_send_buffer **inp);
-CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...)
-  WARN_UNUSED_RESULT;
-CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr,
-                         size_t size) WARN_UNUSED_RESULT;
-CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
-                              struct connectdata *conn,
-                              curl_off_t *bytes_written,
-                              size_t included_body_bytes,
-                              int socketindex);
+CURLcode Curl_buffer_send(struct dynbuf *in,
+                          struct connectdata *conn,
+                          curl_off_t *bytes_written,
+                          size_t included_body_bytes,
+                          int socketindex);
 
 
 CURLcode Curl_add_timecondition(const struct connectdata *conn,
 CURLcode Curl_add_timecondition(const struct connectdata *conn,
-                                Curl_send_buffer *buf);
+                                struct dynbuf *buf);
 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);
+                                 struct dynbuf *req_buffer);
 CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
 CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
-                                    Curl_send_buffer **buffer,
+                                    struct dynbuf *buf,
                                     struct Curl_easy *handle);
                                     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 */
@@ -154,9 +135,9 @@ struct HTTP {
   } sending;
   } sending;
 
 
 #ifndef CURL_DISABLE_HTTP
 #ifndef CURL_DISABLE_HTTP
-  Curl_send_buffer *send_buffer; /* used if the request couldn't be sent in
-                                    one chunk, points to an allocated
-                                    send_buffer struct */
+  struct dynbuf send_buffer; /* used if the request couldn't be sent in one
+                                chunk, points to an allocated send_buffer
+                                struct */
 #endif
 #endif
 #ifdef USE_NGHTTP2
 #ifdef USE_NGHTTP2
   /*********** for HTTP/2 we store stream-local data here *************/
   /*********** for HTTP/2 we store stream-local data here *************/
@@ -164,10 +145,9 @@ struct HTTP {
 
 
   bool bodystarted;
   bool bodystarted;
   /* We store non-final and final response headers here, per-stream */
   /* We store non-final and final response headers here, per-stream */
-  Curl_send_buffer *header_recvbuf;
+  struct dynbuf header_recvbuf;
   size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into
   size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into
                                   upper layer */
                                   upper layer */
-  Curl_send_buffer *trailer_recvbuf;
   int status_code; /* HTTP status code */
   int status_code; /* HTTP status code */
   const uint8_t *pausedata; /* pointer to data received in on_data_chunk */
   const uint8_t *pausedata; /* pointer to data received in on_data_chunk */
   size_t pauselen; /* the number of bytes left in data */
   size_t pauselen; /* the number of bytes left in data */
@@ -201,9 +181,7 @@ struct HTTP {
 #ifdef USE_NGHTTP3
 #ifdef USE_NGHTTP3
   size_t unacked_window;
   size_t unacked_window;
   struct h3out *h3out; /* per-stream buffers for upload */
   struct h3out *h3out; /* per-stream buffers for upload */
-  char *overflow_buf; /* excess data received during a single Curl_read */
-  size_t overflow_buflen; /* amount of data currently in overflow_buf */
-  size_t overflow_bufsize; /* size of the overflow_buf allocation */
+  struct dynbuf overflow; /* excess data received during a single Curl_read */
 #endif
 #endif
 };
 };
 
 

+ 78 - 105
Utilities/cmcurl/lib/http2.c

@@ -36,6 +36,7 @@
 #include "connect.h"
 #include "connect.h"
 #include "strtoofft.h"
 #include "strtoofft.h"
 #include "strdup.h"
 #include "strdup.h"
+#include "dynbuf.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"
@@ -124,8 +125,7 @@ static int http2_getsock(struct connectdata *conn,
 static void http2_stream_free(struct HTTP *http)
 static void http2_stream_free(struct HTTP *http)
 {
 {
   if(http) {
   if(http) {
-    Curl_add_buffer_free(&http->header_recvbuf);
-    Curl_add_buffer_free(&http->trailer_recvbuf);
+    Curl_dyn_free(&http->header_recvbuf);
     for(; http->push_headers_used > 0; --http->push_headers_used) {
     for(; http->push_headers_used > 0; --http->push_headers_used) {
       free(http->push_headers[http->push_headers_used - 1]);
       free(http->push_headers[http->push_headers_used - 1]);
     }
     }
@@ -258,16 +258,14 @@ static unsigned int http2_conncheck(struct connectdata *check,
 void Curl_http2_setup_req(struct Curl_easy *data)
 void Curl_http2_setup_req(struct Curl_easy *data)
 {
 {
   struct HTTP *http = data->req.protop;
   struct HTTP *http = data->req.protop;
-
-  http->nread_header_recvbuf = 0;
   http->bodystarted = FALSE;
   http->bodystarted = FALSE;
   http->status_code = -1;
   http->status_code = -1;
   http->pausedata = NULL;
   http->pausedata = NULL;
   http->pauselen = 0;
   http->pauselen = 0;
   http->closed = FALSE;
   http->closed = FALSE;
   http->close_handled = FALSE;
   http->close_handled = FALSE;
-  http->mem = data->state.buffer;
-  http->len = data->set.buffer_size;
+  http->mem = NULL;
+  http->len = 0;
   http->memlen = 0;
   http->memlen = 0;
 }
 }
 
 
@@ -333,7 +331,7 @@ 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 msnprintf(p, len, " nghttp2/%s", h2->version_str);
+  return msnprintf(p, len, "nghttp2/%s", h2->version_str);
 }
 }
 
 
 /*
 /*
@@ -463,15 +461,9 @@ static struct Curl_easy *duphandle(struct Curl_easy *data)
     }
     }
     else {
     else {
       second->req.protop = http;
       second->req.protop = http;
-      http->header_recvbuf = Curl_add_buffer_init();
-      if(!http->header_recvbuf) {
-        free(http);
-        (void)Curl_close(&second);
-      }
-      else {
-        Curl_http2_setup_req(second);
-        second->state.stream_weight = data->state.stream_weight;
-      }
+      Curl_dyn_init(&http->header_recvbuf, DYN_H2_HEADERS);
+      Curl_http2_setup_req(second);
+      second->state.stream_weight = data->state.stream_weight;
     }
     }
   }
   }
   return second;
   return second;
@@ -668,15 +660,17 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
       stream->status_code = -1;
       stream->status_code = -1;
     }
     }
 
 
-    result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
+    result = Curl_dyn_add(&stream->header_recvbuf, "\r\n");
     if(result)
     if(result)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
       return NGHTTP2_ERR_CALLBACK_FAILURE;
 
 
-    left = stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
+    left = Curl_dyn_len(&stream->header_recvbuf) -
+      stream->nread_header_recvbuf;
     ncopy = CURLMIN(stream->len, left);
     ncopy = CURLMIN(stream->len, left);
 
 
     memcpy(&stream->mem[stream->memlen],
     memcpy(&stream->mem[stream->memlen],
-           stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
+           Curl_dyn_ptr(&stream->header_recvbuf) +
+           stream->nread_header_recvbuf,
            ncopy);
            ncopy);
     stream->nread_header_recvbuf += ncopy;
     stream->nread_header_recvbuf += ncopy;
 
 
@@ -852,12 +846,6 @@ static int on_begin_headers(nghttp2_session *session,
     return 0;
     return 0;
   }
   }
 
 
-  if(!stream->trailer_recvbuf) {
-    stream->trailer_recvbuf = Curl_add_buffer_init();
-    if(!stream->trailer_recvbuf) {
-      return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
-    }
-  }
   return 0;
   return 0;
 }
 }
 
 
@@ -973,26 +961,19 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
   }
   }
 
 
   if(stream->bodystarted) {
   if(stream->bodystarted) {
-    /* This is trailer fields. */
-    /* 4 is for ": " and "\r\n". */
-    uint32_t n = (uint32_t)(namelen + valuelen + 4);
-
+    /* This is a trailer */
+    struct dynbuf trail;
     H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
     H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
                  value));
                  value));
-
-    result = Curl_add_buffer(&stream->trailer_recvbuf, &n, sizeof(n));
-    if(result)
-      return NGHTTP2_ERR_CALLBACK_FAILURE;
-    result = Curl_add_buffer(&stream->trailer_recvbuf, name, namelen);
-    if(result)
-      return NGHTTP2_ERR_CALLBACK_FAILURE;
-    result = Curl_add_buffer(&stream->trailer_recvbuf, ": ", 2);
-    if(result)
-      return NGHTTP2_ERR_CALLBACK_FAILURE;
-    result = Curl_add_buffer(&stream->trailer_recvbuf, value, valuelen);
-    if(result)
-      return NGHTTP2_ERR_CALLBACK_FAILURE;
-    result = Curl_add_buffer(&stream->trailer_recvbuf, "\r\n\0", 3);
+    Curl_dyn_init(&trail, DYN_H2_TRAILER);
+    result = Curl_dyn_addf(&trail,
+                           "%.*s: %.*s\r\n", namelen, name,
+                           valuelen, value);
+    if(!result)
+      result = Curl_client_write(conn, CLIENTWRITE_HEADER,
+                                 Curl_dyn_ptr(&trail),
+                                 Curl_dyn_len(&trail));
+    Curl_dyn_free(&trail);
     if(result)
     if(result)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
       return NGHTTP2_ERR_CALLBACK_FAILURE;
 
 
@@ -1007,14 +988,14 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
     stream->status_code = decode_status_code(value, valuelen);
     stream->status_code = decode_status_code(value, valuelen);
     DEBUGASSERT(stream->status_code != -1);
     DEBUGASSERT(stream->status_code != -1);
 
 
-    result = Curl_add_buffer(&stream->header_recvbuf, "HTTP/2 ", 7);
+    result = Curl_dyn_add(&stream->header_recvbuf, "HTTP/2 ");
     if(result)
     if(result)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
       return NGHTTP2_ERR_CALLBACK_FAILURE;
-    result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
+    result = Curl_dyn_addn(&stream->header_recvbuf, value, valuelen);
     if(result)
     if(result)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
       return NGHTTP2_ERR_CALLBACK_FAILURE;
     /* the space character after the status code is mandatory */
     /* the space character after the status code is mandatory */
-    result = Curl_add_buffer(&stream->header_recvbuf, " \r\n", 3);
+    result = Curl_dyn_add(&stream->header_recvbuf, " \r\n");
     if(result)
     if(result)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
       return NGHTTP2_ERR_CALLBACK_FAILURE;
     /* if we receive data for another handle, wake that up */
     /* if we receive data for another handle, wake that up */
@@ -1029,16 +1010,16 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
   /* nghttp2 guarantees that namelen > 0, and :status was already
   /* nghttp2 guarantees that namelen > 0, and :status was already
      received, and this is not pseudo-header field . */
      received, and this is not pseudo-header field . */
   /* convert to a HTTP1-style header */
   /* convert to a HTTP1-style header */
-  result = Curl_add_buffer(&stream->header_recvbuf, name, namelen);
+  result = Curl_dyn_addn(&stream->header_recvbuf, name, namelen);
   if(result)
   if(result)
     return NGHTTP2_ERR_CALLBACK_FAILURE;
     return NGHTTP2_ERR_CALLBACK_FAILURE;
-  result = Curl_add_buffer(&stream->header_recvbuf, ": ", 2);
+  result = Curl_dyn_add(&stream->header_recvbuf, ": ");
   if(result)
   if(result)
     return NGHTTP2_ERR_CALLBACK_FAILURE;
     return NGHTTP2_ERR_CALLBACK_FAILURE;
-  result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
+  result = Curl_dyn_addn(&stream->header_recvbuf, value, valuelen);
   if(result)
   if(result)
     return NGHTTP2_ERR_CALLBACK_FAILURE;
     return NGHTTP2_ERR_CALLBACK_FAILURE;
-  result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
+  result = Curl_dyn_add(&stream->header_recvbuf, "\r\n");
   if(result)
   if(result)
     return NGHTTP2_ERR_CALLBACK_FAILURE;
     return NGHTTP2_ERR_CALLBACK_FAILURE;
   /* if we receive data for another handle, wake that up */
   /* if we receive data for another handle, wake that up */
@@ -1139,17 +1120,14 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
 
 
   /* there might be allocated resources done before this got the 'h2' pointer
   /* there might be allocated resources done before this got the 'h2' pointer
      setup */
      setup */
-  if(http->header_recvbuf) {
-    Curl_add_buffer_free(&http->header_recvbuf);
-    Curl_add_buffer_free(&http->trailer_recvbuf);
-    if(http->push_headers) {
-      /* if they weren't used and then freed before */
-      for(; http->push_headers_used > 0; --http->push_headers_used) {
-        free(http->push_headers[http->push_headers_used - 1]);
-      }
-      free(http->push_headers);
-      http->push_headers = NULL;
+  Curl_dyn_free(&http->header_recvbuf);
+  if(http->push_headers) {
+    /* if they weren't used and then freed before */
+    for(; http->push_headers_used > 0; --http->push_headers_used) {
+      free(http->push_headers[http->push_headers_used - 1]);
     }
     }
+    free(http->push_headers);
+    http->push_headers = NULL;
   }
   }
 
 
   if(!httpc->h2) /* not HTTP/2 ? */
   if(!httpc->h2) /* not HTTP/2 ? */
@@ -1238,7 +1216,7 @@ static CURLcode http2_init(struct connectdata *conn)
 /*
 /*
  * Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
  * Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
  */
  */
-CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
+CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
                                     struct connectdata *conn)
                                     struct connectdata *conn)
 {
 {
   CURLcode result;
   CURLcode result;
@@ -1257,7 +1235,7 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
                                          httpc->local_settings_num);
                                          httpc->local_settings_num);
   if(!binlen) {
   if(!binlen) {
     failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
     failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
-    Curl_add_buffer_free(&req);
+    Curl_dyn_free(req);
     return CURLE_FAILED_INIT;
     return CURLE_FAILED_INIT;
   }
   }
   conn->proto.httpc.binlen = binlen;
   conn->proto.httpc.binlen = binlen;
@@ -1265,15 +1243,15 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
   result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
   result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
                                  &base64, &blen);
                                  &base64, &blen);
   if(result) {
   if(result) {
-    Curl_add_buffer_free(&req);
+    Curl_dyn_free(req);
     return result;
     return result;
   }
   }
 
 
-  result = Curl_add_bufferf(&req,
-                            "Connection: Upgrade, HTTP2-Settings\r\n"
-                            "Upgrade: %s\r\n"
-                            "HTTP2-Settings: %s\r\n",
-                            NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
+  result = Curl_dyn_addf(req,
+                         "Connection: Upgrade, HTTP2-Settings\r\n"
+                         "Upgrade: %s\r\n"
+                         "HTTP2-Settings: %s\r\n",
+                         NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
   free(base64);
   free(base64);
 
 
   k->upgr101 = UPGR101_REQUESTED;
   k->upgr101 = UPGR101_REQUESTED;
@@ -1367,10 +1345,11 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
 
 
     struct HTTP *stream = conn->data->req.protop;
     struct HTTP *stream = conn->data->req.protop;
 
 
+    struct http_conn *httpc = &conn->proto.httpc;
+    nghttp2_session *h2 = httpc->h2;
+
     if(stream->upload_left) {
     if(stream->upload_left) {
       /* If the stream still thinks there's data left to upload. */
       /* If the stream still thinks there's data left to upload. */
-      struct http_conn *httpc = &conn->proto.httpc;
-      nghttp2_session *h2 = httpc->h2;
 
 
       stream->upload_left = 0; /* DONE! */
       stream->upload_left = 0; /* DONE! */
 
 
@@ -1380,6 +1359,23 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
 
 
       (void)h2_process_pending_input(conn, httpc, &result);
       (void)h2_process_pending_input(conn, httpc, &result);
     }
     }
+
+    /* If nghttp2 still has pending frames unsent */
+    if(nghttp2_session_want_write(h2)) {
+      struct Curl_easy *data = conn->data;
+      struct SingleRequest *k = &data->req;
+      int rv;
+
+      H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)\n", data));
+
+      /* re-set KEEP_SEND to make sure we are called again */
+      k->keepon |= KEEP_SEND;
+
+      /* and attempt to send the pending frames */
+      rv = h2_session_send(data, h2);
+      if(rv != 0)
+        result = CURLE_SEND_ERROR;
+    }
   }
   }
   return result;
   return result;
 }
 }
@@ -1388,8 +1384,6 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
                                          struct Curl_easy *data,
                                          struct Curl_easy *data,
                                          struct HTTP *stream, CURLcode *err)
                                          struct HTTP *stream, CURLcode *err)
 {
 {
-  char *trailer_pos, *trailer_end;
-  CURLcode result;
   struct http_conn *httpc = &conn->proto.httpc;
   struct http_conn *httpc = &conn->proto.httpc;
 
 
   if(httpc->pause_stream_id == stream->stream_id) {
   if(httpc->pause_stream_id == stream->stream_id) {
@@ -1432,25 +1426,6 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
     return -1;
     return -1;
   }
   }
 
 
-  if(stream->trailer_recvbuf && stream->trailer_recvbuf->buffer) {
-    trailer_pos = stream->trailer_recvbuf->buffer;
-    trailer_end = trailer_pos + stream->trailer_recvbuf->size_used;
-
-    for(; trailer_pos < trailer_end;) {
-      uint32_t n;
-      memcpy(&n, trailer_pos, sizeof(n));
-      trailer_pos += sizeof(n);
-
-      result = Curl_client_write(conn, CLIENTWRITE_HEADER, trailer_pos, n);
-      if(result) {
-        *err = result;
-        return -1;
-      }
-
-      trailer_pos += n + 1;
-    }
-  }
-
   stream->close_handled = TRUE;
   stream->close_handled = TRUE;
 
 
   H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
   H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
@@ -1541,13 +1516,13 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
    */
    */
 
 
   if(stream->bodystarted &&
   if(stream->bodystarted &&
-     stream->nread_header_recvbuf < stream->header_recvbuf->size_used) {
-    /* If there is body data pending for this stream to return, do that */
+     stream->nread_header_recvbuf < Curl_dyn_len(&stream->header_recvbuf)) {
+    /* If there is header data pending for this stream to return, do that */
     size_t left =
     size_t left =
-      stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
+      Curl_dyn_len(&stream->header_recvbuf) - stream->nread_header_recvbuf;
     size_t ncopy = CURLMIN(len, left);
     size_t ncopy = CURLMIN(len, left);
-    memcpy(mem, stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
-           ncopy);
+    memcpy(mem, Curl_dyn_ptr(&stream->header_recvbuf) +
+           stream->nread_header_recvbuf, ncopy);
     stream->nread_header_recvbuf += ncopy;
     stream->nread_header_recvbuf += ncopy;
 
 
     H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n",
     H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n",
@@ -1727,8 +1702,6 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
 
 
     return retlen;
     return retlen;
   }
   }
-  /* If this stream is closed, return 0 to signal the http routine to close
-     the connection */
   if(stream->closed)
   if(stream->closed)
     return 0;
     return 0;
   *err = CURLE_AGAIN;
   *err = CURLE_AGAIN;
@@ -2058,7 +2031,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
 
 
   h2_pri_spec(conn->data, &pri_spec);
   h2_pri_spec(conn->data, &pri_spec);
 
 
-  switch(conn->data->set.httpreq) {
+  switch(conn->data->state.httpreq) {
   case HTTPREQ_POST:
   case HTTPREQ_POST:
   case HTTPREQ_POST_FORM:
   case HTTPREQ_POST_FORM:
   case HTTPREQ_POST_MIME:
   case HTTPREQ_POST_MIME:
@@ -2129,13 +2102,11 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
   struct http_conn *httpc = &conn->proto.httpc;
   struct http_conn *httpc = &conn->proto.httpc;
   struct HTTP *stream = conn->data->req.protop;
   struct HTTP *stream = conn->data->req.protop;
 
 
+  DEBUGASSERT(conn->data->state.buffer);
+
   stream->stream_id = -1;
   stream->stream_id = -1;
 
 
-  if(!stream->header_recvbuf) {
-    stream->header_recvbuf = Curl_add_buffer_init();
-    if(!stream->header_recvbuf)
-      return CURLE_OUT_OF_MEMORY;
-  }
+  Curl_dyn_init(&stream->header_recvbuf, DYN_H2_HEADERS);
 
 
   if((conn->handler == &Curl_handler_http2_ssl) ||
   if((conn->handler == &Curl_handler_http2_ssl) ||
      (conn->handler == &Curl_handler_http2))
      (conn->handler == &Curl_handler_http2))
@@ -2148,7 +2119,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
 
 
   result = http2_init(conn);
   result = http2_init(conn);
   if(result) {
   if(result) {
-    Curl_add_buffer_free(&stream->header_recvbuf);
+    Curl_dyn_free(&stream->header_recvbuf);
     return result;
     return result;
   }
   }
 
 
@@ -2156,6 +2127,8 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
   stream->upload_left = 0;
   stream->upload_left = 0;
   stream->upload_mem = NULL;
   stream->upload_mem = NULL;
   stream->upload_len = 0;
   stream->upload_len = 0;
+  stream->mem = conn->data->state.buffer;
+  stream->len = conn->data->set.buffer_size;
 
 
   httpc->inbuflen = 0;
   httpc->inbuflen = 0;
   httpc->nread_inbuf = 0;
   httpc->nread_inbuf = 0;

+ 1 - 1
Utilities/cmcurl/lib/http2.h

@@ -42,7 +42,7 @@ const char *Curl_http2_strerror(uint32_t err);
 CURLcode Curl_http2_init(struct connectdata *conn);
 CURLcode Curl_http2_init(struct connectdata *conn);
 void Curl_http2_init_state(struct UrlState *state);
 void Curl_http2_init_state(struct UrlState *state);
 void Curl_http2_init_userset(struct UserDefined *set);
 void Curl_http2_init_userset(struct UserDefined *set);
-CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
+CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
                                     struct connectdata *conn);
                                     struct connectdata *conn);
 CURLcode Curl_http2_setup(struct connectdata *conn);
 CURLcode Curl_http2_setup(struct connectdata *conn);
 CURLcode Curl_http2_switched(struct connectdata *conn,
 CURLcode Curl_http2_switched(struct connectdata *conn,

+ 17 - 32
Utilities/cmcurl/lib/http_chunks.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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,7 +26,7 @@
 
 
 #include "urldata.h" /* it includes http_chunks.h */
 #include "urldata.h" /* it includes http_chunks.h */
 #include "sendf.h"   /* for the client write stuff */
 #include "sendf.h"   /* for the client write stuff */
-
+#include "dynbuf.h"
 #include "content_encoding.h"
 #include "content_encoding.h"
 #include "http.h"
 #include "http.h"
 #include "non-ascii.h" /* for Curl_convert_to_network prototype */
 #include "non-ascii.h" /* for Curl_convert_to_network prototype */
@@ -93,6 +93,7 @@ void Curl_httpchunk_init(struct connectdata *conn)
   chunk->hexindex = 0;      /* start at 0 */
   chunk->hexindex = 0;      /* start at 0 */
   chunk->dataleft = 0;      /* no data left yet! */
   chunk->dataleft = 0;      /* no data left yet! */
   chunk->state = CHUNK_HEX; /* we get hex first! */
   chunk->state = CHUNK_HEX; /* we get hex first! */
+  Curl_dyn_init(&conn->trailer, DYN_H1_TRAILER);
 }
 }
 
 
 /*
 /*
@@ -177,7 +178,6 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
         /* we're now expecting data to come, unless size was zero! */
         /* we're now expecting data to come, unless size was zero! */
         if(0 == ch->datasize) {
         if(0 == ch->datasize) {
           ch->state = CHUNK_TRAILER; /* now check for trailers */
           ch->state = CHUNK_TRAILER; /* now check for trailers */
-          conn->trlPos = 0;
         }
         }
         else
         else
           ch->state = CHUNK_DATA;
           ch->state = CHUNK_DATA;
@@ -229,32 +229,33 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
 
 
     case CHUNK_TRAILER:
     case CHUNK_TRAILER:
       if((*datap == 0x0d) || (*datap == 0x0a)) {
       if((*datap == 0x0d) || (*datap == 0x0a)) {
+        char *tr = Curl_dyn_ptr(&conn->trailer);
         /* this is the end of a trailer, but if the trailer was zero bytes
         /* this is the end of a trailer, but if the trailer was zero bytes
            there was no trailer and we move on */
            there was no trailer and we move on */
 
 
-        if(conn->trlPos) {
-          /* we allocate trailer with 3 bytes extra room to fit this */
-          conn->trailer[conn->trlPos++] = 0x0d;
-          conn->trailer[conn->trlPos++] = 0x0a;
-          conn->trailer[conn->trlPos] = 0;
+        if(tr) {
+          size_t trlen;
+          result = Curl_dyn_add(&conn->trailer, (char *)"\x0d\x0a");
+          if(result)
+            return CHUNKE_OUT_OF_MEMORY;
 
 
+          tr = Curl_dyn_ptr(&conn->trailer);
+          trlen = Curl_dyn_len(&conn->trailer);
           /* Convert to host encoding before calling Curl_client_write */
           /* Convert to host encoding before calling Curl_client_write */
-          result = Curl_convert_from_network(conn->data, conn->trailer,
-                                             conn->trlPos);
+          result = Curl_convert_from_network(conn->data, tr, trlen);
           if(result)
           if(result)
             /* Curl_convert_from_network calls failf if unsuccessful */
             /* Curl_convert_from_network calls failf if unsuccessful */
             /* Treat it as a bad chunk */
             /* Treat it as a bad chunk */
             return CHUNKE_BAD_CHUNK;
             return CHUNKE_BAD_CHUNK;
 
 
           if(!data->set.http_te_skip) {
           if(!data->set.http_te_skip) {
-            result = Curl_client_write(conn, CLIENTWRITE_HEADER,
-                                       conn->trailer, conn->trlPos);
+            result = Curl_client_write(conn, CLIENTWRITE_HEADER, tr, trlen);
             if(result) {
             if(result) {
               *extrap = result;
               *extrap = result;
               return CHUNKE_PASSTHRU_ERROR;
               return CHUNKE_PASSTHRU_ERROR;
             }
             }
           }
           }
-          conn->trlPos = 0;
+          Curl_dyn_reset(&conn->trailer);
           ch->state = CHUNK_TRAILER_CR;
           ch->state = CHUNK_TRAILER_CR;
           if(*datap == 0x0a)
           if(*datap == 0x0a)
             /* already on the LF */
             /* already on the LF */
@@ -267,25 +268,9 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
         }
         }
       }
       }
       else {
       else {
-        /* conn->trailer is assumed to be freed in url.c on a
-           connection basis */
-        if(conn->trlPos >= conn->trlMax) {
-          /* we always allocate three extra bytes, just because when the full
-             header has been received we append CRLF\0 */
-          char *ptr;
-          if(conn->trlMax) {
-            conn->trlMax *= 2;
-            ptr = realloc(conn->trailer, conn->trlMax + 3);
-          }
-          else {
-            conn->trlMax = 128;
-            ptr = malloc(conn->trlMax + 3);
-          }
-          if(!ptr)
-            return CHUNKE_OUT_OF_MEMORY;
-          conn->trailer = ptr;
-        }
-        conn->trailer[conn->trlPos++]=*datap;
+        result = Curl_dyn_addn(&conn->trailer, datap, 1);
+        if(result)
+          return CHUNKE_OUT_OF_MEMORY;
       }
       }
       datap++;
       datap++;
       length--;
       length--;

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

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -94,15 +94,19 @@ CURLcode Curl_output_digest(struct connectdata *conn,
   struct auth *authp;
   struct auth *authp;
 
 
   if(proxy) {
   if(proxy) {
+#ifdef CURL_DISABLE_PROXY
+    return CURLE_NOT_BUILT_IN;
+#else
     digest = &data->state.proxydigest;
     digest = &data->state.proxydigest;
-    allocuserpwd = &conn->allocptr.proxyuserpwd;
+    allocuserpwd = &data->state.aptr.proxyuserpwd;
     userp = conn->http_proxy.user;
     userp = conn->http_proxy.user;
     passwdp = conn->http_proxy.passwd;
     passwdp = conn->http_proxy.passwd;
     authp = &data->state.authproxy;
     authp = &data->state.authproxy;
+#endif
   }
   }
   else {
   else {
     digest = &data->state.digest;
     digest = &data->state.digest;
-    allocuserpwd = &conn->allocptr.userpwd;
+    allocuserpwd = &data->state.aptr.userpwd;
     userp = conn->user;
     userp = conn->user;
     passwdp = conn->passwd;
     passwdp = conn->passwd;
     authp = &data->state.authhost;
     authp = &data->state.authhost;

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

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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

+ 12 - 7
Utilities/cmcurl/lib/http_negotiate.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -52,6 +52,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
   curlnegotiate state;
   curlnegotiate state;
 
 
   if(proxy) {
   if(proxy) {
+#ifndef CURL_DISABLE_PROXY
     userp = conn->http_proxy.user;
     userp = conn->http_proxy.user;
     passwdp = conn->http_proxy.passwd;
     passwdp = conn->http_proxy.passwd;
     service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
     service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
@@ -59,6 +60,9 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     host = conn->http_proxy.host.name;
     host = conn->http_proxy.host.name;
     neg_ctx = &conn->proxyneg;
     neg_ctx = &conn->proxyneg;
     state = conn->proxy_negotiate_state;
     state = conn->proxy_negotiate_state;
+#else
+    return CURLE_NOT_BUILT_IN;
+#endif
   }
   }
   else {
   else {
     userp = conn->user;
     userp = conn->user;
@@ -119,7 +123,8 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
   struct auth *authp = proxy ? &conn->data->state.authproxy :
   struct auth *authp = proxy ? &conn->data->state.authproxy :
     &conn->data->state.authhost;
     &conn->data->state.authhost;
   curlnegotiate *state = proxy ? &conn->proxy_negotiate_state :
   curlnegotiate *state = proxy ? &conn->proxy_negotiate_state :
-                                 &conn->http_negotiate_state;
+    &conn->http_negotiate_state;
+  struct Curl_easy *data = conn->data;
   char *base64 = NULL;
   char *base64 = NULL;
   size_t len = 0;
   size_t len = 0;
   char *userp;
   char *userp;
@@ -164,15 +169,15 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
       return result;
       return result;
 
 
     userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
     userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
-      base64);
+                    base64);
 
 
     if(proxy) {
     if(proxy) {
-      Curl_safefree(conn->allocptr.proxyuserpwd);
-      conn->allocptr.proxyuserpwd = userp;
+      Curl_safefree(data->state.aptr.proxyuserpwd);
+      data->state.aptr.proxyuserpwd = userp;
     }
     }
     else {
     else {
-      Curl_safefree(conn->allocptr.userpwd);
-      conn->allocptr.userpwd = userp;
+      Curl_safefree(data->state.aptr.userpwd);
+      data->state.aptr.userpwd = userp;
     }
     }
 
 
     free(base64);
     free(base64);

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

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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,6 +33,8 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
 
 
 void Curl_http_auth_cleanup_negotiate(struct connectdata *conn);
 void Curl_http_auth_cleanup_negotiate(struct connectdata *conn);
 
 
-#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
+#else /* !CURL_DISABLE_HTTP && USE_SPNEGO */
+#define Curl_http_auth_cleanup_negotiate(x)
+#endif
 
 
 #endif /* HEADER_CURL_HTTP_NEGOTIATE_H */
 #endif /* HEADER_CURL_HTTP_NEGOTIATE_H */

+ 10 - 4
Utilities/cmcurl/lib/http_ntlm.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -131,12 +131,15 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
   struct ntlmdata *ntlm;
   struct ntlmdata *ntlm;
   curlntlm *state;
   curlntlm *state;
   struct auth *authp;
   struct auth *authp;
+  struct Curl_easy *data = conn->data;
+
 
 
   DEBUGASSERT(conn);
   DEBUGASSERT(conn);
-  DEBUGASSERT(conn->data);
+  DEBUGASSERT(data);
 
 
   if(proxy) {
   if(proxy) {
-    allocuserpwd = &conn->allocptr.proxyuserpwd;
+#ifndef CURL_DISABLE_PROXY
+    allocuserpwd = &data->state.aptr.proxyuserpwd;
     userp = conn->http_proxy.user;
     userp = conn->http_proxy.user;
     passwdp = conn->http_proxy.passwd;
     passwdp = conn->http_proxy.passwd;
     service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ?
     service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ?
@@ -145,9 +148,12 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
     ntlm = &conn->proxyntlm;
     ntlm = &conn->proxyntlm;
     state = &conn->proxy_ntlm_state;
     state = &conn->proxy_ntlm_state;
     authp = &conn->data->state.authproxy;
     authp = &conn->data->state.authproxy;
+#else
+    return CURLE_NOT_BUILT_IN;
+#endif
   }
   }
   else {
   else {
-    allocuserpwd = &conn->allocptr.userpwd;
+    allocuserpwd = &data->state.aptr.userpwd;
     userp = conn->user;
     userp = conn->user;
     passwdp = conn->passwd;
     passwdp = conn->passwd;
     service = conn->data->set.str[STRING_SERVICE_NAME] ?
     service = conn->data->set.str[STRING_SERVICE_NAME] ?

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

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -35,6 +35,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
 
 
 void Curl_http_auth_cleanup_ntlm(struct connectdata *conn);
 void Curl_http_auth_cleanup_ntlm(struct connectdata *conn);
 
 
-#endif /* !CURL_DISABLE_HTTP && USE_NTLM */
+#else /* !CURL_DISABLE_HTTP && USE_NTLM */
+#define Curl_http_auth_cleanup_ntlm(x)
+#endif
 
 
 #endif /* HEADER_CURL_HTTP_NTLM_H */
 #endif /* HEADER_CURL_HTTP_NTLM_H */

+ 79 - 94
Utilities/cmcurl/lib/http_proxy.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -72,6 +72,7 @@ static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex)
 
 
 CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
 CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
 {
 {
+  struct Curl_easy *data = conn->data;
   if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
   if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
     const CURLcode result = https_proxy_connect(conn, sockindex);
     const CURLcode result = https_proxy_connect(conn, sockindex);
     if(result)
     if(result)
@@ -127,7 +128,7 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
     conn->data->req.protop = prot_save;
     conn->data->req.protop = prot_save;
     if(CURLE_OK != result)
     if(CURLE_OK != result)
       return result;
       return result;
-    Curl_safefree(conn->allocptr.proxyuserpwd);
+    Curl_safefree(data->state.aptr.proxyuserpwd);
 #else
 #else
     return CURLE_NOT_BUILT_IN;
     return CURLE_NOT_BUILT_IN;
 #endif
 #endif
@@ -158,15 +159,15 @@ static CURLcode connect_init(struct connectdata *conn, bool reinit)
       return CURLE_OUT_OF_MEMORY;
       return CURLE_OUT_OF_MEMORY;
     infof(conn->data, "allocate connect buffer!\n");
     infof(conn->data, "allocate connect buffer!\n");
     conn->connect_state = s;
     conn->connect_state = s;
+    Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
   }
   }
   else {
   else {
     DEBUGASSERT(conn->connect_state);
     DEBUGASSERT(conn->connect_state);
     s = conn->connect_state;
     s = conn->connect_state;
+    Curl_dyn_reset(&s->rcvbuf);
   }
   }
   s->tunnel_state = TUNNEL_INIT;
   s->tunnel_state = TUNNEL_INIT;
   s->keepon = TRUE;
   s->keepon = TRUE;
-  s->line_start = s->connect_buffer;
-  s->ptr = s->line_start;
   s->cl = 0;
   s->cl = 0;
   s->close_connection = FALSE;
   s->close_connection = FALSE;
   return CURLE_OK;
   return CURLE_OK;
@@ -176,6 +177,7 @@ static void connect_done(struct connectdata *conn)
 {
 {
   struct http_connect_state *s = conn->connect_state;
   struct http_connect_state *s = conn->connect_state;
   s->tunnel_state = TUNNEL_COMPLETE;
   s->tunnel_state = TUNNEL_COMPLETE;
+  Curl_dyn_free(&s->rcvbuf);
   infof(conn->data, "CONNECT phase completed!\n");
   infof(conn->data, "CONNECT phase completed!\n");
 }
 }
 
 
@@ -190,6 +192,8 @@ static CURLcode CONNECT(struct connectdata *conn,
   CURLcode result;
   CURLcode result;
   curl_socket_t tunnelsocket = conn->sock[sockindex];
   curl_socket_t tunnelsocket = conn->sock[sockindex];
   struct http_connect_state *s = conn->connect_state;
   struct http_connect_state *s = conn->connect_state;
+  char *linep;
+  size_t perline;
 
 
 #define SELECT_OK      0
 #define SELECT_OK      0
 #define SELECT_ERROR   1
 #define SELECT_ERROR   1
@@ -204,7 +208,7 @@ static CURLcode CONNECT(struct connectdata *conn,
     if(TUNNEL_INIT == s->tunnel_state) {
     if(TUNNEL_INIT == s->tunnel_state) {
       /* BEGIN CONNECT PHASE */
       /* BEGIN CONNECT PHASE */
       char *host_port;
       char *host_port;
-      Curl_send_buffer *req_buffer;
+      struct dynbuf req;
 
 
       infof(data, "Establish HTTP proxy tunnel to %s:%d\n",
       infof(data, "Establish HTTP proxy tunnel to %s:%d\n",
             hostname, remote_port);
             hostname, remote_port);
@@ -215,17 +219,12 @@ static CURLcode CONNECT(struct connectdata *conn,
       free(data->req.newurl);
       free(data->req.newurl);
       data->req.newurl = NULL;
       data->req.newurl = NULL;
 
 
-      /* initialize a dynamic send-buffer */
-      req_buffer = Curl_add_buffer_init();
-
-      if(!req_buffer)
-        return CURLE_OUT_OF_MEMORY;
-
       host_port = aprintf("%s:%d", hostname, remote_port);
       host_port = aprintf("%s:%d", hostname, remote_port);
-      if(!host_port) {
-        Curl_add_buffer_free(&req_buffer);
+      if(!host_port)
         return CURLE_OUT_OF_MEMORY;
         return CURLE_OUT_OF_MEMORY;
-      }
+
+      /* initialize a dynamic send-buffer */
+      Curl_dyn_init(&req, DYN_HTTP_REQUEST);
 
 
       /* Setup the proxy-authorization header, if any */
       /* Setup the proxy-authorization header, if any */
       result = Curl_http_output_auth(conn, "CONNECT", host_port, TRUE);
       result = Curl_http_output_auth(conn, "CONNECT", host_port, TRUE);
@@ -236,8 +235,8 @@ static CURLcode CONNECT(struct connectdata *conn,
         char *host = NULL;
         char *host = NULL;
         const char *proxyconn = "";
         const char *proxyconn = "";
         const char *useragent = "";
         const char *useragent = "";
-        const char *http = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ?
-          "1.0" : "1.1";
+        const char *httpv =
+          (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1";
         bool ipv6_ip = conn->bits.ipv6_ip;
         bool ipv6_ip = conn->bits.ipv6_ip;
         char *hostheader;
         char *hostheader;
 
 
@@ -248,7 +247,7 @@ static CURLcode CONNECT(struct connectdata *conn,
           aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
           aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
                   remote_port);
                   remote_port);
         if(!hostheader) {
         if(!hostheader) {
-          Curl_add_buffer_free(&req_buffer);
+          Curl_dyn_free(&req);
           return CURLE_OUT_OF_MEMORY;
           return CURLE_OUT_OF_MEMORY;
         }
         }
 
 
@@ -256,7 +255,7 @@ static CURLcode CONNECT(struct connectdata *conn,
           host = aprintf("Host: %s\r\n", hostheader);
           host = aprintf("Host: %s\r\n", hostheader);
           if(!host) {
           if(!host) {
             free(hostheader);
             free(hostheader);
-            Curl_add_buffer_free(&req_buffer);
+            Curl_dyn_free(&req);
             return CURLE_OUT_OF_MEMORY;
             return CURLE_OUT_OF_MEMORY;
           }
           }
         }
         }
@@ -265,52 +264,49 @@ static CURLcode CONNECT(struct connectdata *conn,
 
 
         if(!Curl_checkProxyheaders(conn, "User-Agent") &&
         if(!Curl_checkProxyheaders(conn, "User-Agent") &&
            data->set.str[STRING_USERAGENT])
            data->set.str[STRING_USERAGENT])
-          useragent = conn->allocptr.uagent;
+          useragent = data->state.aptr.uagent;
 
 
         result =
         result =
-          Curl_add_bufferf(&req_buffer,
-                           "CONNECT %s HTTP/%s\r\n"
-                           "%s"  /* Host: */
-                           "%s"  /* Proxy-Authorization */
-                           "%s"  /* User-Agent */
-                           "%s", /* Proxy-Connection */
-                           hostheader,
-                           http,
-                           host?host:"",
-                           conn->allocptr.proxyuserpwd?
-                           conn->allocptr.proxyuserpwd:"",
-                           useragent,
-                           proxyconn);
+          Curl_dyn_addf(&req,
+                        "CONNECT %s HTTP/%s\r\n"
+                        "%s"  /* Host: */
+                        "%s"  /* Proxy-Authorization */
+                        "%s"  /* User-Agent */
+                        "%s", /* Proxy-Connection */
+                        hostheader,
+                        httpv,
+                        host?host:"",
+                        data->state.aptr.proxyuserpwd?
+                        data->state.aptr.proxyuserpwd:"",
+                        useragent,
+                        proxyconn);
 
 
         if(host)
         if(host)
           free(host);
           free(host);
         free(hostheader);
         free(hostheader);
 
 
         if(!result)
         if(!result)
-          result = Curl_add_custom_headers(conn, TRUE, req_buffer);
+          result = Curl_add_custom_headers(conn, TRUE, &req);
 
 
         if(!result)
         if(!result)
           /* CRLF terminate the request */
           /* CRLF terminate the request */
-          result = Curl_add_bufferf(&req_buffer, "\r\n");
+          result = Curl_dyn_add(&req, "\r\n");
 
 
         if(!result) {
         if(!result) {
           /* Send the connect request to the proxy */
           /* Send the connect request to the proxy */
           /* BLOCKING */
           /* BLOCKING */
-          result =
-            Curl_add_buffer_send(&req_buffer, conn,
-                                 &data->info.request_size, 0, sockindex);
+          result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+                                    sockindex);
         }
         }
-        req_buffer = NULL;
         if(result)
         if(result)
           failf(data, "Failed sending CONNECT to proxy");
           failf(data, "Failed sending CONNECT to proxy");
       }
       }
 
 
-      Curl_add_buffer_free(&req_buffer);
+      Curl_dyn_free(&req);
       if(result)
       if(result)
         return result;
         return result;
 
 
       s->tunnel_state = TUNNEL_CONNECT;
       s->tunnel_state = TUNNEL_CONNECT;
-      s->perline = 0;
     } /* END CONNECT PHASE */
     } /* END CONNECT PHASE */
 
 
     check = Curl_timeleft(data, NULL, TRUE);
     check = Curl_timeleft(data, NULL, TRUE);
@@ -330,16 +326,11 @@ static CURLcode CONNECT(struct connectdata *conn,
 
 
       while(s->keepon) {
       while(s->keepon) {
         ssize_t gotbytes;
         ssize_t gotbytes;
-
-        /* make sure we have space to read more data */
-        if(s->ptr >= &s->connect_buffer[CONNECT_BUFFER_SIZE]) {
-          failf(data, "CONNECT response too large!");
-          return CURLE_RECV_ERROR;
-        }
+        char byte;
 
 
         /* Read one byte at a time to avoid a race condition. Wait at most one
         /* Read one byte at a time to avoid a race condition. Wait at most one
            second before looping to ensure continuous pgrsUpdates. */
            second before looping to ensure continuous pgrsUpdates. */
-        result = Curl_read(conn, tunnelsocket, s->ptr, 1, &gotbytes);
+        result = Curl_read(conn, tunnelsocket, &byte, 1, &gotbytes);
         if(result == CURLE_AGAIN)
         if(result == CURLE_AGAIN)
           /* socket buffer drained, return */
           /* socket buffer drained, return */
           return CURLE_OK;
           return CURLE_OK;
@@ -366,11 +357,9 @@ static CURLcode CONNECT(struct connectdata *conn,
           break;
           break;
         }
         }
 
 
-
         if(s->keepon > TRUE) {
         if(s->keepon > TRUE) {
           /* This means we are currently ignoring a response-body */
           /* This means we are currently ignoring a response-body */
 
 
-          s->ptr = s->connect_buffer;
           if(s->cl) {
           if(s->cl) {
             /* A Content-Length based body: simply count down the counter
             /* A Content-Length based body: simply count down the counter
                and make sure to break out of the loop when we're done! */
                and make sure to break out of the loop when we're done! */
@@ -390,7 +379,7 @@ static CURLcode CONNECT(struct connectdata *conn,
 
 
             /* now parse the chunked piece of data so that we can
             /* now parse the chunked piece of data so that we can
                properly tell when the stream ends */
                properly tell when the stream ends */
-            r = Curl_httpchunk_read(conn, s->ptr, 1, &tookcareof, &extra);
+            r = Curl_httpchunk_read(conn, &byte, 1, &tookcareof, &extra);
             if(r == CHUNKE_STOP) {
             if(r == CHUNKE_STOP) {
               /* we're done reading chunks! */
               /* we're done reading chunks! */
               infof(data, "chunk reading DONE\n");
               infof(data, "chunk reading DONE\n");
@@ -402,25 +391,27 @@ static CURLcode CONNECT(struct connectdata *conn,
           continue;
           continue;
         }
         }
 
 
-        s->perline++; /* amount of bytes in this line so far */
+        if(Curl_dyn_addn(&s->rcvbuf, &byte, 1)) {
+          failf(data, "CONNECT response too large!");
+          return CURLE_RECV_ERROR;
+        }
 
 
         /* if this is not the end of a header line then continue */
         /* if this is not the end of a header line then continue */
-        if(*s->ptr != 0x0a) {
-          s->ptr++;
+        if(byte != 0x0a)
           continue;
           continue;
-        }
+
+        linep = Curl_dyn_ptr(&s->rcvbuf);
+        perline = Curl_dyn_len(&s->rcvbuf); /* amount of bytes in this line */
 
 
         /* convert from the network encoding */
         /* convert from the network encoding */
-        result = Curl_convert_from_network(data, s->line_start,
-                                           (size_t)s->perline);
+        result = Curl_convert_from_network(data, linep, perline);
         /* Curl_convert_from_network calls failf if unsuccessful */
         /* Curl_convert_from_network calls failf if unsuccessful */
         if(result)
         if(result)
           return result;
           return result;
 
 
         /* output debug if that is requested */
         /* output debug if that is requested */
         if(data->set.verbose)
         if(data->set.verbose)
-          Curl_debug(data, CURLINFO_HEADER_IN,
-                     s->line_start, (size_t)s->perline);
+          Curl_debug(data, CURLINFO_HEADER_IN, linep, perline);
 
 
         if(!data->set.suppress_connect_headers) {
         if(!data->set.suppress_connect_headers) {
           /* send the header to the callback */
           /* send the header to the callback */
@@ -428,23 +419,22 @@ static CURLcode CONNECT(struct connectdata *conn,
           if(data->set.include_header)
           if(data->set.include_header)
             writetype |= CLIENTWRITE_BODY;
             writetype |= CLIENTWRITE_BODY;
 
 
-          result = Curl_client_write(conn, writetype,
-                                     s->line_start, s->perline);
+          result = Curl_client_write(conn, writetype, linep, perline);
           if(result)
           if(result)
             return result;
             return result;
         }
         }
 
 
-        data->info.header_size += (long)s->perline;
-        data->req.headerbytecount += (long)s->perline;
+        data->info.header_size += (long)perline;
+        data->req.headerbytecount += (long)perline;
 
 
         /* Newlines are CRLF, so the CR is ignored as the line isn't
         /* Newlines are CRLF, so the CR is ignored as the line isn't
            really terminated until the LF comes. Treat a following CR
            really terminated until the LF comes. Treat a following CR
            as end-of-headers as well.*/
            as end-of-headers as well.*/
 
 
-        if(('\r' == s->line_start[0]) ||
-           ('\n' == s->line_start[0])) {
+        if(('\r' == linep[0]) ||
+           ('\n' == linep[0])) {
           /* end of response-headers from the proxy */
           /* end of response-headers from the proxy */
-          s->ptr = s->connect_buffer;
+
           if((407 == k->httpcode) && !data->state.authproblem) {
           if((407 == k->httpcode) && !data->state.authproblem) {
             /* If we get a 407 response code with content length
             /* If we get a 407 response code with content length
                when we have no auth problem, we must ignore the
                when we have no auth problem, we must ignore the
@@ -461,21 +451,18 @@ static CURLcode CONNECT(struct connectdata *conn,
 
 
               infof(data, "Ignore chunked response-body\n");
               infof(data, "Ignore chunked response-body\n");
 
 
-              /* We set ignorebody true here since the chunked
-                 decoder function will acknowledge that. Pay
-                 attention so that this is cleared again when this
-                 function returns! */
+              /* We set ignorebody true here since the chunked decoder
+                 function will acknowledge that. Pay attention so that this is
+                 cleared again when this function returns! */
               k->ignorebody = TRUE;
               k->ignorebody = TRUE;
 
 
-              if(s->line_start[1] == '\n') {
-                /* this can only be a LF if the letter at index 0
-                   was a CR */
-                s->line_start++;
-              }
+              if(linep[1] == '\n')
+                /* this can only be a LF if the letter at index 0 was a CR */
+                linep++;
 
 
-              /* now parse the chunked piece of data so that we can
-                 properly tell when the stream ends */
-              r = Curl_httpchunk_read(conn, s->line_start + 1, 1, &gotbytes,
+              /* now parse the chunked piece of data so that we can properly
+                 tell when the stream ends */
+              r = Curl_httpchunk_read(conn, linep + 1, 1, &gotbytes,
                                       &extra);
                                       &extra);
               if(r == CHUNKE_STOP) {
               if(r == CHUNKE_STOP) {
                 /* we're done reading chunks! */
                 /* we're done reading chunks! */
@@ -500,14 +487,13 @@ static CURLcode CONNECT(struct connectdata *conn,
           continue;
           continue;
         }
         }
 
 
-        s->line_start[s->perline] = 0; /* zero terminate the buffer */
-        if((checkprefix("WWW-Authenticate:", s->line_start) &&
+        if((checkprefix("WWW-Authenticate:", linep) &&
             (401 == k->httpcode)) ||
             (401 == k->httpcode)) ||
-           (checkprefix("Proxy-authenticate:", s->line_start) &&
+           (checkprefix("Proxy-authenticate:", linep) &&
             (407 == k->httpcode))) {
             (407 == k->httpcode))) {
 
 
           bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
           bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
-          char *auth = Curl_copy_header_value(s->line_start);
+          char *auth = Curl_copy_header_value(linep);
           if(!auth)
           if(!auth)
             return CURLE_OUT_OF_MEMORY;
             return CURLE_OUT_OF_MEMORY;
 
 
@@ -518,7 +504,7 @@ static CURLcode CONNECT(struct connectdata *conn,
           if(result)
           if(result)
             return result;
             return result;
         }
         }
-        else if(checkprefix("Content-Length:", s->line_start)) {
+        else if(checkprefix("Content-Length:", linep)) {
           if(k->httpcode/100 == 2) {
           if(k->httpcode/100 == 2) {
             /* A client MUST ignore any Content-Length or Transfer-Encoding
             /* A client MUST ignore any Content-Length or Transfer-Encoding
                header fields received in a successful response to CONNECT.
                header fields received in a successful response to CONNECT.
@@ -527,13 +513,13 @@ static CURLcode CONNECT(struct connectdata *conn,
                   k->httpcode);
                   k->httpcode);
           }
           }
           else {
           else {
-            (void)curlx_strtoofft(s->line_start +
+            (void)curlx_strtoofft(linep +
                                   strlen("Content-Length:"), NULL, 10, &s->cl);
                                   strlen("Content-Length:"), NULL, 10, &s->cl);
           }
           }
         }
         }
-        else if(Curl_compareheader(s->line_start, "Connection:", "close"))
+        else if(Curl_compareheader(linep, "Connection:", "close"))
           s->close_connection = TRUE;
           s->close_connection = TRUE;
-        else if(checkprefix("Transfer-Encoding:", s->line_start)) {
+        else if(checkprefix("Transfer-Encoding:", linep)) {
           if(k->httpcode/100 == 2) {
           if(k->httpcode/100 == 2) {
             /* A client MUST ignore any Content-Length or Transfer-Encoding
             /* A client MUST ignore any Content-Length or Transfer-Encoding
                header fields received in a successful response to CONNECT.
                header fields received in a successful response to CONNECT.
@@ -541,7 +527,7 @@ static CURLcode CONNECT(struct connectdata *conn,
             infof(data, "Ignoring Transfer-Encoding in "
             infof(data, "Ignoring Transfer-Encoding in "
                   "CONNECT %03d response\n", k->httpcode);
                   "CONNECT %03d response\n", k->httpcode);
           }
           }
-          else if(Curl_compareheader(s->line_start,
+          else if(Curl_compareheader(linep,
                                      "Transfer-Encoding:", "chunked")) {
                                      "Transfer-Encoding:", "chunked")) {
             infof(data, "CONNECT responded chunked\n");
             infof(data, "CONNECT responded chunked\n");
             s->chunked_encoding = TRUE;
             s->chunked_encoding = TRUE;
@@ -549,19 +535,16 @@ static CURLcode CONNECT(struct connectdata *conn,
             Curl_httpchunk_init(conn);
             Curl_httpchunk_init(conn);
           }
           }
         }
         }
-        else if(Curl_compareheader(s->line_start,
-                                   "Proxy-Connection:", "close"))
+        else if(Curl_compareheader(linep, "Proxy-Connection:", "close"))
           s->close_connection = TRUE;
           s->close_connection = TRUE;
-        else if(2 == sscanf(s->line_start, "HTTP/1.%d %d",
+        else if(2 == sscanf(linep, "HTTP/1.%d %d",
                             &subversion,
                             &subversion,
                             &k->httpcode)) {
                             &k->httpcode)) {
           /* store the HTTP code from the proxy */
           /* store the HTTP code from the proxy */
           data->info.httpproxycode = k->httpcode;
           data->info.httpproxycode = k->httpcode;
         }
         }
 
 
-        s->perline = 0; /* line starts over here */
-        s->ptr = s->connect_buffer;
-        s->line_start = s->ptr;
+        Curl_dyn_reset(&s->rcvbuf);
       } /* while there's buffer left and loop is requested */
       } /* while there's buffer left and loop is requested */
 
 
       if(Curl_pgrsUpdate(conn))
       if(Curl_pgrsUpdate(conn))
@@ -622,6 +605,7 @@ static CURLcode CONNECT(struct connectdata *conn,
     if(conn->bits.proxy_connect_closed)
     if(conn->bits.proxy_connect_closed)
       /* this is not an error, just part of the connection negotiation */
       /* this is not an error, just part of the connection negotiation */
       return CURLE_OK;
       return CURLE_OK;
+    Curl_dyn_free(&s->rcvbuf);
     failf(data, "Received HTTP code %d from proxy after CONNECT",
     failf(data, "Received HTTP code %d from proxy after CONNECT",
           data->req.httpcode);
           data->req.httpcode);
     return CURLE_RECV_ERROR;
     return CURLE_RECV_ERROR;
@@ -632,8 +616,8 @@ static CURLcode CONNECT(struct connectdata *conn,
   /* If a proxy-authorization header was used for the proxy, then we should
   /* If a proxy-authorization header was used for the proxy, then we should
      make sure that it isn't accidentally used for the document request
      make sure that it isn't accidentally used for the document request
      after we've connected. So let's free and clear it here. */
      after we've connected. So let's free and clear it here. */
-  Curl_safefree(conn->allocptr.proxyuserpwd);
-  conn->allocptr.proxyuserpwd = NULL;
+  Curl_safefree(data->state.aptr.proxyuserpwd);
+  data->state.aptr.proxyuserpwd = NULL;
 
 
   data->state.authproxy.done = TRUE;
   data->state.authproxy.done = TRUE;
   data->state.authproxy.multipass = FALSE;
   data->state.authproxy.multipass = FALSE;
@@ -643,6 +627,7 @@ static CURLcode CONNECT(struct connectdata *conn,
   data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */
   data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */
   conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the
   conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the
                                          document request  */
                                          document request  */
+  Curl_dyn_free(&s->rcvbuf);
   return CURLE_OK;
   return CURLE_OK;
 }
 }
 
 

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

@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -47,5 +47,6 @@ bool Curl_connect_ongoing(struct connectdata *conn);
 #endif
 #endif
 
 
 void Curl_connect_free(struct Curl_easy *data);
 void Curl_connect_free(struct Curl_easy *data);
+void Curl_connect_done(struct Curl_easy *data);
 
 
 #endif /* HEADER_CURL_HTTP_PROXY_H */
 #endif /* HEADER_CURL_HTTP_PROXY_H */

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

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -72,13 +72,13 @@ bool curl_win32_idn_to_ascii(const char *in, char **out)
 {
 {
   bool success = FALSE;
   bool success = FALSE;
 
 
-  wchar_t *in_w = Curl_convert_UTF8_to_wchar(in);
+  wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
   if(in_w) {
   if(in_w) {
     wchar_t punycode[IDN_MAX_LENGTH];
     wchar_t punycode[IDN_MAX_LENGTH];
     int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH);
     int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH);
     free(in_w);
     free(in_w);
     if(chars) {
     if(chars) {
-      *out = Curl_convert_wchar_to_UTF8(punycode);
+      *out = curlx_convert_wchar_to_UTF8(punycode);
       if(*out)
       if(*out)
         success = TRUE;
         success = TRUE;
     }
     }
@@ -91,7 +91,7 @@ bool curl_win32_ascii_to_idn(const char *in, char **out)
 {
 {
   bool success = FALSE;
   bool success = FALSE;
 
 
-  wchar_t *in_w = Curl_convert_UTF8_to_wchar(in);
+  wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
   if(in_w) {
   if(in_w) {
     size_t in_len = wcslen(in_w) + 1;
     size_t in_len = wcslen(in_w) + 1;
     wchar_t unicode[IDN_MAX_LENGTH];
     wchar_t unicode[IDN_MAX_LENGTH];
@@ -99,7 +99,7 @@ bool curl_win32_ascii_to_idn(const char *in, char **out)
                              unicode, IDN_MAX_LENGTH);
                              unicode, IDN_MAX_LENGTH);
     free(in_w);
     free(in_w);
     if(chars) {
     if(chars) {
-      *out = Curl_convert_wchar_to_UTF8(unicode);
+      *out = curlx_convert_wchar_to_UTF8(unicode);
       if(*out)
       if(*out)
         success = TRUE;
         success = TRUE;
     }
     }

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

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -129,11 +129,11 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
               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) {
-                /* We are interested only in interface addresses whose
-                   scope matches the remote address we want to
-                   connect to: global for global, link-local for
-                   link-local, etc... */
-                if(res == IF2IP_NOT_FOUND) res = IF2IP_AF_NOT_SUPPORTED;
+                /* We are interested only in interface addresses whose scope
+                   matches the remote address we want to connect to: global
+                   for global, link-local for link-local, etc... */
+                if(res == IF2IP_NOT_FOUND)
+                  res = IF2IP_AF_NOT_SUPPORTED;
                 continue;
                 continue;
               }
               }
 
 

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

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -187,7 +187,7 @@ static void imap_to_imaps(struct connectdata *conn)
   conn->handler = &Curl_handler_imaps;
   conn->handler = &Curl_handler_imaps;
 
 
   /* Set the connection's upgraded to TLS flag */
   /* Set the connection's upgraded to TLS flag */
-  conn->tls_upgraded = TRUE;
+  conn->bits.tls_upgraded = TRUE;
 }
 }
 #else
 #else
 #define imap_to_imaps(x) Curl_nop_stmt
 #define imap_to_imaps(x) Curl_nop_stmt
@@ -1710,7 +1710,7 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
     return result;
     return result;
 
 
   /* Clear the TLS upgraded flag */
   /* Clear the TLS upgraded flag */
-  conn->tls_upgraded = FALSE;
+  conn->bits.tls_upgraded = FALSE;
 
 
   return CURLE_OK;
   return CURLE_OK;
 }
 }

+ 30 - 30
Utilities/cmcurl/lib/ldap.c

@@ -5,7 +5,7 @@
  *                | (__| |_| |  _ <| |___
  *                | (__| |_| |  _ <| |___
  *                 \___|\___/|_| \_\_____|
  *                 \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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,7 +75,7 @@
 
 
 /* Use our own implementation. */
 /* Use our own implementation. */
 
 
-typedef struct {
+struct ldap_urldesc {
   char   *lud_host;
   char   *lud_host;
   int     lud_port;
   int     lud_port;
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
@@ -95,10 +95,10 @@ typedef struct {
   size_t    lud_attrs_dups; /* how many were dup'ed, this field is not in the
   size_t    lud_attrs_dups; /* how many were dup'ed, this field is not in the
                                "real" struct so can only be used in code
                                "real" struct so can only be used in code
                                without HAVE_LDAP_URL_PARSE defined */
                                without HAVE_LDAP_URL_PARSE defined */
-} CURL_LDAPURLDesc;
+};
 
 
 #undef LDAPURLDesc
 #undef LDAPURLDesc
-#define LDAPURLDesc             CURL_LDAPURLDesc
+#define LDAPURLDesc struct ldap_urldesc
 
 
 static int  _ldap_url_parse(const struct connectdata *conn,
 static int  _ldap_url_parse(const struct connectdata *conn,
                             LDAPURLDesc **ludp);
                             LDAPURLDesc **ludp);
@@ -239,13 +239,13 @@ static int ldap_win_bind(struct connectdata *conn, LDAP *server,
   PTCHAR inpass = NULL;
   PTCHAR inpass = NULL;
 
 
   if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) {
   if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) {
-    inuser = Curl_convert_UTF8_to_tchar((char *) user);
-    inpass = Curl_convert_UTF8_to_tchar((char *) passwd);
+    inuser = curlx_convert_UTF8_to_tchar((char *) user);
+    inpass = curlx_convert_UTF8_to_tchar((char *) passwd);
 
 
     rc = ldap_simple_bind_s(server, inuser, inpass);
     rc = ldap_simple_bind_s(server, inuser, inpass);
 
 
-    Curl_unicodefree(inuser);
-    Curl_unicodefree(inpass);
+    curlx_unicodefree(inuser);
+    curlx_unicodefree(inpass);
   }
   }
 #if defined(USE_WINDOWS_SSPI)
 #if defined(USE_WINDOWS_SSPI)
   else {
   else {
@@ -306,7 +306,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
           ldap_ssl ? "encrypted" : "cleartext");
           ldap_ssl ? "encrypted" : "cleartext");
 
 
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-  host = Curl_convert_UTF8_to_tchar(conn->host.name);
+  host = curlx_convert_UTF8_to_tchar(conn->host.name);
   if(!host) {
   if(!host) {
     result = CURLE_OUT_OF_MEMORY;
     result = CURLE_OUT_OF_MEMORY;
 
 
@@ -517,7 +517,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       size_t name_len;
       size_t name_len;
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
       TCHAR *dn = ldap_get_dn(server, entryIterator);
       TCHAR *dn = ldap_get_dn(server, entryIterator);
-      name = Curl_convert_tchar_to_UTF8(dn);
+      name = curlx_convert_tchar_to_UTF8(dn);
       if(!name) {
       if(!name) {
         ldap_memfree(dn);
         ldap_memfree(dn);
 
 
@@ -533,7 +533,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
       result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
       if(result) {
       if(result) {
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-        Curl_unicodefree(name);
+        curlx_unicodefree(name);
 #endif
 #endif
         ldap_memfree(dn);
         ldap_memfree(dn);
 
 
@@ -544,7 +544,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
                                  name_len);
                                  name_len);
       if(result) {
       if(result) {
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-        Curl_unicodefree(name);
+        curlx_unicodefree(name);
 #endif
 #endif
         ldap_memfree(dn);
         ldap_memfree(dn);
 
 
@@ -554,7 +554,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
       result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
       if(result) {
       if(result) {
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-        Curl_unicodefree(name);
+        curlx_unicodefree(name);
 #endif
 #endif
         ldap_memfree(dn);
         ldap_memfree(dn);
 
 
@@ -564,7 +564,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       dlsize += name_len + 5;
       dlsize += name_len + 5;
 
 
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-      Curl_unicodefree(name);
+      curlx_unicodefree(name);
 #endif
 #endif
       ldap_memfree(dn);
       ldap_memfree(dn);
     }
     }
@@ -576,7 +576,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
       BerValue **vals;
       BerValue **vals;
       size_t attr_len;
       size_t attr_len;
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-      char *attr = Curl_convert_tchar_to_UTF8(attribute);
+      char *attr = curlx_convert_tchar_to_UTF8(attribute);
       if(!attr) {
       if(!attr) {
         if(ber)
         if(ber)
           ber_free(ber, 0);
           ber_free(ber, 0);
@@ -597,7 +597,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
           if(result) {
           if(result) {
             ldap_value_free_len(vals);
             ldap_value_free_len(vals);
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-            Curl_unicodefree(attr);
+            curlx_unicodefree(attr);
 #endif
 #endif
             ldap_memfree(attribute);
             ldap_memfree(attribute);
             if(ber)
             if(ber)
@@ -611,7 +611,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
           if(result) {
           if(result) {
             ldap_value_free_len(vals);
             ldap_value_free_len(vals);
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-            Curl_unicodefree(attr);
+            curlx_unicodefree(attr);
 #endif
 #endif
             ldap_memfree(attribute);
             ldap_memfree(attribute);
             if(ber)
             if(ber)
@@ -624,7 +624,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
           if(result) {
           if(result) {
             ldap_value_free_len(vals);
             ldap_value_free_len(vals);
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-            Curl_unicodefree(attr);
+            curlx_unicodefree(attr);
 #endif
 #endif
             ldap_memfree(attribute);
             ldap_memfree(attribute);
             if(ber)
             if(ber)
@@ -646,7 +646,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
             if(result) {
             if(result) {
               ldap_value_free_len(vals);
               ldap_value_free_len(vals);
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-              Curl_unicodefree(attr);
+              curlx_unicodefree(attr);
 #endif
 #endif
               ldap_memfree(attribute);
               ldap_memfree(attribute);
               if(ber)
               if(ber)
@@ -662,7 +662,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
               if(result) {
               if(result) {
                 ldap_value_free_len(vals);
                 ldap_value_free_len(vals);
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-                Curl_unicodefree(attr);
+                curlx_unicodefree(attr);
 #endif
 #endif
                 ldap_memfree(attribute);
                 ldap_memfree(attribute);
                 if(ber)
                 if(ber)
@@ -680,7 +680,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
             if(result) {
             if(result) {
               ldap_value_free_len(vals);
               ldap_value_free_len(vals);
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-              Curl_unicodefree(attr);
+              curlx_unicodefree(attr);
 #endif
 #endif
               ldap_memfree(attribute);
               ldap_memfree(attribute);
               if(ber)
               if(ber)
@@ -696,7 +696,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
           if(result) {
           if(result) {
             ldap_value_free_len(vals);
             ldap_value_free_len(vals);
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-            Curl_unicodefree(attr);
+            curlx_unicodefree(attr);
 #endif
 #endif
             ldap_memfree(attribute);
             ldap_memfree(attribute);
             if(ber)
             if(ber)
@@ -714,7 +714,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
 
 
       /* Free the attribute as we are done with it */
       /* Free the attribute as we are done with it */
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-      Curl_unicodefree(attr);
+      curlx_unicodefree(attr);
 #endif
 #endif
       ldap_memfree(attribute);
       ldap_memfree(attribute);
 
 
@@ -746,7 +746,7 @@ quit:
 #endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
 #endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
 
 
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
-  Curl_unicodefree(host);
+  curlx_unicodefree(host);
 #endif
 #endif
 
 
   /* no data to transfer */
   /* no data to transfer */
@@ -892,10 +892,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 
 
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
     /* Convert the unescaped string to a tchar */
     /* Convert the unescaped string to a tchar */
-    ludp->lud_dn = Curl_convert_UTF8_to_tchar(unescaped);
+    ludp->lud_dn = curlx_convert_UTF8_to_tchar(unescaped);
 
 
     /* Free the unescaped string as we are done with it */
     /* Free the unescaped string as we are done with it */
-    Curl_unicodefree(unescaped);
+    curlx_unicodefree(unescaped);
 
 
     if(!ludp->lud_dn) {
     if(!ludp->lud_dn) {
       rc = LDAP_NO_MEMORY;
       rc = LDAP_NO_MEMORY;
@@ -960,10 +960,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 
 
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
       /* Convert the unescaped string to a tchar */
       /* Convert the unescaped string to a tchar */
-      ludp->lud_attrs[i] = Curl_convert_UTF8_to_tchar(unescaped);
+      ludp->lud_attrs[i] = curlx_convert_UTF8_to_tchar(unescaped);
 
 
       /* Free the unescaped string as we are done with it */
       /* Free the unescaped string as we are done with it */
-      Curl_unicodefree(unescaped);
+      curlx_unicodefree(unescaped);
 
 
       if(!ludp->lud_attrs[i]) {
       if(!ludp->lud_attrs[i]) {
         free(attributes);
         free(attributes);
@@ -1027,10 +1027,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
 
 
 #if defined(USE_WIN32_LDAP)
 #if defined(USE_WIN32_LDAP)
     /* Convert the unescaped string to a tchar */
     /* Convert the unescaped string to a tchar */
-    ludp->lud_filter = Curl_convert_UTF8_to_tchar(unescaped);
+    ludp->lud_filter = curlx_convert_UTF8_to_tchar(unescaped);
 
 
     /* Free the unescaped string as we are done with it */
     /* Free the unescaped string as we are done with it */
-    Curl_unicodefree(unescaped);
+    curlx_unicodefree(unescaped);
 
 
     if(!ludp->lud_filter) {
     if(!ludp->lud_filter) {
       rc = LDAP_NO_MEMORY;
       rc = LDAP_NO_MEMORY;

+ 14 - 7
Utilities/cmcurl/lib/md4.c

@@ -29,6 +29,10 @@
 
 
 #ifdef USE_OPENSSL
 #ifdef USE_OPENSSL
 #include <openssl/opensslconf.h>
 #include <openssl/opensslconf.h>
+#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
+/* OpenSSL 3.0.0 marks the MD4 functions as deprecated */
+#define OPENSSL_NO_MD4
+#endif
 #endif /* USE_OPENSSL */
 #endif /* USE_OPENSSL */
 
 
 #ifdef USE_MBEDTLS
 #ifdef USE_MBEDTLS
@@ -135,10 +139,11 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
 /* The last #include file should be: */
 /* The last #include file should be: */
 #include "memdebug.h"
 #include "memdebug.h"
 
 
-typedef struct {
+struct md4_ctx {
   HCRYPTPROV hCryptProv;
   HCRYPTPROV hCryptProv;
   HCRYPTHASH hHash;
   HCRYPTHASH hHash;
-} MD4_CTX;
+};
+typedef struct md4_ctx MD4_CTX;
 
 
 static void MD4_Init(MD4_CTX *ctx)
 static void MD4_Init(MD4_CTX *ctx)
 {
 {
@@ -146,7 +151,7 @@ static void MD4_Init(MD4_CTX *ctx)
   ctx->hHash = 0;
   ctx->hHash = 0;
 
 
   if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
   if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
-                         CRYPT_VERIFYCONTEXT)) {
+                         CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
     CryptCreateHash(ctx->hCryptProv, CALG_MD4, 0, 0, &ctx->hHash);
     CryptCreateHash(ctx->hCryptProv, CALG_MD4, 0, 0, &ctx->hHash);
   }
   }
 }
 }
@@ -180,10 +185,11 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
 /* The last #include file should be: */
 /* The last #include file should be: */
 #include "memdebug.h"
 #include "memdebug.h"
 
 
-typedef struct {
+struct md4_ctx {
   void *data;
   void *data;
   unsigned long size;
   unsigned long size;
-} MD4_CTX;
+};
+typedef struct md4_ctx MD4_CTX;
 
 
 static void MD4_Init(MD4_CTX *ctx)
 static void MD4_Init(MD4_CTX *ctx)
 {
 {
@@ -262,12 +268,13 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
 /* Any 32-bit or wider unsigned integer data type will do */
 /* Any 32-bit or wider unsigned integer data type will do */
 typedef unsigned int MD4_u32plus;
 typedef unsigned int MD4_u32plus;
 
 
-typedef struct {
+struct md4_ctx {
   MD4_u32plus lo, hi;
   MD4_u32plus lo, hi;
   MD4_u32plus a, b, c, d;
   MD4_u32plus a, b, c, d;
   unsigned char buffer[64];
   unsigned char buffer[64];
   MD4_u32plus block[16];
   MD4_u32plus block[16];
-} MD4_CTX;
+};
+typedef struct md4_ctx MD4_CTX;
 
 
 static void MD4_Init(MD4_CTX *ctx);
 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);

+ 14 - 12
Utilities/cmcurl/lib/md5.c

@@ -179,15 +179,16 @@ static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
 /* The last #include file should be: */
 /* The last #include file should be: */
 #include "memdebug.h"
 #include "memdebug.h"
 
 
-typedef struct {
+struct md5_ctx {
   HCRYPTPROV hCryptProv;
   HCRYPTPROV hCryptProv;
   HCRYPTHASH hHash;
   HCRYPTHASH hHash;
-} MD5_CTX;
+};
+typedef struct md5_ctx MD5_CTX;
 
 
 static void MD5_Init(MD5_CTX *ctx)
 static void MD5_Init(MD5_CTX *ctx)
 {
 {
-  if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL,
-                         PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+  if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_FULL,
+                         CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
     CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash);
     CryptCreateHash(ctx->hCryptProv, CALG_MD5, 0, 0, &ctx->hHash);
   }
   }
 }
 }
@@ -261,12 +262,13 @@ static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
 /* Any 32-bit or wider unsigned integer data type will do */
 /* Any 32-bit or wider unsigned integer data type will do */
 typedef unsigned int MD5_u32plus;
 typedef unsigned int MD5_u32plus;
 
 
-typedef struct {
+struct md5_ctx {
   MD5_u32plus lo, hi;
   MD5_u32plus lo, hi;
   MD5_u32plus a, b, c, d;
   MD5_u32plus a, b, c, d;
   unsigned char buffer[64];
   unsigned char buffer[64];
   MD5_u32plus block[16];
   MD5_u32plus block[16];
-} MD5_CTX;
+};
+typedef struct md5_ctx MD5_CTX;
 
 
 static void MD5_Init(MD5_CTX *ctx);
 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);
@@ -528,7 +530,7 @@ static void MD5_Final(unsigned char *result, MD5_CTX *ctx)
 
 
 #endif /* CRYPTO LIBS */
 #endif /* CRYPTO LIBS */
 
 
-const HMAC_params Curl_HMAC_MD5[] = {
+const struct HMAC_params Curl_HMAC_MD5[] = {
   {
   {
     /* Hash initialization function. */
     /* Hash initialization function. */
     CURLX_FUNCTION_CAST(HMAC_hinit_func, MD5_Init),
     CURLX_FUNCTION_CAST(HMAC_hinit_func, MD5_Init),
@@ -545,7 +547,7 @@ const HMAC_params Curl_HMAC_MD5[] = {
   }
   }
 };
 };
 
 
-const MD5_params Curl_DIGEST_MD5[] = {
+const struct MD5_params Curl_DIGEST_MD5[] = {
   {
   {
     /* Digest initialization function */
     /* Digest initialization function */
     CURLX_FUNCTION_CAST(Curl_MD5_init_func, MD5_Init),
     CURLX_FUNCTION_CAST(Curl_MD5_init_func, MD5_Init),
@@ -573,9 +575,9 @@ void Curl_md5it(unsigned char *outbuffer, const unsigned char *input,
   MD5_Final(outbuffer, &ctx);
   MD5_Final(outbuffer, &ctx);
 }
 }
 
 
-MD5_context *Curl_MD5_init(const MD5_params *md5params)
+struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params)
 {
 {
-  MD5_context *ctxt;
+  struct MD5_context *ctxt;
 
 
   /* Create MD5 context */
   /* Create MD5 context */
   ctxt = malloc(sizeof(*ctxt));
   ctxt = malloc(sizeof(*ctxt));
@@ -597,7 +599,7 @@ MD5_context *Curl_MD5_init(const MD5_params *md5params)
   return ctxt;
   return ctxt;
 }
 }
 
 
-CURLcode Curl_MD5_update(MD5_context *context,
+CURLcode Curl_MD5_update(struct MD5_context *context,
                          const unsigned char *data,
                          const unsigned char *data,
                          unsigned int len)
                          unsigned int len)
 {
 {
@@ -606,7 +608,7 @@ CURLcode Curl_MD5_update(MD5_context *context,
   return CURLE_OK;
   return CURLE_OK;
 }
 }
 
 
-CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result)
+CURLcode Curl_MD5_final(struct 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);
 
 

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

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1998 - 2020, 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
@@ -328,7 +328,7 @@ void curl_dbg_free(void *ptr, int line, const char *source)
     (Curl_cfree)(mem);
     (Curl_cfree)(mem);
   }
   }
 
 
-  if(source)
+  if(source && ptr)
     curl_dbg_log("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
     curl_dbg_log("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
 }
 }
 
 

+ 213 - 65
Utilities/cmcurl/lib/mime.c

@@ -26,6 +26,7 @@
 
 
 #include "mime.h"
 #include "mime.h"
 #include "non-ascii.h"
 #include "non-ascii.h"
+#include "warnless.h"
 #include "urldata.h"
 #include "urldata.h"
 #include "sendf.h"
 #include "sendf.h"
 
 
@@ -52,6 +53,10 @@
 
 
 
 
 #define READ_ERROR                      ((size_t) -1)
 #define READ_ERROR                      ((size_t) -1)
+#define STOP_FILLING                    ((size_t) -2)
+
+static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
+                                 void *instream, bool *hasread);
 
 
 /* Encoders. */
 /* Encoders. */
 static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
 static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
@@ -66,7 +71,7 @@ static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
                               curl_mimepart *part);
                               curl_mimepart *part);
 static curl_off_t encoder_qp_size(curl_mimepart *part);
 static curl_off_t encoder_qp_size(curl_mimepart *part);
 
 
-static const mime_encoder encoders[] = {
+static const struct mime_encoder encoders[] = {
   {"binary", encoder_nop_read, encoder_nop_size},
   {"binary", encoder_nop_read, encoder_nop_size},
   {"8bit", encoder_nop_read, encoder_nop_size},
   {"8bit", encoder_nop_read, encoder_nop_size},
   {"7bit", encoder_7bit_read, encoder_nop_size},
   {"7bit", encoder_7bit_read, encoder_nop_size},
@@ -264,7 +269,8 @@ static char *Curl_basename(char *path)
 
 
 
 
 /* Set readback state. */
 /* Set readback state. */
-static void mimesetstate(mime_state *state, enum mimestate tok, void *ptr)
+static void mimesetstate(struct mime_state *state,
+                         enum mimestate tok, void *ptr)
 {
 {
   state->state = tok;
   state->state = tok;
   state->ptr = ptr;
   state->ptr = ptr;
@@ -337,7 +343,7 @@ static char *strippath(const char *fullfile)
 }
 }
 
 
 /* Initialize data encoder state. */
 /* Initialize data encoder state. */
-static void cleanup_encoder_state(mime_encoder_state *p)
+static void cleanup_encoder_state(struct mime_encoder_state *p)
 {
 {
   p->pos = 0;
   p->pos = 0;
   p->bufbeg = 0;
   p->bufbeg = 0;
@@ -347,17 +353,22 @@ static void cleanup_encoder_state(mime_encoder_state *p)
 
 
 /* Dummy encoder. This is used for 8bit and binary content encodings. */
 /* Dummy encoder. This is used for 8bit and binary content encodings. */
 static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
 static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
-                               curl_mimepart *part)
+                               struct curl_mimepart *part)
 {
 {
-  mime_encoder_state *st = &part->encstate;
+  struct mime_encoder_state *st = &part->encstate;
   size_t insize = st->bufend - st->bufbeg;
   size_t insize = st->bufend - st->bufbeg;
 
 
   (void) ateof;
   (void) ateof;
 
 
+  if(!size)
+    return STOP_FILLING;
+
   if(size > insize)
   if(size > insize)
     size = insize;
     size = insize;
+
   if(size)
   if(size)
-    memcpy(buffer, st->buf, size);
+    memcpy(buffer, st->buf + st->bufbeg, size);
+
   st->bufbeg += size;
   st->bufbeg += size;
   return size;
   return size;
 }
 }
@@ -372,11 +383,14 @@ static curl_off_t encoder_nop_size(curl_mimepart *part)
 static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof,
 static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof,
                                 curl_mimepart *part)
                                 curl_mimepart *part)
 {
 {
-  mime_encoder_state *st = &part->encstate;
+  struct mime_encoder_state *st = &part->encstate;
   size_t cursize = st->bufend - st->bufbeg;
   size_t cursize = st->bufend - st->bufbeg;
 
 
   (void) ateof;
   (void) ateof;
 
 
+  if(!size)
+    return STOP_FILLING;
+
   if(size > cursize)
   if(size > cursize)
     size = cursize;
     size = cursize;
 
 
@@ -395,7 +409,7 @@ static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof,
 static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
 static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
                                 curl_mimepart *part)
                                 curl_mimepart *part)
 {
 {
-  mime_encoder_state *st = &part->encstate;
+  struct mime_encoder_state *st = &part->encstate;
   size_t cursize = 0;
   size_t cursize = 0;
   int i;
   int i;
   char *ptr = buffer;
   char *ptr = buffer;
@@ -404,8 +418,11 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
     /* Line full ? */
     /* Line full ? */
     if(st->pos > MAX_ENCODED_LINE_LENGTH - 4) {
     if(st->pos > MAX_ENCODED_LINE_LENGTH - 4) {
       /* Yes, we need 2 characters for CRLF. */
       /* Yes, we need 2 characters for CRLF. */
-      if(size < 2)
+      if(size < 2) {
+        if(!cursize)
+          return STOP_FILLING;
         break;
         break;
+      }
       *ptr++ = '\r';
       *ptr++ = '\r';
       *ptr++ = '\n';
       *ptr++ = '\n';
       st->pos = 0;
       st->pos = 0;
@@ -414,7 +431,12 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
     }
     }
 
 
     /* Be sure there is enough space and input data for a base64 group. */
     /* Be sure there is enough space and input data for a base64 group. */
-    if(size < 4 || st->bufend - st->bufbeg < 3)
+    if(size < 4) {
+      if(!cursize)
+        return STOP_FILLING;
+      break;
+    }
+    if(st->bufend - st->bufbeg < 3)
       break;
       break;
 
 
     /* Encode three bytes as four characters. */
     /* Encode three bytes as four characters. */
@@ -431,25 +453,31 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
   }
   }
 
 
   /* If at eof, we have to flush the buffered data. */
   /* If at eof, we have to flush the buffered data. */
-  if(ateof && size >= 4) {
-    /* Buffered data size can only be 0, 1 or 2. */
-    ptr[2] = ptr[3] = '=';
-    i = 0;
-    switch(st->bufend - st->bufbeg) {
-    case 2:
-      i = (st->buf[st->bufbeg + 1] & 0xFF) << 8;
-      /* FALLTHROUGH */
-    case 1:
-      i |= (st->buf[st->bufbeg] & 0xFF) << 16;
-      ptr[0] = base64[(i >> 18) & 0x3F];
-      ptr[1] = base64[(i >> 12) & 0x3F];
-      if(++st->bufbeg != st->bufend) {
-        ptr[2] = base64[(i >> 6) & 0x3F];
-        st->bufbeg++;
+  if(ateof) {
+    if(size < 4) {
+      if(!cursize)
+        return STOP_FILLING;
+    }
+    else {
+      /* Buffered data size can only be 0, 1 or 2. */
+      ptr[2] = ptr[3] = '=';
+      i = 0;
+      switch(st->bufend - st->bufbeg) {
+      case 2:
+        i = (st->buf[st->bufbeg + 1] & 0xFF) << 8;
+        /* FALLTHROUGH */
+      case 1:
+        i |= (st->buf[st->bufbeg] & 0xFF) << 16;
+        ptr[0] = base64[(i >> 18) & 0x3F];
+        ptr[1] = base64[(i >> 12) & 0x3F];
+        if(++st->bufbeg != st->bufend) {
+          ptr[2] = base64[(i >> 6) & 0x3F];
+          st->bufbeg++;
+        }
+        cursize += 4;
+        st->pos += 4;
+        break;
       }
       }
-      cursize += 4;
-      st->pos += 4;
-      break;
     }
     }
   }
   }
 
 
@@ -485,7 +513,7 @@ static curl_off_t encoder_base64_size(curl_mimepart *part)
  * Check if a CRLF or end of data is in input buffer at current position + n.
  * Check if a CRLF or end of data is in input buffer at current position + n.
  * Return -1 if more data needed, 1 if CRLF or end of data, else 0.
  * Return -1 if more data needed, 1 if CRLF or end of data, else 0.
  */
  */
-static int qp_lookahead_eol(mime_encoder_state *st, int ateof, size_t n)
+static int qp_lookahead_eol(struct mime_encoder_state *st, int ateof, size_t n)
 {
 {
   n += st->bufbeg;
   n += st->bufbeg;
   if(n >= st->bufend && ateof)
   if(n >= st->bufend && ateof)
@@ -502,7 +530,7 @@ static int qp_lookahead_eol(mime_encoder_state *st, int ateof, size_t n)
 static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
 static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
                               curl_mimepart *part)
                               curl_mimepart *part)
 {
 {
-  mime_encoder_state *st = &part->encstate;
+  struct mime_encoder_state *st = &part->encstate;
   char *ptr = buffer;
   char *ptr = buffer;
   size_t cursize = 0;
   size_t cursize = 0;
   int softlinebreak;
   int softlinebreak;
@@ -567,7 +595,6 @@ static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
         switch(qp_lookahead_eol(st, ateof, consumed)) {
         switch(qp_lookahead_eol(st, ateof, consumed)) {
         case -1:        /* Need more data. */
         case -1:        /* Need more data. */
           return cursize;
           return cursize;
-          break;
         case 0:         /* Not followed by a CRLF. */
         case 0:         /* Not followed by a CRLF. */
           softlinebreak = 1;
           softlinebreak = 1;
           break;
           break;
@@ -581,8 +608,11 @@ static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
     }
     }
 
 
     /* If the output buffer would overflow, do not store. */
     /* If the output buffer would overflow, do not store. */
-    if(len > size)
+    if(len > size) {
+      if(!cursize)
+        return STOP_FILLING;
       break;
       break;
+    }
 
 
     /* Append to output buffer. */
     /* Append to output buffer. */
     memcpy(ptr, buf, len);
     memcpy(ptr, buf, len);
@@ -612,16 +642,18 @@ static size_t mime_mem_read(char *buffer, size_t size, size_t nitems,
                             void *instream)
                             void *instream)
 {
 {
   curl_mimepart *part = (curl_mimepart *) instream;
   curl_mimepart *part = (curl_mimepart *) instream;
-  size_t sz = (size_t) part->datasize - part->state.offset;
+  size_t sz = curlx_sotouz(part->datasize - part->state.offset);
   (void) size;   /* Always 1.*/
   (void) size;   /* Always 1.*/
 
 
+  if(!nitems)
+    return STOP_FILLING;
+
   if(sz > nitems)
   if(sz > nitems)
     sz = nitems;
     sz = nitems;
 
 
   if(sz)
   if(sz)
-    memcpy(buffer, (char *) &part->data[part->state.offset], sz);
+    memcpy(buffer, part->data + curlx_sotouz(part->state.offset), sz);
 
 
-  part->state.offset += sz;
   return sz;
   return sz;
 }
 }
 
 
@@ -641,7 +673,7 @@ static int mime_mem_seek(void *instream, curl_off_t offset, int whence)
   if(offset < 0 || offset > part->datasize)
   if(offset < 0 || offset > part->datasize)
     return CURL_SEEKFUNC_FAIL;
     return CURL_SEEKFUNC_FAIL;
 
 
-  part->state.offset = (size_t) offset;
+  part->state.offset = offset;
   return CURL_SEEKFUNC_OK;
   return CURL_SEEKFUNC_OK;
 }
 }
 
 
@@ -653,7 +685,7 @@ static void mime_mem_free(void *ptr)
 
 
 /* Named file callbacks. */
 /* Named file callbacks. */
 /* Argument is a pointer to the mime part. */
 /* Argument is a pointer to the mime part. */
-static int mime_open_file(curl_mimepart * part)
+static int mime_open_file(curl_mimepart *part)
 {
 {
   /* Open a MIMEKIND_FILE part. */
   /* Open a MIMEKIND_FILE part. */
 
 
@@ -668,6 +700,9 @@ static size_t mime_file_read(char *buffer, size_t size, size_t nitems,
 {
 {
   curl_mimepart *part = (curl_mimepart *) instream;
   curl_mimepart *part = (curl_mimepart *) instream;
 
 
+  if(!nitems)
+    return STOP_FILLING;
+
   if(mime_open_file(part))
   if(mime_open_file(part))
     return READ_ERROR;
     return READ_ERROR;
 
 
@@ -705,21 +740,22 @@ static void mime_file_free(void *ptr)
 /* Argument is a pointer to the mime structure. */
 /* Argument is a pointer to the mime structure. */
 
 
 /* Readback a byte string segment. */
 /* Readback a byte string segment. */
-static size_t readback_bytes(mime_state *state,
+static size_t readback_bytes(struct mime_state *state,
                              char *buffer, size_t bufsize,
                              char *buffer, size_t bufsize,
                              const char *bytes, size_t numbytes,
                              const char *bytes, size_t numbytes,
                              const char *trail)
                              const char *trail)
 {
 {
   size_t sz;
   size_t sz;
+  size_t offset = curlx_sotouz(state->offset);
 
 
-  if(numbytes > state->offset) {
-    sz = numbytes - state->offset;
-    bytes += state->offset;
+  if(numbytes > offset) {
+    sz = numbytes - offset;
+    bytes += offset;
   }
   }
   else {
   else {
     size_t tsz = strlen(trail);
     size_t tsz = strlen(trail);
 
 
-    sz = state->offset - numbytes;
+    sz = offset - numbytes;
     if(sz >= tsz)
     if(sz >= tsz)
       return 0;
       return 0;
     bytes = trail + sz;
     bytes = trail + sz;
@@ -736,25 +772,79 @@ static size_t readback_bytes(mime_state *state,
 
 
 /* Read a non-encoded part content. */
 /* Read a non-encoded part content. */
 static size_t read_part_content(curl_mimepart *part,
 static size_t read_part_content(curl_mimepart *part,
-                                char *buffer, size_t bufsize)
+                                char *buffer, size_t bufsize, bool *hasread)
 {
 {
   size_t sz = 0;
   size_t sz = 0;
 
 
-  if(part->readfunc)
-    sz = part->readfunc(buffer, 1, bufsize, part->arg);
+  switch(part->lastreadstatus) {
+  case 0:
+  case CURL_READFUNC_ABORT:
+  case CURL_READFUNC_PAUSE:
+  case READ_ERROR:
+    return part->lastreadstatus;
+  default:
+    break;
+  }
+
+  /* If we can determine we are at end of part data, spare a read. */
+  if(part->datasize != (curl_off_t) -1 &&
+     part->state.offset >= part->datasize) {
+    /* sz is already zero. */
+  }
+  else {
+    switch(part->kind) {
+    case MIMEKIND_MULTIPART:
+      /*
+       * Cannot be processed as other kinds since read function requires
+       * an additional parameter and is highly recursive.
+       */
+       sz = mime_subparts_read(buffer, 1, bufsize, part->arg, hasread);
+       break;
+    case MIMEKIND_FILE:
+      if(part->fp && feof(part->fp))
+        break;  /* At EOF. */
+      /* FALLTHROUGH */
+    default:
+      if(part->readfunc) {
+        if(!(part->flags & MIME_FAST_READ)) {
+          if(*hasread)
+            return STOP_FILLING;
+          *hasread = TRUE;
+        }
+        sz = part->readfunc(buffer, 1, bufsize, part->arg);
+      }
+      break;
+    }
+  }
+
+  switch(sz) {
+  case STOP_FILLING:
+    break;
+  case 0:
+  case CURL_READFUNC_ABORT:
+  case CURL_READFUNC_PAUSE:
+  case READ_ERROR:
+    part->lastreadstatus = sz;
+    break;
+  default:
+    part->state.offset += sz;
+    part->lastreadstatus = sz;
+    break;
+  }
+
   return sz;
   return sz;
 }
 }
 
 
 /* Read and encode part content. */
 /* Read and encode part content. */
-static size_t read_encoded_part_content(curl_mimepart *part,
-                                        char *buffer, size_t bufsize)
+static size_t read_encoded_part_content(curl_mimepart *part, char *buffer,
+                                        size_t bufsize, bool *hasread)
 {
 {
-  mime_encoder_state *st = &part->encstate;
+  struct mime_encoder_state *st = &part->encstate;
   size_t cursize = 0;
   size_t cursize = 0;
   size_t sz;
   size_t sz;
   bool ateof = FALSE;
   bool ateof = FALSE;
 
 
-  while(bufsize) {
+  for(;;) {
     if(st->bufbeg < st->bufend || ateof) {
     if(st->bufbeg < st->bufend || ateof) {
       /* Encode buffered data. */
       /* Encode buffered data. */
       sz = part->encoder->encodefunc(buffer, bufsize, ateof, part);
       sz = part->encoder->encodefunc(buffer, bufsize, ateof, part);
@@ -763,9 +853,8 @@ static size_t read_encoded_part_content(curl_mimepart *part,
         if(ateof)
         if(ateof)
           return cursize;
           return cursize;
         break;
         break;
-      case CURL_READFUNC_ABORT:
-      case CURL_READFUNC_PAUSE:
       case READ_ERROR:
       case READ_ERROR:
+      case STOP_FILLING:
         return cursize? cursize: sz;
         return cursize? cursize: sz;
       default:
       default:
         cursize += sz;
         cursize += sz;
@@ -787,7 +876,7 @@ static size_t read_encoded_part_content(curl_mimepart *part,
     if(st->bufend >= sizeof(st->buf))
     if(st->bufend >= sizeof(st->buf))
       return cursize? cursize: READ_ERROR;    /* Buffer full. */
       return cursize? cursize: READ_ERROR;    /* Buffer full. */
     sz = read_part_content(part, st->buf + st->bufend,
     sz = read_part_content(part, st->buf + st->bufend,
-                           sizeof(st->buf) - st->bufend);
+                           sizeof(st->buf) - st->bufend, hasread);
     switch(sz) {
     switch(sz) {
     case 0:
     case 0:
       ateof = TRUE;
       ateof = TRUE;
@@ -795,6 +884,7 @@ static size_t read_encoded_part_content(curl_mimepart *part,
     case CURL_READFUNC_ABORT:
     case CURL_READFUNC_ABORT:
     case CURL_READFUNC_PAUSE:
     case CURL_READFUNC_PAUSE:
     case READ_ERROR:
     case READ_ERROR:
+    case STOP_FILLING:
       return cursize? cursize: sz;
       return cursize? cursize: sz;
     default:
     default:
       st->bufend += sz;
       st->bufend += sz;
@@ -802,12 +892,12 @@ static size_t read_encoded_part_content(curl_mimepart *part,
     }
     }
   }
   }
 
 
-  return cursize;
+  /* NOTREACHED */
 }
 }
 
 
 /* Readback a mime part. */
 /* Readback a mime part. */
 static size_t readback_part(curl_mimepart *part,
 static size_t readback_part(curl_mimepart *part,
-                            char *buffer, size_t bufsize)
+                            char *buffer, size_t bufsize, bool *hasread)
 {
 {
   size_t cursize = 0;
   size_t cursize = 0;
 #ifdef CURL_DOES_CONVERSIONS
 #ifdef CURL_DOES_CONVERSIONS
@@ -866,9 +956,9 @@ static size_t readback_part(curl_mimepart *part,
       break;
       break;
     case MIMESTATE_CONTENT:
     case MIMESTATE_CONTENT:
       if(part->encoder)
       if(part->encoder)
-        sz = read_encoded_part_content(part, buffer, bufsize);
+        sz = read_encoded_part_content(part, buffer, bufsize, hasread);
       else
       else
-        sz = read_part_content(part, buffer, bufsize);
+        sz = read_part_content(part, buffer, bufsize, hasread);
       switch(sz) {
       switch(sz) {
       case 0:
       case 0:
         mimesetstate(&part->state, MIMESTATE_END, NULL);
         mimesetstate(&part->state, MIMESTATE_END, NULL);
@@ -881,6 +971,7 @@ static size_t readback_part(curl_mimepart *part,
       case CURL_READFUNC_ABORT:
       case CURL_READFUNC_ABORT:
       case CURL_READFUNC_PAUSE:
       case CURL_READFUNC_PAUSE:
       case READ_ERROR:
       case READ_ERROR:
+      case STOP_FILLING:
         return cursize? cursize: sz;
         return cursize? cursize: sz;
       }
       }
       break;
       break;
@@ -909,9 +1000,9 @@ static size_t readback_part(curl_mimepart *part,
   return cursize;
   return cursize;
 }
 }
 
 
-/* Readback from mime. */
+/* Readback from mime. Warning: not a read callback function. */
 static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
 static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
-                                 void *instream)
+                                 void *instream, bool *hasread)
 {
 {
   curl_mime *mime = (curl_mime *) instream;
   curl_mime *mime = (curl_mime *) instream;
   size_t cursize = 0;
   size_t cursize = 0;
@@ -932,7 +1023,7 @@ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
 #endif
 #endif
       mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, mime->firstpart);
       mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, mime->firstpart);
       /* The first boundary always follows the header termination empty line,
       /* The first boundary always follows the header termination empty line,
-         so is always preceded by a CRLK. We can then spare 2 characters
+         so is always preceded by a CRLF. We can then spare 2 characters
          by skipping the leading CRLF in boundary. */
          by skipping the leading CRLF in boundary. */
       mime->state.offset += 2;
       mime->state.offset += 2;
       break;
       break;
@@ -962,11 +1053,12 @@ static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
         mimesetstate(&mime->state, MIMESTATE_END, NULL);
         mimesetstate(&mime->state, MIMESTATE_END, NULL);
         break;
         break;
       }
       }
-      sz = readback_part(part, buffer, nitems);
+      sz = readback_part(part, buffer, nitems, hasread);
       switch(sz) {
       switch(sz) {
       case CURL_READFUNC_ABORT:
       case CURL_READFUNC_ABORT:
       case CURL_READFUNC_PAUSE:
       case CURL_READFUNC_PAUSE:
       case READ_ERROR:
       case READ_ERROR:
+      case STOP_FILLING:
         return cursize? cursize: sz;
         return cursize? cursize: sz;
       case 0:
       case 0:
 #ifdef CURL_DOES_CONVERSIONS
 #ifdef CURL_DOES_CONVERSIONS
@@ -1031,6 +1123,7 @@ static int mime_part_rewind(curl_mimepart *part)
   if(res == CURL_SEEKFUNC_OK)
   if(res == CURL_SEEKFUNC_OK)
     mimesetstate(&part->state, targetstate, NULL);
     mimesetstate(&part->state, targetstate, NULL);
 
 
+  part->lastreadstatus = 1; /* Successful read status. */
   return res;
   return res;
 }
 }
 
 
@@ -1073,6 +1166,8 @@ static void cleanup_part_content(curl_mimepart *part)
   part->datasize = (curl_off_t) 0;    /* No size yet. */
   part->datasize = (curl_off_t) 0;    /* No size yet. */
   cleanup_encoder_state(&part->encstate);
   cleanup_encoder_state(&part->encstate);
   part->kind = MIMEKIND_NONE;
   part->kind = MIMEKIND_NONE;
+  part->flags &= ~MIME_FAST_READ;
+  part->lastreadstatus = 1; /* Successful read status. */
 }
 }
 
 
 static void mime_subparts_free(void *ptr)
 static void mime_subparts_free(void *ptr)
@@ -1238,6 +1333,7 @@ void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
 {
 {
   memset((char *) part, 0, sizeof(*part));
   memset((char *) part, 0, sizeof(*part));
   part->easy = easy;
   part->easy = easy;
+  part->lastreadstatus = 1; /* Successful read status. */
   mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
   mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
 }
 }
 
 
@@ -1328,6 +1424,7 @@ CURLcode curl_mime_data(curl_mimepart *part,
     part->readfunc = mime_mem_read;
     part->readfunc = mime_mem_read;
     part->seekfunc = mime_mem_seek;
     part->seekfunc = mime_mem_seek;
     part->freefunc = mime_mem_free;
     part->freefunc = mime_mem_free;
+    part->flags |= MIME_FAST_READ;
     part->kind = MIMEKIND_DATA;
     part->kind = MIMEKIND_DATA;
   }
   }
 
 
@@ -1405,7 +1502,7 @@ CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype)
 CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding)
 CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding)
 {
 {
   CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
   CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
-  const mime_encoder *mep;
+  const struct mime_encoder *mep;
 
 
   if(!part)
   if(!part)
     return result;
     return result;
@@ -1502,7 +1599,7 @@ CURLcode Curl_mime_set_subparts(curl_mimepart *part,
     }
     }
 
 
     subparts->parent = part;
     subparts->parent = part;
-    part->readfunc = mime_subparts_read;
+    /* Subparts are processed internally: no read callback. */
     part->seekfunc = mime_subparts_seek;
     part->seekfunc = mime_subparts_seek;
     part->freefunc = take_ownership? mime_subparts_free: mime_subparts_unbind;
     part->freefunc = take_ownership? mime_subparts_free: mime_subparts_unbind;
     part->arg = subparts;
     part->arg = subparts;
@@ -1524,9 +1621,23 @@ CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts)
 size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
 size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
 {
 {
   curl_mimepart *part = (curl_mimepart *) instream;
   curl_mimepart *part = (curl_mimepart *) instream;
+  size_t ret;
+  bool hasread;
 
 
   (void) size;   /* Always 1. */
   (void) size;   /* Always 1. */
-  return readback_part(part, buffer, nitems);
+
+  do {
+    hasread = FALSE;
+    ret = readback_part(part, buffer, nitems, &hasread);
+    /*
+     * If this is not possible to get some data without calling more than
+     * one read callback (probably because a content encoder is not able to
+     * deliver a new bunch for the few data accumulated so far), force another
+     * read until we get enough data or a special exit code.
+     */
+  } while(ret == STOP_FILLING);
+
+  return ret;
 }
 }
 
 
 /* Rewind mime stream. */
 /* Rewind mime stream. */
@@ -1667,6 +1778,23 @@ const char *Curl_mime_contenttype(const char *filename)
   return NULL;
   return NULL;
 }
 }
 
 
+static bool content_type_match(const char *contenttype, const char *target)
+{
+  size_t len = strlen(target);
+
+  if(contenttype && strncasecompare(contenttype, target, len))
+    switch(contenttype[len]) {
+    case '\0':
+    case '\t':
+    case '\r':
+    case '\n':
+    case ' ':
+    case ';':
+      return TRUE;
+    }
+  return FALSE;
+}
+
 CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
 CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
                                    const char *contenttype,
                                    const char *contenttype,
                                    const char *disposition,
                                    const char *disposition,
@@ -1718,7 +1846,7 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
       boundary = mime->boundary;
       boundary = mime->boundary;
   }
   }
   else if(contenttype && !customct &&
   else if(contenttype && !customct &&
-          strcasecompare(contenttype, "text/plain"))
+          content_type_match(contenttype, "text/plain"))
     if(strategy == MIMESTRATEGY_MAIL || !part->filename)
     if(strategy == MIMESTRATEGY_MAIL || !part->filename)
       contenttype = NULL;
       contenttype = NULL;
 
 
@@ -1794,7 +1922,7 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
     curl_mimepart *subpart;
     curl_mimepart *subpart;
 
 
     disposition = NULL;
     disposition = NULL;
-    if(strcasecompare(contenttype, "multipart/form-data"))
+    if(content_type_match(contenttype, "multipart/form-data"))
       disposition = "form-data";
       disposition = "form-data";
     for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) {
     for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) {
       ret = Curl_mime_prepare_headers(subpart, NULL, disposition, strategy);
       ret = Curl_mime_prepare_headers(subpart, NULL, disposition, strategy);
@@ -1805,6 +1933,26 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
   return ret;
   return ret;
 }
 }
 
 
+/* Recursively reset paused status in the given part. */
+void Curl_mime_unpause(curl_mimepart *part)
+{
+  if(part) {
+    if(part->lastreadstatus == CURL_READFUNC_PAUSE)
+      part->lastreadstatus = 1; /* Successful read status. */
+    if(part->kind == MIMEKIND_MULTIPART) {
+      curl_mime *mime = (curl_mime *) part->arg;
+
+      if(mime) {
+        curl_mimepart *subpart;
+
+        for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart)
+          Curl_mime_unpause(subpart);
+      }
+    }
+  }
+}
+
+
 #else /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
 #else /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
 
 
 /* Mime not compiled in: define stubs for externally-referenced functions. */
 /* Mime not compiled in: define stubs for externally-referenced functions. */

+ 27 - 21
Utilities/cmcurl/lib/mime.h

@@ -31,6 +31,7 @@
 /* Part flags. */
 /* Part flags. */
 #define MIME_USERHEADERS_OWNER  (1 << 0)
 #define MIME_USERHEADERS_OWNER  (1 << 0)
 #define MIME_BODY_ONLY          (1 << 1)
 #define MIME_BODY_ONLY          (1 << 1)
+#define MIME_FAST_READ          (1 << 2)
 
 
 #define FILE_CONTENTTYPE_DEFAULT        "application/octet-stream"
 #define FILE_CONTENTTYPE_DEFAULT        "application/octet-stream"
 #define MULTIPART_CONTENTTYPE_DEFAULT   "multipart/mixed"
 #define MULTIPART_CONTENTTYPE_DEFAULT   "multipart/mixed"
@@ -68,43 +69,43 @@ enum mimestrategy {
 };
 };
 
 
 /* Content transfer encoder. */
 /* Content transfer encoder. */
-typedef struct {
+struct mime_encoder {
   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;
+};
 
 
 /* Content transfer encoder state. */
 /* Content transfer encoder state. */
-typedef struct {
+struct mime_encoder_state {
   size_t         pos;           /* Position on output line. */
   size_t         pos;           /* Position on output line. */
   size_t         bufbeg;        /* Next data index in input buffer. */
   size_t         bufbeg;        /* Next data index in input buffer. */
   size_t         bufend;        /* First unused byte index in input buffer. */
   size_t         bufend;        /* First unused byte index in input buffer. */
   char           buf[ENCODING_BUFFER_SIZE]; /* Input buffer. */
   char           buf[ENCODING_BUFFER_SIZE]; /* Input buffer. */
-}  mime_encoder_state;
+};
 
 
 /* Mime readback state. */
 /* Mime readback state. */
-typedef struct {
+struct mime_state {
   enum mimestate state;       /* Current state token. */
   enum mimestate state;       /* Current state token. */
   void *ptr;                  /* State-dependent pointer. */
   void *ptr;                  /* State-dependent pointer. */
-  size_t offset;              /* State-dependent offset. */
-}  mime_state;
+  curl_off_t offset;          /* State-dependent offset. */
+};
 
 
 /* minimum buffer size for the boundary string */
 /* minimum buffer size for the boundary string */
 #define MIME_BOUNDARY_LEN (24 + MIME_RAND_BOUNDARY_CHARS + 1)
 #define MIME_BOUNDARY_LEN (24 + MIME_RAND_BOUNDARY_CHARS + 1)
 
 
 /* A mime multipart. */
 /* A mime multipart. */
-struct curl_mime_s {
+struct curl_mime {
   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[MIME_BOUNDARY_LEN]; /* The part boundary. */
   char boundary[MIME_BOUNDARY_LEN]; /* The part boundary. */
-  mime_state state;                /* Current readback state. */
+  struct mime_state state;         /* Current readback state. */
 };
 };
 
 
 /* A mime part. */
 /* A mime part. */
-struct curl_mimepart_s {
+struct curl_mimepart {
   struct Curl_easy *easy;          /* The associated easy handle. */
   struct Curl_easy *easy;          /* The associated easy handle. */
   curl_mime *parent;               /* Parent mime structure. */
   curl_mime *parent;               /* Parent mime structure. */
   curl_mimepart *nextpart;         /* Forward linked list. */
   curl_mimepart *nextpart;         /* Forward linked list. */
@@ -122,9 +123,10 @@ struct curl_mimepart_s {
   char *name;                      /* Data name. */
   char *name;                      /* Data name. */
   curl_off_t datasize;             /* Expected data size. */
   curl_off_t datasize;             /* Expected data size. */
   unsigned int flags;              /* Flags. */
   unsigned int flags;              /* Flags. */
-  mime_state state;                /* Current readback state. */
-  const mime_encoder *encoder;     /* Content data encoder. */
-  mime_encoder_state encstate;     /* Data encoder state. */
+  struct mime_state state;         /* Current readback state. */
+  const struct mime_encoder *encoder; /* Content data encoder. */
+  struct mime_encoder_state encstate; /* Data encoder state. */
+  size_t lastreadstatus;           /* Last read callback returned status. */
 };
 };
 
 
 CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
 CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
@@ -133,20 +135,23 @@ CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
   !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
   !defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
 
 
 /* Prototypes. */
 /* Prototypes. */
-void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy);
-void Curl_mime_cleanpart(curl_mimepart *part);
-CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src);
-CURLcode Curl_mime_set_subparts(curl_mimepart *part,
-                                curl_mime *subparts, int take_ownership);
-CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
+void Curl_mime_initpart(struct curl_mimepart *part, struct Curl_easy *easy);
+void Curl_mime_cleanpart(struct curl_mimepart *part);
+CURLcode Curl_mime_duppart(struct curl_mimepart *dst,
+                           const curl_mimepart *src);
+CURLcode Curl_mime_set_subparts(struct curl_mimepart *part,
+                                struct curl_mime *subparts,
+                                int take_ownership);
+CURLcode Curl_mime_prepare_headers(struct curl_mimepart *part,
                                    const char *contenttype,
                                    const char *contenttype,
                                    const char *disposition,
                                    const char *disposition,
                                    enum mimestrategy strategy);
                                    enum mimestrategy strategy);
-curl_off_t Curl_mime_size(curl_mimepart *part);
+curl_off_t Curl_mime_size(struct curl_mimepart *part);
 size_t Curl_mime_read(char *buffer, size_t size, size_t nitems,
 size_t Curl_mime_read(char *buffer, size_t size, size_t nitems,
                       void *instream);
                       void *instream);
-CURLcode Curl_mime_rewind(curl_mimepart *part);
+CURLcode Curl_mime_rewind(struct curl_mimepart *part);
 const char *Curl_mime_contenttype(const char *filename);
 const char *Curl_mime_contenttype(const char *filename);
+void Curl_mime_unpause(struct curl_mimepart *part);
 
 
 #else
 #else
 /* if disabled */
 /* if disabled */
@@ -158,6 +163,7 @@ const char *Curl_mime_contenttype(const char *filename);
 #define Curl_mime_size(x) (curl_off_t) -1
 #define Curl_mime_size(x) (curl_off_t) -1
 #define Curl_mime_read NULL
 #define Curl_mime_read NULL
 #define Curl_mime_rewind(x) ((void)x, CURLE_NOT_BUILT_IN)
 #define Curl_mime_rewind(x) ((void)x, CURLE_NOT_BUILT_IN)
+#define Curl_mime_unpause(x)
 #endif
 #endif
 
 
 
 

+ 22 - 63
Utilities/cmcurl/lib/mprintf.c

@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *                             \___|\___/|_| \_\_____|
  *
  *
- * Copyright (C) 1999 - 2019, Daniel Stenberg, <[email protected]>, et al.
+ * Copyright (C) 1999 - 2020, 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
@@ -36,6 +36,7 @@
  */
  */
 
 
 #include "curl_setup.h"
 #include "curl_setup.h"
+#include "dynbuf.h"
 #include <curl/mprintf.h>
 #include <curl/mprintf.h>
 
 
 #include "curl_memory.h"
 #include "curl_memory.h"
@@ -145,7 +146,7 @@ enum {
   FLAGS_FLOATG     = 1<<19  /* %g or %G */
   FLAGS_FLOATG     = 1<<19  /* %g or %G */
 };
 };
 
 
-typedef struct {
+struct va_stack {
   FormatType type;
   FormatType type;
   int flags;
   int flags;
   long width;     /* width OR width parameter number */
   long width;     /* width OR width parameter number */
@@ -159,7 +160,7 @@ typedef struct {
     } num;
     } num;
     double dnum;
     double dnum;
   } data;
   } data;
-} va_stack_t;
+};
 
 
 struct nsprintf {
 struct nsprintf {
   char *buffer;
   char *buffer;
@@ -168,11 +169,9 @@ struct nsprintf {
 };
 };
 
 
 struct asprintf {
 struct asprintf {
-  char *buffer; /* allocated buffer */
-  size_t len;   /* length of string */
-  size_t alloc; /* length of alloc */
-  int fail;     /* (!= 0) if an alloc has failed and thus
-                   the output is not the complete data */
+  struct dynbuf b;
+  bool fail; /* if an alloc has failed and thus the output is not the complete
+                data */
 };
 };
 
 
 static long dprintf_DollarString(char *input, char **end)
 static long dprintf_DollarString(char *input, char **end)
@@ -224,8 +223,8 @@ static bool dprintf_IsQualifierNoDollar(const char *fmt)
  *
  *
  ******************************************************************/
  ******************************************************************/
 
 
-static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
-                         va_list arglist)
+static int dprintf_Pass1(const char *format, struct va_stack *vto,
+                         char **endpos, va_list arglist)
 {
 {
   char *fmt = (char *)format;
   char *fmt = (char *)format;
   int param_num = 0;
   int param_num = 0;
@@ -571,13 +570,11 @@ static int dprintf_formatf(
   long param; /* current parameter to read */
   long param; /* current parameter to read */
   long param_num = 0; /* parameter counter */
   long param_num = 0; /* parameter counter */
 
 
-  va_stack_t vto[MAX_PARAMETERS];
+  struct va_stack vto[MAX_PARAMETERS];
   char *endpos[MAX_PARAMETERS];
   char *endpos[MAX_PARAMETERS];
   char **end;
   char **end;
-
   char work[BUFFSIZE];
   char work[BUFFSIZE];
-
-  va_stack_t *p;
+  struct va_stack *p;
 
 
   /* 'workend' points to the final buffer byte position, but with an extra
   /* 'workend' points to the final buffer byte position, but with an extra
      byte as margin to avoid the (false?) warning Coverity gives us
      byte as margin to avoid the (false?) warning Coverity gives us
@@ -1031,35 +1028,10 @@ static int alloc_addbyter(int output, FILE *data)
   struct asprintf *infop = (struct asprintf *)data;
   struct asprintf *infop = (struct asprintf *)data;
   unsigned char outc = (unsigned char)output;
   unsigned char outc = (unsigned char)output;
 
 
-  if(!infop->buffer) {
-    infop->buffer = malloc(32);
-    if(!infop->buffer) {
-      infop->fail = 1;
-      return -1; /* fail */
-    }
-    infop->alloc = 32;
-    infop->len = 0;
-  }
-  else if(infop->len + 1 >= infop->alloc) {
-    char *newptr = NULL;
-    size_t newsize = infop->alloc*2;
-
-    /* detect wrap-around or other overflow problems */
-    if(newsize > infop->alloc)
-      newptr = realloc(infop->buffer, newsize);
-
-    if(!newptr) {
-      infop->fail = 1;
-      return -1; /* fail */
-    }
-    infop->buffer = newptr;
-    infop->alloc = newsize;
+  if(Curl_dyn_addn(&infop->b, &outc, 1)) {
+    infop->fail = 1;
+    return -1; /* fail */
   }
   }
-
-  infop->buffer[ infop->len ] = outc;
-
-  infop->len++;
-
   return outc; /* fputc() returns like this on success */
   return outc; /* fputc() returns like this on success */
 }
 }
 
 
@@ -1068,24 +1040,18 @@ char *curl_maprintf(const char *format, ...)
   va_list ap_save; /* argument pointer */
   va_list ap_save; /* argument pointer */
   int retcode;
   int retcode;
   struct asprintf info;
   struct asprintf info;
-
-  info.buffer = NULL;
-  info.len = 0;
-  info.alloc = 0;
+  Curl_dyn_init(&info.b, DYN_APRINTF);
   info.fail = 0;
   info.fail = 0;
 
 
   va_start(ap_save, format);
   va_start(ap_save, format);
   retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
   retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
   va_end(ap_save);
   va_end(ap_save);
   if((-1 == retcode) || info.fail) {
   if((-1 == retcode) || info.fail) {
-    if(info.alloc)
-      free(info.buffer);
+    Curl_dyn_free(&info.b);
     return NULL;
     return NULL;
   }
   }
-  if(info.alloc) {
-    info.buffer[info.len] = 0; /* we terminate this with a zero byte */
-    return info.buffer;
-  }
+  if(Curl_dyn_len(&info.b))
+    return Curl_dyn_ptr(&info.b);
   return strdup("");
   return strdup("");
 }
 }
 
 
@@ -1093,23 +1059,16 @@ char *curl_mvaprintf(const char *format, va_list ap_save)
 {
 {
   int retcode;
   int retcode;
   struct asprintf info;
   struct asprintf info;
-
-  info.buffer = NULL;
-  info.len = 0;
-  info.alloc = 0;
+  Curl_dyn_init(&info.b, DYN_APRINTF);
   info.fail = 0;
   info.fail = 0;
 
 
   retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
   retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
   if((-1 == retcode) || info.fail) {
   if((-1 == retcode) || info.fail) {
-    if(info.alloc)
-      free(info.buffer);
+    Curl_dyn_free(&info.b);
     return NULL;
     return NULL;
   }
   }
-
-  if(info.alloc) {
-    info.buffer[info.len] = 0; /* we terminate this with a zero byte */
-    return info.buffer;
-  }
+  if(Curl_dyn_len(&info.b))
+    return Curl_dyn_ptr(&info.b);
   return strdup("");
   return strdup("");
 }
 }
 
 

Некоторые файлы не были показаны из-за большого количества измененных файлов