gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnurl] branch master updated (697584161 -> 10e1f0a79)


From: gnunet
Subject: [gnurl] branch master updated (697584161 -> 10e1f0a79)
Date: Wed, 01 Apr 2020 14:27:45 +0200

This is an automated email from the git hooks/post-receive script.

ng0 pushed a change to branch master
in repository gnurl.

    from 697584161 Merge tag 'curl-7_68_0'
     new 5059f5552 RELEASE-PROCEDURE.md: fix next release date (Feb 26)
     new a7d4693a4 runtests: make random seed fixed for a month
     new 3b75084ce docs/RELEASE-PROCEDURE.md: pushed some release dates
     new 446665606 KNOWN_BUGS: AUTH PLAIN for SMTP is not working on all servers
     new 4027bd72d tool_dirhie: Allow directory traversal during creation
     new e858ae942 bump: work towards 7.69.0 is started
     new f4d60b6f8 tool_dirhie.c: fix the copyright year range
     new 1adebe788 curl.h: remove WIN32 define
     new 920deff86 include: remove non-curl prefixed defines
     new 5ebe5044a libtest/mk-lib1521: adapt to new public header layout
     new fb723fd9d test1167: verify global symbols in public headers are curl 
prefixed
     new 062eaa63b scripts/delta: adapt to new public header layout
     new 875314ed0 hostip: move code to resolve IP address literals to 
`Curl_resolv`
     new 8bd14c871 fix: Copyright year out of date, should be 2020
     new c9c551f1f vtls: Refactor Curl_multissl_version to make the code clearer
     new ea6d6205d cmake: Enable SMB for Windows builds
     new b700662b1 multi: Change curl_multi_wait/poll to error on negative 
timeout
     new cbb542900 ngtcp2: Add an error code for QUIC connection errors
     new 29e40a6d8 schannel: Make CURLOPT_CAINFO work better on Windows 7
     new 8792a5922 cmake: Improve libssh2 check on Windows
     new 272282a05 libssh2: add support for forcing a hostkey type
     new 29babeafe misc: Copyright year out of date, should be 2020
     new ad0aa27a9 curl: remove 'config' field from OutStruct
     new 6773c7ca6 wolfSSH: new SSH backend
     new 4431ed248 curl: make #0 not output the full URL
     new 960753287 ConnectionExists: respect the max_concurrent_streams limits
     new f128c00a9 RELEASE-NOTES: synced
     new 4ccf7622d CMake: Add support for CMAKE_LTO option.
     new 9d1a0922b HTTP-COOKIES.md: describe the cookie file format
     new 16da8bcd7 schannel_verify: Fix alt names manual verify for UNICODE 
builds
     new be578eea7 CMake: use check_symbol_exists also for inet_pton
     new 820775a29 wolfssh: remove fprintf() calls (and uses of __func__)
     new 68403cdbc wolfssh: set the password correctly for PASSWORD auth
     new c2feed05b curl:progressbarinit: ignore column width from terminals < 20
     new 6f69edf96 libssh2: fix variable type
     new 6357a19ff polarssl: removed
     new 59c1caf7f wolfssl: use the wc-prefixed symbol alternatives
     new a7ded055a RELEASE-NOTES: synced
     new c275aa990 ROADMAP: thread-safe `curl_global_init()`
     new 7ff9222ce HTTP: increase EXPECT_100_THRESHOLD to 1Mb
     new ff807c16d http.h: Copyright year out of date, should be 2020
     new 295ea5f64 CMake: support specifying the target Windows version
     new 81e1b1ec2 data.d: remove "Multiple files can also be specified"
     new 1774dbd74 curl: Let -D merge headers in one file again
     new dea17b519 http: move "oauth_bearer" from connectdata to Curl_easy
     new 23a17e039 copyright: fix year ranges
     new 4a4609bf3 smtp: Allow RCPT TO command to fail for some recipients
     new 599d92e7d RELEASE-NOTES: synced
     new 1ebc53df2 mk-ca-bundle: add support for CKA_NSS_SERVER_DISTRUST_AFTER
     new 5e2ad2d01 CURLOPT_PROXY_SSL_OPTIONS.3: Sync with CURLOPT_SSL_OPTIONS.3
     new 3ecdfb195 openssl: make CURLINFO_CERTINFO not truncate x509v3 fields
     new 1c532870e form.d: fix two minor typos
     new 920af1a66 wolfssh: make it init properly via Curl_ssh_init()
     new d265a7d36 singleuse.pl: support new API functions, fix curl_dbg_ 
handling
     new ea284778f strcase: turn Curl_raw_tolower into static
     new 774500033 conncache: removed unused Curl_conncache_bundle_size()
     new c0d7b05c4 llist: removed unused Curl_llist_move()
     new 34e6bc42b conn: do not reuse connection if SOCKS proxy credentials 
differ
     new 1ad49feb7 global_init: assume the EINTR bit by default
     new 9870b80f8 curl: make the -# spaceship bar not wrap the line
     new 422870046 urldata: do string enums without #ifdefs for build scripts
     new 337072519 RELEASE-NOTES: synced
     new 8bd863f97 curl.h: define CURL_WIN32 on windows
     new 872ea75ac README: mention that the docs is in docs/
     new 0b030a5b2 global_init: move the IPv6 works status bool to multi handle
     new d3dc0a07e urlapi: guess scheme correct even with credentials given
     new 8b7fff331 location.d: the method change is from POST to GET only
     new db9af3463 multi_done: if multiplexed, make conn->data point to another 
transfer
     new d3e5311f6 oauth2-bearer.d: works for HTTP too
     new 0a7b7a9d4 KNOWN_BUGS: Multiple methods in a single WWW-Authenticate: 
header
     new 5af016556 cookie: check __Secure- and __Host- case sensitively
     new da9e8ec72 ngtcp2: update to git master and its draft-25 support
     new 7fc63d723 quiche: update to draft-25
     new 33a77cb52 altsvc: use h3-25
     new 28b5b1c20 quiche: Copyright year out of date
     new 6ef123522 ntlm: Move the winbind data into the NTLM data structure
     new 4b6fd29f1 cleanup: fix typos and wording in docs and comments
     new 70ae5c46e cirrus: Add some missing semicolons
     new 27956e963 travis: update non-OpenSSL Linux jobs to Bionic
     new 5cd0f5cc7 openssl: remove redundant assignment
     new f41deddde ntlm: Ensure the HTTP header data is not stored in the 
challenge/response
     new 2bc373740 curl: avoid using strlen for testing if a string is empty
     new 643b9e4da tool_operhlp: Copyright year out of date, should be 2020
     new c2220ed63 RELEASE-NOTES: synced
     new b765cb3c8 ntlm: Pass the Curl_easy structure to the private winbind 
functions
     new 9c27386ef docs/HTTP3: update the OpenSSL branch to use for ngtcp2
     new defe4c08f ngtcp2: fixed to only use AF_INET6 when ENABLE_IPV6
     new 9e1f72075 altsvc: improved header parser
     new d913c1e99 altsvc: set h3 version at a common single spot
     new 1fa83b268 RELEASE-PROCEDURE: feature win is closed post-release a few 
days
     new faaa63f32 docs/HTTP3: add --enable-alt-svc to curl's configure
     new 1cc97ba6e curl: error on --alt-svc use w/o support
     new 671c48eb1 ftp: shrink temp buffers used for PORT
     new 5296abe3a scripts: use last set tag if none given
     new d2411a78e contrithanks: Use the most recent tag by default
     new 8a5c1cf1f contributors: Also include people who contributed to curl-www
     new c87730dae ntlm_wb: Use Curl_socketpair() for greater portability
     new 950b53da0 ftp: remove superfluous checking for crlf in user or pwd
     new 5ce7102ce ftp: remove the duplicated user/password struct fields
     new feba3f054 digest: Do not quote algorithm in HTTP authorisation
     new 511e0c197 checksrc.bat: Fix not being able to run script from the main 
curl directory
     new 8f74bb361 configure.ac: fix comments about --with-quiche
     new 11ee0640a github: Instructions to post "uname -a" on Unix systems in 
issues
     new 05d3312f7 asyn-thread: remove dead code
     new f8f4a9446 url: Include the failure reason when 
curl_win32_idn_to_ascii() fails
     new 02f8de651 altsvc: keep a copy of the file name to survive handle reset
     new 0b8651d48 smtp: Simplify the MAIL command and avoid a duplication of 
send strings
     new 355a5a310 RELEASE-NOTES: synced
     new 8957e6e4e CURLOPT_ALTSVC_CTRL.3: fix the DEFAULT wording
     new d78672b5b create-dirs.d: mention the mode
     new 55bb83c92 easy: remove dead code
     new 4d1aa8d43 multi: fix outdated comment
     new 1c4fa67e8 strerror: Increase STRERROR_LEN 128 -> 256
     new 39d5621cb strerror.h: Copyright year out of date
     new 9dc350b60 tool_homedir: Change GetEnv() to use libcurl's curl_getenv()
     new 46af41daf tool_home: Fix the copyright year being out of date
     new af9afd8b1 azure: disable brotli on the macos debug-builds
     new 95d628e13 TODO: CURLOPT_SSL_CTX_FUNCTION for LDAPS
     new b26c92fbf TODO: Paged searches on LDAP server
     new 03564deba CURLINFO_COOKIELIST.3: Fix example
     new c188391a9 ftp: convert 'sock_accepted' to a plain boolean
     new d60b1b37a multi: if Curl_readwrite sets 'comeback' use expire, not loop
     new 4a4b63daa socks: make the connect phase non-blocking
     new 3ea15be3f RELEASE-NOTES: synced
     new b834890a3 cookies: make saving atomic with a rename
     new 330f13322 rename: a new file for Curl_rename()
     new 14916a82e altsvc: make saving the cache an atomic operation
     new 0ae578ac9 docs/GOVERNANCE: refreshed + added "donations" and 
"commercial support"
     new d79ee4ae3 CURLOPT_REDIR_PROTOCOLS.3: update the DEFAULT section
     new 3735107d6 SOCKS: fix typo in printf formatting
     new 1fc0617dc tool_util: Improve Windows version of tvnow()
     new 05b1b3508 nit: Copyright year out of date
     new 67d26a361 HTTP-COOKIES: mention that a trailing newline is required
     new 1b6cfb9d2 connect: remove some spurious infof() calls
     new 150f45e8d win32: USE_WIN32_CRYPTO to enable Win32 based MD4, MD5 and 
SHA256 functions
     new 0c76795ca cleanup: comment typos
     new 7224e70f4 github action: add CIFuzz
     new 41fcb4f60 GnuTLS: Always send client cert
     new 3a34b930a gtls: fix the copyright year
     new 5808a0d0f http2: now require nghttp2 >= 1.12.0
     new 45160a812 RELEASE-NOTES: synced
     new 84762ff81 md4: Fixed compilation issues when using GNU TLS gcrypt
     new 81c371243 tests: Added a unit test for SHA256 digest generation
     new 4959be810 digest: Corrected the name of the local HTTP digest function
     new 37dc4df27 md5/sha256: Updated the functions to allow non-string data 
to be hashed
     new 2d432f7e4 ntlm: Removed the dependency on the TLS libaries when using 
MD5
     new 1f4911bc2 test1610: Fixed the link to the unit test
     new baf0b680f md4: Use const for the length input parameter
     new fa009cc79 tests: Added a unit test for MD4 digest generation
     new 7def168a4 ntlm: Moved the HMAC MD5 function into the HMAC module as a 
generic function
     new 3f74e5e60 hmac: Added a unit test for the HMAC hash generation
     new 80ccc2641 ftpserver: Corrected the e-mail address regex in MAIL_smtp() 
and RCTP_smtp()
     new 6995b77a5 ftpserver: Updated VRFY_smtp() so the response isn't 
necessary in the test case
     new 4c140a562 smtp: Added UTF-8 mailbox tests to verify existing behaviour
     new 9352a4077 url: Make the IDN conversion functions available to others
     new 68fb25fa3 smtp: Support UTF-8 based host names in the MAIL command
     new e7959c280 smtp: Support UTF-8 based host names in the RCPT TO command
     new 2aa6c1735 smtp: Support UTF-8 based host names in the VRFY command
     new 4754c55cd smtp: Detect server support for the UTF-8 extension as 
defined in RFC-6531
     new aba1bf630 smtp: Support the SMTPUTF8 extension in the MAIL command
     new 483edeb8d smtp: Support the SMTPUTF8 extension in the RCPT TO command
     new efce3ea5a smtp: Support the SMTPUTF8 extension in the VRFY command
     new 34a1ffb05 smtp: Support the SMTPUTF8 extension for the EXPN command
     new 8220ec821 smtp: Tidy up, following recent changes, to maintain the 
coding style
     new 6375b205a http: added 417 response treatment
     new 7730d1157 cookie: remove unnecessary check for 'out != 0'
     new d9e40f57d test1323: Added the missing 'unit test' feature requirement 
in the test case
     new 0922f7624 tests: Automatically deduce the tool name from the test case 
for unit tests
     new 507cf6a13 libssh: improve known hosts handling
     new 15f51474c http2: make pausing/unpausing set/clear local stream window
     new 9faa0d2b4 RELEASE-NOTES: synced
     new 1d1e9e8ad Curl_is_ASCII_name: handle a NULL argument
     new 7c3c5492c RELEASE-NOTES: Corrected the link to issue #4892
     new 9d5893105 gtls: Fixed compilation when using GnuTLS < 3.5.0
     new 81ade13c3 smtp: fix memory leak on exit path
     new 02988b70c runtests: restore the command log
     new 8c7c4a627 tests: fix Python 3 compatibility of smbserver.py
     new f093dcc39 ci/tests: Add Windows builds via Azure Pipelines using Docker
     new 1f114be62 ci/tests: align Azure Pipeline job names with each other
     new 513b5387a ci/tests: Increase timeouts of Windows builds due to new 
tests
     new ea1b2eb97 CIfuzz: switch off 'dry_run' mode
     new aeb292301 smtp: overwriting 'from' leaks memory
     new 0e06c1637 TODO: curl --proxycommand
     new fa0216b29 pause: force-drain the transfer on unpause
     new ada581f2c ci/tests: Send test results to Azure DevOps for reporting
     new f0ec0e902 md4: Use non-deprecated functions in mbedTLS >= 2.7.0
     new 5aea558dc md5: Use pointer notation for array parameters in GnuTLS 
implementation
     new 1d421de9a md5: Added implementation for mbedTLS
     new 5b46790f1 docs: fix typo on CURLINFO_RETRY_AFTER - alwaus -> always
     new a2ad27875 polarssl: Additional removal
     new 711f022c0 runtests: fix output to command log
     new fc9312f71 CMake: clean up and improve build procedures
     new d6e3273bb build: remove all HAVE_OPENSSL_ENGINE_H defines
     new 597cf2f1f ci/tests: Make sure that the AZURE_ACCESS_TOKEN is available
     new d753cfc16 ci/tests: Fix typo in previous commit 597cf2
     new c77060923 ci/tests: Update Azure DevOps pipeline job display names
     new cdcc9df18 configure.ac: Disable metalink support if an incompatible 
SSL/TLS specified
     new cf1466bd4 unit1651: Fixed conversion compilation warning
     new 87869e38d mime: latch last read callback status.
     new ed0f357f7 mime: do not perform more than one read in a row
     new b2caaa068 mime: fix the binary encoder to handle large data properly
     new ff3b1f486 altsvc: both h3 backends now speak h3-27
     new e002f6c0c Revert "mime: fix the binary encoder to handle large data 
properly"
     new d7242f475 Revert "mime: do not perform more than one read in a row"
     new 8cd4e6d81 Revert "mime: latch last read callback status."
     new 0b3e3644e formdata/mime: copyright year range update
     new df207d2dd tests: disable SMTP UTF-8 tests on Windows
     new 967bf4633 configure: bump the AC_COPYRIGHT year range
     new 8ef1f55ad ci/tests: fine-tune Azure Pipeline timeouts with a small 
puffer
     new 5494afac8 tests: disable 962, 963 and 964 on Windows
     new 0caae3c4b http: mark POSTs with no body as "upload done" from the start
     new cf7760ab5 multi_wait: stop loop when sread() returns zero
     new 0e539970e ci/tests: some MacOS builds randomly take longer than 20min
     new 0b337ecc9 md4: use init/update/final functions in Secure Transport
     new 1722eb83b curl_getenv.3: Fix the memory handling description
     new 256a29361 curl_escape.3: Add a link to curl_free
     new 365f4ea53 sha256: Added GNU TLS Nettle implementation
     new 8fbd93724 sha256: Added GNU TLS gcrypt implementation
     new 425ceb015 sha256: Added mbedtls implementation
     new 4feb38dee sha256: Added SecureTransport implementation
     new f22a5c35e sha256: Added WinCrypt implementation
     new e6322feb3 sha256: Tidy up following recent changes
     new 18901c7bb configure.ac: Disable metalink if mbedTLS is specified
     new c537b0057 dist: include tests/azure.pm in the tarball
     new b572e0be5 Revert "sha256: Added SecureTransport implementation"
     new c0d8b96f2 ci/tests: Send test results to AppVeyor for status overview
     new 3feb60d28 ci/tests: Move CI test result creation above environment 
setup
     new 86ceb9b00 README.md: add Azure DevOps Pipelines build status badge
     new 119ea453f ci/tests: Make it possible to still run but ignore failing 
tests
     new e4b4ccbc6 cmake: Show HTTPS-proxy in the features output
     new e7c144f1d ci/tests: fix escaping of testnames and disable proxy for CI 
APIs
     new b44f18f1f THANKS: from 7.69.0
     new b8d136685 RELEASE-NOTES: 7.69.0
     new 691b71be9 cirrus-ci: disable the FreeBSD 13 builds
     new 1eecb0e02 runtests.1: rephrase how to specify what tests to run
     new 9aaca0904 tests: try to make sleeping portable by avoiding select
     new 3c1b9145c tests: align some Windows sleep defines with each other
     new 30f736002 tests: wrap ignored test failures in braces
     new 52d302ed6 polarssl: remove more references and mentions
     new beea6f8be KNOWN_BUGS: configure --with-gssapi with Heimdal is ignored 
on macOS
     new a52a1a05f MANUAL: update a dict-using command line
     new 32a28dc28 RELEASE-NOTES: synced
     new 8aa04e9a2 Revert "pause: force-drain the transfer on unpause"
     new 6f17df7a6 urldata: remove the 'stream_was_rewound' connectdata struct 
member
     new 0b7735c45 transfer: set correct copyright year range
     new 2258b7bcc multi: skip EINTR check on wakeup socket if it was closed
     new 485d4470d curl_share_setopt.3: Note sharing cookies doesn't enable the 
engine
     new 64258bd0a pause: return early for calls that don't change pause state
     new 3c3db98b6 unit1612: fixed the inclusion and compilation of the HMAC 
unit test
     new e54b1885d pause: bail out on bad input
     new 09aa80724 libssh: Fix matching user-specified MD5 hex key
     new 4b786abc4 socks5: switch state properly when the resolve is done
     new e040146f2 pause: force a connection (re-)check after unpausing
     new 2f4c36357 config-win32: Windows does not have ftruncate
     new a39e5bfb9 seek: fix fallback for missing ftruncate on Windows
     new c0780e4a9 tool_cb_see: set correct copyright year range
     new 99c688ba2 perl: align order and completeness of Windows OS checks
     new a6fed41f6 tests: use native Sleep function as fallback on Windows
     new 310dc709f RELEASE-NOTES: synced
     new e364546fb version: make curl_version* thread-safe without using global 
context
     new c8f086bcc ares: store dns parameters for duphandle
     new 3dce9849b runtests: fix missing use of exe_ext helper function
     new 96972ec1c mime: latch last read callback status.
     new 1e4cb333e mime: do not perform more than one read in a row
     new e5b366c0b mime: fix the binary encoder to handle large data properly
     new 0a04dc4d5 lib1564: reduce number of mid-wait wakeup calls
     new 92d63a10a sha256: Added SecureTransport implementation
     new 1369b8ad3 sha256: Added WinCrypt implementation
     new a75f12768 test 1560: avoid valgrind false positives
     new 06a1b8214 cookie: get_top_domain() sets zero length for null domains
     new 77336671d silly web server: silent a compilation warning
     new f0e816054 socks4: fix host resolve regression
     new 464d944b5 RELEASE-NOTES: synced
     new e96fe70ca sftp: fix segfault regression introduced by #4747
     new 4d43d0614 runtests: log minimal and maximal used port numbers
     new 26c5ba0e6 tests/server: fix missing use of exe_ext helper function
     new 94ced8e36 tests/data: fix static ip:port instead of dynamic values 
being used
     new f11b2cb62 tests/data: fix static ip instead of dynamic value being used
     new fb6134427 test1129: fix invalid case of closing XML-tag and 
Content-Length
     new 2d47224e1 THANKS: from the 7.69.1 release
     new b81e0b077 RELEASE-NOTES: 7.69.1
     new 10e1f0a79 Merge tag 'curl-7_69_1'

The 282 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .azure-pipelines.yml                               |  304 ++++-
 .cirrus.yml                                        |    8 +-
 .mailmap                                           |    5 +
 .travis.yml                                        |   40 +-
 CMake/CurlSymbolHiding.cmake                       |    8 +-
 CMake/FindNSS.cmake                                |    4 +-
 CMake/OtherTests.cmake                             |    4 +-
 CMake/Utilities.cmake                              |    5 +-
 CMakeLists.txt                                     |  114 +-
 README                                             |    2 +
 README.md                                          |    1 +
 RELEASE-NOTES                                      |  329 ++----
 acinclude.m4                                       |   10 +-
 appveyor.yml                                       |    2 +-
 configure.ac                                       |   60 +-
 docs/DEPRECATE.md                                  |   32 +-
 docs/GOVERNANCE.md                                 |   29 +-
 docs/HTTP-COOKIES.md                               |   21 +
 docs/HTTP3.md                                      |    8 +-
 docs/INSTALL.md                                    |    1 -
 docs/INTERNALS.md                                  |    3 +-
 docs/KNOWN_BUGS                                    |   54 +-
 docs/MANUAL.md                                     |    2 +-
 docs/RELEASE-PROCEDURE.md                          |   30 +-
 docs/ROADMAP.md                                    |    7 +
 docs/THANKS                                        |  269 +++--
 docs/TODO                                          |   25 +-
 docs/cmdline-opts/alt-svc.d                        |    2 +-
 docs/cmdline-opts/create-dirs.d                    |    2 +
 docs/cmdline-opts/data.d                           |   11 +-
 docs/cmdline-opts/form.d                           |    4 +-
 docs/cmdline-opts/location.d                       |   16 +-
 docs/cmdline-opts/mail-rcpt-allowfails.d           |   15 +
 docs/cmdline-opts/oauth2-bearer.d                  |    2 +-
 docs/libcurl/gnurl_easy_reset.3                    |    5 +-
 docs/libcurl/gnurl_easy_setopt.3                   |    2 +
 docs/libcurl/gnurl_escape.3                        |    2 +-
 docs/libcurl/gnurl_getenv.3                        |    8 +-
 docs/libcurl/gnurl_global_init.3                   |   10 +-
 docs/libcurl/gnurl_global_sslset.3                 |    4 +-
 docs/libcurl/gnurl_share_setopt.3                  |    2 +
 docs/libcurl/libgnurl-errors.3                     |    7 +-
 docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLLOWFAILS.3  |   71 ++
 docs/libcurl/opts/GNURLINFO_COOKIELIST.3           |    6 +-
 docs/libcurl/opts/GNURLINFO_RETRY_AFTER.3          |    2 +-
 docs/libcurl/opts/GNURLINFO_TLS_SSL_PTR.3          |   14 +-
 docs/libcurl/opts/GNURLOPT_ALTSVC_CTRL.3           |    7 +-
 docs/libcurl/opts/GNURLOPT_CAPATH.3                |    7 +-
 docs/libcurl/opts/GNURLOPT_COOKIEFILE.3            |    6 +-
 docs/libcurl/opts/GNURLOPT_COOKIELIST.3            |    6 +-
 docs/libcurl/opts/GNURLOPT_FOLLOWLOCATION.3        |    4 +-
 docs/libcurl/opts/GNURLOPT_POSTFIELDS.3            |    4 +-
 docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3     |   38 +-
 docs/libcurl/opts/GNURLOPT_REDIR_PROTOCOLS.3       |    7 +-
 docs/libcurl/opts/Makefile.inc                     |  701 ++++++------
 docs/libcurl/symbols-in-versions                   |   17 +-
 include/gnurl/curl.h                               |  682 ++++++------
 include/gnurl/curlver.h                            |   12 +-
 include/gnurl/multi.h                              |   48 +-
 lib/CMakeLists.txt                                 |    6 +
 lib/Makefile.inc                                   |   23 +-
 lib/Makefile.m32                                   |    4 +-
 lib/Makefile.netware                               |    3 +-
 lib/altsvc.c                                       |  254 +++--
 lib/altsvc.h                                       |    9 +-
 lib/asyn-ares.c                                    |   19 +-
 lib/asyn-thread.c                                  |   42 +-
 lib/checksrc.pl                                    |    2 +-
 lib/config-dos.h                                   |    3 +-
 lib/config-plan9.h                                 |    3 +-
 lib/config-symbian.h                               |    5 +-
 lib/config-tpf.h                                   |    6 +-
 lib/config-vxworks.h                               |    5 +-
 lib/config-win32.h                                 |    6 +-
 lib/conncache.c                                    |   14 +-
 lib/conncache.h                                    |    3 +-
 lib/connect.c                                      |   87 +-
 lib/cookie.c                                       |   82 +-
 lib/curl_config.h.cmake                            |    9 +-
 lib/curl_hmac.h                                    |    9 +-
 lib/curl_md4.h                                     |    5 +-
 lib/curl_md5.h                                     |    6 +-
 lib/curl_ntlm_core.c                               |   39 +-
 lib/curl_ntlm_core.h                               |   10 +-
 lib/curl_ntlm_wb.c                                 |  103 +-
 lib/curl_sasl.c                                    |   16 +-
 lib/curl_sha256.h                                  |    9 +-
 lib/doh.c                                          |    4 +-
 lib/easy.c                                         |  141 ++-
 lib/formdata.c                                     |   14 +-
 lib/ftp.c                                          |   52 +-
 lib/ftp.h                                          |    4 +-
 lib/getenv.c                                       |   47 +-
 lib/hmac.c                                         |   39 +-
 lib/hostip.c                                       |   82 +-
 lib/hostip.h                                       |   33 +-
 lib/hostip4.c                                      |  294 +++--
 lib/hostip6.c                                      |   26 +-
 lib/http.c                                         |   29 +-
 lib/http.h                                         |    4 +-
 lib/http2.c                                        |  115 +-
 lib/http2.h                                        |    4 +-
 lib/llist.c                                        |   53 +-
 lib/llist.h                                        |    5 +-
 lib/md4.c                                          |   60 +-
 lib/md5.c                                          |   69 +-
 lib/mime.c                                         |  231 +++-
 lib/mime.h                                         |    8 +-
 lib/mk-ca-bundle.pl                                |   62 +-
 lib/multi.c                                        |   43 +-
 lib/multihandle.h                                  |   13 +-
 lib/multiif.h                                      |    8 +-
 lib/{getenv.c => rename.c}                         |   52 +-
 lib/{curl_sha256.h => rename.h}                    |   15 +-
 lib/select.c                                       |  215 ++--
 lib/select.h                                       |   10 +-
 lib/sendf.c                                        |   19 +-
 lib/setopt.c                                       |   32 +-
 lib/sha256.c                                       |  267 ++++-
 lib/smtp.c                                         |  324 +++++-
 lib/smtp.h                                         |    7 +-
 lib/socks.c                                        | 1134 +++++++++++--------
 lib/socks.h                                        |   15 +-
 lib/socks_gssapi.c                                 |    6 +-
 lib/socks_sspi.c                                   |    5 +-
 lib/strcase.c                                      |    8 +-
 lib/strcase.h                                      |    3 +-
 lib/strerror.c                                     |    6 +
 lib/strerror.h                                     |    4 +-
 lib/system_win32.c                                 |    4 +-
 lib/timeval.c                                      |    3 +-
 lib/transfer.c                                     |    8 +-
 lib/url.c                                          |  111 +-
 lib/url.h                                          |    7 +-
 lib/urlapi.c                                       |   68 +-
 lib/urldata.h                                      |  100 +-
 lib/vauth/digest.c                                 |   74 +-
 lib/vauth/ntlm.c                                   |   13 +-
 lib/version.c                                      |  198 ++--
 lib/vquic/ngtcp2.c                                 |   36 +-
 lib/vquic/quiche.c                                 |    6 +-
 lib/vssh/libssh.c                                  |  121 +-
 lib/vssh/libssh2.c                                 |  142 ++-
 lib/vssh/ssh.h                                     |   22 +-
 lib/vssh/wolfssh.c                                 | 1156 ++++++++++++++++++++
 lib/{vtls/polarssl.h => vssh/wolfssh.h}            |   15 +-
 lib/vtls/gtls.c                                    |    6 +-
 lib/vtls/mbedtls.c                                 |   16 +-
 ...{polarssl_threadlock.c => mbedtls_threadlock.c} |   38 +-
 ...{polarssl_threadlock.h => mbedtls_threadlock.h} |   28 +-
 lib/vtls/openssl.c                                 |   32 +-
 lib/vtls/polarssl.c                                |  931 ----------------
 lib/vtls/schannel.c                                |   12 +-
 lib/vtls/schannel_verify.c                         |  152 ++-
 lib/vtls/sectransp.c                               |    4 +-
 lib/vtls/vtls.c                                    |   46 +-
 lib/vtls/vtls.h                                    |    4 +-
 lib/vtls/wolfssl.c                                 |   12 +-
 m4/curl-confopts.m4                                |    6 +-
 m4/curl-functions.m4                               |    4 +-
 packages/OS400/ccsidcurl.c                         |   16 -
 packages/OS400/chkstrings.c                        |   62 ++
 packages/OS400/curl.inc.in                         |    6 +-
 packages/OS400/make-lib.sh                         |   20 +
 packages/Symbian/group/libcurl.mmp                 |    2 +-
 packages/vms/compare_curl_source.com               |    2 +-
 packages/vms/curl_crtl_init.c                      |    2 +-
 packages/vms/generate_config_vms_h_curl.com        |    5 +-
 packages/vms/readme                                |    4 +-
 scripts/contributors.sh                            |   22 +-
 scripts/contrithanks.sh                            |   21 +-
 scripts/delta                                      |   18 +-
 scripts/singleuse.pl                               |   19 +-
 src/CMakeLists.txt                                 |    6 +
 src/tool_cb_hdr.c                                  |   32 +-
 src/tool_cb_prg.c                                  |   55 +-
 src/tool_cb_rea.c                                  |    5 +-
 src/tool_cb_see.c                                  |    6 +-
 src/tool_cb_see.h                                  |   11 +-
 src/tool_cb_wrt.c                                  |   15 +-
 src/tool_cb_wrt.h                                  |    5 +-
 src/tool_cfgable.h                                 |    3 +-
 src/tool_dirhie.c                                  |   21 +-
 src/tool_doswin.c                                  |   28 +-
 src/tool_doswin.h                                  |    3 +-
 src/tool_getparam.c                                |   11 +-
 src/tool_help.c                                    |    4 +-
 src/tool_homedir.c                                 |   57 +-
 src/tool_main.c                                    |   35 +-
 src/tool_metalink.c                                |   71 +-
 src/tool_operate.c                                 |   40 +-
 src/tool_operhlp.c                                 |    4 +-
 src/tool_progress.c                                |    5 +-
 src/tool_sdecls.h                                  |    3 +-
 src/tool_urlglob.c                                 |    4 +-
 src/tool_util.c                                    |   44 +-
 tests/.gitignore                                   |    1 +
 tests/FILEFORMAT                                   |   15 +-
 tests/Makefile.am                                  |    5 +-
 tests/appveyor.pm                                  |  114 ++
 tests/azure.pm                                     |  146 +++
 tests/badsymbols.pl                                |  132 +++
 tests/data/Makefile.inc                            |   26 +-
 tests/data/test1070                                |    4 +-
 tests/data/test1129                                |   10 +-
 tests/data/test1133                                |    1 -
 tests/data/{test1395 => test1167}                  |   14 +-
 tests/data/{test490 => test1176}                   |   42 +-
 tests/data/test1293                                |    2 +-
 tests/data/test1300                                |    4 -
 tests/data/test1301                                |    4 -
 tests/data/test1302                                |    4 -
 tests/data/test1303                                |    4 -
 tests/data/test1304                                |    4 -
 tests/data/test1305                                |    4 -
 tests/data/test1307                                |    4 -
 tests/data/test1308                                |    4 -
 tests/data/test1309                                |    4 -
 tests/data/test1323                                |    6 +-
 tests/data/test1330                                |    6 -
 tests/data/test1394                                |    4 -
 tests/data/test1395                                |    5 -
 tests/data/test1396                                |    3 -
 tests/data/test1397                                |    3 -
 tests/data/test1398                                |    3 -
 tests/data/test1399                                |    4 -
 tests/data/test1437                                |    2 +-
 tests/data/test1459                                |   46 +
 tests/data/test153                                 |    2 +-
 tests/data/test1538                                |    6 +-
 tests/data/test1600                                |    4 -
 tests/data/test1601                                |    4 -
 tests/data/test1602                                |    4 -
 tests/data/test1603                                |    4 -
 tests/data/test1604                                |    4 -
 tests/data/test1605                                |    4 -
 tests/data/test1606                                |    4 -
 tests/data/test1607                                |    4 -
 tests/data/test1608                                |    4 -
 tests/data/test1609                                |    4 -
 tests/data/{test1650 => test1610}                  |    9 +-
 tests/data/{test1650 => test1611}                  |    9 +-
 tests/data/{test1650 => test1612}                  |    9 +-
 tests/data/test1620                                |    4 -
 tests/data/test1621                                |    4 -
 tests/data/test1650                                |    4 -
 tests/data/test1651                                |    4 -
 tests/data/test1652                                |    3 -
 tests/data/test1653                                |    3 -
 tests/data/test1654                                |    3 -
 tests/data/test1655                                |    4 -
 tests/data/test1800                                |    2 +-
 tests/data/test1908                                |   71 ++
 tests/data/test2006                                |    4 +
 tests/data/test2007                                |    4 +
 tests/data/test2008                                |    4 +
 tests/data/test2009                                |    4 +
 tests/data/test2010                                |    4 +
 tests/data/test2033                                |    8 +-
 tests/data/test2058                                |    2 +-
 tests/data/test2059                                |    2 +-
 tests/data/test2060                                |    2 +-
 tests/data/test2061                                |    2 +-
 tests/data/test2062                                |    2 +-
 tests/data/test2063                                |    2 +-
 tests/data/test2064                                |    2 +-
 tests/data/test2065                                |    2 +-
 tests/data/test2066                                |    2 +-
 tests/data/test2067                                |    2 +-
 tests/data/test2068                                |    2 +-
 tests/data/test2069                                |    2 +-
 tests/data/test2078                                |    2 +-
 tests/data/test2100                                |  Bin 1639 -> 1642 bytes
 tests/data/test3002                                |   55 +
 tests/data/test3003                                |   55 +
 tests/data/test3004                                |   55 +
 tests/data/test3005                                |   55 +
 tests/data/test3006                                |   51 +
 tests/data/test3007                                |   47 +
 tests/data/test304                                 |    1 -
 tests/data/test357                                 |   97 ++
 tests/data/test39                                  |    1 -
 tests/data/test490                                 |    4 +-
 tests/data/test491                                 |    2 +-
 tests/data/test492                                 |    8 +-
 tests/data/test552                                 |  Bin 142985 -> 142941 
bytes
 tests/data/test558                                 |    2 -
 tests/data/test643                                 |   12 +-
 tests/data/test644                                 |    3 +-
 tests/data/test645                                 |   64 +-
 tests/data/test650                                 |   12 +-
 tests/data/test651                                 |    1 -
 tests/data/test654                                 |   18 +-
 tests/data/test664                                 |   44 +
 tests/data/test665                                 |   44 +
 tests/data/test666                                 |  293 +++++
 tests/data/{test654 => test667}                    |   44 +-
 tests/data/{test654 => test668}                    |   46 +-
 tests/data/{test1293 => test670}                   |   57 +-
 tests/data/{test1293 => test671}                   |   57 +-
 tests/data/{test1293 => test672}                   |   57 +-
 tests/data/{test1293 => test673}                   |   57 +-
 tests/data/{test923 => test894}                    |   23 +-
 tests/data/test923                                 |    3 -
 tests/data/test955                                 |   56 +
 tests/data/test956                                 |   57 +
 tests/data/test957                                 |   51 +
 tests/data/test958                                 |   51 +
 tests/data/test959                                 |   57 +
 tests/data/test960                                 |   58 +
 tests/data/test961                                 |   52 +
 tests/data/test962                                 |   63 ++
 tests/data/test963                                 |   63 ++
 tests/data/test964                                 |   49 +
 tests/data/test965                                 |   66 ++
 tests/data/test966                                 |   66 ++
 tests/data/test967                                 |   55 +
 tests/data/test968                                 |   52 +
 tests/data/test969                                 |   51 +
 tests/ftp.pm                                       |   38 +-
 tests/ftpserver.pl                                 |   62 +-
 tests/keywords.pl                                  |    4 +-
 tests/libtest/Makefile.inc                         |   36 +-
 tests/libtest/lib1515.c                            |    2 +-
 tests/libtest/lib1531.c                            |    2 +-
 tests/libtest/lib1560.c                            |   15 +-
 tests/libtest/lib1564.c                            |    4 +-
 src/tool_cb_see.h => tests/libtest/lib1908.c       |   52 +-
 tests/libtest/lib643.c                             |   19 +-
 tests/libtest/lib652.c                             |    5 +-
 tests/libtest/lib654.c                             |    8 +-
 tests/libtest/{lib652.c => lib666.c}               |   50 +-
 tests/libtest/{lib654.c => lib667.c}               |   77 +-
 tests/libtest/lib668.c                             |  122 +++
 tests/libtest/lib670.c                             |  259 +++++
 tests/libtest/mk-lib1521.pl                        |   47 +-
 tests/python_dependencies/impacket/smbserver.py    |    7 +-
 tests/rtspserver.pl                                |    6 +-
 tests/runtests.1                                   |   57 +-
 tests/runtests.pl                                  |  234 +++-
 tests/server/sws.c                                 |   32 +-
 tests/server/util.h                                |    6 +-
 tests/sshhelp.pm                                   |    3 +
 tests/sshserver.pl                                 |   28 +-
 tests/testcurl.pl                                  |    2 +-
 tests/tftpserver.pl                                |    6 +-
 tests/unit/Makefile.inc                            |   34 +-
 tests/unit/unit1300.c                              |   52 +-
 tests/unit/unit1601.c                              |   20 +-
 tests/unit/{unit1601.c => unit1610.c}              |   22 +-
 tests/unit/{unit1601.c => unit1611.c}              |   20 +-
 tests/unit/{unit1601.c => unit1612.c}              |   26 +-
 tests/unit/unit1651.c                              |    4 +-
 tests/unit/unit1654.c                              |    4 +-
 354 files changed, 10311 insertions(+), 5517 deletions(-)
 create mode 100644 docs/cmdline-opts/mail-rcpt-allowfails.d
 create mode 100644 docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLLOWFAILS.3
 copy lib/{getenv.c => rename.c} (53%)
 copy lib/{curl_sha256.h => rename.h} (76%)
 create mode 100644 lib/vssh/wolfssh.c
 rename lib/{vtls/polarssl.h => vssh/wolfssh.h} (73%)
 rename lib/vtls/{polarssl_threadlock.c => mbedtls_threadlock.c} (76%)
 rename lib/vtls/{polarssl_threadlock.h => mbedtls_threadlock.h} (64%)
 delete mode 100644 lib/vtls/polarssl.c
 create mode 100644 packages/OS400/chkstrings.c
 create mode 100644 tests/appveyor.pm
 create mode 100644 tests/azure.pm
 create mode 100755 tests/badsymbols.pl
 copy tests/data/{test1395 => test1167} (50%)
 copy tests/data/{test490 => test1176} (57%)
 create mode 100644 tests/data/test1459
 copy tests/data/{test1650 => test1610} (82%)
 copy tests/data/{test1650 => test1611} (82%)
 copy tests/data/{test1650 => test1612} (82%)
 create mode 100644 tests/data/test1908
 create mode 100644 tests/data/test3002
 create mode 100644 tests/data/test3003
 create mode 100644 tests/data/test3004
 create mode 100644 tests/data/test3005
 create mode 100644 tests/data/test3006
 create mode 100644 tests/data/test3007
 create mode 100644 tests/data/test357
 create mode 100644 tests/data/test664
 create mode 100644 tests/data/test665
 create mode 100644 tests/data/test666
 copy tests/data/{test654 => test667} (62%)
 copy tests/data/{test654 => test668} (67%)
 copy tests/data/{test1293 => test670} (59%)
 copy tests/data/{test1293 => test671} (59%)
 copy tests/data/{test1293 => test672} (59%)
 copy tests/data/{test1293 => test673} (59%)
 copy tests/data/{test923 => test894} (59%)
 create mode 100644 tests/data/test955
 create mode 100644 tests/data/test956
 create mode 100644 tests/data/test957
 create mode 100644 tests/data/test958
 create mode 100644 tests/data/test959
 create mode 100644 tests/data/test960
 create mode 100644 tests/data/test961
 create mode 100644 tests/data/test962
 create mode 100644 tests/data/test963
 create mode 100644 tests/data/test964
 create mode 100644 tests/data/test965
 create mode 100644 tests/data/test966
 create mode 100644 tests/data/test967
 create mode 100644 tests/data/test968
 create mode 100644 tests/data/test969
 copy src/tool_cb_see.h => tests/libtest/lib1908.c (61%)
 copy tests/libtest/{lib652.c => lib666.c} (74%)
 copy tests/libtest/{lib654.c => lib667.c} (56%)
 create mode 100644 tests/libtest/lib668.c
 create mode 100644 tests/libtest/lib670.c
 copy tests/unit/{unit1601.c => unit1610.c} (61%)
 copy tests/unit/{unit1601.c => unit1611.c} (67%)
 copy tests/unit/{unit1601.c => unit1612.c} (59%)

diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 93f8cd067..9e2d74e99 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -4,85 +4,109 @@
 # https://aka.ms/yaml
 
 trigger:
-- master
+- 'master'
+- '*/ci'
+
+stages:
 
 ##########################################
 ### Linux jobs first
 ##########################################
 
-jobs:
-  - job: vanilla_ubuntu
-    displayName: unbuntu default
+- stage: linux
+  dependsOn: []
+  jobs:
+  - job: vanilla
+    displayName: ubuntu default
+    timeoutInMinutes: 20
     pool:
       vmImage: 'ubuntu-latest'
     steps:
     - script: ./buildconf && ./configure --enable-debug --enable-werror
-      displayName: 'Run configure'
+      displayName: 'configure debug'
 
     - script: make
       displayName: 'make'
 
     - script: make test-nonflaky
       displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
 
   - job: disable_ipv6
     displayName: ubuntu w/o IPv6
+    timeoutInMinutes: 20
     pool:
       vmImage: 'ubuntu-latest'
     steps:
     - script: ./buildconf && ./configure --disable-ipv6
-      displayName: 'Run configure --disable-ipv6'
+      displayName: 'configure disable ipv6'
 
     - script: make
       displayName: 'make'
 
     - script: make test-nonflaky
       displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
 
   - job: disable_http_smtp_imap
     displayName: ubuntu w/o HTTP/SMTP/IMAP
+    timeoutInMinutes: 20
     pool:
       vmImage: 'ubuntu-latest'
     steps:
     - script: ./buildconf && ./configure --disable-http --disable-smtp 
--disable-imap
-      displayName: 'Run configure'
+      displayName: 'configure disable http/smtp/imap'
 
     - script: make
       displayName: 'make'
 
     - script: make test-nonflaky
       displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
 
   - job: disable_thredres
     displayName: ubuntu sync resolver
+    timeoutInMinutes: 20
     pool:
       vmImage: 'ubuntu-latest'
     steps:
     - script: ./buildconf && ./configure --disable-threaded-resolver
-      displayName: 'Run configure'
+      displayName: 'configure disable threaded-resolver'
 
     - script: make
       displayName: 'make'
 
     - script: make test-nonflaky
       displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
 
   - job: http_only
     displayName: ubuntu HTTP only
+    timeoutInMinutes: 20
     pool:
       vmImage: 'ubuntu-latest'
     steps:
     - script: ./buildconf && ./configure --disable-dict --disable-file 
--disable-ftp --disable-gopher --disable-imap --disable-ldap --disable-pop3 
--disable-rtmp --disable-rtsp --disable-scp --disable-sftp --disable-smb 
--disable-smtp --disable-telnet --disable-tftp
-      displayName: 'Run configure'
+      displayName: 'configure disable non-http'
 
     - script: make
       displayName: 'make'
 
     - script: make test-nonflaky
       displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
 
+- stage: linux_torture
+  dependsOn: linux
+  jobs:
   - job: torture
     displayName: ubuntu torture tests
+    timeoutInMinutes: 50
     pool:
       vmImage: 'ubuntu-latest'
     steps:
@@ -90,7 +114,7 @@ jobs:
       displayName: 'apt install'
 
     - script: ./buildconf && ./configure --enable-debug --disable-shared 
--disable-threaded-resolver --enable-alt-svc
-      displayName: 'Run configure'
+      displayName: 'configure torture'
 
     - script: make
       displayName: 'make'
@@ -102,61 +126,75 @@ jobs:
 ### macOS jobs below
 ##########################################
 
-  - job: macos_plain
+- stage: macos
+  dependsOn: []
+  jobs:
+  - job: macos_vanilla
     displayName: macos default
+    timeoutInMinutes: 30
     pool:
       vmImage: 'macOS-latest'
     steps:
     - script: brew update && brew install libtool autoconf automake nghttp2 
pkg-config
-      displayName: Install packages
+      displayName: 'brew install'
 
-    - script: ./buildconf && ./configure --enable-debug --enable-werror
-      displayName: 'Run configure'
+    - script: ./buildconf && ./configure --enable-debug --enable-werror 
--without-brotli
+      displayName: 'configure debug without brotli'
 
     - script: make
       displayName: 'make'
 
     - script: make test-nonflaky
       displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
 
   - job: macos_libssh2
     displayName: macos libssh2
+    timeoutInMinutes: 30
     pool:
       vmImage: 'macOS-latest'
     steps:
     - script: brew update && brew install libtool autoconf automake nghttp2 
pkg-config libssh2
-      displayName: Install packages
+      displayName: 'brew install'
 
-    - script: ./buildconf && ./configure --with-libssh2 --enable-debug
-      displayName: 'Run configure'
+    - script: ./buildconf && ./configure --enable-debug --with-libssh2
+      displayName: 'configure debug with libssh2'
 
     - script: make
       displayName: 'make'
 
     - script: make test-nonflaky
       displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
 
   - job: macos_cmake
     displayName: macos cmake openssl
+    timeoutInMinutes: 20
     pool:
       vmImage: 'macOS-latest'
     steps:
     - script: brew update && brew install libtool autoconf automake nghttp2 
pkg-config openssl
-      displayName: Install packages
+      displayName: 'brew install'
 
     - script: cmake -H. -Bbuild -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl 
-DCURL_DISABLE_LDAP=ON -DCURL_DISABLE_LDAPS=ON && cmake --build build
-      displayName: 'Run cmake'
+      displayName: 'cmake build'
 
+- stage: macos_torture
+  dependsOn: macos
+  jobs:
   - job: macos_torture
     displayName: macos torture
+    timeoutInMinutes: 50
     pool:
       vmImage: 'macOS-latest'
     steps:
     - script: brew update && brew install libtool autoconf automake nghttp2 
pkg-config
-      displayName: Install packages
+      displayName: 'brew install'
 
     - script: ./buildconf && ./configure --enable-debug --disable-shared 
--disable-threaded-resolver --enable-alt-svc
-      displayName: 'Run configure'
+      displayName: 'configure torture'
 
     - script: make
       displayName: 'make'
@@ -164,3 +202,227 @@ jobs:
     - script: make "TFLAGS=-n -t --shallow=25 '!FTP'" test-nonflaky
       displayName: 'torture test'
 
+##########################################
+### Windows jobs below
+##########################################
+
+- stage: windows
+  dependsOn: []
+  jobs:
+  - job: windows_msys2_mingw32_debug_openssl
+    displayName: msys2 mingw32 debug openssl
+    timeoutInMinutes: 70
+    pool:
+      vmImage: 'windows-2019'
+    container:
+      image: mback2k/curl-docker-winbuildenv-msys2-mingw32:ltsc2019
+      env:
+        MSYSTEM: MINGW32
+        MSYS2_PATH_TYPE: inherit
+        TFLAGS: "~323 ~1056 ~1299"
+    steps:
+    - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && 
./configure --host=i686-w64-mingw32 --build=i686-w64-mingw32 --enable-debug 
--enable-werror"
+      displayName: 'configure debug'
+
+    - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make"
+      displayName: 'make'
+
+    - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make 
test-nonflaky"
+      displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
+
+  - job: windows_msys2_mingw64_debug_openssl
+    displayName: msys2 mingw64 debug openssl
+    timeoutInMinutes: 70
+    pool:
+      vmImage: 'windows-2019'
+    container:
+      image: mback2k/curl-docker-winbuildenv-msys2-mingw64:ltsc2019
+      env:
+        MSYSTEM: MINGW64
+        MSYS2_PATH_TYPE: inherit
+        TFLAGS: "~323 ~1056 ~1299"
+    steps:
+    - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && 
./configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --enable-debug 
--enable-werror"
+      displayName: 'configure debug'
+
+    - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make"
+      displayName: 'make'
+
+    - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make 
test-nonflaky"
+      displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
+
+  - job: windows_msys1_mingw_debug_openssl
+    displayName: msys1 mingw debug openssl
+    timeoutInMinutes: 70
+    pool:
+      vmImage: 'windows-2019'
+    container:
+      image: mback2k/curl-docker-winbuildenv-msys1-mingw:ltsc2019
+      env:
+        TFLAGS: "~203 ~1056 ~1143"
+    steps:
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf 
&& ./configure --host=i686-pc-mingw32 --build=i686-pc-mingw32 --prefix=/mingw 
--enable-debug"
+      displayName: 'configure debug'
+
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make"
+      displayName: 'make'
+
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make 
test-nonflaky"
+      displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
+
+  - job: windows_msys1_mingw32_debug_openssl
+    displayName: msys1 mingw32 debug openssl
+    timeoutInMinutes: 70
+    pool:
+      vmImage: 'windows-2019'
+    container:
+      image: mback2k/curl-docker-winbuildenv-msys1-mingw32:ltsc2019
+      env:
+        TFLAGS: "~203 ~1056 ~1143 ~1299"
+    steps:
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf 
&& ./configure --host=i686-w64-mingw32 --build=i686-w64-mingw32 
--prefix=/mingw32 --enable-debug --enable-werror --without-zlib"
+      displayName: 'configure debug without zlib'
+
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make"
+      displayName: 'make'
+
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make 
test-nonflaky"
+      displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
+
+  - job: windows_msys1_mingw64_debug_openssl
+    displayName: msys1 mingw64 debug openssl
+    timeoutInMinutes: 70
+    pool:
+      vmImage: 'windows-2019'
+    container:
+      image: mback2k/curl-docker-winbuildenv-msys1-mingw64:ltsc2019
+      env:
+        TFLAGS: "~203 ~1056 ~1143 ~1299"
+    steps:
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf 
&& ./configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 
--prefix=/mingw64 --enable-debug --enable-werror --without-zlib"
+      displayName: 'configure debug without zlib'
+
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make"
+      displayName: 'make'
+
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make 
test-nonflaky"
+      displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
+
+  - job: windows_msys2_mingw32_debug_schannel
+    displayName: msys2 mingw32 debug schannel
+    timeoutInMinutes: 70
+    pool:
+      vmImage: 'windows-2019'
+    container:
+      image: mback2k/curl-docker-winbuildenv-msys2-mingw32:ltsc2019
+      env:
+        MSYSTEM: MINGW32
+        MSYS2_PATH_TYPE: inherit
+        TFLAGS: "~165 ~310 ~1013 ~1056 ~1299 ~1448 ~2034 ~2037 ~2041 ~2046 
~2047 ~3000 ~3001"
+    steps:
+    - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && 
./configure --host=i686-w64-mingw32 --build=i686-w64-mingw32 --enable-debug 
--enable-werror --enable-sspi --without-ssl --with-schannel --with-winidn"
+      displayName: 'configure debug with sspi/schannel/winidn'
+
+    - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make"
+      displayName: 'make'
+
+    - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make 
test-nonflaky"
+      displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
+
+  - job: windows_msys2_mingw64_debug_schannel
+    displayName: msys2 mingw64 debug schannel
+    timeoutInMinutes: 70
+    pool:
+      vmImage: 'windows-2019'
+    container:
+      image: mback2k/curl-docker-winbuildenv-msys2-mingw64:ltsc2019
+      env:
+        MSYSTEM: MINGW64
+        MSYS2_PATH_TYPE: inherit
+        TFLAGS: "~165 ~310 ~1013 ~1056 ~1299 ~1448 ~2034 ~2037 ~2041 ~2046 
~2047 ~3000 ~3001"
+    steps:
+    - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && 
./configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --enable-debug 
--enable-werror --enable-sspi --without-ssl --with-schannel --with-winidn"
+      displayName: 'configure debug with sspi/schannel/winidn'
+
+    - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make"
+      displayName: 'make'
+
+    - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make 
test-nonflaky"
+      displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
+
+  - job: windows_msys1_mingw_debug_schannel
+    displayName: msys1 mingw debug schannel
+    timeoutInMinutes: 70
+    pool:
+      vmImage: 'windows-2019'
+    container:
+      image: mback2k/curl-docker-winbuildenv-msys1-mingw:ltsc2019
+      env:
+        TFLAGS: "~203 ~305 ~310 ~311 ~312 ~313 ~404 ~1013 ~1056 ~1143 ~2034 
~2035 ~2037 ~2038 ~2041 ~2042 ~2048 ~3000 ~3001"
+    steps:
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf 
&& ./configure --host=i686-pc-mingw32 --build=i686-pc-mingw32 --prefix=/mingw 
--enable-debug --enable-sspi --without-ssl --with-schannel --with-winidn"
+      displayName: 'configure debug with sspi/schannel/winidn'
+
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make"
+      displayName: 'make'
+
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make 
test-nonflaky"
+      displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
+
+  - job: windows_msys1_mingw32_debug_schannel
+    displayName: msys1 mingw32 debug schannel
+    timeoutInMinutes: 70
+    pool:
+      vmImage: 'windows-2019'
+    container:
+      image: mback2k/curl-docker-winbuildenv-msys1-mingw32:ltsc2019
+      env:
+        TFLAGS: "~203 ~310 ~1013 ~1056 ~1143 ~1299 ~2034 ~2037 ~2041 ~3000 
~3001"
+    steps:
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf 
&& ./configure --host=i686-w64-mingw32 --build=i686-w64-mingw32 
--prefix=/mingw32 --enable-debug --enable-werror --enable-sspi --without-ssl 
--with-schannel --with-winidn --without-zlib"
+      displayName: 'configure debug with sspi/schannel/winidn without zlib'
+
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make"
+      displayName: 'make'
+
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make 
test-nonflaky"
+      displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
+
+  - job: windows_msys1_mingw64_debug_schannel
+    displayName: msys1 mingw64 debug schannel
+    timeoutInMinutes: 70
+    pool:
+      vmImage: 'windows-2019'
+    container:
+      image: mback2k/curl-docker-winbuildenv-msys1-mingw64:ltsc2019
+      env:
+        TFLAGS: "~203 ~310 ~1013 ~1056 ~1143 ~1299 ~2034 ~2037 ~2041 ~3000 
~3001"
+    steps:
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf 
&& ./configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 
--prefix=/mingw64  --enable-debug --enable-werror --enable-sspi --without-ssl 
--with-schannel --with-winidn --without-zlib"
+      displayName: 'configure debug with sspi/schannel/winidn without zlib'
+
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make"
+      displayName: 'make'
+
+    - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make 
test-nonflaky"
+      displayName: 'test'
+      env:
+        AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
diff --git a/.cirrus.yml b/.cirrus.yml
index 17a277145..5bf6b35a4 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -5,8 +5,8 @@ task:
   name: FreeBSD
   freebsd_instance:
     matrix:
-      # There isn't a stable 13.0 image yet (2019-12)
-      image_family: freebsd-13-0-snap
+      # A stable 13.0 image likely won't be available before early 2021
+      # image_family: freebsd-13-0-snap
       image_family: freebsd-12-1
       # The stable 11.3 image causes "Agent is not responding" so use a 
snapshot
       image_family: freebsd-11-3-snap
@@ -23,8 +23,8 @@ task:
     - case `uname -r` in
         13.0*)
         export CC=clang;
-        export CFLAGS="-fsanitize=address,undefined,signed-integer-overflow 
-fno-sanitize-recover=undefined,integer -Wformat -Werror=format-security 
-Werror=array-bounds -g"
-        export CXXFLAGS="-fsanitize=address,undefined 
-fno-sanitize-recover=undefined,integer -Wformat -Werror=format-security 
-Werror=array-bounds -g"
+        export CFLAGS="-fsanitize=address,undefined,signed-integer-overflow 
-fno-sanitize-recover=undefined,integer -Wformat -Werror=format-security 
-Werror=array-bounds -g";
+        export CXXFLAGS="-fsanitize=address,undefined 
-fno-sanitize-recover=undefined,integer -Wformat -Werror=format-security 
-Werror=array-bounds -g";
         export LDFLAGS="-fsanitize=address,undefined 
-fno-sanitize-recover=undefined,integer" ;;
       esac
     - ./configure --prefix="${HOME}"/install --enable-debug --with-libssh2 
--with-brotli --with-gssapi --with-libidn2 --enable-manual --enable-ldap 
--enable-ldaps --with-librtmp --with-libmetalink --with-libpsl --with-nghttp2 
|| { tail -300 config.log; false; }
diff --git a/.mailmap b/.mailmap
index 1fbbf1d89..626341a2c 100644
--- a/.mailmap
+++ b/.mailmap
@@ -58,3 +58,8 @@ Massimiliano Fantuzzi <address@hidden>
 Niall O'Reilly <address@hidden>
 Mohammad Hasbini <address@hidden>
 Andrew Ishchuk <address@hidden>
+Nicolas Guillier <address@hidden>
+Nikita Gillmann <address@hidden>
+Nikita Gillmann <address@hidden> ng0 <address@hidden>
+Nikita Gillmann <address@hidden> ng0 <address@hidden>
+Nikita Gillmann <address@hidden> Nils Gillmann <address@hidden>
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index eacb36493..4174168ec 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -65,7 +65,7 @@ matrix:
               - OVERRIDE_CC="CC=gcc-8" OVERRIDE_CXX="CXX=g++-8"
         - os: linux
           compiler: gcc
-          dist: xenial
+          dist: bionic
           env:
               - T=normal C="--disable-verbose" CPPFLAGS="-Wno-variadic-macros" 
NOTESTS=1
               - OVERRIDE_CC="CC=gcc-8" OVERRIDE_CXX="CXX=g++-8"
@@ -79,7 +79,7 @@ matrix:
                       - libbrotli-dev
         - os: linux
           compiler: gcc
-          dist: xenial
+          dist: bionic
           before_install:
               # Install and use the current stable release of Go
               - gimme --list
@@ -97,7 +97,7 @@ matrix:
                       - *common_packages
         - os: linux
           compiler: gcc
-          dist: xenial
+          dist: bionic
           before_install:
               # Install and use the current stable release of Go
               - gimme --list
@@ -130,7 +130,7 @@ matrix:
                       - libbrotli-dev
         - os: linux
           compiler: gcc
-          dist: xenial
+          dist: bionic
           env:
               - T=debug-wolfssl C="--with-wolfssl --without-ssl"
               - OVERRIDE_CC="CC=gcc-8" OVERRIDE_CXX="CXX=g++-8"
@@ -144,7 +144,7 @@ matrix:
                       - libbrotli-dev
         - os: linux
           compiler: gcc
-          dist: xenial
+          dist: bionic
           env:
               - T=debug-mesalink C="--with-mesalink --without-ssl"
               - OVERRIDE_CC="CC=gcc-8" OVERRIDE_CXX="CXX=g++-8"
@@ -207,7 +207,7 @@ matrix:
                       - libmbedtls-dev
         - os: linux
           compiler: clang
-          dist: xenial
+          dist: bionic
           env:
               - T=debug C="--with-gnutls --without-ssl"
               - OVERRIDE_CC="CC=clang-7" OVERRIDE_CXX="CXX=clang++-7"
@@ -215,7 +215,7 @@ matrix:
               apt:
                   sources:
                       - *common_sources
-                      - llvm-toolchain-xenial-7
+                      - llvm-toolchain-bionic-7
                   packages:
                       - *common_packages
                       - clang-7
@@ -224,7 +224,7 @@ matrix:
                       - libbrotli-dev
         - os: linux
           compiler: clang
-          dist: xenial
+          dist: bionic
           env:
               - T=debug C="--with-nss --without-ssl" NOTESTS=1 
CPPFLAGS="-isystem /usr/include/nss"
               - OVERRIDE_CC="CC=clang-7" OVERRIDE_CXX="CXX=clang++-7"
@@ -232,7 +232,7 @@ matrix:
               apt:
                   sources:
                       - *common_sources
-                      - llvm-toolchain-xenial-7
+                      - llvm-toolchain-bionic-7
                   packages:
                       - *common_packages
                       - clang-7
@@ -269,7 +269,7 @@ matrix:
           env: T=cmake
         - os: linux
           compiler: gcc
-          dist: xenial
+          dist: bionic
           env:
               - T=cmake
               - OVERRIDE_CC="CC=gcc-8" OVERRIDE_CXX="CXX=g++-8"
@@ -283,7 +283,7 @@ matrix:
                       - libbrotli-dev
         - os: linux
           compiler: clang
-          dist: xenial
+          dist: bionic
           env:
               - T=cmake
               - OVERRIDE_CC="CC=clang-7" OVERRIDE_CXX="CXX=clang++-7"
@@ -291,7 +291,7 @@ matrix:
               apt:
                   sources:
                       - *common_sources
-                      - llvm-toolchain-xenial-7
+                      - llvm-toolchain-bionic-7
                   packages:
                       - *common_packages
                       - clang-7
@@ -315,7 +315,7 @@ matrix:
                       - libssh2-1-dev
         - os: linux
           compiler: gcc
-          dist: xenial
+          dist: bionic
           env:
               - T=distcheck
               - OVERRIDE_CC="CC=gcc-8" OVERRIDE_CXX="CXX=g++-8"
@@ -329,7 +329,7 @@ matrix:
                       - libbrotli-dev
         - os: linux
           compiler: clang
-          dist: xenial
+          dist: bionic
           env:
               - T=fuzzer
               - OVERRIDE_CC="CC=clang-7" OVERRIDE_CXX="CXX=clang++-7"
@@ -337,7 +337,7 @@ matrix:
               apt:
                   sources:
                       - *common_sources
-                      - llvm-toolchain-xenial-7
+                      - llvm-toolchain-bionic-7
                   packages:
                       - *common_packages
                       - clang-7
@@ -345,7 +345,7 @@ matrix:
                       - libbrotli-dev
         - os: linux
           compiler: clang
-          dist: xenial
+          dist: bionic
           env:
               - T=tidy
               - OVERRIDE_CC="CC=clang-7" OVERRIDE_CXX="CXX=clang++-7"
@@ -353,7 +353,7 @@ matrix:
               apt:
                   sources:
                       - *common_sources
-                      - llvm-toolchain-xenial-7
+                      - llvm-toolchain-bionic-7
                   packages:
                       - *common_packages
                       - clang-7
@@ -362,7 +362,7 @@ matrix:
                       - libbrotli-dev
         - os: linux
           compiler: clang
-          dist: xenial
+          dist: bionic
           env:
               - T=scan-build
               - OVERRIDE_CC="CC=clang-7" OVERRIDE_CXX="CXX=clang++-7"
@@ -370,7 +370,7 @@ matrix:
               apt:
                   sources:
                       - *common_sources
-                      - llvm-toolchain-xenial-7
+                      - llvm-toolchain-bionic-7
                   packages:
                       - *common_packages
                       - clang-7
@@ -395,7 +395,7 @@ matrix:
         - os: linux
           arch: arm64
           compiler: gcc
-          dist: xenial
+          dist: bionic
           env:
               - T=debug C="--enable-alt-svc"
               - OVERRIDE_CC="CC=gcc-8" OVERRIDE_CXX="CXX=g++-8"
diff --git a/CMake/CurlSymbolHiding.cmake b/CMake/CurlSymbolHiding.cmake
index 224755a31..8e5fd67a0 100644
--- a/CMake/CurlSymbolHiding.cmake
+++ b/CMake/CurlSymbolHiding.cmake
@@ -11,13 +11,7 @@ if(CURL_HIDDEN_SYMBOLS)
     set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
     set(_CFLAG_SYMBOLS_HIDE "-fvisibility=hidden")
   elseif(CMAKE_COMPILER_IS_GNUCC)
-    if(NOT CMAKE_VERSION VERSION_LESS 2.8.10)
-      set(GCC_VERSION ${CMAKE_C_COMPILER_VERSION})
-    else()
-      execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
-                      OUTPUT_VARIABLE GCC_VERSION)
-    endif()
-    if(NOT GCC_VERSION VERSION_LESS 3.4)
+    if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4)
       # note: this is considered buggy prior to 4.0 but the autotools don't 
care, so let's ignore that fact
       set(SUPPORTS_SYMBOL_HIDING TRUE)
       set(_SYMBOL_EXTERN "__attribute__ ((__visibility__ (\"default\")))")
diff --git a/CMake/FindNSS.cmake b/CMake/FindNSS.cmake
index 277c7dfb2..0043ce853 100644
--- a/CMake/FindNSS.cmake
+++ b/CMake/FindNSS.cmake
@@ -10,6 +10,8 @@ set(NSS_LIBRARIES ${PC_NSS_LINK_LIBRARIES})
 set(NSS_INCLUDE_DIRS ${PC_NSS_INCLUDE_DIRS})
 
 include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(NSS DEFAULT_MSG NSS_INCLUDE_DIRS 
NSS_LIBRARIES)
+find_package_handle_standard_args(NSS
+    REQUIRED_VARS NSS_LIBRARIES NSS_INCLUDE_DIRS
+    VERSION_VAR PC_NSS_VERSION)
 
 mark_as_advanced(NSS_INCLUDE_DIRS NSS_LIBRARIES)
diff --git a/CMake/OtherTests.cmake b/CMake/OtherTests.cmake
index c1c9aa32a..8b150290c 100644
--- a/CMake/OtherTests.cmake
+++ b/CMake/OtherTests.cmake
@@ -32,7 +32,7 @@ int main(void) {
     return 0;
 }" curl_cv_recv)
 if(curl_cv_recv)
-  if(NOT DEFINED curl_cv_func_recv_args OR "${curl_cv_func_recv_args}" 
STREQUAL "unknown")
+  if(NOT DEFINED curl_cv_func_recv_args OR curl_cv_func_recv_args STREQUAL 
"unknown")
     foreach(recv_retv "int" "ssize_t" )
       foreach(recv_arg1 "SOCKET" "int" )
         foreach(recv_arg2 "char *" "void *" )
@@ -81,7 +81,7 @@ if(curl_cv_recv)
     string(REGEX REPLACE "^[^,]*,[^,]*,[^,]*,[^,]*,([^,]*)$" "\\1" 
RECV_TYPE_RETV "${curl_cv_func_recv_args}")
   endif()
 
-  if("${curl_cv_func_recv_args}" STREQUAL "unknown")
+  if(curl_cv_func_recv_args STREQUAL "unknown")
     message(FATAL_ERROR "Cannot find proper types to use for recv args")
   endif()
 else()
diff --git a/CMake/Utilities.cmake b/CMake/Utilities.cmake
index 5cb1d4497..ffc411ae9 100644
--- a/CMake/Utilities.cmake
+++ b/CMake/Utilities.cmake
@@ -2,12 +2,11 @@
 
 # Returns a list of arguments that evaluate to true
 function(count_true output_count_var)
-  set(lst)
+  set(lst_len 0)
   foreach(option_var IN LISTS ARGN)
     if(${option_var})
-      list(APPEND lst ${option_var})
+      math(EXPR lst_len "${lst_len} + 1")
     endif()
   endforeach()
-  list(LENGTH lst lst_len)
   set(${output_count_var} ${lst_len} PARENT_SCOPE)
 endfunction()
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5419b525b..97483ca8e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -38,7 +38,8 @@
 # To check:
 # (From Daniel Stenberg) The cmake build selected to run gcc with -fPIC on my 
box while the plain configure script did not.
 # (From Daniel Stenberg) The gcc command line use neither -g nor any -O 
options. As a developer, I also treasure our configure scripts's --enable-debug 
option that sets a long range of "picky" compiler options.
-cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.0...3.16 FATAL_ERROR)
+
 set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
 include(Utilities)
 include(Macros)
@@ -47,7 +48,9 @@ include(CheckCCompilerFlag)
 
 project(GNURL C)
 
-file(READ ${GNURL_SOURCE_DIR}/include/gnurl/curlver.h CURL_VERSION_H_CONTENTS)
+message(WARNING "the curl cmake build system is poorly maintained. Be aware")
+
+file(STRINGS $GNURL_SOURCE_DIR}/include/gnurl/curlver.h 
CURL_VERSION_H_CONTENTS REGEX "#define LIBCURL_VERSION( |_NUM )")
 string(REGEX MATCH "#define LIBCURL_VERSION \"[^\"]*"
   CURL_VERSION ${CURL_VERSION_H_CONTENTS})
 string(REGEX REPLACE "[^\"]+\"" "" CURL_VERSION ${CURL_VERSION})
@@ -77,7 +80,18 @@ option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
 if(WIN32)
   option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on 
Windows (/MT)." OFF)
   option(ENABLE_INET_PTON "Set to OFF to prevent usage of inet_pton when 
building against modern SDKs while still requiring compatibility with older 
Windows versions, such as Windows XP, Windows Server 2003 etc." ON)
+  set(CURL_TARGET_WINDOWS_VERSION "" CACHE STRING "Minimum target Windows 
version as hex string")
+  if(CURL_TARGET_WINDOWS_VERSION)
+    add_definitions(-D_WIN32_WINNT=${CURL_TARGET_WINDOWS_VERSION})
+  elseif(ENABLE_INET_PTON)
+    # _WIN32_WINNT_VISTA (0x0600)
+    add_definitions(-D_WIN32_WINNT=0x0600)
+  else()
+    # _WIN32_WINNT_WINXP (0x0501)
+    add_definitions(-D_WIN32_WINNT=0x0501)
+  endif()
 endif()
+option(CURL_LTO "Turn on compiler Link Time Optimizations" OFF)
 
 cmake_dependent_option(ENABLE_THREADED_RESOLVER "Set to ON to enable threaded 
DNS lookup"
         ON "NOT ENABLE_ARES"
@@ -91,8 +105,9 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
     foreach(_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings -Wunused 
-Wshadow -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes 
-Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wundef 
-Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes 
-Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits 
-Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered 
-Wignored-qualifiers -Wconversion -Wno-sign-conversion -Wv [...]
       # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each 
new
       # test result in.
-      check_c_compiler_flag(${_CCOPT} OPT${_CCOPT})
-      if(OPT${_CCOPT})
+      string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
+      check_c_compiler_flag(${_CCOPT} ${_optvarname})
+      if(${_optvarname})
         set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}")
       endif()
     endforeach()
@@ -121,7 +136,6 @@ if(ENABLE_ARES)
   set(USE_ARES 1)
   find_package(CARES REQUIRED)
   list(APPEND GNURL_LIBS ${CARES_LIBRARY})
-  set(GNURL_LIBS ${GNURL_LIBS} ${CARES_LIBRARY})
 endif()
 
 include(CurlSymbolHiding)
@@ -171,6 +185,22 @@ mark_as_advanced(CURL_DISABLE_SMTP)
 option(CURL_DISABLE_GOPHER "to disable Gopher" ON)
 mark_as_advanced(CURL_DISABLE_GOPHER)
 
+if(HTTP_ONLY)
+  set(CURL_DISABLE_FTP ON)
+  set(CURL_DISABLE_LDAP ON)
+  set(CURL_DISABLE_LDAPS ON)
+  set(CURL_DISABLE_TELNET ON)
+  set(CURL_DISABLE_DICT ON)
+  set(CURL_DISABLE_FILE ON)
+  set(CURL_DISABLE_TFTP ON)
+  set(CURL_DISABLE_RTSP ON)
+  set(CURL_DISABLE_POP3 ON)
+  set(CURL_DISABLE_IMAP ON)
+  set(CURL_DISABLE_SMB ON)
+  set(CURL_DISABLE_SMTP ON)
+  set(CURL_DISABLE_GOPHER ON)
+endif()
+
 option(CURL_DISABLE_COOKIES "to disable cookies support" OFF)
 mark_as_advanced(CURL_DISABLE_COOKIES)
 
@@ -284,7 +314,7 @@ if(WIN32)
 endif()
 
 # check SSL libraries
-# TODO support GNUTLS, POLARSSL, CYASSL
+# TODO support GnuTLS and WolfSSL
 
 if(APPLE)
   option(CMAKE_USE_SECTRANSP "enable Apple OS native SSL/TLS" OFF)
@@ -435,6 +465,10 @@ if(USE_NGHTTP2)
   list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES})
 endif()
 
+if(WIN32)
+  set(USE_WIN32_CRYPTO ON)
+endif()
+
 if(NOT CURL_DISABLE_LDAP)
   if(WIN32)
     option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON)
@@ -913,20 +947,7 @@ check_symbol_exists(fcntl          "${GNURL_INCLUDES}" 
HAVE_FCNTL)
 check_symbol_exists(ioctl          "${GNURL_INCLUDES}" HAVE_IOCTL)
 check_symbol_exists(setsockopt     "${GNURL_INCLUDES}" HAVE_SETSOCKOPT)
 check_function_exists(mach_absolute_time HAVE_MACH_ABSOLUTE_TIME)
-
-# symbol exists in win32, but function does not.
-if(WIN32)
-  if(ENABLE_INET_PTON)
-    check_function_exists(inet_pton HAVE_INET_PTON)
-    # _WIN32_WINNT_VISTA (0x0600)
-    add_definitions(-D_WIN32_WINNT=0x0600)
-  else()
-    # _WIN32_WINNT_WINXP (0x0501)
-    add_definitions(-D_WIN32_WINNT=0x0501)
-  endif()
-else()
-  check_function_exists(inet_pton HAVE_INET_PTON)
-endif()
+check_symbol_exists(inet_pton      "${CURL_INCLUDES}" HAVE_INET_PTON)
 
 check_symbol_exists(fsetxattr "${GNURL_INCLUDES}" HAVE_FSETXATTR)
 if(HAVE_FSETXATTR)
@@ -1150,6 +1171,23 @@ if(CURL_WERROR)
   endif()
 endif()
 
+if(CURL_LTO)
+  if(CMAKE_VERSION VERSION_LESS 3.9)
+    message(FATAL_ERROR "Requested LTO but your cmake version ${CMAKE_VERSION} 
is to old. You need at least 3.9")
+  endif()
+
+  cmake_policy(SET CMP0069 NEW)
+
+  include(CheckIPOSupported)
+  check_ipo_supported(RESULT CURL_HAS_LTO OUTPUT CURL_LTO_ERROR LANGUAGES C)
+  if(CURL_HAS_LTO)
+    message(STATUS "LTO supported and enabled")
+  else()
+    message(FATAL_ERROR "LTO was requested - but compiler doesn't support 
it\n${CURL_LTO_ERROR}")
+  endif()
+endif()
+
+
 # Ugly (but functional) way to include "Makefile.inc" by transforming it (= 
regenerate it).
 function(transform_makefile_inc INPUT_FILE OUTPUT_FILE)
   file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT)
@@ -1188,14 +1226,22 @@ if(BUILD_TESTING)
   add_subdirectory(tests)
 endif()
 
+# NTLM support requires crypto function adaptions from various SSL libs
+# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
+if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR 
USE_DARWINSSL OR USE_MBEDTLS OR USE_WIN32_CRYPTO))
+  set(use_ntlm ON)
+else()
+  set(use_ntlm OFF)
+endif()
+
 # Helper to populate a list (_items) with a label when conditions (the 
remaining
 # args) are satisfied
-function(_add_if label)
-  # TODO need to disable policy CMP0054 (CMake 3.1) to allow this indirection
+macro(_add_if label)
+  # needs to be a macro to allow this indirection
   if(${ARGN})
-    set(_items ${_items} "${label}" PARENT_SCOPE)
+    set(_items ${_items} "${label}")
   endif()
-endfunction()
+endmacro()
 
 # Clear list and try to detect available features
 set(_items)
@@ -1217,15 +1263,21 @@ _add_if("Kerberos"      NOT CURL_DISABLE_CRYPTO_AUTH AND
                         (HAVE_GSSAPI OR USE_WINDOWS_SSPI))
 # NTLM support requires crypto function adaptions from various SSL libs
 # TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
-if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR 
USE_SECTRANSP OR USE_MBEDTLS OR USE_NSS OR USE_GNUTLS))
-  _add_if("NTLM"        1)
-  # TODO missing option (autoconf: --enable-ntlm-wb)
-  _add_if("NTLM_WB"     NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
-endif()
+
+#if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR 
USE_SECTRANSP OR USE_MBEDTLS OR USE_NSS OR USE_GNUTLS))
+#  _add_if("NTLM"        1)
+#  # TODO missing option (autoconf: --enable-ntlm-wb)
+#  _add_if("NTLM_WB"     NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
+#endif()
+
+_add_if("NTLM"        use_ntlm)
+# TODO missing option (autoconf: --enable-ntlm-wb)
+_add_if("NTLM_WB"     use_ntlm AND NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
 # TODO missing option (--enable-tls-srp), depends on GNUTLS_SRP/OPENSSL_SRP
 _add_if("TLS-SRP"       USE_TLS_SRP)
 # TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header
 _add_if("HTTP2"         USE_NGHTTP2)
+_add_if("HTTPS-proxy"   SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS OR USE_NSS))
 string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
 message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
 
@@ -1250,6 +1302,8 @@ _add_if("POP3"          NOT CURL_DISABLE_POP3)
 _add_if("POP3S"         NOT CURL_DISABLE_POP3 AND SSL_ENABLED)
 _add_if("IMAP"          NOT CURL_DISABLE_IMAP)
 _add_if("IMAPS"         NOT CURL_DISABLE_IMAP AND SSL_ENABLED)
+_add_if("SMB"           NOT CURL_DISABLE_SMB 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("SMTPS"         NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
 _add_if("SCP"           USE_LIBSSH2)
diff --git a/README b/README
index b70ec28f3..e14fec55f 100644
--- a/README
+++ b/README
@@ -208,6 +208,8 @@ README
   curl binaries or other binaries that involve libcurl, you might enjoy the
   LICENSE-MIXING document.
 
+  All of those documents and more can be found in the docs/ directory.
+
 CONTACT
 
   If you have problems, questions, ideas or suggestions, please contact us
diff --git a/README.md b/README.md
index 8e1986ba1..16e4b006c 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@
 [![Coverity 
passed](https://scan.coverity.com/projects/curl/badge.svg)](https://scan.coverity.com/projects/curl)
 [![Travis-CI Build 
Status](https://travis-ci.org/curl/curl.svg?branch=master)](https://travis-ci.org/curl/curl)
 [![AppVeyor Build 
Status](https://ci.appveyor.com/api/projects/status/l1vv31029huhf4g4?svg=true)](https://ci.appveyor.com/project/curlorg/curl)
+[![Azure DevOps Build 
Status](https://dev.azure.com/daniel0244/curl/_apis/build/status/curl.curl?branchName=master)](https://dev.azure.com/daniel0244/curl/_build/latest?definitionId=1&branchName=master)
 [![Cirrus Build 
Status](https://api.cirrus-ci.com/github/curl/curl.svg?branch=master)](https://cirrus-ci.com/github/curl/curl)
 [![Backers on Open 
Collective](https://opencollective.com/curl/backers/badge.svg)](#backers)
 [![Sponsors on Open 
Collective](https://opencollective.com/curl/sponsors/badge.svg)](#sponsors)
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 7a1211271..ef3e38d14 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,146 +1,40 @@
-curl and libcurl 7.68.0
+curl and libcurl 7.69.1
 
- Public curl releases:         188
- Command line options:         229
- curl_easy_setopt() options:   269
+ Public curl releases:         190
+ Command line options:         230
+ curl_easy_setopt() options:   270
  Public functions in libcurl:  82
- Contributors:                 2088
-
-This release includes the following changes:
-
- o TLS: add BearSSL vtls implementation [37]
- o XFERINFOFUNCTION: support CURL_PROGRESSFUNC_CONTINUE [36]
- o curl: add --etag-compare and --etag-save [31]
- o curl: add --parallel-immediate [29]
- o multi: add curl_multi_wakeup() [38]
- o openssl: CURLSSLOPT_NO_PARTIALCHAIN can disable partial cert chains [45]
+ Contributors:                 2133
 
 This release includes the following bugfixes:
 
- o CVE-2019-15601: file: on Windows, refuse paths that start with \\ [106]
- o Azure Pipelines: add several builds
- o CMake: add support for building with the NSS vtls backend [43]
- o CURL-DISABLE: initial docs for the CURL_DISABLE_* defines [19]
- o CURLOPT_HEADERFUNCTION.3: Document that size is always 1 [100]
- o CURLOPT_QUOTE.3: fix typos [78]
- o CURLOPT_READFUNCTION.3: fix the example [107]
- o CURLOPT_URL.3: "curl supports SMB version 1 (only)"
- o CURLOPT_VERBOSE.3: see also ERRORBUFFER
- o HISTORY: added cmake, HTTP/3 and parallel downloads with curl
- o HISTORY: the SMB(S) support landed in 2014
- o INSTALL.md: provide Android build instructions [10]
- o KNOWN_BUGS: Connection information when using TCP Fast Open [85]
- o KNOWN_BUGS: LDAP on Windows doesn't work correctly [86]
- o KNOWN_BUGS: TLS session cache doesn't work with TFO [56]
- o OPENSOCKETFUNCTION.3: correct the purpose description [48]
- o TrackMemory tests: always remove CR before LF [111]
- o altsvc: bump to h3-24 [6]
- o altsvc: make the save function ignore NULL filenames [67]
- o build: Disable Visual Studio warning "conditional expression is constant" 
[49]
- o build: fix for CURL_DISABLE_DOH [2]
- o checksrc.bat: Add a check for vquic and vssh directories [40]
- o checksrc: repair the copyrightyear check [25]
- o cirrus-ci: enable clang sanitizers on freebsd 13 [60]
- o cirrus: Drop the FreeBSD 10.4 build
- o config-win32: cpu-machine-OS for Windows on ARM [13]
- o configure: avoid unportable `==' test(1) operator [1]
- o configure: enable IPv6 support without `getaddrinfo` [44]
- o configure: fix typo in help text [4]
- o conncache: CONNECT_ONLY connections assumed always in-use [71]
- o conncache: fix multi-thread use of shared connection cache [61]
- o copyrights: fix copyright year range [25]
- o create_conn: prefer multiplexing to using new connections [76]
- o curl -w: handle a blank input file correctly [105]
- o curl.h: add two missing defines for "pre ISO C" compilers [75]
- o curl/parseconfig: fix mem-leak [81]
- o curl/parseconfig: use curl_free() to free memory allocated by libcurl [80]
- o curl: cleanup multi handle on failure [103]
- o curl: fix --upload-file . hangs if delay in STDIN [35]
- o curl: fix -T globbing [16]
- o curl: improved cleanup in upload error path [69]
- o curl: make a few char pointers point to const char instead [95]
- o curl: properly free mimepost data [104]
- o curl: show better error message when no homedir is found [47]
- o curl: show error for --http3 if libcurl lacks support [108]
- o curl_setup_once: consistently use WHILE_FALSE in macros [54]
- o define: remove HAVE_ENGINE_LOAD_BUILTIN_ENGINES, not used anymore [83]
- o docs: Change 'experiemental' to 'experimental' [30]
- o docs: TLS SRP doesn't work with TLS 1.3 [87]
- o docs: fix several typos [62]
- o docs: mention CURL_MAX_INPUT_LENGTH restrictions [109]
- o doh: improved both encoding and decoding [11]
- o doh: make it behave when built without proxy support [68]
- o examples/postinmemory.c: Call curl_global_cleanup always [101]
- o examples/url2file.c: corrected erroneous comment [102]
- o examples: add multi-poll.c [14]
- o global_init: undo the "intialized" bump in case of failure [52]
- o hostip: suppress compiler warning [64]
- o http_ntlm: Remove duplicate NSS initialisation [55]
- o lib: Move lib/ssh.h -> lib/vssh/ssh.h [9]
- o lib: fix compiler warnings with `CURL_DISABLE_VERBOSE_STRINGS` [93]
- o lib: fix warnings found when porting to NuttX [99]
- o lib: remove ASSIGNWITHINCONDITION exceptions, use our code style [84]
- o lib: remove erroneous +x file permission on some c files [99]
- o libssh2: add support for ECDSA and ed25519 knownhost keys [89]
- o multi.h: remove INITIAL_MAX_CONCURRENT_STREAMS from public header [110]
- o multi: free sockhash on OOM [63]
- o multi_poll: avoid busy-loop when called without easy handles attached [15]
- o ngtcp2: Support the latest update key callback type [92]
- o ngtcp2: fix thread-safety bug in error-handling [33]
- o ngtcp2: free used resources on disconnect [7]
- o ngtcp2: handle key updates as ngtcp2 master branch tells us [8]
- o ngtcp2: increase QUIC window size when data is consumed [12]
- o ngtcp2: use overflow buffer for extra HTTP/3 data [5]
- o ntlm: USE_WIN32_CRYPTO check removed to get USE_NTLM2SESSION set [3]
- o ntlm_wb: fix double-free in OOM [65]
- o openssl: Revert to less sensitivity for SYSCALL errors [26]
- o openssl: improve error message for SYSCALL during connect [27]
- o openssl: prevent recursive function calls from ctx callbacks [18]
- o openssl: retrieve reported LibreSSL version at runtime [50]
- o openssl: set X509_V_FLAG_PARTIAL_CHAIN by default [46]
- o parsedate: offer a getdate_capped() alternative [53]
- o pause: avoid updating socket if done was already called [22]
- o projects: Fix Visual Studio projects SSH builds [41]
- o projects: Fix Visual Studio wolfSSL configurations
- o quiche: reject HTTP/3 headers in the wrong order [17]
- o remove_handle: clear expire timers after multi_done() [20]
- o runtests: --repeat=[num] to repeat tests [91]
- o runtests: introduce --shallow to reduce huge torture tests [70]
- o schannel: fix --tls-max for when min is --tlsv1 or default [39]
- o setopt: Fix ALPN / NPN user option when built without HTTP2 [42]
- o strerror: Add Curl_winapi_strerror for Win API specific errors [51]
- o strerror: Fix an error looking up some Windows error strings
- o strerror: Fix compiler warning "empty expression" [79]
- o system.h: fix for MCST lcc compiler [23]
- o test/sws: search for "Testno:" header unconditionally if no testno [73]
- o test1175: verify symbols-in-versions and libcurl-errors.3 in sync [28]
- o test1270: a basic -w redirect_url test [82]
- o test1456: remove the use of a fixed local port number [77]
- o test1558: use double slash after file: [21]
- o test1560: require IPv6 for IPv6 aware URL parsing [24]
- o tests/lib1557: fix mem-leak in OOM [66]
- o tests/lib1559: fix mem-leak in OOM [66]
- o tests/lib1591: free memory properly on OOM, in the trailers callback [90]
- o tests/unit1607: fix mem-leak in OOM [66]
- o tests/unit1609: fix mem-leak in OOM [66]
- o tests/unit1620: fix bad free in OOM [66]
- o tests: Change NTLM tests to require SSL [96]
- o tests: Fix bounce requests with truncated writes [94]
- o tests: fix build with `CURL_DISABLE_DOH` [64]
- o tests: fix permissions of ssh keys in WSL [58]
- o tests: make it possible to set executable extensions [58]
- o tests: make sure checksrc runs on header files too
- o tests: set LC_ALL=en_US.UTF-8 instead of blank in several tests [74]
- o tests: use DoH feature for DoH tests [64]
- o tests: use \r\n for log messages in WSL [58]
- o tool_operate: fix mem leak when failed config parse [98]
- o travis: Fix error detection [97]
- o travis: abandon coveralls, it is not reliable [57]
- o travis: build ngtcp2 with --enable-lib-only [32]
- o travis: export the CC/CXX variables when set [34]
- o vtls: make BearSSL possible to set with CURL_SSL_BACKEND [72]
- o winbuild: Define CARES_STATICLIB when WITH_CARES=static [59]
- o winbuild: Document CURL_STATICLIB requirement for static libcurl [88]
+ o ares: store dns parameters for duphandle [20]
+ o cirrus-ci: disable the FreeBSD 13 builds [3]
+ o curl_share_setopt.3: Note sharing cookies doesn't enable the engine [11]
+ o lib1564: reduce number of mid-wait wakeup calls [16]
+ o libssh: Fix matching user-specified MD5 hex key [7]
+ o MANUAL: update a dict-using command line
+ o mime: do not perform more than one read in a row [18]
+ o mime: fix the binary encoder to handle large data properly [17]
+ o mime: latch last read callback status [19]
+ o multi: skip EINTR check on wakeup socket if it was closed [12]
+ o pause: bail out on bad input [8]
+ o pause: force a connection recheck after unpausing (take 2) [5]
+ o pause: return early for calls that don't change pause state [10]
+ o runtests.1: rephrase how to specify what tests to run [2]
+ o runtests: fix missing use of exe_ext helper function
+ o seek: fix fall back for missing ftruncate on Windows [4]
+ o sftp: fix segfault regression introduced by #4747 in 7.69.0 [22]
+ o sha256: Added SecureTransport implementation [15]
+ o sha256: Added WinCrypt implementation [15]
+ o socks4: fix host resolve regression [14]
+ o socks5: host name resolv regression fix [6]
+ o tests/server: fix missing use of exe_ext helper function [24]
+ o tests: fix static ip:port instead of dynamic values being used [23]
+ o tests: make sleeping portable by avoiding select [1]
+ o unit1612: fix the inclusion and compilation of the HMAC unit test [9]
+ o urldata: remove the 'stream_was_rewound' connectdata struct member [13]
+ o version: make curl_version* thread-safe without using global context [21]
 
 This release includes the following known bugs:
 
@@ -149,137 +43,38 @@ This release includes the following known bugs:
 This release would not have looked like this without help, code, reports and
 advice from friends like these:
 
-  3dyd on github, Anderson Sasaki, Andreas Falkenhahn, Andrew Ishchuk,
-  bdry on github, Bjoern Franke, Brian Carpenter, bxac on github,
-  Bylon2 on github, Christian Schmitz, Christopher Head, Christopher Reid,
-  Christoph M. Becker, Cynthia Coan, Dan Fandrich, Daniel Gustafsson,
-  Daniel Stenberg, David Benjamin, Emil Engler, Fernando Muñoz, Frank Gevaerts,
-  Geeknik Labs, Gergely Nagy, Gisle Vanem, JanB on github, Javier Blazquez,
-  Jeff Mears, Jeffrey Walton, John Schroeder, Kamil Dudka,
-  kouzhudong on github, Kunal Ekawde, Leonardo Taccari, Marc Aldorasi,
-  Marcel Raad, marc-groundctl on github, Marc Hörsken, Maros Priputen,
-  Massimiliano Fantuzzi, Max Kellermann, Melissa Mears, Michael Forney,
-  Michael Vittiglio, Mohammad Hasbini, Niall O'Reilly, Paul Groke,
-  Paul Hoffman, Paul Joyce, Paulo Roberto Tomasi, Pavel Löbl, Pavel Pavlov,
-  Peter Wu, Ram Krushna Mishra, Ray Satiro, Richard Alcock, Richard Bowker,
-  Rickard Hallerbäck, Santino Keupp, sayrer on github, Shailesh Kapse,
-  Simon Warta, SLDiggie on github, Steve Holme, Tatsuhiro Tsujikawa,
-  Tom van der Woerdt, Victor Magierski, Vlastimil Ovčáčík, Wyatt O'Day,
-  Xiang Xiao, Xiaoyin Liu,
-  (70 contributors)
+  amishmm on github, Anders Berg, Andy Fiddaman, Christopher Reid,
+  Dan Fandrich, Daniel Stenberg, Ernst Sjöstrand, fds242 on github,
+  Fedor Korotkov, Felipe Gasper, Jim Fuller, Marcel Raad, Marc Hörsken,
+  MrdUkk on github, Patrick Monnerat, Ray Satiro, RuurdBeerstra on github,
+  Steve Holme, vitaha85 on github,
+  (19 contributors)
 
         Thanks! (and sorry if I forgot to mention someone)
 
 References to bug reports and discussions on issues:
 
- [1] = https://curl.haxx.se/bug/?i=4567
- [2] = https://curl.haxx.se/bug/?i=4565
- [3] = https://curl.haxx.se/bug/?i=3704
- [4] = https://curl.haxx.se/bug/?i=4570
- [5] = https://curl.haxx.se/bug/?i=4525
- [6] = https://curl.haxx.se/bug/?i=4604
- [7] = https://curl.haxx.se/bug/?i=4614
- [8] = https://curl.haxx.se/bug/?i=4612
- [9] = https://curl.haxx.se/bug/?i=4609
- [10] = https://curl.haxx.se/bug/?i=4606
- [11] = https://curl.haxx.se/bug/?i=4598
- [12] = https://curl.haxx.se/bug/?i=4600
- [13] = https://curl.haxx.se/bug/?i=4590
- [14] = https://curl.haxx.se/bug/?i=4596
- [15] = https://curl.haxx.se/bug/?i=4594
- [16] = https://curl.haxx.se/bug/?i=4588
- [17] = https://curl.haxx.se/bug/?i=4571
- [18] = https://curl.haxx.se/bug/?i=4585
- [19] = https://curl.haxx.se/bug/?i=4545
- [20] = https://curl.haxx.se/bug/?i=4575
- [21] = https://curl.haxx.se/bug/?i=4554
- [22] = https://curl.haxx.se/bug/?i=4563
- [23] = https://curl.haxx.se/bug/?i=4576
- [24] = https://curl.haxx.se/bug/?i=4556
- [25] = https://curl.haxx.se/bug/?i=4549
- [26] = https://curl.haxx.se/bug/?i=4624
- [27] = https://curl.haxx.se/bug/?i=4593
- [28] = https://curl.haxx.se/bug/?i=4628
- [29] = https://curl.haxx.se/bug/?i=4500
- [30] = https://curl.haxx.se/bug/?i=4618
- [31] = https://curl.haxx.se/bug/?i=4543
- [32] = https://curl.haxx.se/bug/?i=4646
- [33] = https://curl.haxx.se/bug/?i=4645
- [34] = https://curl.haxx.se/bug/?i=4637
- [35] = https://curl.haxx.se/bug/?i=2051
- [36] = https://curl.haxx.se/bug/?i=4599
- [37] = https://curl.haxx.se/bug/?i=4597
- [38] = https://curl.haxx.se/bug/?i=4418
- [39] = https://curl.haxx.se/bug/?i=4633
- [40] = https://curl.haxx.se/bug/?i=4607
- [41] = https://curl.haxx.se/bug/?i=4492
- [42] = https://curl.haxx.se/bug/?i=4668
- [43] = https://curl.haxx.se/bug/?i=4663
- [44] = https://curl.haxx.se/bug/?i=4662
- [45] = https://curl.haxx.se/bug/?i=4665
- [46] = https://curl.haxx.se/mail/lib-2019-11/0094.html
- [47] = https://curl.haxx.se/bug/?i=4644
- [48] = https://curl.haxx.se/mail/lib-2019-12/0007.html
- [49] = https://curl.haxx.se/bug/?i=4658
- [50] = https://curl.haxx.se/bug/?i=2425
- [51] = https://curl.haxx.se/bug/?i=4550
- [52] = https://curl.haxx.se/bug/?i=4636
- [53] = https://curl.haxx.se/bug/?i=4152
- [54] = https://curl.haxx.se/bug/?i=4649
- [55] = https://curl.haxx.se/bug/?i=3935
- [56] = https://curl.haxx.se/bug/?i=4301
- [57] = https://curl.haxx.se/bug/?i=4694
- [58] = https://curl.haxx.se/bug/?i=3899
- [59] = https://curl.haxx.se/bug/?i=4688
- [60] = https://curl.haxx.se/bug/?i=4557
- [61] = https://curl.haxx.se/bug/?i=4544
- [62] = https://curl.haxx.se/bug/?i=4680
- [63] = https://curl.haxx.se/bug/?i=4713
- [64] = https://curl.haxx.se/bug/?i=4692
- [65] = https://curl.haxx.se/bug/?i=4710
- [66] = https://curl.haxx.se/bug/?i=4709
- [67] = https://curl.haxx.se/bug/?i=4707
- [68] = https://curl.haxx.se/bug/?i=4704
- [69] = https://curl.haxx.se/bug/?i=4705
- [70] = https://curl.haxx.se/bug/?i=4699
- [71] = https://curl.haxx.se/bug/?i=4369
- [72] = https://curl.haxx.se/bug/?i=4698
- [73] = https://curl.haxx.se/bug/?i=4744
- [74] = https://curl.haxx.se/bug/?i=4738
- [75] = https://curl.haxx.se/bug/?i=4739
- [76] = https://curl.haxx.se/bug/?i=4732
- [77] = https://curl.haxx.se/bug/?i=4733
- [78] = https://curl.haxx.se/bug/?i=4736
- [79] = https://github.com/curl/curl/commit/5b22e1a#r36458547
- [80] = https://curl.haxx.se/bug/?i=4730
- [81] = https://curl.haxx.se/bug/?i=4731
- [82] = https://curl.haxx.se/bug/?i=4728
- [83] = https://curl.haxx.se/bug/?i=4725
- [84] = https://curl.haxx.se/bug/?i=4683
- [85] = https://curl.haxx.se/bug/?i=4296
- [86] = https://curl.haxx.se/bug/?i=4261
- [87] = https://curl.haxx.se/bug/?i=4262
- [88] = https://curl.haxx.se/bug/?i=4721
- [89] = https://curl.haxx.se/bug/?i=4714
- [90] = https://curl.haxx.se/bug/?i=4720
- [91] = https://curl.haxx.se/bug/?i=4715
- [92] = https://curl.haxx.se/bug/?i=4735
- [93] = https://curl.haxx.se/bug/?i=4775
- [94] = https://github.com/curl/curl/pull/4717#issuecomment-570240785
- [95] = https://curl.haxx.se/bug/?i=4771
- [96] = https://curl.haxx.se/bug/?i=4768
- [97] = https://curl.haxx.se/bug/?i=3730
- [98] = https://curl.haxx.se/bug/?i=4767
- [99] = https://curl.haxx.se/bug/?i=4756
- [100] = https://curl.haxx.se/bug/?i=4758
- [101] = https://curl.haxx.se/bug/?i=4751
- [102] = https://curl.haxx.se/bug/?i=4745
- [103] = https://curl.haxx.se/bug/?i=4772
- [104] = https://curl.haxx.se/bug/?i=4781
- [105] = https://curl.haxx.se/bug/?i=4786
- [106] = https://curl.haxx.se/docs/CVE-2019-15601.html
- [107] = https://curl.haxx.se/bug/?i=4787
- [108] = https://curl.haxx.se/bug/?i=4785
- [109] = https://curl.haxx.se/bug/?i=4783
- [110] = https://curl.haxx.se/bug/?i=4790
- [111] = https://curl.haxx.se/bug/?i=4788
+ [1] = https://curl.haxx.se/bug/?i=5035
+ [2] = https://curl.haxx.se/bug/?i=5033
+ [3] = https://curl.haxx.se/bug/?i=5028
+ [4] = https://curl.haxx.se/bug/?i=5055
+ [5] = https://curl.haxx.se/bug/?i=5049
+ [6] = https://curl.haxx.se/bug/?i=5053
+ [7] = https://curl.haxx.se/bug/?i=4971
+ [8] = https://curl.haxx.se/bug/?i=5050
+ [9] = https://curl.haxx.se/bug/?i=5024
+ [10] = https://curl.haxx.se/bug/?i=5026
+ [11] = https://curl.haxx.se/mail/lib-2020-03/0019.html
+ [12] = https://curl.haxx.se/bug/?i=5047
+ [13] = https://curl.haxx.se/bug/?i=5046
+ [14] = https://curl.haxx.se/bug/?i=5061
+ [15] = https://curl.haxx.se/bug/?i=5030
+ [16] = https://curl.haxx.se/bug/?i=5037
+ [17] = https://curl.haxx.se/bug/?i=4860
+ [18] = https://curl.haxx.se/bug/?i=4826
+ [19] = https://curl.haxx.se/bug/?i=4813
+ [20] = https://curl.haxx.se/bug/?i=4893
+ [21] = https://curl.haxx.se/bug/?i=5010
+ [22] = https://curl.haxx.se/bug/?i=5041
+ [23] = https://curl.haxx.se/bug/?i=5065
+ [24] = https://curl.haxx.se/bug/?i=5064
diff --git a/acinclude.m4 b/acinclude.m4
index 24dad3914..3ad55c388 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2018, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -2174,8 +2174,8 @@ AC_HELP_STRING([--without-ca-bundle], [Don't use a 
default CA bundle]),
   AC_ARG_WITH(ca-path,
 AC_HELP_STRING([--with-ca-path=DIRECTORY],
 [Path to a directory containing CA certificates stored individually, with \
-their filenames in a hash format. This option can be used with OpenSSL, \
-GnuTLS and PolarSSL backends. Refer to OpenSSL c_rehash for details. \
+their filenames in a hash format. This option can be used with the OpenSSL, \
+GnuTLS and mbedTLS backends. Refer to OpenSSL c_rehash for details. \
 (example: /etc/certificates)])
 AC_HELP_STRING([--without-ca-path], [Don't use a default CA path]),
   [
@@ -2201,8 +2201,8 @@ AC_HELP_STRING([--without-ca-path], [Don't use a default 
CA path]),
     capath="no"
   elif test "x$want_capath" != "xno" -a "x$want_capath" != "xunset"; then
     dnl --with-ca-path given
-    if test "x$OPENSSL_ENABLED" != "x1" -a "x$GNUTLS_ENABLED" != "x1" -a 
"x$POLARSSL_ENABLED" != "x1"; then
-      AC_MSG_ERROR([--with-ca-path only works with OpenSSL, GnuTLS or 
PolarSSL])
+    if test "x$OPENSSL_ENABLED" != "x1" -a "x$GNUTLS_ENABLED" != "x1" -a 
"x$MBEDTLS_ENABLED" != "x1"; then
+      AC_MSG_ERROR([--with-ca-path only works with OpenSSL, GnuTLS or mbedTLS])
     fi
     capath="$want_capath"
     ca="no"
diff --git a/appveyor.yml b/appveyor.yml
index 9b4ad5cf5..25361a0b6 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -81,7 +81,7 @@ environment:
         HTTP_ONLY: OFF
         TESTING: ON
         SHARED: OFF
-        DISABLED_TESTS: "!198 !1139"
+        DISABLED_TESTS: "!1139"
         COMPILER_PATH: 
"C:\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin"
         MSYS2_ARG_CONV_EXCL: "/*"
         BUILD_OPT: -k
diff --git a/configure.ac b/configure.ac
index 9b78ccd42..a7fec097f 100755
--- a/configure.ac
+++ b/configure.ac
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@ XC_OVR_ZZ60
 CURL_OVERRIDE_AUTOCONF
 
 dnl configure script copyright
-AC_COPYRIGHT([Copyright (c) 1998 - 2019 Daniel Stenberg, <address@hidden>
+AC_COPYRIGHT([Copyright (c) 1998 - 2020 Daniel Stenberg, <address@hidden>
 This configure script may be copied, distributed and modified under the
 terms of the curl license; see COPYING for more details])
 
@@ -2859,6 +2859,12 @@ if test X"$OPT_LIBMETALINK" != Xno; then
       AC_MSG_NOTICE([libmetalink library defective or too old])
       want_metalink="no"
     ])
+    if test "x$OPENSSL_ENABLED" != "x1" -a "x$USE_WINDOWS_SSPI" != "x1" \
+        -a "x$GNUTLS_ENABLED" != "x1" -a "x$NSS_ENABLED" != "x1" \
+        -a "x$SECURETRANSPORT_ENABLED" != "x1"; then
+      AC_MSG_WARN([metalink support requires a compatible SSL/TLS backend])
+      want_metalink="no"
+    fi
     CPPFLAGS="$clean_CPPFLAGS"
     LDFLAGS="$clean_LDFLAGS"
     LIBS="$clean_LIBS"
@@ -2884,17 +2890,23 @@ dnl 
**********************************************************************
 dnl Default to compiler & linker defaults for LIBSSH2 files & libraries.
 OPT_LIBSSH2=off
 AC_ARG_WITH(libssh2,dnl
-AC_HELP_STRING([--with-libssh2=PATH],[Where to look for libssh2, PATH points 
to the LIBSSH2 installation; when possible, set the PKG_CONFIG_PATH environment 
variable instead of using this option])
-AC_HELP_STRING([--with-libssh2], [enable LIBSSH2]),
+AC_HELP_STRING([--with-libssh2=PATH],[Where to look for libssh2, PATH points 
to the libssh2 installation; when possible, set the PKG_CONFIG_PATH environment 
variable instead of using this option])
+AC_HELP_STRING([--with-libssh2], [enable libssh2]),
   OPT_LIBSSH2=$withval, OPT_LIBSSH2=no)
 
 
 OPT_LIBSSH=off
 AC_ARG_WITH(libssh,dnl
-AC_HELP_STRING([--with-libssh=PATH],[Where to look for libssh, PATH points to 
the LIBSSH installation; when possible, set the PKG_CONFIG_PATH environment 
variable instead of using this option])
-AC_HELP_STRING([--with-libssh], [enable LIBSSH]),
+AC_HELP_STRING([--with-libssh=PATH],[Where to look for libssh, PATH points to 
the libssh installation; when possible, set the PKG_CONFIG_PATH environment 
variable instead of using this option])
+AC_HELP_STRING([--with-libssh], [enable libssh]),
   OPT_LIBSSH=$withval, OPT_LIBSSH=no)
 
+OPT_WOLFSSH=off
+AC_ARG_WITH(wolfssh,dnl
+AC_HELP_STRING([--with-wolfssh=PATH],[Where to look for wolfssh, PATH points 
to the wolfSSH installation; when possible, set the PKG_CONFIG_PATH environment 
variable instead of using this option])
+AC_HELP_STRING([--with-wolfssh], [enable wolfssh]),
+  OPT_WOLFSSH=$withval, OPT_WOLFSSH=no)
+
 if test X"$OPT_LIBSSH2" != Xno; then
   dnl backup the pre-libssh2 variables
   CLEANLDFLAGS="$LDFLAGS"
@@ -3044,6 +3056,28 @@ elif test X"$OPT_LIBSSH" != Xno; then
     CPPFLAGS=$CLEANCPPFLAGS
     LIBS=$CLEANLIBS
   fi
+elif test X"$OPT_WOLFSSH" != Xno; then
+  dnl backup the pre-wolfssh variables
+  CLEANLDFLAGS="$LDFLAGS"
+  CLEANCPPFLAGS="$CPPFLAGS"
+  CLEANLIBS="$LIBS"
+
+
+  if test "$OPT_WOLFSSH" != yes; then
+     WOLFCONFIG="$OPT_WOLFSSH/bin/wolfssh-config"
+     LDFLAGS="$LDFLAGS `$WOLFCONFIG --libs`"
+     CPPFLAGS="$CPPFLAGS `$WOLFCONFIG --cflags`"
+  fi
+
+  AC_CHECK_LIB(wolfssh, wolfSSH_Init)
+
+  AC_CHECK_HEADERS(wolfssh/ssh.h,
+    curl_ssh_msg="enabled (wolfSSH)"
+    WOLFSSH_ENABLED=1
+    AC_DEFINE(USE_WOLFSSH, 1, [if wolfSSH is in use])
+    AC_SUBST(USE_WOLFSSH, [1])
+  )
+
 fi
 
 dnl **********************************************************************
@@ -3448,9 +3482,9 @@ if test X"$want_h2" != Xno; then
     CPPFLAGS="$CPPFLAGS $CPP_H2"
     LIBS="$LIB_H2 $LIBS"
 
-    # use nghttp2_option_set_no_recv_client_magic to require nghttp2
-    # >= 1.0.0
-    AC_CHECK_LIB(nghttp2, nghttp2_option_set_no_recv_client_magic,
+    # use nghttp2_session_set_local_window_size to require nghttp2
+    # >= 1.12.0
+    AC_CHECK_LIB(nghttp2, nghttp2_session_set_local_window_size,
       [
        AC_CHECK_HEADERS(nghttp2/nghttp2.h,
           curl_h2_msg="enabled (nghttp2)"
@@ -3792,9 +3826,9 @@ if test X"$want_quiche" != Xno; then
         LIBS=$CLEANLIBS
     )
   else
-    dnl no nghttp3 pkg-config found, deal with it
+    dnl no quiche pkg-config found, deal with it
     if test X"$want_quiche" != Xdefault; then
-      dnl To avoid link errors, we do not allow --with-nghttp3 without
+      dnl To avoid link errors, we do not allow --with-quiche without
       dnl a pkgconfig file
       AC_MSG_ERROR([--with-quiche was specified but could not find quiche 
pkg-config file.])
     fi
@@ -4865,6 +4899,10 @@ if test "x$USE_LIBSSH" = "x1"; then
   SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SCP"
   SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SFTP"
 fi
+if test "x$USE_WOLFSSH" = "x1"; then
+  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SCP"
+  SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SFTP"
+fi
 if test "x$CURL_DISABLE_RTSP" != "x1"; then
   SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS RTSP"
 fi
diff --git a/docs/DEPRECATE.md b/docs/DEPRECATE.md
index 4f4ef8ab6..26877c48a 100644
--- a/docs/DEPRECATE.md
+++ b/docs/DEPRECATE.md
@@ -5,32 +5,8 @@ email the curl-library mailing list as soon as possible and 
explain to us why
 this is a problem for you and how your use case can't be satisfied properly
 using a work around.
 
-## PolarSSL
+## Past removals
 
-The polarssl TLS library has not had an update in over three years. The last
-release was done on [January 7
-2016](https://tls.mbed.org/tech-updates/releases). This library has been
-superseded by the mbedTLS library, which is the current incarnation of
-PolarSSL. curl has supported mbedTLS since 2015.
-
-It seems unlikely that this library is a good choice for users to get proper
-TLS security and support today and at the same time there are plenty of good
-and updated alternatives.
-
-I consider it likely that the existing users of curl + polarssl out there are
-stuck on old curl versions and when they eventually manage to update curl they
-should also be able to update their TLS library.
-
-### State
-
-In the curl 7.65.2 release (July 17, 2019) the ability to build with this TLS
-backend is removed from the configure script. The code remains and can be
-built and used going forward, but it has to be manually enabled in a build (or
-the configure removal reverted).
-
-### Removal
-
-The support for PolarSSL and all code for it will be completely removed from
-the curl code base six months after it ships disabled in configure in a
-release. In the release on or near February 27, 2020. (possibly called curl
-7.70.0).
+ - Pipelining
+ - axTLS
+ - PolarSSL
diff --git a/docs/GOVERNANCE.md b/docs/GOVERNANCE.md
index d49358b95..81747179b 100644
--- a/docs/GOVERNANCE.md
+++ b/docs/GOVERNANCE.md
@@ -18,7 +18,8 @@ expects from us.
 
 There is no legal entity. The curl project is just a bunch of people scattered
 around the globe with the common goal to produce source code that creates
-great products.
+great products. We are not part of any umbrella organization and we are not
+located in any specific country. We are totally independent.
 
 The copyrights in the project are owned by the individuals and organizations
 that wrote those parts of the code.
@@ -36,6 +37,28 @@ If there is no obvious consensus, a maintainer who's 
knowledgeable in the
 specific area will take an "executive" decision that they think is the right
 for the project.
 
+## Donations
+
+Donating plain money to curl is best done to curl's [Open Collective
+fund](https://opencollective.com/curl). Open Collective is a US based
+non-profit organization that holds on to funds for us. This fund is then used
+for paying the curl security bug bounties, to reimburse project related
+expenses etc.
+
+Donations to the project can also come in form of server hosting, providing
+services and paying for people to work on curl related code etc. Usually, such
+donations are services paid for directly by the sponsors.
+
+We grade sponsors in a few different levels and if they meet the criterias,
+they can be mentioned on the Sponsors page on the curl web site.
+
+## Commercial Support
+
+The curl project does not do or offer commercial support. It only hosts
+mailing lists, runs bug trackers etc to facilitate communication and work.
+
+However, Daniel works for wolfSSL and we offer commercial curl support there.
+
 ## Key roles
 
 ### Maintainers
@@ -108,8 +131,8 @@ within the area of personal expertise and experience.
 
 ### Recommendations
 
-- please enable 2fa on your github account to reduce risk of malicious source
-  code tampering
+- we require two-factor authentication enabled on your github account to
+  reduce risk of malicious source code tampering
 - consider enabling signed git commits for additional verification of changes
 
 ### Merge advice
diff --git a/docs/HTTP-COOKIES.md b/docs/HTTP-COOKIES.md
index 06790f8a7..31af9f6d9 100644
--- a/docs/HTTP-COOKIES.md
+++ b/docs/HTTP-COOKIES.md
@@ -43,6 +43,27 @@
   When libcurl saves a cookiejar, it creates a file header of its own in which
   there is a URL mention that will link to the web version of this document.
 
+## Cookie file format
+
+  The cookie file format is text based and stores one cookie per line. Lines
+  that start with `#` are treated as comments.
+
+  Each line that each specifies a single cookie consists of seven text fields
+  separated with TAB characters. A valid line must end with a newline
+  character.
+
+### Fields in the file
+
+  Field number, what type and example data and the meaning of it:
+
+  0. string `example.com` - the domain name
+  1. boolean `FALSE` - include subdomains
+  2. string `/foobar/` - path
+  3. boolean `TRUE` - send/receive over HTTPS only
+  4. number `1462299217` - expires at - seconds since Jan 1st 1970, or 0
+  5. string `person` - name of the cookie
+  6. string `daniel` - value of the cookie
+
 ## Cookies with curl the command line tool
 
   curl has a full cookie "engine" built in. If you just activate it, you can
diff --git a/docs/HTTP3.md b/docs/HTTP3.md
index c77f7743d..55bdd0263 100644
--- a/docs/HTTP3.md
+++ b/docs/HTTP3.md
@@ -33,7 +33,7 @@ in the master branch using pull-requests, just like ordinary 
changes.
 
 Build (patched) OpenSSL
 
-     % git clone --depth 1 -b openssl-quic-draft-23 
https://github.com/tatsuhiro-t/openssl
+     % git clone --depth 1 -b OpenSSL_1_1_1d-quic-draft-27 
https://github.com/tatsuhiro-t/openssl
      % cd openssl
      % ./config enable-tls1_3 --prefix=<somewhere1>
      % make
@@ -65,7 +65,7 @@ Build curl
      % git clone https://github.com/curl/curl
      % cd curl
      % ./buildconf
-     % LDFLAGS="-Wl,-rpath,<somewhere1>/lib" ./configure 
--with-ssl=<somewhere1> --with-nghttp3=<somewhere2> --with-ngtcp2=<somewhere3>
+     % LDFLAGS="-Wl,-rpath,<somewhere1>/lib" ./configure 
--with-ssl=<somewhere1> --with-nghttp3=<somewhere2> --with-ngtcp2=<somewhere3> 
--enable-alt-svc
      % make
 
 # quiche version
@@ -93,13 +93,13 @@ Build quiche:
      % cd ../..
      % QUICHE_BSSL_PATH=$PWD/deps/boringssl cargo build --release --features 
pkg-config-meta
 
-Clone and build curl:
+Build curl:
 
      % cd ..
      % git clone https://github.com/curl/curl
      % cd curl
      % ./buildconf
-     % ./configure LDFLAGS="-Wl,-rpath,$PWD/../quiche/target/release" 
--with-ssl=$PWD/../quiche/deps/boringssl/.openssl 
--with-quiche=$PWD/../quiche/target/release
+     % ./configure LDFLAGS="-Wl,-rpath,$PWD/../quiche/target/release" 
--with-ssl=$PWD/../quiche/deps/boringssl/.openssl 
--with-quiche=$PWD/../quiche/target/release --enable-alt-svc
      % make
 
 ## Run
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index 380f3b38e..63d41421b 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -115,7 +115,6 @@ libressl.
  - GnuTLS: `--without-ssl --with-gnutls`.
  - wolfSSL: `--without-ssl --with-wolfssl`
  - NSS: `--without-ssl --with-nss`
- - PolarSSL: `--without-ssl --with-polarssl`
  - mbedTLS: `--without-ssl --with-mbedtls`
  - schannel: `--without-ssl --with-schannel`
  - secure transport: `--without-ssl --with-secure-transport`
diff --git a/docs/INTERNALS.md b/docs/INTERNALS.md
index 9ae722898..add8b417f 100644
--- a/docs/INTERNALS.md
+++ b/docs/INTERNALS.md
@@ -95,9 +95,8 @@ Dependencies
  - MIT Kerberos 1.2.4
  - GSKit        V5R3M0
  - NSS          3.14.x
- - PolarSSL     1.3.0
  - Heimdal      ?
- - nghttp2      1.0.0
+ - nghttp2      1.12.0
 
 Operating Systems
 -----------------
diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS
index 5fd230f86..26f21dc67 100644
--- a/docs/KNOWN_BUGS
+++ b/docs/KNOWN_BUGS
@@ -12,6 +12,7 @@ check the changelog of the current development status, as one 
or more of these
 problems may have been fixed or changed somewhat since this was written!
 
  1. HTTP
+ 1.2 Multiple methods in a single WWW-Authenticate: header
  1.3 STARTTRANSFER time is wrong for HTTP POSTs
  1.4 multipart formposts file name encoding
  1.5 Expect-100 meets 417
@@ -35,8 +36,8 @@ problems may have been fixed or changed somewhat since this 
was written!
  3. Email protocols
  3.1 IMAP SEARCH ALL truncated response
  3.2 No disconnect command
- 3.3 SMTP to multiple recipients
- 3.4 POP3 expects "CRLF.CRLF" eob for some single-line responses
+ 3.3 POP3 expects "CRLF.CRLF" eob for some single-line responses
+ 3.4 AUTH PLAIN for SMTP is not working on all servers
 
  4. Command line
  4.1 -J and -O with %-encoded file names
@@ -56,6 +57,7 @@ problems may have been fixed or changed somewhat since this 
was written!
  5.8 configure finding libs in wrong directory
  5.9 Utilize Requires.private directives in libcurl.pc
  5.10 IDN tests failing on Windows / MSYS2
+ 5.11 configure --with-gssapi with Heimdal is ignored on macOS
 
  6. Authentication
  6.1 NTLM authentication and unicode
@@ -86,8 +88,6 @@ problems may have been fixed or changed somewhat since this 
was written!
  9.1 SFTP doesn't do CURLOPT_POSTQUOTE correct
 
  10. SOCKS
- 10.1 SOCKS proxy connections are done blocking
- 10.2 SOCKS don't support timeouts
  10.3 FTPS over SOCKS
  10.4 active FTP over a SOCKS
 
@@ -115,6 +115,13 @@ problems may have been fixed or changed somewhat since 
this was written!
 
 1. HTTP
 
+1.2 Multiple methods in a single WWW-Authenticate: header
+
+ The HTTP responses headers WWW-Authenticate: can provide information about
+ multiple authentication methods as multiple headers or as several methods
+ within a single header. The latter way, several methods in the same physical
+ line, is not supported by libcurl's parser. (For no good reason.)
+
 1.3 STARTTRANSFER time is wrong for HTTP POSTs
 
  Wrong STARTTRANSFER timer accounting for POST requests Timer works fine with
@@ -143,7 +150,7 @@ problems may have been fixed or changed somewhat since this 
was written!
 1.6 Unnecessary close when 401 received waiting for 100
 
  libcurl closes the connection if an HTTP 401 reply is received while it is
- waiting for the the 100-continue response.
+ waiting for the 100-continue response.
  https://curl.haxx.se/mail/lib-2008-08/0462.html
 
 1.7 Deflate error after all content was received
@@ -275,20 +282,18 @@ problems may have been fixed or changed somewhat since 
this was written!
  The disconnect commands (LOGOUT and QUIT) may not be sent by IMAP, POP3 and
  SMTP if a failure occurs during the authentication phase of a connection.
 
-3.3 SMTP to multiple recipients
-
- When sending data to multiple recipients, curl will abort and return failure
- if one of the recipients indicate failure (on the "RCPT TO"
- command). Ordinary mail programs would proceed and still send to the ones
- that can receive data. This is subject for change in the future.
- https://curl.haxx.se/bug/view.cgi?id=1116
-
-3.4 POP3 expects "CRLF.CRLF" eob for some single-line responses
+3.3 POP3 expects "CRLF.CRLF" eob for some single-line responses
 
  You have to tell libcurl not to expect a body, when dealing with one line
  response commands. Please see the POP3 examples and test cases which show
  this for the NOOP and DELE commands. https://curl.haxx.se/bug/?i=740
 
+3.4 AUTH PLAIN for SMTP is not working on all servers
+
+ Specifying "--login-options AUTH=PLAIN" on the command line doesn't seem to
+ work correctly.
+
+ See https://github.com/curl/curl/issues/4080
 
 4. Command line
 
@@ -433,6 +438,12 @@ problems may have been fixed or changed somewhat since 
this was written!
 
  https://github.com/curl/curl/issues/3747
 
+5.11 configure --with-gssapi with Heimdal is ignored on macOS
+
+ ... unless you also pass --with-gssapi-libs
+
+ https://github.com/curl/curl/issues/3841
+
 6. Authentication
 
 6.1 NTLM authentication and unicode
@@ -615,21 +626,6 @@ problems may have been fixed or changed somewhat since 
this was written!
 
 10. SOCKS
 
-10.1 SOCKS proxy connections are done blocking
-
- Both SOCKS5 and SOCKS4 proxy connections are done blocking, which is very bad
- when used with the multi interface.
-
-10.2 SOCKS don't support timeouts
-
- The SOCKS4 connection codes don't properly acknowledge (connect) timeouts.
- According to bug #1556528, even the SOCKS5 connect code does not do it right:
- https://curl.haxx.se/bug/view.cgi?id=604
-
- When connecting to a SOCK proxy, the (connect) timeout is not properly
- acknowledged after the actual TCP connect (during the SOCKS "negotiate"
- phase).
-
 10.3 FTPS over SOCKS
 
  libcurl doesn't support FTPS over a SOCKS proxy.
diff --git a/docs/MANUAL.md b/docs/MANUAL.md
index 73ce57d44..7063dbc8b 100644
--- a/docs/MANUAL.md
+++ b/docs/MANUAL.md
@@ -745,7 +745,7 @@ For fun try
 
     curl dict://dict.org/m:curl
     curl dict://dict.org/d:heisenbug:jargon
-    curl dict://dict.org/d:daniel:web1913
+    curl dict://dict.org/d:daniel:gcide
 
 Aliases for 'm' are 'match' and 'find', and aliases for 'd' are 'define' and
 'lookup'. For example,
diff --git a/docs/RELEASE-PROCEDURE.md b/docs/RELEASE-PROCEDURE.md
index d203458be..f2b4343bd 100644
--- a/docs/RELEASE-PROCEDURE.md
+++ b/docs/RELEASE-PROCEDURE.md
@@ -61,12 +61,12 @@ celebrate
 curl release scheduling
 =======================
 
-Basics
-------
+Release Cycle
+-------------
 
 We do releases every 8 weeks on Wednesdays. If critical problems arise, we can
 insert releases outside of the schedule or we can move the release date - but
-this is very rare.
+this is rare.
 
 Each 8 week release cycle is split in two 4-week periods.
 
@@ -78,20 +78,28 @@ Each 8 week release cycle is split in two 4-week periods.
   then only focus on fixing bugs and polishing things to make a solid coming
   release.
 
+- After a regular procedure-following release (made on Wednesdays), the
+  feature window remains closed until the following Monday in case of special
+  actions or patch releases etc.
+
+If a future release date happens to end up on a "bad date", like in the middle
+of common public holidays or when the lead release manager is away traveling,
+the release date can be moved forwards or backwards a full week. This is then
+advertised well in advance.
+
 Coming dates
 ------------
 
 Based on the description above, here are some planned release dates (at the
 time of this writing):
 
-- January 8, 2020 (moved)
-- February 27, 2020
-- April 22, 2020
-- June 17, 2020
-- August 12, 2020
-- October 7, 2020
-- December 2, 2020
-- January 27, 2021
+- March 4, 2020 (7.69.0)
+- April 29, 2020
+- June 24, 2020
+- August 19, 2020
+- October 14, 2020
+- December 9, 2020
+- February 3, 2021
 
 The above (and more) curl-related dates are published in
 [iCalendar 
format](https://calendar.google.com/calendar/ical/c9u5d64odop9js55oltfarjk6g%40group.calendar.google.com/public/basic.ics)
diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md
index 1d47682bf..7bd07196f 100644
--- a/docs/ROADMAP.md
+++ b/docs/ROADMAP.md
@@ -27,6 +27,13 @@ ESNI (Encrypted SNI)
 
  Initial work exists in https://github.com/curl/curl/pull/4011
 
+thread-safe `curl_global_init()`
+--------------------------------
+
+ Fix the libcurl specific parts of the function to be thread-safe. Make sure
+ it can be thread-safe if built with thread-safe 3rd party libraries.
+ (probably can't include `curl_global_init_mem()` for obvious reasons)
+
 tiny-curl
 ---------
 
diff --git a/docs/THANKS b/docs/THANKS
index af74c0bd6..53735cb6f 100644
--- a/docs/THANKS
+++ b/docs/THANKS
@@ -4,15 +4,15 @@
 
  If you have contributed but are missing here, please let us know!
 
-"Captain Basil"
-"Spoon Man"
 1ocalhost on github
 3dyd on github
 Aaro Koskinen
 Aaron Oneal
 Aaron Orenstein
 Aaron Scarisbrick
+aasivov on github
 Abram Pousada
+accountantM on github
 AceCrow on Github
 Adam Barclay
 Adam Brown
@@ -24,10 +24,13 @@ Adam Marcionek
 Adam Piggott
 Adam Sampson
 Adam Tkac
+adnn on github
 Adrian Burcea
 Adrian Peniak
 Adrian Schuur
 Adriano Meirelles
+afrind on github
+ahodesuka on github
 Ajit Dhumale
 Akhil Kedia
 Aki Koskinen
@@ -46,6 +49,7 @@ Ales Mlakar
 Ales Novak
 Alessandro Ghedini
 Alessandro Vesely
+Alex aka WindEagle
 Alex Baines
 Alex Bligh
 Alex Chan
@@ -63,7 +67,6 @@ Alex Rousskov
 Alex Samorukov
 Alex Suykov
 Alex Vinnik
-Alex aka WindEagle
 Alexander Beedie
 Alexander Dyagilev
 Alexander Elgert
@@ -88,12 +91,14 @@ Alfonso Martone
 Alfred Gebert
 Allen Pulsifer
 Alona Rossen
+amishmm on github
 Amit Katyal
 Amol Pattekar
 Amr Shahin
 Anatol Belski
 Anatoli Tubman
 Anders Bakken
+Anders Berg
 Anders Gustafsson
 Anders Havn
 Anders Roxell
@@ -127,6 +132,7 @@ Andrej E Baranov
 Andrew Benham
 Andrew Biggs
 Andrew Bushnell
+Andrew de los Reyes
 Andrew Francis
 Andrew Fuller
 Andrew Ishchuk
@@ -134,16 +140,19 @@ Andrew Krieger
 Andrew Kurushin
 Andrew Lambert
 Andrew Moise
+Andrew Potter
 Andrew Robbins
 Andrew Wansink
-Andrew de los Reyes
 Andrey Labunets
 Andrii Moiseiev
+Andrius Merkys
 Andrés García
 Andy Cedilnik
+Andy Fiddaman
 Andy Serpa
 Andy Tsouladze
 Angus Mackay
+anshnd on github
 Anthon Pang
 Anthony Avina
 Anthony Bryan
@@ -159,6 +168,7 @@ Antoni Villalonga
 Antonio Larrosa
 Antony74 on github
 Antti Hätälä
+arainchik on github
 Archangel_SDY on github
 Arkadiusz Miskiewicz
 Armel Asselin
@@ -166,15 +176,18 @@ Arnaud Compan
 Arnaud Ebalard
 Arnaud Rebillout
 Aron Bergman
+Aron Rotteveel
 Artak Galoyan
 Arthur Murray
 Arve Knudsen
 Arvid Norberg
+asavah on github
 Ashish Shukla
 Ask Bjørn Hansen
 Askar Safin
 Ates Goral
 Augustus Saunders
+Austin Green
 Avery Fay
 Axel Tillequin
 Ayoub Boudhar
@@ -190,6 +203,8 @@ Bas Mevissen
 Bas van Schaik
 Bastien Bouclet
 Basuke Suzuki
+baumanj on github
+bdry on github
 Ben Boeckel
 Ben Darnell
 Ben Greear
@@ -231,9 +246,11 @@ Bjorn Augustsson
 Bjorn Reese
 Björn Stenberg
 Blaise Potard
+bnfp on github
 Bob Relyea
 Bob Richmond
 Bob Schader
+bobmitchell1956 on github
 Bogdan Nicula
 Brad Burdick
 Brad Fitzpatrick
@@ -242,6 +259,7 @@ Brad Hards
 Brad King
 Brad Spencer
 Bradford Bruce
+bramus on github
 Brandon Casey
 Brandon Dong
 Brandon Wang
@@ -262,11 +280,14 @@ Brock Noland
 Bru Rom
 Bruce Mitchener
 Bruce Stephens
+Bruno de Carvalho
 Bruno Grasselli
 Bruno Thomsen
-Bruno de Carvalho
 Bryan Henderson
 Bryan Kemp
+bsammon on github
+buzo-ffm on github
+bxac on github
 Bylon2 on github
 Byrial Jensen
 Caleb Raitto
@@ -274,6 +295,7 @@ Cameron Kaiser
 Cameron MacMinn
 Camille Moncelier
 Caolan McNamara
+Captain Basil
 Carie Pointer
 Carlo Cannas
 Carlo Marcelo Arenas Belón
@@ -283,6 +305,8 @@ Carlos ORyan
 Carsten Lange
 Casey O'Donnell
 Catalin Patulea
+cbartl on github
+cclauss on github
 Chad Monroe
 Chandrakant Bagul
 Charles Kerr
@@ -330,11 +354,14 @@ Ciprian Badescu
 Claes Jakobsson
 Clarence Gardner
 Claudio Neves
+clbr on github
 Clemens Gruber
 Cliff Crosland
 Clifford Wolf
 Clint Clayton
 Clément Notin
+cmfrolick on github
+codesniffer13 on github
 Cody Jones
 Cody Mack
 Colby Ranger
@@ -347,10 +374,13 @@ Cory Benfield
 Cory Nelson
 Costya Shulyupin
 Craig A West
+Craig Andrews
 Craig Davison
-Craig Markwardt
 Craig de Stigter
+Craig Markwardt
+crazydef on github
 Cris Bailiff
+Cristian Greco
 Cristian Rodríguez
 Curt Bogmine
 Cynthia Coan
@@ -359,7 +389,9 @@ Cyrill Osterwalder
 Cédric Connes
 Cédric Deltheil
 D. Flinkmann
+d912e3 on github
 Da-Yoon Chung
+daboul on github
 Dag Ekengren
 Dagobert Michelsen
 Dair Grant
@@ -379,6 +411,7 @@ Dan Nelson
 Dan Petitt
 Dan Torop
 Dan Zitter
+Daniel at touchtunes
 Daniel Bankhead
 Daniel Black
 Daniel Cater
@@ -391,6 +424,7 @@ Daniel Kahn Gillmor
 Daniel Krügler
 Daniel Lee Hwang
 Daniel Lublin
+Daniel Marjamäki
 Daniel Melani
 Daniel Mentz
 Daniel Romero
@@ -401,13 +435,13 @@ Daniel Silverstone
 Daniel Steinberg
 Daniel Stenberg
 Daniel Theron
-Daniel at touchtunes
 Daphne Luong
 Dario Nieuwenhuis
 Dario Weißer
 Darryl House
 Darshan Mody
 Darío Hereñú
+dasimx on github
 Dave Dribin
 Dave Halbakken
 Dave Hamilton
@@ -435,6 +469,7 @@ David Kimdon
 David L.
 David Lang
 David LeBlanc
+David Lopes
 David Lord
 David McCreedy
 David Odin
@@ -451,6 +486,7 @@ David Walser
 David Woodhouse
 David Wright
 David Yan
+dbrowndan on github
 Dengminwen
 Denis Chaplygin
 Denis Feklushkin
@@ -458,6 +494,7 @@ Denis Ollier
 Dennis Clarke
 Derek Higgins
 Desmond O. Chang
+destman on github
 Detlef Schmier
 Dheeraj Sangamkar
 Didier Brisebourg
@@ -476,9 +513,12 @@ Dinar
 Dirk Eddelbuettel
 Dirk Feytons
 Dirk Manske
+dkjjr89 on github
+dkwolfe4 on github
 Dmitri Shubin
 Dmitri Tikhonov
 Dmitriy Sergeyev
+dmitrmax on github
 Dmitry Bartsevich
 Dmitry Eremin-Solenikov
 Dmitry Falko
@@ -488,6 +528,7 @@ Dmitry Mikhirev
 Dmitry Popov
 Dmitry Rechkin
 Dmitry S. Baikov
+dnivras on github
 Dolbneff A.V
 Domenico Andreoli
 Dominick Meglio
@@ -505,7 +546,9 @@ Douglas Mencken
 Douglas R. Horner
 Douglas Steinwand
 Dov Murik
+dpull on github
 Drake Arconis
+dtmsecurity on github
 Duane Cathey
 Duncan Mac-Vicar Prett
 Dustin Boswell
@@ -520,6 +563,7 @@ Earnestly on github
 Eason-Yu on github
 Ebenezer Ikonne
 Ed Morley
+Edgaras Janušauskas
 Edin Kadribasic
 Edmond Yu
 Eduard Bloch
@@ -531,11 +575,14 @@ Eelco Dolstra
 Eetu Ojanen
 Egon Eckert
 Eldar Zaitov
+elelel on github
+elephoenix on github
 Eli Schwartz
 Elia Tufarolo
 Elliot Saba
 Ellis Pritchard
 Elmira A Semenova
+elsamuko on github
 Emanuele Bovisio
 Emil Engler
 Emil Lerner
@@ -581,6 +628,7 @@ Even Rouault
 Evert Pot
 Evgeny Grin
 Evgeny Turnaev
+eXeC64 on github
 Eygene Ryabinkin
 Fabian Frank
 Fabian Hiernaux
@@ -589,13 +637,17 @@ Fabian Ruff
 Fabrice Fontaine
 Fabrizio Ammollo
 Fahim Chandurwala
+Faizur Rahman
+fds242 on github
 Federico Bianchi
 Fedor Karpelevitch
+Fedor Korotkov
 Feist Josselin
+Felipe Gasper
 Felix Hädicke
 Felix Kaiser
-Felix Yan
 Felix von Leitner
+Felix Yan
 Feng Tu
 Fernando Muñoz
 Flavio Medeiros
@@ -683,6 +735,7 @@ Grigory Entin
 Guenole Bescon
 Guido Berhoerster
 Guillaume Arluison
+guitared on github
 Gunter Knauf
 Gustaf Hui
 Gustavo Grieco
@@ -694,6 +747,7 @@ Götz Babin-Ebell
 Hagai Auro
 Haibo Huang
 Hamish Mackenzie
+hamstergene on github
 Han Han
 Han Qiao
 Hang Kin Lau
@@ -729,6 +783,7 @@ Hoi-Ho Chan
 Hongli Lai
 Howard Blaise
 Howard Chu
+hsiao yi
 Hubert Kario
 Huzaifa Sidhpurwala
 Hzhijun
@@ -750,8 +805,10 @@ Iida Yosiaki
 Ilguiz Latypov
 Ilja van Sprundel
 Ilya Kosarev
+imilli on github
 Immanuel Gregoire
 Inca R
+infinnovation-dev on github
 Ingmar Runge
 Ingo Ralf Blum
 Ingo Wilken
@@ -763,7 +820,9 @@ Isaiah Norton
 Ishan SinghLevett
 Ithubg on github
 Ivan Avdeev
+IvanoG on github
 Ivo Bellin Salarin
+iz8mbw on github
 Jack Zhang
 Jackarain on github
 Jacky Lam
@@ -773,6 +832,7 @@ Jacob Moshenko
 Jactry Zeng
 Jad Chamcham
 Jaime Fullaondo
+jakirkham on github
 Jakub Wilk
 Jakub Zakrzewski
 James Atwill
@@ -782,6 +842,7 @@ James Cheng
 James Clancy
 James Cone
 James Dury
+James Fuller
 James Gallagher
 James Griffiths
 James Housley
@@ -805,6 +866,7 @@ Jared Jennings
 Jared Lundell
 Jari Aalto
 Jari Sundell
+jasal82 on github
 Jason Baietto
 Jason Glasgow
 Jason Juang
@@ -861,6 +923,7 @@ Jesper Jensen
 Jesse Chisholm
 Jesse Noller
 Jesse Tan
+jethrogb on github
 Jie He
 Jim Drash
 Jim Freeman
@@ -872,6 +935,7 @@ Jiri Dvorak
 Jiri Hruska
 Jiri Jaburek
 Jiří Malák
+jnbr on github
 Jocelyn Jaubert
 Joe Halpin
 Joe Malicki
@@ -923,6 +987,7 @@ Jojojov on github
 Jon DeVree
 Jon Grubbs
 Jon Nelson
+Jon Rumsey
 Jon Sargeant
 Jon Seymour
 Jon Spencer
@@ -940,6 +1005,7 @@ Jonathan Hseu
 Jonathan Moerman
 Jonathan Nieder
 Jongki Suwandi
+jonrumsey on github
 Joombalaya on github
 Joonas Kuorilehto
 Jose Alf
@@ -947,6 +1013,7 @@ Jose Kahan
 Josef Wolf
 Josh Bialkowski
 Josh Kapell
+joshhe on github
 Joshua Kwan
 Joshua Swink
 Josie Huddleston
@@ -969,6 +1036,7 @@ Julien Chaffraix
 Julien Nabet
 Julien Royer
 Jun-ichiro itojun Hagino
+jungle-boogie on github
 Junho Choi
 Jurij Smakov
 Juro Bystricky
@@ -977,11 +1045,14 @@ Justin Ehlert
 Justin Fletcher
 Justin Karneges
 Justin Maggard
+jveazey on github
+jzinn on github
 János Fekete
 Jérémy Rocher
 Jörg Mueller-Tolk
 Jörn Hartroth
 K. R. Walker
+ka7 on github
 Kai Engert
 Kai Noda
 Kai Sommerfeld
@@ -1028,11 +1099,14 @@ Kobi Gurkan
 Koen Dergent
 Konstantin Isakov
 Konstantin Kushnir
+kouzhudong on github
+kreshano on github
 Kris Kennaway
 Krishnendu Majumdar
 Krister Johansen
 Kristian Gunstone
 Kristian Köhntopp
+Kristian Mide
 Kristiyan Tsaklev
 Kristoffer Gleditsch
 Kunal Ekawde
@@ -1044,6 +1118,7 @@ Kyle L. Huff
 Kyle Sallee
 Kyohei Kadota
 Kyselgov E.N
+l00p3r on Hackerone
 Lachlan O'Dea
 Ladar Levison
 Lance Ware
@@ -1073,11 +1148,13 @@ Len Krause
 Len Marinaccio
 Lenaic Lefever
 Lenny Rachitsky
+Leo Neat
 Leon Breedt
 Leon Winter
 Leonardo Rosati
 Leonardo Taccari
 Liam Healy
+lijian996 on github
 Lijo Antony
 Linas Vepstas
 Lindley French
@@ -1106,6 +1183,7 @@ Ludovico Cavedon
 Ludwig Nussel
 Lukas Ruzicka
 Lukasz Czekierda
+lukaszgn on github
 Luke Amery
 Luke Call
 Luke Dashjr
@@ -1115,10 +1193,10 @@ Luz Paz
 Luật Nguyễn
 Lyman Epp
 Lyndon Hill
-MAntoniak on github
 Maciej Karpiuk
 Maciej Puzio
 Maciej W. Rozycki
+madblobfish on github
 Mahmoud Samir Fayed
 Maks Naumov
 Maksim Kuzevanov
@@ -1127,6 +1205,7 @@ Mamoru Tasaka
 Mamta Upadhyay
 Mandy Wu
 Manfred Schwarb
+MAntoniak on github
 Manuel Massing
 Marc Aldorasi
 Marc Boucher
@@ -1138,6 +1217,7 @@ Marc Kleine-Budde
 Marc Renault
 Marc Schlatter
 Marc-Antoine Perennou
+marc-groundctl on github
 Marcel Hernandez
 Marcel Raad
 Marcel Roelofs
@@ -1197,6 +1277,7 @@ Martin Storsjö
 Martin Vejnár
 Marty Kuhrt
 Maruko
+masbug on github
 Massimiliano Fantuzzi
 Massimiliano Ziccardi
 Massimo Callegari
@@ -1235,6 +1316,8 @@ Maxim Perenesenko
 Maxim Prohorov
 Maxime Larocque
 Maxime Legros
+mbeifuss on github
+mccormickt12 on github
 Mehmet Bozkurt
 Mekonikum
 Melissa Mears
@@ -1284,6 +1367,7 @@ Michel Promonet
 Michele Bini
 Miguel Angel
 Miguel Diaz
+migueljcrum on github
 Mihai Ionescu
 Mikael Johansson
 Mikael Sennerholm
@@ -1292,11 +1376,13 @@ Mike Bytnar
 Mike Crowe
 Mike Dobbs
 Mike Dowell
+Mike Frysinger
 Mike Giancola
 Mike Hasselberg
 Mike Henshaw
 Mike Hommey
 Mike Mio
+Mike Norton
 Mike Power
 Mike Protts
 Mike Revi
@@ -1305,19 +1391,24 @@ Miloš Ljumović
 Mingliang Zhu
 Miroslav Franc
 Miroslav Spousta
+Mischa Salle
 Mitz Wark
+mkzero on github
 Mohamed Lrhazi
 Mohammad AlSaleh
 Mohammad Hasbini
 Mohun Biswas
+momala454 on github
+moohoorama on github
 Mostyn Bramley-Moore
 Moti Avrahami
+MrdUkk on github
 MrSorcus on github
 Muz Dima
 Myk Taylor
-NTMan on Github
 Nach M. S.
 Nagai H
+naost3rn on github
 Nate Prewitt
 Nathan Coulter
 Nathan O'Sullivan
@@ -1327,12 +1418,18 @@ Nathaniel Waisbrot
 Naveen Chandran
 Naveen Noel
 Neal Poole
+nedres on github
+neex on github
 Nehal J Wani
+neheb on github
 Neil Bowers
 Neil Dunbar
 Neil Kolban
 Neil Spring
+nevv on HackerOne/curl
 Niall O'Reilly
+niallor on github
+nianxuejie on github
 Nic Roets
 Nicholas Maniscalco
 Nick Draffen
@@ -1342,10 +1439,12 @@ Nick Miyake
 Nick Zitzmann
 Nicklas Avén
 Nico Baggus
+nico-abram on github
 Nicolas Berloquin
 Nicolas Croiset
 Nicolas François
 Nicolas Grekas
+Nicolas Guillier
 Nicolas Morey-Chaisemartin
 Niels van Tongeren
 Nikita Schmidt
@@ -1355,14 +1454,18 @@ Niklas Hambüchen
 Nikolai Kondrashov
 Nikos Mavrogiannopoulos
 Nikos Tsipinakis
+niner on github
 Ning Dong
 Nir Soffer
 Nis Jorgensen
+nk
 Nobuhiro Ban
 Nodak Sodak
+nopjmp on github
 Norbert Frese
 Norbert Kett
 Norbert Novotny
+NTMan on Github
 Octavio Schroeder
 Ofer
 Okhin Vasilij
@@ -1371,6 +1474,7 @@ Olaf Flebbe
 Olaf Stüben
 Oleg Pudeyev
 Olen Andoni
+olesteban on github
 Oli Kingshott
 Oliver Gondža
 Oliver Graute
@@ -1379,15 +1483,18 @@ Oliver Schindler
 Olivier Berger
 Olivier Brunel
 Omar Ramadan
+omau on github
 Orange Tsai
 Oren Souroujon
 Oren Tirosh
 Orgad Shaneh
 Ori Avtalion
+osabc on github
 Oscar Koeroo
 Oscar Norlander
 Oskar Liljeblad
 Oumph on github
+ovidiu-benea on github
 P R Schaffner
 Palo Markovic
 Paolo Mossino
@@ -1398,6 +1505,8 @@ Pascal Terjan
 Pasha Kuznetsov
 Pasi Karkkainen
 Pat Ray
+patelvivekv1993 on github
+patnyb on github
 Patrice Guerin
 Patricia Muscalu
 Patrick Bihan-Faou
@@ -1435,11 +1544,14 @@ Pavel Orehov
 Pavel Pavlov
 Pavel Raiskup
 Pavel Rochnyak
+Pavel Volgarev
 Pavol Markovic
 Pawel A. Gajda
 Pawel Kierski
 Pedro Larroy
+Pedro Monreal
 Pedro Neves
+pendrek at hackerone
 Peng Li
 Per Lundberg
 Per Malmberg
@@ -1492,6 +1604,7 @@ Pierre Brico
 Pierre Chapuis
 Pierre Joye
 Pierre Ynard
+Pierre-Yves Bigourdan
 Piotr Dobrogost
 Piotr Komborski
 Po-Chuan Hsieh
@@ -1502,6 +1615,7 @@ Prash Dush
 Praveen Pvs
 Priyanka Shah
 Przemysław Tomaszewski
+pszemus on github
 Puneet Pawaia
 Quagmire
 Quanah Gibson-Mount
@@ -1594,6 +1708,7 @@ Rob Ward
 Robert A. Monat
 Robert B. Harris
 Robert D. Young
+Robert Dunaj
 Robert Foreman
 Robert Iakobashvili
 Robert Kolcun
@@ -1637,6 +1752,7 @@ Ruslan Baratov
 Ruslan Gazizov
 Rutger Hofman
 Ruurd Beerstra
+RuurdBeerstra on github
 Ryan Braud
 Ryan Chan
 Ryan Nelson
@@ -1646,8 +1762,6 @@ Ryan Winograd
 Ryuichi KAWAMATA
 Rémy Léone
 S. Moonesamy
-SBKarr on github
-SLDiggie on github
 Salah-Eddin Shaban
 Salvador Dávila
 Salvatore Sorrentino
@@ -1670,6 +1784,8 @@ Saran Neti
 Sascha Swiercy
 Saul good
 Saurav Babu
+sayrer on github
+SBKarr on github
 Scott Bailey
 Scott Barrett
 Scott Cantor
@@ -1715,23 +1831,29 @@ Shmulik Regev
 Siddhartha Prakash Jain
 Sidney San Martín
 Siegfried Gyuricsko
+silveja1 on github
 Simon Dick
 Simon H.
 Simon Josefsson
 Simon Legner
 Simon Liu
 Simon Warta
+SLDiggie on github
+smuellerDD on github
 Somnath Kundu
 Song Ma
 Sonia Subramanian
 Spacen Jasset
 Spezifant on github
 Spiridonoff A.V
+Spoon Man
 Spork Schivago
+sstruchtrup on github
 Stadler Stephan
 Stan van de Burgt
 Stanislav Ivochkin
 Stanislav Zidek
+steelman on github
 Stefan Agner
 Stefan Bühler
 Stefan Eissing
@@ -1745,6 +1867,7 @@ Stefan Tomanek
 Stefan Ulrich
 Stefano Simonelli
 Steinar H. Gunderson
+steini2000 on github
 Stepan Broz
 Stephan Bergmann
 Stephan Lagerholm
@@ -1773,26 +1896,29 @@ Steven M. Schweda
 Steven Parkes
 Stian Soiland-Reyes
 Stoned Elipot
+stootill on github
 Stuart Henderson
 SumatraPeter on github
 Sune Ahlgren
+Sunny Bean
 Sunny Purushe
 Sven Anders
 Sven Blumenstein
 Sven Neuhaus
 Sven Wegener
 Svyatoslav Mishyn
+swalkaus at yahoo.com
 Sylvestre Ledru
 Symeon Paraschoudis
 Sébastien Willemijns
 T. Bharath
 T. Yamada
-TJ Saunders
 Tae Hyoung Ahn
 Tae Wong
 Taiyu Len
 Taneli Vähäkangas
 Tanguy Fautre
+tarek112 on github
 Tatsuhiro Tsujikawa
 Teemu Yli-Elsila
 Temprimus
@@ -1801,6 +1927,7 @@ Terry Wu
 The Infinnovation team
 TheAssassin on github
 Theodore Dubois
+tholin on github
 Thomas Braun
 Thomas Gamper
 Thomas Glanzmann
@@ -1812,8 +1939,8 @@ Thomas Petazzoni
 Thomas Ruecker
 Thomas Schwinge
 Thomas Tonino
-Thomas Vegas
 Thomas van Hesteren
+Thomas Vegas
 Thorsten Schöning
 Tiit Pikma
 Till Maas
@@ -1837,7 +1964,9 @@ Timotej Lazar
 Timothe Litt
 Timothy Polich
 Tinus van den Berg
+TJ Saunders
 Tobias Blomberg
+Tobias Hieta
 Tobias Hintze
 Tobias Lindgren
 Tobias Markus
@@ -1860,9 +1989,9 @@ Tom Mueller
 Tom Regner
 Tom Seddon
 Tom Sparrow
+Tom van der Woerdt
 Tom Wright
 Tom Zerucha
-Tom van der Woerdt
 Tomas Hoger
 Tomas Jakobsson
 Tomas Mlcoch
@@ -1873,16 +2002,19 @@ Tomas Tomecek
 Tomasz Kojm
 Tomasz Lacki
 Tommie Gannert
+tommink[at]post.pl
 Tommy Tam
 Ton Voon
 Toni Moreno
 Tony Kelman
+tonystz on Github
 Toon Verwaest
 Tor Arntsen
 Torben Dannhauer
 Torsten Foertsch
 Toshio Kuratomi
 Toshiyuki Maezawa
+tpaukrt on github
 Traian Nicolescu
 Travis Burtrum
 Travis Obenhaus
@@ -1901,6 +2033,7 @@ Ulrich Telle
 Ulrich Zadow
 Valentin David
 Valerii Zapodovnikov
+vanillajonathan on github
 Vasiliy Faronov
 Vasily Lobaskin
 Vasy Okhin
@@ -1921,6 +2054,7 @@ Vincent Le Normand
 Vincent Penquerc'h
 Vincent Sanders
 Vincent Torri
+vitaha85 on github
 Vlad Grachov
 Vlad Ureche
 Vladimir Grishchenko
@@ -1932,6 +2066,7 @@ Vojtech Minarik
 Vojtěch Král
 Volker Schmid
 Vsevolod Novikov
+vshmuk on hackerone
 W. Mark Kubacki
 Waldek Kozba
 Walter J. Mack
@@ -1941,6 +2076,7 @@ Wayne Haigh
 Wenchao Li
 Wenxiang Qian
 Werner Koch
+wesinator on github
 Wesley Laxton
 Wesley Miaw
 Wez Furlong
@@ -1950,6 +2086,8 @@ Will Dietz
 Willem Sparreboom
 William A. Rowe Jr
 William Ahern
+wmsch on github
+wncboy on github
 Wojciech Zwiefka
 Wouter Van Rooy
 Wu Yongzheng
@@ -1968,10 +2106,12 @@ Yasuhiro Matsumoto
 Yechiel Kalmenson
 Yehezkel Horowitz
 Yehoshua Hershberg
+ygthien on github
 Yi Huang
 Yiming Jing
 Yingwei Liu
 Yonggang Luo
+youngchopin on github
 Yousuke Kimoto
 Yu Xin
 Yukihiro Kawada
@@ -1982,6 +2122,7 @@ Yves Lejeune
 Zachary Seguin
 Zdenek Pavlas
 Zekun Ni
+zelinchen on github
 Zenju on github
 Zero King
 Zhao Yisha
@@ -1990,105 +2131,9 @@ Zhibiao Wu
 Zhouyihai Ding
 Zmey Petroff
 Zvi Har'El
-aasivov on github
-accountantM on github
-adnn on github
-afrind on github
-ahodesuka on github
-anshnd on github
-arainchik on github
-asavah on github
-baumanj on github
-bdry on github
-bobmitchell1956 on github
-bsammon on github
-buzo-ffm on github
-bxac on github
-cbartl on github
-cclauss on github
-clbr on github
-cmfrolick on github
-codesniffer13 on github
-d912e3 on github
-daboul on github
-dasimx on github
-dbrowndan on github
-destman on github
-dkjjr89 on github
-dkwolfe4 on github
-dnivras on github
-dpull on github
-dtmsecurity on github
-eXeC64 on github
-elelel on github
-elephoenix on github
-elsamuko on github
-guitared on github
-hsiao yi
-imilli on github
-infinnovation-dev on github
-iz8mbw on github
-jakirkham on github
-jasal82 on github
-jnbr on github
-jonrumsey on github
-joshhe on github
-jungle-boogie on github
-jveazey on github
-jzinn on github
-ka7 on github
-kouzhudong on github
-kreshano on github
-l00p3r on Hackerone
-lijian996 on github
-lukaszgn on github
-madblobfish on github
-marc-groundctl on github
-masbug on github
-mccormickt12 on github
-migueljcrum on github
-mkzero on github
-momala454 on github
-moohoorama on github
-nedres on github
-neex on github
-neheb on github
-nevv on HackerOne/curl
-niallor on github
-nianxuejie on github
-nico-abram on github
-niner on github
-nk
-nopjmp on github
-olesteban on github
-omau on github
-osabc on github
-ovidiu-benea on github
-patelvivekv1993 on github
-patnyb on github
-pendrek at hackerone
-pszemus on github
-sayrer on github
-silveja1 on github
-smuellerDD on github
-sstruchtrup on github
-steelman on github
-steini2000 on github
-stootill on github
-swalkaus at yahoo.com
-tarek112 on github
-tholin on github
-tommink[at]post.pl
-tonystz on Github
-tpaukrt on github
-vanillajonathan on github
-wesinator on github
-wmsch on github
-wncboy on github
-youngchopin on github
-zelinchen on github
 zzq1015 on github
 İsmail Dönmez
 Łukasz Domeradzki
 Štefan Kremeň
 Никита Дорохин
+加藤郁之
diff --git a/docs/TODO b/docs/TODO
index 6f4919c23..b288e4dbb 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -87,6 +87,8 @@
 
  10. LDAP
  10.1 SASL based authentication mechanisms
+ 10.2 CURLOPT_SSL_CTX_FUNCTION for LDAPS
+ 10.3 Paged searches on LDAP server
 
  11. SMB
  11.1 File listing support
@@ -132,6 +134,7 @@
  18.1 sync
  18.2 glob posts
  18.3 prevent file overwriting
+ 18.4 --proxycommand
  18.5 UTF-8 filenames in Content-Disposition
  18.7 at least N milliseconds between requests
  18.9 Choose the name of file in braces for complex URLs
@@ -403,7 +406,6 @@
  EWOULDBLOCK or similar. Blocking cases include:
 
  - Name resolves on non-windows unless c-ares or the threaded resolver is used
- - SOCKS proxy handshakes
  - file:// transfers
  - TELNET transfers
  - The "DONE" operation (post transfer protocol-specific actions) for the
@@ -603,6 +605,17 @@
  be possible to use ldap_bind_s() instead specifying the security context
  information ourselves.
 
+10.2 CURLOPT_SSL_CTX_FUNCTION for LDAPS
+
+ CURLOPT_SSL_CTX_FUNCTION works perfectly for HTTPS and email protocols, but
+ it has no effect for LDAPS connections.
+
+ https://github.com/curl/curl/issues/4108
+
+10.3 Paged searches on LDAP server
+
+ https://github.com/curl/curl/issues/4452
+
 11. SMB
 
 11.1 File listing support
@@ -857,6 +870,16 @@ that doesn't exist on the server, just like 
--ftp-create-dirs.
  existing). So that index.html becomes first index.html.1 and then
  index.html.2 etc.
 
+18.4 --proxycommand
+
+ Allow the user to make curl run a command and use its stdio to make requests
+ and not do any network connection by itself. Example:
+
+   curl --proxycommand 'ssh pi@raspberrypi.local -W 10.1.1.75 80' \
+        http://some/otherwise/unavailable/service.php
+
+ See https://github.com/curl/curl/issues/4941
+
 18.5 UTF-8 filenames in Content-Disposition
 
  RFC 6266 documents how UTF-8 names can be passed to a client in the
diff --git a/docs/cmdline-opts/alt-svc.d b/docs/cmdline-opts/alt-svc.d
index df10bf257..15877a2fe 100644
--- a/docs/cmdline-opts/alt-svc.d
+++ b/docs/cmdline-opts/alt-svc.d
@@ -14,4 +14,4 @@ Specify a "" file name (zero length) to avoid loading/saving 
and make curl
 just handle the cache in memory.
 
 If this option is used several times, curl will load contents from all the
-files but the the last one will be used for saving.
+files but the last one will be used for saving.
diff --git a/docs/cmdline-opts/create-dirs.d b/docs/cmdline-opts/create-dirs.d
index 49e22e75a..b09d96ca7 100644
--- a/docs/cmdline-opts/create-dirs.d
+++ b/docs/cmdline-opts/create-dirs.d
@@ -6,4 +6,6 @@ necessary local directory hierarchy as needed. This option 
creates the dirs
 mentioned with the --output option, nothing else. If the --output file name
 uses no dir or if the dirs it mentions already exist, no dir will be created.
 
+Created dirs are made with mode 0750 on unix style file systems.
+
 To create remote directories when using FTP or SFTP, try --ftp-create-dirs.
diff --git a/docs/cmdline-opts/data.d b/docs/cmdline-opts/data.d
index d18312aaa..8b5200d34 100644
--- a/docs/cmdline-opts/data.d
+++ b/docs/cmdline-opts/data.d
@@ -22,9 +22,8 @@ data pieces specified will be merged together with a 
separating
 chunk that looks like \&'name=daniel&skill=lousy'.
 
 If you start the data with the letter @, the rest should be a file name to
-read the data from, or - if you want curl to read the data from
-stdin. Multiple files can also be specified. Posting data from a file named
-\&'foobar' would thus be done with --data @foobar. When --data is told to read
-from a file like that, carriage returns and newlines will be stripped out. If
-you don't want the @ character to have a special interpretation use --data-raw
-instead.
+read the data from, or - if you want curl to read the data from stdin. Posting
+data from a file named \&'foobar' would thus be done with --data @foobar. When
+--data is told to read from a file like that, carriage returns and newlines
+will be stripped out. If you don't want the @ character to have a special
+interpretation use --data-raw instead.
diff --git a/docs/cmdline-opts/form.d b/docs/cmdline-opts/form.d
index 0bbc3701f..7f1aa31c3 100644
--- a/docs/cmdline-opts/form.d
+++ b/docs/cmdline-opts/form.d
@@ -33,11 +33,11 @@ form-field to which the file portrait.jpg will be the input:
 
  curl -F profile=@portrait.jpg https://example.com/upload.cgi
 
-Example: send a your name and shoe size in two text fields to the server:
+Example: send your name and shoe size in two text fields to the server:
 
  curl -F name=John -F shoesize=11 https://example.com/
 
-Example: send a your essay in a text field to the server. Send it as a plain
+Example: send your essay in a text field to the server. Send it as a plain
 text field, but get the contents for it from a local file:
 
  curl -F "story=<hugefile.txt" https://example.com/
diff --git a/docs/cmdline-opts/location.d b/docs/cmdline-opts/location.d
index 7c70e6981..b5ba1f4fa 100644
--- a/docs/cmdline-opts/location.d
+++ b/docs/cmdline-opts/location.d
@@ -13,11 +13,13 @@ intercept the user+password. See also --location-trusted on 
how to change
 this. You can limit the amount of redirects to follow by using the
 --max-redirs option.
 
-When curl follows a redirect and the request is not a plain GET (for example
-POST or PUT), it will do the following request with a GET if the HTTP response
-was 301, 302, or 303. If the response code was any other 3xx code, curl will
-re-send the following request using the same unmodified method.
+When curl follows a redirect and if the request is a POST, it will do the
+following request with a GET if the HTTP response was 301, 302, or 303. If the
+response code was any other 3xx code, curl will re-send the following request
+using the same unmodified method.
 
-You can tell curl to not change the non-GET request method to GET after a 30x
-response by using the dedicated options for that: --post301, --post302 and
---post303.
+You can tell curl to not change POST requests to GET after a 30x response by
+using the dedicated options for that: --post301, --post302 and --post303.
+
+The method set with --request overrides the method curl would otherwise select
+to use.
diff --git a/docs/cmdline-opts/mail-rcpt-allowfails.d 
b/docs/cmdline-opts/mail-rcpt-allowfails.d
new file mode 100644
index 000000000..b5723df34
--- /dev/null
+++ b/docs/cmdline-opts/mail-rcpt-allowfails.d
@@ -0,0 +1,15 @@
+Long: mail-rcpt-allowfails
+Help: Allow RCPT TO command to fail for some recipients
+Protocols: SMTP
+Added: 7.69.0
+---
+When sending data to multiple recipients, by default curl will abort SMTP
+conversation if at least one of the recipients causes RCPT TO command to
+return an error.
+
+The default behavior can be changed by passing --mail-rcpt-allowfails
+command-line option which will make curl ignore errors and proceed with the
+remaining valid recipients.
+
+In case when all recipients cause RCPT TO command to fail, curl will abort SMTP
+conversation and return the error received from to the last RCPT TO command.
\ No newline at end of file
diff --git a/docs/cmdline-opts/oauth2-bearer.d 
b/docs/cmdline-opts/oauth2-bearer.d
index 780716748..30466e579 100644
--- a/docs/cmdline-opts/oauth2-bearer.d
+++ b/docs/cmdline-opts/oauth2-bearer.d
@@ -1,7 +1,7 @@
 Long: oauth2-bearer
 Help: OAuth 2 Bearer Token
 Arg: <token>
-Protocols: IMAP POP3 SMTP
+Protocols: IMAP POP3 SMTP HTTP
 ---
 Specify the Bearer Token for OAUTH 2.0 server authentication. The Bearer Token
 is used in conjunction with the user name which can be specified as part of
diff --git a/docs/libcurl/gnurl_easy_reset.3 b/docs/libcurl/gnurl_easy_reset.3
index 56f5bbea7..5bf6ddf9a 100644
--- a/docs/libcurl/gnurl_easy_reset.3
+++ b/docs/libcurl/gnurl_easy_reset.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2014, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -33,7 +33,8 @@ default values. This puts back the handle to the same state 
as it was in when
 it was just created with \fIcurl_easy_init(3)\fP.
 
 It does not change the following information kept in the handle: live
-connections, the Session ID cache, the DNS cache, the cookies and shares.
+connections, the Session ID cache, the DNS cache, the cookies, the shares or
+the alt-svc cache.
 .SH AVAILABILITY
 This function was added in libcurl 7.12.1
 .SH RETURN VALUE
diff --git a/docs/libcurl/gnurl_easy_setopt.3 b/docs/libcurl/gnurl_easy_setopt.3
index a936efadb..196899fab 100644
--- a/docs/libcurl/gnurl_easy_setopt.3
+++ b/docs/libcurl/gnurl_easy_setopt.3
@@ -357,6 +357,8 @@ Address of the sender. See \fICURLOPT_MAIL_FROM(3)\fP
 Address of the recipients. See \fICURLOPT_MAIL_RCPT(3)\fP
 .IP CURLOPT_MAIL_AUTH
 Authentication address. See \fICURLOPT_MAIL_AUTH(3)\fP
+.IP CURLOPT_MAIL_RCPT_ALLLOWFAILS
+Allow RCPT TO command to fail for some recipients. See 
\fICURLOPT_MAIL_RCPT_ALLLOWFAILS(3)\fP
 .SH TFTP OPTIONS
 .IP CURLOPT_TFTP_BLKSIZE
 TFTP block size. See \fICURLOPT_TFTP_BLKSIZE(3)\fP
diff --git a/docs/libcurl/gnurl_escape.3 b/docs/libcurl/gnurl_escape.3
index 33f756eae..58c4e0c1a 100644
--- a/docs/libcurl/gnurl_escape.3
+++ b/docs/libcurl/gnurl_escape.3
@@ -38,7 +38,7 @@ two-digit hexadecimal number).
 If the 'length' argument is set to 0, curl_escape() will use strlen() on the
 input 'url' string to find out the size.
 
-You must curl_free() the returned string when you're done with it.
+You must \fIcurl_free(3)\fP the returned string when you're done with it.
 .SH AVAILABILITY
 Since 7.15.4, \fIcurl_easy_escape(3)\fP should be used. This function will
 be removed in a future release.
diff --git a/docs/libcurl/gnurl_getenv.3 b/docs/libcurl/gnurl_getenv.3
index 7be52d1db..98d928582 100644
--- a/docs/libcurl/gnurl_getenv.3
+++ b/docs/libcurl/gnurl_getenv.3
@@ -31,15 +31,15 @@ curl_getenv - return value for environment name
 curl_getenv() is a portable wrapper for the getenv() function, meant to
 emulate its behaviour and provide an identical interface for all operating
 systems libcurl builds on (including win32).
+
+You must \fIcurl_free(3)\fP the returned string when you're done with it.
 .SH AVAILABILITY
 This function will be removed from the public libcurl API in a near future. It
 will instead be made "available" by source code access only, and then as
 curlx_getenv().
 .SH RETURN VALUE
-If successful, curl_getenv() returns a pointer to the value of the specified
-environment. The memory it refers to is malloc()ed so the application must
-free() this when the data is no longer needed. When \fIcurl_getenv(3)\fP fails
-to find the specified name, it returns a null pointer.
+A pointer to a zero terminated string or NULL if it failed to find the
+specified name.
 .SH NOTE
 Under unix operating systems, there isn't any point in returning an allocated
 memory, although other systems won't work properly if this isn't done. The
diff --git a/docs/libcurl/gnurl_global_init.3 b/docs/libcurl/gnurl_global_init.3
index 797c0d7ff..db84fad00 100644
--- a/docs/libcurl/gnurl_global_init.3
+++ b/docs/libcurl/gnurl_global_init.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -87,9 +87,11 @@ Initialise nothing extra. This sets no bit.
 A sensible default. It will init both SSL and Win32. Right now, this equals
 the functionality of the \fBCURL_GLOBAL_ALL\fP mask.
 .IP CURL_GLOBAL_ACK_EINTR
-When this flag is set, curl will acknowledge EINTR condition when connecting
-or when waiting for data.  Otherwise, curl waits until full timeout
-elapses. (Added in 7.30.0)
+This bit has no point since 7.69.0 but its behavior is instead the default.
+
+Before 7.69.0: when this flag is set, curl will acknowledge EINTR condition
+when connecting or when waiting for data.  Otherwise, curl waits until full
+timeout elapses. (Added in 7.30.0)
 .SH RETURN VALUE
 If this function returns non-zero, something went wrong and you cannot use the
 other curl functions.
diff --git a/docs/libcurl/gnurl_global_sslset.3 
b/docs/libcurl/gnurl_global_sslset.3
index a631d1893..ee48a6abb 100644
--- a/docs/libcurl/gnurl_global_sslset.3
+++ b/docs/libcurl/gnurl_global_sslset.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2018, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -37,7 +37,7 @@ typedef enum {
   CURLSSLBACKEND_GNUTLS = 2,
   CURLSSLBACKEND_NSS = 3,
   CURLSSLBACKEND_GSKIT = 5,
-  CURLSSLBACKEND_POLARSSL = 6,
+  CURLSSLBACKEND_POLARSSL = 6, /* deprecated */
   CURLSSLBACKEND_WOLFSSL = 7,
   CURLSSLBACKEND_SCHANNEL = 8,
   CURLSSLBACKEND_DARWINSSL = 9,
diff --git a/docs/libcurl/gnurl_share_setopt.3 
b/docs/libcurl/gnurl_share_setopt.3
index fd464b349..b58bef623 100644
--- a/docs/libcurl/gnurl_share_setopt.3
+++ b/docs/libcurl/gnurl_share_setopt.3
@@ -59,6 +59,8 @@ be set to one of the values described below.
 .RS
 .IP CURL_LOCK_DATA_COOKIE
 Cookie data will be shared across the easy handles using this shared object.
+Note that this does not activate an easy handle's cookie handling. You can do
+that separately by using \fICURLOPT_COOKIEFILE(3)\fP for example.
 .IP CURL_LOCK_DATA_DNS
 Cached DNS hosts will be shared across the easy handles using this shared
 object. Note that when you use the multi interface, all easy handles added to
diff --git a/docs/libcurl/libgnurl-errors.3 b/docs/libcurl/libgnurl-errors.3
index 0305af43e..eff6544b6 100644
--- a/docs/libcurl/libgnurl-errors.3
+++ b/docs/libcurl/libgnurl-errors.3
@@ -147,7 +147,7 @@ Function not found. A required zlib function was not found.
 .IP "CURLE_ABORTED_BY_CALLBACK (42)"
 Aborted by callback. A callback returned "abort" to libcurl.
 .IP "CURLE_BAD_FUNCTION_ARGUMENT (43)"
-Internal error. A function was called with a bad parameter.
+A function was called with a bad parameter.
 .IP "CURLE_INTERFACE_FAILED (45)"
 Interface error. A specified outgoing interface could not be used. Set which
 interface to use for outgoing connections' source IP address with
@@ -259,6 +259,9 @@ An authentication function returned an error.
 .IP "CURLE_HTTP3 (95)"
 A problem was detected in the HTTP/3 layer. This is somewhat generic and can
 be one out of several problems, see the error buffer for details.
+.IP "CURLE_QUIC_CONNECT_ERROR (96)"
+QUIC connection error. This error may be caused by an SSL library error. QUIC
+is the protocol used for HTTP/3 transfers.
 .IP "CURLE_OBSOLETE*"
 These error codes will never be returned. They were used in an old libcurl
 version and are currently unused.
@@ -299,6 +302,8 @@ second time. (Added in 7.32.1)
 An API function was called from inside a callback.
 .IP "CURLM_WAKEUP_FAILURE (9)"
 Wakeup is unavailable or failed.
+.IP "CURLM_BAD_FUNCTION_ARGUMENT (10)"
+A function was called with a bad parameter.
 .SH "CURLSHcode"
 The "share" interface will return a CURLSHcode to indicate when an error has
 occurred.  Also consider \fIcurl_share_strerror(3)\fP.
diff --git a/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLLOWFAILS.3 
b/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLLOWFAILS.3
new file mode 100644
index 000000000..aeff2955a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLLOWFAILS.3
@@ -0,0 +1,71 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, 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.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_MAIL_RCPT_ALLLOWFAILS 3 "16 Jan 2020" "libcurl 7.69.0" 
"curl_easy_setopt options"
+.SH NAME
+CURLOPT_MAIL_RCPT_ALLLOWFAILS \- allow RCPT TO command to fail for some 
recipients
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_RCPT_ALLLOWFAILS,
+                          long allow);
+.SH DESCRIPTION
+If \fIallow\fP is set to 1L, allow RCPT TO command to fail for some recipients.
+
+When sending data to multiple recipients, by default curl will abort SMTP
+conversation if at least one of the recipients causes RCPT TO command to
+return an error.
+
+The default behavior can be changed by setting \fIignore\fP to 1L which will
+make curl ignore errors and proceed with the remaining valid recipients.
+
+In case when all recipients cause RCPT TO command to fail, curl will abort SMTP
+conversation and return the error received from to the last RCPT TO command.
+.SH DEFAULT
+0
+.SH PROTOCOLS
+SMTP
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+  struct curl_slist *list;
+
+  /* Adding one valid and one invalid email address */
+  list = curl_slist_append(NULL, "address@hidden");
+  list = curl_slist_append(list, "invalidemailaddress");
+
+  curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/");
+  curl_easy_setopt(curl, CURLOPT_MAIL_RCPT_ALLLOWFAILS, 1L);
+
+  ret = curl_easy_perform(curl);
+  curl_slist_free_all(list);
+  curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in 7.69.0.
+.SH RETURN VALUE
+Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLOPT_MAIL_FROM "(3), " CURLOPT_MAIL_RCPT "(3), "
diff --git a/docs/libcurl/opts/GNURLINFO_COOKIELIST.3 
b/docs/libcurl/opts/GNURLINFO_COOKIELIST.3
index 280ac0c9f..2335f71db 100644
--- a/docs/libcurl/opts/GNURLINFO_COOKIELIST.3
+++ b/docs/libcurl/opts/GNURLINFO_COOKIELIST.3
@@ -45,8 +45,8 @@ CURL *curl = curl_easy_init();
 if(curl) {
   curl_easy_setopt(curl, CURLOPT_URL, "http://example.com";);
 
-  /* enable the cookie engine with a non-existing file */
-  curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "-");
+  /* enable the cookie engine */
+  curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
 
   res = curl_easy_perform(curl);
 
@@ -58,7 +58,7 @@ if(curl) {
       /* a linked list of cookies in cookie file format */
       struct curl_slist *each = cookies;
       while(each) {
-        printf("%s", each->data);
+        printf("%s\\n", each->data);
         each = each->next;
       }
       /* we must free these cookies when we're done */
diff --git a/docs/libcurl/opts/GNURLINFO_RETRY_AFTER.3 
b/docs/libcurl/opts/GNURLINFO_RETRY_AFTER.3
index e752567c3..52d926cd3 100644
--- a/docs/libcurl/opts/GNURLINFO_RETRY_AFTER.3
+++ b/docs/libcurl/opts/GNURLINFO_RETRY_AFTER.3
@@ -33,7 +33,7 @@ HTTP server suggesets the client should wait until the next 
request is
 issued. The information from the "Retry-After:" header.
 
 While the HTTP header might contain a fixed date string, the
-\fICURLINFO_RETRY_AFTER(3)\fP will alwaus return number of seconds to wait -
+\fICURLINFO_RETRY_AFTER(3)\fP will always return number of seconds to wait -
 or zero if there was no header or the header couldn't be parsed.
 .SH DEFAULT
 Returns zero delay if there was no header.
diff --git a/docs/libcurl/opts/GNURLINFO_TLS_SSL_PTR.3 
b/docs/libcurl/opts/GNURLINFO_TLS_SSL_PTR.3
index 0f06b9af6..820268c4e 100644
--- a/docs/libcurl/opts/GNURLINFO_TLS_SSL_PTR.3
+++ b/docs/libcurl/opts/GNURLINFO_TLS_SSL_PTR.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -54,11 +54,11 @@ struct curl_tlssessioninfo {
 
 The \fIbackend\fP struct member is one of the defines in the CURLSSLBACKEND_*
 series: CURLSSLBACKEND_NONE (when built without TLS support),
-CURLSSLBACKEND_WOLFSSL, CURLSSLBACKEND_DARWINSSL,
-CURLSSLBACKEND_GNUTLS, CURLSSLBACKEND_GSKIT, CURLSSLBACKEND_MBEDTLS,
-CURLSSLBACKEND_NSS, CURLSSLBACKEND_OPENSSL, CURLSSLBACKEND_POLARSSL,
-CURLSSLBACKEND_SCHANNEL or CURLSSLBACKEND_MESALINK. (Note that the OpenSSL
-forks are all reported as just OpenSSL here.)
+CURLSSLBACKEND_WOLFSSL, CURLSSLBACKEND_DARWINSSL, CURLSSLBACKEND_GNUTLS,
+CURLSSLBACKEND_GSKIT, CURLSSLBACKEND_MBEDTLS, CURLSSLBACKEND_NSS,
+CURLSSLBACKEND_OPENSSL, CURLSSLBACKEND_SCHANNEL or
+CURLSSLBACKEND_MESALINK. (Note that the OpenSSL forks are all reported as just
+OpenSSL here.)
 
 The \fIinternals\fP struct member will point to a TLS library specific pointer
 for the active ("in use") SSL connection, with the following underlying types:
@@ -79,8 +79,6 @@ as well:
 .RS
 .IP mbedTLS
 mbedtls_ssl_context *
-.IP PolarSSL
-ssl_context *
 .IP "Secure Channel"
 CtxtHandle *
 .IP "Secure Transport"
diff --git a/docs/libcurl/opts/GNURLOPT_ALTSVC_CTRL.3 
b/docs/libcurl/opts/GNURLOPT_ALTSVC_CTRL.3
index fa8e88967..287da646e 100644
--- a/docs/libcurl/opts/GNURLOPT_ALTSVC_CTRL.3
+++ b/docs/libcurl/opts/GNURLOPT_ALTSVC_CTRL.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -69,7 +69,10 @@ Accept alternative services offered over HTTP/3. This will 
only be used if
 libcurl was also built to actually support HTTP/3, otherwise this bit will be
 ignored.
 .SH DEFAULT
-0. No Alt-Svc treatment.
+Alt-Svc handling is disabled by default. If \fICURLOPT_ALTSVC(3)\fP is set,
+\fICURLOPT_ALTSVC_CTRL(3)\fP has a default value corresponding to
+CURLALTSVC_H1 | CURLALTSVC_H2 | CURLALTSVC_H3 - the HTTP/2 and HTTP/3 bits are
+only set if libcurl was built with support for those versions.
 .SH PROTOCOLS
 HTTPS
 .SH EXAMPLE
diff --git a/docs/libcurl/opts/GNURLOPT_CAPATH.3 
b/docs/libcurl/opts/GNURLOPT_CAPATH.3
index e5175ede0..8436e2746 100644
--- a/docs/libcurl/opts/GNURLOPT_CAPATH.3
+++ b/docs/libcurl/opts/GNURLOPT_CAPATH.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -54,9 +54,8 @@ if(curl) {
 }
 .fi
 .SH AVAILABILITY
-This option is supported by the OpenSSL, GnuTLS, PolarSSL and mbedTLS
-(since 7.56.0) backends. The NSS backend provides the option only for
-backward compatibility.
+This option is supported by the OpenSSL, GnuTLS and mbedTLS (since 7.56.0)
+backends. The NSS backend provides the option only for backward compatibility.
 .SH RETURN VALUE
 CURLE_OK if supported; or an error such as:
 
diff --git a/docs/libcurl/opts/GNURLOPT_COOKIEFILE.3 
b/docs/libcurl/opts/GNURLOPT_COOKIEFILE.3
index e379aaed1..71e0d2c5f 100644
--- a/docs/libcurl/opts/GNURLOPT_COOKIEFILE.3
+++ b/docs/libcurl/opts/GNURLOPT_COOKIEFILE.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2018, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -75,6 +75,10 @@ if(curl) {
   curl_easy_cleanup(curl);
 }
 .fi
+.SH "Cookie file format"
+The cookie file format and general cookie concepts in curl are described in
+the HTTP-COOKIES.md file, also hosted online here:
+https://curl.haxx.se/docs/http-cookies.html
 .SH AVAILABILITY
 As long as HTTP is supported
 .SH RETURN VALUE
diff --git a/docs/libcurl/opts/GNURLOPT_COOKIELIST.3 
b/docs/libcurl/opts/GNURLOPT_COOKIELIST.3
index c5a66f5d1..fe0c19380 100644
--- a/docs/libcurl/opts/GNURLOPT_COOKIELIST.3
+++ b/docs/libcurl/opts/GNURLOPT_COOKIELIST.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -104,6 +104,10 @@ curl_easy_perform(curl);  /* cookies imported from 
cookies.txt */
 
 curl_easy_cleanup(curl);  /* cookies exported to cookies.txt */
 .fi
+.SH "Cookie file format"
+The cookie file format and general cookie concepts in curl are described in
+the HTTP-COOKIES.md file, also hosted online here:
+https://curl.haxx.se/docs/http-cookies.html
 .SH AVAILABILITY
 ALL was added in 7.14.1
 
diff --git a/docs/libcurl/opts/GNURLOPT_FOLLOWLOCATION.3 
b/docs/libcurl/opts/GNURLOPT_FOLLOWLOCATION.3
index bb64da48c..bc7d76ae5 100644
--- a/docs/libcurl/opts/GNURLOPT_FOLLOWLOCATION.3
+++ b/docs/libcurl/opts/GNURLOPT_FOLLOWLOCATION.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -46,7 +46,7 @@ are also disabled.
 
 When following a Location:, the 3xx response code that redirected it also
 dictates which request method it will use in the subsequent request: For 301,
-302 and 303 responses libcurl will switch method to GET unless
+302 and 303 responses libcurl will switch method from POST to GET unless
 \fICURLOPT_POSTREDIR(3)\fP instructs libcurl otherwise. All other 3xx codes
 will make libcurl send the same method again.
 
diff --git a/docs/libcurl/opts/GNURLOPT_POSTFIELDS.3 
b/docs/libcurl/opts/GNURLOPT_POSTFIELDS.3
index a4ed8e5f2..80b746320 100644
--- a/docs/libcurl/opts/GNURLOPT_POSTFIELDS.3
+++ b/docs/libcurl/opts/GNURLOPT_POSTFIELDS.3
@@ -54,8 +54,8 @@ the POST data from the read callback. If you want to send a 
zero-byte POST set
 
 Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header,
 and libcurl will add that header automatically if the POST is either known to
-be larger than 1024 bytes or if the expected size is unknown. You can disable
-this header with \fICURLOPT_HTTPHEADER(3)\fP as usual.
+be larger than 1MB or if the expected size is unknown. You can disable this
+header with \fICURLOPT_HTTPHEADER(3)\fP as usual.
 
 To make multipart/formdata posts (aka RFC2388-posts), check out the
 \fICURLOPT_HTTPPOST(3)\fP option combined with \fIcurl_formadd(3)\fP.
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3
index 7478e52f3..9b6e3b09e 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3
@@ -28,25 +28,31 @@ CURLOPT_PROXY_SSL_OPTIONS \- set proxy SSL behavior options
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_OPTIONS, long 
bitmask);
 .SH DESCRIPTION
-Pass a long with a bitmask to tell libcurl about specific SSL behaviors.
-
-\fICURLSSLOPT_ALLOW_BEAST\fP tells libcurl to not attempt to use any
-workarounds for a security flaw in the SSL3 and TLS1.0 protocols.  If this
-option isn't used or this bit is set to 0, the SSL layer libcurl uses may use
-a work-around for this flaw although it might cause interoperability problems
-with some (older) SSL implementations. WARNING: avoiding this work-around
-lessens the security, and by setting this option to 1 you ask for exactly
-that.  This option is only supported for DarwinSSL, NSS and OpenSSL.
-
-\fICURLSSLOPT_NO_REVOKE\fP tells libcurl to disable certificate revocation
-checks for those SSL backends where such behavior is present. This option is
-only supported for Schannel (the native Windows SSL library), with an
-exception in the case of Windows' Untrusted Publishers blacklist which it
-seems can't be bypassed.
+Pass a long with a bitmask to tell libcurl about specific SSL
+behaviors. Available bits:
+.IP CURLSSLOPT_ALLOW_BEAST
+Tells libcurl to not attempt to use any workarounds for a security flaw in the
+SSL3 and TLS1.0 protocols.  If this option isn't used or this bit is set to 0,
+the SSL layer libcurl uses may use a work-around for this flaw although it
+might cause interoperability problems with some (older) SSL
+implementations. WARNING: avoiding this work-around lessens the security, and
+by setting this option to 1 you ask for exactly that.  This option is only
+supported for DarwinSSL, NSS and OpenSSL.
+.IP CURLSSLOPT_NO_REVOKE
+Tells libcurl to disable certificate revocation checks for those SSL backends
+where such behavior is present. This option is only supported for Schannel
+(the native Windows SSL library), with an exception in the case of Windows'
+Untrusted Publishers blacklist which it seems can't be bypassed. (Added in
+7.44.0)
+.IP CURLSSLOPT_NO_PARTIALCHAIN
+Tells libcurl to not accept "partial" certificate chains, which it otherwise
+does by default. This option is only supported for OpenSSL and will fail the
+certificate verification if the chain ends with an intermediate certificate
+and not with a root cert. (Added in 7.68.0)
 .SH DEFAULT
 0
 .SH PROTOCOLS
-All
+All TLS-based protocols
 .SH AVAILABLE
 Added in 7.52.0
 .SH EXAMPLE
diff --git a/docs/libcurl/opts/GNURLOPT_REDIR_PROTOCOLS.3 
b/docs/libcurl/opts/GNURLOPT_REDIR_PROTOCOLS.3
index b1b4fdda0..3a9f07475 100644
--- a/docs/libcurl/opts/GNURLOPT_REDIR_PROTOCOLS.3
+++ b/docs/libcurl/opts/GNURLOPT_REDIR_PROTOCOLS.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -75,7 +75,10 @@ CURLPROTO_TELNET
 CURLPROTO_TFTP
 .fi
 .SH DEFAULT
-All protocols except for FILE, SCP and since 7.40.0 SMB and SMBS.
+HTTP, HTTPS, FTP and FTPS (Since 7.65.2).
+
+Older versions defaulted to all protocols except FILE, SCP and since 7.40.0
+SMB and SMBS.
 .SH PROTOCOLS
 All
 .SH EXAMPLE
diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc
index 56550f05f..52bf422f4 100644
--- a/docs/libcurl/opts/Makefile.inc
+++ b/docs/libcurl/opts/Makefile.inc
@@ -1,353 +1,354 @@
 # Shared between Makefile.am and CMakeLists.txt
 
 man_MANS =                                      \
-  GNURLINFO_ACTIVESOCKET.3                       \
-  GNURLINFO_APPCONNECT_TIME.3                    \
-  GNURLINFO_APPCONNECT_TIME_T.3                  \
-  GNURLINFO_CERTINFO.3                           \
-  GNURLINFO_CONDITION_UNMET.3                    \
-  GNURLINFO_CONNECT_TIME.3                       \
-  GNURLINFO_CONNECT_TIME_T.3                     \
-  GNURLINFO_CONTENT_LENGTH_DOWNLOAD.3            \
-  GNURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3          \
-  GNURLINFO_CONTENT_LENGTH_UPLOAD.3              \
-  GNURLINFO_CONTENT_LENGTH_UPLOAD_T.3            \
-  GNURLINFO_CONTENT_TYPE.3                       \
-  GNURLINFO_COOKIELIST.3                         \
-  GNURLINFO_EFFECTIVE_URL.3                      \
-  GNURLINFO_FILETIME.3                           \
-  GNURLINFO_FILETIME_T.3                         \
-  GNURLINFO_FTP_ENTRY_PATH.3                     \
-  GNURLINFO_HEADER_SIZE.3                        \
-  GNURLINFO_HTTPAUTH_AVAIL.3                     \
-  GNURLINFO_HTTP_CONNECTCODE.3                   \
-  GNURLINFO_HTTP_VERSION.3                       \
-  GNURLINFO_LASTSOCKET.3                         \
-  GNURLINFO_LOCAL_IP.3                           \
-  GNURLINFO_LOCAL_PORT.3                         \
-  GNURLINFO_NAMELOOKUP_TIME.3                    \
-  GNURLINFO_NAMELOOKUP_TIME_T.3                  \
-  GNURLINFO_NUM_CONNECTS.3                       \
-  GNURLINFO_OS_ERRNO.3                           \
-  GNURLINFO_PRETRANSFER_TIME.3                   \
-  GNURLINFO_PRETRANSFER_TIME_T.3                 \
-  GNURLINFO_PRIMARY_IP.3                         \
-  GNURLINFO_PRIMARY_PORT.3                       \
-  GNURLINFO_PRIVATE.3                            \
-  GNURLINFO_PROTOCOL.3                           \
-  GNURLINFO_PROXYAUTH_AVAIL.3                    \
-  GNURLINFO_PROXY_SSL_VERIFYRESULT.3             \
-  GNURLINFO_REDIRECT_COUNT.3                     \
-  GNURLINFO_REDIRECT_TIME.3                      \
-  GNURLINFO_REDIRECT_TIME_T.3                    \
-  GNURLINFO_REDIRECT_URL.3                       \
-  GNURLINFO_REQUEST_SIZE.3                       \
-  GNURLINFO_RESPONSE_CODE.3                      \
-  GNURLINFO_RETRY_AFTER.3                        \
-  GNURLINFO_RTSP_CLIENT_CSEQ.3                   \
-  GNURLINFO_RTSP_CSEQ_RECV.3                     \
-  GNURLINFO_RTSP_SERVER_CSEQ.3                   \
-  GNURLINFO_RTSP_SESSION_ID.3                    \
-  GNURLINFO_SCHEME.3                             \
-  GNURLINFO_SIZE_DOWNLOAD.3                      \
-  GNURLINFO_SIZE_DOWNLOAD_T.3                    \
-  GNURLINFO_SIZE_UPLOAD.3                        \
-  GNURLINFO_SIZE_UPLOAD_T.3                      \
-  GNURLINFO_SPEED_DOWNLOAD.3                     \
-  GNURLINFO_SPEED_DOWNLOAD_T.3                   \
-  GNURLINFO_SPEED_UPLOAD.3                       \
-  GNURLINFO_SPEED_UPLOAD_T.3                     \
-  GNURLINFO_SSL_ENGINES.3                        \
-  GNURLINFO_SSL_VERIFYRESULT.3                   \
-  GNURLINFO_STARTTRANSFER_TIME.3                 \
-  GNURLINFO_STARTTRANSFER_TIME_T.3               \
-  GNURLINFO_TLS_SESSION.3                        \
-  GNURLINFO_TLS_SSL_PTR.3                        \
-  GNURLINFO_TOTAL_TIME.3                         \
-  GNURLINFO_TOTAL_TIME_T.3                       \
-  GNURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3          \
-  GNURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3        \
-  GNURLMOPT_MAXCONNECTS.3                        \
-  GNURLMOPT_MAX_CONCURRENT_STREAMS.3             \
-  GNURLMOPT_MAX_HOST_CONNECTIONS.3               \
-  GNURLMOPT_MAX_PIPELINE_LENGTH.3                \
-  GNURLMOPT_MAX_TOTAL_CONNECTIONS.3              \
-  GNURLMOPT_PIPELINING.3                         \
-  GNURLMOPT_PIPELINING_SERVER_BL.3               \
-  GNURLMOPT_PIPELINING_SITE_BL.3                 \
-  GNURLMOPT_PUSHDATA.3                           \
-  GNURLMOPT_PUSHFUNCTION.3                       \
-  GNURLMOPT_SOCKETDATA.3                         \
-  GNURLMOPT_SOCKETFUNCTION.3                     \
-  GNURLMOPT_TIMERDATA.3                          \
-  GNURLMOPT_TIMERFUNCTION.3                      \
-  GNURLOPT_ABSTRACT_UNIX_SOCKET.3                \
-  GNURLOPT_ACCEPTTIMEOUT_MS.3                    \
-  GNURLOPT_ACCEPT_ENCODING.3                     \
-  GNURLOPT_ADDRESS_SCOPE.3                       \
-  GNURLOPT_ALTSVC.3                              \
-  GNURLOPT_ALTSVC_CTRL.3                         \
-  GNURLOPT_APPEND.3                              \
-  GNURLOPT_AUTOREFERER.3                         \
-  GNURLOPT_BUFFERSIZE.3                          \
-  GNURLOPT_CAINFO.3                              \
-  GNURLOPT_CAPATH.3                              \
-  GNURLOPT_CERTINFO.3                            \
-  GNURLOPT_CHUNK_BGN_FUNCTION.3                  \
-  GNURLOPT_CHUNK_DATA.3                          \
-  GNURLOPT_CHUNK_END_FUNCTION.3                  \
-  GNURLOPT_CLOSESOCKETDATA.3                     \
-  GNURLOPT_CLOSESOCKETFUNCTION.3                 \
-  GNURLOPT_CONNECTTIMEOUT.3                      \
-  GNURLOPT_CONNECTTIMEOUT_MS.3                   \
-  GNURLOPT_CONNECT_ONLY.3                        \
-  GNURLOPT_CONNECT_TO.3                          \
-  GNURLOPT_CONV_FROM_NETWORK_FUNCTION.3          \
-  GNURLOPT_CONV_FROM_UTF8_FUNCTION.3             \
-  GNURLOPT_CONV_TO_NETWORK_FUNCTION.3            \
-  GNURLOPT_COOKIE.3                              \
-  GNURLOPT_COOKIEFILE.3                          \
-  GNURLOPT_COOKIEJAR.3                           \
-  GNURLOPT_COOKIELIST.3                          \
-  GNURLOPT_COOKIESESSION.3                       \
-  GNURLOPT_COPYPOSTFIELDS.3                      \
-  GNURLOPT_CRLF.3                                \
-  GNURLOPT_CRLFILE.3                             \
-  GNURLOPT_CURLU.3                               \
-  GNURLOPT_CUSTOMREQUEST.3                       \
-  GNURLOPT_DEBUGDATA.3                           \
-  GNURLOPT_DEBUGFUNCTION.3                       \
-  GNURLOPT_DEFAULT_PROTOCOL.3                    \
-  GNURLOPT_DIRLISTONLY.3                         \
-  GNURLOPT_DISALLOW_USERNAME_IN_URL.3            \
-  GNURLOPT_DNS_CACHE_TIMEOUT.3                   \
-  GNURLOPT_DNS_INTERFACE.3                       \
-  GNURLOPT_DNS_LOCAL_IP4.3                       \
-  GNURLOPT_DNS_LOCAL_IP6.3                       \
-  GNURLOPT_DNS_SERVERS.3                         \
-  GNURLOPT_DNS_SHUFFLE_ADDRESSES.3               \
-  GNURLOPT_DNS_USE_GLOBAL_CACHE.3                \
-  GNURLOPT_DOH_URL.3                             \
-  GNURLOPT_EGDSOCKET.3                           \
-  GNURLOPT_ERRORBUFFER.3                         \
-  GNURLOPT_EXPECT_100_TIMEOUT_MS.3               \
-  GNURLOPT_FAILONERROR.3                         \
-  GNURLOPT_FILETIME.3                            \
-  GNURLOPT_FNMATCH_DATA.3                        \
-  GNURLOPT_FNMATCH_FUNCTION.3                    \
-  GNURLOPT_FOLLOWLOCATION.3                      \
-  GNURLOPT_FORBID_REUSE.3                        \
-  GNURLOPT_FRESH_CONNECT.3                       \
-  GNURLOPT_FTPPORT.3                             \
-  GNURLOPT_FTPSSLAUTH.3                          \
-  GNURLOPT_FTP_ACCOUNT.3                         \
-  GNURLOPT_FTP_ALTERNATIVE_TO_USER.3             \
-  GNURLOPT_FTP_CREATE_MISSING_DIRS.3             \
-  GNURLOPT_FTP_FILEMETHOD.3                      \
-  GNURLOPT_FTP_RESPONSE_TIMEOUT.3                \
-  GNURLOPT_FTP_SKIP_PASV_IP.3                    \
-  GNURLOPT_FTP_SSL_CCC.3                         \
-  GNURLOPT_FTP_USE_EPRT.3                        \
-  GNURLOPT_FTP_USE_EPSV.3                        \
-  GNURLOPT_FTP_USE_PRET.3                        \
-  GNURLOPT_GSSAPI_DELEGATION.3                   \
-  GNURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3           \
-  GNURLOPT_HAPROXYPROTOCOL.3                     \
-  GNURLOPT_HEADER.3                              \
-  GNURLOPT_HEADERDATA.3                          \
-  GNURLOPT_HEADERFUNCTION.3                      \
-  GNURLOPT_HEADEROPT.3                           \
-  GNURLOPT_HTTP09_ALLOWED.3                      \
-  GNURLOPT_HTTP200ALIASES.3                      \
-  GNURLOPT_HTTPAUTH.3                            \
-  GNURLOPT_HTTPGET.3                             \
-  GNURLOPT_HTTPHEADER.3                          \
-  GNURLOPT_HTTPPOST.3                            \
-  GNURLOPT_HTTPPROXYTUNNEL.3                     \
-  GNURLOPT_HTTP_CONTENT_DECODING.3               \
-  GNURLOPT_HTTP_TRANSFER_DECODING.3              \
-  GNURLOPT_HTTP_VERSION.3                        \
-  GNURLOPT_IGNORE_CONTENT_LENGTH.3               \
-  GNURLOPT_INFILESIZE.3                          \
-  GNURLOPT_INFILESIZE_LARGE.3                    \
-  GNURLOPT_INTERFACE.3                           \
-  GNURLOPT_INTERLEAVEDATA.3                      \
-  GNURLOPT_INTERLEAVEFUNCTION.3                  \
-  GNURLOPT_IOCTLDATA.3                           \
-  GNURLOPT_IOCTLFUNCTION.3                       \
-  GNURLOPT_IPRESOLVE.3                           \
-  GNURLOPT_ISSUERCERT.3                          \
-  GNURLOPT_KEEP_SENDING_ON_ERROR.3               \
-  GNURLOPT_KEYPASSWD.3                           \
-  GNURLOPT_KRBLEVEL.3                            \
-  GNURLOPT_LOCALPORT.3                           \
-  GNURLOPT_LOCALPORTRANGE.3                      \
-  GNURLOPT_LOGIN_OPTIONS.3                       \
-  GNURLOPT_LOW_SPEED_LIMIT.3                     \
-  GNURLOPT_LOW_SPEED_TIME.3                      \
-  GNURLOPT_MAIL_AUTH.3                           \
-  GNURLOPT_MAIL_FROM.3                           \
-  GNURLOPT_MAIL_RCPT.3                           \
-  GNURLOPT_MAXAGE_CONN.3                         \
-  GNURLOPT_MAXCONNECTS.3                         \
-  GNURLOPT_MAXFILESIZE.3                         \
-  GNURLOPT_MAXFILESIZE_LARGE.3                   \
-  GNURLOPT_MAXREDIRS.3                           \
-  GNURLOPT_MAX_RECV_SPEED_LARGE.3                \
-  GNURLOPT_MAX_SEND_SPEED_LARGE.3                \
-  GNURLOPT_MIMEPOST.3                            \
-  GNURLOPT_NETRC.3                               \
-  GNURLOPT_NETRC_FILE.3                          \
-  GNURLOPT_NEW_DIRECTORY_PERMS.3                 \
-  GNURLOPT_NEW_FILE_PERMS.3                      \
-  GNURLOPT_NOBODY.3                              \
-  GNURLOPT_NOPROGRESS.3                          \
-  GNURLOPT_NOPROXY.3                             \
-  GNURLOPT_NOSIGNAL.3                            \
-  GNURLOPT_OPENSOCKETDATA.3                      \
-  GNURLOPT_OPENSOCKETFUNCTION.3                  \
-  GNURLOPT_PASSWORD.3                            \
-  GNURLOPT_PATH_AS_IS.3                          \
-  GNURLOPT_PINNEDPUBLICKEY.3                     \
-  GNURLOPT_PIPEWAIT.3                            \
-  GNURLOPT_PORT.3                                \
-  GNURLOPT_POST.3                                \
-  GNURLOPT_POSTFIELDS.3                          \
-  GNURLOPT_POSTFIELDSIZE.3                       \
-  GNURLOPT_POSTFIELDSIZE_LARGE.3                 \
-  GNURLOPT_POSTQUOTE.3                           \
-  GNURLOPT_POSTREDIR.3                           \
-  GNURLOPT_PREQUOTE.3                            \
-  GNURLOPT_PRE_PROXY.3                           \
-  GNURLOPT_PRIVATE.3                             \
-  GNURLOPT_PROGRESSDATA.3                        \
-  GNURLOPT_PROGRESSFUNCTION.3                    \
-  GNURLOPT_PROTOCOLS.3                           \
-  GNURLOPT_PROXY.3                               \
-  GNURLOPT_PROXYAUTH.3                           \
-  GNURLOPT_PROXYHEADER.3                         \
-  GNURLOPT_PROXYPASSWORD.3                       \
-  GNURLOPT_PROXYPORT.3                           \
-  GNURLOPT_PROXYTYPE.3                           \
-  GNURLOPT_PROXYUSERNAME.3                       \
-  GNURLOPT_PROXYUSERPWD.3                        \
-  GNURLOPT_PROXY_CAINFO.3                        \
-  GNURLOPT_PROXY_CAPATH.3                        \
-  GNURLOPT_PROXY_CRLFILE.3                       \
-  GNURLOPT_PROXY_KEYPASSWD.3                     \
-  GNURLOPT_PROXY_PINNEDPUBLICKEY.3               \
-  GNURLOPT_PROXY_SERVICE_NAME.3                  \
-  GNURLOPT_PROXY_SSLCERT.3                       \
-  GNURLOPT_PROXY_SSLCERTTYPE.3                   \
-  GNURLOPT_PROXY_SSLKEY.3                        \
-  GNURLOPT_PROXY_SSLKEYTYPE.3                    \
-  GNURLOPT_PROXY_SSLVERSION.3                    \
-  GNURLOPT_PROXY_SSL_CIPHER_LIST.3               \
-  GNURLOPT_PROXY_SSL_OPTIONS.3                   \
-  GNURLOPT_PROXY_SSL_VERIFYHOST.3                \
-  GNURLOPT_PROXY_SSL_VERIFYPEER.3                \
-  GNURLOPT_PROXY_TLS13_CIPHERS.3                 \
-  GNURLOPT_PROXY_TLSAUTH_PASSWORD.3              \
-  GNURLOPT_PROXY_TLSAUTH_TYPE.3                  \
-  GNURLOPT_PROXY_TLSAUTH_USERNAME.3              \
-  GNURLOPT_PROXY_TRANSFER_MODE.3                 \
-  GNURLOPT_PUT.3                                 \
-  GNURLOPT_QUOTE.3                               \
-  GNURLOPT_RANDOM_FILE.3                         \
-  GNURLOPT_RANGE.3                               \
-  GNURLOPT_READDATA.3                            \
-  GNURLOPT_READFUNCTION.3                        \
-  GNURLOPT_REDIR_PROTOCOLS.3                     \
-  GNURLOPT_REFERER.3                             \
-  GNURLOPT_REQUEST_TARGET.3                      \
-  GNURLOPT_RESOLVE.3                             \
-  GNURLOPT_RESOLVER_START_DATA.3                 \
-  GNURLOPT_RESOLVER_START_FUNCTION.3             \
-  GNURLOPT_RESUME_FROM.3                         \
-  GNURLOPT_RESUME_FROM_LARGE.3                   \
-  GNURLOPT_RTSP_CLIENT_CSEQ.3                    \
-  GNURLOPT_RTSP_REQUEST.3                        \
-  GNURLOPT_RTSP_SERVER_CSEQ.3                    \
-  GNURLOPT_RTSP_SESSION_ID.3                     \
-  GNURLOPT_RTSP_STREAM_URI.3                     \
-  GNURLOPT_RTSP_TRANSPORT.3                      \
-  GNURLOPT_SASL_AUTHZID.3                        \
-  GNURLOPT_SASL_IR.3                             \
-  GNURLOPT_SEEKDATA.3                            \
-  GNURLOPT_SEEKFUNCTION.3                        \
-  GNURLOPT_SERVICE_NAME.3                        \
-  GNURLOPT_SHARE.3                               \
-  GNURLOPT_SOCKOPTDATA.3                         \
-  GNURLOPT_SOCKOPTFUNCTION.3                     \
-  GNURLOPT_SOCKS5_AUTH.3                         \
-  GNURLOPT_SOCKS5_GSSAPI_NEC.3                   \
-  GNURLOPT_SOCKS5_GSSAPI_SERVICE.3               \
-  GNURLOPT_SSH_AUTH_TYPES.3                      \
-  GNURLOPT_SSH_COMPRESSION.3                     \
-  GNURLOPT_SSH_HOST_PUBLIC_KEY_MD5.3             \
-  GNURLOPT_SSH_KEYDATA.3                         \
-  GNURLOPT_SSH_KEYFUNCTION.3                     \
-  GNURLOPT_SSH_KNOWNHOSTS.3                      \
-  GNURLOPT_SSH_PRIVATE_KEYFILE.3                 \
-  GNURLOPT_SSH_PUBLIC_KEYFILE.3                  \
-  GNURLOPT_SSLCERT.3                             \
-  GNURLOPT_SSLCERTTYPE.3                         \
-  GNURLOPT_SSLENGINE.3                           \
-  GNURLOPT_SSLENGINE_DEFAULT.3                   \
-  GNURLOPT_SSLKEY.3                              \
-  GNURLOPT_SSLKEYTYPE.3                          \
-  GNURLOPT_SSLVERSION.3                          \
-  GNURLOPT_SSL_CIPHER_LIST.3                     \
-  GNURLOPT_SSL_CTX_DATA.3                        \
-  GNURLOPT_SSL_CTX_FUNCTION.3                    \
-  GNURLOPT_SSL_ENABLE_ALPN.3                     \
-  GNURLOPT_SSL_ENABLE_NPN.3                      \
-  GNURLOPT_SSL_FALSESTART.3                      \
-  GNURLOPT_SSL_OPTIONS.3                         \
-  GNURLOPT_SSL_SESSIONID_CACHE.3                 \
-  GNURLOPT_SSL_VERIFYHOST.3                      \
-  GNURLOPT_SSL_VERIFYPEER.3                      \
-  GNURLOPT_SSL_VERIFYSTATUS.3                    \
-  GNURLOPT_STDERR.3                              \
-  GNURLOPT_STREAM_DEPENDS.3                      \
-  GNURLOPT_STREAM_DEPENDS_E.3                    \
-  GNURLOPT_STREAM_WEIGHT.3                       \
-  GNURLOPT_SUPPRESS_CONNECT_HEADERS.3            \
-  GNURLOPT_TCP_FASTOPEN.3                        \
-  GNURLOPT_TCP_KEEPALIVE.3                       \
-  GNURLOPT_TCP_KEEPIDLE.3                        \
-  GNURLOPT_TCP_KEEPINTVL.3                       \
-  GNURLOPT_TCP_NODELAY.3                         \
-  GNURLOPT_TELNETOPTIONS.3                       \
-  GNURLOPT_TFTP_BLKSIZE.3                        \
-  GNURLOPT_TFTP_NO_OPTIONS.3                     \
-  GNURLOPT_TIMECONDITION.3                       \
-  GNURLOPT_TIMEOUT.3                             \
-  GNURLOPT_TIMEOUT_MS.3                          \
-  GNURLOPT_TIMEVALUE.3                           \
-  GNURLOPT_TIMEVALUE_LARGE.3                     \
-  GNURLOPT_TLS13_CIPHERS.3                       \
-  GNURLOPT_TLSAUTH_PASSWORD.3                    \
-  GNURLOPT_TLSAUTH_TYPE.3                        \
-  GNURLOPT_TLSAUTH_USERNAME.3                    \
-  GNURLOPT_TRAILERDATA.3                         \
-  GNURLOPT_TRAILERFUNCTION.3                     \
-  GNURLOPT_TRANSFERTEXT.3                        \
-  GNURLOPT_TRANSFER_ENCODING.3                   \
-  GNURLOPT_UNIX_SOCKET_PATH.3                    \
-  GNURLOPT_UNRESTRICTED_AUTH.3                   \
-  GNURLOPT_UPKEEP_INTERVAL_MS.3                  \
-  GNURLOPT_UPLOAD.3                              \
-  GNURLOPT_UPLOAD_BUFFERSIZE.3                   \
-  GNURLOPT_URL.3                                 \
-  GNURLOPT_USERAGENT.3                           \
-  GNURLOPT_USERNAME.3                            \
-  GNURLOPT_USERPWD.3                             \
-  GNURLOPT_USE_SSL.3                             \
-  GNURLOPT_VERBOSE.3                             \
-  GNURLOPT_WILDCARDMATCH.3                       \
-  GNURLOPT_WRITEDATA.3                           \
-  GNURLOPT_WRITEFUNCTION.3                       \
-  GNURLOPT_XFERINFODATA.3                        \
-  GNURLOPT_XFERINFOFUNCTION.3                    \
-  GNURLOPT_XOAUTH2_BEARER.3
+  CURLINFO_ACTIVESOCKET.3                       \
+  CURLINFO_APPCONNECT_TIME.3                    \
+  CURLINFO_APPCONNECT_TIME_T.3                  \
+  CURLINFO_CERTINFO.3                           \
+  CURLINFO_CONDITION_UNMET.3                    \
+  CURLINFO_CONNECT_TIME.3                       \
+  CURLINFO_CONNECT_TIME_T.3                     \
+  CURLINFO_CONTENT_LENGTH_DOWNLOAD.3            \
+  CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3          \
+  CURLINFO_CONTENT_LENGTH_UPLOAD.3              \
+  CURLINFO_CONTENT_LENGTH_UPLOAD_T.3            \
+  CURLINFO_CONTENT_TYPE.3                       \
+  CURLINFO_COOKIELIST.3                         \
+  CURLINFO_EFFECTIVE_URL.3                      \
+  CURLINFO_FILETIME.3                           \
+  CURLINFO_FILETIME_T.3                         \
+  CURLINFO_FTP_ENTRY_PATH.3                     \
+  CURLINFO_HEADER_SIZE.3                        \
+  CURLINFO_HTTPAUTH_AVAIL.3                     \
+  CURLINFO_HTTP_CONNECTCODE.3                   \
+  CURLINFO_HTTP_VERSION.3                       \
+  CURLINFO_LASTSOCKET.3                         \
+  CURLINFO_LOCAL_IP.3                           \
+  CURLINFO_LOCAL_PORT.3                         \
+  CURLINFO_NAMELOOKUP_TIME.3                    \
+  CURLINFO_NAMELOOKUP_TIME_T.3                  \
+  CURLINFO_NUM_CONNECTS.3                       \
+  CURLINFO_OS_ERRNO.3                           \
+  CURLINFO_PRETRANSFER_TIME.3                   \
+  CURLINFO_PRETRANSFER_TIME_T.3                 \
+  CURLINFO_PRIMARY_IP.3                         \
+  CURLINFO_PRIMARY_PORT.3                       \
+  CURLINFO_PRIVATE.3                            \
+  CURLINFO_PROTOCOL.3                           \
+  CURLINFO_PROXYAUTH_AVAIL.3                    \
+  CURLINFO_PROXY_SSL_VERIFYRESULT.3             \
+  CURLINFO_REDIRECT_COUNT.3                     \
+  CURLINFO_REDIRECT_TIME.3                      \
+  CURLINFO_REDIRECT_TIME_T.3                    \
+  CURLINFO_REDIRECT_URL.3                       \
+  CURLINFO_REQUEST_SIZE.3                       \
+  CURLINFO_RESPONSE_CODE.3                      \
+  CURLINFO_RETRY_AFTER.3                        \
+  CURLINFO_RTSP_CLIENT_CSEQ.3                   \
+  CURLINFO_RTSP_CSEQ_RECV.3                     \
+  CURLINFO_RTSP_SERVER_CSEQ.3                   \
+  CURLINFO_RTSP_SESSION_ID.3                    \
+  CURLINFO_SCHEME.3                             \
+  CURLINFO_SIZE_DOWNLOAD.3                      \
+  CURLINFO_SIZE_DOWNLOAD_T.3                    \
+  CURLINFO_SIZE_UPLOAD.3                        \
+  CURLINFO_SIZE_UPLOAD_T.3                      \
+  CURLINFO_SPEED_DOWNLOAD.3                     \
+  CURLINFO_SPEED_DOWNLOAD_T.3                   \
+  CURLINFO_SPEED_UPLOAD.3                       \
+  CURLINFO_SPEED_UPLOAD_T.3                     \
+  CURLINFO_SSL_ENGINES.3                        \
+  CURLINFO_SSL_VERIFYRESULT.3                   \
+  CURLINFO_STARTTRANSFER_TIME.3                 \
+  CURLINFO_STARTTRANSFER_TIME_T.3               \
+  CURLINFO_TLS_SESSION.3                        \
+  CURLINFO_TLS_SSL_PTR.3                        \
+  CURLINFO_TOTAL_TIME.3                         \
+  CURLINFO_TOTAL_TIME_T.3                       \
+  CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3          \
+  CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3        \
+  CURLMOPT_MAXCONNECTS.3                        \
+  CURLMOPT_MAX_CONCURRENT_STREAMS.3             \
+  CURLMOPT_MAX_HOST_CONNECTIONS.3               \
+  CURLMOPT_MAX_PIPELINE_LENGTH.3                \
+  CURLMOPT_MAX_TOTAL_CONNECTIONS.3              \
+  CURLMOPT_PIPELINING.3                         \
+  CURLMOPT_PIPELINING_SERVER_BL.3               \
+  CURLMOPT_PIPELINING_SITE_BL.3                 \
+  CURLMOPT_PUSHDATA.3                           \
+  CURLMOPT_PUSHFUNCTION.3                       \
+  CURLMOPT_SOCKETDATA.3                         \
+  CURLMOPT_SOCKETFUNCTION.3                     \
+  CURLMOPT_TIMERDATA.3                          \
+  CURLMOPT_TIMERFUNCTION.3                      \
+  CURLOPT_ABSTRACT_UNIX_SOCKET.3                \
+  CURLOPT_ACCEPTTIMEOUT_MS.3                    \
+  CURLOPT_ACCEPT_ENCODING.3                     \
+  CURLOPT_ADDRESS_SCOPE.3                       \
+  CURLOPT_ALTSVC.3                              \
+  CURLOPT_ALTSVC_CTRL.3                         \
+  CURLOPT_APPEND.3                              \
+  CURLOPT_AUTOREFERER.3                         \
+  CURLOPT_BUFFERSIZE.3                          \
+  CURLOPT_CAINFO.3                              \
+  CURLOPT_CAPATH.3                              \
+  CURLOPT_CERTINFO.3                            \
+  CURLOPT_CHUNK_BGN_FUNCTION.3                  \
+  CURLOPT_CHUNK_DATA.3                          \
+  CURLOPT_CHUNK_END_FUNCTION.3                  \
+  CURLOPT_CLOSESOCKETDATA.3                     \
+  CURLOPT_CLOSESOCKETFUNCTION.3                 \
+  CURLOPT_CONNECTTIMEOUT.3                      \
+  CURLOPT_CONNECTTIMEOUT_MS.3                   \
+  CURLOPT_CONNECT_ONLY.3                        \
+  CURLOPT_CONNECT_TO.3                          \
+  CURLOPT_CONV_FROM_NETWORK_FUNCTION.3          \
+  CURLOPT_CONV_FROM_UTF8_FUNCTION.3             \
+  CURLOPT_CONV_TO_NETWORK_FUNCTION.3            \
+  CURLOPT_COOKIE.3                              \
+  CURLOPT_COOKIEFILE.3                          \
+  CURLOPT_COOKIEJAR.3                           \
+  CURLOPT_COOKIELIST.3                          \
+  CURLOPT_COOKIESESSION.3                       \
+  CURLOPT_COPYPOSTFIELDS.3                      \
+  CURLOPT_CRLF.3                                \
+  CURLOPT_CRLFILE.3                             \
+  CURLOPT_CURLU.3                               \
+  CURLOPT_CUSTOMREQUEST.3                       \
+  CURLOPT_DEBUGDATA.3                           \
+  CURLOPT_DEBUGFUNCTION.3                       \
+  CURLOPT_DEFAULT_PROTOCOL.3                    \
+  CURLOPT_DIRLISTONLY.3                         \
+  CURLOPT_DISALLOW_USERNAME_IN_URL.3            \
+  CURLOPT_DNS_CACHE_TIMEOUT.3                   \
+  CURLOPT_DNS_INTERFACE.3                       \
+  CURLOPT_DNS_LOCAL_IP4.3                       \
+  CURLOPT_DNS_LOCAL_IP6.3                       \
+  CURLOPT_DNS_SERVERS.3                         \
+  CURLOPT_DNS_SHUFFLE_ADDRESSES.3               \
+  CURLOPT_DNS_USE_GLOBAL_CACHE.3                \
+  CURLOPT_DOH_URL.3                             \
+  CURLOPT_EGDSOCKET.3                           \
+  CURLOPT_ERRORBUFFER.3                         \
+  CURLOPT_EXPECT_100_TIMEOUT_MS.3               \
+  CURLOPT_FAILONERROR.3                         \
+  CURLOPT_FILETIME.3                            \
+  CURLOPT_FNMATCH_DATA.3                        \
+  CURLOPT_FNMATCH_FUNCTION.3                    \
+  CURLOPT_FOLLOWLOCATION.3                      \
+  CURLOPT_FORBID_REUSE.3                        \
+  CURLOPT_FRESH_CONNECT.3                       \
+  CURLOPT_FTPPORT.3                             \
+  CURLOPT_FTPSSLAUTH.3                          \
+  CURLOPT_FTP_ACCOUNT.3                         \
+  CURLOPT_FTP_ALTERNATIVE_TO_USER.3             \
+  CURLOPT_FTP_CREATE_MISSING_DIRS.3             \
+  CURLOPT_FTP_FILEMETHOD.3                      \
+  CURLOPT_FTP_RESPONSE_TIMEOUT.3                \
+  CURLOPT_FTP_SKIP_PASV_IP.3                    \
+  CURLOPT_FTP_SSL_CCC.3                         \
+  CURLOPT_FTP_USE_EPRT.3                        \
+  CURLOPT_FTP_USE_EPSV.3                        \
+  CURLOPT_FTP_USE_PRET.3                        \
+  CURLOPT_GSSAPI_DELEGATION.3                   \
+  CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3           \
+  CURLOPT_HAPROXYPROTOCOL.3                     \
+  CURLOPT_HEADER.3                              \
+  CURLOPT_HEADERDATA.3                          \
+  CURLOPT_HEADERFUNCTION.3                      \
+  CURLOPT_HEADEROPT.3                           \
+  CURLOPT_HTTP09_ALLOWED.3                      \
+  CURLOPT_HTTP200ALIASES.3                      \
+  CURLOPT_HTTPAUTH.3                            \
+  CURLOPT_HTTPGET.3                             \
+  CURLOPT_HTTPHEADER.3                          \
+  CURLOPT_HTTPPOST.3                            \
+  CURLOPT_HTTPPROXYTUNNEL.3                     \
+  CURLOPT_HTTP_CONTENT_DECODING.3               \
+  CURLOPT_HTTP_TRANSFER_DECODING.3              \
+  CURLOPT_HTTP_VERSION.3                        \
+  CURLOPT_IGNORE_CONTENT_LENGTH.3               \
+  CURLOPT_INFILESIZE.3                          \
+  CURLOPT_INFILESIZE_LARGE.3                    \
+  CURLOPT_INTERFACE.3                           \
+  CURLOPT_INTERLEAVEDATA.3                      \
+  CURLOPT_INTERLEAVEFUNCTION.3                  \
+  CURLOPT_IOCTLDATA.3                           \
+  CURLOPT_IOCTLFUNCTION.3                       \
+  CURLOPT_IPRESOLVE.3                           \
+  CURLOPT_ISSUERCERT.3                          \
+  CURLOPT_KEEP_SENDING_ON_ERROR.3               \
+  CURLOPT_KEYPASSWD.3                           \
+  CURLOPT_KRBLEVEL.3                            \
+  CURLOPT_LOCALPORT.3                           \
+  CURLOPT_LOCALPORTRANGE.3                      \
+  CURLOPT_LOGIN_OPTIONS.3                       \
+  CURLOPT_LOW_SPEED_LIMIT.3                     \
+  CURLOPT_LOW_SPEED_TIME.3                      \
+  CURLOPT_MAIL_AUTH.3                           \
+  CURLOPT_MAIL_FROM.3                           \
+  CURLOPT_MAIL_RCPT.3                           \
+  CURLOPT_MAIL_RCPT_ALLLOWFAILS.3               \
+  CURLOPT_MAXAGE_CONN.3                         \
+  CURLOPT_MAXCONNECTS.3                         \
+  CURLOPT_MAXFILESIZE.3                         \
+  CURLOPT_MAXFILESIZE_LARGE.3                   \
+  CURLOPT_MAXREDIRS.3                           \
+  CURLOPT_MAX_RECV_SPEED_LARGE.3                \
+  CURLOPT_MAX_SEND_SPEED_LARGE.3                \
+  CURLOPT_MIMEPOST.3                            \
+  CURLOPT_NETRC.3                               \
+  CURLOPT_NETRC_FILE.3                          \
+  CURLOPT_NEW_DIRECTORY_PERMS.3                 \
+  CURLOPT_NEW_FILE_PERMS.3                      \
+  CURLOPT_NOBODY.3                              \
+  CURLOPT_NOPROGRESS.3                          \
+  CURLOPT_NOPROXY.3                             \
+  CURLOPT_NOSIGNAL.3                            \
+  CURLOPT_OPENSOCKETDATA.3                      \
+  CURLOPT_OPENSOCKETFUNCTION.3                  \
+  CURLOPT_PASSWORD.3                            \
+  CURLOPT_PATH_AS_IS.3                          \
+  CURLOPT_PINNEDPUBLICKEY.3                     \
+  CURLOPT_PIPEWAIT.3                            \
+  CURLOPT_PORT.3                                \
+  CURLOPT_POST.3                                \
+  CURLOPT_POSTFIELDS.3                          \
+  CURLOPT_POSTFIELDSIZE.3                       \
+  CURLOPT_POSTFIELDSIZE_LARGE.3                 \
+  CURLOPT_POSTQUOTE.3                           \
+  CURLOPT_POSTREDIR.3                           \
+  CURLOPT_PREQUOTE.3                            \
+  CURLOPT_PRE_PROXY.3                           \
+  CURLOPT_PRIVATE.3                             \
+  CURLOPT_PROGRESSDATA.3                        \
+  CURLOPT_PROGRESSFUNCTION.3                    \
+  CURLOPT_PROTOCOLS.3                           \
+  CURLOPT_PROXY.3                               \
+  CURLOPT_PROXYAUTH.3                           \
+  CURLOPT_PROXYHEADER.3                         \
+  CURLOPT_PROXYPASSWORD.3                       \
+  CURLOPT_PROXYPORT.3                           \
+  CURLOPT_PROXYTYPE.3                           \
+  CURLOPT_PROXYUSERNAME.3                       \
+  CURLOPT_PROXYUSERPWD.3                        \
+  CURLOPT_PROXY_CAINFO.3                        \
+  CURLOPT_PROXY_CAPATH.3                        \
+  CURLOPT_PROXY_CRLFILE.3                       \
+  CURLOPT_PROXY_KEYPASSWD.3                     \
+  CURLOPT_PROXY_PINNEDPUBLICKEY.3               \
+  CURLOPT_PROXY_SERVICE_NAME.3                  \
+  CURLOPT_PROXY_SSLCERT.3                       \
+  CURLOPT_PROXY_SSLCERTTYPE.3                   \
+  CURLOPT_PROXY_SSLKEY.3                        \
+  CURLOPT_PROXY_SSLKEYTYPE.3                    \
+  CURLOPT_PROXY_SSLVERSION.3                    \
+  CURLOPT_PROXY_SSL_CIPHER_LIST.3               \
+  CURLOPT_PROXY_SSL_OPTIONS.3                   \
+  CURLOPT_PROXY_SSL_VERIFYHOST.3                \
+  CURLOPT_PROXY_SSL_VERIFYPEER.3                \
+  CURLOPT_PROXY_TLS13_CIPHERS.3                 \
+  CURLOPT_PROXY_TLSAUTH_PASSWORD.3              \
+  CURLOPT_PROXY_TLSAUTH_TYPE.3                  \
+  CURLOPT_PROXY_TLSAUTH_USERNAME.3              \
+  CURLOPT_PROXY_TRANSFER_MODE.3                 \
+  CURLOPT_PUT.3                                 \
+  CURLOPT_QUOTE.3                               \
+  CURLOPT_RANDOM_FILE.3                         \
+  CURLOPT_RANGE.3                               \
+  CURLOPT_READDATA.3                            \
+  CURLOPT_READFUNCTION.3                        \
+  CURLOPT_REDIR_PROTOCOLS.3                     \
+  CURLOPT_REFERER.3                             \
+  CURLOPT_REQUEST_TARGET.3                      \
+  CURLOPT_RESOLVE.3                             \
+  CURLOPT_RESOLVER_START_DATA.3                 \
+  CURLOPT_RESOLVER_START_FUNCTION.3             \
+  CURLOPT_RESUME_FROM.3                         \
+  CURLOPT_RESUME_FROM_LARGE.3                   \
+  CURLOPT_RTSP_CLIENT_CSEQ.3                    \
+  CURLOPT_RTSP_REQUEST.3                        \
+  CURLOPT_RTSP_SERVER_CSEQ.3                    \
+  CURLOPT_RTSP_SESSION_ID.3                     \
+  CURLOPT_RTSP_STREAM_URI.3                     \
+  CURLOPT_RTSP_TRANSPORT.3                      \
+  CURLOPT_SASL_AUTHZID.3                        \
+  CURLOPT_SASL_IR.3                             \
+  CURLOPT_SEEKDATA.3                            \
+  CURLOPT_SEEKFUNCTION.3                        \
+  CURLOPT_SERVICE_NAME.3                        \
+  CURLOPT_SHARE.3                               \
+  CURLOPT_SOCKOPTDATA.3                         \
+  CURLOPT_SOCKOPTFUNCTION.3                     \
+  CURLOPT_SOCKS5_AUTH.3                         \
+  CURLOPT_SOCKS5_GSSAPI_NEC.3                   \
+  CURLOPT_SOCKS5_GSSAPI_SERVICE.3               \
+  CURLOPT_SSH_AUTH_TYPES.3                      \
+  CURLOPT_SSH_COMPRESSION.3                     \
+  CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.3             \
+  CURLOPT_SSH_KEYDATA.3                         \
+  CURLOPT_SSH_KEYFUNCTION.3                     \
+  CURLOPT_SSH_KNOWNHOSTS.3                      \
+  CURLOPT_SSH_PRIVATE_KEYFILE.3                 \
+  CURLOPT_SSH_PUBLIC_KEYFILE.3                  \
+  CURLOPT_SSLCERT.3                             \
+  CURLOPT_SSLCERTTYPE.3                         \
+  CURLOPT_SSLENGINE.3                           \
+  CURLOPT_SSLENGINE_DEFAULT.3                   \
+  CURLOPT_SSLKEY.3                              \
+  CURLOPT_SSLKEYTYPE.3                          \
+  CURLOPT_SSLVERSION.3                          \
+  CURLOPT_SSL_CIPHER_LIST.3                     \
+  CURLOPT_SSL_CTX_DATA.3                        \
+  CURLOPT_SSL_CTX_FUNCTION.3                    \
+  CURLOPT_SSL_ENABLE_ALPN.3                     \
+  CURLOPT_SSL_ENABLE_NPN.3                      \
+  CURLOPT_SSL_FALSESTART.3                      \
+  CURLOPT_SSL_OPTIONS.3                         \
+  CURLOPT_SSL_SESSIONID_CACHE.3                 \
+  CURLOPT_SSL_VERIFYHOST.3                      \
+  CURLOPT_SSL_VERIFYPEER.3                      \
+  CURLOPT_SSL_VERIFYSTATUS.3                    \
+  CURLOPT_STDERR.3                              \
+  CURLOPT_STREAM_DEPENDS.3                      \
+  CURLOPT_STREAM_DEPENDS_E.3                    \
+  CURLOPT_STREAM_WEIGHT.3                       \
+  CURLOPT_SUPPRESS_CONNECT_HEADERS.3            \
+  CURLOPT_TCP_FASTOPEN.3                        \
+  CURLOPT_TCP_KEEPALIVE.3                       \
+  CURLOPT_TCP_KEEPIDLE.3                        \
+  CURLOPT_TCP_KEEPINTVL.3                       \
+  CURLOPT_TCP_NODELAY.3                         \
+  CURLOPT_TELNETOPTIONS.3                       \
+  CURLOPT_TFTP_BLKSIZE.3                        \
+  CURLOPT_TFTP_NO_OPTIONS.3                     \
+  CURLOPT_TIMECONDITION.3                       \
+  CURLOPT_TIMEOUT.3                             \
+  CURLOPT_TIMEOUT_MS.3                          \
+  CURLOPT_TIMEVALUE.3                           \
+  CURLOPT_TIMEVALUE_LARGE.3                     \
+  CURLOPT_TLS13_CIPHERS.3                       \
+  CURLOPT_TLSAUTH_PASSWORD.3                    \
+  CURLOPT_TLSAUTH_TYPE.3                        \
+  CURLOPT_TLSAUTH_USERNAME.3                    \
+  CURLOPT_TRAILERDATA.3                         \
+  CURLOPT_TRAILERFUNCTION.3                     \
+  CURLOPT_TRANSFERTEXT.3                        \
+  CURLOPT_TRANSFER_ENCODING.3                   \
+  CURLOPT_UNIX_SOCKET_PATH.3                    \
+  CURLOPT_UNRESTRICTED_AUTH.3                   \
+  CURLOPT_UPKEEP_INTERVAL_MS.3                  \
+  CURLOPT_UPLOAD.3                              \
+  CURLOPT_UPLOAD_BUFFERSIZE.3                   \
+  CURLOPT_URL.3                                 \
+  CURLOPT_USERAGENT.3                           \
+  CURLOPT_USERNAME.3                            \
+  CURLOPT_USERPWD.3                             \
+  CURLOPT_USE_SSL.3                             \
+  CURLOPT_VERBOSE.3                             \
+  CURLOPT_WILDCARDMATCH.3                       \
+  CURLOPT_WRITEDATA.3                           \
+  CURLOPT_WRITEFUNCTION.3                       \
+  CURLOPT_XFERINFODATA.3                        \
+  CURLOPT_XFERINFOFUNCTION.3                    \
+  CURLOPT_XOAUTH2_BEARER.3
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index 18f04bd70..93930c435 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -105,6 +105,7 @@ CURLE_OPERATION_TIMEOUTED       7.1           7.17.0
 CURLE_OUT_OF_MEMORY             7.1
 CURLE_PARTIAL_FILE              7.1
 CURLE_PEER_FAILED_VERIFICATION  7.17.1
+CURLE_QUIC_CONNECT_ERROR        7.69.0
 CURLE_QUOTE_ERROR               7.17.0
 CURLE_RANGE_ERROR               7.17.0
 CURLE_READ_ERROR                7.1
@@ -317,10 +318,10 @@ CURLKHTYPE_UNKNOWN              7.19.6
 CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 7.30.0
 CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 7.30.0
 CURLMOPT_MAXCONNECTS            7.16.3
+CURLMOPT_MAX_CONCURRENT_STREAMS  7.67.0
 CURLMOPT_MAX_HOST_CONNECTIONS   7.30.0
 CURLMOPT_MAX_PIPELINE_LENGTH    7.30.0
 CURLMOPT_MAX_TOTAL_CONNECTIONS  7.30.0
-CURLMOPT_MAX_CONCURRENT_STREAMS  7.67.0
 CURLMOPT_PIPELINING             7.16.0
 CURLMOPT_PIPELINING_SERVER_BL   7.30.0
 CURLMOPT_PIPELINING_SITE_BL     7.30.0
@@ -334,6 +335,7 @@ CURLMSG_DONE                    7.9.6
 CURLMSG_NONE                    7.9.6
 CURLM_ADDED_ALREADY             7.32.1
 CURLM_BAD_EASY_HANDLE           7.9.6
+CURLM_BAD_FUNCTION_ARGUMENT     7.69.0
 CURLM_BAD_HANDLE                7.9.6
 CURLM_BAD_SOCKET                7.15.4
 CURLM_CALL_MULTI_PERFORM        7.9.6
@@ -342,14 +344,15 @@ CURLM_INTERNAL_ERROR            7.9.6
 CURLM_OK                        7.9.6
 CURLM_OUT_OF_MEMORY             7.9.6
 CURLM_RECURSIVE_API_CALL        7.59.0
-CURLM_WAKEUP_FAILURE            7.68.0
 CURLM_UNKNOWN_OPTION            7.15.4
+CURLM_WAKEUP_FAILURE            7.68.0
+CURLOPT                         7.69.0
 CURLOPTTYPE_FUNCTIONPOINT       7.1
 CURLOPTTYPE_LONG                7.1
 CURLOPTTYPE_OBJECTPOINT         7.1
 CURLOPTTYPE_OFF_T               7.11.0
-CURLOPTTYPE_STRINGPOINT         7.46.0
 CURLOPTTYPE_SLISTPOINT          7.65.2
+CURLOPTTYPE_STRINGPOINT         7.46.0
 CURLOPT_ABSTRACT_UNIX_SOCKET    7.53.0
 CURLOPT_ACCEPTTIMEOUT_MS        7.24.0
 CURLOPT_ACCEPT_ENCODING         7.21.6
@@ -468,6 +471,7 @@ CURLOPT_LOW_SPEED_TIME          7.1
 CURLOPT_MAIL_AUTH               7.25.0
 CURLOPT_MAIL_FROM               7.20.0
 CURLOPT_MAIL_RCPT               7.20.0
+CURLOPT_MAIL_RCPT_ALLLOWFAILS   7.69.0
 CURLOPT_MAXAGE_CONN             7.65.0
 CURLOPT_MAXCONNECTS             7.7
 CURLOPT_MAXFILESIZE             7.10.8
@@ -732,7 +736,7 @@ CURLSSLBACKEND_MESALINK         7.62.0
 CURLSSLBACKEND_NONE             7.34.0
 CURLSSLBACKEND_NSS              7.34.0
 CURLSSLBACKEND_OPENSSL          7.34.0
-CURLSSLBACKEND_POLARSSL         7.34.0
+CURLSSLBACKEND_POLARSSL         7.34.0       7.69.0
 CURLSSLBACKEND_QSOSSL           7.34.0        -           7.38.1
 CURLSSLBACKEND_SCHANNEL         7.34.0
 CURLSSLBACKEND_SECURETRANSPORT  7.64.1
@@ -783,8 +787,8 @@ CURLU_DEFAULT_SCHEME            7.62.0
 CURLU_DISALLOW_USER             7.62.0
 CURLU_GUESS_SCHEME              7.62.0
 CURLU_NON_SUPPORT_SCHEME        7.62.0
-CURLU_NO_DEFAULT_PORT           7.62.0
 CURLU_NO_AUTHORITY              7.67.0
+CURLU_NO_DEFAULT_PORT           7.62.0
 CURLU_PATH_AS_IS                7.62.0
 CURLU_URLDECODE                 7.62.0
 CURLU_URLENCODE                 7.62.0
@@ -793,8 +797,8 @@ CURLVERSION_FIRST               7.10
 CURLVERSION_FOURTH              7.16.1
 CURLVERSION_NOW                 7.10
 CURLVERSION_SECOND              7.11.1
-CURLVERSION_THIRD               7.12.0
 CURLVERSION_SIXTH               7.66.0
+CURLVERSION_THIRD               7.12.0
 CURL_CHUNK_BGN_FUNC_FAIL        7.21.0
 CURL_CHUNK_BGN_FUNC_OK          7.21.0
 CURL_CHUNK_BGN_FUNC_SKIP        7.21.0
@@ -956,5 +960,6 @@ CURL_VERSION_UNIX_SOCKETS       7.40.0
 CURL_WAIT_POLLIN                7.28.0
 CURL_WAIT_POLLOUT               7.28.0
 CURL_WAIT_POLLPRI               7.28.0
+CURL_WIN32                      7.69.0
 CURL_WRITEFUNC_PAUSE            7.18.0
 CURL_ZERO_TERMINATED            7.56.0
diff --git a/include/gnurl/curl.h b/include/gnurl/curl.h
index a9754fd64..b7cb30a58 100644
--- a/include/gnurl/curl.h
+++ b/include/gnurl/curl.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -38,12 +38,12 @@
 #include "system.h"          /* determine things run-time */
 
 /*
- * Define WIN32 when build target is Win32 API
+ * Define CURL_WIN32 when build target is Win32 API
  */
 
-#if (defined(_WIN32) || defined(__WIN32__)) && \
-     !defined(WIN32) && !defined(__SYMBIAN32__)
-#define WIN32
+#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) &&        \
+  !defined(__SYMBIAN32__)
+#define CURL_WIN32
 #endif
 
 #include <stdio.h>
@@ -58,7 +58,7 @@
 #include <sys/types.h>
 #include <time.h>
 
-#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
+#if defined(CURL_WIN32) && !defined(_WIN32_WCE) && !defined(__CYGWIN__)
 #if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H) || \
       defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H))
 /* The check above prevents the winsock2 inclusion if winsock.h already was
@@ -79,11 +79,11 @@
 #include <sys/select.h>
 #endif
 
-#if !defined(WIN32) && !defined(_WIN32_WCE)
+#if !defined(CURL_WIN32) && !defined(_WIN32_WCE)
 #include <sys/socket.h>
 #endif
 
-#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__)
+#if !defined(CURL_WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__)
 #include <sys/time.h>
 #endif
 
@@ -114,7 +114,7 @@ typedef void CURLSH;
 
 #ifdef CURL_STATICLIB
 #  define CURL_EXTERN
-#elif defined(WIN32) || defined(__SYMBIAN32__) || \
+#elif defined(CURL_WIN32) || defined(__SYMBIAN32__) || \
      (__has_declspec_attribute(dllexport) && \
       __has_declspec_attribute(dllimport))
 #  if defined(BUILDING_LIBCURL)
@@ -130,7 +130,7 @@ typedef void CURLSH;
 
 #ifndef curl_socket_typedef
 /* socket typedef */
-#if defined(WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
+#if defined(CURL_WIN32) && !defined(__LWIP_OPT_H__) && !defined(LWIP_HDR_OPT_H)
 typedef SOCKET curl_socket_t;
 #define CURL_SOCKET_BAD INVALID_SOCKET
 #else
@@ -609,6 +609,7 @@ typedef enum {
   CURLE_AUTH_ERROR,              /* 94 - an authentication function returned an
                                     error */
   CURLE_HTTP3,                   /* 95 - An HTTP/3 layer problem */
+  CURLE_QUIC_CONNECT_ERROR,      /* 96 - QUIC connection error */
   CURL_LAST /* never use! */
 } CURLcode;
 
@@ -943,77 +944,58 @@ typedef enum {
 /* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the
    string options from the header file */
 
-/* name is uppercase CURLOPT_<name>,
-   type is one of the defined CURLOPTTYPE_<type>
-   number is unique identifier */
-#ifdef CINIT
-#undef CINIT
-#endif
 
-#ifdef CURL_ISOCPP
-#define CINIT(na,t,nu) CURLOPT_ ## na = CURLOPTTYPE_ ## t + nu
-#else
-/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
-#define LONG          CURLOPTTYPE_LONG
-#define OBJECTPOINT   CURLOPTTYPE_OBJECTPOINT
-#define STRINGPOINT   CURLOPTTYPE_OBJECTPOINT
-#define SLISTPOINT    CURLOPTTYPE_OBJECTPOINT
-#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
-#define OFF_T         CURLOPTTYPE_OFF_T
-#define CINIT(name,type,number) CURLOPT_/**/name = type + number
-#endif
+#define CURLOPT(na,t,nu) na = t + nu
 
 /* handy aliases that make no run-time difference */
 #define CURLOPTTYPE_STRINGPOINT  CURLOPTTYPE_OBJECTPOINT
 #define CURLOPTTYPE_SLISTPOINT  CURLOPTTYPE_OBJECTPOINT
 
 /*
- * This macro-mania below setups the CURLOPT_[what] enum, to be used with
- * curl_easy_setopt(). The first argument in the CINIT() macro is the [what]
- * word.
+ * All CURLOPT_* values.
  */
 
 typedef enum {
   /* This is the FILE * or void * the regular output should be written to. */
-  CINIT(WRITEDATA, OBJECTPOINT, 1),
+  CURLOPT(CURLOPT_WRITEDATA, CURLOPTTYPE_OBJECTPOINT, 1),
 
   /* The full URL to get/put */
-  CINIT(URL, STRINGPOINT, 2),
+  CURLOPT(CURLOPT_URL, CURLOPTTYPE_STRINGPOINT, 2),
 
   /* Port number to connect to, if other than default. */
-  CINIT(PORT, LONG, 3),
+  CURLOPT(CURLOPT_PORT, CURLOPTTYPE_LONG, 3),
 
   /* Name of proxy to use. */
-  CINIT(PROXY, STRINGPOINT, 4),
+  CURLOPT(CURLOPT_PROXY, CURLOPTTYPE_STRINGPOINT, 4),
 
   /* "user:password;options" to use when fetching. */
-  CINIT(USERPWD, STRINGPOINT, 5),
+  CURLOPT(CURLOPT_USERPWD, CURLOPTTYPE_STRINGPOINT, 5),
 
   /* "user:password" to use with proxy. */
-  CINIT(PROXYUSERPWD, STRINGPOINT, 6),
+  CURLOPT(CURLOPT_PROXYUSERPWD, CURLOPTTYPE_STRINGPOINT, 6),
 
   /* Range to get, specified as an ASCII string. */
-  CINIT(RANGE, STRINGPOINT, 7),
+  CURLOPT(CURLOPT_RANGE, CURLOPTTYPE_STRINGPOINT, 7),
 
   /* not used */
 
   /* Specified file stream to upload from (use as input): */
-  CINIT(READDATA, OBJECTPOINT, 9),
+  CURLOPT(CURLOPT_READDATA, CURLOPTTYPE_OBJECTPOINT, 9),
 
   /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
    * bytes big. */
-  CINIT(ERRORBUFFER, OBJECTPOINT, 10),
+  CURLOPT(CURLOPT_ERRORBUFFER, CURLOPTTYPE_OBJECTPOINT, 10),
 
   /* Function that will be called to store the output (instead of fwrite). The
    * parameters will use fwrite() syntax, make sure to follow them. */
-  CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
+  CURLOPT(CURLOPT_WRITEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 11),
 
   /* Function that will be called to read the input (instead of fread). The
    * parameters will use fread() syntax, make sure to follow them. */
-  CINIT(READFUNCTION, FUNCTIONPOINT, 12),
+  CURLOPT(CURLOPT_READFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 12),
 
   /* Time-out the read operation after this amount of seconds */
-  CINIT(TIMEOUT, LONG, 13),
+  CURLOPT(CURLOPT_TIMEOUT, CURLOPTTYPE_LONG, 13),
 
   /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
    * how large the file being sent really is. That allows better error
@@ -1024,20 +1006,20 @@ typedef enum {
    * which takes an off_t type, allowing platforms with larger off_t
    * sizes to handle larger files.  See below for INFILESIZE_LARGE.
    */
-  CINIT(INFILESIZE, LONG, 14),
+  CURLOPT(CURLOPT_INFILESIZE, CURLOPTTYPE_LONG, 14),
 
   /* POST static input fields. */
-  CINIT(POSTFIELDS, OBJECTPOINT, 15),
+  CURLOPT(CURLOPT_POSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 15),
 
   /* Set the referrer page (needed by some CGIs) */
-  CINIT(REFERER, STRINGPOINT, 16),
+  CURLOPT(CURLOPT_REFERER, CURLOPTTYPE_STRINGPOINT, 16),
 
   /* Set the FTP PORT string (interface name, named or numerical IP address)
      Use i.e '-' to use default address. */
-  CINIT(FTPPORT, STRINGPOINT, 17),
+  CURLOPT(CURLOPT_FTPPORT, CURLOPTTYPE_STRINGPOINT, 17),
 
   /* Set the User-Agent string (examined by some CGIs) */
-  CINIT(USERAGENT, STRINGPOINT, 18),
+  CURLOPT(CURLOPT_USERAGENT, CURLOPTTYPE_STRINGPOINT, 18),
 
   /* If the download receives less than "low speed limit" bytes/second
    * during "low speed time" seconds, the operations is aborted.
@@ -1046,10 +1028,10 @@ typedef enum {
    */
 
   /* Set the "low speed limit" */
-  CINIT(LOW_SPEED_LIMIT, LONG, 19),
+  CURLOPT(CURLOPT_LOW_SPEED_LIMIT, CURLOPTTYPE_LONG, 19),
 
   /* Set the "low speed time" */
-  CINIT(LOW_SPEED_TIME, LONG, 20),
+  CURLOPT(CURLOPT_LOW_SPEED_TIME, CURLOPTTYPE_LONG, 20),
 
   /* Set the continuation offset.
    *
@@ -1057,48 +1039,48 @@ typedef enum {
    * off_t types, allowing for large file offsets on platforms which
    * use larger-than-32-bit off_t's.  Look below for RESUME_FROM_LARGE.
    */
-  CINIT(RESUME_FROM, LONG, 21),
+  CURLOPT(CURLOPT_RESUME_FROM, CURLOPTTYPE_LONG, 21),
 
   /* Set cookie in request: */
-  CINIT(COOKIE, STRINGPOINT, 22),
+  CURLOPT(CURLOPT_COOKIE, CURLOPTTYPE_STRINGPOINT, 22),
 
   /* This points to a linked list of headers, struct curl_slist kind. This
      list is also used for RTSP (in spite of its name) */
-  CINIT(HTTPHEADER, SLISTPOINT, 23),
+  CURLOPT(CURLOPT_HTTPHEADER, CURLOPTTYPE_SLISTPOINT, 23),
 
   /* This points to a linked list of post entries, struct curl_httppost */
-  CINIT(HTTPPOST, OBJECTPOINT, 24),
+  CURLOPT(CURLOPT_HTTPPOST, CURLOPTTYPE_OBJECTPOINT, 24),
 
   /* name of the file keeping your private SSL-certificate */
-  CINIT(SSLCERT, STRINGPOINT, 25),
+  CURLOPT(CURLOPT_SSLCERT, CURLOPTTYPE_STRINGPOINT, 25),
 
   /* password for the SSL or SSH private key */
-  CINIT(KEYPASSWD, STRINGPOINT, 26),
+  CURLOPT(CURLOPT_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 26),
 
   /* send TYPE parameter? */
-  CINIT(CRLF, LONG, 27),
+  CURLOPT(CURLOPT_CRLF, CURLOPTTYPE_LONG, 27),
 
   /* send linked-list of QUOTE commands */
-  CINIT(QUOTE, SLISTPOINT, 28),
+  CURLOPT(CURLOPT_QUOTE, CURLOPTTYPE_SLISTPOINT, 28),
 
   /* send FILE * or void * to store headers to, if you use a callback it
      is simply passed to the callback unmodified */
-  CINIT(HEADERDATA, OBJECTPOINT, 29),
+  CURLOPT(CURLOPT_HEADERDATA, CURLOPTTYPE_OBJECTPOINT, 29),
 
   /* point to a file to read the initial cookies from, also enables
      "cookie awareness" */
-  CINIT(COOKIEFILE, STRINGPOINT, 31),
+  CURLOPT(CURLOPT_COOKIEFILE, CURLOPTTYPE_STRINGPOINT, 31),
 
   /* What version to specifically try to use.
      See CURL_SSLVERSION defines below. */
-  CINIT(SSLVERSION, LONG, 32),
+  CURLOPT(CURLOPT_SSLVERSION, CURLOPTTYPE_LONG, 32),
 
   /* What kind of HTTP time condition to use, see defines */
-  CINIT(TIMECONDITION, LONG, 33),
+  CURLOPT(CURLOPT_TIMECONDITION, CURLOPTTYPE_LONG, 33),
 
   /* Time to use with the above condition. Specified in number of seconds
      since 1 Jan 1970 */
-  CINIT(TIMEVALUE, LONG, 34),
+  CURLOPT(CURLOPT_TIMEVALUE, CURLOPTTYPE_LONG, 34),
 
   /* 35 = OBSOLETE */
 
@@ -1106,37 +1088,58 @@ typedef enum {
      HTTP: DELETE, TRACE and others
      FTP: to use a different list command
      */
-  CINIT(CUSTOMREQUEST, STRINGPOINT, 36),
+  CURLOPT(CURLOPT_CUSTOMREQUEST, CURLOPTTYPE_STRINGPOINT, 36),
 
   /* FILE handle to use instead of stderr */
-  CINIT(STDERR, OBJECTPOINT, 37),
+  CURLOPT(CURLOPT_STDERR, CURLOPTTYPE_OBJECTPOINT, 37),
 
   /* 38 is not used */
 
   /* send linked-list of post-transfer QUOTE commands */
-  CINIT(POSTQUOTE, SLISTPOINT, 39),
+  CURLOPT(CURLOPT_POSTQUOTE, CURLOPTTYPE_SLISTPOINT, 39),
+
+   /* OBSOLETE, do not use! */
+  CURLOPT(CURLOPT_OBSOLETE40, CURLOPTTYPE_OBJECTPOINT, 40),
+
+  /* talk a lot */
+  CURLOPT(CURLOPT_VERBOSE, CURLOPTTYPE_LONG, 41),
+
+  /* throw the header out too */
+  CURLOPT(CURLOPT_HEADER, CURLOPTTYPE_LONG, 42),
+
+  /* shut off the progress meter */
+  CURLOPT(CURLOPT_NOPROGRESS, CURLOPTTYPE_LONG, 43),
+
+  /* use HEAD to get http document */
+  CURLOPT(CURLOPT_NOBODY, CURLOPTTYPE_LONG, 44),
+
+  /* no output on http error codes >= 400 */
+  CURLOPT(CURLOPT_FAILONERROR, CURLOPTTYPE_LONG, 45),
 
-  CINIT(OBSOLETE40, OBJECTPOINT, 40), /* OBSOLETE, do not use! */
+  /* this is an upload */
+  CURLOPT(CURLOPT_UPLOAD, CURLOPTTYPE_LONG, 46),
 
-  CINIT(VERBOSE, LONG, 41),      /* talk a lot */
-  CINIT(HEADER, LONG, 42),       /* throw the header out too */
-  CINIT(NOPROGRESS, LONG, 43),   /* shut off the progress meter */
-  CINIT(NOBODY, LONG, 44),       /* use HEAD to get http document */
-  CINIT(FAILONERROR, LONG, 45),  /* no output on http error codes >= 400 */
-  CINIT(UPLOAD, LONG, 46),       /* this is an upload */
-  CINIT(POST, LONG, 47),         /* HTTP POST method */
-  CINIT(DIRLISTONLY, LONG, 48),  /* bare names when listing directories */
+  /* HTTP POST method */
+  CURLOPT(CURLOPT_POST, CURLOPTTYPE_LONG, 47),
 
-  CINIT(APPEND, LONG, 50),       /* Append instead of overwrite on upload! */
+  /* bare names when listing directories */
+  CURLOPT(CURLOPT_DIRLISTONLY, CURLOPTTYPE_LONG, 48),
+
+  /* Append instead of overwrite on upload! */
+  CURLOPT(CURLOPT_APPEND, CURLOPTTYPE_LONG, 50),
 
   /* Specify whether to read the user+password from the .netrc or the URL.
    * This must be one of the CURL_NETRC_* enums below. */
-  CINIT(NETRC, LONG, 51),
+  CURLOPT(CURLOPT_NETRC, CURLOPTTYPE_LONG, 51),
+
+  /* use Location: Luke! */
+  CURLOPT(CURLOPT_FOLLOWLOCATION, CURLOPTTYPE_LONG, 52),
 
-  CINIT(FOLLOWLOCATION, LONG, 52),  /* use Location: Luke! */
+   /* transfer data in text/ASCII format */
+  CURLOPT(CURLOPT_TRANSFERTEXT, CURLOPTTYPE_LONG, 53),
 
-  CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
-  CINIT(PUT, LONG, 54),          /* HTTP PUT */
+  /* HTTP PUT */
+  CURLOPT(CURLOPT_PUT, CURLOPTTYPE_LONG, 54),
 
   /* 55 = OBSOLETE */
 
@@ -1144,265 +1147,267 @@ typedef enum {
    * Function that will be called instead of the internal progress display
    * function. This function should be defined as the curl_progress_callback
    * prototype defines. */
-  CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
+  CURLOPT(CURLOPT_PROGRESSFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 56),
 
   /* Data passed to the CURLOPT_PROGRESSFUNCTION and CURLOPT_XFERINFOFUNCTION
      callbacks */
-  CINIT(PROGRESSDATA, OBJECTPOINT, 57),
+  CURLOPT(CURLOPT_PROGRESSDATA, CURLOPTTYPE_OBJECTPOINT, 57),
 #define CURLOPT_XFERINFODATA CURLOPT_PROGRESSDATA
 
   /* We want the referrer field set automatically when following locations */
-  CINIT(AUTOREFERER, LONG, 58),
+  CURLOPT(CURLOPT_AUTOREFERER, CURLOPTTYPE_LONG, 58),
 
   /* Port of the proxy, can be set in the proxy string as well with:
      "[host]:[port]" */
-  CINIT(PROXYPORT, LONG, 59),
+  CURLOPT(CURLOPT_PROXYPORT, CURLOPTTYPE_LONG, 59),
 
   /* size of the POST input data, if strlen() is not good to use */
-  CINIT(POSTFIELDSIZE, LONG, 60),
+  CURLOPT(CURLOPT_POSTFIELDSIZE, CURLOPTTYPE_LONG, 60),
 
   /* tunnel non-http operations through a HTTP proxy */
-  CINIT(HTTPPROXYTUNNEL, LONG, 61),
+  CURLOPT(CURLOPT_HTTPPROXYTUNNEL, CURLOPTTYPE_LONG, 61),
 
   /* Set the interface string to use as outgoing network interface */
-  CINIT(INTERFACE, STRINGPOINT, 62),
+  CURLOPT(CURLOPT_INTERFACE, CURLOPTTYPE_STRINGPOINT, 62),
 
   /* Set the krb4/5 security level, this also enables krb4/5 awareness.  This
    * is a string, 'clear', 'safe', 'confidential' or 'private'.  If the string
    * is set but doesn't match one of these, 'private' will be used.  */
-  CINIT(KRBLEVEL, STRINGPOINT, 63),
+  CURLOPT(CURLOPT_KRBLEVEL, CURLOPTTYPE_STRINGPOINT, 63),
 
   /* Set if we should verify the peer in ssl handshake, set 1 to verify. */
-  CINIT(SSL_VERIFYPEER, LONG, 64),
+  CURLOPT(CURLOPT_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 64),
 
   /* The CApath or CAfile used to validate the peer certificate
      this option is used only if SSL_VERIFYPEER is true */
-  CINIT(CAINFO, STRINGPOINT, 65),
+  CURLOPT(CURLOPT_CAINFO, CURLOPTTYPE_STRINGPOINT, 65),
 
   /* 66 = OBSOLETE */
   /* 67 = OBSOLETE */
 
   /* Maximum number of http redirects to follow */
-  CINIT(MAXREDIRS, LONG, 68),
+  CURLOPT(CURLOPT_MAXREDIRS, CURLOPTTYPE_LONG, 68),
 
   /* Pass a long set to 1 to get the date of the requested document (if
      possible)! Pass a zero to shut it off. */
-  CINIT(FILETIME, LONG, 69),
+  CURLOPT(CURLOPT_FILETIME, CURLOPTTYPE_LONG, 69),
 
   /* This points to a linked list of telnet options */
-  CINIT(TELNETOPTIONS, SLISTPOINT, 70),
+  CURLOPT(CURLOPT_TELNETOPTIONS, CURLOPTTYPE_SLISTPOINT, 70),
 
   /* Max amount of cached alive connections */
-  CINIT(MAXCONNECTS, LONG, 71),
+  CURLOPT(CURLOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 71),
 
-  CINIT(OBSOLETE72, LONG, 72), /* OBSOLETE, do not use! */
+  /* OBSOLETE, do not use! */
+  CURLOPT(CURLOPT_OBSOLETE72, CURLOPTTYPE_LONG, 72),
 
   /* 73 = OBSOLETE */
 
   /* Set to explicitly use a new connection for the upcoming transfer.
      Do not use this unless you're absolutely sure of this, as it makes the
      operation slower and is less friendly for the network. */
-  CINIT(FRESH_CONNECT, LONG, 74),
+  CURLOPT(CURLOPT_FRESH_CONNECT, CURLOPTTYPE_LONG, 74),
 
   /* Set to explicitly forbid the upcoming transfer's connection to be re-used
      when done. Do not use this unless you're absolutely sure of this, as it
      makes the operation slower and is less friendly for the network. */
-  CINIT(FORBID_REUSE, LONG, 75),
+  CURLOPT(CURLOPT_FORBID_REUSE, CURLOPTTYPE_LONG, 75),
 
   /* Set to a file name that contains random data for libcurl to use to
      seed the random engine when doing SSL connects. */
-  CINIT(RANDOM_FILE, STRINGPOINT, 76),
+  CURLOPT(CURLOPT_RANDOM_FILE, CURLOPTTYPE_STRINGPOINT, 76),
 
   /* Set to the Entropy Gathering Daemon socket pathname */
-  CINIT(EGDSOCKET, STRINGPOINT, 77),
+  CURLOPT(CURLOPT_EGDSOCKET, CURLOPTTYPE_STRINGPOINT, 77),
 
   /* Time-out connect operations after this amount of seconds, if connects are
      OK within this time, then fine... This only aborts the connect phase. */
-  CINIT(CONNECTTIMEOUT, LONG, 78),
+  CURLOPT(CURLOPT_CONNECTTIMEOUT, CURLOPTTYPE_LONG, 78),
 
   /* Function that will be called to store headers (instead of fwrite). The
    * parameters will use fwrite() syntax, make sure to follow them. */
-  CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
+  CURLOPT(CURLOPT_HEADERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 79),
 
   /* Set this to force the HTTP request to get back to GET. Only really usable
      if POST, PUT or a custom request have been used first.
    */
-  CINIT(HTTPGET, LONG, 80),
+  CURLOPT(CURLOPT_HTTPGET, CURLOPTTYPE_LONG, 80),
 
   /* Set if we should verify the Common name from the peer certificate in ssl
    * handshake, set 1 to check existence, 2 to ensure that it matches the
    * provided hostname. */
-  CINIT(SSL_VERIFYHOST, LONG, 81),
+  CURLOPT(CURLOPT_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 81),
 
   /* Specify which file name to write all known cookies in after completed
      operation. Set file name to "-" (dash) to make it go to stdout. */
-  CINIT(COOKIEJAR, STRINGPOINT, 82),
+  CURLOPT(CURLOPT_COOKIEJAR, CURLOPTTYPE_STRINGPOINT, 82),
 
   /* Specify which SSL ciphers to use */
-  CINIT(SSL_CIPHER_LIST, STRINGPOINT, 83),
+  CURLOPT(CURLOPT_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 83),
 
   /* Specify which HTTP version to use! This must be set to one of the
      CURL_HTTP_VERSION* enums set below. */
-  CINIT(HTTP_VERSION, LONG, 84),
+  CURLOPT(CURLOPT_HTTP_VERSION, CURLOPTTYPE_LONG, 84),
 
   /* Specifically switch on or off the FTP engine's use of the EPSV command. By
      default, that one will always be attempted before the more traditional
      PASV command. */
-  CINIT(FTP_USE_EPSV, LONG, 85),
+  CURLOPT(CURLOPT_FTP_USE_EPSV, CURLOPTTYPE_LONG, 85),
 
   /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */
-  CINIT(SSLCERTTYPE, STRINGPOINT, 86),
+  CURLOPT(CURLOPT_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 86),
 
   /* name of the file keeping your private SSL-key */
-  CINIT(SSLKEY, STRINGPOINT, 87),
+  CURLOPT(CURLOPT_SSLKEY, CURLOPTTYPE_STRINGPOINT, 87),
 
   /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */
-  CINIT(SSLKEYTYPE, STRINGPOINT, 88),
+  CURLOPT(CURLOPT_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 88),
 
   /* crypto engine for the SSL-sub system */
-  CINIT(SSLENGINE, STRINGPOINT, 89),
+  CURLOPT(CURLOPT_SSLENGINE, CURLOPTTYPE_STRINGPOINT, 89),
 
   /* set the crypto engine for the SSL-sub system as default
      the param has no meaning...
    */
-  CINIT(SSLENGINE_DEFAULT, LONG, 90),
+  CURLOPT(CURLOPT_SSLENGINE_DEFAULT, CURLOPTTYPE_LONG, 90),
 
   /* Non-zero value means to use the global dns cache */
-  CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* DEPRECATED, do not use! */
+  /* DEPRECATED, do not use! */
+  CURLOPT(CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOPTTYPE_LONG, 91),
 
   /* DNS cache timeout */
-  CINIT(DNS_CACHE_TIMEOUT, LONG, 92),
+  CURLOPT(CURLOPT_DNS_CACHE_TIMEOUT, CURLOPTTYPE_LONG, 92),
 
   /* send linked-list of pre-transfer QUOTE commands */
-  CINIT(PREQUOTE, SLISTPOINT, 93),
+  CURLOPT(CURLOPT_PREQUOTE, CURLOPTTYPE_SLISTPOINT, 93),
 
   /* set the debug function */
-  CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94),
+  CURLOPT(CURLOPT_DEBUGFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 94),
 
   /* set the data for the debug function */
-  CINIT(DEBUGDATA, OBJECTPOINT, 95),
+  CURLOPT(CURLOPT_DEBUGDATA, CURLOPTTYPE_OBJECTPOINT, 95),
 
   /* mark this as start of a cookie session */
-  CINIT(COOKIESESSION, LONG, 96),
+  CURLOPT(CURLOPT_COOKIESESSION, CURLOPTTYPE_LONG, 96),
 
   /* The CApath directory used to validate the peer certificate
      this option is used only if SSL_VERIFYPEER is true */
-  CINIT(CAPATH, STRINGPOINT, 97),
+  CURLOPT(CURLOPT_CAPATH, CURLOPTTYPE_STRINGPOINT, 97),
 
   /* Instruct libcurl to use a smaller receive buffer */
-  CINIT(BUFFERSIZE, LONG, 98),
+  CURLOPT(CURLOPT_BUFFERSIZE, CURLOPTTYPE_LONG, 98),
 
   /* Instruct libcurl to not use any signal/alarm handlers, even when using
      timeouts. This option is useful for multi-threaded applications.
      See libcurl-the-guide for more background information. */
-  CINIT(NOSIGNAL, LONG, 99),
+  CURLOPT(CURLOPT_NOSIGNAL, CURLOPTTYPE_LONG, 99),
 
   /* Provide a CURLShare for mutexing non-ts data */
-  CINIT(SHARE, OBJECTPOINT, 100),
+  CURLOPT(CURLOPT_SHARE, CURLOPTTYPE_OBJECTPOINT, 100),
 
   /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default),
      CURLPROXY_HTTPS, CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and
      CURLPROXY_SOCKS5. */
-  CINIT(PROXYTYPE, LONG, 101),
+  CURLOPT(CURLOPT_PROXYTYPE, CURLOPTTYPE_LONG, 101),
 
   /* Set the Accept-Encoding string. Use this to tell a server you would like
      the response to be compressed. Before 7.21.6, this was known as
      CURLOPT_ENCODING */
-  CINIT(ACCEPT_ENCODING, STRINGPOINT, 102),
+  CURLOPT(CURLOPT_ACCEPT_ENCODING, CURLOPTTYPE_STRINGPOINT, 102),
 
   /* Set pointer to private data */
-  CINIT(PRIVATE, OBJECTPOINT, 103),
+  CURLOPT(CURLOPT_PRIVATE, CURLOPTTYPE_OBJECTPOINT, 103),
 
   /* Set aliases for HTTP 200 in the HTTP Response header */
-  CINIT(HTTP200ALIASES, SLISTPOINT, 104),
+  CURLOPT(CURLOPT_HTTP200ALIASES, CURLOPTTYPE_SLISTPOINT, 104),
 
   /* Continue to send authentication (user+password) when following locations,
      even when hostname changed. This can potentially send off the name
      and password to whatever host the server decides. */
-  CINIT(UNRESTRICTED_AUTH, LONG, 105),
+  CURLOPT(CURLOPT_UNRESTRICTED_AUTH, CURLOPTTYPE_LONG, 105),
 
   /* Specifically switch on or off the FTP engine's use of the EPRT command (
      it also disables the LPRT attempt). By default, those ones will always be
      attempted before the good old traditional PORT command. */
-  CINIT(FTP_USE_EPRT, LONG, 106),
+  CURLOPT(CURLOPT_FTP_USE_EPRT, CURLOPTTYPE_LONG, 106),
 
   /* Set this to a bitmask value to enable the particular authentications
      methods you like. Use this in combination with CURLOPT_USERPWD.
      Note that setting multiple bits may cause extra network round-trips. */
-  CINIT(HTTPAUTH, LONG, 107),
+  CURLOPT(CURLOPT_HTTPAUTH, CURLOPTTYPE_LONG, 107),
 
   /* Set the ssl context callback function, currently only for OpenSSL or
      WolfSSL ssl_ctx, or mbedTLS mbedtls_ssl_config in the second argument.
      The function must match the curl_ssl_ctx_callback prototype. */
-  CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108),
+  CURLOPT(CURLOPT_SSL_CTX_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 108),
 
   /* Set the userdata for the ssl context callback function's third
      argument */
-  CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
+  CURLOPT(CURLOPT_SSL_CTX_DATA, CURLOPTTYPE_OBJECTPOINT, 109),
 
   /* FTP Option that causes missing dirs to be created on the remote server.
      In 7.19.4 we introduced the convenience enums for this option using the
      CURLFTP_CREATE_DIR prefix.
   */
-  CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110),
+  CURLOPT(CURLOPT_FTP_CREATE_MISSING_DIRS, CURLOPTTYPE_LONG, 110),
 
   /* Set this to a bitmask value to enable the particular authentications
      methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
      Note that setting multiple bits may cause extra network round-trips. */
-  CINIT(PROXYAUTH, LONG, 111),
+  CURLOPT(CURLOPT_PROXYAUTH, CURLOPTTYPE_LONG, 111),
 
   /* FTP option that changes the timeout, in seconds, associated with
      getting a response.  This is different from transfer timeout time and
      essentially places a demand on the FTP server to acknowledge commands
      in a timely manner. */
-  CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112),
+  CURLOPT(CURLOPT_FTP_RESPONSE_TIMEOUT, CURLOPTTYPE_LONG, 112),
 #define CURLOPT_SERVER_RESPONSE_TIMEOUT CURLOPT_FTP_RESPONSE_TIMEOUT
 
   /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to
      tell libcurl to resolve names to those IP versions only. This only has
      affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */
-  CINIT(IPRESOLVE, LONG, 113),
+  CURLOPT(CURLOPT_IPRESOLVE, CURLOPTTYPE_LONG, 113),
 
   /* Set this option to limit the size of a file that will be downloaded from
      an HTTP or FTP server.
 
      Note there is also _LARGE version which adds large file support for
      platforms which have larger off_t sizes.  See MAXFILESIZE_LARGE below. */
-  CINIT(MAXFILESIZE, LONG, 114),
+  CURLOPT(CURLOPT_MAXFILESIZE, CURLOPTTYPE_LONG, 114),
 
   /* See the comment for INFILESIZE above, but in short, specifies
    * the size of the file being uploaded.  -1 means unknown.
    */
-  CINIT(INFILESIZE_LARGE, OFF_T, 115),
+  CURLOPT(CURLOPT_INFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 115),
 
-  /* Sets the continuation offset.  There is also a LONG version of this;
-   * look above for RESUME_FROM.
+  /* Sets the continuation offset.  There is also a CURLOPTTYPE_LONG version
+   * of this; look above for RESUME_FROM.
    */
-  CINIT(RESUME_FROM_LARGE, OFF_T, 116),
+  CURLOPT(CURLOPT_RESUME_FROM_LARGE, CURLOPTTYPE_OFF_T, 116),
 
   /* Sets the maximum size of data that will be downloaded from
    * an HTTP or FTP server.  See MAXFILESIZE above for the LONG version.
    */
-  CINIT(MAXFILESIZE_LARGE, OFF_T, 117),
+  CURLOPT(CURLOPT_MAXFILESIZE_LARGE, CURLOPTTYPE_OFF_T, 117),
 
   /* Set this option to the file name of your .netrc file you want libcurl
      to parse (using the CURLOPT_NETRC option). If not set, libcurl will do
      a poor attempt to find the user's home directory and check for a .netrc
      file in there. */
-  CINIT(NETRC_FILE, STRINGPOINT, 118),
+  CURLOPT(CURLOPT_NETRC_FILE, CURLOPTTYPE_STRINGPOINT, 118),
 
   /* Enable SSL/TLS for FTP, pick one of:
      CURLUSESSL_TRY     - try using SSL, proceed anyway otherwise
      CURLUSESSL_CONTROL - SSL for the control connection or fail
      CURLUSESSL_ALL     - SSL for all communication or fail
   */
-  CINIT(USE_SSL, LONG, 119),
+  CURLOPT(CURLOPT_USE_SSL, CURLOPTTYPE_LONG, 119),
 
   /* The _LARGE version of the standard POSTFIELDSIZE option */
-  CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
+  CURLOPT(CURLOPT_POSTFIELDSIZE_LARGE, CURLOPTTYPE_OFF_T, 120),
 
   /* Enable/disable the TCP Nagle algorithm */
-  CINIT(TCP_NODELAY, LONG, 121),
+  CURLOPT(CURLOPT_TCP_NODELAY, CURLOPTTYPE_LONG, 121),
 
   /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */
   /* 123 OBSOLETE. Gone in 7.16.0 */
@@ -1422,143 +1427,143 @@ typedef enum {
      CURLFTPAUTH_SSL     - try "AUTH SSL" first, then TLS
      CURLFTPAUTH_TLS     - try "AUTH TLS" first, then SSL
   */
-  CINIT(FTPSSLAUTH, LONG, 129),
+  CURLOPT(CURLOPT_FTPSSLAUTH, CURLOPTTYPE_LONG, 129),
 
-  CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130),
-  CINIT(IOCTLDATA, OBJECTPOINT, 131),
+  CURLOPT(CURLOPT_IOCTLFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 130),
+  CURLOPT(CURLOPT_IOCTLDATA, CURLOPTTYPE_OBJECTPOINT, 131),
 
   /* 132 OBSOLETE. Gone in 7.16.0 */
   /* 133 OBSOLETE. Gone in 7.16.0 */
 
   /* zero terminated string for pass on to the FTP server when asked for
      "account" info */
-  CINIT(FTP_ACCOUNT, STRINGPOINT, 134),
+  CURLOPT(CURLOPT_FTP_ACCOUNT, CURLOPTTYPE_STRINGPOINT, 134),
 
   /* feed cookie into cookie engine */
-  CINIT(COOKIELIST, STRINGPOINT, 135),
+  CURLOPT(CURLOPT_COOKIELIST, CURLOPTTYPE_STRINGPOINT, 135),
 
   /* ignore Content-Length */
-  CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
+  CURLOPT(CURLOPT_IGNORE_CONTENT_LENGTH, CURLOPTTYPE_LONG, 136),
 
   /* Set to non-zero to skip the IP address received in a 227 PASV FTP server
      response. Typically used for FTP-SSL purposes but is not restricted to
      that. libcurl will then instead use the same IP address it used for the
      control connection. */
-  CINIT(FTP_SKIP_PASV_IP, LONG, 137),
+  CURLOPT(CURLOPT_FTP_SKIP_PASV_IP, CURLOPTTYPE_LONG, 137),
 
   /* Select "file method" to use when doing FTP, see the curl_ftpmethod
      above. */
-  CINIT(FTP_FILEMETHOD, LONG, 138),
+  CURLOPT(CURLOPT_FTP_FILEMETHOD, CURLOPTTYPE_LONG, 138),
 
   /* Local port number to bind the socket to */
-  CINIT(LOCALPORT, LONG, 139),
+  CURLOPT(CURLOPT_LOCALPORT, CURLOPTTYPE_LONG, 139),
 
   /* Number of ports to try, including the first one set with LOCALPORT.
      Thus, setting it to 1 will make no additional attempts but the first.
   */
-  CINIT(LOCALPORTRANGE, LONG, 140),
+  CURLOPT(CURLOPT_LOCALPORTRANGE, CURLOPTTYPE_LONG, 140),
 
   /* no transfer, set up connection and let application use the socket by
      extracting it with CURLINFO_LASTSOCKET */
-  CINIT(CONNECT_ONLY, LONG, 141),
+  CURLOPT(CURLOPT_CONNECT_ONLY, CURLOPTTYPE_LONG, 141),
 
   /* Function that will be called to convert from the
      network encoding (instead of using the iconv calls in libcurl) */
-  CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142),
+  CURLOPT(CURLOPT_CONV_FROM_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 142),
 
   /* Function that will be called to convert to the
      network encoding (instead of using the iconv calls in libcurl) */
-  CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143),
+  CURLOPT(CURLOPT_CONV_TO_NETWORK_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 143),
 
   /* Function that will be called to convert from UTF8
      (instead of using the iconv calls in libcurl)
      Note that this is used only for SSL certificate processing */
-  CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144),
+  CURLOPT(CURLOPT_CONV_FROM_UTF8_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 144),
 
   /* if the connection proceeds too quickly then need to slow it down */
   /* limit-rate: maximum number of bytes per second to send or receive */
-  CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145),
-  CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146),
+  CURLOPT(CURLOPT_MAX_SEND_SPEED_LARGE, CURLOPTTYPE_OFF_T, 145),
+  CURLOPT(CURLOPT_MAX_RECV_SPEED_LARGE, CURLOPTTYPE_OFF_T, 146),
 
   /* Pointer to command string to send if USER/PASS fails. */
-  CINIT(FTP_ALTERNATIVE_TO_USER, STRINGPOINT, 147),
+  CURLOPT(CURLOPT_FTP_ALTERNATIVE_TO_USER, CURLOPTTYPE_STRINGPOINT, 147),
 
   /* callback function for setting socket options */
-  CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148),
-  CINIT(SOCKOPTDATA, OBJECTPOINT, 149),
+  CURLOPT(CURLOPT_SOCKOPTFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 148),
+  CURLOPT(CURLOPT_SOCKOPTDATA, CURLOPTTYPE_OBJECTPOINT, 149),
 
   /* set to 0 to disable session ID re-use for this transfer, default is
      enabled (== 1) */
-  CINIT(SSL_SESSIONID_CACHE, LONG, 150),
+  CURLOPT(CURLOPT_SSL_SESSIONID_CACHE, CURLOPTTYPE_LONG, 150),
 
   /* allowed SSH authentication methods */
-  CINIT(SSH_AUTH_TYPES, LONG, 151),
+  CURLOPT(CURLOPT_SSH_AUTH_TYPES, CURLOPTTYPE_LONG, 151),
 
   /* Used by scp/sftp to do public/private key authentication */
-  CINIT(SSH_PUBLIC_KEYFILE, STRINGPOINT, 152),
-  CINIT(SSH_PRIVATE_KEYFILE, STRINGPOINT, 153),
+  CURLOPT(CURLOPT_SSH_PUBLIC_KEYFILE, CURLOPTTYPE_STRINGPOINT, 152),
+  CURLOPT(CURLOPT_SSH_PRIVATE_KEYFILE, CURLOPTTYPE_STRINGPOINT, 153),
 
   /* Send CCC (Clear Command Channel) after authentication */
-  CINIT(FTP_SSL_CCC, LONG, 154),
+  CURLOPT(CURLOPT_FTP_SSL_CCC, CURLOPTTYPE_LONG, 154),
 
   /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */
-  CINIT(TIMEOUT_MS, LONG, 155),
-  CINIT(CONNECTTIMEOUT_MS, LONG, 156),
+  CURLOPT(CURLOPT_TIMEOUT_MS, CURLOPTTYPE_LONG, 155),
+  CURLOPT(CURLOPT_CONNECTTIMEOUT_MS, CURLOPTTYPE_LONG, 156),
 
   /* set to zero to disable the libcurl's decoding and thus pass the raw body
      data to the application even when it is encoded/compressed */
-  CINIT(HTTP_TRANSFER_DECODING, LONG, 157),
-  CINIT(HTTP_CONTENT_DECODING, LONG, 158),
+  CURLOPT(CURLOPT_HTTP_TRANSFER_DECODING, CURLOPTTYPE_LONG, 157),
+  CURLOPT(CURLOPT_HTTP_CONTENT_DECODING, CURLOPTTYPE_LONG, 158),
 
   /* Permission used when creating new files and directories on the remote
      server for protocols that support it, SFTP/SCP/FILE */
-  CINIT(NEW_FILE_PERMS, LONG, 159),
-  CINIT(NEW_DIRECTORY_PERMS, LONG, 160),
+  CURLOPT(CURLOPT_NEW_FILE_PERMS, CURLOPTTYPE_LONG, 159),
+  CURLOPT(CURLOPT_NEW_DIRECTORY_PERMS, CURLOPTTYPE_LONG, 160),
 
   /* Set the behaviour of POST when redirecting. Values must be set to one
      of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */
-  CINIT(POSTREDIR, LONG, 161),
+  CURLOPT(CURLOPT_POSTREDIR, CURLOPTTYPE_LONG, 161),
 
   /* used by scp/sftp to verify the host's public key */
-  CINIT(SSH_HOST_PUBLIC_KEY_MD5, STRINGPOINT, 162),
+  CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, CURLOPTTYPE_STRINGPOINT, 162),
 
   /* Callback function for opening socket (instead of socket(2)). Optionally,
      callback is able change the address or refuse to connect returning
      CURL_SOCKET_BAD.  The callback should have type
      curl_opensocket_callback */
-  CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163),
-  CINIT(OPENSOCKETDATA, OBJECTPOINT, 164),
+  CURLOPT(CURLOPT_OPENSOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 163),
+  CURLOPT(CURLOPT_OPENSOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 164),
 
   /* POST volatile input fields. */
-  CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165),
+  CURLOPT(CURLOPT_COPYPOSTFIELDS, CURLOPTTYPE_OBJECTPOINT, 165),
 
   /* set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy */
-  CINIT(PROXY_TRANSFER_MODE, LONG, 166),
+  CURLOPT(CURLOPT_PROXY_TRANSFER_MODE, CURLOPTTYPE_LONG, 166),
 
   /* Callback function for seeking in the input stream */
-  CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167),
-  CINIT(SEEKDATA, OBJECTPOINT, 168),
+  CURLOPT(CURLOPT_SEEKFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 167),
+  CURLOPT(CURLOPT_SEEKDATA, CURLOPTTYPE_OBJECTPOINT, 168),
 
   /* CRL file */
-  CINIT(CRLFILE, STRINGPOINT, 169),
+  CURLOPT(CURLOPT_CRLFILE, CURLOPTTYPE_STRINGPOINT, 169),
 
   /* Issuer certificate */
-  CINIT(ISSUERCERT, STRINGPOINT, 170),
+  CURLOPT(CURLOPT_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 170),
 
   /* (IPv6) Address scope */
-  CINIT(ADDRESS_SCOPE, LONG, 171),
+  CURLOPT(CURLOPT_ADDRESS_SCOPE, CURLOPTTYPE_LONG, 171),
 
   /* Collect certificate chain info and allow it to get retrievable with
      CURLINFO_CERTINFO after the transfer is complete. */
-  CINIT(CERTINFO, LONG, 172),
+  CURLOPT(CURLOPT_CERTINFO, CURLOPTTYPE_LONG, 172),
 
   /* "name" and "pwd" to use when fetching. */
-  CINIT(USERNAME, STRINGPOINT, 173),
-  CINIT(PASSWORD, STRINGPOINT, 174),
+  CURLOPT(CURLOPT_USERNAME, CURLOPTTYPE_STRINGPOINT, 173),
+  CURLOPT(CURLOPT_PASSWORD, CURLOPTTYPE_STRINGPOINT, 174),
 
     /* "name" and "pwd" to use with Proxy when fetching. */
-  CINIT(PROXYUSERNAME, STRINGPOINT, 175),
-  CINIT(PROXYPASSWORD, STRINGPOINT, 176),
+  CURLOPT(CURLOPT_PROXYUSERNAME, CURLOPTTYPE_STRINGPOINT, 175),
+  CURLOPT(CURLOPT_PROXYPASSWORD, CURLOPTTYPE_STRINGPOINT, 176),
 
   /* Comma separated list of hostnames defining no-proxy zones. These should
      match both hostnames directly, and hostnames within a domain. For
@@ -1567,102 +1572,103 @@ typedef enum {
      implementations of this, .local.com will be considered to be the same as
      local.com. A single * is the only valid wildcard, and effectively
      disables the use of proxy. */
-  CINIT(NOPROXY, STRINGPOINT, 177),
+  CURLOPT(CURLOPT_NOPROXY, CURLOPTTYPE_STRINGPOINT, 177),
 
   /* block size for TFTP transfers */
-  CINIT(TFTP_BLKSIZE, LONG, 178),
+  CURLOPT(CURLOPT_TFTP_BLKSIZE, CURLOPTTYPE_LONG, 178),
 
   /* Socks Service */
-  CINIT(SOCKS5_GSSAPI_SERVICE, STRINGPOINT, 179), /* DEPRECATED, do not use! */
+  /* DEPRECATED, do not use! */
+  CURLOPT(CURLOPT_SOCKS5_GSSAPI_SERVICE, CURLOPTTYPE_STRINGPOINT, 179),
 
   /* Socks Service */
-  CINIT(SOCKS5_GSSAPI_NEC, LONG, 180),
+  CURLOPT(CURLOPT_SOCKS5_GSSAPI_NEC, CURLOPTTYPE_LONG, 180),
 
   /* set the bitmask for the protocols that are allowed to be used for the
      transfer, which thus helps the app which takes URLs from users or other
      external inputs and want to restrict what protocol(s) to deal
      with. Defaults to CURLPROTO_ALL. */
-  CINIT(PROTOCOLS, LONG, 181),
+  CURLOPT(CURLOPT_PROTOCOLS, CURLOPTTYPE_LONG, 181),
 
   /* set the bitmask for the protocols that libcurl is allowed to follow to,
      as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
      to be set in both bitmasks to be allowed to get redirected to. */
-  CINIT(REDIR_PROTOCOLS, LONG, 182),
+  CURLOPT(CURLOPT_REDIR_PROTOCOLS, CURLOPTTYPE_LONG, 182),
 
   /* set the SSH knownhost file name to use */
-  CINIT(SSH_KNOWNHOSTS, STRINGPOINT, 183),
+  CURLOPT(CURLOPT_SSH_KNOWNHOSTS, CURLOPTTYPE_STRINGPOINT, 183),
 
   /* set the SSH host key callback, must point to a curl_sshkeycallback
      function */
-  CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184),
+  CURLOPT(CURLOPT_SSH_KEYFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 184),
 
   /* set the SSH host key callback custom pointer */
-  CINIT(SSH_KEYDATA, OBJECTPOINT, 185),
+  CURLOPT(CURLOPT_SSH_KEYDATA, CURLOPTTYPE_OBJECTPOINT, 185),
 
   /* set the SMTP mail originator */
-  CINIT(MAIL_FROM, STRINGPOINT, 186),
+  CURLOPT(CURLOPT_MAIL_FROM, CURLOPTTYPE_STRINGPOINT, 186),
 
   /* set the list of SMTP mail receiver(s) */
-  CINIT(MAIL_RCPT, SLISTPOINT, 187),
+  CURLOPT(CURLOPT_MAIL_RCPT, CURLOPTTYPE_SLISTPOINT, 187),
 
   /* FTP: send PRET before PASV */
-  CINIT(FTP_USE_PRET, LONG, 188),
+  CURLOPT(CURLOPT_FTP_USE_PRET, CURLOPTTYPE_LONG, 188),
 
   /* RTSP request method (OPTIONS, SETUP, PLAY, etc...) */
-  CINIT(RTSP_REQUEST, LONG, 189),
+  CURLOPT(CURLOPT_RTSP_REQUEST, CURLOPTTYPE_LONG, 189),
 
   /* The RTSP session identifier */
-  CINIT(RTSP_SESSION_ID, STRINGPOINT, 190),
+  CURLOPT(CURLOPT_RTSP_SESSION_ID, CURLOPTTYPE_STRINGPOINT, 190),
 
   /* The RTSP stream URI */
-  CINIT(RTSP_STREAM_URI, STRINGPOINT, 191),
+  CURLOPT(CURLOPT_RTSP_STREAM_URI, CURLOPTTYPE_STRINGPOINT, 191),
 
   /* The Transport: header to use in RTSP requests */
-  CINIT(RTSP_TRANSPORT, STRINGPOINT, 192),
+  CURLOPT(CURLOPT_RTSP_TRANSPORT, CURLOPTTYPE_STRINGPOINT, 192),
 
   /* Manually initialize the client RTSP CSeq for this handle */
-  CINIT(RTSP_CLIENT_CSEQ, LONG, 193),
+  CURLOPT(CURLOPT_RTSP_CLIENT_CSEQ, CURLOPTTYPE_LONG, 193),
 
   /* Manually initialize the server RTSP CSeq for this handle */
-  CINIT(RTSP_SERVER_CSEQ, LONG, 194),
+  CURLOPT(CURLOPT_RTSP_SERVER_CSEQ, CURLOPTTYPE_LONG, 194),
 
   /* The stream to pass to INTERLEAVEFUNCTION. */
-  CINIT(INTERLEAVEDATA, OBJECTPOINT, 195),
+  CURLOPT(CURLOPT_INTERLEAVEDATA, CURLOPTTYPE_OBJECTPOINT, 195),
 
   /* Let the application define a custom write method for RTP data */
-  CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196),
+  CURLOPT(CURLOPT_INTERLEAVEFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 196),
 
   /* Turn on wildcard matching */
-  CINIT(WILDCARDMATCH, LONG, 197),
+  CURLOPT(CURLOPT_WILDCARDMATCH, CURLOPTTYPE_LONG, 197),
 
   /* Directory matching callback called before downloading of an
      individual file (chunk) started */
-  CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198),
+  CURLOPT(CURLOPT_CHUNK_BGN_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 198),
 
   /* Directory matching callback called after the file (chunk)
      was downloaded, or skipped */
-  CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199),
+  CURLOPT(CURLOPT_CHUNK_END_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 199),
 
   /* Change match (fnmatch-like) callback for wildcard matching */
-  CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200),
+  CURLOPT(CURLOPT_FNMATCH_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 200),
 
   /* Let the application define custom chunk data pointer */
-  CINIT(CHUNK_DATA, OBJECTPOINT, 201),
+  CURLOPT(CURLOPT_CHUNK_DATA, CURLOPTTYPE_OBJECTPOINT, 201),
 
   /* FNMATCH_FUNCTION user pointer */
-  CINIT(FNMATCH_DATA, OBJECTPOINT, 202),
+  CURLOPT(CURLOPT_FNMATCH_DATA, CURLOPTTYPE_OBJECTPOINT, 202),
 
   /* send linked-list of name:port:address sets */
-  CINIT(RESOLVE, SLISTPOINT, 203),
+  CURLOPT(CURLOPT_RESOLVE, CURLOPTTYPE_SLISTPOINT, 203),
 
   /* Set a username for authenticated TLS */
-  CINIT(TLSAUTH_USERNAME, STRINGPOINT, 204),
+  CURLOPT(CURLOPT_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 204),
 
   /* Set a password for authenticated TLS */
-  CINIT(TLSAUTH_PASSWORD, STRINGPOINT, 205),
+  CURLOPT(CURLOPT_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 205),
 
   /* Set authentication type for authenticated TLS */
-  CINIT(TLSAUTH_TYPE, STRINGPOINT, 206),
+  CURLOPT(CURLOPT_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 206),
 
   /* Set to 1 to enable the "TE:" header in HTTP requests to ask for
      compressed transfer-encoded responses. Set to 0 to disable the use of TE:
@@ -1674,271 +1680,274 @@ typedef enum {
      option is set to 1.
 
   */
-  CINIT(TRANSFER_ENCODING, LONG, 207),
+  CURLOPT(CURLOPT_TRANSFER_ENCODING, CURLOPTTYPE_LONG, 207),
 
   /* Callback function for closing socket (instead of close(2)). The callback
      should have type curl_closesocket_callback */
-  CINIT(CLOSESOCKETFUNCTION, FUNCTIONPOINT, 208),
-  CINIT(CLOSESOCKETDATA, OBJECTPOINT, 209),
+  CURLOPT(CURLOPT_CLOSESOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 208),
+  CURLOPT(CURLOPT_CLOSESOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 209),
 
   /* allow GSSAPI credential delegation */
-  CINIT(GSSAPI_DELEGATION, LONG, 210),
+  CURLOPT(CURLOPT_GSSAPI_DELEGATION, CURLOPTTYPE_LONG, 210),
 
   /* Set the name servers to use for DNS resolution */
-  CINIT(DNS_SERVERS, STRINGPOINT, 211),
+  CURLOPT(CURLOPT_DNS_SERVERS, CURLOPTTYPE_STRINGPOINT, 211),
 
   /* Time-out accept operations (currently for FTP only) after this amount
      of milliseconds. */
-  CINIT(ACCEPTTIMEOUT_MS, LONG, 212),
+  CURLOPT(CURLOPT_ACCEPTTIMEOUT_MS, CURLOPTTYPE_LONG, 212),
 
   /* Set TCP keepalive */
-  CINIT(TCP_KEEPALIVE, LONG, 213),
+  CURLOPT(CURLOPT_TCP_KEEPALIVE, CURLOPTTYPE_LONG, 213),
 
   /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */
-  CINIT(TCP_KEEPIDLE, LONG, 214),
-  CINIT(TCP_KEEPINTVL, LONG, 215),
+  CURLOPT(CURLOPT_TCP_KEEPIDLE, CURLOPTTYPE_LONG, 214),
+  CURLOPT(CURLOPT_TCP_KEEPINTVL, CURLOPTTYPE_LONG, 215),
 
   /* Enable/disable specific SSL features with a bitmask, see CURLSSLOPT_* */
-  CINIT(SSL_OPTIONS, LONG, 216),
+  CURLOPT(CURLOPT_SSL_OPTIONS, CURLOPTTYPE_LONG, 216),
 
   /* Set the SMTP auth originator */
-  CINIT(MAIL_AUTH, STRINGPOINT, 217),
+  CURLOPT(CURLOPT_MAIL_AUTH, CURLOPTTYPE_STRINGPOINT, 217),
 
   /* Enable/disable SASL initial response */
-  CINIT(SASL_IR, LONG, 218),
+  CURLOPT(CURLOPT_SASL_IR, CURLOPTTYPE_LONG, 218),
 
   /* Function that will be called instead of the internal progress display
    * function. This function should be defined as the curl_xferinfo_callback
    * prototype defines. (Deprecates CURLOPT_PROGRESSFUNCTION) */
-  CINIT(XFERINFOFUNCTION, FUNCTIONPOINT, 219),
+  CURLOPT(CURLOPT_XFERINFOFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 219),
 
   /* The XOAUTH2 bearer token */
-  CINIT(XOAUTH2_BEARER, STRINGPOINT, 220),
+  CURLOPT(CURLOPT_XOAUTH2_BEARER, CURLOPTTYPE_STRINGPOINT, 220),
 
   /* Set the interface string to use as outgoing network
    * interface for DNS requests.
    * Only supported by the c-ares DNS backend */
-  CINIT(DNS_INTERFACE, STRINGPOINT, 221),
+  CURLOPT(CURLOPT_DNS_INTERFACE, CURLOPTTYPE_STRINGPOINT, 221),
 
   /* Set the local IPv4 address to use for outgoing DNS requests.
    * Only supported by the c-ares DNS backend */
-  CINIT(DNS_LOCAL_IP4, STRINGPOINT, 222),
+  CURLOPT(CURLOPT_DNS_LOCAL_IP4, CURLOPTTYPE_STRINGPOINT, 222),
 
   /* Set the local IPv6 address to use for outgoing DNS requests.
    * Only supported by the c-ares DNS backend */
-  CINIT(DNS_LOCAL_IP6, STRINGPOINT, 223),
+  CURLOPT(CURLOPT_DNS_LOCAL_IP6, CURLOPTTYPE_STRINGPOINT, 223),
 
   /* Set authentication options directly */
-  CINIT(LOGIN_OPTIONS, STRINGPOINT, 224),
+  CURLOPT(CURLOPT_LOGIN_OPTIONS, CURLOPTTYPE_STRINGPOINT, 224),
 
   /* Enable/disable TLS NPN extension (http2 over ssl might fail without) */
-  CINIT(SSL_ENABLE_NPN, LONG, 225),
+  CURLOPT(CURLOPT_SSL_ENABLE_NPN, CURLOPTTYPE_LONG, 225),
 
   /* Enable/disable TLS ALPN extension (http2 over ssl might fail without) */
-  CINIT(SSL_ENABLE_ALPN, LONG, 226),
+  CURLOPT(CURLOPT_SSL_ENABLE_ALPN, CURLOPTTYPE_LONG, 226),
 
   /* Time to wait for a response to a HTTP request containing an
    * Expect: 100-continue header before sending the data anyway. */
-  CINIT(EXPECT_100_TIMEOUT_MS, LONG, 227),
+  CURLOPT(CURLOPT_EXPECT_100_TIMEOUT_MS, CURLOPTTYPE_LONG, 227),
 
   /* This points to a linked list of headers used for proxy requests only,
      struct curl_slist kind */
-  CINIT(PROXYHEADER, SLISTPOINT, 228),
+  CURLOPT(CURLOPT_PROXYHEADER, CURLOPTTYPE_SLISTPOINT, 228),
 
   /* Pass in a bitmask of "header options" */
-  CINIT(HEADEROPT, LONG, 229),
+  CURLOPT(CURLOPT_HEADEROPT, CURLOPTTYPE_LONG, 229),
 
   /* The public key in DER form used to validate the peer public key
      this option is used only if SSL_VERIFYPEER is true */
-  CINIT(PINNEDPUBLICKEY, STRINGPOINT, 230),
+  CURLOPT(CURLOPT_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 230),
 
   /* Path to Unix domain socket */
-  CINIT(UNIX_SOCKET_PATH, STRINGPOINT, 231),
+  CURLOPT(CURLOPT_UNIX_SOCKET_PATH, CURLOPTTYPE_STRINGPOINT, 231),
 
   /* Set if we should verify the certificate status. */
-  CINIT(SSL_VERIFYSTATUS, LONG, 232),
+  CURLOPT(CURLOPT_SSL_VERIFYSTATUS, CURLOPTTYPE_LONG, 232),
 
   /* Set if we should enable TLS false start. */
-  CINIT(SSL_FALSESTART, LONG, 233),
+  CURLOPT(CURLOPT_SSL_FALSESTART, CURLOPTTYPE_LONG, 233),
 
   /* Do not squash dot-dot sequences */
-  CINIT(PATH_AS_IS, LONG, 234),
+  CURLOPT(CURLOPT_PATH_AS_IS, CURLOPTTYPE_LONG, 234),
 
   /* Proxy Service Name */
-  CINIT(PROXY_SERVICE_NAME, STRINGPOINT, 235),
+  CURLOPT(CURLOPT_PROXY_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 235),
 
   /* Service Name */
-  CINIT(SERVICE_NAME, STRINGPOINT, 236),
+  CURLOPT(CURLOPT_SERVICE_NAME, CURLOPTTYPE_STRINGPOINT, 236),
 
   /* Wait/don't wait for pipe/mutex to clarify */
-  CINIT(PIPEWAIT, LONG, 237),
+  CURLOPT(CURLOPT_PIPEWAIT, CURLOPTTYPE_LONG, 237),
 
   /* Set the protocol used when curl is given a URL without a protocol */
-  CINIT(DEFAULT_PROTOCOL, STRINGPOINT, 238),
+  CURLOPT(CURLOPT_DEFAULT_PROTOCOL, CURLOPTTYPE_STRINGPOINT, 238),
 
   /* Set stream weight, 1 - 256 (default is 16) */
-  CINIT(STREAM_WEIGHT, LONG, 239),
+  CURLOPT(CURLOPT_STREAM_WEIGHT, CURLOPTTYPE_LONG, 239),
 
   /* Set stream dependency on another CURL handle */
-  CINIT(STREAM_DEPENDS, OBJECTPOINT, 240),
+  CURLOPT(CURLOPT_STREAM_DEPENDS, CURLOPTTYPE_OBJECTPOINT, 240),
 
   /* Set E-xclusive stream dependency on another CURL handle */
-  CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241),
+  CURLOPT(CURLOPT_STREAM_DEPENDS_E, CURLOPTTYPE_OBJECTPOINT, 241),
 
   /* Do not send any tftp option requests to the server */
-  CINIT(TFTP_NO_OPTIONS, LONG, 242),
+  CURLOPT(CURLOPT_TFTP_NO_OPTIONS, CURLOPTTYPE_LONG, 242),
 
   /* Linked-list of host:port:connect-to-host:connect-to-port,
      overrides the URL's host:port (only for the network layer) */
-  CINIT(CONNECT_TO, SLISTPOINT, 243),
+  CURLOPT(CURLOPT_CONNECT_TO, CURLOPTTYPE_SLISTPOINT, 243),
 
   /* Set TCP Fast Open */
-  CINIT(TCP_FASTOPEN, LONG, 244),
+  CURLOPT(CURLOPT_TCP_FASTOPEN, CURLOPTTYPE_LONG, 244),
 
   /* Continue to send data if the server responds early with an
    * HTTP status code >= 300 */
-  CINIT(KEEP_SENDING_ON_ERROR, LONG, 245),
+  CURLOPT(CURLOPT_KEEP_SENDING_ON_ERROR, CURLOPTTYPE_LONG, 245),
 
   /* The CApath or CAfile used to validate the proxy certificate
      this option is used only if PROXY_SSL_VERIFYPEER is true */
-  CINIT(PROXY_CAINFO, STRINGPOINT, 246),
+  CURLOPT(CURLOPT_PROXY_CAINFO, CURLOPTTYPE_STRINGPOINT, 246),
 
   /* The CApath directory used to validate the proxy certificate
      this option is used only if PROXY_SSL_VERIFYPEER is true */
-  CINIT(PROXY_CAPATH, STRINGPOINT, 247),
+  CURLOPT(CURLOPT_PROXY_CAPATH, CURLOPTTYPE_STRINGPOINT, 247),
 
   /* Set if we should verify the proxy in ssl handshake,
      set 1 to verify. */
-  CINIT(PROXY_SSL_VERIFYPEER, LONG, 248),
+  CURLOPT(CURLOPT_PROXY_SSL_VERIFYPEER, CURLOPTTYPE_LONG, 248),
 
   /* Set if we should verify the Common name from the proxy certificate in ssl
    * handshake, set 1 to check existence, 2 to ensure that it matches
    * the provided hostname. */
-  CINIT(PROXY_SSL_VERIFYHOST, LONG, 249),
+  CURLOPT(CURLOPT_PROXY_SSL_VERIFYHOST, CURLOPTTYPE_LONG, 249),
 
   /* What version to specifically try to use for proxy.
      See CURL_SSLVERSION defines below. */
-  CINIT(PROXY_SSLVERSION, LONG, 250),
+  CURLOPT(CURLOPT_PROXY_SSLVERSION, CURLOPTTYPE_LONG, 250),
 
   /* Set a username for authenticated TLS for proxy */
-  CINIT(PROXY_TLSAUTH_USERNAME, STRINGPOINT, 251),
+  CURLOPT(CURLOPT_PROXY_TLSAUTH_USERNAME, CURLOPTTYPE_STRINGPOINT, 251),
 
   /* Set a password for authenticated TLS for proxy */
-  CINIT(PROXY_TLSAUTH_PASSWORD, STRINGPOINT, 252),
+  CURLOPT(CURLOPT_PROXY_TLSAUTH_PASSWORD, CURLOPTTYPE_STRINGPOINT, 252),
 
   /* Set authentication type for authenticated TLS for proxy */
-  CINIT(PROXY_TLSAUTH_TYPE, STRINGPOINT, 253),
+  CURLOPT(CURLOPT_PROXY_TLSAUTH_TYPE, CURLOPTTYPE_STRINGPOINT, 253),
 
   /* name of the file keeping your private SSL-certificate for proxy */
-  CINIT(PROXY_SSLCERT, STRINGPOINT, 254),
+  CURLOPT(CURLOPT_PROXY_SSLCERT, CURLOPTTYPE_STRINGPOINT, 254),
 
   /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") for
      proxy */
-  CINIT(PROXY_SSLCERTTYPE, STRINGPOINT, 255),
+  CURLOPT(CURLOPT_PROXY_SSLCERTTYPE, CURLOPTTYPE_STRINGPOINT, 255),
 
   /* name of the file keeping your private SSL-key for proxy */
-  CINIT(PROXY_SSLKEY, STRINGPOINT, 256),
+  CURLOPT(CURLOPT_PROXY_SSLKEY, CURLOPTTYPE_STRINGPOINT, 256),
 
   /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") for
      proxy */
-  CINIT(PROXY_SSLKEYTYPE, STRINGPOINT, 257),
+  CURLOPT(CURLOPT_PROXY_SSLKEYTYPE, CURLOPTTYPE_STRINGPOINT, 257),
 
   /* password for the SSL private key for proxy */
-  CINIT(PROXY_KEYPASSWD, STRINGPOINT, 258),
+  CURLOPT(CURLOPT_PROXY_KEYPASSWD, CURLOPTTYPE_STRINGPOINT, 258),
 
   /* Specify which SSL ciphers to use for proxy */
-  CINIT(PROXY_SSL_CIPHER_LIST, STRINGPOINT, 259),
+  CURLOPT(CURLOPT_PROXY_SSL_CIPHER_LIST, CURLOPTTYPE_STRINGPOINT, 259),
 
   /* CRL file for proxy */
-  CINIT(PROXY_CRLFILE, STRINGPOINT, 260),
+  CURLOPT(CURLOPT_PROXY_CRLFILE, CURLOPTTYPE_STRINGPOINT, 260),
 
   /* Enable/disable specific SSL features with a bitmask for proxy, see
      CURLSSLOPT_* */
-  CINIT(PROXY_SSL_OPTIONS, LONG, 261),
+  CURLOPT(CURLOPT_PROXY_SSL_OPTIONS, CURLOPTTYPE_LONG, 261),
 
   /* Name of pre proxy to use. */
-  CINIT(PRE_PROXY, STRINGPOINT, 262),
+  CURLOPT(CURLOPT_PRE_PROXY, CURLOPTTYPE_STRINGPOINT, 262),
 
   /* The public key in DER form used to validate the proxy public key
      this option is used only if PROXY_SSL_VERIFYPEER is true */
-  CINIT(PROXY_PINNEDPUBLICKEY, STRINGPOINT, 263),
+  CURLOPT(CURLOPT_PROXY_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 263),
 
   /* Path to an abstract Unix domain socket */
-  CINIT(ABSTRACT_UNIX_SOCKET, STRINGPOINT, 264),
+  CURLOPT(CURLOPT_ABSTRACT_UNIX_SOCKET, CURLOPTTYPE_STRINGPOINT, 264),
 
   /* Suppress proxy CONNECT response headers from user callbacks */
-  CINIT(SUPPRESS_CONNECT_HEADERS, LONG, 265),
+  CURLOPT(CURLOPT_SUPPRESS_CONNECT_HEADERS, CURLOPTTYPE_LONG, 265),
 
   /* The request target, instead of extracted from the URL */
-  CINIT(REQUEST_TARGET, STRINGPOINT, 266),
+  CURLOPT(CURLOPT_REQUEST_TARGET, CURLOPTTYPE_STRINGPOINT, 266),
 
   /* bitmask of allowed auth methods for connections to SOCKS5 proxies */
-  CINIT(SOCKS5_AUTH, LONG, 267),
+  CURLOPT(CURLOPT_SOCKS5_AUTH, CURLOPTTYPE_LONG, 267),
 
   /* Enable/disable SSH compression */
-  CINIT(SSH_COMPRESSION, LONG, 268),
+  CURLOPT(CURLOPT_SSH_COMPRESSION, CURLOPTTYPE_LONG, 268),
 
   /* Post MIME data. */
-  CINIT(MIMEPOST, OBJECTPOINT, 269),
+  CURLOPT(CURLOPT_MIMEPOST, CURLOPTTYPE_OBJECTPOINT, 269),
 
   /* Time to use with the CURLOPT_TIMECONDITION. Specified in number of
      seconds since 1 Jan 1970. */
-  CINIT(TIMEVALUE_LARGE, OFF_T, 270),
+  CURLOPT(CURLOPT_TIMEVALUE_LARGE, CURLOPTTYPE_OFF_T, 270),
 
   /* Head start in milliseconds to give happy eyeballs. */
-  CINIT(HAPPY_EYEBALLS_TIMEOUT_MS, LONG, 271),
+  CURLOPT(CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, CURLOPTTYPE_LONG, 271),
 
   /* Function that will be called before a resolver request is made */
-  CINIT(RESOLVER_START_FUNCTION, FUNCTIONPOINT, 272),
+  CURLOPT(CURLOPT_RESOLVER_START_FUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 272),
 
   /* User data to pass to the resolver start callback. */
-  CINIT(RESOLVER_START_DATA, OBJECTPOINT, 273),
+  CURLOPT(CURLOPT_RESOLVER_START_DATA, CURLOPTTYPE_OBJECTPOINT, 273),
 
   /* send HAProxy PROXY protocol header? */
-  CINIT(HAPROXYPROTOCOL, LONG, 274),
+  CURLOPT(CURLOPT_HAPROXYPROTOCOL, CURLOPTTYPE_LONG, 274),
 
   /* shuffle addresses before use when DNS returns multiple */
-  CINIT(DNS_SHUFFLE_ADDRESSES, LONG, 275),
+  CURLOPT(CURLOPT_DNS_SHUFFLE_ADDRESSES, CURLOPTTYPE_LONG, 275),
 
   /* Specify which TLS 1.3 ciphers suites to use */
-  CINIT(TLS13_CIPHERS, STRINGPOINT, 276),
-  CINIT(PROXY_TLS13_CIPHERS, STRINGPOINT, 277),
+  CURLOPT(CURLOPT_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 276),
+  CURLOPT(CURLOPT_PROXY_TLS13_CIPHERS, CURLOPTTYPE_STRINGPOINT, 277),
 
   /* Disallow specifying username/login in URL. */
-  CINIT(DISALLOW_USERNAME_IN_URL, LONG, 278),
+  CURLOPT(CURLOPT_DISALLOW_USERNAME_IN_URL, CURLOPTTYPE_LONG, 278),
 
   /* DNS-over-HTTPS URL */
-  CINIT(DOH_URL, STRINGPOINT, 279),
+  CURLOPT(CURLOPT_DOH_URL, CURLOPTTYPE_STRINGPOINT, 279),
 
   /* Preferred buffer size to use for uploads */
-  CINIT(UPLOAD_BUFFERSIZE, LONG, 280),
+  CURLOPT(CURLOPT_UPLOAD_BUFFERSIZE, CURLOPTTYPE_LONG, 280),
 
   /* Time in ms between connection upkeep calls for long-lived connections. */
-  CINIT(UPKEEP_INTERVAL_MS, LONG, 281),
+  CURLOPT(CURLOPT_UPKEEP_INTERVAL_MS, CURLOPTTYPE_LONG, 281),
 
   /* Specify URL using CURL URL API. */
-  CINIT(CURLU, OBJECTPOINT, 282),
+  CURLOPT(CURLOPT_CURLU, CURLOPTTYPE_OBJECTPOINT, 282),
 
   /* add trailing data just after no more data is available */
-  CINIT(TRAILERFUNCTION, FUNCTIONPOINT, 283),
+  CURLOPT(CURLOPT_TRAILERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 283),
 
   /* pointer to be passed to HTTP_TRAILER_FUNCTION */
-  CINIT(TRAILERDATA, OBJECTPOINT, 284),
+  CURLOPT(CURLOPT_TRAILERDATA, CURLOPTTYPE_OBJECTPOINT, 284),
 
   /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */
-  CINIT(HTTP09_ALLOWED, LONG, 285),
+  CURLOPT(CURLOPT_HTTP09_ALLOWED, CURLOPTTYPE_LONG, 285),
 
   /* alt-svc control bitmask */
-  CINIT(ALTSVC_CTRL, LONG, 286),
+  CURLOPT(CURLOPT_ALTSVC_CTRL, CURLOPTTYPE_LONG, 286),
 
   /* alt-svc cache file name to possibly read from/write to */
-  CINIT(ALTSVC, STRINGPOINT, 287),
+  CURLOPT(CURLOPT_ALTSVC, CURLOPTTYPE_STRINGPOINT, 287),
 
   /* maximum age of a connection to consider it for reuse (in seconds) */
-  CINIT(MAXAGE_CONN, LONG, 288),
+  CURLOPT(CURLOPT_MAXAGE_CONN, CURLOPTTYPE_LONG, 288),
 
   /* SASL authorisation identity */
-  CINIT(SASL_AUTHZID, STRINGPOINT, 289),
+  CURLOPT(CURLOPT_SASL_AUTHZID, CURLOPTTYPE_STRINGPOINT, 289),
+
+  /* allow RCPT TO command to fail for some recipients */
+  CURLOPT(CURLOPT_MAIL_RCPT_ALLLOWFAILS, CURLOPTTYPE_LONG, 290),
 
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
@@ -2220,52 +2229,35 @@ CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart 
*part,
                                        struct curl_slist *headers,
                                        int take_ownership);
 
-/* Old form API. */
-/* name is uppercase CURLFORM_<name> */
-#ifdef CFINIT
-#undef CFINIT
-#endif
-
-#ifdef CURL_ISOCPP
-#define CFINIT(name) CURLFORM_ ## name
-#else
-/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
-#define CFINIT(name) CURLFORM_/**/name
-#endif
-
 typedef enum {
-  CFINIT(NOTHING),        /********* the first one is unused ************/
-
-  /*  */
-  CFINIT(COPYNAME),
-  CFINIT(PTRNAME),
-  CFINIT(NAMELENGTH),
-  CFINIT(COPYCONTENTS),
-  CFINIT(PTRCONTENTS),
-  CFINIT(CONTENTSLENGTH),
-  CFINIT(FILECONTENT),
-  CFINIT(ARRAY),
-  CFINIT(OBSOLETE),
-  CFINIT(FILE),
-
-  CFINIT(BUFFER),
-  CFINIT(BUFFERPTR),
-  CFINIT(BUFFERLENGTH),
-
-  CFINIT(CONTENTTYPE),
-  CFINIT(CONTENTHEADER),
-  CFINIT(FILENAME),
-  CFINIT(END),
-  CFINIT(OBSOLETE2),
-
-  CFINIT(STREAM),
-  CFINIT(CONTENTLEN), /* added in 7.46.0, provide a curl_off_t length */
+  CURLFORM_NOTHING,        /********* the first one is unused ************/
+  CURLFORM_COPYNAME,
+  CURLFORM_PTRNAME,
+  CURLFORM_NAMELENGTH,
+  CURLFORM_COPYCONTENTS,
+  CURLFORM_PTRCONTENTS,
+  CURLFORM_CONTENTSLENGTH,
+  CURLFORM_FILECONTENT,
+  CURLFORM_ARRAY,
+  CURLFORM_OBSOLETE,
+  CURLFORM_FILE,
+
+  CURLFORM_BUFFER,
+  CURLFORM_BUFFERPTR,
+  CURLFORM_BUFFERLENGTH,
+
+  CURLFORM_CONTENTTYPE,
+  CURLFORM_CONTENTHEADER,
+  CURLFORM_FILENAME,
+  CURLFORM_END,
+  CURLFORM_OBSOLETE2,
+
+  CURLFORM_STREAM,
+  CURLFORM_CONTENTLEN, /* added in 7.46.0, provide a curl_off_t length */
 
   CURLFORM_LASTENTRY /* the last unused */
 } CURLformoption;
 
-#undef CFINIT /* done */
-
 /* structure to be used as parameter for CURLFORM_ARRAY */
 struct curl_forms {
   CURLformoption option;
diff --git a/include/gnurl/curlver.h b/include/gnurl/curlver.h
index 5b0df8ede..aeb39d01c 100644
--- a/include/gnurl/curlver.h
+++ b/include/gnurl/curlver.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -26,17 +26,17 @@
    a script at release-time. This was made its own header file in 7.11.2 */
 
 /* This is the global package copyright */
-#define LIBCURL_COPYRIGHT "1996 - 2019 Daniel Stenberg, <address@hidden>."
+#define LIBCURL_COPYRIGHT "1996 - 2020 Daniel Stenberg, <address@hidden>."
 
 /* This is the version number of the libcurl package from which this header
    file origins: */
-#define LIBCURL_VERSION "7.68.0-DEV"
+#define LIBCURL_VERSION "7.69.1-DEV"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 68
-#define LIBCURL_VERSION_PATCH 0
+#define LIBCURL_VERSION_MINOR 69
+#define LIBCURL_VERSION_PATCH 1
 
 /* This is the numeric version of the libcurl version number, meant for easier
    parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
@@ -57,7 +57,7 @@
    CURL_VERSION_BITS() macro since curl's own configure script greps for it
    and needs it to contain the full number.
 */
-#define LIBCURL_VERSION_NUM 0x074400
+#define LIBCURL_VERSION_NUM 0x074501
 
 /*
  * This is the date and time when the full source package was created. The
diff --git a/include/gnurl/multi.h b/include/gnurl/multi.h
index 0fcf734d4..04b2cf7f3 100644
--- a/include/gnurl/multi.h
+++ b/include/gnurl/multi.h
@@ -72,7 +72,8 @@ typedef enum {
                             attempted to get added - again */
   CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
                                callback */
-  CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */
+  CURLM_WAKEUP_FAILURE,  /* wakeup is unavailable or failed */
+  CURLM_BAD_FUNCTION_ARGUMENT,  /* function called with a bad parameter */
   CURLM_LAST
 } CURLMcode;
 
@@ -343,71 +344,58 @@ CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM 
*multi_handle,
 CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
                                          long *milliseconds);
 
-#undef CINIT /* re-using the same name as in curl.h */
-
-#ifdef CURL_ISOCPP
-#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
-#else
-/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
-#define LONG          CURLOPTTYPE_LONG
-#define OBJECTPOINT   CURLOPTTYPE_OBJECTPOINT
-#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
-#define OFF_T         CURLOPTTYPE_OFF_T
-#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
-#endif
-
 typedef enum {
   /* This is the socket callback function pointer */
-  CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
+  CURLOPT(CURLMOPT_SOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1),
 
   /* This is the argument passed to the socket callback */
-  CINIT(SOCKETDATA, OBJECTPOINT, 2),
+  CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2),
 
     /* set to 1 to enable pipelining for this multi handle */
-  CINIT(PIPELINING, LONG, 3),
+  CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3),
 
    /* This is the timer callback function pointer */
-  CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
+  CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4),
 
   /* This is the argument passed to the timer callback */
-  CINIT(TIMERDATA, OBJECTPOINT, 5),
+  CURLOPT(CURLMOPT_TIMERDATA, CURLOPTTYPE_OBJECTPOINT, 5),
 
   /* maximum number of entries in the connection cache */
-  CINIT(MAXCONNECTS, LONG, 6),
+  CURLOPT(CURLMOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 6),
 
   /* maximum number of (pipelining) connections to one host */
-  CINIT(MAX_HOST_CONNECTIONS, LONG, 7),
+  CURLOPT(CURLMOPT_MAX_HOST_CONNECTIONS, CURLOPTTYPE_LONG, 7),
 
   /* maximum number of requests in a pipeline */
-  CINIT(MAX_PIPELINE_LENGTH, LONG, 8),
+  CURLOPT(CURLMOPT_MAX_PIPELINE_LENGTH, CURLOPTTYPE_LONG, 8),
 
   /* a connection with a content-length longer than this
      will not be considered for pipelining */
-  CINIT(CONTENT_LENGTH_PENALTY_SIZE, OFF_T, 9),
+  CURLOPT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 9),
 
   /* a connection with a chunk length longer than this
      will not be considered for pipelining */
-  CINIT(CHUNK_LENGTH_PENALTY_SIZE, OFF_T, 10),
+  CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10),
 
   /* a list of site names(+port) that are blacklisted from
      pipelining */
-  CINIT(PIPELINING_SITE_BL, OBJECTPOINT, 11),
+  CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11),
 
   /* a list of server types that are blacklisted from
      pipelining */
-  CINIT(PIPELINING_SERVER_BL, OBJECTPOINT, 12),
+  CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12),
 
   /* maximum number of open connections in total */
-  CINIT(MAX_TOTAL_CONNECTIONS, LONG, 13),
+  CURLOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, CURLOPTTYPE_LONG, 13),
 
    /* This is the server push callback function pointer */
-  CINIT(PUSHFUNCTION, FUNCTIONPOINT, 14),
+  CURLOPT(CURLMOPT_PUSHFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 14),
 
   /* This is the argument passed to the server push callback */
-  CINIT(PUSHDATA, OBJECTPOINT, 15),
+  CURLOPT(CURLMOPT_PUSHDATA, CURLOPTTYPE_OBJECTPOINT, 15),
 
   /* maximum number of concurrent streams to support on a connection */
-  CINIT(MAX_CONCURRENT_STREAMS, LONG, 16),
+  CURLOPT(CURLMOPT_MAX_CONCURRENT_STREAMS, CURLOPTTYPE_LONG, 16),
 
   CURLMOPT_LASTENTRY /* the last unused */
 } CURLMoption;
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 5bd15654c..dcedbc56d 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -96,6 +96,12 @@ endif()
 set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
 set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "")
 
+if(CURL_HAS_LTO)
+  set_target_properties(${LIB_NAME} PROPERTIES
+    INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
+    INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
+endif()
+
 if(WIN32)
   if(BUILD_SHARED_LIBS)
     # Add "_imp" as a suffix before the extension to avoid conflicting with 
the statically linked "libcurl.lib"
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index 6c90c2675..46ded90bb 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -28,21 +28,20 @@ LIB_VAUTH_CFILES = vauth/vauth.c vauth/cleartext.c 
vauth/cram.c         \
 LIB_VAUTH_HFILES = vauth/vauth.h vauth/digest.h vauth/ntlm.h
 
 LIB_VTLS_CFILES = vtls/openssl.c vtls/gtls.c vtls/vtls.c vtls/nss.c     \
-  vtls/polarssl.c vtls/polarssl_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
+  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_HFILES = vtls/openssl.h vtls/vtls.h vtls/gtls.h                \
-  vtls/nssg.h vtls/polarssl.h vtls/polarssl_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/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_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c
 
 LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h
 
-LIB_VSSH_CFILES = vssh/libssh2.c vssh/libssh.c
+LIB_VSSH_CFILES = vssh/libssh2.c vssh/libssh.c vssh/wolfssh.c
 
 LIB_VSSH_HFILES = vssh/ssh.h
 
@@ -64,7 +63,7 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c 
formdata.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
+  doh.c urlapi.c curl_get_line.c altsvc.c socketpair.c rename.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         \
@@ -85,7 +84,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h 
progress.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
+  curl_get_line.h altsvc.h quic.h socketpair.h rename.h
 
 LIB_RCFILES = libcurl.rc
 
diff --git a/lib/Makefile.m32 b/lib/Makefile.m32
index b6ef0a5cb..ac6b3de63 100644
--- a/lib/Makefile.m32
+++ b/lib/Makefile.m32
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1999 - 2019, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1999 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -270,7 +270,7 @@ ifdef SSL
     OPENSSL_LIBS += -lgdi32 -lcrypt32
   endif
   INCLUDES += -I"$(OPENSSL_INCLUDE)"
-  CFLAGS += -DUSE_OPENSSL -DHAVE_OPENSSL_ENGINE_H -DHAVE_OPENSSL_PKCS12_H \
+  CFLAGS += -DUSE_OPENSSL -DHAVE_OPENSSL_PKCS12_H \
             -DOPENSSL_NO_KRB5
   DLL_LIBS += -L"$(OPENSSL_LIBPATH)" $(OPENSSL_LIBS)
   ifdef SRP
diff --git a/lib/Makefile.netware b/lib/Makefile.netware
index adc1ce6c3..f066fd02e 100644
--- a/lib/Makefile.netware
+++ b/lib/Makefile.netware
@@ -6,7 +6,7 @@
 #                             \___|\___/|_| \_\_____|
 #
 # Copyright (C) 2004 - 2015, Guenter Knauf
-# Copyright (C) 2001 - 2018, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 2001 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -639,7 +639,6 @@ ifdef WITH_SSL
        @echo $(DL)#define HAVE_OPENSSL_PEM_H 1$(DL) >> $@
        @echo $(DL)#define HAVE_OPENSSL_ERR_H 1$(DL) >> $@
        @echo $(DL)#define HAVE_OPENSSL_CRYPTO_H 1$(DL) >> $@
-       @echo $(DL)#define HAVE_OPENSSL_ENGINE_H 1$(DL) >> $@
        @echo $(DL)#define OPENSSL_NO_KRB5 1$(DL) >> $@
 ifdef WITH_SRP
        @echo $(DL)#define USE_TLS_SRP 1$(DL) >> $@
diff --git a/lib/altsvc.c b/lib/altsvc.c
index 1533a274b..9da0917a8 100644
--- a/lib/altsvc.c
+++ b/lib/altsvc.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2019 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -34,6 +34,8 @@
 #include "parsedate.h"
 #include "sendf.h"
 #include "warnless.h"
+#include "rand.h"
+#include "rename.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -48,19 +50,20 @@
 #define MAX_ALTSVC_ALPNLENSTR "10"
 #define MAX_ALTSVC_ALPNLEN 10
 
+#if (defined(USE_QUICHE) || defined(USE_NGTCP2)) && !defined(UNITTESTS)
+#define H3VERSION "h3-27"
+#else
+#define H3VERSION "h3"
+#endif
+
 static enum alpnid alpn2alpnid(char *name)
 {
   if(strcasecompare(name, "h1"))
     return ALPN_h1;
   if(strcasecompare(name, "h2"))
     return ALPN_h2;
-#if (defined(USE_QUICHE) || defined(USE_NGTCP2)) && !defined(UNITTESTS)
-  if(strcasecompare(name, "h3-24"))
-    return ALPN_h3;
-#else
-  if(strcasecompare(name, "h3"))
+  if(strcasecompare(name, H3VERSION))
     return ALPN_h3;
-#endif
   return ALPN_none; /* unknown, probably rubbish input */
 }
 
@@ -73,11 +76,7 @@ const char *Curl_alpnid2str(enum alpnid id)
   case ALPN_h2:
     return "h2";
   case ALPN_h3:
-#if (defined(USE_QUICHE) || defined(USE_NGTCP2)) && !defined(UNITTESTS)
-    return "h3-24";
-#else
-    return "h3";
-#endif
+    return H3VERSION;
   default:
     return ""; /* bad */
   }
@@ -188,7 +187,16 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const 
char *file)
 {
   CURLcode result = CURLE_OK;
   char *line = NULL;
-  FILE *fp = fopen(file, FOPEN_READTEXT);
+  FILE *fp;
+
+  /* we need a private copy of the file name so that the altsvc cache file
+     name survives an easy handle reset */
+  free(asi->filename);
+  asi->filename = strdup(file);
+  if(!asi->filename)
+    return CURLE_OUT_OF_MEMORY;
+
+  fp = fopen(file, FOPEN_READTEXT);
   if(fp) {
     line = malloc(MAX_ALTSVC_LINE);
     if(!line)
@@ -209,6 +217,7 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const 
char *file)
   return result;
 
   fail:
+  Curl_safefree(asi->filename);
   free(line);
   fclose(fp);
   return CURLE_OUT_OF_MEMORY;
@@ -302,6 +311,7 @@ void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
       n = e->next;
       altsvc_free(as);
     }
+    free(altsvc->filename);
     free(altsvc);
   }
 }
@@ -309,34 +319,57 @@ void Curl_altsvc_cleanup(struct altsvcinfo *altsvc)
 /*
  * Curl_altsvc_save() writes the altsvc cache to a file.
  */
-CURLcode Curl_altsvc_save(struct altsvcinfo *altsvc, const char *file)
+CURLcode Curl_altsvc_save(struct Curl_easy *data,
+                          struct altsvcinfo *altsvc, const char *file)
 {
   struct curl_llist_element *e;
   struct curl_llist_element *n;
   CURLcode result = CURLE_OK;
   FILE *out;
+  char *tempstore;
+  unsigned char randsuffix[9];
 
   if(!altsvc)
     /* no cache activated */
     return CURLE_OK;
 
+  /* if not new name is given, use the one we stored from the load */
+  if(!file && altsvc->filename)
+    file = altsvc->filename;
+
   if((altsvc->flags & CURLALTSVC_READONLYFILE) || !file || !file[0])
     /* marked as read-only, no file or zero length file name */
     return CURLE_OK;
-  out = fopen(file, FOPEN_WRITETEXT);
+
+  if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
+    return CURLE_FAILED_INIT;
+
+  tempstore = aprintf("%s.%s.tmp", file, randsuffix);
+  if(!tempstore)
+    return CURLE_OUT_OF_MEMORY;
+
+  out = fopen(tempstore, FOPEN_WRITETEXT);
   if(!out)
-    return CURLE_WRITE_ERROR;
-  fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n";
-        "# This file was generated by libcurl! Edit at your own risk.\n",
-        out);
-  for(e = altsvc->list.head; e; e = n) {
-    struct altsvc *as = e->ptr;
-    n = e->next;
-    result = altsvc_out(as, out);
+    result = CURLE_WRITE_ERROR;
+  else {
+    fputs("# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html\n";
+          "# This file was generated by libcurl! Edit at your own risk.\n",
+          out);
+    for(e = altsvc->list.head; e; e = n) {
+      struct altsvc *as = e->ptr;
+      n = e->next;
+      result = altsvc_out(as, out);
+      if(result)
+        break;
+    }
+    fclose(out);
+    if(!result && Curl_rename(tempstore, file))
+      result = CURLE_WRITE_ERROR;
+
     if(result)
-      break;
+      unlink(tempstore);
   }
-  fclose(out);
+  free(tempstore);
   return result;
 }
 
@@ -351,12 +384,12 @@ static CURLcode getalnum(const char **ptr, char *alpnbuf, 
size_t buflen)
   while(*p && !ISBLANK(*p) && (*p != ';') && (*p != '='))
     p++;
   len = p - protop;
+  *ptr = p;
 
   if(!len || (len >= buflen))
     return CURLE_BAD_FUNCTION_ARGUMENT;
   memcpy(alpnbuf, protop, len);
   alpnbuf[len] = 0;
-  *ptr = p;
   return CURLE_OK;
 }
 
@@ -402,6 +435,10 @@ static time_t debugtime(void *unused)
  *
  * 'value' points to the header *value*. That's contents to the right of the
  * header name.
+ *
+ * Currently this function rejects invalid data without returning an error.
+ * Invalid host name, port number will result in the specific alternative
+ * being rejected. Unknown protocols are skipped.
  */
 CURLcode Curl_altsvc_parse(struct Curl_easy *data,
                            struct altsvcinfo *asi, const char *value,
@@ -415,12 +452,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
   char alpnbuf[MAX_ALTSVC_ALPNLEN] = "";
   struct altsvc *as;
   unsigned short dstport = srcport; /* the same by default */
-  const char *semip;
-  time_t maxage = 24 * 3600; /* default is 24 hours */
-  bool persist = FALSE;
   CURLcode result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
-  if(result)
-    return result;
+  if(result) {
+    infof(data, "Excessive alt-svc header, ignoring...\n");
+    return CURLE_OK;
+  }
 
   DEBUGASSERT(asi);
 
@@ -432,57 +468,20 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
     return CURLE_OK;
   }
 
-  /* The 'ma' and 'persist' flags are annoyingly meant for all alternatives
-     but are set after the list on the line. Scan for the semicolons and get
-     those fields first! */
-  semip = p;
-  do {
-    semip = strchr(semip, ';');
-    if(semip) {
-      char option[32];
-      unsigned long num;
-      char *end_ptr;
-      bool quoted = FALSE;
-      semip++; /* pass the semicolon */
-      result = getalnum(&semip, option, sizeof(option));
-      if(result)
-        break;
-      while(*semip && ISBLANK(*semip))
-        semip++;
-      if(*semip != '=')
-        continue;
-      semip++;
-      while(*semip && ISBLANK(*semip))
-        semip++;
-      if(*semip == '\"') {
-        /* quoted value */
-        semip++;
-        quoted = TRUE;
-      }
-      num = strtoul(semip, &end_ptr, 10);
-      if((end_ptr != semip) && num && (num < ULONG_MAX)) {
-        if(strcasecompare("ma", option))
-          maxage = num;
-        else if(strcasecompare("persist", option) && (num == 1))
-          persist = TRUE;
-        if(quoted && (*end_ptr == '\"'))
-          end_ptr++;
-      }
-      semip = end_ptr;
-    }
-  } while(semip);
-
   do {
     if(*p == '=') {
       /* [protocol]="[host][:port]" */
       dstalpnid = alpn2alpnid(alpnbuf);
-      if(!dstalpnid) {
-        infof(data, "Unknown alt-svc protocol \"%s\", ignoring...\n", alpnbuf);
-        return CURLE_OK;
-      }
       p++;
       if(*p == '\"') {
         const char *dsthost;
+        const char *value_ptr;
+        char option[32];
+        unsigned long num;
+        char *end_ptr;
+        bool quoted = FALSE;
+        time_t maxage = 24 * 3600; /* default is 24 hours */
+        bool persist = FALSE;
         p++;
         if(*p != ':') {
           /* host name starts here */
@@ -490,11 +489,15 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
           while(*p && (ISALNUM(*p) || (*p == '.') || (*p == '-')))
             p++;
           len = p - hostp;
-          if(!len || (len >= MAX_ALTSVC_HOSTLEN))
-            return CURLE_BAD_FUNCTION_ARGUMENT;
-          memcpy(namebuf, hostp, len);
-          namebuf[len] = 0;
-          dsthost = namebuf;
+          if(!len || (len >= MAX_ALTSVC_HOSTLEN)) {
+            infof(data, "Excessive alt-svc host name, ignoring...\n");
+            dstalpnid = ALPN_none;
+          }
+          else {
+            memcpy(namebuf, hostp, len);
+            namebuf[len] = 0;
+            dsthost = namebuf;
+          }
         }
         else {
           /* no destination name, use source host */
@@ -502,31 +505,86 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
         }
         if(*p == ':') {
           /* a port number */
-          char *end_ptr;
           unsigned long port = strtoul(++p, &end_ptr, 10);
           if(port > USHRT_MAX || end_ptr == p || *end_ptr != '\"') {
             infof(data, "Unknown alt-svc port number, ignoring...\n");
-            return CURLE_OK;
+            dstalpnid = ALPN_none;
           }
           p = end_ptr;
           dstport = curlx_ultous(port);
         }
         if(*p++ != '\"')
-          return CURLE_BAD_FUNCTION_ARGUMENT;
-        as = altsvc_createid(srchost, dsthost,
-                             srcalpnid, dstalpnid,
-                             srcport, dstport);
-        if(as) {
-          /* The expires time also needs to take the Age: value (if any) into
-             account. [See RFC 7838 section 3.1] */
-          as->expires = maxage + time(NULL);
-          as->persist = persist;
-          Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
-          asi->num++; /* one more entry */
-          infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
-                Curl_alpnid2str(dstalpnid));
+          break;
+        /* Handle the optional 'ma' and 'persist' flags. Unknown flags
+           are skipped. */
+        for(;;) {
+          while(*p && ISBLANK(*p) && *p != ';' && *p != ',')
+            p++;
+          if(!*p || *p == ',')
+            break;
+          p++; /* pass the semicolon */
+          if(!*p)
+            break;
+          result = getalnum(&p, option, sizeof(option));
+          if(result) {
+            /* skip option if name is too long */
+            option[0] = '\0';
+          }
+          while(*p && ISBLANK(*p))
+            p++;
+          if(*p != '=')
+            return CURLE_OK;
+          p++;
+          while(*p && ISBLANK(*p))
+            p++;
+          if(!*p)
+            return CURLE_OK;
+          if(*p == '\"') {
+            /* quoted value */
+            p++;
+            quoted = TRUE;
+          }
+          value_ptr = p;
+          if(quoted) {
+            while(*p && *p != '\"')
+              p++;
+            if(!*p++)
+              return CURLE_OK;
+          }
+          else {
+            while(*p && !ISBLANK(*p) && *p!= ';' && *p != ',')
+              p++;
+          }
+          num = strtoul(value_ptr, &end_ptr, 10);
+          if((end_ptr != value_ptr) && (num < ULONG_MAX)) {
+            if(strcasecompare("ma", option))
+              maxage = num;
+            else if(strcasecompare("persist", option) && (num == 1))
+              persist = TRUE;
+          }
+        }
+        if(dstalpnid) {
+          as = altsvc_createid(srchost, dsthost,
+                               srcalpnid, dstalpnid,
+                               srcport, dstport);
+          if(as) {
+            /* The expires time also needs to take the Age: value (if any) into
+               account. [See RFC 7838 section 3.1] */
+            as->expires = maxage + time(NULL);
+            as->persist = persist;
+            Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
+            asi->num++; /* one more entry */
+            infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
+                  Curl_alpnid2str(dstalpnid));
+          }
+        }
+        else {
+          infof(data, "Unknown alt-svc protocol \"%s\", skipping...\n",
+                alpnbuf);
         }
       }
+      else
+        break;
       /* after the double quote there can be a comma if there's another
          string or a semicolon if no more */
       if(*p == ',') {
@@ -534,11 +592,11 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
         p++;
         result = getalnum(&p, alpnbuf, sizeof(alpnbuf));
         if(result)
-          /* failed to parse, but since we already did at least one host we
-             return OK */
-          return CURLE_OK;
+          break;
       }
     }
+    else
+      break;
   } while(*p && (*p != ';') && (*p != '\n') && (*p != '\r'));
 
   return CURLE_OK;
diff --git a/lib/altsvc.h b/lib/altsvc.h
index 8f09aa3c5..4e1e77aa4 100644
--- a/lib/altsvc.h
+++ b/lib/altsvc.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2019 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -59,7 +59,8 @@ struct altsvcinfo {
 const char *Curl_alpnid2str(enum alpnid id);
 struct altsvcinfo *Curl_altsvc_init(void);
 CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file);
-CURLcode Curl_altsvc_save(struct altsvcinfo *asi, const char *file);
+CURLcode Curl_altsvc_save(struct Curl_easy *data,
+                          struct altsvcinfo *asi, const char *file);
 CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl);
 void Curl_altsvc_cleanup(struct altsvcinfo *altsvc);
 CURLcode Curl_altsvc_parse(struct Curl_easy *data,
@@ -70,9 +71,9 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi,
                         enum alpnid srcalpnid, const char *srchost,
                         int srcport,
                         struct altsvc **dstentry,
-                        int versions); /* one or more CURLALTSVC_H* bits */
+                        const int versions); /* CURLALTSVC_H* bits */
 #else
 /* disabled */
-#define Curl_altsvc_save(a,b)
+#define Curl_altsvc_save(a,b,c)
 #endif /* CURL_DISABLE_HTTP || USE_ALTSVC */
 #endif /* HEADER_CURL_ALTSVC_H */
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index 835cfa48f..b76e66548 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -626,26 +626,11 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct 
connectdata *conn,
 {
   char *bufp;
   struct Curl_easy *data = conn->data;
-  struct in_addr in;
   int family = PF_INET;
-#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
-  struct in6_addr in6;
-#endif /* CURLRES_IPV6 */
 
   *waitp = 0; /* default to synchronous response */
 
-  /* 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 */
-    return Curl_ip2addr(AF_INET, &in, hostname, port);
-  }
-
 #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
-  /* Otherwise, check if this is an IPv6 address string */
-  if(Curl_inet_pton (AF_INET6, hostname, &in6) > 0)
-    /* This must be an IPv6 address literal.  */
-    return Curl_ip2addr(AF_INET6, &in6, hostname, port);
-
   switch(conn->ip_version) {
   default:
 #if ARES_VERSION >= 0x010601
@@ -684,7 +669,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata 
*conn,
     res->last_status = ARES_ENOTFOUND;
 #ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
     if(family == PF_UNSPEC) {
-      if(Curl_ipv6works()) {
+      if(Curl_ipv6works(conn)) {
         res->num_pending = 2;
 
         /* areschannel is already setup in the Curl_open() function */
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index b08497aaa..68dcbb3ec 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -71,7 +71,6 @@
 #include "strerror.h"
 #include "url.h"
 #include "multiif.h"
-#include "inet_pton.h"
 #include "inet_ntop.h"
 #include "curl_threads.h"
 #include "connect.h"
@@ -692,26 +691,11 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct 
connectdata *conn,
                                          int port,
                                          int *waitp)
 {
-  struct in_addr in;
   struct Curl_easy *data = conn->data;
   struct resdata *reslv = (struct resdata *)data->state.resolver;
 
   *waitp = 0; /* default to synchronous response */
 
-#ifdef ENABLE_IPV6
-  {
-    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 */
-      return Curl_ip2addr(AF_INET6, &in6, hostname, port);
-  }
-#endif /* ENABLE_IPV6 */
-
-  if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
-    /* This is a dotted IP address 123.123.123.123-style */
-    return Curl_ip2addr(AF_INET, &in, hostname, port);
-
   reslv->start = Curl_now();
 
   /* fire up a new resolver thread! */
@@ -736,32 +720,12 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct 
connectdata *conn,
                                          int *waitp)
 {
   struct addrinfo hints;
-  char sbuf[12];
   int pf = PF_INET;
   struct Curl_easy *data = conn->data;
   struct resdata *reslv = (struct resdata *)data->state.resolver;
 
   *waitp = 0; /* default to synchronous response */
 
-#ifndef USE_RESOLVE_ON_IPS
-  {
-    struct in_addr in;
-    /* 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 */
-      return Curl_ip2addr(AF_INET, &in, hostname, port);
-  }
-#ifdef ENABLE_IPV6
-  {
-    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 */
-      return Curl_ip2addr(AF_INET6, &in6, hostname, port);
-  }
-#endif /* ENABLE_IPV6 */
-#endif /* !USE_RESOLVE_ON_IPS */
-
 #ifdef CURLRES_IPV6
   /*
    * Check if a limited name resolve has been requested.
@@ -778,7 +742,7 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata 
*conn,
     break;
   }
 
-  if((pf != PF_INET) && !Curl_ipv6works())
+  if((pf != PF_INET) && !Curl_ipv6works(conn))
     /* The stack seems to be a non-IPv6 one */
     pf = PF_INET;
 #endif /* CURLRES_IPV6 */
@@ -788,8 +752,6 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata 
*conn,
   hints.ai_socktype = (conn->transport == TRNSPRT_TCP)?
     SOCK_STREAM : SOCK_DGRAM;
 
-  msnprintf(sbuf, sizeof(sbuf), "%d", port);
-
   reslv->start = Curl_now();
   /* fire up a new resolver thread! */
   if(init_resolve_thread(conn, hostname, port, &hints)) {
diff --git a/lib/checksrc.pl b/lib/checksrc.pl
index 834364561..e1bb1a633 100755
--- a/lib/checksrc.pl
+++ b/lib/checksrc.pl
@@ -36,7 +36,7 @@ my $file;
 my $dir=".";
 my $wlist="";
 my @alist;
-my $windows_os = $^O eq 'MSWin32' || $^O eq 'msys' || $^O eq 'cygwin';
+my $windows_os = $^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'msys';
 my $verbose;
 my %whitelist;
 
diff --git a/lib/config-dos.h b/lib/config-dos.h
index 25f751eb5..aa83c4be5 100644
--- a/lib/config-dos.h
+++ b/lib/config-dos.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -138,7 +138,6 @@
 /* USE_OPENSSL on cmd-line */
 #ifdef USE_OPENSSL
   #define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1
-  #define HAVE_OPENSSL_ENGINE_H  1
   #define OPENSSL_NO_KRB5        1
 #endif
 
diff --git a/lib/config-plan9.h b/lib/config-plan9.h
index 4063d4bbd..41440a14e 100644
--- a/lib/config-plan9.h
+++ b/lib/config-plan9.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -138,7 +138,6 @@
 
 #define USE_OPENSSL 1
 #define HAVE_OPENSSL_CRYPTO_H 1
-#define HAVE_OPENSSL_ENGINE_H 1
 #define HAVE_OPENSSL_ERR_H 1
 #define HAVE_OPENSSL_PEM_H 1
 #define HAVE_OPENSSL_PKCS12_H 1
diff --git a/lib/config-symbian.h b/lib/config-symbian.h
index c01e1bfab..82a27bfef 100644
--- a/lib/config-symbian.h
+++ b/lib/config-symbian.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -358,9 +358,6 @@
 /* Define to 1 if you have the <openssl/crypto.h> header file. */
 /*#define HAVE_OPENSSL_CRYPTO_H 1*/
 
-/* Define to 1 if you have the <openssl/engine.h> header file. */
-/*#define HAVE_OPENSSL_ENGINE_H 1*/
-
 /* Define to 1 if you have the <openssl/err.h> header file. */
 /*#define HAVE_OPENSSL_ERR_H 1*/
 
diff --git a/lib/config-tpf.h b/lib/config-tpf.h
index 85b634f9d..a79afae6d 100644
--- a/lib/config-tpf.h
+++ b/lib/config-tpf.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -316,10 +316,6 @@
 /* #undef HAVE_OPENSSL_CRYPTO_H */
 #define HAVE_OPENSSL_CRYPTO_H 1
 
-/* Define to 1 if you have the <openssl/engine.h> header file. */
-/* #undef HAVE_OPENSSL_ENGINE_H */
-#define HAVE_OPENSSL_ENGINE_H 1
-
 /* Define to 1 if you have the <openssl/err.h> header file. */
 /* #undef HAVE_OPENSSL_ERR_H */
 #define HAVE_OPENSSL_ERR_H 1
diff --git a/lib/config-vxworks.h b/lib/config-vxworks.h
index 004fd4e80..2769cdfd9 100644
--- a/lib/config-vxworks.h
+++ b/lib/config-vxworks.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -418,9 +418,6 @@
 /* Define to 1 if you have the <openssl/crypto.h> header file. */
 #define HAVE_OPENSSL_CRYPTO_H 1
 
-/* Define to 1 if you have the <openssl/engine.h> header file. */
-#define HAVE_OPENSSL_ENGINE_H 1
-
 /* Define to 1 if you have the <openssl/err.h> header file. */
 #define HAVE_OPENSSL_ERR_H 1
 
diff --git a/lib/config-win32.h b/lib/config-win32.h
index 1dcce0db4..d19665d71 100644
--- a/lib/config-win32.h
+++ b/lib/config-win32.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -183,7 +183,7 @@
 /* #define HAVE_DOPRNT 1 */
 
 /* Define if you have the ftruncate function. */
-#define HAVE_FTRUNCATE 1
+/* #define HAVE_FTRUNCATE 1 */
 
 /* Define to 1 if you have the `getpeername' function. */
 #define HAVE_GETPEERNAME 1
@@ -714,7 +714,9 @@ Vista
 #endif
 
 /* Define to use the Windows crypto library. */
+#if !defined(CURL_WINDOWS_APP)
 #define USE_WIN32_CRYPTO
+#endif
 
 /* Define to use Unix sockets. */
 #if defined(_MSC_VER) && (_MSC_VER >= 1500)
diff --git a/lib/conncache.c b/lib/conncache.c
index d26272459..e7ba564b4 100644
--- a/lib/conncache.c
+++ b/lib/conncache.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2012 - 2016, Linus Nielsen Feltzing, <address@hidden>
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2012 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -179,18 +179,6 @@ size_t Curl_conncache_size(struct Curl_easy *data)
   return num;
 }
 
-/* Returns number of connections currently held in the connections's bundle
-   Locks/unlocks the cache itself!
-*/
-size_t Curl_conncache_bundle_size(struct connectdata *conn)
-{
-  size_t num;
-  CONN_LOCK(conn->data);
-  num = conn->bundle->num_connections;
-  CONN_UNLOCK(conn->data);
-  return num;
-}
-
 /* Look up the bundle with all the connections to the same host this
    connectdata struct is setup to use.
 
diff --git a/lib/conncache.h b/lib/conncache.h
index 5fe80b4c8..e3e4c9c28 100644
--- a/lib/conncache.h
+++ b/lib/conncache.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2015 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2015 - 2020, Daniel Stenberg, <address@hidden>, et al.
  * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, <address@hidden>
  *
  * This software is licensed as described in the file COPYING, which
@@ -80,7 +80,6 @@ struct connectbundle *Curl_conncache_find_bundle(struct 
connectdata *conn,
 void Curl_conncache_unlock(struct Curl_easy *data);
 /* returns number of connections currently held in the connection cache */
 size_t Curl_conncache_size(struct Curl_easy *data);
-size_t Curl_conncache_bundle_size(struct connectdata *conn);
 
 bool Curl_conncache_return_conn(struct Curl_easy *data,
                                 struct connectdata *conn);
diff --git a/lib/connect.c b/lib/connect.c
index 611d6d2f0..0a7475cb6 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -745,13 +745,15 @@ void Curl_updateconninfo(struct connectdata *conn, 
curl_socket_t sockfd)
   Curl_persistconninfo(conn);
 }
 
-/* after a TCP connection to the proxy has been verified, this function does
-   the next magic step.
+/* After a TCP connection to the proxy has been verified, this function does
+   the next magic steps. If 'done' isn't set TRUE, it is not done yet and
+   must be called again.
 
    Note: this function's sub-functions call failf()
 
 */
-static CURLcode connected_proxy(struct connectdata *conn, int sockindex)
+static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
+                              bool *done)
 {
   CURLcode result = CURLE_OK;
 
@@ -760,43 +762,62 @@ static CURLcode connected_proxy(struct connectdata *conn, 
int sockindex)
     /* for the secondary socket (FTP), use the "connect to host"
      * but ignore the "connect to port" (use the secondary port)
      */
-    const char * const host = conn->bits.httpproxy ?
-                              conn->http_proxy.host.name :
-                              conn->bits.conn_to_host ?
-                              conn->conn_to_host.name :
-                              sockindex == SECONDARYSOCKET ?
-                              conn->secondaryhostname : conn->host.name;
-    const int port = conn->bits.httpproxy ? (int)conn->http_proxy.port :
-                     sockindex == SECONDARYSOCKET ? conn->secondary_port :
-                     conn->bits.conn_to_port ? conn->conn_to_port :
-                     conn->remote_port;
-    conn->bits.socksproxy_connecting = TRUE;
+    const char * const host =
+      conn->bits.httpproxy ?
+      conn->http_proxy.host.name :
+      conn->bits.conn_to_host ?
+      conn->conn_to_host.name :
+      sockindex == SECONDARYSOCKET ?
+      conn->secondaryhostname : conn->host.name;
+    const int port =
+      conn->bits.httpproxy ? (int)conn->http_proxy.port :
+      sockindex == SECONDARYSOCKET ? conn->secondary_port :
+      conn->bits.conn_to_port ? conn->conn_to_port :
+      conn->remote_port;
     switch(conn->socks_proxy.proxytype) {
     case CURLPROXY_SOCKS5:
     case CURLPROXY_SOCKS5_HOSTNAME:
       result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
-                         host, port, sockindex, conn);
+                           host, port, sockindex, conn, done);
       break;
 
     case CURLPROXY_SOCKS4:
     case CURLPROXY_SOCKS4A:
       result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
-                           conn);
+                           conn, done);
       break;
 
     default:
       failf(conn->data, "unknown proxytype option given");
       result = CURLE_COULDNT_CONNECT;
     } /* switch proxytype */
-    conn->bits.socksproxy_connecting = FALSE;
 #else
   (void)sockindex;
 #endif /* CURL_DISABLE_PROXY */
   }
+  else
+    *done = TRUE; /* no SOCKS proxy, so consider us connected */
 
   return result;
 }
 
+/*
+ * post_SOCKS() is called after a successful connect to the peer, which
+ * *could* be a SOCKS proxy
+ */
+static void post_SOCKS(struct connectdata *conn,
+                       int sockindex,
+                       bool *connected)
+{
+  conn->bits.tcpconnect[sockindex] = TRUE;
+
+  *connected = TRUE;
+  if(sockindex == FIRSTSOCKET)
+    Curl_pgrsTime(conn->data, TIMER_CONNECT); /* connect done */
+  Curl_updateconninfo(conn, conn->sock[sockindex]);
+  Curl_verboseconnect(conn);
+}
+
 /*
  * Curl_is_connected() checks if the socket has connected.
  */
@@ -834,6 +855,14 @@ CURLcode Curl_is_connected(struct connectdata *conn,
     return CURLE_OPERATION_TIMEDOUT;
   }
 
+  if(SOCKS_STATE(conn->cnnct.state)) {
+    /* still doing SOCKS */
+    result = connect_SOCKS(conn, sockindex, connected);
+    if(!result && *connected)
+      post_SOCKS(conn, sockindex, connected);
+    return result;
+  }
+
   for(i = 0; i<2; i++) {
     const int other = i ^ 1;
     if(conn->tempsock[i] == CURL_SOCKET_BAD)
@@ -900,18 +929,13 @@ CURLcode Curl_is_connected(struct connectdata *conn,
           conn->tempsock[other] = CURL_SOCKET_BAD;
         }
 
-        /* see if we need to do any proxy magic first once we connected */
-        result = connected_proxy(conn, sockindex);
-        if(result)
+        /* see if we need to kick off any SOCKS proxy magic once we
+           connected */
+        result = connect_SOCKS(conn, sockindex, connected);
+        if(result || !*connected)
           return result;
 
-        conn->bits.tcpconnect[sockindex] = TRUE;
-
-        *connected = TRUE;
-        if(sockindex == FIRSTSOCKET)
-          Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
-        Curl_updateconninfo(conn, conn->sock[sockindex]);
-        Curl_verboseconnect(conn);
+        post_SOCKS(conn, sockindex, connected);
 
         return CURLE_OK;
       }
@@ -1007,8 +1031,6 @@ static void tcpnodelay(struct connectdata *conn, 
curl_socket_t sockfd)
                 sizeof(onoff)) < 0)
     infof(data, "Could not set TCP_NODELAY: %s\n",
           Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
-  else
-    infof(data, "TCP_NODELAY set\n");
 #else
   (void)conn;
   (void)sockfd;
@@ -1216,8 +1238,6 @@ static CURLcode singleipconnect(struct connectdata *conn,
       if(setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
                     (void *)&optval, sizeof(optval)) < 0)
         infof(data, "Failed to enable TCP Fast Open on fd %d\n", sockfd);
-      else
-        infof(data, "TCP_FASTOPEN_CONNECT set\n");
 
       rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
 #elif defined(MSG_FASTOPEN) /* old Linux */
@@ -1428,12 +1448,11 @@ int Curl_closesocket(struct connectdata *conn,
                       curl_socket_t sock)
 {
   if(conn && conn->fclosesocket) {
-    if((sock == conn->sock[SECONDARYSOCKET]) &&
-       conn->sock_accepted[SECONDARYSOCKET])
+    if((sock == conn->sock[SECONDARYSOCKET]) && conn->sock_accepted)
       /* if this socket matches the second socket, and that was created with
          accept, then we MUST NOT call the callback but clear the accepted
          status */
-      conn->sock_accepted[SECONDARYSOCKET] = FALSE;
+      conn->sock_accepted = FALSE;
     else {
       int rc;
       Curl_multi_closed(conn->data, sock);
diff --git a/lib/cookie.c b/lib/cookie.c
index 0091132aa..68054e1c4 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -97,6 +97,8 @@ Example set of cookies:
 #include "curl_memrchr.h"
 #include "inet_pton.h"
 #include "parsedate.h"
+#include "rand.h"
+#include "rename.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -243,18 +245,17 @@ pathmatched:
  */
 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;
 
-  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)
@@ -537,9 +538,9 @@ Curl_cookie_add(struct Curl_easy *data,
          * only test for names where that can possibly be true.
          */
         if(nlen > 3 && name[0] == '_' && name[1] == '_') {
-          if(strncasecompare("__Secure-", name, 9))
+          if(!strncmp("__Secure-", name, 9))
             co->prefix |= COOKIE_PREFIX__SECURE;
-          else if(strncasecompare("__Host-", name, 7))
+          else if(!strncmp("__Host-", name, 7))
             co->prefix |= COOKIE_PREFIX__HOST;
         }
 
@@ -1046,7 +1047,7 @@ Curl_cookie_add(struct Curl_easy *data,
 
         *clist = *co;  /* then store all the new data */
 
-        free(co);   /* free the newly alloced memory */
+        free(co);   /* free the newly allocated memory */
         co = clist; /* point to the previous struct instead */
 
         /* We have replaced a cookie, now skip the rest of the list but
@@ -1501,11 +1502,14 @@ static char *get_netscape_format(const struct Cookie 
*co)
  *
  * The function returns non-zero on write failure.
  */
-static int cookie_output(struct CookieInfo *c, const char *dumphere)
+static int cookie_output(struct Curl_easy *data,
+                         struct CookieInfo *c, const char *filename)
 {
   struct Cookie *co;
-  FILE *out;
+  FILE *out = NULL;
   bool use_stdout = FALSE;
+  char *tempstore = NULL;
+  bool error = false;
 
   if(!c)
     /* no cookie engine alive */
@@ -1514,16 +1518,24 @@ static int cookie_output(struct CookieInfo *c, const 
char *dumphere)
   /* at first, remove expired cookies */
   remove_expired(c);
 
-  if(!strcmp("-", dumphere)) {
+  if(!strcmp("-", filename)) {
     /* use stdout */
     out = stdout;
     use_stdout = TRUE;
   }
   else {
-    out = fopen(dumphere, FOPEN_WRITETEXT);
-    if(!out) {
-      return 1; /* failure */
-    }
+    unsigned char randsuffix[9];
+
+    if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix)))
+      return 2;
+
+    tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
+    if(!tempstore)
+      return 1;
+
+    out = fopen(tempstore, FOPEN_WRITETEXT);
+    if(!out)
+      goto error;
   }
 
   fputs("# Netscape HTTP Cookie File\n"
@@ -1538,9 +1550,7 @@ static int cookie_output(struct CookieInfo *c, const char 
*dumphere)
 
     array = calloc(1, sizeof(struct Cookie *) * c->numcookies);
     if(!array) {
-      if(!use_stdout)
-        fclose(out);
-      return 1;
+      goto error;
     }
 
     /* only sort the cookies with a domain property */
@@ -1559,9 +1569,7 @@ static int cookie_output(struct CookieInfo *c, const char 
*dumphere)
       if(format_ptr == NULL) {
         fprintf(out, "#\n# Fatal libcurl error\n");
         free(array);
-        if(!use_stdout)
-          fclose(out);
-        return 1;
+        goto error;
       }
       fprintf(out, "%s\n", format_ptr);
       free(format_ptr);
@@ -1569,10 +1577,24 @@ static int cookie_output(struct CookieInfo *c, const 
char *dumphere)
 
     free(array);
   }
-  if(!use_stdout)
+
+  if(!use_stdout) {
     fclose(out);
+    out = NULL;
+    if(Curl_rename(tempstore, filename)) {
+      unlink(tempstore);
+      goto error;
+    }
+  }
 
-  return 0;
+  goto cleanup;
+error:
+  error = true;
+cleanup:
+  if(out && !use_stdout)
+    fclose(out);
+  free(tempstore);
+  return error ? 1 : 0;
 }
 
 static struct curl_slist *cookie_list(struct Curl_easy *data)
@@ -1631,7 +1653,7 @@ void Curl_flush_cookies(struct Curl_easy *data, bool 
cleanup)
     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
 
     /* if we have a destination file for all the cookies to get dumped to */
-    if(cookie_output(data->cookies, data->set.str[STRING_COOKIEJAR]))
+    if(cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR]))
       infof(data, "WARNING: failed to save cookies in %s\n",
             data->set.str[STRING_COOKIEJAR]);
   }
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index 2c3b6562d..98cdf5145 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -73,6 +73,9 @@
 #define CURL_EXTERN_SYMBOL
 #endif
 
+/* Allow SMB to work on Windows */
+#cmakedefine USE_WIN32_CRYPTO
+
 /* Use Windows LDAP implementation */
 #cmakedefine USE_WIN32_LDAP 1
 
@@ -452,9 +455,6 @@
 /* Define to 1 if you have the <openssl/crypto.h> header file. */
 #cmakedefine HAVE_OPENSSL_CRYPTO_H 1
 
-/* Define to 1 if you have the <openssl/engine.h> header file. */
-#cmakedefine HAVE_OPENSSL_ENGINE_H 1
-
 /* Define to 1 if you have the <openssl/err.h> header file. */
 #cmakedefine HAVE_OPENSSL_ERR_H 1
 
@@ -936,9 +936,6 @@ ${SIZEOF_TIME_T_CODE}
 /* if GnuTLS is enabled */
 #cmakedefine USE_GNUTLS 1
 
-/* if PolarSSL is enabled */
-#cmakedefine USE_POLARSSL 1
-
 /* if Secure Transport is enabled */
 #cmakedefine USE_SECTRANSP 1
 
diff --git a/lib/curl_hmac.h b/lib/curl_hmac.h
index 756dc9e4c..3ff799bbd 100644
--- a/lib/curl_hmac.h
+++ b/lib/curl_hmac.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -24,6 +24,8 @@
 
 #ifndef CURL_DISABLE_CRYPTO_AUTH
 
+#define HMAC_MD5_LENGTH 16
+
 typedef void    (* HMAC_hinit_func)(void *context);
 typedef void    (* HMAC_hupdate_func)(void *context,
                                       const unsigned char *data,
@@ -62,6 +64,11 @@ int Curl_HMAC_update(HMAC_context *context,
                      unsigned int len);
 int Curl_HMAC_final(HMAC_context *context, unsigned char *result);
 
+CURLcode Curl_hmacit(const HMAC_params *hashparams,
+                     const unsigned char *key, const size_t keylen,
+                     const unsigned char *data, const size_t datalen,
+                     unsigned char *output);
+
 #endif
 
 #endif /* HEADER_CURL_HMAC_H */
diff --git a/lib/curl_md4.h b/lib/curl_md4.h
index 82df708ce..c7bb20981 100644
--- a/lib/curl_md4.h
+++ b/lib/curl_md4.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -28,7 +28,8 @@
 
 #define MD4_DIGEST_LENGTH 16
 
-void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len);
+void Curl_md4it(unsigned char *output, const unsigned char *input,
+                const size_t len);
 
 #endif /* !defined(CURL_DISABLE_CRYPTO_AUTH) */
 
diff --git a/lib/curl_md5.h b/lib/curl_md5.h
index aaf25f61b..dd464416a 100644
--- a/lib/curl_md5.h
+++ b/lib/curl_md5.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -49,8 +49,8 @@ typedef struct {
 extern const MD5_params Curl_DIGEST_MD5[1];
 extern const 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);
 
 MD5_context * Curl_MD5_init(const MD5_params *md5params);
 CURLcode Curl_MD5_update(MD5_context *context,
diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c
index 19f9b61d8..f9b823b4f 100644
--- a/lib/curl_ntlm_core.c
+++ b/lib/curl_ntlm_core.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -120,7 +120,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#define NTLM_HMAC_MD5_LEN     (16)
 #define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00"
 #define NTLMv2_BLOB_LEN       (44 -16 + ntlm->target_info_len + 4)
 
@@ -567,25 +566,6 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
 
 #if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI)
 
-/* This returns the HMAC MD5 digest */
-static CURLcode hmac_md5(const unsigned char *key, unsigned int keylen,
-                         const unsigned char *data, unsigned int datalen,
-                         unsigned char *output)
-{
-  HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen);
-
-  if(!ctxt)
-    return CURLE_OUT_OF_MEMORY;
-
-  /* Update the digest with the given challenge */
-  Curl_HMAC_update(ctxt, data, datalen);
-
-  /* Finalise the digest */
-  Curl_HMAC_final(ctxt, output);
-
-  return CURLE_OK;
-}
-
 /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
  * (uppercase UserName + Domain) as the data
  */
@@ -615,8 +595,8 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, 
size_t userlen,
   ascii_uppercase_to_unicode_le(identity, user, userlen);
   ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
 
-  result = hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len),
-                    ntlmv2hash);
+  result = Curl_hmacit(Curl_HMAC_MD5, ntlmhash, 16, identity, identity_len,
+                       ntlmv2hash);
   free(identity);
 
   return result;
@@ -662,7 +642,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char 
*ntlmv2hash,
 
   unsigned int len = 0;
   unsigned char *ptr = NULL;
-  unsigned char hmac_output[NTLM_HMAC_MD5_LEN];
+  unsigned char hmac_output[HMAC_MD5_LENGTH];
   curl_off_t tw;
 
   CURLcode result = CURLE_OK;
@@ -681,7 +661,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char 
*ntlmv2hash,
     tw = ((curl_off_t)time(NULL) + CURL_OFF_T_C(11644473600)) * 10000000;
 
   /* Calculate the response len */
-  len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN;
+  len = HMAC_MD5_LENGTH + NTLMv2_BLOB_LEN;
 
   /* Allocate the response */
   ptr = calloc(1, len);
@@ -689,7 +669,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char 
*ntlmv2hash,
     return CURLE_OUT_OF_MEMORY;
 
   /* Create the BLOB structure */
-  msnprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
+  msnprintf((char *)ptr + HMAC_MD5_LENGTH, NTLMv2_BLOB_LEN,
             "%c%c%c%c"   /* NTLMv2_BLOB_SIGNATURE */
             "%c%c%c%c",  /* Reserved = 0 */
             NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1],
@@ -702,7 +682,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char 
*ntlmv2hash,
 
   /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
   memcpy(ptr + 8, &ntlm->nonce[0], 8);
-  result = hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8,
+  result = Curl_hmacit(Curl_HMAC_MD5, ntlmv2hash, HMAC_MD5_LENGTH, ptr + 8,
                     NTLMv2_BLOB_LEN + 8, hmac_output);
   if(result) {
     free(ptr);
@@ -710,7 +690,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char 
*ntlmv2hash,
   }
 
   /* Concatenate the HMAC MD5 output  with the BLOB */
-  memcpy(ptr, hmac_output, NTLM_HMAC_MD5_LEN);
+  memcpy(ptr, hmac_output, HMAC_MD5_LENGTH);
 
   /* Return the response */
   *ntresp = ptr;
@@ -745,7 +725,8 @@ CURLcode  Curl_ntlm_core_mk_lmv2_resp(unsigned char 
*ntlmv2hash,
   memcpy(&data[0], challenge_server, 8);
   memcpy(&data[8], challenge_client, 8);
 
-  result = hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output);
+  result = Curl_hmacit(Curl_HMAC_MD5, ntlmv2hash, 16, &data[0], 16,
+                       hmac_output);
   if(result)
     return result;
 
diff --git a/lib/curl_ntlm_core.h b/lib/curl_ntlm_core.h
index 392a1b81d..e1643d627 100644
--- a/lib/curl_ntlm_core.h
+++ b/lib/curl_ntlm_core.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -46,11 +46,9 @@
 #define USE_NTRESPONSES
 
 /* Define USE_NTLM2SESSION in order to make the type-3 message include the
-   NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a
-   Crypto engine that we have curl_ssl_md5sum() for. */
-#if defined(USE_NTRESPONSES) && \
-  (!defined(USE_WIN32_CRYPTO) || \
-  (defined(USE_SSL) && !defined(CURL_DISABLE_CRYPTO_AUTH)))
+   NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and
+   MD5 support */
+#if defined(USE_NTRESPONSES) && !defined(CURL_DISABLE_CRYPTO_AUTH)
 #define USE_NTLM2SESSION
 #endif
 
diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c
index 30b54de44..f820b842e 100644
--- a/lib/curl_ntlm_wb.c
+++ b/lib/curl_ntlm_wb.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -76,22 +76,22 @@
 #  define sclose_nolog(x)  close((x))
 #endif
 
-void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn)
+static void ntlm_wb_cleanup(struct ntlmdata *ntlm)
 {
-  if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
-    sclose(conn->ntlm_auth_hlpr_socket);
-    conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
+  if(ntlm->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) {
+    sclose(ntlm->ntlm_auth_hlpr_socket);
+    ntlm->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
   }
 
-  if(conn->ntlm_auth_hlpr_pid) {
+  if(ntlm->ntlm_auth_hlpr_pid) {
     int i;
     for(i = 0; i < 4; i++) {
-      pid_t ret = waitpid(conn->ntlm_auth_hlpr_pid, NULL, WNOHANG);
-      if(ret == conn->ntlm_auth_hlpr_pid || errno == ECHILD)
+      pid_t ret = waitpid(ntlm->ntlm_auth_hlpr_pid, NULL, WNOHANG);
+      if(ret == ntlm->ntlm_auth_hlpr_pid || errno == ECHILD)
         break;
       switch(i) {
       case 0:
-        kill(conn->ntlm_auth_hlpr_pid, SIGTERM);
+        kill(ntlm->ntlm_auth_hlpr_pid, SIGTERM);
         break;
       case 1:
         /* Give the process another moment to shut down cleanly before
@@ -99,20 +99,21 @@ void Curl_http_auth_cleanup_ntlm_wb(struct connectdata 
*conn)
         Curl_wait_ms(1);
         break;
       case 2:
-        kill(conn->ntlm_auth_hlpr_pid, SIGKILL);
+        kill(ntlm->ntlm_auth_hlpr_pid, SIGKILL);
         break;
       case 3:
         break;
       }
     }
-    conn->ntlm_auth_hlpr_pid = 0;
+    ntlm->ntlm_auth_hlpr_pid = 0;
   }
 
-  Curl_safefree(conn->challenge_header);
-  Curl_safefree(conn->response_header);
+  Curl_safefree(ntlm->challenge);
+  Curl_safefree(ntlm->response);
 }
 
-static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
+static CURLcode ntlm_wb_init(struct Curl_easy *data, struct ntlmdata *ntlm,
+                             const char *userp)
 {
   curl_socket_t sockfds[2];
   pid_t child_pid;
@@ -126,9 +127,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, 
const char *userp)
 #endif
   char buffer[STRERROR_LEN];
 
+#if defined(CURL_DISABLE_VERBOSE_STRINGS)
+  (void) data;
+#endif
+
   /* Return if communication with ntlm_auth already set up */
-  if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
-     conn->ntlm_auth_hlpr_pid)
+  if(ntlm->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
+     ntlm->ntlm_auth_hlpr_pid)
     return CURLE_OK;
 
   username = userp;
@@ -179,13 +184,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, 
const char *userp)
     ntlm_auth = NTLM_WB_FILE;
 
   if(access(ntlm_auth, X_OK) != 0) {
-    failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s",
+    failf(data, "Could not access ntlm_auth: %s errno %d: %s",
           ntlm_auth, errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     goto done;
   }
 
-  if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
-    failf(conn->data, "Could not open socket pair. errno %d: %s",
+  if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
+    failf(data, "Could not open socket pair. errno %d: %s",
           errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     goto done;
   }
@@ -194,7 +199,7 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, 
const char *userp)
   if(child_pid == -1) {
     sclose(sockfds[0]);
     sclose(sockfds[1]);
-    failf(conn->data, "Could not fork. errno %d: %s",
+    failf(data, "Could not fork. errno %d: %s",
           errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     goto done;
   }
@@ -206,13 +211,13 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, 
const char *userp)
     /* Don't use sclose in the child since it fools the socket leak detector */
     sclose_nolog(sockfds[0]);
     if(dup2(sockfds[1], STDIN_FILENO) == -1) {
-      failf(conn->data, "Could not redirect child stdin. errno %d: %s",
+      failf(data, "Could not redirect child stdin. errno %d: %s",
             errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       exit(1);
     }
 
     if(dup2(sockfds[1], STDOUT_FILENO) == -1) {
-      failf(conn->data, "Could not redirect child stdout. errno %d: %s",
+      failf(data, "Could not redirect child stdout. errno %d: %s",
             errno, Curl_strerror(errno, buffer, sizeof(buffer)));
       exit(1);
     }
@@ -232,14 +237,14 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, 
const char *userp)
             NULL);
 
     sclose_nolog(sockfds[1]);
-    failf(conn->data, "Could not execl(). errno %d: %s",
+    failf(data, "Could not execl(). errno %d: %s",
           errno, Curl_strerror(errno, buffer, sizeof(buffer)));
     exit(1);
   }
 
   sclose(sockfds[1]);
-  conn->ntlm_auth_hlpr_socket = sockfds[0];
-  conn->ntlm_auth_hlpr_pid = child_pid;
+  ntlm->ntlm_auth_hlpr_socket = sockfds[0];
+  ntlm->ntlm_auth_hlpr_pid = child_pid;
   free(domain);
   free(ntlm_auth_alloc);
   return CURLE_OK;
@@ -253,17 +258,21 @@ done:
 /* if larger than this, something is seriously wrong */
 #define MAX_NTLM_WB_RESPONSE 100000
 
-static CURLcode ntlm_wb_response(struct connectdata *conn,
+static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
                                  const char *input, curlntlm state)
 {
   char *buf = malloc(NTLM_BUFSIZE);
   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;
 
   while(len_in > 0) {
-    ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in);
+    ssize_t written = swrite(ntlm->ntlm_auth_hlpr_socket, input, len_in);
     if(written == -1) {
       /* Interrupted by a signal, retry it */
       if(errno == EINTR)
@@ -279,7 +288,7 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
     ssize_t size;
     char *newbuf;
 
-    size = sread(conn->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE);
+    size = sread(ntlm->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE);
     if(size == -1) {
       if(errno == EINTR)
         continue;
@@ -295,7 +304,7 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
     }
 
     if(len_out > MAX_NTLM_WB_RESPONSE) {
-      failf(conn->data, "too large ntlm_wb response!");
+      failf(data, "too large ntlm_wb response!");
       free(buf);
       return CURLE_OUT_OF_MEMORY;
     }
@@ -323,9 +332,9 @@ static CURLcode ntlm_wb_response(struct connectdata *conn,
      (buf[0]!='A' || buf[1]!='F' || buf[2]!=' '))
     goto done;
 
-  conn->response_header = aprintf("NTLM %.*s", len_out - 4, buf + 3);
+  ntlm->response = aprintf("%.*s", len_out - 4, buf + 3);
   free(buf);
-  if(!conn->response_header)
+  if(!ntlm->response)
     return CURLE_OUT_OF_MEMORY;
   return CURLE_OK;
 done:
@@ -337,6 +346,7 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
                             bool proxy,
                             const char *header)
 {
+  struct ntlmdata *ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
   curlntlm *state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
 
   if(!checkprefix("NTLM", header))
@@ -347,8 +357,8 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
     header++;
 
   if(*header) {
-    conn->challenge_header = strdup(header);
-    if(!conn->challenge_header)
+    ntlm->challenge = strdup(header);
+    if(!ntlm->challenge)
       return CURLE_OUT_OF_MEMORY;
 
     *state = NTLMSTATE_TYPE2; /* We got a type-2 message */
@@ -387,6 +397,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   char **allocuserpwd;
   /* point to the name and password for this */
   const char *userp;
+  struct ntlmdata *ntlm;
   curlntlm *state;
   struct auth *authp;
 
@@ -398,12 +409,14 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   if(proxy) {
     allocuserpwd = &conn->allocptr.proxyuserpwd;
     userp = conn->http_proxy.user;
+    ntlm = &conn->proxyntlm;
     state = &conn->proxy_ntlm_state;
     authp = &conn->data->state.authproxy;
   }
   else {
     allocuserpwd = &conn->allocptr.userpwd;
     userp = conn->user;
+    ntlm = &conn->ntlm;
     state = &conn->http_ntlm_state;
     authp = &conn->data->state.authhost;
   }
@@ -429,36 +442,36 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
      * request handling process.
      */
     /* Create communication with ntlm_auth */
-    res = ntlm_wb_init(conn, userp);
+    res = ntlm_wb_init(conn->data, ntlm, userp);
     if(res)
       return res;
-    res = ntlm_wb_response(conn, "YR\n", *state);
+    res = ntlm_wb_response(conn->data, ntlm, "YR\n", *state);
     if(res)
       return res;
 
     free(*allocuserpwd);
-    *allocuserpwd = aprintf("%sAuthorization: %s\r\n",
+    *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
                             proxy ? "Proxy-" : "",
-                            conn->response_header);
+                            ntlm->response);
     DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
-    Curl_safefree(conn->response_header);
+    Curl_safefree(ntlm->response);
     if(!*allocuserpwd)
       return CURLE_OUT_OF_MEMORY;
     break;
 
   case NTLMSTATE_TYPE2: {
-    char *input = aprintf("TT %s\n", conn->challenge_header);
+    char *input = aprintf("TT %s\n", ntlm->challenge);
     if(!input)
       return CURLE_OUT_OF_MEMORY;
-    res = ntlm_wb_response(conn, input, *state);
+    res = ntlm_wb_response(conn->data, ntlm, input, *state);
     free(input);
     if(res)
       return res;
 
     free(*allocuserpwd);
-    *allocuserpwd = aprintf("%sAuthorization: %s\r\n",
+    *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
                             proxy ? "Proxy-" : "",
-                            conn->response_header);
+                            ntlm->response);
     DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
     *state = NTLMSTATE_TYPE3; /* we sent a type-3 */
     authp->done = TRUE;
@@ -481,4 +494,10 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
   return CURLE_OK;
 }
 
+void Curl_http_auth_cleanup_ntlm_wb(struct connectdata *conn)
+{
+  ntlm_wb_cleanup(&conn->ntlm);
+  ntlm_wb_cleanup(&conn->proxyntlm);
+}
+
 #endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index 30ee45438..f6d7ae007 100644
--- a/lib/curl_sasl.c
+++ b/lib/curl_sasl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2012 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -272,6 +272,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct 
connectdata *conn,
     data->set.str[STRING_SERVICE_NAME] :
     sasl->params->service;
 #endif
+  const char *oauth_bearer = data->set.str[STRING_BEARER];
 
   sasl->force_ir = force_ir;    /* Latch for future use */
   sasl->authused = 0;           /* No mechanism used yet */
@@ -341,7 +342,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct 
connectdata *conn,
       }
     else
 #endif
-    if((enabledmechs & SASL_MECH_OAUTHBEARER) && conn->oauth_bearer) {
+    if((enabledmechs & SASL_MECH_OAUTHBEARER) && oauth_bearer) {
       mech = SASL_MECH_STRING_OAUTHBEARER;
       state1 = SASL_OAUTH2;
       state2 = SASL_OAUTH2_RESP;
@@ -351,17 +352,17 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct 
connectdata *conn,
         result = Curl_auth_create_oauth_bearer_message(data, conn->user,
                                                        hostname,
                                                        port,
-                                                       conn->oauth_bearer,
+                                                       oauth_bearer,
                                                        &resp, &len);
     }
-    else if((enabledmechs & SASL_MECH_XOAUTH2) && conn->oauth_bearer) {
+    else if((enabledmechs & SASL_MECH_XOAUTH2) && oauth_bearer) {
       mech = SASL_MECH_STRING_XOAUTH2;
       state1 = SASL_OAUTH2;
       sasl->authused = SASL_MECH_XOAUTH2;
 
       if(force_ir || data->set.sasl_ir)
         result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
-                                                        conn->oauth_bearer,
+                                                        oauth_bearer,
                                                         &resp, &len);
     }
     else if(enabledmechs & SASL_MECH_PLAIN) {
@@ -431,6 +432,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct 
connectdata *conn,
   char *serverdata;
 #endif
   size_t len = 0;
+  const char *oauth_bearer = data->set.str[STRING_BEARER];
 
   *progress = SASL_INPROGRESS;
 
@@ -558,7 +560,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct 
connectdata *conn,
       result = Curl_auth_create_oauth_bearer_message(data, conn->user,
                                                      hostname,
                                                      port,
-                                                     conn->oauth_bearer,
+                                                     oauth_bearer,
                                                      &resp, &len);
 
       /* Failures maybe sent by the server as continuations for OAUTHBEARER */
@@ -566,7 +568,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct 
connectdata *conn,
     }
     else
       result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
-                                                      conn->oauth_bearer,
+                                                      oauth_bearer,
                                                       &resp, &len);
     break;
 
diff --git a/lib/curl_sha256.h b/lib/curl_sha256.h
index 14b6414ea..35d286ceb 100644
--- a/lib/curl_sha256.h
+++ b/lib/curl_sha256.h
@@ -7,7 +7,8 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Florin Petriuc, <address@hidden>
+ * Copyright (C) 2017, Florin Petriuc, <address@hidden>
+ * Copyright (C) 2018 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -24,8 +25,10 @@
 
 #ifndef CURL_DISABLE_CRYPTO_AUTH
 
-void Curl_sha256it(unsigned char *outbuffer,
-                const unsigned char *input);
+#define SHA256_DIGEST_LENGTH 32
+
+void Curl_sha256it(unsigned char *outbuffer, const unsigned char *input,
+                   const size_t len);
 
 #endif
 
diff --git a/lib/doh.c b/lib/doh.c
index 7f4eee5d8..aaa8f15ca 100644
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2018 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2018 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -548,7 +548,7 @@ static DOHcode store_cname(unsigned char *doh,
       if((index + 1) >= dohlen)
         return DOH_DNS_OUT_OF_RANGE;
 
-      /* move to the the new index */
+      /* move to the new index */
       newpos = (length & 0x3f) << 8 | doh[index + 1];
       index = newpos;
       continue;
diff --git a/lib/easy.c b/lib/easy.c
index d281be6dd..762669179 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -76,14 +76,13 @@
 #include "setopt.h"
 #include "http_digest.h"
 #include "system_win32.h"
+#include "http2.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "memdebug.h"
 
-void Curl_version_init(void);
-
 /* true globals -- for curl_global_init() and curl_global_cleanup() */
 static unsigned int  initialized;
 static long          init_flags;
@@ -185,21 +184,21 @@ static CURLcode global_init(long flags, bool memoryfuncs)
     goto fail;
   }
 
-  (void)Curl_ipv6works();
-
 #if defined(USE_SSH)
   if(Curl_ssh_init()) {
     goto fail;
   }
 #endif
 
-  if(flags & CURL_GLOBAL_ACK_EINTR)
-    Curl_ack_eintr = 1;
+#ifdef USE_WOLFSSH
+  if(WS_SUCCESS != wolfSSH_Init()) {
+    DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n"));
+    return CURLE_FAILED_INIT;
+  }
+#endif
 
   init_flags = flags;
 
-  Curl_version_init();
-
   return CURLE_OK;
 
   fail:
@@ -272,6 +271,10 @@ void curl_global_cleanup(void)
 
   Curl_ssh_cleanup();
 
+#ifdef USE_WOLFSSH
+  (void)wolfSSH_Cleanup();
+#endif
+
   init_flags  = 0;
 }
 
@@ -684,10 +687,6 @@ static CURLcode easy_perform(struct Curl_easy *data, bool 
events)
 
   sigpipe_ignore(data, &pipe_st);
 
-  /* assign this after curl_multi_add_handle() since that function checks for
-     it and rejects this handle otherwise */
-  data->multi = multi;
-
   /* run the transfer */
   result = events ? easy_events(multi) : easy_transfer(multi);
 
@@ -884,6 +883,17 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy 
*data)
                              data->state.resolver))
     goto fail;
 
+#ifdef USE_ARES
+  if(Curl_set_dns_servers(outcurl, data->set.str[STRING_DNS_SERVERS]))
+    goto fail;
+  if(Curl_set_dns_interface(outcurl, data->set.str[STRING_DNS_INTERFACE]))
+    goto fail;
+  if(Curl_set_dns_local_ip4(outcurl, data->set.str[STRING_DNS_LOCAL_IP4]))
+    goto fail;
+  if(Curl_set_dns_local_ip6(outcurl, data->set.str[STRING_DNS_LOCAL_IP6]))
+    goto fail;
+#endif /* USE_ARES */
+
   Curl_convert_setup(outcurl);
 
   Curl_initinfo(outcurl);
@@ -970,56 +980,81 @@ void curl_easy_reset(struct Curl_easy *data)
  */
 CURLcode curl_easy_pause(struct Curl_easy *data, int action)
 {
-  struct SingleRequest *k = &data->req;
+  struct SingleRequest *k;
   CURLcode result = CURLE_OK;
+  int oldstate;
+  int newstate;
+
+  if(!GOOD_EASY_HANDLE(data) || !data->conn)
+    /* crazy input, don't continue */
+    return CURLE_BAD_FUNCTION_ARGUMENT;
 
-  /* first switch off both pause bits */
-  int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
+  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);
 
+  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 */
   k->keepon = newstate;
 
-  if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempcount) {
-    /* there are buffers for sending that can be delivered as the receive
-       pausing is lifted! */
-    unsigned int i;
-    unsigned int count = data->state.tempcount;
-    struct tempbuf writebuf[3]; /* there can only be three */
-    struct connectdata *conn = data->conn;
-    struct Curl_easy *saved_data = NULL;
-
-    /* copy the structs to allow for immediate re-pausing */
-    for(i = 0; i < data->state.tempcount; i++) {
-      writebuf[i] = data->state.tempwrite[i];
-      data->state.tempwrite[i].buf = NULL;
-    }
-    data->state.tempcount = 0;
+  if(!(newstate & KEEP_RECV_PAUSE)) {
+    Curl_http2_stream_pause(data, FALSE);
+
+    if(data->state.tempcount) {
+      /* there are buffers for sending that can be delivered as the receive
+         pausing is lifted! */
+      unsigned int i;
+      unsigned int count = data->state.tempcount;
+      struct tempbuf writebuf[3]; /* there can only be three */
+      struct connectdata *conn = data->conn;
+      struct Curl_easy *saved_data = NULL;
+
+      /* copy the structs to allow for immediate re-pausing */
+      for(i = 0; i < data->state.tempcount; i++) {
+        writebuf[i] = data->state.tempwrite[i];
+        data->state.tempwrite[i].buf = NULL;
+      }
+      data->state.tempcount = 0;
 
-    /* set the connection's current owner */
-    if(conn->data != data) {
-      saved_data = conn->data;
-      conn->data = data;
-    }
+      /* set the connection's current owner */
+      if(conn->data != data) {
+        saved_data = conn->data;
+        conn->data = data;
+      }
 
-    for(i = 0; i < count; i++) {
-      /* even if one function returns error, this loops through and frees all
-         buffers */
-      if(!result)
-        result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf,
-                                   writebuf[i].len);
-      free(writebuf[i].buf);
-    }
+      for(i = 0; i < count; i++) {
+        /* even if one function returns error, this loops through and frees
+           all buffers */
+        if(!result)
+          result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf,
+                                     writebuf[i].len);
+        free(writebuf[i].buf);
+      }
 
-    /* recover previous owner of the connection */
-    if(saved_data)
-      conn->data = saved_data;
+      /* recover previous owner of the connection */
+      if(saved_data)
+        conn->data = saved_data;
 
-    if(result)
-      return result;
+      if(result)
+        return result;
+    }
   }
 
   /* if there's no error and we're not pausing both directions, we want
@@ -1027,6 +1062,10 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int 
action)
   if((newstate & (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
      (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) {
     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)
       Curl_update_timer(data->multi);
   }
diff --git a/lib/formdata.c b/lib/formdata.c
index ae453b1c6..7a9a650de 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -727,14 +727,10 @@ int curl_formget(struct curl_httppost *form, void *arg,
     if(!nread)
       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;
     }
   }
 
diff --git a/lib/ftp.c b/lib/ftp.c
index acdac63a2..242c2d85c 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -55,7 +55,6 @@
 #include "transfer.h"
 #include "escape.h"
 #include "http.h" /* for HTTP proxy tunnel stuff */
-#include "socks.h"
 #include "ftp.h"
 #include "fileinfo.h"
 #include "ftplistparser.h"
@@ -78,6 +77,7 @@
 #include "warnless.h"
 #include "http_proxy.h"
 #include "non-ascii.h"
+#include "socks.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -253,18 +253,6 @@ static void freedirs(struct ftp_conn *ftpc)
   Curl_safefree(ftpc->newhost);
 }
 
-/* Returns non-zero if the given string contains CR (\r) or LF (\n),
-   which are not allowed within RFC 959 <string>.
-   Note: The input string is in the client's encoding which might
-   not be ASCII, so escape sequences \r & \n must be used instead
-   of hex values 0x0d & 0x0a.
-*/
-static bool isBadFtpString(const char *string)
-{
-  return ((NULL != strchr(string, '\r')) ||
-          (NULL != strchr(string, '\n'))) ? TRUE : FALSE;
-}
-
 /***********************************************************************
  *
  * AcceptServerConnect()
@@ -303,7 +291,7 @@ static CURLcode AcceptServerConnect(struct connectdata 
*conn)
 
   conn->sock[SECONDARYSOCKET] = s;
   (void)curlx_nonblock(s, TRUE); /* enable non-blocking */
-  conn->sock_accepted[SECONDARYSOCKET] = TRUE;
+  conn->sock_accepted = TRUE;
 
   if(data->set.fsockopt) {
     int error = 0;
@@ -785,9 +773,8 @@ static void _state(struct connectdata *conn,
 static CURLcode ftp_state_user(struct connectdata *conn)
 {
   CURLcode result;
-  struct FTP *ftp = conn->data->req.protop;
   /* send USER */
-  PPSENDF(&conn->proto.ftpc.pp, "USER %s", ftp->user?ftp->user:"");
+  PPSENDF(&conn->proto.ftpc.pp, "USER %s", conn->user?conn->user:"");
 
   state(conn, FTP_USER);
   conn->data->state.ftp_trying_alternative = FALSE;
@@ -823,6 +810,9 @@ static int ftp_domore_getsock(struct connectdata *conn, 
curl_socket_t *socks)
    * handle ordinary commands.
    */
 
+  if(SOCKS_STATE(conn->cnnct.state))
+    return Curl_SOCKS_getsock(conn, socks, SECONDARYSOCKET);
+
   if(FTP_STOP == ftpc->state) {
     int bits = GETSOCK_READSOCK(0);
 
@@ -920,7 +910,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   struct Curl_easy *data = conn->data;
   curl_socket_t portsock = CURL_SOCKET_BAD;
-  char myhost[256] = "";
+  char myhost[MAX_IPADR_LEN + 1] = "";
 
   struct Curl_sockaddr_storage ss;
   Curl_addrinfo *res, *ai;
@@ -931,9 +921,8 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
 #ifdef ENABLE_IPV6
   struct sockaddr_in6 * const sa6 = (void *)sa;
 #endif
-  char tmp[1024];
   static const char mode[][5] = { "EPRT", "PORT" };
-  int rc;
+  enum resolve_t rc;
   int error;
   char *host = NULL;
   char *string_ftpport = data->set.str[STRING_FTPPORT];
@@ -1246,8 +1235,10 @@ static CURLcode ftp_state_use_port(struct connectdata 
*conn,
       break;
     }
     if(PORT == fcmd) {
+      /* large enough for [IP address],[num],[num] */
+      char target[sizeof(myhost) + 20];
       char *source = myhost;
-      char *dest = tmp;
+      char *dest = target;
 
       /* translate x.x.x.x to x,x,x,x */
       while(source && *source) {
@@ -1261,7 +1252,7 @@ static CURLcode ftp_state_use_port(struct connectdata 
*conn,
       *dest = 0;
       msnprintf(dest, 20, ",%d,%d", (int)(port>>8), (int)(port&0xff));
 
-      result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], tmp);
+      result = Curl_pp_sendf(&ftpc->pp, "%s %s", mode[fcmd], target);
       if(result) {
         failf(data, "Failure sending PORT command: %s",
               curl_easy_strerror(result));
@@ -1806,7 +1797,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata 
*conn,
   CURLcode result;
   struct Curl_easy *data = conn->data;
   struct Curl_dns_entry *addr = NULL;
-  int rc;
+  enum resolve_t rc;
   unsigned short connectport; /* the local port connect() should use! */
   char *str = &data->state.buffer[4];  /* start on the first letter */
 
@@ -2528,7 +2519,6 @@ static CURLcode ftp_state_user_resp(struct connectdata 
*conn,
 {
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
-  struct FTP *ftp = data->req.protop;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   (void)instate; /* no use for this yet */
 
@@ -2536,7 +2526,7 @@ static CURLcode ftp_state_user_resp(struct connectdata 
*conn,
   if((ftpcode == 331) && (ftpc->state == FTP_USER)) {
     /* 331 Password required for ...
        (the server requires to send the user's password too) */
-    PPSENDF(&ftpc->pp, "PASS %s", ftp->passwd?ftp->passwd:"");
+    PPSENDF(&ftpc->pp, "PASS %s", conn->passwd?conn->passwd:"");
     state(conn, FTP_PASS);
   }
   else if(ftpcode/100 == 2) {
@@ -4369,18 +4359,6 @@ static CURLcode ftp_setup_connection(struct connectdata 
*conn)
   /* get some initial data into the ftp struct */
   ftp->transfer = FTPTRANSFER_BODY;
   ftp->downloadsize = 0;
-
-  /* No need to duplicate user+password, the connectdata struct won't change
-     during a session, but we re-init them here since on subsequent inits
-     since the conn struct may have changed or been replaced.
-  */
-  ftp->user = conn->user;
-  ftp->passwd = conn->passwd;
-  if(isBadFtpString(ftp->user))
-    return CURLE_URL_MALFORMAT;
-  if(isBadFtpString(ftp->passwd))
-    return CURLE_URL_MALFORMAT;
-
   conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
 
   return CURLE_OK;
diff --git a/lib/ftp.h b/lib/ftp.h
index 2c88d568c..984347f2a 100644
--- a/lib/ftp.h
+++ b/lib/ftp.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -102,8 +102,6 @@ typedef enum {
    perhaps the Curl_easy is changed between the times the connection is
    used. */
 struct FTP {
-  char *user;    /* user name string */
-  char *passwd;  /* password string */
   char *path;    /* points to the urlpieces struct field */
   char *pathalloc; /* if non-NULL a pointer to an allocated path */
 
diff --git a/lib/getenv.c b/lib/getenv.c
index fa2abe3af..e0e5d2f4b 100644
--- a/lib/getenv.c
+++ b/lib/getenv.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -27,25 +27,48 @@
 
 #include "memdebug.h"
 
-static
-char *GetEnv(const char *variable)
+static char *GetEnv(const char *variable)
 {
 #if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
   (void)variable;
   return NULL;
-#else
-#ifdef WIN32
-  char env[4096];
-  char *temp = getenv(variable);
-  env[0] = '\0';
-  if(temp != NULL)
-    ExpandEnvironmentStringsA(temp, env, sizeof(env));
-  return (env[0] != '\0')?strdup(env):NULL;
+#elif defined(WIN32)
+  /* This uses Windows API instead of C runtime getenv() to get the environment
+     variable since some changes aren't always visible to the latter. #4774 */
+  char *buf = NULL;
+  char *tmp;
+  DWORD bufsize;
+  DWORD rc = 1;
+  const DWORD max = 32768; /* max env var size from MSCRT source */
+
+  for(;;) {
+    tmp = realloc(buf, rc);
+    if(!tmp) {
+      free(buf);
+      return NULL;
+    }
+
+    buf = tmp;
+    bufsize = rc;
+
+    /* It's possible for rc to be 0 if the variable was found but empty.
+       Since getenv doesn't make that distinction we ignore it as well. */
+    rc = GetEnvironmentVariableA(variable, buf, bufsize);
+    if(!rc || rc == bufsize || rc > max) {
+      free(buf);
+      return NULL;
+    }
+
+    /* if rc < bufsize then rc is bytes written not including null */
+    if(rc < bufsize)
+      return buf;
+
+    /* else rc is bytes needed, try again */
+  }
 #else
   char *env = getenv(variable);
   return (env && env[0])?strdup(env):NULL;
 #endif
-#endif
 }
 
 char *curl_getenv(const char *v)
diff --git a/lib/hmac.c b/lib/hmac.c
index f6a033c00..e7b582621 100644
--- a/lib/hmac.c
+++ b/lib/hmac.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -30,6 +30,7 @@
 
 #include "curl_hmac.h"
 #include "curl_memory.h"
+#include "warnless.h"
 
 /* The last #include file should be: */
 #include "memdebug.h"
@@ -129,4 +130,40 @@ int Curl_HMAC_final(HMAC_context *ctxt, unsigned char 
*result)
   return 0;
 }
 
+/*
+ * Curl_hmacit()
+ *
+ * This is used to generate a HMAC hash, for the specified input data, given
+ * the specified hash function and key.
+ *
+ * Parameters:
+ *
+ * hashparams [in]     - The hash function (Curl_HMAC_MD5).
+ * key        [in]     - The key to use.
+ * keylen     [in]     - The length of the key.
+ * data       [in]     - The data to encrypt.
+ * datalen    [in]     - The length of the data.
+ * output     [in/out] - The output buffer.
+ *
+ * Returns CURLE_OK on success.
+ */
+CURLcode Curl_hmacit(const HMAC_params *hashparams,
+                     const unsigned char *key, const size_t keylen,
+                     const unsigned char *data, const size_t datalen,
+                     unsigned char *output)
+{
+  HMAC_context *ctxt = Curl_HMAC_init(hashparams, key, curlx_uztoui(keylen));
+
+  if(!ctxt)
+    return CURLE_OUT_OF_MEMORY;
+
+  /* Update the digest with the given challenge */
+  Curl_HMAC_update(ctxt, data, curlx_uztoui(datalen));
+
+  /* Finalise the digest */
+  Curl_HMAC_final(ctxt, output);
+
+  return CURLE_OK;
+}
+
 #endif /* CURL_DISABLE_CRYPTO_AUTH */
diff --git a/lib/hostip.c b/lib/hostip.c
index b434b390a..c0feb79fb 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -59,6 +59,7 @@
 #include "strerror.h"
 #include "url.h"
 #include "inet_ntop.h"
+#include "inet_pton.h"
 #include "multiif.h"
 #include "doh.h"
 #include "warnless.h"
@@ -482,16 +483,16 @@ Curl_cache_addr(struct Curl_easy *data,
  * CURLRESOLV_PENDING  (1) = waiting for response, no pointer
  */
 
-int Curl_resolv(struct connectdata *conn,
-                const char *hostname,
-                int port,
-                bool allowDOH,
-                struct Curl_dns_entry **entry)
+enum resolve_t Curl_resolv(struct connectdata *conn,
+                           const char *hostname,
+                           int port,
+                           bool allowDOH,
+                           struct Curl_dns_entry **entry)
 {
   struct Curl_dns_entry *dns = NULL;
   struct Curl_easy *data = conn->data;
   CURLcode result;
-  int rc = CURLRESOLV_ERROR; /* default to failure */
+  enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
 
   *entry = NULL;
 
@@ -512,13 +513,11 @@ int Curl_resolv(struct connectdata *conn,
   if(!dns) {
     /* The entry was not in the cache. Resolve it to IP address */
 
-    Curl_addrinfo *addr;
+    Curl_addrinfo *addr = NULL;
     int respwait = 0;
-
-    /* Check what IP specifics the app has requested and if we can provide it.
-     * If not, bail out. */
-    if(!Curl_ipvalid(conn))
-      return CURLRESOLV_ERROR;
+#ifndef USE_RESOLVE_ON_IPS
+    struct in_addr in;
+#endif
 
     /* notify the resolver start callback */
     if(data->set.resolver_start) {
@@ -531,20 +530,43 @@ int Curl_resolv(struct connectdata *conn,
         return CURLRESOLV_ERROR;
     }
 
-    if(allowDOH && data->set.doh) {
-      addr = Curl_doh(conn, hostname, port, &respwait);
+#ifndef 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 */
+      addr = Curl_ip2addr(AF_INET, &in, hostname, port);
+#ifdef ENABLE_IPV6
+    if(!addr) {
+      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 */
+        addr = Curl_ip2addr(AF_INET6, &in6, hostname, port);
     }
-    else {
-      /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
-         non-zero value indicating that we need to wait for the response to the
-         resolve call */
-      addr = Curl_getaddrinfo(conn,
+#endif /* ENABLE_IPV6 */
+#endif /* !USE_RESOLVE_ON_IPS */
+
+    if(!addr) {
+      /* Check what IP specifics the app has requested and if we can provide
+       * it. If not, bail out. */
+      if(!Curl_ipvalid(conn))
+        return CURLRESOLV_ERROR;
+
+      if(allowDOH && data->set.doh) {
+        addr = Curl_doh(conn, hostname, port, &respwait);
+      }
+      else {
+        /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
+           non-zero value indicating that we need to wait for the response to
+           the resolve call */
+        addr = Curl_getaddrinfo(conn,
 #ifdef DEBUGBUILD
-                              (data->set.str[STRING_DEVICE]
-                               && !strcmp(data->set.str[STRING_DEVICE],
-                                          "LocalHost"))?"localhost":
+                                (data->set.str[STRING_DEVICE]
+                                 && !strcmp(data->set.str[STRING_DEVICE],
+                                            "LocalHost"))?"localhost":
 #endif
-                              hostname, port, &respwait);
+                                hostname, port, &respwait);
+      }
     }
     if(!addr) {
       if(respwait) {
@@ -620,11 +642,11 @@ RETSIGTYPE alarmfunc(int sig)
  * CURLRESOLV_PENDING  (1) = waiting for response, no pointer
  */
 
-int Curl_resolv_timeout(struct connectdata *conn,
-                        const char *hostname,
-                        int port,
-                        struct Curl_dns_entry **entry,
-                        timediff_t timeoutms)
+enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
+                                   const char *hostname,
+                                   int port,
+                                   struct Curl_dns_entry **entry,
+                                   timediff_t timeoutms)
 {
 #ifdef USE_ALARM_TIMEOUT
 #ifdef HAVE_SIGACTION
@@ -640,7 +662,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
   volatile unsigned int prev_alarm = 0;
   struct Curl_easy *data = conn->data;
 #endif /* USE_ALARM_TIMEOUT */
-  int rc;
+  enum resolve_t rc;
 
   *entry = NULL;
 
diff --git a/lib/hostip.h b/lib/hostip.h
index e0597ea96..baf1e5860 100644
--- a/lib/hostip.h
+++ b/lib/hostip.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -79,26 +79,29 @@ struct Curl_dns_entry {
  * use, or we'll leak memory!
  */
 /* return codes */
-#define CURLRESOLV_TIMEDOUT -2
-#define CURLRESOLV_ERROR    -1
-#define CURLRESOLV_RESOLVED  0
-#define CURLRESOLV_PENDING   1
-int Curl_resolv(struct connectdata *conn,
-                const char *hostname,
-                int port,
-                bool allowDOH,
-                struct Curl_dns_entry **dnsentry);
-int Curl_resolv_timeout(struct connectdata *conn, const char *hostname,
-                        int port, struct Curl_dns_entry **dnsentry,
-                        timediff_t timeoutms);
+enum resolve_t {
+  CURLRESOLV_TIMEDOUT = -2,
+  CURLRESOLV_ERROR    = -1,
+  CURLRESOLV_RESOLVED =  0,
+  CURLRESOLV_PENDING  =  1
+};
+enum resolve_t Curl_resolv(struct connectdata *conn,
+                           const char *hostname,
+                           int port,
+                           bool allowDOH,
+                           struct Curl_dns_entry **dnsentry);
+enum resolve_t Curl_resolv_timeout(struct connectdata *conn,
+                                   const char *hostname, int port,
+                                   struct Curl_dns_entry **dnsentry,
+                                   timediff_t timeoutms);
 
 #ifdef CURLRES_IPV6
 /*
  * Curl_ipv6works() returns TRUE if IPv6 seems to work.
  */
-bool Curl_ipv6works(void);
+bool Curl_ipv6works(struct connectdata *conn);
 #else
-#define Curl_ipv6works() FALSE
+#define Curl_ipv6works(x) FALSE
 #endif
 
 /*
diff --git a/lib/hostip4.c b/lib/hostip4.c
index 2636851e6..d5009a3ef 100644
--- a/lib/hostip4.c
+++ b/lib/hostip4.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -52,7 +52,6 @@
 #include "share.h"
 #include "strerror.h"
 #include "url.h"
-#include "inet_pton.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -128,38 +127,22 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
 #endif
   Curl_addrinfo *ai = NULL;
   struct hostent *h = NULL;
-  struct in_addr in;
   struct hostent *buf = NULL;
 
-#ifdef ENABLE_IPV6
-  {
-    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 */
-      return Curl_ip2addr(AF_INET6, &in6, hostname, port);
-  }
-#endif /* ENABLE_IPV6 */
-
-  if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
-    /* This is a dotted IP address 123.123.123.123-style */
-    return Curl_ip2addr(AF_INET, &in, hostname, port);
-
 #if defined(HAVE_GETADDRINFO_THREADSAFE)
-  else {
-    struct addrinfo hints;
-    char sbuf[12];
-    char *sbufptr = NULL;
-
-    memset(&hints, 0, sizeof(hints));
-    hints.ai_family = PF_INET;
-    hints.ai_socktype = SOCK_STREAM;
-    if(port) {
-      msnprintf(sbuf, sizeof(sbuf), "%d", port);
-      sbufptr = sbuf;
-    }
+  struct addrinfo hints;
+  char sbuf[12];
+  char *sbufptr = NULL;
+
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = PF_INET;
+  hints.ai_socktype = SOCK_STREAM;
+  if(port) {
+    msnprintf(sbuf, sizeof(sbuf), "%d", port);
+    sbufptr = sbuf;
+  }
 
-    (void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai);
+  (void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai);
 
 #elif defined(HAVE_GETHOSTBYNAME_R)
   /*
@@ -167,144 +150,141 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
    * Since there are three different versions of it, the following code is
    * somewhat #ifdef-ridden.
    */
-  else {
-    int h_errnop;
-
-    buf = calloc(1, CURL_HOSTENT_SIZE);
-    if(!buf)
-      return NULL; /* major failure */
-    /*
-     * The clearing of the buffer is a workaround for a gethostbyname_r bug in
-     * qnx nto and it is also _required_ for some of these functions on some
-     * platforms.
-     */
+  int h_errnop;
+
+  buf = calloc(1, CURL_HOSTENT_SIZE);
+  if(!buf)
+    return NULL; /* major failure */
+  /*
+   * The clearing of the buffer is a workaround for a gethostbyname_r bug in
+   * qnx nto and it is also _required_ for some of these functions on some
+   * platforms.
+   */
 
 #if defined(HAVE_GETHOSTBYNAME_R_5)
-    /* Solaris, IRIX and more */
-    h = gethostbyname_r(hostname,
-                        (struct hostent *)buf,
-                        (char *)buf + sizeof(struct hostent),
-                        CURL_HOSTENT_SIZE - sizeof(struct hostent),
-                        &h_errnop);
-
-    /* If the buffer is too small, it returns NULL and sets errno to
-     * ERANGE. The errno is thread safe if this is compiled with
-     * -D_REENTRANT as then the 'errno' variable is a macro defined to get
-     * used properly for threads.
-     */
+  /* Solaris, IRIX and more */
+  h = gethostbyname_r(hostname,
+                      (struct hostent *)buf,
+                      (char *)buf + sizeof(struct hostent),
+                      CURL_HOSTENT_SIZE - sizeof(struct hostent),
+                      &h_errnop);
+
+  /* If the buffer is too small, it returns NULL and sets errno to
+   * ERANGE. The errno is thread safe if this is compiled with
+   * -D_REENTRANT as then the 'errno' variable is a macro defined to get
+   * used properly for threads.
+   */
 
-    if(h) {
-      ;
-    }
-    else
+  if(h) {
+    ;
+  }
+  else
 #elif defined(HAVE_GETHOSTBYNAME_R_6)
-    /* Linux */
-
-    (void)gethostbyname_r(hostname,
-                        (struct hostent *)buf,
-                        (char *)buf + sizeof(struct hostent),
-                        CURL_HOSTENT_SIZE - sizeof(struct hostent),
-                        &h, /* DIFFERENCE */
-                        &h_errnop);
-    /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a
-     * sudden this function returns EAGAIN if the given buffer size is too
-     * small. Previous versions are known to return ERANGE for the same
-     * problem.
-     *
-     * This wouldn't be such a big problem if older versions wouldn't
-     * sometimes return EAGAIN on a common failure case. Alas, we can't
-     * assume that EAGAIN *or* ERANGE means ERANGE for any given version of
-     * glibc.
-     *
-     * For now, we do that and thus we may call the function repeatedly and
-     * fail for older glibc versions that return EAGAIN, until we run out of
-     * buffer size (step_size grows beyond CURL_HOSTENT_SIZE).
-     *
-     * If anyone has a better fix, please tell us!
-     *
-     * -------------------------------------------------------------------
-     *
-     * On October 23rd 2003, Dan C dug up more details on the mysteries of
-     * gethostbyname_r() in glibc:
-     *
-     * In glibc 2.2.5 the interface is different (this has also been
-     * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't
-     * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32
-     * (shipped/upgraded by Redhat 7.2) don't show this behavior!
-     *
-     * In this "buggy" version, the return code is -1 on error and 'errno'
-     * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a
-     * thread-safe variable.
-     */
+  /* Linux */
+
+  (void)gethostbyname_r(hostname,
+                      (struct hostent *)buf,
+                      (char *)buf + sizeof(struct hostent),
+                      CURL_HOSTENT_SIZE - sizeof(struct hostent),
+                      &h, /* DIFFERENCE */
+                      &h_errnop);
+  /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a
+   * sudden this function returns EAGAIN if the given buffer size is too
+   * small. Previous versions are known to return ERANGE for the same
+   * problem.
+   *
+   * This wouldn't be such a big problem if older versions wouldn't
+   * sometimes return EAGAIN on a common failure case. Alas, we can't
+   * assume that EAGAIN *or* ERANGE means ERANGE for any given version of
+   * glibc.
+   *
+   * For now, we do that and thus we may call the function repeatedly and
+   * fail for older glibc versions that return EAGAIN, until we run out of
+   * buffer size (step_size grows beyond CURL_HOSTENT_SIZE).
+   *
+   * If anyone has a better fix, please tell us!
+   *
+   * -------------------------------------------------------------------
+   *
+   * On October 23rd 2003, Dan C dug up more details on the mysteries of
+   * gethostbyname_r() in glibc:
+   *
+   * In glibc 2.2.5 the interface is different (this has also been
+   * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't
+   * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32
+   * (shipped/upgraded by Redhat 7.2) don't show this behavior!
+   *
+   * In this "buggy" version, the return code is -1 on error and 'errno'
+   * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a
+   * thread-safe variable.
+   */
 
-    if(!h) /* failure */
+  if(!h) /* failure */
 #elif defined(HAVE_GETHOSTBYNAME_R_3)
-    /* AIX, Digital Unix/Tru64, HPUX 10, more? */
-
-    /* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of
-     * the plain fact that it does not return unique full buffers on each
-     * call, but instead several of the pointers in the hostent structs will
-     * point to the same actual data! This have the unfortunate down-side that
-     * our caching system breaks down horribly. Luckily for us though, AIX 4.3
-     * and more recent versions have a "completely thread-safe"[*] libc where
-     * all the data is stored in thread-specific memory areas making calls to
-     * the plain old gethostbyname() work fine even for multi-threaded
-     * programs.
-     *
-     * This AIX 4.3 or later detection is all made in the configure script.
-     *
-     * Troels Walsted Hansen helped us work this out on March 3rd, 2003.
-     *
-     * [*] = much later we've found out that it isn't at all "completely
-     * thread-safe", but at least the gethostbyname() function is.
+  /* AIX, Digital Unix/Tru64, HPUX 10, more? */
+
+  /* For AIX 4.3 or later, we don't use gethostbyname_r() at all, because of
+   * the plain fact that it does not return unique full buffers on each
+   * call, but instead several of the pointers in the hostent structs will
+   * point to the same actual data! This have the unfortunate down-side that
+   * our caching system breaks down horribly. Luckily for us though, AIX 4.3
+   * and more recent versions have a "completely thread-safe"[*] libc where
+   * all the data is stored in thread-specific memory areas making calls to
+   * the plain old gethostbyname() work fine even for multi-threaded
+   * programs.
+   *
+   * This AIX 4.3 or later detection is all made in the configure script.
+   *
+   * Troels Walsted Hansen helped us work this out on March 3rd, 2003.
+   *
+   * [*] = much later we've found out that it isn't at all "completely
+   * thread-safe", but at least the gethostbyname() function is.
+   */
+
+  if(CURL_HOSTENT_SIZE >=
+     (sizeof(struct hostent) + sizeof(struct hostent_data))) {
+
+    /* August 22nd, 2000: Albert Chin-A-Young brought an updated version
+     * that should work! September 20: Richard Prescott worked on the buffer
+     * size dilemma.
      */
 
-    if(CURL_HOSTENT_SIZE >=
-       (sizeof(struct hostent) + sizeof(struct hostent_data))) {
-
-      /* August 22nd, 2000: Albert Chin-A-Young brought an updated version
-       * that should work! September 20: Richard Prescott worked on the buffer
-       * size dilemma.
-       */
-
-      res = gethostbyname_r(hostname,
-                            (struct hostent *)buf,
-                            (struct hostent_data *)((char *)buf +
-                                                    sizeof(struct hostent)));
-      h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */
-    }
-    else
-      res = -1; /* failure, too smallish buffer size */
-
-    if(!res) { /* success */
-
-      h = buf; /* result expected in h */
-
-      /* This is the worst kind of the different gethostbyname_r() interfaces.
-       * Since we don't know how big buffer this particular lookup required,
-       * we can't realloc down the huge alloc without doing closer analysis of
-       * the returned data. Thus, we always use CURL_HOSTENT_SIZE for every
-       * name lookup. Fixing this would require an extra malloc() and then
-       * calling Curl_addrinfo_copy() that subsequent realloc()s down the new
-       * memory area to the actually used amount.
-       */
-    }
-    else
+    res = gethostbyname_r(hostname,
+                          (struct hostent *)buf,
+                          (struct hostent_data *)((char *)buf +
+                                                  sizeof(struct hostent)));
+    h_errnop = SOCKERRNO; /* we don't deal with this, but set it anyway */
+  }
+  else
+    res = -1; /* failure, too smallish buffer size */
+
+  if(!res) { /* success */
+
+    h = buf; /* result expected in h */
+
+    /* This is the worst kind of the different gethostbyname_r() interfaces.
+     * Since we don't know how big buffer this particular lookup required,
+     * we can't realloc down the huge alloc without doing closer analysis of
+     * the returned data. Thus, we always use CURL_HOSTENT_SIZE for every
+     * name lookup. Fixing this would require an extra malloc() and then
+     * calling Curl_addrinfo_copy() that subsequent realloc()s down the new
+     * memory area to the actually used amount.
+     */
+  }
+  else
 #endif /* HAVE_...BYNAME_R_5 || HAVE_...BYNAME_R_6 || HAVE_...BYNAME_R_3 */
-    {
-      h = NULL; /* set return code to NULL */
-      free(buf);
-    }
+  {
+    h = NULL; /* set return code to NULL */
+    free(buf);
+  }
 #else /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
-    /*
-     * Here is code for platforms that don't have a thread safe
-     * getaddrinfo() nor gethostbyname_r() function or for which
-     * gethostbyname() is the preferred one.
-     */
-  else {
-    h = gethostbyname((void *)hostname);
+  /*
+   * Here is code for platforms that don't have a thread safe
+   * getaddrinfo() nor gethostbyname_r() function or for which
+   * gethostbyname() is the preferred one.
+   */
+  h = gethostbyname((void *)hostname);
 #endif /* HAVE_GETADDRINFO_THREADSAFE || HAVE_GETHOSTBYNAME_R */
-  }
 
   if(h) {
     ai = Curl_he2ai(h, port);
diff --git a/lib/hostip6.c b/lib/hostip6.c
index e0e0c58df..41ff98696 100644
--- a/lib/hostip6.c
+++ b/lib/hostip6.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -62,13 +62,19 @@
 /*
  * Curl_ipv6works() returns TRUE if IPv6 seems to work.
  */
-bool Curl_ipv6works(void)
+bool Curl_ipv6works(struct connectdata *conn)
 {
-  /* the nature of most system is that IPv6 status doesn't come and go
-     during a program's lifetime so we only probe the first time and then we
-     have the info kept for fast re-use */
-  static int ipv6_works = -1;
-  if(-1 == ipv6_works) {
+  if(conn) {
+    /* the nature of most system is that IPv6 status doesn't come and go
+       during a program's lifetime so we only probe the first time and then we
+       have the info kept for fast re-use */
+    DEBUGASSERT(conn);
+    DEBUGASSERT(conn->data);
+    DEBUGASSERT(conn->data->multi);
+    return conn->data->multi->ipv6_works;
+  }
+  else {
+    int ipv6_works = -1;
     /* probe to see if we have a working IPv6 stack */
     curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
     if(s == CURL_SOCKET_BAD)
@@ -78,8 +84,8 @@ bool Curl_ipv6works(void)
       ipv6_works = 1;
       Curl_closesocket(NULL, s);
     }
+    return (ipv6_works>0)?TRUE:FALSE;
   }
-  return (ipv6_works>0)?TRUE:FALSE;
 }
 
 /*
@@ -89,7 +95,7 @@ bool Curl_ipv6works(void)
 bool Curl_ipvalid(struct connectdata *conn)
 {
   if(conn->ip_version == CURL_IPRESOLVE_V6)
-    return Curl_ipv6works();
+    return Curl_ipv6works(conn);
 
   return TRUE;
 }
@@ -159,7 +165,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
     break;
   }
 
-  if((pf != PF_INET) && !Curl_ipv6works())
+  if((pf != PF_INET) && !Curl_ipv6works(conn))
     /* The stack seems to be a non-IPv6 one */
     pf = PF_INET;
 
diff --git a/lib/http.c b/lib/http.c
index 1c019e6ae..0d25f037c 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -344,7 +344,7 @@ static CURLcode http_output_bearer(struct connectdata *conn)
   userp = &conn->allocptr.userpwd;
   free(*userp);
   *userp = aprintf("Authorization: Bearer %s\r\n",
-                   conn->oauth_bearer);
+                   conn->data->set.str[STRING_BEARER]);
 
   if(!*userp) {
     result = CURLE_OUT_OF_MEMORY;
@@ -555,7 +555,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
   CURLcode result = CURLE_OK;
   unsigned long authmask = ~0ul;
 
-  if(!conn->oauth_bearer)
+  if(!data->set.str[STRING_BEARER])
     authmask &= (unsigned long)~CURLAUTH_BEARER;
 
   if(100 <= data->req.httpcode && 199 >= data->req.httpcode)
@@ -565,7 +565,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
   if(data->state.authproblem)
     return data->set.http_fail_on_error?CURLE_HTTP_RETURNED_ERROR:CURLE_OK;
 
-  if((conn->bits.user_passwd || conn->oauth_bearer) &&
+  if((conn->bits.user_passwd || data->set.str[STRING_BEARER]) &&
      ((data->req.httpcode == 401) ||
       (conn->bits.authneg && data->req.httpcode < 300))) {
     pickhost = pickoneauth(&data->state.authhost, authmask);
@@ -641,9 +641,7 @@ output_auth_headers(struct connectdata *conn,
 {
   const char *auth = NULL;
   CURLcode result = CURLE_OK;
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
   struct Curl_easy *data = conn->data;
-#endif
 
 #ifdef CURL_DISABLE_CRYPTO_AUTH
   (void)request;
@@ -707,7 +705,7 @@ output_auth_headers(struct connectdata *conn,
   }
   if(authstatus->picked == CURLAUTH_BEARER) {
     /* Bearer */
-    if((!proxy && conn->oauth_bearer &&
+    if((!proxy && data->set.str[STRING_BEARER] &&
         !Curl_checkheaders(conn, "Authorization:"))) {
       auth = "Bearer";
       result = http_output_bearer(conn);
@@ -765,7 +763,7 @@ Curl_http_output_auth(struct connectdata *conn,
   authproxy = &data->state.authproxy;
 
   if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
-     conn->bits.user_passwd || conn->oauth_bearer)
+     conn->bits.user_passwd || data->set.str[STRING_BEARER])
     /* continue please */;
   else {
     authhost->done = TRUE;
@@ -1691,7 +1689,7 @@ static CURLcode expect100(struct Curl_easy *data,
   CURLcode result = CURLE_OK;
   data->state.expect100header = FALSE; /* default to false unless it is set
                                           to TRUE below */
-  if(use_http_1_1plus(data, conn) &&
+  if(!data->state.disableexpect && use_http_1_1plus(data, conn) &&
      (conn->httpversion < 20)) {
     /* if not doing HTTP 1.0 or version 2, or disabled explicitly, we add an
        Expect: 100-continue to the headers which actually speeds up post
@@ -2390,7 +2388,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
         return CURLE_OUT_OF_MEMORY;
       }
     }
-    /* Extract the the URL to use in the request. Store in STRING_TEMP_URL for
+    /* Extract the URL to use in the request. Store in STRING_TEMP_URL for
        clean-up reasons if the function returns before the free() further
        down. */
     uc = curl_url_get(h, CURLUPART_URL, &data->set.str[STRING_TEMP_URL], 0);
@@ -3046,6 +3044,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   }
   if(result)
     return result;
+  if(!postsize)
+    data->req.upload_done = TRUE;
 
   if(data->req.writebytecount) {
     /* if a request-body has been sent off, we make sure this progress is noted
@@ -3545,7 +3545,16 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy 
*data,
              */
             Curl_expire_done(data, EXPIRE_100_TIMEOUT);
             if(!k->upload_done) {
-              if(data->set.http_keep_sending_on_error) {
+              if((k->httpcode == 417) && data->state.expect100header) {
+                /* 417 Expectation Failed - try again without the Expect
+                   header */
+                infof(data, "Got 417 while waiting for a 100\n");
+                data->state.disableexpect = TRUE;
+                DEBUGASSERT(!data->req.newurl);
+                data->req.newurl = strdup(conn->data->change.url);
+                Curl_done_sending(conn, k);
+              }
+              else if(data->set.http_keep_sending_on_error) {
                 infof(data, "HTTP error before end of send, keep sending\n");
                 if(k->exp100 > EXP100_SEND_DATA) {
                   k->exp100 = EXP100_SEND_DATA;
diff --git a/lib/http.h b/lib/http.h
index a59c96ba4..e6b511c20 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -116,7 +116,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn);
  *
  */
 #ifndef EXPECT_100_THRESHOLD
-#define EXPECT_100_THRESHOLD 1024
+#define EXPECT_100_THRESHOLD (1024*1024)
 #endif
 
 #endif /* CURL_DISABLE_HTTP */
diff --git a/lib/http2.c b/lib/http2.c
index 7d44e2e4b..bc1d1ea1a 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -43,19 +43,11 @@
 
 #define H2_BUFSIZE 32768
 
-#if (NGHTTP2_VERSION_NUM < 0x010000)
+#if (NGHTTP2_VERSION_NUM < 0x010c00)
 #error too old nghttp2 version, upgrade!
 #endif
 
-#if (NGHTTP2_VERSION_NUM > 0x010800)
-#define NGHTTP2_HAS_HTTP2_STRERROR 1
-#endif
-
-#if (NGHTTP2_VERSION_NUM >= 0x010900)
-/* nghttp2_session_callbacks_set_error_callback is present in nghttp2 1.9.0 or
-   later */
-#define NGHTTP2_HAS_ERROR_CALLBACK 1
-#else
+#ifdef CURL_DISABLE_VERBOSE_STRINGS
 #define nghttp2_session_callbacks_set_error_callback(x,y)
 #endif
 
@@ -63,7 +55,7 @@
 #define NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE 1
 #endif
 
-#define HTTP2_HUGE_WINDOW_SIZE (1 << 30)
+#define HTTP2_HUGE_WINDOW_SIZE (32 * 1024 * 1024) /* 32 MB */
 
 #ifdef DEBUG_HTTP2
 #define H2BUGF(x) x
@@ -341,36 +333,7 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
 int Curl_http2_ver(char *p, size_t len)
 {
   nghttp2_info *h2 = nghttp2_version(0);
-  return msnprintf(p, len, " nghttp2/%s", h2->version_str);
-}
-
-/* HTTP/2 error code to name based on the Error Code Registry.
-https://tools.ietf.org/html/rfc7540#page-77
-nghttp2_error_code enums are identical.
-*/
-static const char *http2_strerror(uint32_t err)
-{
-#ifndef NGHTTP2_HAS_HTTP2_STRERROR
-  const char *str[] = {
-    "NO_ERROR",             /* 0x0 */
-    "PROTOCOL_ERROR",       /* 0x1 */
-    "INTERNAL_ERROR",       /* 0x2 */
-    "FLOW_CONTROL_ERROR",   /* 0x3 */
-    "SETTINGS_TIMEOUT",     /* 0x4 */
-    "STREAM_CLOSED",        /* 0x5 */
-    "FRAME_SIZE_ERROR",     /* 0x6 */
-    "REFUSED_STREAM",       /* 0x7 */
-    "CANCEL",               /* 0x8 */
-    "COMPRESSION_ERROR",    /* 0x9 */
-    "CONNECT_ERROR",        /* 0xA */
-    "ENHANCE_YOUR_CALM",    /* 0xB */
-    "INADEQUATE_SECURITY",  /* 0xC */
-    "HTTP_1_1_REQUIRED"     /* 0xD */
-  };
-  return (err < sizeof(str) / sizeof(str[0])) ? str[err] : "unknown";
-#else
-  return nghttp2_http2_strerror(err);
-#endif
+  return msnprintf(p, len, "nghttp2/%s", h2->version_str);
 }
 
 /*
@@ -838,7 +801,7 @@ static int on_stream_close(nghttp2_session *session, 
int32_t stream_id,
       return 0;
     }
     H2BUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n",
-                 http2_strerror(error_code), error_code, stream_id));
+                 nghttp2_strerror(error_code), error_code, stream_id));
     stream = data_s->req.protop;
     if(!stream)
       return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -1138,8 +1101,7 @@ static ssize_t data_source_read_callback(nghttp2_session 
*session,
   return nread;
 }
 
-#if defined(NGHTTP2_HAS_ERROR_CALLBACK) &&      \
-  !defined(CURL_DISABLE_VERBOSE_STRINGS)
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
 static int error_callback(nghttp2_session *session,
                           const char *msg,
                           size_t len,
@@ -1156,9 +1118,10 @@ static void populate_settings(struct connectdata *conn,
                               struct http_conn *httpc)
 {
   nghttp2_settings_entry *iv = httpc->local_settings;
+  DEBUGASSERT(conn->data);
 
   iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
-  iv[0].value = (uint32_t)Curl_multi_max_concurrent_streams(conn->data->multi);
+  iv[0].value = Curl_multi_max_concurrent_streams(conn->data->multi);
 
   iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
   iv[1].value = HTTP2_HUGE_WINDOW_SIZE;
@@ -1257,9 +1220,7 @@ static CURLcode http2_init(struct connectdata *conn)
     /* nghttp2_on_header_callback */
     nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header);
 
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
     nghttp2_session_callbacks_set_error_callback(callbacks, error_callback);
-#endif
 
     /* The nghttp2 session is not yet setup, do it */
     rc = nghttp2_session_client_new(&conn->proto.httpc.h2, callbacks, conn);
@@ -1457,7 +1418,7 @@ static ssize_t http2_handle_stream_close(struct 
connectdata *conn,
   }
   else if(httpc->error_code != NGHTTP2_NO_ERROR) {
     failf(data, "HTTP/2 stream %d was not closed cleanly: %s (err %u)",
-          stream->stream_id, http2_strerror(httpc->error_code),
+          stream->stream_id, nghttp2_strerror(httpc->error_code),
           httpc->error_code);
     *err = CURLE_HTTP2_STREAM;
     return -1;
@@ -1594,8 +1555,12 @@ static ssize_t http2_recv(struct connectdata *conn, int 
sockindex,
     return ncopy;
   }
 
-  H2BUGF(infof(data, "http2_recv: easy %p (stream %u)\n",
-               data, stream->stream_id));
+  H2BUGF(infof(data, "http2_recv: easy %p (stream %u) win %u/%u\n",
+               data, stream->stream_id,
+               nghttp2_session_get_local_window_size(httpc->h2),
+               nghttp2_session_get_stream_local_window_size(httpc->h2,
+                                                            stream->stream_id)
+           ));
 
   if((data->state.drain) && stream->memlen) {
     H2BUGF(infof(data, "http2_recv: DRAIN %zu bytes stream %u!! (%p => %p)\n",
@@ -1626,7 +1591,6 @@ static ssize_t http2_recv(struct connectdata *conn, int 
sockindex,
     stream->pausedata += nread;
     stream->pauselen -= nread;
 
-    infof(data, "%zd data bytes written\n", nread);
     if(stream->pauselen == 0) {
       H2BUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
       DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
@@ -2264,7 +2228,6 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
     }
   }
 
-#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
   rv = nghttp2_session_set_local_window_size(httpc->h2, NGHTTP2_FLAG_NONE, 0,
                                              HTTP2_HUGE_WINDOW_SIZE);
   if(rv != 0) {
@@ -2272,7 +2235,6 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
           nghttp2_strerror(rv), rv);
     return CURLE_HTTP2;
   }
-#endif
 
   /* we are going to copy mem to httpc->inbuf.  This is required since
      mem is part of buffer pointed by stream->mem, and callbacks
@@ -2330,6 +2292,51 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
   return CURLE_OK;
 }
 
+CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause)
+{
+  DEBUGASSERT(data);
+  DEBUGASSERT(data->conn);
+  /* if it isn't HTTP/2, we're done */
+  if(!data->conn->proto.httpc.h2)
+    return CURLE_OK;
+#ifdef NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE
+  else {
+    struct HTTP *stream = data->req.protop;
+    struct http_conn *httpc = &data->conn->proto.httpc;
+    uint32_t window = !pause * HTTP2_HUGE_WINDOW_SIZE;
+    int rv = nghttp2_session_set_local_window_size(httpc->h2,
+                                                   NGHTTP2_FLAG_NONE,
+                                                   stream->stream_id,
+                                                   window);
+    if(rv) {
+      failf(data, "nghttp2_session_set_local_window_size() failed: %s(%d)",
+            nghttp2_strerror(rv), rv);
+      return CURLE_HTTP2;
+    }
+
+    /* make sure the window update gets sent */
+    rv = h2_session_send(data, httpc->h2);
+    if(rv)
+      return CURLE_SEND_ERROR;
+
+    DEBUGF(infof(data, "Set HTTP/2 window size to %u for stream %u\n",
+                 window, stream->stream_id));
+
+#ifdef DEBUGBUILD
+    {
+      /* read out the stream local window again */
+      uint32_t window2 =
+        nghttp2_session_get_stream_local_window_size(httpc->h2,
+                                                     stream->stream_id);
+      DEBUGF(infof(data, "HTTP/2 window size is now %u for stream %u\n",
+                   window2, stream->stream_id));
+    }
+#endif
+  }
+#endif
+  return CURLE_OK;
+}
+
 CURLcode Curl_http2_add_child(struct Curl_easy *parent,
                               struct Curl_easy *child,
                               bool exclusive)
diff --git a/lib/http2.h b/lib/http2.h
index 12d36eef9..1989aff82 100644
--- a/lib/http2.h
+++ b/lib/http2.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -58,6 +58,7 @@ CURLcode Curl_http2_add_child(struct Curl_easy *parent,
 void Curl_http2_remove_child(struct Curl_easy *parent,
                              struct Curl_easy *child);
 void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
+CURLcode Curl_http2_stream_pause(struct Curl_easy *data, bool pause);
 
 /* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */
 bool Curl_h2_http_1_1_error(struct connectdata *conn);
@@ -74,6 +75,7 @@ bool Curl_h2_http_1_1_error(struct connectdata *conn);
 #define Curl_http2_add_child(x, y, z)
 #define Curl_http2_remove_child(x, y)
 #define Curl_http2_cleanup_dependencies(x)
+#define Curl_http2_stream_pause(x, y)
 #define Curl_h2_http_1_1_error(x) 0
 #endif
 
diff --git a/lib/llist.c b/lib/llist.c
index 59174c86e..694b0fbaf 100644
--- a/lib/llist.c
+++ b/lib/llist.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -144,54 +144,3 @@ Curl_llist_count(struct curl_llist *list)
 {
   return list->size;
 }
-
-/*
- * @unittest: 1300
- */
-void Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e,
-                     struct curl_llist *to_list,
-                     struct curl_llist_element *to_e)
-{
-  /* Remove element from list */
-  if(e == NULL || list->size == 0)
-    return;
-
-  if(e == list->head) {
-    list->head = e->next;
-
-    if(list->head == NULL)
-      list->tail = NULL;
-    else
-      e->next->prev = NULL;
-  }
-  else {
-    e->prev->next = e->next;
-    if(!e->next)
-      list->tail = e->prev;
-    else
-      e->next->prev = e->prev;
-  }
-
-  --list->size;
-
-  /* Add element to to_list after to_e */
-  if(to_list->size == 0) {
-    to_list->head = e;
-    to_list->head->prev = NULL;
-    to_list->head->next = NULL;
-    to_list->tail = e;
-  }
-  else {
-    e->next = to_e->next;
-    e->prev = to_e;
-    if(to_e->next) {
-      to_e->next->prev = e;
-    }
-    else {
-      to_list->tail = e;
-    }
-    to_e->next = e;
-  }
-
-  ++to_list->size;
-}
diff --git a/lib/llist.h b/lib/llist.h
index a5e2ecbfb..0178c4259 100644
--- a/lib/llist.h
+++ b/lib/llist.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -47,7 +47,4 @@ void Curl_llist_remove(struct curl_llist *, struct 
curl_llist_element *,
                        void *);
 size_t Curl_llist_count(struct curl_llist *);
 void Curl_llist_destroy(struct curl_llist *, void *);
-void Curl_llist_move(struct curl_llist *, struct curl_llist_element *,
-                     struct curl_llist *, struct curl_llist_element *);
-
 #endif /* HEADER_CURL_LLIST_H */
diff --git a/lib/md4.c b/lib/md4.c
index bbf897508..38f1b2bc9 100644
--- a/lib/md4.c
+++ b/lib/md4.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -29,10 +29,16 @@
 
 #ifdef USE_OPENSSL
 #include <openssl/opensslconf.h>
-#endif
+#endif /* USE_OPENSSL */
+
 #ifdef USE_MBEDTLS
 #include <mbedtls/config.h>
+#include <mbedtls/version.h>
+
+#if(MBEDTLS_VERSION_NUMBER >= 0x02070000)
+  #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
 #endif
+#endif /* USE_MBEDTLS */
 
 #if defined(USE_GNUTLS_NETTLE)
 
@@ -65,10 +71,11 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
 #include <gcrypt.h>
 
 #include "curl_memory.h"
+
 /* The last #include file should be: */
 #include "memdebug.h"
 
-typedef struct gcry_md_hd_t MD4_CTX;
+typedef gcry_md_hd_t MD4_CTX;
 
 static void MD4_Init(MD4_CTX *ctx)
 {
@@ -82,52 +89,41 @@ static void MD4_Update(MD4_CTX *ctx, const void *data, 
unsigned long size)
 
 static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
 {
-  memcpy(result, gcry_md_read(ctx, 0), MD4_DIGEST_LENGTH);
-  gcry_md_close(ctx);
+  memcpy(result, gcry_md_read(*ctx, 0), MD4_DIGEST_LENGTH);
+  gcry_md_close(*ctx);
 }
 
 #elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4)
 /* When OpenSSL is available we use the MD4-functions from OpenSSL */
 #include <openssl/md4.h>
 
-#elif defined(USE_SECTRANSP)
+#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
+              (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
+      (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
+              (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
 
 #include <CommonCrypto/CommonDigest.h>
 
 #include "curl_memory.h"
+
 /* The last #include file should be: */
 #include "memdebug.h"
 
-typedef struct {
-  void *data;
-  unsigned long size;
-} MD4_CTX;
+typedef CC_MD4_CTX MD4_CTX;
 
 static void MD4_Init(MD4_CTX *ctx)
 {
-  ctx->data = NULL;
-  ctx->size = 0;
+  (void)CC_MD4_Init(ctx);
 }
 
 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
 {
-  if(ctx->data == NULL) {
-    ctx->data = malloc(size);
-    if(ctx->data != NULL) {
-      memcpy(ctx->data, data, size);
-      ctx->size = size;
-    }
-  }
+  (void)CC_MD4_Update(ctx, data, (CC_LONG)size);
 }
 
 static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
 {
-  if(ctx->data != NULL) {
-    (void)CC_MD4(ctx->data, (CC_LONG) ctx->size, result);
-
-    Curl_safefree(ctx->data);
-    ctx->size = 0;
-  }
+  (void)CC_MD4_Final(result, ctx);
 }
 
 #elif defined(USE_WIN32_CRYPTO)
@@ -135,7 +131,8 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
 #include <wincrypt.h>
 
 #include "curl_memory.h"
- /* The last #include file should be: */
+
+/* The last #include file should be: */
 #include "memdebug.h"
 
 typedef struct {
@@ -156,7 +153,7 @@ static void MD4_Init(MD4_CTX *ctx)
 
 static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size)
 {
-  CryptHashData(ctx->hHash, data, (unsigned int) size, 0);
+  CryptHashData(ctx->hHash, (BYTE *)data, (unsigned int) size, 0);
 }
 
 static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
@@ -179,6 +176,7 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
 #include <mbedtls/md4.h>
 
 #include "curl_memory.h"
+
 /* The last #include file should be: */
 #include "memdebug.h"
 
@@ -207,7 +205,11 @@ static void MD4_Update(MD4_CTX *ctx, const void *data, 
unsigned long size)
 static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
 {
   if(ctx->data != NULL) {
+#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
     mbedtls_md4(ctx->data, ctx->size, result);
+#else
+    (void) mbedtls_md4_ret(ctx->data, ctx->size, result);
+#endif
 
     Curl_safefree(ctx->data);
     ctx->size = 0;
@@ -505,9 +507,11 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
 
 #endif /* CRYPTO LIBS */
 
-void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
+void Curl_md4it(unsigned char *output, const unsigned char *input,
+                const size_t len)
 {
   MD4_CTX ctx;
+
   MD4_Init(&ctx);
   MD4_Update(&ctx, input, curlx_uztoui(len));
   MD4_Final(output, &ctx);
diff --git a/lib/md5.c b/lib/md5.c
index 8811f4429..d5624326f 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -30,6 +30,14 @@
 #include "curl_hmac.h"
 #include "warnless.h"
 
+#ifdef USE_MBEDTLS
+#include <mbedtls/version.h>
+
+#if(MBEDTLS_VERSION_NUMBER >= 0x02070000)
+  #define HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS
+#endif
+#endif /* USE_MBEDTLS */
+
 #if defined(USE_GNUTLS_NETTLE)
 
 #include <nettle/md5.h>
@@ -51,7 +59,7 @@ static void MD5_Update(MD5_CTX *ctx,
   md5_update(ctx, inputLen, input);
 }
 
-static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
+static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
 {
   md5_digest(ctx, 16, digest);
 }
@@ -77,7 +85,7 @@ static void MD5_Update(MD5_CTX *ctx,
   gcry_md_write(*ctx, input, inputLen);
 }
 
-static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
+static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
 {
   memcpy(digest, gcry_md_read(*ctx, 0), 16);
   gcry_md_close(*ctx);
@@ -90,6 +98,46 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
 /* The last #include file should be: */
 #include "memdebug.h"
 
+#elif defined(USE_MBEDTLS)
+
+#include <mbedtls/md5.h>
+
+#include "curl_memory.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+typedef mbedtls_md5_context MD5_CTX;
+
+static void MD5_Init(MD5_CTX *ctx)
+{
+#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
+  mbedtls_md5_starts(ctx);
+#else
+  (void) mbedtls_md5_starts_ret(ctx);
+#endif
+}
+
+static void MD5_Update(MD5_CTX *ctx,
+                       const unsigned char *data,
+                       unsigned int length)
+{
+#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
+  mbedtls_md5_update(ctx, data, length);
+#else
+  (void) mbedtls_md5_update_ret(ctx, data, length);
+#endif
+}
+
+static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
+{
+#if !defined(HAS_MBEDTLS_RESULT_CODE_BASED_FUNCTIONS)
+  mbedtls_md5_finish(ctx, digest);
+#else
+  (void) mbedtls_md5_finish_ret(ctx, digest);
+#endif
+}
+
 #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
               (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
       (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
@@ -119,12 +167,12 @@ static void MD5_Update(MD5_CTX *ctx,
   CC_MD5_Update(ctx, input, inputLen);
 }
 
-static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
+static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
 {
   CC_MD5_Final(digest, ctx);
 }
 
-#elif defined(WIN32) && !defined(CURL_WINDOWS_APP)
+#elif defined(USE_WIN32_CRYPTO)
 
 #include <wincrypt.h>
 #include "curl_memory.h"
@@ -151,7 +199,7 @@ static void MD5_Update(MD5_CTX *ctx,
   CryptHashData(ctx->hHash, (unsigned char *)input, inputLen, 0);
 }
 
-static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
+static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
 {
   unsigned long length = 0;
   CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
@@ -164,7 +212,9 @@ static void MD5_Final(unsigned char digest[16], MD5_CTX 
*ctx)
 }
 
 #else
+
 /* When no other crypto library is available we use this code segment */
+
 /*
  * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
  * MD5 Message-Digest Algorithm (RFC 1321).
@@ -513,12 +563,13 @@ const MD5_params Curl_DIGEST_MD5[] = {
 /*
  * @unittest: 1601
  */
-void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
-                const unsigned char *input)
+void Curl_md5it(unsigned char *outbuffer, const unsigned char *input,
+                const size_t len)
 {
   MD5_CTX ctx;
+
   MD5_Init(&ctx);
-  MD5_Update(&ctx, input, curlx_uztoui(strlen((char *)input)));
+  MD5_Update(&ctx, input, curlx_uztoui(len));
   MD5_Final(outbuffer, &ctx);
 }
 
diff --git a/lib/mime.c b/lib/mime.c
index c974d195a..e93e425a2 100644
--- a/lib/mime.c
+++ b/lib/mime.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -26,6 +26,7 @@
 
 #include "mime.h"
 #include "non-ascii.h"
+#include "warnless.h"
 #include "urldata.h"
 #include "sendf.h"
 
@@ -52,6 +53,10 @@
 
 
 #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. */
 static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
@@ -354,10 +359,15 @@ static size_t encoder_nop_read(char *buffer, size_t size, 
bool ateof,
 
   (void) ateof;
 
+  if(!size)
+    return STOP_FILLING;
+
   if(size > insize)
     size = insize;
+
   if(size)
-    memcpy(buffer, st->buf, size);
+    memcpy(buffer, st->buf + st->bufbeg, size);
+
   st->bufbeg += size;
   return size;
 }
@@ -377,6 +387,9 @@ static size_t encoder_7bit_read(char *buffer, size_t size, 
bool ateof,
 
   (void) ateof;
 
+  if(!size)
+    return STOP_FILLING;
+
   if(size > cursize)
     size = cursize;
 
@@ -404,8 +417,11 @@ static size_t encoder_base64_read(char *buffer, size_t 
size, bool ateof,
     /* Line full ? */
     if(st->pos > MAX_ENCODED_LINE_LENGTH - 4) {
       /* Yes, we need 2 characters for CRLF. */
-      if(size < 2)
+      if(size < 2) {
+        if(!cursize)
+          return STOP_FILLING;
         break;
+      }
       *ptr++ = '\r';
       *ptr++ = '\n';
       st->pos = 0;
@@ -414,7 +430,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. */
-    if(size < 4 || st->bufend - st->bufbeg < 3)
+    if(size < 4) {
+      if(!cursize)
+        return STOP_FILLING;
+      break;
+    }
+    if(st->bufend - st->bufbeg < 3)
       break;
 
     /* Encode three bytes as four characters. */
@@ -431,25 +452,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(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;
     }
   }
 
@@ -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(len > size)
+    if(len > size) {
+      if(!cursize)
+        return STOP_FILLING;
       break;
+    }
 
     /* Append to output buffer. */
     memcpy(ptr, buf, len);
@@ -612,16 +642,18 @@ static size_t mime_mem_read(char *buffer, size_t size, 
size_t nitems,
                             void *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.*/
 
+  if(!nitems)
+    return STOP_FILLING;
+
   if(sz > nitems)
     sz = nitems;
 
   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;
 }
 
@@ -641,7 +673,7 @@ static int mime_mem_seek(void *instream, curl_off_t offset, 
int whence)
   if(offset < 0 || offset > part->datasize)
     return CURL_SEEKFUNC_FAIL;
 
-  part->state.offset = (size_t) offset;
+  part->state.offset = offset;
   return CURL_SEEKFUNC_OK;
 }
 
@@ -668,6 +700,9 @@ static size_t mime_file_read(char *buffer, size_t size, 
size_t nitems,
 {
   curl_mimepart *part = (curl_mimepart *) instream;
 
+  if(!nitems)
+    return STOP_FILLING;
+
   if(mime_open_file(part))
     return READ_ERROR;
 
@@ -711,15 +746,16 @@ static size_t readback_bytes(mime_state *state,
                              const char *trail)
 {
   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 {
     size_t tsz = strlen(trail);
 
-    sz = state->offset - numbytes;
+    sz = offset - numbytes;
     if(sz >= tsz)
       return 0;
     bytes = trail + sz;
@@ -736,25 +772,79 @@ static size_t readback_bytes(mime_state *state,
 
 /* Read a non-encoded part content. */
 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;
 
-  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;
 }
 
 /* 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;
   size_t cursize = 0;
   size_t sz;
   bool ateof = FALSE;
 
-  while(bufsize) {
+  for(;;) {
     if(st->bufbeg < st->bufend || ateof) {
       /* Encode buffered data. */
       sz = part->encoder->encodefunc(buffer, bufsize, ateof, part);
@@ -763,9 +853,8 @@ static size_t read_encoded_part_content(curl_mimepart *part,
         if(ateof)
           return cursize;
         break;
-      case CURL_READFUNC_ABORT:
-      case CURL_READFUNC_PAUSE:
       case READ_ERROR:
+      case STOP_FILLING:
         return cursize? cursize: sz;
       default:
         cursize += sz;
@@ -787,7 +876,7 @@ static size_t read_encoded_part_content(curl_mimepart *part,
     if(st->bufend >= sizeof(st->buf))
       return cursize? cursize: READ_ERROR;    /* Buffer full. */
     sz = read_part_content(part, st->buf + st->bufend,
-                           sizeof(st->buf) - st->bufend);
+                           sizeof(st->buf) - st->bufend, hasread);
     switch(sz) {
     case 0:
       ateof = TRUE;
@@ -795,6 +884,7 @@ static size_t read_encoded_part_content(curl_mimepart *part,
     case CURL_READFUNC_ABORT:
     case CURL_READFUNC_PAUSE:
     case READ_ERROR:
+    case STOP_FILLING:
       return cursize? cursize: sz;
     default:
       st->bufend += sz;
@@ -802,12 +892,12 @@ static size_t read_encoded_part_content(curl_mimepart 
*part,
     }
   }
 
-  return cursize;
+  /* NOTREACHED */
 }
 
 /* Readback a mime 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;
 #ifdef CURL_DOES_CONVERSIONS
@@ -866,9 +956,9 @@ static size_t readback_part(curl_mimepart *part,
       break;
     case MIMESTATE_CONTENT:
       if(part->encoder)
-        sz = read_encoded_part_content(part, buffer, bufsize);
+        sz = read_encoded_part_content(part, buffer, bufsize, hasread);
       else
-        sz = read_part_content(part, buffer, bufsize);
+        sz = read_part_content(part, buffer, bufsize, hasread);
       switch(sz) {
       case 0:
         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_PAUSE:
       case READ_ERROR:
+      case STOP_FILLING:
         return cursize? cursize: sz;
       }
       break;
@@ -909,9 +1000,9 @@ static size_t readback_part(curl_mimepart *part,
   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,
-                                 void *instream)
+                                 void *instream, bool *hasread)
 {
   curl_mime *mime = (curl_mime *) instream;
   size_t cursize = 0;
@@ -932,7 +1023,7 @@ static size_t mime_subparts_read(char *buffer, size_t 
size, size_t nitems,
 #endif
       mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, mime->firstpart);
       /* 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. */
       mime->state.offset += 2;
       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);
         break;
       }
-      sz = readback_part(part, buffer, nitems);
+      sz = readback_part(part, buffer, nitems, hasread);
       switch(sz) {
       case CURL_READFUNC_ABORT:
       case CURL_READFUNC_PAUSE:
       case READ_ERROR:
+      case STOP_FILLING:
         return cursize? cursize: sz;
       case 0:
 #ifdef CURL_DOES_CONVERSIONS
@@ -1031,6 +1123,7 @@ static int mime_part_rewind(curl_mimepart *part)
   if(res == CURL_SEEKFUNC_OK)
     mimesetstate(&part->state, targetstate, NULL);
 
+  part->lastreadstatus = 1; /* Successful read status. */
   return res;
 }
 
@@ -1073,6 +1166,8 @@ static void cleanup_part_content(curl_mimepart *part)
   part->datasize = (curl_off_t) 0;    /* No size yet. */
   cleanup_encoder_state(&part->encstate);
   part->kind = MIMEKIND_NONE;
+  part->flags &= ~MIME_FAST_READ;
+  part->lastreadstatus = 1; /* Successful read status. */
 }
 
 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));
   part->easy = easy;
+  part->lastreadstatus = 1; /* Successful read status. */
   mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
 }
 
@@ -1328,6 +1424,7 @@ CURLcode curl_mime_data(curl_mimepart *part,
     part->readfunc = mime_mem_read;
     part->seekfunc = mime_mem_seek;
     part->freefunc = mime_mem_free;
+    part->flags |= MIME_FAST_READ;
     part->kind = MIMEKIND_DATA;
   }
 
@@ -1502,7 +1599,7 @@ CURLcode Curl_mime_set_subparts(curl_mimepart *part,
     }
 
     subparts->parent = part;
-    part->readfunc = mime_subparts_read;
+    /* Subparts are processed internally: no read callback. */
     part->seekfunc = mime_subparts_seek;
     part->freefunc = take_ownership? mime_subparts_free: mime_subparts_unbind;
     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)
 {
   curl_mimepart *part = (curl_mimepart *) instream;
+  size_t ret;
+  bool hasread;
 
   (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. */
@@ -1805,6 +1916,26 @@ CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
   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 */
 
 /* Mime not compiled in: define stubs for externally-referenced functions. */
diff --git a/lib/mime.h b/lib/mime.h
index 3241fdc1f..d7f25132e 100644
--- a/lib/mime.h
+++ b/lib/mime.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -31,6 +31,7 @@
 /* Part flags. */
 #define MIME_USERHEADERS_OWNER  (1 << 0)
 #define MIME_BODY_ONLY          (1 << 1)
+#define MIME_FAST_READ          (1 << 2)
 
 #define FILE_CONTENTTYPE_DEFAULT        "application/octet-stream"
 #define MULTIPART_CONTENTTYPE_DEFAULT   "multipart/mixed"
@@ -87,7 +88,7 @@ typedef struct {
 typedef struct {
   enum mimestate state;       /* Current state token. */
   void *ptr;                  /* State-dependent pointer. */
-  size_t offset;              /* State-dependent offset. */
+  curl_off_t offset;          /* State-dependent offset. */
 }  mime_state;
 
 /* minimum buffer size for the boundary string */
@@ -125,6 +126,7 @@ struct curl_mimepart_s {
   mime_state state;                /* Current readback state. */
   const mime_encoder *encoder;     /* Content data encoder. */
   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, ...);
@@ -147,6 +149,7 @@ size_t Curl_mime_read(char *buffer, size_t size, size_t 
nitems,
                       void *instream);
 CURLcode Curl_mime_rewind(curl_mimepart *part);
 const char *Curl_mime_contenttype(const char *filename);
+void Curl_mime_unpause(curl_mimepart *part);
 
 #else
 /* if disabled */
@@ -158,6 +161,7 @@ const char *Curl_mime_contenttype(const char *filename);
 #define Curl_mime_size(x) (curl_off_t) -1
 #define Curl_mime_read NULL
 #define Curl_mime_rewind(x) ((void)x, CURLE_NOT_BUILT_IN)
+#define Curl_mime_unpause(x)
 #endif
 
 
diff --git a/lib/mk-ca-bundle.pl b/lib/mk-ca-bundle.pl
index 33977f322..09e8e5b9b 100755
--- a/lib/mk-ca-bundle.pl
+++ b/lib/mk-ca-bundle.pl
@@ -6,7 +6,7 @@
 # *                            | (__| |_| |  _ <| |___
 # *                             \___|\___/|_| \_\_____|
 # *
-# * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+# * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 # *
 # * This software is licensed as described in the file COPYING, which
 # * you should have received as part of this distribution. The terms
@@ -38,6 +38,7 @@ use warnings;
 use vars qw($opt_b $opt_d $opt_f $opt_h $opt_i $opt_k $opt_l $opt_m $opt_n 
$opt_p $opt_q $opt_s $opt_t $opt_u $opt_v $opt_w);
 use List::Util;
 use Text::Wrap;
+use Time::Local;
 my $MOD_SHA = "Digest::SHA";
 eval "require $MOD_SHA";
 if ($@) {
@@ -421,6 +422,8 @@ my $certnum = 0;
 my $skipnum = 0;
 my $start_of_cert = 0;
 my @precert;
+my $cka_value;
+my $valid = 1;
 
 open(TXT,"$txt") or die "Couldn't open $txt: $!\n";
 while (<TXT>) {
@@ -435,6 +438,7 @@ while (<TXT>) {
   }
   elsif(/^# (Issuer|Serial Number|Subject|Not Valid Before|Not Valid After 
|Fingerprint \(MD5\)|Fingerprint \(SHA1\)):/) {
       push @precert, $_;
+      $valid = 1;
       next;
   }
   elsif(/^#|^\s*$/) {
@@ -443,6 +447,49 @@ while (<TXT>) {
   }
   chomp;
 
+  # Example:
+  # CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL
+  # \062\060\060\066\061\067\060\060\060\060\060\060\132
+  # END
+
+  if (/^CKA_NSS_SERVER_DISTRUST_AFTER (CK_BBOOL CK_FALSE|MULTILINE_OCTAL)/) {
+      if($1 eq "MULTILINE_OCTAL") {
+          my @timestamp;
+          while (<TXT>) {
+              last if (/^END/);
+              chomp;
+              my @octets = split(/\\/);
+              shift @octets;
+              for (@octets) {
+                  push @timestamp, chr(oct);
+              }
+          }
+          # A trailing Z in the timestamp signifies UTC
+          if($timestamp[12] ne "Z") {
+              report "distrust date stamp is not using UTC";
+          }
+          # Example date: 200617000000Z
+          # Means 2020-06-17 00:00:00 UTC
+          my $distrustat =
+            timegm($timestamp[10] . $timestamp[11], # second
+                   $timestamp[8] . $timestamp[9],   # minute
+                   $timestamp[6] . $timestamp[7],   # hour
+                   $timestamp[4] . $timestamp[5],   # day
+                   ($timestamp[2] . $timestamp[3]) - 1, # month
+                   "20" . $timestamp[0] . $timestamp[1]); # year
+          if(time >= $distrustat) {
+              # not trusted anymore
+              $skipnum++;
+              report "Skipping: $caname is not trusted anymore" if ($opt_v);
+              $valid = 0;
+          }
+          else {
+              # still trusted
+          }
+      }
+      next;
+  }
+
   # this is a match for the start of a certificate
   if (/^CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE/) {
     $start_of_cert = 1
@@ -452,21 +499,18 @@ while (<TXT>) {
   }
   my %trust_purposes_by_level;
   if ($start_of_cert && /^CKA_VALUE MULTILINE_OCTAL/) {
-    my $data;
+    $cka_value="";
     while (<TXT>) {
       last if (/^END/);
       chomp;
       my @octets = split(/\\/);
       shift @octets;
       for (@octets) {
-        $data .= chr(oct);
+        $cka_value .= chr(oct);
       }
     }
-    # scan forwards until the trust part
-    while (<TXT>) {
-      last if (/^CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST/);
-      chomp;
-    }
+  }
+  if(/^CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST/ && $valid) {
     # now scan the trust part to determine how we should trust this cert
     while (<TXT>) {
       last if (/^#/);
@@ -485,6 +529,8 @@ while (<TXT>) {
       $skipnum ++;
       report "Skipping: $caname" if ($opt_v);
     } else {
+      my $data = $cka_value;
+      $cka_value = "";
       my $encoded = MIME::Base64::encode_base64($data, '');
       $encoded =~ s/(.{1,${opt_w}})/$1\n/g;
       my $pem = "-----BEGIN CERTIFICATE-----\n"
diff --git a/lib/multi.c b/lib/multi.c
index dbf95f473..c89fe79a4 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -47,6 +47,7 @@
 #include "http_proxy.h"
 #include "http2.h"
 #include "socketpair.h"
+#include "socks.h"
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
@@ -369,6 +370,8 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* 
socket hash */
 
   /* -1 means it not set by user, use the default value */
   multi->maxconnects = -1;
+  multi->max_concurrent_streams = 100;
+  multi->ipv6_works = Curl_ipv6works(NULL);
 
 #ifdef ENABLE_WAKEUP
   if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, multi->wakeup_pair) < 0) {
@@ -590,6 +593,9 @@ static CURLcode multi_done(struct Curl_easy *data,
   detach_connnection(data);
   if(CONN_INUSE(conn)) {
     /* Stop if still used. */
+    /* conn->data must not remain pointing to this transfer since it is going
+       away! Find another to own it! */
+    conn->data = conn->easyq.head->ptr;
     CONN_UNLOCK(data);
     DEBUGF(infof(data, "Connection still in use %zu, "
                  "no more multi_done now!\n",
@@ -725,8 +731,8 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
        we don't leave a half-baked one around */
     if(easy_owns_conn) {
 
-      /* multi_done() clears the conn->data field to lose the association
-         between the easy handle and the connection
+      /* multi_done() clears the association between the easy handle and the
+         connection.
 
          Note that this ignores the return code simply because there's
          nothing really useful to do with it anyway! */
@@ -851,6 +857,9 @@ static int waitconnect_getsock(struct connectdata *conn,
     return Curl_ssl_getsock(conn, sock);
 #endif
 
+  if(SOCKS_STATE(conn->cnnct.state))
+    return Curl_SOCKS_getsock(conn, sock, FIRSTSOCKET);
+
   for(i = 0; i<2; i++) {
     if(conn->tempsock[i] != CURL_SOCKET_BAD) {
       sock[s] = conn->tempsock[i];
@@ -1048,6 +1057,9 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
   if(multi->in_callback)
     return CURLM_RECURSIVE_API_CALL;
 
+  if(timeout_ms < 0)
+    return CURLM_BAD_FUNCTION_ARGUMENT;
+
   /* Count up how many fds we have from the multi handle */
   data = multi->easyp;
   while(data) {
@@ -1182,14 +1194,16 @@ static CURLMcode Curl_multi_wait(struct Curl_multi 
*multi,
       if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) {
         if(ufds[curlfds + extra_nfds].revents & POLLIN) {
           char buf[64];
+          ssize_t nread;
           while(1) {
             /* the reading socket is non-blocking, try to read
                data from it until it receives an error (except EINTR).
                In normal cases it will get EAGAIN or EWOULDBLOCK
                when there is no more data, breaking the loop. */
-            if(sread(multi->wakeup_pair[0], buf, sizeof(buf)) < 0) {
+            nread = sread(multi->wakeup_pair[0], buf, sizeof(buf));
+            if(nread <= 0) {
 #ifndef USE_WINSOCK
-              if(EINTR == SOCKERRNO)
+              if(nread < 0 && EINTR == SOCKERRNO)
                 continue;
 #endif
               break;
@@ -2183,8 +2197,13 @@ static CURLMcode multi_runsingle(struct Curl_multi 
*multi,
           }
         }
       }
-      else if(comeback)
-        rc = CURLM_CALL_MULTI_PERFORM;
+      else if(comeback) {
+        /* This avoids CURLM_CALL_MULTI_PERFORM so that a very fast transfer
+           won't get stuck on this transfer at the expense of other concurrent
+           transfers */
+        Curl_expire(data, 0, EXPIRE_RUN_NOW);
+        rc = CURLM_OK;
+      }
       break;
     }
 
@@ -2897,8 +2916,8 @@ CURLMcode curl_multi_setopt(struct Curl_multi *multi,
       if(streams < 1)
         streams = 100;
       multi->max_concurrent_streams =
-          (streams > (long)INITIAL_MAX_CONCURRENT_STREAMS)?
-          (long)INITIAL_MAX_CONCURRENT_STREAMS : streams;
+        (streams > (long)INITIAL_MAX_CONCURRENT_STREAMS)?
+        INITIAL_MAX_CONCURRENT_STREAMS : (unsigned int)streams;
     }
     break;
   default:
@@ -3340,8 +3359,8 @@ void Curl_multi_dump(struct Curl_multi *multi)
 }
 #endif
 
-size_t Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
+unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi)
 {
-  return multi ? ((size_t)multi->max_concurrent_streams ?
-                  (size_t)multi->max_concurrent_streams : 100) : 0;
+  DEBUGASSERT(multi);
+  return multi->max_concurrent_streams;
 }
diff --git a/lib/multihandle.h b/lib/multihandle.h
index 0bf09e6bb..91eca16c4 100644
--- a/lib/multihandle.h
+++ b/lib/multihandle.h
@@ -119,11 +119,6 @@ struct Curl_multi {
      same actual socket) */
   struct curl_hash sockhash;
 
-  /* multiplexing wanted */
-  bool multiplexing;
-
-  bool recheckstate; /* see Curl_multi_connchanged */
-
   /* Shared connection cache (bundles)*/
   struct conncache conn_cache;
 
@@ -141,13 +136,17 @@ struct Curl_multi {
   void *timer_userp;
   struct curltime timer_lastcall; /* the fixed time for the timeout for the
                                     previous callback */
-  bool in_callback;            /* true while executing a callback */
-  long max_concurrent_streams; /* max concurrent streams client to support */
+  unsigned int max_concurrent_streams;
 
 #ifdef ENABLE_WAKEUP
   curl_socket_t wakeup_pair[2]; /* socketpair() used for wakeup
                                    0 is used for read, 1 is used for write */
 #endif
+  /* multiplexing wanted */
+  bool multiplexing;
+  bool recheckstate; /* see Curl_multi_connchanged */
+  bool in_callback;            /* true while executing a callback */
+  bool ipv6_works;
 };
 
 #endif /* HEADER_CURL_MULTIHANDLE_H */
diff --git a/lib/multiif.h b/lib/multiif.h
index 75025232c..bde755ee0 100644
--- a/lib/multiif.h
+++ b/lib/multiif.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -90,9 +90,7 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi,
                                  struct connectdata *conn);
 
 
-/* Return the value of the CURLMOPT_MAX_CONCURRENT_STREAMS option
- * If not specified or 0, default would be 100
- */
-size_t Curl_multi_max_concurrent_streams(struct Curl_multi *multi);
+/* Return the value of the CURLMOPT_MAX_CONCURRENT_STREAMS option */
+unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi);
 
 #endif /* HEADER_CURL_MULTIIF_H */
diff --git a/lib/getenv.c b/lib/rename.c
similarity index 53%
copy from lib/getenv.c
copy to lib/rename.c
index fa2abe3af..bb170d3cc 100644
--- a/lib/getenv.c
+++ b/lib/rename.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -20,35 +20,43 @@
  *
  ***************************************************************************/
 
+#include "rename.h"
+
 #include "curl_setup.h"
 
-#include <gnurl/curl.h>
-#include "curl_memory.h"
+#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)) ||  \
+  defined(USE_ALTSVC)
+
+#include "timeval.h"
 
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
 #include "memdebug.h"
 
-static
-char *GetEnv(const char *variable)
+/* return 0 on success, 1 on error */
+int Curl_rename(const char *oldpath, const char *newpath)
 {
-#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
-  (void)variable;
-  return NULL;
-#else
 #ifdef WIN32
-  char env[4096];
-  char *temp = getenv(variable);
-  env[0] = '\0';
-  if(temp != NULL)
-    ExpandEnvironmentStringsA(temp, env, sizeof(env));
-  return (env[0] != '\0')?strdup(env):NULL;
+  /* rename() on Windows doesn't overwrite, so we can't use it here.
+     MoveFileExA() will overwrite and is usually atomic, however it fails
+     when there are open handles to the file. */
+  const int max_wait_ms = 1000;
+  struct curltime start = Curl_now();
+  for(;;) {
+    timediff_t diff;
+    if(MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
+      break;
+    diff = Curl_timediff(Curl_now(), start);
+    if(diff < 0 || diff > max_wait_ms)
+      return 1;
+    Sleep(1);
+  }
 #else
-  char *env = getenv(variable);
-  return (env && env[0])?strdup(env):NULL;
-#endif
+  if(rename(oldpath, newpath))
+    return 1;
 #endif
+  return 0;
 }
 
-char *curl_getenv(const char *v)
-{
-  return GetEnv(v);
-}
+#endif
diff --git a/lib/curl_sha256.h b/lib/rename.h
similarity index 76%
copy from lib/curl_sha256.h
copy to lib/rename.h
index 14b6414ea..d7442c844 100644
--- a/lib/curl_sha256.h
+++ b/lib/rename.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_SHA256_H
-#define HEADER_CURL_SHA256_H
+#ifndef HEADER_CURL_RENAME_H
+#define HEADER_CURL_RENAME_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Florin Petriuc, <address@hidden>
+ * Copyright (C) 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,11 +22,6 @@
  *
  ***************************************************************************/
 
-#ifndef CURL_DISABLE_CRYPTO_AUTH
+int Curl_rename(const char *oldpath, const char *newpath);
 
-void Curl_sha256it(unsigned char *outbuffer,
-                const unsigned char *input);
-
-#endif
-
-#endif /* HEADER_CURL_SHA256_H */
+#endif /* HEADER_CURL_RENAME_H */
diff --git a/lib/select.c b/lib/select.c
index 190fb51ff..b836698f3 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -53,9 +53,6 @@
 /* Convenience local macros */
 #define ELAPSED_MS() (int)Curl_timediff(Curl_now(), initial_tv)
 
-int Curl_ack_eintr = 0;
-#define ERROR_NOT_EINTR(error) (Curl_ack_eintr || error != EINTR)
-
 /*
  * Internal function used for waiting a specific amount of ms
  * in Curl_socket_check() and Curl_poll() when no file descriptor
@@ -74,13 +71,6 @@ int Curl_ack_eintr = 0;
  */
 int Curl_wait_ms(int timeout_ms)
 {
-#if !defined(MSDOS) && !defined(USE_WINSOCK)
-#ifndef HAVE_POLL_FINE
-  struct timeval pending_tv;
-#endif
-  struct curltime initial_tv;
-  int pending_ms;
-#endif
   int r = 0;
 
   if(!timeout_ms)
@@ -94,28 +84,16 @@ int Curl_wait_ms(int timeout_ms)
 #elif defined(USE_WINSOCK)
   Sleep(timeout_ms);
 #else
-  pending_ms = timeout_ms;
-  initial_tv = Curl_now();
-  do {
-    int error;
 #if defined(HAVE_POLL_FINE)
-    r = poll(NULL, 0, pending_ms);
+  r = poll(NULL, 0, timeout_ms);
 #else
-    pending_tv.tv_sec = pending_ms / 1000;
-    pending_tv.tv_usec = (pending_ms % 1000) * 1000;
+  {
+    struct timeval pending_tv;
+    pending_tv.tv_sec = timeout_ms / 1000;
+    pending_tv.tv_usec = (timeout_ms % 1000) * 1000;
     r = select(0, NULL, NULL, NULL, &pending_tv);
+  }
 #endif /* HAVE_POLL_FINE */
-    if(r != -1)
-      break;
-    error = SOCKERRNO;
-    if(error && ERROR_NOT_EINTR(error))
-      break;
-    pending_ms = timeout_ms - ELAPSED_MS();
-    if(pending_ms <= 0) {
-      r = 0;  /* Simulate a "call timed out" case */
-      break;
-    }
-  } while(r == -1);
 #endif /* USE_WINSOCK */
   if(r)
     r = -1;
@@ -158,7 +136,6 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets 
to read from */
   fd_set fds_err;
   curl_socket_t maxfd;
 #endif
-  struct curltime initial_tv = {0, 0};
   int pending_ms = 0;
   int r;
   int ret;
@@ -183,7 +160,6 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets 
to read from */
 
   if(timeout_ms > 0) {
     pending_ms = (int)timeout_ms;
-    initial_tv = Curl_now();
   }
 
 #ifdef HAVE_POLL_FINE
@@ -208,26 +184,11 @@ int Curl_socket_check(curl_socket_t readfd0, /* two 
sockets to read from */
     num++;
   }
 
-  do {
-    int error;
-    if(timeout_ms < 0)
-      pending_ms = -1;
-    else if(!timeout_ms)
-      pending_ms = 0;
-    r = poll(pfd, num, pending_ms);
-    if(r != -1)
-      break;
-    error = SOCKERRNO;
-    if(error && ERROR_NOT_EINTR(error))
-      break;
-    if(timeout_ms > 0) {
-      pending_ms = (int)(timeout_ms - ELAPSED_MS());
-      if(pending_ms <= 0) {
-        r = 0;  /* Simulate a "call timed out" case */
-        break;
-      }
-    }
-  } while(r == -1);
+  if(timeout_ms < 0)
+    pending_ms = -1;
+  else if(!timeout_ms)
+    pending_ms = 0;
+  r = poll(pfd, num, pending_ms);
 
   if(r < 0)
     return -1;
@@ -290,61 +251,45 @@ int Curl_socket_check(curl_socket_t readfd0, /* two 
sockets to read from */
 
   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
 
-  do {
-    int error;
-    if(timeout_ms > 0) {
-      pending_tv.tv_sec = pending_ms / 1000;
-      pending_tv.tv_usec = (pending_ms % 1000) * 1000;
-    }
-    else if(!timeout_ms) {
-      pending_tv.tv_sec = 0;
-      pending_tv.tv_usec = 0;
-    }
+  if(timeout_ms > 0) {
+    pending_tv.tv_sec = pending_ms / 1000;
+    pending_tv.tv_usec = (pending_ms % 1000) * 1000;
+  }
+  else if(!timeout_ms) {
+    pending_tv.tv_sec = 0;
+    pending_tv.tv_usec = 0;
+  }
 
-    /* WinSock select() must not be called with an fd_set that contains zero
-       fd flags, or it will return WSAEINVAL.  But, it also can't be called
-       with no fd_sets at all!  From the documentation:
+  /* WinSock select() must not be called with an fd_set that contains zero
+     fd flags, or it will return WSAEINVAL.  But, it also can't be called
+     with no fd_sets at all!  From the documentation:
 
-         Any two of the parameters, readfds, writefds, or exceptfds, can be
-         given as null. At least one must be non-null, and any non-null
-         descriptor set must contain at least one handle to a socket.
+     Any two of the parameters, readfds, writefds, or exceptfds, can be
+     given as null. At least one must be non-null, and any non-null
+     descriptor set must contain at least one handle to a socket.
 
-       We know that we have at least one bit set in at least two fd_sets in
-       this case, but we may have no bits set in either fds_read or fd_write,
-       so check for that and handle it.  Luckily, with WinSock, we can _also_
-       ask how many bits are set on an fd_set.
+     We know that we have at least one bit set in at least two fd_sets in
+     this case, but we may have no bits set in either fds_read or fd_write,
+     so check for that and handle it.  Luckily, with WinSock, we can _also_
+     ask how many bits are set on an fd_set.
 
-       It is unclear why WinSock doesn't just handle this for us instead of
-       calling this an error.
+     It is unclear why WinSock doesn't just handle this for us instead of
+     calling this an error.
 
-       Note also that WinSock ignores the first argument, so we don't worry
-       about the fact that maxfd is computed incorrectly with WinSock (since
-       curl_socket_t is unsigned in such cases and thus -1 is the largest
-       value).
-    */
+     Note also that WinSock ignores the first argument, so we don't worry
+     about the fact that maxfd is computed incorrectly with WinSock (since
+     curl_socket_t is unsigned in such cases and thus -1 is the largest
+     value).
+  */
 #ifdef USE_WINSOCK
-    r = select((int)maxfd + 1,
-               fds_read.fd_count ? &fds_read : NULL,
-               fds_write.fd_count ? &fds_write : NULL,
-               &fds_err, ptimeout);
+  r = select((int)maxfd + 1,
+             fds_read.fd_count ? &fds_read : NULL,
+             fds_write.fd_count ? &fds_write : NULL,
+             &fds_err, ptimeout);
 #else
-    r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
+  r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
 #endif
 
-    if(r != -1)
-      break;
-    error = SOCKERRNO;
-    if(error && ERROR_NOT_EINTR(error))
-      break;
-    if(timeout_ms > 0) {
-      pending_ms = (int)(timeout_ms - ELAPSED_MS());
-      if(pending_ms <= 0) {
-        r = 0;  /* Simulate a "call timed out" case */
-        break;
-      }
-    }
-  } while(r == -1);
-
   if(r < 0)
     return -1;
   if(r == 0)
@@ -399,7 +344,6 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int 
timeout_ms)
   fd_set fds_err;
   curl_socket_t maxfd;
 #endif
-  struct curltime initial_tv = {0, 0};
   bool fds_none = TRUE;
   unsigned int i;
   int pending_ms = 0;
@@ -425,31 +369,15 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, 
int timeout_ms)
 
   if(timeout_ms > 0) {
     pending_ms = timeout_ms;
-    initial_tv = Curl_now();
   }
 
 #ifdef HAVE_POLL_FINE
 
-  do {
-    int error;
-    if(timeout_ms < 0)
-      pending_ms = -1;
-    else if(!timeout_ms)
-      pending_ms = 0;
-    r = poll(ufds, nfds, pending_ms);
-    if(r != -1)
-      break;
-    error = SOCKERRNO;
-    if(error && ERROR_NOT_EINTR(error))
-      break;
-    if(timeout_ms > 0) {
-      pending_ms = (int)(timeout_ms - ELAPSED_MS());
-      if(pending_ms <= 0) {
-        r = 0;  /* Simulate a "call timed out" case */
-        break;
-      }
-    }
-  } while(r == -1);
+  if(timeout_ms < 0)
+    pending_ms = -1;
+  else if(!timeout_ms)
+    pending_ms = 0;
+  r = poll(ufds, nfds, pending_ms);
 
   if(r < 0)
     return -1;
@@ -502,42 +430,27 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, 
int timeout_ms)
 
   ptimeout = (timeout_ms < 0) ? NULL : &pending_tv;
 
-  do {
-    int error;
-    if(timeout_ms > 0) {
-      pending_tv.tv_sec = pending_ms / 1000;
-      pending_tv.tv_usec = (pending_ms % 1000) * 1000;
-    }
-    else if(!timeout_ms) {
-      pending_tv.tv_sec = 0;
-      pending_tv.tv_usec = 0;
-    }
+  if(timeout_ms > 0) {
+    pending_tv.tv_sec = pending_ms / 1000;
+    pending_tv.tv_usec = (pending_ms % 1000) * 1000;
+  }
+  else if(!timeout_ms) {
+    pending_tv.tv_sec = 0;
+    pending_tv.tv_usec = 0;
+  }
 
 #ifdef USE_WINSOCK
-    r = select((int)maxfd + 1,
-               /* WinSock select() can't handle fd_sets with zero bits set, so
-                  don't give it such arguments.  See the comment about this in
-                  Curl_check_socket().
-               */
-               fds_read.fd_count ? &fds_read : NULL,
-               fds_write.fd_count ? &fds_write : NULL,
-               fds_err.fd_count ? &fds_err : NULL, ptimeout);
+  r = select((int)maxfd + 1,
+             /* WinSock select() can't handle fd_sets with zero bits set, so
+                don't give it such arguments.  See the comment about this in
+                Curl_check_socket().
+             */
+             fds_read.fd_count ? &fds_read : NULL,
+             fds_write.fd_count ? &fds_write : NULL,
+             fds_err.fd_count ? &fds_err : NULL, ptimeout);
 #else
-    r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
+  r = select((int)maxfd + 1, &fds_read, &fds_write, &fds_err, ptimeout);
 #endif
-    if(r != -1)
-      break;
-    error = SOCKERRNO;
-    if(error && ERROR_NOT_EINTR(error))
-      break;
-    if(timeout_ms > 0) {
-      pending_ms = timeout_ms - ELAPSED_MS();
-      if(pending_ms <= 0) {
-        r = 0;  /* Simulate a "call timed out" case */
-        break;
-      }
-    }
-  } while(r == -1);
 
   if(r < 0)
     return -1;
diff --git a/lib/select.h b/lib/select.h
index 687ab164c..ec3021aac 100644
--- a/lib/select.h
+++ b/lib/select.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -75,20 +75,12 @@ struct pollfd
 int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
                       curl_socket_t writefd,
                       time_t timeout_ms);
-
 #define SOCKET_READABLE(x,z) \
   Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, (time_t)z)
 #define SOCKET_WRITABLE(x,z) \
   Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, x, (time_t)z)
 
 int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);
-
-/* On non-DOS and non-Winsock platforms, when Curl_ack_eintr is set,
- * EINTR condition is honored and function might exit early without
- * awaiting full timeout.  Otherwise EINTR will be ignored and full
- * timeout will elapse. */
-extern int Curl_ack_eintr;
-
 int Curl_wait_ms(int timeout_ms);
 
 #ifdef TPF
diff --git a/lib/sendf.c b/lib/sendf.c
index 4bfc97864..fe106e7f3 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -43,6 +43,7 @@
 #include "strerror.h"
 #include "select.h"
 #include "strdup.h"
+#include "http2.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -501,6 +502,9 @@ static CURLcode pausewrite(struct Curl_easy *data,
   unsigned int i;
   bool newtype = TRUE;
 
+  /* If this transfers over HTTP/2, pause the stream! */
+  Curl_http2_stream_pause(data, TRUE);
+
   if(s->tempcount) {
     for(i = 0; i< s->tempcount; i++) {
       if(s->tempwrite[i].type == type) {
@@ -529,6 +533,8 @@ static CURLcode pausewrite(struct Curl_easy *data,
     /* update the pointer and the size */
     s->tempwrite[i].buf = newptr;
     s->tempwrite[i].len = newlen;
+
+    len = newlen; /* for the debug output below */
   }
   else {
     dupl = Curl_memdup(ptr, len);
@@ -692,19 +698,20 @@ CURLcode Curl_read_plain(curl_socket_t sockfd,
   ssize_t nread = sread(sockfd, buf, bytesfromsocket);
 
   if(-1 == nread) {
-    int err = SOCKERRNO;
-    int return_error;
+    const int err = SOCKERRNO;
+    const bool return_error =
 #ifdef USE_WINSOCK
-    return_error = WSAEWOULDBLOCK == err;
+      WSAEWOULDBLOCK == err
 #else
-    return_error = EWOULDBLOCK == err || EAGAIN == err || EINTR == err;
+      EWOULDBLOCK == err || EAGAIN == err || EINTR == err
 #endif
+      ;
+    *n = 0; /* no data returned */
     if(return_error)
       return CURLE_AGAIN;
     return CURLE_RECV_ERROR;
   }
 
-  /* we only return number of bytes read when we return OK */
   *n = nread;
   return CURLE_OK;
 }
diff --git a/lib/setopt.c b/lib/setopt.c
index 29cea3590..20acfc4ef 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -2288,7 +2288,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption 
option, va_list param)
 
   case CURLOPT_SSH_KEYFUNCTION:
     /* setting to NULL is fine since the ssh.c functions themselves will
-       then rever to use the internal default */
+       then revert to use the internal default */
     data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
     break;
 
@@ -2391,6 +2391,10 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption 
option, va_list param)
     /* Set the list of mail recipients */
     data->set.mail_rcpt = va_arg(param, struct curl_slist *);
     break;
+  case CURLOPT_MAIL_RCPT_ALLLOWFAILS:
+    /* allow RCPT TO command to fail for some recipients */
+    data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    break;
 #endif
 
   case CURLOPT_SASL_AUTHZID:
@@ -2579,16 +2583,32 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, 
CURLoption option, va_list param)
 #endif
 #ifdef USE_ARES
   case CURLOPT_DNS_SERVERS:
-    result = Curl_set_dns_servers(data, va_arg(param, char *));
+    result = Curl_setstropt(&data->set.str[STRING_DNS_SERVERS],
+                            va_arg(param, char *));
+    if(result)
+      return result;
+    result = Curl_set_dns_servers(data, data->set.str[STRING_DNS_SERVERS]);
     break;
   case CURLOPT_DNS_INTERFACE:
-    result = Curl_set_dns_interface(data, va_arg(param, char *));
+    result = Curl_setstropt(&data->set.str[STRING_DNS_INTERFACE],
+                            va_arg(param, char *));
+    if(result)
+      return result;
+    result = Curl_set_dns_interface(data, data->set.str[STRING_DNS_INTERFACE]);
     break;
   case CURLOPT_DNS_LOCAL_IP4:
-    result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
+    result = Curl_setstropt(&data->set.str[STRING_DNS_LOCAL_IP4],
+                            va_arg(param, char *));
+    if(result)
+      return result;
+    result = Curl_set_dns_local_ip4(data, data->set.str[STRING_DNS_LOCAL_IP4]);
     break;
   case CURLOPT_DNS_LOCAL_IP6:
-    result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
+    result = Curl_setstropt(&data->set.str[STRING_DNS_LOCAL_IP6],
+                            va_arg(param, char *));
+    if(result)
+      return result;
+    result = Curl_set_dns_local_ip6(data, data->set.str[STRING_DNS_LOCAL_IP6]);
     break;
 #endif
   case CURLOPT_TCP_KEEPALIVE:
diff --git a/lib/sha256.c b/lib/sha256.c
index bcaaeae30..352d577e8 100644
--- a/lib/sha256.c
+++ b/lib/sha256.c
@@ -5,7 +5,8 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Florin Petriuc, <address@hidden>
+ * Copyright (C) 2017, Florin Petriuc, <address@hidden>
+ * Copyright (C) 2018 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -35,16 +36,209 @@
 #define USE_OPENSSL_SHA256
 #endif
 
+#endif /* USE_OPENSSL */
+
+#ifdef USE_MBEDTLS
+#include <mbedtls/version.h>
+
+#if(MBEDTLS_VERSION_NUMBER >= 0x02070000)
+  #define HAS_RESULT_CODE_BASED_FUNCTIONS
 #endif
+#endif /* USE_MBEDTLS */
+
+/* Please keep the SSL backend-specific #if branches in this order:
+ *
+ * 1. USE_OPENSSL
+ * 2. USE_GNUTLS_NETTLE
+ * 3. USE_GNUTLS
+ * 4. USE_MBEDTLS
+ * 5. USE_COMMON_CRYPTO
+ * 6. USE_WIN32_CRYPTO
+ *
+ * This ensures that the same SSL branch gets activated throughout this source
+ * file even if multiple backends are enabled at the same time.
+ */
+
+#if defined(USE_OPENSSL_SHA256)
 
-#ifdef USE_OPENSSL_SHA256
 /* When OpenSSL is available we use the SHA256-function from OpenSSL */
 #include <openssl/sha.h>
+
+#elif defined(USE_GNUTLS_NETTLE)
+
+#include <nettle/sha.h>
+
+#include "curl_memory.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+typedef struct sha256_ctx SHA256_CTX;
+
+static void SHA256_Init(SHA256_CTX *ctx)
+{
+  sha256_init(ctx);
+}
+
+static void SHA256_Update(SHA256_CTX *ctx,
+                          const unsigned char *data,
+                          unsigned int length)
+{
+  sha256_update(ctx, length, data);
+}
+
+static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx)
+{
+  sha256_digest(ctx, SHA256_DIGEST_SIZE, digest);
+}
+
+#elif defined(USE_GNUTLS)
+
+#include <gcrypt.h>
+
+#include "curl_memory.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+typedef gcry_md_hd_t SHA256_CTX;
+
+static void SHA256_Init(SHA256_CTX *ctx)
+{
+  gcry_md_open(ctx, GCRY_MD_SHA256, 0);
+}
+
+static void SHA256_Update(SHA256_CTX *ctx,
+                          const unsigned char *data,
+                          unsigned int length)
+{
+  gcry_md_write(*ctx, data, length);
+}
+
+static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx)
+{
+  memcpy(digest, gcry_md_read(*ctx, 0), SHA256_DIGEST_LENGTH);
+  gcry_md_close(*ctx);
+}
+
+#elif defined(USE_MBEDTLS)
+
+#include <mbedtls/sha256.h>
+
+#include "curl_memory.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+typedef mbedtls_sha256_context SHA256_CTX;
+
+static void SHA256_Init(SHA256_CTX *ctx)
+{
+#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS)
+  mbedtls_sha256_starts(ctx, 0);
+#else
+  (void) mbedtls_sha256_starts_ret(ctx, 0);
+#endif
+}
+
+static void SHA256_Update(SHA256_CTX *ctx,
+                          const unsigned char *data,
+                          unsigned int length)
+{
+#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS)
+  mbedtls_sha256_update(ctx, data, length);
+#else
+  (void) mbedtls_sha256_update_ret(ctx, data, length);
+#endif
+}
+
+static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx)
+{
+#if !defined(HAS_RESULT_CODE_BASED_FUNCTIONS)
+  mbedtls_sha256_finish(ctx, digest);
+#else
+  (void) mbedtls_sha256_finish_ret(ctx, digest);
+#endif
+}
+
+#elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
+              (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
+      (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
+              (__IPHONE_OS_VERSION_MAX_ALLOWED >= 20000))
+
+#include <CommonCrypto/CommonDigest.h>
+
+#include "curl_memory.h"
+
+/* The last #include file should be: */
+#include "memdebug.h"
+
+typedef CC_SHA256_CTX SHA256_CTX;
+
+static void SHA256_Init(SHA256_CTX *ctx)
+{
+  (void) CC_SHA256_Init(ctx);
+}
+
+static void SHA256_Update(SHA256_CTX *ctx,
+                          const unsigned char *data,
+                          unsigned int length)
+{
+  (void) CC_SHA256_Update(ctx, data, length);
+}
+
+static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx)
+{
+  (void) CC_SHA256_Final(digest, ctx);
+}
+
+#elif defined(USE_WIN32_CRYPTO)
+
+#include <wincrypt.h>
+
+typedef struct {
+  HCRYPTPROV hCryptProv;
+  HCRYPTHASH hHash;
+} SHA256_CTX;
+
+#if !defined(CALG_SHA_256)
+#define CALG_SHA_256 0x0000800c
+#endif
+
+static void SHA256_Init(SHA256_CTX *ctx)
+{
+  if(CryptAcquireContext(&ctx->hCryptProv, NULL, NULL,
+                         PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
+    CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash);
+  }
+}
+
+static void SHA256_Update(SHA256_CTX *ctx,
+                          const unsigned char *data,
+                          unsigned int length)
+{
+  CryptHashData(ctx->hHash, (unsigned char *) data, length, 0);
+}
+
+static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx)
+{
+  unsigned long length;
+
+  CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
+  if(length == SHA256_DIGEST_LENGTH)
+    CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &length, 0);
+
+  if(ctx->hHash)
+    CryptDestroyHash(ctx->hHash);
+
+  if(ctx->hCryptProv)
+    CryptReleaseContext(ctx->hCryptProv, 0);
+}
+
 #else
 
 /* When no other crypto library is available we use this code segment */
 
-/* ===== start - public domain SHA256 implementation ===== */
 /* This is based on SHA256 implementation in LibTomCrypt that was released into
  * public domain by Tom St Denis. */
 
@@ -95,7 +289,8 @@ typedef struct sha256_state {
   unsigned long state[8], curlen;
   unsigned char buf[64];
 } SHA256_CTX;
-/* the K array */
+
+/* The K array */
 static const unsigned long K[64] = {
   0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
   0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
@@ -111,6 +306,7 @@ static const unsigned long K[64] = {
   0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
   0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
 };
+
 /* Various logical functions */
 #define RORc(x, y) \
 (((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \
@@ -123,13 +319,15 @@ static const unsigned long K[64] = {
 #define Sigma1(x)   (S(x, 6) ^ S(x, 11) ^ S(x, 25))
 #define Gamma0(x)   (S(x, 7) ^ S(x, 18) ^ R(x, 3))
 #define Gamma1(x)   (S(x, 17) ^ S(x, 19) ^ R(x, 10))
-/* compress 512-bits */
+
+/* Compress 512-bits */
 static int sha256_compress(struct sha256_state *md,
                            unsigned char *buf)
 {
   unsigned long S[8], W[64];
   int i;
-  /* copy state into S */
+
+  /* Copy state into S */
   for(i = 0; i < 8; i++) {
     S[i] = md->state[i];
   }
@@ -141,6 +339,7 @@ static int sha256_compress(struct sha256_state *md,
     W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
       W[i - 16];
   }
+
   /* Compress */
 #define RND(a,b,c,d,e,f,g,h,i)                                  \
   unsigned long t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
@@ -153,12 +352,15 @@ static int sha256_compress(struct sha256_state *md,
     t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
     S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
   }
-  /* feedback */
+
+  /* Feedback */
   for(i = 0; i < 8; i++) {
     md->state[i] = md->state[i] + S[i];
   }
+
   return 0;
 }
+
 /* Initialize the hash state */
 static void SHA256_Init(struct sha256_state *md)
 {
@@ -173,7 +375,8 @@ static void SHA256_Init(struct sha256_state *md)
   md->state[6] = 0x1F83D9ABUL;
   md->state[7] = 0x5BE0CD19UL;
 }
-/**
+
+/*
    Process a block of memory though the hash
    @param md     The hash state
    @param in     The data to hash
@@ -185,6 +388,7 @@ static int SHA256_Update(struct sha256_state *md,
                          unsigned long inlen)
 {
   unsigned long n;
+
 #define block_size 64
   if(md->curlen > sizeof(md->buf))
     return -1;
@@ -210,9 +414,11 @@ static int SHA256_Update(struct sha256_state *md,
       }
     }
   }
+
   return 0;
 }
-/**
+
+/*
    Terminate the hash to get the digest
    @param md  The hash state
    @param out [out] The destination of the hash (32 bytes)
@@ -222,13 +428,17 @@ static int SHA256_Final(unsigned char *out,
                         struct sha256_state *md)
 {
   int i;
+
   if(md->curlen >= sizeof(md->buf))
     return -1;
-  /* increase the length of the message */
+
+  /* Increase the length of the message */
   md->length += md->curlen * 8;
-  /* append the '1' bit */
+
+  /* Append the '1' bit */
   md->buf[md->curlen++] = (unsigned char)0x80;
-  /* if the length is currently above 56 bytes we append zeros
+
+  /* If the length is currently above 56 bytes we append zeros
    * then compress.  Then we can fall back to padding zeros and length
    * encoding like normal.
    */
@@ -239,29 +449,44 @@ static int SHA256_Final(unsigned char *out,
     sha256_compress(md, md->buf);
     md->curlen = 0;
   }
-  /* pad up to 56 bytes of zeroes */
+
+  /* Pad up to 56 bytes of zeroes */
   while(md->curlen < 56) {
     md->buf[md->curlen++] = (unsigned char)0;
   }
-  /* store length */
+
+  /* Store length */
   WPA_PUT_BE64(md->buf + 56, md->length);
   sha256_compress(md, md->buf);
-  /* copy output */
+
+  /* Copy output */
   for(i = 0; i < 8; i++)
     WPA_PUT_BE32(out + (4 * i), md->state[i]);
+
   return 0;
 }
-/* ===== end - public domain SHA256 implementation ===== */
 
-#endif
+#endif /* CRYPTO LIBS */
 
-void Curl_sha256it(unsigned char *outbuffer, /* 32 unsigned chars */
-                   const unsigned char *input)
+/*
+ * Curl_sha256it()
+ *
+ * Generates a SHA256 hash for the given input data.
+ *
+ * Parameters:
+ *
+ * output [in/out] - The output buffer.
+ * input  [in]     - The input data.
+ * length [in]     - The input length.
+ */
+void Curl_sha256it(unsigned char *output, const unsigned char *input,
+                   const size_t length)
 {
   SHA256_CTX ctx;
+
   SHA256_Init(&ctx);
-  SHA256_Update(&ctx, input, curlx_uztoui(strlen((char *)input)));
-  SHA256_Final(outbuffer, &ctx);
+  SHA256_Update(&ctx, input, curlx_uztoui(length));
+  SHA256_Final(output, &ctx);
 }
 
 #endif /* CURL_DISABLE_CRYPTO_AUTH */
diff --git a/lib/smtp.c b/lib/smtp.c
index 9d3cfbf49..7d71a2201 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -27,6 +27,9 @@
  * RFC4752 The Kerberos V5 ("GSSAPI") SASL Mechanism
  * RFC4954 SMTP Authentication
  * RFC5321 SMTP protocol
+ * RFC5890 Internationalized Domain Names for Applications (IDNA)
+ * RFC6531 SMTP Extension for Internationalized Email
+ * RFC6532 Internationalized Email Headers
  * RFC6749 OAuth 2.0 Authorization Framework
  * RFC8314 Use of TLS for Email Submission and Access
  * Draft   SMTP URL Interface   <draft-earhart-url-smtp-00.txt>
@@ -101,6 +104,8 @@ static CURLcode smtp_setup_connection(struct connectdata 
*conn);
 static CURLcode smtp_parse_url_options(struct connectdata *conn);
 static CURLcode smtp_parse_url_path(struct connectdata *conn);
 static CURLcode smtp_parse_custom_request(struct connectdata *conn);
+static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma,
+                                   char **address, struct hostname *host);
 static CURLcode smtp_perform_auth(struct connectdata *conn, const char *mech,
                                   const char *initresp);
 static CURLcode smtp_continue_auth(struct connectdata *conn, const char *resp);
@@ -481,13 +486,55 @@ static CURLcode smtp_perform_command(struct connectdata 
*conn)
   struct Curl_easy *data = conn->data;
   struct SMTP *smtp = data->req.protop;
 
-  /* Send the command */
-  if(smtp->rcpt)
-    result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s",
-                           smtp->custom && smtp->custom[0] != '\0' ?
-                           smtp->custom : "VRFY",
-                           smtp->rcpt->data);
+  if(smtp->rcpt) {
+    /* We notify the server we are sending UTF-8 data if a) it supports the
+       SMTPUTF8 extension and b) The mailbox contains UTF-8 charaacters, in
+       either the local address or host name parts. This is regardless of
+       whether the host name is encoded using IDN ACE */
+    bool utf8 = FALSE;
+
+    if((!smtp->custom) || (!smtp->custom[0])) {
+      char *address = NULL;
+      struct hostname host = { NULL, NULL, NULL, NULL };
+
+      /* Parse the mailbox to verify into the local address and host name
+         parts, converting the host name to an IDN A-label if necessary */
+      result = smtp_parse_address(conn, smtp->rcpt->data,
+                                  &address, &host);
+      if(result)
+        return result;
+
+      /* Establish whether we should report SMTPUTF8 to the server for this
+         mailbox as per RFC-6531 sect. 3.1 point 6 */
+      utf8 = (conn->proto.smtpc.utf8_supported) &&
+             ((host.encalloc) || (!Curl_is_ASCII_name(address)) ||
+              (!Curl_is_ASCII_name(host.name)));
+
+      /* Send the VRFY command (Note: The host name part may be absent when the
+         host is a local system) */
+      result = Curl_pp_sendf(&conn->proto.smtpc.pp, "VRFY %s%s%s%s",
+                             address,
+                             host.name ? "@" : "",
+                             host.name ? host.name : "",
+                             utf8 ? " SMTPUTF8" : "");
+
+      Curl_free_idnconverted_hostname(&host);
+      free(address);
+    }
+    else {
+      /* Establish whether we should report that we support SMTPUTF8 for EXPN
+         commands to the server as per RFC-6531 sect. 3.1 point 6 */
+      utf8 = (conn->proto.smtpc.utf8_supported) &&
+             (!strcmp(smtp->custom, "EXPN"));
+
+      /* Send the custom recipient based command such as the EXPN command */
+      result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s %s%s", smtp->custom,
+                             smtp->rcpt->data,
+                             utf8 ? " SMTPUTF8" : "");
+    }
+  }
   else
+    /* Send the non-recipient based command such as HELP */
     result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s",
                            smtp->custom && smtp->custom[0] != '\0' ?
                            smtp->custom : "HELP");
@@ -512,22 +559,86 @@ static CURLcode smtp_perform_mail(struct connectdata 
*conn)
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
 
+  /* We notify the server we are sending UTF-8 data if a) it supports the
+     SMTPUTF8 extension and b) The mailbox contains UTF-8 charaacters, in
+     either the local address or host name parts. This is regardless of
+     whether the host name is encoded using IDN ACE */
+  bool utf8 = FALSE;
+
   /* Calculate the FROM parameter */
-  if(!data->set.str[STRING_MAIL_FROM])
+  if(data->set.str[STRING_MAIL_FROM]) {
+    char *address = NULL;
+    struct hostname host = { NULL, NULL, NULL, NULL };
+
+    /* Parse the FROM mailbox into the local address and host name parts,
+       converting the host name to an IDN A-label if necessary */
+    result = smtp_parse_address(conn, data->set.str[STRING_MAIL_FROM],
+                                &address, &host);
+    if(result)
+      return result;
+
+    /* Establish whether we should report SMTPUTF8 to the server for this
+       mailbox as per RFC-6531 sect. 3.1 point 4 and sect. 3.4 */
+    utf8 = (conn->proto.smtpc.utf8_supported) &&
+           ((host.encalloc) || (!Curl_is_ASCII_name(address)) ||
+            (!Curl_is_ASCII_name(host.name)));
+
+    if(host.name) {
+      from = aprintf("<%s@%s>", address, host.name);
+
+      Curl_free_idnconverted_hostname(&host);
+    }
+    else
+      /* An invalid mailbox was provided but we'll simply let the server worry
+         about that and reply with a 501 error */
+      from = aprintf("<%s>", address);
+
+    free(address);
+  }
+  else
     /* Null reverse-path, RFC-5321, sect. 3.6.3 */
     from = strdup("<>");
-  else if(data->set.str[STRING_MAIL_FROM][0] == '<')
-    from = aprintf("%s", data->set.str[STRING_MAIL_FROM]);
-  else
-    from = aprintf("<%s>", data->set.str[STRING_MAIL_FROM]);
 
   if(!from)
     return CURLE_OUT_OF_MEMORY;
 
   /* Calculate the optional AUTH parameter */
   if(data->set.str[STRING_MAIL_AUTH] && conn->proto.smtpc.sasl.authused) {
-    if(data->set.str[STRING_MAIL_AUTH][0] != '\0')
-      auth = aprintf("%s", data->set.str[STRING_MAIL_AUTH]);
+    if(data->set.str[STRING_MAIL_AUTH][0] != '\0') {
+      char *address = NULL;
+      struct hostname host = { NULL, NULL, NULL, NULL };
+
+      /* Parse the AUTH mailbox into the local address and host name parts,
+         converting the host name to an IDN A-label if necessary */
+      result = smtp_parse_address(conn, data->set.str[STRING_MAIL_AUTH],
+                                  &address, &host);
+      if(result) {
+        free(from);
+        return result;
+      }
+
+      /* Establish whether we should report SMTPUTF8 to the server for this
+         mailbox as per RFC-6531 sect. 3.1 point 4 and sect. 3.4 */
+      if((!utf8) && (conn->proto.smtpc.utf8_supported) &&
+         ((host.encalloc) || (!Curl_is_ASCII_name(address)) ||
+          (!Curl_is_ASCII_name(host.name))))
+        utf8 = TRUE;
+
+      if(host.name) {
+        free(from);
+        from = aprintf("<%s@%s>", address, host.name);
+
+        Curl_free_idnconverted_hostname(&host);
+      }
+      else
+        /* An invalid mailbox was provided but we'll simply let the server
+           worry about it */
+        auth = aprintf("<%s>", address);
+
+      free(address);
+      if(!from)
+        return CURLE_OUT_OF_MEMORY;
+    }
     else
       /* Empty AUTH, RFC-2554, sect. 5 */
       auth = strdup("<>");
@@ -561,6 +672,7 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
     if(result) {
       free(from);
       free(auth);
+
       return result;
     }
 
@@ -583,19 +695,33 @@ static CURLcode smtp_perform_mail(struct connectdata 
*conn)
     }
   }
 
+  /* If the mailboxes in the FROM and AUTH parameters don't include a UTF-8
+     based address then quickly scan through the recipient list and check if
+     any there do, as we need to correctly identify our support for SMTPUTF8
+     in the envelope, as per RFC-6531 sect. 3.4 */
+  if(conn->proto.smtpc.utf8_supported && !utf8) {
+    struct SMTP *smtp = data->req.protop;
+    struct curl_slist *rcpt = smtp->rcpt;
+
+    while(rcpt && !utf8) {
+      /* Does the host name contain non-ASCII characters? */
+      if(!Curl_is_ASCII_name(rcpt->data))
+        utf8 = TRUE;
+
+      rcpt = rcpt->next;
+    }
+  }
+
   /* Send the MAIL command */
-  if(!auth && !size)
-    result = Curl_pp_sendf(&conn->proto.smtpc.pp,
-                           "MAIL FROM:%s", from);
-  else if(auth && !size)
-    result = Curl_pp_sendf(&conn->proto.smtpc.pp,
-                           "MAIL FROM:%s AUTH=%s", from, auth);
-  else if(auth && size)
-    result = Curl_pp_sendf(&conn->proto.smtpc.pp,
-                           "MAIL FROM:%s AUTH=%s SIZE=%s", from, auth, size);
-  else
-    result = Curl_pp_sendf(&conn->proto.smtpc.pp,
-                           "MAIL FROM:%s SIZE=%s", from, size);
+  result = Curl_pp_sendf(&conn->proto.smtpc.pp,
+                         "MAIL FROM:%s%s%s%s%s%s",
+                         from,                 /* Mandatory                 */
+                         auth ? " AUTH=" : "", /* Optional on AUTH support  */
+                         auth ? auth : "",     /*                           */
+                         size ? " SIZE=" : "", /* Optional on SIZE support  */
+                         size ? size : "",     /*                           */
+                         utf8 ? " SMTPUTF8"    /* Internationalised mailbox */
+                               : "");          /* included in our envelope  */
 
   free(from);
   free(auth);
@@ -619,14 +745,28 @@ static CURLcode smtp_perform_rcpt_to(struct connectdata 
*conn)
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
   struct SMTP *smtp = data->req.protop;
+  char *address = NULL;
+  struct hostname host = { NULL, NULL, NULL, NULL };
+
+  /* Parse the recipient mailbox into the local address and host name parts,
+     converting the host name to an IDN A-label if necessary */
+  result = smtp_parse_address(conn, smtp->rcpt->data,
+                              &address, &host);
+  if(result)
+    return result;
 
   /* Send the RCPT TO command */
-  if(smtp->rcpt->data[0] == '<')
-    result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:%s",
-                           smtp->rcpt->data);
+  if(host.name)
+    result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s@%s>", address,
+                           host.name);
   else
-    result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>",
-                           smtp->rcpt->data);
+    /* An invalid mailbox was provided but we'll simply let the server worry
+       about that and reply with a 501 error */
+    result = Curl_pp_sendf(&conn->proto.smtpc.pp, "RCPT TO:<%s>", address);
+
+  Curl_free_idnconverted_hostname(&host);
+  free(address);
+
   if(!result)
     state(conn, SMTP_RCPT);
 
@@ -726,6 +866,10 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata 
*conn, int smtpcode,
     else if(len >= 4 && !memcmp(line, "SIZE", 4))
       smtpc->size_supported = TRUE;
 
+    /* Does the server support the UTF-8 capability? */
+    else if(len >= 8 && !memcmp(line, "SMTPUTF8", 8))
+      smtpc->utf8_supported = TRUE;
+
     /* Does the server support authentication? */
     else if(len >= 5 && !memcmp(line, "AUTH ", 5)) {
       smtpc->auth_supported = TRUE;
@@ -915,25 +1059,53 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata 
*conn, int smtpcode,
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
   struct SMTP *smtp = data->req.protop;
+  bool is_smtp_err = FALSE;
+  bool is_smtp_blocking_err = FALSE;
 
   (void)instate; /* no use for this yet */
 
-  if(smtpcode/100 != 2) {
-    failf(data, "RCPT failed: %d", smtpcode);
-    result = CURLE_SEND_ERROR;
+  is_smtp_err = (smtpcode/100 != 2) ? TRUE : FALSE;
+
+  /* If there's multiple RCPT TO to be issued, it's possible to ignore errors
+     and proceed with only the valid addresses. */
+  is_smtp_blocking_err =
+    (is_smtp_err && !data->set.mail_rcpt_allowfails) ? TRUE : FALSE;
+
+  if(is_smtp_err) {
+    /* Remembering the last failure which we can report if all "RCPT TO" have
+       failed and we cannot proceed. */
+    smtp->rcpt_last_error = smtpcode;
+
+    if(is_smtp_blocking_err) {
+      failf(data, "RCPT failed: %d", smtpcode);
+      result = CURLE_SEND_ERROR;
+    }
   }
   else {
+    /* Some RCPT TO commands have succeeded. */
+    smtp->rcpt_had_ok = TRUE;
+  }
+
+  if(!is_smtp_blocking_err) {
     smtp->rcpt = smtp->rcpt->next;
 
     if(smtp->rcpt)
       /* Send the next RCPT TO command */
       result = smtp_perform_rcpt_to(conn);
     else {
-      /* Send the DATA command */
-      result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA");
+      /* We weren't able to issue a successful RCPT TO command while going
+         over recipients (potentially multiple). Sending back last error. */
+      if(!smtp->rcpt_had_ok) {
+        failf(data, "RCPT failed: %d (last error)", smtp->rcpt_last_error);
+        result = CURLE_SEND_ERROR;
+      }
+      else {
+        /* Send the DATA command */
+        result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", "DATA");
 
-      if(!result)
-        state(conn, SMTP_DATA);
+        if(!result)
+          state(conn, SMTP_DATA);
+      }
     }
   }
 
@@ -1287,6 +1459,12 @@ static CURLcode smtp_perform(struct connectdata *conn, 
bool *connected,
   /* Store the first recipient (or NULL if not specified) */
   smtp->rcpt = data->set.mail_rcpt;
 
+  /* Track of whether we've successfully sent at least one RCPT TO command */
+  smtp->rcpt_had_ok = FALSE;
+
+  /* Track of the last error we've received by sending RCPT TO command */
+  smtp->rcpt_last_error = 0;
+
   /* Initial data character is the first character in line: it is implicitly
      preceded by a virtual CRLF. */
   smtp->trailing_crlf = TRUE;
@@ -1537,6 +1715,76 @@ static CURLcode smtp_parse_custom_request(struct 
connectdata *conn)
   return result;
 }
 
+/***********************************************************************
+ *
+ * smtp_parse_address()
+ *
+ * Parse the fully qualified mailbox address into a local address part and the
+ * host name, converting the host name to an IDN A-label, as per RFC-5890, if
+ * necessary.
+ *
+ * Parameters:
+ *
+ * conn  [in]              - The connection handle.
+ * fqma  [in]              - The fully qualified mailbox address (which may or
+ *                           may not contain UTF-8 characters).
+ * address        [in/out] - A new allocated buffer which holds the local
+ *                           address part of the mailbox. This buffer must be
+ *                           free'ed by the caller.
+ * host           [in/out] - The host name structure that holds the original,
+ *                           and optionally encoded, host name.
+ *                           Curl_free_idnconverted_hostname() must be called
+ *                           once the caller has finished with the structure.
+ *
+ * Returns CURLE_OK on success.
+ *
+ * Notes:
+ *
+ * Should a UTF-8 host name require conversion to IDN ACE and we cannot honor
+ * that convertion then we shall return success. This allow the caller to send
+ * the data to the server as a U-label (as per RFC-6531 sect. 3.2).
+ *
+ * If an mailbox '@' seperator cannot be located then the mailbox is considered
+ * to be either a local mailbox or an invalid mailbox (depending on what the
+ * calling function deems it to be) then the input will simply be returned in
+ * the address part with the host name being NULL.
+ */
+static CURLcode smtp_parse_address(struct connectdata *conn, const char *fqma,
+                                   char **address, struct hostname *host)
+{
+  CURLcode result = CURLE_OK;
+  size_t length;
+
+  /* Duplicate the fully qualified email address so we can manipulate it,
+     ensuring it doesn't contain the delimiters if specified */
+  char *dup = strdup(fqma[0] == '<' ? fqma + 1  : fqma);
+  if(!dup)
+    return CURLE_OUT_OF_MEMORY;
+
+  length = strlen(dup);
+  if(dup[length - 1] == '>')
+    dup[length - 1] = '\0';
+
+  /* Extract the host name from the addresss (if we can) */
+  host->name = strpbrk(dup, "@");
+  if(host->name) {
+    *host->name = '\0';
+    host->name = host->name + 1;
+
+    /* Attempt to convert the host name to IDN ACE */
+    (void) Curl_idnconvert_hostname(conn, host);
+
+    /* If Curl_idnconvert_hostname() fails then we shall attempt to continue
+       and send the host name using UTF-8 rather than as 7-bit ACE (which is
+       our preference) */
+  }
+
+  /* Extract the local address from the mailbox */
+  *address = dup;
+
+  return result;
+}
+
 CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
 {
   /* When sending a SMTP payload we must detect CRLF. sequences making sure
diff --git a/lib/smtp.h b/lib/smtp.h
index 20fc08119..164a175d7 100644
--- a/lib/smtp.h
+++ b/lib/smtp.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2009 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2009 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -55,6 +55,9 @@ struct SMTP {
   curl_pp_transfer transfer;
   char *custom;            /* Custom Request */
   struct curl_slist *rcpt; /* Recipient list */
+  bool rcpt_had_ok;        /* Whether any of RCPT TO commands (depends on
+                              total number of recipients) succeeded so far */
+  int rcpt_last_error;     /* The last error received for RCPT TO command */
   size_t eob;              /* Number of bytes of the EOB (End Of Body) that
                               have been received so far */
   bool trailing_crlf;      /* Specifies if the tailing CRLF is present */
@@ -71,6 +74,8 @@ struct smtp_conn {
   bool tls_supported;      /* StartTLS capability supported by server */
   bool size_supported;     /* If server supports SIZE extension according to
                               RFC 1870 */
+  bool utf8_supported;     /* If server supports SMTPUTF8 extension according
+                              to RFC 6531 */
   bool auth_supported;     /* AUTH capability supported by server */
 };
 
diff --git a/lib/socks.c b/lib/socks.c
index 6ae98184d..37099130e 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -37,18 +37,19 @@
 #include "connect.h"
 #include "timeval.h"
 #include "socks.h"
+#include "multiif.h" /* for getsock macros */
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "memdebug.h"
 
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
 /*
  * Helper read-from-socket functions. Does the same as Curl_read() but it
  * blocks until all bytes amount of buffersize will be read. No more, no less.
  *
- * This is STUPID BLOCKING behaviour which we frown upon, but right now this
- * is what we have...
+ * This is STUPID BLOCKING behavior. Only used by the SOCKS GSSAPI functions.
  */
 int Curl_blockread_all(struct connectdata *conn, /* connection data */
                        curl_socket_t sockfd,     /* read from this socket */
@@ -94,6 +95,81 @@ int Curl_blockread_all(struct connectdata *conn, /* 
connection data */
   }
   return result;
 }
+#endif
+
+#ifndef DEBUGBUILD
+#define sxstate(x,y) socksstate(x,y)
+#else
+#define sxstate(x,y) socksstate(x,y, __LINE__)
+#endif
+
+
+/* always use this function to change state, to make debugging easier */
+static void socksstate(struct connectdata *conn,
+                       enum connect_t state
+#ifdef DEBUGBUILD
+                       , int lineno
+#endif
+)
+{
+  enum connect_t oldstate = conn->cnnct.state;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+  /* synced with the state list in urldata.h */
+  static const char * const statename[] = {
+    "INIT",
+    "SOCKS_INIT",
+    "SOCKS_SEND",
+    "SOCKS_READ_INIT",
+    "SOCKS_READ",
+    "GSSAPI_INIT",
+    "AUTH_INIT",
+    "AUTH_SEND",
+    "AUTH_READ",
+    "REQ_INIT",
+    "RESOLVING",
+    "RESOLVED",
+    "RESOLVE_REMOTE",
+    "REQ_SEND",
+    "REQ_SENDING",
+    "REQ_READ",
+    "REQ_READ_MORE",
+    "DONE"
+  };
+#endif
+
+  if(oldstate == state)
+    /* don't bother when the new state is the same as the old state */
+    return;
+
+  conn->cnnct.state = state;
+
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+  infof(conn->data,
+        "SXSTATE: %s => %s conn %p; line %d\n",
+        statename[oldstate], statename[conn->cnnct.state], conn,
+        lineno);
+#endif
+}
+
+int Curl_SOCKS_getsock(struct connectdata *conn, curl_socket_t *sock,
+                       int sockindex)
+{
+  int rc = 0;
+  sock[0] = conn->sock[sockindex];
+  switch(conn->cnnct.state) {
+  case CONNECT_RESOLVING:
+  case CONNECT_SOCKS_READ:
+  case CONNECT_AUTH_READ:
+  case CONNECT_REQ_READ:
+  case CONNECT_REQ_READ_MORE:
+    rc = GETSOCK_READSOCK(0);
+    break;
+  default:
+    rc = GETSOCK_WRITESOCK(0);
+    break;
+  }
+  return rc;
+}
 
 /*
 * This function logs in to a SOCKS4 proxy and sends the specifics to the final
@@ -110,62 +186,91 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
                      const char *hostname,
                      int remote_port,
                      int sockindex,
-                     struct connectdata *conn)
+                     struct connectdata *conn,
+                     bool *done)
 {
   const bool protocol4a =
     (conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
-#define SOCKS4REQLEN 262
-  unsigned char socksreq[SOCKS4REQLEN]; /* room for SOCKS4 request incl. user
-                                           id */
-  CURLcode code;
-  curl_socket_t sock = conn->sock[sockindex];
+  unsigned char *socksreq = &conn->cnnct.socksreq[0];
+  CURLcode result;
+  curl_socket_t sockfd = conn->sock[sockindex];
   struct Curl_easy *data = conn->data;
+  struct connstate *sx = &conn->cnnct;
+  struct Curl_dns_entry *dns = NULL;
+  ssize_t actualread;
+  ssize_t written;
 
-  if(Curl_timeleft(data, NULL, TRUE) < 0) {
-    /* time-out, bail out, go home */
-    failf(data, "Connection time-out");
-    return CURLE_OPERATION_TIMEDOUT;
-  }
-
-  if(conn->bits.httpproxy)
-    infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
-          protocol4a ? "a" : "", hostname, remote_port);
-
-  (void)curlx_nonblock(sock, FALSE);
+  if(!SOCKS_STATE(sx->state) && !*done)
+    sxstate(conn, CONNECT_SOCKS_INIT);
 
-  infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
+  switch(sx->state) {
+  case CONNECT_SOCKS_INIT:
+    /* SOCKS4 can only do IPv4, insist! */
+    conn->ip_version = CURL_IPRESOLVE_V4;
+    if(conn->bits.httpproxy)
+      infof(conn->data, "SOCKS4%s: connecting to HTTP proxy %s port %d\n",
+            protocol4a ? "a" : "", hostname, remote_port);
 
-  /*
-   * Compose socks4 request
-   *
-   * Request format
-   *
-   *     +----+----+----+----+----+----+----+----+----+----+....+----+
-   *     | VN | CD | DSTPORT |      DSTIP        | USERID       |NULL|
-   *     +----+----+----+----+----+----+----+----+----+----+....+----+
-   * # of bytes:  1    1      2              4           variable       1
-   */
+    infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port);
 
-  socksreq[0] = 4; /* version (SOCKS4) */
-  socksreq[1] = 1; /* connect */
-  socksreq[2] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */
-  socksreq[3] = (unsigned char)(remote_port & 0xff);        /* PORT LSB */
-
-  /* DNS resolve only for SOCKS4, not SOCKS4a */
-  if(!protocol4a) {
-    struct Curl_dns_entry *dns;
-    Curl_addrinfo *hp = NULL;
-    int rc;
+    /*
+     * Compose socks4 request
+     *
+     * Request format
+     *
+     *     +----+----+----+----+----+----+----+----+----+----+....+----+
+     *     | VN | CD | DSTPORT |      DSTIP        | USERID       |NULL|
+     *     +----+----+----+----+----+----+----+----+----+----+....+----+
+     * # of bytes:  1    1      2              4           variable       1
+     */
 
-    rc = Curl_resolv(conn, hostname, remote_port, FALSE, &dns);
+    socksreq[0] = 4; /* version (SOCKS4) */
+    socksreq[1] = 1; /* connect */
+    socksreq[2] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */
+    socksreq[3] = (unsigned char)(remote_port & 0xff);        /* PORT LSB */
+
+    /* DNS resolve only for SOCKS4, not SOCKS4a */
+    if(!protocol4a) {
+      enum resolve_t rc =
+        Curl_resolv(conn, hostname, remote_port, FALSE, &dns);
+
+      if(rc == CURLRESOLV_ERROR)
+        return CURLE_COULDNT_RESOLVE_PROXY;
+      else if(rc == CURLRESOLV_PENDING) {
+        sxstate(conn, CONNECT_RESOLVING);
+        infof(data, "SOCKS4 non-blocking resolve of %s\n", hostname);
+        return CURLE_OK;
+      }
+      sxstate(conn, CONNECT_RESOLVED);
+      goto CONNECT_RESOLVED;
+    }
 
-    if(rc == CURLRESOLV_ERROR)
-      return CURLE_COULDNT_RESOLVE_PROXY;
+    /* socks4a doesn't resolve anything locally */
+    sxstate(conn, CONNECT_REQ_INIT);
+    goto CONNECT_REQ_INIT;
 
-    if(rc == CURLRESOLV_PENDING)
-      /* ignores the return code, but 'dns' remains NULL on failure */
-      (void)Curl_resolver_wait_resolv(conn, &dns);
+  case CONNECT_RESOLVING:
+    /* check if we have the name resolved by now */
+    dns = Curl_fetch_addr(conn, hostname, (int)conn->port);
 
+    if(dns) {
+#ifdef CURLRES_ASYNCH
+      conn->async.dns = dns;
+      conn->async.done = TRUE;
+#endif
+      infof(data, "Hostname '%s' was found\n", hostname);
+      sxstate(conn, CONNECT_RESOLVED);
+    }
+    else {
+      result = Curl_resolv_check(data->conn, &dns);
+      if(!dns)
+        return result;
+    }
+    /* FALLTHROUGH */
+  CONNECT_RESOLVED:
+  case CONNECT_RESOLVED: {
+    Curl_addrinfo *hp = NULL;
+    char buf[64];
     /*
      * We cannot use 'hostent' as a struct that Curl_resolv() returns.  It
      * returns a Curl_addrinfo pointer that may not always look the same.
@@ -173,7 +278,6 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
     if(dns)
       hp = dns->addr;
     if(hp) {
-      char buf[64];
       Curl_printable_address(hp, buf, sizeof(buf));
 
       if(hp->ai_family == AF_INET) {
@@ -189,7 +293,6 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
       }
       else {
         hp = NULL; /* fail! */
-
         failf(data, "SOCKS4 connection to %s not supported\n", buf);
       }
 
@@ -201,149 +304,166 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
       return CURLE_COULDNT_RESOLVE_HOST;
     }
   }
-
-  /*
-   * This is currently not supporting "Identification Protocol (RFC1413)".
-   */
-  socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
-  if(proxy_user) {
-    size_t plen = strlen(proxy_user);
-    if(plen >= sizeof(socksreq) - 8) {
-      failf(data, "Too long SOCKS proxy name, can't use!\n");
-      return CURLE_COULDNT_CONNECT;
+    /* FALLTHROUGH */
+  CONNECT_REQ_INIT:
+  case CONNECT_REQ_INIT:
+    /*
+     * This is currently not supporting "Identification Protocol (RFC1413)".
+     */
+    socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
+    if(proxy_user) {
+      size_t plen = strlen(proxy_user);
+      if(plen >= sizeof(sx->socksreq) - 8) {
+        failf(data, "Too long SOCKS proxy name, can't use!\n");
+        return CURLE_COULDNT_CONNECT;
+      }
+      /* copy the proxy name WITH trailing zero */
+      memcpy(socksreq + 8, proxy_user, plen + 1);
     }
-    /* copy the proxy name WITH trailing zero */
-    memcpy(socksreq + 8, proxy_user, plen + 1);
-  }
 
-  /*
-   * Make connection
-   */
-  {
-    int result;
-    ssize_t actualread;
-    ssize_t written;
-    ssize_t hostnamelen = 0;
-    ssize_t packetsize = 9 +
-      strlen((char *)socksreq + 8); /* size including NUL */
-
-    /* If SOCKS4a, set special invalid IP address 0.0.0.x */
-    if(protocol4a) {
-      socksreq[4] = 0;
-      socksreq[5] = 0;
-      socksreq[6] = 0;
-      socksreq[7] = 1;
-      /* If still enough room in buffer, also append hostname */
-      hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */
-      if(packetsize + hostnamelen <= SOCKS4REQLEN)
-        strcpy((char *)socksreq + packetsize, hostname);
-      else
-        hostnamelen = 0; /* Flag: hostname did not fit in buffer */
+    /*
+     * Make connection
+     */
+    {
+      ssize_t packetsize = 9 +
+        strlen((char *)socksreq + 8); /* size including NUL */
+
+      /* If SOCKS4a, set special invalid IP address 0.0.0.x */
+      if(protocol4a) {
+        ssize_t hostnamelen = 0;
+        socksreq[4] = 0;
+        socksreq[5] = 0;
+        socksreq[6] = 0;
+        socksreq[7] = 1;
+        /* append hostname */
+        hostnamelen = (ssize_t)strlen(hostname) + 1; /* length including NUL */
+        if(hostnamelen <= 255)
+          strcpy((char *)socksreq + packetsize, hostname);
+        else {
+          failf(data, "SOCKS4: too long host name");
+          return CURLE_COULDNT_CONNECT;
+        }
+        packetsize += hostnamelen;
+      }
+      sx->outp = socksreq;
+      sx->outstanding = packetsize;
+      sxstate(conn, CONNECT_REQ_SENDING);
     }
-
+    /* FALLTHROUGH */
+  case CONNECT_REQ_SENDING:
     /* Send request */
-    code = Curl_write_plain(conn, sock, (char *)socksreq,
-                            packetsize + hostnamelen,
-                            &written);
-    if(code || (written != packetsize + hostnamelen)) {
+    result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
+                              sx->outstanding, &written);
+    if(result && (CURLE_AGAIN != result)) {
       failf(data, "Failed to send SOCKS4 connect request.");
       return CURLE_COULDNT_CONNECT;
     }
-    if(protocol4a && hostnamelen == 0) {
-      /* SOCKS4a with very long hostname - send that name separately */
-      hostnamelen = (ssize_t)strlen(hostname) + 1;
-      code = Curl_write_plain(conn, sock, (char *)hostname, hostnamelen,
-                              &written);
-      if(code || (written != hostnamelen)) {
-        failf(data, "Failed to send SOCKS4 connect request.");
-        return CURLE_COULDNT_CONNECT;
-      }
+    if(written != sx->outstanding) {
+      /* not done, remain in state */
+      sx->outstanding -= written;
+      sx->outp += written;
+      return CURLE_OK;
     }
 
-    packetsize = 8; /* receive data size */
+    /* done sending! */
+    sx->outstanding = 8; /* receive data size */
+    sx->outp = socksreq;
+    sxstate(conn, CONNECT_SOCKS_READ);
 
+    /* FALLTHROUGH */
+  case CONNECT_SOCKS_READ:
     /* Receive response */
-    result = Curl_blockread_all(conn, sock, (char *)socksreq, packetsize,
-                                &actualread);
-    if(result || (actualread != packetsize)) {
-      failf(data, "Failed to receive SOCKS4 connect request ack.");
+    result = Curl_read_plain(sockfd, (char *)sx->outp,
+                             sx->outstanding, &actualread);
+    if(result && (CURLE_AGAIN != result)) {
+      failf(data, "SOCKS4: Failed receiving connect request ack: %s",
+            curl_easy_strerror(result));
       return CURLE_COULDNT_CONNECT;
     }
-
-    /*
-     * Response format
-     *
-     *     +----+----+----+----+----+----+----+----+
-     *     | VN | CD | DSTPORT |      DSTIP        |
-     *     +----+----+----+----+----+----+----+----+
-     * # of bytes:  1    1      2              4
-     *
-     * VN is the version of the reply code and should be 0. CD is the result
-     * code with one of the following values:
-     *
-     * 90: request granted
-     * 91: request rejected or failed
-     * 92: request rejected because SOCKS server cannot connect to
-     *     identd on the client
-     * 93: request rejected because the client program and identd
-     *     report different user-ids
-     */
-
-    /* wrong version ? */
-    if(socksreq[0] != 0) {
-      failf(data,
-            "SOCKS4 reply has wrong version, version should be 0.");
-      return CURLE_COULDNT_CONNECT;
+    else if(actualread != sx->outstanding) {
+      /* remain in reading state */
+      sx->outstanding -= actualread;
+      sx->outp += actualread;
+      return CURLE_OK;
     }
+    sxstate(conn, CONNECT_DONE);
+    break;
+  default: /* lots of unused states in SOCKS4 */
+    break;
+  }
 
-    /* Result */
-    switch(socksreq[1]) {
-    case 90:
-      infof(data, "SOCKS4%s request granted.\n", protocol4a?"a":"");
-      break;
-    case 91:
-      failf(data,
-            "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
-            ", request rejected or failed.",
-            (unsigned char)socksreq[4], (unsigned char)socksreq[5],
-            (unsigned char)socksreq[6], (unsigned char)socksreq[7],
-            (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
-            (unsigned char)socksreq[1]);
-      return CURLE_COULDNT_CONNECT;
-    case 92:
-      failf(data,
-            "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
-            ", request rejected because SOCKS server cannot connect to "
-            "identd on the client.",
-            (unsigned char)socksreq[4], (unsigned char)socksreq[5],
-            (unsigned char)socksreq[6], (unsigned char)socksreq[7],
-            (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
-            (unsigned char)socksreq[1]);
-      return CURLE_COULDNT_CONNECT;
-    case 93:
-      failf(data,
-            "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
-            ", request rejected because the client program and identd "
-            "report different user-ids.",
-            (unsigned char)socksreq[4], (unsigned char)socksreq[5],
-            (unsigned char)socksreq[6], (unsigned char)socksreq[7],
-            (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
-            (unsigned char)socksreq[1]);
-      return CURLE_COULDNT_CONNECT;
-    default:
-      failf(data,
-            "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
-            ", Unknown.",
-            (unsigned char)socksreq[4], (unsigned char)socksreq[5],
-            (unsigned char)socksreq[6], (unsigned char)socksreq[7],
-            (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
-            (unsigned char)socksreq[1]);
-      return CURLE_COULDNT_CONNECT;
-    }
+  /*
+   * Response format
+   *
+   *     +----+----+----+----+----+----+----+----+
+   *     | VN | CD | DSTPORT |      DSTIP        |
+   *     +----+----+----+----+----+----+----+----+
+   * # of bytes:  1    1      2              4
+   *
+   * VN is the version of the reply code and should be 0. CD is the result
+   * code with one of the following values:
+   *
+   * 90: request granted
+   * 91: request rejected or failed
+   * 92: request rejected because SOCKS server cannot connect to
+   *     identd on the client
+   * 93: request rejected because the client program and identd
+   *     report different user-ids
+   */
+
+  /* wrong version ? */
+  if(socksreq[0] != 0) {
+    failf(data,
+          "SOCKS4 reply has wrong version, version should be 0.");
+    return CURLE_COULDNT_CONNECT;
   }
 
-  (void)curlx_nonblock(sock, TRUE);
+  /* Result */
+  switch(socksreq[1]) {
+  case 90:
+    infof(data, "SOCKS4%s request granted.\n", protocol4a?"a":"");
+    break;
+  case 91:
+    failf(data,
+          "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
+          ", request rejected or failed.",
+          (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+          (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+          (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
+          (unsigned char)socksreq[1]);
+    return CURLE_COULDNT_CONNECT;
+  case 92:
+    failf(data,
+          "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
+          ", request rejected because SOCKS server cannot connect to "
+          "identd on the client.",
+          (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+          (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+          (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
+          (unsigned char)socksreq[1]);
+    return CURLE_COULDNT_CONNECT;
+  case 93:
+    failf(data,
+          "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
+          ", request rejected because the client program and identd "
+          "report different user-ids.",
+          (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+          (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+          (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
+          (unsigned char)socksreq[1]);
+    return CURLE_COULDNT_CONNECT;
+  default:
+    failf(data,
+          "Can't complete SOCKS4 connection to %d.%d.%d.%d:%d. (%d)"
+          ", Unknown.",
+          (unsigned char)socksreq[4], (unsigned char)socksreq[5],
+          (unsigned char)socksreq[6], (unsigned char)socksreq[7],
+          (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
+          (unsigned char)socksreq[1]);
+    return CURLE_COULDNT_CONNECT;
+  }
 
+  *done = TRUE;
   return CURLE_OK; /* Proxy was successful! */
 }
 
@@ -356,7 +476,8 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
                      const char *hostname,
                      int remote_port,
                      int sockindex,
-                     struct connectdata *conn)
+                     struct connectdata *conn,
+                     bool *done)
 {
   /*
     According to the RFC1928, section "6.  Replies". This is what a SOCK5
@@ -374,141 +495,158 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
     o  REP    Reply field:
     o  X'00' succeeded
   */
-#define REQUEST_BUFSIZE 600  /* room for large user/pw (255 max each) */
-  unsigned char socksreq[REQUEST_BUFSIZE];
-  char dest[REQUEST_BUFSIZE] = "unknown";  /* printable hostname:port */
+  unsigned char *socksreq = &conn->cnnct.socksreq[0];
+  char dest[256] = "unknown";  /* printable hostname:port */
   int idx;
   ssize_t actualread;
   ssize_t written;
-  int result;
-  CURLcode code;
-  curl_socket_t sock = conn->sock[sockindex];
+  CURLcode result;
+  curl_socket_t sockfd = conn->sock[sockindex];
   struct Curl_easy *data = conn->data;
-  timediff_t timeout;
   bool socks5_resolve_local =
     (conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
   const size_t hostname_len = strlen(hostname);
   ssize_t len = 0;
   const unsigned long auth = data->set.socks5auth;
   bool allow_gssapi = FALSE;
+  struct connstate *sx = &conn->cnnct;
+  struct Curl_dns_entry *dns = NULL;
+
+  if(!SOCKS_STATE(sx->state) && !*done)
+    sxstate(conn, CONNECT_SOCKS_INIT);
+
+  switch(sx->state) {
+  case CONNECT_SOCKS_INIT:
+    if(conn->bits.httpproxy)
+      infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
+            hostname, remote_port);
+
+    /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
+    if(!socks5_resolve_local && hostname_len > 255) {
+      infof(conn->data, "SOCKS5: server resolving disabled for hostnames of "
+            "length > 255 [actual len=%zu]\n", hostname_len);
+      socks5_resolve_local = TRUE;
+    }
 
-  if(conn->bits.httpproxy)
-    infof(conn->data, "SOCKS5: connecting to HTTP proxy %s port %d\n",
-          hostname, remote_port);
-
-  /* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
-  if(!socks5_resolve_local && hostname_len > 255) {
-    infof(conn->data, "SOCKS5: server resolving disabled for hostnames of "
-          "length > 255 [actual len=%zu]\n", hostname_len);
-    socks5_resolve_local = TRUE;
-  }
-
-  /* get timeout */
-  timeout = Curl_timeleft(data, NULL, TRUE);
-
-  if(timeout < 0) {
-    /* time-out, bail out, go home */
-    failf(data, "Connection time-out");
-    return CURLE_OPERATION_TIMEDOUT;
-  }
-
-  (void)curlx_nonblock(sock, TRUE);
-
-  /* wait until socket gets connected */
-  result = SOCKET_WRITABLE(sock, timeout);
-
-  if(-1 == result) {
-    failf(conn->data, "SOCKS5: no connection here");
-    return CURLE_COULDNT_CONNECT;
-  }
-  if(0 == result) {
-    failf(conn->data, "SOCKS5: connection timeout");
-    return CURLE_OPERATION_TIMEDOUT;
-  }
-
-  if(result & CURL_CSELECT_ERR) {
-    failf(conn->data, "SOCKS5: error occurred during connection");
-    return CURLE_COULDNT_CONNECT;
-  }
-
-  if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
-    infof(conn->data,
-        "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n",
-        auth);
-  if(!(auth & CURLAUTH_BASIC))
-    /* disable username/password auth */
-    proxy_user = NULL;
+    if(auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
+      infof(conn->data,
+            "warning: unsupported value passed to CURLOPT_SOCKS5_AUTH: %lu\n",
+            auth);
+    if(!(auth & CURLAUTH_BASIC))
+      /* disable username/password auth */
+      proxy_user = NULL;
 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
-  if(auth & CURLAUTH_GSSAPI)
-    allow_gssapi = TRUE;
+    if(auth & CURLAUTH_GSSAPI)
+      allow_gssapi = TRUE;
 #endif
 
-  idx = 0;
-  socksreq[idx++] = 5;   /* version */
-  idx++;                 /* reserve for the number of authentication methods */
-  socksreq[idx++] = 0;   /* no authentication */
-  if(allow_gssapi)
-    socksreq[idx++] = 1; /* GSS-API */
-  if(proxy_user)
-    socksreq[idx++] = 2; /* username/password */
-  /* write the number of authentication methods */
-  socksreq[1] = (unsigned char) (idx - 2);
-
-  (void)curlx_nonblock(sock, FALSE);
-
-  infof(data, "SOCKS5 communication to %s:%d\n", hostname, remote_port);
-
-  code = Curl_write_plain(conn, sock, (char *)socksreq, (2 + (int)socksreq[1]),
-                          &written);
-  if(code || (written != (2 + (int)socksreq[1]))) {
-    failf(data, "Unable to send initial SOCKS5 request.");
-    return CURLE_COULDNT_CONNECT;
-  }
-
-  (void)curlx_nonblock(sock, TRUE);
-
-  result = SOCKET_READABLE(sock, timeout);
-
-  if(-1 == result) {
-    failf(conn->data, "SOCKS5 nothing to read");
-    return CURLE_COULDNT_CONNECT;
-  }
-  if(0 == result) {
-    failf(conn->data, "SOCKS5 read timeout");
-    return CURLE_OPERATION_TIMEDOUT;
-  }
-
-  if(result & CURL_CSELECT_ERR) {
-    failf(conn->data, "SOCKS5 read error occurred");
-    return CURLE_RECV_ERROR;
-  }
-
-  (void)curlx_nonblock(sock, FALSE);
-
-  result = Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
-  if(result || (actualread != 2)) {
-    failf(data, "Unable to receive initial SOCKS5 response.");
-    return CURLE_COULDNT_CONNECT;
-  }
-
-  if(socksreq[0] != 5) {
-    failf(data, "Received invalid version in initial SOCKS5 response.");
-    return CURLE_COULDNT_CONNECT;
-  }
-  if(socksreq[1] == 0) {
-    /* Nothing to do, no authentication needed */
-    ;
-  }
+    idx = 0;
+    socksreq[idx++] = 5;   /* version */
+    idx++;                 /* number of authentication methods */
+    socksreq[idx++] = 0;   /* no authentication */
+    if(allow_gssapi)
+      socksreq[idx++] = 1; /* GSS-API */
+    if(proxy_user)
+      socksreq[idx++] = 2; /* username/password */
+    /* write the number of authentication methods */
+    socksreq[1] = (unsigned char) (idx - 2);
+
+    result = Curl_write_plain(conn, sockfd, (char *)socksreq, idx, &written);
+    if(result && (CURLE_AGAIN != result)) {
+      failf(data, "Unable to send initial SOCKS5 request.");
+      return CURLE_COULDNT_CONNECT;
+    }
+    if(written != idx) {
+      sxstate(conn, CONNECT_SOCKS_SEND);
+      sx->outstanding = idx - written;
+      sx->outp = &socksreq[written];
+      return CURLE_OK;
+    }
+    sxstate(conn, CONNECT_SOCKS_READ);
+    goto CONNECT_SOCKS_READ_INIT;
+  case CONNECT_SOCKS_SEND:
+    result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
+                              sx->outstanding, &written);
+    if(result && (CURLE_AGAIN != result)) {
+      failf(data, "Unable to send initial SOCKS5 request.");
+      return CURLE_COULDNT_CONNECT;
+    }
+    if(written != sx->outstanding) {
+      /* not done, remain in state */
+      sx->outstanding -= written;
+      sx->outp += written;
+      return CURLE_OK;
+    }
+    /* FALLTHROUGH */
+  CONNECT_SOCKS_READ_INIT:
+  case CONNECT_SOCKS_READ_INIT:
+    sx->outstanding = 2; /* expect two bytes */
+    sx->outp = socksreq; /* store it here */
+    /* FALLTHROUGH */
+  case CONNECT_SOCKS_READ:
+    result = Curl_read_plain(sockfd, (char *)sx->outp,
+                             sx->outstanding, &actualread);
+    if(result && (CURLE_AGAIN != result)) {
+      failf(data, "Unable to receive initial SOCKS5 response.");
+      return CURLE_COULDNT_CONNECT;
+    }
+    else if(actualread != sx->outstanding) {
+      /* remain in reading state */
+      sx->outstanding -= actualread;
+      sx->outp += actualread;
+      return CURLE_OK;
+    }
+    else if(socksreq[0] != 5) {
+      failf(data, "Received invalid version in initial SOCKS5 response.");
+      return CURLE_COULDNT_CONNECT;
+    }
+    else if(socksreq[1] == 0) {
+      /* DONE! No authentication needed. Send request. */
+      sxstate(conn, CONNECT_REQ_INIT);
+      goto CONNECT_REQ_INIT;
+    }
+    else if(socksreq[1] == 2) {
+      /* regular name + password authentication */
+      sxstate(conn, CONNECT_AUTH_INIT);
+      goto CONNECT_AUTH_INIT;
+    }
 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
-  else if(allow_gssapi && (socksreq[1] == 1)) {
-    code = Curl_SOCKS5_gssapi_negotiate(sockindex, conn);
-    if(code) {
-      failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
+    else if(allow_gssapi && (socksreq[1] == 1)) {
+      sxstate(conn, CONNECT_GSSAPI_INIT);
+      result = Curl_SOCKS5_gssapi_negotiate(sockindex, conn);
+      if(result) {
+        failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
+        return CURLE_COULDNT_CONNECT;
+      }
+    }
+#endif
+    else {
+      /* error */
+      if(!allow_gssapi && (socksreq[1] == 1)) {
+        failf(data,
+              "SOCKS5 GSSAPI per-message authentication is not supported.");
+        return CURLE_COULDNT_CONNECT;
+      }
+      else if(socksreq[1] == 255) {
+        failf(data, "No authentication method was acceptable.");
+        return CURLE_COULDNT_CONNECT;
+      }
+      failf(data,
+            "Undocumented SOCKS5 mode attempted to be used by server.");
       return CURLE_COULDNT_CONNECT;
     }
-  }
+    break;
+#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
+  case CONNECT_GSSAPI_INIT:
+    /* GSSAPI stuff done non-blocking */
+    break;
 #endif
-  else if(socksreq[1] == 2) {
+
+  default: /* do nothing! */
+    break;
+
+  CONNECT_AUTH_INIT:
+  case CONNECT_AUTH_INIT: {
     /* Needs user name and password */
     size_t proxy_user_len, proxy_password_len;
     if(proxy_user && proxy_password) {
@@ -549,18 +687,41 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
       memcpy(socksreq + len, proxy_password, proxy_password_len);
     }
     len += proxy_password_len;
-
-    code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written);
-    if(code || (len != written)) {
+    sxstate(conn, CONNECT_AUTH_SEND);
+    sx->outstanding = len;
+    sx->outp = socksreq;
+  }
+    /* FALLTHROUGH */
+  case CONNECT_AUTH_SEND:
+    result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
+                              sx->outstanding, &written);
+    if(result && (CURLE_AGAIN != result)) {
       failf(data, "Failed to send SOCKS5 sub-negotiation request.");
       return CURLE_COULDNT_CONNECT;
     }
-
-    result = Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
-    if(result || (actualread != 2)) {
+    if(sx->outstanding != written) {
+      /* remain in state */
+      sx->outstanding -= written;
+      sx->outp += written;
+      return CURLE_OK;
+    }
+    sx->outp = socksreq;
+    sx->outstanding = 2;
+    sxstate(conn, CONNECT_AUTH_READ);
+    /* FALLTHROUGH */
+  case CONNECT_AUTH_READ:
+    result = Curl_read_plain(sockfd, (char *)sx->outp,
+                             sx->outstanding, &actualread);
+    if(result && (CURLE_AGAIN != result)) {
       failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
       return CURLE_COULDNT_CONNECT;
     }
+    if(actualread != sx->outstanding) {
+      /* remain in state */
+      sx->outstanding -= actualread;
+      sx->outp += actualread;
+      return CURLE_OK;
+    }
 
     /* ignore the first (VER) byte */
     if(socksreq[1] != 0) { /* status */
@@ -570,209 +731,248 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
     }
 
     /* Everything is good so far, user was authenticated! */
-  }
-  else {
-    /* error */
-    if(!allow_gssapi && (socksreq[1] == 1)) {
-      failf(data,
-            "SOCKS5 GSSAPI per-message authentication is not supported.");
-      return CURLE_COULDNT_CONNECT;
-    }
-    if(socksreq[1] == 255) {
-      if(!proxy_user || !*proxy_user) {
-        failf(data,
-              "No authentication method was acceptable. (It is quite likely"
-              " that the SOCKS5 server wanted a username/password, since none"
-              " was supplied to the server on this connection.)");
+    sxstate(conn, CONNECT_REQ_INIT);
+    /* FALLTHROUGH */
+  CONNECT_REQ_INIT:
+  case CONNECT_REQ_INIT:
+    if(socks5_resolve_local) {
+      enum resolve_t rc = Curl_resolv(conn, hostname, remote_port,
+                                      FALSE, &dns);
+
+      if(rc == CURLRESOLV_ERROR)
+        return CURLE_COULDNT_RESOLVE_HOST;
+
+      if(rc == CURLRESOLV_PENDING) {
+        sxstate(conn, CONNECT_RESOLVING);
+        return CURLE_OK;
       }
-      else {
-        failf(data, "No authentication method was acceptable.");
-      }
-      return CURLE_COULDNT_CONNECT;
+      sxstate(conn, CONNECT_RESOLVED);
+      goto CONNECT_RESOLVED;
     }
-    else {
-      failf(data,
-            "Undocumented SOCKS5 mode attempted to be used by server.");
-      return CURLE_COULDNT_CONNECT;
-    }
-  }
+    goto CONNECT_RESOLVE_REMOTE;
 
-  /* Authentication is complete, now specify destination to the proxy */
-  len = 0;
-  socksreq[len++] = 5; /* version (SOCKS5) */
-  socksreq[len++] = 1; /* connect */
-  socksreq[len++] = 0; /* must be zero */
-
-  if(!socks5_resolve_local) {
-    socksreq[len++] = 3; /* ATYP: domain name = 3 */
-    socksreq[len++] = (char) hostname_len; /* address length */
-    memcpy(&socksreq[len], hostname, hostname_len); /* address str w/o NULL */
-    len += hostname_len;
-    msnprintf(dest, sizeof(dest), "%s:%d", hostname, remote_port);
-    infof(data, "SOCKS5 connect to %s (remotely resolved)\n", dest);
-  }
-  else {
-    struct Curl_dns_entry *dns;
-    Curl_addrinfo *hp = NULL;
-    int rc = Curl_resolv(conn, hostname, remote_port, FALSE, &dns);
-
-    if(rc == CURLRESOLV_ERROR)
-      return CURLE_COULDNT_RESOLVE_HOST;
+  case CONNECT_RESOLVING:
+    /* check if we have the name resolved by now */
+    dns = Curl_fetch_addr(conn, hostname, (int)conn->port);
 
-    if(rc == CURLRESOLV_PENDING) {
-      /* this requires that we're in "wait for resolve" state */
-      code = Curl_resolver_wait_resolv(conn, &dns);
-      if(code)
-        return code;
+    if(dns) {
+#ifdef CURLRES_ASYNCH
+      conn->async.dns = dns;
+      conn->async.done = TRUE;
+#endif
+      infof(data, "SOCKS5: hostname '%s' found\n", hostname);
     }
 
-    /*
-     * We cannot use 'hostent' as a struct that Curl_resolv() returns.  It
-     * returns a Curl_addrinfo pointer that may not always look the same.
-     */
+    if(!dns) {
+      result = Curl_resolv_check(data->conn, &dns);
+      if(!dns)
+        return result;
+    }
+    /* FALLTHROUGH */
+  CONNECT_RESOLVED:
+  case CONNECT_RESOLVED: {
+    Curl_addrinfo *hp = NULL;
     if(dns)
       hp = dns->addr;
-    if(hp) {
-      if(Curl_printable_address(hp, dest, sizeof(dest))) {
-        size_t destlen = strlen(dest);
-        msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", remote_port);
-      }
-      else {
-        strcpy(dest, "unknown");
-      }
-
-      if(hp->ai_family == AF_INET) {
-        int i;
-        struct sockaddr_in *saddr_in;
-        socksreq[len++] = 1; /* ATYP: IPv4 = 1 */
-
-        saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr;
-        for(i = 0; i < 4; i++) {
-          socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i];
-        }
+    if(!hp) {
+      failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
+            hostname);
+      return CURLE_COULDNT_RESOLVE_HOST;
+    }
 
-        infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", dest);
-      }
-#ifdef ENABLE_IPV6
-      else if(hp->ai_family == AF_INET6) {
-        int i;
-        struct sockaddr_in6 *saddr_in6;
-        socksreq[len++] = 4; /* ATYP: IPv6 = 4 */
-
-        saddr_in6 = (struct sockaddr_in6 *)(void *)hp->ai_addr;
-        for(i = 0; i < 16; i++) {
-          socksreq[len++] =
-            ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i];
-        }
+    if(Curl_printable_address(hp, dest, sizeof(dest))) {
+      size_t destlen = strlen(dest);
+      msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", remote_port);
+    }
+    else {
+      strcpy(dest, "unknown");
+    }
 
-        infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", dest);
+    len = 0;
+    socksreq[len++] = 5; /* version (SOCKS5) */
+    socksreq[len++] = 1; /* connect */
+    socksreq[len++] = 0; /* must be zero */
+    if(hp->ai_family == AF_INET) {
+      int i;
+      struct sockaddr_in *saddr_in;
+      socksreq[len++] = 1; /* ATYP: IPv4 = 1 */
+
+      saddr_in = (struct sockaddr_in *)(void *)hp->ai_addr;
+      for(i = 0; i < 4; i++) {
+        socksreq[len++] = ((unsigned char *)&saddr_in->sin_addr.s_addr)[i];
       }
-#endif
-      else {
-        hp = NULL; /* fail! */
 
-        failf(data, "SOCKS5 connection to %s not supported\n", dest);
+      infof(data, "SOCKS5 connect to IPv4 %s (locally resolved)\n", dest);
+    }
+#ifdef ENABLE_IPV6
+    else if(hp->ai_family == AF_INET6) {
+      int i;
+      struct sockaddr_in6 *saddr_in6;
+      socksreq[len++] = 4; /* ATYP: IPv6 = 4 */
+
+      saddr_in6 = (struct sockaddr_in6 *)(void *)hp->ai_addr;
+      for(i = 0; i < 16; i++) {
+        socksreq[len++] =
+          ((unsigned char *)&saddr_in6->sin6_addr.s6_addr)[i];
       }
 
-      Curl_resolv_unlock(data, dns); /* not used anymore from now on */
+      infof(data, "SOCKS5 connect to IPv6 %s (locally resolved)\n", dest);
     }
-    if(!hp) {
-      failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
-            hostname);
-      return CURLE_COULDNT_RESOLVE_HOST;
+#endif
+    else {
+      hp = NULL; /* fail! */
+      failf(data, "SOCKS5 connection to %s not supported\n", dest);
     }
+
+    Curl_resolv_unlock(data, dns); /* not used anymore from now on */
+    goto CONNECT_REQ_SEND;
   }
+  CONNECT_RESOLVE_REMOTE:
+  case CONNECT_RESOLVE_REMOTE:
+    /* Authentication is complete, now specify destination to the proxy */
+    len = 0;
+    socksreq[len++] = 5; /* version (SOCKS5) */
+    socksreq[len++] = 1; /* connect */
+    socksreq[len++] = 0; /* must be zero */
+
+    if(!socks5_resolve_local) {
+      socksreq[len++] = 3; /* ATYP: domain name = 3 */
+      socksreq[len++] = (char) hostname_len; /* one byte address length */
+      memcpy(&socksreq[len], hostname, hostname_len); /* address w/o NULL */
+      len += hostname_len;
+      infof(data, "SOCKS5 connect to %s:%d (remotely resolved)\n",
+            hostname, remote_port);
+    }
+    /* FALLTHROUGH */
 
-  socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */
-  socksreq[len++] = (unsigned char)(remote_port & 0xff);        /* PORT LSB */
+  CONNECT_REQ_SEND:
+  case CONNECT_REQ_SEND:
+    /* PORT MSB */
+    socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff);
+    /* PORT LSB */
+    socksreq[len++] = (unsigned char)(remote_port & 0xff);
 
 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
-  if(conn->socks5_gssapi_enctype) {
-    failf(data, "SOCKS5 GSS-API protection not yet implemented.");
-  }
-  else
+    if(conn->socks5_gssapi_enctype) {
+      failf(data, "SOCKS5 GSS-API protection not yet implemented.");
+      return CURLE_COULDNT_CONNECT;
+    }
 #endif
-    code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written);
-
-  if(code || (len != written)) {
-    failf(data, "Failed to send SOCKS5 connect request.");
-    return CURLE_COULDNT_CONNECT;
-  }
-
-  len = 10; /* minimum packet size is 10 */
-
+    sx->outp = socksreq;
+    sx->outstanding = len;
+    sxstate(conn, CONNECT_REQ_SENDING);
+    /* FALLTHROUGH */
+  case CONNECT_REQ_SENDING:
+    result = Curl_write_plain(conn, sockfd, (char *)sx->outp,
+                              sx->outstanding, &written);
+    if(result && (CURLE_AGAIN != result)) {
+      failf(data, "Failed to send SOCKS5 connect request.");
+      return CURLE_COULDNT_CONNECT;
+    }
+    if(sx->outstanding != written) {
+      /* remain in state */
+      sx->outstanding -= written;
+      sx->outp += written;
+      return CURLE_OK;
+    }
 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
-  if(conn->socks5_gssapi_enctype) {
-    failf(data, "SOCKS5 GSS-API protection not yet implemented.");
-  }
-  else
+    if(conn->socks5_gssapi_enctype) {
+      failf(data, "SOCKS5 GSS-API protection not yet implemented.");
+      return CURLE_COULDNT_CONNECT;
+    }
 #endif
-    result = Curl_blockread_all(conn, sock, (char *)socksreq,
-                                len, &actualread);
-
-  if(result || (len != actualread)) {
-    failf(data, "Failed to receive SOCKS5 connect request ack.");
-    return CURLE_COULDNT_CONNECT;
-  }
-
-  if(socksreq[0] != 5) { /* version */
-    failf(data,
-          "SOCKS5 reply has wrong version, version should be 5.");
-    return CURLE_COULDNT_CONNECT;
-  }
-
-  /* Fix: in general, returned BND.ADDR is variable length parameter by RFC
-     1928, so the reply packet should be read until the end to avoid errors at
-     subsequent protocol level.
-
-    +----+-----+-------+------+----------+----------+
-    |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
-    +----+-----+-------+------+----------+----------+
-    | 1  |  1  | X'00' |  1   | Variable |    2     |
-    +----+-----+-------+------+----------+----------+
+    sx->outstanding = 10; /* minimum packet size is 10 */
+    sx->outp = socksreq;
+    sxstate(conn, CONNECT_REQ_READ);
+    /* FALLTHROUGH */
+  case CONNECT_REQ_READ:
+    result = Curl_read_plain(sockfd, (char *)sx->outp,
+                             sx->outstanding, &actualread);
+    if(result && (CURLE_AGAIN != result)) {
+      failf(data, "Failed to receive SOCKS5 connect request ack.");
+      return CURLE_COULDNT_CONNECT;
+    }
+    else if(actualread != sx->outstanding) {
+      /* remain in state */
+      sx->outstanding -= actualread;
+      sx->outp += actualread;
+      return CURLE_OK;
+    }
 
-     ATYP:
-     o  IP v4 address: X'01', BND.ADDR = 4 byte
-     o  domain name:  X'03', BND.ADDR = [ 1 byte length, string ]
-     o  IP v6 address: X'04', BND.ADDR = 16 byte
-     */
+    if(socksreq[0] != 5) { /* version */
+      failf(data,
+            "SOCKS5 reply has wrong version, version should be 5.");
+      return CURLE_COULDNT_CONNECT;
+    }
+    else if(socksreq[1] != 0) { /* Anything besides 0 is an error */
+      failf(data, "Can't complete SOCKS5 connection to %s. (%d)",
+            hostname, (unsigned char)socksreq[1]);
+      return CURLE_COULDNT_CONNECT;
+    }
 
-  /* Calculate real packet size */
-  if(socksreq[3] == 3) {
-    /* domain name */
-    int addrlen = (int) socksreq[4];
-    len = 5 + addrlen + 2;
-  }
-  else if(socksreq[3] == 4) {
-    /* IPv6 */
-    len = 4 + 16 + 2;
-  }
+    /* Fix: in general, returned BND.ADDR is variable length parameter by RFC
+       1928, so the reply packet should be read until the end to avoid errors
+       at subsequent protocol level.
+
+       +----+-----+-------+------+----------+----------+
+       |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
+       +----+-----+-------+------+----------+----------+
+       | 1  |  1  | X'00' |  1   | Variable |    2     |
+       +----+-----+-------+------+----------+----------+
+
+       ATYP:
+       o  IP v4 address: X'01', BND.ADDR = 4 byte
+       o  domain name:  X'03', BND.ADDR = [ 1 byte length, string ]
+       o  IP v6 address: X'04', BND.ADDR = 16 byte
+    */
+
+    /* Calculate real packet size */
+    if(socksreq[3] == 3) {
+      /* domain name */
+      int addrlen = (int) socksreq[4];
+      len = 5 + addrlen + 2;
+    }
+    else if(socksreq[3] == 4) {
+      /* IPv6 */
+      len = 4 + 16 + 2;
+    }
 
-  /* At this point we already read first 10 bytes */
+    /* At this point we already read first 10 bytes */
 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
-  if(!conn->socks5_gssapi_enctype) {
-    /* decrypt_gssapi_blockread already read the whole packet */
+    if(!conn->socks5_gssapi_enctype) {
+      /* decrypt_gssapi_blockread already read the whole packet */
 #endif
-    if(len > 10) {
-      result = Curl_blockread_all(conn, sock, (char *)&socksreq[10],
-                                  len - 10, &actualread);
-      if(result || ((len - 10) != actualread)) {
-        failf(data, "Failed to receive SOCKS5 connect request ack.");
-        return CURLE_COULDNT_CONNECT;
+      if(len > 10) {
+        sx->outstanding = len - 10; /* get the rest */
+        sx->outp = &socksreq[10];
+        sxstate(conn, CONNECT_REQ_READ_MORE);
+      }
+      else {
+        sxstate(conn, CONNECT_DONE);
+        break;
       }
-    }
 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
-  }
+    }
 #endif
-
-  if(socksreq[1] != 0) { /* Anything besides 0 is an error */
-    failf(data, "Can't complete SOCKS5 connection to %s. (%d)",
-          dest, (unsigned char)socksreq[1]);
-    return CURLE_COULDNT_CONNECT;
+    /* FALLTHROUGH */
+  case CONNECT_REQ_READ_MORE:
+    result = Curl_read_plain(sockfd, (char *)sx->outp,
+                             sx->outstanding, &actualread);
+    if(result && (CURLE_AGAIN != result)) {
+      failf(data, "Failed to receive SOCKS5 connect request ack.");
+      return CURLE_COULDNT_CONNECT;
+    }
+    if(actualread != sx->outstanding) {
+      /* remain in state */
+      sx->outstanding -= actualread;
+      sx->outp += actualread;
+      return CURLE_OK;
+    }
+    sxstate(conn, CONNECT_DONE);
   }
   infof(data, "SOCKS5 request granted.\n");
 
-  (void)curlx_nonblock(sock, TRUE);
+  *done = TRUE;
   return CURLE_OK; /* Proxy was successful! */
 }
 
diff --git a/lib/socks.h b/lib/socks.h
index 3b319a6ef..64a756337 100644
--- a/lib/socks.h
+++ b/lib/socks.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -27,13 +27,13 @@
 #ifdef CURL_DISABLE_PROXY
 #define Curl_SOCKS4(a,b,c,d,e) CURLE_NOT_BUILT_IN
 #define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN
+#define Curl_SOCKS_getsock(x,y,z) 0
 #else
 /*
  * Helper read-from-socket functions. Does the same as Curl_read() but it
  * blocks until all bytes amount of buffersize will be read. No more, no less.
  *
- * This is STUPID BLOCKING behaviour which we frown upon, but right now this
- * is what we have...
+ * This is STUPID BLOCKING behavior
  */
 int Curl_blockread_all(struct connectdata *conn,
                        curl_socket_t sockfd,
@@ -41,6 +41,9 @@ int Curl_blockread_all(struct connectdata *conn,
                        ssize_t buffersize,
                        ssize_t *n);
 
+int Curl_SOCKS_getsock(struct connectdata *conn,
+                       curl_socket_t *sock,
+                       int sockindex);
 /*
  * This function logs in to a SOCKS4(a) proxy and sends the specifics to the
  * final destination server.
@@ -49,7 +52,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
                      const char *hostname,
                      int remote_port,
                      int sockindex,
-                     struct connectdata *conn);
+                     struct connectdata *conn,
+                     bool *done);
 
 /*
  * This function logs in to a SOCKS5 proxy and sends the specifics to the
@@ -60,7 +64,8 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
                      const char *hostname,
                      int remote_port,
                      int sockindex,
-                     struct connectdata *conn);
+                     struct connectdata *conn,
+                     bool *done);
 
 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
 /*
diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c
index 65294bbeb..97ee7183e 100644
--- a/lib/socks_gssapi.c
+++ b/lib/socks_gssapi.c
@@ -5,8 +5,8 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
+ * Copyright (C) 2012 - 2020, Daniel Stenberg, <address@hidden>, et al.
  * Copyright (C) 2009, Markus Moeller, <address@hidden>
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -167,6 +167,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     return CURLE_COULDNT_CONNECT;
   }
 
+  (void)curlx_nonblock(sock, FALSE);
+
   /* As long as we need to keep sending some context info, and there's no  */
   /* errors, keep sending it...                                            */
   for(;;) {
@@ -513,6 +515,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     gss_release_buffer(&gss_status, &gss_recv_token);
   }
 
+  (void)curlx_nonblock(sock, TRUE);
+
   infof(data, "SOCKS5 access with%s protection granted.\n",
         (socksreq[0] == 0)?"out GSS-API data":
         ((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality"));
diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c
index 57027ef68..d5be64a3c 100644
--- a/lib/socks_sspi.c
+++ b/lib/socks_sspi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2012 - 2020, Daniel Stenberg, <address@hidden>, et al.
  * Copyright (C) 2009, 2011, Markus Moeller, <address@hidden>
  *
  * This software is licensed as described in the file COPYING, which
@@ -153,6 +153,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     return CURLE_COULDNT_CONNECT;
   }
 
+  (void)curlx_nonblock(sock, FALSE);
+
   /* As long as we need to keep sending some context info, and there's no  */
   /* errors, keep sending it...                                            */
   for(;;) {
@@ -587,6 +589,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer);
     s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
   }
+  (void)curlx_nonblock(sock, TRUE);
 
   infof(data, "SOCKS5 access with%s protection granted.\n",
         (socksreq[0] == 0)?"out GSS-API data":
diff --git a/lib/strcase.c b/lib/strcase.c
index c286df26b..1c2d104aa 100644
--- a/lib/strcase.c
+++ b/lib/strcase.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -26,6 +26,8 @@
 
 #include "strcase.h"
 
+static char raw_tolower(char in);
+
 /* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
    its behavior is altered by the current locale. */
 char Curl_raw_toupper(char in)
@@ -96,7 +98,7 @@ char Curl_raw_toupper(char in)
 
 /* Portable, consistent tolower (remember EBCDIC). Do not use tolower() because
    its behavior is altered by the current locale. */
-char Curl_raw_tolower(char in)
+static char raw_tolower(char in)
 {
 #if !defined(CURL_DOES_CONVERSIONS)
   if(in >= 'A' && in <= 'Z')
@@ -245,7 +247,7 @@ void Curl_strntolower(char *dest, const char *src, size_t n)
     return;
 
   do {
-    *dest++ = Curl_raw_tolower(*src);
+    *dest++ = raw_tolower(*src);
   } while(*src++ && --n);
 }
 
diff --git a/lib/strcase.h b/lib/strcase.h
index db9a8aff2..6e9e3e0b2 100644
--- a/lib/strcase.h
+++ b/lib/strcase.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -40,7 +40,6 @@ int Curl_safe_strcasecompare(const char *first, const char 
*second);
 int Curl_strncasecompare(const char *first, const char *second, size_t max);
 
 char Curl_raw_toupper(char in);
-char Curl_raw_tolower(char in);
 
 /* checkprefix() is a shorter version of the above, used when the first
    argument is zero-byte terminated */
diff --git a/lib/strerror.c b/lib/strerror.c
index d917d7716..3ac447089 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -317,6 +317,9 @@ curl_easy_strerror(CURLcode error)
   case CURLE_HTTP3:
     return "HTTP/3 error";
 
+  case CURLE_QUIC_CONNECT_ERROR:
+    return "QUIC connection error";
+
     /* error codes not used by current libcurl */
   case CURLE_OBSOLETE20:
   case CURLE_OBSOLETE24:
@@ -392,6 +395,9 @@ curl_multi_strerror(CURLMcode error)
   case CURLM_WAKEUP_FAILURE:
     return "Wakeup is unavailable or failed";
 
+  case CURLM_BAD_FUNCTION_ARGUMENT:
+    return "A libcurl function was given a bad argument";
+
   case CURLM_LAST:
     break;
   }
diff --git a/lib/strerror.h b/lib/strerror.h
index 278c1082f..bae8f8974 100644
--- a/lib/strerror.h
+++ b/lib/strerror.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -24,7 +24,7 @@
 
 #include "urldata.h"
 
-#define STRERROR_LEN 128 /* a suitable length */
+#define STRERROR_LEN 256 /* a suitable length */
 
 const char *Curl_strerror(int err, char *buf, size_t buflen);
 #if defined(WIN32) || defined(_WIN32_WCE)
diff --git a/lib/system_win32.c b/lib/system_win32.c
index adc227cfc..eef33b5e8 100644
--- a/lib/system_win32.c
+++ b/lib/system_win32.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2016 - 2019, Steve Holme, <address@hidden>.
+ * Copyright (C) 2016 - 2020, Steve Holme, <address@hidden>.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -109,11 +109,11 @@ CURLcode Curl_win32_init(long flags)
   if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
                                  VERSION_GREATER_THAN_EQUAL)) {
     Curl_isVistaOrGreater = TRUE;
-    QueryPerformanceFrequency(&Curl_freq);
   }
   else
     Curl_isVistaOrGreater = FALSE;
 
+  QueryPerformanceFrequency(&Curl_freq);
   return CURLE_OK;
 }
 
diff --git a/lib/timeval.c b/lib/timeval.c
index 9b05cf051..e761966a1 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -28,6 +28,7 @@
 extern LARGE_INTEGER Curl_freq;
 extern bool Curl_isVistaOrGreater;
 
+/* In case of bug fix this function has a counterpart in tool_util.c */
 struct curltime Curl_now(void)
 {
   struct curltime now;
diff --git a/lib/transfer.c b/lib/transfer.c
index ed197c4f1..ac895cc08 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -890,7 +890,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
 
     } /* if(!header and data to read) */
 
-    if(conn->handler->readwrite && excess && !conn->bits.stream_was_rewound) {
+    if(conn->handler->readwrite && excess) {
       /* Parse the excess data */
       k->str += nread;
 
@@ -1234,9 +1234,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
   /* We go ahead and do a read if we have a readable socket or if
      the stream was rewound (in which case we have data in a
      buffer) */
-  if((k->keepon & KEEP_RECV) &&
-     ((select_res & CURL_CSELECT_IN) || conn->bits.stream_was_rewound)) {
-
+  if((k->keepon & KEEP_RECV) && (select_res & CURL_CSELECT_IN)) {
     result = readwrite_data(data, conn, k, &didwhat, done, comeback);
     if(result || *done)
       return result;
diff --git a/lib/url.c b/lib/url.c
index 56fb73636..47fc66aed 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -128,7 +128,6 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
 #include "memdebug.h"
 
 static void conn_free(struct connectdata *conn);
-static void free_idnconverted_hostname(struct hostname *host);
 static unsigned int get_protocol_family(unsigned int protocol);
 
 /* Some parts of the code (e.g. chunked encoding) assume this buffer has at
@@ -187,7 +186,7 @@ static const struct Curl_handler * const protocols[] = {
   &Curl_handler_tftp,
 #endif
 
-#if defined(USE_SSH)
+#if defined(USE_SSH) && !defined(USE_WOLFSSH)
   &Curl_handler_scp,
 #endif
 
@@ -380,7 +379,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
   Curl_safefree(data->state.ulbuf);
   Curl_flush_cookies(data, TRUE);
 #ifdef USE_ALTSVC
-  Curl_altsvc_save(data->asi, data->set.str[STRING_ALTSVC]);
+  Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]);
   Curl_altsvc_cleanup(data->asi);
   data->asi = NULL;
 #endif
@@ -714,14 +713,13 @@ static void conn_free(struct connectdata *conn)
   if(!conn)
     return;
 
-  free_idnconverted_hostname(&conn->host);
-  free_idnconverted_hostname(&conn->conn_to_host);
-  free_idnconverted_hostname(&conn->http_proxy.host);
-  free_idnconverted_hostname(&conn->socks_proxy.host);
+  Curl_free_idnconverted_hostname(&conn->host);
+  Curl_free_idnconverted_hostname(&conn->conn_to_host);
+  Curl_free_idnconverted_hostname(&conn->http_proxy.host);
+  Curl_free_idnconverted_hostname(&conn->socks_proxy.host);
 
   Curl_safefree(conn->user);
   Curl_safefree(conn->passwd);
-  Curl_safefree(conn->oauth_bearer);
   Curl_safefree(conn->sasl_authzid);
   Curl_safefree(conn->options);
   Curl_safefree(conn->http_proxy.user);
@@ -883,9 +881,37 @@ proxy_info_matches(const struct proxy_info* data,
 
   return FALSE;
 }
+
+static bool
+socks_proxy_info_matches(const struct proxy_info* data,
+                         const struct proxy_info* needle)
+{
+  if(!proxy_info_matches(data, needle))
+    return FALSE;
+
+  /* the user information is case-sensitive
+     or at least it is not defined as case-insensitive
+     see https://tools.ietf.org/html/rfc3986#section-3.2.1 */
+  if((data->user == NULL) != (needle->user == NULL))
+    return FALSE;
+  /* curl_strequal does a case insentive comparison, so do not use it here! */
+  if(data->user &&
+     needle->user &&
+     strcmp(data->user, needle->user) != 0)
+    return FALSE;
+  if((data->passwd == NULL) != (needle->passwd == NULL))
+    return FALSE;
+  /* curl_strequal does a case insentive comparison, so do not use it here! */
+  if(data->passwd &&
+     needle->passwd &&
+     strcmp(data->passwd, needle->passwd) != 0)
+    return FALSE;
+  return TRUE;
+}
 #else
 /* disabled, won't get called */
 #define proxy_info_matches(x,y) FALSE
+#define socks_proxy_info_matches(x,y) FALSE
 #endif
 
 /* A connection has to have been idle for a shorter time than 'maxage_conn' to
@@ -1073,7 +1099,7 @@ ConnectionExists(struct Curl_easy *data,
     curr = bundle->conn_list.head;
     while(curr) {
       bool match = FALSE;
-      size_t multiplexed;
+      size_t multiplexed = 0;
 
       /*
        * Note that if we use a HTTP proxy in normal mode (no tunneling), we
@@ -1086,8 +1112,8 @@ ConnectionExists(struct Curl_easy *data,
         /* connect-only or to-be-closed connections will not be reused */
         continue;
 
-      multiplexed = CONN_INUSE(check) &&
-        (bundle->multiuse == BUNDLE_MULTIPLEX);
+      if(bundle->multiuse == BUNDLE_MULTIPLEX)
+        multiplexed = CONN_INUSE(check);
 
       if(canmultiplex) {
         ;
@@ -1144,8 +1170,9 @@ ConnectionExists(struct Curl_easy *data,
          needle->bits.socksproxy != check->bits.socksproxy)
         continue;
 
-      if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy,
-                                                        &check->socks_proxy))
+      if(needle->bits.socksproxy &&
+        !socks_proxy_info_matches(&needle->socks_proxy,
+                                  &check->socks_proxy))
         continue;
 
       if(needle->bits.conn_to_host != check->bits.conn_to_host)
@@ -1185,6 +1212,8 @@ ConnectionExists(struct Curl_easy *data,
         }
       }
 
+      DEBUGASSERT(!check->data || GOOD_EASY_HANDLE(check->data));
+
       if(!canmultiplex && check->data)
         /* this request can't be multiplexed but the checked connection is
            already in use so we skip it */
@@ -1239,7 +1268,7 @@ ConnectionExists(struct Curl_easy *data,
              needle->conn_to_port == check->conn_to_port) &&
            strcasecompare(needle->host.name, check->host.name) &&
            needle->remote_port == check->remote_port) {
-          /* The schemes match or the the protocol family is the same and the
+          /* The schemes match or the protocol family is the same and the
              previous connection was TLS upgraded, and the hostname and host
              port match */
           if(needle->handler->flags & PROTOPT_SSL) {
@@ -1347,6 +1376,13 @@ ConnectionExists(struct Curl_easy *data,
                     multiplexed);
               continue;
             }
+            else if(multiplexed >=
+                    Curl_multi_max_concurrent_streams(needle->data->multi)) {
+              infof(data, "client side MAX_CONCURRENT_STREAMS reached"
+                    ", skip (%zu)\n",
+                    multiplexed);
+              continue;
+            }
           }
 #endif
           /* When not multiplexed, we have a match here! */
@@ -1400,10 +1436,14 @@ void Curl_verboseconnect(struct connectdata *conn)
 /*
  * Helpers for IDNA conversions.
  */
-static bool is_ASCII_name(const char *hostname)
+bool Curl_is_ASCII_name(const char *hostname)
 {
+  /* get an UNSIGNED local version of the pointer */
   const unsigned char *ch = (const unsigned char *)hostname;
 
+  if(!hostname) /* bad input, consider it ASCII! */
+    return TRUE;
+
   while(*ch) {
     if(*ch++ & 0x80)
       return FALSE;
@@ -1428,8 +1468,8 @@ static void strip_trailing_dot(struct hostname *host)
 /*
  * Perform any necessary IDN conversion of hostname
  */
-static CURLcode idnconvert_hostname(struct connectdata *conn,
-                                    struct hostname *host)
+CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
+                                  struct hostname *host)
 {
   struct Curl_easy *data = conn->data;
 
@@ -1444,7 +1484,7 @@ static CURLcode idnconvert_hostname(struct connectdata 
*conn,
   host->dispname = host->name;
 
   /* Check name for non-ASCII and convert hostname to ACE form if we can */
-  if(!is_ASCII_name(host->name)) {
+  if(!Curl_is_ASCII_name(host->name)) {
 #ifdef USE_LIBIDN2
     if(idn2_check_version(IDN2_VERSION)) {
       char *ace_hostname = NULL;
@@ -1477,7 +1517,9 @@ static CURLcode idnconvert_hostname(struct connectdata 
*conn,
       host->name = host->encalloc;
     }
     else {
-      failf(data, "Failed to convert %s to ACE;\n", host->name);
+      char buffer[STRERROR_LEN];
+      failf(data, "Failed to convert %s to ACE; %s\n", host->name,
+            Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
       return CURLE_URL_MALFORMAT;
     }
 #else
@@ -1490,7 +1532,7 @@ static CURLcode idnconvert_hostname(struct connectdata 
*conn,
 /*
  * Frees data allocated by idnconvert_hostname()
  */
-static void free_idnconverted_hostname(struct hostname *host)
+void Curl_free_idnconverted_hostname(struct hostname *host)
 {
 #if defined(USE_LIBIDN2)
   if(host->encalloc) {
@@ -1615,7 +1657,8 @@ static struct connectdata *allocate_conn(struct Curl_easy 
*data)
 
 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
     defined(NTLM_WB_ENABLED)
-  conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
+  conn->ntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
+  conn->proxyntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
 #endif
 
   /* Initialize the easy handle list */
@@ -3194,8 +3237,8 @@ static CURLcode resolve_server(struct Curl_easy *data,
 static void reuse_conn(struct connectdata *old_conn,
                        struct connectdata *conn)
 {
-  free_idnconverted_hostname(&old_conn->http_proxy.host);
-  free_idnconverted_hostname(&old_conn->socks_proxy.host);
+  Curl_free_idnconverted_hostname(&old_conn->http_proxy.host);
+  Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host);
 
   free(old_conn->http_proxy.host.rawalloc);
   free(old_conn->socks_proxy.host.rawalloc);
@@ -3239,8 +3282,8 @@ static void reuse_conn(struct connectdata *old_conn,
 
   /* host can change, when doing keepalive with a proxy or if the case is
      different this time etc */
-  free_idnconverted_hostname(&conn->host);
-  free_idnconverted_hostname(&conn->conn_to_host);
+  Curl_free_idnconverted_hostname(&conn->host);
+  Curl_free_idnconverted_hostname(&conn->conn_to_host);
   Curl_safefree(conn->host.rawalloc);
   Curl_safefree(conn->conn_to_host.rawalloc);
   conn->host = old_conn->host;
@@ -3336,14 +3379,6 @@ static CURLcode create_conn(struct Curl_easy *data,
   if(result)
     goto out;
 
-  if(data->set.str[STRING_BEARER]) {
-    conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
-    if(!conn->oauth_bearer) {
-      result = CURLE_OUT_OF_MEMORY;
-      goto out;
-    }
-  }
-
   if(data->set.str[STRING_SASL_AUTHZID]) {
     conn->sasl_authzid = strdup(data->set.str[STRING_SASL_AUTHZID]);
     if(!conn->sasl_authzid) {
@@ -3407,21 +3442,21 @@ static CURLcode create_conn(struct Curl_easy *data,
   /*************************************************************
    * IDN-convert the hostnames
    *************************************************************/
-  result = idnconvert_hostname(conn, &conn->host);
+  result = Curl_idnconvert_hostname(conn, &conn->host);
   if(result)
     goto out;
   if(conn->bits.conn_to_host) {
-    result = idnconvert_hostname(conn, &conn->conn_to_host);
+    result = Curl_idnconvert_hostname(conn, &conn->conn_to_host);
     if(result)
       goto out;
   }
   if(conn->bits.httpproxy) {
-    result = idnconvert_hostname(conn, &conn->http_proxy.host);
+    result = Curl_idnconvert_hostname(conn, &conn->http_proxy.host);
     if(result)
       goto out;
   }
   if(conn->bits.socksproxy) {
-    result = idnconvert_hostname(conn, &conn->socks_proxy.host);
+    result = Curl_idnconvert_hostname(conn, &conn->socks_proxy.host);
     if(result)
       goto out;
   }
diff --git a/lib/url.h b/lib/url.h
index 053fbdffc..5000c512a 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -62,6 +62,11 @@ CURLcode Curl_parse_login_details(const char *login, const 
size_t len,
 
 const struct Curl_handler *Curl_builtin_scheme(const char *scheme);
 
+bool Curl_is_ASCII_name(const char *hostname);
+CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
+                                  struct hostname *host);
+void Curl_free_idnconverted_hostname(struct hostname *host);
+
 #define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */
 #define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless
                                              specified */
diff --git a/lib/urlapi.c b/lib/urlapi.c
index fa514bce5..506e244dc 100644
--- a/lib/urlapi.c
+++ b/lib/urlapi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -428,7 +428,6 @@ static char *concat_url(const char *base, const char 
*relurl)
  *
  */
 static CURLUcode parse_hostname_login(struct Curl_URL *u,
-                                      const struct Curl_handler *h,
                                       char **hostname,
                                       unsigned int flags)
 {
@@ -437,6 +436,7 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
   char *userp = NULL;
   char *passwdp = NULL;
   char *optionsp = NULL;
+  const struct Curl_handler *h = NULL;
 
   /* At this point, we're hoping all the other special cases have
    * been taken care of, so conn->host.name is at most
@@ -456,6 +456,10 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u,
    * ftp://user:address@hidden:8021/README */
   *hostname = ++ptr;
 
+  /* if this is a known scheme, get some details */
+  if(u->scheme)
+    h = Curl_builtin_scheme(u->scheme);
+
   /* We could use the login information in the URL so extract it. Only parse
      options if the handler says we should. Note that 'h' might be NULL! */
   ccode = Curl_parse_login_details(login, ptr - login - 1,
@@ -571,7 +575,7 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, char 
*hostname)
 }
 
 /* scan for byte values < 31 or 127 */
-static CURLUcode junkscan(char *part)
+static CURLUcode junkscan(const char *part)
 {
   if(part) {
     static const char badbytes[]={
@@ -668,10 +672,9 @@ static CURLUcode seturl(const char *url, CURLU *u, 
unsigned int flags)
   CURLUcode result;
   bool url_has_scheme = FALSE;
   char schemebuf[MAX_SCHEME_LEN + 1];
-  char *schemep = NULL;
+  const char *schemep = NULL;
   size_t schemelen = 0;
   size_t urllen;
-  const struct Curl_handler *h = NULL;
 
   if(!url)
     return CURLUE_MALFORMED_INPUT;
@@ -798,7 +801,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned 
int flags)
       if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME)))
         return CURLUE_MALFORMED_INPUT;
       if(flags & CURLU_DEFAULT_SCHEME)
-        schemep = (char *) DEFAULT_SCHEME;
+        schemep = DEFAULT_SCHEME;
 
       /*
        * The URL was badly formatted, let's try without scheme specified.
@@ -820,36 +823,17 @@ static CURLUcode seturl(const char *url, CURLU *u, 
unsigned int flags)
         return CURLUE_MALFORMED_INPUT;
     }
 
-    if((flags & CURLU_GUESS_SCHEME) && !schemep) {
-      /* legacy curl-style guess based on host name */
-      if(checkprefix("ftp.", hostname))
-        schemep = (char *)"ftp";
-      else if(checkprefix("dict.", hostname))
-        schemep = (char *)"dict";
-      else if(checkprefix("ldap.", hostname))
-        schemep = (char *)"ldap";
-      else if(checkprefix("imap.", hostname))
-        schemep = (char *)"imap";
-      else if(checkprefix("smtp.", hostname))
-        schemep = (char *)"smtp";
-      else if(checkprefix("pop3.", hostname))
-        schemep = (char *)"pop3";
-      else
-        schemep = (char *)"http";
-    }
-
     len = strlen(p);
     memcpy(path, p, len);
     path[len] = 0;
 
-    u->scheme = strdup(schemep);
-    if(!u->scheme)
-      return CURLUE_OUT_OF_MEMORY;
+    if(schemep) {
+      u->scheme = strdup(schemep);
+      if(!u->scheme)
+        return CURLUE_OUT_OF_MEMORY;
+    }
   }
 
-  /* if this is a known scheme, get some details */
-  h = Curl_builtin_scheme(u->scheme);
-
   if(junkscan(path))
     return CURLUE_MALFORMED_INPUT;
 
@@ -916,7 +900,7 @@ static CURLUcode seturl(const char *url, CURLU *u, unsigned 
int flags)
     if(junkscan(hostname))
       return CURLUE_MALFORMED_INPUT;
 
-    result = parse_hostname_login(u, h, &hostname, flags);
+    result = parse_hostname_login(u, &hostname, flags);
     if(result)
       return result;
 
@@ -936,6 +920,28 @@ static CURLUcode seturl(const char *url, CURLU *u, 
unsigned int flags)
     u->host = strdup(hostname);
     if(!u->host)
       return CURLUE_OUT_OF_MEMORY;
+
+    if((flags & CURLU_GUESS_SCHEME) && !schemep) {
+      /* legacy curl-style guess based on host name */
+      if(checkprefix("ftp.", hostname))
+        schemep = "ftp";
+      else if(checkprefix("dict.", hostname))
+        schemep = "dict";
+      else if(checkprefix("ldap.", hostname))
+        schemep = "ldap";
+      else if(checkprefix("imap.", hostname))
+        schemep = "imap";
+      else if(checkprefix("smtp.", hostname))
+        schemep = "smtp";
+      else if(checkprefix("pop3.", hostname))
+        schemep = "pop3";
+      else
+        schemep = "http";
+
+      u->scheme = strdup(schemep);
+      if(!u->scheme)
+        return CURLUE_OUT_OF_MEMORY;
+    }
   }
 
   Curl_safefree(u->scratch);
diff --git a/lib/urldata.h b/lib/urldata.h
index aabced282..d1394fb84 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -368,6 +368,14 @@ struct ntlmdata {
   unsigned char nonce[8];
   void *target_info; /* TargetInfo received in the ntlm type-2 message */
   unsigned int target_info_len;
+
+#if defined(NTLM_WB_ENABLED)
+  /* used for communication with Samba's winbind daemon helper ntlm_auth */
+  curl_socket_t ntlm_auth_hlpr_socket;
+  pid_t ntlm_auth_hlpr_pid;
+  char *challenge; /* The received base64 encoded ntlm type-2 message */
+  char *response;  /* The generated base64 ntlm type-1/type-3 message */
+#endif
 #endif
 };
 #endif
@@ -457,8 +465,6 @@ struct ConnectBits {
 #endif
   BIT(netrc);         /* name+password provided by netrc */
   BIT(userpwd_in_url); /* name+password found in url */
-  BIT(stream_was_rewound); /* The stream was rewound after a request read
-                              past the end of its response byte boundary */
   BIT(proxy_connect_closed); /* TRUE if a proxy disconnected the connection
                                 in a CONNECT request with auth, so that
                                 libcurl should reconnect and continue. */
@@ -469,7 +475,6 @@ struct ConnectBits {
   BIT(tcp_fastopen); /* use TCP Fast Open */
   BIT(tls_enable_npn);  /* TLS NPN extension? */
   BIT(tls_enable_alpn); /* TLS ALPN extension? */
-  BIT(socksproxy_connecting); /* connecting through a socks proxy */
   BIT(connect_only);
 };
 
@@ -810,6 +815,41 @@ struct http_connect_state {
 
 struct ldapconninfo;
 
+/* for the (SOCKS) connect state machine */
+enum connect_t {
+  CONNECT_INIT,
+  CONNECT_SOCKS_INIT, /* 1 */
+  CONNECT_SOCKS_SEND, /* 2 waiting to send more first data */
+  CONNECT_SOCKS_READ_INIT, /* 3 set up read */
+  CONNECT_SOCKS_READ, /* 4 read server response */
+  CONNECT_GSSAPI_INIT, /* 5 */
+  CONNECT_AUTH_INIT, /* 6 setup outgoing auth buffer */
+  CONNECT_AUTH_SEND, /* 7 send auth */
+  CONNECT_AUTH_READ, /* 8 read auth response */
+  CONNECT_REQ_INIT,  /* 9 init SOCKS "request" */
+  CONNECT_RESOLVING, /* 10 */
+  CONNECT_RESOLVED,  /* 11 */
+  CONNECT_RESOLVE_REMOTE, /* 12 */
+  CONNECT_REQ_SEND,  /* 13 */
+  CONNECT_REQ_SENDING, /* 14 */
+  CONNECT_REQ_READ,  /* 15 */
+  CONNECT_REQ_READ_MORE, /* 16 */
+  CONNECT_DONE /* 17 connected fine to the remote or the SOCKS proxy */
+};
+
+#define SOCKS_STATE(x) (((x) >= CONNECT_SOCKS_INIT) &&  \
+                        ((x) < CONNECT_DONE))
+#define SOCKS_REQUEST_BUFSIZE 600  /* room for large user/pw (255 max each) */
+
+struct connstate {
+  enum connect_t state;
+  unsigned char socksreq[SOCKS_REQUEST_BUFSIZE];
+
+  /* CONNECT_SOCKS_SEND */
+  ssize_t outstanding;  /* send this many bytes more */
+  unsigned char *outp; /* send from this pointer */
+};
+
 /*
  * The connectdata struct contains all fields and variables that should be
  * unique for an entire connection.
@@ -819,7 +859,7 @@ struct connectdata {
      caution that this might very well vary between different times this
      connection is used! */
   struct Curl_easy *data;
-
+  struct connstate cnnct;
   struct curl_llist_element bundle_node; /* conncache */
 
   /* chunk is for HTTP chunked encoding, but is in the general connectdata
@@ -907,7 +947,6 @@ struct connectdata {
   char *passwd;  /* password string, allocated */
   char *options; /* options string, allocated */
 
-  char *oauth_bearer;     /* bearer token for OAuth 2.0, allocated */
   char *sasl_authzid;     /* authorisation identity string, allocated */
 
   int httpversion;        /* the HTTP version*10 reported by the server */
@@ -919,8 +958,6 @@ struct connectdata {
   curl_socket_t sock[2]; /* two sockets, the second is used for the data
                             transfer when doing FTP */
   curl_socket_t tempsock[2]; /* temporary sockets for happy eyeballs */
-  bool sock_accepted[2]; /* TRUE if the socket on this index was created with
-                            accept() */
   Curl_recv *recv[2];
   Curl_send *send[2];
 
@@ -1012,14 +1049,6 @@ struct connectdata {
                                because it authenticates connections, not
                                single requests! */
   struct ntlmdata proxyntlm; /* NTLM data for proxy */
-
-#if defined(NTLM_WB_ENABLED)
-  /* used for communication with Samba's winbind daemon helper ntlm_auth */
-  curl_socket_t ntlm_auth_hlpr_socket;
-  pid_t ntlm_auth_hlpr_pid;
-  char *challenge_header;
-  char *response_header;
-#endif
 #endif
 
 #ifdef USE_SPNEGO
@@ -1083,6 +1112,8 @@ struct connectdata {
                               handle */
   BIT(writechannel_inuse); /* whether the write channel is in use by an easy
                               handle */
+  BIT(sock_accepted); /* TRUE if the SECONDARYSOCKET was created with
+                         accept() */
 };
 
 /* The end of connectdata. */
@@ -1410,6 +1441,8 @@ struct UrlState {
   BIT(ftp_trying_alternative);
   BIT(wildcardmatch); /* enable wildcard matching */
   BIT(expect100header);  /* TRUE if we added Expect: 100-continue */
+  BIT(disableexpect);    /* TRUE if Expect: is disabled due to a previous
+                            417 response */
   BIT(use_range);
   BIT(rangestringalloc); /* the range string is malloc()'ed */
   BIT(done); /* set to FALSE when Curl_init_do() is called and set to TRUE
@@ -1452,6 +1485,14 @@ struct DynamicStatic {
 
 struct Curl_multi;    /* declared and used only in multi.c */
 
+/*
+ * This enumeration MUST not use conditional directives (#ifdefs), new
+ * null terminated strings MUST be added to the enumeration immediately
+ * before STRING_LASTZEROTERMINATED, binary fields immediately before
+ * STRING_LAST. When doing so, ensure that the packages/OS400/chkstring.c
+ * test is updated and applicable changes for EBCDIC to ASCII conversion
+ * are catered for in curl_easy_setopt_ccsid()
+ */
 enum dupstring {
   STRING_CERT_ORIG,       /* client certificate file name */
   STRING_CERT_PROXY,      /* client certificate file name */
@@ -1508,36 +1549,40 @@ enum dupstring {
   STRING_RTSP_SESSION_ID, /* Session ID to use */
   STRING_RTSP_STREAM_URI, /* Stream URI for this request */
   STRING_RTSP_TRANSPORT,  /* Transport for this session */
-#ifdef USE_SSH
+
   STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */
   STRING_SSH_PUBLIC_KEY,  /* path to the public key file for auth */
   STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */
   STRING_SSH_KNOWNHOSTS,  /* file name of knownhosts file */
-#endif
+
   STRING_PROXY_SERVICE_NAME, /* Proxy service name */
   STRING_SERVICE_NAME,    /* Service name */
   STRING_MAIL_FROM,
   STRING_MAIL_AUTH,
 
-#ifdef USE_TLS_SRP
   STRING_TLSAUTH_USERNAME_ORIG,  /* TLS auth <username> */
   STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth <username> */
   STRING_TLSAUTH_PASSWORD_ORIG,  /* TLS auth <password> */
   STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth <password> */
-#endif
+
   STRING_BEARER,                /* <bearer>, if used */
-#ifdef USE_UNIX_SOCKETS
+
   STRING_UNIX_SOCKET_PATH,      /* path to Unix socket, if used */
-#endif
+
   STRING_TARGET,                /* CURLOPT_REQUEST_TARGET */
   STRING_DOH,                   /* CURLOPT_DOH_URL */
-#ifdef USE_ALTSVC
+
   STRING_ALTSVC,                /* CURLOPT_ALTSVC */
-#endif
+
   STRING_SASL_AUTHZID,          /* CURLOPT_SASL_AUTHZID */
-#ifndef CURL_DISABLE_PROXY
+
   STRING_TEMP_URL,              /* temp URL storage for proxy use */
-#endif
+
+  STRING_DNS_SERVERS,
+  STRING_DNS_INTERFACE,
+  STRING_DNS_LOCAL_IP4,
+  STRING_DNS_LOCAL_IP6,
+
   /* -- end of zero-terminated strings -- */
 
   STRING_LASTZEROTERMINATED,
@@ -1546,6 +1591,7 @@ enum dupstring {
 
   STRING_COPYPOSTFIELDS,  /* if POST, set the fields' values here */
 
+
   STRING_LAST /* not used, just an end-of-list marker */
 };
 
@@ -1793,6 +1839,8 @@ struct UserDefined {
   BIT(doh); /* DNS-over-HTTPS enabled */
   BIT(doh_get); /* use GET for DoH requests, instead of POST */
   BIT(http09_allowed); /* allow HTTP/0.9 responses */
+  BIT(mail_rcpt_allowfails); /* allow RCPT TO command to fail for some
+                                recipients */
 };
 
 struct Names {
diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c
index 6222a4bcf..ae4097217 100644
--- a/lib/vauth/digest.c
+++ b/lib/vauth/digest.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -62,7 +62,7 @@
    what ultimately goes over the network.
 */
 #define CURL_OUTPUT_DIGEST_CONV(a, b) \
-  result = Curl_convert_to_network(a, (char *)b, strlen((const char *)b)); \
+  result = Curl_convert_to_network(a, b, strlen(b)); \
   if(result) { \
     free(b); \
     return result; \
@@ -660,7 +660,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char 
*chlg,
 }
 
 /*
- * _Curl_auth_create_digest_http_message()
+ * auth_create_digest_http_message()
  *
  * This is used to generate a HTTP DIGEST response message ready for sending
  * to the recipient.
@@ -679,7 +679,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char 
*chlg,
  *
  * Returns CURLE_OK on success.
  */
-static CURLcode _Curl_auth_create_digest_http_message(
+static CURLcode auth_create_digest_http_message(
                   struct Curl_easy *data,
                   const char *userp,
                   const char *passwdp,
@@ -688,12 +688,12 @@ static CURLcode _Curl_auth_create_digest_http_message(
                   struct digestdata *digest,
                   char **outptr, size_t *outlen,
                   void (*convert_to_ascii)(unsigned char *, unsigned char *),
-                  void (*hash)(unsigned char *, const unsigned char *))
+                  void (*hash)(unsigned char *, const unsigned char *,
+                               const size_t))
 {
   CURLcode result;
   unsigned char hashbuf[32]; /* 32 bytes/256 bits */
   unsigned char request_digest[65];
-  unsigned char *hashthis;
   unsigned char ha1[65];    /* 64 digits and 1 zero byte */
   unsigned char ha2[65];    /* 64 digits and 1 zero byte */
   char userh[65];
@@ -701,6 +701,7 @@ static CURLcode _Curl_auth_create_digest_http_message(
   size_t cnonce_sz = 0;
   char *userp_quoted;
   char *response = NULL;
+  char *hashthis = NULL;
   char *tmp = NULL;
 
   if(!digest->nc)
@@ -722,12 +723,12 @@ static CURLcode _Curl_auth_create_digest_http_message(
   }
 
   if(digest->userhash) {
-    hashthis = (unsigned char *) aprintf("%s:%s", userp, digest->realm);
+    hashthis = aprintf("%s:%s", userp, digest->realm);
     if(!hashthis)
       return CURLE_OUT_OF_MEMORY;
 
     CURL_OUTPUT_DIGEST_CONV(data, hashthis);
-    hash(hashbuf, hashthis);
+    hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
     free(hashthis);
     convert_to_ascii(hashbuf, (unsigned char *)userh);
   }
@@ -743,14 +744,13 @@ static CURLcode _Curl_auth_create_digest_http_message(
            unq(nonce-value) ":" unq(cnonce-value)
   */
 
-  hashthis = (unsigned char *)
-    aprintf("%s:%s:%s", digest->userhash ? userh : userp,
-                                    digest->realm, passwdp);
+  hashthis = aprintf("%s:%s:%s", digest->userhash ? userh : userp,
+                                 digest->realm, passwdp);
   if(!hashthis)
     return CURLE_OUT_OF_MEMORY;
 
   CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */
-  hash(hashbuf, hashthis);
+  hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
   free(hashthis);
   convert_to_ascii(hashbuf, ha1);
 
@@ -763,7 +763,7 @@ static CURLcode _Curl_auth_create_digest_http_message(
       return CURLE_OUT_OF_MEMORY;
 
     CURL_OUTPUT_DIGEST_CONV(data, tmp); /* Convert on non-ASCII machines */
-    hash(hashbuf, (unsigned char *) tmp);
+    hash(hashbuf, (unsigned char *) tmp, strlen(tmp));
     free(tmp);
     convert_to_ascii(hashbuf, ha1);
   }
@@ -781,19 +781,19 @@ static CURLcode _Curl_auth_create_digest_http_message(
     5.1.1 of RFC 2616)
   */
 
-  hashthis = (unsigned char *) aprintf("%s:%s", request, uripath);
+  hashthis = aprintf("%s:%s", request, uripath);
   if(!hashthis)
     return CURLE_OUT_OF_MEMORY;
 
   if(digest->qop && strcasecompare(digest->qop, "auth-int")) {
     /* We don't support auth-int for PUT or POST */
     char hashed[65];
-    unsigned char *hashthis2;
+    char *hashthis2;
 
-    hash(hashbuf, (const unsigned char *)"");
+    hash(hashbuf, (const unsigned char *)"", 0);
     convert_to_ascii(hashbuf, (unsigned char *)hashed);
 
-    hashthis2 = (unsigned char *)aprintf("%s:%s", hashthis, hashed);
+    hashthis2 = aprintf("%s:%s", hashthis, hashed);
     free(hashthis);
     hashthis = hashthis2;
   }
@@ -802,31 +802,23 @@ static CURLcode _Curl_auth_create_digest_http_message(
     return CURLE_OUT_OF_MEMORY;
 
   CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */
-  hash(hashbuf, hashthis);
+  hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
   free(hashthis);
   convert_to_ascii(hashbuf, ha2);
 
   if(digest->qop) {
-    hashthis = (unsigned char *) aprintf("%s:%s:%08x:%s:%s:%s",
-                                        ha1,
-                                        digest->nonce,
-                                        digest->nc,
-                                        digest->cnonce,
-                                        digest->qop,
-                                        ha2);
+    hashthis = aprintf("%s:%s:%08x:%s:%s:%s", ha1, digest->nonce, digest->nc,
+                       digest->cnonce, digest->qop, ha2);
   }
   else {
-    hashthis = (unsigned char *) aprintf("%s:%s:%s",
-                                        ha1,
-                                        digest->nonce,
-                                        ha2);
+    hashthis = aprintf("%s:%s:%s", ha1, digest->nonce, ha2);
   }
 
   if(!hashthis)
     return CURLE_OUT_OF_MEMORY;
 
   CURL_OUTPUT_DIGEST_CONV(data, hashthis); /* convert on non-ASCII machines */
-  hash(hashbuf, hashthis);
+  hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis));
   free(hashthis);
   convert_to_ascii(hashbuf, request_digest);
 
@@ -899,7 +891,7 @@ static CURLcode _Curl_auth_create_digest_http_message(
 
   if(digest->algorithm) {
     /* Append the algorithm */
-    tmp = aprintf("%s, algorithm=\"%s\"", response, digest->algorithm);
+    tmp = aprintf("%s, algorithm=%s", response, digest->algorithm);
     free(response);
     if(!tmp)
       return CURLE_OUT_OF_MEMORY;
@@ -955,21 +947,21 @@ CURLcode Curl_auth_create_digest_http_message(struct 
Curl_easy *data,
   switch(digest->algo) {
   case CURLDIGESTALGO_MD5:
   case CURLDIGESTALGO_MD5SESS:
-    return _Curl_auth_create_digest_http_message(data, userp, passwdp,
-                                                 request, uripath, digest,
-                                                 outptr, outlen,
-                                                 auth_digest_md5_to_ascii,
-                                                 Curl_md5it);
+    return auth_create_digest_http_message(data, userp, passwdp,
+                                           request, uripath, digest,
+                                           outptr, outlen,
+                                           auth_digest_md5_to_ascii,
+                                           Curl_md5it);
 
   case CURLDIGESTALGO_SHA256:
   case CURLDIGESTALGO_SHA256SESS:
   case CURLDIGESTALGO_SHA512_256:
   case CURLDIGESTALGO_SHA512_256SESS:
-    return _Curl_auth_create_digest_http_message(data, userp, passwdp,
-                                                 request, uripath, digest,
-                                                 outptr, outlen,
-                                                 auth_digest_sha256_to_ascii,
-                                                 Curl_sha256it);
+    return auth_create_digest_http_message(data, userp, passwdp,
+                                           request, uripath, digest,
+                                           outptr, outlen,
+                                           auth_digest_sha256_to_ascii,
+                                           Curl_sha256it);
 
   default:
     return CURLE_UNSUPPORTED_PROTOCOL;
diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c
index 047c2b5a3..8f9103806 100644
--- a/lib/vauth/ntlm.c
+++ b/lib/vauth/ntlm.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -40,6 +40,7 @@
 #include "curl_ntlm_core.h"
 #include "curl_gethostname.h"
 #include "curl_multibyte.h"
+#include "curl_md5.h"
 #include "warnless.h"
 #include "rand.h"
 #include "vtls/vtls.h"
@@ -621,11 +622,11 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct 
Curl_easy *data,
     memcpy(tmp, &ntlm->nonce[0], 8);
     memcpy(tmp + 8, entropy, 8);
 
-    result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH);
-    if(!result)
-      /* We shall only use the first 8 bytes of md5sum, but the des code in
-         Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
-      result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
+    Curl_md5it(md5sum, tmp, 16);
+
+    /* We shall only use the first 8 bytes of md5sum, but the des code in
+       Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
+    result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
     if(result)
       return result;
 
diff --git a/lib/version.c b/lib/version.c
index f4d1bb60d..ca4ab5717 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -66,16 +66,6 @@
 #include <brotli/decode.h>
 #endif
 
-void Curl_version_init(void);
-
-/* For thread safety purposes this function is called by global_init so that
-   the static data in both version functions is initialized. */
-void Curl_version_init(void)
-{
-  curl_version();
-  curl_version_info(CURLVERSION_NOW);
-}
-
 #ifdef HAVE_BROTLI
 static size_t brotli_version(char *buf, size_t bufsz)
 {
@@ -88,95 +78,108 @@ static size_t brotli_version(char *buf, size_t bufsz)
 }
 #endif
 
+/*
+ * curl_version() returns a pointer to a static buffer.
+ *
+ * It is implemented to work multi-threaded by making sure repeated invokes
+ * generate the exact same string and never write any temporary data like
+ * zeros in the data.
+ */
 char *curl_version(void)
 {
-  static bool initialized;
-  static char version[250];
-  char *ptr = version;
-  size_t len;
-  size_t left = sizeof(version);
-
-  if(initialized)
-    return version;
-
-  strcpy(ptr, LIBCURL_NAME "/" LIBCURL_VERSION);
-  len = strlen(ptr);
-  left -= len;
-  ptr += len;
-
-  len = Curl_ssl_version(ptr + 1, left - 1);
-
-  if(len > 0) {
-    *ptr = ' ';
-    left -= ++len;
-    ptr += len;
-  }
+  static char out[250];
+  char *outp;
+  size_t outlen;
+  const char *src[14];
+#ifdef USE_SSL
+  char ssl_version[40];
+#endif
+#ifdef HAVE_LIBZ
+  char z_version[40];
+#endif
+#ifdef HAVE_BROTLI
+  char br_version[40] = "brotli/";
+#endif
+#ifdef USE_ARES
+  char cares_version[40];
+#endif
+#if defined(USE_LIBIDN2) || defined(USE_WIN32_IDN)
+  char idn_version[40];
+#endif
+#ifdef USE_LIBPSL
+  char psl_version[40];
+#endif
+#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
+  char iconv_version[40]="iconv";
+#endif
+#ifdef USE_SSH
+  char ssh_version[40];
+#endif
+#ifdef USE_NGHTTP2
+  char h2_version[40];
+#endif
+#ifdef ENABLE_QUIC
+  char h3_version[40];
+#endif
+#ifdef USE_LIBRTMP
+  char rtmp_version[40];
+#endif
+  int i = 0;
+  int j;
 
+  src[i++] = LIBCURL_NAME "/" LIBCURL_VERSION;
+#ifdef USE_SSL
+  Curl_ssl_version(ssl_version, sizeof(ssl_version));
+  src[i++] = ssl_version;
+#endif
 #ifdef HAVE_LIBZ
-  len = msnprintf(ptr, left, " zlib/%s", zlibVersion());
-  left -= len;
-  ptr += len;
+  msnprintf(z_version, sizeof(z_version), "zlib/%s", zlibVersion());
+  src[i++] = z_version;
 #endif
 #ifdef HAVE_BROTLI
-  len = msnprintf(ptr, left, "%s", " brotli/");
-  left -= len;
-  ptr += len;
-  len = brotli_version(ptr, left);
-  left -= len;
-  ptr += len;
+  brotli_version(&br_version[7], sizeof(br_version) - 7);
+  src[i++] = br_version;
 #endif
 #ifdef USE_ARES
-  /* this function is only present in c-ares, not in the original ares */
-  len = msnprintf(ptr, left, " c-ares/%s", ares_version(NULL));
-  left -= len;
-  ptr += len;
+  msnprintf(cares_version, sizeof(cares_version),
+            "c-ares/%s", ares_version(NULL));
+  src[i++] = cares_version;
 #endif
 #ifdef USE_LIBIDN2
   if(idn2_check_version(IDN2_VERSION)) {
-    len = msnprintf(ptr, left, " libidn2/%s", idn2_check_version(NULL));
-    left -= len;
-    ptr += len;
+    msnprintf(idn_version, sizeof(idn_version),
+              "libidn2/%s", idn2_check_version(NULL));
+    src[i++] = idn_version;
   }
+#elif defined(USE_WIN32_IDN)
+  msnprintf(idn_version, sizeof(idn_version), "WinIDN");
+  src[i++] = idn_version;
 #endif
+
 #ifdef USE_LIBPSL
-  len = msnprintf(ptr, left, " libpsl/%s", psl_get_version());
-  left -= len;
-  ptr += len;
-#endif
-#ifdef USE_WIN32_IDN
-  len = msnprintf(ptr, left, " WinIDN");
-  left -= len;
-  ptr += len;
+  msnprintf(psl_version, sizeof(psl_version), "libpsl/%s", psl_get_version());
+  src[i++] = psl_version;
 #endif
 #if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS)
 #ifdef _LIBICONV_VERSION
-  len = msnprintf(ptr, left, " iconv/%d.%d",
-                  _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255);
+  msnprintf(iconv_version, sizeof(iconv_version), "iconv/%d.%d",
+            _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255);
 #else
-  /* version unknown */
-  len = msnprintf(ptr, left, " iconv");
+  /* version unknown, let the default stand */
 #endif /* _LIBICONV_VERSION */
-  left -= len;
-  ptr += len;
+  src[i++] = iconv_version;
 #endif
 #ifdef USE_SSH
-  if(left) {
-    *ptr++=' ';
-    left--;
-  }
-  len = Curl_ssh_version(ptr, left);
-  left -= len;
-  ptr += len;
+  Curl_ssh_version(ssh_version, sizeof(ssh_version));
+  src[i++] = ssh_version;
 #endif
 #ifdef USE_NGHTTP2
-  len = Curl_http2_ver(ptr, left);
-  left -= len;
-  ptr += len;
+  Curl_http2_ver(h2_version, sizeof(h2_version));
+  src[i++] = h2_version;
 #endif
 #ifdef ENABLE_QUIC
-  len = Curl_quic_ver(ptr, left);
-  left -= len;
-  ptr += len;
+  Curl_quic_ver(h3_version, sizeof(h3_version));
+  src[i++] = h3_version;
 #endif
 #ifdef USE_LIBRTMP
   {
@@ -188,27 +191,32 @@ char *curl_version(void)
     else
       suff[0] = '\0';
 
-    msnprintf(ptr, left, " librtmp/%d.%d%s",
+    msnprintf(rtmp_version, sizeof(rtmp_version), "librtmp/%d.%d%s",
               RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff,
               suff);
-/*
-  If another lib version is added below this one, this code would
-  also have to do:
-
-    len = what msnprintf() returned
-
-    left -= len;
-    ptr += len;
-*/
+    src[i++] = rtmp_version;
   }
 #endif
 
-  /* Silent scan-build even if librtmp is not enabled. */
-  (void) left;
-  (void) ptr;
+  outp = &out[0];
+  outlen = sizeof(out);
+  for(j = 0; j < i; j++) {
+    size_t n = strlen(src[j]);
+    /* we need room for a space, the string and the final zero */
+    if(outlen <= (n + 2))
+      break;
+    if(j) {
+      /* prepend a space if not the first */
+      *outp++ = ' ';
+      outlen--;
+    }
+    memcpy(outp, src[j], n);
+    outp += n;
+    outlen -= n;
+  }
+  *outp = 0;
 
-  initialized = true;
-  return version;
+  return out;
 }
 
 /* data for curl_version_info
@@ -265,8 +273,10 @@ static const char * const protocols[] = {
 #ifndef CURL_DISABLE_RTSP
   "rtsp",
 #endif
-#if defined(USE_SSH)
+#if defined(USE_SSH) && !defined(USE_WOLFSSH)
   "scp",
+#endif
+#ifdef USE_SSH
   "sftp",
 #endif
 #if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
@@ -389,7 +399,6 @@ static curl_version_info_data version_info = {
 
 curl_version_info_data *curl_version_info(CURLversion stamp)
 {
-  static bool initialized;
 #if defined(USE_SSH)
   static char ssh_buffer[80];
 #endif
@@ -404,9 +413,6 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
   static char brotli_buffer[80];
 #endif
 
-  if(initialized)
-    return &version_info;
-
 #ifdef USE_SSL
   Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
   version_info.ssl_version = ssl_buffer;
@@ -474,7 +480,5 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
 #endif
 
   (void)stamp; /* avoid compiler warnings, we don't use this */
-
-  initialized = true;
   return &version_info;
 }
diff --git a/lib/vquic/ngtcp2.c b/lib/vquic/ngtcp2.c
index e97e9e871..2f6ee8bdf 100644
--- a/lib/vquic/ngtcp2.c
+++ b/lib/vquic/ngtcp2.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -146,7 +146,7 @@ static void quic_settings(ngtcp2_settings *s,
   s->transport_params.initial_max_data = QUIC_MAX_DATA;
   s->transport_params.initial_max_streams_bidi = 1;
   s->transport_params.initial_max_streams_uni = 3;
-  s->transport_params.idle_timeout = QUIC_IDLE_TIMEOUT;
+  s->transport_params.max_idle_timeout = QUIC_IDLE_TIMEOUT;
 }
 
 static FILE *keylog_file; /* not thread-safe */
@@ -535,6 +535,8 @@ static ngtcp2_conn_callbacks ng_callbacks = {
   NULL, /* extend_max_remote_streams_bidi */
   NULL, /* extend_max_remote_streams_uni */
   cb_extend_max_stream_data,
+  NULL, /* dcid_status */
+  NULL  /* handshake_confirmed */
 };
 
 /*
@@ -574,10 +576,10 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
   qs->version = NGTCP2_PROTO_VER;
   qs->sslctx = quic_ssl_ctx(data);
   if(!qs->sslctx)
-    return CURLE_FAILED_INIT; /* TODO: better return code */
+    return CURLE_QUIC_CONNECT_ERROR;
 
   if(quic_init_ssl(qs))
-    return CURLE_FAILED_INIT; /* TODO: better return code */
+    return CURLE_QUIC_CONNECT_ERROR;
 
   qs->dcid.datalen = NGTCP2_MAX_CIDLEN;
   result = Curl_rand(data, qs->dcid.data, NGTCP2_MAX_CIDLEN);
@@ -595,7 +597,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
   rv = getsockname(sockfd, (struct sockaddr *)&qs->local_addr,
                    &qs->local_addrlen);
   if(rv == -1)
-    return CURLE_FAILED_INIT;
+    return CURLE_QUIC_CONNECT_ERROR;
 
   ngtcp2_addr_init(&path.local, (uint8_t *)&qs->local_addr, qs->local_addrlen,
                    NULL);
@@ -609,7 +611,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
   rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path, QUICVER,
                               &ng_callbacks, &qs->settings, NULL, qs);
   if(rc)
-    return CURLE_FAILED_INIT; /* TODO: create a QUIC error code */
+    return CURLE_QUIC_CONNECT_ERROR;
 
   ngtcp2_conn_get_local_transport_params(qs->qconn, &params);
   nwrite = ngtcp2_encode_transport_params(
@@ -618,15 +620,15 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
   if(nwrite < 0) {
     failf(data, "ngtcp2_encode_transport_params: %s\n",
           ngtcp2_strerror((int)nwrite));
-    return CURLE_FAILED_INIT;
+    return CURLE_QUIC_CONNECT_ERROR;
   }
 
   if(!SSL_set_quic_transport_params(qs->ssl, paramsbuf, nwrite))
-    return CURLE_FAILED_INIT;
+    return CURLE_QUIC_CONNECT_ERROR;
 
   rc = setup_initial_crypto_context(qs);
   if(rc)
-    return CURLE_FAILED_INIT; /* TODO: better return code */
+    return CURLE_QUIC_CONNECT_ERROR;
 
   return CURLE_OK;
 }
@@ -639,7 +641,7 @@ int Curl_quic_ver(char *p, size_t len)
 {
   ngtcp2_info *ng2 = ngtcp2_version(0);
   nghttp3_info *ht3 = nghttp3_version(0);
-  return msnprintf(p, len, " ngtcp2/%s nghttp3/%s",
+  return msnprintf(p, len, "ngtcp2/%s nghttp3/%s",
                    ng2->version_str, ht3->version_str);
 }
 
@@ -998,7 +1000,7 @@ static int init_ngh3_conn(struct quicsocket *qs)
 
   if(ngtcp2_conn_get_max_local_streams_uni(qs->qconn) < 3) {
     failf(qs->conn->data, "too few available QUIC streams");
-    return CURLE_FAILED_INIT;
+    return CURLE_QUIC_CONNECT_ERROR;
   }
 
   nghttp3_conn_settings_default(&qs->h3settings);
@@ -1015,32 +1017,32 @@ static int init_ngh3_conn(struct quicsocket *qs)
 
   rc = ngtcp2_conn_open_uni_stream(qs->qconn, &ctrl_stream_id, NULL);
   if(rc) {
-    result = CURLE_FAILED_INIT;
+    result = CURLE_QUIC_CONNECT_ERROR;
     goto fail;
   }
 
   rc = nghttp3_conn_bind_control_stream(qs->h3conn, ctrl_stream_id);
   if(rc) {
-    result = CURLE_FAILED_INIT;
+    result = CURLE_QUIC_CONNECT_ERROR;
     goto fail;
   }
 
   rc = ngtcp2_conn_open_uni_stream(qs->qconn, &qpack_enc_stream_id, NULL);
   if(rc) {
-    result = CURLE_FAILED_INIT;
+    result = CURLE_QUIC_CONNECT_ERROR;
     goto fail;
   }
 
   rc = ngtcp2_conn_open_uni_stream(qs->qconn, &qpack_dec_stream_id, NULL);
   if(rc) {
-    result = CURLE_FAILED_INIT;
+    result = CURLE_QUIC_CONNECT_ERROR;
     goto fail;
   }
 
   rc = nghttp3_conn_bind_qpack_streams(qs->h3conn, qpack_enc_stream_id,
                                        qpack_dec_stream_id);
   if(rc) {
-    result = CURLE_FAILED_INIT;
+    result = CURLE_QUIC_CONNECT_ERROR;
     goto fail;
   }
 
@@ -1599,9 +1601,11 @@ static CURLcode ng_flush_egress(struct connectdata 
*conn, int sockfd,
   case AF_INET:
     pktlen = NGTCP2_MAX_PKTLEN_IPV4;
     break;
+#ifdef ENABLE_IPV6
   case AF_INET6:
     pktlen = NGTCP2_MAX_PKTLEN_IPV6;
     break;
+#endif
   default:
     assert(0);
   }
diff --git a/lib/vquic/quiche.c b/lib/vquic/quiche.c
index e2f43237f..c40e5e937 100644
--- a/lib/vquic/quiche.c
+++ b/lib/vquic/quiche.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -171,7 +171,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn, 
curl_socket_t sockfd,
     return CURLE_FAILED_INIT;
   }
 
-  quiche_config_set_idle_timeout(qs->cfg, QUIC_IDLE_TIMEOUT);
+  quiche_config_set_max_idle_timeout(qs->cfg, QUIC_IDLE_TIMEOUT);
   quiche_config_set_initial_max_data(qs->cfg, QUIC_MAX_DATA);
   quiche_config_set_initial_max_stream_data_bidi_local(qs->cfg, QUIC_MAX_DATA);
   quiche_config_set_initial_max_stream_data_bidi_remote(qs->cfg,
@@ -532,7 +532,7 @@ static ssize_t h3_stream_send(struct connectdata *conn,
  */
 int Curl_quic_ver(char *p, size_t len)
 {
-  return msnprintf(p, len, " quiche/%s", quiche_version());
+  return msnprintf(p, len, "quiche/%s", quiche_version());
 }
 
 /* Index where :authority header field will appear in request header
diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c
index c030362a2..5717d12fa 100644
--- a/lib/vssh/libssh.c
+++ b/lib/vssh/libssh.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2017 - 2019 Red Hat, Inc.
+ * Copyright (C) 2017 - 2020 Red Hat, Inc.
  *
  * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
  *          Robert Kolcun, Andreas Schneider
@@ -322,25 +322,50 @@ static int myssh_is_known(struct connectdata *conn)
   ssh_key pubkey;
   size_t hlen;
   unsigned char *hash = NULL;
-  char *base64 = NULL;
+  char *found_base64 = NULL;
+  char *known_base64 = NULL;
   int vstate;
   enum curl_khmatch keymatch;
   struct curl_khkey foundkey;
+  struct curl_khkey *knownkeyp = NULL;
   curl_sshkeycallback func =
     data->set.ssh_keyfunc;
 
+#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
+  struct ssh_knownhosts_entry *knownhostsentry = NULL;
+  struct curl_khkey knownkey;
+#endif
+
+#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,8,0)
+  rc = ssh_get_server_publickey(sshc->ssh_session, &pubkey);
+#else
   rc = ssh_get_publickey(sshc->ssh_session, &pubkey);
+#endif
   if(rc != SSH_OK)
     return rc;
 
   if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {
+    int i;
+    char md5buffer[33];
+    const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
+
     rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5,
                                 &hash, &hlen);
-    if(rc != SSH_OK)
+    if(rc != SSH_OK || hlen != 16) {
+      failf(data,
+            "Denied establishing ssh session: md5 fingerprint not available");
       goto cleanup;
+    }
+
+    for(i = 0; i < 16; i++)
+      msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char)hash[i]);
+
+    infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
 
-    if(hlen != strlen(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) ||
-       memcmp(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], hash, hlen)) {
+    if(!strcasecompare(md5buffer, pubkey_md5)) {
+      failf(data,
+            "Denied establishing ssh session: mismatch md5 fingerprint. "
+            "Remote %s is not equal to %s", md5buffer, pubkey_md5);
       rc = SSH_ERROR;
       goto cleanup;
     }
@@ -354,6 +379,65 @@ static int myssh_is_known(struct connectdata *conn)
     goto cleanup;
   }
 
+#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
+  /* Get the known_key from the known hosts file */
+  vstate = ssh_session_get_known_hosts_entry(sshc->ssh_session,
+                                             &knownhostsentry);
+
+  /* Case an entry was found in a known hosts file */
+  if(knownhostsentry) {
+    if(knownhostsentry->publickey) {
+      rc = ssh_pki_export_pubkey_base64(knownhostsentry->publickey,
+                                        &known_base64);
+      if(rc != SSH_OK) {
+        goto cleanup;
+      }
+      knownkey.key = known_base64;
+      knownkey.len = strlen(known_base64);
+
+      switch(ssh_key_type(knownhostsentry->publickey)) {
+        case SSH_KEYTYPE_RSA:
+          knownkey.keytype = CURLKHTYPE_RSA;
+          break;
+        case SSH_KEYTYPE_RSA1:
+          knownkey.keytype = CURLKHTYPE_RSA1;
+          break;
+        case SSH_KEYTYPE_ECDSA:
+          knownkey.keytype = CURLKHTYPE_ECDSA;
+          break;
+        case SSH_KEYTYPE_ED25519:
+          knownkey.keytype = CURLKHTYPE_ED25519;
+          break;
+        case SSH_KEYTYPE_DSS:
+          knownkey.keytype = CURLKHTYPE_DSS;
+          break;
+        default:
+          rc = SSH_ERROR;
+          goto cleanup;
+      }
+      knownkeyp = &knownkey;
+    }
+  }
+
+  switch(vstate) {
+    case SSH_KNOWN_HOSTS_OK:
+      keymatch = CURLKHMATCH_OK;
+      break;
+    case SSH_KNOWN_HOSTS_OTHER:
+      /* fallthrough */
+    case SSH_KNOWN_HOSTS_NOT_FOUND:
+      /* fallthrough */
+    case SSH_KNOWN_HOSTS_UNKNOWN:
+      /* fallthrough */
+    case SSH_KNOWN_HOSTS_ERROR:
+      keymatch = CURLKHMATCH_MISSING;
+      break;
+  default:
+      keymatch = CURLKHMATCH_MISMATCH;
+      break;
+  }
+
+#else
   vstate = ssh_is_server_known(sshc->ssh_session);
   switch(vstate) {
     case SSH_SERVER_KNOWN_OK:
@@ -368,14 +452,15 @@ static int myssh_is_known(struct connectdata *conn)
       keymatch = CURLKHMATCH_MISMATCH;
       break;
   }
+#endif
 
   if(func) { /* use callback to determine action */
-    rc = ssh_pki_export_pubkey_base64(pubkey, &base64);
+    rc = ssh_pki_export_pubkey_base64(pubkey, &found_base64);
     if(rc != SSH_OK)
       goto cleanup;
 
-    foundkey.key = base64;
-    foundkey.len = strlen(base64);
+    foundkey.key = found_base64;
+    foundkey.len = strlen(found_base64);
 
     switch(ssh_key_type(pubkey)) {
       case SSH_KEYTYPE_RSA:
@@ -400,15 +485,19 @@ static int myssh_is_known(struct connectdata *conn)
         goto cleanup;
     }
 
-    /* we don't have anything equivalent to knownkey. Always NULL */
     Curl_set_in_callback(data, true);
-    rc = func(data, NULL, &foundkey, /* from the remote host */
+    rc = func(data, knownkeyp, /* from the knownhosts file */
+              &foundkey, /* from the remote host */
               keymatch, data->set.ssh_keyfunc_userp);
     Curl_set_in_callback(data, false);
 
     switch(rc) {
       case CURLKHSTAT_FINE_ADD_TO_FILE:
+#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,8,0)
+        rc = ssh_session_update_known_hosts(sshc->ssh_session);
+#else
         rc = ssh_write_knownhost(sshc->ssh_session);
+#endif
         if(rc != SSH_OK) {
           goto cleanup;
         }
@@ -429,9 +518,20 @@ static int myssh_is_known(struct connectdata *conn)
   rc = SSH_OK;
 
 cleanup:
+  if(found_base64) {
+    free(found_base64);
+  }
+  if(known_base64) {
+    free(known_base64);
+  }
   if(hash)
     ssh_clean_pubkey_hash(&hash);
   ssh_key_free(pubkey);
+#if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
+  if(knownhostsentry) {
+    ssh_knownhosts_entry_free(knownhostsentry);
+  }
+#endif
   return rc;
 }
 
@@ -1586,7 +1686,6 @@ static CURLcode myssh_statemach_act(struct connectdata 
*conn, bool *block)
             return CURLE_BAD_DOWNLOAD_RESUME;
           }
         }
-        /* Does a completed file need to be seeked and started or closed ? */
         /* Now store the number of bytes we are expected to download */
         data->req.size = size - data->state.resume_from;
         data->req.maxdownload = size - data->state.resume_from;
diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c
index 27026b7a7..ed8986e21 100644
--- a/lib/vssh/libssh2.c
+++ b/lib/vssh/libssh2.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -106,6 +106,7 @@ static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
 static LIBSSH2_FREE_FUNC(my_libssh2_free);
 
+static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn);
 static CURLcode ssh_connect(struct connectdata *conn, bool *done);
 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
 static CURLcode ssh_do(struct connectdata *conn, bool *done);
@@ -648,6 +649,138 @@ static CURLcode ssh_check_fingerprint(struct connectdata 
*conn)
   return ssh_knownhost(conn);
 }
 
+/*
+ * ssh_force_knownhost_key_type() will check the known hosts file and try to
+ * force a specific public key type from the server if an entry is found.
+ */
+static CURLcode ssh_force_knownhost_key_type(struct connectdata *conn)
+{
+  CURLcode result = CURLE_OK;
+
+#ifdef HAVE_LIBSSH2_KNOWNHOST_API
+
+#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
+  static const char * const hostkey_method_ssh_ed25519
+    = "ssh-ed25519";
+#endif
+#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521
+  static const char * const hostkey_method_ssh_ecdsa_521
+    = "ecdsa-sha2-nistp521";
+#endif
+#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384
+  static const char * const hostkey_method_ssh_ecdsa_384
+    = "ecdsa-sha2-nistp384";
+#endif
+#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
+  static const char * const hostkey_method_ssh_ecdsa_256
+    = "ecdsa-sha2-nistp256";
+#endif
+  static const char * const hostkey_method_ssh_rsa
+    = "ssh-rsa";
+  static const char * const hostkey_method_ssh_dss
+    = "ssh-dss";
+
+  const char *hostkey_method = NULL;
+  struct ssh_conn *sshc = &conn->proto.sshc;
+  struct Curl_easy *data = conn->data;
+  struct libssh2_knownhost* store = NULL;
+  const char *kh_name_end = NULL;
+  size_t kh_name_size = 0;
+  int port = 0;
+  bool found = false;
+
+  if(sshc->kh && !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {
+    /* lets try to find our host in the known hosts file */
+    while(!libssh2_knownhost_get(sshc->kh, &store, store)) {
+      /* For non-standard ports, the name will be enclosed in */
+      /* square brackets, followed by a colon and the port */
+      if(store) {
+        if(store->name) {
+          if(store->name[0] == '[') {
+            kh_name_end = strstr(store->name, "]:");
+            if(!kh_name_end) {
+              infof(data, "Invalid host pattern %s in %s\n",
+                    store->name, data->set.str[STRING_SSH_KNOWNHOSTS]);
+              continue;
+            }
+            port = atoi(kh_name_end + 2);
+            if(kh_name_end && (port == conn->remote_port)) {
+              kh_name_size = strlen(store->name) - 1 - strlen(kh_name_end);
+              if(strncmp(store->name + 1,
+                 conn->host.name, kh_name_size) == 0) {
+                found = true;
+                break;
+              }
+            }
+          }
+          else if(strcmp(store->name, conn->host.name) == 0) {
+            found = true;
+            break;
+          }
+        }
+        else {
+          found = true;
+          break;
+        }
+      }
+    }
+
+    if(found) {
+      infof(data, "Found host %s in %s\n",
+            conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]);
+
+      switch(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) {
+#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
+      case LIBSSH2_KNOWNHOST_KEY_ED25519:
+        hostkey_method = hostkey_method_ssh_ed25519;
+        break;
+#endif
+#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_521
+      case LIBSSH2_KNOWNHOST_KEY_ECDSA_521:
+        hostkey_method = hostkey_method_ssh_ecdsa_521;
+        break;
+#endif
+#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_384
+      case LIBSSH2_KNOWNHOST_KEY_ECDSA_384:
+        hostkey_method = hostkey_method_ssh_ecdsa_384;
+        break;
+#endif
+#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
+      case LIBSSH2_KNOWNHOST_KEY_ECDSA_256:
+        hostkey_method = hostkey_method_ssh_ecdsa_256;
+        break;
+#endif
+      case LIBSSH2_KNOWNHOST_KEY_SSHRSA:
+        hostkey_method = hostkey_method_ssh_rsa;
+        break;
+      case LIBSSH2_KNOWNHOST_KEY_SSHDSS:
+        hostkey_method = hostkey_method_ssh_dss;
+        break;
+      case LIBSSH2_KNOWNHOST_KEY_RSA1:
+        failf(data, "Found host key type RSA1 which is not supported\n");
+        return CURLE_SSH;
+      default:
+        failf(data, "Unknown host key type: %i\n",
+              (store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK));
+        return CURLE_SSH;
+      }
+
+      infof(data, "Set \"%s\" as SSH hostkey type\n", hostkey_method);
+      result = libssh2_session_error_to_CURLE(
+          libssh2_session_method_pref(
+              sshc->ssh_session, LIBSSH2_METHOD_HOSTKEY, hostkey_method));
+    }
+    else {
+      infof(data, "Did not find host %s in %s\n",
+            conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]);
+    }
+  }
+
+#endif /* HAVE_LIBSSH2_KNOWNHOST_API */
+
+  return result;
+}
+
 /*
  * ssh_statemach_act() runs the SSH state machine as far as it can without
  * blocking and without reaching the end.  The data the pointer 'block' points
@@ -680,6 +813,12 @@ static CURLcode ssh_statemach_act(struct connectdata 
*conn, bool *block)
          non-blocking */
       libssh2_session_set_blocking(sshc->ssh_session, 0);
 
+      result = ssh_force_knownhost_key_type(conn);
+      if(result) {
+        state(conn, SSH_SESSION_FREE);
+        break;
+      }
+
       state(conn, SSH_S_STARTUP);
       /* FALLTHROUGH */
 
@@ -2251,7 +2390,6 @@ static CURLcode ssh_statemach_act(struct connectdata 
*conn, bool *block)
             return CURLE_BAD_DOWNLOAD_RESUME;
           }
         }
-        /* Does a completed file need to be seeked and started or closed ? */
         /* Now store the number of bytes we are expected to download */
         data->req.size = attrs.filesize - data->state.resume_from;
         data->req.maxdownload = attrs.filesize - data->state.resume_from;
diff --git a/lib/vssh/ssh.h b/lib/vssh/ssh.h
index 3213c5a52..0d4ee521d 100644
--- a/lib/vssh/ssh.h
+++ b/lib/vssh/ssh.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -30,7 +30,10 @@
 #elif defined(HAVE_LIBSSH_LIBSSH_H)
 #include <libssh/libssh.h>
 #include <libssh/sftp.h>
-#endif /* HAVE_LIBSSH2_H */
+#elif defined(USE_WOLFSSH)
+#include <wolfssh/ssh.h>
+#include <wolfssh/wolfsftp.h>
+#endif
 
 /****************************************************************************
  * SSH unique setup
@@ -188,6 +191,12 @@ struct ssh_conn {
 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
   LIBSSH2_KNOWNHOSTS *kh;
 #endif
+#elif defined(USE_WOLFSSH)
+  WOLFSSH *ssh_session;
+  WOLFSSH_CTX *ctx;
+  word32 handleSz;
+  byte handle[WOLFSSH_MAX_HANDLE];
+  curl_off_t offset;
 #endif /* USE_LIBSSH */
 };
 
@@ -195,9 +204,6 @@ struct ssh_conn {
 
 #define CURL_LIBSSH_VERSION ssh_version(0)
 
-extern const struct Curl_handler Curl_handler_scp;
-extern const struct Curl_handler Curl_handler_sftp;
-
 #elif defined(USE_LIBSSH2)
 
 /* Feature detection based on version numbers to better work with
@@ -237,11 +243,13 @@ extern const struct Curl_handler Curl_handler_sftp;
 #define CURL_LIBSSH2_VERSION LIBSSH2_VERSION
 #endif
 
-extern const struct Curl_handler Curl_handler_scp;
-extern const struct Curl_handler Curl_handler_sftp;
 #endif /* USE_LIBSSH2 */
 
 #ifdef USE_SSH
+
+extern const struct Curl_handler Curl_handler_scp;
+extern const struct Curl_handler Curl_handler_sftp;
+
 /* generic SSH backend functions */
 CURLcode Curl_ssh_init(void);
 void Curl_ssh_cleanup(void);
diff --git a/lib/vssh/wolfssh.c b/lib/vssh/wolfssh.c
new file mode 100644
index 000000000..363a52c77
--- /dev/null
+++ b/lib/vssh/wolfssh.c
@@ -0,0 +1,1156 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2019 - 2020, Daniel Stenberg, <address@hidden>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_WOLFSSH
+
+#include <limits.h>
+
+#include <wolfssh/ssh.h>
+#include <wolfssh/wolfsftp.h>
+#include "urldata.h"
+#include "connect.h"
+#include "sendf.h"
+#include "progress.h"
+#include "curl_path.h"
+#include "strtoofft.h"
+#include "transfer.h"
+#include "speedcheck.h"
+#include "select.h"
+#include "multiif.h"
+#include "warnless.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+static CURLcode wssh_connect(struct connectdata *conn, bool *done);
+static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done);
+static CURLcode wssh_do(struct connectdata *conn, bool *done);
+#if 0
+static CURLcode wscp_done(struct connectdata *conn,
+                          CURLcode, bool premature);
+static CURLcode wscp_doing(struct connectdata *conn,
+                           bool *dophase_done);
+static CURLcode wscp_disconnect(struct connectdata *conn,
+                                bool dead_connection);
+#endif
+static CURLcode wsftp_done(struct connectdata *conn,
+                           CURLcode, bool premature);
+static CURLcode wsftp_doing(struct connectdata *conn,
+                            bool *dophase_done);
+static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead);
+static int wssh_getsock(struct connectdata *conn,
+                        curl_socket_t *sock);
+static int wssh_perform_getsock(const struct connectdata *conn,
+                                curl_socket_t *sock);
+static CURLcode wssh_setup_connection(struct connectdata *conn);
+
+#if 0
+/*
+ * SCP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_scp = {
+  "SCP",                                /* scheme */
+  wssh_setup_connection,                /* setup_connection */
+  wssh_do,                              /* do_it */
+  wscp_done,                            /* done */
+  ZERO_NULL,                            /* do_more */
+  wssh_connect,                         /* connect_it */
+  wssh_multi_statemach,                 /* connecting */
+  wscp_doing,                           /* doing */
+  wssh_getsock,                         /* proto_getsock */
+  wssh_getsock,                         /* doing_getsock */
+  ZERO_NULL,                            /* domore_getsock */
+  wssh_perform_getsock,                 /* perform_getsock */
+  wscp_disconnect,                      /* disconnect */
+  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* connection_check */
+  PORT_SSH,                             /* defport */
+  CURLPROTO_SCP,                        /* protocol */
+  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
+  | PROTOPT_NOURLQUERY                  /* flags */
+};
+
+#endif
+
+/*
+ * SFTP protocol handler.
+ */
+
+const struct Curl_handler Curl_handler_sftp = {
+  "SFTP",                               /* scheme */
+  wssh_setup_connection,                /* setup_connection */
+  wssh_do,                              /* do_it */
+  wsftp_done,                           /* done */
+  ZERO_NULL,                            /* do_more */
+  wssh_connect,                         /* connect_it */
+  wssh_multi_statemach,                 /* connecting */
+  wsftp_doing,                          /* doing */
+  wssh_getsock,                         /* proto_getsock */
+  wssh_getsock,                         /* doing_getsock */
+  ZERO_NULL,                            /* domore_getsock */
+  wssh_perform_getsock,                 /* perform_getsock */
+  wsftp_disconnect,                     /* disconnect */
+  ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* connection_check */
+  PORT_SSH,                             /* defport */
+  CURLPROTO_SFTP,                       /* protocol */
+  PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
+  | PROTOPT_NOURLQUERY                  /* flags */
+};
+
+/*
+ * SSH State machine related code
+ */
+/* This is the ONLY way to change SSH state! */
+static void state(struct connectdata *conn, sshstate nowstate)
+{
+  struct ssh_conn *sshc = &conn->proto.sshc;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+  /* for debug purposes */
+  static const char * const names[] = {
+    "SSH_STOP",
+    "SSH_INIT",
+    "SSH_S_STARTUP",
+    "SSH_HOSTKEY",
+    "SSH_AUTHLIST",
+    "SSH_AUTH_PKEY_INIT",
+    "SSH_AUTH_PKEY",
+    "SSH_AUTH_PASS_INIT",
+    "SSH_AUTH_PASS",
+    "SSH_AUTH_AGENT_INIT",
+    "SSH_AUTH_AGENT_LIST",
+    "SSH_AUTH_AGENT",
+    "SSH_AUTH_HOST_INIT",
+    "SSH_AUTH_HOST",
+    "SSH_AUTH_KEY_INIT",
+    "SSH_AUTH_KEY",
+    "SSH_AUTH_GSSAPI",
+    "SSH_AUTH_DONE",
+    "SSH_SFTP_INIT",
+    "SSH_SFTP_REALPATH",
+    "SSH_SFTP_QUOTE_INIT",
+    "SSH_SFTP_POSTQUOTE_INIT",
+    "SSH_SFTP_QUOTE",
+    "SSH_SFTP_NEXT_QUOTE",
+    "SSH_SFTP_QUOTE_STAT",
+    "SSH_SFTP_QUOTE_SETSTAT",
+    "SSH_SFTP_QUOTE_SYMLINK",
+    "SSH_SFTP_QUOTE_MKDIR",
+    "SSH_SFTP_QUOTE_RENAME",
+    "SSH_SFTP_QUOTE_RMDIR",
+    "SSH_SFTP_QUOTE_UNLINK",
+    "SSH_SFTP_QUOTE_STATVFS",
+    "SSH_SFTP_GETINFO",
+    "SSH_SFTP_FILETIME",
+    "SSH_SFTP_TRANS_INIT",
+    "SSH_SFTP_UPLOAD_INIT",
+    "SSH_SFTP_CREATE_DIRS_INIT",
+    "SSH_SFTP_CREATE_DIRS",
+    "SSH_SFTP_CREATE_DIRS_MKDIR",
+    "SSH_SFTP_READDIR_INIT",
+    "SSH_SFTP_READDIR",
+    "SSH_SFTP_READDIR_LINK",
+    "SSH_SFTP_READDIR_BOTTOM",
+    "SSH_SFTP_READDIR_DONE",
+    "SSH_SFTP_DOWNLOAD_INIT",
+    "SSH_SFTP_DOWNLOAD_STAT",
+    "SSH_SFTP_CLOSE",
+    "SSH_SFTP_SHUTDOWN",
+    "SSH_SCP_TRANS_INIT",
+    "SSH_SCP_UPLOAD_INIT",
+    "SSH_SCP_DOWNLOAD_INIT",
+    "SSH_SCP_DOWNLOAD",
+    "SSH_SCP_DONE",
+    "SSH_SCP_SEND_EOF",
+    "SSH_SCP_WAIT_EOF",
+    "SSH_SCP_WAIT_CLOSE",
+    "SSH_SCP_CHANNEL_FREE",
+    "SSH_SESSION_DISCONNECT",
+    "SSH_SESSION_FREE",
+    "QUIT"
+  };
+
+  /* a precaution to make sure the lists are in sync */
+  DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
+
+  if(sshc->state != nowstate) {
+    infof(conn->data, "wolfssh %p state change from %s to %s\n",
+          (void *)sshc, names[sshc->state], names[nowstate]);
+  }
+#endif
+
+  sshc->state = nowstate;
+}
+
+static ssize_t wscp_send(struct connectdata *conn, int sockindex,
+                         const void *mem, size_t len, CURLcode *err)
+{
+  ssize_t nwrite = 0;
+  (void)conn;
+  (void)sockindex; /* we only support SCP on the fixed known primary socket */
+  (void)mem;
+  (void)len;
+  (void)err;
+
+  return nwrite;
+}
+
+static ssize_t wscp_recv(struct connectdata *conn, int sockindex,
+                         char *mem, size_t len, CURLcode *err)
+{
+  ssize_t nread = 0;
+  (void)conn;
+  (void)sockindex; /* we only support SCP on the fixed known primary socket */
+  (void)mem;
+  (void)len;
+  (void)err;
+
+  return nread;
+}
+
+/* return number of sent bytes */
+static ssize_t wsftp_send(struct connectdata *conn, int sockindex,
+                          const void *mem, size_t len, CURLcode *err)
+{
+  struct ssh_conn *sshc = &conn->proto.sshc;
+  word32 offset[2];
+  int rc;
+  (void)sockindex;
+
+  offset[0] =  (word32)sshc->offset&0xFFFFFFFF;
+  offset[1] =  (word32)(sshc->offset>>32)&0xFFFFFFFF;
+
+  rc = wolfSSH_SFTP_SendWritePacket(sshc->ssh_session, sshc->handle,
+                                    sshc->handleSz,
+                                    &offset[0],
+                                    (byte *)mem, (word32)len);
+
+  if(rc == WS_FATAL_ERROR)
+    rc = wolfSSH_get_error(sshc->ssh_session);
+  if(rc == WS_WANT_READ) {
+    conn->waitfor = KEEP_RECV;
+    *err = CURLE_AGAIN;
+    return -1;
+  }
+  else if(rc == WS_WANT_WRITE) {
+    conn->waitfor = KEEP_SEND;
+    *err = CURLE_AGAIN;
+    return -1;
+  }
+  if(rc < 0) {
+    failf(conn->data, "wolfSSH_SFTP_SendWritePacket returned %d\n", rc);
+    return -1;
+  }
+  DEBUGASSERT(rc == (int)len);
+  infof(conn->data, "sent %zd bytes SFTP from offset %zd\n",
+        len, sshc->offset);
+  sshc->offset += len;
+  return (ssize_t)rc;
+}
+
+/*
+ * Return number of received (decrypted) bytes
+ * or <0 on error
+ */
+static ssize_t wsftp_recv(struct connectdata *conn, int sockindex,
+                          char *mem, size_t len, CURLcode *err)
+{
+  int rc;
+  struct ssh_conn *sshc = &conn->proto.sshc;
+  word32 offset[2];
+  (void)sockindex;
+
+  offset[0] =  (word32)sshc->offset&0xFFFFFFFF;
+  offset[1] =  (word32)(sshc->offset>>32)&0xFFFFFFFF;
+
+  rc = wolfSSH_SFTP_SendReadPacket(sshc->ssh_session, sshc->handle,
+                                   sshc->handleSz,
+                                   &offset[0],
+                                   (byte *)mem, (word32)len);
+  if(rc == WS_FATAL_ERROR)
+    rc = wolfSSH_get_error(sshc->ssh_session);
+  if(rc == WS_WANT_READ) {
+    conn->waitfor = KEEP_RECV;
+    *err = CURLE_AGAIN;
+    return -1;
+  }
+  else if(rc == WS_WANT_WRITE) {
+    conn->waitfor = KEEP_SEND;
+    *err = CURLE_AGAIN;
+    return -1;
+  }
+
+  DEBUGASSERT(rc <= (int)len);
+
+  if(rc < 0) {
+    failf(conn->data, "wolfSSH_SFTP_SendReadPacket returned %d\n", rc);
+    return -1;
+  }
+  sshc->offset += len;
+
+  return (ssize_t)rc;
+}
+
+/*
+ * SSH setup and connection
+ */
+static CURLcode wssh_setup_connection(struct connectdata *conn)
+{
+  struct SSHPROTO *ssh;
+
+  conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
+  if(!ssh)
+    return CURLE_OUT_OF_MEMORY;
+
+  return CURLE_OK;
+}
+
+static Curl_recv wscp_recv, wsftp_recv;
+static Curl_send wscp_send, wsftp_send;
+
+static int userauth(byte authtype,
+                    WS_UserAuthData* authdata,
+                    void *ctx)
+{
+  struct connectdata *conn = ctx;
+  DEBUGF(infof(conn->data, "wolfssh callback: type %s\n",
+               authtype == WOLFSSH_USERAUTH_PASSWORD ? "PASSWORD" :
+               "PUBLICCKEY"));
+  if(authtype == WOLFSSH_USERAUTH_PASSWORD) {
+    authdata->sf.password.password = (byte *)conn->passwd;
+    authdata->sf.password.passwordSz = (word32) strlen(conn->passwd);
+  }
+
+  return 0;
+}
+
+static CURLcode wssh_connect(struct connectdata *conn, bool *done)
+{
+  struct Curl_easy *data = conn->data;
+  struct ssh_conn *sshc;
+  curl_socket_t sock = conn->sock[FIRSTSOCKET];
+  int rc;
+
+  /* initialize per-handle data if not already */
+  if(!data->req.protop)
+    wssh_setup_connection(conn);
+
+  /* We default to persistent connections. We set this already in this connect
+     function to make the re-use checks properly be able to check this bit. */
+  connkeep(conn, "SSH default");
+
+  if(conn->handler->protocol & CURLPROTO_SCP) {
+    conn->recv[FIRSTSOCKET] = wscp_recv;
+    conn->send[FIRSTSOCKET] = wscp_send;
+  }
+  else {
+    conn->recv[FIRSTSOCKET] = wsftp_recv;
+    conn->send[FIRSTSOCKET] = wsftp_send;
+  }
+  sshc = &conn->proto.sshc;
+  sshc->ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL);
+  if(!sshc->ctx) {
+    failf(data, "No wolfSSH context");
+    goto error;
+  }
+
+  sshc->ssh_session = wolfSSH_new(sshc->ctx);
+  if(sshc->ssh_session == NULL) {
+    failf(data, "No wolfSSH session");
+    goto error;
+  }
+
+  rc = wolfSSH_SetUsername(sshc->ssh_session, conn->user);
+  if(rc != WS_SUCCESS) {
+    failf(data, "wolfSSH failed to set user name");
+    goto error;
+  }
+
+  /* set callback for authentication */
+  wolfSSH_SetUserAuth(sshc->ctx, userauth);
+  wolfSSH_SetUserAuthCtx(sshc->ssh_session, conn);
+
+  rc = wolfSSH_set_fd(sshc->ssh_session, (int)sock);
+  if(rc) {
+    failf(data, "wolfSSH failed to set socket");
+    goto error;
+  }
+
+#if 0
+  wolfSSH_Debugging_ON();
+#endif
+
+  *done = TRUE;
+  if(conn->handler->protocol & CURLPROTO_SCP)
+    state(conn, SSH_INIT);
+  else
+    state(conn, SSH_SFTP_INIT);
+
+  return wssh_multi_statemach(conn, done);
+  error:
+  wolfSSH_free(sshc->ssh_session);
+  wolfSSH_CTX_free(sshc->ctx);
+  return CURLE_FAILED_INIT;
+}
+
+/*
+ * wssh_statemach_act() runs the SSH state machine as far as it can without
+ * blocking and without reaching the end.  The data the pointer 'block' points
+ * to will be set to TRUE if the wolfssh function returns EAGAIN meaning it
+ * wants to be called again when the socket is ready
+ */
+
+static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
+{
+  CURLcode result = CURLE_OK;
+  struct ssh_conn *sshc = &conn->proto.sshc;
+  struct Curl_easy *data = conn->data;
+  struct SSHPROTO *sftp_scp = data->req.protop;
+  WS_SFTPNAME *name;
+  int rc = 0;
+  *block = FALSE; /* we're not blocking by default */
+
+  do {
+    switch(sshc->state) {
+    case SSH_INIT:
+      state(conn, SSH_S_STARTUP);
+      /* FALLTHROUGH */
+    case SSH_S_STARTUP:
+      rc = wolfSSH_connect(sshc->ssh_session);
+      if(rc != WS_SUCCESS)
+        rc = wolfSSH_get_error(sshc->ssh_session);
+      if(rc == WS_WANT_READ) {
+        *block = TRUE;
+        conn->waitfor = KEEP_RECV;
+        return CURLE_OK;
+      }
+      else if(rc == WS_WANT_WRITE) {
+        *block = TRUE;
+        conn->waitfor = KEEP_SEND;
+        return CURLE_OK;
+      }
+      else if(rc != WS_SUCCESS) {
+        state(conn, SSH_STOP);
+        return CURLE_SSH;
+      }
+      infof(data, "wolfssh connected!\n");
+      state(conn, SSH_STOP);
+      break;
+    case SSH_STOP:
+      break;
+
+    case SSH_SFTP_INIT:
+      rc = wolfSSH_SFTP_connect(sshc->ssh_session);
+      if(rc != WS_SUCCESS)
+        rc = wolfSSH_get_error(sshc->ssh_session);
+      if(rc == WS_WANT_READ) {
+        *block = TRUE;
+        conn->waitfor = KEEP_RECV;
+        return CURLE_OK;
+      }
+      else if(rc == WS_WANT_WRITE) {
+        *block = TRUE;
+        conn->waitfor = KEEP_SEND;
+        return CURLE_OK;
+      }
+      else if(rc == WS_SUCCESS) {
+        infof(data, "wolfssh SFTP connected!\n");
+        state(conn, SSH_SFTP_REALPATH);
+      }
+      else {
+        failf(data, "wolfssh SFTP connect error %d", rc);
+        return CURLE_SSH;
+      }
+      break;
+    case SSH_SFTP_REALPATH:
+      name = wolfSSH_SFTP_RealPath(sshc->ssh_session, (char *)".");
+      rc = wolfSSH_get_error(sshc->ssh_session);
+      if(rc == WS_WANT_READ) {
+        *block = TRUE;
+        conn->waitfor = KEEP_RECV;
+        return CURLE_OK;
+      }
+      else if(rc == WS_WANT_WRITE) {
+        *block = TRUE;
+        conn->waitfor = KEEP_SEND;
+        return CURLE_OK;
+      }
+      else if(name && (rc == WS_SUCCESS)) {
+        sshc->homedir = malloc(name->fSz + 1);
+        if(!sshc->homedir) {
+          sshc->actualcode = CURLE_OUT_OF_MEMORY;
+        }
+        else {
+          memcpy(sshc->homedir, name->fName, name->fSz);
+          sshc->homedir[name->fSz] = 0;
+          infof(data, "wolfssh SFTP realpath succeeded!\n");
+        }
+        wolfSSH_SFTPNAME_list_free(name);
+        state(conn, SSH_STOP);
+        return CURLE_OK;
+      }
+      failf(data, "wolfssh SFTP realpath %d", rc);
+      return CURLE_SSH;
+
+    case SSH_SFTP_QUOTE_INIT:
+      result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
+      if(result) {
+        sshc->actualcode = result;
+        state(conn, SSH_STOP);
+        break;
+      }
+
+      if(data->set.quote) {
+        infof(data, "Sending quote commands\n");
+        sshc->quote_item = data->set.quote;
+        state(conn, SSH_SFTP_QUOTE);
+      }
+      else {
+        state(conn, SSH_SFTP_GETINFO);
+      }
+      break;
+    case SSH_SFTP_GETINFO:
+      if(data->set.get_filetime) {
+        state(conn, SSH_SFTP_FILETIME);
+      }
+      else {
+        state(conn, SSH_SFTP_TRANS_INIT);
+      }
+      break;
+    case SSH_SFTP_TRANS_INIT:
+      if(data->set.upload)
+        state(conn, SSH_SFTP_UPLOAD_INIT);
+      else {
+        if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
+          state(conn, SSH_SFTP_READDIR_INIT);
+        else
+          state(conn, SSH_SFTP_DOWNLOAD_INIT);
+      }
+      break;
+    case SSH_SFTP_UPLOAD_INIT: {
+      word32 flags;
+      WS_SFTP_FILEATRB createattrs;
+      if(data->state.resume_from) {
+        WS_SFTP_FILEATRB attrs;
+        if(data->state.resume_from < 0) {
+          rc = wolfSSH_SFTP_STAT(sshc->ssh_session, sftp_scp->path,
+                                 &attrs);
+          if(rc != WS_SUCCESS)
+            break;
+
+          if(rc) {
+            data->state.resume_from = 0;
+          }
+          else {
+            curl_off_t size = ((curl_off_t)attrs.sz[1] << 32) | attrs.sz[0];
+            if(size < 0) {
+              failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
+              return CURLE_BAD_DOWNLOAD_RESUME;
+            }
+            data->state.resume_from = size;
+          }
+        }
+      }
+
+      if(data->set.ftp_append)
+        /* Try to open for append, but create if nonexisting */
+        flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_APPEND;
+      else if(data->state.resume_from > 0)
+        /* If we have restart position then open for append */
+        flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_APPEND;
+      else
+        /* Clear file before writing (normal behaviour) */
+        flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_TRUNC;
+
+      memset(&createattrs, 0, sizeof(createattrs));
+      createattrs.per = (word32)data->set.new_file_perms;
+      sshc->handleSz = sizeof(sshc->handle);
+      rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path,
+                             flags, &createattrs,
+                             sshc->handle, &sshc->handleSz);
+      if(rc == WS_FATAL_ERROR)
+        rc = wolfSSH_get_error(sshc->ssh_session);
+      if(rc == WS_WANT_READ) {
+        *block = TRUE;
+        conn->waitfor = KEEP_RECV;
+        return CURLE_OK;
+      }
+      else if(rc == WS_WANT_WRITE) {
+        *block = TRUE;
+        conn->waitfor = KEEP_SEND;
+        return CURLE_OK;
+      }
+      else if(rc == WS_SUCCESS) {
+        infof(data, "wolfssh SFTP open succeeded!\n");
+      }
+      else {
+        failf(data, "wolfssh SFTP upload open failed: %d", rc);
+        return CURLE_SSH;
+      }
+      state(conn, SSH_SFTP_DOWNLOAD_STAT);
+
+      /* If we have a restart point then we need to seek to the correct
+         position. */
+      if(data->state.resume_from > 0) {
+        /* Let's read off the proper amount of bytes from the input. */
+        int seekerr = CURL_SEEKFUNC_OK;
+        if(conn->seek_func) {
+          Curl_set_in_callback(data, true);
+          seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
+                                    SEEK_SET);
+          Curl_set_in_callback(data, false);
+        }
+
+        if(seekerr != CURL_SEEKFUNC_OK) {
+          curl_off_t passed = 0;
+
+          if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
+            failf(data, "Could not seek stream");
+            return CURLE_FTP_COULDNT_USE_REST;
+          }
+          /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
+          do {
+            size_t readthisamountnow =
+              (data->state.resume_from - passed > data->set.buffer_size) ?
+              (size_t)data->set.buffer_size :
+              curlx_sotouz(data->state.resume_from - passed);
+
+            size_t actuallyread;
+            Curl_set_in_callback(data, true);
+            actuallyread = data->state.fread_func(data->state.buffer, 1,
+                                                  readthisamountnow,
+                                                  data->state.in);
+            Curl_set_in_callback(data, false);
+
+            passed += actuallyread;
+            if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
+              /* this checks for greater-than only to make sure that the
+                 CURL_READFUNC_ABORT return code still aborts */
+              failf(data, "Failed to read data");
+              return CURLE_FTP_COULDNT_USE_REST;
+            }
+          } while(passed < data->state.resume_from);
+        }
+
+        /* now, decrease the size of the read */
+        if(data->state.infilesize > 0) {
+          data->state.infilesize -= data->state.resume_from;
+          data->req.size = data->state.infilesize;
+          Curl_pgrsSetUploadSize(data, data->state.infilesize);
+        }
+
+        sshc->offset += data->state.resume_from;
+      }
+      if(data->state.infilesize > 0) {
+        data->req.size = data->state.infilesize;
+        Curl_pgrsSetUploadSize(data, data->state.infilesize);
+      }
+      /* upload data */
+      Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
+
+      /* not set by Curl_setup_transfer to preserve keepon bits */
+      conn->sockfd = conn->writesockfd;
+
+      if(result) {
+        state(conn, SSH_SFTP_CLOSE);
+        sshc->actualcode = result;
+      }
+      else {
+        /* store this original bitmask setup to use later on if we can't
+           figure out a "real" bitmask */
+        sshc->orig_waitfor = data->req.keepon;
+
+        /* we want to use the _sending_ function even when the socket turns
+           out readable as the underlying libssh2 sftp send function will deal
+           with both accordingly */
+        conn->cselect_bits = CURL_CSELECT_OUT;
+
+        /* since we don't really wait for anything at this point, we want the
+           state machine to move on as soon as possible so we set a very short
+           timeout here */
+        Curl_expire(data, 0, EXPIRE_RUN_NOW);
+
+        state(conn, SSH_STOP);
+      }
+      break;
+    }
+    case SSH_SFTP_DOWNLOAD_INIT:
+      sshc->handleSz = sizeof(sshc->handle);
+      rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path,
+                             WOLFSSH_FXF_READ, NULL,
+                             sshc->handle, &sshc->handleSz);
+      if(rc == WS_FATAL_ERROR)
+        rc = wolfSSH_get_error(sshc->ssh_session);
+      if(rc == WS_WANT_READ) {
+        *block = TRUE;
+        conn->waitfor = KEEP_RECV;
+        return CURLE_OK;
+      }
+      else if(rc == WS_WANT_WRITE) {
+        *block = TRUE;
+        conn->waitfor = KEEP_SEND;
+        return CURLE_OK;
+      }
+      else if(rc == WS_SUCCESS) {
+        infof(data, "wolfssh SFTP open succeeded!\n");
+        state(conn, SSH_SFTP_DOWNLOAD_STAT);
+        return CURLE_OK;
+      }
+
+      failf(data, "wolfssh SFTP open failed: %d", rc);
+      return CURLE_SSH;
+
+    case SSH_SFTP_DOWNLOAD_STAT: {
+      WS_SFTP_FILEATRB attrs;
+      curl_off_t size;
+
+      rc = wolfSSH_SFTP_STAT(sshc->ssh_session, sftp_scp->path, &attrs);
+      if(rc == WS_FATAL_ERROR)
+        rc = wolfSSH_get_error(sshc->ssh_session);
+      if(rc == WS_WANT_READ) {
+        *block = TRUE;
+        conn->waitfor = KEEP_RECV;
+        return CURLE_OK;
+      }
+      else if(rc == WS_WANT_WRITE) {
+        *block = TRUE;
+        conn->waitfor = KEEP_SEND;
+        return CURLE_OK;
+      }
+      else if(rc == WS_SUCCESS) {
+        infof(data, "wolfssh STAT succeeded!\n");
+      }
+      else {
+        failf(data, "wolfssh SFTP open failed: %d", rc);
+        data->req.size = -1;
+        data->req.maxdownload = -1;
+        Curl_pgrsSetDownloadSize(data, -1);
+        return CURLE_SSH;
+      }
+
+      size = ((curl_off_t)attrs.sz[1] <<32) | attrs.sz[0];
+
+      data->req.size = size;
+      data->req.maxdownload = size;
+      Curl_pgrsSetDownloadSize(data, size);
+
+      infof(data, "SFTP download %" CURL_FORMAT_CURL_OFF_T " bytes\n", size);
+
+      /* We cannot seek with wolfSSH so resuming and range requests are not
+         possible */
+      if(conn->data->state.use_range || data->state.resume_from) {
+        infof(data, "wolfSSH cannot do range/seek on SFTP\n");
+        return CURLE_BAD_DOWNLOAD_RESUME;
+      }
+
+      /* Setup the actual download */
+      if(data->req.size == 0) {
+        /* no data to transfer */
+        Curl_setup_transfer(data, -1, -1, FALSE, -1);
+        infof(data, "File already completely downloaded\n");
+        state(conn, SSH_STOP);
+        break;
+      }
+      Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
+
+      /* not set by Curl_setup_transfer to preserve keepon bits */
+      conn->writesockfd = conn->sockfd;
+
+      /* we want to use the _receiving_ function even when the socket turns
+         out writableable as the underlying libssh2 recv function will deal
+         with both accordingly */
+      conn->cselect_bits = CURL_CSELECT_IN;
+
+      if(result) {
+        /* this should never occur; the close state should be entered
+           at the time the error occurs */
+        state(conn, SSH_SFTP_CLOSE);
+        sshc->actualcode = result;
+      }
+      else {
+        state(conn, SSH_STOP);
+      }
+      break;
+    }
+    case SSH_SFTP_CLOSE:
+      if(sshc->handleSz)
+        rc = wolfSSH_SFTP_Close(sshc->ssh_session, sshc->handle,
+                                sshc->handleSz);
+      else
+        rc = WS_SUCCESS; /* directory listing */
+      if(rc == WS_WANT_READ) {
+        *block = TRUE;
+        conn->waitfor = KEEP_RECV;
+        return CURLE_OK;
+      }
+      else if(rc == WS_WANT_WRITE) {
+        *block = TRUE;
+        conn->waitfor = KEEP_SEND;
+        return CURLE_OK;
+      }
+      else if(rc == WS_SUCCESS) {
+        state(conn, SSH_STOP);
+        return CURLE_OK;
+      }
+
+      failf(data, "wolfssh SFTP CLOSE failed: %d", rc);
+      return CURLE_SSH;
+
+    case SSH_SFTP_READDIR_INIT:
+      Curl_pgrsSetDownloadSize(data, -1);
+      if(data->set.opt_no_body) {
+        state(conn, SSH_STOP);
+        break;
+      }
+      state(conn, SSH_SFTP_READDIR);
+      /* FALLTHROUGH */
+    case SSH_SFTP_READDIR:
+      name = wolfSSH_SFTP_LS(sshc->ssh_session, sftp_scp->path);
+      if(!name)
+        rc = wolfSSH_get_error(sshc->ssh_session);
+      else
+        rc = WS_SUCCESS;
+
+      if(rc == WS_WANT_READ) {
+        *block = TRUE;
+        conn->waitfor = KEEP_RECV;
+        return CURLE_OK;
+      }
+      else if(rc == WS_WANT_WRITE) {
+        *block = TRUE;
+        conn->waitfor = KEEP_SEND;
+        return CURLE_OK;
+      }
+      else if(name && (rc == WS_SUCCESS)) {
+        WS_SFTPNAME *origname = name;
+        result = CURLE_OK;
+        while(name) {
+          char *line = aprintf("%s\n",
+                               data->set.ftp_list_only ?
+                               name->fName : name->lName);
+          if(line == NULL) {
+            state(conn, SSH_SFTP_CLOSE);
+            sshc->actualcode = CURLE_OUT_OF_MEMORY;
+            break;
+          }
+          result = Curl_client_write(conn, CLIENTWRITE_BODY,
+                                     line, strlen(line));
+          free(line);
+          if(result) {
+            sshc->actualcode = result;
+            break;
+          }
+          name = name->next;
+        }
+        wolfSSH_SFTPNAME_list_free(origname);
+        state(conn, SSH_STOP);
+        return result;
+      }
+      failf(data, "wolfssh SFTP ls failed: %d", rc);
+      return CURLE_SSH;
+
+    case SSH_SFTP_SHUTDOWN:
+      Curl_safefree(sshc->homedir);
+      wolfSSH_free(sshc->ssh_session);
+      wolfSSH_CTX_free(sshc->ctx);
+      state(conn, SSH_STOP);
+      return CURLE_OK;
+    default:
+      break;
+    }
+  } while(!rc && (sshc->state != SSH_STOP));
+  return result;
+}
+
+/* called repeatedly until done from multi.c */
+static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done)
+{
+  struct ssh_conn *sshc = &conn->proto.sshc;
+  CURLcode result = CURLE_OK;
+  bool block; /* we store the status and use that to provide a ssh_getsock()
+                 implementation */
+  do {
+    result = wssh_statemach_act(conn, &block);
+    *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
+    /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
+       try again */
+    if(*done) {
+      DEBUGF(infof(conn->data, "wssh_statemach_act says DONE\n"));
+    }
+  } while(!result && !*done && !block);
+
+  return result;
+}
+
+static
+CURLcode wscp_perform(struct connectdata *conn,
+                      bool *connected,
+                      bool *dophase_done)
+{
+  (void)conn;
+  (void)connected;
+  (void)dophase_done;
+  return CURLE_OK;
+}
+
+static
+CURLcode wsftp_perform(struct connectdata *conn,
+                       bool *connected,
+                       bool *dophase_done)
+{
+  CURLcode result = CURLE_OK;
+
+  DEBUGF(infof(conn->data, "DO phase starts\n"));
+
+  *dophase_done = FALSE; /* not done yet */
+
+  /* start the first command in the DO phase */
+  state(conn, SSH_SFTP_QUOTE_INIT);
+
+  /* run the state-machine */
+  result = wssh_multi_statemach(conn, dophase_done);
+
+  *connected = conn->bits.tcpconnect[FIRSTSOCKET];
+
+  if(*dophase_done) {
+    DEBUGF(infof(conn->data, "DO phase is complete\n"));
+  }
+
+  return result;
+}
+
+/*
+ * The DO function is generic for both protocols.
+ */
+static CURLcode wssh_do(struct connectdata *conn, bool *done)
+{
+  CURLcode result;
+  bool connected = 0;
+  struct Curl_easy *data = conn->data;
+  struct ssh_conn *sshc = &conn->proto.sshc;
+
+  *done = FALSE; /* default to false */
+  data->req.size = -1; /* make sure this is unknown at this point */
+  sshc->actualcode = CURLE_OK; /* reset error code */
+  sshc->secondCreateDirs = 0;   /* reset the create dir attempt state
+                                   variable */
+
+  Curl_pgrsSetUploadCounter(data, 0);
+  Curl_pgrsSetDownloadCounter(data, 0);
+  Curl_pgrsSetUploadSize(data, -1);
+  Curl_pgrsSetDownloadSize(data, -1);
+
+  if(conn->handler->protocol & CURLPROTO_SCP)
+    result = wscp_perform(conn, &connected,  done);
+  else
+    result = wsftp_perform(conn, &connected,  done);
+
+  return result;
+}
+
+static CURLcode wssh_block_statemach(struct connectdata *conn,
+                                    bool disconnect)
+{
+  struct ssh_conn *sshc = &conn->proto.sshc;
+  CURLcode result = CURLE_OK;
+  struct Curl_easy *data = conn->data;
+
+  while((sshc->state != SSH_STOP) && !result) {
+    bool block;
+    timediff_t left = 1000;
+    struct curltime now = Curl_now();
+
+    result = wssh_statemach_act(conn, &block);
+    if(result)
+      break;
+
+    if(!disconnect) {
+      if(Curl_pgrsUpdate(conn))
+        return CURLE_ABORTED_BY_CALLBACK;
+
+      result = Curl_speedcheck(data, now);
+      if(result)
+        break;
+
+      left = Curl_timeleft(data, NULL, FALSE);
+      if(left < 0) {
+        failf(data, "Operation timed out");
+        return CURLE_OPERATION_TIMEDOUT;
+      }
+    }
+
+    if(!result) {
+      int dir = conn->waitfor;
+      curl_socket_t sock = conn->sock[FIRSTSOCKET];
+      curl_socket_t fd_read = CURL_SOCKET_BAD;
+      curl_socket_t fd_write = CURL_SOCKET_BAD;
+      if(dir == KEEP_RECV)
+        fd_read = sock;
+      else if(dir == KEEP_SEND)
+        fd_write = sock;
+
+      /* wait for the socket to become ready */
+      (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
+                              left>1000?1000:left); /* ignore result */
+    }
+  }
+
+  return result;
+}
+
+/* generic done function for both SCP and SFTP called from their specific
+   done functions */
+static CURLcode wssh_done(struct connectdata *conn, CURLcode status)
+{
+  CURLcode result = CURLE_OK;
+  struct SSHPROTO *sftp_scp = conn->data->req.protop;
+
+  if(!status) {
+    /* run the state-machine */
+    result = wssh_block_statemach(conn, FALSE);
+  }
+  else
+    result = status;
+
+  if(sftp_scp)
+    Curl_safefree(sftp_scp->path);
+  if(Curl_pgrsDone(conn))
+    return CURLE_ABORTED_BY_CALLBACK;
+
+  conn->data->req.keepon = 0; /* clear all bits */
+  return result;
+}
+
+#if 0
+static CURLcode wscp_done(struct connectdata *conn,
+                         CURLcode code, bool premature)
+{
+  CURLcode result = CURLE_OK;
+  (void)conn;
+  (void)code;
+  (void)premature;
+
+  return result;
+}
+
+static CURLcode wscp_doing(struct connectdata *conn,
+                          bool *dophase_done)
+{
+  CURLcode result = CURLE_OK;
+  (void)conn;
+  (void)dophase_done;
+
+  return result;
+}
+
+static CURLcode wscp_disconnect(struct connectdata *conn, bool dead_connection)
+{
+  CURLcode result = CURLE_OK;
+  (void)conn;
+  (void)dead_connection;
+
+  return result;
+}
+#endif
+
+static CURLcode wsftp_done(struct connectdata *conn,
+                          CURLcode code, bool premature)
+{
+  (void)premature;
+  state(conn, SSH_SFTP_CLOSE);
+
+  return wssh_done(conn, code);
+}
+
+static CURLcode wsftp_doing(struct connectdata *conn,
+                           bool *dophase_done)
+{
+  CURLcode result = wssh_multi_statemach(conn, dophase_done);
+
+  if(*dophase_done) {
+    DEBUGF(infof(conn->data, "DO phase is complete\n"));
+  }
+  return result;
+}
+
+static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead)
+{
+  CURLcode result = CURLE_OK;
+  (void)dead;
+
+  DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
+
+  if(conn->proto.sshc.ssh_session) {
+    /* only if there's a session still around to use! */
+    state(conn, SSH_SFTP_SHUTDOWN);
+    result = wssh_block_statemach(conn, TRUE);
+  }
+
+  DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
+  return result;
+}
+
+static int wssh_getsock(struct connectdata *conn,
+                        curl_socket_t *sock)
+{
+  return wssh_perform_getsock(conn, sock);
+}
+
+static int wssh_perform_getsock(const struct connectdata *conn,
+                                curl_socket_t *sock)
+{
+  int bitmap = GETSOCK_BLANK;
+  int dir = conn->waitfor;
+  sock[0] = conn->sock[FIRSTSOCKET];
+
+  if(dir == KEEP_RECV)
+    bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
+  else if(dir == KEEP_SEND)
+    bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
+
+  return bitmap;
+}
+
+size_t Curl_ssh_version(char *buffer, size_t buflen)
+{
+  return msnprintf(buffer, buflen, "wolfssh/%s", LIBWOLFSSH_VERSION_STRING);
+}
+
+CURLcode Curl_ssh_init(void)
+{
+  if(WS_SUCCESS != wolfSSH_Init()) {
+    DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n"));
+    return CURLE_FAILED_INIT;
+  }
+
+  return CURLE_OK;
+}
+void Curl_ssh_cleanup(void)
+{
+}
+
+#endif /* USE_WOLFSSH */
diff --git a/lib/vtls/polarssl.h b/lib/vssh/wolfssh.h
similarity index 73%
rename from lib/vtls/polarssl.h
rename to lib/vssh/wolfssh.h
index f36f24f8d..a9b9a3b09 100644
--- a/lib/vtls/polarssl.h
+++ b/lib/vssh/wolfssh.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_POLARSSL_H
-#define HEADER_CURL_POLARSSL_H
+#ifndef HEADER_CURL_WOLFSSH_H
+#define HEADER_CURL_WOLFSSH_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -7,8 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <address@hidden>, et al.
- * Copyright (C) 2010, Hoi-Ho Chan, <address@hidden>
+ * Copyright (C) 2019 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,11 +21,7 @@
  * KIND, either express or implied.
  *
  ***************************************************************************/
-#include "curl_setup.h"
 
-#ifdef USE_POLARSSL
+extern const struct Curl_handler Curl_handler_sftp;
 
-extern const struct Curl_ssl Curl_ssl_polarssl;
-
-#endif /* USE_POLARSSL */
-#endif /* HEADER_CURL_POLARSSL_H */
+#endif /* HEADER_CURL_WOLFSSH_H */
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index 3737d7c68..5f740eeba 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -666,6 +666,10 @@ gtls_connect_step1(struct connectdata *conn,
   /* Initialize TLS session as a client */
   init_flags = GNUTLS_CLIENT;
 
+#if defined(GNUTLS_FORCE_CLIENT_CERT)
+  init_flags |= GNUTLS_FORCE_CLIENT_CERT;
+#endif
+
 #if defined(GNUTLS_NO_TICKETS)
   /* Disable TLS session tickets */
   init_flags |= GNUTLS_NO_TICKETS;
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index e34ec9d13..f057315f3 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <address@hidden>
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2012 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -55,7 +55,7 @@
 #include "connect.h" /* for the connect timeout */
 #include "select.h"
 #include "multiif.h"
-#include "polarssl_threadlock.h"
+#include "mbedtls_threadlock.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -91,12 +91,12 @@ static int entropy_init_initialized = 0;
 static void entropy_init_mutex(mbedtls_entropy_context *ctx)
 {
   /* lock 0 = entropy_init_mutex() */
-  Curl_polarsslthreadlock_lock_function(0);
+  Curl_mbedtlsthreadlock_lock_function(0);
   if(entropy_init_initialized == 0) {
     mbedtls_entropy_init(ctx);
     entropy_init_initialized = 1;
   }
-  Curl_polarsslthreadlock_unlock_function(0);
+  Curl_mbedtlsthreadlock_unlock_function(0);
 }
 /* end of entropy_init_mutex() */
 
@@ -105,9 +105,9 @@ static int entropy_func_mutex(void *data, unsigned char 
*output, size_t len)
 {
   int ret;
   /* lock 1 = entropy_func_mutex() */
-  Curl_polarsslthreadlock_lock_function(1);
+  Curl_mbedtlsthreadlock_lock_function(1);
   ret = mbedtls_entropy_func(data, output, len);
-  Curl_polarsslthreadlock_unlock_function(1);
+  Curl_mbedtlsthreadlock_unlock_function(1);
 
   return ret;
 }
@@ -1017,12 +1017,12 @@ static CURLcode Curl_mbedtls_connect(struct connectdata 
*conn, int sockindex)
  */
 static int Curl_mbedtls_init(void)
 {
-  return Curl_polarsslthreadlock_thread_setup();
+  return Curl_mbedtlsthreadlock_thread_setup();
 }
 
 static void Curl_mbedtls_cleanup(void)
 {
-  (void)Curl_polarsslthreadlock_thread_cleanup();
+  (void)Curl_mbedtlsthreadlock_thread_cleanup();
 }
 
 static bool Curl_mbedtls_data_pending(const struct connectdata *conn,
diff --git a/lib/vtls/polarssl_threadlock.c b/lib/vtls/mbedtls_threadlock.c
similarity index 76%
rename from lib/vtls/polarssl_threadlock.c
rename to lib/vtls/mbedtls_threadlock.c
index 4e269c8e6..4d672f106 100644
--- a/lib/vtls/polarssl_threadlock.c
+++ b/lib/vtls/mbedtls_threadlock.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2013 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2013 - 2020, Daniel Stenberg, <address@hidden>, et al.
  * Copyright (C) 2010, 2011, Hoi-Ho Chan, <address@hidden>
  *
  * This software is licensed as described in the file COPYING, which
@@ -22,19 +22,19 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
-#if (defined(USE_POLARSSL) || defined(USE_MBEDTLS)) && \
-    ((defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
-     (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)))
+#if defined(USE_MBEDTLS) &&                                     \
+  ((defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) ||   \
+   (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)))
 
 #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
 #  include <pthread.h>
-#  define POLARSSL_MUTEX_T pthread_mutex_t
+#  define MBEDTLS_MUTEX_T pthread_mutex_t
 #elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
 #  include <process.h>
-#  define POLARSSL_MUTEX_T HANDLE
+#  define MBEDTLS_MUTEX_T HANDLE
 #endif
 
-#include "polarssl_threadlock.h"
+#include "mbedtls_threadlock.h"
 #include "curl_printf.h"
 #include "curl_memory.h"
 /* The last #include file should be: */
@@ -43,14 +43,14 @@
 /* number of thread locks */
 #define NUMT                    2
 
-/* This array will store all of the mutexes available to PolarSSL. */
-static POLARSSL_MUTEX_T *mutex_buf = NULL;
+/* This array will store all of the mutexes available to Mbedtls. */
+static MBEDTLS_MUTEX_T *mutex_buf = NULL;
 
-int Curl_polarsslthreadlock_thread_setup(void)
+int Curl_mbedtlsthreadlock_thread_setup(void)
 {
   int i;
 
-  mutex_buf = calloc(NUMT * sizeof(POLARSSL_MUTEX_T), 1);
+  mutex_buf = calloc(NUMT * sizeof(MBEDTLS_MUTEX_T), 1);
   if(!mutex_buf)
     return 0;     /* error, no number of threads defined */
 
@@ -70,7 +70,7 @@ int Curl_polarsslthreadlock_thread_setup(void)
   return 1; /* OK */
 }
 
-int Curl_polarsslthreadlock_thread_cleanup(void)
+int Curl_mbedtlsthreadlock_thread_cleanup(void)
 {
   int i;
 
@@ -95,7 +95,7 @@ int Curl_polarsslthreadlock_thread_cleanup(void)
   return 1; /* OK */
 }
 
-int Curl_polarsslthreadlock_lock_function(int n)
+int Curl_mbedtlsthreadlock_lock_function(int n)
 {
   if(n < NUMT) {
     int ret;
@@ -103,14 +103,14 @@ int Curl_polarsslthreadlock_lock_function(int n)
     ret = pthread_mutex_lock(&mutex_buf[n]);
     if(ret) {
       DEBUGF(fprintf(stderr,
-                     "Error: polarsslthreadlock_lock_function failed\n"));
+                     "Error: mbedtlsthreadlock_lock_function failed\n"));
       return 0; /* pthread_mutex_lock failed */
     }
 #elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
     ret = (WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED?1:0);
     if(ret) {
       DEBUGF(fprintf(stderr,
-                     "Error: polarsslthreadlock_lock_function failed\n"));
+                     "Error: mbedtlsthreadlock_lock_function failed\n"));
       return 0; /* pthread_mutex_lock failed */
     }
 #endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */
@@ -118,7 +118,7 @@ int Curl_polarsslthreadlock_lock_function(int n)
   return 1; /* OK */
 }
 
-int Curl_polarsslthreadlock_unlock_function(int n)
+int Curl_mbedtlsthreadlock_unlock_function(int n)
 {
   if(n < NUMT) {
     int ret;
@@ -126,14 +126,14 @@ int Curl_polarsslthreadlock_unlock_function(int n)
     ret = pthread_mutex_unlock(&mutex_buf[n]);
     if(ret) {
       DEBUGF(fprintf(stderr,
-                     "Error: polarsslthreadlock_unlock_function failed\n"));
+                     "Error: mbedtlsthreadlock_unlock_function failed\n"));
       return 0; /* pthread_mutex_unlock failed */
     }
 #elif defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H)
     ret = ReleaseMutex(mutex_buf[n]);
     if(!ret) {
       DEBUGF(fprintf(stderr,
-                     "Error: polarsslthreadlock_unlock_function failed\n"));
+                     "Error: mbedtlsthreadlock_unlock_function failed\n"));
       return 0; /* pthread_mutex_lock failed */
     }
 #endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */
@@ -141,4 +141,4 @@ int Curl_polarsslthreadlock_unlock_function(int n)
   return 1; /* OK */
 }
 
-#endif /* USE_POLARSSL || USE_MBEDTLS */
+#endif /* USE_MBEDTLS */
diff --git a/lib/vtls/polarssl_threadlock.h b/lib/vtls/mbedtls_threadlock.h
similarity index 64%
rename from lib/vtls/polarssl_threadlock.h
rename to lib/vtls/mbedtls_threadlock.h
index c1900bfe8..96a787d1a 100644
--- a/lib/vtls/polarssl_threadlock.h
+++ b/lib/vtls/mbedtls_threadlock.h
@@ -1,5 +1,5 @@
-#ifndef HEADER_CURL_POLARSSL_THREADLOCK_H
-#define HEADER_CURL_POLARSSL_THREADLOCK_H
+#ifndef HEADER_CURL_MBEDTLS_THREADLOCK_H
+#define HEADER_CURL_MBEDTLS_THREADLOCK_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2013 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2013 - 2020, Daniel Stenberg, <address@hidden>, et al.
  * Copyright (C) 2010, Hoi-Ho Chan, <address@hidden>
  *
  * This software is licensed as described in the file COPYING, which
@@ -24,25 +24,25 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
-#if (defined USE_POLARSSL) || (defined USE_MBEDTLS)
+#ifdef USE_MBEDTLS
 
 #if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
     (defined(USE_THREADS_WIN32) && defined(HAVE_PROCESS_H))
 
-int Curl_polarsslthreadlock_thread_setup(void);
-int Curl_polarsslthreadlock_thread_cleanup(void);
-int Curl_polarsslthreadlock_lock_function(int n);
-int Curl_polarsslthreadlock_unlock_function(int n);
+int Curl_mbedtlsthreadlock_thread_setup(void);
+int Curl_mbedtlsthreadlock_thread_cleanup(void);
+int Curl_mbedtlsthreadlock_lock_function(int n);
+int Curl_mbedtlsthreadlock_unlock_function(int n);
 
 #else
 
-#define Curl_polarsslthreadlock_thread_setup() 1
-#define Curl_polarsslthreadlock_thread_cleanup() 1
-#define Curl_polarsslthreadlock_lock_function(x) 1
-#define Curl_polarsslthreadlock_unlock_function(x) 1
+#define Curl_mbedtlsthreadlock_thread_setup() 1
+#define Curl_mbedtlsthreadlock_thread_cleanup() 1
+#define Curl_mbedtlsthreadlock_lock_function(x) 1
+#define Curl_mbedtlsthreadlock_unlock_function(x) 1
 
 #endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */
 
-#endif /* USE_POLARSSL */
+#endif /* USE_MBEDTLS */
 
-#endif /* HEADER_CURL_POLARSSL_THREADLOCK_H */
+#endif /* HEADER_CURL_MBEDTLS_THREADLOCK_H */
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 726ff6e7c..1d09cadca 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -2212,7 +2212,6 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata 
*conn)
   curl_ssl_version_max = SSL_CONN_CONFIG(version_max);
 
   /* convert cURL max SSL version option to OpenSSL constant */
-  ossl_ssl_version_max = 0;
   switch(curl_ssl_version_max) {
     case CURL_SSLVERSION_MAX_TLSv1_0:
       ossl_ssl_version_max = TLS1_VERSION;
@@ -3122,28 +3121,25 @@ do {                              \
 } while(0)
 #endif
 
-static int X509V3_ext(struct Curl_easy *data,
+static void X509V3_ext(struct Curl_easy *data,
                       int certnum,
                       CONST_EXTS STACK_OF(X509_EXTENSION) *exts)
 {
   int i;
-  size_t j;
 
   if((int)sk_X509_EXTENSION_num(exts) <= 0)
     /* no extensions, bail out */
-    return 1;
+    return;
 
   for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
     ASN1_OBJECT *obj;
     X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
     BUF_MEM *biomem;
-    char buf[512];
-    char *ptr = buf;
     char namebuf[128];
     BIO *bio_out = BIO_new(BIO_s_mem());
 
     if(!bio_out)
-      return 1;
+      return;
 
     obj = X509_EXTENSION_get_object(ext);
 
@@ -3153,26 +3149,10 @@ static int X509V3_ext(struct Curl_easy *data,
       ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
 
     BIO_get_mem_ptr(bio_out, &biomem);
-
-    for(j = 0; j < (size_t)biomem->length; j++) {
-      const char *sep = "";
-      if(biomem->data[j] == '\n') {
-        sep = ", ";
-        j++; /* skip the newline */
-      };
-      while((j<(size_t)biomem->length) && (biomem->data[j] == ' '))
-        j++;
-      if(j<(size_t)biomem->length)
-        ptr += msnprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep,
-                         biomem->data[j]);
-    }
-
-    Curl_ssl_push_certinfo(data, certnum, namebuf, buf);
-
+    Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data,
+                               biomem->length);
     BIO_free(bio_out);
-
   }
-  return 0; /* all is fine */
 }
 
 #ifdef OPENSSL_IS_BORINGSSL
diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c
deleted file mode 100644
index 9e7dd9043..000000000
--- a/lib/vtls/polarssl.c
+++ /dev/null
@@ -1,931 +0,0 @@
-/***************************************************************************
- *                                  _   _ ____  _
- *  Project                     ___| | | |  _ \| |
- *                             / __| | | | |_) | |
- *                            | (__| |_| |  _ <| |___
- *                             \___|\___/|_| \_\_____|
- *
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <address@hidden>, et al.
- * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <address@hidden>
- *
- * 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.
- *
- ***************************************************************************/
-
-/*
- * Source file for all PolarSSL-specific code for the TLS/SSL layer. No code
- * but vtls.c should ever call or use these functions.
- *
- */
-
-#include "curl_setup.h"
-
-#ifdef USE_POLARSSL
-#include <polarssl/net.h>
-#include <polarssl/ssl.h>
-#include <polarssl/certs.h>
-#include <polarssl/x509.h>
-#include <polarssl/version.h>
-#include <polarssl/sha256.h>
-
-#if POLARSSL_VERSION_NUMBER < 0x01030000
-#error too old PolarSSL
-#endif
-
-#include <polarssl/error.h>
-#include <polarssl/entropy.h>
-#include <polarssl/ctr_drbg.h>
-
-#include "urldata.h"
-#include "sendf.h"
-#include "inet_pton.h"
-#include "polarssl.h"
-#include "vtls.h"
-#include "parsedate.h"
-#include "connect.h" /* for the connect timeout */
-#include "select.h"
-#include "strcase.h"
-#include "polarssl_threadlock.h"
-#include "multiif.h"
-#include "curl_printf.h"
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
-
-/* See https://tls.mbed.org/discussions/generic/
-   howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der
-*/
-#define RSA_PUB_DER_MAX_BYTES   (38 + 2 * POLARSSL_MPI_MAX_SIZE)
-#define ECP_PUB_DER_MAX_BYTES   (30 + 2 * POLARSSL_ECP_MAX_BYTES)
-
-#define PUB_DER_MAX_BYTES   (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
-                             RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
-
-struct ssl_backend_data {
-  ctr_drbg_context ctr_drbg;
-  entropy_context entropy;
-  ssl_context ssl;
-  int server_fd;
-  x509_crt cacert;
-  x509_crt clicert;
-  x509_crl crl;
-  rsa_context rsa;
-};
-
-#define BACKEND connssl->backend
-
-/* apply threading? */
-#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
-#define THREADING_SUPPORT
-#endif
-
-#ifndef POLARSSL_ERROR_C
-#define error_strerror(x,y,z)
-#endif /* POLARSSL_ERROR_C */
-
-
-#if defined(THREADING_SUPPORT)
-static entropy_context entropy;
-
-static int  entropy_init_initialized  = 0;
-
-/* start of entropy_init_mutex() */
-static void entropy_init_mutex(entropy_context *ctx)
-{
-  /* lock 0 = entropy_init_mutex() */
-  Curl_polarsslthreadlock_lock_function(0);
-  if(entropy_init_initialized == 0) {
-    entropy_init(ctx);
-    entropy_init_initialized = 1;
-  }
-  Curl_polarsslthreadlock_unlock_function(0);
-}
-/* end of entropy_init_mutex() */
-
-/* start of entropy_func_mutex() */
-static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
-{
-  int ret;
-  /* lock 1 = entropy_func_mutex() */
-  Curl_polarsslthreadlock_lock_function(1);
-  ret = entropy_func(data, output, len);
-  Curl_polarsslthreadlock_unlock_function(1);
-
-  return ret;
-}
-/* end of entropy_func_mutex() */
-
-#endif /* THREADING_SUPPORT */
-
-/* Define this to enable lots of debugging for PolarSSL */
-#undef POLARSSL_DEBUG
-
-#ifdef POLARSSL_DEBUG
-static void polarssl_debug(void *context, int level, const char *line)
-{
-  struct Curl_easy *data = NULL;
-
-  if(!context)
-    return;
-
-  data = (struct Curl_easy *)context;
-
-  infof(data, "%s", line);
-  (void) level;
-}
-#else
-#endif
-
-/* ALPN for http2? */
-#ifdef POLARSSL_SSL_ALPN
-#  define HAS_ALPN
-#endif
-
-static Curl_recv polarssl_recv;
-static Curl_send polarssl_send;
-
-static CURLcode polarssl_version_from_curl(int *polarver, long ssl_version)
-{
-  switch(ssl_version) {
-    case CURL_SSLVERSION_TLSv1_0:
-      *polarver = SSL_MINOR_VERSION_1;
-      return CURLE_OK;
-    case CURL_SSLVERSION_TLSv1_1:
-      *polarver = SSL_MINOR_VERSION_2;
-      return CURLE_OK;
-    case CURL_SSLVERSION_TLSv1_2:
-      *polarver = SSL_MINOR_VERSION_3;
-      return CURLE_OK;
-    case CURL_SSLVERSION_TLSv1_3:
-      break;
-  }
-  return CURLE_SSL_CONNECT_ERROR;
-}
-
-static CURLcode
-set_ssl_version_min_max(struct connectdata *conn, int sockindex)
-{
-  struct Curl_easy *data = conn->data;
-  struct ssl_connect_data* connssl = &conn->ssl[sockindex];
-  long ssl_version = SSL_CONN_CONFIG(version);
-  long ssl_version_max = SSL_CONN_CONFIG(version_max);
-  int ssl_min_ver = SSL_MINOR_VERSION_1;
-  int ssl_max_ver = SSL_MINOR_VERSION_1;
-  CURLcode result = CURLE_OK;
-
-  switch(ssl_version) {
-    case CURL_SSLVERSION_DEFAULT:
-    case CURL_SSLVERSION_TLSv1:
-      ssl_version = CURL_SSLVERSION_TLSv1_0;
-      break;
-  }
-
-  switch(ssl_version_max) {
-    case CURL_SSLVERSION_MAX_NONE:
-    case CURL_SSLVERSION_MAX_DEFAULT:
-      ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
-      break;
-  }
-
-  result = polarssl_version_from_curl(&ssl_min_ver, ssl_version);
-  if(result) {
-    failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
-    return result;
-  }
-  result = polarssl_version_from_curl(&ssl_max_ver, ssl_version_max >> 16);
-  if(result) {
-    failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
-    return result;
-  }
-
-  ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver);
-  ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver);
-
-  return result;
-}
-
-static CURLcode
-polarssl_connect_step1(struct connectdata *conn,
-                       int sockindex)
-{
-  struct Curl_easy *data = conn->data;
-  struct ssl_connect_data* connssl = &conn->ssl[sockindex];
-  const char *capath = SSL_CONN_CONFIG(CApath);
-  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
-    conn->host.name;
-  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
-  int ret = -1;
-  char errorbuf[128];
-  errorbuf[0] = 0;
-
-  /* PolarSSL only supports SSLv3 and TLSv1 */
-  if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
-    failf(data, "PolarSSL does not support SSLv2");
-    return CURLE_SSL_CONNECT_ERROR;
-  }
-
-#ifdef THREADING_SUPPORT
-  entropy_init_mutex(&entropy);
-
-  if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func_mutex, &entropy,
-                          NULL, 0)) != 0) {
-    error_strerror(ret, errorbuf, sizeof(errorbuf));
-    failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
-          -ret, errorbuf);
-  }
-#else
-  entropy_init(&BACKEND->entropy);
-
-  if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func, &BACKEND->entropy,
-                          NULL, 0)) != 0) {
-    error_strerror(ret, errorbuf, sizeof(errorbuf));
-    failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
-          -ret, errorbuf);
-  }
-#endif /* THREADING_SUPPORT */
-
-  /* Load the trusted CA */
-  memset(&BACKEND->cacert, 0, sizeof(x509_crt));
-
-  if(SSL_CONN_CONFIG(CAfile)) {
-    ret = x509_crt_parse_file(&BACKEND->cacert,
-                              SSL_CONN_CONFIG(CAfile));
-
-    if(ret<0) {
-      error_strerror(ret, errorbuf, sizeof(errorbuf));
-      failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s",
-            SSL_CONN_CONFIG(CAfile), -ret, errorbuf);
-
-      if(SSL_CONN_CONFIG(verifypeer))
-        return CURLE_SSL_CACERT_BADFILE;
-    }
-  }
-
-  if(capath) {
-    ret = x509_crt_parse_path(&BACKEND->cacert, capath);
-
-    if(ret<0) {
-      error_strerror(ret, errorbuf, sizeof(errorbuf));
-      failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s",
-            capath, -ret, errorbuf);
-
-      if(SSL_CONN_CONFIG(verifypeer))
-        return CURLE_SSL_CACERT_BADFILE;
-    }
-  }
-
-  /* Load the client certificate */
-  memset(&BACKEND->clicert, 0, sizeof(x509_crt));
-
-  if(SSL_SET_OPTION(cert)) {
-    ret = x509_crt_parse_file(&BACKEND->clicert,
-                              SSL_SET_OPTION(cert));
-
-    if(ret) {
-      error_strerror(ret, errorbuf, sizeof(errorbuf));
-      failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s",
-            SSL_SET_OPTION(cert), -ret, errorbuf);
-
-      return CURLE_SSL_CERTPROBLEM;
-    }
-  }
-
-  /* Load the client private key */
-  if(SSL_SET_OPTION(key)) {
-    pk_context pk;
-    pk_init(&pk);
-    ret = pk_parse_keyfile(&pk, SSL_SET_OPTION(key),
-                           SSL_SET_OPTION(key_passwd));
-    if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
-      ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
-    if(ret == 0)
-      rsa_copy(&BACKEND->rsa, pk_rsa(pk));
-    else
-      rsa_free(&BACKEND->rsa);
-    pk_free(&pk);
-
-    if(ret) {
-      error_strerror(ret, errorbuf, sizeof(errorbuf));
-      failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s",
-            SSL_SET_OPTION(key), -ret, errorbuf);
-
-      return CURLE_SSL_CERTPROBLEM;
-    }
-  }
-
-  /* Load the CRL */
-  memset(&BACKEND->crl, 0, sizeof(x509_crl));
-
-  if(SSL_SET_OPTION(CRLfile)) {
-    ret = x509_crl_parse_file(&BACKEND->crl,
-                              SSL_SET_OPTION(CRLfile));
-
-    if(ret) {
-      error_strerror(ret, errorbuf, sizeof(errorbuf));
-      failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s",
-            SSL_SET_OPTION(CRLfile), -ret, errorbuf);
-
-      return CURLE_SSL_CRL_BADFILE;
-    }
-  }
-
-  infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port);
-
-  if(ssl_init(&BACKEND->ssl)) {
-    failf(data, "PolarSSL: ssl_init failed");
-    return CURLE_SSL_CONNECT_ERROR;
-  }
-
-  switch(SSL_CONN_CONFIG(version)) {
-  case CURL_SSLVERSION_DEFAULT:
-  case CURL_SSLVERSION_TLSv1:
-    ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
-                        SSL_MINOR_VERSION_1);
-    break;
-  case CURL_SSLVERSION_SSLv3:
-    ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
-                        SSL_MINOR_VERSION_0);
-    ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
-                        SSL_MINOR_VERSION_0);
-    infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
-    break;
-  case CURL_SSLVERSION_TLSv1_0:
-  case CURL_SSLVERSION_TLSv1_1:
-  case CURL_SSLVERSION_TLSv1_2:
-  case CURL_SSLVERSION_TLSv1_3:
-    {
-      CURLcode result = set_ssl_version_min_max(conn, sockindex);
-      if(result != CURLE_OK)
-        return result;
-      break;
-    }
-  default:
-    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
-    return CURLE_SSL_CONNECT_ERROR;
-  }
-
-  ssl_set_endpoint(&BACKEND->ssl, SSL_IS_CLIENT);
-  ssl_set_authmode(&BACKEND->ssl, SSL_VERIFY_OPTIONAL);
-
-  ssl_set_rng(&BACKEND->ssl, ctr_drbg_random,
-              &BACKEND->ctr_drbg);
-  ssl_set_bio(&BACKEND->ssl,
-              net_recv, &conn->sock[sockindex],
-              net_send, &conn->sock[sockindex]);
-
-  ssl_set_ciphersuites(&BACKEND->ssl, ssl_list_ciphersuites());
-
-  /* Check if there's a cached ID we can/should use here! */
-  if(SSL_SET_OPTION(primary.sessionid)) {
-    void *old_session = NULL;
-
-    Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
-      ret = ssl_set_session(&BACKEND->ssl, old_session);
-      if(ret) {
-        Curl_ssl_sessionid_unlock(conn);
-        failf(data, "ssl_set_session returned -0x%x", -ret);
-        return CURLE_SSL_CONNECT_ERROR;
-      }
-      infof(data, "PolarSSL re-using session\n");
-    }
-    Curl_ssl_sessionid_unlock(conn);
-  }
-
-  ssl_set_ca_chain(&BACKEND->ssl,
-                   &BACKEND->cacert,
-                   &BACKEND->crl,
-                   hostname);
-
-  ssl_set_own_cert_rsa(&BACKEND->ssl,
-                       &BACKEND->clicert, &BACKEND->rsa);
-
-  if(ssl_set_hostname(&BACKEND->ssl, hostname)) {
-    /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name
-       to set in the SNI extension. So even if curl connects to a host
-       specified as an IP address, this function must be used. */
-    failf(data, "couldn't set hostname in PolarSSL");
-    return CURLE_SSL_CONNECT_ERROR;
-  }
-
-#ifdef HAS_ALPN
-  if(conn->bits.tls_enable_alpn) {
-    static const char *protocols[3];
-    int cur = 0;
-
-#ifdef USE_NGHTTP2
-    if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
-      protocols[cur++] = NGHTTP2_PROTO_VERSION_ID;
-      infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
-    }
-#endif
-
-    protocols[cur++] = ALPN_HTTP_1_1;
-    infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
-
-    protocols[cur] = NULL;
-
-    ssl_set_alpn_protocols(&BACKEND->ssl, protocols);
-  }
-#endif
-
-#ifdef POLARSSL_DEBUG
-  ssl_set_dbg(&BACKEND->ssl, polarssl_debug, data);
-#endif
-
-  connssl->connecting_state = ssl_connect_2;
-
-  return CURLE_OK;
-}
-
-static CURLcode
-polarssl_connect_step2(struct connectdata *conn,
-                       int sockindex)
-{
-  int ret;
-  struct Curl_easy *data = conn->data;
-  struct ssl_connect_data* connssl = &conn->ssl[sockindex];
-  char buffer[1024];
-  const char * const pinnedpubkey = SSL_IS_PROXY() ?
-            data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
-            data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
-
-
-  char errorbuf[128];
-  errorbuf[0] = 0;
-
-  conn->recv[sockindex] = polarssl_recv;
-  conn->send[sockindex] = polarssl_send;
-
-  ret = ssl_handshake(&BACKEND->ssl);
-
-  switch(ret) {
-  case 0:
-    break;
-
-  case POLARSSL_ERR_NET_WANT_READ:
-    connssl->connecting_state = ssl_connect_2_reading;
-    return CURLE_OK;
-
-  case POLARSSL_ERR_NET_WANT_WRITE:
-    connssl->connecting_state = ssl_connect_2_writing;
-    return CURLE_OK;
-
-  default:
-    error_strerror(ret, errorbuf, sizeof(errorbuf));
-    failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s",
-          -ret, errorbuf);
-    return CURLE_SSL_CONNECT_ERROR;
-  }
-
-  infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
-        ssl_get_ciphersuite(&BACKEND->ssl) );
-
-  ret = ssl_get_verify_result(&BACKEND->ssl);
-
-  if(ret && SSL_CONN_CONFIG(verifypeer)) {
-    if(ret & BADCERT_EXPIRED)
-      failf(data, "Cert verify failed: BADCERT_EXPIRED");
-
-    if(ret & BADCERT_REVOKED) {
-      failf(data, "Cert verify failed: BADCERT_REVOKED");
-      return CURLE_PEER_FAILED_VERIFICATION;
-    }
-
-    if(ret & BADCERT_CN_MISMATCH)
-      failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
-
-    if(ret & BADCERT_NOT_TRUSTED)
-      failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
-
-    return CURLE_PEER_FAILED_VERIFICATION;
-  }
-
-  if(ssl_get_peer_cert(&(BACKEND->ssl))) {
-    /* If the session was resumed, there will be no peer certs */
-    memset(buffer, 0, sizeof(buffer));
-
-    if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ",
-                     ssl_get_peer_cert(&(BACKEND->ssl))) != -1)
-      infof(data, "Dumping cert info:\n%s\n", buffer);
-  }
-
-  /* adapted from mbedtls.c */
-  if(pinnedpubkey) {
-    int size;
-    CURLcode result;
-    x509_crt *p;
-    unsigned char pubkey[PUB_DER_MAX_BYTES];
-    const x509_crt *peercert;
-
-    peercert = ssl_get_peer_cert(&BACKEND->ssl);
-
-    if(!peercert || !peercert->raw.p || !peercert->raw.len) {
-      failf(data, "Failed due to missing peer certificate");
-      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
-    }
-
-    p = calloc(1, sizeof(*p));
-
-    if(!p)
-      return CURLE_OUT_OF_MEMORY;
-
-    x509_crt_init(p);
-
-    /* Make a copy of our const peercert because pk_write_pubkey_der
-       needs a non-const key, for now.
-       https://github.com/ARMmbed/mbedtls/issues/396 */
-    if(x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
-      failf(data, "Failed copying peer certificate");
-      x509_crt_free(p);
-      free(p);
-      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
-    }
-
-    size = pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
-
-    if(size <= 0) {
-      failf(data, "Failed copying public key from peer certificate");
-      x509_crt_free(p);
-      free(p);
-      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
-    }
-
-    /* pk_write_pubkey_der writes data at the end of the buffer. */
-    result = Curl_pin_peer_pubkey(data,
-                                  pinnedpubkey,
-                                  &pubkey[PUB_DER_MAX_BYTES - size], size);
-    if(result) {
-      x509_crt_free(p);
-      free(p);
-      return result;
-    }
-
-    x509_crt_free(p);
-    free(p);
-  }
-
-#ifdef HAS_ALPN
-  if(conn->bits.tls_enable_alpn) {
-    const char *next_protocol = ssl_get_alpn_protocol(&BACKEND->ssl);
-
-    if(next_protocol != NULL) {
-      infof(data, "ALPN, server accepted to use %s\n", next_protocol);
-
-#ifdef USE_NGHTTP2
-      if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
-                  NGHTTP2_PROTO_VERSION_ID_LEN)) {
-        conn->negnpn = CURL_HTTP_VERSION_2;
-      }
-      else
-#endif
-        if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) {
-          conn->negnpn = CURL_HTTP_VERSION_1_1;
-        }
-    }
-    else
-      infof(data, "ALPN, server did not agree to a protocol\n");
-    Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
-                        BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
-  }
-#endif
-
-  connssl->connecting_state = ssl_connect_3;
-  infof(data, "SSL connected\n");
-
-  return CURLE_OK;
-}
-
-static CURLcode
-polarssl_connect_step3(struct connectdata *conn,
-                       int sockindex)
-{
-  CURLcode retcode = CURLE_OK;
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  struct Curl_easy *data = conn->data;
-
-  DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
-
-  if(SSL_SET_OPTION(primary.sessionid)) {
-    int ret;
-    ssl_session *our_ssl_sessionid;
-    void *old_ssl_sessionid = NULL;
-
-    our_ssl_sessionid = calloc(1, sizeof(ssl_session));
-    if(!our_ssl_sessionid)
-      return CURLE_OUT_OF_MEMORY;
-
-    ret = ssl_get_session(&BACKEND->ssl, our_ssl_sessionid);
-    if(ret) {
-      failf(data, "ssl_get_session returned -0x%x", -ret);
-      return CURLE_SSL_CONNECT_ERROR;
-    }
-
-    /* If there's already a matching session in the cache, delete it */
-    Curl_ssl_sessionid_lock(conn);
-    if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
-      Curl_ssl_delsessionid(conn, old_ssl_sessionid);
-
-    retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
-    Curl_ssl_sessionid_unlock(conn);
-    if(retcode) {
-      free(our_ssl_sessionid);
-      failf(data, "failed to store ssl session");
-      return retcode;
-    }
-  }
-
-  connssl->connecting_state = ssl_connect_done;
-
-  return CURLE_OK;
-}
-
-static ssize_t polarssl_send(struct connectdata *conn,
-                             int sockindex,
-                             const void *mem,
-                             size_t len,
-                             CURLcode *curlcode)
-{
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  int ret = -1;
-
-  ret = ssl_write(&BACKEND->ssl,
-                  (unsigned char *)mem, len);
-
-  if(ret < 0) {
-    *curlcode = (ret == POLARSSL_ERR_NET_WANT_WRITE) ?
-      CURLE_AGAIN : CURLE_SEND_ERROR;
-    ret = -1;
-  }
-
-  return ret;
-}
-
-static void Curl_polarssl_close(struct connectdata *conn, int sockindex)
-{
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  rsa_free(&BACKEND->rsa);
-  x509_crt_free(&BACKEND->clicert);
-  x509_crt_free(&BACKEND->cacert);
-  x509_crl_free(&BACKEND->crl);
-  ssl_free(&BACKEND->ssl);
-}
-
-static ssize_t polarssl_recv(struct connectdata *conn,
-                             int num,
-                             char *buf,
-                             size_t buffersize,
-                             CURLcode *curlcode)
-{
-  struct ssl_connect_data *connssl = &conn->ssl[num];
-  int ret = -1;
-  ssize_t len = -1;
-
-  memset(buf, 0, buffersize);
-  ret = ssl_read(&BACKEND->ssl, (unsigned char *)buf, buffersize);
-
-  if(ret <= 0) {
-    if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
-      return 0;
-
-    *curlcode = (ret == POLARSSL_ERR_NET_WANT_READ) ?
-      CURLE_AGAIN : CURLE_RECV_ERROR;
-    return -1;
-  }
-
-  len = ret;
-
-  return len;
-}
-
-static void Curl_polarssl_session_free(void *ptr)
-{
-  ssl_session_free(ptr);
-  free(ptr);
-}
-
-/* 1.3.10 was the first rebranded version. All new releases (in 1.3 branch and
-   higher) will be mbed TLS branded.. */
-
-static size_t Curl_polarssl_version(char *buffer, size_t size)
-{
-  unsigned int version = version_get_number();
-  return msnprintf(buffer, size, "%s/%d.%d.%d",
-                   version >= 0x01030A00?"mbedTLS":"PolarSSL",
-                   version>>24, (version>>16)&0xff, (version>>8)&0xff);
-}
-
-static CURLcode
-polarssl_connect_common(struct connectdata *conn,
-                        int sockindex,
-                        bool nonblocking,
-                        bool *done)
-{
-  CURLcode result;
-  struct Curl_easy *data = conn->data;
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  curl_socket_t sockfd = conn->sock[sockindex];
-  timediff_t timeout_ms;
-  int what;
-
-  /* check if the connection has already been established */
-  if(ssl_connection_complete == connssl->state) {
-    *done = TRUE;
-    return CURLE_OK;
-  }
-
-  if(ssl_connect_1 == connssl->connecting_state) {
-    /* Find out how much more time we're allowed */
-    timeout_ms = Curl_timeleft(data, NULL, TRUE);
-
-    if(timeout_ms < 0) {
-      /* no need to continue if time already is up */
-      failf(data, "SSL connection timeout");
-      return CURLE_OPERATION_TIMEDOUT;
-    }
-
-    result = polarssl_connect_step1(conn, sockindex);
-    if(result)
-      return result;
-  }
-
-  while(ssl_connect_2 == connssl->connecting_state ||
-        ssl_connect_2_reading == connssl->connecting_state ||
-        ssl_connect_2_writing == connssl->connecting_state) {
-
-    /* check allowed time left */
-    timeout_ms = Curl_timeleft(data, NULL, TRUE);
-
-    if(timeout_ms < 0) {
-      /* no need to continue if time already is up */
-      failf(data, "SSL connection timeout");
-      return CURLE_OPERATION_TIMEDOUT;
-    }
-
-    /* if ssl is expecting something, check if it's available. */
-    if(connssl->connecting_state == ssl_connect_2_reading ||
-       connssl->connecting_state == ssl_connect_2_writing) {
-
-      curl_socket_t writefd = ssl_connect_2_writing ==
-        connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
-      curl_socket_t readfd = ssl_connect_2_reading ==
-        connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
-
-      what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
-                               nonblocking?0:(time_t)timeout_ms);
-      if(what < 0) {
-        /* fatal error */
-        failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
-        return CURLE_SSL_CONNECT_ERROR;
-      }
-      else if(0 == what) {
-        if(nonblocking) {
-          *done = FALSE;
-          return CURLE_OK;
-        }
-        else {
-          /* timeout */
-          failf(data, "SSL connection timeout");
-          return CURLE_OPERATION_TIMEDOUT;
-        }
-      }
-      /* socket is readable or writable */
-    }
-
-    /* Run transaction, and return to the caller if it failed or if
-     * this connection is part of a multi handle and this loop would
-     * execute again. This permits the owner of a multi handle to
-     * abort a connection attempt before step2 has completed while
-     * ensuring that a client using select() or epoll() will always
-     * have a valid fdset to wait on.
-     */
-    result = polarssl_connect_step2(conn, sockindex);
-    if(result || (nonblocking &&
-                  (ssl_connect_2 == connssl->connecting_state ||
-                   ssl_connect_2_reading == connssl->connecting_state ||
-                   ssl_connect_2_writing == connssl->connecting_state)))
-      return result;
-
-  } /* repeat step2 until all transactions are done. */
-
-  if(ssl_connect_3 == connssl->connecting_state) {
-    result = polarssl_connect_step3(conn, sockindex);
-    if(result)
-      return result;
-  }
-
-  if(ssl_connect_done == connssl->connecting_state) {
-    connssl->state = ssl_connection_complete;
-    conn->recv[sockindex] = polarssl_recv;
-    conn->send[sockindex] = polarssl_send;
-    *done = TRUE;
-  }
-  else
-    *done = FALSE;
-
-  /* Reset our connect state machine */
-  connssl->connecting_state = ssl_connect_1;
-
-  return CURLE_OK;
-}
-
-static CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn,
-                                                  int sockindex, bool *done)
-{
-  return polarssl_connect_common(conn, sockindex, TRUE, done);
-}
-
-
-static CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex)
-{
-  CURLcode result;
-  bool done = FALSE;
-
-  result = polarssl_connect_common(conn, sockindex, FALSE, &done);
-  if(result)
-    return result;
-
-  DEBUGASSERT(done);
-
-  return CURLE_OK;
-}
-
-/*
- * return 0 error initializing SSL
- * return 1 SSL initialized successfully
- */
-static int Curl_polarssl_init(void)
-{
-  return Curl_polarsslthreadlock_thread_setup();
-}
-
-static void Curl_polarssl_cleanup(void)
-{
-  (void)Curl_polarsslthreadlock_thread_cleanup();
-}
-
-static bool Curl_polarssl_data_pending(const struct connectdata *conn,
-                                       int sockindex)
-{
-  const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  return ssl_get_bytes_avail(&BACKEND->ssl) != 0;
-}
-
-static CURLcode Curl_polarssl_sha256sum(const unsigned char *input,
-                                    size_t inputlen,
-                                    unsigned char *sha256sum,
-                                    size_t sha256len UNUSED_PARAM)
-{
-  (void)sha256len;
-  sha256(input, inputlen, sha256sum, 0);
-  return CURLE_OK;
-}
-
-static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl,
-                                         CURLINFO info UNUSED_PARAM)
-{
-  (void)info;
-  return &BACKEND->ssl;
-}
-
-const struct Curl_ssl Curl_ssl_polarssl = {
-  { CURLSSLBACKEND_POLARSSL, "polarssl" }, /* info */
-
-  SSLSUPP_CA_PATH |
-  SSLSUPP_PINNEDPUBKEY,
-
-  sizeof(struct ssl_backend_data),
-
-  Curl_polarssl_init,                /* init */
-  Curl_polarssl_cleanup,             /* cleanup */
-  Curl_polarssl_version,             /* version */
-  Curl_none_check_cxn,               /* check_cxn */
-  Curl_none_shutdown,                /* shutdown */
-  Curl_polarssl_data_pending,        /* data_pending */
-  /* This might cause libcurl to use a weeker random! */
-  Curl_none_random,                  /* random */
-  Curl_none_cert_status_request,     /* cert_status_request */
-  Curl_polarssl_connect,             /* connect */
-  Curl_polarssl_connect_nonblocking, /* connect_nonblocking */
-  Curl_polarssl_get_internals,       /* get_internals */
-  Curl_polarssl_close,               /* close_one */
-  Curl_none_close_all,               /* close_all */
-  Curl_polarssl_session_free,        /* session_free */
-  Curl_none_set_engine,              /* set_engine */
-  Curl_none_set_engine_default,      /* set_engine_default */
-  Curl_none_engines_list,            /* engines_list */
-  Curl_none_false_start,             /* false_start */
-  Curl_none_md5sum,                  /* md5sum */
-  Curl_polarssl_sha256sum            /* sha256sum */
-};
-
-#endif /* USE_POLARSSL */
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index dc58ed0d3..f665ee340 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -27,16 +27,6 @@
  * but vtls.c should ever call or use these functions.
  */
 
-/*
- * Based upon the PolarSSL implementation in polarssl.c and polarssl.h:
- *   Copyright (C) 2010, 2011, Hoi-Ho Chan, <address@hidden>
- *
- * Based upon the CyaSSL implementation in cyassl.c and cyassl.h:
- *   Copyright (C) 1998 - 2012, Daniel Stenberg, <address@hidden>, et al.
- *
- * Thanks for code and inspiration!
- */
-
 #include "curl_setup.h"
 
 #ifdef USE_SCHANNEL
@@ -718,7 +708,7 @@ schannel_connect_step1(struct connectdata *conn, int 
sockindex)
     unsigned short* list_len = NULL;
 
     /* The first four bytes will be an unsigned int indicating number
-       of bytes of data in the rest of the the buffer. */
+       of bytes of data in the rest of the buffer. */
     extension_len = (unsigned int *)(&alpn_buffer[cur]);
     cur += sizeof(unsigned int);
 
diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c
index 3a668adc7..e75132cad 100644
--- a/lib/vtls/schannel_verify.c
+++ b/lib/vtls/schannel_verify.c
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 2012 - 2016, Marc Hoersken, <address@hidden>
  * Copyright (C) 2012, Mark Salisbury, <address@hidden>
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2012 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -293,6 +293,133 @@ cleanup:
   return result;
 }
 
+/*
+ * Returns the number of characters necessary to populate all the host_names.
+ * If host_names is not NULL, populate it with all the host names. Each string
+ * in the host_names is null-terminated and the last string is double
+ * null-terminated. If no DNS names are found, a single null-terminated empty
+ * string is returned.
+ */
+static DWORD cert_get_name_string(struct Curl_easy *data,
+                                  CERT_CONTEXT *cert_context,
+                                  LPTSTR host_names,
+                                  DWORD length)
+{
+  DWORD actual_length = 0;
+  BOOL compute_content = FALSE;
+  CERT_INFO *cert_info = NULL;
+  CERT_EXTENSION *extension = NULL;
+  CRYPT_DECODE_PARA decode_para = {0, 0, 0};
+  CERT_ALT_NAME_INFO *alt_name_info = NULL;
+  DWORD alt_name_info_size = 0;
+  BOOL ret_val = FALSE;
+  LPTSTR current_pos = NULL;
+  DWORD i;
+
+  /* CERT_NAME_SEARCH_ALL_NAMES_FLAG is available from Windows 8 onwards. */
+  if(Curl_verify_windows_version(6, 2, PLATFORM_WINNT,
+                                 VERSION_GREATER_THAN_EQUAL)) {
+#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
+    /* CertGetNameString will provide the 8-bit character string without
+     * any decoding */
+    DWORD name_flags =
+      CERT_NAME_DISABLE_IE4_UTF8_FLAG | CERT_NAME_SEARCH_ALL_NAMES_FLAG;
+    actual_length = CertGetNameString(cert_context,
+                                      CERT_NAME_DNS_TYPE,
+                                      name_flags,
+                                      NULL,
+                                      host_names,
+                                      length);
+    return actual_length;
+#endif
+  }
+
+  compute_content = host_names != NULL && length != 0;
+
+  /* Initialize default return values. */
+  actual_length = 1;
+  if(compute_content) {
+    *host_names = '\0';
+  }
+
+  if(!cert_context) {
+    failf(data, "schannel: Null certificate context.");
+    return actual_length;
+  }
+
+  cert_info = cert_context->pCertInfo;
+  if(!cert_info) {
+    failf(data, "schannel: Null certificate info.");
+    return actual_length;
+  }
+
+  extension = CertFindExtension(szOID_SUBJECT_ALT_NAME2,
+                                cert_info->cExtension,
+                                cert_info->rgExtension);
+  if(!extension) {
+    failf(data, "schannel: CertFindExtension() returned no extension.");
+    return actual_length;
+  }
+
+  decode_para.cbSize  =  sizeof(CRYPT_DECODE_PARA);
+
+  ret_val =
+    CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+                        szOID_SUBJECT_ALT_NAME2,
+                        extension->Value.pbData,
+                        extension->Value.cbData,
+                        CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
+                        &decode_para,
+                        &alt_name_info,
+                        &alt_name_info_size);
+  if(!ret_val) {
+    failf(data,
+          "schannel: CryptDecodeObjectEx() returned no alternate name "
+          "information.");
+    return actual_length;
+  }
+
+  current_pos = host_names;
+
+  /* Iterate over the alternate names and populate host_names. */
+  for(i = 0; i < alt_name_info->cAltEntry; i++) {
+    const CERT_ALT_NAME_ENTRY *entry = &alt_name_info->rgAltEntry[i];
+    wchar_t *dns_w = NULL;
+    size_t current_length = 0;
+
+    if(entry->dwAltNameChoice != CERT_ALT_NAME_DNS_NAME) {
+      continue;
+    }
+    if(entry->pwszDNSName == NULL) {
+      infof(data, "schannel: Empty DNS name.");
+      continue;
+    }
+    current_length = wcslen(entry->pwszDNSName) + 1;
+    if(!compute_content) {
+      actual_length += (DWORD)current_length;
+      continue;
+    }
+    /* Sanity check to prevent buffer overrun. */
+    if((actual_length + current_length) > length) {
+      failf(data, "schannel: Not enough memory to list all host names.");
+      break;
+    }
+    dns_w = entry->pwszDNSName;
+    /* pwszDNSName is in ia5 string format and hence doesn't contain any
+     * non-ascii characters. */
+    while(*dns_w != '\0') {
+      *current_pos++ = (char)(*dns_w++);
+    }
+    *current_pos++ = '\0';
+    actual_length += (DWORD)current_length;
+  }
+  if(compute_content) {
+    /* Last string has double null-terminator. */
+    *current_pos = '\0';
+  }
+  return actual_length;
+}
+
 static CURLcode verify_host(struct Curl_easy *data,
                             CERT_CONTEXT *pCertContextServer,
                             const char * const conn_hostname)
@@ -303,21 +430,8 @@ static CURLcode verify_host(struct Curl_easy *data,
   DWORD len = 0;
   DWORD actual_len = 0;
 
-  /* CertGetNameString will provide the 8-bit character string without
-   * any decoding */
-  DWORD name_flags = CERT_NAME_DISABLE_IE4_UTF8_FLAG;
-
-#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
-  name_flags |= CERT_NAME_SEARCH_ALL_NAMES_FLAG;
-#endif
-
   /* Determine the size of the string needed for the cert hostname */
-  len = CertGetNameString(pCertContextServer,
-                          CERT_NAME_DNS_TYPE,
-                          name_flags,
-                          NULL,
-                          NULL,
-                          0);
+  len = cert_get_name_string(data, pCertContextServer, NULL, 0);
   if(len == 0) {
     failf(data,
           "schannel: CertGetNameString() returned no "
@@ -334,12 +448,8 @@ static CURLcode verify_host(struct Curl_easy *data,
     result = CURLE_OUT_OF_MEMORY;
     goto cleanup;
   }
-  actual_len = CertGetNameString(pCertContextServer,
-                                 CERT_NAME_DNS_TYPE,
-                                 name_flags,
-                                 NULL,
-                                 (LPTSTR) cert_hostname_buff,
-                                 len);
+  actual_len = cert_get_name_string(
+    data, pCertContextServer, (LPTSTR)cert_hostname_buff, len);
 
   /* Sanity check */
   if(actual_len != len) {
diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c
index 4eece89d5..7dd028fb7 100644
--- a/lib/vtls/sectransp.c
+++ b/lib/vtls/sectransp.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2012 - 2017, Nick Zitzmann, <address@hidden>.
- * Copyright (C) 2012 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2012 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -1164,7 +1164,7 @@ static OSStatus CopyIdentityFromPKCS12File(const char 
*cPath,
    * the Keychain.
    *
    * As this doesn't match iOS, and apps may not want to see their client
-   * certificate saved in the the user's keychain, we use SecItemImport
+   * certificate saved in the user's keychain, we use SecItemImport
    * with a NULL keychain to avoid importing it.
    *
    * This returns a SecCertificateRef from which we can construct a
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index c493b1516..dfefa1bd5 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -516,7 +516,7 @@ void Curl_ssl_close_all(struct Curl_easy *data)
 }
 
 #if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
-  defined(USE_SECTRANSP) || defined(USE_POLARSSL) || defined(USE_NSS) || \
+  defined(USE_SECTRANSP) || defined(USE_NSS) || \
   defined(USE_MBEDTLS) || defined(USE_WOLFSSL) || defined(USE_BEARSSL)
 int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks)
 {
@@ -1183,8 +1183,6 @@ const struct Curl_ssl *Curl_ssl =
   &Curl_ssl_nss;
 #elif defined(USE_OPENSSL)
   &Curl_ssl_openssl;
-#elif defined(USE_POLARSSL)
-  &Curl_ssl_polarssl;
 #elif defined(USE_SCHANNEL)
   &Curl_ssl_schannel;
 #elif defined(USE_MESALINK)
@@ -1217,9 +1215,6 @@ static const struct Curl_ssl *available_backends[] = {
 #if defined(USE_OPENSSL)
   &Curl_ssl_openssl,
 #endif
-#if defined(USE_POLARSSL)
-  &Curl_ssl_polarssl,
-#endif
 #if defined(USE_SCHANNEL)
   &Curl_ssl_schannel,
 #endif
@@ -1236,7 +1231,7 @@ static size_t Curl_multissl_version(char *buffer, size_t 
size)
 {
   static const struct Curl_ssl *selected;
   static char backends[200];
-  static size_t total;
+  static size_t backends_len;
   const struct Curl_ssl *current;
 
   current = Curl_ssl == &Curl_ssl_multi ? available_backends[0] : Curl_ssl;
@@ -1248,27 +1243,32 @@ static size_t Curl_multissl_version(char *buffer, 
size_t size)
 
     selected = current;
 
-    for(i = 0; available_backends[i] && p < (end - 4); i++) {
-      if(i)
-        *(p++) = ' ';
-      if(selected != available_backends[i])
-        *(p++) = '(';
-      p += available_backends[i]->version(p, end - p - 2);
-      if(selected != available_backends[i])
-        *(p++) = ')';
+    backends[0] = '\0';
+
+    for(i = 0; available_backends[i]; ++i) {
+      char vb[200];
+      bool paren = (selected != available_backends[i]);
+
+      if(available_backends[i]->version(vb, sizeof(vb))) {
+        p += msnprintf(p, end - p, "%s%s%s%s", (p != backends ? " " : ""),
+                       (paren ? "(" : ""), vb, (paren ? ")" : ""));
+      }
     }
-    *p = '\0';
-    total = p - backends;
+
+    backends_len = p - backends;
   }
 
-  if(size > total)
-    memcpy(buffer, backends, total + 1);
-  else {
-    memcpy(buffer, backends, size - 1);
+  if(!size)
+    return 0;
+
+  if(size <= backends_len) {
+    strncpy(buffer, backends, size - 1);
     buffer[size - 1] = '\0';
+    return size - 1;
   }
 
-  return CURLMIN(size - 1, total);
+  strcpy(buffer, backends);
+  return backends_len;
 }
 
 static int multissl_init(const struct Curl_ssl *backend)
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index 976cc4360..a81b2f22d 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -102,7 +102,6 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t 
inputlen,
 #include "gtls.h"           /* GnuTLS versions */
 #include "nssg.h"           /* NSS versions */
 #include "gskit.h"          /* Global Secure ToolKit versions */
-#include "polarssl.h"       /* PolarSSL versions */
 #include "wolfssl.h"        /* wolfSSL versions */
 #include "schannel.h"       /* Schannel SSPI version */
 #include "sectransp.h"      /* SecureTransport (Darwin) version */
@@ -263,7 +262,6 @@ bool Curl_ssl_false_start(void);
 #define Curl_ssl_send(a,b,c,d,e) -1
 #define Curl_ssl_recv(a,b,c,d,e) -1
 #define Curl_ssl_initsessions(x,y) CURLE_OK
-#define Curl_ssl_version(x,y) 0
 #define Curl_ssl_data_pending(x,y) 0
 #define Curl_ssl_check_cxn(x) 0
 #define Curl_ssl_free_certinfo(x) Curl_nop_stmt
diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c
index 890bcbf79..8c2d3f4a2 100644
--- a/lib/vtls/wolfssl.c
+++ b/lib/vtls/wolfssl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -923,7 +923,7 @@ static CURLcode Curl_wolfssl_connect(struct connectdata 
*conn, int sockindex)
 static CURLcode Curl_wolfssl_random(struct Curl_easy *data,
                                    unsigned char *entropy, size_t length)
 {
-  RNG rng;
+  WC_RNG rng;
   (void)data;
   if(wc_InitRng(&rng))
     return CURLE_FAILED_INIT;
@@ -937,11 +937,11 @@ static CURLcode Curl_wolfssl_random(struct Curl_easy 
*data,
 }
 
 static CURLcode Curl_wolfssl_sha256sum(const unsigned char *tmp, /* input */
-                                  size_t tmplen,
-                                  unsigned char *sha256sum /* output */,
-                                  size_t unused)
+                                       size_t tmplen,
+                                       unsigned char *sha256sum /* output */,
+                                       size_t unused)
 {
-  Sha256 SHA256pw;
+  wc_Sha256 SHA256pw;
   (void)unused;
   wc_InitSha256(&SHA256pw);
   wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen);
diff --git a/m4/curl-confopts.m4 b/m4/curl-confopts.m4
index dc826f00b..566db8ec5 100644
--- a/m4/curl-confopts.m4
+++ b/m4/curl-confopts.m4
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -107,7 +107,7 @@ AC_HELP_STRING([--disable-curldebug],[Disable curl debug 
memory tracking]),
       ;;
     default)
       dnl configure's curldebug option not specified. Initially we will
-      dnl handle this as a a request to use the same setting as option
+      dnl handle this as a request to use the same setting as option
       dnl --enable-debug. IOW, initially, for debug-enabled builds
       dnl this will be handled as a request to enable curldebug if
       dnl possible, and for debug-disabled builds this will be handled
@@ -198,7 +198,7 @@ AC_HELP_STRING([--disable-optimize],[Disable compiler 
optimizations]),
       ;;
     default)
       dnl configure's optimize option not specified. Initially we will
-      dnl handle this as a a request contrary to configure's setting
+      dnl handle this as a request contrary to configure's setting
       dnl for --enable-debug. IOW, initially, for debug-enabled builds
       dnl this will be handled as a request to disable optimizations if
       dnl possible, and for debug-disabled builds this will be handled
diff --git a/m4/curl-functions.m4 b/m4/curl-functions.m4
index 9020f3942..e773f6700 100644
--- a/m4/curl-functions.m4
+++ b/m4/curl-functions.m4
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -6350,7 +6350,7 @@ dnl glibc-style strerror_r:
 dnl
 dnl      char *strerror_r(int errnum, char *workbuf, size_t bufsize);
 dnl
-dnl  glibc-style strerror_r returns a pointer to the the error string,
+dnl  glibc-style strerror_r returns a pointer to the error string,
 dnl  and might use the provided workbuf as a scratch area if needed. A
 dnl  quick test on a few systems shows that it's usually not used at all.
 dnl
diff --git a/packages/OS400/ccsidcurl.c b/packages/OS400/ccsidcurl.c
index 11e4c777e..64fb7393d 100644
--- a/packages/OS400/ccsidcurl.c
+++ b/packages/OS400/ccsidcurl.c
@@ -1130,22 +1130,6 @@ curl_easy_setopt_ccsid(CURL *curl, CURLoption tag, ...)
   char *cp;
   unsigned int ccsid;
   curl_off_t pfsize;
-  static char testwarn = 1;
-
-  /* Warns if this procedure has not been updated when the dupstring enum
-     changes.
-     We (try to) do it only once: there is no need to issue several times
-     the same message; but since threadsafeness is not handled here,
-     this may occur (and we don't care!). */
-
-  if(testwarn) {
-    testwarn = 0;
-
-    if((int) STRING_LASTZEROTERMINATED != (int) STRING_SASL_AUTHZID + 1 ||
-       (int) STRING_LAST != (int) STRING_COPYPOSTFIELDS + 1)
-      curl_mfprintf(stderr,
-       "*** WARNING: curl_easy_setopt_ccsid() should be reworked ***\n");
-  }
 
   data = (struct Curl_easy *) curl;
   va_start(arg, tag);
diff --git a/packages/OS400/chkstrings.c b/packages/OS400/chkstrings.c
new file mode 100644
index 000000000..613540e42
--- /dev/null
+++ b/packages/OS400/chkstrings.c
@@ -0,0 +1,62 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, 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 <stdlib.h>
+#pragma enum(int)
+#include "curl_setup.h"
+#include "urldata.h"
+
+/* The following defines indicate the expected dupstring enum values
+ * in curl_easy_setopt_ccsid() in packages/OS400/ccsidcurl.c. If a
+ * mismatch is flagged during the build, it indicates that 
curl_easy_setopt_ccsid()
+ * may need updating to perform data EBCDIC to ASCII data conversion on 
+ * the string.
+ * Once any applicable changes to curl_easy_setopt_ccsid() have been
+ * made, the EXPECTED_STRING_LASTZEROTERMINATED/EXPECTED_STRING_LAST
+ * values can be updated to match the latest enum values in urldata.h.
+ */
+#define EXPECTED_STRING_LASTZEROTERMINATED  (STRING_TEMP_URL + 1)
+#define EXPECTED_STRING_LAST                (STRING_COPYPOSTFIELDS + 1)
+
+int main(int argc, char *argv[])
+{
+  int rc = 0;
+
+  if (STRING_LASTZEROTERMINATED != EXPECTED_STRING_LASTZEROTERMINATED)
+  {
+    fprintf(stderr,"STRING_LASTZEROTERMINATED(%d) is not expected 
value(%d).\n", 
+            STRING_LASTZEROTERMINATED, EXPECTED_STRING_LASTZEROTERMINATED);
+    rc += 1;
+  }
+  if (STRING_LAST != EXPECTED_STRING_LAST)
+  {
+    fprintf(stderr,"STRING_LAST(%d) is not expected value(%d).\n", 
+            STRING_LAST, EXPECTED_STRING_LAST);
+    rc += 2;
+  }
+  if (rc != 0)
+  {
+    fprintf(stderr,"curl_easy_setopt_ccsid() in packages/OS400/ccsidcurl.c"
+            " may need updating if new strings are provided as input via the 
curl API.\n");
+  }
+  return rc;
+}
\ No newline at end of file
diff --git a/packages/OS400/curl.inc.in b/packages/OS400/curl.inc.in
index 4e34de162..a160f1085 100644
--- a/packages/OS400/curl.inc.in
+++ b/packages/OS400/curl.inc.in
@@ -602,6 +602,8 @@
      d                 c                   94
      d  CURLE_HTTP3...
      d                 c                   95
+     d  CURLE_QUIC_CONNECT_ERROR...
+     d                 c                   96
       *
       /if not defined(CURL_NO_OLDIES)
      d  CURLE_URL_MALFORMAT_USER...
@@ -1816,7 +1818,9 @@
      d                 c                   8
      d  CURLM_WAKEUP_FAILURE...
      d                 c                   9
-     d  CURLM_LAST     c                   10
+     d  CURLM_BAD_FUNCTION_ARGUMENT...
+     d                 c                   10
+     d  CURLM_LAST     c                   11
       *
      d CURLMSG         s             10i 0 based(######ptr######)              
 Enum
      d  CURLMSG_NONE   c                   0
diff --git a/packages/OS400/make-lib.sh b/packages/OS400/make-lib.sh
index c1da92445..8b97f6b67 100644
--- a/packages/OS400/make-lib.sh
+++ b/packages/OS400/make-lib.sh
@@ -46,6 +46,26 @@ sed -e ':begin'                                              
           \
 
 INCLUDES="'`pwd`'"
 
+# Create a small C program to check ccsidcurl.c is up to date
+if action_needed "${LIBIFSNAME}/CHKSTRINGS.PGM"
+then
+  CMD="CRTBNDC PGM(${TARGETLIB}/CHKSTRINGS) 
SRCSTMF('${SCRIPTDIR}/chkstrings.c')"
+  CMD="${CMD} INCDIR('${TOPDIR}/include/curl' '${TOPDIR}/include' '${SRCDIR}' 
${INCLUDES})"
+  system -i "${CMD}"
+  if [ $? -ne 0 ]
+  then
+    echo "ERROR: Failed to build CHKSTRINGS *PGM object!"
+    exit 2
+  else
+    ${LIBIFSNAME}/CHKSTRINGS.PGM
+    if [ $? -ne 0 ]
+    then
+      echo "ERROR: CHKSTRINGS failed!"
+      exit 2
+    fi
+  fi
+fi
+
 make_module     OS400SYS        "${SCRIPTDIR}/os400sys.c"
 make_module     CCSIDCURL       "${SCRIPTDIR}/ccsidcurl.c"
 
diff --git a/packages/Symbian/group/libcurl.mmp 
b/packages/Symbian/group/libcurl.mmp
index f125654e0..20e383fbc 100644
--- a/packages/Symbian/group/libcurl.mmp
+++ b/packages/Symbian/group/libcurl.mmp
@@ -34,7 +34,7 @@ SOURCE \
   ssh.c vtls/nss.c strcase.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     \
-  vtls/polarssl.c curl_rtmp.c openldap.c curl_gethostname.c gopher.c   \
+  curl_rtmp.c openldap.c curl_gethostname.c gopher.c   \
   idn_win32.c vtls/cyassl.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 vtls/schannel.c curl_multibyte.c        \
diff --git a/packages/vms/compare_curl_source.com 
b/packages/vms/compare_curl_source.com
index eeaec31dc..66f6a4598 100644
--- a/packages/vms/compare_curl_source.com
+++ b/packages/vms/compare_curl_source.com
@@ -17,7 +17,7 @@ $!        me because VMS Backup can create a saveset of files 
from a
 $!        NFS mounted volume.
 $!
 $! First the files in the original source directory which is assumed to be
-$! under source codde control are compared with the copy directory.
+$! under source code control are compared with the copy directory.
 $!
 $! Then the files are are only in the copy directory are listed.
 $!
diff --git a/packages/vms/curl_crtl_init.c b/packages/vms/curl_crtl_init.c
index 7a8d84743..9f7cf66c7 100644
--- a/packages/vms/curl_crtl_init.c
+++ b/packages/vms/curl_crtl_init.c
@@ -1,7 +1,7 @@
 /* File: curl_crtl_init.c
  *
  * This file makes sure that the DECC Unix settings are correct for
- * the mode the the program is run in.
+ * the mode the program is run in.
  *
  * The CRTL has not been initialized at the time that these routines
  * are called, so many routines can not be called.
diff --git a/packages/vms/generate_config_vms_h_curl.com 
b/packages/vms/generate_config_vms_h_curl.com
index 809aaaf98..6c65b24cb 100644
--- a/packages/vms/generate_config_vms_h_curl.com
+++ b/packages/vms/generate_config_vms_h_curl.com
@@ -17,7 +17,7 @@ $! and the [.lib]config-vms.h file do two different tasks and 
that the
 $! filenames are slightly different.
 $!
 $!
-$! Copyright 2013, John Malmberg
+$! Copyright 2013 - 2020, John Malmberg
 $!
 $! Permission to use, copy, modify, and/or distribute this software for any
 $! purpose with or without fee is hereby granted, provided that the above
@@ -349,9 +349,6 @@ $write cvh "#endif"
 $write cvh "#ifdef USE_OPENLDAP"
 $write cvh "#undef USE_OPENLDAP"
 $write cvh "#endif"
-$write cvh "#ifdef USE_POLARSSL"
-$write cvh "#undef USE_POLARSSL"
-$write cvh "#endif"
 $write cvh "#ifdef USE_THREADS_POSIX"
 $write cvh "#undef USE_THREADS_POSIX"
 $write cvh "#endif"
diff --git a/packages/vms/readme b/packages/vms/readme
index ddfac747a..be1278fca 100644
--- a/packages/vms/readme
+++ b/packages/vms/readme
@@ -194,7 +194,7 @@ LDAP and Kerberos installed, you can use the 
GNV_LINK_CURL.COM file.
 The GNV_LINK_CURL.COM contains information on how to link and run with a newer
 version of HP SSL than what may be install on an Alpha or IA64 based system.
 
-To build the PCSI kit, follow the the instructions in the file
+To build the PCSI kit, follow the instructions in the file
 curl_gnv_build_steps.txt.
 
 Other Notes:
@@ -206,7 +206,7 @@ The libcurl formdata.c module and Curl tools post form now 
have some
 understanding of VMS file types.  Files will be posted in STREAM_LF format.
 
 The Curl tool now has some understanding of VMS file types and will upload the
-files in STREAM_LF fomat.
+files in STREAM_LF format.
 
 When CURL is uploading a VARIABLE format VMS file, it is less efficient as in
 order to get the file size, it will first read the entire file once, and then
diff --git a/scripts/contributors.sh b/scripts/contributors.sh
index a826595c9..6a6d34484 100755
--- a/scripts/contributors.sh
+++ b/scripts/contributors.sh
@@ -6,7 +6,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 2013-2019, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 2013-2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -29,10 +29,19 @@
 
 start=$1
 
-if test -z "$start"; then
+if test "$start" = "-h"; then
     echo "Usage: $0 <since this tag/hash> [--releasenotes]"
     exit
 fi
+if test -z "$start"; then
+    start=`git tag --sort=taggerdate | tail -1`;
+    echo "Since $start:"
+fi
+
+# We also include curl-www if possible. Override by setting CURLWWW
+if [ -z "$CURLWWW" ] ; then
+    CURLWWW=../curl-www
+fi
 
 # filter out Author:, Commit: and *by: lines
 # cut off the email parts
@@ -43,8 +52,15 @@ fi
 # only count names with a space (ie more than one word)
 # sort all unique names
 # awk them into RELEASE-NOTES format
+
 (
-git log --pretty=full --use-mailmap $start..HEAD | \
+ (
+  git log --pretty=full --use-mailmap $start..HEAD
+  if [ -d "$CURLWWW" ]
+  then
+   git -C ../curl-www log --pretty=full --use-mailmap $start..HEAD
+  fi
+ ) | \
 egrep -ai '(^Author|^Commit|by):' | \
 cut -d: -f2- | \
 cut '-d(' -f1 | \
diff --git a/scripts/contrithanks.sh b/scripts/contrithanks.sh
index 85af71038..44e461455 100755
--- a/scripts/contrithanks.sh
+++ b/scripts/contrithanks.sh
@@ -28,14 +28,31 @@
 
 start=$1
 
-if test -z "$start"; then
+if test "$start" = "-h"; then
   echo "Usage: $0 <since this tag/hash>"
+  exit
+fi
+if test -z "$start"; then
+  start=`git tag --sort=taggerdate | tail -1`;
+fi
+
+
+# We also include curl-www if possible. Override by setting CURLWWW
+if [ -z "$CURLWWW" ] ; then
+    CURLWWW=../curl-www
 fi
 
 cat ./docs/THANKS
 
 (
-git log --use-mailmap $start..HEAD | \
+ (
+  git log --use-mailmap $start..HEAD
+  if [ -d "$CURLWWW" ]
+  then
+   git -C ../curl-www log --use-mailmap $start..HEAD
+  fi
+ ) | \
+
 egrep -ai '(^Author|^Commit|by):' | \
 cut -d: -f2- | \
 cut '-d(' -f1 | \
diff --git a/scripts/delta b/scripts/delta
index 63cc1522b..28642aab0 100755
--- a/scripts/delta
+++ b/scripts/delta
@@ -6,7 +6,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 2018-2019, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 2018-2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -30,10 +30,14 @@
 
 $start = $ARGV[0];
 
-if($start eq "") {
+if($start eq "-h") {
     print "Usage: summary [tag]\n";
     exit;
 }
+elsif($start eq "") {
+    $start = `git tag --sort=taggerdate | tail -1`;
+    chomp $start;
+}
 
 $commits = `git log --oneline $start.. | wc -l`;
 $committers = `git shortlog -s $start.. | wc -l`;
@@ -45,16 +49,16 @@ $acommitters = `git shortlog -s | wc -l`;
 # delta from now compared to before
 $ncommitters = $acommitters - $bcommitters;
 
-# number of contributors right now (according to THANKS)
-$acontribs = `cat docs/THANKS | grep -c '^[^ ]'`;
+# number of contributors right now
+$acontribs = `./scripts/contrithanks.sh | grep -c '^[^ ]'`;
 # number when the tag tag was set
 $bcontribs = `git show $start:docs/THANKS | grep -c '^[^ ]'`;
 # delta
 $contribs = $acontribs - $bcontribs;
 
 # number of setops:
-$asetopts=`grep "^  CINIT" include/gnurl/curl.h  | grep -cv OBSOLETE`;
-$bsetopts=`git show $start:include/gnurl/curl.h | grep "^  CINIT" | grep -cv 
OBSOLETE`;
+$asetopts=`grep '^  CURLOPT(' include/gnurl/curl.h  | grep -cv OBSOLETE`;
+$bsetopts=`git show $start:include/gnurl/curl.h | grep '^  CURLOPT(' | grep 
-cv OBSOLETE`;
 $nsetopts = $asetopts - $bsetopts;
 
 # Number of command line options:
@@ -118,7 +122,7 @@ printf "Commit authors: %d out of which %d are new (out of 
%d)\n",
     $committers, $ncommitters, $acommitters;
 printf "Contributors in RELEASE-NOTES: %d\n",
     $numcontributors;
-printf "New contributors (in THANKS): %d (out of %d)\n",
+printf "New contributors: %d (out of %d)\n",
     $contribs, $acontribs;
 printf "New curl_easy_setopt() options: %d (out of %d)\n",
     $nsetopts, $asetopts;
diff --git a/scripts/singleuse.pl b/scripts/singleuse.pl
index 10b9e27cd..ce77fdf05 100755
--- a/scripts/singleuse.pl
+++ b/scripts/singleuse.pl
@@ -6,7 +6,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 2019, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 2019 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -116,9 +116,11 @@ my %api = (
     'curl_multi_socket' => 'API',
     'curl_multi_socket_action' => 'API',
     'curl_multi_socket_all' => 'API',
+    'curl_multi_poll' => 'API',
     'curl_multi_strerror' => 'API',
     'curl_multi_timeout' => 'API',
     'curl_multi_wait' => 'API',
+    'curl_multi_wakeup' => 'API',
     'curl_mvaprintf' => 'API',
     'curl_mvfprintf' => 'API',
     'curl_mvprintf' => 'API',
@@ -179,16 +181,16 @@ for(sort keys %exist) {
     #printf "%s is defined in %s, used by: %s\n", $_, $exist{$_}, $uses{$_};
     if(!$uses{$_}) {
         # this is a symbol with no "global" user
-        if($_ =~ /^curl_/) {
+        if($_ =~ /^curl_dbg_/) {
+            # we ignore the memdebug symbols
+        }
+        elsif($_ =~ /^curl_/) {
             if(!$api{$_}) {
                 # not present in the API, or for debug-builds
                 print STDERR "Bad curl-prefix: $_\n";
                 $err++;
             }
         }
-        elsif($_ =~ /^curl_dbg_/) {
-            # we ignore the memdebug symbols
-        }
         elsif($wl{$_}) {
             #print "$_ is WL\n";
         }
@@ -201,8 +203,11 @@ for(sort keys %exist) {
         # global prefix, make sure it is "blessed"
         if(!$api{$_}) {
             # not present in the API, or for debug-builds
-            print STDERR "Bad curl-prefix $_\n";
-            $err++;
+            if($_ !~ /^curl_dbg_/) {
+                # ignore the memdebug symbols
+                print STDERR "Bad curl-prefix $_\n";
+                $err++;
+            }
         }
     }
 }
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 35fcfbb80..838e3b78a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -46,6 +46,12 @@ add_executable(
   ${GNURL_FILES}
   )
 
+if(CURL_HAS_LTO)
+  set_target_properties(${EXE_NAME} PROPERTIES
+    INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
+    INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
+endif()
+
 source_group("curlX source files" FILES ${GNURLX_CFILES})
 source_group("curl source files" FILES ${GNURL_CFILES})
 source_group("curl header files" FILES ${GNURL_HFILES})
diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c
index 77224adba..3b1023888 100644
--- a/src/tool_cb_hdr.c
+++ b/src/tool_cb_hdr.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -73,12 +73,12 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, 
void *userdata)
    */
   size_t failure = (size && nmemb) ? 0 : 1;
 
-  if(!heads->config)
+  if(!per->config)
     return failure;
 
 #ifdef DEBUGBUILD
   if(size * nmemb > (size_t)CURL_MAX_HTTP_HEADER) {
-    warnf(heads->config->global, "Header data exceeds single call write "
+    warnf(per->config->global, "Header data exceeds single call write "
           "limit!\n");
     return failure;
   }
@@ -88,7 +88,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, 
void *userdata)
    * Write header data when curl option --dump-header (-D) is given.
    */
 
-  if(heads->config->headerfile && heads->stream) {
+  if(per->config->headerfile && heads->stream) {
     size_t rc = fwrite(ptr, size, nmemb, heads->stream);
     if(rc != cb)
       return rc;
@@ -100,7 +100,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, 
void *userdata)
    * Write etag to file when --etag-save option is given.
    * etag string that we want is enveloped in double quotes
    */
-  if(etag_save->config->etag_save_file && etag_save->stream) {
+  if(per->config->etag_save_file && etag_save->stream) {
     /* match only header that start with etag (case insensitive) */
     if(curl_strnequal(str, "etag:", 5)) {
       char *etag_h = NULL;
@@ -109,7 +109,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, 
void *userdata)
       size_t etag_length = 0;
 
       etag_h = ptr;
-      /* point to first occurence of double quote */
+      /* point to first occurrence of double quote */
       first = memchr(etag_h, '\"', cb);
 
       /*
@@ -118,9 +118,8 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, 
void *userdata)
        */
 
       if(!first) {
-        warnf(
-          etag_save->config->global,
-          "\nReceived header etag is missing double quote/s\n");
+        warnf(per->config->global,
+              "\nReceived header etag is missing double quote/s\n");
         return 1;
       }
       else {
@@ -128,13 +127,12 @@ size_t tool_header_cb(char *ptr, size_t size, size_t 
nmemb, void *userdata)
         first++;
       }
 
-      /* point to last occurence of double quote */
+      /* point to last occurrence of double quote */
       last = memchr(first, '\"', cb);
 
       if(!last) {
-        warnf(
-          etag_save->config->global,
-          "\nReceived header etag is missing double quote/s\n");
+        warnf(per->config->global,
+              "\nReceived header etag is missing double quote/s\n");
         return 1;
       }
 
@@ -197,7 +195,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, 
void *userdata)
           /* rename the initial file name to the new file name */
           rc = rename(outs->filename, filename);
           if(rc != 0) {
-            warnf(outs->config->global, "Failed to rename %s -> %s: %s\n",
+            warnf(per->config->global, "Failed to rename %s -> %s: %s\n",
                   outs->filename, filename, strerror(errno));
           }
           if(outs->alloc_filename)
@@ -213,12 +211,12 @@ size_t tool_header_cb(char *ptr, size_t size, size_t 
nmemb, void *userdata)
         outs->filename = filename;
         outs->alloc_filename = TRUE;
         hdrcbdata->honor_cd_filename = FALSE; /* done now! */
-        if(!tool_create_output_file(outs))
+        if(!tool_create_output_file(outs, per->config))
           return failure;
       }
       break;
     }
-    if(!outs->stream && !tool_create_output_file(outs))
+    if(!outs->stream && !tool_create_output_file(outs, per->config))
       return failure;
   }
 
@@ -228,7 +226,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, 
void *userdata)
     /* bold headers only for selected protocols */
     char *value = NULL;
 
-    if(!outs->stream && !tool_create_output_file(outs))
+    if(!outs->stream && !tool_create_output_file(outs, per->config))
       return failure;
 
     if(hdrcbdata->global->isatty && hdrcbdata->global->styled_output)
diff --git a/src/tool_cb_prg.c b/src/tool_cb_prg.c
index 505ae751f..aad451b87 100644
--- a/src/tool_cb_prg.c
+++ b/src/tool_cb_prg.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -46,25 +46,32 @@
 
    my $pi = 3.1415;
    foreach my $i (1 .. 200) {
-     printf "%d, ", sin($i/200 * 2 * $pi) * 5000 + 5000;
+     printf "%d, ", sin($i/200 * 2 * $pi) * 500000 + 500000;
    }
 */
 static const unsigned int sinus[] = {
-  5157, 5313, 5470, 5626, 5782, 5936, 6090, 6243, 6394, 6545, 6693, 6840, 6985,
-  7128, 7269, 7408, 7545, 7679, 7810, 7938, 8064, 8187, 8306, 8422, 8535, 8644,
-  8750, 8852, 8950, 9045, 9135, 9221, 9303, 9381, 9454, 9524, 9588, 9648, 9704,
-  9755, 9801, 9842, 9879, 9911, 9938, 9960, 9977, 9990, 9997, 9999, 9997, 9990,
-  9977, 9960, 9938, 9911, 9879, 9842, 9801, 9755, 9704, 9648, 9588, 9524, 9455,
-  9381, 9303, 9221, 9135, 9045, 8950, 8852, 8750, 8645, 8535, 8422, 8306, 8187,
-  8064, 7939, 7810, 7679, 7545, 7409, 7270, 7129, 6986, 6841, 6694, 6545, 6395,
-  6243, 6091, 5937, 5782, 5627, 5470, 5314, 5157, 5000, 4843, 4686, 4529, 4373,
-  4218, 4063, 3909, 3757, 3605, 3455, 3306, 3159, 3014, 2871, 2730, 2591, 2455,
-  2321, 2190, 2061, 1935, 1813, 1693, 1577, 1464, 1355, 1249, 1147, 1049, 955,
-  864, 778, 696, 618, 545, 476, 411, 351, 295, 244, 198, 157, 120, 88, 61, 39,
-  22, 9, 2, 0, 2, 9, 22, 39, 61, 88, 120, 156, 198, 244, 295, 350, 410, 475,
-  544, 618, 695, 777, 864, 954, 1048, 1146, 1248, 1354, 1463, 1576, 1692, 1812,
-  1934, 2060, 2188, 2320, 2454, 2590, 2729, 2870, 3013, 3158, 3305, 3454, 3604,
-  3755, 3908, 4062, 4216, 4372, 4528, 4685, 4842, 4999
+  515704, 531394, 547052, 562664, 578214, 593687, 609068, 624341, 639491,
+  654504, 669364, 684057, 698568, 712883, 726989, 740870, 754513, 767906,
+  781034, 793885, 806445, 818704, 830647, 842265, 853545, 864476, 875047,
+  885248, 895069, 904500, 913532, 922156, 930363, 938145, 945495, 952406,
+  958870, 964881, 970434, 975522, 980141, 984286, 987954, 991139, 993840,
+  996054, 997778, 999011, 999752, 999999, 999754, 999014, 997783, 996060,
+  993848, 991148, 987964, 984298, 980154, 975536, 970449, 964898, 958888,
+  952426, 945516, 938168, 930386, 922180, 913558, 904527, 895097, 885277,
+  875077, 864507, 853577, 842299, 830682, 818739, 806482, 793922, 781072,
+  767945, 754553, 740910, 727030, 712925, 698610, 684100, 669407, 654548,
+  639536, 624386, 609113, 593733, 578260, 562710, 547098, 531440, 515751,
+  500046, 484341, 468651, 452993, 437381, 421830, 406357, 390976, 375703,
+  360552, 345539, 330679, 315985, 301474, 287158, 273052, 259170, 245525,
+  232132, 219003, 206152, 193590, 181331, 169386, 157768, 146487, 135555,
+  124983, 114781, 104959, 95526, 86493, 77868, 69660, 61876, 54525, 47613,
+  41147, 35135, 29581, 24491, 19871, 15724, 12056, 8868, 6166, 3951, 2225,
+  990, 248, 0, 244, 982, 2212, 3933, 6144, 8842, 12025, 15690, 19832, 24448,
+  29534, 35084, 41092, 47554, 54462, 61809, 69589, 77794, 86415, 95445,
+  104873, 114692, 124891, 135460, 146389, 157667, 169282, 181224, 193480,
+  206039, 218888, 232015, 245406, 259048, 272928, 287032, 301346, 315856,
+  330548, 345407, 360419, 375568, 390841, 406221, 421693, 437243, 452854,
+  468513, 484202, 499907
 };
 
 static void fly(struct ProgressData *bar, bool moved)
@@ -76,13 +83,13 @@ static void fly(struct ProgressData *bar, bool moved)
   msnprintf(buf, sizeof(buf), "%*s\r", bar->width-1, " ");
   memcpy(&buf[bar->bar], "-=O=-", 5);
 
-  pos = sinus[bar->tick%200] / (10000 / check);
+  pos = sinus[bar->tick%200] / (1000000 / check);
   buf[pos] = '#';
-  pos = sinus[(bar->tick + 5)%200] / (10000 / check);
+  pos = sinus[(bar->tick + 5)%200] / (1000000 / check);
   buf[pos] = '#';
-  pos = sinus[(bar->tick + 10)%200] / (10000 / check);
+  pos = sinus[(bar->tick + 10)%200] / (1000000 / check);
   buf[pos] = '#';
-  pos = sinus[(bar->tick + 15)%200] / (10000 / check);
+  pos = sinus[(bar->tick + 15)%200] / (1000000 / check);
   buf[pos] = '#';
 
   fputs(buf, bar->out);
@@ -123,8 +130,7 @@ int tool_progress_cb(void *clientp,
 
   struct timeval now = tvnow();
   struct per_transfer *per = clientp;
-  struct OutStruct *outs = &per->outs;
-  struct OperationConfig *config = outs->config;
+  struct OperationConfig *config = per->config;
   struct ProgressData *bar = &per->progressbar;
   curl_off_t total;
   curl_off_t point;
@@ -252,7 +258,8 @@ void progressbarinit(struct ProgressData *bar,
       }
     }
 #endif /* TIOCGSIZE */
-    bar->width = cols;
+    if(cols > 20)
+      bar->width = cols;
   }
 
   if(!bar->width)
diff --git a/src/tool_cb_rea.c b/src/tool_cb_rea.c
index 03ed4a467..78a169fb0 100644
--- a/src/tool_cb_rea.c
+++ b/src/tool_cb_rea.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -63,8 +63,7 @@ int tool_readbusy_cb(void *clientp,
                      curl_off_t ultotal, curl_off_t ulnow)
 {
   struct per_transfer *per = clientp;
-  struct OutStruct *outs = &per->outs;
-  struct OperationConfig *config = outs->config;
+  struct OperationConfig *config = per->config;
 
   (void)dltotal;  /* unused */
   (void)dlnow;  /* unused */
diff --git a/src/tool_cb_see.c b/src/tool_cb_see.c
index 99be273d1..9d660313e 100644
--- a/src/tool_cb_see.c
+++ b/src/tool_cb_see.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -88,7 +88,7 @@ int tool_seek_cb(void *userdata, curl_off_t offset, int 
whence)
   return CURL_SEEKFUNC_OK;
 }
 
-#if defined(WIN32) && !defined(__MINGW64__)
+#ifdef USE_TOOL_FTRUNCATE
 
 #ifdef __BORLANDC__
 /* 64-bit lseek-like function unavailable */
@@ -129,4 +129,4 @@ int tool_ftruncate64(int fd, curl_off_t where)
   return 0;
 }
 
-#endif /* WIN32  && ! __MINGW64__ */
+#endif /* USE_TOOL_FTRUNCATE */
diff --git a/src/tool_cb_see.h b/src/tool_cb_see.h
index fed8bbf8d..b5b787ed0 100644
--- a/src/tool_cb_see.h
+++ b/src/tool_cb_see.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -23,18 +23,17 @@
  ***************************************************************************/
 #include "tool_setup.h"
 
-#if defined(WIN32) && !defined(__MINGW64__)
+#if defined(WIN32) && !defined(HAVE_FTRUNCATE)
 
 int tool_ftruncate64(int fd, curl_off_t where);
 
 #undef  ftruncate
 #define ftruncate(fd,where) tool_ftruncate64(fd,where)
 
-#ifndef HAVE_FTRUNCATE
-#  define HAVE_FTRUNCATE 1
-#endif
+#define HAVE_FTRUNCATE 1
+#define USE_TOOL_FTRUNCATE 1
 
-#endif /* WIN32  && ! __MINGW64__ */
+#endif /* WIN32  && ! HAVE_FTRUNCATE */
 
 /*
 ** callback for CURLOPT_SEEKFUNCTION
diff --git a/src/tool_cb_wrt.c b/src/tool_cb_wrt.c
index 0f47b4d0f..ed108911e 100644
--- a/src/tool_cb_wrt.c
+++ b/src/tool_cb_wrt.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -33,11 +33,14 @@
 #include "memdebug.h" /* keep this as LAST include */
 
 /* create a local file for writing, return TRUE on success */
-bool tool_create_output_file(struct OutStruct *outs)
+bool tool_create_output_file(struct OutStruct *outs,
+                             struct OperationConfig *config)
 {
-  struct GlobalConfig *global = outs->config->global;
+  struct GlobalConfig *global;
   FILE *file;
-
+  DEBUGASSERT(outs);
+  DEBUGASSERT(config);
+  global = config->global;
   if(!outs->filename || !*outs->filename) {
     warnf(global, "Remote filename has no length!\n");
     return FALSE;
@@ -78,7 +81,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, 
void *userdata)
   size_t rc;
   struct per_transfer *per = userdata;
   struct OutStruct *outs = &per->outs;
-  struct OperationConfig *config = outs->config;
+  struct OperationConfig *config = per->config;
   size_t bytes = sz * nmemb;
   bool is_tty = config->global->isatty;
 #ifdef WIN32
@@ -147,7 +150,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, 
void *userdata)
   }
 #endif
 
-  if(!outs->stream && !tool_create_output_file(outs))
+  if(!outs->stream && !tool_create_output_file(outs, per->config))
     return failure;
 
   if(is_tty && (outs->bytes < 2000) && !config->terminal_binary_ok) {
diff --git a/src/tool_cb_wrt.h b/src/tool_cb_wrt.h
index 188d3ea7d..e49d8f35d 100644
--- a/src/tool_cb_wrt.h
+++ b/src/tool_cb_wrt.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -30,6 +30,7 @@
 size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata);
 
 /* create a local file for writing, return TRUE on success */
-bool tool_create_output_file(struct OutStruct *outs);
+bool tool_create_output_file(struct OutStruct *outs,
+                             struct OperationConfig *config);
 
 #endif /* HEADER_CURL_TOOL_CB_WRT_H */
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index 32e811eaa..e093b2c84 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -108,6 +108,7 @@ struct OperationConfig {
   char *mail_from;
   struct curl_slist *mail_rcpt;
   char *mail_auth;
+  bool mail_rcpt_allowfails; /* --mail-rcpt-allowfails */
   char *sasl_authzid;       /* Authorisation identity (identity to use) */
   bool sasl_ir;             /* Enable/disable SASL initial response */
   bool proxytunnel;
diff --git a/src/tool_dirhie.c b/src/tool_dirhie.c
index 06b3c03e8..320fb3688 100644
--- a/src/tool_dirhie.c
+++ b/src/tool_dirhie.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -125,6 +125,7 @@ CURLcode create_dir_hierarchy(const char *outfile, FILE 
*errors)
   tempdir = strtok(outdup, PATH_DELIMITERS);
 
   while(tempdir != NULL) {
+    bool skip = false;
     tempdir2 = strtok(NULL, PATH_DELIMITERS);
     /* since strtok returns a token for the last word even
        if not ending with DIR_CHAR, we need to prune it */
@@ -133,13 +134,27 @@ CURLcode create_dir_hierarchy(const char *outfile, FILE 
*errors)
       if(dlen)
         msnprintf(&dirbuildup[dlen], outlen - dlen, "%s%s", DIR_CHAR, tempdir);
       else {
-        if(outdup == tempdir)
+        if(outdup == tempdir) {
+#if defined(MSDOS) || defined(WIN32)
+          /* Skip creating a drive's current directory.
+             It may seem as though that would harmlessly fail but it could be
+             a corner case if X: did not exist, since we would be creating it
+             erroneously.
+             eg if outfile is X:\foo\bar\filename then don't mkdir X:
+             This logic takes into account unsupported drives !:, 1:, etc. */
+          char *p = strchr(tempdir, ':');
+          if(p && !p[1])
+            skip = true;
+#endif
           /* the output string doesn't start with a separator */
           strcpy(dirbuildup, tempdir);
+        }
         else
           msnprintf(dirbuildup, outlen, "%s%s", DIR_CHAR, tempdir);
       }
-      if((-1 == mkdir(dirbuildup, (mode_t)0000750)) && (errno != EEXIST)) {
+      /* Create directory. Ignore access denied error to allow traversal. */
+      if(!skip && (-1 == mkdir(dirbuildup, (mode_t)0000750)) &&
+         (errno != EACCES) && (errno != EEXIST)) {
         show_dir_errno(errors, dirbuildup);
         result = CURLE_WRITE_ERROR;
         break; /* get out of loop */
diff --git a/src/tool_doswin.c b/src/tool_doswin.c
index a64a81633..221e3864b 100644
--- a/src/tool_doswin.c
+++ b/src/tool_doswin.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -697,6 +697,32 @@ cleanup:
   return slist;
 }
 
+LARGE_INTEGER Curl_freq;
+bool Curl_isVistaOrGreater;
+
+CURLcode win32_init(void)
+{
+  OSVERSIONINFOEXA osvi;
+  unsigned __int64 mask = 0;
+  unsigned char op = VER_GREATER_EQUAL;
+
+  memset(&osvi, 0, sizeof(osvi));
+  osvi.dwOSVersionInfoSize = sizeof(osvi);
+  osvi.dwMajorVersion = 6;
+  VER_SET_CONDITION(mask, VER_MAJORVERSION, op);
+  VER_SET_CONDITION(mask, VER_MINORVERSION, op);
+
+  if(VerifyVersionInfoA(&osvi, (VER_MAJORVERSION | VER_MINORVERSION), mask))
+    Curl_isVistaOrGreater = true;
+  else if(GetLastError() == ERROR_OLD_WIN_VERSION)
+    Curl_isVistaOrGreater = false;
+  else
+    return CURLE_FAILED_INIT;
+
+  QueryPerformanceFrequency(&Curl_freq);
+  return CURLE_OK;
+}
+
 #endif /* WIN32 */
 
 #endif /* MSDOS || WIN32 */
diff --git a/src/tool_doswin.h b/src/tool_doswin.h
index 457637665..d1649d1f3 100644
--- a/src/tool_doswin.h
+++ b/src/tool_doswin.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -61,6 +61,7 @@ CURLcode FindWin32CACert(struct OperationConfig *config,
                          curl_sslbackend backend,
                          const char *bundle_file);
 struct curl_slist *GetLoadedModulePaths(void);
+CURLcode win32_init(void);
 
 #endif /* WIN32 */
 
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index 8df6e5e24..764caa203 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -273,6 +273,7 @@ static const struct LongShort aliases[]= {
   {"f",  "fail",                     ARG_BOOL},
   {"fa", "fail-early",               ARG_BOOL},
   {"fb", "styled-output",            ARG_BOOL},
+  {"fc", "mail-rcpt-allowfails",     ARG_BOOL},
   {"F",  "form",                     ARG_STRING},
   {"Fs", "form-string",              ARG_STRING},
   {"g",  "globoff",                  ARG_BOOL},
@@ -421,7 +422,7 @@ void parse_cert_parameter(const char *cert_parameter,
       /* escaped colons and Windows drive letter colons were handled
        * above; if we're still here, this is a separating colon */
       param_place++;
-      if(strlen(param_place) > 0) {
+      if(*param_place) {
         *passphrase = strdup(param_place);
       }
       goto done;
@@ -1277,7 +1278,10 @@ ParameterError getparameter(const char *flag, /* f or 
-long-flag */
     case 'b':
       switch(subletter) {
       case 'a': /* --alt-svc */
-        GetStr(&config->altsvc, nextarg);
+        if(curlinfo->features & CURL_VERSION_ALTSVC)
+          GetStr(&config->altsvc, nextarg);
+        else
+          return PARAM_LIBCURL_DOESNT_SUPPORT;
         break;
       default:  /* --cookie string coming up: */
         if(nextarg[0] == '@') {
@@ -1722,6 +1726,9 @@ ParameterError getparameter(const char *flag, /* f or 
-long-flag */
       case 'b': /* --styled-output */
         global->styled_output = toggle;
         break;
+      case 'c': /* --mail-rcpt-allowfails */
+        config->mail_rcpt_allowfails = toggle;
+        break;
       default: /* --fail (hard on errors)  */
         config->failonerror = toggle;
       }
diff --git a/src/tool_help.c b/src/tool_help.c
index 8d3f34547..9ee99d174 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -239,6 +239,8 @@ static const struct helptxt helptext[] = {
    "Mail from this address"},
   {"    --mail-rcpt <address>",
    "Mail to this address"},
+  {"    --mail-rcpt-allowfails",
+   "Allow RCPT TO command to fail for some recipients"},
   {"-M, --manual",
    "Display the full manual"},
   {"    --max-filesize <bytes>",
diff --git a/src/tool_homedir.c b/src/tool_homedir.c
index 6bc69551e..719ff6a55 100644
--- a/src/tool_homedir.c
+++ b/src/tool_homedir.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -25,38 +25,23 @@
 #  include <pwd.h>
 #endif
 
+#include <curl/mprintf.h>
+
 #include "tool_homedir.h"
 
 #include "memdebug.h" /* keep this as LAST include */
 
-static char *GetEnv(const char *variable, char do_expand)
+static char *GetEnv(const char *variable)
 {
-  char *env = NULL;
-#ifdef WIN32
-  char  buf1[1024], buf2[1024];
-  DWORD rc;
+  char *dupe, *env;
 
-  /* Don't use getenv(); it doesn't find variable added after program was
-   * started. Don't accept truncated results (i.e. rc >= sizeof(buf1)).  */
+  env = curl_getenv(variable);
+  if(!env)
+    return NULL;
 
-  rc = GetEnvironmentVariableA(variable, buf1, sizeof(buf1));
-  if(rc > 0 && rc < sizeof(buf1)) {
-    env = buf1;
-    variable = buf1;
-  }
-  if(do_expand && strchr(variable, '%')) {
-    /* buf2 == variable if not expanded */
-    rc = ExpandEnvironmentStringsA(variable, buf2, sizeof(buf2));
-    if(rc > 0 && rc < sizeof(buf2) &&
-       !strchr(buf2, '%'))    /* no vars still unexpanded */
-      env = buf2;
-  }
-#else
-  (void)do_expand;
-  /* no length control */
-  env = getenv(variable);
-#endif
-  return (env && env[0]) ? strdup(env) : NULL;
+  dupe = strdup(env);
+  curl_free(env);
+  return dupe;
 }
 
 /* return the home directory of the current user as an allocated string */
@@ -64,11 +49,11 @@ char *homedir(void)
 {
   char *home;
 
-  home = GetEnv("CURL_HOME", FALSE);
+  home = GetEnv("CURL_HOME");
   if(home)
     return home;
 
-  home = GetEnv("HOME", FALSE);
+  home = GetEnv("HOME");
   if(home)
     return home;
 
@@ -86,10 +71,18 @@ char *homedir(void)
  }
 #endif /* PWD-stuff */
 #ifdef WIN32
-  home = GetEnv("APPDATA", TRUE);
-  if(!home)
-    home = GetEnv("%USERPROFILE%\\Application Data", TRUE); /* Normally only
-                                                               on Win-2K/XP */
+  home = GetEnv("APPDATA");
+  if(!home) {
+    char *env = GetEnv("USERPROFILE");
+    if(env) {
+      char *path = curl_maprintf("%s\\Application Data", env);
+      if(path) {
+        home = strdup(path);
+        curl_free(path);
+      }
+      free(env);
+    }
+  }
 #endif /* WIN32 */
   return home;
 }
diff --git a/src/tool_main.c b/src/tool_main.c
index 06923c332..25042895f 100644
--- a/src/tool_main.c
+++ b/src/tool_main.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -279,6 +279,24 @@ int main(int argc, char *argv[])
   struct GlobalConfig global;
   memset(&global, 0, sizeof(global));
 
+#ifdef WIN32
+  /* Undocumented diagnostic option to list the full paths of all loaded
+     modules. This is purposely pre-init. */
+  if(argc == 2 && !strcmp(argv[1], "--dump-module-paths")) {
+    struct curl_slist *item, *head = GetLoadedModulePaths();
+    for(item = head; item; item = item->next)
+      printf("%s\n", item->data);
+    curl_slist_free_all(head);
+    return head ? 0 : 1;
+  }
+  /* win32_init must be called before other init routines. */
+  result = win32_init();
+  if(result) {
+    fprintf(stderr, "curl: (%d) Windows-specific init failed.\n", result);
+    return result;
+  }
+#endif
+
   /* Perform any platform-specific terminal configuration */
   configure_terminal();
 
@@ -294,21 +312,6 @@ int main(int argc, char *argv[])
   /* Initialize the curl library - do not call any libcurl functions before
      this point */
   result = main_init(&global);
-
-#ifdef WIN32
-  /* Undocumented diagnostic option to list the full paths of all loaded
-     modules, regardless of whether or not initialization succeeded. */
-  if(argc == 2 && !strcmp(argv[1], "--dump-module-paths")) {
-    struct curl_slist *item, *head = GetLoadedModulePaths();
-    for(item = head; item; item = item->next) {
-      printf("%s\n", item->data);
-    }
-    curl_slist_free_all(head);
-    if(!result)
-      main_free(&global);
-  }
-  else
-#endif /* WIN32 */
   if(!result) {
     /* Start our curl operation */
     result = operate(&global, argc, argv);
diff --git a/src/tool_metalink.c b/src/tool_metalink.c
index 6d62f2d93..f87f686f1 100644
--- a/src/tool_metalink.c
+++ b/src/tool_metalink.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -54,13 +54,6 @@
 #  define SHA256_CTX void *
 #  define HAVE_NSS_CONTEXT
    static NSSInitContext *nss_context;
-#elif defined(USE_POLARSSL)
-#  include <polarssl/md5.h>
-#  include <polarssl/sha1.h>
-#  include <polarssl/sha256.h>
-#  define MD5_CTX    md5_context
-#  define SHA_CTX    sha1_context
-#  define SHA256_CTX sha256_context
 #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \
               (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \
       (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \
@@ -73,7 +66,7 @@
    and later. If you're building for an older cat, well, sorry. */
 #  define COMMON_DIGEST_FOR_OPENSSL
 #  include <CommonCrypto/CommonDigest.h>
-#elif defined(WIN32)
+#elif defined(USE_WIN32_CRYPTO)
 /* For Windows: If no other crypto library is provided, we fallback
    to the hash functions provided within the Microsoft Windows CryptoAPI */
 #  include <wincrypt.h>
@@ -325,63 +318,7 @@ static void SHA256_Final(unsigned char digest[32], 
SHA256_CTX *pctx)
   nss_hash_final(pctx, digest, 32);
 }
 
-#elif defined(USE_POLARSSL)
-
-static int MD5_Init(MD5_CTX *ctx)
-{
-  md5_starts(ctx);
-  return 1;
-}
-
-static void MD5_Update(MD5_CTX *ctx,
-                       const unsigned char *input,
-                       unsigned int inputLen)
-{
-  md5_update(ctx, input, inputLen);
-}
-
-static void MD5_Final(unsigned char digest[16], MD5_CTX *ctx)
-{
-  md5_finish(ctx, digest);
-}
-
-static int SHA1_Init(SHA_CTX *ctx)
-{
-  sha1_starts(ctx);
-  return 1;
-}
-
-static void SHA1_Update(SHA_CTX *ctx,
-                        const unsigned char *input,
-                        unsigned int inputLen)
-{
-  sha1_update(ctx, input, inputLen);
-}
-
-static void SHA1_Final(unsigned char digest[20], SHA_CTX *ctx)
-{
-  sha1_finish(ctx, digest);
-}
-
-static int SHA256_Init(SHA256_CTX *ctx)
-{
-  sha256_starts(ctx, 0); /* 0 = sha256 */
-  return 1;
-}
-
-static void SHA256_Update(SHA256_CTX *ctx,
-                          const unsigned char *input,
-                          unsigned int inputLen)
-{
-  sha256_update(ctx, input, inputLen);
-}
-
-static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
-{
-  sha256_finish(ctx, digest);
-}
-
-#elif defined(WIN32)
+#elif defined(USE_WIN32_CRYPTO)
 
 static void win32_crypto_final(struct win32_crypto_hash *ctx,
                                unsigned char *digest,
@@ -895,7 +832,7 @@ size_t metalink_write_cb(void *buffer, size_t sz, size_t 
nmemb,
 {
   struct per_transfer *per = userdata;
   struct OutStruct *outs = &per->outs;
-  struct OperationConfig *config = outs->config;
+  struct OperationConfig *config = per->config;
   int rv;
 
   /*
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 08123687d..cb877986c 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -380,7 +380,7 @@ static CURLcode post_per_transfer(struct GlobalConfig 
*global,
     /* do not create (or even overwrite) the file in case we get no
        data because of unmet condition */
     curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &cond_unmet);
-    if(!cond_unmet && !tool_create_output_file(outs))
+    if(!cond_unmet && !tool_create_output_file(outs, config))
       result = CURLE_WRITE_ERROR;
   }
 
@@ -866,13 +866,13 @@ static CURLcode single_transfer(struct GlobalConfig 
*global,
         /* default headers output stream is stdout */
         heads = &per->heads;
         heads->stream = stdout;
-        heads->config = config;
 
         /* Single header file for all URLs */
         if(config->headerfile) {
           /* open file for output: */
           if(strcmp(config->headerfile, "-")) {
-            FILE *newfile = fopen(config->headerfile, "wb");
+            FILE *newfile;
+            newfile = fopen(config->headerfile, per->prev == NULL?"wb":"ab");
             if(!newfile) {
               warnf(config->global, "Failed to open %s\n", config->headerfile);
               result = CURLE_WRITE_ERROR;
@@ -891,10 +891,22 @@ static CURLcode single_transfer(struct GlobalConfig 
*global,
           }
         }
 
+        hdrcbdata = &per->hdrcbdata;
+
+        outs = &per->outs;
+        input = &per->input;
+
+        per->outfile = NULL;
+        per->infdopen = FALSE;
+        per->infd = STDIN_FILENO;
+
+        /* default output stream is stdout */
+        outs->stream = stdout;
+
         /* --etag-save */
         etag_save = &per->etag_save;
         etag_save->stream = stdout;
-        etag_save->config = config;
+
         if(config->etag_save_file) {
           /* open file for output: */
           if(strcmp(config->etag_save_file, "-")) {
@@ -961,19 +973,6 @@ static CURLcode single_transfer(struct GlobalConfig 
*global,
           }
         }
 
-        hdrcbdata = &per->hdrcbdata;
-
-        outs = &per->outs;
-        input = &per->input;
-
-        per->outfile = NULL;
-        per->infdopen = FALSE;
-        per->infd = STDIN_FILENO;
-
-        /* default output stream is stdout */
-        outs->stream = stdout;
-        outs->config = config;
-
         if(metalink) {
           /* For Metalink download, use name in Metalink file as
              filename. */
@@ -1836,6 +1835,10 @@ static CURLcode single_transfer(struct GlobalConfig 
*global,
         if(config->mail_rcpt)
           my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
 
+        /* curl 7.69.x */
+        my_setopt(curl, CURLOPT_MAIL_RCPT_ALLLOWFAILS,
+          config->mail_rcpt_allowfails ? 1L : 0L);
+
         /* curl 7.20.x */
         if(config->ftp_pret)
           my_setopt(curl, CURLOPT_FTP_USE_PRET, 1L);
@@ -1963,11 +1966,8 @@ static CURLcode single_transfer(struct GlobalConfig 
*global,
         if(config->disallow_username_in_url)
           my_setopt(curl, CURLOPT_DISALLOW_USERNAME_IN_URL, 1L);
 
-#ifdef USE_ALTSVC
-        /* only if explicitly enabled in configure */
         if(config->altsvc)
           my_setopt_str(curl, CURLOPT_ALTSVC, config->altsvc);
-#endif
 
 #ifdef USE_METALINK
         if(!metalink && config->use_metalink) {
diff --git a/src/tool_operhlp.c b/src/tool_operhlp.c
index 8a9b7c9e8..05c9d864a 100644
--- a/src/tool_operhlp.c
+++ b/src/tool_operhlp.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -85,7 +85,7 @@ char *add_file_name_to_url(char *url, const char *filename)
   else
     ptr = url;
   ptr = strrchr(ptr, '/');
-  if(!ptr || !strlen(++ptr)) {
+  if(!ptr || !*++ptr) {
     /* The URL has no file name part, add the local file name. In order
        to be able to do so, we have to create a new URL in another
        buffer.*/
diff --git a/src/tool_progress.c b/src/tool_progress.c
index ac4f58f41..31cd56ae4 100644
--- a/src/tool_progress.c
+++ b/src/tool_progress.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -95,8 +95,7 @@ int xferinfo_cb(void *clientp,
                 curl_off_t ulnow)
 {
   struct per_transfer *per = clientp;
-  struct OutStruct *outs = &per->outs;
-  struct OperationConfig *config = outs->config;
+  struct OperationConfig *config = per->config;
   per->dltotal = dltotal;
   per->dlnow = dlnow;
   per->ultotal = ultotal;
diff --git a/src/tool_sdecls.h b/src/tool_sdecls.h
index 562fef852..ccc9f5aba 100644
--- a/src/tool_sdecls.h
+++ b/src/tool_sdecls.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -69,7 +69,6 @@ struct OutStruct {
   bool s_isreg;
   bool fopened;
   FILE *stream;
-  struct OperationConfig *config;
   curl_off_t bytes;
   curl_off_t init;
 #ifdef USE_METALINK
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index 450cdcf32..6c8716104 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -627,7 +627,7 @@ CURLcode glob_match_url(char **result, char *filename, 
URLGlob *glob)
       unsigned long num = strtoul(&filename[1], &filename, 10);
       URLPattern *pat = NULL;
 
-      if(num < glob->size) {
+      if(num && (num < glob->size)) {
         unsigned long i;
         num--; /* make it zero based */
         /* find the correct glob entry */
diff --git a/src/tool_util.c b/src/tool_util.c
index 04d73e4e3..8bbfae03e 100644
--- a/src/tool_util.c
+++ b/src/tool_util.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -27,27 +27,35 @@
 
 #if defined(WIN32) && !defined(MSDOS)
 
+/* set in win32_init() */
+extern LARGE_INTEGER Curl_freq;
+extern bool Curl_isVistaOrGreater;
+
+/* In case of bug fix this function has a counterpart in timeval.c */
 struct timeval tvnow(void)
 {
-  /*
-  ** GetTickCount() is available on _all_ Windows versions from W95 up
-  ** to nowadays. Returns milliseconds elapsed since last system boot,
-  ** increases monotonically and wraps once 49.7 days have elapsed.
-  **
-  ** GetTickCount64() is available on Windows version from Windows Vista
-  ** and Windows Server 2008 up to nowadays. The resolution of the
-  ** function is limited to the resolution of the system timer, which
-  ** is typically in the range of 10 milliseconds to 16 milliseconds.
-  */
   struct timeval now;
-#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) && \
-    (!defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR))
-  ULONGLONG milliseconds = GetTickCount64();
-#else
-  DWORD milliseconds = GetTickCount();
+  if(Curl_isVistaOrGreater) { /* QPC timer might have issues pre-Vista */
+    LARGE_INTEGER count;
+    QueryPerformanceCounter(&count);
+    now.tv_sec = (long)(count.QuadPart / Curl_freq.QuadPart);
+    now.tv_usec = (long)((count.QuadPart % Curl_freq.QuadPart) * 1000000 /
+                         Curl_freq.QuadPart);
+  }
+  else {
+    /* Disable /analyze warning that GetTickCount64 is preferred  */
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable:28159)
+#endif
+    DWORD milliseconds = GetTickCount();
+#if defined(_MSC_VER)
+#pragma warning(pop)
 #endif
-  now.tv_sec = (long)(milliseconds / 1000);
-  now.tv_usec = (long)((milliseconds % 1000) * 1000);
+
+    now.tv_sec = (long)(milliseconds / 1000);
+    now.tv_usec = (long)((milliseconds % 1000) * 1000);
+  }
   return now;
 }
 
diff --git a/tests/.gitignore b/tests/.gitignore
index 80e90dbf5..cfd109379 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -6,6 +6,7 @@ curl_client_key.pub
 curl_client_knownhosts
 curl_host_rsa_key
 curl_host_rsa_key.pub
+curl_host_rsa_key.pub_md5
 curl_sftp_cmds
 curl_sftp_config
 curl_ssh_config
diff --git a/tests/FILEFORMAT b/tests/FILEFORMAT
index 8a9eb3579..16e7d3092 100644
--- a/tests/FILEFORMAT
+++ b/tests/FILEFORMAT
@@ -156,18 +156,17 @@ auth_required   if this is set and a POST/PUT is made 
without auth, the
 idle            do nothing after receiving the request, just "sit idle"
 stream          continuously send data to the client, never-ending
 writedelay: [secs] delay this amount between reply packets
-skip: [num]     instructs the server to ignore reading this many bytes from a 
PUT
-                or POST request
-
+skip: [num]     instructs the server to ignore reading this many bytes from a
+                PUT or POST request
 rtp: part [num] channel [num] size [num]
                stream a fake RTP packet for the given part on a chosen channel
                with the given payload size
-
 connection-monitor When used, this will log [DISCONNECT] to the server.input
                log when the connection is disconnected.
 upgrade        when an HTTP upgrade header is found, the server will upgrade
                to http2
 swsclose       instruct server to close connection after response
+no-expect      don't read the request body if Expect: is present
 
 For TFTP:
 writedelay: [secs] delay this amount between reply packets (each packet being
@@ -217,6 +216,7 @@ SKIPPED.
 
 Features testable here are:
 
+alt-svc
 crypto
 debug
 getrlimit
@@ -227,6 +227,7 @@ idn
 ipv6
 Kerberos
 large_file
+ld_preload
 libz
 manual
 Metalink
@@ -239,14 +240,13 @@ SPNEGO
 SSL
 SSLpinning
 SSPI
+threaded-resolver
 TLS-SRP
 TrackMemory
-threaded-resolver
 unittest
 unix-sockets
+win32
 WinSSL
-ld_preload
-alt-svc
 
 as well as each protocol that curl supports.  A protocol only needs to be
 specified if it is different from the server (useful when the server
@@ -366,6 +366,7 @@ Available substitute variables include:
 %FILE_PWD  - Current directory, on windows prefixed with a slash
 %RTSP6PORT - IPv6 port number of the RTSP server
 %RTSPPORT  - Port number of the RTSP server
+%SSHSRVMD5 - MD5 of SSH server's public key
 %SMTP6PORT - IPv6 port number of the SMTP server
 %SMTPPORT  - Port number of the SMTP server
 %SOCKSPORT - Port number of the SOCKS4/5 server
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5d877d7ec..16cb9ae1b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -39,8 +39,9 @@ ED_5 = mem-include-scan.pl valgrind.supp extern-scan.pl
 ED_6 = manpage-scan.pl nroff-scan.pl http2-server.pl dictserver.py.in
 ED_7 = negtelnetserver.py.in $(SMBDEPS) objnames-test08.sh objnames-test10.sh
 ED_8 = objnames.inc disable-scan.pl error-codes.pl CMakeLists.txt
+ED_9 = badsymbols.pl azure.pm appveyor.pm
 
-EXTRA_DIST = $(ED_1) $(ED_2) $(ED_3) $(ED_4) $(ED_5) $(ED_6) $(ED_7) $(ED_8)
+EXTRA_DIST = $(ED_1) $(ED_2) $(ED_3) $(ED_4) $(ED_5) $(ED_6) $(ED_7) $(ED_8) 
$(ED_9)
 
 check_SCRIPTS = smbserver.py curl_test_data.py negtelnetserver.py dictserver.py
 
diff --git a/tests/appveyor.pm b/tests/appveyor.pm
new file mode 100644
index 000000000..4906d2c8c
--- /dev/null
+++ b/tests/appveyor.pm
@@ -0,0 +1,114 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 2020, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 2020, Marc Hoersken, <address@hidden>
+#
+# 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.
+#
+###########################################################################
+
+use strict;
+use warnings;
+
+my %APPVEYOR_TEST_NAMES;
+
+sub appveyor_check_environment {
+    if(defined $ENV{'APPVEYOR_API_URL'} && $ENV{'APPVEYOR_API_URL'}) {
+        return 1;
+    }
+    return 0;
+}
+
+sub appveyor_create_test_result {
+    my ($testnum, $testname)=@_;
+    $testname =~ s/\\/\\\\/g;
+    $testname =~ s/\'/\\\'/g;
+    $testname =~ s/\"/\\\"/g;
+    my $appveyor_baseurl="$ENV{'APPVEYOR_API_URL'}";
+    my $appveyor_result=`curl --silent --noproxy "*" \\
+    --header "Content-Type: application/json" \\
+    --data "
+        {
+            'testName': '$testname',
+            'testFramework': 'runtests.pl',
+            'fileName': 'tests/data/test$testnum',
+            'outcome': 'Running'
+        }
+    " \\
+    "$appveyor_baseurl/api/tests"`;
+    print $appveyor_result;
+    $APPVEYOR_TEST_NAMES{$testnum}=$testname;
+}
+
+sub appveyor_update_test_result {
+    my ($testnum, $error, $start, $stop)=@_;
+    my $testname=$APPVEYOR_TEST_NAMES{$testnum};
+    if(!defined $testname) {
+        return;
+    }
+    if(!defined $stop) {
+        $stop = $start;
+    }
+    my $appveyor_duration = sprintf("%.0f", ($stop-$start)*1000);
+    my $appveyor_outcome;
+    my $appveyor_category;
+    if($error == 2) {
+        $appveyor_outcome = 'Ignored';
+        $appveyor_category = 'Warning';
+    }
+    elsif($error < 0) {
+        $appveyor_outcome = 'NotRunnable';
+        $appveyor_category = 'Warning';
+    }
+    elsif(!$error) {
+        $appveyor_outcome = 'Passed';
+        $appveyor_category = 'Information';
+    }
+    else {
+        $appveyor_outcome = 'Failed';
+        $appveyor_category = 'Error';
+    }
+    my $appveyor_baseurl="$ENV{'APPVEYOR_API_URL'}";
+    my $appveyor_result=`curl --silent --noproxy "*" --request PUT \\
+    --header "Content-Type: application/json" \\
+    --data "
+        {
+            'testName': '$testname',
+            'testFramework': 'runtests.pl',
+            'fileName': 'tests/data/test$testnum',
+            'outcome': '$appveyor_outcome',
+            'durationMilliseconds': $appveyor_duration
+        }
+    " \\
+    "$appveyor_baseurl/api/tests"`;
+    print $appveyor_result;
+    if($appveyor_category eq 'Error') {
+        $appveyor_result=`curl --silent --noproxy "*" \\
+        --header "Content-Type: application/json" \\
+        --data "
+            {
+                'message': '$testname $appveyor_outcome',
+                'category': '$appveyor_category',
+                'details': 'Test $testnum $appveyor_outcome'
+            }
+        " \\
+        "$appveyor_baseurl/api/build/messages"`;
+        print $appveyor_result;
+    }
+}
+
+1;
diff --git a/tests/azure.pm b/tests/azure.pm
new file mode 100644
index 000000000..9dcb56c78
--- /dev/null
+++ b/tests/azure.pm
@@ -0,0 +1,146 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 2020, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 2020, Marc Hoersken, <address@hidden>
+#
+# 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.
+#
+###########################################################################
+
+use strict;
+use warnings;
+
+use POSIX qw(strftime);
+
+sub azure_check_environment {
+    if(defined $ENV{'AZURE_ACCESS_TOKEN'} && $ENV{'AZURE_ACCESS_TOKEN'} &&
+       defined $ENV{'AGENT_JOBNAME'} && $ENV{'BUILD_BUILDID'} &&
+       defined $ENV{'SYSTEM_TEAMFOUNDATIONCOLLECTIONURI'} &&
+       defined $ENV{'SYSTEM_TEAMPROJECTID'}) {
+        return 1;
+    }
+    return 0;
+}
+
+sub azure_create_test_run {
+    my 
$azure_baseurl="$ENV{'SYSTEM_TEAMFOUNDATIONCOLLECTIONURI'}$ENV{'SYSTEM_TEAMPROJECTID'}";
+    my $azure_run=`curl --silent --noproxy "*" \\
+    --header "Authorization: Bearer $ENV{'AZURE_ACCESS_TOKEN'}" \\
+    --header "Content-Type: application/json" \\
+    --data "
+        {
+            'name': '$ENV{'AGENT_JOBNAME'}',
+            'automated': true,
+            'build': {'id': '$ENV{'BUILD_BUILDID'}'}
+        }
+    " \\
+    "$azure_baseurl/_apis/test/runs?api-version=5.0"`;
+    if($azure_run =~ /"id":(\d+)/) {
+        return $1;
+    }
+    return "";
+}
+
+sub azure_create_test_result {
+    my ($azure_run_id, $testnum, $testname)=@_;
+    $testname =~ s/\\/\\\\/g;
+    $testname =~ s/\'/\\\'/g;
+    $testname =~ s/\"/\\\"/g;
+    my 
$azure_baseurl="$ENV{'SYSTEM_TEAMFOUNDATIONCOLLECTIONURI'}$ENV{'SYSTEM_TEAMPROJECTID'}";
+    my $azure_result=`curl --silent --noproxy "*" \\
+    --header "Authorization: Bearer $ENV{'AZURE_ACCESS_TOKEN'}" \\
+    --header "Content-Type: application/json" \\
+    --data "
+        [
+            {
+                'build': {'id': '$ENV{'BUILD_BUILDID'}'},
+                'testCase': {'id': $testnum},
+                'testCaseTitle': '$testname',
+                'automatedTestName': 'curl.tests.$testnum',
+                'outcome': 'InProgress'
+            }
+        ]
+    " \\
+    "$azure_baseurl/_apis/test/runs/$azure_run_id/results?api-version=5.0"`;
+    if($azure_result =~ /\[\{"id":(\d+)/) {
+        return $1;
+    }
+    return "";
+}
+
+sub azure_update_test_result {
+    my ($azure_run_id, $azure_result_id, $testnum, $error, $start, $stop)=@_;
+    if(!defined $stop) {
+        $stop = $start;
+    }
+    my $azure_start = strftime "%Y-%m-%dT%H:%M:%SZ", gmtime $start;
+    my $azure_complete = strftime "%Y-%m-%dT%H:%M:%SZ", gmtime $stop;
+    my $azure_duration = sprintf("%.0f", ($stop-$start)*1000);
+    my $azure_outcome;
+    if($error == 2) {
+        $azure_outcome = 'Not applicable';
+    }
+    elsif($error < 0) {
+        $azure_outcome = 'Not executed';
+    }
+    elsif(!$error) {
+        $azure_outcome = 'Passed';
+    }
+    else {
+        $azure_outcome = 'Failed';
+    }
+    my 
$azure_baseurl="$ENV{'SYSTEM_TEAMFOUNDATIONCOLLECTIONURI'}$ENV{'SYSTEM_TEAMPROJECTID'}";
+    my $azure_result=`curl --silent --noproxy "*" --request PATCH \\
+    --header "Authorization: Bearer $ENV{'AZURE_ACCESS_TOKEN'}" \\
+    --header "Content-Type: application/json" \\
+    --data "
+        [
+            {
+                'id': $azure_result_id,
+                'outcome': '$azure_outcome',
+                'startedDate': '$azure_start',
+                'completedDate': '$azure_complete',
+                'durationInMs': $azure_duration
+            }
+        ]
+    " \\
+    "$azure_baseurl/_apis/test/runs/$azure_run_id/results?api-version=5.0"`;
+    if($azure_result =~ /\[\{"id":(\d+)/) {
+        return $1;
+    }
+    return "";
+}
+
+sub azure_update_test_run {
+    my ($azure_run_id)=@_;
+    my 
$azure_baseurl="$ENV{'SYSTEM_TEAMFOUNDATIONCOLLECTIONURI'}$ENV{'SYSTEM_TEAMPROJECTID'}";
+    my $azure_run=`curl --silent --noproxy "*" --request PATCH \\
+    --header "Authorization: Bearer $ENV{'AZURE_ACCESS_TOKEN'}" \\
+    --header "Content-Type: application/json" \\
+    --data "
+        {
+            'state': 'Completed'
+        }
+    " \\
+    "$azure_baseurl/_apis/test/runs/$azure_run_id?api-version=5.0"`;
+    if($azure_run =~ /"id":(\d+)/) {
+        return $1;
+    }
+    return "";
+}
+
+1;
diff --git a/tests/badsymbols.pl b/tests/badsymbols.pl
new file mode 100755
index 000000000..05d325c3d
--- /dev/null
+++ b/tests/badsymbols.pl
@@ -0,0 +1,132 @@
+#!/usr/bin/env perl
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 2010-2020, Daniel Stenberg, <address@hidden>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.haxx.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+###########################################################################
+#
+# This script grew out of help from Przemyslaw Iskra and Balint Szilakszi
+# a late evening in the #curl IRC channel on freenode.
+#
+
+use strict;
+use warnings;
+use vars qw($Cpreprocessor);
+
+#
+# configurehelp perl module is generated by configure script
+#
+my $rc = eval {
+    require configurehelp;
+    configurehelp->import(qw(
+        $Cpreprocessor
+    ));
+    1;
+};
+# Set default values if configure has not generated a configurehelp.pm file.
+# This is the case with cmake.
+if (!$rc) {
+    $Cpreprocessor = 'cpp';
+}
+
+# we may get the dir root pointed out
+my $root=$ARGV[0] || ".";
+
+# need an include directory when building out-of-tree
+my $i = ($ARGV[1]) ? "-I$ARGV[1] " : '';
+
+my $incdir = "$root/include/curl";
+
+my $verbose=0;
+my $summary=0;
+my $misses=0;
+
+my @syms;
+my %doc;
+my %rem;
+
+sub scanenums {
+    my ($file)=@_;
+    my $skipit = 0;
+
+    open H_IN, "-|", "$Cpreprocessor $i$file" || die "Cannot preprocess $file";
+    while ( <H_IN> ) {
+        if( /^#(line|) (\d+) \"(.*)\"/) {
+            # if the included file isn't in our incdir, then we skip this 
section
+            # until next #line
+            #
+            if($3 !~ /^$incdir/) {
+                $skipit = 1;
+                next;
+            }
+            # parse this!
+            $skipit = 0,
+        }
+        if($skipit) {
+            next;
+        }
+        if ( /enum\s+(\S+\s+)?{/ .. /}/ ) {
+            s/^\s+//;
+            chomp;
+            s/[,\s].*//;
+            if(($_ !~ /\}(;|)/) &&
+               ($_ ne "typedef") &&
+               ($_ ne "enum") &&
+               ($_ !~ /^[ \t]*$/) &&
+               ($_ ne "#")) {
+                push @syms, $_;
+            }
+        }
+    }
+    close H_IN || die "Error preprocessing $file";
+}
+
+sub scanheader {
+    my ($f)=@_;
+    scanenums($f);
+    open H, "<$f";
+    while(<H>) {
+        if (/^#define +([^ \n]*)/) {
+            push @syms, $1;
+        }
+    }
+    close H;
+}
+
+
+opendir(my $dh, $incdir) || die "Can't opendir: $!";
+my @hfiles = grep { /\.h$/ } readdir($dh);
+closedir $dh;
+
+for(@hfiles) {
+    scanheader("$incdir/$_");
+}
+
+my $errors = 0;
+for my $s (@syms) {
+    if($s !~ /^(lib|)curl/i) {
+        print "Bad symbols in public header files:\n" if(!$errors);
+        $errors++;
+        print "  $s\n";
+    }
+}
+if($errors) {
+    exit 1;
+}
+printf "%d fine symbols found\n", scalar(@syms);
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 3e26bcdc7..651f21643 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -59,7 +59,7 @@ test316 test317 test318 test319 test320 test321 test322 
test323 test324 \
 test325 test326 test327 test328 test329 test330 test331 test332 test333 \
 test334 test335 test336 test337 test338 test339 test340 test341 test342 \
 test343 \
-test350 test351 test352 test353 test354 test355 test356 \
+test350 test351 test352 test353 test354 test355 test356 test357 \
 test393 test394 test395 \
 \
 test400 test401 test402 test403 test404 test405 test406 test407 test408 \
@@ -85,7 +85,8 @@ test626 test627 test628 test629 test630 test631 test632 
test633 test634 \
 test635 test636 test637 test638 test639 test640 test641 test642 \
 test643 test644 test645 test646 test647 test648 test649 test650 test651 \
 test652 test653 test654 test655 test656 test658 test659 test660 test661 \
-test662 test663 \
+test662 test663 test664 test665 test666 test667 test668 \
+test670 test671 test672 test673 \
 \
 test700 test701 test702 test703 test704 test705 test706 test707 test708 \
 test709 test710 test711 test712 test713 test714 test715 test716 test717 \
@@ -96,12 +97,11 @@ test818 test819 test820 test821 test822 test823 test824 
test825 test826 \
 test827 test828 test829 test830 test831 test832 test833 test834 test835 \
 test836 test837 test838 test839 test840 test841 test842 test843 test844 \
 test845 test846 test847 test848 test849 \
-\
 test850 test851 test852 test853 test854 test855 test856 test857 test858 \
 test859 test860 test861 test862 test863 test864 test865 test866 test867 \
 test868 test869 test870 test871 test872 test873 test874 test875 test876 \
 test877 test878 test879 test880 test881 test882 test883 test884 test885 \
-test886 test887 test888 test889 test890 test891 test892 test893 \
+test886 test887 test888 test889 test890 test891 test892 test893 test894 \
 \
 test900 test901 test902 test903 test904 test905 test906 test907 test908 \
 test909 test910 test911 test912 test913 test914 test915 test916 test917 \
@@ -109,7 +109,8 @@ test918 test919 test920 test921 test922 test923 test924 
test925 test926 \
 test927 test928 test929 test930 test931 test932 test933 test934 test935 \
 test936 test937 test938 test939 test940 test941 test942 test943 test944 \
 test945 test946 test947 test948 test949 test950 test951 test952 test953 \
-test954 \
+test954 test955 test956 test957 test958 test959 test960 test961 test962 \
+test963 test964 test965 test966 test967 test968 test969 \
 \
 test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
 test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
@@ -131,8 +132,9 @@ test1128 test1129 test1130 test1131 test1132 test1133 
test1134 test1135 \
 test1136 test1137 test1138                   test1141 test1142 test1143 \
 test1144 test1145 test1146 test1147 test1148 test1149 test1150 test1151 \
 test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 \
-test1160 test1161 test1162 test1163 test1164 test1165 test1166 \
-test1170 test1171 test1172 test1173 test1174 test1175 \
+test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 \
+\
+test1170 test1171 test1172 test1173 test1174 test1175 test1176 \
 \
 test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
 test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
@@ -169,7 +171,7 @@ test1424 test1425 test1426 test1427 \
 test1428 test1429 test1430 test1431 test1432 test1433 test1434 test1435 \
 test1436 test1437 test1438 test1439 test1440 test1441 test1442 test1443 \
 test1444 test1445 test1446 test1447 test1448 test1449 test1450 test1451 \
-test1452 test1453 test1454 test1455 test1456 test1457 test1458\
+test1452 test1453 test1454 test1455 test1456 test1457 test1458 test1459 \
 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
 test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \
 test1516 test1517 test1518 test1519 test1520 test1521 test1522 test1523 \
@@ -183,7 +185,9 @@ test1558 test1559 test1560 test1561 test1562 test1563 
test1564 test1565 \
 test1590 test1591 test1592 test1593 test1594 test1595 test1596 \
 \
 test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 \
-test1608 test1609 test1620 test1621 \
+test1608 test1609 test1610 test1611 test1612 \
+\
+test1620 test1621 \
 \
 test1650 test1651 test1652 test1653 test1654 test1655 \
 \
@@ -192,6 +196,7 @@ test1700 test1701 test1702 \
 test1800 test1801 \
 \
 test1900 test1901 test1902 test1903 test1904 test1905 test1906 test1907 \
+test1908 \
 \
 test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
 test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \
@@ -207,4 +212,5 @@ test2078 \
 test2080 \
 test2100 \
 \
-test3000 test3001
+test3000 test3001 \
+test3002 test3003 test3004 test3005 test3006 test3007
diff --git a/tests/data/test1070 b/tests/data/test1070
index d202a9c07..81b473de4 100644
--- a/tests/data/test1070
+++ b/tests/data/test1070
@@ -32,7 +32,7 @@ http
 HTTP POST with server closing connection before (all) data is received
  </name>
  <command>
- -d @log/input1070 http://%HOSTIP:%HTTPPORT/1070
+ -d @log/input1070 http://%HOSTIP:%HTTPPORT/1070 -H "Expect: 100-continue"
 </command>
 <file name="log/input1070">
 This creates the named file with this content before the test case is run,
@@ -55,9 +55,9 @@ 
OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
 POST /1070 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
+Expect: 100-continue
 Content-Length: 2313
 Content-Type: application/x-www-form-urlencoded
-Expect: 100-continue
 
 This creates 
 </protocol>
diff --git a/tests/data/test1129 b/tests/data/test1129
index f47141cd3..cc5236733 100644
--- a/tests/data/test1129
+++ b/tests/data/test1129
@@ -33,16 +33,16 @@ Content-Type: text/html
 # we use skip to make the test server never read the full payload off
 # the socket and instead return the response at once 
 <servercmd>
-skip: 1025
+skip: 1053700
 </servercmd>
 </reply>
 
 #
 # Client-side
 <client>
-# 1025 x 'x'
+# 1053700 x 'x'
 <file name="log/file1129">
-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 [...]
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 [...]
 </file>
 <server>
 http
@@ -81,14 +81,14 @@ Content-Type: text/html
 POST /1129 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 1025
+Content-Length: 1053700
 Content-Type: application/x-www-form-urlencoded
 Expect: 100-continue
 
 POST /11290001 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 1025
+Content-Length: 1053700
 Content-Type: application/x-www-form-urlencoded
 Expect: 100-continue
 
diff --git a/tests/data/test1133 b/tests/data/test1133
index 737f9d9e2..738e80614 100644
--- a/tests/data/test1133
+++ b/tests/data/test1133
@@ -48,7 +48,6 @@ User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 
OpenSSL/0.9.7a ipv6 z
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 1264
-Expect: 100-continue
 Content-Type: multipart/form-data; 
boundary=----------------------------24e78000bd32
 
 ------------------------------24e78000bd32
diff --git a/tests/data/test1395 b/tests/data/test1167
similarity index 50%
copy from tests/data/test1395
copy to tests/data/test1167
index 967c8d492..9eebe1c4e 100644
--- a/tests/data/test1395
+++ b/tests/data/test1167
@@ -1,7 +1,7 @@
 <testcase>
 <info>
 <keywords>
-unittest
+source analysis
 </keywords>
 </info>
 
@@ -11,16 +11,14 @@ unittest
 <server>
 none
 </server>
-<features>
-unittest
-</features>
+
  <name>
-Curl_dedotdotify
+Verify curl prefix of public symbols in header files
  </name>
-<tool>
-unit1395
-</tool>
 
+<command type="perl">
+%SRCDIR/badsymbols.pl %SRCDIR/..
+</command>
 </client>
 
 </testcase>
diff --git a/tests/data/test490 b/tests/data/test1176
similarity index 57%
copy from tests/data/test490
copy to tests/data/test1176
index a3383a9d1..491bee16f 100644
--- a/tests/data/test490
+++ b/tests/data/test1176
@@ -1,15 +1,14 @@
 <testcase>
 <info>
 <keywords>
-HTTP
-HTTP PUT
+globbing
 </keywords>
 </info>
 
 #
 # Server-side
 <reply>
-<data>
+<data nocheck="yes">
 HTTP/1.1 200 OK
 Date: Thu, 09 Nov 2010 14:49:00 GMT
 Server: test-server/fake
@@ -32,14 +31,11 @@ Funny-head: yesyes
 http
 </server>
  <name>
-Two globbed HTTP PUTs
+HTTP GET
  </name>
- <command>
-http://%HOSTIP:%HTTPPORT/490 -T '{log/in490,log/in490}'
+ <command option="no-output">
+http://%HOSTIP:%HTTPPORT/1176 -o 'log/base-#0'
 </command>
-<file name="log/in490">
-surprise!
-</file>
 </client>
 
 #
@@ -49,20 +45,24 @@ surprise!
 ^User-Agent:.*
 </strip>
 <protocol>
-PUT /490 HTTP/1.1
-Host: 127.0.0.1:8990
-Accept: */*
-Content-Length: 10
-Expect: 100-continue
-
-surprise!
-PUT /490 HTTP/1.1
-Host: 127.0.0.1:8990
+GET /1176 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 10
-Expect: 100-continue
 
-surprise!
 </protocol>
+<file name="log/base-#0">
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</file>
 </verify>
 </testcase>
diff --git a/tests/data/test1293 b/tests/data/test1293
index 11a28a326..e2143d103 100644
--- a/tests/data/test1293
+++ b/tests/data/test1293
@@ -52,7 +52,7 @@ 
s/boundary=------------------------[a-z0-9]*/boundary=--------------------------
 </strippart>
 <protocol>
 POST /1293 HTTP/1.1
-Host: 127.0.0.1:8990
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 126
 Content-Type: multipart/form-data; boundary=----------------------------
diff --git a/tests/data/test1300 b/tests/data/test1300
index 100888561..118341213 100644
--- a/tests/data/test1300
+++ b/tests/data/test1300
@@ -18,9 +18,5 @@ unittest
  <name>
 llist unit tests
  </name>
-<tool>
-unit1300
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1301 b/tests/data/test1301
index 8506c0005..5aea24b65 100644
--- a/tests/data/test1301
+++ b/tests/data/test1301
@@ -18,9 +18,5 @@ unittest
  <name>
 curl_strcasecompare unit tests
  </name>
-<tool>
-unit1301
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1302 b/tests/data/test1302
index 27ea86248..9e9039cac 100644
--- a/tests/data/test1302
+++ b/tests/data/test1302
@@ -18,9 +18,5 @@ unittest
  <name>
 base64 encode/decode unit tests
  </name>
-<tool>
-unit1302
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1303 b/tests/data/test1303
index 925b47e15..bb23352df 100644
--- a/tests/data/test1303
+++ b/tests/data/test1303
@@ -18,9 +18,5 @@ unittest
  <name>
 Curl_timeleft unit tests
  </name>
-<tool>
-unit1303
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1304 b/tests/data/test1304
index d518de9e4..b402bfc8b 100644
--- a/tests/data/test1304
+++ b/tests/data/test1304
@@ -18,13 +18,9 @@ unittest
  <name>
 netrc parsing unit tests
  </name>
-<tool>
-unit1304
-</tool>
 <file name="log/netrc1304">
 machine example.com login admin password passwd
 machine curl.example.com login none password none
 </file>
 </client>
-
 </testcase>
diff --git a/tests/data/test1305 b/tests/data/test1305
index 91149b3ad..52efbcbb0 100644
--- a/tests/data/test1305
+++ b/tests/data/test1305
@@ -19,12 +19,8 @@ unittest
  <name>
 internal hash create/destroy testing
  </name>
-<tool>
-unit1305
-</tool>
 <command>
 1305
 </command>
 </client>
-
 </testcase>
diff --git a/tests/data/test1307 b/tests/data/test1307
index c4f7ac729..f0e96bfa0 100644
--- a/tests/data/test1307
+++ b/tests/data/test1307
@@ -20,9 +20,5 @@ ftp
  <name>
 internal Curl_fnmatch() testing
  </name>
-<tool>
-unit1307
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1308 b/tests/data/test1308
index 88e9771dd..3755ef8b4 100644
--- a/tests/data/test1308
+++ b/tests/data/test1308
@@ -20,12 +20,8 @@ http
  <name>
 formpost unit tests
  </name>
-<tool>
-unit1308
-</tool>
 <file name="log/test-1308">
 Piece of the file that is to uploaded as a formpost
 </file>
 </client>
-
 </testcase>
diff --git a/tests/data/test1309 b/tests/data/test1309
index 0e0cad1e8..7005d5f13 100644
--- a/tests/data/test1309
+++ b/tests/data/test1309
@@ -18,9 +18,6 @@ unittest
  <name>
 splay unit tests
  </name>
-<tool>
-unit1309
-</tool>
 </client>
 
 <verify>
@@ -1564,5 +1561,4 @@ removed payload 1013[1]
 removed payload 1013[2]
 </stdout>
 </verify>
-
 </testcase>
diff --git a/tests/data/test1323 b/tests/data/test1323
index c5e598cc4..66bac61ff 100644
--- a/tests/data/test1323
+++ b/tests/data/test1323
@@ -17,12 +17,12 @@ curlx_tvdiff
 <server>
 none
 </server>
+<features>
+unittest
+</features>
 <name>
 curlx_tvdiff
 </name>
-<tool>
-unit1323
-</tool>
 </client>
 
 #
diff --git a/tests/data/test1330 b/tests/data/test1330
index a78dc30b8..ce04e3331 100644
--- a/tests/data/test1330
+++ b/tests/data/test1330
@@ -20,11 +20,6 @@ none
 unittest
 TrackMemory
 </features>
-# tool is what to use instead of 'curl'
-<tool>
-unit1330
-</tool>
-
 <name>
 unit tests memory tracking operational
 </name>
@@ -48,5 +43,4 @@ s:^(MEM )(.*/)(.*):$1$3:
 s/\r\n/\n/
 </stripfile>
 </verify>
-
 </testcase>
diff --git a/tests/data/test1394 b/tests/data/test1394
index 34d4a0e37..d3ffb2d33 100644
--- a/tests/data/test1394
+++ b/tests/data/test1394
@@ -17,14 +17,10 @@ unittest
  <name>
 unit test for parse_cert_parameter()
  </name>
-<tool>
-unit1394
-</tool>
 </client>
 
 <verify>
 <stdout mode="text">
 </stdout>
 </verify>
-
 </testcase>
diff --git a/tests/data/test1395 b/tests/data/test1395
index 967c8d492..409e0d631 100644
--- a/tests/data/test1395
+++ b/tests/data/test1395
@@ -17,10 +17,5 @@ unittest
  <name>
 Curl_dedotdotify
  </name>
-<tool>
-unit1395
-</tool>
-
 </client>
-
 </testcase>
diff --git a/tests/data/test1396 b/tests/data/test1396
index 8ffe35f4c..d8b432d8b 100644
--- a/tests/data/test1396
+++ b/tests/data/test1396
@@ -19,9 +19,6 @@ unittest
  <name>
 curl_easy_escape and curl_easy_unescape
  </name>
-<tool>
-unit1396
-</tool>
 </client>
 
 </testcase>
diff --git a/tests/data/test1397 b/tests/data/test1397
index 5f479b468..84f962abe 100644
--- a/tests/data/test1397
+++ b/tests/data/test1397
@@ -19,9 +19,6 @@ unittest
  <name>
 Check wildcard certificate matching function Curl_cert_hostcheck
  </name>
-<tool>
-unit1397
-</tool>
 </client>
 
 </testcase>
diff --git a/tests/data/test1398 b/tests/data/test1398
index dd50baa62..436cac82d 100644
--- a/tests/data/test1398
+++ b/tests/data/test1398
@@ -18,9 +18,6 @@ unittest
  <name>
 curl_msnprintf unit tests
  </name>
-<tool>
-unit1398
-</tool>
 </client>
 
 </testcase>
diff --git a/tests/data/test1399 b/tests/data/test1399
index fe3879df1..6d6ec7a5b 100644
--- a/tests/data/test1399
+++ b/tests/data/test1399
@@ -18,9 +18,5 @@ unittest
  <name>
 Curl_pgrsTime unit tests
  </name>
-<tool>
-unit1399
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1437 b/tests/data/test1437
index 19ccece04..6a48444fb 100644
--- a/tests/data/test1437
+++ b/tests/data/test1437
@@ -75,7 +75,7 @@ Accept: */*
 
 GET /1437 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest username="testuser", realm="testrealm", nonce="2", 
uri="/1437", response="4376eb639bf8e7343a6e7b56e1b89c4f", algorithm="MD5"
+Authorization: Digest username="testuser", realm="testrealm", nonce="2", 
uri="/1437", response="4376eb639bf8e7343a6e7b56e1b89c4f", algorithm=MD5
 User-Agent: curl/7.10.5 (i686-pc-linux-gnu) libcurl/7.10.5 OpenSSL/0.9.7a ipv6 
zlib/1.1.3
 Accept: */*
 
diff --git a/tests/data/test1459 b/tests/data/test1459
new file mode 100644
index 000000000..3e89595e4
--- /dev/null
+++ b/tests/data/test1459
@@ -0,0 +1,46 @@
+<testcase>
+<info>
+<keywords>
+SFTP
+known_hosts
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+sftp
+</server>
+<precheck>
+mkdir -p %PWD/log/test1459.dir/.ssh
+</precheck>
+<features>
+sftp
+</features>
+ <name>
+SFTP with corrupted known_hosts
+ </name>
+ <command>
+-u : sftp://%HOSTIP:%SSHPORT/ -l
+</command>
+<file name="log/test1459.dir/.ssh/known_hosts">
+|1|qy29Y1x/+/F39AzdG5515YSSw+c=|iB2WX5jrU3ZTWc+ZfGau7HHEvBc= ssh-rsa 
AAAAB3NzaC1yc2EAAAABIwAAAIEAynDN8cDJ3xNzRjTNNGciSHSxpubxhZ6YnkLdp1TkrGW8n\
+R93Ey5VtBeBblYTRlFXBWJgKFcTKBRJ/O4qBZwbUgt10AHj31i6h8NehfT19tR8wG/YCmj3KtYLHmwdzmW1edEL9G2NdX2KiKYv7/zuly3QvmP0QA0NhWkAz0KdWNM=
+</file>
+<setenv>
+CURL_HOME=%PWD/log/test1459.dir
+</setenv>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+60
+</errorcode>
+<valgrind>
+disable
+</valgrind>
+</verify>
+</testcase>
+
diff --git a/tests/data/test153 b/tests/data/test153
index 77f7adb01..1f55f39b6 100644
--- a/tests/data/test153
+++ b/tests/data/test153
@@ -115,7 +115,7 @@ Accept: */*
 
 GET /1530002 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest username="testuser", realm="testrealm", nonce="999999", 
uri="/1530002", cnonce="MTA4MzIy", nc="00000001", qop="auth", 
response="25291c357671604a16c0242f56721c07", algorithm="MD5"
+Authorization: Digest username="testuser", realm="testrealm", nonce="999999", 
uri="/1530002", cnonce="MTA4MzIy", nc="00000001", qop="auth", 
response="25291c357671604a16c0242f56721c07", algorithm=MD5
 User-Agent: curl/7.11.0-CVS (i686-pc-linux-gnu) libcurl/7.11.0-CVS 
OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS
 Accept: */*
 
diff --git a/tests/data/test1538 b/tests/data/test1538
index 3b22ebc27..ea8eddbb8 100644
--- a/tests/data/test1538
+++ b/tests/data/test1538
@@ -128,7 +128,8 @@ e92: Stream error in the HTTP/2 framing layer
 e93: API function called from within callback
 e94: An authentication function returned an error
 e95: HTTP/3 error
-e96: Unknown error
+e96: QUIC connection error
+e97: Unknown error
 m-1: Please call curl_multi_perform() soon
 m0: No error
 m1: Invalid multi handle
@@ -140,7 +141,8 @@ m6: Unknown option
 m7: The easy handle is already added to a multi handle
 m8: API function called from within callback
 m9: Wakeup is unavailable or failed
-m10: Unknown error
+m10: A libcurl function was given a bad argument
+m11: Unknown error
 s0: No error
 s1: Unknown share option
 s2: Share currently in use
diff --git a/tests/data/test1600 b/tests/data/test1600
index 88040747a..33413d7c3 100644
--- a/tests/data/test1600
+++ b/tests/data/test1600
@@ -19,9 +19,5 @@ NTLM
  <name>
 NTLM unit tests
  </name>
-<tool>
-unit1600
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1601 b/tests/data/test1601
index 125493bb0..2065fdd1d 100644
--- a/tests/data/test1601
+++ b/tests/data/test1601
@@ -18,9 +18,5 @@ unittest
  <name>
 MD5 unit tests
  </name>
-<tool>
-unit1601
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1602 b/tests/data/test1602
index 4717058ce..56e243ff8 100644
--- a/tests/data/test1602
+++ b/tests/data/test1602
@@ -18,9 +18,5 @@ unittest
  <name>
 Internal hash create/add/destroy testing, exercising clean functions
  </name>
-<tool>
-unit1602
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1603 b/tests/data/test1603
index 805c9e378..406d197ee 100644
--- a/tests/data/test1603
+++ b/tests/data/test1603
@@ -18,9 +18,5 @@ unittest
  <name>
 Internal hash add, retrieval, deletion testing
  </name>
-<tool>
-unit1603
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1604 b/tests/data/test1604
index cf207750d..39daf9ddc 100644
--- a/tests/data/test1604
+++ b/tests/data/test1604
@@ -17,9 +17,5 @@ unittest
  <name>
 Test WIN32/MSDOS filename sanitization
  </name>
-<tool>
-unit1604
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1605 b/tests/data/test1605
index 09ef66942..a123b01a1 100644
--- a/tests/data/test1605
+++ b/tests/data/test1605
@@ -17,9 +17,5 @@ unittest
  <name>
 Test negative data lengths as input to libcurl functions
  </name>
-<tool>
-unit1605
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1606 b/tests/data/test1606
index 15488d407..83e984427 100644
--- a/tests/data/test1606
+++ b/tests/data/test1606
@@ -18,9 +18,5 @@ unittest
  <name>
 verify speedcheck
  </name>
-<tool>
-unit1606
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1607 b/tests/data/test1607
index 9628324e4..6d28d6eb4 100644
--- a/tests/data/test1607
+++ b/tests/data/test1607
@@ -18,9 +18,5 @@ unittest
  <name>
 CURLOPT_RESOLVE parsing
  </name>
-<tool>
-unit1607
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1608 b/tests/data/test1608
index 702310757..fbc623895 100644
--- a/tests/data/test1608
+++ b/tests/data/test1608
@@ -18,9 +18,5 @@ unittest
  <name>
 verify DNS shuffling
  </name>
-<tool>
-unit1608
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1609 b/tests/data/test1609
index c1b7c7a11..6d28d6eb4 100644
--- a/tests/data/test1609
+++ b/tests/data/test1609
@@ -18,9 +18,5 @@ unittest
  <name>
 CURLOPT_RESOLVE parsing
  </name>
-<tool>
-unit1609
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1650 b/tests/data/test1610
similarity index 82%
copy from tests/data/test1650
copy to tests/data/test1610
index 7a02a6dac..fff973371 100644
--- a/tests/data/test1650
+++ b/tests/data/test1610
@@ -2,7 +2,7 @@
 <info>
 <keywords>
 unittest
-DOH
+SHA256
 </keywords>
 </info>
 
@@ -14,14 +14,9 @@ none
 </server>
 <features>
 unittest
-DoH
 </features>
  <name>
-DOH
+SHA256 unit tests
  </name>
-<tool>
-unit1650
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1650 b/tests/data/test1611
similarity index 82%
copy from tests/data/test1650
copy to tests/data/test1611
index 7a02a6dac..008aea7ec 100644
--- a/tests/data/test1650
+++ b/tests/data/test1611
@@ -2,7 +2,7 @@
 <info>
 <keywords>
 unittest
-DOH
+MD4
 </keywords>
 </info>
 
@@ -14,14 +14,9 @@ none
 </server>
 <features>
 unittest
-DoH
 </features>
  <name>
-DOH
+MD4 unit tests
  </name>
-<tool>
-unit1650
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1650 b/tests/data/test1612
similarity index 82%
copy from tests/data/test1650
copy to tests/data/test1612
index 7a02a6dac..3e92b6791 100644
--- a/tests/data/test1650
+++ b/tests/data/test1612
@@ -2,7 +2,7 @@
 <info>
 <keywords>
 unittest
-DOH
+HMAC
 </keywords>
 </info>
 
@@ -14,14 +14,9 @@ none
 </server>
 <features>
 unittest
-DoH
 </features>
  <name>
-DOH
+HMAC unit tests
  </name>
-<tool>
-unit1650
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1620 b/tests/data/test1620
index 83b08c7a8..038bbcc1b 100644
--- a/tests/data/test1620
+++ b/tests/data/test1620
@@ -18,9 +18,5 @@ unittest
  <name>
 unit tests for url.c
  </name>
-<tool>
-unit1620
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1621 b/tests/data/test1621
index 1117d1bd2..62c81052f 100644
--- a/tests/data/test1621
+++ b/tests/data/test1621
@@ -19,9 +19,5 @@ https
  <name>
 unit tests for stripcredentials from URL
  </name>
-<tool>
-unit1621
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1650 b/tests/data/test1650
index 7a02a6dac..6248b9814 100644
--- a/tests/data/test1650
+++ b/tests/data/test1650
@@ -19,9 +19,5 @@ DoH
  <name>
 DOH
  </name>
-<tool>
-unit1650
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1651 b/tests/data/test1651
index 28a9b714c..d29974bf2 100644
--- a/tests/data/test1651
+++ b/tests/data/test1651
@@ -18,9 +18,5 @@ unittest
  <name>
 x509 parsing
  </name>
-<tool>
-unit1651
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1652 b/tests/data/test1652
index c41169019..678d19517 100644
--- a/tests/data/test1652
+++ b/tests/data/test1652
@@ -16,8 +16,5 @@ unittest
 <name>
 infof
 </name>
-<tool>
-unit1652
-</tool>
 </client>
 </testcase>
diff --git a/tests/data/test1653 b/tests/data/test1653
index 0de2c14b5..59ec3f396 100644
--- a/tests/data/test1653
+++ b/tests/data/test1653
@@ -16,8 +16,5 @@ unittest
 <name>
 urlapi
 </name>
-<tool>
-unit1653
-</tool>
 </client>
 </testcase>
diff --git a/tests/data/test1654 b/tests/data/test1654
index 6a82daa08..6155635ab 100644
--- a/tests/data/test1654
+++ b/tests/data/test1654
@@ -26,9 +26,6 @@ alt-svc
 <command>
 log/1654
 </command>
-<tool>
-unit1654
-</tool>
 <file name="log/1654" mode="text">
 h2 example.com 443 h3 shiny.example.com 8443 "20191231 00:00:00" 0 1
 # a comment
diff --git a/tests/data/test1655 b/tests/data/test1655
index 2e73f55d9..e161fb662 100644
--- a/tests/data/test1655
+++ b/tests/data/test1655
@@ -19,9 +19,5 @@ DoH
  <name>
 unit test for doh_encode
  </name>
-<tool>
-unit1655
-</tool>
 </client>
-
 </testcase>
diff --git a/tests/data/test1800 b/tests/data/test1800
index 011018400..c308c99b0 100644
--- a/tests/data/test1800
+++ b/tests/data/test1800
@@ -48,7 +48,7 @@ Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Connection: Upgrade, HTTP2-Settings
 Upgrade: %H2CVER
-HTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA
+HTTP2-Settings: AAMAAABkAAQCAAAAAAIAAAAA
 
 </protocol>
 </verify>
diff --git a/tests/data/test1908 b/tests/data/test1908
new file mode 100644
index 000000000..de34d0ee2
--- /dev/null
+++ b/tests/data/test1908
@@ -0,0 +1,71 @@
+<testcase>
+<info>
+<keywords>
+CURLINFO_EFFECTIVE_URL
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Funny-head: yesyes swsclose
+Content-Length: 0
+alt-svc: h2="3dbbdetxoyw4nsp6c3cc456oj2ays6s43ezxzsfxxri3h5xqd.example:443"; 
ma=315360000; persist=1
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+
+# require debug so that alt-svc can work over plain old HTTP
+<features>
+alt-svc
+debug
+</features>
+<name>
+alt-svc cache save after resetting the handle
+</name>
+<setenv>
+# make debug-curl accept Alt-Svc over plain HTTP
+CURL_ALTSVC_HTTP="yeah"
+</setenv>
+<tool>
+lib1908
+</tool>
+
+<command>
+%HOSTIP:%HTTPPORT/1908
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /1908 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+<stripfile>
+# strip out the (dynamic) expire date from the file so that the rest
+# matches
+s/\"([^\"]*)\"/TIMESTAMP/
+</stripfile>
+<file name="log/altsvc-1908">
+# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html
+# This file was generated by libcurl! Edit at your own risk.
+h1 127.0.0.1 8990 h2 3dbbdetxoyw4nsp6c3cc456oj2ays6s43ezxzsfxxri3h5xqd.example 
443 TIMESTAMP 1 0
+</file>
+</verify>
+</testcase>
diff --git a/tests/data/test2006 b/tests/data/test2006
index 1f5971726..0b84937ed 100644
--- a/tests/data/test2006
+++ b/tests/data/test2006
@@ -86,6 +86,10 @@ Accept: */*
 Some data delivered from an HTTP resource
 </file1>
 <file2 name="log/heads2006">
+Content-Length: 496
+Accept-ranges: bytes
+
+
 HTTP/1.1 200 OK
 Date: Thu, 21 Jun 2012 14:49:01 GMT
 Server: test-server/fake
diff --git a/tests/data/test2007 b/tests/data/test2007
index a8e5f1b45..c8c023efb 100644
--- a/tests/data/test2007
+++ b/tests/data/test2007
@@ -90,6 +90,10 @@ Something delivered from an HTTP resource
 s/Last-Modified:.*//
 </stripfile2>
 <file2 name="log/heads2007">
+Content-Length: 496
+Accept-ranges: bytes
+
+
 HTTP/1.1 200 OK
 Date: Thu, 21 Jun 2012 14:50:02 GMT
 Server: test-server/fake
diff --git a/tests/data/test2008 b/tests/data/test2008
index 1a0033285..570cdba7d 100644
--- a/tests/data/test2008
+++ b/tests/data/test2008
@@ -82,6 +82,10 @@ Some stuff delivered from an HTTP resource
 s/Last-Modified:.*//
 </stripfile2>
 <file2 name="log/heads2008">
+Content-Length: 496
+Accept-ranges: bytes
+
+
 HTTP/1.1 200 OK
 Date: Thu, 21 Jun 2012 15:23:48 GMT
 Server: test-server/fake
diff --git a/tests/data/test2009 b/tests/data/test2009
index 08308d03e..10f95df4c 100644
--- a/tests/data/test2009
+++ b/tests/data/test2009
@@ -83,6 +83,10 @@ Some contents delivered from an HTTP resource
 s/Last-Modified:.*//
 </stripfile2>
 <file2 name="log/heads2009">
+Content-Length: 496
+Accept-ranges: bytes
+
+
 HTTP/1.1 200 OK
 Date: Thu, 21 Jun 2012 16:27:17 GMT
 Server: test-server/fake
diff --git a/tests/data/test2010 b/tests/data/test2010
index 068c481b5..d43f4f1e1 100644
--- a/tests/data/test2010
+++ b/tests/data/test2010
@@ -82,6 +82,10 @@ Contents delivered from an HTTP resource
 s/Last-Modified:.*//
 </stripfile2>
 <file2 name="log/heads2010">
+Content-Length: 496
+Accept-ranges: bytes
+
+
 HTTP/1.1 200 OK
 Date: Thu, 21 Jun 2012 17:37:27 GMT
 Server: test-server/fake
diff --git a/tests/data/test2033 b/tests/data/test2033
index 5293b66e8..0b33ccaac 100644
--- a/tests/data/test2033
+++ b/tests/data/test2033
@@ -101,22 +101,22 @@ chkhostname curlhost
 </strip>
 <protocol>
 GET /20320100 HTTP/1.1
-Host: 127.0.0.1:%HTTPPORT
+Host: %HOSTIP:%HTTPPORT
 Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
 Accept: */*
 
 GET /20320100 HTTP/1.1
-Host: 127.0.0.1:%HTTPPORT
+Host: %HOSTIP:%HTTPPORT
 Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
 Accept: */*
 
 GET /20320200 HTTP/1.1
-Host: 127.0.0.1:%HTTPPORT
+Host: %HOSTIP:%HTTPPORT
 Authorization: NTLM TlRMTVNTUAABAAAABoIIAAAAAAAAAAAAAAAAAAAAAAA=
 Accept: */*
 
 GET /20320200 HTTP/1.1
-Host: 127.0.0.1:%HTTPPORT
+Host: %HOSTIP:%HTTPPORT
 Authorization: NTLM 
TlRMTVNTUAADAAAAGAAYAEAAAAAYABgAWAAAAAAAAABwAAAACAAIAHAAAAAIAAgAeAAAAAAAAAAAAAAAhoABAI+/Fp9IERAQ74OsdNPbBpg7o8CVwLSO4DtFyIcZHUMKVktWIu92s2892OVpd2JzqnRlc3R1c2VyY3VybGhvc3Q=
 Accept: */*
 
diff --git a/tests/data/test2058 b/tests/data/test2058
index 65a907f43..613dff001 100644
--- a/tests/data/test2058
+++ b/tests/data/test2058
@@ -95,7 +95,7 @@ Content-Length: 0
 
 GET http://%HOSTIP:%HTTPPORT/2058 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", 
uri="/2058", 
response="fbed69f9f3fd304c8f1acb1a43eb32688b933c0e28055c16b926cbcec070aeed", 
algorithm="SHA-256"
+Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", 
uri="/2058", 
response="fbed69f9f3fd304c8f1acb1a43eb32688b933c0e28055c16b926cbcec070aeed", 
algorithm=SHA-256
 Content-Range: bytes 2-4/5
 Accept: */*
 Proxy-Connection: Keep-Alive
diff --git a/tests/data/test2059 b/tests/data/test2059
index 4272a7b41..15799ae07 100644
--- a/tests/data/test2059
+++ b/tests/data/test2059
@@ -95,7 +95,7 @@ Content-Length: 0
 
 GET http://%HOSTIP:%HTTPPORT/2059 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest 
username="fddc3bc7b753b73ab0848fd83cb20cbbca971258eb8d20c941dd5e0b010d66be", 
realm="testrealm", nonce="1053604144", uri="/2059", 
response="fc09be8192851e284e73e8b719b32a2f6f91cca0594e68713da8c49dc2c1656e", 
algorithm="SHA-512-256", userhash=true
+Authorization: Digest 
username="fddc3bc7b753b73ab0848fd83cb20cbbca971258eb8d20c941dd5e0b010d66be", 
realm="testrealm", nonce="1053604144", uri="/2059", 
response="fc09be8192851e284e73e8b719b32a2f6f91cca0594e68713da8c49dc2c1656e", 
algorithm=SHA-512-256, userhash=true
 Content-Range: bytes 2-4/5
 Accept: */*
 Proxy-Connection: Keep-Alive
diff --git a/tests/data/test2060 b/tests/data/test2060
index a0b291dc2..05ce35103 100644
--- a/tests/data/test2060
+++ b/tests/data/test2060
@@ -95,7 +95,7 @@ Content-Length: 0
 
 GET http://%HOSTIP:%HTTPPORT/2060 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", 
uri="/2060", 
response="3ce1e25ffa611bdbe90e2ab367b9602fa223db9f6de76ac667f0d6157e2178a6", 
algorithm="SHA-512-256"
+Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", 
uri="/2060", 
response="3ce1e25ffa611bdbe90e2ab367b9602fa223db9f6de76ac667f0d6157e2178a6", 
algorithm=SHA-512-256
 Content-Range: bytes 2-4/5
 Accept: */*
 Proxy-Connection: Keep-Alive
diff --git a/tests/data/test2061 b/tests/data/test2061
index af3758c97..bee88e34a 100644
--- a/tests/data/test2061
+++ b/tests/data/test2061
@@ -75,7 +75,7 @@ Accept: */*
 
 GET /2061 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest username="testuser", realm="testrealm", 
nonce="1053604145", uri="/2061", 
response="9dc55255f1a2537b838311674b621d45346b862a81631bb20e4ce356ef25062d", 
algorithm="SHA-256"
+Authorization: Digest username="testuser", realm="testrealm", 
nonce="1053604145", uri="/2061", 
response="9dc55255f1a2537b838311674b621d45346b862a81631bb20e4ce356ef25062d", 
algorithm=SHA-256
 User-Agent: curl/7.10.5 (i686-pc-linux-gnu) libcurl/7.10.5 OpenSSL/0.9.7a ipv6 
zlib/1.1.3
 Accept: */*
 
diff --git a/tests/data/test2062 b/tests/data/test2062
index d5ce6899f..f6d4aff24 100644
--- a/tests/data/test2062
+++ b/tests/data/test2062
@@ -75,7 +75,7 @@ Accept: */*
 
 GET /2062 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest username="testuser", realm="testrealm", 
nonce="1053604145", uri="/2062", 
response="2af735ec3508f4dff99248ffbbe9de9002bfd7cc770cfa2b026cb334042a54e3", 
algorithm="SHA-512-256"
+Authorization: Digest username="testuser", realm="testrealm", 
nonce="1053604145", uri="/2062", 
response="2af735ec3508f4dff99248ffbbe9de9002bfd7cc770cfa2b026cb334042a54e3", 
algorithm=SHA-512-256
 User-Agent: curl/7.10.5 (i686-pc-linux-gnu) libcurl/7.10.5 OpenSSL/0.9.7a ipv6 
zlib/1.1.3
 Accept: */*
 
diff --git a/tests/data/test2063 b/tests/data/test2063
index 220fe4ebe..af9a9f0aa 100644
--- a/tests/data/test2063
+++ b/tests/data/test2063
@@ -75,7 +75,7 @@ Accept: */*
 
 GET /2063 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest 
username="75af8a3500f771e58a52093a25e7905d6e428a511285c12ea1420c73078dfd61", 
realm="testrealm", nonce="1053604145", uri="/2063", 
response="43f7ab531dff687b5dc75617daa59d1fd67d648341d6d2655ca65ef5064cfb51", 
algorithm="SHA-512-256", userhash=true
+Authorization: Digest 
username="75af8a3500f771e58a52093a25e7905d6e428a511285c12ea1420c73078dfd61", 
realm="testrealm", nonce="1053604145", uri="/2063", 
response="43f7ab531dff687b5dc75617daa59d1fd67d648341d6d2655ca65ef5064cfb51", 
algorithm=SHA-512-256, userhash=true
 User-Agent: curl/7.10.5 (i686-pc-linux-gnu) libcurl/7.10.5 OpenSSL/0.9.7a ipv6 
zlib/1.1.3
 Accept: */*
 
diff --git a/tests/data/test2064 b/tests/data/test2064
index aa20c0bc0..bfaaa05e8 100644
--- a/tests/data/test2064
+++ b/tests/data/test2064
@@ -75,7 +75,7 @@ Accept: */*
 
 GET /2064 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest username="testuser", realm="testrealm", 
nonce="2053604145", uri="/2064", 
response="a9c3ec1036068b336cbabefe9dfcad52ee8b89bc7c91ddbb5bb415c6acdf38a5", 
algorithm="SHA-256"
+Authorization: Digest username="testuser", realm="testrealm", 
nonce="2053604145", uri="/2064", 
response="a9c3ec1036068b336cbabefe9dfcad52ee8b89bc7c91ddbb5bb415c6acdf38a5", 
algorithm=SHA-256
 User-Agent: curl/7.10.5 (i686-pc-linux-gnu) libcurl/7.10.5 OpenSSL/0.9.7a ipv6 
zlib/1.1.3
 Accept: */*
 
diff --git a/tests/data/test2065 b/tests/data/test2065
index d3afe0b13..d18b008ad 100644
--- a/tests/data/test2065
+++ b/tests/data/test2065
@@ -75,7 +75,7 @@ Accept: */*
 
 GET /2065 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest username="testuser", realm="testrealm", 
nonce="2053604145", uri="/2065", 
response="5a5f20b0e601aeddc6f96422c2332d49ff431c49ab143b5f836ef76e9ac78f5e", 
algorithm="SHA-512-256"
+Authorization: Digest username="testuser", realm="testrealm", 
nonce="2053604145", uri="/2065", 
response="5a5f20b0e601aeddc6f96422c2332d49ff431c49ab143b5f836ef76e9ac78f5e", 
algorithm=SHA-512-256
 User-Agent: curl/7.10.5 (i686-pc-linux-gnu) libcurl/7.10.5 OpenSSL/0.9.7a ipv6 
zlib/1.1.3
 Accept: */*
 
diff --git a/tests/data/test2066 b/tests/data/test2066
index e6ec28a1e..b6effee0e 100644
--- a/tests/data/test2066
+++ b/tests/data/test2066
@@ -75,7 +75,7 @@ Accept: */*
 
 GET /2066 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest 
username="75af8a3500f771e58a52093a25e7905d6e428a511285c12ea1420c73078dfd61", 
realm="testrealm", nonce="2053604145", uri="/2066", 
response="a2e2ae589f575fb132991d6f550ef14bf7ef697d2fef1242d2498f07eafc77dc", 
algorithm="SHA-512-256", userhash=true
+Authorization: Digest 
username="75af8a3500f771e58a52093a25e7905d6e428a511285c12ea1420c73078dfd61", 
realm="testrealm", nonce="2053604145", uri="/2066", 
response="a2e2ae589f575fb132991d6f550ef14bf7ef697d2fef1242d2498f07eafc77dc", 
algorithm=SHA-512-256, userhash=true
 User-Agent: curl/7.10.5 (i686-pc-linux-gnu) libcurl/7.10.5 OpenSSL/0.9.7a ipv6 
zlib/1.1.3
 Accept: */*
 
diff --git a/tests/data/test2067 b/tests/data/test2067
index faa7c57fa..c203343e6 100644
--- a/tests/data/test2067
+++ b/tests/data/test2067
@@ -78,7 +78,7 @@ Content-Type: application/x-www-form-urlencoded
 
 POST /2067 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", 
uri="/2067", 
response="67b97af219c92fa7e8685e5bebb8e74892f6c6792e911c52bd2dfbf0b49272eb", 
algorithm="SHA-256"
+Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", 
uri="/2067", 
response="67b97af219c92fa7e8685e5bebb8e74892f6c6792e911c52bd2dfbf0b49272eb", 
algorithm=SHA-256
 Accept: */*
 Content-Length: 11
 Content-Type: application/x-www-form-urlencoded
diff --git a/tests/data/test2068 b/tests/data/test2068
index 43a50e626..5a197ce27 100644
--- a/tests/data/test2068
+++ b/tests/data/test2068
@@ -78,7 +78,7 @@ Content-Type: application/x-www-form-urlencoded
 
 POST /2068 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", 
uri="/2068", 
response="4bc9c97a72f1856bcec9b0e1518c6b7ee28773f91357d56840bdc30bd89ca68f", 
algorithm="SHA-512-256"
+Authorization: Digest username="auser", realm="testrealm", nonce="1053604144", 
uri="/2068", 
response="4bc9c97a72f1856bcec9b0e1518c6b7ee28773f91357d56840bdc30bd89ca68f", 
algorithm=SHA-512-256
 Accept: */*
 Content-Length: 11
 Content-Type: application/x-www-form-urlencoded
diff --git a/tests/data/test2069 b/tests/data/test2069
index e8040a5e0..99fd71d0e 100644
--- a/tests/data/test2069
+++ b/tests/data/test2069
@@ -78,7 +78,7 @@ Content-Type: application/x-www-form-urlencoded
 
 POST /2069 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
-Authorization: Digest 
username="fddc3bc7b753b73ab0848fd83cb20cbbca971258eb8d20c941dd5e0b010d66be", 
realm="testrealm", nonce="1053604144", uri="/2069", 
response="ff13d977110a471f30de75e747976e4de78d7a3d2425cd23ff46e67f4bc9ead7", 
algorithm="SHA-512-256", userhash=true
+Authorization: Digest 
username="fddc3bc7b753b73ab0848fd83cb20cbbca971258eb8d20c941dd5e0b010d66be", 
realm="testrealm", nonce="1053604144", uri="/2069", 
response="ff13d977110a471f30de75e747976e4de78d7a3d2425cd23ff46e67f4bc9ead7", 
algorithm=SHA-512-256, userhash=true
 Accept: */*
 Content-Length: 11
 Content-Type: application/x-www-form-urlencoded
diff --git a/tests/data/test2078 b/tests/data/test2078
index 99bc2dbee..51ace296a 100644
--- a/tests/data/test2078
+++ b/tests/data/test2078
@@ -43,7 +43,7 @@ http://%HOSTIP:%HTTPPORT/2078 -u : --negotiate --data 
name=value
 </strip>
 <protocol nonewline="yes">
 POST /2078 HTTP/1.1
-Host: 127.0.0.1:8990
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 10
 Content-Type: application/x-www-form-urlencoded
diff --git a/tests/data/test2100 b/tests/data/test2100
index 6dce69b64..0deedbd74 100644
Binary files a/tests/data/test2100 and b/tests/data/test2100 differ
diff --git a/tests/data/test3002 b/tests/data/test3002
new file mode 100644
index 000000000..ac6820214
--- /dev/null
+++ b/tests/data/test3002
@@ -0,0 +1,55 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+ <name>
+SMTP with multiple and invalid (first) --mail-rcpt and --mail-rcpt-allowfails
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/3002 --mail-rcpt-allowfails --mail-rcpt invalid.one 
--mail-rcpt address@hidden --mail-rcpt address@hidden --mail-rcpt 
address@hidden --mail-rcpt address@hidden --mail-from address@hidden -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO 3002
+MAIL FROM:<address@hidden>
+RCPT TO:<invalid.one>
+RCPT TO:<address@hidden>
+RCPT TO:<address@hidden>
+RCPT TO:<address@hidden>
+RCPT TO:<address@hidden>
+DATA
+QUIT
+</protocol>
+<upload>
+From: different
+To: another
+
+body
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test3003 b/tests/data/test3003
new file mode 100644
index 000000000..7515affbc
--- /dev/null
+++ b/tests/data/test3003
@@ -0,0 +1,55 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+ <name>
+SMTP with multiple and invalid (last) --mail-rcpt and --mail-rcpt-allowfails
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/3003 --mail-rcpt-allowfails --mail-rcpt 
address@hidden --mail-rcpt address@hidden --mail-rcpt address@hidden 
--mail-rcpt address@hidden --mail-rcpt invalid.five --mail-from address@hidden 
-T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO 3003
+MAIL FROM:<address@hidden>
+RCPT TO:<address@hidden>
+RCPT TO:<address@hidden>
+RCPT TO:<address@hidden>
+RCPT TO:<address@hidden>
+RCPT TO:<invalid.five>
+DATA
+QUIT
+</protocol>
+<upload>
+From: different
+To: another
+
+body
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test3004 b/tests/data/test3004
new file mode 100644
index 000000000..e021cde41
--- /dev/null
+++ b/tests/data/test3004
@@ -0,0 +1,55 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+ <name>
+SMTP with multiple and invalid (middle) --mail-rcpt and --mail-rcpt-allowfails
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/3004 --mail-rcpt-allowfails --mail-rcpt 
address@hidden --mail-rcpt address@hidden --mail-rcpt invalid.three --mail-rcpt 
address@hidden --mail-rcpt address@hidden --mail-from address@hidden -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO 3004
+MAIL FROM:<address@hidden>
+RCPT TO:<address@hidden>
+RCPT TO:<address@hidden>
+RCPT TO:<invalid.three>
+RCPT TO:<address@hidden>
+RCPT TO:<address@hidden>
+DATA
+QUIT
+</protocol>
+<upload>
+From: different
+To: another
+
+body
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test3005 b/tests/data/test3005
new file mode 100644
index 000000000..256555ac9
--- /dev/null
+++ b/tests/data/test3005
@@ -0,0 +1,55 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+ <name>
+SMTP with multiple and invalid (all but one) --mail-rcpt and 
--mail-rcpt-allowfails
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/3005 --mail-rcpt-allowfails --mail-rcpt invalid.one 
--mail-rcpt address@hidden --mail-rcpt invalid.three --mail-rcpt invalid.four 
--mail-rcpt invalid.five --mail-from address@hidden -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO 3005
+MAIL FROM:<address@hidden>
+RCPT TO:<invalid.one>
+RCPT TO:<address@hidden>
+RCPT TO:<invalid.three>
+RCPT TO:<invalid.four>
+RCPT TO:<invalid.five>
+DATA
+QUIT
+</protocol>
+<upload>
+From: different
+To: another
+
+body
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test3006 b/tests/data/test3006
new file mode 100644
index 000000000..f54d71c8d
--- /dev/null
+++ b/tests/data/test3006
@@ -0,0 +1,51 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+ <name>
+SMTP with multiple invalid (all) --mail-rcpt and --mail-rcpt-allowfails
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/3006 --mail-rcpt-allowfails --mail-rcpt invalid.one 
--mail-rcpt invalid.two --mail-rcpt invalid.three --mail-rcpt invalid.four 
--mail-rcpt invalid.five --mail-from address@hidden -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 55 - CURLE_SEND_ERROR
+<errorcode>
+55
+</errorcode>
+<protocol>
+EHLO 3006
+MAIL FROM:<address@hidden>
+RCPT TO:<invalid.one>
+RCPT TO:<invalid.two>
+RCPT TO:<invalid.three>
+RCPT TO:<invalid.four>
+RCPT TO:<invalid.five>
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test3007 b/tests/data/test3007
new file mode 100644
index 000000000..b0d690262
--- /dev/null
+++ b/tests/data/test3007
@@ -0,0 +1,47 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+ <name>
+SMTP with invalid --mail-rcpt and --mail-rcpt-allowfails
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/3007 --mail-rcpt-allowfails --mail-rcpt invalid.one 
--mail-from address@hidden -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 55 - CURLE_SEND_ERROR
+<errorcode>
+55
+</errorcode>
+<protocol>
+EHLO 3007
+MAIL FROM:<address@hidden>
+RCPT TO:<invalid.one>
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test304 b/tests/data/test304
index fedf18ff5..01d3a2d67 100644
--- a/tests/data/test304
+++ b/tests/data/test304
@@ -49,7 +49,6 @@ User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 
OpenSSL/0.9.7a ipv6 z
 Host: %HOSTIP:%HTTPSPORT
 Accept: */*
 Content-Length: 1386
-Expect: 100-continue
 Content-Type: multipart/form-data; 
boundary=----------------------------c3b2ef7f0bb8
 
 ------------------------------c3b2ef7f0bb8
diff --git a/tests/data/test357 b/tests/data/test357
new file mode 100644
index 000000000..d0437c685
--- /dev/null
+++ b/tests/data/test357
@@ -0,0 +1,97 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP PUT
+Expect
+</keywords>
+</info>
+# Server-side
+<reply>
+# 417 means the server didn't like the Expect header
+<data>
+HTTP/1.1 417 OK swsbounce
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+
+</data>
+<data1>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 10
+
+blablabla
+</data1>
+<datacheck>
+HTTP/1.1 417 OK swsbounce
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 10
+
+blablabla
+</datacheck>
+<servercmd>
+no-expect
+</servercmd>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP PUT with Expect: 100-continue and 417 response
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/we/want/357 -T log/test357.txt
+</command>
+<file name="log/test357.txt">
+Weird
+     file
+         to
+   upload
+for
+   testing
+the
+   PUT
+      feature
+</file>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+PUT /we/want/357 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 78
+Expect: 100-continue
+
+PUT /we/want/357 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 78
+
+Weird
+     file
+         to
+   upload
+for
+   testing
+the
+   PUT
+      feature
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test39 b/tests/data/test39
index 1867b6081..3c6c57328 100644
--- a/tests/data/test39
+++ b/tests/data/test39
@@ -48,7 +48,6 @@ User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 
OpenSSL/0.9.7a ipv6 z
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 1184
-Expect: 100-continue
 Content-Type: multipart/form-data; 
boundary=----------------------------24e78000bd32
 
 ------------------------------24e78000bd32
diff --git a/tests/data/test490 b/tests/data/test490
index a3383a9d1..86ebb0112 100644
--- a/tests/data/test490
+++ b/tests/data/test490
@@ -50,14 +50,14 @@ surprise!
 </strip>
 <protocol>
 PUT /490 HTTP/1.1
-Host: 127.0.0.1:8990
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 10
 Expect: 100-continue
 
 surprise!
 PUT /490 HTTP/1.1
-Host: 127.0.0.1:8990
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 10
 Expect: 100-continue
diff --git a/tests/data/test491 b/tests/data/test491
index b49c06ce7..c230dfb78 100644
--- a/tests/data/test491
+++ b/tests/data/test491
@@ -50,7 +50,7 @@ surprise!
 </strip>
 <protocol>
 PUT /491 HTTP/1.1
-Host: 127.0.0.1:8990
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 10
 Expect: 100-continue
diff --git a/tests/data/test492 b/tests/data/test492
index 12edd8bc0..ddb0405ef 100644
--- a/tests/data/test492
+++ b/tests/data/test492
@@ -53,7 +53,7 @@ second 492 contents
 </strip>
 <protocol>
 PUT /one/first492 HTTP/1.1
-Host: 127.0.0.1:8990
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Testno: 492
 Content-Length: 19
@@ -61,7 +61,7 @@ Expect: 100-continue
 
 first 492 contents
 PUT /two/first492 HTTP/1.1
-Host: 127.0.0.1:8990
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Testno: 492
 Content-Length: 19
@@ -69,7 +69,7 @@ Expect: 100-continue
 
 first 492 contents
 PUT /one/second492 HTTP/1.1
-Host: 127.0.0.1:8990
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Testno: 492
 Content-Length: 20
@@ -77,7 +77,7 @@ Expect: 100-continue
 
 second 492 contents
 PUT /two/second492 HTTP/1.1
-Host: 127.0.0.1:8990
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Testno: 492
 Content-Length: 20
diff --git a/tests/data/test552 b/tests/data/test552
index 5d1478bd5..47dd41abb 100644
Binary files a/tests/data/test552 and b/tests/data/test552 differ
diff --git a/tests/data/test558 b/tests/data/test558
index 49ef1c70b..dccb8080a 100644
--- a/tests/data/test558
+++ b/tests/data/test558
@@ -36,8 +36,6 @@ nothing
 # Verify data after the test has been "shot"
 <verify>
 <file name="log/memdump">
-FD hostip6.c: socket()
-FD connect.c: sclose()
 MEM lib558.c: malloc()
 MEM lib558.c: free()
 MEM escape.c: malloc()
diff --git a/tests/data/test643 b/tests/data/test643
index 0eaf22c5f..e8da2b1c4 100644
--- a/tests/data/test643
+++ b/tests/data/test643
@@ -69,18 +69,18 @@ 
s/boundary=------------------------[a-z0-9]*/boundary=--------------------------
 POST /643 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 718
+Content-Length: 640
 Content-Type: multipart/form-data; boundary=----------------------------
 
 ------------------------------
 Content-Disposition: form-data; name="sendfile"; filename="postit2.c"
 
-this is what we post to the silly web server
+dummy
 
 ------------------------------
 Content-Disposition: form-data; name="callbackdata"
 
-this is what we post to the silly web server
+dummy
 
 ------------------------------
 Content-Disposition: form-data; name="filename"
@@ -99,18 +99,18 @@ blah blah
 POST /643 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 732
+Content-Length: 654
 Content-Type: multipart/form-data; boundary=----------------------------
 
 ------------------------------
 Content-Disposition: form-data; name="sendfile alternative"; filename="file 
name 2"
 
-this is what we post to the silly web server
+dummy
 
 ------------------------------
 Content-Disposition: form-data; name="callbackdata"
 
-this is what we post to the silly web server
+dummy
 
 ------------------------------
 Content-Disposition: form-data; name="filename"
diff --git a/tests/data/test644 b/tests/data/test644
index 4c9a501ed..99337ae0f 100644
--- a/tests/data/test644
+++ b/tests/data/test644
@@ -44,12 +44,13 @@ 
s/boundary=------------------------[a-z0-9]*/boundary=--------------------------
 POST /644 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 718
+Content-Length: 640
 Content-Type: multipart/form-data; boundary=----------------------------
 
 ------------------------------
 Content-Disposition: form-data; name="sendfile"; filename="postit2.c"
 
+
 </protocol>
 # CURLE_ABORTED_BY_CALLBACK (42)
 <errorcode>
diff --git a/tests/data/test645 b/tests/data/test645
index 6533944b4..eeb15f994 100644
--- a/tests/data/test645
+++ b/tests/data/test645
@@ -73,16 +73,42 @@ Transfer-Encoding: chunked
 Content-Type: multipart/form-data; boundary=----------------------------
 Expect: 100-continue
 
-2ce
+76
 ------------------------------
 Content-Disposition: form-data; name="sendfile"; filename="postit2.c"
 
-this is what we post to the silly web server
+d
+1
+u
+1
+m
+1
+m
+1
+y
+1
+
+
+65
 
 ------------------------------
 Content-Disposition: form-data; name="callbackdata"
 
-this is what we post to the silly web server
+
+1
+d
+1
+u
+1
+m
+1
+m
+1
+y
+1
+
+
+19a
 
 ------------------------------
 Content-Disposition: form-data; name="filename"
@@ -108,16 +134,42 @@ Transfer-Encoding: chunked
 Content-Type: multipart/form-data; boundary=----------------------------
 Expect: 100-continue
 
-2dc
+84
 ------------------------------
 Content-Disposition: form-data; name="sendfile alternative"; filename="file 
name 2"
 
-this is what we post to the silly web server
+d
+1
+u
+1
+m
+1
+m
+1
+y
+1
+
+
+65
 
 ------------------------------
 Content-Disposition: form-data; name="callbackdata"
 
-this is what we post to the silly web server
+
+1
+d
+1
+u
+1
+m
+1
+m
+1
+y
+1
+
+
+19a
 
 ------------------------------
 Content-Disposition: form-data; name="filename"
diff --git a/tests/data/test650 b/tests/data/test650
index 1a06064c7..03fe43816 100644
--- a/tests/data/test650
+++ b/tests/data/test650
@@ -63,7 +63,7 @@ Transfer-Encoding: chunked
 Content-Type: multipart/form-data; boundary=----------------------------
 Expect: 100-continue
 
-60a
+361
 ------------------------------
 Content-Disposition: form-data; name="fieldname"
 Content-Type: text/plain
@@ -89,12 +89,16 @@ This is data from a file.
 Content-Disposition: attachment; filename="test650.filedata"
 Content-Type: text/whatever
 
+
+a5
 This is data from a file.
 
 ------------------------------
 Content-Disposition: attachment; filename="test650.filedata"
 Content-Type: text/whatever
 
+
+af
 This is data from a file.
 
 --------------------------------
@@ -102,6 +106,8 @@ This is data from a file.
 ------------------------------
 Content-Disposition: form-data; name="filecontents"
 
+
+10f
 This is data from a file.
 
 ------------------------------
@@ -112,8 +118,12 @@ Content-Disposition: form-data; name="formlength"
 Content-Disposition: form-data; name="standardinput"
 Content-Type: application/octet-stream
 
+
+16
  Some data from stdin
 
+30
+
 --------------------------------
 
 0
diff --git a/tests/data/test651 b/tests/data/test651
index ae6409479..dd5736a70 100644
--- a/tests/data/test651
+++ b/tests/data/test651
@@ -61,7 +61,6 @@ Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 17139
 Content-Type: multipart/form-data; boundary=----------------------------
-Expect: 100-continue
 
 ------------------------------
 Content-Disposition: form-data; name="hello"
diff --git a/tests/data/test654 b/tests/data/test654
index 21697e763..9d4bf45a1 100644
--- a/tests/data/test654
+++ b/tests/data/test654
@@ -81,7 +81,7 @@ Transfer-Encoding: chunked
 Content-Type: multipart/form-data; boundary=----------------------------
 Expect: 100-continue
 
-20c
+1af
 ------------------------------
 Content-Disposition: form-data; name="greeting"
 Content-Type: application/X-Greeting
@@ -98,7 +98,21 @@ This is data from a file
 ------------------------------
 Content-Disposition: form-data
 
-this is what we post to the silly web server
+
+1
+d
+1
+u
+1
+m
+1
+m
+1
+y
+1
+
+
+30
 
 --------------------------------
 
diff --git a/tests/data/test664 b/tests/data/test664
new file mode 100644
index 000000000..cb73b248b
--- /dev/null
+++ b/tests/data/test664
@@ -0,0 +1,44 @@
+<testcase>
+<info>
+<keywords>
+SFTP
+server key check
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+test
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+sftp
+</server>
+ <name>
+SFTP correct host key
+ </name>
+ <command>
+--hostpubmd5 %SSHSRVMD5 --key curl_client_key --pubkey curl_client_key.pub -u 
%USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file664.txt
+</command>
+<file name="log/file664.txt">
+test
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+0
+</errorcode>
+<valgrind>
+disable
+</valgrind>
+</verify>
+</testcase>
diff --git a/tests/data/test665 b/tests/data/test665
new file mode 100644
index 000000000..830adb8f6
--- /dev/null
+++ b/tests/data/test665
@@ -0,0 +1,44 @@
+<testcase>
+<info>
+<keywords>
+SCP
+server key check
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+test
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+scp
+</server>
+ <name>
+SCP correct host key
+ </name>
+ <command>
+--hostpubmd5 %SSHSRVMD5 --key curl_client_key --pubkey curl_client_key.pub -u 
%USER: scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file665.txt
+</command>
+<file name="log/file665.txt">
+test
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+0
+</errorcode>
+<valgrind>
+disable
+</valgrind>
+</verify>
+</testcase>
diff --git a/tests/data/test666 b/tests/data/test666
new file mode 100644
index 000000000..bb60caf6d
--- /dev/null
+++ b/tests/data/test666
@@ -0,0 +1,293 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+HTTP MIME POST
+MIME
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK swsclose
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 3
+
+OK
+</data>
+<datacheck>
+HTTP/1.1 200 OK swsclose
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 3
+
+OK
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+<tool>
+lib666
+</tool>
+
+ <name>
+HTTP mime post with binary-encoded huge data contents
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/666
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+<protocol>
+POST /666 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 17225
+Content-Type: multipart/form-data; boundary=----------------------------
+
+------------------------------
+Content-Disposition: form-data; name="upfile"; filename="myfile.txt"
+Content-Type: text/plain
+Content-Transfer-Encoding: binary
+
+ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX
+ZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW
+YZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV
+XYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU
+WXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRST
+VWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRS
+UVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQR
+TUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ
+STUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP
+RSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNO
+QRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN
+PQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM
+OPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL
+NOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJK
+MNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ
+LMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI
+KLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH
+JKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFG
+IJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF
+HIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDE
+GHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCD
+FGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABC
+EFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB
+DEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZA
+CDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
+BCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY
+ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX
+ZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW
+YZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV
+XYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU
+WXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRST
+VWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRS
+UVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQR
+TUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ
+STUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP
+RSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNO
+QRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN
+PQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM
+OPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL
+NOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJK
+MNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ
+LMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI
+KLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH
+JKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFG
+IJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF
+HIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDE
+GHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCD
+FGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABC
+EFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB
+DEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZA
+CDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
+BCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY
+ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX
+ZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW
+YZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV
+XYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU
+WXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRST
+VWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRS
+UVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQR
+TUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ
+STUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP
+RSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNO
+QRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN
+PQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM
+OPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL
+NOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJK
+MNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ
+LMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI
+KLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH
+JKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFG
+IJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF
+HIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDE
+GHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCD
+FGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABC
+EFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB
+DEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZA
+CDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
+BCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY
+ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX
+ZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW
+YZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV
+XYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU
+WXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRST
+VWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRS
+UVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQR
+TUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ
+STUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP
+RSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNO
+QRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN
+PQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM
+OPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL
+NOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJK
+MNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ
+LMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI
+KLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH
+JKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFG
+IJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF
+HIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDE
+GHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCD
+FGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABC
+EFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB
+DEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZA
+CDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
+BCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY
+ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX
+ZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW
+YZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV
+XYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU
+WXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRST
+VWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRS
+UVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQR
+TUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ
+STUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP
+RSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNO
+QRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN
+PQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM
+OPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL
+NOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJK
+MNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ
+LMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI
+KLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH
+JKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFG
+IJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF
+HIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDE
+GHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCD
+FGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABC
+EFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB
+DEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZA
+CDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
+BCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY
+ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX
+ZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW
+YZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV
+XYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU
+WXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRST
+VWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRS
+UVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQR
+TUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ
+STUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP
+RSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNO
+QRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN
+PQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM
+OPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL
+NOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJK
+MNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ
+LMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI
+KLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH
+JKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFG
+IJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF
+HIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDE
+GHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCD
+FGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABC
+EFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB
+DEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZA
+CDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
+BCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY
+ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX
+ZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW
+YZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV
+XYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU
+WXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRST
+VWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRS
+UVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQR
+TUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ
+STUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP
+RSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNO
+QRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN
+PQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM
+OPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL
+NOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJK
+MNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ
+LMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI
+KLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH
+JKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFG
+IJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF
+HIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDE
+GHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCD
+FGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABC
+EFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB
+DEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZA
+CDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
+BCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY
+ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX
+ZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW
+YZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV
+XYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU
+WXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRST
+VWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRS
+UVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQR
+TUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ
+STUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP
+RSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNO
+QRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN
+PQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM
+OPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL
+NOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJK
+MNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ
+LMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI
+KLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH
+JKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFG
+IJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF
+HIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDE
+GHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCD
+FGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABC
+EFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB
+DEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZA
+CDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
+BCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY
+ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX
+ZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW
+YZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV
+XYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTU
+WXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRST
+VWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRS
+UVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQR
+TUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQ
+STUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP
+RSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNO
+QRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN
+PQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM
+OPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV
+--------------------------------
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test654 b/tests/data/test667
similarity index 62%
copy from tests/data/test654
copy to tests/data/test667
index 21697e763..2a183753b 100644
--- a/tests/data/test654
+++ b/tests/data/test667
@@ -26,13 +26,6 @@ Server: test-server/fake swsclose
 Connection: close
 Content-Type: text/html
 
-hello
-HTTP/1.1 200 OK
-Date: Thu, 09 Nov 2010 14:49:00 GMT
-Server: test-server/fake swsclose
-Connection: close
-Content-Type: text/html
-
 hello
 </datacheck>
 </reply>
@@ -44,18 +37,15 @@ http
 </server>
 # tool is what to use instead of 'curl'
 <tool>
-lib654
+lib667
 </tool>
 
  <name>
-HTTP duplicate easy handle with mime data
+HTTP chunked mimepost using single-byte read callback with encoder
  </name>
  <command>
-http://%HOSTIP:%HTTPPORT/654
+http://%HOSTIP:%HTTPPORT/667
 </command>
-<file name="log/file654.txt">
-This is data from a file
-</file>
 </client>
 
 #
@@ -69,37 +59,23 @@ 
s/boundary=------------------------[a-z0-9]*/boundary=--------------------------
 # boundary string and since 5 of them are in the body contents, we see
 # (5*12) == 60 bytes less
 <protocol>
-POST /654 HTTP/1.1
-Host: %HOSTIP:%HTTPPORT
-Accept: */*
-Content-Length: 0
-
-POST /654 HTTP/1.1
+POST /667 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Transfer-Encoding: chunked
 Content-Type: multipart/form-data; boundary=----------------------------
 Expect: 100-continue
 
-20c
+7f
 ------------------------------
-Content-Disposition: form-data; name="greeting"
-Content-Type: application/X-Greeting
+Content-Disposition: form-data; name="field"
 Content-Transfer-Encoding: base64
-X-Test-Number: 654
-
-aGVsbG8=
-------------------------------
-Content-Disposition: form-data; filename="file654.txt"
-Content-Type: text/plain
-
-This is data from a file
-
-------------------------------
-Content-Disposition: form-data
 
-this is what we post to the silly web server
 
+4
+ZHVt
+34
+bXk=
 --------------------------------
 
 0
diff --git a/tests/data/test654 b/tests/data/test668
similarity index 67%
copy from tests/data/test654
copy to tests/data/test668
index 21697e763..af0a72051 100644
--- a/tests/data/test654
+++ b/tests/data/test668
@@ -26,13 +26,6 @@ Server: test-server/fake swsclose
 Connection: close
 Content-Type: text/html
 
-hello
-HTTP/1.1 200 OK
-Date: Thu, 09 Nov 2010 14:49:00 GMT
-Server: test-server/fake swsclose
-Connection: close
-Content-Type: text/html
-
 hello
 </datacheck>
 </reply>
@@ -44,16 +37,16 @@ http
 </server>
 # tool is what to use instead of 'curl'
 <tool>
-lib654
+lib668
 </tool>
 
  <name>
-HTTP duplicate easy handle with mime data
+HTTP mimepost early end of data detection
  </name>
  <command>
-http://%HOSTIP:%HTTPPORT/654
+http://%HOSTIP:%HTTPPORT/668
 </command>
-<file name="log/file654.txt">
+<file name="log/file668.txt">
 This is data from a file
 </file>
 </client>
@@ -69,36 +62,33 @@ 
s/boundary=------------------------[a-z0-9]*/boundary=--------------------------
 # boundary string and since 5 of them are in the body contents, we see
 # (5*12) == 60 bytes less
 <protocol>
-POST /654 HTTP/1.1
-Host: %HOSTIP:%HTTPPORT
-Accept: */*
-Content-Length: 0
-
-POST /654 HTTP/1.1
+POST /668 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Transfer-Encoding: chunked
 Content-Type: multipart/form-data; boundary=----------------------------
 Expect: 100-continue
 
-20c
+c1
 ------------------------------
-Content-Disposition: form-data; name="greeting"
-Content-Type: application/X-Greeting
-Content-Transfer-Encoding: base64
-X-Test-Number: 654
+Content-Disposition: form-data; name="field1"
 
-aGVsbG8=
+dummy
 ------------------------------
-Content-Disposition: form-data; filename="file654.txt"
-Content-Type: text/plain
+Content-Disposition: form-data; name="field2"
 
-This is data from a file
+
+5
+dummy
+91
 
 ------------------------------
-Content-Disposition: form-data
+Content-Disposition: form-data; name="field3"; filename="file668.txt"
+Content-Type: text/plain
 
-this is what we post to the silly web server
+
+49
+This is data from a file
 
 --------------------------------
 
diff --git a/tests/data/test1293 b/tests/data/test670
similarity index 59%
copy from tests/data/test1293
copy to tests/data/test670
index 11a28a326..19a51a4e0 100644
--- a/tests/data/test1293
+++ b/tests/data/test670
@@ -2,65 +2,70 @@
 <info>
 <keywords>
 HTTP
-HTTP GET
--F
+HTTP POST
+MIME
 </keywords>
 </info>
 
 #
 # Server-side
 <reply>
-<data nocheck="yes">
-HTTP/1.1 200 OK
-Date: Thu, 09 Nov 2010 14:49:00 GMT
-Server: test-server/fake
-Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
-ETag: "21025-dc7-39462498"
-Accept-Ranges: bytes
-Content-Length: 6
-Connection: close
-Content-Type: text/html
-Funny-head: yesyes
-
--foo-
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
 </data>
+<datacheck>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
+</datacheck>
 </reply>
 
-#
 # Client-side
 <client>
 <server>
 http
 </server>
+# tool is what to use instead of 'curl'
+<tool>
+lib670
+</tool>
+
  <name>
-Multipart formpost to two URLs, the first failing
+Request pause from mime read callback: multi
  </name>
  <command>
-http://0 http://%HOSTIP:%HTTPPORT/1293 -F=
+http://%HOSTIP:%HTTPPORT/670
 </command>
 </client>
 
 #
 # Verify data after the test has been "shot"
 <verify>
-<strip>
-^User-Agent:.*
-</strip>
 <strippart>
 s/^--------------------------[a-z0-9]*/------------------------------/
 
s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
 </strippart>
 <protocol>
-POST /1293 HTTP/1.1
-Host: 127.0.0.1:8990
+POST /670 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 126
+Content-Length: 142
 Content-Type: multipart/form-data; boundary=----------------------------
 
 ------------------------------
-Content-Disposition: form-data
-
+Content-Disposition: form-data; name="field"
 
+AB
 --------------------------------
 </protocol>
 </verify>
diff --git a/tests/data/test1293 b/tests/data/test671
similarity index 59%
copy from tests/data/test1293
copy to tests/data/test671
index 11a28a326..eada50a6e 100644
--- a/tests/data/test1293
+++ b/tests/data/test671
@@ -2,65 +2,70 @@
 <info>
 <keywords>
 HTTP
-HTTP GET
--F
+HTTP POST
+MIME
 </keywords>
 </info>
 
 #
 # Server-side
 <reply>
-<data nocheck="yes">
-HTTP/1.1 200 OK
-Date: Thu, 09 Nov 2010 14:49:00 GMT
-Server: test-server/fake
-Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
-ETag: "21025-dc7-39462498"
-Accept-Ranges: bytes
-Content-Length: 6
-Connection: close
-Content-Type: text/html
-Funny-head: yesyes
-
--foo-
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
 </data>
+<datacheck>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
+</datacheck>
 </reply>
 
-#
 # Client-side
 <client>
 <server>
 http
 </server>
+# tool is what to use instead of 'curl'
+<tool>
+lib671
+</tool>
+
  <name>
-Multipart formpost to two URLs, the first failing
+Request pause from mime read callback: easy
  </name>
  <command>
-http://0 http://%HOSTIP:%HTTPPORT/1293 -F=
+http://%HOSTIP:%HTTPPORT/671
 </command>
 </client>
 
 #
 # Verify data after the test has been "shot"
 <verify>
-<strip>
-^User-Agent:.*
-</strip>
 <strippart>
 s/^--------------------------[a-z0-9]*/------------------------------/
 
s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
 </strippart>
 <protocol>
-POST /1293 HTTP/1.1
-Host: 127.0.0.1:8990
+POST /671 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 126
+Content-Length: 142
 Content-Type: multipart/form-data; boundary=----------------------------
 
 ------------------------------
-Content-Disposition: form-data
-
+Content-Disposition: form-data; name="field"
 
+AB
 --------------------------------
 </protocol>
 </verify>
diff --git a/tests/data/test1293 b/tests/data/test672
similarity index 59%
copy from tests/data/test1293
copy to tests/data/test672
index 11a28a326..9c5f24556 100644
--- a/tests/data/test1293
+++ b/tests/data/test672
@@ -2,65 +2,70 @@
 <info>
 <keywords>
 HTTP
-HTTP GET
--F
+HTTP POST
+FORM
 </keywords>
 </info>
 
 #
 # Server-side
 <reply>
-<data nocheck="yes">
-HTTP/1.1 200 OK
-Date: Thu, 09 Nov 2010 14:49:00 GMT
-Server: test-server/fake
-Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
-ETag: "21025-dc7-39462498"
-Accept-Ranges: bytes
-Content-Length: 6
-Connection: close
-Content-Type: text/html
-Funny-head: yesyes
-
--foo-
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
 </data>
+<datacheck>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
+</datacheck>
 </reply>
 
-#
 # Client-side
 <client>
 <server>
 http
 </server>
+# tool is what to use instead of 'curl'
+<tool>
+lib672
+</tool>
+
  <name>
-Multipart formpost to two URLs, the first failing
+Request pause from form read callback: multi
  </name>
  <command>
-http://0 http://%HOSTIP:%HTTPPORT/1293 -F=
+http://%HOSTIP:%HTTPPORT/672
 </command>
 </client>
 
 #
 # Verify data after the test has been "shot"
 <verify>
-<strip>
-^User-Agent:.*
-</strip>
 <strippart>
 s/^--------------------------[a-z0-9]*/------------------------------/
 
s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
 </strippart>
 <protocol>
-POST /1293 HTTP/1.1
-Host: 127.0.0.1:8990
+POST /672 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 126
+Content-Length: 142
 Content-Type: multipart/form-data; boundary=----------------------------
 
 ------------------------------
-Content-Disposition: form-data
-
+Content-Disposition: form-data; name="field"
 
+AB
 --------------------------------
 </protocol>
 </verify>
diff --git a/tests/data/test1293 b/tests/data/test673
similarity index 59%
copy from tests/data/test1293
copy to tests/data/test673
index 11a28a326..efed2727b 100644
--- a/tests/data/test1293
+++ b/tests/data/test673
@@ -2,65 +2,70 @@
 <info>
 <keywords>
 HTTP
-HTTP GET
--F
+HTTP POST
+FORM
 </keywords>
 </info>
 
 #
 # Server-side
 <reply>
-<data nocheck="yes">
-HTTP/1.1 200 OK
-Date: Thu, 09 Nov 2010 14:49:00 GMT
-Server: test-server/fake
-Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
-ETag: "21025-dc7-39462498"
-Accept-Ranges: bytes
-Content-Length: 6
-Connection: close
-Content-Type: text/html
-Funny-head: yesyes
-
--foo-
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
 </data>
+<datacheck>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Connection: close
+Content-Type: text/html
+
+hello
+</datacheck>
 </reply>
 
-#
 # Client-side
 <client>
 <server>
 http
 </server>
+# tool is what to use instead of 'curl'
+<tool>
+lib673
+</tool>
+
  <name>
-Multipart formpost to two URLs, the first failing
+Request pause from form read callback: easy
  </name>
  <command>
-http://0 http://%HOSTIP:%HTTPPORT/1293 -F=
+http://%HOSTIP:%HTTPPORT/673
 </command>
 </client>
 
 #
 # Verify data after the test has been "shot"
 <verify>
-<strip>
-^User-Agent:.*
-</strip>
 <strippart>
 s/^--------------------------[a-z0-9]*/------------------------------/
 
s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
 </strippart>
 <protocol>
-POST /1293 HTTP/1.1
-Host: 127.0.0.1:8990
+POST /673 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 126
+Content-Length: 142
 Content-Type: multipart/form-data; boundary=----------------------------
 
 ------------------------------
-Content-Disposition: form-data
-
+Content-Disposition: form-data; name="field"
 
+AB
 --------------------------------
 </protocol>
 </verify>
diff --git a/tests/data/test923 b/tests/data/test894
similarity index 59%
copy from tests/data/test923
copy to tests/data/test894
index cb811bb0e..db79830ca 100644
--- a/tests/data/test923
+++ b/tests/data/test894
@@ -1,40 +1,37 @@
 <testcase>
 <info>
 <keywords>
-SMTP
-VRFY
+POP3
+Clear Text
+RETR
 </keywords>
 </info>
 
 #
 # Server-side
 <reply>
-<data>
-250 <address@hidden>
-</data>
 </reply>
 
 #
 # Client-side
 <client>
 <server>
-smtp
+pop3
 </server>
  <name>
-SMTP VRFY
+POP3 with CR in username
  </name>
  <command>
-smtp://%HOSTIP:%SMTPPORT/923 --mail-rcpt recipient
+pop3://user%0dFRIGGING_cmd:secret@%HOSTIP:%POP3PORT/894
 </command>
 </client>
 
 #
 # Verify data after the test has been "shot"
 <verify>
-<protocol>
-EHLO 923
-VRFY recipient
-QUIT
-</protocol>
+# malformed URL
+<errorcode>
+3
+</errorcode>
 </verify>
 </testcase>
diff --git a/tests/data/test923 b/tests/data/test923
index cb811bb0e..9d9722f9a 100644
--- a/tests/data/test923
+++ b/tests/data/test923
@@ -9,9 +9,6 @@ VRFY
 #
 # Server-side
 <reply>
-<data>
-250 <address@hidden>
-</data>
 </reply>
 
 #
diff --git a/tests/data/test955 b/tests/data/test955
new file mode 100644
index 000000000..57d618c7d
--- /dev/null
+++ b/tests/data/test955
@@ -0,0 +1,56 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP without SMTPUTF8 support - UTF-8 based sender (local part only)
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+<command>
+smtp://%HOSTIP:%SMTPPORT/955 --mail-rcpt address@hidden --mail-from 
Avsäaddress@hidden -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 55 - CURLE_SEND_ERROR
+<errorcode>
+55
+</errorcode>
+<protocol>
+EHLO 955
+MAIL FROM:<Avsäaddress@hidden>
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test956 b/tests/data/test956
new file mode 100644
index 000000000..7fc9bc9af
--- /dev/null
+++ b/tests/data/test956
@@ -0,0 +1,57 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP without SMTPUTF8 support - UTF-8 based recipient (local part only)
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+<command>
+smtp://%HOSTIP:%SMTPPORT/956 --mail-rcpt Stöaddress@hidden --mail-from 
address@hidden -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 55 - CURLE_SEND_ERROR
+<errorcode>
+55
+</errorcode>
+<protocol>
+EHLO 956
+MAIL FROM:<address@hidden>
+RCPT TO:<Stöaddress@hidden>
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test957 b/tests/data/test957
new file mode 100644
index 000000000..28c9c478a
--- /dev/null
+++ b/tests/data/test957
@@ -0,0 +1,51 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+VRFY
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP VRFY without SMTPUTF8 support - UTF-8 based recipient (local part only)
+ </name>
+<command>
+smtp://%HOSTIP:%SMTPPORT/957 --mail-rcpt Användaren
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 56 - CURLE_RECV_ERROR
+<errorcode>
+56
+</errorcode>
+<protocol>
+EHLO 957
+VRFY Användaren
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test958 b/tests/data/test958
new file mode 100644
index 000000000..66ba414cb
--- /dev/null
+++ b/tests/data/test958
@@ -0,0 +1,51 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+VRFY
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP external VRFY without SMTPUTF8 support - UTF-8 based recipient (local 
part only)
+ </name>
+<command>
+smtp://%HOSTIP:%SMTPPORT/958 --mail-rcpt Anväaddress@hidden
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 56 - CURLE_RECV_ERROR
+<errorcode>
+56
+</errorcode>
+<protocol>
+EHLO 958
+VRFY Anväaddress@hidden
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test959 b/tests/data/test959
new file mode 100644
index 000000000..a61c3d142
--- /dev/null
+++ b/tests/data/test959
@@ -0,0 +1,57 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+!idn
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP without SMTPUTF8 support - UTF-8 based sender (host part only)
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+<command>
+smtp://%HOSTIP:%SMTPPORT/959 --mail-rcpt address@hidden --mail-from 
sender@åäö.se -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 55 - CURLE_SEND_ERROR
+<errorcode>
+55
+</errorcode>
+<protocol>
+EHLO 959
+MAIL FROM:<sender@åäö.se>
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test960 b/tests/data/test960
new file mode 100644
index 000000000..32834cda0
--- /dev/null
+++ b/tests/data/test960
@@ -0,0 +1,58 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+!idn
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP without SMTPUTF8 support - UTF-8 based recipient (host part only)
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+<command>
+smtp://%HOSTIP:%SMTPPORT/960 --mail-rcpt recipient@åäö.se --mail-from 
address@hidden -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 55 - CURLE_SEND_ERROR
+<errorcode>
+55
+</errorcode>
+<protocol>
+EHLO 960
+MAIL FROM:<address@hidden>
+RCPT TO:<recipient@åäö.se>
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test961 b/tests/data/test961
new file mode 100644
index 000000000..2148a0ce5
--- /dev/null
+++ b/tests/data/test961
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+VRFY
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+!idn
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP external VRFY without SMTPUTF8 support - UTF-8 based recipient (host part 
only)
+ </name>
+<command>
+smtp://%HOSTIP:%SMTPPORT/961 --mail-rcpt user@åäö.se
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 56 - CURLE_RECV_ERROR
+<errorcode>
+56
+</errorcode>
+<protocol>
+EHLO 961
+VRFY user@åäö.se
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test962 b/tests/data/test962
new file mode 100644
index 000000000..35b368cfd
--- /dev/null
+++ b/tests/data/test962
@@ -0,0 +1,63 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+IDN
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+idn
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP without SMTPUTF8 support - UTF-8 based sender (host part only)
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+<command>
+smtp://%HOSTIP:%SMTPPORT/962 --mail-rcpt address@hidden --mail-from 
sender@åäö.se -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO 962
+MAIL FROM:<address@hidden>
+RCPT TO:<address@hidden>
+DATA
+QUIT
+</protocol>
+<upload>
+From: different
+To: another
+
+body
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test963 b/tests/data/test963
new file mode 100644
index 000000000..7ea121507
--- /dev/null
+++ b/tests/data/test963
@@ -0,0 +1,63 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+IDN
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+idn
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP without SMTPUTF8 support (IDN Enabked) - UTF-8 based recipient (host part 
only)
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+<command>
+smtp://%HOSTIP:%SMTPPORT/963 --mail-rcpt recipient@åäö.se --mail-from 
address@hidden -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO 963
+MAIL FROM:<address@hidden>
+RCPT TO:<address@hidden>
+DATA
+QUIT
+</protocol>
+<upload>
+From: different
+To: another
+
+body
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test964 b/tests/data/test964
new file mode 100644
index 000000000..5448d0f21
--- /dev/null
+++ b/tests/data/test964
@@ -0,0 +1,49 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+VRFY
+IDN
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+idn
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP external VRFY without SMTPUTF8 support (IDN Enabled) - UTF-8 based 
recipient (host part only)
+ </name>
+<command>
+smtp://%HOSTIP:%SMTPPORT/964 --mail-rcpt user@åäö.se
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO 964
+VRFY address@hidden
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test965 b/tests/data/test965
new file mode 100644
index 000000000..8c93bc0c8
--- /dev/null
+++ b/tests/data/test965
@@ -0,0 +1,66 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+IDN
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+CAPA SMTPUTF8
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+idn
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP with SMTPUTF8 support - UTF-8 based sender
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+<command>
+smtp://%HOSTIP:%SMTPPORT/965 --mail-rcpt address@hidden --mail-from 
Avsändaren@åäö.se -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO 965
+MAIL FROM:<Avsäaddress@hidden> SMTPUTF8
+RCPT TO:<address@hidden>
+DATA
+QUIT
+</protocol>
+<upload>
+From: different
+To: another
+
+body
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test966 b/tests/data/test966
new file mode 100644
index 000000000..499fdda61
--- /dev/null
+++ b/tests/data/test966
@@ -0,0 +1,66 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+IDN
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+CAPA SMTPUTF8
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+idn
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP with SMTPUTF8 support - UTF-8 based recipient
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+<command>
+smtp://%HOSTIP:%SMTPPORT/966 --mail-rcpt Stödmottagaren@åäö.se --mail-from 
address@hidden -T -
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO 966
+MAIL FROM:<address@hidden> SMTPUTF8
+RCPT TO:<Stöaddress@hidden>
+DATA
+QUIT
+</protocol>
+<upload>
+From: different
+To: another
+
+body
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test967 b/tests/data/test967
new file mode 100644
index 000000000..2813f508b
--- /dev/null
+++ b/tests/data/test967
@@ -0,0 +1,55 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+VRFY
+IDN
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+CAPA SMTPUTF8
+</servercmd>
+<data>
+252 Send some mail and I'll try my best
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+idn
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP external VRFY with SMTPUTF8 support
+ </name>
+<command>
+smtp://%HOSTIP:%SMTPPORT/967 --mail-rcpt Användaren@åäö.se
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO 967
+VRFY Anväaddress@hidden SMTPUTF8
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test968 b/tests/data/test968
new file mode 100644
index 000000000..ca58970c2
--- /dev/null
+++ b/tests/data/test968
@@ -0,0 +1,52 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+VRFY
+IDN
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+CAPA SMTPUTF8
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+idn
+!win32
+</features>
+<setenv>
+LC_ALL=en_US.UTF-8
+LC_CTYPE=en_US.UTF-8
+</setenv>
+<precheck>
+perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if 
(lc(langinfo(CODESET())) ne "utf-8");'
+</precheck>
+ <name>
+SMTP VRFY with SMTPUTF8 support
+ </name>
+<command>
+smtp://%HOSTIP:%SMTPPORT/968 --mail-rcpt Användaren
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO 968
+VRFY Användaren SMTPUTF8
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test969 b/tests/data/test969
new file mode 100644
index 000000000..9d3fa93e8
--- /dev/null
+++ b/tests/data/test969
@@ -0,0 +1,51 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+EXPN
+CUSTOMREQUEST
+IDN
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+CAPA SMTPUTF8
+</servercmd>
+<data>
+250-Joe Smith <address@hidden>
+250-Harry Smith <address@hidden>
+250 Melvin Smith <address@hidden>
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+<features>
+idn
+!win32
+</features>
+ <name>
+SMTP mailing list EXPN (CUSTOMREQUEST) with SMTPUTF8 support
+ </name>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/969 --mail-rcpt Friends -X EXPN
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+EHLO 969
+EXPN Friends SMTPUTF8
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/ftp.pm b/tests/ftp.pm
index f4a4acedd..5e92ce7f9 100644
--- a/tests/ftp.pm
+++ b/tests/ftp.pm
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2010, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -20,6 +20,19 @@
 #
 ###########################################################################
 
+BEGIN {
+    # portable sleeping needs Time::HiRes
+    eval {
+        no warnings "all";
+        require Time::HiRes;
+    };
+    # portable sleeping falls back to native Sleep on Win32
+    eval {
+        no warnings "all";
+        require Win32;
+    }
+}
+
 use strict;
 use warnings;
 
@@ -29,6 +42,27 @@ use serverhelp qw(
     datasockf_pidfilename
     );
 
+#######################################################################
+# portable_sleep uses Time::HiRes::sleep if available and falls back
+# to the classic approach of using select(undef, undef, undef, ...).
+# even though that one is not portable due to being implemented using
+# select on Windows: https://perldoc.perl.org/perlport.html#select
+# On Windows it also just uses full-second sleep for waits >1 second.
+#
+sub portable_sleep {
+    my ($seconds) = @_;
+
+    if($Time::HiRes::VERSION) {
+        Time::HiRes::sleep($seconds);
+    }
+    elsif ($^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'msys') {
+        Win32::Sleep($seconds*1000);
+    }
+    else {
+        select(undef, undef, undef, $seconds);
+    }
+}
+
 #######################################################################
 # pidfromfile returns the pid stored in the given pidfile.  The value
 # of the returned pid will never be a negative value. It will be zero
@@ -216,7 +250,7 @@ sub killpid {
                 }
             }
             last if(not scalar(@signalled));
-            select(undef, undef, undef, 0.05);
+            portable_sleep(0.05);
         }
     }
 
diff --git a/tests/ftpserver.pl b/tests/ftpserver.pl
index ac02722e9..431bd2586 100755
--- a/tests/ftpserver.pl
+++ b/tests/ftpserver.pl
@@ -6,7 +6,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2018, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -493,7 +493,7 @@ sub sendcontrol {
 
         for(@a) {
             sockfilt $_;
-            select(undef, undef, undef, 0.01);
+            portable_sleep(0.01);
         }
     }
     my $log;
@@ -530,7 +530,7 @@ sub senddata {
             # pause between each byte
             for (split(//,$l)) {
                 sockfiltsecondary $_;
-                select(undef, undef, undef, 0.01);
+                portable_sleep(0.01);
             }
         }
     }
@@ -813,6 +813,7 @@ sub MAIL_smtp {
     else {
         my $from;
         my $size;
+        my $smtputf8 = grep /^SMTPUTF8$/, @capabilities;
         my @elements = split(/ /, $args);
 
         # Get the FROM and SIZE parameters
@@ -827,11 +828,11 @@ sub MAIL_smtp {
 
         # Validate the from address (only <> and a valid email address inside
         # <> are allowed, such as <address@hidden>)
-        if ((!$from) || (($from ne "<>") && ($from !~
-            /^<([a-zA-Z0-9._%+-]+)\@([a-zA-Z0-9.-]+).([a-zA-Z]{2,4})>$/))) {
-            sendcontrol "501 Invalid address\r\n";
-        }
-        else {
+        if (($from eq "<>") ||
+            (!$smtputf8 && $from =~
+              /^<([a-zA-Z0-9._%+-]+)\@(([a-zA-Z0-9-]+)\.)+([a-zA-Z]{2,4})>$/) 
||
+            ($smtputf8 && $from =~
+              
/^<([a-zA-Z0-9\x{80}-\x{ff}._%+-]+)\@(([a-zA-Z0-9\x{80}-\x{ff}-]+)\.)+([a-zA-Z]{2,4})>$/))
 {
             my @found;
             my $valid = 1;
 
@@ -852,6 +853,9 @@ sub MAIL_smtp {
                 sendcontrol "250 Sender OK\r\n";
             }
         }
+        else {
+            sendcontrol "501 Invalid address\r\n";
+        }
     }
 
     return 0;
@@ -867,16 +871,19 @@ sub RCPT_smtp {
         sendcontrol "501 Unrecognized parameter\r\n";
     }
     else {
+        my $smtputf8 = grep /^SMTPUTF8$/, @capabilities;
         my $to = $1;
 
         # Validate the to address (only a valid email address inside <> is
         # allowed, such as <address@hidden>)
-        if ($to !~
-            /^<([a-zA-Z0-9._%+-]+)\@([a-zA-Z0-9.-]+).([a-zA-Z]{2,4})>$/) {
-            sendcontrol "501 Invalid address\r\n";
+        if ((!$smtputf8 && $to =~
+              /^<([a-zA-Z0-9._%+-]+)\@(([a-zA-Z0-9-]+)\.)+([a-zA-Z]{2,4})>$/) 
||
+            ($smtputf8 && $to =~
+              
/^<([a-zA-Z0-9\x{80}-\x{ff}._%+-]+)\@(([a-zA-Z0-9\x{80}-\x{ff}-]+)\.)+([a-zA-Z]{2,4})>$/))
 {
+            sendcontrol "250 Recipient OK\r\n";      
         }
         else {
-            sendcontrol "250 Recipient OK\r\n";
+            sendcontrol "501 Invalid address\r\n";
         }
     }
 
@@ -1030,10 +1037,33 @@ sub VRFY_smtp {
         sendcontrol "501 Unrecognized parameter\r\n";
     }
     else {
-        my @data = getreplydata($smtp_client);
+        my $smtputf8 = grep /^SMTPUTF8$/, @capabilities;
 
-        for my $d (@data) {
-            sendcontrol $d;
+        # Validate the username (only a valid local or external username is
+        # allowed, such as user or address@hidden)
+        if ((!$smtputf8 && $username =~
+            /^([a-zA-Z0-9._%+-]+)(\@(([a-zA-Z0-9-]+)\.)+([a-zA-Z]{2,4}))?$/) ||
+            ($smtputf8 && $username =~
+            
/^([a-zA-Z0-9\x{80}-\x{ff}._%+-]+)(\@(([a-zA-Z0-9\x{80}-\x{ff}-]+)\.)+([a-zA-Z]{2,4}))?$/))
 {
+
+            my @data = getreplydata($smtp_client);
+
+            if(!@data) {
+                if ($username !~
+                    
/^([a-zA-Z0-9._%+-]+)\@(([a-zA-Z0-9-]+)\.)+([a-zA-Z]{2,4})$/) {
+                  push @data, "250 <$username\@example.com>\r\n"
+                }
+                else {
+                  push @data, "250 <$username>\r\n"
+                }
+            }
+
+            for my $d (@data) {
+                sendcontrol $d;
+            }
+        }
+        else {
+            sendcontrol "501 Invalid address\r\n";
         }
     }
 
@@ -3169,7 +3199,7 @@ while(1) {
             logmsg("Sleep for $delay seconds\n");
             my $twentieths = $delay * 20;
             while($twentieths--) {
-                select(undef, undef, undef, 0.05) unless($got_exit_signal);
+                portable_sleep(0.05) unless($got_exit_signal);
             }
         }
 
diff --git a/tests/keywords.pl b/tests/keywords.pl
index 7ab907fe3..a84753ada 100755
--- a/tests/keywords.pl
+++ b/tests/keywords.pl
@@ -6,7 +6,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2014, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -42,7 +42,7 @@ my $TESTCASES; # start with no test cases
 for(@cmds) {
     $_ =~ s/[a-z\/\.]*//g;
 }
-# the the numbers from low to high
+# the numbers from low to high
 for(sort { $a <=> $b } @cmds) {
     $TESTCASES .= " $_";
 }
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
index 374a66747..ab2680c97 100644
--- a/tests/libtest/Makefile.inc
+++ b/tests/libtest/Makefile.inc
@@ -22,7 +22,8 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect     
           \
  lib571 lib572 lib573 lib574 lib575 lib576        lib578 lib579 lib582   \
  lib583 lib585 lib586 lib587 lib589 lib590 lib591 lib597 lib598 lib599   \
  lib643 lib644 lib645 lib650 lib651 lib652 lib653 lib654 lib655 lib658   \
- lib659 lib661 \
+ lib659 lib661 lib666 lib667 lib668 \
+ lib670 lib671 lib672 lib673 \
  lib1156 \
  lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1507 lib1508 \
  lib1509 lib1510 lib1511 lib1512 lib1513 lib1514 lib1515         lib1517 \
@@ -33,7 +34,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect     
           \
  lib1550 lib1551 lib1552 lib1553 lib1554 lib1555 lib1556 lib1557 \
  lib1558 lib1559 lib1560 lib1564 lib1565 \
  lib1591 lib1592 lib1593 lib1594 lib1596 \
- lib1900 lib1905 lib1906 lib1907 \
+ lib1900 lib1905 lib1906 lib1907 lib1908 \
  lib2033
 
 chkdecimalpoint_SOURCES = chkdecimalpoint.c ../../lib/mprintf.c \
@@ -348,6 +349,33 @@ lib659_CPPFLAGS = $(AM_CPPFLAGS)
 lib661_SOURCES = lib661.c $(SUPPORTFILES)
 lib661_CPPFLAGS = $(AM_CPPFLAGS)
 
+lib666_SOURCES = lib666.c $(SUPPORTFILES)
+lib666_CPPFLAGS = $(AM_CPPFLAGS)
+
+lib667_SOURCES = lib667.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib667_LDADD = $(TESTUTIL_LIBS)
+lib667_CPPFLAGS = $(AM_CPPFLAGS)
+
+lib668_SOURCES = lib668.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib668_LDADD = $(TESTUTIL_LIBS)
+lib668_CPPFLAGS = $(AM_CPPFLAGS)
+
+lib670_SOURCES = lib670.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib670_LDADD = $(TESTUTIL_LIBS)
+lib670_CPPFLAGS = $(AM_CPPFLAGS) -DLIB670
+
+lib671_SOURCES = lib670.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib671_LDADD = $(TESTUTIL_LIBS)
+lib671_CPPFLAGS = $(AM_CPPFLAGS) -DLIB671
+
+lib672_SOURCES = lib670.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib672_LDADD = $(TESTUTIL_LIBS)
+lib672_CPPFLAGS = $(AM_CPPFLAGS) -DLIB672
+
+lib673_SOURCES = lib670.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib673_LDADD = $(TESTUTIL_LIBS)
+lib673_CPPFLAGS = $(AM_CPPFLAGS) -DLIB673
+
 lib1500_SOURCES = lib1500.c $(SUPPORTFILES) $(TESTUTIL)
 lib1500_LDADD = $(TESTUTIL_LIBS)
 lib1500_CPPFLAGS = $(AM_CPPFLAGS)
@@ -578,6 +606,10 @@ lib1907_SOURCES = lib1907.c $(SUPPORTFILES) $(TESTUTIL) 
$(WARNLESS)
 lib1907_LDADD = $(TESTUTIL_LIBS)
 lib1907_CPPFLAGS = $(AM_CPPFLAGS)
 
+lib1908_SOURCES = lib1908.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1908_LDADD = $(TESTUTIL_LIBS)
+lib1908_CPPFLAGS = $(AM_CPPFLAGS)
+
 lib2033_SOURCES = libntlmconnect.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
 lib2033_LDADD = $(TESTUTIL_LIBS)
 lib2033_CPPFLAGS = $(AM_CPPFLAGS) -DUSE_PIPELINING
diff --git a/tests/libtest/lib1515.c b/tests/libtest/lib1515.c
index c72554a3b..b879836f9 100644
--- a/tests/libtest/lib1515.c
+++ b/tests/libtest/lib1515.c
@@ -36,7 +36,7 @@
 #define DNS_TIMEOUT 1
 
 #if defined(WIN32) || defined(_WIN32)
-#define sleep(s) Sleep(s * 1000)
+#define sleep(sec) Sleep ((sec)*1000)
 #endif
 
 static int debug_callback(CURL *curl, curl_infotype info, char *msg,
diff --git a/tests/libtest/lib1531.c b/tests/libtest/lib1531.c
index 4a4dc133a..5c9399559 100644
--- a/tests/libtest/lib1531.c
+++ b/tests/libtest/lib1531.c
@@ -107,7 +107,7 @@ int test(char *URL)
        curl_multi_fdset() doc. */
 
     if(maxfd == -1) {
-#ifdef _WIN32
+#if defined(WIN32) || defined(_WIN32)
       Sleep(100);
       rc = 0;
 #else
diff --git a/tests/libtest/lib1560.c b/tests/libtest/lib1560.c
index 7f8accc7d..fbe642c20 100644
--- a/tests/libtest/lib1560.c
+++ b/tests/libtest/lib1560.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -60,7 +60,7 @@ static int checkparts(CURLU *u, const char *in, const char 
*wanted,
     {CURLUPART_FRAGMENT, "fragment"},
     {0, NULL}
   };
-  buf[0] = 0;
+  memset(buf, 0, sizeof(buf));
 
   for(i = 0; parts[i].name; i++) {
     char *p = NULL;
@@ -129,6 +129,14 @@ struct querycase {
 };
 
 static struct testcase get_parts_list[] ={
+  {"user:address@hidden/color/#green?no-black",
+   "ftp | user | moo | [13] | ftp.example.com | [15] | /color/ | [16] | "
+   "green?no-black",
+   CURLU_GUESS_SCHEME, 0, CURLUE_OK },
+  {"ftp.user:address@hidden/color/#green?no-black",
+   "http | ftp.user | moo | [13] | example.com | [15] | /color/ | [16] | "
+   "green?no-black",
+   CURLU_GUESS_SCHEME, 0, CURLUE_OK },
 #ifdef WIN32
   {"file:/C:\\programs\\foo",
    "file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
@@ -637,6 +645,9 @@ static CURLUcode updateurl(CURLU *u, const char *cmd, 
unsigned int setflags)
       char buf[80];
       char part[80];
       char value[80];
+
+      memset(part, 0, sizeof(part)); /* Avoid valgrind false positive. */
+      memset(value, 0, sizeof(value)); /* Avoid valgrind false positive. */
       memcpy(buf, p, n);
       buf[n] = 0;
       if(2 == sscanf(buf, "%79[^=]=%79[^,]", part, value)) {
diff --git a/tests/libtest/lib1564.c b/tests/libtest/lib1564.c
index 225c8c6d7..13ac5b01e 100644
--- a/tests/libtest/lib1564.c
+++ b/tests/libtest/lib1564.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -26,7 +26,7 @@
 #include "memdebug.h"
 
 #define TEST_HANG_TIMEOUT 60 * 1000
-#define WAKEUP_NUM 1234567
+#define WAKEUP_NUM 10
 
 int test(char *URL)
 {
diff --git a/src/tool_cb_see.h b/tests/libtest/lib1908.c
similarity index 61%
copy from src/tool_cb_see.h
copy to tests/libtest/lib1908.c
index fed8bbf8d..bacbc9710 100644
--- a/src/tool_cb_see.h
+++ b/tests/libtest/lib1908.c
@@ -1,5 +1,3 @@
-#ifndef HEADER_CURL_TOOL_CB_SEE_H
-#define HEADER_CURL_TOOL_CB_SEE_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -7,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2013 - 2020, Linus Nielsen Feltzing, <address@hidden>
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -21,25 +19,29 @@
  * KIND, either express or implied.
  *
  ***************************************************************************/
-#include "tool_setup.h"
-
-#if defined(WIN32) && !defined(__MINGW64__)
-
-int tool_ftruncate64(int fd, curl_off_t where);
-
-#undef  ftruncate
-#define ftruncate(fd,where) tool_ftruncate64(fd,where)
-
-#ifndef HAVE_FTRUNCATE
-#  define HAVE_FTRUNCATE 1
-#endif
-
-#endif /* WIN32  && ! __MINGW64__ */
-
-/*
-** callback for CURLOPT_SEEKFUNCTION
-*/
-
-int tool_seek_cb(void *userdata, curl_off_t offset, int whence);
-
-#endif /* HEADER_CURL_TOOL_CB_SEE_H */
+#include "test.h"
+
+#include "testutil.h"
+#include "warnless.h"
+#include "memdebug.h"
+
+int test(char *URL)
+{
+  CURLcode ret = CURLE_OK;
+  CURL *hnd;
+  start_test_timing();
+
+  curl_global_init(CURL_GLOBAL_ALL);
+
+  hnd = curl_easy_init();
+  if(hnd) {
+    curl_easy_setopt(hnd, CURLOPT_URL, URL);
+    curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
+    curl_easy_setopt(hnd, CURLOPT_ALTSVC, "log/altsvc-1908");
+    ret = curl_easy_perform(hnd);
+    curl_easy_reset(hnd);
+    curl_easy_cleanup(hnd);
+  }
+  curl_global_cleanup();
+  return (int)ret;
+}
diff --git a/tests/libtest/lib643.c b/tests/libtest/lib643.c
index 7432dfce8..5af0f4a14 100644
--- a/tests/libtest/lib643.c
+++ b/tests/libtest/lib643.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -26,11 +26,9 @@
 static char data[]=
 #ifdef CURL_DOES_CONVERSIONS
   /* ASCII representation with escape sequences for non-ASCII platforms */
-  "\x74\x68\x69\x73\x20\x69\x73\x20\x77\x68\x61\x74\x20\x77\x65\x20\x70"
-  "\x6f\x73\x74\x20\x74\x6f\x20\x74\x68\x65\x20\x73\x69\x6c\x6c\x79\x20"
-  "\x77\x65\x62\x20\x73\x65\x72\x76\x65\x72\x0a";
+  "\x64\x75\x6d\x6d\x79\x0a";
 #else
-  "this is what we post to the silly web server\n";
+  "dummy\n";
 #endif
 
 struct WriteThis {
@@ -41,11 +39,20 @@ struct WriteThis {
 static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
 {
 #ifdef LIB644
+  static int count = 0;
   (void)ptr;
   (void)size;
   (void)nmemb;
   (void)userp;
-  return CURL_READFUNC_ABORT;
+  switch(count++) {
+  case 0: /* Return a single byte. */
+    *ptr = '\n';
+    return 1;
+  case 1: /* Request abort. */
+    return CURL_READFUNC_ABORT;
+  }
+  printf("Wrongly called >2 times\n");
+  exit(1); /* trigger major failure */
 #else
 
   struct WriteThis *pooh = (struct WriteThis *)userp;
diff --git a/tests/libtest/lib652.c b/tests/libtest/lib652.c
index 5c9cba5fb..3d247d27b 100644
--- a/tests/libtest/lib652.c
+++ b/tests/libtest/lib652.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -105,6 +105,9 @@ int test(char *URL)
   /* send a multi-part mail */
   test_setopt(curl, CURLOPT_MIMEPOST, mime);
 
+  /* Shorten upload buffer. */
+  test_setopt(curl, CURLOPT_UPLOAD_BUFFERSIZE, 16411L);
+
   /* get verbose debug output please */
   test_setopt(curl, CURLOPT_VERBOSE, 1L);
 
diff --git a/tests/libtest/lib654.c b/tests/libtest/lib654.c
index 45051a9c7..f9c8b9118 100644
--- a/tests/libtest/lib654.c
+++ b/tests/libtest/lib654.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -26,11 +26,9 @@
 static char data[]=
 #ifdef CURL_DOES_CONVERSIONS
   /* ASCII representation with escape sequences for non-ASCII platforms */
-  "\x74\x68\x69\x73\x20\x69\x73\x20\x77\x68\x61\x74\x20\x77\x65\x20\x70"
-  "\x6f\x73\x74\x20\x74\x6f\x20\x74\x68\x65\x20\x73\x69\x6c\x6c\x79\x20"
-  "\x77\x65\x62\x20\x73\x65\x72\x76\x65\x72\x0a";
+  "\x64\x75\x6d\x6d\x79\x0a";
 #else
-  "this is what we post to the silly web server\n";
+  "dummy\n";
 #endif
 
 struct WriteThis {
diff --git a/tests/libtest/lib652.c b/tests/libtest/lib666.c
similarity index 74%
copy from tests/libtest/lib652.c
copy to tests/libtest/lib666.c
index 5c9cba5fb..c75936eeb 100644
--- a/tests/libtest/lib652.c
+++ b/tests/libtest/lib666.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -31,14 +31,16 @@ int test(char *URL)
   CURLcode res = CURLE_OK;
   curl_mime *mime = NULL;
   curl_mimepart *part;
-  struct curl_slist *recipients = NULL;
+  size_t i;
 
-  /* create a buffer with AAAA...BBBBB...CCCC...etc */
-  int i;
-  int size = (int)sizeof(buffer) / 10;
+  /* Checks huge binary-encoded mime post. */
 
-  for(i = 0; i < size ; i++)
-    memset(&buffer[i * 10], 65 + (i % 26), 10);
+  /* Create a buffer with pseudo-binary data. */
+  for(i = 0; i < sizeof(buffer); i++)
+    if(i % 77 == 76)
+      buffer[i] = '\n';
+    else
+      buffer[i] = (char) (0x41 + i % 26); /* A...Z */
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
     fprintf(stderr, "curl_global_init() failed\n");
@@ -65,14 +67,14 @@ int test(char *URL)
     res = (CURLcode) TEST_ERR_MAJOR_BAD;
     goto test_cleanup;
   }
-  res = curl_mime_filename(part, "myfile.jpg");
+  res = curl_mime_name(part, "upfile");
   if(res) {
-    fprintf(stderr, "curl_mime_filename() failed\n");
+    fprintf(stderr, "curl_mime_name() failed\n");
     goto test_cleanup;
   }
-  res = curl_mime_type(part, "image/jpeg");
+  res = curl_mime_filename(part, "myfile.txt");
   if(res) {
-    fprintf(stderr, "curl_mime_type() failed\n");
+    fprintf(stderr, "curl_mime_filename() failed\n");
     goto test_cleanup;
   }
   res = curl_mime_data(part, buffer, sizeof(buffer));
@@ -80,34 +82,27 @@ int test(char *URL)
     fprintf(stderr, "curl_mime_data() failed\n");
     goto test_cleanup;
   }
-  res = curl_mime_encoder(part, "base64");
+  res = curl_mime_encoder(part, "binary");
   if(res) {
     fprintf(stderr, "curl_mime_encoder() failed\n");
     goto test_cleanup;
   }
 
-  /* Prepare recipients. */
-  recipients = curl_slist_append(NULL, "address@hidden");
-  if(!recipients) {
-    fprintf(stderr, "curl_slist_append() failed\n");
-    goto test_cleanup;
-  }
-
   /* First set the URL that is about to receive our mime mail. */
   test_setopt(curl, CURLOPT_URL, URL);
 
-  /* Set sender. */
-  test_setopt(curl, CURLOPT_MAIL_FROM, "address@hidden");
-
-  /* Set recipients. */
-  test_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
-
-  /* send a multi-part mail */
+  /* Post form */
   test_setopt(curl, CURLOPT_MIMEPOST, mime);
 
+  /* Shorten upload buffer. */
+  test_setopt(curl, CURLOPT_UPLOAD_BUFFERSIZE, 16411L);
+
   /* get verbose debug output please */
   test_setopt(curl, CURLOPT_VERBOSE, 1L);
 
+  /* include headers in the output */
+  test_setopt(curl, CURLOPT_HEADER, 1L);
+
   /* Perform the request, res will get the return code */
   res = curl_easy_perform(curl);
 
@@ -119,9 +114,6 @@ test_cleanup:
   /* now cleanup the mime structure */
   curl_mime_free(mime);
 
-  /* cleanup the recipients. */
-  curl_slist_free_all(recipients);
-
   curl_global_cleanup();
 
   return res;
diff --git a/tests/libtest/lib654.c b/tests/libtest/lib667.c
similarity index 56%
copy from tests/libtest/lib654.c
copy to tests/libtest/lib667.c
index 45051a9c7..8bf7be43f 100644
--- a/tests/libtest/lib654.c
+++ b/tests/libtest/lib667.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -26,26 +26,16 @@
 static char data[]=
 #ifdef CURL_DOES_CONVERSIONS
   /* ASCII representation with escape sequences for non-ASCII platforms */
-  "\x74\x68\x69\x73\x20\x69\x73\x20\x77\x68\x61\x74\x20\x77\x65\x20\x70"
-  "\x6f\x73\x74\x20\x74\x6f\x20\x74\x68\x65\x20\x73\x69\x6c\x6c\x79\x20"
-  "\x77\x65\x62\x20\x73\x65\x72\x76\x65\x72\x0a";
+  "\x64\x75\x6d\x6d\x79";
 #else
-  "this is what we post to the silly web server\n";
+  "dummy";
 #endif
 
 struct WriteThis {
   char *readptr;
   curl_off_t sizeleft;
-  int freecount;
 };
 
-static void free_callback(void *userp)
-{
-  struct WriteThis *pooh = (struct WriteThis *) userp;
-
-  pooh->freecount++;
-}
-
 static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
 {
   struct WriteThis *pooh = (struct WriteThis *)userp;
@@ -70,17 +60,15 @@ static size_t read_callback(char *ptr, size_t size, size_t 
nmemb, void *userp)
 int test(char *URL)
 {
   CURL *easy = NULL;
-  CURL *easy2 = NULL;
   curl_mime *mime = NULL;
   curl_mimepart *part;
-  struct curl_slist *hdrs = NULL;
   CURLcode result;
   int res = TEST_ERR_FAILURE;
   struct WriteThis pooh;
 
   /*
-   * Check proper copy/release of mime post data bound to a duplicated
-   * easy handle.
+   * Check proper handling of mime encoder feature when the part read callback
+   * delivers data bytes one at a time. Use chunked encoding for accurate test.
    */
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
@@ -102,72 +90,27 @@ int test(char *URL)
   /* Prepare the callback structure. */
   pooh.readptr = data;
   pooh.sizeleft = (curl_off_t) strlen(data);
-  pooh.freecount = 0;
 
   /* Build the mime tree. */
   mime = curl_mime_init(easy);
   part = curl_mime_addpart(mime);
-  curl_mime_data(part, "hello", CURL_ZERO_TERMINATED);
-  curl_mime_name(part, "greeting");
-  curl_mime_type(part, "application/X-Greeting");
+  curl_mime_name(part, "field");
   curl_mime_encoder(part, "base64");
-  hdrs = curl_slist_append(hdrs, "X-Test-Number: 654");
-  curl_mime_headers(part, hdrs, TRUE);
-  part = curl_mime_addpart(mime);
-  curl_mime_filedata(part, "log/file654.txt");
-  part = curl_mime_addpart(mime);
-  curl_mime_data_cb(part, (curl_off_t) -1, read_callback, NULL, free_callback,
-                    &pooh);
+  /* Using an undefined length forces chunked transfer. */
+  curl_mime_data_cb(part, (curl_off_t) -1, read_callback, NULL, NULL, &pooh);
 
   /* Bind mime data to its easy handle. */
   test_setopt(easy, CURLOPT_MIMEPOST, mime);
 
-  /* Duplicate the handle. */
-  easy2 = curl_easy_duphandle(easy);
-  if(!easy2) {
-    fprintf(stderr, "curl_easy_duphandle() failed\n");
-    res = TEST_ERR_FAILURE;
-    goto test_cleanup;
-  }
-
-  /* Now free the mime structure: it should unbind it from the first
-     easy handle. */
-  curl_mime_free(mime);
-  mime = NULL;  /* Already cleaned up. */
-
-  /* Perform on the first handle: should not send any data. */
+  /* Send data. */
   result = curl_easy_perform(easy);
   if(result) {
-    fprintf(stderr, "curl_easy_perform(original) failed\n");
-    res = (int) result;
-    goto test_cleanup;
-  }
-
-  /* Perform on the second handle: if the bound mime structure has not been
-     duplicated properly, it should cause a valgrind error. */
-  result = curl_easy_perform(easy2);
-  if(result) {
-    fprintf(stderr, "curl_easy_perform(duplicated) failed\n");
+    fprintf(stderr, "curl_easy_perform() failed\n");
     res = (int) result;
-    goto test_cleanup;
-  }
-
-  /* Free the duplicated handle: it should call free_callback again.
-     If the mime copy was bad or not automatically released, valgrind
-     will signal it. */
-  curl_easy_cleanup(easy2);
-  easy2 = NULL;  /* Already cleaned up. */
-
-  if(pooh.freecount != 2) {
-    fprintf(stderr, "free_callback() called %d times instead of 2\n",
-            pooh.freecount);
-    res = TEST_ERR_FAILURE;
-    goto test_cleanup;
   }
 
 test_cleanup:
   curl_easy_cleanup(easy);
-  curl_easy_cleanup(easy2);
   curl_mime_free(mime);
   curl_global_cleanup();
   return res;
diff --git a/tests/libtest/lib668.c b/tests/libtest/lib668.c
new file mode 100644
index 000000000..c0b608a0a
--- /dev/null
+++ b/tests/libtest/lib668.c
@@ -0,0 +1,122 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, 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 "test.h"
+
+#include "memdebug.h"
+
+static char data[]=
+#ifdef CURL_DOES_CONVERSIONS
+  /* ASCII representation with escape sequences for non-ASCII platforms */
+  "\x64\x75\x6d\x6d\x79";
+#else
+  "dummy";
+#endif
+
+struct WriteThis {
+  char *readptr;
+  curl_off_t sizeleft;
+};
+
+static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
+{
+  struct WriteThis *pooh = (struct WriteThis *)userp;
+  size_t len = strlen(pooh->readptr);
+
+  (void) size; /* Always 1.*/
+
+  if(len > nmemb)
+    len = nmemb;
+  if(len) {
+    memcpy(ptr, pooh->readptr, len);
+    pooh->readptr += len;
+  }
+  return len;
+}
+
+int test(char *URL)
+{
+  CURL *easy = NULL;
+  curl_mime *mime = NULL;
+  curl_mimepart *part;
+  CURLcode result;
+  int res = TEST_ERR_FAILURE;
+  struct WriteThis pooh1, pooh2;
+
+  /*
+   * Check early end of part data detection.
+   */
+
+  if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+    fprintf(stderr, "curl_global_init() failed\n");
+    return TEST_ERR_MAJOR_BAD;
+  }
+
+  easy = curl_easy_init();
+
+  /* First set the URL that is about to receive our POST. */
+  test_setopt(easy, CURLOPT_URL, URL);
+
+  /* get verbose debug output please */
+  test_setopt(easy, CURLOPT_VERBOSE, 1L);
+
+  /* include headers in the output */
+  test_setopt(easy, CURLOPT_HEADER, 1L);
+
+  /* Prepare the callback structures. */
+  pooh1.readptr = data;
+  pooh1.sizeleft = (curl_off_t) strlen(data);
+  pooh2 = pooh1;
+
+  /* Build the mime tree. */
+  mime = curl_mime_init(easy);
+  part = curl_mime_addpart(mime);
+  curl_mime_name(part, "field1");
+  /* Early end of data detection can be done because the data size is known. */
+  curl_mime_data_cb(part, (curl_off_t) strlen(data),
+                    read_callback, NULL, NULL, &pooh1);
+  part = curl_mime_addpart(mime);
+  curl_mime_name(part, "field2");
+  /* Using an undefined length forces chunked transfer and disables early
+     end of data detection for this part. */
+  curl_mime_data_cb(part, (curl_off_t) -1, read_callback, NULL, NULL, &pooh2);
+  part = curl_mime_addpart(mime);
+  curl_mime_name(part, "field3");
+  /* Regular file part sources early end of data can be detected because
+     the file size is known. In addition, and EOF test is performed. */
+  curl_mime_filedata(part, "log/file668.txt");
+
+  /* Bind mime data to its easy handle. */
+  test_setopt(easy, CURLOPT_MIMEPOST, mime);
+
+  /* Send data. */
+  result = curl_easy_perform(easy);
+  if(result) {
+    fprintf(stderr, "curl_easy_perform() failed\n");
+    res = (int) result;
+  }
+
+test_cleanup:
+  curl_easy_cleanup(easy);
+  curl_mime_free(mime);
+  curl_global_cleanup();
+  return res;
+}
diff --git a/tests/libtest/lib670.c b/tests/libtest/lib670.c
new file mode 100644
index 000000000..2e6040714
--- /dev/null
+++ b/tests/libtest/lib670.c
@@ -0,0 +1,259 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, 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 <time.h>
+
+#include "test.h"
+
+#include "memdebug.h"
+
+#define PAUSE_TIME      2
+
+
+static const char name[] = "field";
+
+struct ReadThis {
+  CURL *easy;
+  time_t origin;
+  int count;
+};
+
+
+static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
+{
+  struct ReadThis *pooh = (struct ReadThis *) userp;
+  time_t delta;
+
+  if(size * nmemb < 1)
+    return 0;
+
+  switch(pooh->count++) {
+  case 0:
+    *ptr = '\x41'; /* ASCII A. */
+    return 1;
+  case 1:
+    pooh->origin = time(NULL);
+    return CURL_READFUNC_PAUSE;
+  case 2:
+    delta = time(NULL) - pooh->origin;
+    *ptr = delta >= PAUSE_TIME? '\x42': '\x41'; /* ASCII A or B. */
+    return 1;
+  case 3:
+    return 0;
+  }
+  fprintf(stderr, "Read callback called after EOF\n");
+  exit(1);
+}
+
+#if !defined(LIB670) && !defined(LIB672)
+static int xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow,
+                    curl_off_t ultotal, curl_off_t ulnow)
+{
+  struct ReadThis *pooh = (struct ReadThis *) clientp;
+
+  (void) dltotal;
+  (void) dlnow;
+  (void) ultotal;
+  (void) ulnow;
+
+  if(pooh->origin) {
+    time_t delta = time(NULL) - pooh->origin;
+
+    if(delta >= 4 * PAUSE_TIME) {
+      fprintf(stderr, "unpausing failed: drain problem?\n");
+      return CURLE_ABORTED_BY_CALLBACK;
+    }
+
+    if(delta >= PAUSE_TIME)
+      curl_easy_pause(pooh->easy, CURLPAUSE_CONT);
+  }
+
+  return 0;
+}
+#endif
+
+int test(char *URL)
+{
+#if defined(LIB670) || defined(LIB671)
+  curl_mime *mime = NULL;
+  curl_mimepart *part;
+#else
+  CURLFORMcode formrc;
+  struct curl_httppost *formpost = NULL;
+  struct curl_httppost *lastptr = NULL;
+#endif
+#if defined(LIB670) || defined(LIB672)
+  CURLM *multi = NULL;
+  CURLMcode mres;
+  CURLMsg *msg;
+  int msgs_left;
+  int still_running = 0;
+#endif
+
+  struct ReadThis pooh;
+  CURLcode result;
+  int res = TEST_ERR_FAILURE;
+
+  /*
+   * Check proper pausing/unpausing from a mime or form read callback.
+   */
+
+  if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+    fprintf(stderr, "curl_global_init() failed\n");
+    return TEST_ERR_MAJOR_BAD;
+  }
+
+  pooh.origin = (time_t) 0;
+  pooh.count = 0;
+  pooh.easy = curl_easy_init();
+
+  /* First set the URL that is about to receive our POST. */
+  test_setopt(pooh.easy, CURLOPT_URL, URL);
+
+  /* get verbose debug output please */
+  test_setopt(pooh.easy, CURLOPT_VERBOSE, 1L);
+
+  /* include headers in the output */
+  test_setopt(pooh.easy, CURLOPT_HEADER, 1L);
+
+#if defined(LIB670) || defined(LIB671)
+  /* Build the mime tree. */
+  mime = curl_mime_init(pooh.easy);
+  part = curl_mime_addpart(mime);
+  result = curl_mime_name(part, name);
+  if(!result)
+    res = curl_mime_data_cb(part, (curl_off_t) 2, read_callback,
+                            NULL, NULL, &pooh);
+
+  if(result) {
+    fprintf(stderr,
+            "Something went wrong when building the mime structure: %d\n",
+            (int) result);
+    goto test_cleanup;
+  }
+
+  /* Bind mime data to its easy handle. */
+  if(!res)
+    test_setopt(pooh.easy, CURLOPT_MIMEPOST, mime);
+#else
+  /* Build the form. */
+  formrc = curl_formadd(&formpost, &lastptr,
+                        CURLFORM_COPYNAME, name,
+                        CURLFORM_STREAM, &pooh,
+                        CURLFORM_CONTENTLEN, (curl_off_t) 2,
+                        CURLFORM_END);
+  if(formrc) {
+    fprintf(stderr, "curl_formadd() = %d\n", (int) formrc);
+    goto test_cleanup;
+  }
+
+  /* We want to use our own read function. */
+  test_setopt(pooh.easy, CURLOPT_READFUNCTION, read_callback);
+
+  /* Send a multi-part formpost. */
+  test_setopt(pooh.easy, CURLOPT_HTTPPOST, formpost);
+#endif
+
+#if defined(LIB670) || defined(LIB672)
+  /* Use the multi interface. */
+  multi = curl_multi_init();
+  mres = curl_multi_add_handle(multi, pooh.easy);
+  while(!mres) {
+    struct timeval timeout;
+    int rc = 0;
+    fd_set fdread;
+    fd_set fdwrite;
+    fd_set fdexcept;
+    int maxfd = -1;
+
+    mres = curl_multi_perform(multi, &still_running);
+    if(!still_running || mres != CURLM_OK)
+      break;
+
+    if(pooh.origin) {
+      time_t delta = time(NULL) - pooh.origin;
+
+      if(delta >= 4 * PAUSE_TIME) {
+        fprintf(stderr, "unpausing failed: drain problem?\n");
+        res = CURLE_OPERATION_TIMEDOUT;
+        break;
+      }
+
+      if(delta >= PAUSE_TIME)
+        curl_easy_pause(pooh.easy, CURLPAUSE_CONT);
+    }
+
+    FD_ZERO(&fdread);
+    FD_ZERO(&fdwrite);
+    FD_ZERO(&fdexcept);
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 1000000 * PAUSE_TIME / 10;
+    mres = curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcept, &maxfd);
+    if(mres)
+      break;
+#ifdef _WIN32
+    if(maxfd == -1)
+      Sleep(100);
+    else
+#endif
+    rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcept, &timeout);
+    if(rc == -1) {
+      fprintf(stderr, "Select error\n");
+      break;
+    }
+  }
+
+  if(mres != CURLM_OK)
+    for(;;) {
+      msg = curl_multi_info_read(multi, &msgs_left);
+      if(!msg)
+        break;
+      if(msg->msg == CURLMSG_DONE) {
+        result = msg->data.result;
+        res = (int) result;
+      }
+    }
+
+  curl_multi_remove_handle(multi, pooh.easy);
+  curl_multi_cleanup(multi);
+
+#else
+  /* Use the easy interface. */
+  test_setopt(pooh.easy, CURLOPT_XFERINFODATA, &pooh);
+  test_setopt(pooh.easy, CURLOPT_XFERINFOFUNCTION, xferinfo);
+  test_setopt(pooh.easy, CURLOPT_NOPROGRESS, 0L);
+  result = curl_easy_perform(pooh.easy);
+  res = (int) result;
+#endif
+
+
+test_cleanup:
+  curl_easy_cleanup(pooh.easy);
+#if defined(LIB670) || defined(LIB671)
+  curl_mime_free(mime);
+#else
+  curl_formfree(formpost);
+#endif
+
+  curl_global_cleanup();
+  return res;
+}
diff --git a/tests/libtest/mk-lib1521.pl b/tests/libtest/mk-lib1521.pl
index 9f25ce2fb..27fadcfce 100755
--- a/tests/libtest/mk-lib1521.pl
+++ b/tests/libtest/mk-lib1521.pl
@@ -6,7 +6,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 2017 - 2019, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 2017 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -173,45 +173,45 @@ HEADER
     ;
 
 while(<STDIN>) {
-    if($_ =~ /^  CINIT\(([^ ]*), ([^ ]*), (\d*)\)/) {
+    if($_ =~ /^  CURLOPT\(([^ ]*), ([^ ]*), (\d*)\)/) {
         my ($name, $type, $val)=($1, $2, $3);
         my $w="  ";
-        my $pref = "${w}res = curl_easy_setopt(curl, CURLOPT_$name,";
+        my $pref = "${w}res = curl_easy_setopt(curl, $name,";
         my $i = ' ' x (length($w) + 23);
-        my $check = "  if(UNEX(res)) {\n    err(\"$name\", res, __LINE__); 
goto test_cleanup; }\n";
-        if($type eq "STRINGPOINT") {
+        my $check = "  if(UNEX(res)) {\n    err(\"$name\", res, __LINE__);\n   
 goto test_cleanup;\n  }\n";
+        if($type eq "CURLOPTTYPE_STRINGPOINT") {
             print "${pref} \"string\");\n$check";
             print "${pref} NULL);\n$check";
         }
-        elsif($type eq "LONG") {
+        elsif($type eq "CURLOPTTYPE_LONG") {
             print "${pref} 0L);\n$check";
             print "${pref} 22L);\n$check";
             print "${pref} LO);\n$check";
             print "${pref} HI);\n$check";
         }
-        elsif($type eq "OBJECTPOINT") {
+        elsif($type eq "CURLOPTTYPE_OBJECTPOINT") {
             if($name =~ /DEPENDS/) {
               print "${pref} dep);\n$check";
             }
             elsif($name =~ "SHARE") {
               print "${pref} share);\n$check";
             }
-            elsif($name eq "ERRORBUFFER") {
+            elsif($name eq "CURLOPT_ERRORBUFFER") {
               print "${pref} errorbuffer);\n$check";
             }
-            elsif(($name eq "POSTFIELDS") ||
-                  ($name eq "COPYPOSTFIELDS")) {
-              # set size to zero to avoid it being "illegal"
-              print "  (void)curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 
0);\n";
-              print "${pref} stringpointerextra);\n$check";
+            elsif(($name eq "CURLOPT_POSTFIELDS") ||
+                  ($name eq "CURLOPT_COPYPOSTFIELDS")) {
+                # set size to zero to avoid it being "illegal"
+                print "  (void)curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 
0);\n";
+                print "${pref} stringpointerextra);\n$check";
             }
-            elsif($name eq "HTTPPOST") {
+            elsif($name eq "CURLOPT_HTTPPOST") {
               print "${pref} httppost);\n$check";
             }
-            elsif($name eq "MIMEPOST") {
+            elsif($name eq "CURLOPT_MIMEPOST") {
               print "${pref} mimepost);\n$check";
             }
-            elsif($name eq "STDERR") {
+            elsif($name eq "CURLOPT_STDERR") {
               print "${pref} stream);\n$check";
             }
             else {
@@ -219,20 +219,21 @@ while(<STDIN>) {
             }
             print "${pref} NULL);\n$check";
         }
-        elsif($type eq "SLISTPOINT") {
+        elsif($type eq "CURLOPTTYPE_SLISTPOINT") {
             print "${pref} slist);\n$check";
         }
-        elsif($type eq "FUNCTIONPOINT") {
+        elsif($type eq "CURLOPTTYPE_FUNCTIONPOINT") {
             if($name =~ /([^ ]*)FUNCTION/) {
-              my $l=lc($1);
-              print "${pref}\n$i${l}cb);\n$check";
+                my $l=lc($1);
+                $l =~ s/^curlopt_//;
+                print "${pref}\n$i${l}cb);\n$check";
             }
             else {
-              print "${pref} &func);\n$check";
+                print "${pref} &func);\n$check";
             }
             print "${pref} NULL);\n$check";
         }
-        elsif($type eq "OFF_T") {
+        elsif($type eq "CURLOPTTYPE_OFF_T") {
             # play conservative to work with 32bit curl_off_t
             print "${pref} OFF_NO);\n$check";
             print "${pref} OFF_HI);\n$check";
@@ -249,7 +250,7 @@ while(<STDIN>) {
           ($_ =~ /^  CURLINFO_([^ ]*) *= *CURLINFO_([^ ]*)/)) {
        my ($info, $type)=($1, $2);
        my $c = "  res = curl_easy_getinfo(curl, CURLINFO_$info,";
-       my $check = "  if(UNEX(res)) {\n    geterr(\"$info\", res, __LINE__); 
goto test_cleanup; }\n";
+       my $check = "  if(UNEX(res)) {\n    geterr(\"$info\", res, __LINE__);\n 
   goto test_cleanup;\n  }\n";
        if($type eq "STRING") {
          print "$c &charp);\n$check";
        }
diff --git a/tests/python_dependencies/impacket/smbserver.py 
b/tests/python_dependencies/impacket/smbserver.py
index 3473c9f0c..c481b27ba 100644
--- a/tests/python_dependencies/impacket/smbserver.py
+++ b/tests/python_dependencies/impacket/smbserver.py
@@ -26,7 +26,10 @@ import socket
 import time
 import datetime
 import struct
-import ConfigParser
+try: # Python 3
+    import configparser
+except ImportError: # Python 2
+    import ConfigParser as configparser
 import SocketServer
 import threading
 import logging
@@ -4130,7 +4133,7 @@ smb.SMB.TRANS_TRANSACT_NMPIPE          
:self.__smbTransHandler.transactNamedPipe
         if self.__serverConfig is None:
             if configFile is None:
                 configFile = 'smb.conf'
-            self.__serverConfig = ConfigParser.ConfigParser()
+            self.__serverConfig = configparser.ConfigParser()
             self.__serverConfig.read(configFile)
 
         self.__serverName   = self.__serverConfig.get('global','server_name')
diff --git a/tests/rtspserver.pl b/tests/rtspserver.pl
index 02d2f9f90..026a81950 100755
--- a/tests/rtspserver.pl
+++ b/tests/rtspserver.pl
@@ -34,6 +34,10 @@ use serverhelp qw(
     server_logfilename
     );
 
+use sshhelp qw(
+    exe_ext
+    );
+
 my $verbose = 0;     # set to 1 for debugging
 my $port = 8990;     # just a default
 my $ipvnum = 4;      # default IP version of rtsp server
@@ -106,4 +110,4 @@ if(!$logfile) {
 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
 $flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\"";
 
-exec("server/rtspd $flags");
+exec("server/rtspd".exe_ext('SRV')." $flags");
diff --git a/tests/runtests.1 b/tests/runtests.1
index fab635233..26cd3afb9 100644
--- a/tests/runtests.1
+++ b/tests/runtests.1
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 .\" *
 .\" * This software is licensed as described in the file COPYING, which
 .\" * you should have received as part of this distribution. The terms
@@ -20,28 +20,37 @@
 .\" *
 .\" **************************************************************************
 .\"
-.TH runtests.pl 1 "2 Feb 2010" "Curl 7.20.0" "runtests"
+.TH runtests.pl 1 "2 Feb 2010" "Curl 7.69.0" "runtests"
 .SH NAME
 runtests.pl \- run one or more test cases
 .SH SYNOPSIS
-.B runtests.pl [options] [test number] [!test number] [key word] [!key word]
+.B runtests.pl [options] [tests]
 .SH DESCRIPTION
 \fIruntests.pl\fP runs one, several or all the existing test cases in curl's
 test suite. It is often called from the root Makefile of the curl package with
 \&'make test'.
-.SH "TEST NUMBER"
-If no test case number is given, all existing tests that the script can find
-will be considered for running. You can specify single test cases to run,
-space-separated, like "1 3 5 7 11", and you can specify a range like "45 to
-67". You can also specify only the tests you don't want to run by listing
-the numbers with a leading exclamation point, like "!66".
-.P
-It is also possible to specify tests to skip based on a key word describing
-the test. These are specified with a leading exclamation point and the
-key word or phrase, like "!HTTP NTLM auth".  Likewise, tests to run can
-be specified simply by specifying the unadorned key words, like "FTPS".
-Remember that the exclamation marks and spaces will need to be quoted somehow
-when entered at many command shells.
+.SH "TESTS"
+Specify which test(s) to run by specifying test numbers or keywords.
+
+If no test number or keyword is given, all existing tests that the script can
+find will be considered for running. You can specify single test cases to run
+by specifying test numbers space-separated, like "1 3 5 7 11", and you can
+specify a range of tests like "45 to 67".
+
+Specify tests to not run with a leading exclamation point, like "!66", which
+runs all available tests except number 66.
+
+Prefix a test number with a tilde (~) to still run it, but ignore the results.
+
+It is also possible to specify tests based on a keyword describing the test(s)
+to run, like "FTPS". The keywords are strings used in the indiviual tests.
+
+You can also specify keywords with a leading exclamation point and the keyword
+or phrase, like "!HTTP NTLM auth" to run all tests \fBexcept\fP those using
+this keyword. Remember that the exclamation marks and spaces will need to be
+quoted somehow when entered at many command shells.
+
+Prefix a keyword with a tilde (~) to still run it, but ignore the results.
 .SH OPTIONS
 .IP "-a"
 Continue running the rest of the test cases even if one test fails. By
@@ -78,6 +87,9 @@ people checking the failures and the reasons for them might 
not have physical
 access to the machine and logs.
 .IP "-R"
 Run the tests in a scrambled, or randomized, order instead of sequentially.
+
+The random seed initially set for this is fixed per month and can be set with
+\fI--seed\fP.
 .IP "-r"
 Display run time statistics. (Requires Perl Time::HiRes module)
 .IP "-rf"
@@ -91,11 +103,18 @@ If \fB-R\fP is also used, the scrambling is done after the 
repeats have
 extended the test sequence.
 .IP "-s"
 Shorter output. Speaks less than default.
-.IP "--shallow=[num](,seed)"
+.IP "--seed=[num]"
+When using \fI--shallow\fP or \fI-R\rP that random certain aspects of the
+behavior, this option can set the initial seed. If not set, the random seed
+will be set based on the currently set local year and month and the first line
+of the "curl -V" output.
+.IP "--shallow=[num]"
 Used together with \fB-t\fP. This limits the number of tests to fail in
 torture mode to no more than 'num' per test case. If this reduces the amount,
-the given 'seed' will be used to randomly discard entries to fail until the
-amount is 'num'.
+the script will randomly discard entries to fail until the amount is 'num'.
+
+The random seed initially set for this is fixed per month and can be set with
+\fI--seed\fP.
 .IP "-t[num]"
 Selects a \fBtorture\fP test for the given tests. This makes runtests.pl first
 run the tests once and count the number of memory allocations made. It then
diff --git a/tests/runtests.pl b/tests/runtests.pl
index e5c10858c..47c3931af 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -6,7 +6,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
 #
 # This software is licensed as described in the file COPYING, which
 # you should have received as part of this distribution. The terms
@@ -69,6 +69,7 @@ BEGIN {
 use strict;
 use warnings;
 use Cwd;
+use Digest::MD5 qw(md5);
 
 # Subs imported from serverhelp module
 use serverhelp qw(
@@ -110,6 +111,8 @@ use pathhelp;
 require "getpart.pm"; # array functions
 require "valgrind.pm"; # valgrind report parser
 require "ftp.pm";
+require "azure.pm";
+require "appveyor.pm";
 
 my $HOSTIP="127.0.0.1";   # address on which the test server listens
 my $HOST6IP="[::1]";      # address on which the test server listens
@@ -117,6 +120,8 @@ my $CLIENTIP="127.0.0.1"; # address which curl uses for 
incoming connections
 my $CLIENT6IP="[::1]";    # address which curl uses for incoming connections
 
 my $base = 8990; # base port number
+my $minport;     # minimum used port number
+my $maxport;     # maximum used port number
 
 my $HTTPPORT;            # HTTP server port
 my $HTTP6PORT;           # HTTP IPv6 server port
@@ -149,6 +154,8 @@ my $SMBPORT;             # SMB server port
 my $SMBSPORT;            # SMBS server port
 my $NEGTELNETPORT;       # TELNET server port with negotiation
 
+my $SSHSRVMD5;           # MD5 of ssh server public key
+
 my $srcdir = $ENV{'srcdir'} || '.';
 my $CURL="../src/gnurl".exe_ext('TOOL'); # what curl executable to run on the 
tests
 my $VCURL=$CURL;   # what curl binary to use to verify the servers with
@@ -163,7 +170,7 @@ my $UNITDIR="./unit";
 my $SERVERIN="$LOGDIR/server.input"; # what curl sent the server
 my $SERVER2IN="$LOGDIR/server2.input"; # what curl sent the second server
 my $PROXYIN="$LOGDIR/proxy.input"; # what curl sent the proxy
-my $CURLLOG="$LOGDIR/curl.log"; # all command lines run
+my $CURLLOG="commands.log"; # all command lines run
 my $FTPDCMD="$LOGDIR/ftpserver.cmd"; # copy ftp server instructions here
 my $SERVERLOGS_LOCK="$LOGDIR/serverlogs.lock"; # server logs advisor read lock
 my $CURLCONFIG="../gnurl-config"; # curl-config from current build
@@ -241,6 +248,7 @@ my $has_altsvc;     # set if libcurl is built with alt-svc 
support
 my $has_ldpreload;  # set if curl is built for systems supporting LD_PRELOAD
 my $has_multissl;   # set if curl is build with MultiSSL support
 my $has_manual;     # set if curl is built with built-in manual
+my $has_win32;      # set if curl is built for Windows
 
 # this version is decided by the particular nghttp2 library that is being used
 my $h2cver = "h2c";
@@ -249,7 +257,6 @@ my $has_openssl;    # built with a lib using an 
OpenSSL-like API
 my $has_gnutls;     # built with GnuTLS
 my $has_nss;        # built with NSS
 my $has_wolfssl;    # built with wolfSSL
-my $has_polarssl;   # built with polarssl
 my $has_winssl;     # built with WinSSL    (Secure Channel aka Schannel)
 my $has_darwinssl;  # built with DarwinSSL (Secure Transport)
 my $has_boringssl;  # built with BoringSSL
@@ -272,8 +279,10 @@ my $skipped=0;  # number of tests skipped; reported in 
main loop
 my %skipped;    # skipped{reason}=counter, reasons for skip
 my @teststat;   # teststat[testnum]=reason, reasons for skip
 my %disabled_keywords;  # key words of tests to skip
+my %ignored_keywords;   # key words of tests to ignore results
 my %enabled_keywords;   # key words of tests to run
 my %disabled;           # disabled test cases
+my %ignored;            # ignored results of test cases
 
 my $sshdid;      # for socks server, ssh daemon version id
 my $sshdvernum;  # for socks server, ssh daemon version number
@@ -295,7 +304,8 @@ my %timevrfyend; # timestamp for each test result 
verification end
 
 my $testnumcheck; # test number, set in singletest sub.
 my %oldenv;
-my %feature; # array of enabled features
+my %feature;      # array of enabled features
+my %keywords;     # array of keywords from the test spec
 
 #######################################################################
 # variables that command line options may set
@@ -323,7 +333,11 @@ my $torture;
 my $tortnum;
 my $tortalloc;
 my $shallow;
-my $shallowseed;
+my $randseed = 0;
+
+# Azure Pipelines specific variables
+my $AZURE_RUN_ID = 0;
+my $AZURE_RESULT_ID = 0;
 
 #######################################################################
 # logmsg is our general message logging subroutine.
@@ -471,7 +485,7 @@ sub startnew {
             logmsg "startnew: failed to write fake $pidfile with pid=$child\n";
         }
         # could/should do a while connect fails sleep a bit and loop
-        sleep $timeout;
+        portable_sleep($timeout);
         if (checkdied($child)) {
             logmsg "startnew: child process has failed to start\n" 
if($verbose);
             return (-1,-1);
@@ -2129,6 +2143,18 @@ sub runsshserver {
         return (0,0);
     }
 
+    my $hstpubmd5f = "curl_host_rsa_key.pub_md5";
+    if(!open(PUBMD5FILE, "<", $hstpubmd5f) ||
+       (read(PUBMD5FILE, $SSHSRVMD5, 32) != 32) ||
+       !close(PUBMD5FILE) ||
+       ($SSHSRVMD5 !~ /^[a-f0-9]{32}$/i))
+    {
+        my $msg = "Fatal: $srvrname pubkey md5 missing : \"$hstpubmd5f\" : $!";
+        logmsg "$msg\n";
+        stopservers($verbose);
+        die $msg;
+    }
+
     if($verbose) {
         logmsg "RUN: $srvrname server is now running PID $pid2\n";
     }
@@ -2172,7 +2198,7 @@ sub runsocksserver {
     $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
 
     # start our socks server, get commands from the FTP cmd file
-    my $cmd="server/socksd".
+    my $cmd="server/socksd".exe_ext('SRV').
         " --port $port ".
         " --pidfile $pidfile".
         " --backend $HOSTIP".
@@ -2559,7 +2585,7 @@ sub cleardir {
     opendir(DIR, $dir) ||
         return 0; # can't open dir
     while($file = readdir(DIR)) {
-        if($file !~ /^\./) {
+        if(($file !~ /^\./)) {
             unlink("$dir/$file");
             $count++;
         }
@@ -2632,6 +2658,7 @@ sub setupfeatures {
     $feature{"alt-svc"} = $has_altsvc;
     $feature{"manual"} = $has_manual;
     $feature{"unix-sockets"} = $has_unix;
+    $feature{"win32"} = $has_win32;
 
     # make each protocol an enabled "feature"
     for my $p (@protocols) {
@@ -2685,7 +2712,7 @@ sub checksystem {
     @version = <VERSOUT>;
     close(VERSOUT);
 
-    open(DISABLED, "server/disabled|");
+    open(DISABLED, "server/disabled".exe_ext('TOOL')."|");
     @disabled = <DISABLED>;
     close(DISABLED);
 
@@ -2711,6 +2738,7 @@ sub checksystem {
                 # Win32-style path.
                 $pwd = pathhelp::sys_native_current_path();
                 $has_textaware = 1;
+                $has_win32 = 1;
             }
            if ($libcurl =~ /(winssl|schannel)/i) {
                $has_winssl=1;
@@ -2732,10 +2760,6 @@ sub checksystem {
                $has_wolfssl=1;
                $has_sslpinning=1;
            }
-           elsif ($libcurl =~ /polarssl/i) {
-               $has_polarssl=1;
-               $has_sslpinning=1;
-           }
            elsif ($libcurl =~ /securetransport/i) {
                $has_darwinssl=1;
                $has_sslpinning=1;
@@ -3008,6 +3032,8 @@ sub checksystem {
     logmsg sprintf("* Env: %s%s", $valgrind?"Valgrind ":"",
                    $run_event_based?"event-based ":"");
     logmsg sprintf("%s\n", $libtool?"Libtool ":"");
+    logmsg ("* Seed: $randseed\n");
+    logmsg ("* Port range: $minport-$maxport\n");
 
     if($verbose) {
         logmsg "* Ports:\n";
@@ -3149,8 +3175,18 @@ sub subVariables {
   $$thing =~ s/%SRCDIR/$srcdir/g;
   $$thing =~ s/%USER/$USER/g;
 
+  if($$thing =~ /%SSHSRVMD5/) {
+      if(!$SSHSRVMD5) {
+          my $msg = "Fatal: Missing SSH server pubkey MD5. Is server running?";
+          logmsg "$msg\n";
+          stopservers($verbose);
+          die $msg;
+      }
+      $$thing =~ s/%SSHSRVMD5/$SSHSRVMD5/g;
+  }
+
   # The purpose of FTPTIME2 and FTPTIME3 is to provide times that can be
-  # used for time-out tests and that whould work on most hosts as these
+  # used for time-out tests and that would work on most hosts as these
   # adjust for the startup/check time for this particular host. We needed
   # to do this to make the test suite run better on very slow hosts.
 
@@ -3238,6 +3274,7 @@ sub singletest {
     my $why;
     my $cmd;
     my $disablevalgrind;
+    my $errorreturncode = 1; # 1 means normal error, 2 means ignored error
 
     # fist, remove all lingering log files
     cleardir($LOGDIR);
@@ -3255,6 +3292,10 @@ sub singletest {
     if($disabled{$testnum}) {
         logmsg "Warning: test$testnum is explicitly disabled\n";
     }
+    if($ignored{$testnum}) {
+        logmsg "Warning: test$testnum result is ignored\n";
+        $errorreturncode = 2;
+    }
 
     # load the test case file definition
     if(loadtest("${TESTDIR}/test${testnum}")) {
@@ -3304,21 +3345,30 @@ sub singletest {
     }
 
     if(!$why) {
-        my @keywords = getpart("info", "keywords");
+        my @info_keywords = getpart("info", "keywords");
         my $match;
         my $k;
 
-        if(!$keywords[0]) {
+        # Clear the list of keywords from the last test
+        %keywords = ();
+
+        if(!$info_keywords[0]) {
             $why = "missing the <keywords> section!";
         }
 
-        for $k (@keywords) {
+        for $k (@info_keywords) {
             chomp $k;
             if ($disabled_keywords{lc($k)}) {
                 $why = "disabled by keyword";
             } elsif ($enabled_keywords{lc($k)}) {
                 $match = 1;
             }
+            if ($ignored_keywords{lc($k)}) {
+                logmsg "Warning: test$testnum result is ignored due to $k\n";
+                $errorreturncode = 2;
+            }
+
+            $keywords{$k} = 1;
         }
 
         if(!$why && !$match && %enabled_keywords) {
@@ -3341,6 +3391,19 @@ sub singletest {
         delete $oldenv{$var};
     }
 
+    # get the name of the test early
+    my @testname= getpart("client", "name");
+    my $testname = $testname[0];
+    $testname =~ s/\n//g;
+
+    # create test result in CI services
+    if(azure_check_environment() && $AZURE_RUN_ID) {
+        $AZURE_RESULT_ID = azure_create_test_result($AZURE_RUN_ID, $testnum, 
$testname);
+    }
+    elsif(appveyor_check_environment()) {
+        appveyor_create_test_result($testnum, $testname);
+    }
+
     # remove test server commands file before servers are started/verified
     unlink($FTPDCMD) if(-f $FTPDCMD);
 
@@ -3500,9 +3563,6 @@ sub singletest {
     my $CURLOUT="$LOGDIR/curl$testnum.out"; # curl output if not stdout
 
     # name of the test
-    my @testname= getpart("client", "name");
-    my $testname = $testname[0];
-    $testname =~ s/\n//g;
     logmsg "[$testname]\n" if(!$short);
 
     if($listonly) {
@@ -3614,7 +3674,7 @@ sub singletest {
         $tool=$CMDLINE;
         $disablevalgrind=1;
     }
-    elsif(!$tool) {
+    elsif(!$tool && !$keywords{"unittest"}) {
         # run curl, add suitable command line options
         my $inc="";
         if((!$cmdhash{'option'}) || ($cmdhash{'option'} !~ /no-include/)) {
@@ -3634,6 +3694,11 @@ sub singletest {
         $cmdargs = " $cmd"; # $cmd is the command line for the test file
         $CURLOUT = $STDOUT; # sends received data to stdout
 
+        # Default the tool to a unit test with the same name as the test spec
+        if($keywords{"unittest"} && !$tool) {
+            $tool="unit$testnum";
+        }
+
         if($tool =~ /^lib/) {
             $CMDLINE="$LIBDIR/$tool";
         }
@@ -3703,7 +3768,9 @@ sub singletest {
         logmsg "$CMDLINE\n";
     }
 
+    open(CMDLOG, ">", "$LOGDIR/$CURLLOG");
     print CMDLOG "$CMDLINE\n";
+    close(CMDLOG);
 
     unlink("core");
 
@@ -3778,7 +3845,7 @@ sub singletest {
     if($serverlogslocktimeout) {
         my $lockretry = $serverlogslocktimeout * 20;
         while((-f $SERVERLOGS_LOCK) && $lockretry--) {
-            select(undef, undef, undef, 0.05);
+            portable_sleep(0.05);
         }
         if(($lockretry < 0) &&
            ($serverlogslocktimeout >= $defserverlogslocktimeout)) {
@@ -3795,7 +3862,7 @@ sub singletest {
     # based tests might need a small delay once that the client command has
     # run to avoid false test failures.
 
-    sleep($postcommanddelay) if($postcommanddelay);
+    portable_sleep($postcommanddelay) if($postcommanddelay);
 
     # timestamp removal of server logs advisor read lock
     $timesrvrlog{$testnum} = Time::HiRes::time();
@@ -3884,7 +3951,7 @@ sub singletest {
                 logmsg " postcheck FAILED\n";
                 # timestamp test result verification end
                 $timevrfyend{$testnum} = Time::HiRes::time();
-                return 1;
+                return $errorreturncode;
             }
         }
     }
@@ -3956,7 +4023,7 @@ sub singletest {
 
         $res = compare($testnum, $testname, "stdout", \@actual, \@validstdout);
         if($res) {
-            return 1;
+            return $errorreturncode;
         }
         $ok .= "s";
     }
@@ -4007,7 +4074,7 @@ sub singletest {
 
         $res = compare($testnum, $testname, "stderr", \@actual, \@validstderr);
         if($res) {
-            return 1;
+            return $errorreturncode;
         }
         $ok .= "r";
     }
@@ -4053,7 +4120,7 @@ sub singletest {
 
         $res = compare($testnum, $testname, "protocol", \@out, \@protstrip);
         if($res) {
-            return 1;
+            return $errorreturncode;
         }
 
         $ok .= "p";
@@ -4068,7 +4135,7 @@ sub singletest {
         my @out = loadarray($CURLOUT);
         $res = compare($testnum, $testname, "data", \@out, \@reply);
         if ($res) {
-            return 1;
+            return $errorreturncode;
         }
         $ok .= "d";
     }
@@ -4092,7 +4159,7 @@ sub singletest {
 
         $res = compare($testnum, $testname, "upload", \@out, \@upload);
         if ($res) {
-            return 1;
+            return $errorreturncode;
         }
         $ok .= "u";
     }
@@ -4138,7 +4205,7 @@ sub singletest {
 
         $res = compare($testnum, $testname, "proxy", \@out, \@protstrip);
         if($res) {
-            return 1;
+            return $errorreturncode;
         }
 
         $ok .= "P";
@@ -4196,7 +4263,7 @@ sub singletest {
             $res = compare($testnum, $testname, "output ($filename)",
                            \@generated, \@outfile);
             if($res) {
-                return 1;
+                return $errorreturncode;
             }
 
             $outputok = 1; # output checked
@@ -4226,7 +4293,7 @@ sub singletest {
         logmsg " exit FAILED\n";
         # timestamp test result verification end
         $timevrfyend{$testnum} = Time::HiRes::time();
-        return 1;
+        return $errorreturncode;
     }
 
     if($has_memory_tracking) {
@@ -4249,7 +4316,7 @@ sub singletest {
                 logmsg @memdata;
                 # timestamp test result verification end
                 $timevrfyend{$testnum} = Time::HiRes::time();
-                return 1;
+                return $errorreturncode;
             }
             else {
                 $ok .= "m";
@@ -4266,7 +4333,7 @@ sub singletest {
                 logmsg "ERROR: unable to read $LOGDIR\n";
                 # timestamp test result verification end
                 $timevrfyend{$testnum} = Time::HiRes::time();
-                return 1;
+                return $errorreturncode;
             }
             my @files = readdir(DIR);
             closedir(DIR);
@@ -4281,7 +4348,7 @@ sub singletest {
                 logmsg "ERROR: valgrind log file missing for test $testnum\n";
                 # timestamp test result verification end
                 $timevrfyend{$testnum} = Time::HiRes::time();
-                return 1;
+                return $errorreturncode;
             }
             my @e = valgrindparse("$LOGDIR/$vgfile");
             if(@e && $e[0]) {
@@ -4294,7 +4361,7 @@ sub singletest {
                 }
                 # timestamp test result verification end
                 $timevrfyend{$testnum} = Time::HiRes::time();
-                return 1;
+                return $errorreturncode;
             }
             $ok .= "v";
         }
@@ -4333,6 +4400,9 @@ sub singletest {
         logmsg "PASS: $testnum - $testname\n";
     }
 
+    if($errorreturncode==2) {
+        logmsg "Warning: test$testnum result is ignored, but passed!\n";
+    }
 
     return 0;
 }
@@ -5046,18 +5116,20 @@ while(@ARGV) {
             $tortalloc = $1;
         }
     }
-    elsif($ARGV[0] =~ /--shallow=(\d+)(,|)(\d*)/) {
+    elsif($ARGV[0] =~ /--shallow=(\d+)/) {
         # Fail no more than this amount per tests when running
         # torture.
-        my ($num, $seed)=($1,$3);
+        my ($num)=($1);
         $shallow=$num;
-        $shallowseed=$seed?$seed:1234; # get a real seed later
-        srand($shallowseed); # make it predictable
     }
     elsif($ARGV[0] =~ /--repeat=(\d+)/) {
         # Repeat-run the given tests this many times
         $repeat = $1;
     }
+    elsif($ARGV[0] =~ /--seed=(\d+)/) {
+        # Set a fixed random seed (used for -R and --shallow)
+        $randseed = $1;
+    }
     elsif($ARGV[0] eq "-a") {
         # continue anyway, even if a test fail
         $anyway=1;
@@ -5118,18 +5190,21 @@ Usage: runtests.pl [options] [test selection(s)]
   -l       list all test case names/descriptions
   -n       no valgrind
   -p       print log file contents when a test fails
-  -R       scrambled order
+  -R       scrambled order (uses the random seed, see --seed)
   -r       run time statistics
   -rf      full run time statistics
   -s       short output
-  --shallow=[num](,seed) make the torture tests thinner
+  --seed=[num] set the random seed to a fixed number
+  --shallow=[num] randomly makes the torture tests "thinner"
   -t[N]    torture (simulate function failures); N means fail Nth function
   -v       verbose output
   -vc path use this curl only to verify the existing servers
   [num]    like "5 6 9" or " 5 to 22 " to run those tests only
   [!num]   like "!5 !6 !9" to disable those tests
+  [~num]   like "~5 ~6 ~9" to ignore the result of those tests
   [keyword] like "IPv6" to select only tests containing the key word
   [!keyword] like "!cookies" to disable any tests containing the key word
+  [~keyword] like "~cookies" to ignore results of tests containing key word
 EOHELP
     ;
         exit;
@@ -5162,9 +5237,16 @@ EOHELP
         $fromnum = -1;
         $disabled{$1}=$1;
     }
+    elsif($ARGV[0] =~ /^~(\d+)/) {
+        $fromnum = -1;
+        $ignored{$1}=$1;
+    }
     elsif($ARGV[0] =~ /^!(.+)/) {
         $disabled_keywords{lc($1)}=$1;
     }
+    elsif($ARGV[0] =~ /^~(.+)/) {
+        $ignored_keywords{lc($1)}=$1;
+    }
     elsif($ARGV[0] =~ /^([-[{a-zA-Z].*)/) {
         $enabled_keywords{lc($1)}=$1;
     }
@@ -5175,6 +5257,20 @@ EOHELP
     shift @ARGV;
 }
 
+if(!$randseed) {
+    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
+        localtime(time);
+    # seed of the month. December 2019 becomes 201912
+    $randseed = ($year+1900)*100 + $mon+1;
+    open(C, "$CURL --version 2>/dev/null|");
+    my @c = <C>;
+    close(C);
+    # use the first line of output and get the md5 out of it
+    my $str = md5($c[0]);
+    $randseed += unpack('S', $str);  # unsigned 16 bit value
+}
+srand $randseed;
+
 if(@testthis && ($testthis[0] ne "")) {
     $TESTCASES=join(" ", @testthis);
 }
@@ -5231,6 +5327,8 @@ if ($gdbthis) {
     }
 }
 
+$minport         = $base; # original base port number
+
 $HTTPPORT        = $base++; # HTTP server port
 $HTTPSPORT       = $base++; # HTTPS (stunnel) server port
 $FTPPORT         = $base++; # FTP server port
@@ -5262,6 +5360,8 @@ $SMBSPORT        = $base++; # SMBS port
 $NEGTELNETPORT   = $base++; # TELNET port with negotiation
 $HTTPUNIXPATH    = 'http.sock'; # HTTP server Unix domain socket path
 
+$maxport         = $base-1; # updated base port number
+
 #######################################################################
 # clear and create logging directory:
 #
@@ -5372,14 +5472,6 @@ if($scrambleorder) {
     $TESTCASES = join(" ", @rand);
 }
 
-#######################################################################
-# Start the command line log
-#
-open(CMDLOG, ">$CURLLOG") ||
-    logmsg "can't log command lines to $CURLLOG\n";
-
-#######################################################################
-
 # Display the contents of the given file.  Line endings are canonicalized
 # and excessively long files are elided
 sub displaylogcontent {
@@ -5474,6 +5566,15 @@ sub displaylogs {
     }
 }
 
+#######################################################################
+# Setup Azure Pipelines Test Run (if running in Azure DevOps)
+#
+
+if(azure_check_environment()) {
+    $AZURE_RUN_ID = azure_create_test_run();
+    logmsg "Azure Run ID: $AZURE_RUN_ID\n" if ($verbose);
+}
+
 #######################################################################
 # The main test-loop
 #
@@ -5481,6 +5582,7 @@ sub displaylogs {
 my $failed;
 my $testnum;
 my $ok=0;
+my $ign=0;
 my $total=0;
 my $lasttest=0;
 my @at = split(" ", $TESTCASES);
@@ -5494,6 +5596,16 @@ foreach $testnum (@at) {
     $count++;
 
     my $error = singletest($run_event_based, $testnum, $count, scalar(@at));
+
+    # update test result in CI services
+    if(azure_check_environment() && $AZURE_RUN_ID && $AZURE_RESULT_ID) {
+        $AZURE_RESULT_ID = azure_update_test_result($AZURE_RUN_ID, 
$AZURE_RESULT_ID, $testnum, $error,
+                                                    $timeprepini{$testnum}, 
$timevrfyend{$testnum});
+    }
+    elsif(appveyor_check_environment()) {
+        appveyor_update_test_result($testnum, $error, $timeprepini{$testnum}, 
$timevrfyend{$testnum});
+    }
+
     if($error < 0) {
         # not a test we can run
         next;
@@ -5502,12 +5614,21 @@ foreach $testnum (@at) {
     $total++; # number of tests we've run
 
     if($error>0) {
-        $failed.= "$testnum ";
+        if($error==2) {
+            # ignored test failures are wrapped in ()
+            $failed.= "($testnum) ";
+        }
+        else {
+            $failed.= "$testnum ";
+        }
         if($postmortem) {
             # display all files in log/ in a nice way
             displaylogs($testnum);
         }
-        if(!$anyway) {
+        if($error==2) {
+            $ign++; # ignored test result counter
+        }
+        elsif(!$anyway) {
             # a test failed, abort
             logmsg "\n - abort tests\n";
             last;
@@ -5523,9 +5644,12 @@ foreach $testnum (@at) {
 my $sofar = time() - $start;
 
 #######################################################################
-# Close command log
+# Finish Azure Pipelines Test Run (if running in Azure DevOps)
 #
-close(CMDLOG);
+
+if(azure_check_environment() && $AZURE_RUN_ID) {
+    $AZURE_RUN_ID = azure_update_test_run($AZURE_RUN_ID);
+}
 
 # Tests done, stop the servers
 stopservers($verbose);
@@ -5580,6 +5704,6 @@ if($skipped && !$short) {
     }
 }
 
-if($total && ($ok != $total)) {
+if($total && (($ok+$ign) != $total)) {
     exit 1;
 }
diff --git a/tests/server/sws.c b/tests/server/sws.c
index 10982b63a..b397ed19b 100644
--- a/tests/server/sws.c
+++ b/tests/server/sws.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -118,6 +118,8 @@ struct httprequest {
   int rcmd;       /* doing a special command, see defines above */
   int prot_version;  /* HTTP version * 10 */
   int callcount;  /* times ProcessRequest() gets called */
+  bool skipall;   /* skip all incoming data */
+  bool noexpect;  /* refuse Expect: (don't read the body) */
   bool connmon;   /* monitor the state of the connection, log disconnects */
   bool upgrade;   /* test case allows upgrade to http2 */
   bool upgrade_request; /* upgrade request found and allowed */
@@ -179,6 +181,9 @@ const char *serverlogfile = DEFAULT_LOGFILE;
 /* close connection */
 #define CMD_SWSCLOSE "swsclose"
 
+/* deny Expect: requests */
+#define CMD_NOEXPECT "no-expect"
+
 #define END_OF_HEADERS "\r\n\r\n"
 
 enum {
@@ -427,6 +432,10 @@ static int parse_servercmd(struct httprequest *req)
         logmsg("instructed to skip this number of bytes %d", num);
         req->skip = num;
       }
+      else if(!strncmp(CMD_NOEXPECT, cmd, strlen(CMD_NOEXPECT))) {
+        logmsg("instructed to reject Expect: 100-continue");
+        req->noexpect = TRUE;
+      }
       else if(1 == sscanf(cmd, "writedelay: %d", &num)) {
         logmsg("instructed to delay %d secs between packets", num);
         req->writedelay = num;
@@ -605,7 +614,7 @@ static int ProcessRequest(struct httprequest *req)
     }
 
     if(req->testno == DOCNUMBER_NOTHING) {
-      /* Still no test case number. Try to get the the number off the last dot
+      /* Still no test case number. Try to get the number off the last dot
          instead, IE we consider the TLD to be the test number. Test 123 can
          then be written as "example.com.123". */
 
@@ -735,19 +744,28 @@ static int ProcessRequest(struct httprequest *req)
         req->open = FALSE; /* closes connection */
         return 1; /* done */
       }
-      req->cl = clen - req->skip;
+      if(req->skipall)
+        req->cl = 0;
+      else
+        req->cl = clen - req->skip;
 
       logmsg("Found Content-Length: %lu in the request", clen);
       if(req->skip)
         logmsg("... but will abort after %zu bytes", req->cl);
-      break;
     }
     else if(strncasecompare("Transfer-Encoding: chunked", line,
                             strlen("Transfer-Encoding: chunked"))) {
       /* chunked data coming in */
       chunked = TRUE;
     }
-
+    else if(req->noexpect &&
+            strncasecompare("Expect: 100-continue", line,
+                            strlen("Expect: 100-continue"))) {
+      if(req->cl)
+        req->cl = 0;
+      req->skipall = TRUE;
+      logmsg("Found Expect: 100-continue, ignore body");
+    }
 
     if(chunked) {
       if(strstr(req->reqbuf, "\r\n0\r\n\r\n")) {
@@ -939,6 +957,8 @@ static void init_httprequest(struct httprequest *req)
   req->digest = FALSE;
   req->ntlm = FALSE;
   req->skip = 0;
+  req->skipall = FALSE;
+  req->noexpect = FALSE;
   req->writedelay = 0;
   req->rcmd = RCMD_NORMALREQ;
   req->prot_version = 0;
@@ -2143,7 +2163,7 @@ int main(int argc, char *argv[])
   case AF_UNIX:
     memset(&me.sau, 0, sizeof(me.sau));
     me.sau.sun_family = AF_UNIX;
-    strncpy(me.sau.sun_path, unix_socket, sizeof(me.sau.sun_path));
+    strncpy(me.sau.sun_path, unix_socket, sizeof(me.sau.sun_path) - 1);
     rc = bind(sock, &me.sa, sizeof(me.sau));
     if(0 != rc && errno == EADDRINUSE) {
       struct stat statbuf;
diff --git a/tests/server/util.h b/tests/server/util.h
index 7b4ec1626..236d4550e 100644
--- a/tests/server/util.h
+++ b/tests/server/util.h
@@ -37,16 +37,16 @@ extern const char *path;
 /* global variable, log file name */
 extern const char *serverlogfile;
 
-#ifdef WIN32
+#if defined(WIN32) || defined(_WIN32)
 #include <process.h>
 #include <fcntl.h>
 
-#define sleep(sec)   Sleep ((sec)*1000)
+#define sleep(sec) Sleep ((sec)*1000)
 
 #undef perror
 #define perror(m) win32_perror(m)
 void win32_perror(const char *msg);
-#endif  /* WIN32 */
+#endif  /* WIN32 or _WIN32 */
 
 #ifdef USE_WINSOCK
 void win32_init(void);
diff --git a/tests/sshhelp.pm b/tests/sshhelp.pm
index 248be67a2..e43f86532 100644
--- a/tests/sshhelp.pm
+++ b/tests/sshhelp.pm
@@ -50,6 +50,7 @@ use vars qw(
     $sftpcmds
     $hstprvkeyf
     $hstpubkeyf
+    $hstpubmd5f
     $cliprvkeyf
     $clipubkeyf
     @sftppath
@@ -82,6 +83,7 @@ use vars qw(
     $sftpcmds
     $hstprvkeyf
     $hstpubkeyf
+    $hstpubmd5f
     $cliprvkeyf
     $clipubkeyf
     display_sshdconfig
@@ -122,6 +124,7 @@ $sftpcmds        = 'curl_sftp_cmds';         # sftp client 
commands batch file
 $knownhosts      = 'curl_client_knownhosts'; # ssh knownhosts file
 $hstprvkeyf      = 'curl_host_rsa_key';      # host private key file
 $hstpubkeyf      = 'curl_host_rsa_key.pub';  # host public key file
+$hstpubmd5f      = 'curl_host_rsa_key.pub_md5';  # md5 hash of host public key
 $cliprvkeyf      = 'curl_client_key';        # client private key file
 $clipubkeyf      = 'curl_client_key.pub';    # client public key file
 
diff --git a/tests/sshserver.pl b/tests/sshserver.pl
index 197e8b872..4414ca51b 100644
--- a/tests/sshserver.pl
+++ b/tests/sshserver.pl
@@ -28,6 +28,9 @@ use strict;
 use warnings;
 use Cwd;
 use Cwd 'abs_path';
+use Digest::MD5;
+use Digest::MD5 'md5_hex';
+use MIME::Base64;
 
 #***************************************************************************
 # Variables and subs imported from sshhelp module
@@ -48,6 +51,7 @@ use sshhelp qw(
     $sftpcmds
     $hstprvkeyf
     $hstpubkeyf
+    $hstpubmd5f
     $cliprvkeyf
     $clipubkeyf
     display_sshdconfig
@@ -357,10 +361,11 @@ if((($sshid =~ /OpenSSH/) && ($sshvernum < 299)) ||
 #
 if((! -e $hstprvkeyf) || (! -s $hstprvkeyf) ||
    (! -e $hstpubkeyf) || (! -s $hstpubkeyf) ||
+   (! -e $hstpubmd5f) || (! -s $hstpubmd5f) ||
    (! -e $cliprvkeyf) || (! -s $cliprvkeyf) ||
    (! -e $clipubkeyf) || (! -s $clipubkeyf)) {
     # Make sure all files are gone so ssh-keygen doesn't complain
-    unlink($hstprvkeyf, $hstpubkeyf, $cliprvkeyf, $clipubkeyf);
+    unlink($hstprvkeyf, $hstpubkeyf, $hstpubmd5f, $cliprvkeyf, $clipubkeyf);
     logmsg 'generating host keys...' if($verbose);
     if(system "\"$sshkeygen\" -q -t rsa -f $hstprvkeyf -C 'curl test server' 
-N ''") {
         logmsg 'Could not generate host key';
@@ -374,6 +379,21 @@ if((! -e $hstprvkeyf) || (! -s $hstprvkeyf) ||
     # Make sure that permissions are restricted so openssh doesn't complain
     system "chmod 600 $hstprvkeyf";
     system "chmod 600 $cliprvkeyf";
+    # Save md5 hash of public host key
+    open(RSAKEYFILE, "<$hstpubkeyf");
+    my @rsahostkey = do { local $/ = ' '; <RSAKEYFILE> };
+    close(RSAKEYFILE);
+    if(!$rsahostkey[1]) {
+        logmsg 'Failed parsing base64 encoded RSA host key';
+        exit 1;
+    }
+    open(PUBMD5FILE, ">$hstpubmd5f");
+    print PUBMD5FILE md5_hex(decode_base64($rsahostkey[1]));
+    close(PUBMD5FILE);
+    if((! -e $hstpubmd5f) || (! -s $hstpubmd5f)) {
+        logmsg 'Failed writing md5 hash of RSA host key';
+        exit 1;
+    }
 }
 
 
@@ -1099,8 +1119,8 @@ elsif($verbose && ($rc >> 8)) {
 #***************************************************************************
 # Clean up once the server has stopped
 #
-unlink($hstprvkeyf, $hstpubkeyf, $cliprvkeyf, $clipubkeyf, $knownhosts);
-unlink($sshdconfig, $sshconfig, $sftpconfig);
-
+unlink($hstprvkeyf, $hstpubkeyf, $hstpubmd5f,
+       $cliprvkeyf, $clipubkeyf, $knownhosts,
+       $sshdconfig, $sshconfig, $sftpconfig);
 
 exit 0;
diff --git a/tests/testcurl.pl b/tests/testcurl.pl
index 5000253c3..48f154ec2 100755
--- a/tests/testcurl.pl
+++ b/tests/testcurl.pl
@@ -173,7 +173,7 @@ if ($^O eq 'MSWin32' || $targetos) {
   }
 }
 
-if (($^O eq 'MSWin32' || $^O eq 'msys') &&
+if (($^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'msys') &&
     ($targetos =~ /vc/ || $targetos =~ /mingw32/ ||
      $targetos =~ /borland/ || $targetos =~ /watcom/)) {
 
diff --git a/tests/tftpserver.pl b/tests/tftpserver.pl
index 8c84111bf..c16a9e140 100755
--- a/tests/tftpserver.pl
+++ b/tests/tftpserver.pl
@@ -34,6 +34,10 @@ use serverhelp qw(
     server_logfilename
     );
 
+use sshhelp qw(
+    exe_ext
+    );
+
 my $verbose = 0;     # set to 1 for debugging
 my $port = 8997;     # just a default
 my $ipvnum = 4;      # default IP version of tftp server
@@ -107,4 +111,4 @@ if(!$logfile) {
 $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" ";
 $flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\"";
 
-exec("server/tftpd $flags");
+exec("server/tftpd".exe_ext('SRV')." $flags");
diff --git a/tests/unit/Makefile.inc b/tests/unit/Makefile.inc
index 6ad42bd42..158619657 100644
--- a/tests/unit/Makefile.inc
+++ b/tests/unit/Makefile.inc
@@ -1,3 +1,25 @@
+#***************************************************************************
+#                                  _   _ ____  _
+#  Project                     ___| | | |  _ \| |
+#                             / __| | | | |_) | |
+#                            | (__| |_| |  _ <| |___
+#                             \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, 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.
+#
+###########################################################################
+
 # these files are used in every single unit test program
 
 UNITFILES = curlcheck.h \
@@ -10,7 +32,8 @@ UNITPROGS = unit1300 unit1301 unit1302 unit1303 unit1304 
unit1305 unit1307 \
  unit1330 unit1394 unit1395 unit1396 unit1397 unit1398 \
  unit1399 \
  unit1600 unit1601 unit1602 unit1603 unit1604 unit1605 unit1606 unit1607 \
- unit1608 unit1609 unit1620 unit1621 \
+ unit1608 unit1609 unit1610 unit1611 unit1612 \
+ unit1620 unit1621 \
  unit1650 unit1651 unit1652 unit1653 unit1654 unit1655
 
 unit1300_SOURCES = unit1300.c $(UNITFILES)
@@ -97,6 +120,15 @@ unit1608_CPPFLAGS = $(AM_CPPFLAGS)
 unit1609_SOURCES = unit1609.c $(UNITFILES)
 unit1609_CPPFLAGS = $(AM_CPPFLAGS)
 
+unit1610_SOURCES = unit1610.c $(UNITFILES)
+unit1610_CPPFLAGS = $(AM_CPPFLAGS)
+
+unit1611_SOURCES = unit1611.c $(UNITFILES)
+unit1611_CPPFLAGS = $(AM_CPPFLAGS)
+
+unit1612_SOURCES = unit1612.c $(UNITFILES)
+unit1612_CPPFLAGS = $(AM_CPPFLAGS)
+
 unit1620_SOURCES = unit1620.c $(UNITFILES)
 unit1620_CPPFLAGS = $(AM_CPPFLAGS)
 
diff --git a/tests/unit/unit1300.c b/tests/unit/unit1300.c
index 5cfa6daf3..5d8799779 100644
--- a/tests/unit/unit1300.c
+++ b/tests/unit/unit1300.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -54,7 +54,6 @@ UNITTEST_START
   struct curl_llist_element case2_list;
   struct curl_llist_element case3_list;
   struct curl_llist_element case4_list;
-  struct curl_llist_element case5_list;
   struct curl_llist_element *head;
   struct curl_llist_element *element_next;
   struct curl_llist_element *element_prev;
@@ -216,55 +215,6 @@ UNITTEST_START
   fail_unless(llist.tail == NULL,
               "llist tail is not NULL while the llist is empty");
 
-  /* @testing Curl_llist_move(struct curl_llist *,
-   * struct curl_llist_element *, struct curl_llist *,
-   * struct curl_llist_element *);
-  */
-
-  /**
-   * @case 1:
-   * moving head from an llist containing one element to an empty llist
-   * @assumptions:
-   * 1: llist size will be 0
-   * 2: llist_destination size will be 1
-   * 3: llist head will be NULL
-   * 4: llist_destination head == llist_destination tail != NULL
-   */
-
-  /*
-  * @setup
-  * add one element to the list
-  */
-
-  Curl_llist_insert_next(&llist, llist.head, &unusedData_case1,
-                         &case5_list);
-  /* necessary assertions */
-
-  abort_unless(Curl_llist_count(&llist) == 1,
-  "Number of list elements is not as expected, Aborting");
-  abort_unless(Curl_llist_count(&llist_destination) == 0,
-  "Number of list elements is not as expected, Aborting");
-
-  /*actual testing code*/
-  Curl_llist_move(&llist, llist.head, &llist_destination, NULL);
-  fail_unless(Curl_llist_count(&llist) == 0,
-      "moving element from llist didn't decrement the size");
-
-  fail_unless(Curl_llist_count(&llist_destination) == 1,
-        "moving element to llist_destination didn't increment the size");
-
-  fail_unless(llist.head == NULL,
-      "llist head not set to null after moving the head");
-
-  fail_unless(llist_destination.head != NULL,
-        "llist_destination head set to null after moving an element");
-
-  fail_unless(llist_destination.tail != NULL,
-          "llist_destination tail set to null after moving an element");
-
-  fail_unless(llist_destination.tail == llist_destination.head,
-            "llist_destination tail doesn't equal llist_destination head");
-
   Curl_llist_destroy(&llist, NULL);
   Curl_llist_destroy(&llist_destination, NULL);
 }
diff --git a/tests/unit/unit1601.c b/tests/unit/unit1601.c
index a6120e1c2..bf00bc7e9 100644
--- a/tests/unit/unit1601.c
+++ b/tests/unit/unit1601.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -36,18 +36,20 @@ static void unit_stop(void)
 UNITTEST_START
 
 #ifndef CURL_DISABLE_CRYPTO_AUTH
-  unsigned char output[16];
+  const char string1[] = "1";
+  const char string2[] = "hello-you-fool";
+  unsigned char output[MD5_DIGEST_LEN];
   unsigned char *testp = output;
-  Curl_md5it(output, (const unsigned char *)"1");
 
-/* !checksrc! disable LONGLINE 2 */
-  verify_memory(testp,
-                
"\xc4\xca\x42\x38\xa0\xb9\x23\x82\x0d\xcc\x50\x9a\x6f\x75\x84\x9b", 16);
+  Curl_md5it(output, (const unsigned char *) string1, strlen(string1));
 
-  Curl_md5it(output, (const unsigned char *)"hello-you-fool");
+  verify_memory(testp, "\xc4\xca\x42\x38\xa0\xb9\x23\x82\x0d\xcc\x50\x9a\x6f"
+                "\x75\x84\x9b", MD5_DIGEST_LEN);
 
-  verify_memory(testp,
-                
"\x88\x67\x0b\x6d\x5d\x74\x2f\xad\xa5\xcd\xf9\xb6\x82\x87\x5f\x22", 16);
+  Curl_md5it(output, (const unsigned char *) string2, strlen(string2));
+
+  verify_memory(testp, "\x88\x67\x0b\x6d\x5d\x74\x2f\xad\xa5\xcd\xf9\xb6\x82"
+                "\x87\x5f\x22", MD5_DIGEST_LEN);
 #endif
 
 
diff --git a/tests/unit/unit1601.c b/tests/unit/unit1610.c
similarity index 61%
copy from tests/unit/unit1601.c
copy to tests/unit/unit1610.c
index a6120e1c2..bb9c937c9 100644
--- a/tests/unit/unit1601.c
+++ b/tests/unit/unit1610.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
  ***************************************************************************/
 #include "curlcheck.h"
 
-#include "curl_md5.h"
+#include "curl_sha256.h"
 
 static CURLcode unit_setup(void)
 {
@@ -36,18 +36,24 @@ static void unit_stop(void)
 UNITTEST_START
 
 #ifndef CURL_DISABLE_CRYPTO_AUTH
-  unsigned char output[16];
+  const char string1[] = "1";
+  const char string2[] = "hello-you-fool";
+  unsigned char output[SHA256_DIGEST_LENGTH];
   unsigned char *testp = output;
-  Curl_md5it(output, (const unsigned char *)"1");
 
-/* !checksrc! disable LONGLINE 2 */
+  Curl_sha256it(output, (const unsigned char *) string1, strlen(string1));
+
   verify_memory(testp,
-                
"\xc4\xca\x42\x38\xa0\xb9\x23\x82\x0d\xcc\x50\x9a\x6f\x75\x84\x9b", 16);
+                "\x6b\x86\xb2\x73\xff\x34\xfc\xe1\x9d\x6b\x80\x4e\xff\x5a\x3f"
+                "\x57\x47\xad\xa4\xea\xa2\x2f\x1d\x49\xc0\x1e\x52\xdd\xb7\x87"
+                "\x5b\x4b", SHA256_DIGEST_LENGTH);
 
-  Curl_md5it(output, (const unsigned char *)"hello-you-fool");
+  Curl_sha256it(output, (const unsigned char *) string2, strlen(string2));
 
   verify_memory(testp,
-                
"\x88\x67\x0b\x6d\x5d\x74\x2f\xad\xa5\xcd\xf9\xb6\x82\x87\x5f\x22", 16);
+                "\xcb\xb1\x6a\x8a\xb9\xcb\xb9\x35\xa8\xcb\xa0\x2e\x28\xc0\x26"
+                "\x30\xd1\x19\x9c\x1f\x02\x17\xf4\x7c\x96\x20\xf3\xef\xe8\x27"
+                "\x15\xae", SHA256_DIGEST_LENGTH);
 #endif
 
 
diff --git a/tests/unit/unit1601.c b/tests/unit/unit1611.c
similarity index 67%
copy from tests/unit/unit1601.c
copy to tests/unit/unit1611.c
index a6120e1c2..bc19f8a5c 100644
--- a/tests/unit/unit1601.c
+++ b/tests/unit/unit1611.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -21,7 +21,7 @@
  ***************************************************************************/
 #include "curlcheck.h"
 
-#include "curl_md5.h"
+#include "curl_md4.h"
 
 static CURLcode unit_setup(void)
 {
@@ -36,18 +36,22 @@ static void unit_stop(void)
 UNITTEST_START
 
 #ifndef CURL_DISABLE_CRYPTO_AUTH
-  unsigned char output[16];
+  const char string1[] = "1";
+  const char string2[] = "hello-you-fool";
+  unsigned char output[MD4_DIGEST_LENGTH];
   unsigned char *testp = output;
-  Curl_md5it(output, (const unsigned char *)"1");
 
-/* !checksrc! disable LONGLINE 2 */
+  Curl_md4it(output, (const unsigned char *) string1, strlen(string1));
+
   verify_memory(testp,
-                
"\xc4\xca\x42\x38\xa0\xb9\x23\x82\x0d\xcc\x50\x9a\x6f\x75\x84\x9b", 16);
+                "\x8b\xe1\xec\x69\x7b\x14\xad\x3a\x53\xb3\x71\x43\x61\x20\x64"
+                "\x1d", MD4_DIGEST_LENGTH);
 
-  Curl_md5it(output, (const unsigned char *)"hello-you-fool");
+  Curl_md4it(output, (const unsigned char *) string2, strlen(string2));
 
   verify_memory(testp,
-                
"\x88\x67\x0b\x6d\x5d\x74\x2f\xad\xa5\xcd\xf9\xb6\x82\x87\x5f\x22", 16);
+                "\xa7\x16\x1c\xad\x7e\xbe\xdb\xbc\xf8\xc7\x23\x10\x2d\x2c\xe2"
+                "\x0b", MD4_DIGEST_LENGTH);
 #endif
 
 
diff --git a/tests/unit/unit1601.c b/tests/unit/unit1612.c
similarity index 59%
copy from tests/unit/unit1601.c
copy to tests/unit/unit1612.c
index a6120e1c2..3fb2de033 100644
--- a/tests/unit/unit1601.c
+++ b/tests/unit/unit1612.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -21,6 +21,7 @@
  ***************************************************************************/
 #include "curlcheck.h"
 
+#include "curl_hmac.h"
 #include "curl_md5.h"
 
 static CURLcode unit_setup(void)
@@ -36,18 +37,29 @@ static void unit_stop(void)
 UNITTEST_START
 
 #ifndef CURL_DISABLE_CRYPTO_AUTH
-  unsigned char output[16];
+  const char password[] = "Pa55worD";
+  const char string1[] = "1";
+  const char string2[] = "hello-you-fool";
+  unsigned char output[HMAC_MD5_LENGTH];
   unsigned char *testp = output;
-  Curl_md5it(output, (const unsigned char *)"1");
 
-/* !checksrc! disable LONGLINE 2 */
+  Curl_hmacit(Curl_HMAC_MD5,
+              (const unsigned char *) password, strlen(password),
+              (const unsigned char *) string1, strlen(string1),
+              output);
+
   verify_memory(testp,
-                
"\xc4\xca\x42\x38\xa0\xb9\x23\x82\x0d\xcc\x50\x9a\x6f\x75\x84\x9b", 16);
+                "\xd1\x29\x75\x43\x58\xdc\xab\x78\xdf\xcd\x7f\x2b\x29\x31\x13"
+                "\x37", HMAC_MD5_LENGTH);
 
-  Curl_md5it(output, (const unsigned char *)"hello-you-fool");
+  Curl_hmacit(Curl_HMAC_MD5,
+              (const unsigned char *) password, strlen(password),
+              (const unsigned char *) string2, strlen(string2),
+              output);
 
   verify_memory(testp,
-                
"\x88\x67\x0b\x6d\x5d\x74\x2f\xad\xa5\xcd\xf9\xb6\x82\x87\x5f\x22", 16);
+                "\x75\xf1\xa7\xb9\xf5\x40\xe5\xa4\x98\x83\x9f\x64\x5a\x27\x6d"
+                "\xd0", HMAC_MD5_LENGTH);
 #endif
 
 
diff --git a/tests/unit/unit1651.c b/tests/unit/unit1651.c
index 3652601f9..44dbf4b51 100644
--- a/tests/unit/unit1651.c
+++ b/tests/unit/unit1651.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2018 - 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2018 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -368,7 +368,7 @@ UNITTEST_START
   for(byte = 1 ; byte < 255; byte += 17) {
     for(i = 0; i < 45; i++) {
       char backup = cert[i];
-      cert[i] = (unsigned char)byte&0xff;
+      cert[i] = (unsigned char) (byte & 0xff);
       (void) Curl_extract_certinfo(&conn, 0, beg, end);
       cert[i] = backup;
     }
diff --git a/tests/unit/unit1654.c b/tests/unit/unit1654.c
index a800d9c3a..d05d0b214 100644
--- a/tests/unit/unit1654.c
+++ b/tests/unit/unit1654.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2019, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2019 - 2020, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -124,7 +124,7 @@ UNITTEST_START
   }
   fail_unless(asi->num == 10, "wrong number of entries");
 
-  Curl_altsvc_save(asi, outname);
+  Curl_altsvc_save(curl, asi, outname);
 
   curl_easy_cleanup(curl);
   fail:

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]