gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [gnurl] branch master updated (dc3acc160 -> 64d20516f)


From: gnunet
Subject: [GNUnet-SVN] [gnurl] branch master updated (dc3acc160 -> 64d20516f)
Date: Fri, 06 Oct 2017 19:41:31 +0200

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

ng0 pushed a change to branch master
in repository gnurl.

    from dc3acc160 gnURL: Mention unbound + GnuTLS in the README as "optional 
but recommended".
     add 4ba1569ad RELEASE-NOTES: reset and go toward 7.51.0 (again)
     add d93215621 openssl: fix per-thread memory leak usiong 1.0.1 or 1.0.2
     add d4c5a9172 http: accept "Transfer-Encoding: chunked" for HTTP/2 as well
     add f423a0097 http2: debug ouput sent HTTP/2 request headers
     add 710f0572c KNOWN_BUGS: chunked-encoded requests with HTTP/2 is fixed
     add e01d0f103 LICENSE-MIXING.md: update with mbedTLS dual licensing
     add 45c1c54c4 examples/imap-append: Set size of data to be uploaded
     add 19445f35b test2048: fix url
     add d086b2394 configure: change "iOS/Mac OS X native" to "Apple OS native"
     add 227ee9d84 darwinssl: disable RC4 cipher-suite support
     add 6ee9ea5e7 CURLOPT_PINNEDPUBLICKEY.3: fix the AVAILABILITY formatting
     add fb0032a33 TODO: Support SSLKEYLOGFILE
     add de71e6800 openssl: don’t call CRYTPO_cleanup_all_ex_data
     add a2b360f89 openssl: don't call ERR_remote_thread_state on >= 1.1.0
     add 31dd3bf67 TODO: Add PINNEDPUBLICKEY - HPKP compatibility, HSTS & HPKP
     add 01c8db47a libressl: fix version output
     add 79607eec5 darwinssl: Fix typo in comment
     add 6834ebaaa RELEASE-NOTES: synced with 79607eec51055
     add 22cfeac73 easy: Reset all statistical session info in curl_easy_reset
     add 88e3743dd MAIL-ETIQUETTE: language
     add aab94da61 curl_global_cleanup.3: don't unload the lib with sub threads 
running
     add 82279c82c dist: add CurlSymbolHiding.cmake to the tarball
     add 36e53ec6f docs: Remove that --proto is just used for initial retrieval
     add 759122027 nss: fix typo in ecdhe_rsa_null cipher suite string
     add 049aa9254 nss: add cipher suites using SHA384 if supported by NSS
     add d1f1c857a nss: add chacha20-poly1305 cipher suites if supported by NSS
     add e9e536619 New libcurl option to keep sending on error
     add cd7f562bd SECURITY: remove the top ascii logo
     add 1e7b79731 configure: Fixed builds with libssh2 in a custom location
     add bd742adb6 KNOWN_BUGS: 5.8 configure finding libs in wrong directory
     add 7ea146946 curl.1: --trace supports % for sending to stderr!
     add dd42963a5 CONTRIBUTE.md: Fix typo in 'About pull requests' section. 
(#1045)
     add 9eda44a20 KNOWN_BUGS: Fix typos in section 5.8.
     add 2a1d53896 FAQ: Fix typos in section 5.14 (#1047)
     add 54e48b14e cookies: same domain handling changed to match browser 
behavior
     add bdf162af2 formpost: trying to attach a directory no longer crashes
     add 203c5d5b3 TODO: Add easy argument to formpost functions
     add 8fd2a754f memdup: use 'void *' as return and source type
     add 15aefc6ad CURLOPT_KEEP_SENDING_ON_ERROR.3: mention when it is added
     add 6bf909d5c RELEASE-NOTES: synced with 8fd2a754f0de
     add 2a3bca9aa TODO: TCP Fast Open for windows
     add c271b1c29 CURLOPT_DEBUGFUNCTION.3: unused argument warning (#1056)
     add da1a2d1ac TODO: Leave secure cookies alone
     add 13f391247 TODO: Introduce --fail-fast to exit on first transfer fail
     add 4f43236a4 tests: Fix a small typo in the tests README (#1060)
     add e11da9f4b TODO: Support better than MD5 hostkey hash (for ssh)
     add f74baaf3b TODO: build: Enable PIE and RELRO by default
     add 9885c9508 formpost: avoid silent snprintf() truncation
     add 8238ba9c5 ftp: fix Curl_ftpsendf()
     add 71588c9ae mprintf: return error on too many arguments
     add ac8a31491 test557: verify printf() with 128 and 129 arguments
     add 827204906 smb: properly check incoming packet boundaries
     add f68042a2a RELEASE-NOTES: synced with 82720490628cb53a
     add 8c2b5580a RELEASE-NOTES: spellfix
     add 7cc9c876e GIT-INFO: remove the Mac 10.1-specific details
     add eb5199317 resolve: add error message when resolving using SIGALRM
     add d522ff469 cmake: add nghttp2 support
     add 358fd3282 dist: remove PDF and HTML converted docs from the releases
     add 9297ca49f configure: detect the broken poll() in macOS 10.12
     add 3b36bd8e1 dist: add missing cmake modules to the tarball
     add 1671d84b3 vtls: only re-use session-ids using the same scheme
     add e5f0b1ab4 url: skip to-be-closed connections when pipelining
     add 4ddc772b3 KNOWN_BUGS: minor formatting edit
     add 422db18f1 win: fix Universal Windows Platform build
     add 96e3c0774 KNOWN_BUGS: two more existing problems
     add a1a5cd048 curl: do not set CURLOPT_SSLENGINEDEFAULT automatically
     add f7d6bdca6 RELEASE-NOTES: synced with a1a5cd04877fd6fd
     add 9291a34d5 HTTP2: mention the tool's limited support
     add aec0c993c url: skip to-be-closed connections when pipelining 
(follow-up)
     add d18c54645 maketgz: make it support "only" generating version info
     add 9aa2afc3a Curl_socket_check: add extra check to avoid integer overflow
     add a05906190 select: use more proper macro-looking names
     add 8a6e89a9e select: switch to macros in uppercase
     add 9a509680f gopher: properly return error for poll failures
     add 8e8afa82c curl: set INTERLEAVEDATA too
     add ace237ae4 Curl_polarsslthreadlock_thread_setup: clear array at init
     add 1e3161a20 polarssl: fix unaligned SSL session-id lock
     add 8748d4787 polarssl: reduce #ifdef madness with a macro
     add 88753c1e8 polarssl: indented code, removed unused variables
     add 0f1996321 s/cURL/curl
     add f36f8c145 test14xx: fixed --libcurl output tests again after 
8e8afa82cbb
     add 97dfe3864 RELEASE-NOTES: synced with f36f8c14551efc6772
     add a34c7ce75 configure/CURL_CHECK_FUNC_POLL: disable poll completely on 
mac
     add 5c3d8d20a curl_multi_add_handle: set timeouts in closure handles
     add 4f8d0b6f0 configure: set min version flags for builds on mac
     add c9cb17fbd configure: Check for other variants of the 
-m*os*-version-min flags
     add 8571d1c0b INSTALL: converted to markdown => INSTALL.md
     add a84e0713e testcurl.1: update URLs
     add fc458679c testcurl.1: fix the URL to the autobuild summary
     add 406506ca9 curl_multi_remove_handle: fix a double-free
     add 6290c3c26 multi: force connections to get closed in 
close_all_connections
     add 50ee3aaf1 INSTALL.md: Updated minimum file sizes for 7.50.3
     add c30a2d97e RELEASE-NOTES: synced with 50ee3aaf1a9b22d
     add 1ad2bdcf1 mk-ca-bundle: Change URL retrieval to HTTPS-only by default
     add f435308cf mk-ca-bundle.1: document -k
     add 21b9e5405 TODO: add "--retry should resume"
     add cc8c8f957 TODO: Remove the generated include file
     add 4d7fc0a9b TODO: indent code to make it render properly
     add d2c6d1568 mk-ca-bundle: Update the vbscript version
     add eb84412b3 nss: fix tight loop in non-blocking TLS handhsake over proxy
     add 62a8095e7 mbedtls: stop using deprecated include file
     add 50ef91b59 docs: fix req->data in multi-uv example
     add a65db0bbc SECURITY: minor updates
     add 905f493bd configure.in: Fix test syntax
     add c443a8ce2 KNOWN_BUGS: c-ares deviates from stock resolver on 
http://1346569778
     add 4eb7657a1 KNOWN_BUGS: HTTP/2 server push enabled when no pushes can be 
accepted
     add 568037f6a CURLMOPT_MAX_PIPELINE_LENGTH.3: Clarify it's not for HTTP/2
     add d0623f856 BINDINGS: converted to markdown
     add 2e750ce45 mk-ca-bundle.vbs: Fix UTF-8 output
     add 13f491330 INTERNALS: better markdown
     add 164ee10b0 INTERNALS: better markdown (follow-up)
     add 3bb273db7 urlparse: accept '#' as end of host name
     add 42b650b9e test1246: verify URL parsing with host name ending with '#'
     add 9c91ec778 idn: switch to libidn2 use and IDNA2008 support
     add fba28277c TODO: remove IDNA2008
     add c5be3d726 cookies: getlist() now holds deep copies of all cookies
     add 53e71e47d unescape: avoid integer overflow
     add 46133aa53 escape: avoid using curl_easy_unescape() internally
     add 96a80b5a2 parsedate: handle cut off numbers better
     add fbb5f1aa0 range: prevent negative end number in a glob range
     add 269a88910 glob_next_url: make sure to stay within the given output 
buffer
     add ee4f76606 range: reject char globs with missing end like '[L-]'
     add 8732ec40d aprintf: detect wrap-around when growing allocation
     add 3d6460ede krb5: avoid realloc(0)
     add efd24d574 base64: check for integer overflow on large input
     add b3ee26c5d connectionexists: use case sensitive user/password 
comparisons
     add ce8d09483 SSH: check md5 fingerprint case sensitively
     add 1833a45dd ftp: check for previous patch must be case sensitive!
     add 502acba2a strcasecompare: is the new name for strequal()
     add 811a693b8 strcasecompare: all case insensitive string compares ignore 
locale now
     add cff89bc08 cookie: replace use of fgets() with custom version
     add ad16f8979 test165: adapted to the libidn2 use and IDNA2008 fix
     add 532491a27 ldap: fix strcase use
     add 44c53cc38 strcase: s/strequal/strcasecompare
     add 8fe4bd084 curl_strequal: part of public API/ABI, needs to be kept
     add c27013c05 url: remove unconditional idn2.h include
     add cce5250f6 ldap: fix include
     add 06bc2100d unit1301: keep testing curl_strequal
     add d14538d25 configure: raise the default minimum version for macos to 
10.8
     add 9934f4fe9 RELEASE-NOTES: synced with d14538d2501ef0da
     add 52a2c2fb5 libauthretry: use the external function curl_strequal
     add 4f97d9832 digest_sspi: fix include
     add 9363f1a37 strcasecompare: replaced remaining rawstr.h with strcase.h
     add 309d6e80d msvc builds: s/rawstr/strcase
     add 64c2d24c4 strcase: fix the remaining rawstr users
     add 47a21ca9b strcasecompare: include curl.h in strcase.c
     add 107168094 gskit, nss: do not include strequal.h
     add 95bd2b3e7 strcase: make the tool use curl_str[n]equal instead
     add 07b95ea26 tests/util: get a private strncasecompare clone
     add b744950f4 curl.1: expand on how multiple uses of -o looks
     add e5c49b9e6 curl.1: typo
     add e44bfc766 strcase: fixed Metalink builds by redefining checkprefix()
     add f9e51fb55 file: fix compiler warning
     add 6b52b7eb2 metalink: simplify the hex parsing function
     add ee96ffa2a generate.bat: Remove strcase.[ch] from curl tool VS projects
     add 0e727979a generate.bat: Include include/curl in libcurl VS projects
     add 3c6c2bcd5 ftp: remove dead code in ftp_done
     add f81a83646 ftp_done: don't clobber the passed in error code
     add 1fe755f99 RELEASE-NOTES: 7.51.0
     add 3c561c657 THANKS: synced with 7.51.0
     add 788b319df msvc: removed a straggling reference to strequal.c
     add d7e5f1827 winbuild: remove strcase.obj from curl build
     add 71cfce9ce bump: start working on 7.51.1
     add b1aeed302 docs: remove unused variables in multi-uv example
     add e6882ce48 docs: multi-uv: don't use CURLMsg after cleanup
     add 82b6fd411 docs: handle CURL_POLL_INOUT in multi-uv example
     add c8e6e60b4 docs: shorten and simplify the top comment in multi-uv.c
     add 6724242cf configure: verify that compiler groks 
-Werror=partial-availability
     add 9ea3a6e15 mbedtls: fix build with mbedtls versions < 2.4.0
     add 8ed52bde0 dist: add CMakeLists.txt to the tarball
     add ebeffe81d curl -w: added more decimal digits to timing counters
     add 456463678 easy: Initialize info variables on easy init and duphandle
     add 6aa9cfa2b cmake: disable poll for macOS
     add 677d8b3fe curl.1: explain the SMTP data expected for -T
     add 0269f6446 http2: Don't send header fields prohibited by HTTP/2 spec
     add 27302abb9 s/cURL/curl
     add 5d45ced7a nss: map CURL_SSLVERSION_DEFAULT to NSS default
     add 6ad3add60 vtls: support TLS 1.3 via CURL_SSLVERSION_TLSv1_3
     add a110a03b4 curl: introduce the --tlsv1.3 option to force TLS 1.3
     add 50aded1cd ssh: check md5 fingerprints case insensitively (regression)
     add 9e8b0a283 openssl: initial TLS 1.3 adaptions
     add 5e6c04f91 nss: silence warning 'SSL_NEXT_PROTO_EARLY_VALUE not handled 
in switch'
     add c2bc47ddb curl_formadd.3: *_FILECONTENT and *_FILE need the file to be 
kept
     add 5dd1b65f7 printf: fix ".*f" handling
     add dfcdaaba3 examples/fileupload.c: fclose the file as well
     add de39e8973 RELEASE-NOTES: synced with dfcdaaba371e9a3
     add 397abc8b4 bump: next version will be 7.52.0
     add 1299df686 CODE_STYLE.md: link to INTERNALS.md correctly
     add 46f906a1b SPNEGO: Fix memory leak when authentication fails
     add f43b7b6cb vtls: Fail on unrecognized param for CURLOPT_SSLVERSION
     add ea80a2dcf openssl: raise the max_version to 1.3 if asked for
     add cdfda3ee8 curl: Add --retry-connrefused
     add 0649433da realloc: use Curl_saferealloc to avoid common mistakes
     add cbec00d91 Curl_pgrsUpdate: use dedicated function for time passed
     add f9de7c405 openssl: RAND_status always exists in OpenSSL >= 0.9.7
     add 942c952db openssl: avoid unnecessary seeding if already done
     add ddefc056b openssl: make sure to fail in the unlikely event that PRNG 
seeding fails
     add 8c15e0de6 test558: adapt to 0649433da
     add 346340808 URL-parser: for file://[host]/ URLs, the [host] must be 
localhost
     add ff662f1c3 RELEASE-NOTES: synced with 346340808c
     add 56bb7b1a3 tests: fixed variable might be clobbered warning
     add de4de4e3c timeval: prefer time_t to hold seconds instead of long
     add ebf985c15 time_t fix: follow-up to de4de4e3c7c
     add 050aa8030 cmdline-opts: first test version of a new man page generator 
kit
     add f682156a4 Curl_rand: fixed and moved to rand.c
     add f82bbe01c curl: add --fail-early
     add 8c630ef05 glob: fix [a-c] globbing regression
     add 0744506cd curl: add --fail-early to help output
     add 7c9b9add6 darwinssl: fix SSL client certificate not found on MacOS 
Sierra
     add b8c35f40f cmdline-opts: support generating the --help output
     add cfd69c133 docs: the next release will be 7.52.0
     add 771f3f22d docs: Spelling fixes
     add 7f439f165 curl.1: Clarify --dump-header only writes received headers
     add 03d707fc5 tool_help: Clarify --dump-header only writes received headers
     add b65f79d9e http2: Fix address sanitizer memcpy warning
     add 1ef1f10ca cmdline/gen: replace options in texts better
     add 81e61cda3 gen: support 'redirect'
     add 41b1f649b cmdline-docs: more options converted over
     add 5781e3653 gen: support 'single' to make an individual page man page
     add c3c1e9618 gen: support 'protos'
     add 342aa4797 cmdline-docs: more conversion
     add a4d888857 http2: Use huge HTTP/2 windows
     add 2ece147cc tests: Fix HTTP2-Settings header for huge window size
     add 0b8d682f8 Don't mix unix domain sockets with regular ones
     add 21aa32d30 lib: fix compiler warnings after de4de4e3c7c
     add c0ae2dbb8 vtls: fix build warnings
     add 8626632f3 rand: Fix potentially uninitialized result warning
     add f18f7bf93 rand: pass in number of randoms as an unsigned argument
     add 3e9c0230f url: Fix conn reuse for local ports and interfaces
     add 945f60e8a Limit ASN.1 structure sizes to 256K. Prevent some allocation 
size overflows. See CRL-01-006.
     add 8034d8fc6 Declare endian read functions argument as a const pointer. 
This is done for all functions of the form Curl_read[136][624]_[lb]e.
     add cb4e2be7c proxy: Support HTTPS proxy and SOCKS+HTTP(s)
     add 8cb872df1 mbedtls: Fix compile errors
     add 8b4352658 gtls: fix indent to silence compiler warning
     add 49765cd75 darwinssl: adopted to the HTTPS proxy changes
     add c6da05a5e HTTPS-proxy: fixed mbedtls and polishing
     add 74ffa040a openssl: remove dead code
     add bc7e08471 checksrc: add ASTERISKSPACE
     add dbadaebfc checksrc: code style: use 'char *name' style
     add ec0a5c96a checksrc: verify ASTERISKNOSPACE
     add 8657c268e checksrc: white space edits to comply to stricter checksrc
     add 80e7cfeb8 checksrc: detect wrongly placed open braces in func 
declarations
     add 6832c1d4b checksrc: move open braces to comply with function 
declaration style
     add 63198a475 curl.1: the new --proxy options ship in 7.52.0
     add 54789f944 RELEASE-NOTES: synced with 63198a4750aeb
     add ba410f6c6 add CURLINFO_SCHEME, CURLINFO_PROTOCOL, and %{scheme}
     add 7d967c80b RELEASE-NOTES: update option counters
     add 212745701 x509asn1: Restore the parameter check in Curl_getASN1Element
     add c34fa31f3 test1135: Fix curl_easy_duphandle prototype for code style
     add 93c04cb14 os400: sync ILE/RPG binding
     add 4bda3e04b tool_help: Change description for --retry-connrefused
     add a6618b525 tool_urlglob: Improve sanity check in glob_range
     add 65894c984 winbuild: add config option ENABLE_NGHTTP2
     add 8ebc5cda8 TODO: removed "HTTPS proxy"
     add 1232dbb8b url: proxy: Use 443 as default port for https proxies
     add 4f8b17743 HTTPS Proxy: Implement CURLOPT_PROXY_PINNEDPUBLICKEY
     add 9bfb00efc docs: include all opts man pages in dist
     add 67edddeb9 curl_easy_setopt.3: add CURLOPT_PROXY_PINNEDPUBLICKEY
     add 2527dd437 CURLOPT_PROXY_CRLFILE.3: clarify https proxy and availability
     add 3f7d9b900 CURLOPT_PROXY_CAINFO.3: clarify proxy use
     add 267b26b24 curl_easy_reset: clear info for CULRINFO_PROTOCOL and 
CURLINFO_SCHEME
     add e38fe7abb tests: Add some testcases for recent new features.
     add a4b2f7aaf curl_version_info: add CURL_VERSION_HTTPS_PROXY
     add d2c5503e0 os400: support CURLOPT_PROXY_PINNEDPUBLICKEY
     add c67f84209 CURLOPT_PROXY_*.3: polished some proxy option man pages
     add 720ea577d curl: remove --proxy-ssl* options
     add 5c4a52638 cmdline-opts: more command line options documented
     add 30593d453 lib1536: checksrc compliance
     add ac85f332f gen: include footer in mainpage output
     add a387d881e cmdline-docs: more options converted and fixed
     add 421f74016 http2: Fix crashes when parent stream gets aborted
     add 19613fb35 http2: check nghttp2_session_set_local_window_size exists
     add 4e8e22c25 RELEASE-NOTES: synced with 19613fb3
     add 12d6794b1 BUGS: describe bug handling process
     add b34ea05d9 CURLOPT_CONNECT_TO: Skip non-matching "connect-to" entries 
properly
     add 18b02f196 cyassl: fixed typo introduced in 4f8b1774
     add 42253ad94 runtests: made Servers: output be more consistent by 
removing OFF
     add aab33215a URL parser: reject non-numerical port numbers
     add c50b878c1 CONNECT: reject TE or CL in 2xx responses
     add 3ea351842 CONNECT: read responses one byte at a time
     add 3b77aa6b2 tests: fix CONNECT test cases to be more strict
     add 74595b223 http_proxy: simplify CONNECT response reading
     add cee0fb324 curl: support zero-length argument strings in config files
     add 7117a9a6c test1281: added http as a required feature
     add 254c0b305 libcurl-multi.3: typo
     add dacfecb7b test2032: Mark test as flaky
     add 71a55534f openssl: don't use OpenSSL's ERR_PACK.
     add 65c3d3fe9 RELEASE-NOTES: synced with 71a55534fa6
     add 5fad800ef ISSUE_TEMPLATE: try mentioning known bugs/todo in new issue 
template
     add b228d2952 checksrc: stricter no-space-before-paren enforcement
     add 1c3e8bbfe checksrc: warn for assignments within if() expressions
     add 558b5f68a curl_multi_socket.3: fix typo
     add 7907a2bec CURLOPT_SOCKS_PROXYTYPE: removed
     add 642398c65 curl: normal socks proxies still use CURLOPT_PROXY
     add 845522cad preproxy: renamed what was added as SOCKS_PROXY
     add 7ebd9bcfc cmdline-opts/page-header: mention it is generated
     add b0fcb92f8 HTTPS-PROXY docs: update/polish
     add c58884056 CURLINFO_SSL_VERIFYRESULT.3: language
     add 4b8b7a2d3 cmdline-opts: added some missing info
     add c7eab72de curl.1: generated with gen.pl
     add a8ab99766 cmdline-opts: include the man page split up files in the dist
     add 20b12987c symbols: removed two, added one
     add 6bec14f38 curl_easy_setopt.3: CURLOPT_PRE_PROXY instead of 
CURLOPT_SOCKS_PROXY
     add c47b1eced cmdline-opts/proxy-tlsuser.d: remove trailing .d
     add 58206f0ef cmdline-opts/gen.pl: trim off trailing spaces
     add 7618e60c2 manpage-scan.pl: allow deprecated options to get removed 
from curl.1
     add de0cd5e55 tool_getparam.c: make comments use the up-to-date option 
names
     add 2bd2538eb curl_easy_setopt.3: removed CURLOPT_SOCKS_PROXYTYPE
     add e79d31715 cmdline-opts: formatting fixes
     add 5f9ce4b05 curl.1: regenerated
     add 6cce4dbf8 cmdline-opts/post30X.d: fix the RFC references
     add 4c9567e39 curl.1: generated after 6cce4dbf830
     add 6bc105160 CIPHERS.md: attempt to document TLS cipher names
     add 82245eaa5 Curl_getconnectinfo: avoid checking if the connection is 
closed
     add afff64dbc curl_easy_recv: Improve documentation and example program
     add f9484d9fb openssl: simplify expression in Curl_ossl_version
     add 111f3c1fd form-string.d: fix format mistake
     add 4517158ab CIPHERS.md: backtick the names to show underscores fine
     add 3dcbd06d0 RELEASE-NOTES: synced with 4517158abfeba
     add c56232999 config-amigaos.h: fix bug report email reference
     add 60450d507 config-amigaos.h: (embarrassed) made the line shorter
     add 3ab3c16db printf: fix floating point buffer overflow issues
     add 0354eed41 schannel: fix wildcard cert name validation on Win CE
     add afb57f7b0 cmdline-opts/tlsv1.d: rephrased
     add d00f2a8f2 http_proxy: Fix proxy CONNECT hang on pending data
     add c2402b6e0 tests: checksrc compliance
     add 21a7a96c9 Curl_recv_has_postponed_data: silence compiler warnings
     add f44cf7914 ssh: inhibit coverity warning with (void)
     add 7fda9ce46 RELEASE-NOTES: 7.52.0
     add 95c717bbd THANKS: 13 new contributors from 7.52.0
     add 773cef4fa lib: fix MSVC compiler warnings
     add 462650e45 bump: toward next release
     add e7458c1bc lib557: move the "enable LONGLINE" to allow more long lines
     add 7a01b33c3 tests/Makefile: run checksrc on debug builds
     add f81b2277a randit: store the value in the buffer
     add 5c823f51d runtests: remove the valgrind parser
     add fab16de6e lib557.c: use a shorter MAXIMIZE representation
     add 44b9b4d4f RELEASE-NOTES: curl 7.52.1
     add c7834ecd4 gnutls-random: check return code for failed random
     add 00c817068 openssl-random: check return code when asking for random
     add 9aa259a13 http: remove "Curl_http_done: called premature" message
     add ad4b348c4 bump: toward next release
     add cdbdef6f9 cyassl: use time_t instead of long for timeout
     add 57cad8109 build-wolfssl: Sync config with wolfSSL 3.10
     add 5fe164a25 ftp-gss: check for init before use
     add 913312f41 test1282: verify the ftp-gss check
     add 0bc24d6f9 configure: accept --with-libidn2 instead
     add 9314bf840 ftp: failure to resolve proxy should return that error code
     add e50abe647 formdata: use NULL, not 0, when returning pointers
     add 7776abb2e cmdline-opts/page-footer: add three more exit codes
     add 209b23022 docs/ciphers: link to our own new page about ciphers
     add a7b38c9dc vtls: s/SSLEAY/OPENSSL
     add 2bb00705b RELEASE-NOTES: synced with a7b38c9dc98481e
     add aa6db9642 curl: remove superfluous include file
     add 8db3afe16 darwinssl: fix iOS build
     add e53f0736c darwinssl: fix CFArrayRef leak
     add 1b711ca10 cmake: use crypt32.lib when building with OpenSSL on windows
     add 0128925de curl_formadd.3: CURLFORM_CONTENTSLENGTH not needed when 
chunked
     add 89b789884 digest_sspi: copy terminating NUL as well
     add ee3c83f39 tool_operate: Fix --remote-time incorrect times on Windows
     add 278034a61 page-footer: error 36 is protocol agnostic!
     add ad10eb5fe content_encoding: change return code on a failure
     add 9b3fbf6b8 curl.h: CURLE_FUNCTION_NOT_FOUND is no longer in use
     add 4f2239c5c docs/libcurl: TCP_KEEPALIVE start and interval default to 60
     add ffbb0f0d3 darwinssl: --insecure overrides --cacert if both settings 
are in use
     add feca30419 TheArtOfHttpScripting: grammar
     add 5d7a7fcdc CIPHERS.md: document GSKit ciphers
     add bbee0d4ee wolfssl: support setting cipher list
     add ba19feba9 wolfssl: display negotiated SSL version and cipher
     add e8404adc8 docs/page-header: mention how to disable the progress meter
     add acd29dc10 docs/silent: mention --show-error in --silent description
     add 7fc0e1dfc COPYING: update the generic copyright year range
     add 5df25fdce ROADMAP: 2017 cleanup
     add 8805be2cf lib506: fix build for Open Watcom
     add ed2fcd542 asiohiper: improved socket handling
     add a41e8592d examples: make the C++ examples follow our code style too
     add d3a313c09 RELEASE-NOTES: synced with a41e8592d6b3e58
     add 62e67c777 sws: retry send() on EWOULDBLOCK
     add 192466e08 cmake: Fix passing _WINSOCKAPI_ macro to compiler
     add c6778aa46 http2_send: avoid unsigned integer wrap around
     add 4e6f483d0 smtp: Fix STARTTLS denied error message
     add a18db7926 STARTTLS: Don't print response character in denied messages
     add 807698db0 rand: make it work without TLS backing
     add 1d4202ade url: Fix parsing for when 'file' is the default protocol
     add 7ba8020c4 gnutls: check for alpn and ocsp in configure
     add cd6b99ef3 docs: FAQ MAIL-ETIQUETTE language fixes
     add f30cbcac1 IDN: Use TR46 'transitional' for toASCII translations
     add 1b5755788 url: Fix NO_PROXY env var to work properly with --proxy 
option.
     add efdbfde7c url: Refactor detect_proxy()
     add 2ac1942c7 url: --noproxy option overrides NO_PROXY environment variable
     add ba315745f IDN: Fix compile time detection of linidn2 TR46
     add ee357664d IDN: revert use of the transitional option
     add 7d6e3f8cf IDN: Use TR46 non-transitional
     add d2b2c6385 CURLOPT_PREQUOTE.3: takes a struct curl_slist*, not a char*
     add dbd379385 docs: Add note about libcurl copying strings to CURLOPT_* 
manpages
     add a301cbb65 curl: reset the easy handle at --next
     add ac548bbaa next.d: --trace and --trace-ascii are also global
     add a7c73ae30 write-out.d: 'time_total' is not always shown with ms 
precision
     add 1d786faee unix_socket: add support for abstract unix domain socket
     add d758e99ce RELEASE-NOTES: synced with a7c73ae309c
     add d24c4ea2d THANKS-filter: Jiri Malak
     add 6e12bb7cb addrinfo: fix compiler warning on offsetof() use
     add eb6cf7513 TODO: Improve formpost API, not just add an easy argument
     add 9dea60e55 TODO: Chunked transfer multipart formpost
     add 535a29c01 TODO: implemened "--fail-fast to exit on first transfer fail"
     add e3b911463 TODO: send only part of --data
     add 1ad1a0d18 http: print correct HTTP string in verbose output when using 
HTTP/2
     add 02ee3b273 docs: improved language in README.md HISTORY.md CONTRIBUTE.md
     add 9ad034e5a http2: disable server push if not requested
     add 25ed9ea51 nss: use the correct lock in nss_find_slot_by_name()
     add 8f8ba6122 bump: next release will be 7.53.0
     add 25543b839 TODO: share OpenSSL contexts
     add afd156421 openssl: Fix random generation
     add e9f45aa91 parseurl: move back buffer to function scope
     add 3a4326efd usercertinmem.c: improve the short description
     add 2d6831b75 CURLOPT_CONNECT_TO: Fix compile warnings
     add f1261b125 docs: non-blocking SSL handshake is now supported with NSS
     add df86db7de *.rc: escape non-ASCII/non-UTF-8 character for clarity
     add 1a9a99adf KNOWN_BUGS: HTTP/2 server push enabled when no pushes can be 
accepted
     add 81cb255cb sws: use SOCKERRNO, not errno
     add 6b7616690 CURLOPT_BUFFERSIZE: support enlarging receive buffer
     add 06b1197ee vtls: fix mbedtls multi non blocking handshake.
     add 01ab7c30b vtls: fix PolarSSL non-blocking handling
     add a2bcaa319 RELEASE-NOTES: synced with 01ab7c30bba6f
     add 40e3d6c8c contri*.sh: cut off parentheses from names too
     add fd3ca89ce vtls: source indentation fix
     add 4c49b8359 docs/curl.1: generate from the cmdline-opts script
     add d0837f36d cmdline-opts/gen.pl: Open input files in CRLF mode
     add 8611d985e VC: remove the makefile.vc6 build infra
     add d8a3aa702 telnet: fix windows compiler warnings
     add 77350cef0 INTERNALS.md: language improvements
     add 074405786 TODO: remove "Support TLS v1.3"
     add cbd4e1fa0 cookies: do not assume a valid domain has a dot
     add bcca842e0 polarssl: fix hangs
     add 511674ab2 gnutls: disable TLS session tickets
     add ab08d8264 mbedtls: disable TLS session tickets
     add 54210fa5b RELEASE-NOTES; synced with ab08d82648
     add bd7eaf75f docs: proofread README.netware README.win32
     add a1a5dd14d docs: we no longer ship HTML versions of man pages
     add a90a5bccd mbedtls: implement CTR-DRBG and HAVEGE random generators
     add 028391df5 openssl: Don't use certificate after transferring ownership
     add 1c877a071 cmake: Support curl --xattr when built with cmake
     add a49d2d0e2 OS400: Fix symbols
     add 423a93ce3 docs: Add more HTTPS proxy documentation
     add 88bdd7cf6 use *.sourceforge.io and misc URL updates
     add edb2d0285 cmdline-opts: Fixed build and test in out of source tree 
builds
     add d3ab22f87 CHANGES.0: removed
     add 5aef498b8 CHANGES: spell fix, use correct path to script
     add 18495ecac schannel: Remove incorrect SNI disabled message
     add 3509aa802 darwinssl: Avoid parsing certificates when not in verbose 
mode
     add e695b070a test552: Fix typos
     add 3c5bfe489 telnet: Fix typos
     add 6ffe0f5d9 transfer: only retry nobody-requests for HTTP
     add d83612376 http2: reset push header counter fixes crash
     add 102454459 THANKS-filter: polish some recent contributors
     add 372680283 RELEASE-NOTES: synced with 102454459dd688c
     add 3cc2229c1 test1139: Added the --manual keyword since the manual is 
required
     add a7e4348cf polarssl, mbedtls: Fix detection of pending data
     add 7fe81ec29 http_proxy: Fix tiny memory leak upon edge case connecting 
to proxy
     add e2e182227 http_proxy: avoid freeing static memory
     add bef0d0011 examples/multithread.c: link to our multi-thread docs
     add 8fa540980 nss: make FTPS work with --proxytunnel
     add 1dcf24472 CURLOPT_SSL_VERIFYPEER.3: also the https proxy version
     add 7017c421a cmdline-opts/socks*: Mention --preproxy in --socks* opts
     add c5c4e816b URL: only accept ";options" in SMTP/POP3/IMAP URL schemes
     add 8721f3a50 cmdline-opts/page-footer: ftp.sunet.se is no longer an FTP 
mirror
     add e1187c42a tool_operate: Show HTTPS-Proxy options on CURLE_SSL_CACERT
     add bde1e2e09 http2: fix memory-leak when denying push streams
     add c1071283e configure: Allow disabling pthreads, fall back on Win32 
threads
     add 97c7591a5 smb: code indent
     add 690935390 curl: fix typo in time condition warning message
     add 04aa9645b RELEASE-NOTES: synced with 690935390c29c
     add a08db4964 axtls: adapt to API changes
     add 7a9f5748b tool_urlglob: Allow a glob range with the same start and stop
     add c2127b448 TODO: consider file name from the redirected URL with -O ?
     add 62c857acd RELEASE-PROCEDURE: update the upcoming release calendar
     add 3cc30e820 winbuild: add note on auto-detection of MACHINE in 
Makefile.vc
     add 13e3a18b3 http: fix missing 'Content-Length: 0' while negotiating auth
     add 2f8d0df08 proxy: fix hostname resolution and IDN conversion
     add 4ddf9798a docs: fix timeout handling in multi-uv example
     add a5e8fcbc1 speed caps: update the timeouts if the speed is too low/high
     add f45de0e87 tests: removed the obsolete name parameter
     add ddedc1b3f string formatting: fix 4 printf-style format strings
     add 889ca45ab examples/multi-uv: checksrc compliance
     add f77dabefd digest_sspi: Fix nonce-count generation in HTTP digest
     add af30f1152 sftp: improved checks for create dir failures
     add 563a4b067 RELEASE-NOTES: synced with af30f1152d43dcdb
     add 73ef4ed61 TODO: CURLOPT_RESOLVE for any port number
     add de1c1a8d8 smb: use getpid replacement for windows UWP builds
     add af5fbb14b digest_sspi: Handle 'stale=TRUE' directive in HTTP digest
     add ca6ea6d9b TLS: make SSL_VERIFYSTATUS work again
     add 588960be2 cookie: fix declaration of 'dup' shadows a global declaration
     add a7135ac3c release: 7.53.0
     add 0e8d3e838 cyassl: fix typo
     add b259646ea url: Improve CURLOPT_PROXY_CAPATH error handling
     add f4739f639 urldata: include curl_sspi.h when Windows SSPI is enabled
     add b702a4d84 TODO: brotli is deployed widely now
     add f57eb1f8e TODO: HTTP Digest using SHA-256
     add 035c2ecee docs: gitignore curl.1
     add 86f566078 formdata: check for EOF when reading from stdin
     add d3838dc68 bump: 7.53.1 coming up
     add 2bfe55037 tests: Set CHARSET & LANG to UTF-8 in 1035, 2046 and 2047
     add 443e5b03a THANKS-filter: shachaf
     add 656441d91 RELEASE-NOTES: synced with 443e5b03a7d441
     add ed74c6442 TODO: "OPTIONS *"
     add 53ab183c1 rand: added missing #ifdef HAVE_FCNTL_H around fcntl.h header
     add 93cce2489 url: Default the CA proxy bundle location to CURL_CA_BUNDLE
     add ecd1d020a tests: use consistent environment variables for setting 
charset
     add 13314ffd6 Revert "tests: use consistent environment variables for 
setting charset"
     add 25df50aa3 release: 7.53.1
     add 03bd26852 bump: work on the next release
     add bbc81c46e cmake: Replace invalid UTF-8 byte sequence
     add 832b0105f test557: explicitly use the C locale so the numeric output 
is as expected
     add c6ddb606d tests: use consistent environment variables for setting 
charset
     add ce9ba3ba1 proxy: fixed a memory leak on OOM
     add 79221d8d5 ftp: removed an erroneous free in an OOM path
     add eac0dc6a3 docs: de-duplicate file lists in the Makefiles
     add 516e60aa8 ftp: fixed a NULL pointer dereference on OOM
     add f7285cc02 gopher: fixed detection of an error condition from 
Curl_urldecode
     add 1f8023ceb url: fix unix-socket support for proxy-disabled builds
     add 4fa2de369 test1139: allow for the possibility that the man page is not 
rebuilt
     add a21cae5f9 cyassl: get library version string at runtime
     add 727917555 digest_sspi: fix compilation warning
     add 41388b9ba tests: enable HTTP/2 tests to run with non-default port 
numbers
     add a162d8b21 warnless: suppress compiler warning
     add 0966ab5bd darwinssl: Warn that disabling host verify also disables SNI
     add 5f139d6b6 configure: fix for --enable-pthreads
     add 14cd405d2 checksrc.bat: Ignore curl_config.h.in, curl_config.h
     add e95240240 no-keepalive.d: fix typo
     add 6fc91f6d3 configure: fix --with-zlib when a path is specified
     add cbff751e9 build: fix gcc7 implicit fallthrough warnings
     add 9f2033344 url: split off proxy init and parsing from create_conn
     add 97a04145e tests: fixed a typo in some comments
     add 658b9a200 fix some typos in the doc (#1306)
     add 7b1430c0b fix potential use of uninitialized variables
     add 21512a015 CURLOPT_SSL_CTX_FUNCTION.3: Fix EXAMPLE formatting errors
     add f85ff14d5 CMake: Reorganize SSL support, separate WinSSL and SSPI
     add eb19e89f2 CMake: Add DarwinSSL support
     add c6a97466b CMake: Add mbedTLS support
     add 813263dc3 CMake: Set at most one SSL library
     add 29be83ee7 ares: return error at once if timed out before name resolve 
starts
     add bfcb3150a BINDINGS: add misssing C++ bindings
     add 5e99ede6d BINDINGS: add go-curl and perl6-net-curl
     add df77f1772 BINDINGS: add Scilab binding
     add 7ad72e0fc BINDINGS: update the Lua-cURL URL
     add aadb7c7b6 URL: return error on malformed URLs with junk after port 
number
     add 3914c07ed test1260: removed errant XML tag
     add f023f258f KNOWN_BUGS: Add DarwinSSL won't import PKCS#12 without a 
password
     add bfaab3180 ares: better error return on timeouts
     add 958e17668 ares: Curl_resolver_wait_resolv: clear *entry first in 
function
     add 475c2583d http2: Fix assertion error on redirect with CL=0
     add 698aae270 updatemanpages.pl: Update man pages to use current date and 
versions
     add e159fff13 Makefile.am: Added scripts/updatemanpages.pl to EXTRA_DIST
     add f5712ca27 Makefile.am: Remove distribution man pages when running 
'make clean'
     add d960e5702 gitignore: Ignore man page dist files
     add beff139d3 maketgz: Run updatemanpages.pl to update man pages
     add 348f8a3da test1260: added http as a required feature
     add 324bf2fd3 insecure.d: clarify that this is for server connections
     add 6888a670a MANPAGE: clarify the dash situation in meta data
     add b66690733 RELEASE-NOTES: synced with 6888a670aa01
     add 6448f98c1 vtls: add options to specify range of enabled TLS versions
     add 6733acc90 openssl: unbreak the build after 6448f98c1857de
     add 28a3453ac bump: next release will be known as 7.54.0
     add 7d62502d6 polarssl: fixed compile errors introduced in 6448f98c
     add 9f3bc40f7 mkhelp: simplified the gzip code
     add b1dc45a82 build: fixed making man page in out-of-tree tarball builds
     add e1960fef1 tls-max.d: added to the makefile
     add 26e9fc27a tests: disabled 1903 now
     add 12f04142c openssl: add two /* FALLTHROUGH */ to satisfy coverity
     add 7c847ab9d ISSUE_TEMPLATE: for bugs, ask questions on the mailing list
     add 1e54c5fb0 README.md: add coverity and travis badges
     add 03c5223ee cmdline-opts: fixed a few typos
     add 381aff038 url: don't compile detect_proxy if HTTP support is disabled
     add 5278462c3 authneg: clear auth.multi flag at http_done
     add 0afbcfd80 curl_easy_reset: Also reset the authentication state
     add e84a863dc proxy: skip SSL initialization for closed connections
     add 8d1052099 tests: fix the authretry tests
     add e08c0cd32 mbedtls: fix typo in variable name
     add ec1d0ed1c http_proxy: Ignore TE and CL in CONNECT 2xx responses
     add d2bcf1e3e url: add option CURLOPT_SUPPRESS_CONNECT_HEADERS
     add 1890d5990 tool_writeout: fixed a buffer read overrun on --write-out
     add 75398731e test1287: added verbose logs keyword
     add 3863de57f tests: clear the SSL_CERT_FILE variable on --libcurl tests
     add db900ab73 test1440/1: depend on well-defined file: behaviour
     add c25e0761d make: regenerate docs/curl.1 by runinng make in docs
     add bfb2a0ad7 RELEASE-NOTES: synced with c25e0761d0fc49c4
     add db87bcfcf winbuild: add basic support for OpenSSL 1.1.x
     add 66de56348 Improve code readbility
     add 3627769d1 build: removed redundant DEPENDENCIES from makefiles
     add a2eb08607 KNOWN_BUGS: remove libidn related issue
     add 280e8c6e3 BINDINGS: a Delphi binding
     add c5357b7b9 SSLCERTS.md: mention HTTPS proxies and their separate options
     add 49f7b1353 CURLINFO_LOCAL_PORT.3: added example
     add f7b3914c5 CURLINFO_LOCAL_PORT.3: fix typo
     add 98afec033 tool_operate: Fix showing HTTPS-Proxy options on 
CURLE_SSL_CACERT
     add 9873431c6 darwinssl: fix typo in variable name
     add 25d43d19d tests: strip more options from non-HTTP --libcurl tests
     add 718709c67 test714/5: added HTTP as a required feature
     add 1bca868f6 tests: fixed the documented test server port numbers
     add de2b31aa5 runtests.pl: fixed display of the Gopher IPv6 port number
     add 0005d0076 CONTRIBUTE: mention referring to github issues in commit msgs
     add 6e0f26c8a multi: fix streamclose() crash in debug mode
     add b3b9c627b RELEASE-NOTES: synced with 6e0f26c8a8c28df
     add 131e432bd RELEASE-NOTES: typo
     add 26baf39f3 examples: comment typos in http2 examples
     add 6f6e9193d docs: split file lists into Makefile.inc
     add 84a226a30 cmake: build manual pages (including curl.1)
     add 898b012a9 cmake: add support for building HTML and PDF docs
     add a360906de mbedtls: add support for CURLOPT_SSL_CTX_FUNCTION
     add 96d6942b2 test2033: flaky
     add 207f58898 make: introduce 'test-nonflaky' target
     add 5091e18e8 travis: run tests-nonflaky instead of tests-full
     add e369303cd CURLINFO_PRIMARY_IP.3: add example
     add f355a92cd tests/README: mention nroff for --manual tests
     add ae22034d0 mkhelp: disable compression if the perl gzip module is 
unavailable
     add b999d35c7 openssl: fall back on SSL_ERROR_* string when no error detail
     add f99fcb0fe openssl: made the error table static const
     add 99d708a01 asiohiper: make sure socket is open in event_cb
     add 68aac9a83 openssl: fix comparison between signed and unsigned integer 
expressions
     add d14563454 tests/README: make "Run" section foolproof
     add 8e6587787 curl: check for end of input in writeout backslash handling
     add f7df67cff spelling fixes
     add 2c3af5b4c .gitattributes: turn off CRLF for *.am
     add 068cd1ad4 multi: fix MinGW-w64 compiler warnings
     add 23d48c35c schannel: fix variable shadowing warning
     add 041ded045 examples/fopen: checksrc compliance
     add b04e4ebdd openssl: exclude DSA code when OPENSSL_NO_DSA is defined
     add 7975d10cf http: Fix proxy connection reuse with basic-auth
     add 452203341 pause: handle mixed types of data when paused
     add 2549831da http: do not treat FTPS over CONNECT as HTTPS
     add 2066072ff conncache: make hashkey avoid malloc
     add d1ddda7e7 make: use the variable MAKE for recursive calls
     add 556c51a2d KNOWN_BUGS: typo
     add 396f34250 RELEASE-NOTES: synced with 556c51a2df
     add aced311d1 curl: fix callback argument inconsistency
     add 9bc92eeb0 NTLM: check for features with #ifdef instead of #if
     add 6a819089a docs/Makefile.am: include CMakeLists.txt in the dist tarball
     add 63dd7bbc5 cmake: add more missing files to the dist
     add f8952932e cmake: add cmake file in docs/libcurl/opts/ to dist
     add 1b4b2c1a5 select: use correct SIZEOF_ constant
     add a8e523f08 connect: fix unreferenced parameter warning
     add f104f7d91 schannel: fix unused variable warning
     add 244e0a36b gcc7: fix ‘*’ in boolean context, suggest ‘&&’ instead 
[-Wint-in-bool-context]
     add baaf0ba35 curl: fix callback functions to match prototype
     add 4a5b900cb http2: silence unused parameter warnings
     add e358a626f ssh: fix narrowing conversion warning
     add ec493dbda cmake: fix build with cmake 2.8.12.2
     add 2ff9c3e14 dist: add missing files to the tarball
     add d6bf5abd6 docs/index.html: removed, was not shipped anyway
     add 9bd7f004d libcurl.def: removed, unused
     add d5d85e707 CTestConfig.cmake: removed, unused
     add 76c21ed3f telnet: (win32) fix read callback return variable
     add 15b8c6795 docs: Explain --fail-early does not imply --fail
     add fb84faf00 fail-early.d: fix typos
     add 721f8c05c docs: added examples for CURLINFO_FILETIME.3 and 
CURLOPT_FILETIME.3
     add 55f4ababd tests/server/util: remove in6addr_any for recent MinGW
     add 5f1163517 multi: make curl_multi_wait avoid malloc in the typical case
     add 9506d01ee include: curl/system.h is a run-time version of curlbuild.h
     add d9c9611a2 docs: minor typo in write-out.d
     add a68ca63d7 easy: silence compiler warning
     add e60fe20fd llist: replace Curl_llist_alloc with Curl_llist_init
     add 4f2e348f9 hash: move key into hash struct to reduce mallocs
     add 5fadd0311 RELEASE-NOTES: synced with 4f2e348f9b42c69c480
     add 36e604fc7 url: don't free postponed data on connection reuse
     add 2d4413fef curl_sasl: declare mechtable static
     add d40f4e15e tool: fix Windows Unicode build
     add de05bcb70 multi: fix queueing of pending easy handles
     add 6193770ee tests: added test for Curl_splaygetbest to unit1309
     add 81284374b configure: prefer 'long long' to int64_t for curl_off_t
     add 446eaa941 tool_operate: move filetime code to its own function
     add b547fff56 tool_operate: fix MinGW compiler warning
     add 65154588f Revert "configure: prefer 'long long' to int64_t for 
curl_off_t"
     add 8761a40fd test1541: ignore the curl_off_t variable type name comparison
     add 1526912b9 INSTALL.cmake: more problems
     add c59fcdac9 nss: fix build after e60fe20fdf94e829ba5fce33f7a9d6c281149f7d
     add ae485279a system.h: set sizeof long to 4 on "default 32 bit" systems
     add 2d5711dc1 low_speed_limit: improved function for longer time periods
     add d2bdc9875 test1606: verify speedcheck
     add aa2e9e901 gtls: fix compiler warning
     add 1f152a42a sspi: print out InitializeSecurityContext() error message
     add 33ca733ee schannel: fix compiler warnings
     add e61c04b45 system.h: add section for tcc
     add e10db122a BUGS: "Bugs in old versions"
     add 45c78ad5b vtls: fix unreferenced variable warnings
     add e8c3c92d5 INSTALL.md: fix secure transport configure arguments
     add fa6640328 CURLINFO_SCHEME.3: fix variable type
     add ced57e9a9 .github/stale.yml: enable the stale bot
     add 1b9b90d94 libcurl-thread.3: also mention threaded-resolver
     add f9d1e9a27 libcurl-thread.3: fixed a bad macro that caused test 1140 to 
fail
     add 764ad34ca RELEASE-NOTES: synced with f9d1e9a27f7e1
     add d29e9de14 nss: load CA certificates even with --insecure
     add 5ed16e6a7 openssl: fix this statement may fall through 
[-Wimplicit-fallthrough=]
     add aa573c3c5 poll: prefer <poll.h> over <sys/poll.h>
     add 580da62d8 polarssl: unbreak build with versions < 1.3.8
     add f79913050 system.h: fix mingw section
     add ab6d23278 Curl_expire_latest: ignore already expired timers
     add fad74ba4c tests/server/util: prefer <poll.h> over <sys/poll.h>
     add e50e2850b test1541: also test for CURL_PULL_WS2TCPIP_H
     add 9168e2470 curl-compilers.m4: turn implicit function declarations into 
errors
     add fc347820a mbedtls: fix memory leak in error path
     add 1451271e0 http2: fix handle leak in error path
     add 2af10b2c0 RELEASE-NOTES: synced with 1451271e0
     add 05c9f42e5 unit1303: fix compiler warning
     add a0576e2f3 .gitattributes: force shell scripts to LF
     add 5cefe201e configure.ac: ignore CR after version numbers
     add c25aba125 extern-scan.pl: strip trailing CR
     add aaa7e05c7 code: fix typos and style in comments
     add 47b2f89d7 openssl: make SSL_ERROR_to_str more future-proof
     add 1c92b5b60 openssl: fix thread-safety bugs in error-handling
     add 997504ea5 openssl: don't try to print nonexistant peer private keys
     add 33cfcfd9f TLS: Fix switching off SSL session id when client cert is 
used
     add a4ff8a1a0 nss: fix MinGW compiler warnings
     add a78fc4559 RELEASE-NOTES: curl 7.54.0
     add d957e2189 THANKS: add contributors from 7.54.0 release notes
     add 5b4cbcf11 src/Makefile.am: avoid explicit $<
     add d88d054e9 bump: start working on next release
     add 7c145bb2a Revert "src/Makefile.am: avoid explicit $<"
     add da2af5c04 openssl: fix memory leak in servercert
     add 49eee2882 tests: remove the html and PDF versions from the tarball
     add 5f830eaba mbedtls: enable NTLM (& SMB) even if MD4 support is 
unavailable
     add cbb59ed9c typecheck-gcc: handle function pointers properly
     add cbae73e1d llist: no longer uses malloc
     add f761da76f gnutls: removed some code when --disable-verbose is 
configured
     add 4a8cf6c40 lib: fix maybe-uninitialized warnings
     add be299a4db multi: clarify condition in curl_multi_wait
     add 6b39f9c87 schannel: Don't treat encrypted partial record as pending 
data
     add d87bd46cb llist: fix a comment after cbae73e1dd9
     add c68fed875 configure: fix the -ldl check for openssl, add -lpthread 
check
     add 747441807 RELEASE-NOTES: synced with c68fed875
     add 71d2d3700 curl-compilers.m4: accept -Og and -Ofast GCC flags
     add c8ac0b6a7 nss: adapt to the new Curl_llist API
     add 80a87e8ab Makefile: avoid use of GNU-specific form of $<
     add 93567071b if2ip: fix -Wcast-align warning
     add 338f427a2 configure: stop prepending to LDFLAGS, CPPFLAGS
     add e698b8228 transfer: remove 'uploadbuf' pointer and cleanup 
readwrite_upload()
     add 96ece5c0e curl: set a 100K buffer size by default
     add 9c5aed185 typecheck-gcc: fix _curl_is_slist_info
     add c8ea86f37 nss: do not leak PKCS #11 slot while loading a key
     add fab3d1ec6 nss: factorize out nss_{un,}load_module to separate fncs
     add e3e8d0204 nss: load libnssckbi.so if no other trust is specified
     add e7f8ac194 examples: ftpuploadfrommem.c
     add fb67c977b url: declare get_protocol_family() static
     add 55c3c02e5 http-proxy: remove unused argument from Curl_proxyCONNECT()
     add b85142164 lib: remove unused code
     add 8b03436d3 Makefile: fix make dist
     add afe05ee2e cookie_interface.c: fix cookie domain so the example works
     add 7543f28ad cookie_interface.c: changed the other domain to example.com 
too
     add 63503a969 http-proxy: removed unused argument in CURL_DISABLE_PROXY 
case
     add 3364de00f test1443: test --remote-time
     add 4da846a41 tool_operate: use utimes instead of obsolescent utime when 
available
     add 2ce86d850 runtests.pl: support multiline <postcheck> commands
     add 584142892 tests: added --remote-time tests for remaining protocols 
that support it
     add 12e7a8c3d url: fixed a memory leak on OOM while setting 
CURLOPT_BUFFERSIZE
     add 65c6caaca curl_rtmp: fix missing-variable-declarations warnings
     add 8089dcfc5 tests: fixed OOM handling of unit tests to abort test
     add c0a27c5ce unit1604: fixed compilation under Windows, broken in the 
previous commit
     add 092d01244 unit1604: fixed indentation
     add dc9e4859b http2: declare TU-local variables static
     add c23177d5e examples: declare TU-local variables static
     add 6cba8dace examples: fixed too long line and too long string warnings
     add c3513f7e8 tool_cb_prg: fix double-promotion warning
     add 7dd89c1cd tests: declare TU-local variables static
     add 0912a5c76 getpart: use correct variable type
     add 499a7288f curl_setup: Ensure no more than one IDN lib is enabled
     add 5b13619da tool: Fix missing prototype warnings for 
CURL_DOES_CONVERSIONS
     add 35311b22b anyauthput: remove unused code
     add 94460878c http: use private user:password output buffer
     add 349789e64 ftp: use private buffer for temp storage, not receive buffer
     add c2ddc12d6 CURLOPT_BUFFERSIZE: 1024 bytes is now the minimum size
     add 7c312f84e file: use private buffer for C-L output
     add f535f4f5f buffer_size: make sure it always has the correct size
     add 87eb8d5b3 http: don't clobber the receive buffer for timecond
     add 504eafff8 http2: use the correct set buffer size
     add b8191e975 pingpong: use the set buffer size
     add f2fadf490 failf: use private buffer, don't clobber receive buffer
     add 40a074f25 transfer: fix minor buffer_size mistake
     add 0cab3a394 http-proxy: use a dedicated CONNECT response buffer
     add 8ed81f67c unit1606: do not print/access buffer
     add 89cf6f38d upload: UPLOAD_BUFSIZE is now for the upload buffer
     add c79f4908d krb5: use private buffer for temp string, not receive buffer
     add e40e9d7f0 buffer: use data->set.buffer_size instead of BUFSIZE
     add 7ee52c25f sendf: remove use of BUFSIZE from debug data conversions
     add 799c7048d openssl: use local stack for temp storage
     add e3ed5cb38 BUFSIZE: rename to READBUFFER_*, make separate MASTERBUF_SIZE
     add 4858c451e url: let CURLOPT_BUFFERSIZE realloc to smaller sizes too
     add eab6732fd ssh: fix compiler warning from e40e9d7f0de
     add 6943085b5 gtls: fixed a lingering BUFSIZE reference
     add f2d5d0589 testpart: remove _MPRINTF_REPLACE
     add 913c3c8f5 curl: non-boolean command line args reject --no- prefixes
     add 862b02f89 Telnet: Write full buffer instead of byte-by-byte
     add 120488d9d RELEASE-NOTES: synced with 862b02f89
     add 1bfdbb5a5 abstract-unix-socket.d: shorten the help text to fit within 
79 cols
     add 3ff0d2fb0 typecheck-gcc: add missing string options
     add fa12f54bb typecheck-gcc: add support for CURLINFO_SOCKET
     add cee39aa3b lib: fix compiler warnings
     add b065a508c CURLINFO_EFFECTIVE_URL.3: add example
     add 4b9338219 CURLINFO_REDIRECT_URL.3: add example
     add a51ca050f curl_setup_once: use SEND_QUAL_ARG2 for swrite
     add dfb0595a7 test559: verify use of minimum CURLOPT_BUFFERSIZE
     add ff1085215 curl: fix warning "comma at end of enumerator list"
     add 7cb1e1ee0 test557: set a known good numeric locale
     add 07fd7871b schannel: return a more specific error code for 
SEC_E_UNTRUSTED_ROOT
     add 4032c5da8 tests/server: make string literals const
     add 79bb0afdd sockfilt.c: shortened too long line
     add 067b8f230 runtests: add -o to run test cases in scrambled order
     add 1ef38a95d runtests: use -R for random order
     add ad8c1472f unit1305: fix compiler warning
     add 9b47f6792 curl_slist_append.3: clarify a NULL input creates a new list
     add 22fdb0954 tests/server: run checksrc by default in debug-builds
     add 58a6265a4 docs/opts: 23 more man pages now have examples
     add 2b7bde4d3 docs/opts: 24 more man pages now have examples
     add 6dc3422d4 tests: fix -Wcast-qual warnings
     add ba5fa1c7a runtests.pl: simplify the datacheck read section
     add a8e388dd1 curl: remove tool_writeenv.[ch]
     add 271c63748 opts: examples added to 8 more libcurl option man pages
     add 289236b22 opts: fix bad example formatting \n => \\n
     add 6c7f1f741 buildconf: fix hang on IRIX
     add 3661c8aeb tftp: silence bad-function-cast warning
     add ea1b86478 asyn-thread: fix unused macro warnings
     add f67aa4d31 tool_parsecfg: fix -Wcast-qual warning
     add d99acd937 sendrecv: fix MinGW-w64 warning
     add e2b394106 test537: use correct variable type
     add e3f84efc3 runtests: fix "use of undefined value" warning in -R handling
     add f27c884be RELEASE-NOTES: synced with e3f84efc32d6b01a
     add 780073052 curl.1: depend the build on the Makefile.inc too
     add 141ed8ca0 libtest: fix MinGW-w64 warnings
     add e076fdaf5 tftpd: fix signed/unsigned mismatch warnings
     add dc1a1b505 tool_msgs: remove wrong cast
     add 9e9509e46 tests: give each stunnel.conf file a unique name
     add 1cafede9f rand: treat fake entropy the same regardless of endianness
     add 73afcfc0a tests: updated for modified fake random
     add 8b2f22ed2 curl: generate the --help output
     add 2f6bfd549 tests: list the primary server first in the server section
     add 158d70164 formboundary: convert assert into run-time check
     add 4dc849949 tool: fix remaining -Wcast-qual warnings
     add f5b71d3a6 tests: removed redundant --trace-ascii arguments
     add f19baf27e tests: make test file names more unique
     add 8dfa378e5 tests: remove superfluous test 1399
     add e9fd794a6 multi: assign IDs to all timers and make each timer singleton
     add 31b39c40c multi: use a fixed array of timers instead of malloc
     add b875250e3 formdata: fix -Wcomma warning
     add 77b90997d cookie_interface: fix -Wcomma warning
     add bc3866e3e mbedtls: Support server renegotiation request
     add 4cdb1be82 pipeline: fix mistakenly trying to pipeline POSTs
     add d6c74ff66 multi: remove leftover debug infof() calls from e9fd794a6
     add 6d49695bc FAQ: add 7.4 to toc
     add fa0ac3f4d tests: made a couple of prechecks consistent with others
     add d5649c91a THANKS: add a few missing names
     add 646dc1c42 tests: added missing keywords "chunked Transfer-Encoding"
     add b1fa80b84 lib510: don't write past the end of the buffer if it's too 
small
     add d836c9fee url.c: add a compile-time check that CURL_MAX_WRITE_SIZE is 
large enough
     add 180c75eb6 curl: show the libcurl release date in --version output
     add e366ca2b8 CURLOPT_HTTPPROXYTUNNEL: clarify, add example
     add 5ddad099b docs/libcurl/opts: added more examples in man pages
     add 191956963 man pages: fix example syntax errors
     add eb16305e6 SecureTransport/DarwinSSL: Implement public key pinning
     add 590991d07 RELEASE-NOTES: synced with eb16305e6
     add 4fcc0b09f docs/cmdline-opts/config.d: edit for language
     add 32c27f9e9 curl_sasl: fix build error with CURL_DISABLE_CRYPTO_AUTH + 
USE_NTLM
     add c58063b4f darwinssl: Fix exception when processing a client-side 
certificate file if no error was raised by the API but the SecIdentityRef was 
null
     add a6f657911 oauth2-bearer.d: mention the <token> argument
     add b4cfda8a4 mkhelp.pl: do not add current time into curl binary
     add ce73a3016 cmdline-opts/write-out.d: s/-L/--location
     add d6bb1f1d5 asiohiper.cpp / evhiperfifo.c: deal with negative 
timerfunction input
     add e5491e0f9 ghiper.c/hiperfifo.c: add comment about missing timer 
functionality
     add f31760e63 ssh: ignore timeouts during disconnect
     add 052a14e3c tests: stabilize test 1034
     add edd7603e9 RELEASE-NOTES: synced with 052a14e3c
     add 5606fcc65 cmake: Add CURL_CA_FALLBACK to curl_config.h.cmake
     add 8256cce2c cmake: add CURL_CA_BUNDLE/CURL_CA_FALLBACK/CURL_CA_PATH 
options
     add 6a9489dc4 cmake: auto detection of CURL_CA_BUNDLE/CURL_CA_PATH
     add 2ea297564 cmake: remove CURL_CA_BUNDLE from cmake TODO
     add fab962913 cmake: remove unused variables: GNUTLS_ENABLED, NSS_ENABLED
     add 8589e1fe3 assert: avoid, use DEBUGASSERT instead!
     add 945919db5 memdebug: fix compilation failure
     add a1b3a95c9 url: fix declaration of 'pipe' shadows a global declaration
     add b4d6b9944 cmake: fix build on Ubuntu 14.04
     add f0fe66f13 LDAP: using ldap_bind_s on Windows with methods (#878)
     add 48f2a96a6 LDAP: fixed checksrc issue
     add bba59073c redirect: store the "would redirect to" URL when max redirs 
is reached
     add 63cd0d60e LDAP: documentation update per #878 changes (#1506)
     add df45f2c33 winbuild: fix the nghttp2 build
     add b4d87f54d examples: fix Wimplicit-fallthrough warnings
     add 8ab22a745 time: fix type conversions and compiler warnings
     add 59cc0234e ssh: fix 'left' may be used uninitialized
     add a9de0a9f5 docs/CURLOPT_SSLVERSION.3: Correct define name in example
     add d90b729c3 TODO: 6.4 is done, send telnet data in chunks
     add 14514c979 runtests.pl: removed unused arguments to valgrindparse
     add c2227dae5 opts: more examples added in option man pages
     add 01f948796 runtests.pl: removed <precommand> feature
     add 3aaac8c2f tests: removed some redundant empty <stdout> sections
     add 3558e1496 RELEASE-NOTES: synced with 3aaac8c2f
     add 35e9281ef mbedtls: fix variable shadow warning
     add 35682764a test557: fix ubsan runtime error due to int left shift
     add e54db1b05 transfer: init the infilesize from the postfields...
     add dd9755174 CURLOPT_PROXY.3: describe the environment variables more
     add 2d5fa35e8 docs: clarify NO_PROXY further
     add bb1a8c174 opts: more examples added to man pages
     add 534056297 build-wolfssl: Sync config with wolfSSL 3.11
     add a6ad28a75 CURLOPT_PROXY.3: fix test 1140 breakage
     add 314a7fa3c curl-compilers.m4: enable -Wshift-sign-overflow for clang
     add 55fcb8485 example/externalsocket.c: make it use CLOSESOCKETFUNCTION too
     add 501b9ebe9 examples/sampleconv.c: indent changes, made callbacks static
     add 69a6cc2e1 libtest/lib574.c: use correct callback proto
     add 4600362a5 opts: more than 100 more examples for man pages...
     add 28baf380f CURLOPT_FNMATCH_DATA.3: modified example to avoid fcpp issues
     add f072393fe CURLOPT_FNMATCH_FUNCTION.3: also modified example to avoid 
fcpp issues
     add 399a1a618 CURLOPT_STREAM_DEPENDS.3: typo
     add aae4a4788 CURLOPT_SSH_KEY*.3: typos
     add 45cecfbd3 lib583: fix compiler warning
     add c5de7f50f examples/externalsocket.c: s/closesocket/closecb
     add 5598b0bd6 curl-compilers.m4: fix compiler_num for clang
     add 5e796c5e9 curl-compilers.m4: escape square brackets in regex
     add 5fe4f7890 typecheck-gcc.h: separate getinfo slist checks from other 
pointers
     add 4eafc6c24 typecheck-gcc.h: check CURLINFO_TLS_SSL_PTR and 
CURLINFO_TLS_SESSION
     add efc7c1d86 typecheck-gcc.h: check CURLINFO_CERTINFO
     add f6e0f4556 build: provide easy code coverage measuring
     add b5e143e7a coverage: run event tests too
     add 9b2dfe88b test1537: dedicated tests of the URL (un)escape API calls
     add 4ba20a511 curl_endian: remove unused functions
     add cef9c9e78 test1538: verify the libcurl strerror API calls
     add 61d4870dc test1538: fix typo
     add 769890c7e MD(4|5): silence cast-align clang warning
     add 10e02bc36 mbedtls: make TU-local variable static
     add cfd3e8f39 dedotdot: fixed output for ".." and "." only input
     add 5233de9ac tool_util: remove unused tvdiff_secs and remove tool_ prefix
     add 7207affe2 cyassl: define build macros before including ssl.h
     add 191349eb7 updatemanpages.pl: error out on too old git version
     add f8518059c curl_sasl: fix unused-variable warning
     add 15136a526 x509asn1: fix implicit-fallthrough warning with GCC 7
     add 0932573e7 libtest: fix implicit-fallthrough warnings with GCC 7
     add a1b275a41 libtest: fix int-in-bool-context warnings
     add 7bbb78c74 travis: add coverage, distcheck and cmake builds
     add c3ad22697 CONTRIBUTE.md: mention tests done on pull requests
     add 65ba92650 BINDINGS: add Ring binding
     add 892c5e4cb curl_ntlm_core: pass unsigned char to toupper
     add 6b9f4f7f0 RELEASE-NOTES: synced with 65ba92650
     add 796044273 curl_ntlm_core: use Curl_raw_toupper instead of toupper
     add 1573ebee8 test1262: verify ftp download with -z for "if older than 
this"
     add b95a07ea5 test1538: added "verbose logs" keyword
     add cccac4fb2 test1521: test *all* curl_easy_setopt options
     add b8085f493 typecheck-gcc: allow CURLOPT_STDERR to be NULL too
     add 38125e7f7 test1121: use stricter types to work with typcheck-gcc
     add 798b2e196 test1521: make the code < 80 columns wide
     add de0adda78 lib1521: fix compiler warnings
     add bacb909e1 README.md: show the coverall coverage on github
     add e100afb4d travis: let some builds *not* use --enable-debug
     add f7ee701c6 metalink: remove unused printf() argument
     add 68c6dcb2c file: make speedcheck use current time for checks
     add 165b7f509 configure: fix link with librtmp when specifying path
     add 7fffe97b7 expire: remove Curl_expire_latest()
     add 6c5907452 asyn-ares: s/Curl_expire_latest/Curl_expire
     add bc164de7b examples/multi-uv.c: fix deprecated symbol
     add 01596dbad cmake: Fix inconsistency regarding mbed TLS include directory
     add 844896d06 setopt: check CURLOPT_ADDRESS_SCOPE option range
     add b94a2cdfe lib1521: fix compiler warnings on the use of bad 'long' 
values
     add 15b7b8575 gitignore: ignore all vim swap files
     add 4024a0b93 RELEASE-PROCEDURE: updated future release dates
     add 916ec30a9 test1521: fixed OOM handling
     add e8fecf261 FindWin32CACert: Use a temporary buffer on the stack
     add ab1f4eb01 BINDINGS: update SP-Forth and OCaml urls
     add f6dff827d configure: update the copyright year in the output
     add 5fa028e50 urlglob: fix division by zero
     add 5d7952f52 url: fix buffer overwrite with file protocol (CVE-2017-9502)
     add 9f54ad8f1 libressl: OCSP and intermediate certs workaround no longer 
needed
     add 49ff93903 mk-lib1521.pl: updated to match the test changes in 916ec30a
     add 54b636f14 release: 7.54.1
     add 73a2fcea0 includes: remove curl/curlbuild.h and curl/curlrules.h
     add 11c2fb044 dist: make the hugehelp.c not get regenerated unnecessarily
     add adef394ac timers: store internal time stamps as time_t instead of 
doubles
     add 31a67ac1f system.h: fix MinGW build
     add 1213baba2 progress: let "current speed" be UL + DL speeds combined
     add 5113ad042 http-proxy: do the HTTP CONNECT process entirely non-blocking
     add 2ad80eec5 curl/curlver.h: start working on 7.55.0
     add b3e3a08c3 RELEASE-NOTES: synced with 2ad80eec5
     add 84b945883 curl: allow --header and --proxy-header read from file
     add 1c32b6e91 test1147: verify -H on a file
     add c2aeb1b3b lib/curl_setup.h: remove CURL_WANTS_CA_BUNDLE_ENV
     add 7d7346519 curl_setup.h: error out on CURL_WANTS_CA_BUNDLE_ENV use
     add 4d1147ae2 TODO: the generated include file is gone
     add efc83d6d5 http-proxy: only attempt FTP over HTTP proxy
     add b9ead67e1 fuzz: bring oss-fuzz initial code converted to C89
     add fd3aa8da0 fuzz: corpora file structure, initial commit
     add 7e8247c46 fuzz/README: document how to build
     add 0d39e5cc9 http-proxy: fix build with --disable-proxy or --disable-http
     add 3a283968f configure: disable nghttp2 too if HTTP has been disabled
     add 615326fd9 dist: add the fuzz dir to the tarball
     add ec92afc3f mk-ca-bundle.pl: Check curl's exit code after certdata 
download
     add 2a733d641 url: refactor the check for Windows drive letter in path
     add 6c218252d test1061: mark as flaky
     add de4c74754 test1148: verify the -# progressbar
     add f94fcdba6 tests: stabilize test 2032 and 2033
     add 17c5d0528 HTTPS-Proxy: don't offer h2 for https proxy connections
     add e9422bc19 libtest/libntlmconnect: fix compiler warnings from f94fcdb
     add 12ccaed2a http-proxy: deal with EAGAIN
     add 01811b674 http-proxy: fix chunked-encoded CONNECT responses
     add 783ce023a curl-compilers.m4: enable vla warning for clang
     add b5c5909f3 curl-compilers.m4: enable double-promotion warning
     add 32ec3063d curl-compilers.m4: enable missing-variable-declarations 
clang warning
     add 5bdf835c0 curl-compilers.m4: enable comma clang warning
     add ce2cc568f Makefile.m32: enable -W for MinGW32 build
     add 5385450af curl: prevent binary output spewed to terminal
     add d4cc240c1 tool_wrte_cb: remove check for config == NULL
     add 8bc9cabd7 TODO: implement support for CURLOPT_PREQUOTE with SFTP
     add c095d7b59 TODO: update the TOC too
     add deff7de0e http_proxy: fix compiler warning
     add edafd52be http_proxy: fix build with http and proxy
     add 7b3b4722b CURLOPT_PREQUOTE.3: spellfix man page reference
     add 65ca03051 http2: fix OOM crash
     add 620854700 PIPELINING_SERVER_BL: cleanup the internal list use
     add 3b80d3ca4 getinfo: return sizes as curl_off_t
     add 604edced2 RELEASE-NOTES: synced with 3b80d3ca4
     add fb470a2e4 mkhelp.pl: fix script name in usage text
     add 8621b6104 automake: use $(MKHELP) variable instead if constant 
mkhelp.pl
     add 0bd12d197 lib1521: add curl_easy_getinfo calls to the test set
     add 176ec5138 test1521: test getinfo's OFF_T types too
     add b778ae4c5 http: add --strip-path-slash and CURLOPT_STRIP_PATH_SLASH
     add 0feb762fc travis: do the distcheck test build out-of-tree as well
     add 651e04c4c if2ip: fix compiler warning in ISO C90 mode
     add 60c655ac0 lib: fix the djgpp build
     add f541f7b94 ci: whitelist branches to avoid testing feature branches 
twice
     add ec512074c typecheck-gcc: add support for CURLINFO_OFF_T
     add c1dfc8a07 travis: enable typecheck-gcc warnings
     add 8de8f4eb7 lib1521: fix missing-variable-declarations clang warnings
     add 9b167fd09 --request-target: instead of --strip-path-slash
     add 0537238cb maketgz: switch to xz instead of lzma
     add b4043706e CONTRIBUTE.md: mention the out-of-tree build test too
     add 2647ad2fe libtest/Makefile: remove unused lib1541 variables
     add e76e45241 maketgz: switch to -6e for xz
     add 924cd3e25 CURLINFO_REDIRECT_URL.3: mention the CURLOPT_MAXREDIRS case
     add 64ed44a81 progress: fix "time spent", broke in adef394ac
     add e5d6aa8d6 curl-compilers.m4: fix unknown-warning-option on Apple clang
     add cfe3c08f6 progress: progress.timespent needs to be us
     add cd34ffa61 winbuild: fix boringssl build
     add ceff21ab7 curl/system.h: add check for XTENSA for 32bit gcc
     add e8a4da67f test1521: fix compiler warnings
     add bec809cb2 test1537: fixed memory leak on OOM
     add 922f80060 tool_getparam: fix memory leak on test 1147 OOM (torture 
tests)
     add 467da3af0 libtest/make: generate lib1521.c
     add 641072b91 socks: use proxy_user instead of proxy_name
     add cd1c9f080 socks: deduplicate the code for auth request
     add 8924f58c3 CURLOPT_SOCKS5_AUTH: allowed methods for SOCKS5 proxy auth
     add ce2c3ebda curl --socks5-{basic,gssapi}: control socks5 auth
     add 2ed8bdd3c RELEASE-NOTES: synced with ce2c3ebda
     add ef2a9f22c curl_strequal.3: fix typo in SYNOPSIS
     add f8f040e65 progress: prevent resetting t_starttransfer
     add 192877058 openssl: improve fallback seed of PRNG with a time based hash
     add c75f63d7c handler: refactor connection checking
     add c98e97e9c http2: handle PING frames
     add 77970f484 test1521: fix out-of-tree builds, broken with 467da3af
     add 9b387034a test1450: add simple testing for DICT
     add 0362c7784 test1450: fix up DICT server in torture mode
     add d24838d4d make: build the docs subdir only from within src
     add 8d2b1de28 unit1399: add logging to time comparison
     add 4fc6ebe18 cmake: Added compatibility options for older Windows versions
     add 3a48a1326 unit1399: fix integer overflow
     add c0cdc68c7 gtls: fix build when sizeof(long) < sizeof(void *)
     add b3786f61d url: make the original string get used on subsequent 
transfers
     add f50124f56 timeval.c: Use long long constant type for timeval assignment
     add c1d1a3448 tool_sleep: typecast to avoid macos compiler warning
     add fc2e81c38 travis.yml: use --enable-werror on debug builds
     add f1609155d test: add impacket for SMB testing
     add a6f8d27ef test1451: add SMB support to the testbed
     add 7121a994d dist: add SMB python deps into the tarball
     add 909a5bee8 configure: remove checks for 5 functions never used
     add c53438481 configure: try ldap/lber in reversed order first
     add f8dba473a smb: fix build for djgpp/MSDOS
     add 84a317cf1 travis: install nghttp2 on linux builds
     add 596cfb6c0 smb: add support for CURLOPT_FILETIME
     add fa289ea08 RELEASE-NOTES: synced with 596cfb6c0
     add 40ed7685b cmake: fix send/recv argument scanner for windows
     add add0f7119 TODO: HTTP proxy CONNECT is non-blocking now
     add da08c867e TODO: 1.10 auto-detect proxy
     add 21e070573 inet_pton: fix include on windows to get prototype
     add 7e21e5fd0 select.h: avoid macro redefinition harder
     add 9ee6cb1b7 cmake: if inet_pton is used, bump _WIN32_WINNT
     add b22f93dbb http: s/TINY_INITIAL_POST_SIZE/EXPECT_100_THRESHOLD
     add 6b0aa00ab asyn-thread.c: fix unused variable warnings on macOS
     add 759efe7b5 runtests: support "threaded-resolver" as a feature
     add 23b828b78 test506: skip if threaded-resolver
     add 75c3596f7 cmake: remove spurious "-l" from linker flags
     add ce81aeb87 cmake: add CURL_WERROR for enabling "warning as errors"
     add 2d86e8d12 appveyor: enable CURL_WERROR on all builds
     add 0cec0f461 memdebug: don't setbuf() if the file open failed
     add a126ca848 curl_easy_escape.3: mention the (lack of) encoding
     add efedafe48 travis: do more tests in the coverage run
     add 06a6feba9 test1452: add telnet negotiation
     add bbc9c6d14 CURLOPT_POSTFIELDS.3: explain the 100-continue magic better
     add 45f39945e cmake: offer CMAKE_DEBUG_POSTFIX when building with MSVC
     add 7bcaa1aa2 travis: add SMB, DICT, TELNET torture to coverage test
     add 8b78f7c23 travis: detect and use valgrind for normal builds
     add be2c999b8 valgrind.supp: supress OpenSSL false positive seen on travis
     add ca3545d17 travis: install stunnel
     add a54818354 RELEASE-NOTES: synced with be2c999b8
     add f601f4278 tool_cb_wrt: fix variable shadowing warning
     add 59a0fb243 smb: rename variable to fix shadowing warning
     add 17da67500 tool_getparam: fix potentially uninitialized err
     add af0216251 curl_setup_once: Remove ERRNO/SET_ERRNO macros
     add deadb2348 curl-compilers.m4: disable warning spam with Cygwin's clang
     add b54e0babd ldap: fix MinGW compiler warning
     add 793e831bb make: fix docs build on OpenBSD
     add a5834e525 errno: fix non-windows builds after af0216251b94e7
     add e909de65b tests: Fix up issues with errno in test files
     add c5e87fdb7 strerror: Preserve Windows error code in some functions
     add beb08481d curl_setup: always define WIN32_LEAN_AND_MEAN on Windows
     add 274983b77 ISSUE_TEMPLATE: Add a comment not to file security issues on 
github
     add ef5cac3d8 build: remove WIN32_LEAN_AND_MEAN from individual build 
systems
     add b22ec3964 system.h: include winsock2.h before windows.h
     add 51ccc4850 travis: install libssh2
     add 7333b497a travis: enable warnings also in release mode
     add ffd3162c6 travis: install libidn2
     add cda19a345 winbuild: build with warning level 4
     add a4bef6a91 winbuild: re-enable warning C4127 for curl tool
     add 70cbefeb5 rtspd: fix MSVC level 4 warning
     add 0bdb81125 sockfilt: suppress conversion warning with explicit cast
     add fb3b0f25e libtest: fix MSVC warning C4706
     add 38faf041c rtspd: fix GCC warning after MSVC warning fix
     add 798ad5d92 darwinssl: fix pinnedpubkey build error
     add da6aa3f76 tests/server/resolve.c: fix deprecation warning
     add c89eb6d0f nss: unify the coding style of nss_send() and nss_recv()
     add 42a4cd4c7 nss: fix a possible use-after-free in SelectClientCert()
     add 60cf84f7f checksrc: escape open brace in regex
     add 02c7a2cca multi: mention integer overflow risk if using > 500 million 
sockets
     add 7551e55d6 darwinssl: fix variable type mistake (regression)
     add 4dee50b9c timeval: struct curltime is a struct timeval replacement
     add 001822153 test1323: verify curlx_tvdiff
     add 1cfa4cd42 curl_rtmp: fix a compiler warning
     add 171f8ded2 include.d: clarify that it concerns the response headers
     add f8614af52 splay: fix signed/unsigned mismatch warning
     add de6de94c9 tool_help: clarify --include is only for response headers
     add 001701c47 AppVeyor: now really use CURL_WERROR
     add e88f13329 RELEASE-NOTES: synced with 001701c47
     add 27e2a4733 cmake: support make uninstall
     add 436cd490f include.d: clarify --include is only for response headers
     add 512f8c774 libcurl: Stop using error codes defined under CURL_NO_OLDIES
     add 909283ae5 http: fix response code parser to avoid integer overflow
     add f262b3586 configure: fix the check for IdnToUnicode
     add 53d137d94 curl_setup: Define CURL_NO_OLDIES for building libcurl
     add 164a09368 multi: fix request timer management
     add 821a0854f BUGS: clarify how to report security related bugs
     add 62495ff31 BUGS: improved phrasing about security bugs
     add 013954560 curl_threads: fix MSVC compiler warning
     add 920f777fc tests/server/util: fix curltime mistake from 4dee50b9c80f9
     add 23b4a0521 travis: build osx with openssl too
     add 1767adf43 travis: build osx with libressl too
     add 7e48aa386 CURLOPT_NETRC.3: mention the file name on windows
     add 70934885d CURLOPT_NETRC.3: fix typo in 7e48aa386156f9c2
     add 866e02935 CMake: set MSVC warning level to 4
     add a8e1c2e46 netrc: skip lines starting with '#'
     add 58752b78c test130: verify comments in .netrc
     add fa2f134cb darwinssl: fix curlssl_sha256sum() compiler warnings on 
first argument
     add 6f6cfc90b BUILD.WINDOWS: mention buildconf.bat for builds off git
     add af271ce9b darwin: silence compiler warnings
     add 2b7ce3f56 travis: add osx build with darwinssl
     add fdb163c73 travis: BUILD_TYPE => T
     add b7386c0ac travis: explicitly specify dist
     add 2ccd65af3 FTP: skip unnecessary CWD when in nocwd mode
     add 561e9217c test1010: verify that #1718 is fixed
     add 26e02eae4 RELEASE-NOTES: synced with 561e9217c
     add 54aef857b CMake: fix CURL_WERROR for MSVC
     add 61046e7bd darwinssl: fix compiler warning
     add 0b1166023 gssapi: fix memory leak of output token in multi round 
context
     add d6c8def82 getparameter: avoid returning uninitialized 'usedarg'
     add fa4898735 easy_events: make event data static
     add c9332fa5e file: output the correct buffer to the user
     add 358b2b131 tftp: reject file name lengths that don't fit
     add 453e7a7a0 glob: do not continue parsing after a strtoul() overflow 
range
     add 5c7455fe7 curl: detect and bail out early on parameter integer 
overflows
     add 581011a3d test1427: verify command line parser integer overflow 
detection
     add 18eac3df1 ax_code_coverage.m4: update to latest version
     add 58845f2e2 configure: fix recv/send/select detection on Android
     add 13ef623a8 docs/comments: Update to secure URL versions
     add 7417029e1 THANKS: 20 new contributors in 7.55.0
     add 2679562dc RELEASE-NOTES: curl 7.55.0
     add f864bd8c8 build: fix 'make install' with configure, install 
docs/libcurl/* too
     add a7bbbb7c3 make install: add 8 missing man pages to the installation
     add 45a560390 curl: do bounds check using a double comparison
     add 7e949de1d dist: Add dictserver.py/negtelnetserver.py to EXTRA_DIST
     add 0b5665c98 digest_sspi: Don't reuse context if the user/passwd has 
changed
     add 42ba39b06 gitignore: ignore top-level .vs folder
     add afc9651a6 build: check out *.sln files with Windows line endings
     add 478596b34 travis: verify "make install"
     add 050e3532f dist: fix the cmake build by shipping 
cmake_uninstall.cmake.in too
     add a17e7721d metalink: fix error: ‘*’ in boolean context, suggest ‘&&’ 
instead
     add ac8af8452 cmake: move cmake_uninstall.cmake to CMake/
     add d86e9182e configure: use the threaded resolver backend by default if 
possible
     add f87e77b1d mkhelp.pl: allow executing this script directly
     add 4ebe24dfe maketgz: remove old *.dist files before making the tarball
     add f26f6d258 openssl: remove CONST_ASN1_BIT_STRING.
     add fd07ca1e2 openssl: fix "error: this statement may fall through"
     add 37f2195a9 curlver: bump to 7.55.1
     add 783d43464 RELEASE-NOTES: synced with 37f2195a9
     add 6e0e152ce parse_proxy(): fix memory leak in case of invalid proxy 
server name
     add 77cd4e769 test1447: verifies the parse proxy fix in 6e0e152ce5c
     add be2a4c178 test2033: this went flaky again
     add 4ca5f772e curl/system.h: support more architectures
     add 2747aec34 test1447: require a curl with http support
     add 274f9cac9 docs: fix typo stuct -> struct
     add 34f24fef4 docs: fix grammar in CURL_SSLVERSION_MAX_DEFAULT description
     add a6fdf1177 docs: fix typo funtion -> function
     add 7c711996a curl/system.h: add Oracle Solaris Studio
     add 7973baace bagder/Curl_tvdiff_us: fix the math
     add 1562644e3 connect-to.d: clarified
     add c07898133 connect-to.d: better language
     add 7f9bf5cfd cmake: allow user to override CMAKE_DEBUG_POSTFIX
     add 65c147a46 travis: test cmake build on tarball too
     add 47e4a6fa1 test2032: mark as flaky (again)
     add d6ecb2c85 redirect: skip URL encoding for host names
     add 6bde13a53 test1448: verify redirect to IDN using URL
     add 10b3df105 curl/system.h: GCC doesn't define __ppc__ on PowerPC, uses 
__powerpc__
     add b748d7af7 ipv6_scope: support unique local addresses
     add a905e883d cmake: Threads detection update. ref: #1702
     add 55c8a5573 gitignore: ignore .xz now instead of .lzma
     add 8839c05fb RELEASE-NOTES/THANKS: curl 7.55.1 release time
     new adc35a4f1 examples/ftpuploadresume.c: use portable code
     new 5c2aac716 runtests: match keywords case insensitively
     new b53b4e442 travis: build the examples too
     new ff50fe034 strtoofft: reduce integer overflow risks globally
     new 91c46dc44 test1449: FTP download range with an too large size
     new c39f20435 RELEASE-NOTES: synced with 91c46dc44
     new 9bd2248f9 curlver: toward 7.56.0?
     new ab2a7079c zsh.pl: produce a working completion script again
     new 0969901eb cmake: remove dead code for CURL_DISABLE_RTMP
     new 43d036e72 progress: Track total times following redirects
     new 3cb4bb6b5 curl-confopts.m4: fix --disable-threaded-resolver
     new 774d49af5 cmake: remove dead code for DISABLED_THREADSAFE
     new b5cc7dd36 m4/curl-compilers.m4: use proper quotes around string, not 
backticks
     new 75536e529 darwinssi: fix error: variable length array used
     new 8de5e409c coverage: Use two coveralls commands to get lib/vtls results
     new ca9630f12 travis: add metalink to some osx builds
     new 870d849d4 configure: check for __builtin_available() availability 
(#1788)
     new 801d8765c http_proxy: fix build error for CURL_DOES_CONVERSIONS
     new d18941ea1 examples/ftpuploadresume: checksrc compliance
     new b7b4dc0d4 ssh: add the ability to enable compression (for SCP/SFTP)
     new b4b26cdda curl/system.h: checksrc compliance
     new 525fb7e16 compressed-ssh.d: "Added: 7.56.0"
     new 582f2a130 CURLOPT_SSH_COMPRESSION.3: enable with 1L
     new c95eff4a1 ftp: fix CWD when doing multicwd then nocwd on same 
connection
     new 80d9e3559 system.h: remove all CURL_SIZEOF_* defines
     new 1286b7c09 cmake: sizeof curl_off_t, remove unused detections
     new ae41dd85e config-win32: define SIZEOF_CURL_OFF_T
     new ab2ef24d5 lib557: no longer use CURL_SIZEOF_* defines
     new 6b9bc5a4f CURL_SIZEOF_LONG: removed, use only SIZEOF_LONG
     new 1f39245dc metalink: adjust source code style
     new 74dac344b http: Don't wait on CONNECT when there is no proxy
     new f2d060cf2 curl/system.h: check for __ppc__ as well
     new ffb2bc394 KNOWN_BUGS: HTTP test server 'connection-monitor' problems
     new 9e82d125e http2_recv: return error better on fatal h2 errors
     new 058c8a6f2 mailmap: de-duplify some git authors
     new 8baead425 scripts/contri*sh: use "git log --use-mailmap"
     new c1a75407c RELEASE-NOTES: synced with 8baead425
     new c468c27b5 tests: Make sure libtests call curl_global_cleanup()
     new b9e22e957 runtests: fixed case insensitive matching of keywords
     new 16c71fafb tftp: fix memory leak on too long filename
     new a4f488800 curl/system.h: fix build for hppa
     new b93954261 cmake: enable picky compiler options with clang and gcc
     new ebf46317e config-win32: define SIZEOF_LONG
     new 43fb867a5 makefile.m32: add support for libidn2
     new 88220adb7 tool_main: turn off MinGW CRT's globbing
     new 88c2e2273 request-target.d: mention added in 7.55.0
     new f412a5aab curl: shorten and clean up CA cert verification error message
     new beda1dbe1 config-dos: add missing defines, SIZEOF_* and two others
     new 78a6d917c test1453: Fixed <features>
     new 00da16ca5 config-tpf: define SIZEOF_LONG
     new befaa7b14 imap: support PREAUTH
     new 4a7673c8c CURLOPT_USERPWD.3: see also CURLOPT_PROXYUSERPWD
     new dff069fdf imap: use defined names for response codes
     new e37ab949b examples/threaded-ssl: mention that this is for openssl 
before 1.1
     new 3e1245504 fuzz/Makefile.am: remove curlbuild.h leftovers
     new 09fc61e43 winbuild: fix embedded manifest option
     new d7d0c9d95 tests: Make sure libtests & unittests call 
curl_global_cleanup()
     new 8a84fcc4b system.h: include sys/poll.h for AIX
     new b3b75d177 darwinssl: handle long strings in TLS certs
     new 78b863de7 strtooff: fix build for systems with long long but no 
strtoll option
     new dd02a9a34 vtls: use consistent signature for _random() implementations
     new b31d1dcdd vtls: make sure all _cleanup() functions return void
     new 2568cfed2 vtls: make sure all _data_pending() functions return bool
     new c9d526cdb vtls: make sure every _sha256sum()'s first arg is const
     new e7e03e47d vtls: introduce a new struct for SSL backends
     new e09bb63ed vtls: declare Curl_ssl structs for every SSL backend
     new 52e8237bf vtls: use the Curl_ssl struct to access all SSL backends' 
functionality
     new e35205a0c vtls: move md5sum into the Curl_ssl struct
     new 0a083a66b vtls: move sha256sum into the Curl_ssl struct
     new 937899a3b vtls: convert the have_curlssl_* constants to runtime flags
     new f0b4db1ab vtls: move the SUPPORT_HTTPS_PROXY flag into the Curl_ssl 
struct
     new 3ea5461d4 axtls: reorder functions topologically
     new 742ddc9d8 schannel: reorder functions topologically
     new 6f1eec14e vtls: remove obsolete declarations of SSL backend 
functionality
     new 5d9fcd216 axtls: use Curl_none_* versions of init() and cleanup()
     new 118b074fb vtls: move SSL backends' private constants out of their 
header files
     new 69039fd1f getinfo: access SSL internals via Curl_ssl
     new 583cb03f9 urldata.h: remove support for obsolete PolarSSL version
     new 20c6cf7e9 urldata.h: move SSPI-specific #include to correct location
     new d65e6cc4f vtls: prepare the SSL backends for encapsulated private data
     new 70f1db321 vtls: encapsulate SSL backend-specific data
     new a243ce7ab curl_ntlm_core: don't complain but #include OpenSSL header 
if needed
     new a53bda35e vtls: fold the backend ID into the Curl_ssl structure
     new b0989cd3a vtls: allow selecting which SSL backend to use at runtime
     new b59288f88 vtls: refactor out essential information about the SSL 
backends
     new 1328f69d5 vtls: introduce curl_global_sslset()
     new 0fb412555 Add a man page for curl_global_sslset()
     new a34e141c0 docs/examples: demonstrate how to select SSL backends
     new b180a273f metalink: allow compiling with multiple SSL backends
     new 9d96a5f0b version: add the CURL_VERSION_MULTI_SSL feature flag
     new 81d318fa9 version: if built with more than one SSL backend, report all 
of them
     new 3063254e3 vtls: use Curl_ssl_multi pseudo backend only when needed
     new c7170e20d configure: allow setting the default SSL backend
     new a330bab35 configure: Handle "MultiSSL" specially When versioning 
symbols
     new 11a8778e0 asyn-thread: Set errno to the proper value ENOMEM in OOM 
situation
     new d5d736726 asyn-thread: Improved cleanup after OOM situations
     new 82604c500 unit1606: Fixed shadowed variable warning
     new edcb1ef60 curl_global_init.3: mention curl_global_sslset(3)
     new df29455db asyn-thread: Fixed cleanup after OOM
     new f93bf2c79 HELP-US.md: "How to get started helping out in the curl 
project"
     new 8c33c963a HELP-US.md: spelling
     new ff40c89b8 RELEASE-NOTES: synced with 8c33c963a
     new 73fa6aa00 curl/multi.h: remove duplicated closing c++ brace
     new 860443bee curl_global_sslset.3: clarify
     new 29c2bdee9 curl.h: CURLSSLBACKEND_WOLFSSL used wrong value
     new c86e21b62 makefile.m32: add multissl support
     new 7ec797b13 examples/sslbackend.c: fix failure of 'make checksrc'
     new 5fbb49429 configure: remove the leading comma from the backends list
     new 5734f73f0 polarssl: fix multissl breakage
     new 410bf6b7b cyassl: call it the "WolfSSL" backend
     new aa2ea66cd darwinssl: handle long strings in TLS certs (follow-up)
     new f7512d7be curl_global_sslset.3: show the struct and enum too
     new 529f05680 unit1301: fix error message on first test
     new 222e65fd7 strcase: corrected comment header for Curl_strcasecompare()
     new efeb4a317 ossfuzz: moving towards the ideal integration
     new 1cf323ec4 ossfuzz: additional seed corpora
     new c290b8fb2 curl_global_sslset: select backend by name case insensitively
     new 57001ce3b ossfuzz: Move to C++ for curl_fuzzer.
     new 3b51fa628 http: fix a memory leakage in checkrtspprefix().
     new 70231d6a6 non-ascii: allow conversion functions to be called with a 
NULL data handle.
     new 6869d65f5 Curl_base64_encode: always call with a real data handle.
     new f0cda3414 runtests.pl: Apply strippart to upload too.
     new 989e4d4a3 runtests.pl: allow <file[1-4]> tags in client section.
     new ea4e7bdc8 checksrc: disable SPACEBEFOREPAREN for case statement.
     new 5bae72734 test564: Add a warning comment about shell profile output.
     new ce0881ede mime: new MIME API.
     new fec7a858b mime: use in curl cli tool instead of form API.
     new 3baf36edf mime: tests and examples.
     new 045b076ae mime: fix some implicit curl_off_t --> size_t conversion 
warnings.
     new 1a3f4c199 mime: remove support "-" stdin pseudo-file name in 
curl_mime_filedata().
     new efd930142 mime: use size_t instead of ssize_t in public API interface.
     new 437475901 tool_formparse: fix some trivial warnings
     new 7e36b30da mime: fix signed/unsigned conversions.
     new 0d4a6355a headers: move the global_sslset() proto from multi.h to 
curl.h
     new 1ab9e9b50 lib: bump version info (soname). Adapt and reenable test 
1135.
     new d24c05b90 RELEASE-NOTES: synced with 1ab9e9b50
     new 2e4074c95 docs: curl_mime_*.3 man page formatting edits
     new bd8070085 curl.h: make the curl_strequal() protos use the same style
     new b081f2ada RELEASE-NOTES: fixed the function counter script
     new 12e789391 examples/post-callback: stop returning one byte at a time
     new 4ed618c02 test1135: fixed after bd8070085f9
     new 202c1cc22 schannel: return CURLE_SSL_CACERT on failed verification
     new 841a09ea1 mime: use CURL_ZERO_TERMINATED in examples
     new 1c8725e63 docs: Update to secure URL versions
     new 7b8162366 curl.h: fix "unused checksrc ignore", remove dangling 
reference
     new d491a9c3a MAIL-ETIQUETTE: added "1.9 Your emails are public"
     new 3130414ce http-proxy: treat all 2xx as CONNECT success
     new 889723b00 configure: add MultiSSL to FEATURES when enabled
     new eae21db92 docs/curl_mime_*.3: added examples
     new 25fc694a4 examples/mime: minor example code fixes
     new ea142a837 openssl: use OpenSSL's default ciphers by default
     new 8b902ef0a docs/curl_mime_*.3: use correct variable types in examples
     new 295ce716a curl.h: use lower case curl_mime* as for all public symbols
     new 9926357b4 mime: unified to use the typedef'd mime structs everywhere
     new 328ce03d5 fixup data/test1135
     new 3bbe894fd runtests.pl: support attribute "nonewline" in part 
verify/upload.
     new 63ef436ea mime: implement encoders.
     new c1d0b6f98 mime: replace 'struct Curl_mimepart' by 'curl_mimepart' in 
encoder code.
     new ee5725fb5 mime: fix a trivial warning.
     new 6cdba64e1 openssl: Integrate Peter Wu's SSLKEYLOGFILE implementation
     new 61825be02 vtls: select ssl backend case-insensitive (follow-up)
     new d1da545a6 configure: remove --enable-soname-bump and SONAME_BUMP
     new c96d96bc5 mime: drop internal FILE * support.
     new 70a69f371 SSL: fix unused parameter warnings
     new cd8d9bb93 HISTORY: added some recent items
     new 6b585b118 travis: add c-ares enabled builds linux + osx
     new 4bb80d532 vtls: switch to CURL_SHA256_DIGEST_LENGTH define
     new 955c21939 vtls: fix memory corruption
     new dde4f5c81 OpenSSL: fix erroneous SSL backend encapsulation
     new f4a623825 OpenSSL: fix yet another mistake while encapsulating SSL 
backend data
     new 9ef50ee0a http-proxy: when not doing CONNECT, that phase is done 
immediately
     new 08aeae0e3 KNOWN_BUGS: Remove CMake symbol hiding issue
     new 3dab9f6c7 configure: fix curl_off_t check's include order
     new 3620e569b form API: add new test 650.
     new 1ae2704d6 configure: check for C++ compiler after C, to make it 
non-fatal
     new 261da2a66 ossfuzz: add some more handled CURL options
     new f8548e84a configure: use -Wno-varargs on clang 3.9[.X] debug builds
     new a14f7152c rtsp: do not call fwrite() with NULL pointer FILE *
     new 64bb7ae6a mbedtls: enable CA path processing
     new 7207aaa69 travis: add build without HTTP/SMTP/IMAP
     new 02eb6184a Curl_checkheaders: make it available for IMAP and SMTP too
     new e155f38d1 checksrc: verify spaces around equals signs
     new 6b84438d9 code style: use spaces around equals signs
     new ca86006de checksrc: detect and warn for lack of spaces next to plus 
signs
     new e5743f08e code style: use spaces around pluses
     new 67ade2857 checksrc: verify space after semicolons
     new 20acb58a3 code style: use space after semicolon
     new 59813726d checksrc: detect and warn for multiple spaces
     new 87501e57f code style: remove wrong uses of multiple spaces
     new 7e4634cfe RELEASE-NOTES: synced with 87501e57f
     new 22708eae4 URL: on connection re-use, still pick the new remote port
     new 65872efea test1150: verify same host fetch using different ports over 
proxy
     new 56d949d31 tests: add initial gssapi test using stub implementation
     new 9bba664e0 tests: enable gssapi in travis-ci linux build
     new 08dbed31d rtsp: Segfault in rtsp.c when using WRITEDATA
     new 50b208e23 docs: clarify the CURLOPT_INTERLEAVE* options behavior
     new 2fc1db56c escape.c: error: pointer targets differ in signedness
     new 46e14b694 non-ascii: use iconv() with 'char **' argument
     new 452c906df server/getpart: provide dummy function to build conversion 
enabled
     new 93843c372 conversions: fix several compiler warnings
     new 843200c5b openssl: add missing includes
     new c8666089c schannel: Support partial send for when data is too large
     new 6d436642d socks: fix incorrect port number in SOCKS4 error message
     new 697271fc9 curl: make str2udouble not return values on error
     new 1a072796d travis: on mac, don't install openssl or libidn
     new 2bc230de6 cookies: reject oversized cookies
     new e239eda39 ossfuzz: don't write out to stdout
     new bec50cc28 mime:escape_string minor clarification change
     new c73ebb853 ossfuzz: changes before merging the generated corpora
     new 5fe85587c cookies: use lock when using CURLINFO_COOKIELIST
     new 7f794a224 RELEASE-NOTES: synced with 5fe85587c
     new 1e548f778 smtp: fix memory leak in OOM
     new 299896ca0 curl: check fseek() return code and bail on error
     new f30420186 mime: fix an explicit null dereference (#1899)
     new a7bcf274c mime: rephrase the multipart output state machine (#1898) ...
     new 5d916944a examples/post-callback: use long for CURLOPT_POSTFIELDSIZE
     new fa9482ab0 openssl: only verify RSA private key if supported
     new ee56fdb69 form/mime: field names are not allowed to contain 
zero-valued bytes.
     new b8e0fe19e vtls: provide curl_global_sslset() even in non-SSL builds
     new a4db3f704 tests: make the imap server not verify user+password
     new 3b05f79ef imap: quote atoms properly when escaping characters
     new 7c52b12dd symbols-in-versions: add CURLSSLSET_NO_BACKENDS
     new 6f86022df ntlm: use strict order for SSL backend #if branches
     new de4715893 metalink: fix NSS issue in MultiSSL builds
     new 3a1c7cb3c symbols-in-versions: fix CURLSSLSET_NO_BACKENDS entry
     new b6a90bca3 tests: fix a compiler warning in test 643
     new afbdc9663 file_range: avoid integer overflow when figuring out byte 
range
     new 953b5c4e2 ntlm: move NTLM_NEEDS_NSS_INIT define into core NTLM header
     new d8ab5dc50 tests: adjust .gitignore for new tests
     new 91a6e60c1 RELEASE-NOTES: synced with d8ab5dc50
     new 6aa86c493 curl.h: include <sys/select.h> on cygwin too
     new 284d06df9 reuse_conn: don't copy flags that are known to be equal
     new eac324f28 http: add custom empty headers to repeated requests
     new 46d63bbbe docs: clarify the use of environment variables for proxy
     new c66d94d6d docs: link CURLOPT_CONNECTTIMEOUT and 
CURLOPT_CONNECTTIMEOUT_MS
     new 49d75a4c1 connect: fix race condition with happy eyeballs timeout
     new 20ea22ff7 cookie: fix memory leak on oversized rejection
     new a352e21c0 test1160: verifies cookie leak for large cookies
     new df7839b68 Set and use more necessary options when some protocols are 
disabled
     new cecffff56 test650: Use variable replacement to set the host address 
and port
     new 8392a0cf6 cookie: fix memory leak if path was set twice in header
     new 525251398 libcurl-tutorial: describe MIME API and deprecate form API.
     new 3ac14ab39 TODO: remove deprecated form API items.
     new 753a5da90 libcurl-tutorial: fix two typos.
     new 440dbcb06 cmake: disable tests and man generation if perl/nroff not 
found
     new 5ff2c5ff2 FTP: zero terminate the entry path even on bad input
     new 232289133 test1153: verify quoted double-qoutes in PWD response
     new c3e58d93d examples: bring back curl_formadd-using examples
     new ff6774ea6 libcurl-tutorial: add casts in example to avoid compilation 
warnings.
     new c4ebd8b46 proxy: read the "no_proxy" variable only if necessary
     new 9d3dde37a vtls: compare and clone ssl configs properly
     new 5f1fa5827 idn: fix source code comment
     new e702df7a8 build-openssl.bat: Warn OpenSSL 1.1.0 not yet supported
     new 6119ce080 THANKS: added new 7.56.0 contributors
     new 3ea767905 RELEASE-NOTES: curl 7.56.0
     new 64d20516f Merge tag 'curl-7_56_0'

The 256 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:
 .gitignore                                         |    5 +-
 .mailmap                                           |   26 +
 .travis.yml                                        |   48 +-
 CMake/Macros.cmake                                 |   29 +
 CMakeLists.txt                                     |  114 +-
 Makefile.am                                        |    3 +
 RELEASE-NOTES                                      |  245 ++-
 acinclude.m4                                       |  325 +---
 configure.ac                                       |  218 ++-
 docs/CODE_OF_CONDUCT.md                            |    4 +-
 docs/HELP-US.md                                    |   70 +
 docs/HISTORY.md                                    |   18 +
 docs/INSTALL.md                                    |    3 +
 docs/KNOWN_BUGS                                    |   16 +-
 docs/MAIL-ETIQUETTE                                |   31 +-
 docs/Makefile.am                                   |    2 +-
 docs/THANKS                                        |   30 +-
 docs/TODO                                          |   49 +-
 docs/cmdline-opts/Makefile.inc                     |    3 +-
 docs/cmdline-opts/cacert.d                         |    2 +-
 docs/cmdline-opts/compressed-ssh.d                 |    7 +
 docs/cmdline-opts/form-string.d                    |    4 +-
 docs/cmdline-opts/form.d                           |   80 +-
 docs/cmdline-opts/gen.pl                           |    2 +-
 docs/cmdline-opts/request-target.d                 |    1 +
 docs/examples/.gitignore                           |    1 +
 docs/examples/10-at-a-time.c                       |    8 +-
 docs/examples/Makefile.inc                         |    9 +-
 docs/examples/anyauthput.c                         |    4 +-
 docs/examples/cacertinmem.c                        |   44 +-
 docs/examples/chkspeed.c                           |    4 +-
 docs/examples/curlx.c                              |   71 +-
 docs/examples/debug.c                              |   24 +-
 docs/examples/evhiperfifo.c                        |   24 +-
 docs/examples/fopen.c                              |   81 +-
 docs/examples/ftpget.c                             |    8 +-
 docs/examples/ftpsget.c                            |    8 +-
 docs/examples/ftpupload.c                          |    4 +-
 docs/examples/ftpuploadresume.c                    |   36 +-
 docs/examples/ghiper.c                             |   44 +-
 docs/examples/hiperfifo.c                          |   22 +-
 docs/examples/htmltidy.c                           |    6 +-
 docs/examples/http2-download.c                     |   30 +-
 docs/examples/http2-serverpush.c                   |   28 +-
 docs/examples/http2-upload.c                       |   30 +-
 docs/examples/httpput.c                            |    4 +-
 docs/examples/imap-multi.c                         |    4 +-
 docs/examples/multi-app.c                          |   12 +-
 docs/examples/multi-debugcallback.c                |   26 +-
 docs/examples/multi-double.c                       |    4 +-
 docs/examples/{multi-post.c => multi-formadd.c}    |   12 +-
 docs/examples/multi-post.c                         |   62 +-
 docs/examples/multithread.c                        |    4 +-
 docs/examples/opensslthreadlock.c                  |    4 +-
 docs/examples/pop3-multi.c                         |    4 +-
 docs/examples/post-callback.c                      |   55 +-
 docs/examples/postinmemory.c                       |    4 +-
 docs/examples/{postit2.c => postit2-formadd.c}     |   10 +-
 docs/examples/postit2.c                            |   56 +-
 docs/examples/sendrecv.c                           |    4 +-
 docs/examples/sftpget.c                            |    8 +-
 docs/examples/simplepost.c                         |    4 +-
 docs/examples/simplessl.c                          |    4 +-
 docs/examples/smooth-gtk-thread.c                  |    6 +-
 docs/examples/smtp-mail.c                          |    4 +-
 docs/examples/{smtp-mail.c => smtp-mime.c}         |  117 +-
 docs/examples/smtp-multi.c                         |    8 +-
 docs/examples/smtp-ssl.c                           |    4 +-
 docs/examples/smtp-tls.c                           |    4 +-
 docs/examples/sslbackend.c                         |   77 +
 docs/examples/synctime.c                           |   10 +-
 docs/examples/threaded-ssl.c                       |   18 +-
 docs/examples/usercertinmem.c                      |    4 +-
 docs/libcurl/Makefile.inc                          |    6 +-
 docs/libcurl/gnurl_easy_setopt.3                   |    4 +
 docs/libcurl/gnurl_formadd.3                       |   23 +-
 docs/libcurl/gnurl_formfree.3                      |    8 +-
 docs/libcurl/gnurl_formget.3                       |    7 +-
 docs/libcurl/gnurl_global_init.3                   |    3 +-
 docs/libcurl/gnurl_global_sslset.3                 |   97 +
 docs/libcurl/gnurl_mime_addpart.3                  |   66 +
 docs/libcurl/gnurl_mime_data.3                     |   69 +
 docs/libcurl/gnurl_mime_data_cb.3                  |  160 ++
 docs/libcurl/gnurl_mime_encoder.3                  |   97 +
 docs/libcurl/gnurl_mime_filedata.3                 |   77 +
 docs/libcurl/gnurl_mime_filename.3                 |   72 +
 ...GNURLOPT_REQUEST_TARGET.3 => gnurl_mime_free.3} |   46 +-
 docs/libcurl/gnurl_mime_headers.3                  |   65 +
 docs/libcurl/gnurl_mime_init.3                     |   69 +
 ...NURLINFO_SPEED_UPLOAD_T.3 => gnurl_mime_name.3} |   61 +-
 ...FO_SPEED_DOWNLOAD_T.3 => gnurl_mime_subparts.3} |   54 +-
 docs/libcurl/gnurl_mime_type.3                     |   83 +
 docs/libcurl/gnurl_version_info.3                  |    6 +-
 docs/libcurl/libgnurl-tutorial.3                   |  266 ++-
 docs/libcurl/libgnurl.3                            |    4 +
 .../opts/GNURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3     |    2 +-
 .../opts/GNURLINFO_CONTENT_LENGTH_UPLOAD_T.3       |    2 +-
 docs/libcurl/opts/GNURLINFO_PROTOCOL.3             |    2 +-
 .../opts/GNURLINFO_PROXY_SSL_VERIFYRESULT.3        |    2 +-
 docs/libcurl/opts/GNURLINFO_SCHEME.3               |    2 +-
 docs/libcurl/opts/GNURLINFO_SIZE_DOWNLOAD_T.3      |    2 +-
 docs/libcurl/opts/GNURLINFO_SIZE_UPLOAD_T.3        |    2 +-
 docs/libcurl/opts/GNURLINFO_SPEED_DOWNLOAD_T.3     |    2 +-
 docs/libcurl/opts/GNURLINFO_SPEED_UPLOAD_T.3       |    2 +-
 docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.3  |    2 +-
 docs/libcurl/opts/GNURLOPT_CAPATH.3                |    5 +-
 docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT.3        |    4 +
 docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT_MS.3     |    4 +
 docs/libcurl/opts/GNURLOPT_HTTPPOST.3              |   11 +-
 docs/libcurl/opts/GNURLOPT_INTERLEAVEDATA.3        |    7 +-
 docs/libcurl/opts/GNURLOPT_INTERLEAVEFUNCTION.3    |    8 +-
 docs/libcurl/opts/GNURLOPT_KEEP_SENDING_ON_ERROR.3 |    2 +-
 ...URLOPT_REQUEST_TARGET.3 => GNURLOPT_MIMEPOST.3} |   46 +-
 docs/libcurl/opts/GNURLOPT_NOPROXY.3               |    7 +-
 docs/libcurl/opts/GNURLOPT_PRE_PROXY.3             |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY.3                 |    3 +-
 docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.3          |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.3          |    7 +-
 docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.3         |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.3       |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.3 |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.3         |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.3     |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.3          |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.3      |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY_SSLVERSION.3      |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.3 |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3     |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYHOST.3  |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYPEER.3  |    2 +-
 .../libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.3 |    2 +-
 docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.3    |    2 +-
 .../libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.3 |    2 +-
 docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3        |    2 +-
 docs/libcurl/opts/GNURLOPT_SOCKS5_AUTH.3           |    2 +-
 ...REQUEST_TARGET.3 => GNURLOPT_SSH_COMPRESSION.3} |   34 +-
 docs/libcurl/opts/GNURLOPT_SSL_CTX_DATA.3          |    4 +-
 .../opts/GNURLOPT_SUPPRESS_CONNECT_HEADERS.3       |    2 +-
 docs/libcurl/opts/GNURLOPT_USERPWD.3               |    1 +
 docs/libcurl/opts/Makefile.inc                     |   32 +-
 docs/libcurl/symbols-in-versions                   |   64 +-
 include/README                                     |    2 +-
 include/gnurl/curl.h                               |  230 ++-
 include/gnurl/curlver.h                            |    8 +-
 include/gnurl/multi.h                              |    2 +-
 include/gnurl/system.h                             |  112 +-
 include/gnurl/typecheck-gcc.h                      |    6 +
 lib/Makefile.am                                    |   20 +-
 lib/Makefile.inc                                   |    5 +-
 lib/Makefile.m32                                   |   32 +-
 lib/asyn-ares.c                                    |    4 +-
 lib/asyn-thread.c                                  |   21 +-
 lib/checksrc.pl                                    |   55 +-
 lib/config-dos.h                                   |    6 +-
 lib/config-tpf.h                                   |    3 +
 lib/config-win32.h                                 |    6 +
 lib/config-win32ce.h                               |    3 +
 lib/connect.c                                      |   41 +-
 lib/content_encoding.c                             |    6 +-
 lib/cookie.c                                       |  142 +-
 lib/cookie.h                                       |   11 +-
 lib/curl_addrinfo.c                                |    6 +-
 lib/curl_config.h.cmake                            |    9 +-
 lib/curl_fnmatch.c                                 |   12 +-
 lib/curl_ntlm_core.c                               |   92 +-
 lib/curl_ntlm_core.h                               |   14 +-
 lib/curl_ntlm_wb.c                                 |    7 +-
 lib/curl_sasl.c                                    |    6 +-
 lib/curl_setup.h                                   |   17 +-
 lib/dict.c                                         |   14 +-
 lib/dotdot.c                                       |   30 +-
 lib/easy.c                                         |   16 +-
 lib/escape.c                                       |   26 +-
 lib/file.c                                         |   39 +-
 lib/formdata.c                                     |  888 ++--------
 lib/formdata.h                                     |   54 +-
 lib/ftp.c                                          |  167 +-
 lib/ftp.h                                          |    1 +
 lib/ftplistparser.c                                |   38 +-
 lib/getinfo.c                                      |   65 +-
 lib/gopher.c                                       |   10 +-
 lib/hash.c                                         |    4 +-
 lib/hostcheck.c                                    |   14 +-
 lib/hostip.c                                       |   12 +-
 lib/hostip4.c                                      |    4 +-
 lib/hostip6.c                                      |    4 +-
 lib/http.c                                         |  425 ++---
 lib/http.h                                         |    6 +-
 lib/http2.c                                        |   11 +-
 lib/http_chunks.c                                  |   26 +-
 lib/http_ntlm.c                                    |   13 +-
 lib/http_proxy.c                                   |   30 +-
 lib/if2ip.c                                        |    6 +-
 lib/imap.c                                         |  118 +-
 lib/imap.h                                         |    3 +-
 lib/inet_ntop.c                                    |    2 +-
 lib/ldap.c                                         |    4 +-
 lib/memdebug.c                                     |   18 +-
 lib/mime.c                                         | 1860 ++++++++++++++++++++
 lib/mime.h                                         |  135 ++
 lib/mprintf.c                                      |   38 +-
 lib/multi.c                                        |   62 +-
 lib/netrc.c                                        |   39 +-
 lib/non-ascii.c                                    |   83 +-
 lib/non-ascii.h                                    |    4 +-
 lib/openldap.c                                     |   12 +-
 lib/parsedate.c                                    |   64 +-
 lib/pingpong.c                                     |   28 +-
 lib/progress.c                                     |   56 +-
 lib/progress.h                                     |    2 +-
 lib/rtsp.c                                         |   20 +-
 lib/security.c                                     |    4 +-
 lib/sendf.c                                        |   20 +-
 lib/smtp.c                                         |   40 +-
 lib/socks.c                                        |   22 +-
 lib/socks_gssapi.c                                 |   59 +-
 lib/socks_sspi.c                                   |   24 +-
 lib/splay.c                                        |    2 +-
 lib/splay.h                                        |    4 +-
 lib/ssh.c                                          |   54 +-
 lib/strcase.c                                      |   11 +-
 lib/strdup.c                                       |    6 +-
 lib/strtoofft.c                                    |   63 +-
 lib/strtoofft.h                                    |   37 +-
 lib/telnet.c                                       |   30 +-
 lib/tftp.c                                         |   59 +-
 lib/transfer.c                                     |  140 +-
 lib/transfer.h                                     |    5 +-
 lib/url.c                                          |  254 +--
 lib/urldata.h                                      |  196 +--
 lib/vauth/digest_sspi.c                            |    4 +-
 lib/vauth/ntlm.c                                   |   16 +-
 lib/vauth/ntlm_sspi.c                              |    9 +-
 lib/vauth/vauth.h                                  |    5 +-
 lib/version.c                                      |    8 +-
 lib/vtls/axtls.c                                   |  190 +-
 lib/vtls/axtls.h                                   |   39 +-
 lib/vtls/cyassl.c                                  |  223 ++-
 lib/vtls/cyassl.h                                  |   63 +-
 lib/vtls/darwinssl.c                               |  450 +++--
 lib/vtls/darwinssl.h                               |   71 +-
 lib/vtls/gskit.c                                   |  191 +-
 lib/vtls/gskit.h                                   |   38 +-
 lib/vtls/gtls.c                                    |  210 ++-
 lib/vtls/gtls.h                                    |   64 +-
 lib/vtls/mbedtls.c                                 |  237 ++-
 lib/vtls/mbedtls.h                                 |   52 +-
 lib/vtls/nss.c                                     |  217 ++-
 lib/vtls/nssg.h                                    |   71 +-
 lib/vtls/openssl.c                                 |  574 ++++--
 lib/vtls/openssl.h                                 |   91 +-
 lib/vtls/polarssl.c                                |  198 ++-
 lib/vtls/polarssl.h                                |   52 +-
 lib/vtls/polarssl_threadlock.c                     |    4 +-
 lib/vtls/schannel.c                                |  532 +++---
 lib/vtls/schannel.h                                |   89 +-
 lib/vtls/vtls.c                                    |  499 +++++-
 lib/vtls/vtls.h                                    |   82 +-
 lib/warnless.c                                     |   32 +-
 lib/wildcard.h                                     |    2 +
 m4/curl-compilers.m4                               |    9 +-
 m4/curl-confopts.m4                                |    8 +-
 packages/OS400/curl.inc.in                         |    4 +
 projects/build-openssl.bat                         |   11 +
 scripts/contributors.sh                            |    2 +-
 scripts/contrithanks.sh                            |    2 +-
 scripts/updatemanpages.pl                          |    2 +-
 scripts/zsh.pl                                     |    5 +-
 src/Makefile.am                                    |    3 +-
 src/Makefile.inc                                   |    2 -
 src/Makefile.m32                                   |   32 +-
 src/tool_cb_dbg.c                                  |   29 +-
 src/tool_cb_hdr.c                                  |    2 +-
 src/tool_cb_prg.c                                  |    4 +-
 src/tool_cfgable.c                                 |    8 +-
 src/tool_cfgable.h                                 |    5 +-
 src/tool_easysrc.c                                 |   20 +-
 src/tool_easysrc.h                                 |    4 +-
 src/tool_formparse.c                               |  713 ++++++--
 src/tool_formparse.h                               |    6 +-
 src/tool_getparam.c                                |   39 +-
 src/tool_help.c                                    |   11 +-
 src/tool_main.c                                    |    9 +
 src/tool_metalink.c                                |   19 +-
 src/tool_mfiles.c                                  |  127 --
 src/tool_mfiles.h                                  |   46 -
 src/tool_msgs.c                                    |    4 +-
 src/tool_operate.c                                 |  110 +-
 src/tool_paramhlp.c                                |   36 +-
 src/tool_parsecfg.c                                |    4 +-
 src/tool_sdecls.h                                  |    4 +-
 src/tool_setopt.c                                  |  303 +++-
 src/tool_setopt.h                                  |   12 +-
 src/tool_strdup.c                                  |    6 +-
 src/tool_urlglob.c                                 |   24 +-
 tests/FILEFORMAT                                   |    3 +
 tests/curl_test_data.py                            |   21 +-
 tests/data/Makefile.inc                            |   23 +-
 tests/data/test1053                                |    2 -
 tests/data/test1133                                |    4 +-
 tests/data/test1135                                |   17 +-
 tests/data/test1139                                |   27 +
 tests/data/test1149                                |   64 +
 tests/data/test1150                                |   55 +
 tests/data/test1151                                |   66 +
 tests/data/test1152                                |   61 +
 tests/data/test1153                                |   61 +
 tests/data/test1160                                |   49 +
 tests/data/test1161                                |   54 +
 tests/data/test1315                                |    4 +-
 tests/data/test1401                                |    4 +-
 tests/data/test1404                                |   67 +-
 tests/data/test1449                                |   38 +
 tests/data/test1453                                |   38 +
 tests/data/test158                                 |    1 -
 tests/data/test163                                 |    1 -
 tests/data/test166                                 |    1 -
 tests/data/test173                                 |    6 +-
 tests/data/test186                                 |    5 +-
 tests/data/test1904                                |   79 +
 tests/data/test2056                                |   87 +
 tests/data/test2057                                |  108 ++
 tests/data/test259                                 |    6 +-
 tests/data/test277                                 |    5 +-
 tests/data/test4                                   |   10 +-
 tests/data/test46                                  |    4 +-
 tests/data/test506                                 |   16 +-
 tests/data/test554                                 |    2 -
 tests/data/test564                                 |    2 +
 tests/data/test587                                 |    1 -
 tests/data/test589                                 |   55 +
 tests/data/test642                                 |   42 +
 tests/data/{test554 => test643}                    |   13 +-
 tests/data/{test587 => test644}                    |    8 +-
 tests/data/{test554 => test645}                    |   27 +-
 tests/data/test646                                 |   98 ++
 tests/data/test647                                 |   79 +
 tests/data/test648                                 |   75 +
 tests/data/test649                                 |   72 +
 tests/data/test650                                 |  122 ++
 tests/data/test71                                  |    1 -
 tests/data/test800                                 |    4 +-
 tests/data/test846                                 |   50 +
 tests/data/test856                                 |    3 +
 tests/data/test9                                   |    1 -
 tests/ftpserver.pl                                 |   15 +-
 tests/fuzz/Makefile.am                             |   19 +-
 tests/fuzz/Makefile.inc                            |   26 +-
 tests/fuzz/README                                  |   13 +-
 tests/fuzz/corpus.py                               |   96 +
 tests/fuzz/curl_fuzz_data/oss-fuzz-3327            |  Bin 0 -> 27 bytes
 tests/fuzz/curl_fuzz_data/test1                    |  Bin 0 -> 289 bytes
 tests/fuzz/curl_fuzz_data/test10                   |  Bin 0 -> 226 bytes
 tests/fuzz/curl_fuzz_data/test100                  |  Bin 0 -> 675 bytes
 tests/fuzz/curl_fuzz_data/test12                   |  Bin 0 -> 464 bytes
 tests/fuzz/curl_fuzz_data/test13                   |  Bin 0 -> 179 bytes
 tests/fuzz/curl_fuzz_data/test1326                 |  Bin 0 -> 62 bytes
 tests/fuzz/curl_fuzz_data/test1450                 |  Bin 0 -> 98 bytes
 tests/fuzz/curl_fuzz_data/test2                    |  Bin 0 -> 182 bytes
 tests/fuzz/curl_fuzz_data/test271                  |  Bin 0 -> 74 bytes
 tests/fuzz/curl_fuzz_data/test3                    |  Bin 0 -> 242 bytes
 tests/fuzz/curl_fuzz_data/test4                    |  Bin 0 -> 336 bytes
 tests/fuzz/curl_fuzz_data/test5                    |  Bin 0 -> 185 bytes
 tests/fuzz/curl_fuzz_data/test6                    |  Bin 0 -> 223 bytes
 tests/fuzz/curl_fuzz_data/test800                  |  Bin 0 -> 137 bytes
 tests/fuzz/curl_fuzz_data/test850                  |  Bin 0 -> 130 bytes
 tests/fuzz/curl_fuzz_data/test900                  |  Bin 0 -> 129 bytes
 tests/fuzz/curl_fuzzer.cc                          |  447 +++++
 tests/fuzz/curl_fuzzer.h                           |  186 ++
 tests/fuzz/generate_corpus.py                      |  132 ++
 tests/fuzz/read_corpus.py                          |   69 +
 tests/fuzz/standalone_fuzz_target_runner.cc        |   89 +
 src/tool_formparse.h => tests/fuzz/testinput.h     |   14 +-
 tests/libtest/.gitignore                           |    3 +
 tests/libtest/Makefile.am                          |   15 +
 tests/libtest/Makefile.inc                         |   18 +-
 tests/libtest/first.c                              |   14 +-
 tests/libtest/lib1501.c                            |    4 +-
 tests/libtest/lib1502.c                            |    4 +-
 tests/libtest/lib1506.c                            |   12 +-
 tests/libtest/lib1507.c                            |    4 +-
 tests/libtest/lib1510.c                            |    6 +-
 tests/libtest/lib1512.c                            |    6 +-
 tests/libtest/lib1513.c                            |    4 +-
 tests/libtest/lib1515.c                            |    5 +-
 tests/libtest/lib1517.c                            |    4 +-
 tests/libtest/lib1531.c                            |    8 +-
 tests/libtest/lib1538.c                            |    7 +-
 tests/libtest/lib1550.c                            |   13 +-
 tests/libtest/lib1551.c                            |    2 +
 tests/libtest/lib1900.c                            |   14 +-
 tests/libtest/lib500.c                             |    4 +-
 tests/libtest/lib502.c                             |    4 +-
 tests/libtest/lib503.c                             |    4 +-
 tests/libtest/lib504.c                             |    4 +-
 tests/libtest/lib505.c                             |    4 +-
 tests/libtest/lib506.c                             |    8 +-
 tests/libtest/lib507.c                             |    4 +-
 tests/libtest/lib508.c                             |    4 +-
 tests/libtest/lib510.c                             |    4 +-
 tests/libtest/lib513.c                             |    4 +-
 tests/libtest/lib514.c                             |    4 +-
 tests/libtest/lib515.c                             |    4 +-
 tests/libtest/lib516.c                             |    4 +-
 tests/libtest/lib517.c                             |    4 +-
 tests/libtest/lib525.c                             |    4 +-
 tests/libtest/lib526.c                             |   12 +-
 tests/libtest/lib530.c                             |   10 +-
 tests/libtest/lib533.c                             |    6 +-
 tests/libtest/lib536.c                             |    4 +-
 tests/libtest/lib540.c                             |   10 +-
 tests/libtest/lib543.c                             |   12 +-
 tests/libtest/lib544.c                             |    4 +-
 tests/libtest/lib547.c                             |    4 +-
 tests/libtest/lib552.c                             |   36 +-
 tests/libtest/lib553.c                             |    8 +-
 tests/libtest/lib554.c                             |    8 +-
 tests/libtest/lib555.c                             |    8 +-
 tests/libtest/lib557.c                             |   93 +-
 tests/libtest/lib560.c                             |    4 +-
 tests/libtest/lib564.c                             |    4 +-
 tests/libtest/lib567.c                             |    4 +-
 tests/libtest/lib568.c                             |    6 +-
 tests/libtest/lib569.c                             |    4 +-
 tests/libtest/lib570.c                             |    4 +-
 tests/libtest/lib571.c                             |    6 +-
 tests/libtest/lib572.c                             |    6 +-
 tests/libtest/lib573.c                             |    4 +-
 tests/libtest/lib575.c                             |    4 +-
 tests/libtest/lib578.c                             |    4 +-
 tests/libtest/lib579.c                             |    4 +-
 tests/libtest/lib586.c                             |   10 +-
 tests/libtest/{lib516.c => lib589.c}               |    6 +-
 tests/libtest/lib591.c                             |    4 +-
 tests/libtest/lib597.c                             |   11 +-
 tests/libtest/lib599.c                             |    4 +-
 tests/libtest/lib643.c                             |  270 +++
 tests/libtest/lib650.c                             |  189 ++
 tests/libtest/libntlmconnect.c                     |    4 +-
 tests/libtest/mk-lib1521.pl                        |   12 +-
 tests/libtest/stub_gssapi.c                        |  397 +++++
 tests/libtest/stub_gssapi.h                        |  183 ++
 tests/libtest/testtrace.c                          |   22 +-
 tests/runtests.pl                                  |   69 +-
 tests/server/fake_ntlm.c                           |   13 +-
 tests/server/getpart.c                             |   42 +-
 tests/server/resolve.c                             |    6 +-
 tests/server/rtspd.c                               |   42 +-
 tests/server/sockfilt.c                            |   16 +-
 tests/server/sws.c                                 |   67 +-
 tests/server/tftpd.c                               |   14 +-
 tests/server/util.c                                |    8 +-
 tests/unit/unit1300.c                              |    2 +-
 tests/unit/unit1301.c                              |    4 +-
 tests/unit/unit1302.c                              |    6 +-
 tests/unit/unit1303.c                              |    8 +-
 tests/unit/unit1305.c                              |    4 +-
 tests/unit/unit1308.c                              |    6 +-
 tests/unit/unit1309.c                              |   18 +-
 tests/unit/unit1323.c                              |    2 +-
 tests/unit/unit1395.c                              |    4 +-
 tests/unit/unit1396.c                              |   12 +-
 tests/unit/unit1398.c                              |    4 +-
 tests/unit/unit1399.c                              |   95 +-
 tests/unit/unit1600.c                              |    8 +-
 tests/unit/unit1605.c                              |   15 +-
 tests/unit/unit1606.c                              |   36 +-
 winbuild/MakefileBuild.vc                          |    2 +-
 468 files changed, 14486 insertions(+), 6646 deletions(-)
 create mode 100644 .mailmap
 mode change 100644 => 100755 acinclude.m4
 mode change 100644 => 100755 configure.ac
 create mode 100644 docs/HELP-US.md
 create mode 100644 docs/cmdline-opts/compressed-ssh.d
 copy docs/examples/{multi-post.c => multi-formadd.c} (94%)
 copy docs/examples/{postit2.c => postit2-formadd.c} (94%)
 copy docs/examples/{smtp-mail.c => smtp-mime.c} (56%)
 create mode 100644 docs/examples/sslbackend.c
 create mode 100644 docs/libcurl/gnurl_global_sslset.3
 create mode 100644 docs/libcurl/gnurl_mime_addpart.3
 create mode 100644 docs/libcurl/gnurl_mime_data.3
 create mode 100644 docs/libcurl/gnurl_mime_data_cb.3
 create mode 100644 docs/libcurl/gnurl_mime_encoder.3
 create mode 100644 docs/libcurl/gnurl_mime_filedata.3
 create mode 100644 docs/libcurl/gnurl_mime_filename.3
 copy docs/libcurl/{opts/GNURLOPT_REQUEST_TARGET.3 => gnurl_mime_free.3} (56%)
 create mode 100644 docs/libcurl/gnurl_mime_headers.3
 create mode 100644 docs/libcurl/gnurl_mime_init.3
 copy docs/libcurl/{opts/GNURLINFO_SPEED_UPLOAD_T.3 => gnurl_mime_name.3} (51%)
 copy docs/libcurl/{opts/GNURLINFO_SPEED_DOWNLOAD_T.3 => gnurl_mime_subparts.3} 
(53%)
 create mode 100644 docs/libcurl/gnurl_mime_type.3
 copy docs/libcurl/opts/{GNURLOPT_REQUEST_TARGET.3 => GNURLOPT_MIMEPOST.3} (58%)
 copy docs/libcurl/opts/{GNURLOPT_REQUEST_TARGET.3 => 
GNURLOPT_SSH_COMPRESSION.3} (59%)
 mode change 100644 => 100755 lib/connect.c
 create mode 100644 lib/mime.c
 create mode 100644 lib/mime.h
 delete mode 100644 src/tool_mfiles.c
 delete mode 100644 src/tool_mfiles.h
 create mode 100644 tests/data/test1139
 create mode 100644 tests/data/test1149
 create mode 100644 tests/data/test1150
 create mode 100644 tests/data/test1151
 create mode 100644 tests/data/test1152
 create mode 100644 tests/data/test1153
 create mode 100644 tests/data/test1160
 create mode 100644 tests/data/test1161
 create mode 100644 tests/data/test1449
 create mode 100644 tests/data/test1453
 create mode 100644 tests/data/test1904
 create mode 100644 tests/data/test2056
 create mode 100644 tests/data/test2057
 create mode 100644 tests/data/test589
 create mode 100644 tests/data/test642
 copy tests/data/{test554 => test643} (91%)
 copy tests/data/{test587 => test644} (91%)
 copy tests/data/{test554 => test645} (89%)
 create mode 100644 tests/data/test646
 create mode 100644 tests/data/test647
 create mode 100644 tests/data/test648
 create mode 100644 tests/data/test649
 create mode 100644 tests/data/test650
 create mode 100644 tests/data/test846
 create mode 100644 tests/fuzz/corpus.py
 create mode 100644 tests/fuzz/curl_fuzz_data/oss-fuzz-3327
 create mode 100644 tests/fuzz/curl_fuzz_data/test1
 create mode 100644 tests/fuzz/curl_fuzz_data/test10
 create mode 100644 tests/fuzz/curl_fuzz_data/test100
 create mode 100644 tests/fuzz/curl_fuzz_data/test12
 create mode 100644 tests/fuzz/curl_fuzz_data/test13
 create mode 100644 tests/fuzz/curl_fuzz_data/test1326
 create mode 100644 tests/fuzz/curl_fuzz_data/test1450
 create mode 100644 tests/fuzz/curl_fuzz_data/test2
 create mode 100644 tests/fuzz/curl_fuzz_data/test271
 create mode 100644 tests/fuzz/curl_fuzz_data/test3
 create mode 100644 tests/fuzz/curl_fuzz_data/test4
 create mode 100644 tests/fuzz/curl_fuzz_data/test5
 create mode 100644 tests/fuzz/curl_fuzz_data/test6
 create mode 100644 tests/fuzz/curl_fuzz_data/test800
 create mode 100644 tests/fuzz/curl_fuzz_data/test850
 create mode 100644 tests/fuzz/curl_fuzz_data/test900
 create mode 100644 tests/fuzz/curl_fuzzer.cc
 create mode 100644 tests/fuzz/curl_fuzzer.h
 create mode 100755 tests/fuzz/generate_corpus.py
 create mode 100755 tests/fuzz/read_corpus.py
 create mode 100644 tests/fuzz/standalone_fuzz_target_runner.cc
 copy src/tool_formparse.h => tests/fuzz/testinput.h (69%)
 copy tests/libtest/{lib516.c => lib589.c} (92%)
 create mode 100644 tests/libtest/lib643.c
 create mode 100644 tests/libtest/lib650.c
 create mode 100644 tests/libtest/stub_gssapi.c
 create mode 100644 tests/libtest/stub_gssapi.h

diff --git a/.gitignore b/.gitignore
index 13d10a67f..8d6042fd0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,4 +53,7 @@ mkinstalldirs
 tags
 test-driver
 scripts/_gnurl
-\#*\#
\ No newline at end of file
+\#*\#
+curl_fuzzer
+curl_fuzzer_seed_corpus.zip
+libstandaloneengine.a
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 000000000..18cf8a6d8
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,26 @@
+Guenter Knauf <address@hidden> <address@hidden>
+Gisle Vanem <address@hidden> <address@hidden>
+Gisle Vanem <address@hidden> <address@hidden>
+Alessandro Ghedini <address@hidden> <address@hidden>
+Alessandro Ghedini <address@hidden> <address@hidden>
+Björn Stenberg <address@hidden>
+Björn Stenberg <address@hidden> <address@hidden>
+Viktor Szakáts <address@hidden>
+Daniel Gustafsson <address@hidden> <address@hidden>
+Daniel Gustafsson <address@hidden> <address@hidden>
+Linus Nielsen <address@hidden>
+Yamada Yasuharu <address@hidden>
+Ulion <address@hidden>
+Tim Rühsen <address@hidden>
+Steve Holme <address@hidden> <address@hidden>
+Claes Jakobsson <address@hidden> <address@hidden>
+Sergei Nikulov <address@hidden> <address@hidden>
+Patrick Monnerat <address@hidden> <address@hidden>
+Patrick Monnerat <address@hidden> <address@hidden>
+Patrick Monnerat <address@hidden> <address@hidden>
+Nick Zitzmann <address@hidden><address@hidden>
+Peter Wu <address@hidden> <peter_at_lekensteyn.nl>
+David Woodhouse <address@hidden> <address@hidden>
+Marcel Raad <address@hidden> <address@hidden>
+Marcel Raad <address@hidden> <address@hidden>
+Marcel Raad <address@hidden> <address@hidden>
diff --git a/.travis.yml b/.travis.yml
index 64aecd890..541628d99 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,13 +18,22 @@ addons:
             - stunnel4
             - libidn2-0-dev
             - libssh2-1-dev
+            - krb5-user
 
 matrix:
     include:
         - os: linux
           compiler: gcc
           dist: trusty
-          env: T=normal
+          env: T=normal C=--with-gssapi
+        - os: linux
+          compiler: gcc
+          dist: trusty
+          env: T=normal C="--disable-http --disable-smtp --disable-imap"
+        - os: linux
+          compiler: gcc
+          dist: trusty
+          env: T=normal C=--enable-ares
         - os: linux
           compiler: clang
           dist: trusty
@@ -34,13 +43,16 @@ matrix:
           env: T=debug
         - os: osx
           compiler: gcc
-          env: T=debug C=--with-ssl=/usr/local/opt/openssl
+          env: T=debug C=--enable-ares
+        - os: osx
+          compiler: gcc
+          env: T=debug C="--with-ssl=/usr/local/opt/openssl --with-libmetalink"
         - os: osx
           compiler: gcc
-          env: T=debug C=--with-ssl=/usr/local/opt/libressl
+          env: T=debug C="--with-ssl=/usr/local/opt/libressl 
--with-libmetalink"
         - os: osx
           compiler: clang
-          env: T=debug C="--without-ssl --with-darwinssl"
+          env: T=debug C="--without-ssl --with-darwinssl --with-libmetalink"
         - os: osx
           compiler: clang
           env: T=normal
@@ -60,12 +72,16 @@ matrix:
           compiler: gcc
           dist: trusty
           env: T=distcheck
+        - os: linux
+          compiler: clang
+          dist: trusty
+          env: T=fuzzer
 
 install:
   - pip install --user cpp-coveralls
   - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update > /dev/null; fi
   - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew reinstall libtool > 
/dev/null; fi
-  - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install openssl libidn 
rtmpdump libssh2 c-ares libmetalink libressl nghttp2; fi
+  - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install rtmpdump libssh2 
c-ares libmetalink libressl nghttp2 libmetalink; fi
   - if [ $TRAVIS_OS_NAME = linux ]; then
       curl -L 
https://github.com/nghttp2/nghttp2/releases/download/v1.24.0/nghttp2-1.24.0.tar.gz
 |
          tar xzf - &&
@@ -85,18 +101,19 @@ script:
              tests="1 2 3 4 5 6 7 8 9 10 200 201 202 300 301 302 500 501 502 
503 504 506 507 508 509 510 511 512 513 514 515 516 517 518 519 600 601 800 801 
802 803 900 901 902 903 1000 1001 1002 1004 1302 1303 1304 1305 1306 1308 1400 
1401 1402 1404 1450 1451 1452 1502 1507 1508 1600 1602 1603 1605"
              make "TFLAGS=-n -e $tests" test-nonflaky
              make "TFLAGS=-n -t $tests" test-nonflaky
-             coveralls --gcov /usr/bin/gcov-4.8 --gcov-options '\-lp' -i src 
-i lib -i lib/vtls -i lib/vauth -e tests -e docs
+             coveralls --gcov /usr/bin/gcov-4.8 --gcov-options '\-lp' -i src 
-e lib -e tests -e docs -b $PWD/src
+             coveralls --gcov /usr/bin/gcov-4.8 --gcov-options '\-lp' -e src 
-i lib -e tests -e docs -b $PWD/lib
         fi
     - |
         if [ "$T" = "debug" ]; then
              ./configure --enable-debug --enable-werror $C
-             make
+             make && make examples
              make TFLAGS=-n test-nonflaky
         fi
     - |
         if [ "$T" = "normal" ]; then
              ./configure --enable-warnings --enable-werror $C
-             make
+             make && make examples
              make test-nonflaky
         fi
     - |
@@ -137,6 +154,21 @@ script:
              cmake .. && \
              make)
         fi
+    - |
+        if [ "$T" = "fuzzer" ]; then
+          export CC=clang
+          export CXX=clang++
+          export CFLAGS="-fsanitize=address"
+
+          # Specifically use libstdc++ for travis as libc++ is not installed.
+          # This is ok because we're not compiling against libFuzzer.
+          export CXXFLAGS="-fsanitize=address -stdlib=libstdc++"
+          ./configure --disable-shared --enable-debug --enable-maintainer-mode
+          make
+          cd tests/fuzz
+          make clean
+          make check
+        fi
 
 # whitelist branches to avoid testing feature branches twice (as branch and as 
pull request)
 branches:
diff --git a/CMake/Macros.cmake b/CMake/Macros.cmake
index dab005f73..82aadca9d 100644
--- a/CMake/Macros.cmake
+++ b/CMake/Macros.cmake
@@ -93,3 +93,32 @@ macro(CURL_INTERNAL_TEST_RUN CURL_TEST)
     endif(${CURL_TEST}_COMPILE AND NOT ${CURL_TEST})
   endif()
 endmacro(CURL_INTERNAL_TEST_RUN)
+
+macro(CURL_NROFF_CHECK)
+  find_program(NROFF NAMES gnroff nroff)
+  if(NROFF)
+    # Need a way to write to stdin, this will do
+    file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt" "test")
+    # Tests for a valid nroff option to generate a manpage
+    foreach(_MANOPT "-man" "-mandoc")
+      execute_process(COMMAND "${NROFF}" ${_MANOPT}
+        OUTPUT_VARIABLE NROFF_MANOPT_OUTPUT
+        INPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt"
+        ERROR_QUIET)
+      # Save the option if it was valid
+      if(NROFF_MANOPT_OUTPUT)
+        message("Found *nroff option: -- ${_MANOPT}")
+        set(NROFF_MANOPT ${_MANOPT})
+        set(NROFF_USEFUL ON)
+        break()
+      endif()
+    endforeach()
+    # No need for the temporary file
+    file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt")
+    if(NOT NROFF_USEFUL)
+      message(WARNING "Found no *nroff option to get plaintext from man pages")
+    endif()
+  else()
+    message(WARNING "Found no *nroff program")
+  endif()
+endmacro(CURL_NROFF_CHECK)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index be3fb4b3c..c816467b6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,6 +43,7 @@ set(CMAKE_MODULE_PATH 
"${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
 include(Utilities)
 include(Macros)
 include(CMakeDependentOption)
+include(CheckCCompilerFlag)
 
 project( CURL C )
 
@@ -73,6 +74,7 @@ include_directories(${PROJECT_BINARY_DIR}/include/gnurl)
 include_directories( ${CURL_SOURCE_DIR}/include )
 
 option(CURL_WERROR "Turn compiler warnings into errors" OFF)
+option(PICKY_COMPILER "Enable picky compiler options" ON)
 option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
 option(CURL_STATICLIB "Set to ON to build libcurl with static linking." OFF)
 option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
@@ -88,6 +90,19 @@ CMAKE_DEPENDENT_OPTION(ENABLE_THREADED_RESOLVER "Set to ON 
to enable threaded DN
 option(ENABLE_DEBUG "Set to ON to enable curl debug features" OFF)
 option(ENABLE_CURLDEBUG "Set to ON to build with TrackMemory feature enabled" 
OFF)
 
+if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
+  if (PICKY_COMPILER)
+    foreach (_CCOPT -pedantic -Wall -W -Wpointer-arith -Wwrite-strings 
-Wunused -Wshadow -Winline -Wnested-externs -Wmissing-declarations 
-Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare 
-Wundef -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes 
-Wdeclaration-after-statement -Wstrict-aliasing=3 -Wcast-align -Wtype-limits 
-Wold-style-declaration -Wmissing-parameter-type -Wempty-body -Wclobbered 
-Wignored-qualifiers -Wconversion -Wno-sign-conversion -W [...]
+      # 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})
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_CCOPT}")
+      endif()
+    endforeach()
+  endif(PICKY_COMPILER)
+endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
+
 if (ENABLE_DEBUG)
   # DEBUGBUILD will be defined only for Debug builds
   if(NOT CMAKE_VERSION VERSION_LESS 3.0)
@@ -172,8 +187,6 @@ option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic 
authentication" OFF)
 mark_as_advanced(CURL_DISABLE_CRYPTO_AUTH)
 option(CURL_DISABLE_VERBOSE_STRINGS "to disable verbose strings" OFF)
 mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS)
-option(DISABLED_THREADSAFE "Set to explicitly specify we don't want to use 
thread-safe functions" OFF)
-mark_as_advanced(DISABLED_THREADSAFE)
 option(ENABLE_IPV6 "Define if you want to enable IPv6 support" ON)
 mark_as_advanced(ENABLE_IPV6)
 if(ENABLE_IPV6 AND NOT WIN32)
@@ -190,35 +203,19 @@ if(ENABLE_IPV6 AND NOT WIN32)
   endif()
 endif()
 
-option(ENABLE_MANUAL "to provide the built-in manual" ON)
-unset(USE_MANUAL CACHE) # TODO: cache NROFF/NROFF_MANOPT/USE_MANUAL vars?
+CURL_NROFF_CHECK()
+find_package(Perl)
+
+CMAKE_DEPENDENT_OPTION(ENABLE_MANUAL "to provide the built-in manual"
+    ON "NROFF_USEFUL;PERL_FOUND"
+    OFF)
+
+if(NOT PERL_FOUND)
+  message(STATUS "Perl not found, testing disabled.")
+  set(BUILD_TESTING OFF)
+endif()
 if(ENABLE_MANUAL)
-  find_program(NROFF NAMES gnroff nroff)
-  if(NROFF)
-    # Need a way to write to stdin, this will do
-    file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt" "test")
-    # Tests for a valid nroff option to generate a manpage
-    foreach(_MANOPT "-man" "-mandoc")
-      execute_process(COMMAND "${NROFF}" ${_MANOPT}
-        OUTPUT_VARIABLE NROFF_MANOPT_OUTPUT
-        INPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt"
-        ERROR_QUIET)
-      # Save the option if it was valid
-      if(NROFF_MANOPT_OUTPUT)
-        message("Found *nroff option: -- ${_MANOPT}")
-        set(NROFF_MANOPT ${_MANOPT})
-        set(USE_MANUAL 1)
-        break()
-      endif()
-    endforeach()
-    # No need for the temporary file
-    file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/nroff-input.txt")
-    if(NOT USE_MANUAL)
-      message(WARNING "Found no *nroff option to get plaintext from man pages")
-    endif()
-  else()
-    message(WARNING "Found no *nroff program")
-  endif()
+  set(USE_MANUAL ON)
 endif()
 # Required for building manual, docs, tests
 find_package(Perl REQUIRED)
@@ -801,50 +798,6 @@ if(NOT HAVE_SIZEOF_SSIZE_T)
 endif(NOT HAVE_SIZEOF_SSIZE_T)
 # off_t is sized later, after the HAVE_FILE_OFFSET_BITS test
 
-# Different sizeofs, etc.
-
-#    define CURL_SIZEOF_LONG        4
-#    define CURL_TYPEOF_CURL_OFF_T  long long
-#    define CURL_FORMAT_CURL_OFF_T  "lld"
-#    define CURL_FORMAT_CURL_OFF_TU "llu"
-#    define CURL_FORMAT_OFF_T       "%lld"
-#    define CURL_SIZEOF_CURL_OFF_T  8
-#    define CURL_SUFFIX_CURL_OFF_T  LL
-#    define CURL_SUFFIX_CURL_OFF_TU ULL
-
-set(CURL_SIZEOF_LONG ${SIZEOF_LONG})
-
-if(SIZEOF_LONG EQUAL 8)
-  set(CURL_TYPEOF_CURL_OFF_T long)
-  set(CURL_SIZEOF_CURL_OFF_T 8)
-  set(CURL_FORMAT_CURL_OFF_T "ld")
-  set(CURL_FORMAT_CURL_OFF_TU "lu")
-  set(CURL_FORMAT_OFF_T "%ld")
-  set(CURL_SUFFIX_CURL_OFF_T L)
-  set(CURL_SUFFIX_CURL_OFF_TU UL)
-endif(SIZEOF_LONG EQUAL 8)
-
-if(SIZEOF_LONG_LONG EQUAL 8)
-  set(CURL_TYPEOF_CURL_OFF_T "long long")
-  set(CURL_SIZEOF_CURL_OFF_T 8)
-  set(CURL_FORMAT_CURL_OFF_T "lld")
-  set(CURL_FORMAT_CURL_OFF_TU "llu")
-  set(CURL_FORMAT_OFF_T "%lld")
-  set(CURL_SUFFIX_CURL_OFF_T LL)
-  set(CURL_SUFFIX_CURL_OFF_TU ULL)
-endif(SIZEOF_LONG_LONG EQUAL 8)
-
-if(NOT CURL_TYPEOF_CURL_OFF_T)
-  set(CURL_TYPEOF_CURL_OFF_T ${ssize_t})
-  set(CURL_SIZEOF_CURL_OFF_T ${SIZEOF_SSIZE_T})
-  # TODO: need adjustment here.
-  set(CURL_FORMAT_CURL_OFF_T "ld")
-  set(CURL_FORMAT_CURL_OFF_TU "lu")
-  set(CURL_FORMAT_OFF_T "%ld")
-  set(CURL_SUFFIX_CURL_OFF_T L)
-  set(CURL_SUFFIX_CURL_OFF_TU LU)
-endif(NOT CURL_TYPEOF_CURL_OFF_T)
-
 if(HAVE_SIZEOF_LONG_LONG)
   set(HAVE_LONGLONG 1)
   set(HAVE_LL 1)
@@ -1013,6 +966,13 @@ if(HAVE_FILE_OFFSET_BITS)
   set(CMAKE_REQUIRED_FLAGS "-D_FILE_OFFSET_BITS=64")
 endif(HAVE_FILE_OFFSET_BITS)
 check_type_size("off_t"  SIZEOF_OFF_T)
+
+# include this header to get the type
+set(CMAKE_REQUIRED_INCLUDES "${CURL_SOURCE_DIR}/include")
+set(CMAKE_EXTRA_INCLUDE_FILES "curl/system.h")
+check_type_size("curl_off_t"  SIZEOF_CURL_OFF_T)
+set(CMAKE_EXTRA_INCLUDE_FILES "")
+
 set(CMAKE_REQUIRED_FLAGS)
 
 foreach(CURL_TEST
@@ -1173,8 +1133,12 @@ function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
 
 endfunction()
 
-add_subdirectory(docs)
+if(USE_MANUAL)
+  add_subdirectory(docs)
+endif()
+
 add_subdirectory(lib)
+
 if(BUILD_CURL_EXE)
   add_subdirectory(src)
 endif()
diff --git a/Makefile.am b/Makefile.am
index d668ead22..2b5fcaea7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -210,6 +210,9 @@ test-am:
 
 endif
 
+fuzzer:
+       @(cd tests/fuzz; $(MAKE) all)
+
 examples:
        @(cd docs/examples; $(MAKE) check)
 
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index a735262d0..971336faf 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,40 +1,110 @@
-Curl and libcurl 7.55.1
+Curl and libcurl 7.56.0
 
- Public curl releases:         168
- Command line options:         210
- curl_easy_setopt() options:   247
- Public functions in libcurl:  61
- Contributors:                 1592
+ Public curl releases:         169
+ Command line options:         211
+ curl_easy_setopt() options:   249
+ Public functions in libcurl:  74
+ Contributors:                 1618
+
+This release includes the following changes:
+
+ o curl: enable compression for SCP/SFTP with --compressed-ssh  [11]
+ o libcurl: enable compression for SCP/SFTP with CURLOPT_SSH_COMPRESSION [11]
+ o vtls: added dynamic changing SSL backend with curl_global_sslset() [28]
+ o new MIME API, curl_mime_init() and friends [32]
+ o openssl: initial SSLKEYLOGFILE implementation [36]
 
 This release includes the following bugfixes:
 
- o build: fix 'make install' with configure, install docs/libcurl/* too
- o make install: add 8 missing man pages to the installation
- o curl: do bounds check using a double comparison [1]
- o dist: Add dictserver.py/negtelnetserver.py to release [2]
- o digest_sspi: Don't reuse context if the user/passwd has changed [3]
- o gitignore: ignore top-level .vs folder [4]
- o build: check out *.sln files with Windows line endings [5]
- o travis: verify "make install" [6]
- o dist: fix the cmake build by shipping cmake_uninstall.cmake.in too [7]
- o metalink: fix error: ‘*’ in boolean context, suggest ‘&&’ instead
- o configure: use the threaded resolver backend by default if possible [8]
- o mkhelp.pl: allow executing this script directly [9]
- o maketgz: remove old *.dist files before making the tarball [10]
- o openssl: remove CONST_ASN1_BIT_STRING [11]
- o openssl: fix "error: this statement may fall through"
- o proxy: fix memory leak in case of invalid proxy server name [12]
- o curl/system.h: support more architectures (OpenRISC, ARC) [13]
- o docs: fix typos [14]
- o curl/system.h: add Oracle Solaris Studio [15]
- o CURLINFO_TOTAL_TIME: could wrongly return 4200 seconds [16]
- o docs: --connect-to clarified
- o cmake: allow user to override CMAKE_DEBUG_POSTFIX [17]
- o travis: test cmake build on tarball too
- o redirect: make it handle absolute redirects to IDN names [18]
- o curl/system.h: fix for gcc on PowerPC [19]
- o curl --interface: fixed for IPV6 unique local addresses [20]
- o cmake: threads detection improvements [21]
+ o FTP: zero terminate the entry path even on bad input [67]
+ o examples/ftpuploadresume.c: use portable code
+ o runtests: match keywords case insensitively
+ o travis: build the examples too [1]
+ o strtoofft: reduce integer overflow risks globally [2]
+ o zsh.pl: produce a working completion script again [3]
+ o cmake: remove dead code for CURL_DISABLE_RTMP [4]
+ o progress: Track total times following redirects [5]
+ o configure: fix --disable-threaded-resolver [6]
+ o cmake: remove dead code for DISABLED_THREADSAFE [7]
+ o configure: fix clang version detection
+ o darwinssi: fix error: variable length array used
+ o travis: add metalink to some osx builds [8]
+ o configure: check for __builtin_available() availability [9]
+ o http_proxy: fix build error for CURL_DOES_CONVERSIONS [10]
+ o examples/ftpuploadresume: checksrc compliance
+ o ftp: fix CWD when doing multicwd then nocwd on same connection [12]
+ o system.h: remove all CURL_SIZEOF_* defines [13]
+ o http: Don't wait on CONNECT when there is no proxy [14]
+ o system.h: check for __ppc__ as well [15]
+ o http2_recv: return error better on fatal h2 errors [16]
+ o scripts/contri*sh: use "git log --use-mailmap"
+ o tftp: fix memory leak on too long filename [17]
+ o system.h: fix build for hppa [18]
+ o cmake: enable picky compiler options with clang and gcc [19]
+ o makefile.m32: add support for libidn2 [20]
+ o curl: turn off MinGW CRT's globbing [21]
+ o request-target.d: mention added in 7.55.0
+ o curl: shorten and clean up CA cert verification error message [22]
+ o imap: support PREAUTH [23]
+ o CURLOPT_USERPWD.3: see also CURLOPT_PROXYUSERPWD
+ o examples/threaded-ssl: mention that this is for openssl before 1.1
+ o winbuild: fix embedded manifest option [24]
+ o tests: Make sure libtests & unittests call curl_global_cleanup()
+ o system.h: include sys/poll.h for AIX [25]
+ o darwinssl: handle long strings in TLS certs [26]
+ o strtooff: fix build for systems with long long but no strtoll [27]
+ o asyn-thread: Improved cleanup after OOM situations
+ o HELP-US.md: "How to get started helping out in the curl project" [29]
+ o curl.h: CURLSSLBACKEND_WOLFSSL used wrong value [30]
+ o unit1301: fix error message on first test
+ o ossfuzz: moving towards the ideal integration [31]
+ o http: fix a memory leakage in checkrtspprefix()
+ o examples/post-callback: stop returning one byte at a time
+ o schannel: return CURLE_SSL_CACERT on failed verification [33]
+ o MAIL-ETIQUETTE: added "1.9 Your emails are public"
+ o http-proxy: treat all 2xx as CONNECT success [34]
+ o openssl: use OpenSSL's default ciphers by default [35]
+ o runtests.pl: support attribute "nonewline" in part verify/upload
+ o configure: remove --enable-soname-bump and SONAME_BUMP [37]
+ o travis: add c-ares enabled builds linux + osx [38]
+ o vtls: fix WolfSSL 3.12 build problems [39]
+ o http-proxy: when not doing CONNECT, that phase is done immediately [40]
+ o configure: fix curl_off_t check's include order [41]
+ o configure: use -Wno-varargs on clang 3.9[.X] debug builds
+ o rtsp: do not call fwrite() with NULL pointer FILE * [42]
+ o mbedtls: enable CA path processing [43]
+ o travis: add build without HTTP/SMTP/IMAP
+ o checksrc: verify more code style rules [44]
+ o HTTP proxy: on connection re-use, still use the new remote port [45]
+ o tests: add initial gssapi test using stub implementation [46]
+ o rtsp: Segfault when using WRITEDATA [47]
+ o docs: clarify the CURLOPT_INTERLEAVE* options behavior
+ o non-ascii: use iconv() with 'char **' argument [48]
+ o server/getpart: provide dummy function to build conversion enabled
+ o conversions: fix several compiler warnings
+ o openssl: add missing includes [49]
+ o schannel: Support partial send for when data is too large [50]
+ o socks: fix incorrect port number in SOCKS4 error message [51]
+ o curl: fix integer overflow in timeout options [52]
+ o travis: on mac, don't install openssl or libidn [53]
+ o cookies: reject oversized cookies instead of truncating [54]
+ o cookies: use lock when using CURLINFO_COOKIELIST [55]
+ o curl: check fseek() return code and bail on error
+ o examples/post-callback: use long for CURLOPT_POSTFIELDSIZE
+ o openssl: only verify RSA private key if supported [56]
+ o tests: make the imap server not verify user+password [57]
+ o imap: quote atoms properly when escaping characters [58]
+ o tests: fix a compiler warning in test 643
+ o file_range: avoid integer overflow when figuring out byte range [59]
+ o curl.h: include <sys/select.h> on cygwin too [60]
+ o reuse_conn: don't copy flags that are known to be equal [61]
+ o http: fix adding custom empty headers to repeated requests [62]
+ o docs: clarify the use of environment variables for proxy [63]
+ o docs: link CURLOPT_CONNECTTIMEOUT and CURLOPT_CONNECTTIMEOUT_MS [64]
+ o connect: fix race condition with happy eyeballs timeout [65]
+ o cookie: fix memory leak if path was set twice in header [66]
+ o vtls: compare and clone ssl configs properly [68]
+ o proxy: read the "no_proxy" variable only if necessary [69]
 
 This release includes the following known bugs:
 
@@ -43,36 +113,89 @@ 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:
 
-  Adam Sampson, Alessandro Ghedini, Alex Potapenko, Bernard Spil,
-  Christian Weisgerber, Dagobert Michelsen, Dan Fandrich, Daniel Krügler,
-  Daniel Stenberg, David Benjamin, David Lord, Even Rouault, Han Qiao,
-  Isaac Boukris, James Slaughter, Marcel Raad, paulharris on github,
-  Ray Satiro, Salah-Eddin Shaban, Sergei Nikulov, Simon Warta,
-  Thomas Petazzoni,
-  (22 contributors)
+  Anders Bakken, Andrei Karas, Benbuck Nason, Ben Greear, Benjamin Sergeant,
+  Bill Pyne, Brian Carpenter, Dan Fandrich, Daniel Stenberg, David Benjamin,
+  Dirk Feytons, Even Rouault, Frank Denis, Gergely Nagy, Gisle Vanem,
+  Ian Fette, imilli on github, Isaac Boukris, Jackarain on github,
+  Jakub Zakrzewski, Jan Alexander Steffens, Johannes Schindelin,
+  John David Anglin, joshhe on github, Kamil Dudka, Kevin Smith,
+  Lawrence Wagerfield, Maksim Stsepanenka, Marc Aldorasi, Marcel Raad,
+  Max Dymond, Michael Kaufmann, Michael Smith, Nick Zitzmann,
+  Nicolas Morey-Chaisemartin, Oli Kingshott, Patrick Monnerat, Pavel P,
+  Peter Lamare, Peter Wu, Ray Satiro, Rich Gray, Ryan Schmidt, Ryan Winograd,
+  SBKarr on github, Tatsuhiro Tsujikawa, Viktor Szakáts,
+  (47 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=1750
- [2] = https://curl.haxx.se/bug/?i=1744
- [3] = https://curl.haxx.se/bug/?i=1742
- [4] = https://curl.haxx.se/bug/?i=1746
- [5] = https://curl.haxx.se/bug/?i=1746
- [6] = https://curl.haxx.se/bug/?i=1753
- [7] = https://curl.haxx.se/bug/?i=1755
- [8] = https://curl.haxx.se/bug/?i=1647
- [9] = https://curl.haxx.se/bug/?i=1743
- [10] = https://curl.haxx.se/mail/lib-2017-08/0050.html
- [11] = https://curl.haxx.se/bug/?i=1759
- [12] = https://curl.haxx.se/bug/?i=1761
- [13] = https://curl.haxx.se/bug/?i=1766
- [14] = https://curl.haxx.se/bug/?i=1770
- [15] = https://curl.haxx.se/bug/?i=1752
- [16] = https://curl.haxx.se/bug/?i=1769
- [17] = https://curl.haxx.se/bug/?i=1763
- [18] = https://curl.haxx.se/bug/?i=1762
- [19] = https://curl.haxx.se/bug/?i=1774
- [20] = https://curl.haxx.se/bug/?i=1764
- [21] = https://curl.haxx.se/bug/?i=1719
+ [1] = https://curl.haxx.se/bug/?i=1777
+ [2] = https://curl.haxx.se/bug/?i=1758
+ [3] = https://curl.haxx.se/bug/?i=1779
+ [4] = https://curl.haxx.se/bug/?i=1785
+ [5] = https://curl.haxx.se/bug/?i=1602
+ [6] = https://curl.haxx.se/bug/?i=1784
+ [7] = https://curl.haxx.se/bug/?i=1786
+ [8] = https://curl.haxx.se/bug/?i=1790
+ [9] = https://curl.haxx.se/bug/?i=1788
+ [10] = https://curl.haxx.se/bug/?i=1793
+ [11] = https://curl.haxx.se/bug/?i=1735
+ [12] = https://curl.haxx.se/bug/?i=1782
+ [13] = https://curl.haxx.se/bug/?i=1767
+ [14] = https://curl.haxx.se/bug/?i=1803
+ [15] = https://curl.haxx.se/bug/?i=1797
+ [16] = https://curl.haxx.se/bug/?i=1021
+ [17] = https://curl.haxx.se/bug/?i=1808
+ [18] = https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=872502#10
+ [19] = https://curl.haxx.se/bug/?i=1799
+ [20] = https://curl.haxx.se/bug/?i=1815
+ [21] = https://curl.haxx.se/bug/?i=1751
+ [22] = https://curl.haxx.se/bug/?i=1810
+ [23] = https://curl.haxx.se/bug/?i=1818
+ [24] = https://curl.haxx.se/bug/?i=1832
+ [25] = https://curl.haxx.se/bug/?i=1828
+ [26] = https://curl.haxx.se/bug/?i=1823
+ [27] = https://curl.haxx.se/bug/?i=1829
+ [28] = https://curl.haxx.se/libcurl/c/curl_global_sslset.html
+ [29] = https://curl.haxx.se/bug/?i=1837
+ [30] = https://curl.haxx.se/mail/lib-2017-08/0120.html
+ [31] = https://curl.haxx.se/bug/?i=1842
+ [32] = https://curl.haxx.se/bug/?i=1839
+ [33] = https://curl.haxx.se/bug/?i=1858
+ [34] = https://curl.haxx.se/bug/?i=1859
+ [35] = https://curl.haxx.se/bug/?i=1846
+ [36] = https://curl.haxx.se/bug/?i=1866
+ [37] = https://curl.haxx.se/bug/?i=1861
+ [38] = https://curl.haxx.se/bug/?i=1868
+ [39] = https://curl.haxx.se/bug/?i=1865
+ [40] = https://curl.haxx.se/bug/?i=1853
+ [41] = https://curl.haxx.se/bug/?i=1870
+ [42] = https://curl.haxx.se/bug/?i=1874
+ [43] = https://curl.haxx.se/bug/?i=1877
+ [44] = https://curl.haxx.se/bug/?i=1878
+ [45] = https://curl.haxx.se/bug/?i=1887
+ [46] = https://curl.haxx.se/bug/?i=1687
+ [47] = https://curl.haxx.se/bug/?i=1880
+ [48] = https://curl.haxx.se/mail/lib-2017-09/0031.html
+ [49] = https://curl.haxx.se/bug/?i=1891
+ [50] = https://curl.haxx.se/bug/?i=1890
+ [51] = https://curl.haxx.se/bug/?i=1892
+ [52] = https://curl.haxx.se/bug/?i=1893
+ [53] = https://curl.haxx.se/bug/?i=1895
+ [54] = https://curl.haxx.se/bug/?i=1894
+ [55] = https://curl.haxx.se/bug/?i=1896
+ [56] = https://curl.haxx.se/bug/?i=1904
+ [57] = https://curl.haxx.se/bug/?i=1902
+ [58] = https://curl.haxx.se/bug/?i=1902
+ [59] = https://curl.haxx.se/bug/?i=1908
+ [60] = https://curl.haxx.se/bug/?i=1925
+ [61] = https://curl.haxx.se/bug/?i=1918
+ [62] = https://curl.haxx.se/bug/?i=1920
+ [63] = https://curl.haxx.se/bug/?i=1921
+ [64] = https://curl.haxx.se/bug/?i=1922
+ [65] = https://curl.haxx.se/bug/?i=1928
+ [66] = https://curl.haxx.se/bug/?i=1932
+ [67] = https://curl.haxx.se/docs/adv_20171004.html
+ [68] = https://curl.haxx.se/bug/?i=1917
+ [69] = https://curl.haxx.se/bug/?i=1919
diff --git a/acinclude.m4 b/acinclude.m4
old mode 100644
new mode 100755
index 539322870..69bb6c002
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -2084,20 +2084,6 @@ _EOF
 ])
 
 
-dnl CURL_CONFIGURE_LONG
-dnl -------------------------------------------------
-dnl Find out the size of long as reported by sizeof() and define
-dnl CURL_SIZEOF_LONG.
-
-AC_DEFUN([CURL_CONFIGURE_LONG], [
-  if test -z "$ac_cv_sizeof_long" ||
-    test "$ac_cv_sizeof_long" -eq "0"; then
-    AC_MSG_ERROR([cannot find out size of long.])
-  fi
-  CURL_DEFINE_UNQUOTED([CURL_SIZEOF_LONG], [$ac_cv_sizeof_long])
-])
-
-
 dnl CURL_CONFIGURE_CURL_SOCKLEN_T
 dnl -------------------------------------------------
 dnl The need for the curl_socklen_t definition arises mainly to properly
@@ -2718,291 +2704,6 @@ AC_HELP_STRING([--without-ca-fallback], [Don't use the 
built in CA store of the
   fi
 ])
 
-
-dnl DO_CURL_OFF_T_CHECK (TYPE, SIZE)
-dnl -------------------------------------------------
-dnl Internal macro for CURL_CONFIGURE_CURL_OFF_T
-
-AC_DEFUN([DO_CURL_OFF_T_CHECK], [
-  AC_REQUIRE([CURL_INCLUDES_INTTYPES])dnl
-  if test "$curl_typeof_curl_off_t" = "unknown" && test ! -z "$1"; then
-    tmp_includes=""
-    tmp_source=""
-    tmp_fmt=""
-    case XC_SH_TR_SH([$1]) in
-      int64_t)
-        tmp_includes="$curl_includes_inttypes"
-        tmp_source="char f@<:@@:>@ = PRId64;"
-        tmp_fmt="PRId64"
-        ;;
-      int32_t)
-        tmp_includes="$curl_includes_inttypes"
-        tmp_source="char f@<:@@:>@ = PRId32;"
-        tmp_fmt="PRId32"
-        ;;
-      int16_t)
-        tmp_includes="$curl_includes_inttypes"
-        tmp_source="char f@<:@@:>@ = PRId16;"
-        tmp_fmt="PRId16"
-        ;;
-    esac
-    AC_COMPILE_IFELSE([
-      AC_LANG_PROGRAM([[
-        $tmp_includes
-        typedef $1 curl_off_t;
-        typedef char dummy_arr[sizeof(curl_off_t) == $2 ? 1 : -1];
-      ]],[[
-        $tmp_source
-        curl_off_t dummy;
-      ]])
-    ],[
-      if test -z "$tmp_fmt"; then
-        curl_typeof_curl_off_t="$1"
-        curl_sizeof_curl_off_t="$2"
-      else
-        CURL_CHECK_DEF([$tmp_fmt], [$curl_includes_inttypes], [silent])
-        AS_VAR_PUSHDEF([tmp_HaveFmtDef], [curl_cv_have_def_$tmp_fmt])dnl
-        AS_VAR_PUSHDEF([tmp_FmtDef], [curl_cv_def_$tmp_fmt])dnl
-        if test AS_VAR_GET(tmp_HaveFmtDef) = "yes"; then
-          curl_format_curl_off_t=AS_VAR_GET(tmp_FmtDef)
-          curl_typeof_curl_off_t="$1"
-          curl_sizeof_curl_off_t="$2"
-        fi
-        AS_VAR_POPDEF([tmp_FmtDef])dnl
-        AS_VAR_POPDEF([tmp_HaveFmtDef])dnl
-      fi
-    ])
-  fi
-])
-
-
-dnl DO_CURL_OFF_T_SUFFIX_CHECK (TYPE)
-dnl -------------------------------------------------
-dnl Internal macro for CURL_CONFIGURE_CURL_OFF_T
-
-AC_DEFUN([DO_CURL_OFF_T_SUFFIX_CHECK], [
-  AC_REQUIRE([CURL_INCLUDES_INTTYPES])dnl
-  AC_MSG_CHECKING([constant suffix string for curl_off_t])
-  #
-  curl_suffix_curl_off_t="unknown"
-  curl_suffix_curl_off_tu="unknown"
-  #
-  case XC_SH_TR_SH([$1]) in
-    long_long | __longlong | __longlong_t)
-      tst_suffixes="LL::"
-      ;;
-    long)
-      tst_suffixes="L::"
-      ;;
-    int)
-      tst_suffixes="::"
-      ;;
-    __int64 | int64_t)
-      tst_suffixes="LL:i64::"
-      ;;
-    __int32 | int32_t)
-      tst_suffixes="L:i32::"
-      ;;
-    __int16 | int16_t)
-      tst_suffixes="L:i16::"
-      ;;
-    *)
-      AC_MSG_ERROR([unexpected data type $1])
-      ;;
-  esac
-  #
-  old_IFS=$IFS; IFS=':'
-  for tmp_ssuf in $tst_suffixes ; do
-    IFS=$old_IFS
-    if test "x$curl_suffix_curl_off_t" = "xunknown"; then
-      case $tmp_ssuf in
-        i64 | i32 | i16)
-          tmp_usuf="u$tmp_ssuf"
-          ;;
-        LL | L)
-          tmp_usuf="U$tmp_ssuf"
-          ;;
-        *)
-          tmp_usuf=""
-          ;;
-      esac
-      AC_COMPILE_IFELSE([
-        AC_LANG_PROGRAM([[
-          $curl_includes_inttypes
-          typedef $1 new_t;
-        ]],[[
-          new_t s1;
-          new_t s2;
-          s1 = -10$tmp_ssuf ;
-          s2 =  20$tmp_ssuf ;
-          if(s1 > s2)
-            return 1;
-        ]])
-      ],[
-        curl_suffix_curl_off_t="$tmp_ssuf"
-        curl_suffix_curl_off_tu="$tmp_usuf"
-      ])
-    fi
-  done
-  IFS=$old_IFS
-  #
-  if test "x$curl_suffix_curl_off_t" = "xunknown"; then
-    AC_MSG_ERROR([cannot find constant suffix string for curl_off_t.])
-  else
-    AC_MSG_RESULT([$curl_suffix_curl_off_t])
-    AC_MSG_CHECKING([constant suffix string for unsigned curl_off_t])
-    AC_MSG_RESULT([$curl_suffix_curl_off_tu])
-  fi
-  #
-])
-
-
-dnl CURL_CONFIGURE_CURL_OFF_T
-dnl -------------------------------------------------
-dnl Find out suitable curl_off_t data type definition and associated
-dnl items
-
-AC_DEFUN([CURL_CONFIGURE_CURL_OFF_T], [
-  AC_REQUIRE([CURL_INCLUDES_INTTYPES])dnl
-  #
-  AC_BEFORE([$0],[AC_SYS_LARGEFILE])dnl
-  AC_BEFORE([$0],[CURL_CONFIGURE_REENTRANT])dnl
-  AC_BEFORE([$0],[CURL_CHECK_AIX_ALL_SOURCE])dnl
-  #
-  if test -z "$SED"; then
-    AC_MSG_ERROR([SED not set. Cannot continue without SED being set.])
-  fi
-  #
-  AC_CHECK_SIZEOF(long)
-  AC_CHECK_SIZEOF(void*)
-  #
-  if test -z "$ac_cv_sizeof_long" ||
-    test "$ac_cv_sizeof_long" -eq "0"; then
-    AC_MSG_ERROR([cannot find out size of long.])
-  fi
-  if test -z "$ac_cv_sizeof_voidp" ||
-     test "$ac_cv_sizeof_voidp" -eq "0"; then
-    AC_MSG_ERROR([cannot find out size of void*.])
-  fi
-  #
-  x_LP64_long=""
-  x_LP32_long=""
-  #
-  if test "$ac_cv_sizeof_long" -eq "8" &&
-     test "$ac_cv_sizeof_voidp" -ge "8"; then
-    x_LP64_long="long"
-  elif test "$ac_cv_sizeof_long" -eq "4" &&
-       test "$ac_cv_sizeof_voidp" -ge "4"; then
-    x_LP32_long="long"
-  fi
-  #
-  dnl DO_CURL_OFF_T_CHECK results are stored in next 3 vars
-  #
-  curl_typeof_curl_off_t="unknown"
-  curl_sizeof_curl_off_t="unknown"
-  curl_format_curl_off_t="unknown"
-  curl_format_curl_off_tu="unknown"
-  #
-  if test "$curl_typeof_curl_off_t" = "unknown"; then
-    AC_MSG_CHECKING([for 64-bit curl_off_t data type])
-    for t8 in          \
-      "$x_LP64_long"   \
-      'int64_t'        \
-      '__int64'        \
-      'long long'      \
-      '__longlong'     \
-      '__longlong_t'   ; do
-      DO_CURL_OFF_T_CHECK([$t8], [8])
-    done
-    AC_MSG_RESULT([$curl_typeof_curl_off_t])
-  fi
-  if test "$curl_typeof_curl_off_t" = "unknown"; then
-    AC_MSG_CHECKING([for 32-bit curl_off_t data type])
-    for t4 in          \
-      "$x_LP32_long"   \
-      'int32_t'        \
-      '__int32'        \
-      'int'            ; do
-      DO_CURL_OFF_T_CHECK([$t4], [4])
-    done
-    AC_MSG_RESULT([$curl_typeof_curl_off_t])
-  fi
-  if test "$curl_typeof_curl_off_t" = "unknown"; then
-    AC_MSG_ERROR([cannot find data type for curl_off_t.])
-  fi
-  #
-  AC_MSG_CHECKING([size of curl_off_t])
-  AC_MSG_RESULT([$curl_sizeof_curl_off_t])
-  #
-  AC_MSG_CHECKING([formatting string directive for curl_off_t])
-  if test "$curl_format_curl_off_t" != "unknown"; then
-    x_pull_headers="yes"
-    curl_format_curl_off_t=`echo "$curl_format_curl_off_t" | "$SED" 
's/[["]]//g'`
-    curl_format_curl_off_tu=`echo "$curl_format_curl_off_t" | "$SED" 's/i$/u/'`
-    curl_format_curl_off_tu=`echo "$curl_format_curl_off_tu" | "$SED" 
's/d$/u/'`
-    curl_format_curl_off_tu=`echo "$curl_format_curl_off_tu" | "$SED" 
's/D$/U/'`
-  else
-    x_pull_headers="no"
-    case XC_SH_TR_SH([$curl_typeof_curl_off_t]) in
-      long_long | __longlong | __longlong_t)
-        curl_format_curl_off_t="lld"
-        curl_format_curl_off_tu="llu"
-        ;;
-      long)
-        curl_format_curl_off_t="ld"
-        curl_format_curl_off_tu="lu"
-        ;;
-      int)
-        curl_format_curl_off_t="d"
-        curl_format_curl_off_tu="u"
-        ;;
-      __int64)
-        curl_format_curl_off_t="I64d"
-        curl_format_curl_off_tu="I64u"
-        ;;
-      __int32)
-        curl_format_curl_off_t="I32d"
-        curl_format_curl_off_tu="I32u"
-        ;;
-      __int16)
-        curl_format_curl_off_t="I16d"
-        curl_format_curl_off_tu="I16u"
-        ;;
-      *)
-        AC_MSG_ERROR([cannot find print format string for curl_off_t.])
-        ;;
-    esac
-  fi
-  AC_MSG_RESULT(["$curl_format_curl_off_t"])
-  #
-  AC_MSG_CHECKING([formatting string directive for unsigned curl_off_t])
-  AC_MSG_RESULT(["$curl_format_curl_off_tu"])
-  #
-  DO_CURL_OFF_T_SUFFIX_CHECK([$curl_typeof_curl_off_t])
-  #
-  if test "$x_pull_headers" = "yes"; then
-    if test "x$ac_cv_header_sys_types_h" = "xyes"; then
-      CURL_DEFINE_UNQUOTED([CURL_PULL_SYS_TYPES_H])
-    fi
-    if test "x$ac_cv_header_stdint_h" = "xyes"; then
-      CURL_DEFINE_UNQUOTED([CURL_PULL_STDINT_H])
-    fi
-    if test "x$ac_cv_header_inttypes_h" = "xyes"; then
-      CURL_DEFINE_UNQUOTED([CURL_PULL_INTTYPES_H])
-    fi
-  fi
-  #
-  CURL_DEFINE_UNQUOTED([CURL_TYPEOF_CURL_OFF_T], [$curl_typeof_curl_off_t])
-  CURL_DEFINE_UNQUOTED([CURL_FORMAT_CURL_OFF_T], ["$curl_format_curl_off_t"])
-  CURL_DEFINE_UNQUOTED([CURL_FORMAT_CURL_OFF_TU], ["$curl_format_curl_off_tu"])
-  CURL_DEFINE_UNQUOTED([CURL_FORMAT_OFF_T], ["%$curl_format_curl_off_t"])
-  CURL_DEFINE_UNQUOTED([CURL_SIZEOF_CURL_OFF_T], [$curl_sizeof_curl_off_t])
-  CURL_DEFINE_UNQUOTED([CURL_SUFFIX_CURL_OFF_T], [$curl_suffix_curl_off_t])
-  CURL_DEFINE_UNQUOTED([CURL_SUFFIX_CURL_OFF_TU], [$curl_suffix_curl_off_tu])
-  #
-])
-
-
 dnl CURL_CHECK_WIN32_LARGEFILE
 dnl -------------------------------------------------
 dnl Check if curl's WIN32 large file will be used
@@ -3243,3 +2944,29 @@ AC_DEFUN([CURL_MAC_CFLAGS], [
   fi
 
 ])
+
+
+dnl CURL_SUPPORTS_BUILTIN_AVAILABLE
+dnl
+dnl Check to see if the compiler supports __builtin_available. This built-in
+dnl compiler function first appeared in Apple LLVM 9.0.0. It's so new that, at
+dnl the time this macro was written, the function was not yet documented. Its
+dnl purpose is to return true if the code is running under a certain OS version
+dnl or later.
+
+AC_DEFUN([CURL_SUPPORTS_BUILTIN_AVAILABLE], [
+  AC_MSG_CHECKING([to see if the compiler supports __builtin_available()])
+  AC_COMPILE_IFELSE([
+    AC_LANG_PROGRAM([[
+#include <stdlib.h>
+    ]],[[
+      if (__builtin_available(macOS 10.8, iOS 5.0, *)) {}
+    ]])
+  ],[
+    AC_MSG_RESULT([yes])
+    AC_DEFINE_UNQUOTED(HAVE_BUILTIN_AVAILABLE, 1,
+        [Define to 1 if you have the __builtin_available function.])
+  ],[
+    AC_MSG_RESULT([no])
+  ])
+])
diff --git a/configure.ac b/configure.ac
old mode 100644
new mode 100755
index c27c516e4..0bd697327
--- a/configure.ac
+++ b/configure.ac
@@ -124,6 +124,7 @@ AC_SUBST(libext)
 dnl figure out the libcurl version
 CURLVERSION=`$SED -ne 's/^#define LIBCURL_VERSION "\(.*\)".*/\1/p' 
${srcdir}/include/gnurl/curlver.h`
 XC_CHECK_PROG_CC
+AC_PROG_CXX
 XC_AUTOMAKE
 AC_MSG_CHECKING([curl version])
 AC_MSG_RESULT($CURLVERSION)
@@ -165,7 +166,7 @@ curl_verbose_msg="enabled (--disable-verbose)"
   curl_mtlnk_msg="no      (--with-libmetalink)"
     curl_psl_msg="no      (--with-libpsl)"
 
-    init_ssl_msg=${curl_ssl_msg}
+    ssl_backends=
 
 dnl
 dnl Save some initial values the user might have provided
@@ -183,9 +184,6 @@ AC_DEFINE_UNQUOTED(OS, "${host}", [cpu-machine-OS])
 
 dnl Checks for programs.
 
-dnl Our curl_off_t internal and external configure settings
-CURL_CONFIGURE_CURL_OFF_T
-
 dnl This defines _ALL_SOURCE for AIX
 CURL_CHECK_AIX_ALL_SOURCE
 
@@ -354,6 +352,7 @@ esac
 CURL_CHECK_WIN32_LARGEFILE
 
 CURL_MAC_CFLAGS
+CURL_SUPPORTS_BUILTIN_AVAILABLE
 
 dnl ************************************************************
 dnl switch off particular protocols
@@ -1329,6 +1328,41 @@ else
   CPPFLAGS="$save_CPPFLAGS"
 fi
 
+build_libstubgss=no
+if test x"$want_gss" = "xyes"; then
+  build_libstubgss=yes
+fi
+
+AM_CONDITIONAL(BUILD_STUB_GSS, test "x$build_libstubgss" = "xyes")
+
+dnl -------------------------------------------------------------
+dnl parse --with-default-ssl-backend so it can be validated below
+dnl -------------------------------------------------------------
+
+DEFAULT_SSL_BACKEND=no
+VALID_DEFAULT_SSL_BACKEND=
+AC_ARG_WITH(default-ssl-backend,
+AC_HELP_STRING([--with-default-ssl-backend=NAME],[Use NAME as default SSL 
backend])
+AC_HELP_STRING([--without-default-ssl-backend],[Use implicit default SSL 
backend]),
+  [DEFAULT_SSL_BACKEND=$withval])
+case "$DEFAULT_SSL_BACKEND" in
+  no)
+    dnl --without-default-ssl-backend option used
+    ;;
+  default|yes)
+    dnl --with-default-ssl-backend option used without name
+    AC_MSG_ERROR([The name of the default SSL backend is required.])
+    ;;
+  *)
+    dnl --with-default-ssl-backend option used with name
+    AC_SUBST(DEFAULT_SSL_BACKEND)
+    dnl needs to be validated below
+    VALID_DEFAULT_SSL_BACKEND=no
+    ;;
+esac
+
+dnl **********************************************************************
+
 dnl -------------------------------------------------
 dnl check winssl option before other SSL libraries
 dnl -------------------------------------------------
@@ -1340,13 +1374,15 @@ AC_HELP_STRING([--without-winssl], [disable Windows 
native SSL/TLS]),
   OPT_WINSSL=$withval)
 
 AC_MSG_CHECKING([whether to enable Windows native SSL/TLS (Windows native 
builds only)])
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_WINSSL" != xno; then
+  ssl_msg=
   if test "x$OPT_WINSSL" != "xno"  &&
      test "x$curl_cv_native_windows" = "xyes"; then
     AC_MSG_RESULT(yes)
     AC_DEFINE(USE_SCHANNEL, 1, [to enable Windows native SSL/TLS support])
     AC_SUBST(USE_SCHANNEL, [1])
-    curl_ssl_msg="enabled (Windows-native)"
+    ssl_msg="Windows-native"
+    test schannel != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
     WINSSL_ENABLED=1
     # --with-winssl implies --enable-sspi
     AC_DEFINE(USE_WINDOWS_SSPI, 1, [to enable SSPI support])
@@ -1356,6 +1392,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
   else
     AC_MSG_RESULT(no)
   fi
+  test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
 else
   AC_MSG_RESULT(no)
 fi
@@ -1367,18 +1404,20 @@ AC_HELP_STRING([--without-darwinssl], [disable Apple OS 
native SSL/TLS]),
   OPT_DARWINSSL=$withval)
 
 AC_MSG_CHECKING([whether to enable Apple OS native SSL/TLS])
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_DARWINSSL" != xno; then
   if test "x$OPT_DARWINSSL" != "xno" &&
      test -d "/System/Library/Frameworks/Security.framework"; then
     AC_MSG_RESULT(yes)
     AC_DEFINE(USE_DARWINSSL, 1, [to enable Apple OS native SSL/TLS support])
     AC_SUBST(USE_DARWINSSL, [1])
-    curl_ssl_msg="enabled (Apple OS-native)"
+    ssl_msg="Apple OS-native"
+    test darwinssl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
     DARWINSSL_ENABLED=1
     LDFLAGS="$LDFLAGS -framework CoreFoundation -framework Security"
   else
     AC_MSG_RESULT(no)
   fi
+  test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
 else
   AC_MSG_RESULT(no)
 fi
@@ -1396,7 +1435,10 @@ AC_HELP_STRING([--with-ssl=PATH],[Where to look for 
OpenSSL, PATH points to the
 AC_HELP_STRING([--without-ssl], [disable OpenSSL]),
   OPT_SSL=$withval)
 
-if test "$curl_ssl_msg" = "$init_ssl_msg" && test X"$OPT_SSL" != Xno; then
+if test -z "$ssl_backends" -o "x$OPT_SSL" != xno &&
+   test X"$OPT_SSL" != Xno; then
+  ssl_msg=
+
   dnl backup the pre-ssl variables
   CLEANLDFLAGS="$LDFLAGS"
   CLEANCPPFLAGS="$CPPFLAGS"
@@ -1577,7 +1619,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg" && test 
X"$OPT_SSL" != Xno; then
       dnl Have the libraries--check for OpenSSL headers
       AC_CHECK_HEADERS(openssl/x509.h openssl/rsa.h openssl/crypto.h \
                        openssl/pem.h openssl/ssl.h openssl/err.h,
-        curl_ssl_msg="enabled (OpenSSL)"
+        ssl_msg="OpenSSL"
+       test openssl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
         OPENSSL_ENABLED=1
         AC_DEFINE(USE_OPENSSL, 1, [if OpenSSL is in use]))
 
@@ -1591,7 +1634,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg" && test 
X"$OPT_SSL" != Xno; then
            test $ac_cv_header_crypto_h = yes &&
            test $ac_cv_header_ssl_h = yes; then
           dnl three matches
-          curl_ssl_msg="enabled (OpenSSL)"
+          ssl_msg="OpenSSL"
           OPENSSL_ENABLED=1
         fi
       fi
@@ -1642,7 +1685,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg" && test 
X"$OPT_SSL" != Xno; then
         AC_MSG_RESULT([yes])
         AC_DEFINE_UNQUOTED(HAVE_BORINGSSL, 1,
                            [Define to 1 if using BoringSSL.])
-        curl_ssl_msg="enabled (BoringSSL)"
+        ssl_msg="BoringSSL"
     ],[
         AC_MSG_RESULT([no])
     ])
@@ -1658,7 +1701,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg" && test 
X"$OPT_SSL" != Xno; then
       AC_MSG_RESULT([yes])
       AC_DEFINE_UNQUOTED(HAVE_LIBRESSL, 1,
         [Define to 1 if using libressl.])
-      curl_ssl_msg="enabled (libressl)"
+      ssl_msg="libressl"
     ],[
       AC_MSG_RESULT([no])
     ])
@@ -1678,6 +1721,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg" && test 
X"$OPT_SSL" != Xno; then
     CURL_CHECK_OPENSSL_API
   fi
 
+  test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
 fi
 
 dnl **********************************************************************
@@ -1739,7 +1783,8 @@ AC_HELP_STRING([--with-gnutls=PATH],[where to look for 
GnuTLS, PATH points to th
 AC_HELP_STRING([--without-gnutls], [disable GnuTLS detection]),
   OPT_GNUTLS=$withval)
 
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_GNUTLS" != xno; then
+  ssl_msg=
 
   if test X"$OPT_GNUTLS" != Xno; then
 
@@ -1813,7 +1858,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
        AC_SUBST(USE_GNUTLS, [1])
        GNUTLS_ENABLED=1
        USE_GNUTLS="yes"
-       curl_ssl_msg="enabled (GnuTLS)"
+       ssl_msg="GnuTLS"
+       test gnutls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
        ],
        [
          LIBS="$CLEANLIBS"
@@ -1828,7 +1874,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
           dnl linker doesn't search through, we need to add it to
           dnl LD_LIBRARY_PATH to prevent further configure tests to fail
           dnl due to this
-          if test "x$cross_compiling" != "xyes"; then 
+          if test "x$cross_compiling" != "xyes"; then
             LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$gtlslib"
             export LD_LIBRARY_PATH
             AC_MSG_NOTICE([Added $gtlslib to LD_LIBRARY_PATH])
@@ -1841,6 +1887,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
 
   fi dnl GNUTLS not disabled
 
+  test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
 fi
 
 dnl ---
@@ -1898,7 +1945,8 @@ AC_HELP_STRING([--with-polarssl=PATH],[where to look for 
PolarSSL, PATH points t
 AC_HELP_STRING([--without-polarssl], [disable PolarSSL detection]),
   OPT_POLARSSL=$withval)
 
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_POLARSSL" != xno; then
+  ssl_msg=
 
   if test X"$OPT_POLARSSL" != Xno; then
 
@@ -1916,7 +1964,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
          AC_SUBST(USE_POLARSSL, [1])
          POLARSSL_ENABLED=1
          USE_POLARSSL="yes"
-         curl_ssl_msg="enabled (PolarSSL)"
+         ssl_msg="PolarSSL"
+        test polarssl != "$DEFAULT_SSL_BACKEND" || 
VALID_DEFAULT_SSL_BACKEND=yes
         ])
     fi
 
@@ -1942,7 +1991,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
        AC_SUBST(USE_POLARSSL, [1])
        POLARSSL_ENABLED=1
        USE_POLARSSL="yes"
-       curl_ssl_msg="enabled (PolarSSL)"
+       ssl_msg="PolarSSL"
+       test polarssl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
        ],
        [
          CPPFLAGS=$_cppflags
@@ -1970,6 +2020,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
 
   fi dnl PolarSSL not disabled
 
+  test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
 fi
 
 dnl ----------------------------------------------------
@@ -1985,7 +2036,8 @@ AC_HELP_STRING([--with-mbedtls=PATH],[where to look for 
mbedTLS, PATH points to
 AC_HELP_STRING([--without-mbedtls], [disable mbedTLS detection]),
   OPT_MBEDTLS=$withval)
 
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_MBEDTLS" != xno; then
+  ssl_msg=
 
   if test X"$OPT_MBEDTLS" != Xno; then
 
@@ -2003,7 +2055,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
          AC_SUBST(USE_MBEDTLS, [1])
          MBEDTLS_ENABLED=1
          USE_MBEDTLS="yes"
-         curl_ssl_msg="enabled (mbedTLS)"
+         ssl_msg="mbedTLS"
+        test mbedtls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
         ], [], -lmbedx509 -lmbedcrypto)
     fi
 
@@ -2029,7 +2082,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
        AC_SUBST(USE_MBEDTLS, [1])
        MBEDTLS_ENABLED=1
        USE_MBEDTLS="yes"
-       curl_ssl_msg="enabled (mbedTLS)"
+       ssl_msg="mbedTLS"
+       test mbedtls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
        ],
        [
          CPPFLAGS=$_cppflags
@@ -2057,6 +2111,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
 
   fi dnl mbedTLS not disabled
 
+  test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
 fi
 
 dnl ----------------------------------------------------
@@ -2073,7 +2128,8 @@ AC_HELP_STRING([--with-cyassl=PATH],[where to look for 
CyaSSL, PATH points to th
 AC_HELP_STRING([--without-cyassl], [disable CyaSSL detection]),
   OPT_CYASSL=$withval)
 
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_CYASSL" != xno; then
+  ssl_msg=
 
   if test X"$OPT_CYASSL" != Xno; then
 
@@ -2095,7 +2151,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
          AC_SUBST(USE_CYASSL, [1])
          CYASSL_ENABLED=1
          USE_CYASSL="yes"
-         curl_ssl_msg="enabled (CyaSSL)"
+         ssl_msg="CyaSSL"
+        test cyassl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
         ])
     fi
 
@@ -2121,7 +2178,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
        AC_SUBST(USE_CYASSL, [1])
        CYASSL_ENABLED=1
        USE_CYASSL="yes"
-       curl_ssl_msg="enabled (CyaSSL)"
+       ssl_msg="CyaSSL"
+       test cyassl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
        ],
        [
          CPPFLAGS=$_cppflags
@@ -2166,7 +2224,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
          AC_SUBST(USE_CYASSL, [1])
          CYASSL_ENABLED=1
          USE_CYASSL="yes"
-         curl_ssl_msg="enabled (WolfSSL)"
+         ssl_msg="WolfSSL"
+        test cyassl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
        ],
        [
          AC_MSG_RESULT(no)
@@ -2220,6 +2279,7 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
 
   fi dnl CyaSSL not disabled
 
+  test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
 fi
 
 dnl ----------------------------------------------------
@@ -2234,7 +2294,8 @@ AC_HELP_STRING([--with-nss=PATH],[where to look for NSS, 
PATH points to the inst
 AC_HELP_STRING([--without-nss], [disable NSS detection]),
   OPT_NSS=$withval)
 
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_NSS" != xno; then
+  ssl_msg=
 
   if test X"$OPT_NSS" != Xno; then
 
@@ -2309,7 +2370,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
      AC_SUBST(USE_NSS, [1])
      USE_NSS="yes"
      NSS_ENABLED=1
-     curl_ssl_msg="enabled (NSS)"
+     ssl_msg="NSS"
+     test nss != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
      ],
      [
        LDFLAGS="$CLEANLDFLAGS"
@@ -2338,7 +2400,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
 
   fi dnl NSS not disabled
 
-fi dnl curl_ssl_msg = init_ssl_msg
+  test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
+fi
 
 OPT_AXTLS=off
 
@@ -2347,7 +2410,8 @@ AC_HELP_STRING([--with-axtls=PATH],[Where to look for 
axTLS, PATH points to the
 AC_HELP_STRING([--without-axtls], [disable axTLS]),
   OPT_AXTLS=$withval)
 
-if test "$curl_ssl_msg" = "$init_ssl_msg"; then
+if test -z "$ssl_backends" -o "x$OPT_AXTLS" != xno; then
+  ssl_msg=
   if test X"$OPT_AXTLS" != Xno; then
     dnl backup the pre-axtls variables
     CLEANLDFLAGS="$LDFLAGS"
@@ -2381,7 +2445,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
       AC_SUBST(USE_AXTLS, [1])
       AXTLS_ENABLED=1
       USE_AXTLS="yes"
-      curl_ssl_msg="enabled (axTLS)"
+      ssl_msg="axTLS"
+      test axtls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes
 
       if test "x$cross_compiling" != "xyes"; then
         LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$LIB_AXTLS"
@@ -2394,15 +2459,46 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then
       LIBS="$CLEANLIBS"
     ])
   fi
+  test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg"
 fi
 
-if test 
"x$OPENSSL_ENABLED$GNUTLS_ENABLED$NSS_ENABLED$POLARSSL_ENABLED$MBEDTLS_ENABLED$AXTLS_ENABLED$CYASSL_ENABLED$WINSSL_ENABLED$DARWINSSL_ENABLED"
 = "x"; then
+case 
"x$OPENSSL_ENABLED$GNUTLS_ENABLED$NSS_ENABLED$POLARSSL_ENABLED$MBEDTLS_ENABLED$AXTLS_ENABLED$CYASSL_ENABLED$WINSSL_ENABLED$DARWINSSL_ENABLED"
 in
+x)
   AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and 
more.])
   AC_MSG_WARN([Use --with-ssl, --with-gnutls, --with-polarssl, --with-cyassl, 
--with-nss, --with-axtls, --with-winssl, or --with-darwinssl to address this.])
-else
-  # SSL is enabled, genericly
+  ;;
+x1)
+  # one SSL backend is enabled
+  AC_SUBST(SSL_ENABLED)
+  SSL_ENABLED="1"
+  AC_MSG_NOTICE([built with one SSL backend])
+  ;;
+*)
+  # more than one SSL backend is enabled
   AC_SUBST(SSL_ENABLED)
   SSL_ENABLED="1"
+  AC_SUBST(CURL_WITH_MULTI_SSL)
+  CURL_WITH_MULTI_SSL="1"
+  AC_DEFINE(CURL_WITH_MULTI_SSL, 1, [built with multiple SSL backends])
+  AC_MSG_NOTICE([built with multiple SSL backends])
+  ;;
+esac
+
+if test -n "$ssl_backends"; then
+  curl_ssl_msg="enabled ($ssl_backends)"
+fi
+
+if test no = "$VALID_DEFAULT_SSL_BACKEND"
+then
+  if test -n "$SSL_ENABLED"
+  then
+    AC_MSG_ERROR([Default SSL backend $DEFAULT_SSL_BACKEND not enabled!])
+  else
+    AC_MSG_ERROR([Default SSL backend requires SSL!])
+  fi
+elif test yes = "$VALID_DEFAULT_SSL_BACKEND"
+then
+  AC_DEFINE_UNQUOTED([CURL_DEFAULT_SSL_BACKEND], ["$DEFAULT_SSL_BACKEND"], 
[Default SSL backend])
 fi
 
 dnl **********************************************************************
@@ -2703,7 +2799,9 @@ AC_HELP_STRING([--disable-versioned-symbols], [Disable 
versioned symbols in shar
         AC_MSG_WARN([You need an ld version supporting the --version-script 
option])
     else
         AC_MSG_RESULT(yes)
-        if test "x$OPENSSL_ENABLED" = "x1"; then
+        if test "x$CURL_WITH_MULTI_SSL" = "x1"; then
+          versioned_symbols_flavour="MULTISSL_"
+        elif test "x$OPENSSL_ENABLED" = "x1"; then
           versioned_symbols_flavour="OPENSSL_"
         elif test "x$GNUTLS_ENABLED" = "x1"; then
           versioned_symbols_flavour="GNUTLS_"
@@ -3151,18 +3249,15 @@ AC_CHECK_SIZEOF(size_t)
 AC_CHECK_SIZEOF(long)
 AC_CHECK_SIZEOF(int)
 AC_CHECK_SIZEOF(short)
-CURL_CONFIGURE_LONG
 AC_CHECK_SIZEOF(time_t)
 AC_CHECK_SIZEOF(off_t)
 
-soname_bump=no
-if test x"$curl_cv_native_windows" != "xyes" &&
-   test $ac_cv_sizeof_off_t -ne $curl_sizeof_curl_off_t; then
-  AC_MSG_WARN([This libcurl built is probably not ABI compatible with 
previous])
-  AC_MSG_WARN([builds! You MUST read lib/README.curl_off_t to figure it out.])
-  soname_bump=yes
-fi
-
+o=$CPPFLAGS
+CPPFLAGS="-I$srcdir/include $CPPFLAGS"
+AC_CHECK_SIZEOF(curl_off_t, unused , [
+#include <curl/system.h>
+])
+CPPFLAGS=$o
 
 AC_CHECK_TYPE(long long,
    [AC_DEFINE(HAVE_LONGLONG, 1,
@@ -3641,26 +3736,6 @@ dnl hiding of library internal symbols
 dnl
 CURL_CONFIGURE_SYMBOL_HIDING
 
-dnl ************************************************************
-dnl enforce SONAME bump
-dnl
-
-AC_MSG_CHECKING([whether to enforce SONAME bump])
-AC_ARG_ENABLE(soname-bump,
-AC_HELP_STRING([--enable-soname-bump],[Enable enforced SONAME bump])
-AC_HELP_STRING([--disable-soname-bump],[Disable enforced SONAME bump]),
-[ case "$enableval" in
-  yes)   AC_MSG_RESULT(yes)
-         soname_bump=yes
-         ;;
-  *)
-         AC_MSG_RESULT(no)
-         ;;
-  esac ],
-        AC_MSG_RESULT($soname_bump)
-)
-AM_CONDITIONAL(SONAME_BUMP, test x$soname_bump = xyes)
-
 dnl
 dnl All the library dependencies put into $LIB apply to libcurl only.
 dnl
@@ -3757,6 +3832,10 @@ if test "x$USE_NGHTTP2" = "x1"; then
   SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2"
 fi
 
+if test "x$CURL_WITH_MULTI_SSL" = "x1"; then
+  SUPPORT_FEATURES="$SUPPORT_FEATURES MultiSSL"
+fi
+
 if test "x$OPENSSL_ENABLED" = "x1" -o "x$GNUTLS_ENABLED" = "x1" \
     -o "x$NSS_ENABLED" = "x1"; then
   SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy"
@@ -3944,14 +4023,3 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
   HTTP2 support:    ${curl_h2_msg}
   Protocols:        ${SUPPORT_PROTOCOLS}
 ])
-
-if test "x$soname_bump" = "xyes"; then
-
-cat <<EOM
-  SONAME bump:     yes - WARNING: this library will be built with the SONAME
-                   number bumped due to (a detected) ABI breakage.
-                   See lib/README.curl_off_t for details on this.
-EOM
-
-fi
-
diff --git a/docs/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md
index 04ea66ed9..1f71c387b 100644
--- a/docs/CODE_OF_CONDUCT.md
+++ b/docs/CODE_OF_CONDUCT.md
@@ -28,5 +28,5 @@ reported by opening an issue or contacting one or more of the 
project
 maintainers.
 
 This Code of Conduct is adapted from the [Contributor
-Covenant](http://contributor-covenant.org), version 1.1.0, available at
-[http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/)
+Covenant](https://contributor-covenant.org/), version 1.1.0, available at
+[https://contributor-covenant.org/version/1/1/0/](https://contributor-covenant.org/version/1/1/0/)
diff --git a/docs/HELP-US.md b/docs/HELP-US.md
new file mode 100644
index 000000000..d9e0bddc5
--- /dev/null
+++ b/docs/HELP-US.md
@@ -0,0 +1,70 @@
+# How to get started helping out in the curl project
+
+We are always in need of more help. If you are new to the project and are
+looking for ways to contribute and help out, this document aims to give a few
+good starting points.
+
+A good idea is to start by subscribing to the [curl-library mailing
+list](https://cool.haxx.se/mailman/listinfo/curl-library) to keep track of the
+current discussion topics.
+
+## Scratch your own itch
+
+One of the best ways is to start working on any problems or issues you have
+found yourself or perhaps got annoyed at in the past. It can be a spelling
+error in an error text or a weirdly phrased section in a man page. Hunt it
+down and report the bug. Or make your first pull request with a fix for that.
+
+## PR-welcome
+
+In the issue tracker we occasionally mark bugs with
+[PR-welcome](https://github.com/curl/curl/labels/PR-welcome), as a sign that
+the bug is acknowledged to exist and that there's nobody known to work on this
+issue for the moment. Those are bugs that are fine to "grab" and provide a
+pull request for. The complexity level of these will of course vary, so pick
+one that piques your interest.
+
+## Work on known bugs
+
+Some bugs are known and haven't yet received attention and work enough to get
+fixed. We collect such known existing flaws in the
+[KNOWN_BUGS](https://curl.haxx.se/docs/knownbugs.html) page. Many of them link
+to the original bug report with some additional details, but some may also
+have aged a bit and may require some verification that the bug still exists in
+the same way and that what was said about it in the past is still valid.
+
+## Fix autobuild problems
+
+On the [autobuilds page](https://curl.haxx.se/dev/builds.html) we show a
+collection of test results from the automatic curl build and tests that are
+performed by volunteers. Fixing compiler warnings and errors shown there is
+something we value greatly. Also, if you own or run systems or architectures
+that aren't already tested in the autobuilds, we also appreciate more
+volunteers running builds automatically to help us keep curl portable.
+
+## TODO items
+
+Ideas for features and functions that we have considered worthwhile to
+implement and provide are kept in the
+[TODO](https://curl.haxx.se/docs/todo.html) file. Some of the ideas are
+rough. Some are well thought out. Some probably aren't really suitable
+anymore.
+
+Before you invest a lot of time on a TODO item, do bring it up for discussion
+on the mailing list. For discussion on applicability but also for ideas and
+brainstorming on specific ways to do the implementation etc.
+
+## You decide
+
+You can also come up with a completely new thing you think we should do. Or
+not do. Or fix. Or add to the project. You then either bring it to the mailing
+list first to see if people will shoot down the idea at once, or you bring a
+first draft of the idea as a pull request and take the discussion there around
+the specific implementation. Either way is fine.
+
+## CONTRIBUTE
+
+We offer [guidelines](https://curl.haxx.se/dev/contribute.html) that are
+suitable to be familiar with before you decide to contribute to curl. If
+you're used to open source development, you'll probably not find many
+surprises in there.
diff --git a/docs/HISTORY.md b/docs/HISTORY.md
index 551e7d258..a84ad8f1b 100644
--- a/docs/HISTORY.md
+++ b/docs/HISTORY.md
@@ -275,3 +275,21 @@ August:
  March: first real release supporting HTTP/2
 
  September: Web site had 245,000 unique visitors and served 236GB data
+
+2016
+----
+
+ December: curl 7.52.0 introduced support for HTTPS-proxy!
+
+2017
+----
+
+ September: Added Multi-SSL support
+
+ The web site serves 3100 GB/month
+
+    Public curl releases:         169
+    Command line options:         211
+    curl_easy_setopt() options:   249
+    Public functions in libcurl:  74
+    Contributors:                 1609
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index 6c2c8ce64..67a9378ff 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -222,6 +222,9 @@ subdirectory run following command from mentioned 
subdirectory:
 In order to build sample program simplessl.c an SSL enabled libcurl is
 required, as well as the OpenSSL libeay32.lib and ssleay32.lib libraries.
 
+In order to build sample program `sslbackend.c`, an SSL enabled libcurl
+is required.
+
 ## Disabling Specific Protocols in Windows builds
 
 The configure utility, unfortunately, is not available for the Windows
diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS
index 17731945a..961a62814 100644
--- a/docs/KNOWN_BUGS
+++ b/docs/KNOWN_BUGS
@@ -18,7 +18,6 @@ problems may have been fixed or changed somewhat since this 
was written!
  1.4 multipart formposts file name encoding
  1.5 Expect-100 meets 417
  1.6 Unnecessary close when 401 received waiting for 100
- 1.8 DNS timing is wrong for HTTP redirects
  1.9 HTTP/2 frames while in the connection pool kill reuse
  1.10 Strips trailing dot from host name
  1.11 CURLOPT_SEEKFUNCTION not called with CURLFORM_STREAM
@@ -83,6 +82,7 @@ problems may have been fixed or changed somewhat since this 
was written!
  11.1 Curl leaks .onion hostnames in DNS
  11.2 error buffer not set if connection to multiple addresses fails
  11.3 c-ares deviates from stock resolver on http://1346569778
+ 11.4 HTTP test server 'connection-monitor' problems
 
  12. LDAP and OpenLDAP
  12.1 OpenLDAP hangs after returning results
@@ -140,12 +140,6 @@ problems may have been fixed or changed somewhat since 
this was written!
  waiting for the the 100-continue response.
  https://curl.haxx.se/mail/lib-2008-08/0462.html
 
-1.8 DNS timing is wrong for HTTP redirects
-
- When extracting timing information after HTTP redirects, only the last
- transfer's results are returned and not the totals:
- https://github.com/curl/curl/issues/522
-
 1.9 HTTP/2 frames while in the connection pool kill reuse
 
  If the server sends HTTP/2 frames (like for example an HTTP/2 PING frame) to
@@ -322,7 +316,6 @@ problems may have been fixed or changed somewhat since this 
was written!
  The cmake build setup lacks several features that the autoconf build
  offers. This includes:
 
-  - symbol hiding when the shared library is built
   - use of correct soname for the shared library build
   - support for several TLS backends are missing
   - the unit tests cause link failures in regular non-static builds
@@ -559,6 +552,13 @@ problems may have been fixed or changed somewhat since 
this was written!
 
  See https://github.com/curl/curl/issues/893
 
+11.4 HTTP test server 'connection-monitor' problems
+
+ The 'connection-monitor' feature of the sws HTTP test server doesn't work
+ properly if some tests are run in unexpected order. Like 1509 and then 1525.
+
+ See https://github.com/curl/curl/issues/868
+
 
 12. LDAP and OpenLDAP
 
diff --git a/docs/MAIL-ETIQUETTE b/docs/MAIL-ETIQUETTE
index 897fc9f52..54f1090b7 100644
--- a/docs/MAIL-ETIQUETTE
+++ b/docs/MAIL-ETIQUETTE
@@ -15,6 +15,7 @@ MAIL ETIQUETTE
   1.6 Handling trolls and spam
   1.7 How to unsubscribe
   1.8 I posted, now what?
+  1.9 Your emails are public
 
  2. Sending mail
   2.1 Reply or New Mail
@@ -118,9 +119,9 @@ MAIL ETIQUETTE
   to the page for the particular mailing list you're subscribed to and you 
enter
   your email address and password and press the unsubscribe button.
 
-  Also, the instructions to unsubscribe are included in the headers of every 
-  mail that is sent out to all curl related mailing lists and there's a footer 
-  in each mail that links to the "admin" page on which you can unsubscribe and 
+  Also, the instructions to unsubscribe are included in the headers of every
+  mail that is sent out to all curl related mailing lists and there's a footer
+  in each mail that links to the "admin" page on which you can unsubscribe and
   change other options.
 
   You NEVER EVER email the mailing list requesting someone else to take you off
@@ -151,7 +152,7 @@ MAIL ETIQUETTE
   or repeat the same steps in their locations.
 
   Failing to include details will only delay responses and make people respond
-  and ask for more details and you will have to send a follow-up email that 
+  and ask for more details and you will have to send a follow-up email that
   includes them.
 
   Expect the responses to primarily help YOU debug the issue, or ask YOU
@@ -162,6 +163,27 @@ MAIL ETIQUETTE
   chances are that people will ignore you at will and your chances to get
   responses in the future will greatly diminish.
 
+  1.9 Your emails are public
+
+  Your email, its contents and all its headers and the details in those
+  headers will be received by every subscriber of the mailing list that you
+  send your email to.
+
+  Your email as sent to a curl mailing list will end up in mail archives, on
+  the curl web site and elsewhere, for others to see and read. Today and in
+  the future. In addition to the archives, the mail is sent out to thousands
+  of individuals. There is no way to undo a sent email.
+
+  When sending emails to a curl mailing list, do not include sensitive
+  information such as user names and passwords; use fake ones, temporary ones
+  or just remove them completely from the mail. Note that this includes base64
+  encoded HTTP Basic auth headers.
+
+  This public nature of the curl mailing lists makes automaticly inserted mail
+  footers about mails being "private" or "only meant for the receipient" or
+  similar even more silly than usual. Because they are absolutely not private
+  when sent to a public mailing list.
+
 
 2. Sending mail
 
@@ -261,4 +283,3 @@ MAIL ETIQUETTE
   Getting the solution posted also helps other users that experience the same
   problem(s). They get to see (possibly in the web archives) that the
   suggested fixes actually has helped at least one person.
-
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 0cc9b5acf..70da87ad5 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -46,7 +46,7 @@ EXTRA_DIST = MANUAL BUGS CONTRIBUTE.md FAQ FEATURES 
INTERNALS.md SSLCERTS.md
  README.netware MAIL-ETIQUETTE HTTP-COOKIES.md SECURITY.md RELEASE-PROCEDURE   
 \
  SSL-PROBLEMS.md HTTP2.md ROADMAP.md CODE_OF_CONDUCT.md CODE_STYLE.md          
 \
  CHECKSRC.md CMakeLists.txt README.md CIPHERS.md INSTALL.cmake README.cmake    
 \
- $(noinst_man_MANS)
+ $(noinst_man_MANS) HELP-US.md
 
 MAN2HTML= roffit $< >$@
 
diff --git a/docs/THANKS b/docs/THANKS
index 5e4a98eff..5aa2a122c 100644
--- a/docs/THANKS
+++ b/docs/THANKS
@@ -92,6 +92,7 @@ Andreas Streichardt
 Andreas Wurf
 Andrei Benea
 Andrei Cipu
+Andrei Karas
 Andrei Kurushin
 Andrei Sedoi
 Andrej E Baranov
@@ -158,6 +159,7 @@ Benjamin Gerard
 Benjamin Gilbert
 Benjamin Johnson
 Benjamin Kircher
+Benjamin Sergeant
 Benoit Neil
 Benoit Sigoure
 Bernard Leak
@@ -172,6 +174,7 @@ Bill Egert
 Bill Hoffman
 Bill Middlecamp
 Bill Nagel
+Bill Pyne
 Bjoern Sikora
 Bjorn Augustsson
 Bjorn Reese
@@ -384,6 +387,7 @@ Dimitrios Siganos
 Dimitris Sarris
 Dinar
 Dirk Eddelbuettel
+Dirk Feytons
 Dirk Manske
 Dmitri Shubin
 Dmitriy Sergeyev
@@ -487,6 +491,7 @@ Florian Weimer
 Forrest Cahoon
 Francisco Moraes
 Francois Petitjean
+Frank Denis
 Frank Gevaerts
 Frank Hempel
 Frank Keeney
@@ -595,6 +600,7 @@ Howard Chu
 Hubert Kario
 Hzhijun
 Ian D Allen
+Ian Fette
 Ian Ford
 Ian Gulliver
 Ian Lynagh
@@ -618,6 +624,7 @@ Ishan SinghLevett
 Ivan Avdeev
 Ivo Bellin Salarin
 Jack Zhang
+Jackarain on github
 Jacky Lam
 Jacob Meuser
 Jacob Moshenko
@@ -640,6 +647,7 @@ James Slaughter
 Jamie Lokier
 Jamie Newton
 Jamie Wilkinson
+Jan Alexander Steffens
 Jan Ehrhardt
 Jan Koen Annot
 Jan Kunder
@@ -721,6 +729,7 @@ Johannes Schindelin
 John Bradshaw
 John Coffey
 John Crow
+John David Anglin
 John Dennis
 John Dunn
 John E. Malmberg
@@ -819,6 +828,7 @@ Kevin Ji
 Kevin Lussier
 Kevin Reed
 Kevin Roth
+Kevin Smith
 Kim Minjoong
 Kim Rinnewitz
 Kim Vandry
@@ -852,6 +862,7 @@ Lars Torben Wilson
 Lau Hang Kin
 Laurent Rabret
 Lauri Kasanen
+Lawrence Wagerfield
 Legoff Vincent
 Lehel Bernadt
 Leif W
@@ -903,6 +914,7 @@ Mamoru Tasaka
 Mandy Wu
 Manfred Schwarb
 Manuel Massing
+Marc Aldorasi
 Marc Boucher
 Marc Deslauriers
 Marc Doughty
@@ -1069,6 +1081,7 @@ Nico Baggus
 Nicolas Berloquin
 Nicolas Croiset
 Nicolas François
+Nicolas Morey-Chaisemartin
 Niels van Tongeren
 Nikita Schmidt
 Nikitinskit Dmitriy
@@ -1090,6 +1103,7 @@ Ola Mork
 Olaf Flebbe
 Olaf Stüben
 Oleg Pudeyev
+Oli Kingshott
 Oliver Gondža
 Oliver Graute
 Oliver Kuckertz
@@ -1137,6 +1151,7 @@ Paul Querna
 Paul Saab
 Pavel Cenek
 Pavel Orehov
+Pavel P
 Pavel Raiskup
 Pavel Rochnyak
 Pawel A. Gajda
@@ -1151,6 +1166,7 @@ Peter Gal
 Peter Heuchert
 Peter Hjalmarsson
 Peter Korsgaard
+Peter Lamare
 Peter Lamberg
 Peter Laser
 Peter O'Gorman
@@ -1303,6 +1319,7 @@ Ryan Winograd
 Ryuichi KAWAMATA
 Rémy Léone
 S. Moonesamy
+SBKarr on github
 Salah-Eddin Shaban
 Salvador Dávila
 Salvatore Sorrentino
@@ -1570,12 +1587,13 @@ afrind on github
 asavah on github
 baumanj on github
 bsammon on github
-canavan at github
-destman at github
+canavan on github
+destman on github
 dkjjr89 on github
 eXeC64 on github
-jonrumsey at github
+imilli on github
 jonrumsey on github
+joshhe on github
 jveazey on github
 ka7 on github
 kreshano on github
@@ -1589,17 +1607,17 @@ neex on github
 neheb on github
 nk
 nopjmp on github
-olesteban at github
+olesteban on github
 ovidiu-benea on github
 paulharris on github
 silveja1 on github
-stootill at github
+stootill on github
 swalkaus at yahoo.com
 tarek112 on github
 tommink[at]post.pl
 vanillajonathan on github
 wmsch on github
-wyattoday at github
+wyattoday on github
 zelinchen on github
 İsmail Dönmez
 Štefan Kremeň
diff --git a/docs/TODO b/docs/TODO
index dde2994b6..18896b070 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -27,7 +27,6 @@
  1.9 Cache negative name resolves
  1.10 auto-detect proxy
  1.11 minimize dependencies with dynamically loaded modules
- 1.12 have form functions use CURL handle argument
  1.14 Typesafe curl_easy_setopt()
  1.15 Monitor connections in the connection pool
  1.16 Try to URL encode given URL
@@ -67,9 +66,7 @@
  5.6 Refuse "downgrade" redirects
  5.7 Brotli compression
  5.8 QUIC
- 5.9 Improve formpost API
  5.10 Leave secure cookies alone
- 5.11 Chunked transfer multipart formpost
 
  6. TELNET
  6.1 ditch stdin
@@ -139,7 +136,6 @@
  18.2 glob posts
  18.3 prevent file overwriting
  18.4 simultaneous parallel transfers
- 18.5 provide formpost headers
  18.6 warning when setting an option
  18.8 offer color-coded HTTP header output
  18.9 Choose the name of file in braces for complex URLs
@@ -210,7 +206,7 @@
 1.5 get rid of PATH_MAX
 
  Having code use and rely on PATH_MAX is not nice:
- http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
+ https://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
 
  Currently the SSH based code uses it a bit, but to remove PATH_MAX from there
  we need libssh2 to properly tell us when we pass in a too small buffer and
@@ -276,18 +272,6 @@
  app/invoke/used protocols would be necessary to load.  See
  https://github.com/curl/curl/issues/349
 
-1.12 have form functions use CURL handle argument
-
- curl_formadd() and curl_formget() both currently have no CURL handle
- argument, but both can use a callback that is set in the easy handle, and
- thus curl_formget() with callback cannot function without first having
- curl_easy_perform() (or similar) called - which is hard to grasp and a design
- mistake.
-
- The curl_formadd() design can probably also be reconsidered to make it easier
- to use and less error-prone. Probably easiest by splitting it into several
- function calls.
-
 1.14 Typesafe curl_easy_setopt()
 
  One of the most common problems in libcurl using applications is the lack of
@@ -546,13 +530,6 @@ This is not detailed in any FTP specification.
  implemented. This, to allow other projects to benefit from the work and to
  thus broaden the interest and chance of others to participate.
 
-5.9 Improve formpost API
-
- Revamp the formpost API and making something that is easier to use and
- understand:
-
- https://github.com/curl/curl/wiki/formpost-API-redesigned
-
 5.10 Leave secure cookies alone
 
  Non-secure origins (HTTP sites) should not be allowed to set or modify
@@ -560,16 +537,6 @@ This is not detailed in any FTP specification.
 
  https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone-01
 
-5.11 Chunked transfer multipart formpost
-
- For a case where the file is being made during the upload is progressing
- (like passed on stdin to the curl tool), we cannot know the size before-hand
- and we rather not read the entire thing into memory before it can start the
- upload.
-
- https://github.com/curl/curl/issues/1139
-
-
 6. TELNET
 
 6.1 ditch stdin
@@ -911,20 +878,6 @@ that doesn't exist on the server, just like 
--ftp-create-dirs.
  Using the multi interface would also allow properly using parallel transfers
  with HTTP/2 and supporting HTTP/2 server push from the command line.
 
-18.5 provide formpost headers
-
- Extending the capabilities of the multipart formposting. How about leaving
- the ';type=foo' syntax as it is and adding an extra tag (headers) which
- works like this: curl -F "address@hidden;address@hidden" where
- fil1.hdr contains extra headers like
-
-   Content-Type: text/plain; charset=KOI8-R"
-   Content-Transfer-Encoding: base64
-   X-User-Comment: Please don't use browser specific HTML code
-
- which should overwrite the program reasonable defaults (plain/text,
- 8bit...)
-
 18.6 warning when setting an option
 
  Display a warning when libcurl returns an error when setting an option.
diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc
index 7eea5c6c5..e8f46410b 100644
--- a/docs/cmdline-opts/Makefile.inc
+++ b/docs/cmdline-opts/Makefile.inc
@@ -1,7 +1,8 @@
 # Shared between Makefile.am and CMakeLists.txt
 
 DPAGES = abstract-unix-socket.d anyauth.d append.d basic.d cacert.d capath.d 
cert.d \
-  cert-status.d cert-type.d ciphers.d compressed.d config.d             \
+  cert-status.d cert-type.d ciphers.d compressed.d compressed-ssh.d     \
+  config.d                                                              \
   connect-timeout.d connect-to.d continue-at.d cookie.d cookie-jar.d    \
   create-dirs.d crlf.d crlfile.d data-ascii.d data-binary.d data.d      \
   data-raw.d data-urlencode.d delegation.d digest.d disable.d           \
diff --git a/docs/cmdline-opts/cacert.d b/docs/cmdline-opts/cacert.d
index 04e113980..b2ecf9088 100644
--- a/docs/cmdline-opts/cacert.d
+++ b/docs/cmdline-opts/cacert.d
@@ -1,5 +1,5 @@
 Long: cacert
-Arg: <CA certificate>
+Arg: <file>
 Help: CA certificate to verify peer against
 Protocols: TLS
 ---
diff --git a/docs/cmdline-opts/compressed-ssh.d 
b/docs/cmdline-opts/compressed-ssh.d
new file mode 100644
index 000000000..583452ae4
--- /dev/null
+++ b/docs/cmdline-opts/compressed-ssh.d
@@ -0,0 +1,7 @@
+Long: compressed-ssh
+Help: Enable SSH compression
+Protocols: SCP SFTP
+Added: 7.56.0
+---
+Enables built-in SSH compression.
+This is a request, not an order; the server may or may not do it.
diff --git a/docs/cmdline-opts/form-string.d b/docs/cmdline-opts/form-string.d
index 80790553c..49d0d44ef 100644
--- a/docs/cmdline-opts/form-string.d
+++ b/docs/cmdline-opts/form-string.d
@@ -1,6 +1,6 @@
 Long: form-string
-Help: Specify HTTP multipart POST data
-Protocols: HTTP
+Help: Specify multipart MIME data
+Protocols: HTTP SMTP IMAP
 Arg: <name=string>
 See-also: form
 ---
diff --git a/docs/cmdline-opts/form.d b/docs/cmdline-opts/form.d
index 87a7d0766..232d30c07 100644
--- a/docs/cmdline-opts/form.d
+++ b/docs/cmdline-opts/form.d
@@ -1,21 +1,26 @@
 Long: form
 Short: F
 Arg: <name=content>
-Help: Specify HTTP multipart POST data
-Protocols: HTTP
+Help: Specify multipart MIME data
+Protocols: HTTP SMTP IMAP
 Mutexed: data head upload
 ---
-This lets curl emulate a filled-in form in which a user has pressed the submit
-button. This causes curl to POST data using the Content-Type
-multipart/form-data according to RFC 2388. This enables uploading of binary
+For HTTP protocol family, this lets curl emulate a filled-in form in which a
+user has pressed the submit button. This causes curl to POST data using the
+Content-Type multipart/form-data according to RFC 2388.
+
+For SMTP and IMAP protocols, this is the mean to compose a multipart mail
+message to transmit.
+
+This enables uploading of binary
 files etc. To force the 'content' part to be a file, prefix the file name with
 an @ sign. To just get the content part from a file, prefix the file name with
 the symbol <. The difference between @ and < is then that @ makes a file get
 attached in the post as a file upload, while the < makes a text field and just
 get the contents for that text field from a file.
 
-Example: to send an image to a server, where \&'profile' is the name of the
-form-field to which portrait.jpg will be the input:
+Example: to send an image to an HTTP server, where \&'profile' is the name of
+the form-field to which portrait.jpg will be the input:
 
  curl -F address@hidden https://example.com/upload.cgi
 
@@ -49,6 +54,67 @@ or
 Note that if a filename/path is quoted by double-quotes, any double-quote
 or backslash within the filename must be escaped by backslash.
 
+You can add custom headers to the field by setting headers=, like
+
+  curl -F "submit=OK;headers=\\"X-submit-type: OK\\"" example.com
+
+or
+
+  curl -F "submit=OK;address@hidden" example.com
+
+The headers= keyword may appear more that once and above notes about quoting
+apply. When headers are read from a file, Empty lines and lines starting
+with '#' are comments and ignored; each header can be folded by splitting
+between two words and starting the continuation line with a space; embedded
+carriage-returns and trailing spaces are stripped.
+Here is an example of a header file contents:
+
+  # This file contain two headers.
+.br
+  X-header-1: this is a header
+
+  # The following header is folded.
+.br
+  X-header-2: this is
+.br
+   another header
+
+
+To support sending multipart mail messages, the syntax is extended as follows:
+.br
+- name can be omitted: the equal sign is the first character of the argument,
+.br
+- if data starts with '(', this signals to start a new multipart: it can be
+followed by a content type specification.
+.br
+- a multipart can be terminated with a '=)' argument.
+
+Example: the following command sends an SMTP mime e-mail consisting in an
+inline part in two alternative formats: plain text and HTML. It attaches a
+text file:
+
+ curl -F '=(;type=multipart/alternative' \\
+.br
+         -F '=plain text message' \\
+.br
+         -F '= <body>HTML message</body>;type=text/html' \\
+.br
+      -F '=)' -F 'address@hidden' ...  smtp://example.com
+
+Data can be encoded for transfer using encoder=. Available encodings are
+\fIbinary\fP and \fI8bit\fP that do nothing else than adding the corresponding
+Content-Transfer-Encoding header, \fI7bit\fP that only rejects 8-bit characters
+with a transfer error, \fIquoted-printable\fP and \fIbase64\fP that encodes
+data according to the corresponding schemes, limiting lines length to
+76 characters.
+
+Example: send multipart mail with a quoted-printable text message and a
+base64 attached file:
+
+ curl -F '=text message;encoder=quoted-printable' \\
+.br
+      -F 'address@hidden;encoder=base64' ... smtp://example.com
+
 See further examples and details in the MANUAL.
 
 This option can be used multiple times.
diff --git a/docs/cmdline-opts/gen.pl b/docs/cmdline-opts/gen.pl
index 6f67be6c1..642170988 100755
--- a/docs/cmdline-opts/gen.pl
+++ b/docs/cmdline-opts/gen.pl
@@ -179,7 +179,7 @@ sub single {
     }
 
     if($standalone) {
-        print ".TH gnurl 1 \"30 Nov 2016\" \"gnurl 7.52.0\" \"curl manual\"\n";
+        print ".TH gnurl 1 \"30 Nov 2016\" \"gnurl 7.52.0\" \"gnurl 
manual\"\n";
         print ".SH OPTION\n";
         print "gnurl $opt\n";
     }
diff --git a/docs/cmdline-opts/request-target.d 
b/docs/cmdline-opts/request-target.d
index 630f8b3b4..b46b4af02 100644
--- a/docs/cmdline-opts/request-target.d
+++ b/docs/cmdline-opts/request-target.d
@@ -1,6 +1,7 @@
 Long: request-target
 Help: Specify the target for this request
 Protocols: HTTP
+Added: 7.55.0
 ---
 Tells curl to use an alternative "target" (path) instead of using the path as
 provided in the URL. Particularly useful when wanting to issue HTTP requests
diff --git a/docs/examples/.gitignore b/docs/examples/.gitignore
index aece671c6..f22c7b02f 100644
--- a/docs/examples/.gitignore
+++ b/docs/examples/.gitignore
@@ -70,6 +70,7 @@ smtp-multi
 smtp-ssl
 smtp-tls
 smtp-vrfy
+sslbackend
 url2file
 usercertinmem
 xmlstream
diff --git a/docs/examples/10-at-a-time.c b/docs/examples/10-at-a-time.c
index b0c65b77e..1ffaec301 100644
--- a/docs/examples/10-at-a-time.c
+++ b/docs/examples/10-at-a-time.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -114,7 +114,7 @@ int main(void)
   CURLM *cm;
   CURLMsg *msg;
   long L;
-  unsigned int C=0;
+  unsigned int C = 0;
   int M, Q, U = -1;
   fd_set R, W, E;
   struct timeval T;
@@ -162,9 +162,9 @@ int main(void)
         T.tv_sec = L/1000;
         T.tv_usec = (L%1000)*1000;
 
-        if(0 > select(M+1, &R, &W, &E, &T)) {
+        if(0 > select(M + 1, &R, &W, &E, &T)) {
           fprintf(stderr, "E: select(%i,,,,%li): %i: %s\n",
-              M+1, L, errno, strerror(errno));
+              M + 1, L, errno, strerror(errno));
           return EXIT_FAILURE;
         }
       }
diff --git a/docs/examples/Makefile.inc b/docs/examples/Makefile.inc
index b92ad6bd5..71b804c75 100644
--- a/docs/examples/Makefile.inc
+++ b/docs/examples/Makefile.inc
@@ -26,18 +26,19 @@ check_PROGRAMS = 10-at-a-time anyauthput cookie_interface 
debug fileupload \
   https multi-app multi-debugcallback multi-double multi-post multi-single \
   persistant post-callback postit2 sepheaders simple simplepost simplessl  \
   sendrecv httpcustomheader certinfo chkspeed ftpgetinfo ftp-wildcard      \
-  smtp-mail smtp-multi smtp-ssl smtp-tls smtp-vrfy smtp-expn rtsp          \
-  externalsocket resolve progressfunc pop3-retr pop3-list pop3-uidl        \
+  smtp-mail smtp-mime smtp-multi smtp-ssl smtp-tls smtp-vrfy smtp-expn     \
+  rtsp externalsocket resolve progressfunc pop3-retr pop3-list pop3-uidl   \
   pop3-dele pop3-top pop3-stat pop3-noop pop3-ssl pop3-tls pop3-multi      \
   imap-list imap-lsub imap-fetch imap-store imap-append imap-examine       \
   imap-search imap-create imap-delete imap-copy imap-noop imap-ssl         \
   imap-tls imap-multi url2file sftpget ftpsget postinmemory http2-download \
-  http2-upload http2-serverpush getredirect ftpuploadfrommem
+  http2-upload http2-serverpush getredirect ftpuploadfrommem               \
+  ftpuploadresume sslbackend postit2-formadd multi-formadd
 
 # These examples require external dependencies that may not be commonly
 # available on POSIX systems, so don't bother attempting to compile them here.
 COMPLICATED_EXAMPLES = curlgtk.c curlx.c htmltitle.cpp cacertinmem.c       \
-  ftpuploadresume.c ghiper.c hiperfifo.c htmltidy.c multithread.c          \
+  ghiper.c hiperfifo.c htmltidy.c multithread.c          \
   opensslthreadlock.c sampleconv.c synctime.c threaded-ssl.c evhiperfifo.c \
   smooth-gtk-thread.c version-check.pl href_extractor.c asiohiper.cpp      \
   multi-uv.c xmlstream.c usercertinmem.c sessioninfo.c
diff --git a/docs/examples/anyauthput.c b/docs/examples/anyauthput.c
index 9881d1a6c..bdbc0cb25 100644
--- a/docs/examples/anyauthput.c
+++ b/docs/examples/anyauthput.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +106,7 @@ int main(int argc, char **argv)
   if(argc < 3)
     return 1;
 
-  file= argv[1];
+  file = argv[1];
   url = argv[2];
 
   /* get the file size of the local file */
diff --git a/docs/examples/cacertinmem.c b/docs/examples/cacertinmem.c
index 2a06e51e4..4bbec4663 100644
--- a/docs/examples/cacertinmem.c
+++ b/docs/examples/cacertinmem.c
@@ -37,7 +37,7 @@ size_t writefunction(void *ptr, size_t size, size_t nmemb, 
void *stream)
 static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
 {
   X509_STORE *store;
-  X509 *cert=NULL;
+  X509 *cert = NULL;
   BIO *bio;
   char *mypem = /* www.cacert.org */
     "-----BEGIN CERTIFICATE-----\n"\
@@ -82,7 +82,7 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, 
void *parm)
     "omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD\n"\
     "-----END CERTIFICATE-----\n";
   /* get a BIO */
-  bio=BIO_new_mem_buf(mypem, -1);
+  bio = BIO_new_mem_buf(mypem, -1);
   /* use it to read the PEM formatted certificate from memory into an X509
    * structure that SSL can use
    */
@@ -91,10 +91,10 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, 
void *parm)
     printf("PEM_read_bio_X509 failed...\n");
 
   /* get a pointer to the X509 certificate store (which may be empty!) */
-  store=SSL_CTX_get_cert_store((SSL_CTX *)sslctx);
+  store = SSL_CTX_get_cert_store((SSL_CTX *)sslctx);
 
   /* add our certificate to this store */
-  if(X509_STORE_add_cert(store, cert)==0)
+  if(X509_STORE_add_cert(store, cert) == 0)
     printf("error adding certificate\n");
 
   /* decrease reference counts */
@@ -110,24 +110,24 @@ int main(void)
   CURL *ch;
   CURLcode rv;
 
-  rv=curl_global_init(CURL_GLOBAL_ALL);
-  ch=curl_easy_init();
-  rv=curl_easy_setopt(ch, CURLOPT_VERBOSE, 0L);
-  rv=curl_easy_setopt(ch, CURLOPT_HEADER, 0L);
-  rv=curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1L);
-  rv=curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
-  rv=curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, *writefunction);
-  rv=curl_easy_setopt(ch, CURLOPT_WRITEDATA, stdout);
-  rv=curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, *writefunction);
-  rv=curl_easy_setopt(ch, CURLOPT_HEADERDATA, stderr);
-  rv=curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
-  rv=curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 1L);
-  rv=curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/";);
+  rv = curl_global_init(CURL_GLOBAL_ALL);
+  ch = curl_easy_init();
+  rv = curl_easy_setopt(ch, CURLOPT_VERBOSE, 0L);
+  rv = curl_easy_setopt(ch, CURLOPT_HEADER, 0L);
+  rv = curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1L);
+  rv = curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L);
+  rv = curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, *writefunction);
+  rv = curl_easy_setopt(ch, CURLOPT_WRITEDATA, stdout);
+  rv = curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, *writefunction);
+  rv = curl_easy_setopt(ch, CURLOPT_HEADERDATA, stderr);
+  rv = curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM");
+  rv = curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 1L);
+  rv = curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/";);
 
   /* first try: retrieve page without cacerts' certificate -> will fail
    */
-  rv=curl_easy_perform(ch);
-  if(rv==CURLE_OK)
+  rv = curl_easy_perform(ch);
+  if(rv == CURLE_OK)
     printf("*** transfer succeeded ***\n");
   else
     printf("*** transfer failed ***\n");
@@ -136,9 +136,9 @@ int main(void)
    * load the certificate by installing a function doing the necessary
    * "modifications" to the SSL CONTEXT just before link init
    */
-  rv=curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
-  rv=curl_easy_perform(ch);
-  if(rv==CURLE_OK)
+  rv = curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
+  rv = curl_easy_perform(ch);
+  if(rv == CURLE_OK)
     printf("*** transfer succeeded ***\n");
   else
     printf("*** transfer failed ***\n");
diff --git a/docs/examples/chkspeed.c b/docs/examples/chkspeed.c
index 17283bb7d..5c032db8b 100644
--- a/docs/examples/chkspeed.c
+++ b/docs/examples/chkspeed.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -93,7 +93,7 @@ int main(int argc, char *argv[])
           prttime = 1;
         }
         else if(strncasecmp(*argv, "-M=", 3) == 0) {
-          long m = strtol((*argv)+3, NULL, 10);
+          long m = strtol((*argv) + 3, NULL, 10);
           switch(m) {
           case 1:
             url = URL_1M;
diff --git a/docs/examples/curlx.c b/docs/examples/curlx.c
index 5e3a00be5..24579fa2a 100644
--- a/docs/examples/curlx.c
+++ b/docs/examples/curlx.c
@@ -195,7 +195,8 @@ static int ssl_app_verify_callback(X509_STORE_CTX *ctx, 
void *arg)
   if(p->verbose > 2)
     BIO_printf(p->errorbio, "entering ssl_app_verify_callback\n");
 
-  if((ok= X509_verify_cert(ctx)) && ctx->cert) {
+  ok = X509_verify_cert(ctx);
+  if(ok && ctx->cert) {
     unsigned char *accessinfo;
     if(p->verbose > 1)
       X509_print_ex(p->errorbio, ctx->cert, 0, 0);
@@ -268,16 +269,16 @@ static CURLcode sslctxfun(CURL *curl, void *sslctx, void 
*parm)
 
 int main(int argc, char **argv)
 {
-  BIO* in=NULL;
-  BIO* out=NULL;
+  BIO* in = NULL;
+  BIO* out = NULL;
 
   char *outfile = NULL;
   char *infile = NULL;
 
-  int tabLength=100;
+  int tabLength = 100;
   char *binaryptr;
   char *mimetype;
-  char *mimetypeaccept=NULL;
+  char *mimetypeaccept = NULL;
   char *contenttype;
   const char **pp;
   unsigned char *hostporturl = NULL;
@@ -288,8 +289,8 @@ int main(int argc, char **argv)
   char *response;
 
   CURLcode res;
-  struct curl_slist *headers=NULL;
-  int badarg=0;
+  struct curl_slist *headers = NULL;
+  int badarg = 0;
 
   binaryptr = malloc(tabLength);
 
@@ -307,75 +308,75 @@ int main(int argc, char **argv)
   while(*args && *args[0] == '-') {
     if(!strcmp (*args, "-in")) {
       if(args[1]) {
-        infile=*(++args);
+        infile = *(++args);
       }
       else
-        badarg=1;
+        badarg = 1;
     }
     else if(!strcmp (*args, "-out")) {
       if(args[1]) {
-        outfile=*(++args);
+        outfile = *(++args);
       }
       else
-        badarg=1;
+        badarg = 1;
     }
     else if(!strcmp (*args, "-p12")) {
       if(args[1]) {
         p.p12file = *(++args);
       }
       else
-        badarg=1;
+        badarg = 1;
     }
     else if(strcmp(*args, "-envpass") == 0) {
       if(args[1]) {
         p.pst = getenv(*(++args));
       }
       else
-        badarg=1;
+        badarg = 1;
     }
     else if(strcmp(*args, "-connect") == 0) {
       if(args[1]) {
         hostporturl = *(++args);
       }
       else
-        badarg=1;
+        badarg = 1;
     }
     else if(strcmp(*args, "-mimetype") == 0) {
       if(args[1]) {
         mimetype = *(++args);
       }
       else
-        badarg=1;
+        badarg = 1;
     }
     else if(strcmp(*args, "-acceptmime") == 0) {
       if(args[1]) {
         mimetypeaccept = *(++args);
       }
       else
-        badarg=1;
+        badarg = 1;
     }
     else if(strcmp(*args, "-accesstype") == 0) {
       if(args[1]) {
         p.accesstype = OBJ_obj2nid(OBJ_txt2obj(*++args, 0));
         if(p.accesstype == 0)
-          badarg=1;
+          badarg = 1;
       }
       else
-        badarg=1;
+        badarg = 1;
     }
     else if(strcmp(*args, "-verbose") == 0) {
       p.verbose++;
     }
     else
-      badarg=1;
+      badarg = 1;
     args++;
   }
 
-  if(mimetype==NULL || mimetypeaccept == NULL)
+  if(mimetype == NULL || mimetypeaccept == NULL)
     badarg = 1;
 
   if(badarg) {
-    for(pp=curlx_usage; (*pp != NULL); pp++)
+    for(pp = curlx_usage; (*pp != NULL); pp++)
       BIO_printf(p.errorbio, "%s\n", *pp);
     BIO_printf(p.errorbio, "\n");
     goto err;
@@ -383,7 +384,8 @@ int main(int argc, char **argv)
 
   /* set input */
 
-  if((in=BIO_new(BIO_s_file())) == NULL) {
+  in = BIO_new(BIO_s_file());
+  if(in == NULL) {
     BIO_printf(p.errorbio, "Error setting input bio\n");
     goto err;
   }
@@ -397,7 +399,8 @@ int main(int argc, char **argv)
 
   /* set output  */
 
-  if((out=BIO_new(BIO_s_file())) == NULL) {
+  out = BIO_new(BIO_s_file());
+  if(out == NULL) {
     BIO_printf(p.errorbio, "Error setting output bio.\n");
     goto err;
   }
@@ -429,7 +432,7 @@ int main(int argc, char **argv)
     goto err;
   }
 
-  p.ca= NULL;
+  p.ca = NULL;
   if(!(PKCS12_parse (p.p12, p.pst, &(p.pkey), &(p.usercert), &(p.ca) ) )) {
     BIO_printf(p.errorbio, "Invalid P12 structure in %s\n", p.p12file);
     goto err;
@@ -454,10 +457,10 @@ int main(int argc, char **argv)
                                   given access type */
     serverurl = my_get_ext(p.usercert, p.accesstype, NID_info_access);
     if(!serverurl) {
-      int j=0;
+      int j = 0;
       BIO_printf(p.errorbio, "no service URL in user cert "
                  "cherching in others certificats\n");
-      for(j=0; j<sk_X509_num(p.ca); j++) {
+      for(j = 0; j<sk_X509_num(p.ca); j++) {
         serverurl = my_get_ext(sk_X509_value(p.ca, j), p.accesstype,
                                NID_info_access);
         if(serverurl)
@@ -489,8 +492,8 @@ int main(int argc, char **argv)
 
   /* pass our list of custom made headers */
 
-  contenttype = malloc(15+strlen(mimetype));
-  snprintf(contenttype, 15+strlen(mimetype), "Content-type: %s", mimetype);
+  contenttype = malloc(15 + strlen(mimetype));
+  snprintf(contenttype, 15 + strlen(mimetype), "Content-type: %s", mimetype);
   headers = curl_slist_append(headers, contenttype);
   curl_easy_setopt(p.curl, CURLOPT_HTTPHEADER, headers);
 
@@ -512,12 +515,12 @@ int main(int argc, char **argv)
   curl_easy_setopt(p.curl, CURLOPT_SSL_CTX_DATA, &p);
 
   {
-    int lu; int i=0;
+    int lu; int i = 0;
     while((lu = BIO_read(in, &binaryptr[i], tabLength-i)) >0) {
-      i+=lu;
-      if(i== tabLength) {
-        tabLength+=100;
-        binaryptr=realloc(binaryptr, tabLength); /* should be more careful */
+      i += lu;
+      if(i == tabLength) {
+        tabLength += 100;
+        binaryptr = realloc(binaryptr, tabLength); /* should be more careful */
       }
     }
     tabLength = i;
@@ -533,7 +536,7 @@ int main(int argc, char **argv)
   BIO_printf(p.errorbio, "%d %s %d\n", __LINE__, "curl_easy_perform",
              res = curl_easy_perform(p.curl));
   {
-    int result =curl_easy_getinfo(p.curl, CURLINFO_CONTENT_TYPE, &response);
+    int result = curl_easy_getinfo(p.curl, CURLINFO_CONTENT_TYPE, &response);
     if(mimetypeaccept && p.verbose)
       if(!strcmp(mimetypeaccept, response))
         BIO_printf(p.errorbio, "the response has a correct mimetype : %s\n",
diff --git a/docs/examples/debug.c b/docs/examples/debug.c
index 8a490a281..8f77e1243 100644
--- a/docs/examples/debug.c
+++ b/docs/examples/debug.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 @@ void dump(const char *text,
   size_t i;
   size_t c;
 
-  unsigned int width=0x10;
+  unsigned int width = 0x10;
 
   if(nohex)
     /* without the hex output, we can fit more on screen */
@@ -47,30 +47,32 @@ void dump(const char *text,
   fprintf(stream, "%s, %10.10ld bytes (0x%8.8lx)\n",
           text, (long)size, (long)size);
 
-  for(i=0; i<size; i+= width) {
+  for(i = 0; i<size; i += width) {
 
     fprintf(stream, "%4.4lx: ", (long)i);
 
     if(!nohex) {
       /* hex not disabled, show it */
       for(c = 0; c < width; c++)
-        if(i+c < size)
-          fprintf(stream, "%02x ", ptr[i+c]);
+        if(i + c < size)
+          fprintf(stream, "%02x ", ptr[i + c]);
         else
           fputs("   ", stream);
     }
 
-    for(c = 0; (c < width) && (i+c < size); c++) {
+    for(c = 0; (c < width) && (i + c < size); c++) {
       /* check for 0D0A; if found, skip past and start a new line of output */
-      if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
-        i+=(c+2-width);
+      if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+         ptr[i + c + 1] == 0x0A) {
+        i += (c + 2 - width);
         break;
       }
       fprintf(stream, "%c",
-              (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
+              (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)?ptr[i + c]:'.');
       /* check again for 0D0A, to avoid an extra \n if it's at width */
-      if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
-        i+=(c+3-width);
+      if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+         ptr[i + c + 2] == 0x0A) {
+        i += (c + 3 - width);
         break;
       }
     }
diff --git a/docs/examples/evhiperfifo.c b/docs/examples/evhiperfifo.c
index a41346e31..c41c21f90 100644
--- a/docs/examples/evhiperfifo.c
+++ b/docs/examples/evhiperfifo.c
@@ -136,28 +136,28 @@ static void mcode_or_die(const char *where, CURLMcode 
code)
     const char *s;
     switch(code) {
     case CURLM_BAD_HANDLE:
-      s="CURLM_BAD_HANDLE";
+      s = "CURLM_BAD_HANDLE";
       break;
     case CURLM_BAD_EASY_HANDLE:
-      s="CURLM_BAD_EASY_HANDLE";
+      s = "CURLM_BAD_EASY_HANDLE";
       break;
     case CURLM_OUT_OF_MEMORY:
-      s="CURLM_OUT_OF_MEMORY";
+      s = "CURLM_OUT_OF_MEMORY";
       break;
     case CURLM_INTERNAL_ERROR:
-      s="CURLM_INTERNAL_ERROR";
+      s = "CURLM_INTERNAL_ERROR";
       break;
     case CURLM_UNKNOWN_OPTION:
-      s="CURLM_UNKNOWN_OPTION";
+      s = "CURLM_UNKNOWN_OPTION";
       break;
     case CURLM_LAST:
-      s="CURLM_LAST";
+      s = "CURLM_LAST";
       break;
     default:
-      s="CURLM_unknown";
+      s = "CURLM_unknown";
       break;
     case CURLM_BAD_SOCKET:
-      s="CURLM_BAD_SOCKET";
+      s = "CURLM_BAD_SOCKET";
       fprintf(MSG_OUT, "ERROR: %s returns %s\n", where, s);
       /* ignore this error */
       return;
@@ -257,7 +257,7 @@ static void setsock(SockInfo *f, curl_socket_t s, CURL *e, 
int act,
     ev_io_stop(g->loop, &f->ev);
   ev_io_init(&f->ev, event_cb, f->sockfd, kind);
   f->ev.data = g;
-  f->evset=1;
+  f->evset = 1;
   ev_io_start(g->loop, &f->ev);
 }
 
@@ -371,13 +371,13 @@ static void new_conn(char *url, GlobalInfo *g)
 static void fifo_cb(EV_P_ struct ev_io *w, int revents)
 {
   char s[1024];
-  long int rv=0;
-  int n=0;
+  long int rv = 0;
+  int n = 0;
   GlobalInfo *g = (GlobalInfo *)w->data;
 
   do {
     s[0]='\0';
-    rv=fscanf(g->input, "%1023s%n", s, &n);
+    rv = fscanf(g->input, "%1023s%n", s, &n);
     s[n]='\0';
     if(n && s[0]) {
       new_conn(s, g);  /* if we read a URL, go get it! */
diff --git a/docs/examples/fopen.c b/docs/examples/fopen.c
index d559658a7..590f41a85 100644
--- a/docs/examples/fopen.c
+++ b/docs/examples/fopen.c
@@ -13,7 +13,7 @@
  * See the main() function at the bottom that shows an app that retrieves from
  * a specified url using fgets() and fread() and saves as two output files.
  *
- * Copyright (c) 2003 Simtec Electronics
+ * Copyright (c) 2003, 2017 Simtec Electronics
  *
  * Re-implemented by Vincent Sanders <address@hidden> with extensive
  * reference to original curl example code
@@ -58,9 +58,9 @@
 #include <gnurl/curl.h>
 
 enum fcurl_type_e {
-  CFTYPE_NONE=0,
-  CFTYPE_FILE=1,
-  CFTYPE_CURL=2
+  CFTYPE_NONE = 0,
+  CFTYPE_FILE = 1,
+  CFTYPE_CURL = 2
 };
 
 struct fcurl_data
@@ -102,19 +102,19 @@ static size_t write_callback(char *buffer,
   URL_FILE *url = (URL_FILE *)userp;
   size *= nitems;
 
-  rembuff=url->buffer_len - url->buffer_pos; /* remaining space in buffer */
+  rembuff = url->buffer_len - url->buffer_pos; /* remaining space in buffer */
 
   if(size > rembuff) {
     /* not enough space in buffer */
-    newbuff=realloc(url->buffer, url->buffer_len + (size - rembuff));
-    if(newbuff==NULL) {
+    newbuff = realloc(url->buffer, url->buffer_len + (size - rembuff));
+    if(newbuff == NULL) {
       fprintf(stderr, "callback buffer grow failed\n");
-      size=rembuff;
+      size = rembuff;
     }
     else {
       /* realloc succeeded increase buffer size*/
-      url->buffer_len+=size - rembuff;
-      url->buffer=newbuff;
+      url->buffer_len += size - rembuff;
+      url->buffer = newbuff;
     }
   }
 
@@ -189,7 +189,7 @@ static int fill_buffer(URL_FILE *file, size_t want)
     else {
       /* Note that on some platforms 'timeout' may be modified by select().
          If you need access to the original value save a copy beforehand. */
-      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+      rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
     }
 
     switch(rc) {
@@ -211,12 +211,12 @@ static int fill_buffer(URL_FILE *file, size_t want)
 static int use_buffer(URL_FILE *file, size_t want)
 {
   /* sort out buffer */
-  if((file->buffer_pos - want) <=0) {
+  if((file->buffer_pos - want) <= 0) {
     /* ditch buffer - write will recreate */
     free(file->buffer);
-    file->buffer=NULL;
-    file->buffer_pos=0;
-    file->buffer_len=0;
+    file->buffer = NULL;
+    file->buffer_pos = 0;
+    file->buffer_len = 0;
   }
   else {
     /* move rest down make it available for later */
@@ -243,7 +243,8 @@ URL_FILE *url_fopen(const char *url, const char *operation)
 
   memset(file, 0, sizeof(URL_FILE));
 
-  if((file->handle.file=fopen(url, operation)))
+  file->handle.file = fopen(url, operation);
+  if(file->handle.file)
     file->type = CFTYPE_FILE; /* marked as URL */
 
   else {
@@ -282,11 +283,11 @@ URL_FILE *url_fopen(const char *url, const char 
*operation)
 
 int url_fclose(URL_FILE *file)
 {
-  int ret=0;/* default is good return */
+  int ret = 0;/* default is good return */
 
   switch(file->type) {
   case CFTYPE_FILE:
-    ret=fclose(file->handle.file); /* passthrough */
+    ret = fclose(file->handle.file); /* passthrough */
     break;
 
   case CFTYPE_CURL:
@@ -298,8 +299,8 @@ int url_fclose(URL_FILE *file)
     break;
 
   default: /* unknown or supported type - oh dear */
-    ret=EOF;
-    errno=EBADF;
+    ret = EOF;
+    errno = EBADF;
     break;
   }
 
@@ -311,11 +312,11 @@ int url_fclose(URL_FILE *file)
 
 int url_feof(URL_FILE *file)
 {
-  int ret=0;
+  int ret = 0;
 
   switch(file->type) {
   case CFTYPE_FILE:
-    ret=feof(file->handle.file);
+    ret = feof(file->handle.file);
     break;
 
   case CFTYPE_CURL:
@@ -324,8 +325,8 @@ int url_feof(URL_FILE *file)
     break;
 
   default: /* unknown or supported type - oh dear */
-    ret=-1;
-    errno=EBADF;
+    ret = -1;
+    errno = EBADF;
     break;
   }
   return ret;
@@ -337,7 +338,7 @@ size_t url_fread(void *ptr, size_t size, size_t nmemb, 
URL_FILE *file)
 
   switch(file->type) {
   case CFTYPE_FILE:
-    want=fread(ptr, size, nmemb, file->handle.file);
+    want = fread(ptr, size, nmemb, file->handle.file);
     break;
 
   case CFTYPE_CURL:
@@ -363,8 +364,8 @@ size_t url_fread(void *ptr, size_t size, size_t nmemb, 
URL_FILE *file)
     break;
 
   default: /* unknown or supported type - oh dear */
-    want=0;
-    errno=EBADF;
+    want = 0;
+    errno = EBADF;
     break;
 
   }
@@ -395,24 +396,24 @@ char *url_fgets(char *ptr, size_t size, URL_FILE *file)
 
     /*buffer contains data */
     /* look for newline or eof */
-    for(loop=0;loop < want;loop++) {
+    for(loop = 0; loop < want; loop++) {
       if(file->buffer[loop] == '\n') {
-        want=loop+1;/* include newline */
+        want = loop + 1;/* include newline */
         break;
       }
     }
 
     /* xfer data to caller */
     memcpy(ptr, file->buffer, want);
-    ptr[want]=0;/* always null terminate */
+    ptr[want] = 0;/* always null terminate */
 
     use_buffer(file, want);
 
     break;
 
   default: /* unknown or supported type - oh dear */
-    ptr=NULL;
-    errno=EBADF;
+    ptr = NULL;
+    errno = EBADF;
     break;
   }
 
@@ -435,9 +436,9 @@ void url_rewind(URL_FILE *file)
 
     /* ditch buffer - write will recreate - resets stream pos*/
     free(file->buffer);
-    file->buffer=NULL;
-    file->buffer_pos=0;
-    file->buffer_len=0;
+    file->buffer = NULL;
+    file->buffer_pos = 0;
+    file->buffer_len = 0;
 
     break;
 
@@ -463,12 +464,12 @@ int main(int argc, char *argv[])
   const char *url;
 
   if(argc < 2)
-    url="http://192.168.7.3/testfile";/* default to testurl */
+    url = "http://192.168.7.3/testfile";/* default to testurl */
   else
-    url=argv[1];/* use passed url */
+    url = argv[1];/* use passed url */
 
   /* copy from url line by line with fgets */
-  outf=fopen(FGETSFILE, "wb+");
+  outf = fopen(FGETSFILE, "wb+");
   if(!outf) {
     perror("couldn't open fgets output file\n");
     return 1;
@@ -492,7 +493,7 @@ int main(int argc, char *argv[])
 
 
   /* Copy from url with fread */
-  outf=fopen(FREADFILE, "wb+");
+  outf = fopen(FREADFILE, "wb+");
   if(!outf) {
     perror("couldn't open fread output file\n");
     return 1;
@@ -516,7 +517,7 @@ int main(int argc, char *argv[])
 
 
   /* Test rewind */
-  outf=fopen(REWINDFILE, "wb+");
+  outf = fopen(REWINDFILE, "wb+");
   if(!outf) {
     perror("couldn't open fread output file\n");
     return 1;
diff --git a/docs/examples/ftpget.c b/docs/examples/ftpget.c
index bfb6acb05..f9d78ae7f 100644
--- a/docs/examples/ftpget.c
+++ b/docs/examples/ftpget.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,10 +35,10 @@ struct FtpFile {
 
 static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
 {
-  struct FtpFile *out=(struct FtpFile *)stream;
+  struct FtpFile *out = (struct FtpFile *)stream;
   if(out && !out->stream) {
     /* open file for writing */
-    out->stream=fopen(out->filename, "wb");
+    out->stream = fopen(out->filename, "wb");
     if(!out->stream)
       return -1; /* failure, can't open file to write */
   }
@@ -50,7 +50,7 @@ int main(void)
 {
   CURL *curl;
   CURLcode res;
-  struct FtpFile ftpfile={
+  struct FtpFile ftpfile = {
     "curl.tar.gz", /* name to store the file as if successful */
     NULL
   };
diff --git a/docs/examples/ftpsget.c b/docs/examples/ftpsget.c
index 021cdae13..348747ab4 100644
--- a/docs/examples/ftpsget.c
+++ b/docs/examples/ftpsget.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2015, 2017, 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,10 +37,10 @@ struct FtpFile {
 static size_t my_fwrite(void *buffer, size_t size, size_t nmemb,
                         void *stream)
 {
-  struct FtpFile *out=(struct FtpFile *)stream;
+  struct FtpFile *out = (struct FtpFile *)stream;
   if(out && !out->stream) {
     /* open file for writing */
-    out->stream=fopen(out->filename, "wb");
+    out->stream = fopen(out->filename, "wb");
     if(!out->stream)
       return -1; /* failure, can't open file to write */
   }
@@ -52,7 +52,7 @@ int main(void)
 {
   CURL *curl;
   CURLcode res;
-  struct FtpFile ftpfile={
+  struct FtpFile ftpfile = {
     "yourfile.bin", /* name to store the file as if successful */
     NULL
   };
diff --git a/docs/examples/ftpupload.c b/docs/examples/ftpupload.c
index 3692449f1..ec91c818b 100644
--- a/docs/examples/ftpupload.c
+++ b/docs/examples/ftpupload.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 @@ int main(void)
   struct stat file_info;
   curl_off_t fsize;
 
-  struct curl_slist *headerlist=NULL;
+  struct curl_slist *headerlist = NULL;
   static const char buf_1 [] = "RNFR " UPLOAD_FILE_AS;
   static const char buf_2 [] = "RNTO " RENAME_FILE_TO;
 
diff --git a/docs/examples/ftpuploadresume.c b/docs/examples/ftpuploadresume.c
index 4b6d6677e..c966c76e9 100644
--- a/docs/examples/ftpuploadresume.c
+++ b/docs/examples/ftpuploadresume.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,44 +26,32 @@
 
 #include <stdlib.h>
 #include <stdio.h>
-
 #include <gnurl/curl.h>
 
-#if defined(_MSC_VER) && (_MSC_VER < 1300)
-#  error _snscanf requires MSVC 7.0 or later.
-#endif
-
-/* The MinGW headers are missing a few Win32 function definitions,
-   you shouldn't need this if you use VC++ */
-#if defined(__MINGW32__) && !defined(__MINGW64__)
-int __cdecl _snscanf(const char *input, size_t length,
-                     const char *format, ...);
-#endif
-
-
 /* parse headers for Content-Length */
-size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void *stream)
+static size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb,
+                                   void *stream)
 {
   int r;
   long len = 0;
 
-  /* _snscanf() is Win32 specific */
-  r = _snscanf(ptr, size * nmemb, "Content-Length: %ld\n", &len);
-
-  if(r) /* Microsoft: we don't read the specs */
+  r = sscanf(ptr, "Content-Length: %ld\n", &len);
+  if(r)
     *((long *) stream) = len;
 
   return size * nmemb;
 }
 
 /* discard downloaded data */
-size_t discardfunc(void *ptr, size_t size, size_t nmemb, void *stream)
+static size_t discardfunc(void *ptr, size_t size, size_t nmemb, void *stream)
 {
+  (void)ptr;
+  (void)stream;
   return size * nmemb;
 }
 
 /* read data to upload */
-size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
+static size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream)
 {
   FILE *f = stream;
   size_t n;
@@ -77,8 +65,8 @@ size_t readfunc(void *ptr, size_t size, size_t nmemb, void 
*stream)
 }
 
 
-int upload(CURL *curlhandle, const char *remotepath, const char *localpath,
-           long timeout, long tries)
+static int upload(CURL *curlhandle, const char *remotepath,
+                  const char *localpath, long timeout, long tries)
 {
   FILE *f;
   long uploaded_len = 0;
@@ -156,7 +144,7 @@ int upload(CURL *curlhandle, const char *remotepath, const 
char *localpath,
   }
 }
 
-int main(int c, char **argv)
+int main(void)
 {
   CURL *curlhandle = NULL;
 
diff --git a/docs/examples/ghiper.c b/docs/examples/ghiper.c
index 6c5c5e45e..c76d31d0e 100644
--- a/docs/examples/ghiper.c
+++ b/docs/examples/ghiper.c
@@ -99,14 +99,14 @@ static void mcode_or_die(const char *where, CURLMcode code)
   if(CURLM_OK != code) {
     const char *s;
     switch(code) {
-    case     CURLM_BAD_HANDLE:         s="CURLM_BAD_HANDLE";         break;
-    case     CURLM_BAD_EASY_HANDLE:    s="CURLM_BAD_EASY_HANDLE";    break;
-    case     CURLM_OUT_OF_MEMORY:      s="CURLM_OUT_OF_MEMORY";      break;
-    case     CURLM_INTERNAL_ERROR:     s="CURLM_INTERNAL_ERROR";     break;
-    case     CURLM_BAD_SOCKET:         s="CURLM_BAD_SOCKET";         break;
-    case     CURLM_UNKNOWN_OPTION:     s="CURLM_UNKNOWN_OPTION";     break;
-    case     CURLM_LAST:               s="CURLM_LAST";               break;
-    default: s="CURLM_unknown";
+    case     CURLM_BAD_HANDLE:         s = "CURLM_BAD_HANDLE";         break;
+    case     CURLM_BAD_EASY_HANDLE:    s = "CURLM_BAD_EASY_HANDLE";    break;
+    case     CURLM_OUT_OF_MEMORY:      s = "CURLM_OUT_OF_MEMORY";      break;
+    case     CURLM_INTERNAL_ERROR:     s = "CURLM_INTERNAL_ERROR";     break;
+    case     CURLM_BAD_SOCKET:         s = "CURLM_BAD_SOCKET";         break;
+    case     CURLM_UNKNOWN_OPTION:     s = "CURLM_UNKNOWN_OPTION";     break;
+    case     CURLM_LAST:               s = "CURLM_LAST";               break;
+    default: s = "CURLM_unknown";
     }
     MSG_OUT("ERROR: %s returns %s\n", where, s);
     exit(code);
@@ -156,7 +156,7 @@ static gboolean timer_cb(gpointer data)
 static int update_timeout_cb(CURLM *multi, long timeout_ms, void *userp)
 {
   struct timeval timeout;
-  GlobalInfo *g=(GlobalInfo *)userp;
+  GlobalInfo *g = (GlobalInfo *)userp;
   timeout.tv_sec = timeout_ms/1000;
   timeout.tv_usec = (timeout_ms%1000)*1000;
 
@@ -181,7 +181,7 @@ static gboolean event_cb(GIOChannel *ch, GIOCondition 
condition, gpointer data)
 {
   GlobalInfo *g = (GlobalInfo*) data;
   CURLMcode rc;
-  int fd=g_io_channel_unix_get_fd(ch);
+  int fd = g_io_channel_unix_get_fd(ch);
 
   int action =
     (condition & G_IO_IN ? CURL_CSELECT_IN : 0) |
@@ -228,7 +228,7 @@ static void setsock(SockInfo *f, curl_socket_t s, CURL *e, 
int act,
   if(f->ev) {
     g_source_remove(f->ev);
   }
-  f->ev=g_io_add_watch(f->ch, kind, event_cb, g);
+  f->ev = g_io_add_watch(f->ch, kind, event_cb, g);
 }
 
 /* Initialize a new SockInfo structure */
@@ -237,7 +237,7 @@ static void addsock(curl_socket_t s, CURL *easy, int 
action, GlobalInfo *g)
   SockInfo *fdp = g_malloc0(sizeof(SockInfo));
 
   fdp->global = g;
-  fdp->ch=g_io_channel_unix_new(s);
+  fdp->ch = g_io_channel_unix_new(s);
   setsock(fdp, s, easy, action, g);
   curl_multi_assign(g->multi, s, fdp);
 }
@@ -319,7 +319,7 @@ static void new_conn(char *url, GlobalInfo *g)
   curl_easy_setopt(conn->easy, CURLOPT_LOW_SPEED_TIME, 30L);
 
   MSG_OUT("Adding easy %p to multi %p (%s)\n", conn->easy, g->multi, url);
-  rc =curl_multi_add_handle(g->multi, conn->easy);
+  rc = curl_multi_add_handle(g->multi, conn->easy);
   mcode_or_die("new_conn: curl_multi_add_handle", rc);
 
   /* note that the add_handle() will set a time-out to trigger very soon so
@@ -331,11 +331,11 @@ static gboolean fifo_cb(GIOChannel *ch, GIOCondition 
condition, gpointer data)
 {
 #define BUF_SIZE 1024
   gsize len, tp;
-  gchar *buf, *tmp, *all=NULL;
+  gchar *buf, *tmp, *all = NULL;
   GIOStatus rv;
 
   do {
-    GError *err=NULL;
+    GError *err = NULL;
     rv = g_io_channel_read_line(ch, &buf, &len, &tp, &err);
     if(buf) {
       if(tp) {
@@ -345,15 +345,15 @@ static gboolean fifo_cb(GIOChannel *ch, GIOCondition 
condition, gpointer data)
       g_free(buf);
     }
     else {
-      buf = g_malloc(BUF_SIZE+1);
+      buf = g_malloc(BUF_SIZE + 1);
       while(TRUE) {
         buf[BUF_SIZE]='\0';
         g_io_channel_read_chars(ch, buf, BUF_SIZE, &len, &err);
         if(len) {
           buf[len]='\0';
           if(all) {
-            tmp=all;
-            all=g_strdup_printf("%s%s", tmp, buf);
+            tmp = all;
+            all = g_strdup_printf("%s%s", tmp, buf);
             g_free(tmp);
           }
           else {
@@ -417,12 +417,12 @@ int main(int argc, char **argv)
   GMainLoop*gmain;
   int fd;
   GIOChannel* ch;
-  g=g_malloc0(sizeof(GlobalInfo));
+  g = g_malloc0(sizeof(GlobalInfo));
 
-  fd=init_fifo();
-  ch=g_io_channel_unix_new(fd);
+  fd = init_fifo();
+  ch = g_io_channel_unix_new(fd);
   g_io_add_watch(ch, G_IO_IN, fifo_cb, g);
-  gmain=g_main_loop_new(NULL, FALSE);
+  gmain = g_main_loop_new(NULL, FALSE);
   g->multi = curl_multi_init();
   curl_multi_setopt(g->multi, CURLMOPT_SOCKETFUNCTION, sock_cb);
   curl_multi_setopt(g->multi, CURLMOPT_SOCKETDATA, g);
diff --git a/docs/examples/hiperfifo.c b/docs/examples/hiperfifo.c
index 2d0dc7a31..a502d48f0 100644
--- a/docs/examples/hiperfifo.c
+++ b/docs/examples/hiperfifo.c
@@ -137,15 +137,15 @@ static void mcode_or_die(const char *where, CURLMcode 
code)
   if(CURLM_OK != code) {
     const char *s;
     switch(code) {
-      case     CURLM_BAD_HANDLE:         s="CURLM_BAD_HANDLE";         break;
-      case     CURLM_BAD_EASY_HANDLE:    s="CURLM_BAD_EASY_HANDLE";    break;
-      case     CURLM_OUT_OF_MEMORY:      s="CURLM_OUT_OF_MEMORY";      break;
-      case     CURLM_INTERNAL_ERROR:     s="CURLM_INTERNAL_ERROR";     break;
-      case     CURLM_UNKNOWN_OPTION:     s="CURLM_UNKNOWN_OPTION";     break;
-      case     CURLM_LAST:               s="CURLM_LAST";               break;
-      default: s="CURLM_unknown";
+      case     CURLM_BAD_HANDLE:         s = "CURLM_BAD_HANDLE";         break;
+      case     CURLM_BAD_EASY_HANDLE:    s = "CURLM_BAD_EASY_HANDLE";    break;
+      case     CURLM_OUT_OF_MEMORY:      s = "CURLM_OUT_OF_MEMORY";      break;
+      case     CURLM_INTERNAL_ERROR:     s = "CURLM_INTERNAL_ERROR";     break;
+      case     CURLM_UNKNOWN_OPTION:     s = "CURLM_UNKNOWN_OPTION";     break;
+      case     CURLM_LAST:               s = "CURLM_LAST";               break;
+      default: s = "CURLM_unknown";
         break;
-    case     CURLM_BAD_SOCKET:         s="CURLM_BAD_SOCKET";
+    case     CURLM_BAD_SOCKET:         s = "CURLM_BAD_SOCKET";
       fprintf(MSG_OUT, "ERROR: %s returns %s\n", where, s);
       /* ignore this error */
       return;
@@ -359,15 +359,15 @@ static void new_conn(char *url, GlobalInfo *g)
 static void fifo_cb(int fd, short event, void *arg)
 {
   char s[1024];
-  long int rv=0;
-  int n=0;
+  long int rv = 0;
+  int n = 0;
   GlobalInfo *g = (GlobalInfo *)arg;
   (void)fd; /* unused */
   (void)event; /* unused */
 
   do {
     s[0]='\0';
-    rv=fscanf(g->input, "%1023s%n", s, &n);
+    rv = fscanf(g->input, "%1023s%n", s, &n);
     s[n]='\0';
     if(n && s[0]) {
       new_conn(s, arg);  /* if we read a URL, go get it! */
diff --git a/docs/examples/htmltidy.c b/docs/examples/htmltidy.c
index e6f2f4058..2da21fe6c 100644
--- a/docs/examples/htmltidy.c
+++ b/docs/examples/htmltidy.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 @@ void dumpNode(TidyDoc doc, TidyNode tnod, int indent)
       TidyAttr attr;
       printf("%*.*s%s ", indent, indent, "<", name);
       /* walk the attribute list */
-      for(attr=tidyAttrFirst(child); attr; attr=tidyAttrNext(attr) ) {
+      for(attr = tidyAttrFirst(child); attr; attr = tidyAttrNext(attr) ) {
         printf(tidyAttrName(attr));
         tidyAttrValue(attr)?printf("=\"%s\" ",
                                    tidyAttrValue(attr)):printf(" ");
@@ -95,7 +95,7 @@ int main(int argc, char **argv)
     tidyBufInit(&docbuf);
 
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, &docbuf);
-    err=curl_easy_perform(curl);
+    err = curl_easy_perform(curl);
     if(!err) {
       err = tidyParseBuffer(tdoc, &docbuf); /* parse the input */
       if(err >= 0) {
diff --git a/docs/examples/http2-download.c b/docs/examples/http2-download.c
index 3ccd2e2ee..0a8847b3e 100644
--- a/docs/examples/http2-download.c
+++ b/docs/examples/http2-download.c
@@ -51,7 +51,7 @@ static int num_transfers;
 static int hnd2num(CURL *hnd)
 {
   int i;
-  for(i=0; i< num_transfers; i++) {
+  for(i = 0; i< num_transfers; i++) {
     if(curl_hnd[i] == hnd)
       return i;
   }
@@ -65,7 +65,7 @@ void dump(const char *text, int num, unsigned char *ptr, 
size_t size,
   size_t i;
   size_t c;
 
-  unsigned int width=0x10;
+  unsigned int width = 0x10;
 
   if(nohex)
     /* without the hex output, we can fit more on screen */
@@ -74,30 +74,32 @@ void dump(const char *text, int num, unsigned char *ptr, 
size_t size,
   fprintf(stderr, "%d %s, %ld bytes (0x%lx)\n",
           num, text, (long)size, (long)size);
 
-  for(i=0; i<size; i+= width) {
+  for(i = 0; i<size; i += width) {
 
     fprintf(stderr, "%4.4lx: ", (long)i);
 
     if(!nohex) {
       /* hex not disabled, show it */
       for(c = 0; c < width; c++)
-        if(i+c < size)
-          fprintf(stderr, "%02x ", ptr[i+c]);
+        if(i + c < size)
+          fprintf(stderr, "%02x ", ptr[i + c]);
         else
           fputs("   ", stderr);
     }
 
-    for(c = 0; (c < width) && (i+c < size); c++) {
+    for(c = 0; (c < width) && (i + c < size); c++) {
       /* check for 0D0A; if found, skip past and start a new line of output */
-      if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
-        i+=(c+2-width);
+      if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+         ptr[i + c + 1] == 0x0A) {
+        i += (c + 2 - width);
         break;
       }
       fprintf(stderr, "%c",
-              (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
+              (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)?ptr[i + c]:'.');
       /* check again for 0D0A, to avoid an extra \n if it's at width */
-      if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
-        i+=(c+3-width);
+      if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+         ptr[i + c + 2] == 0x0A) {
+        i += (c + 3 - width);
         break;
       }
     }
@@ -199,7 +201,7 @@ int main(int argc, char **argv)
   /* init a multi stack */
   multi_handle = curl_multi_init();
 
-  for(i=0; i<num_transfers; i++) {
+  for(i = 0; i<num_transfers; i++) {
     easy[i] = curl_easy_init();
     /* set options */
     setup(easy[i], i);
@@ -269,7 +271,7 @@ int main(int argc, char **argv)
     else {
       /* Note that on some platforms 'timeout' may be modified by select().
          If you need access to the original value save a copy beforehand. */
-      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+      rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
     }
 
     switch(rc) {
@@ -286,7 +288,7 @@ int main(int argc, char **argv)
 
   curl_multi_cleanup(multi_handle);
 
-  for(i=0; i<num_transfers; i++)
+  for(i = 0; i<num_transfers; i++)
     curl_easy_cleanup(easy[i]);
 
   return 0;
diff --git a/docs/examples/http2-serverpush.c b/docs/examples/http2-serverpush.c
index a01d165ff..9ad621b97 100644
--- a/docs/examples/http2-serverpush.c
+++ b/docs/examples/http2-serverpush.c
@@ -45,7 +45,7 @@ void dump(const char *text, unsigned char *ptr, size_t size,
   size_t i;
   size_t c;
 
-  unsigned int width=0x10;
+  unsigned int width = 0x10;
 
   if(nohex)
     /* without the hex output, we can fit more on screen */
@@ -54,30 +54,32 @@ void dump(const char *text, unsigned char *ptr, size_t size,
   fprintf(stderr, "%s, %ld bytes (0x%lx)\n",
           text, (long)size, (long)size);
 
-  for(i=0; i<size; i+= width) {
+  for(i = 0; i<size; i += width) {
 
     fprintf(stderr, "%4.4lx: ", (long)i);
 
     if(!nohex) {
       /* hex not disabled, show it */
       for(c = 0; c < width; c++)
-        if(i+c < size)
-          fprintf(stderr, "%02x ", ptr[i+c]);
+        if(i + c < size)
+          fprintf(stderr, "%02x ", ptr[i + c]);
         else
           fputs("   ", stderr);
     }
 
-    for(c = 0; (c < width) && (i+c < size); c++) {
+    for(c = 0; (c < width) && (i + c < size); c++) {
       /* check for 0D0A; if found, skip past and start a new line of output */
-      if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
-        i+=(c+2-width);
+      if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+         ptr[i + c + 1] == 0x0A) {
+        i += (c + 2 - width);
         break;
       }
       fprintf(stderr, "%c",
-              (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
+              (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)?ptr[i + c]:'.');
       /* check again for 0D0A, to avoid an extra \n if it's at width */
-      if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
-        i+=(c+3-width);
+      if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+         ptr[i + c + 2] == 0x0A) {
+        i += (c + 3 - width);
         break;
       }
     }
@@ -181,7 +183,7 @@ static int server_push_callback(CURL *parent,
   fprintf(stderr, "**** push callback approves stream %u, got %d headers!\n",
           count, (int)num_headers);
 
-  for(i=0; i<num_headers; i++) {
+  for(i = 0; i<num_headers; i++) {
     headp = curl_pushheader_bynum(headers, i);
     fprintf(stderr, "**** header %u: %s\n", (int)i, headp);
   }
@@ -204,7 +206,7 @@ int main(void)
   CURL *easy;
   CURLM *multi_handle;
   int still_running; /* keep number of running handles */
-  int transfers=1; /* we start with one */
+  int transfers = 1; /* we start with one */
   struct CURLMsg *m;
 
   /* init a multi stack */
@@ -281,7 +283,7 @@ int main(void)
     else {
       /* Note that on some platforms 'timeout' may be modified by select().
          If you need access to the original value save a copy beforehand. */
-      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+      rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
     }
 
     switch(rc) {
diff --git a/docs/examples/http2-upload.c b/docs/examples/http2-upload.c
index 57bee796b..a2561fe7e 100644
--- a/docs/examples/http2-upload.c
+++ b/docs/examples/http2-upload.c
@@ -53,7 +53,7 @@ static int num_transfers;
 static int hnd2num(CURL *hnd)
 {
   int i;
-  for(i=0; i< num_transfers; i++) {
+  for(i = 0; i< num_transfers; i++) {
     if(curl_hnd[i] == hnd)
       return i;
   }
@@ -66,7 +66,7 @@ void dump(const char *text, int num, unsigned char *ptr, 
size_t size,
 {
   size_t i;
   size_t c;
-  unsigned int width=0x10;
+  unsigned int width = 0x10;
 
   if(nohex)
     /* without the hex output, we can fit more on screen */
@@ -75,30 +75,32 @@ void dump(const char *text, int num, unsigned char *ptr, 
size_t size,
   fprintf(stderr, "%d %s, %ld bytes (0x%lx)\n",
           num, text, (long)size, (long)size);
 
-  for(i=0; i<size; i+= width) {
+  for(i = 0; i<size; i += width) {
 
     fprintf(stderr, "%4.4lx: ", (long)i);
 
     if(!nohex) {
       /* hex not disabled, show it */
       for(c = 0; c < width; c++)
-        if(i+c < size)
-          fprintf(stderr, "%02x ", ptr[i+c]);
+        if(i + c < size)
+          fprintf(stderr, "%02x ", ptr[i + c]);
         else
           fputs("   ", stderr);
     }
 
-    for(c = 0; (c < width) && (i+c < size); c++) {
+    for(c = 0; (c < width) && (i + c < size); c++) {
       /* check for 0D0A; if found, skip past and start a new line of output */
-      if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
-        i+=(c+2-width);
+      if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+         ptr[i + c + 1] == 0x0A) {
+        i += (c + 2 - width);
         break;
       }
       fprintf(stderr, "%c",
-              (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
+              (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)?ptr[i + c]:'.');
       /* check again for 0D0A, to avoid an extra \n if it's at width */
-      if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
-        i+=(c+3-width);
+      if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+         ptr[i + c + 2] == 0x0A) {
+        i += (c + 3 - width);
         break;
       }
     }
@@ -260,7 +262,7 @@ int main(int argc, char **argv)
   /* init a multi stack */
   multi_handle = curl_multi_init();
 
-  for(i=0; i<num_transfers; i++) {
+  for(i = 0; i<num_transfers; i++) {
     easy[i] = curl_easy_init();
     /* set options */
     setup(easy[i], i, filename);
@@ -333,7 +335,7 @@ int main(int argc, char **argv)
     else {
       /* Note that on some platforms 'timeout' may be modified by select().
          If you need access to the original value save a copy beforehand. */
-      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+      rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
     }
 
     switch(rc) {
@@ -350,7 +352,7 @@ int main(int argc, char **argv)
 
   curl_multi_cleanup(multi_handle);
 
-  for(i=0; i<num_transfers; i++)
+  for(i = 0; i<num_transfers; i++)
     curl_easy_cleanup(easy[i]);
 
   return 0;
diff --git a/docs/examples/httpput.c b/docs/examples/httpput.c
index 19d205b78..8399dbfe7 100644
--- a/docs/examples/httpput.c
+++ b/docs/examples/httpput.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 @@ int main(int argc, char **argv)
   if(argc < 3)
     return 1;
 
-  file= argv[1];
+  file = argv[1];
   url = argv[2];
 
   /* get the file size of the local file */
diff --git a/docs/examples/imap-multi.c b/docs/examples/imap-multi.c
index 587be2906..c1f429e14 100644
--- a/docs/examples/imap-multi.c
+++ b/docs/examples/imap-multi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +144,7 @@ int main(void)
     else {
       /* Note that on some platforms 'timeout' may be modified by select().
          If you need access to the original value save a copy beforehand. */
-      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+      rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
     }
 
     if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
diff --git a/docs/examples/multi-app.c b/docs/examples/multi-app.c
index d7e7af78d..01b76c558 100644
--- a/docs/examples/multi-app.c
+++ b/docs/examples/multi-app.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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 @@ int main(void)
   int msgs_left; /* how many messages are left */
 
   /* Allocate one CURL handle per transfer */
-  for(i=0; i<HANDLECOUNT; i++)
+  for(i = 0; i<HANDLECOUNT; i++)
     handles[i] = curl_easy_init();
 
   /* set the options (I left out a few, you'll get the point anyway) */
@@ -68,7 +68,7 @@ int main(void)
   multi_handle = curl_multi_init();
 
   /* add the individual transfers */
-  for(i=0; i<HANDLECOUNT; i++)
+  for(i = 0; i<HANDLECOUNT; i++)
     curl_multi_add_handle(multi_handle, handles[i]);
 
   /* we start some action by calling perform right away */
@@ -130,7 +130,7 @@ int main(void)
     else {
       /* Note that on some platforms 'timeout' may be modified by select().
          If you need access to the original value save a copy beforehand. */
-      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+      rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
     }
 
     switch(rc) {
@@ -150,7 +150,7 @@ int main(void)
       int idx, found = 0;
 
       /* Find out which handle this message is about */
-      for(idx=0; idx<HANDLECOUNT; idx++) {
+      for(idx = 0; idx<HANDLECOUNT; idx++) {
         found = (msg->easy_handle == handles[idx]);
         if(found)
           break;
@@ -170,7 +170,7 @@ int main(void)
   curl_multi_cleanup(multi_handle);
 
   /* Free the CURL handles */
-  for(i=0; i<HANDLECOUNT; i++)
+  for(i = 0; i<HANDLECOUNT; i++)
     curl_easy_cleanup(handles[i]);
 
   return 0;
diff --git a/docs/examples/multi-debugcallback.c 
b/docs/examples/multi-debugcallback.c
index 50c127b97..82ca5cb0f 100644
--- a/docs/examples/multi-debugcallback.c
+++ b/docs/examples/multi-debugcallback.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -45,7 +45,7 @@ void dump(const char *text,
   size_t i;
   size_t c;
 
-  unsigned int width=0x10;
+  unsigned int width = 0x10;
 
   if(nohex)
     /* without the hex output, we can fit more on screen */
@@ -54,30 +54,32 @@ void dump(const char *text,
   fprintf(stream, "%s, %10.10ld bytes (0x%8.8lx)\n",
           text, (long)size, (long)size);
 
-  for(i=0; i<size; i+= width) {
+  for(i = 0; i<size; i += width) {
 
     fprintf(stream, "%4.4lx: ", (long)i);
 
     if(!nohex) {
       /* hex not disabled, show it */
       for(c = 0; c < width; c++)
-        if(i+c < size)
-          fprintf(stream, "%02x ", ptr[i+c]);
+        if(i + c < size)
+          fprintf(stream, "%02x ", ptr[i + c]);
         else
           fputs("   ", stream);
     }
 
-    for(c = 0; (c < width) && (i+c < size); c++) {
+    for(c = 0; (c < width) && (i + c < size); c++) {
       /* check for 0D0A; if found, skip past and start a new line of output */
-      if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
-        i+=(c+2-width);
+      if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+         ptr[i + c + 1] == 0x0A) {
+        i += (c + 2 - width);
         break;
       }
       fprintf(stream, "%c",
-              (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
+              (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)?ptr[i + c]:'.');
       /* check again for 0D0A, to avoid an extra \n if it's at width */
-      if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
-        i+=(c+3-width);
+      if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+         ptr[i + c + 2] == 0x0A) {
+        i += (c + 3 - width);
         break;
       }
     }
@@ -204,7 +206,7 @@ int main(void)
     else {
       /* Note that on some platforms 'timeout' may be modified by select().
          If you need access to the original value save a copy beforehand. */
-      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+      rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
     }
 
     switch(rc) {
diff --git a/docs/examples/multi-double.c b/docs/examples/multi-double.c
index dc6f23e68..c4b134d6c 100644
--- a/docs/examples/multi-double.c
+++ b/docs/examples/multi-double.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -119,7 +119,7 @@ int main(void)
     else {
       /* Note that on some platforms 'timeout' may be modified by select().
          If you need access to the original value save a copy beforehand. */
-      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+      rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
     }
 
     switch(rc) {
diff --git a/docs/examples/multi-post.c b/docs/examples/multi-formadd.c
similarity index 94%
copy from docs/examples/multi-post.c
copy to docs/examples/multi-formadd.c
index d6c082cc7..bd85cc641 100644
--- a/docs/examples/multi-post.c
+++ b/docs/examples/multi-formadd.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 @@
 #include <string.h>
 #include <sys/time.h>
 
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 int main(void)
 {
@@ -37,9 +37,9 @@ int main(void)
   CURLM *multi_handle;
   int still_running;
 
-  struct curl_httppost *formpost=NULL;
-  struct curl_httppost *lastptr=NULL;
-  struct curl_slist *headerlist=NULL;
+  struct curl_httppost *formpost = NULL;
+  struct curl_httppost *lastptr = NULL;
+  struct curl_slist *headerlist = NULL;
   static const char buf[] = "Expect:";
 
   /* Fill in the file upload field. This makes libcurl load data from
@@ -139,7 +139,7 @@ int main(void)
       else {
         /* Note that on some platforms 'timeout' may be modified by select().
            If you need access to the original value save a copy beforehand. */
-        rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+        rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
       }
 
       switch(rc) {
diff --git a/docs/examples/multi-post.c b/docs/examples/multi-post.c
index d6c082cc7..a5df2d237 100644
--- a/docs/examples/multi-post.c
+++ b/docs/examples/multi-post.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,47 +37,43 @@ int main(void)
   CURLM *multi_handle;
   int still_running;
 
-  struct curl_httppost *formpost=NULL;
-  struct curl_httppost *lastptr=NULL;
-  struct curl_slist *headerlist=NULL;
+  curl_mime *form = NULL;
+  curl_mimepart *field = NULL;
+  struct curl_slist *headerlist = NULL;
   static const char buf[] = "Expect:";
 
-  /* Fill in the file upload field. This makes libcurl load data from
-     the given file name when curl_easy_perform() is called. */
-  curl_formadd(&formpost,
-               &lastptr,
-               CURLFORM_COPYNAME, "sendfile",
-               CURLFORM_FILE, "postit2.c",
-               CURLFORM_END);
-
-  /* Fill in the filename field */
-  curl_formadd(&formpost,
-               &lastptr,
-               CURLFORM_COPYNAME, "filename",
-               CURLFORM_COPYCONTENTS, "postit2.c",
-               CURLFORM_END);
-
-  /* Fill in the submit field too, even if this is rarely needed */
-  curl_formadd(&formpost,
-               &lastptr,
-               CURLFORM_COPYNAME, "submit",
-               CURLFORM_COPYCONTENTS, "send",
-               CURLFORM_END);
-
   curl = curl_easy_init();
   multi_handle = curl_multi_init();
 
-  /* initialize custom header list (stating that Expect: 100-continue is not
-     wanted */
-  headerlist = curl_slist_append(headerlist, buf);
   if(curl && multi_handle) {
+    /* Create the form */
+    form = curl_mime_init(curl);
+
+    /* Fill in the file upload field */
+    field = curl_mime_addpart(form);
+    curl_mime_name(field, "sendfile");
+    curl_mime_filedata(field, "multi-post.c");
+
+    /* Fill in the filename field */
+    field = curl_mime_addpart(form);
+    curl_mime_name(field, "filename");
+    curl_mime_data(field, "multi-post.c", CURL_ZERO_TERMINATED);
+
+    /* Fill in the submit field too, even if this is rarely needed */
+    field = curl_mime_addpart(form);
+    curl_mime_name(field, "submit");
+    curl_mime_data(field, "send", CURL_ZERO_TERMINATED);
+
+    /* initialize custom header list (stating that Expect: 100-continue is not
+       wanted */
+    headerlist = curl_slist_append(headerlist, buf);
 
     /* what URL that receives this POST */
     curl_easy_setopt(curl, CURLOPT_URL, "http://www.example.com/upload.cgi";);
     curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
 
     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
-    curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
+    curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
 
     curl_multi_add_handle(multi_handle, curl);
 
@@ -139,7 +135,7 @@ int main(void)
       else {
         /* Note that on some platforms 'timeout' may be modified by select().
            If you need access to the original value save a copy beforehand. */
-        rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+        rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
       }
 
       switch(rc) {
@@ -161,8 +157,8 @@ int main(void)
     /* always cleanup */
     curl_easy_cleanup(curl);
 
-    /* then cleanup the formpost chain */
-    curl_formfree(formpost);
+    /* then cleanup the form */
+    curl_mime_free(form);
 
     /* free slist */
     curl_slist_free_all(headerlist);
diff --git a/docs/examples/multithread.c b/docs/examples/multithread.c
index d3ea526dd..b0f0eb21d 100644
--- a/docs/examples/multithread.c
+++ b/docs/examples/multithread.c
@@ -74,7 +74,7 @@ int main(int argc, char **argv)
   /* Must initialize libcurl before any threads are started */
   curl_global_init(CURL_GLOBAL_ALL);
 
-  for(i=0; i< NUMT; i++) {
+  for(i = 0; i< NUMT; i++) {
     error = pthread_create(&tid[i],
                            NULL, /* default attributes please */
                            pull_one_url,
@@ -86,7 +86,7 @@ int main(int argc, char **argv)
   }
 
   /* now wait for all threads to terminate */
-  for(i=0; i< NUMT; i++) {
+  for(i = 0; i< NUMT; i++) {
     error = pthread_join(tid[i], NULL);
     fprintf(stderr, "Thread %d terminated\n", i);
   }
diff --git a/docs/examples/opensslthreadlock.c 
b/docs/examples/opensslthreadlock.c
index 6f86c7f70..649ef93a9 100644
--- a/docs/examples/opensslthreadlock.c
+++ b/docs/examples/opensslthreadlock.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -50,7 +50,7 @@ void handle_error(const char *file, int lineno, const char 
*msg)
 }
 
 /* This array will store all of the mutexes available to OpenSSL. */
-static MUTEX_TYPE *mutex_buf= NULL;
+static MUTEX_TYPE *mutex_buf = NULL;
 
 static void locking_function(int mode, int n, const char *file, int line)
 {
diff --git a/docs/examples/pop3-multi.c b/docs/examples/pop3-multi.c
index c95a37341..e86084394 100644
--- a/docs/examples/pop3-multi.c
+++ b/docs/examples/pop3-multi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +144,7 @@ int main(void)
     else {
       /* Note that on some platforms 'timeout' may be modified by select().
          If you need access to the original value save a copy beforehand. */
-      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+      rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
     }
 
     if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
diff --git a/docs/examples/post-callback.c b/docs/examples/post-callback.c
index ad4d62b6b..324767bc1 100644
--- a/docs/examples/post-callback.c
+++ b/docs/examples/post-callback.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,36 +20,45 @@
  *
  ***************************************************************************/
 /* <DESC>
- * An example source code that issues a HTTP POST and we provide the actual
- * data through a read callback.
+ * Issue an HTTP POST and provide the data through the read callback.
  * </DESC>
  */
 #include <stdio.h>
 #include <string.h>
 #include <gnurl/curl.h>
 
-static const char data[]="this is what we post to the silly web server";
+/* silly test data to POST */
+static const char data[]="Lorem ipsum dolor sit amet, consectetur adipiscing "
+  "elit. Sed vel urna neque. Ut quis leo metus. Quisque eleifend, ex at "
+  "laoreet rhoncus, odio ipsum semper metus, at tempus ante urna in mauris. "
+  "Suspendisse ornare tempor venenatis. Ut dui neque, pellentesque a varius "
+  "eget, mattis vitae ligula. Fusce ut pharetra est. Ut ullamcorper mi ac "
+  "sollicitudin semper. Praesent sit amet tellus varius, posuere nulla non, "
+  "rhoncus ipsum.";
 
 struct WriteThis {
   const char *readptr;
-  long sizeleft;
+  size_t sizeleft;
 };
 
-static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
+static size_t read_callback(void *dest, size_t size, size_t nmemb, void *userp)
 {
-  struct WriteThis *pooh = (struct WriteThis *)userp;
-
-  if(size*nmemb < 1)
-    return 0;
-
-  if(pooh->sizeleft) {
-    *(char *)ptr = pooh->readptr[0]; /* copy one single byte */
-    pooh->readptr++;                 /* advance pointer */
-    pooh->sizeleft--;                /* less data left */
-    return 1;                        /* we return 1 byte at a time! */
+  struct WriteThis *wt = (struct WriteThis *)userp;
+  size_t buffer_size = size*nmemb;
+
+  if(wt->sizeleft) {
+    /* copy as much as possible from the source to the destination */
+    size_t copy_this_much = wt->sizeleft;
+    if(copy_this_much > buffer_size)
+      copy_this_much = buffer_size;
+    memcpy(dest, wt->readptr, copy_this_much);
+
+    wt->readptr += copy_this_much;
+    wt->sizeleft -= copy_this_much;
+    return copy_this_much; /* we copied this many bytes */
   }
 
-  return 0;                          /* no more data left to deliver */
+  return 0; /* no more data left to deliver */
 }
 
 int main(void)
@@ -57,10 +66,10 @@ int main(void)
   CURL *curl;
   CURLcode res;
 
-  struct WriteThis pooh;
+  struct WriteThis wt;
 
-  pooh.readptr = data;
-  pooh.sizeleft = (long)strlen(data);
+  wt.readptr = data;
+  wt.sizeleft = strlen(data);
 
   /* In windows, this will init the winsock stuff */
   res = curl_global_init(CURL_GLOBAL_DEFAULT);
@@ -75,7 +84,7 @@ int main(void)
   curl = curl_easy_init();
   if(curl) {
     /* First set the URL that is about to receive our POST. */
-    curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/index.cgi";);
+    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/index.cgi";);
 
     /* Now specify we want to POST data */
     curl_easy_setopt(curl, CURLOPT_POST, 1L);
@@ -84,7 +93,7 @@ int main(void)
     curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
 
     /* pointer to pass to our read function */
-    curl_easy_setopt(curl, CURLOPT_READDATA, &pooh);
+    curl_easy_setopt(curl, CURLOPT_READDATA, &wt);
 
     /* get verbose debug output please */
     curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
@@ -108,7 +117,7 @@ int main(void)
 #else
     /* Set the expected POST size. If you want to POST large amounts of data,
        consider CURLOPT_POSTFIELDSIZE_LARGE */
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, pooh.sizeleft);
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)wt.sizeleft);
 #endif
 
 #ifdef DISABLE_EXPECT
diff --git a/docs/examples/postinmemory.c b/docs/examples/postinmemory.c
index 8af16790f..5d32ef462 100644
--- a/docs/examples/postinmemory.c
+++ b/docs/examples/postinmemory.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +58,7 @@ int main(void)
   CURL *curl;
   CURLcode res;
   struct MemoryStruct chunk;
-  static const char *postthis="Field=1&Field=2&Field=3";
+  static const char *postthis = "Field=1&Field=2&Field=3";
 
   chunk.memory = malloc(1);  /* will be grown as needed by realloc above */
   chunk.size = 0;    /* no data at this point */
diff --git a/docs/examples/postit2.c b/docs/examples/postit2-formadd.c
similarity index 94%
copy from docs/examples/postit2.c
copy to docs/examples/postit2-formadd.c
index b40743637..0ac09f259 100644
--- a/docs/examples/postit2.c
+++ b/docs/examples/postit2-formadd.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,16 +40,16 @@
 #include <stdio.h>
 #include <string.h>
 
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 int main(int argc, char *argv[])
 {
   CURL *curl;
   CURLcode res;
 
-  struct curl_httppost *formpost=NULL;
-  struct curl_httppost *lastptr=NULL;
-  struct curl_slist *headerlist=NULL;
+  struct curl_httppost *formpost = NULL;
+  struct curl_httppost *lastptr = NULL;
+  struct curl_slist *headerlist = NULL;
   static const char buf[] = "Expect:";
 
   curl_global_init(CURL_GLOBAL_ALL);
diff --git a/docs/examples/postit2.c b/docs/examples/postit2.c
index b40743637..d357ecc2f 100644
--- a/docs/examples/postit2.c
+++ b/docs/examples/postit2.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,46 +47,42 @@ int main(int argc, char *argv[])
   CURL *curl;
   CURLcode res;
 
-  struct curl_httppost *formpost=NULL;
-  struct curl_httppost *lastptr=NULL;
-  struct curl_slist *headerlist=NULL;
+  curl_mime *form = NULL;
+  curl_mimepart *field = NULL;
+  struct curl_slist *headerlist = NULL;
   static const char buf[] = "Expect:";
 
   curl_global_init(CURL_GLOBAL_ALL);
 
-  /* Fill in the file upload field */
-  curl_formadd(&formpost,
-               &lastptr,
-               CURLFORM_COPYNAME, "sendfile",
-               CURLFORM_FILE, "postit2.c",
-               CURLFORM_END);
+  curl = curl_easy_init();
+  if(curl) {
+    /* Create the form */
+    form = curl_mime_init(curl);
 
-  /* Fill in the filename field */
-  curl_formadd(&formpost,
-               &lastptr,
-               CURLFORM_COPYNAME, "filename",
-               CURLFORM_COPYCONTENTS, "postit2.c",
-               CURLFORM_END);
+    /* Fill in the file upload field */
+    field = curl_mime_addpart(form);
+    curl_mime_name(field, "sendfile");
+    curl_mime_filedata(field, "postit2.c");
 
+    /* Fill in the filename field */
+    field = curl_mime_addpart(form);
+    curl_mime_name(field, "filename");
+    curl_mime_data(field, "postit2.c", CURL_ZERO_TERMINATED);
 
-  /* Fill in the submit field too, even if this is rarely needed */
-  curl_formadd(&formpost,
-               &lastptr,
-               CURLFORM_COPYNAME, "submit",
-               CURLFORM_COPYCONTENTS, "send",
-               CURLFORM_END);
+    /* Fill in the submit field too, even if this is rarely needed */
+    field = curl_mime_addpart(form);
+    curl_mime_name(field, "submit");
+    curl_mime_data(field, "send", CURL_ZERO_TERMINATED);
 
-  curl = curl_easy_init();
-  /* initialize custom header list (stating that Expect: 100-continue is not
-     wanted */
-  headerlist = curl_slist_append(headerlist, buf);
-  if(curl) {
+    /* initialize custom header list (stating that Expect: 100-continue is not
+       wanted */
+    headerlist = curl_slist_append(headerlist, buf);
     /* what URL that receives this POST */
     curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/examplepost.cgi";);
     if((argc == 2) && (!strcmp(argv[1], "noexpectheader")))
       /* only disable 100-continue header if explicitly requested */
       curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
-    curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
+    curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
 
     /* Perform the request, res will get the return code */
     res = curl_easy_perform(curl);
@@ -98,8 +94,8 @@ int main(int argc, char *argv[])
     /* always cleanup */
     curl_easy_cleanup(curl);
 
-    /* then cleanup the formpost chain */
-    curl_formfree(formpost);
+    /* then cleanup the form */
+    curl_mime_free(form);
     /* free slist */
     curl_slist_free_all(headerlist);
   }
diff --git a/docs/examples/sendrecv.c b/docs/examples/sendrecv.c
index 015462974..1e7075e3c 100644
--- a/docs/examples/sendrecv.c
+++ b/docs/examples/sendrecv.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +36,7 @@ static int wait_on_socket(curl_socket_t sockfd, int for_recv, 
long timeout_ms)
   int res;
 
   tv.tv_sec = timeout_ms / 1000;
-  tv.tv_usec= (timeout_ms % 1000) * 1000;
+  tv.tv_usec = (timeout_ms % 1000) * 1000;
 
   FD_ZERO(&infd);
   FD_ZERO(&outfd);
diff --git a/docs/examples/sftpget.c b/docs/examples/sftpget.c
index 02adc878e..7d0aa4292 100644
--- a/docs/examples/sftpget.c
+++ b/docs/examples/sftpget.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,10 +46,10 @@ struct FtpFile {
 static size_t my_fwrite(void *buffer, size_t size, size_t nmemb,
                         void *stream)
 {
-  struct FtpFile *out=(struct FtpFile *)stream;
+  struct FtpFile *out = (struct FtpFile *)stream;
   if(out && !out->stream) {
     /* open file for writing */
-    out->stream=fopen(out->filename, "wb");
+    out->stream = fopen(out->filename, "wb");
     if(!out->stream)
       return -1; /* failure, can't open file to write */
   }
@@ -61,7 +61,7 @@ int main(void)
 {
   CURL *curl;
   CURLcode res;
-  struct FtpFile ftpfile={
+  struct FtpFile ftpfile = {
     "yourfile.bin", /* name to store the file as if successful */
     NULL
   };
diff --git a/docs/examples/simplepost.c b/docs/examples/simplepost.c
index 7e88f944b..613eacc39 100644
--- a/docs/examples/simplepost.c
+++ b/docs/examples/simplepost.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -32,7 +32,7 @@ int main(void)
   CURL *curl;
   CURLcode res;
 
-  static const char *postthis="moo mooo moo moo";
+  static const char *postthis = "moo mooo moo moo";
 
   curl = curl_easy_init();
   if(curl) {
diff --git a/docs/examples/simplessl.c b/docs/examples/simplessl.c
index 036cd58a5..7b6a2b71b 100644
--- a/docs/examples/simplessl.c
+++ b/docs/examples/simplessl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +53,7 @@ int main(void)
   const char *pPassphrase = NULL;
 
   static const char *pCertFile = "testcert.pem";
-  static const char *pCACertFile="cacert.pem";
+  static const char *pCACertFile = "cacert.pem";
   static const char *pHeaderFile = "dumpit";
 
   const char *pKeyName;
diff --git a/docs/examples/smooth-gtk-thread.c 
b/docs/examples/smooth-gtk-thread.c
index 909f97605..54150aabb 100644
--- a/docs/examples/smooth-gtk-thread.c
+++ b/docs/examples/smooth-gtk-thread.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -134,7 +134,7 @@ void *create_thread(void *progress_bar)
   int error;
 
   /* Make sure I don't create more threads than urls. */
-  for(i=0; i < NUMT && i < num_urls ; i++) {
+  for(i = 0; i < NUMT && i < num_urls ; i++) {
     error = pthread_create(&tid[i],
                            NULL, /* default attributes please */
                            pull_one_url,
@@ -146,7 +146,7 @@ void *create_thread(void *progress_bar)
   }
 
   /* Wait for all threads to terminate. */
-  for(i=0; i < NUMT && i < num_urls; i++) {
+  for(i = 0; i < NUMT && i < num_urls; i++) {
     error = pthread_join(tid[i], NULL);
     fprintf(stderr, "Thread %d terminated\n", i);
   }
diff --git a/docs/examples/smtp-mail.c b/docs/examples/smtp-mail.c
index 77101dda8..6d209e64b 100644
--- a/docs/examples/smtp-mail.c
+++ b/docs/examples/smtp-mail.c
@@ -43,8 +43,8 @@
 static const char *payload_text[] = {
   "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n",
   "To: " TO "\r\n",
-  "From: " FROM "(Example User)\r\n",
-  "Cc: " CC "(Another example User)\r\n",
+  "From: " FROM " (Example User)\r\n",
+  "Cc: " CC " (Another example User)\r\n",
   "Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
   "rfcpedant.example.org>\r\n",
   "Subject: SMTP example message\r\n",
diff --git a/docs/examples/smtp-mail.c b/docs/examples/smtp-mime.c
similarity index 56%
copy from docs/examples/smtp-mail.c
copy to docs/examples/smtp-mime.c
index 77101dda8..dcd867f68 100644
--- a/docs/examples/smtp-mail.c
+++ b/docs/examples/smtp-mime.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,75 +21,62 @@
  ***************************************************************************/
 
 /* <DESC>
- * SMTP example showing how to send e-mails
+ * SMTP example showing how to send mime e-mails
  * </DESC>
  */
 
 #include <stdio.h>
 #include <string.h>
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
-/* This is a simple example showing how to send mail using libcurl's SMTP
+/* This is a simple example showing how to send mime mail using libcurl's SMTP
  * capabilities. For an example of using the multi interface please see
  * smtp-multi.c.
  *
- * Note that this example requires libcurl 7.20.0 or above.
+ * Note that this example requires libcurl 7.56.0 or above.
  */
 
 #define FROM    "<address@hidden>"
 #define TO      "<address@hidden>"
 #define CC      "<address@hidden>"
 
-static const char *payload_text[] = {
-  "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n",
-  "To: " TO "\r\n",
-  "From: " FROM "(Example User)\r\n",
-  "Cc: " CC "(Another example User)\r\n",
+static const char *headers_text[] = {
+  "Date: Tue, 22 Aug 2017 14:08:43 +0100",
+  "To: " TO,
+  "From: " FROM " (Example User)",
+  "Cc: " CC " (Another example User)",
   "Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
-  "rfcpedant.example.org>\r\n",
-  "Subject: SMTP example message\r\n",
-  "\r\n", /* empty line to divide headers from body, see RFC5322 */
-  "The body of the message starts here.\r\n",
-  "\r\n",
-  "It could be a lot of lines, could be MIME encoded, whatever.\r\n",
-  "Check RFC5322.\r\n",
+    "rfcpedant.example.org>",
+  "Subject: example sending a MIME-formatted message",
   NULL
 };
 
-struct upload_status {
-  int lines_read;
-};
-
-static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
-{
-  struct upload_status *upload_ctx = (struct upload_status *)userp;
-  const char *data;
-
-  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
-    return 0;
-  }
+static const char inline_text[] =
+  "This is the inline text message of the e-mail.\r\n"
+  "\r\n"
+  "  It could be a lot of lines that would be displayed in an e-mail\r\n"
+  "viewer that is not able to handle HTML.\r\n";
 
-  data = payload_text[upload_ctx->lines_read];
+static const char inline_html[] =
+  "<html><body>\r\n"
+  "<p>This is the inline <b>HTML</b> message of the e-mail.</p>"
+  "<br />\r\n"
+  "<p>It could be a lot of HTML data that would be displayed by "
+  "e-mail viewers able to handle HTML.</p>"
+  "</body></html>\r\n";
 
-  if(data) {
-    size_t len = strlen(data);
-    memcpy(ptr, data, len);
-    upload_ctx->lines_read++;
-
-    return len;
-  }
-
-  return 0;
-}
 
 int main(void)
 {
   CURL *curl;
   CURLcode res = CURLE_OK;
+  struct curl_slist *headers = NULL;
   struct curl_slist *recipients = NULL;
-  struct upload_status upload_ctx;
-
-  upload_ctx.lines_read = 0;
+  struct curl_slist *slist = NULL;
+  curl_mime *mime;
+  curl_mime *alt;
+  curl_mimepart *part;
+  const char **cpp;
 
   curl = curl_easy_init();
   if(curl) {
@@ -112,12 +99,38 @@ int main(void)
     recipients = curl_slist_append(recipients, CC);
     curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
 
-    /* We're using a callback function to specify the payload (the headers and
-     * body of the message). You could just use the CURLOPT_READDATA option to
-     * specify a FILE pointer to read from. */
-    curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
-    curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
-    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
+    /* Build and set the message header list. */
+    for(cpp = headers_text; *cpp; cpp++)
+      headers = curl_slist_append(headers, *cpp);
+    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
+
+    /* Build the mime message. */
+    mime = curl_mime_init(curl);
+
+    /* The inline part is an alterative proposing the html and the text
+       versions of the e-mail. */
+    alt = curl_mime_init(curl);
+
+    /* HTML message. */
+    part = curl_mime_addpart(alt);
+    curl_mime_data(part, inline_html, CURL_ZERO_TERMINATED);
+    curl_mime_type(part, "text/html");
+
+    /* Text message. */
+    part = curl_mime_addpart(alt);
+    curl_mime_data(part, inline_text, CURL_ZERO_TERMINATED);
+
+    /* Create the inline part. */
+    part = curl_mime_addpart(mime);
+    curl_mime_subparts(part, alt);
+    curl_mime_type(part, "multipart/alternative");
+    slist = curl_slist_append(NULL, "Content-Disposition: inline");
+    curl_mime_headers(part, slist, 1);
+
+    /* Add the current source program as an attachment. */
+    part = curl_mime_addpart(mime);
+    curl_mime_filedata(part, "smtp-mime.c");
+    curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
 
     /* Send the message */
     res = curl_easy_perform(curl);
@@ -127,8 +140,9 @@ int main(void)
       fprintf(stderr, "curl_easy_perform() failed: %s\n",
               curl_easy_strerror(res));
 
-    /* Free the list of recipients */
+    /* Free lists. */
     curl_slist_free_all(recipients);
+    curl_slist_free_all(headers);
 
     /* curl won't send the QUIT command until you call cleanup, so you should
      * be able to re-use this connection for additional messages (setting
@@ -139,6 +153,9 @@ int main(void)
      * clean up in the end.
      */
     curl_easy_cleanup(curl);
+
+    /* Free multipart message. */
+    curl_mime_free(mime);
   }
 
   return (int)res;
diff --git a/docs/examples/smtp-multi.c b/docs/examples/smtp-multi.c
index c749092e5..a58f3282f 100644
--- a/docs/examples/smtp-multi.c
+++ b/docs/examples/smtp-multi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -44,8 +44,8 @@
 static const char *payload_text[] = {
   "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n",
   "To: " TO "\r\n",
-  "From: " FROM "(Example User)\r\n",
-  "Cc: " CC "(Another example User)\r\n",
+  "From: " FROM " (Example User)\r\n",
+  "Cc: " CC " (Another example User)\r\n",
   "Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
   "rfcpedant.example.org>\r\n",
   "Subject: SMTP multi example message\r\n",
@@ -211,7 +211,7 @@ int main(void)
     else {
       /* Note that on some platforms 'timeout' may be modified by select().
          If you need access to the original value save a copy beforehand. */
-      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+      rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
     }
 
     if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
diff --git a/docs/examples/smtp-ssl.c b/docs/examples/smtp-ssl.c
index 838f01eec..dff450eea 100644
--- a/docs/examples/smtp-ssl.c
+++ b/docs/examples/smtp-ssl.c
@@ -44,8 +44,8 @@
 static const char *payload_text[] = {
   "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n",
   "To: " TO "\r\n",
-  "From: " FROM "(Example User)\r\n",
-  "Cc: " CC "(Another example User)\r\n",
+  "From: " FROM " (Example User)\r\n",
+  "Cc: " CC " (Another example User)\r\n",
   "Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
   "rfcpedant.example.org>\r\n",
   "Subject: SMTP SSL example message\r\n",
diff --git a/docs/examples/smtp-tls.c b/docs/examples/smtp-tls.c
index 161b0292e..ffc0e504b 100644
--- a/docs/examples/smtp-tls.c
+++ b/docs/examples/smtp-tls.c
@@ -44,8 +44,8 @@
 static const char *payload_text[] = {
   "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n",
   "To: " TO "\r\n",
-  "From: " FROM "(Example User)\r\n",
-  "Cc: " CC "(Another example User)\r\n",
+  "From: " FROM " (Example User)\r\n",
+  "Cc: " CC " (Another example User)\r\n",
   "Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
   "rfcpedant.example.org>\r\n",
   "Subject: SMTP TLS example message\r\n",
diff --git a/docs/examples/sslbackend.c b/docs/examples/sslbackend.c
new file mode 100644
index 000000000..1483dcc2e
--- /dev/null
+++ b/docs/examples/sslbackend.c
@@ -0,0 +1,77 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, 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.
+ *
+ ***************************************************************************/
+/* <DESC>
+ * Shows HTTPS usage with client certs and optional ssl engine use.
+ * </DESC>
+ */
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <curl/curl.h>
+
+/*
+ * An SSL-enabled libcurl is required for this sample to work (at least one
+ * SSL backend has to be configured).
+ *
+ *  **** This example only works with libcurl 7.56.0 and later! ****
+*/
+
+int main(int argc, char **argv)
+{
+  const char *name = argc > 1 ? argv[1] : "openssl";
+  CURLsslset result;
+
+  if(!strcmp("list", name)) {
+    const curl_ssl_backend **list;
+    int i;
+
+    result = curl_global_sslset(-1, NULL, &list);
+    assert(result == CURLSSLSET_UNKNOWN_BACKEND);
+
+    for(i = 0; list[i]; i++)
+      printf("SSL backend #%d: '%s' (ID: %d)\n",
+             i, list[i]->name, list[i]->id);
+
+    return 0;
+  }
+  else if(isdigit(*name)) {
+    curl_sslbackend id = (curl_sslbackend)atoi(name);
+
+    result = curl_global_sslset(id, NULL, NULL);
+  }
+  else
+    result = curl_global_sslset(-1, name, NULL);
+
+  if(result == CURLSSLSET_UNKNOWN_BACKEND) {
+    fprintf(stderr, "Unknown SSL backend id: %s\n", name);
+    return 1;
+  }
+
+  assert(result == CURLSSLSET_OK);
+
+  printf("Version with SSL backend '%s':\n\n\t%s\n", name, curl_version());
+
+  return 0;
+}
diff --git a/docs/examples/synctime.c b/docs/examples/synctime.c
index d5ecc78a2..5d2c0dcb4 100644
--- a/docs/examples/synctime.c
+++ b/docs/examples/synctime.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -94,7 +94,7 @@
 
 
 #define MAX_STRING              256
-#define MAX_STRING1             MAX_STRING+1
+#define MAX_STRING1             MAX_STRING + 1
 
 #define SYNCTIME_UA "synctime/1.0"
 
@@ -158,9 +158,9 @@ size_t SyncTime_CURL_WriteHeader(void *ptr, size_t size, 
size_t nmemb,
 
         if(RetVal == 7) {
           SYSTime.wMilliseconds = 500;    /* adjust to midpoint, 0.5 sec */
-          for(i=0; i<12; i++) {
+          for(i = 0; i<12; i++) {
             if(strcmp(MthStr[i], TmpStr2) == 0) {
-              SYSTime.wMonth = i+1;
+              SYSTime.wMonth = i + 1;
               break;
             }
           }
@@ -243,7 +243,7 @@ int conf_init(conf_t *conf)
   int i;
 
   *conf->http_proxy       = 0;
-  for(i=0; i<MAX_STRING1; i++)
+  for(i = 0; i<MAX_STRING1; i++)
     conf->proxy_user[i]     = 0;    /* Clean up password from memory */
   *conf->timeserver       = 0;
   return 1;
diff --git a/docs/examples/threaded-ssl.c b/docs/examples/threaded-ssl.c
index 30ba60727..280e1c1af 100644
--- a/docs/examples/threaded-ssl.c
+++ b/docs/examples/threaded-ssl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +25,7 @@
  * </DESC>
  */
 /* A multi-threaded example that uses pthreads and fetches 4 remote files at
- * once over HTTPS. The lock callbacks and stuff assume OpenSSL or GnuTLS
+ * once over HTTPS. The lock callbacks and stuff assume OpenSSL <1.1 or GnuTLS
  * (libgcrypt) so far.
  *
  * OpenSSL docs for this:
@@ -63,7 +63,7 @@ static unsigned long thread_id(void)
 {
   unsigned long ret;
 
-  ret=(unsigned long)pthread_self();
+  ret = (unsigned long)pthread_self();
   return ret;
 }
 
@@ -71,9 +71,9 @@ static void init_locks(void)
 {
   int i;
 
-  lockarray=(pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
-                                            sizeof(pthread_mutex_t));
-  for(i=0; i<CRYPTO_num_locks(); i++) {
+  lockarray = (pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *
+                                                sizeof(pthread_mutex_t));
+  for(i = 0; i<CRYPTO_num_locks(); i++) {
     pthread_mutex_init(&(lockarray[i]), NULL);
   }
 
@@ -86,7 +86,7 @@ static void kill_locks(void)
   int i;
 
   CRYPTO_set_locking_callback(NULL);
-  for(i=0; i<CRYPTO_num_locks(); i++)
+  for(i = 0; i<CRYPTO_num_locks(); i++)
     pthread_mutex_destroy(&(lockarray[i]));
 
   OPENSSL_free(lockarray);
@@ -144,7 +144,7 @@ int main(int argc, char **argv)
 
   init_locks();
 
-  for(i=0; i< NUMT; i++) {
+  for(i = 0; i< NUMT; i++) {
     error = pthread_create(&tid[i],
                            NULL, /* default attributes please */
                            pull_one_url,
@@ -156,7 +156,7 @@ int main(int argc, char **argv)
   }
 
   /* now wait for all threads to terminate */
-  for(i=0; i< NUMT; i++) {
+  for(i = 0; i< NUMT; i++) {
     error = pthread_join(tid[i], NULL);
     fprintf(stderr, "Thread %d terminated\n", i);
   }
diff --git a/docs/examples/usercertinmem.c b/docs/examples/usercertinmem.c
index 6235ccfd1..47740dc65 100644
--- a/docs/examples/usercertinmem.c
+++ b/docs/examples/usercertinmem.c
@@ -200,7 +200,7 @@ int main(void)
   /* first try: retrieve page without user certificate and key -> will fail
    */
   rv = curl_easy_perform(ch);
-  if(rv==CURLE_OK) {
+  if(rv == CURLE_OK) {
     printf("*** transfer succeeded ***\n");
   }
   else {
@@ -213,7 +213,7 @@ int main(void)
    */
   rv = curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
   rv = curl_easy_perform(ch);
-  if(rv==CURLE_OK) {
+  if(rv == CURLE_OK) {
     printf("*** transfer succeeded ***\n");
   }
   else {
diff --git a/docs/libcurl/Makefile.inc b/docs/libcurl/Makefile.inc
index b4e49af9a..fc7a7472b 100644
--- a/docs/libcurl/Makefile.inc
+++ b/docs/libcurl/Makefile.inc
@@ -17,4 +17,8 @@ man_MANS = gnurl_easy_cleanup.3 gnurl_easy_getinfo.3 
gnurl_easy_init.3      \
   gnurl_multi_timeout.3 gnurl_formget.3 gnurl_multi_assign.3                \
   gnurl_easy_pause.3 gnurl_easy_recv.3 gnurl_easy_send.3                    \
   gnurl_multi_socket_action.3 gnurl_multi_wait.3 libgnurl-symbols.3         \
-  libgnurl-thread.3 gnurl_multi_socket_all.3
+  libgnurl-thread.3 gnurl_multi_socket_all.3 gnurl_global_sslset.3           \
+  gnurl_mime_init.3 gnurl_mime_free.3 gnurl_mime_addpart.3 gnurl_mime_name.3 \
+  gnurl_mime_data.3 gnurl_mime_data_cb.3 gnurl_mime_filedata.3              \
+  gnurl_mime_filename.3 gnurl_mime_subparts.3                              \
+  gnurl_mime_type.3 gnurl_mime_headers.3 gnurl_mime_encoder.3
diff --git a/docs/libcurl/gnurl_easy_setopt.3 b/docs/libcurl/gnurl_easy_setopt.3
index f756852ba..cafcf0819 100644
--- a/docs/libcurl/gnurl_easy_setopt.3
+++ b/docs/libcurl/gnurl_easy_setopt.3
@@ -411,6 +411,8 @@ Size of file to send. \fICURLOPT_INFILESIZE(3)\fP
 Size of file to send. \fICURLOPT_INFILESIZE_LARGE(3)\fP
 .IP CURLOPT_UPLOAD
 Upload data. See \fICURLOPT_UPLOAD(3)\fP
+.IP CURLOPT_MIMEPOST
+Post/send MIME data. See \fICURLOPT_MIMEPOST(3)\fP
 .IP CURLOPT_MAXFILESIZE
 Maximum file size to get. See \fICURLOPT_MAXFILESIZE(3)\fP
 .IP CURLOPT_MAXFILESIZE_LARGE
@@ -547,6 +549,8 @@ Disable GSS-API delegation. See 
\fICURLOPT_GSSAPI_DELEGATION(3)\fP
 .SH SSH OPTIONS
 .IP CURLOPT_SSH_AUTH_TYPES
 SSH authentication types. See \fICURLOPT_SSH_AUTH_TYPES(3)\fP
+.IP CURLOPT_SSH_COMPRESSION
+Enable SSH compression. See \fICURLOPT_SSH_COMPRESSION(3)\fP
 .IP CURLOPT_SSH_HOST_PUBLIC_KEY_MD5
 MD5 of host's public key. See \fICURLOPT_SSH_HOST_PUBLIC_KEY_MD5(3)\fP
 .IP CURLOPT_SSH_PUBLIC_KEYFILE
diff --git a/docs/libcurl/gnurl_formadd.3 b/docs/libcurl/gnurl_formadd.3
index e3ef58366..12604f1ae 100644
--- a/docs/libcurl/gnurl_formadd.3
+++ b/docs/libcurl/gnurl_formadd.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2017, 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,6 +29,8 @@ curl_formadd - add a section to a multipart/formdata HTTP POST
 .BI "struct curl_httppost ** " lastitem, " ...);"
 .ad
 .SH DESCRIPTION
+This function is deprecated. Do not use! See \fIcurl_mime_init(3)\fP instead!
+
 curl_formadd() is used to append sections when building a multipart/formdata
 HTTP POST (sometimes referred to as RFC2388-style posts). Append one section
 at a time until you've added all the sections you want included and then you
@@ -60,16 +62,15 @@ parts.
 .IP CURLFORM_COPYNAME
 followed by a string which provides the \fIname\fP of this part. libcurl
 copies the string so your application doesn't need to keep it around after
-this function call. If the name isn't NUL-terminated, or if you'd
-like it to contain zero bytes, you must set its length with
-\fBCURLFORM_NAMELENGTH\fP. The copied data will be freed by
-\fIcurl_formfree(3)\fP.
+this function call. If the name isn't NUL-terminated, you must set its length
+with \fBCURLFORM_NAMELENGTH\fP. The \fIname\fP is not allowed to contain
+zero-valued bytes. The copied data will be freed by \fIcurl_formfree(3)\fP.
 .IP CURLFORM_PTRNAME
 followed by a string which provides the \fIname\fP of this part. libcurl
 will use the pointer and refer to the data in your application, so you
 must make sure it remains until curl no longer needs it. If the name
-isn't NUL-terminated, or if you'd like it to contain zero
-bytes, you must set its length with \fBCURLFORM_NAMELENGTH\fP.
+isn't NUL-terminated, you must set its length with \fBCURLFORM_NAMELENGTH\fP.
+The \fIname\fP is not allowed to contain zero-valued bytes.
 .IP CURLFORM_COPYCONTENTS
 followed by a pointer to the contents of this part, the actual data
 to send away. libcurl copies the provided data, so your application doesn't
@@ -169,6 +170,9 @@ the \fICURLOPT_HTTPPOST(3)\fP option), you must not free 
the list until after
 you've called \fIcurl_easy_cleanup(3)\fP for the curl handle.
 
 See example below.
+.SH AVAILABILITY
+Deprecated in 7.56.0. Before this release, field names were allowed to
+contain zero-valued bytes.
 .SH RETURN VALUE
 0 means everything was ok, non-zero means an error occurred corresponding
 to a CURL_FORMADD_* constant defined in
@@ -254,5 +258,6 @@ to a CURL_FORMADD_* constant defined in
  curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
 
 .SH "SEE ALSO"
-.BR curl_easy_setopt "(3), "
-.BR curl_formfree "(3)"
+.BR curl_easy_setopt "(3),"
+.BR curl_formfree "(3),"
+.BR curl_mime_init "(3)"
diff --git a/docs/libcurl/gnurl_formfree.3 b/docs/libcurl/gnurl_formfree.3
index 9c204ea93..80eabd3fd 100644
--- a/docs/libcurl/gnurl_formfree.3
+++ b/docs/libcurl/gnurl_formfree.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2017, 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,8 @@ curl_formfree - free a previously build multipart/formdata 
HTTP POST chain
 .BI "void curl_formfree(struct curl_httppost *" form);
 .ad
 .SH DESCRIPTION
+This function is deprecated. Do not use! See \fIcurl_mime_init(3)\fP instead!
+
 curl_formfree() is used to clean up data previously built/appended with
 \fIcurl_formadd(3)\fP. This must be called when the data has been used, which
 typically means after \fIcurl_easy_perform(3)\fP has been called.
@@ -38,7 +40,9 @@ the \fIcurl_formadd(3)\fP invoke(s).
 
 \fBform\fP is the pointer as returned from a previous call to
 \fIcurl_formadd(3)\fP and may be NULL.
+.SH AVAILABILITY
+Deprecated in 7.56.0.
 .SH RETURN VALUE
 None
 .SH "SEE ALSO"
-.BR curl_formadd "(3) "
+.BR curl_formadd "(3), " curl_mime_init "(3), " curl_mime_free "(3)"
diff --git a/docs/libcurl/gnurl_formget.3 b/docs/libcurl/gnurl_formget.3
index d8ed80af1..f32ce2634 100644
--- a/docs/libcurl/gnurl_formget.3
+++ b/docs/libcurl/gnurl_formget.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2015, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2017, 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
@@ -65,6 +65,7 @@ request as only then will libcurl get the actual read 
callback to use!
    return total_size;
  }
 .SH AVAILABILITY
-This function was added in libcurl 7.15.5
+This function was added in libcurl 7.15.5. The form API is deprecated in
+libcurl 7.56.0.
 .SH "SEE ALSO"
-.BR curl_formadd "(3) "
+.BR curl_formadd "(3), " curl_mime_init "(3)"
diff --git a/docs/libcurl/gnurl_global_init.3 b/docs/libcurl/gnurl_global_init.3
index daa8a3c8b..2d32e6474 100644
--- a/docs/libcurl/gnurl_global_init.3
+++ b/docs/libcurl/gnurl_global_init.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2017, 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
@@ -93,5 +93,6 @@ other curl functions.
 .SH "SEE ALSO"
 .BR curl_global_init_mem "(3), "
 .BR curl_global_cleanup "(3), "
+.BR curl_global_sslset "(3), "
 .BR curl_easy_init "(3) "
 .BR libcurl "(3) "
diff --git a/docs/libcurl/gnurl_global_sslset.3 
b/docs/libcurl/gnurl_global_sslset.3
new file mode 100644
index 000000000..cee84458f
--- /dev/null
+++ b/docs/libcurl/gnurl_global_sslset.3
@@ -0,0 +1,97 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, 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 curl_global_sslset 3 "15 July 2017" "libcurl 7.56" "libcurl Manual"
+.SH NAME
+curl_global_sslset - Select SSL backend to use with libcurl
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.nf
+
+typedef struct {
+  curl_sslbackend id;
+  const char *name;
+} curl_ssl_backend;
+
+typedef enum {
+  CURLSSLBACKEND_NONE = 0,
+  CURLSSLBACKEND_OPENSSL = 1,
+  CURLSSLBACKEND_GNUTLS = 2,
+  CURLSSLBACKEND_NSS = 3,
+  CURLSSLBACKEND_GSKIT = 5,
+  CURLSSLBACKEND_POLARSSL = 6,
+  CURLSSLBACKEND_WOLFSSL = 7,
+  CURLSSLBACKEND_SCHANNEL = 8,
+  CURLSSLBACKEND_DARWINSSL = 9,
+  CURLSSLBACKEND_AXTLS = 10,
+  CURLSSLBACKEND_MBEDTLS = 11
+} curl_sslbackend;
+
+.B "CURLsslset curl_global_sslset(curl_sslbackend " id,
+.B "                              const char *" name,
+.B "                              curl_ssl_backend ***" avail ");"
+.fi
+.SH DESCRIPTION
+This function configures at runtime which SSL backend to use with
+libcurl. This function can only be used to select an SSL backend once, and it
+must be called \fBbefore\fP \fIcurl_global_init(3)\fP.
+
+The backend can be identified by the \fIid\fP
+(e.g. \fBCURLSSLBACKEND_OPENSSL\fP). The backend can also be specified via the
+\fIname\fP parameter for a case insensitive match (passing -1 as \fIid\fP). If
+both \fIid\fP and \fIname\fP are specified, the \fIname\fP will be ignored.
+
+If neither \fIid\fP nor \fPname\fP are specified, the function will fail with
+CURLSSLSET_UNKNOWN_BACKEND and set the \fIavail\fP pointer to the
+NULL-terminated list of available backends. The available backends are those
+that this particular build of libcurl supports.
+
+Upon success, the function returns CURLSSLSET_OK.
+
+If the specified SSL backend is not available, the function returns
+CURLSSLSET_UNKNOWN_BACKEND and sets the \fIavail\fP pointer to a
+NULL-terminated list of available SSL backends. In this case, you may call the
+function again to try to select a different backend.
+
+The SSL backend can be set only once. If it has already been set, a subsequent
+attempt to change it will result in a \fBCURLSSLSET_TOO_LATE\fP.
+
+\fBThis function is not thread safe.\fP You must not call it when any other
+thread in the program (i.e. a thread sharing the same memory) is running.
+This doesn't just mean no other thread that is using libcurl.
+
+.SH AVAILABILITY
+This function was added in libcurl 7.56.0. Before this version, there was no
+support for choosing SSL backends at runtime.
+.SH RETURN VALUE
+If this function returns CURLSSLSET_OK, the backend was successfully selected.
+
+If the chosen backend is unknown (or support for the chosed backend has not
+been compiled into libcurl), the function returns 
\fICURLSSLSET_UNKNOWN_BACKEND\fP.
+
+If the backend had been configured previously, or if \fIcurl_global_init(3)\fP
+has already been called, the function returns \fICURLSSLSET_TOO_LATE\fP.
+
+If this libcurl was built completely without SSL support, with no backends at
+all, this function returns \fICURLSSLSET_NO_BACKENDS\fP.
+.SH "SEE ALSO"
+.BR curl_global_init "(3), "
+.BR libcurl "(3) "
diff --git a/docs/libcurl/gnurl_mime_addpart.3 
b/docs/libcurl/gnurl_mime_addpart.3
new file mode 100644
index 000000000..22350668a
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_addpart.3
@@ -0,0 +1,66 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, 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 curl_mime_addpart 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_addpart - append a new empty part to a mime structure
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "curl_mimepart * curl_mime_addpart(curl_mime * " mime ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_addpart(3)\fP creates and appends a new empty part to the given
+mime structure and returns a handle to it.  The returned part handle can
+subsequently be populated using functions from the mime API.
+
+\fImime\fP is the handle of the mime structure in which the new part must be
+appended.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+A mime part structure handle, or NULL upon failure.
+.SH EXAMPLE
+.nf
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* continue and set name + data to the part */
+ curl_mime_data(part, "This is the field data", CURL_ZERO_TERMINATED);
+ curl_mime_name(part, "data");
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_init "(3),"
+.BR curl_mime_name "(3),"
+.BR curl_mime_data "(3),"
+.BR curl_mime_data_cb "(3),"
+.BR curl_mime_filedata "(3),"
+.BR curl_mime_filename "(3),"
+.BR curl_mime_subparts "(3),"
+.BR curl_mime_type "(3),"
+.BR curl_mime_headers "(3),"
+.BR curl_mime_encoder "(3)"
diff --git a/docs/libcurl/gnurl_mime_data.3 b/docs/libcurl/gnurl_mime_data.3
new file mode 100644
index 000000000..d2112f2d4
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_data.3
@@ -0,0 +1,69 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, 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 curl_mime_data 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_data - set a mime part's body data from memory
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_data(curl_mimepart * " part ", const char * " data
+.BI ", size_t " datasize ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_data(3)\fP sets a mime part's body content from memory data.
+
+\fIdata\fP points to the data bytes: those are copied to the part and their
+storage may safely be reused after call.
+\fIdatasize\fP is the number of data bytes: it can be set to
+\fICURL_ZERO_TERMINATED\fP to indicate \fIdata\fP is a nul-terminated
+character string.
+\fIpart\fP is the part's to assign contents to.
+
+Setting a part's contents twice is valid: only the value set by the last call
+is retained. It is possible to unassign part's contents by setting
+\fIdata\fP to NULL.
+
+Setting very large data is memory consuming: one might consider using
+\fIcurl_mime_data_cb(3)\fP in such a case.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+.nf
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* add data to the part  */
+ curl_mime_data(part, "raw contents to send", CURL_ZERO_TERMINATED);
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_data_cb "(3),"
+.BR curl_mime_name "(3),"
+.BR curl_mime_type "(3)"
diff --git a/docs/libcurl/gnurl_mime_data_cb.3 
b/docs/libcurl/gnurl_mime_data_cb.3
new file mode 100644
index 000000000..bc74a85a5
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_data_cb.3
@@ -0,0 +1,160 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, 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 curl_mime_data_cb 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_data_cb - set a callback-based data source for a mime part's body
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+size_t readfunc(char *buffer, size_t size, size_t nitems, void *arg);
+.br
+int seekfunc(void *arg, curl_off_t offset, int origin);
+.br
+void freefunc(void *arg);
+.sp
+.BI "CURLcode curl_mime_data(curl_mimepart * " part ", curl_off_t " datasize ,
+.br
+.BI "        curl_read_callback " readfunc ", curl_seek_callback " seekfunc ,
+.br
+.BI "        curl_free_callback " freefunc ", void * " arg ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_data_cb(3)\fP sets the data source of a mime part's body content
+from a data read callback function.
+
+\fIpart\fP is the part's to assign contents to.
+
+\fIreadfunc\fP is a pointer to a data read callback function, with a signature
+as shown by the above prototype. It may not be set to NULL.
+
+\fIseekfunc\fP is a pointer to a seek callback function, with a signature as
+shown by the above prototype. This function will be used upon resending data
+(i.e.: after a redirect); this pointer may be set to NULL, in which case a
+resend is not possible.
+
+\fIfreefunc\fP is a pointer to a user resource freeing callback function, with
+a signature as shown by the above prototype. If no resource is to be freed, it
+may safely be set to NULL. This function will be called upon mime structure
+freeing.
+
+\fIarg\fP is a user defined argument to callback functions.
+
+The read callback function gets called by libcurl as soon as it needs to
+read data in order to send it to the peer - like if you ask it to upload or
+post data to the server. The data area pointed at by the pointer \fIbuffer\fP
+should be filled up with at most \fIsize\fP multiplied with \fInmemb\fP number
+of bytes by your function.
+
+Your read function must then return the actual number of bytes that it stored
+in that memory area. Returning 0 will signal end-of-file to the library and
+cause it to stop the current transfer.
+
+If you stop the current transfer by returning 0 "pre-maturely" (i.e before the
+server expected it, like when you've said you will upload N bytes and you
+upload less than N bytes), you may experience that the server "hangs" waiting
+for the rest of the data that won't come.
+
+The read callback may return \fICURL_READFUNC_ABORT\fP to stop the current
+operation immediately, resulting in a \fICURLE_ABORTED_BY_CALLBACK\fP error
+code from the transfer.
+
+The callback can return \fICURL_READFUNC_PAUSE\fP to cause reading from this
+connection to pause. See \fIcurl_easy_pause(3)\fP for further details.
+
+The seek function gets called by libcurl to rewind input stream data or to
+seek to a certain position. The function shall work like fseek(3) or lseek(3)
+and it gets SEEK_SET, SEEK_CUR or SEEK_END as argument for \fIorigin\fP,
+although libcurl currently only passes SEEK_SET.
+
+The callback function must return \fICURL_SEEKFUNC_OK\fP on success,
+\fICURL_SEEKFUNC_FAIL\fP to cause the upload operation to fail or
+\fICURL_SEEKFUNC_CANTSEEK\fP to indicate that while the seek failed, libcurl
+is free to work around the problem if possible. The latter can sometimes be
+done by instead reading from the input or similar.
+
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+Sending a huge data string will cause the same amount of memory to be
+allocated: to avoid overhead resources consumption, one might want to use a
+callback source to avoid data duplication. In this case, original data
+must be retained until after the transfer terminates.
+.nf
+
+char hugedata[512000];
+
+struct ctl {
+  char *buffer;
+  curl_off_t size;
+  curl_off_t position;
+};
+
+size_t read_callback(char *buffer, size_t size, size_t nitems, void *arg)
+{
+  struct ctl *p = (struct ctl *) arg;
+  curl_off_t sz = p->size - p->position;
+
+  nitems *= size;
+  if(sz > nitems)
+    sz = nitems;
+  if(sz)
+    memcpy(buffer, p->buffer + p->position, sz);
+  p->position += sz;
+  return sz;
+}
+
+int seek_callback(void *arg, curl_off_t offset, int origin)
+{
+  struct ctl *p = (struct ctl *) arg;
+
+  switch(origin) {
+  case SEEK_END:
+    offset += p->size;
+    break;
+  case SEEK_CUR:
+    offset += p->position;
+    break;
+  }
+
+  if(offset < 0)
+    return CURL_SEEKFUNC_FAIL;
+  p->position = offset;
+  return CURL_SEEKFUNC_OK;
+}
+
+ CURL *easy = curl_easy_init();
+ curl_mime *mime = curl_mime_init(easy);
+ curl_mimepart *part = curl_mime_addpart(mime);
+ struct ctl hugectl;
+
+ hugectl.buffer = hugedata;
+ hugectl.size = sizeof hugedata;
+ hugectl.position = 0;
+ curl_mime_data_cb(part, hugectl.size, read_callback, seek_callback, NULL,
+                   &hugectl);
+
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_data "(3),"
+.BR curl_mime_name "(3)"
diff --git a/docs/libcurl/gnurl_mime_encoder.3 
b/docs/libcurl/gnurl_mime_encoder.3
new file mode 100644
index 000000000..c17cf25b3
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_encoder.3
@@ -0,0 +1,97 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, 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 curl_mime_encoder 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_encoder - set a mime part's encoder and content transfer encoding
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_encoder(curl_mimepart * " part ,
+.BI "const char * " encoding ");"
+.ad
+.SH DESCRIPTION
+curl_mime_encoder() requests a mime part's content to be encoded before being
+transmitted.
+
+\fIpart\fP is the part's handle to assign an encoder.
+\fIencoding\fP is a pointer to a zero-terminated encoding scheme. It may be
+set to NULL to disable an encoder previously attached to the part. The encoding
+scheme storage may safely be reused after this function returns.
+
+Setting a part's encoder twice is valid: only the value set by the last call is
+retained.
+
+Upon multipart rendering, the part's content is encoded according to the
+pertaining scheme and a corresponding \fIContent-Transfer-Encoding"\fP header
+is added to the part.
+
+Supported encoding schemes are:
+.br
+"\fIbinary\fP": the data is left unchanged, the header is added.
+.br
+"\fI8bit\fP": header added, no data change.
+.br
+"\fI7bit\fP": the data is unchanged, but is each byte is checked
+to be a 7-bit value; if not, a read error occurs.
+.br
+"\fIbase64\fP": Data is converted to base64 encoding, then split in
+CRLF-terminated lines of at most 76 characters.
+.br
+"\fIquoted-printable\fP": data is encoded in quoted printable lines of
+at most 76 characters. Since the resulting size of the final data cannot be
+determined prior to reading the original data, it is left as unknown, causing
+chunked transfer in HTTP. For the same reason, this encoder may not be used
+with IMAP. This encoder targets text data that is mostly ASCII and should
+not be used with other types of data.
+
+If the original data is already encoded in such a scheme, a custom
+\fIContent-Transfer-Encoding\fP header should be added with
+\FIcurl_mime_headers\fP() instead of setting a part encoder.
+
+Encoding should not be applied to multiparts, thus the use of this
+function on a part with content set with \fIcurl_mime_subparts\fP() is
+strongly discouraged.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+.nf
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* send a file */
+ curl_mime_filedata(part, "image.png");
+
+ /* encode file data in base64 for transfer */
+ curl_mime_encoder(part, "base64");
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_headers "(3),"
+.BR curl_mime_subparts "(3)"
diff --git a/docs/libcurl/gnurl_mime_filedata.3 
b/docs/libcurl/gnurl_mime_filedata.3
new file mode 100644
index 000000000..9a57068de
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_filedata.3
@@ -0,0 +1,77 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, 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 curl_mime_filedata 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_filedata - set a mime part's body data from a file contents
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_filedata(curl_mimepart * " part ,
+.BI " const char * " filename ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_filedata(3)\fP sets a mime part's body content from the named
+file's contents. This is an alernative to \fIcurl_mime_data(3)\fP for setting
+data to a mime part.
+
+\fIpart\fP is the part's to assign contents to.
+
+\fIfilename\fP points to the nul-terminated file's path name. The pointer can
+be NULL to detach previous part contents settings.  Filename storage can be
+safely be reused after this call.
+
+As a side effect, the part's remote file name is set to the base name of the
+given \fIfilename\fP if it is a valid named file. This can be undone or
+overriden by a subsequent call to \fIcurl_mime_filename(3)\fP.
+
+The contents of the file is read during the file transfer in a streaming
+manner to allow huge files to get transfered without using much memory. It
+therefore requires that the file is kept intact during the entire request.
+
+Setting a part's contents twice is valid: only the value set by the last call
+is retained.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+.nf
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* send data from this file */
+ curl_mime_filedata(part, "image.png");
+
+ /* set name */
+ curl_mime_name(part, "data");
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_data "(3),"
+.BR curl_mime_filename "(3),"
+.BR curl_mime_name "(3)"
diff --git a/docs/libcurl/gnurl_mime_filename.3 
b/docs/libcurl/gnurl_mime_filename.3
new file mode 100644
index 000000000..42916e598
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_filename.3
@@ -0,0 +1,72 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, 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 curl_mime_filename 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_filename - set a mime part's remote file name
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_filename(curl_mimepart * " part ,
+.BI "const char * " filename ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_filename(3)\fP sets a mime part's remote file name. When remote
+file name is set, content data is processed as a file, whatever is the part's
+content source. A part's remote file name is transmitted to the server in the
+associated Content-Disposition generated header.
+
+\fIpart\fP is the part's handle to assign the remote file name to.
+
+\fIfilename\fP points to the nul-terminated file name string; it may be set to
+NULL to remove a previously attached remote file name.
+
+The remote file name string is copied into the part, thus the associated
+storage may safely be released or reused after call. Setting a part's file
+name twice is valid: only the value set by the last call is retained.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+.nf
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* send image data from memory */
+ curl_mime_data(part, imagebuf, imagebuf_len);
+
+ /* set a file name to make it look like a file upload */
+ curl_mime_filename(part, "image.png");
+
+ /* set name */
+ curl_mime_name(part, "data");
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_filedata "(3),"
+.BR curl_mime_data "(3)"
diff --git a/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3 
b/docs/libcurl/gnurl_mime_free.3
similarity index 56%
copy from docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3
copy to docs/libcurl/gnurl_mime_free.3
index 88ae1397e..9394b5748 100644
--- a/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3
+++ b/docs/libcurl/gnurl_mime_free.3
@@ -19,38 +19,30 @@
 .\" * KIND, either express or implied.
 .\" *
 .\" **************************************************************************
-.\"
-.TH CURLOPT_REQUEST_TARGET 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt 
options"
+.TH curl_mime_free 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
 .SH NAME
-CURLOPT_REQUEST_TARGET \- specify an alternative target for this request
+curl_mime_free - free a previously built mime structure
 .SH SYNOPSIS
-#include <gnurl/curl.h>
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REQUEST_TARGET, string);
+.B #include <curl/curl.h>
+.sp
+.BI "void curl_mime_free(curl_mime *" mime);
+.ad
 .SH DESCRIPTION
-Pass a char * to string which libcurl uses in the upcoming request instead of
-the path as extracted from the URL.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
-  curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/*";);
-  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "OPTIONS");
+\fIcurl_mime_free(3)\fP is used to clean up data previously built/appended
+with \fIcurl_mime_addpart(3)\fP and other mime-handling functions.  This must
+be called when the data has been used, which typically means after
+\fIcurl_easy_perform(3)\fP has been called.
+
+The handle to free is the one you passed to
+the \fICURLOPT_MIMEPOST(3)\fP option: attached subparts mime structures must
+not be explicitly freed as they are by the top structure freeing.
 
-  /* issue an OPTIONS * request (no leading slash) */
-  curl_easy_setopt(curl, CURLOPT_REQUEST_TARGET, "*");
+\fBmime\fP is the handle as returned from a previous call to
+\fIcurl_mime_init(3)\fP and may be NULL.
 
-  /* Perform the request */
-  curl_easy_perform(curl);
-}
-.fi
 .SH AVAILABILITY
-Added in 7.55.0
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
 .SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+None
 .SH "SEE ALSO"
-.BR CURLOPT_CUSTOMREQUEST "(3), " CURLOPT_HTTPGET "(3), "
+.BR curl_mime_init "(3)"
diff --git a/docs/libcurl/gnurl_mime_headers.3 
b/docs/libcurl/gnurl_mime_headers.3
new file mode 100644
index 000000000..1d02e1ee5
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_headers.3
@@ -0,0 +1,65 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, 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 curl_mime_headers 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_headers - set a mime part's custom headers
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_headers(curl_mimepart * " part ,
+.BI "struct curl_slist * " headers ", int " take_ownership ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_headers(3)\fP sets a mime part's custom headers.
+
+\fIpart\fP is the part's handle to assign the custom headers list to.
+
+\fIheaders\fP is the head of a list of custom headers; it may be set to NULL
+to remove a previously attached custom header list.
+
+\fItake_ownership\fP: when non-zero, causes the list to be freed upon
+replacement or mime structure deletion; in this case the list must not be
+freed explicitly.
+
+Setting a part's custom headers list twice is valid: only the value set by
+the last call is retained.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+.nf
+ struct curl_slist *headers = NULL;
+
+ headers = curl_slist_append("Custom-Header: mooo", headers);
+
+ /* use these headers, please take ownership */
+ curl_mime_headers(part, headers, TRUE);
+
+ /* pass on this data */
+ curl_mime_data(part, "12345679", CURL_ZERO_TERMINATED);
+
+ /* set name */
+ curl_mime_name(part, "numbers");
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3)"
diff --git a/docs/libcurl/gnurl_mime_init.3 b/docs/libcurl/gnurl_mime_init.3
new file mode 100644
index 000000000..469f02b7c
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_init.3
@@ -0,0 +1,69 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, 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 curl_mime_init 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_init - create a mime handle
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "curl_mime * curl_mime_init(CURL * " easy_handle ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_init(3)\fP creates a handle to a new empty mime structure
+intended to be used with \fIeasy_handle\fP. This mime structure can be
+subsequently filled using the mime API, then attached to \fIeasy_handle\fP
+using option \fICURLOPT_MIMEPOST(3)\fP within a \fIcurl_easy_setopt(3)\fP
+call.
+
+Using a mime handle is the recommended way to post an HTTP form, format and
+send a multi-part e-mail with SMTP or upload such an e-mail to an IMAP server.
+
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+A mime struct handle, or NULL upon failure.
+.SH EXAMPLE
+.nf
+
+ CURL *easy = curl_easy_init();
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* Build an HTTP form with a single field named "data", */
+ mime = curl_mime_init(easy);
+ part = curl_mime_addpart(mime);
+ curl_mime_data(part, "This is the field data", CURL_ZERO_TERMINATED);
+ curl_mime_name(part, "data");
+
+ /* Post and send it. */
+ curl_easy_setopt(easy, CURLOPT_MIMEPOST, mime);
+ curl_easy_setopt(easy, CURLOPT_URL, "http://example.com";);
+ curl_easy_perform(easy);
+
+ /* Clean-up. */
+ curl_easy_cleanup(easy);
+ curl_mime_free(mime);
+
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_free "(3),"
+.BR CURLOPT_MIMEPOST "(3)"
diff --git a/docs/libcurl/opts/GNURLINFO_SPEED_UPLOAD_T.3 
b/docs/libcurl/gnurl_mime_name.3
similarity index 51%
copy from docs/libcurl/opts/GNURLINFO_SPEED_UPLOAD_T.3
copy to docs/libcurl/gnurl_mime_name.3
index 5a8ba22f7..f821d9082 100644
--- a/docs/libcurl/opts/GNURLINFO_SPEED_UPLOAD_T.3
+++ b/docs/libcurl/gnurl_mime_name.3
@@ -19,40 +19,45 @@
 .\" * KIND, either express or implied.
 .\" *
 .\" **************************************************************************
-.\"
-.TH CURLINFO_SPEED_UPLOAD_T 3 "25 May 2017" "libcurl 7.55.0" 
"curl_easy_getinfo options"
+.TH curl_mime_name 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
 .SH NAME
-CURLINFO_SPEED_UPLOAD_T \- get upload speed
+curl_mime_name - set a mime part's name
 .SH SYNOPSIS
-#include <gnurl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_UPLOAD_T, curl_off_t 
*speed);
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_name(curl_mimepart * " part ", const char * " name ");"
+.ad
 .SH DESCRIPTION
-Pass a pointer to a \fIcurl_off_t\fP to receive the average upload speed that
-curl measured for the complete upload. Measured in bytes/second.
-.SH PROTOCOLS
+\fIcurl_mime_name(3)\fP sets a mime part's name. This is the way HTTP form
+fields are named.
+
+\fIpart\fP is the part's handle to assign a name to.
+
+\fIname\fP points to the zero-terminated name string.
+
+The name string is copied into the part, thus the associated storage may
+safely be released or reused after call. Setting a part's name twice is valid:
+only the value set by the last call is retained. It is possible to "unname" a
+part by setting \fIname\fP to NULL.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
 .SH EXAMPLE
 .nf
-CURL *curl = curl_easy_init();
-if(curl) {
-  curl_easy_setopt(curl, CURLOPT_URL, "http://example.com";);
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
 
-  /* Perform the request */
-  res = curl_easy_perform(curl);
+ /* add a part */
+ part = curl_mime_addpart(mime);
 
-  if(!res) {
-    curl_off_t speed;
-    res = curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD_T, &speed);
-    if(!res) {
-      printf("Upload speed " CURL_FORMAT_CURL_OFF_T " bytes/sec\\n", ul);
-    }
-  }
-}
+ /* give the part a name */
+ curl_mime_name(part, "shoe_size");
 .fi
-.SH AVAILABILITY
-Added in 7.55.0
-.SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
 .SH "SEE ALSO"
-.BR curl_easy_getinfo "(3), " curl_easy_setopt "(3), "
-.BR CURLINFO_SPEED_DOWNLOAD_T "(3), "
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_data "(3),"
+.BR curl_mime_type "(3)"
diff --git a/docs/libcurl/opts/GNURLINFO_SPEED_DOWNLOAD_T.3 
b/docs/libcurl/gnurl_mime_subparts.3
similarity index 53%
copy from docs/libcurl/opts/GNURLINFO_SPEED_DOWNLOAD_T.3
copy to docs/libcurl/gnurl_mime_subparts.3
index 262d3b90f..d5d46febb 100644
--- a/docs/libcurl/opts/GNURLINFO_SPEED_DOWNLOAD_T.3
+++ b/docs/libcurl/gnurl_mime_subparts.3
@@ -19,41 +19,35 @@
 .\" * KIND, either express or implied.
 .\" *
 .\" **************************************************************************
-.\"
-.TH CURLINFO_SPEED_DOWNLOAD_T 3 "28 Aug 2015" "libcurl 7.44.0" 
"curl_easy_getinfo options"
+.TH curl_mime_subparts 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
 .SH NAME
-CURLINFO_SPEED_DOWNLOAD_T \- get download speed
+curl_mime_subparts - set subparts of a multipart mime part
 .SH SYNOPSIS
-#include <gnurl/curl.h>
-
-CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_DOWNLOAD_T, curl_off_t 
*speed);
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_subparts(curl_mimepart * " part ,
+.BI "curl_mime * " subparts ");"
+.ad
 .SH DESCRIPTION
-Pass a pointer to a \fIcurl_off_t\fP to receive the average download speed
-that curl measured for the complete download. Measured in bytes/second.
-.SH PROTOCOLS
-.SH EXAMPLE
-.nf
-CURL *curl = curl_easy_init();
-if(curl) {
-  curl_easy_setopt(curl, CURLOPT_URL, "http://example.com";);
+\fIcurl_mime_subparts(3)\fP sets a multipart mime part's content from a mime
+structure.
 
-  /* Perform the request */
-  res = curl_easy_perform(curl);
+\fIpart\fP is a handle to the multipart part.
 
-  if(!res) {
-    curl_off_t speed;
-    res = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD_T, &speed);
-    if(!res) {
-      printf("Download speed " CURL_FORMAT_CURL_OFF_T " bytes/sec\\n", ul);
-    }
-  }
-}
-.fi
+\fIsubparts\fP is a mime structure handle holding the subparts. After
+\fIcurl_mime_subparts\fP succeeds, the mime structure handle belongs to the
+multipart part and must not be freed explicitly. It may however be updated by
+subsequent calls to mime API functions.
+
+Setting a part's contents twice is valid: only the value set by the last call
+is retained. It is possible to unassign previous part's contents by setting
+\fIsubparts\fP to NULL.
 .SH AVAILABILITY
-Added in 7.55.0
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
 .SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+TODO
 .SH "SEE ALSO"
-.BR curl_easy_getinfo "(3), " curl_easy_setopt "(3), "
-.BR CURLINFO_SPEED_UPLOAD "(3), "
-.BR CURLINFO_SIZE_UPLOAD_T "(3), "
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_init "(3)"
diff --git a/docs/libcurl/gnurl_mime_type.3 b/docs/libcurl/gnurl_mime_type.3
new file mode 100644
index 000000000..59841d5bd
--- /dev/null
+++ b/docs/libcurl/gnurl_mime_type.3
@@ -0,0 +1,83 @@
+.\" **************************************************************************
+.\" *                                  _   _ ____  _
+.\" *  Project                     ___| | | |  _ \| |
+.\" *                             / __| | | | |_) | |
+.\" *                            | (__| |_| |  _ <| |___
+.\" *                             \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2017, 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 curl_mime_type 3 "22 August 2017" "libcurl 7.56.0" "libcurl Manual"
+.SH NAME
+curl_mime_type - set a mime part's content type
+.SH SYNOPSIS
+.B #include <curl/curl.h>
+.sp
+.BI "CURLcode curl_mime_type(curl_mimepart * " part ,
+.BI "const char * " mimetype ");"
+.ad
+.SH DESCRIPTION
+\fIcurl_mime_type(3)\fP sets a mime part's content type.
+
+\fIpart\fP is the part's handle to assign the content type to.
+
+\fImimetype\fP points to the nul-terminated file mime type string; it may be
+set to NULL to remove a previously attached mime type.
+
+The mime type string is copied into the part, thus the associated storage may
+safely be released or reused after call. Setting a part's type twice is valid:
+only the value set by the last call is retained.
+
+In the absence of a mime type and if needed by the protocol specifications,
+a default mime type is determined by the context:
+.br
+- If set as a custom header, use this value.
+.br
+- application/form-data for a HTTP form post.
+.br
+- If a remote file name is set, the mime type is taken from the file name
+extension, or application/octet-stream by default.
+.br
+- For a multipart part, multipart/mixed.
+.br
+- text/plain in other cases.
+.SH AVAILABILITY
+As long as at least one of HTTP, SMTP or IMAP is enabled. Added in 7.56.0.
+.SH RETURN VALUE
+CURLE_OK or a CURL error code upon failure.
+.SH EXAMPLE
+.nf
+ curl_mime *mime;
+ curl_mimepart *part;
+
+ /* create a mime handle */
+ mime = curl_mime_init(easy);
+
+ /* add a part */
+ part = curl_mime_addpart(mime);
+
+ /* get data from this file */
+ curl_mime_filedata(part, "image.png");
+
+ /* content-type for this part */
+ curl_mime_type(part, "image/png");
+
+ /* set name */
+ curl_mime_name(part, "image");
+.fi
+.SH "SEE ALSO"
+.BR curl_mime_addpart "(3),"
+.BR curl_mime_name "(3),"
+.BR curl_mime_data "(3)"
diff --git a/docs/libcurl/gnurl_version_info.3 
b/docs/libcurl/gnurl_version_info.3
index fb590f954..35d7f4522 100644
--- a/docs/libcurl/gnurl_version_info.3
+++ b/docs/libcurl/gnurl_version_info.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2015, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2017, 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
@@ -156,6 +156,10 @@ libcurl ignore cookies with a domain that's on the list.
 .IP CURL_VERSION_HTTPS_PROXY
 libcurl was built with support for HTTPS-proxy.
 (Added in 7.52.0)
+.IP CURL_VERSION_MULTI_SSL
+libcurl was built with multiple SSL backends. For details, see
+\fIcurl_global_sslset(3)\fP.
+(Added in 7.56.0)
 .RE
 \fIssl_version\fP is an ASCII string for the OpenSSL version used. If libcurl
 has no SSL support, this is NULL.
diff --git a/docs/libcurl/libgnurl-tutorial.3 b/docs/libcurl/libgnurl-tutorial.3
index cbfb081dc..187d5ca0f 100644
--- a/docs/libcurl/libgnurl-tutorial.3
+++ b/docs/libcurl/libgnurl-tutorial.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2014, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2017, 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
@@ -477,14 +477,67 @@ multi-part because they're built by a chain of parts, 
each part being a single
 unit of data. Each part has its own name and contents. You can in fact create
 and post a multi-part formpost with the regular libcurl POST support described
 above, but that would require that you build a formpost yourself and provide
-to libcurl. To make that easier, libcurl provides \fIcurl_formadd(3)\fP. Using
-this function, you add parts to the form. When you're done adding parts, you
-post the whole form.
+to libcurl. To make that easier, libcurl provides a MIME API consisting in
+several functions: using those, you can create and fill a multi-part form.
+Function \fIcurl_mime_init(3)\fP creates a multi-part body; you can then
+append new parts to a multi-part body using \fIcurl_mime_addpart(3)\fP.
+There are three possible data sources for a part: memory using
+\fIcurl_mime_data(3)\fP, file using \fIcurl_mime_filedata(3)\fP and
+user-defined data read callback using \fIcurl_mime_data_cb(3)\fP.
+\fIcurl_mime_name(3)\fP sets a part's (i.e.: form field) name, while
+\fIcurl_mime_filename(3)\fP fills in the remote file name. With
+\fIcurl_mime_type(3)\fP, you can tell the MIME type of a part,
+\fIcurl_mime_headers(3)\fP allows defining the part's headers. When a
+multi-part body is no longer needed, you can destroy it using
+\fIcurl_mime_free(3)\fP.
 
 The following example sets two simple text parts with plain textual contents,
 and then a file with binary contents and uploads the whole thing.
 
 .nf
+ curl_mime *multipart = curl_mime_init(easyhandle);
+ curl_mimepart *part = curl_mime_addpart(mutipart);
+ curl_mime_name(part, "name");
+ curl_mime_data(part, "daniel", CURL_ZERO_TERMINATED);
+ part = curl_mime_addpart(mutipart);
+ curl_mime_name(part, "project");
+ curl_mime_data(part, "curl", CURL_ZERO_TERMINATED);
+ part = curl_mime_addpart(mutipart);
+ curl_mime_name(part, "logotype-image");
+ curl_mime_filedata(part, "curl.png");
+ 
+ /* Set the form info */
+ curl_easy_setopt(easyhandle, CURLOPT_MIMEPOST, multipart);
+
+ curl_easy_perform(easyhandle); /* post away! */
+
+ /* free the post data again */
+ curl_mime_free(multipart);
+.fi
+
+To post multiple files for a single form field, you must supply each file in
+a separate part, all with the same field name. Although function
+\fIcurl_mime_subparts(3)\fP implements nested muti-parts, this way of
+multiple files posting is deprecated by RFC 7578, chapter 4.3.
+
+To set the data source from an already opened FILE pointer, use:
+
+.nf
+ curl_mime_data_cb(part, filesize, (curl_read_callback) fread,
+                   (curl_seek_callback) fseek, NULL, filepointer);
+.fi
+
+A deprecated \fIcurl_formadd(3)\fP function is still supported in libcurl.
+It should however not be used anymore for new designs and programs using it
+ought to be converted to the MIME API. It is however described here as an
+aid to conversion.
+
+Using \fIcurl_formadd\fP, you add parts to the form. When you're done adding
+parts, you post the whole form.
+
+The MIME API example above is expressed as follows using this function:
+
+.nf
  struct curl_httppost *post=NULL;
  struct curl_httppost *last=NULL;
  curl_formadd(&post, &last,
@@ -542,6 +595,136 @@ request. You force an easyhandle to go back to GET by 
using the
 Just setting \fICURLOPT_POSTFIELDS(3)\fP to "" or NULL will *not* stop libcurl
 from doing a POST. It will just make it POST without any data to send!
 
+.SH "Converting from deprecated form API to MIME API"
+Four rules have to be respected in building the multi-part:
+.br
+- The easy handle must be created before building the multi-part.
+.br
+- The multi-part is always created by a call to curl_mime_init(easyhandle).
+.br
+- Each part is created by a call to curl_mime_addpart(multipart).
+.br
+- When complete, the multi-part must be bound to the easy handle using
+\fICURLOPT_MIMEPOST(3)\fP instead of \fICURLOPT_HTTPPOST(3)\fP.
+
+Here are some example of \fIcurl_formadd\fP calls to MIME API sequences:
+
+.nf
+ curl_formadd(&post, &last,
+              CURLFORM_COPYNAME, "id",
+              CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END);
+              CURLFORM_CONTENTHEADER, headers,
+              CURLFORM_END);
+.fi
+becomes:
+.nf
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "id");
+ curl_mime_data(part, "daniel", CURL_ZERO_TERMINATED);
+ curl_mime_headers(part, headers, FALSE);
+.fi
+
+Setting the last \fIcurl_mime_headers\fP argument to TRUE would have caused
+the headers to be automatically released upon destroyed the multi-part, thus
+saving a clean-up call to \fIcurl_slist_free_all(3)\fP.
+
+.nf
+ curl_formadd(&post, &last,
+              CURLFORM_PTRNAME, "logotype-image",
+              CURLFORM_FILECONTENT, "-",
+              CURLFORM_END);
+.fi
+becomes:
+.nf
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "logotype-image");
+ curl_mime_data_cb(part, (curl_off_t) -1, fread, fseek, NULL, stdin);
+.fi
+
+\fIcurl_mime_name\fP always copies the field name. The special file name "-"
+is not supported by \fIcurl_mime_file\fP: to read an open file, use
+a callback source using fread(). The transfer will be chunked since the data
+size is unknown.
+
+.nf
+ curl_formadd(&post, &last,
+              CURLFORM_COPYNAME, "datafile[]",
+              CURLFORM_FILE, "file1",
+              CURLFORM_FILE, "file2",
+              CURLFORM_END);
+.fi
+becomes:
+.nf
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "datafile[]");
+ curl_mime_filedata(part, "file1");
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "datafile[]");
+ curl_mime_filedata(part, "file2");
+.fi
+
+The deprecated multipart/mixed implementation of multiple files field is
+translated to two distinct parts with the same name.
+
+.nf
+ curl_easy_setopt(easyhandle, CURLOPT_READFUNCTION, myreadfunc);
+ curl_formadd(&post, &last,
+              CURLFORM_COPYNAME, "stream",
+              CURLFORM_STREAM, arg,
+              CURLFORM_CONTENTLEN, (curl_off_t) datasize,
+              CURLFORM_FILENAME, "archive.zip",
+              CURLFORM_CONTENTTYPE, "application/zip",
+              CURLFORM_END);
+.fi
+becomes:
+.nf
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "stream");
+ curl_mime_data_cb(part, (curl_off_t) datasize,
+                   myreadfunc, NULL, NULL, arg);
+ curl_mime_filename(part, "archive.zip");
+ curl_mime_type(part, "application/zip");
+.fi
+
+\fICURLOPT_READFUNCTION\fP callback is not used: it is replace by directly
+setting the part source data from the callback read function.
+
+.nf
+ curl_formadd(&post, &last,
+              CURLFORM_COPYNAME, "memfile",
+              CURLFORM_BUFFER, "memfile.bin",
+              CURLFORM_BUFFERPTR, databuffer,
+              CURLFORM_BUFFERLENGTH, (long) sizeof databuffer,
+              CURLFORM_END);
+.fi
+becomes:
+.nf
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "memfile");
+ curl_mime_data(part, databuffer, (curl_off_t) sizeof databuffer);
+ curl_mime_filename(part, "memfile.bin");
+.fi
+
+\fIcurl_mime_data\fP always copies the initial data: data buffer is thus
+free for immediate reuse.
+
+.nf
+ curl_formadd(&post, &last,
+              CURLFORM_COPYNAME, "message",
+              CURLFORM_FILECONTENT, "msg.txt",
+              CURLFORM_END);
+.fi
+becomes:
+.nf
+ part = curl_mime_addpart(multipart);
+ curl_mime_name(part, "message");
+ curl_mime_filedata(part, "msg.txt");
+ curl_mime_filename(part, NULL);
+.fi
+
+Use of \fIcurl_mime_filedata\fP sets the remote file name as a side effect: it
+is therefore necessary to clear it for \fICURLFORM_FILECONTENT\fP emulation.
+
 .SH "Showing Progress"
 
 For historical and traditional reasons, libcurl has a built-in progress meter
@@ -1005,6 +1188,81 @@ When doing the "PORT" approach, libcurl will attempt to 
use the EPRT and the
 LPRT before trying PORT, as they work with more protocols. You can disable
 this behavior by setting \fICURLOPT_FTP_USE_EPRT(3)\fP to zero.
 
+.SH "MIME API revisited for SMTP and IMAP"
+In addition to support HTTP multi-part form fields, the MIME API can be used
+to build structured e-mail messages and send them via SMTP or append such
+messages to IMAP directories.
+
+A structured e-mail message may contain several parts: some are displayed
+inline by the MUA, some are attachments. Parts can also be structured as
+multi-part, for example to include another e-mail message or to offer several
+text formats alternatives. This can be nested to any level.
+
+To build such a message, you prepare the nth-level multi-part and then include
+it as a source to the parent multi-part using function
+\fIcurl_mime_subparts(3)\fP. Once it has been
+bound to its parent multi-part, a nth-level multi-part belongs to it and
+should not be freed explicitly.
+
+E-mail messages data is not supposed to be non-ascii and line length is
+limited: fortunately, some transfer encodings are defined by the standards
+to support the transmission of such incompatible data. Function
+\fIcurl_mime_encoder(3)\fP tells a part that its source data must be encoded
+before being sent. It also generates the corresponding header for that part.
+If the part data you want to send is already encoded in such a scheme,
+do not use this function (this would over-encode it), but explicitly set the
+corresponding part header.
+
+Upon sending such a message, libcurl prepends it with the header list
+set with \fICURLOPT_HTTPHEADER(3)\fP, as 0th-level mime part headers.
+
+Here is an example building an e-mail message with an inline plain/html text
+alternative and a file attachment encoded in base64:
+
+.nf
+ curl_mime *message = curl_mime_init(easyhandle);
+
+ /* The inline part is an alterative proposing the html and the text
+    versions of the e-mail. */
+ curl_mime *alt = curl_mime_init(easyhandle);
+
+ /* HTML message. */
+ curl_mimepart *part = curl_mime_addpart(alt);
+ curl_mime_data(part, "<html><body><p>This is HTML</p></body></html>",
+                      CURL_ZERO_TERMINATED);
+ curl_mime_type(part, "text/html");
+
+ /* Text message. */
+ part = curl_mime_addpart(alt);
+ curl_mime_data(part, "This is plain text message",
+                      CURL_ZERO_TERMINATED);
+
+ /* Create the inline part. */
+ part = curl_mime_addpart(message);
+ curl_mime_subparts(part, alt);
+ curl_mime_type(part, "multipart/alternative");
+ struct curl_slist *headers = curl_slist_append(NULL,
+                   "Content-Disposition: inline");
+ curl_mime_headers(part, headers, TRUE);
+
+ /* Add the attachment. */
+ part = curl_mime_addpart(message);
+ curl_mime_filedata(part, "manual.pdf");
+ curl_mime_encoder(part, "base64");
+
+ /* Build the mail headers. */
+ headers = curl_slist_append(NULL, "From: address@hidden");
+ headers = curl_slist_append(headers, "To: address@hidden");
+
+ /* Set these into the easy handle. */
+ curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers);
+ curl_easy_setopt(easyhandle, CURLOPT_MIMEPOST, mime);
+.fi
+
+It should be noted that appending a message to an IMAP directory requires
+the message size to be known prior upload. It is therefore not possible to
+include parts with unknown data size in this context.
+
 .SH "Headers Equal Fun"
 
 Some protocols provide "headers", meta-data separated from the normal
diff --git a/docs/libcurl/libgnurl.3 b/docs/libcurl/libgnurl.3
index 6618734b4..e8ecc31da 100644
--- a/docs/libcurl/libgnurl.3
+++ b/docs/libcurl/libgnurl.3
@@ -38,6 +38,10 @@ while using libcurl.  This essentially means you call
 \fIcurl_global_cleanup(3)\fP at the end.  See \fBGLOBAL CONSTANTS\fP below for
 details.
 
+If libcurl was compiled with support for multiple SSL backends, the function
+\fIcurl_global_sslset(3)\fP can be called before \fIcurl_global_init(3)\fP
+to select the active SSL backend.
+
 To transfer files, you create an "easy handle" using \fIcurl_easy_init(3)\fP
 for a single individual transfer (in either direction). You then set your
 desired set of options in that handle with \fIcurl_easy_setopt(3)\fP. Options
diff --git a/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3 
b/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3
index cfbe876d0..f418d13d7 100644
--- a/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3
+++ b/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLINFO_CONTENT_LENGTH_DOWNLOAD_T \- get content-length of download
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,
                            curl_off_t *content_length);
diff --git a/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_UPLOAD_T.3 
b/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_UPLOAD_T.3
index af92fd3df..04b7811f4 100644
--- a/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_UPLOAD_T.3
+++ b/docs/libcurl/opts/GNURLINFO_CONTENT_LENGTH_UPLOAD_T.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLINFO_CONTENT_LENGTH_UPLOAD_T \- get the specified size of the upload
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_CONTENT_LENGTH_UPLOAD_T,
                            curl_off_t *content_length);
diff --git a/docs/libcurl/opts/GNURLINFO_PROTOCOL.3 
b/docs/libcurl/opts/GNURLINFO_PROTOCOL.3
index e6dc4ac15..b82111876 100644
--- a/docs/libcurl/opts/GNURLINFO_PROTOCOL.3
+++ b/docs/libcurl/opts/GNURLINFO_PROTOCOL.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLINFO_PROTOCOL \- get the protocol used in the connection
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROTOCOL, long *p);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLINFO_PROXY_SSL_VERIFYRESULT.3 
b/docs/libcurl/opts/GNURLINFO_PROXY_SSL_VERIFYRESULT.3
index c148bf329..b6ef7d13e 100644
--- a/docs/libcurl/opts/GNURLINFO_PROXY_SSL_VERIFYRESULT.3
+++ b/docs/libcurl/opts/GNURLINFO_PROXY_SSL_VERIFYRESULT.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLINFO_PROXY_SSL_VERIFYRESULT \- get the result of the proxy certificate 
verification
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PROXY_SSL_VERIFYRESULT, long 
*result);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLINFO_SCHEME.3 
b/docs/libcurl/opts/GNURLINFO_SCHEME.3
index acc501f6d..38a3d15ba 100644
--- a/docs/libcurl/opts/GNURLINFO_SCHEME.3
+++ b/docs/libcurl/opts/GNURLINFO_SCHEME.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLINFO_SCHEME \- get the URL scheme (sometimes called protocol) used in the 
connection
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SCHEME, char **scheme);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLINFO_SIZE_DOWNLOAD_T.3 
b/docs/libcurl/opts/GNURLINFO_SIZE_DOWNLOAD_T.3
index e41411151..834c6d6f0 100644
--- a/docs/libcurl/opts/GNURLINFO_SIZE_DOWNLOAD_T.3
+++ b/docs/libcurl/opts/GNURLINFO_SIZE_DOWNLOAD_T.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLINFO_SIZE_DOWNLOAD_T \- get the number of downloaded bytes
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_DOWNLOAD_T, curl_off_t 
*dlp);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLINFO_SIZE_UPLOAD_T.3 
b/docs/libcurl/opts/GNURLINFO_SIZE_UPLOAD_T.3
index 813ef4913..2999be460 100644
--- a/docs/libcurl/opts/GNURLINFO_SIZE_UPLOAD_T.3
+++ b/docs/libcurl/opts/GNURLINFO_SIZE_UPLOAD_T.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLINFO_SIZE_UPLOAD_T \- get the number of uploaded bytes
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SIZE_UPLOAD_T, curl_off_t 
*uploadp);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLINFO_SPEED_DOWNLOAD_T.3 
b/docs/libcurl/opts/GNURLINFO_SPEED_DOWNLOAD_T.3
index 262d3b90f..413389c80 100644
--- a/docs/libcurl/opts/GNURLINFO_SPEED_DOWNLOAD_T.3
+++ b/docs/libcurl/opts/GNURLINFO_SPEED_DOWNLOAD_T.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLINFO_SPEED_DOWNLOAD_T \- get download speed
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_DOWNLOAD_T, curl_off_t 
*speed);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLINFO_SPEED_UPLOAD_T.3 
b/docs/libcurl/opts/GNURLINFO_SPEED_UPLOAD_T.3
index 5a8ba22f7..36389b34b 100644
--- a/docs/libcurl/opts/GNURLINFO_SPEED_UPLOAD_T.3
+++ b/docs/libcurl/opts/GNURLINFO_SPEED_UPLOAD_T.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLINFO_SPEED_UPLOAD_T \- get upload speed
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SPEED_UPLOAD_T, curl_off_t 
*speed);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.3 
b/docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.3
index b9ee4fff3..8b61854c0 100644
--- a/docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.3
+++ b/docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_ABSTRACT_UNIX_SOCKET \- set an abstract Unix domain socket
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ABSTRACT_UNIX_SOCKET, char 
*path);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_CAPATH.3 
b/docs/libcurl/opts/GNURLOPT_CAPATH.3
index dfef33b4d..bceffdc83 100644
--- a/docs/libcurl/opts/GNURLOPT_CAPATH.3
+++ b/docs/libcurl/opts/GNURLOPT_CAPATH.3
@@ -54,8 +54,9 @@ if(curl) {
 }
 .fi
 .SH AVAILABILITY
-This option is supported by the OpenSSL, GnuTLS and PolarSSL backends. The NSS
-backend provides the option only for backward compatibility.
+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.
 .SH RETURN VALUE
 CURLE_OK if supported; or an error such as:
 
diff --git a/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT.3 
b/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT.3
index 56b371292..3e3dca396 100644
--- a/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT.3
+++ b/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT.3
@@ -36,6 +36,9 @@ default built-in connection timeout - 300 seconds. See also 
the
 
 In unix-like systems, this might cause signals to be used unless
 \fICURLOPT_NOSIGNAL(3)\fP is set.
+
+If both \fICURLOPT_CONNECTTIMEOUT(3)\fP and \fICURLOPT_CONNECTTIMEOUT_MS(3)\fP
+are set, the value set last will be used.
 .SH DEFAULT
 300
 .SH PROTOCOLS
@@ -57,4 +60,5 @@ Always
 .SH RETURN VALUE
 Returns CURLE_OK
 .SH "SEE ALSO"
+.BR CURLOPT_CONNECTTIMEOUT_MS "(3), " 
 .BR CURLOPT_TIMEOUT "(3), " CURLOPT_LOW_SPEED_LIMIT "(3), "
diff --git a/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT_MS.3 
b/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT_MS.3
index 2d86042cc..7a7ee9302 100644
--- a/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT_MS.3
+++ b/docs/libcurl/opts/GNURLOPT_CONNECTTIMEOUT_MS.3
@@ -36,6 +36,9 @@ default built-in connection timeout - 300 seconds. See also 
the
 
 In unix-like systems, this might cause signals to be used unless
 \fICURLOPT_NOSIGNAL(3)\fP is set.
+
+If both \fICURLOPT_CONNECTTIMEOUT(3)\fP and \fICURLOPT_CONNECTTIMEOUT_MS(3)\fP
+are set, the value set last will be used.
 .SH DEFAULT
 300000
 .SH PROTOCOLS
@@ -57,4 +60,5 @@ Always
 .SH RETURN VALUE
 Returns CURLE_OK
 .SH "SEE ALSO"
+.BR CURLOPT_CONNECTTIMEOUT "(3), " 
 .BR CURLOPT_TIMEOUT "(3), " CURLOPT_LOW_SPEED_LIMIT "(3), "
diff --git a/docs/libcurl/opts/GNURLOPT_HTTPPOST.3 
b/docs/libcurl/opts/GNURLOPT_HTTPPOST.3
index 942045000..8cf6018b6 100644
--- a/docs/libcurl/opts/GNURLOPT_HTTPPOST.3
+++ b/docs/libcurl/opts/GNURLOPT_HTTPPOST.3
@@ -5,7 +5,7 @@
 .\" *                            | (__| |_| |  _ <| |___
 .\" *                             \___|\___/|_| \_\_____|
 .\" *
-.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+.\" * Copyright (C) 1998 - 2017, 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,6 +42,9 @@ You can disable this header with \fICURLOPT_HTTPHEADER(3)\fP.
 
 When setting \fICURLOPT_HTTPPOST(3)\fP, it will automatically set
 \fICURLOPT_NOBODY(3)\fP to 0.
+
+This option is deprecated! Do not use it. Use \fICURLOPT_MIMEPOST(3)\fP
+instead after having prepared mime data.
 .SH DEFAULT
 NULL
 .SH PROTOCOLS
@@ -71,9 +74,9 @@ curl_formadd(&formpost,
              CURLFORM_END);
 .fi
 .SH AVAILABILITY
-As long as HTTP is enabled
+As long as HTTP is enabled. Deprecated in 7.56.0.
 .SH RETURN VALUE
 Returns CURLE_OK if HTTP is enabled, and CURLE_UNKNOWN_OPTION if not.
 .SH "SEE ALSO"
-.BR CURLOPT_POSTFIELDS "(3), " CURLOPT_POST "(3), "
-.BR curl_formadd "(3), " curl_formfree "(3), "
+.BR CURLOPT_POSTFIELDS "(3), " CURLOPT_POST "(3), " CURLOPT_MIMEPOST "(3),"
+.BR curl_formadd "(3), " curl_formfree "(3), " curl_mime_init "(3)"
diff --git a/docs/libcurl/opts/GNURLOPT_INTERLEAVEDATA.3 
b/docs/libcurl/opts/GNURLOPT_INTERLEAVEDATA.3
index 232e64abf..79a059446 100644
--- a/docs/libcurl/opts/GNURLOPT_INTERLEAVEDATA.3
+++ b/docs/libcurl/opts/GNURLOPT_INTERLEAVEDATA.3
@@ -22,15 +22,16 @@
 .\"
 .TH CURLOPT_INTERLEAVEDATA 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt 
options"
 .SH NAME
-CURLOPT_INTERLEAVEDATA \- custom pointer to RTSP interleave callback
+CURLOPT_INTERLEAVEDATA \- custom pointer passed to RTSP interleave callback
 .SH SYNOPSIS
 #include <gnurl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_INTERLEAVEDATA, void *pointer);
 .SH DESCRIPTION
 This is the userdata \fIpointer\fP that will be passed to
-\fICURLOPT_INTERLEAVEFUNCTION(3)\fP when interleaved RTP data is
-received.
+\fICURLOPT_INTERLEAVEFUNCTION(3)\fP when interleaved RTP data is received. If
+the interleave function callback is not set, this pointer is not used
+anywhere.
 .SH DEFAULT
 NULL
 .SH PROTOCOLS
diff --git a/docs/libcurl/opts/GNURLOPT_INTERLEAVEFUNCTION.3 
b/docs/libcurl/opts/GNURLOPT_INTERLEAVEFUNCTION.3
index 25bcd0f94..326a29c46 100644
--- a/docs/libcurl/opts/GNURLOPT_INTERLEAVEFUNCTION.3
+++ b/docs/libcurl/opts/GNURLOPT_INTERLEAVEFUNCTION.3
@@ -54,8 +54,12 @@ connection may close. The application may use 
\fICURL_RTSPREQ_RECEIVE\fP to
 service RTP data when no requests are desired. If the application makes a
 request, (e.g.  \fICURL_RTSPREQ_PAUSE\fP) then the response handler will
 process any pending RTP data before marking the request as finished.
+
+The \fICURLOPT_WRITEDATA(3)\fP is passed in the \fIuserdata\fP argument in the
+callback.
 .SH DEFAULT
-NULL
+NULL, the interleave data is then passed to the regular write function:
+\fICURLOPT_WRITEFUNCTION(3)\fP.
 .SH PROTOCOLS
 RTSP
 .SH EXAMPLE
@@ -77,4 +81,4 @@ Added in 7.20.0
 .SH RETURN VALUE
 Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
 .SH "SEE ALSO"
-.BR CURLOPT_INTERLEAVEFUNCTION "(3), " CURLOPT_RTSP_REQUEST "(3), "
+.BR CURLOPT_INTERLEAVEDATA "(3), " CURLOPT_RTSP_REQUEST "(3), "
diff --git a/docs/libcurl/opts/GNURLOPT_KEEP_SENDING_ON_ERROR.3 
b/docs/libcurl/opts/GNURLOPT_KEEP_SENDING_ON_ERROR.3
index fbef74c07..384ca756c 100644
--- a/docs/libcurl/opts/GNURLOPT_KEEP_SENDING_ON_ERROR.3
+++ b/docs/libcurl/opts/GNURLOPT_KEEP_SENDING_ON_ERROR.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_KEEP_SENDING_ON_ERROR \- keep sending on early HTTP response >= 300
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KEEP_SENDING_ON_ERROR,
                           long keep_sending);
diff --git a/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3 
b/docs/libcurl/opts/GNURLOPT_MIMEPOST.3
similarity index 58%
copy from docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3
copy to docs/libcurl/opts/GNURLOPT_MIMEPOST.3
index 88ae1397e..dd64c4b17 100644
--- a/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3
+++ b/docs/libcurl/opts/GNURLOPT_MIMEPOST.3
@@ -20,37 +20,33 @@
 .\" *
 .\" **************************************************************************
 .\"
-.TH CURLOPT_REQUEST_TARGET 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt 
options"
+.TH CURLOPT_MIMEPOST 3 "22 Aug 2017" "libcurl 7.56.0" "curl_easy_setopt 
options"
 .SH NAME
-CURLOPT_REQUEST_TARGET \- specify an alternative target for this request
+CURLOPT_MIMEPOST \- set post/send data from mime structure
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+.nf
+#include <curl/curl.h>
+
+curl_mime *mime;
 
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REQUEST_TARGET, string);
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MIMEPOST, mime);
 .SH DESCRIPTION
-Pass a char * to string which libcurl uses in the upcoming request instead of
-the path as extracted from the URL.
-.SH DEFAULT
-NULL
-.SH PROTOCOLS
-HTTP
-.SH EXAMPLE
-.nf
-curl = curl_easy_init();
-if(curl) {
-  curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/*";);
-  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "OPTIONS");
+Pass a mime handle previously obtained from \fIcurl_mime_init(3)\fP.
 
-  /* issue an OPTIONS * request (no leading slash) */
-  curl_easy_setopt(curl, CURLOPT_REQUEST_TARGET, "*");
+This setting is supported by the HTTP protocol to post forms and by the
+SMTP and IMAP protocols to provide the e-mail data to send/upload.
 
-  /* Perform the request */
-  curl_easy_perform(curl);
-}
-.fi
+This option is the preferred way of posting an HTTP form, replacing and
+extending the deprecated \fICURLOPT_HTTPPOST(3)\fP option.
+.SH PROTOCOLS
+HTTP, SMTP, IMAP.
 .SH AVAILABILITY
-Added in 7.55.0
+Since 7.56.0.
 .SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+This will return CURLE_OK.
+.SH EXAMPLE
+Using this option implies the use of several mime structure building
+functions: see https://curl.haxx.se/libcurl/c/smtp-mime.html for a complete
+example.
 .SH "SEE ALSO"
-.BR CURLOPT_CUSTOMREQUEST "(3), " CURLOPT_HTTPGET "(3), "
+.BR curl_mime_init "(3)"
diff --git a/docs/libcurl/opts/GNURLOPT_NOPROXY.3 
b/docs/libcurl/opts/GNURLOPT_NOPROXY.3
index 9b01eba1f..873724484 100644
--- a/docs/libcurl/opts/GNURLOPT_NOPROXY.3
+++ b/docs/libcurl/opts/GNURLOPT_NOPROXY.3
@@ -41,8 +41,13 @@ If the name in the noproxy list has a leading period, it is 
a domain match
 against the provided host name. This way ".example.com" will switch off proxy
 use for both "www.example.com" as well as for "foo.example.com".
 
+Setting the noproxy string to "" (an empty string) will explicitly enable the
+proxy for all host names, even if there is an environment variable set for it.
+
 The application does not have to keep the string around after setting this
 option.
+.SH "Environment variables"
+See \fIGNURLOPT_PROXY(3)\fP
 .SH DEFAULT
 NULL
 .SH PROTOCOLS
@@ -66,4 +71,4 @@ Added in 7.19.4
 Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
 CURLE_OUT_OF_MEMORY if there was insufficient heap space.
 .SH "SEE ALSO"
-.BR CURLOPT_PROXY "(3), " CURLOPT_PROXYAUTH "(3), "
+.BR GNURLOPT_PROXY "(3), " GNURLOPT_PROXYAUTH "(3), "
diff --git a/docs/libcurl/opts/GNURLOPT_PRE_PROXY.3 
b/docs/libcurl/opts/GNURLOPT_PRE_PROXY.3
index 57dfcf6fe..8894c16da 100644
--- a/docs/libcurl/opts/GNURLOPT_PRE_PROXY.3
+++ b/docs/libcurl/opts/GNURLOPT_PRE_PROXY.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PRE_PROXY \- set pre-proxy to use
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PRE_PROXY, char *preproxy);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY.3 
b/docs/libcurl/opts/GNURLOPT_PROXY.3
index 1fc4000b3..615af887d 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY.3
@@ -84,7 +84,8 @@ names to not use a proxy for (even if one of the previous 
mention variables
 are set). That is the exact equivalent of setting the \fICURLOPT_NOPROXY(3)\fP
 option.
 
-The \fICURLOPT_PROXY(3)\fP option overrides environment variables.
+The \fICURLOPT_PROXY(3)\fP and \fICURLOPT_NOPROXY(3)\fP options override
+environment variables.
 .SH DEFAULT
 Default is NULL, meaning no proxy is used.
 
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.3
index 792fab689..a5f61a5bd 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_CAINFO \- path to proxy Certificate Authority (CA) bundle
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAINFO, char *path);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.3
index 91a807f89..1e7345ed3 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_CAPATH \- specify directory holding proxy CA certificates
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAPATH, char *capath);
 .SH DESCRIPTION
@@ -55,8 +55,9 @@ if(curl) {
 .SH AVAILABILITY
 Added in 7.52.0
 
-This option is supported by the OpenSSL, GnuTLS and PolarSSL backends. The NSS
-backend provides the option only for backward compatibility.
+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.
 .SH RETURN VALUE
 CURLE_OK if supported; or an error such as:
 
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.3
index 602e09ede..310ad7a4e 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_CRLFILE \- specify a proxy Certificate Revocation List file
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CRLFILE, char *file);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.3
index 52ed676df..594290274 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_KEYPASSWD \- set passphrase to proxy private key
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_KEYPASSWD, char *pwd);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.3
index 14a011e87..f6d56ebe9 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_PINNEDPUBLICKEY \- set pinned public key for https proxy
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_PINNEDPUBLICKEY, char 
*pinnedpubkey);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.3
index 5402c0df6..41e73190e 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_SSLCERT \- set SSL proxy client certificate
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT, char *cert);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.3
index 8603acc35..b8a6be0bb 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_SSLCERTTYPE \- specify type of the proxy client SSL certificate
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERTTYPE, char *type);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.3
index 585ff00fc..8df1c1ee6 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_SSLKEY \- specify private keyfile for TLS and SSL proxy client 
cert
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEY, char *keyfile);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.3
index d9de3218c..687c229a0 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_SSLKEYTYPE \- set type of the proxy private key file
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEYTYPE, char *type);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLVERSION.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_SSLVERSION.3
index 40adadc1a..6b9ff7dee 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLVERSION.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLVERSION.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_SSLVERSION \- set preferred proxy TLS/SSL version
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLVERSION, long 
version);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.3
index c959607fa..caaef81a3 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_SSL_CIPHER_LIST \- specify ciphers to use for proxy TLS
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_CIPHER_LIST, char 
*list);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3
index f0a70fda6..428efc38e 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_SSL_OPTIONS \- set proxy SSL behavior options
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_OPTIONS, long 
bitmask);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYHOST.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYHOST.3
index 584a6b5f1..de4b15b34 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYHOST.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYHOST.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_SSL_VERIFYHOST \- verify the proxy certificate's name against 
host
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYHOST, long 
verify);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYPEER.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYPEER.3
index 9f156d1f2..9473495cf 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYPEER.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_VERIFYPEER.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_SSL_VERIFYPEER \- verify the proxy's SSL certificate
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_VERIFYPEER, long 
verify);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.3
index 3bde5392b..db3a3d1bb 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_TLSAUTH_PASSWORD \- password to use for proxy TLS authentication
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_PASSWORD, char 
*pwd);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.3
index 6130577d3..47f4dae4a 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_TLSAUTH_TYPE \- set proxy TLS authentication methods
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_TYPE, char 
*type);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.3 
b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.3
index 7623ba37a..6a2c4388d 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_PROXY_TLSAUTH_USERNAME \- user name to use for proxy TLS authentication
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_USERNAME, char 
*user);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3 
b/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3
index 88ae1397e..eabefaa2d 100644
--- a/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3
+++ b/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_REQUEST_TARGET \- specify an alternative target for this request
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REQUEST_TARGET, string);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_SOCKS5_AUTH.3 
b/docs/libcurl/opts/GNURLOPT_SOCKS5_AUTH.3
index 2b66830db..7b5e5822b 100644
--- a/docs/libcurl/opts/GNURLOPT_SOCKS5_AUTH.3
+++ b/docs/libcurl/opts/GNURLOPT_SOCKS5_AUTH.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_SOCKS5_AUTH \- set allowed methods for SOCKS5 proxy authentication
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SOCKS5_AUTH, long bitmask);
 .SH DESCRIPTION
diff --git a/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3 
b/docs/libcurl/opts/GNURLOPT_SSH_COMPRESSION.3
similarity index 59%
copy from docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3
copy to docs/libcurl/opts/GNURLOPT_SSH_COMPRESSION.3
index 88ae1397e..5445cb0d2 100644
--- a/docs/libcurl/opts/GNURLOPT_REQUEST_TARGET.3
+++ b/docs/libcurl/opts/GNURLOPT_SSH_COMPRESSION.3
@@ -20,37 +20,39 @@
 .\" *
 .\" **************************************************************************
 .\"
-.TH CURLOPT_REQUEST_TARGET 3 "17 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt 
options"
+.TH CURLOPT_SSH_COMPRESSION 3 "05 Aug 2017" "libcurl 7.56.0" "curl_easy_setopt 
options"
 .SH NAME
-CURLOPT_REQUEST_TARGET \- specify an alternative target for this request
+CURLOPT_SSH_COMPRESSION \- enables automatic decompression of HTTP downloads
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REQUEST_TARGET, string);
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_COMPRESSION, long enable);
 .SH DESCRIPTION
-Pass a char * to string which libcurl uses in the upcoming request instead of
-the path as extracted from the URL.
+Pass a long as parameter set to 1L to enable or 0L to disable.
+
+Enables built-in SSH compression.  This is a request, not an order; the server
+may or may not do it.
 .SH DEFAULT
-NULL
+0, disabled
 .SH PROTOCOLS
-HTTP
+All SSH based protocols: SCP, SFTP
 .SH EXAMPLE
 .nf
-curl = curl_easy_init();
+CURL *curl = curl_easy_init();
 if(curl) {
-  curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/*";);
-  curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "OPTIONS");
+  curl_easy_setopt(curl, CURLOPT_URL, "sftp://example.com";);
 
-  /* issue an OPTIONS * request (no leading slash) */
-  curl_easy_setopt(curl, CURLOPT_REQUEST_TARGET, "*");
+  /* enable built-in compression */
+  curl_easy_setopt(curl, CURLOPT_SSH_COMPRESSION, 1L);
 
   /* Perform the request */
   curl_easy_perform(curl);
 }
 .fi
 .SH AVAILABILITY
-Added in 7.55.0
+Added in 7.56.0
 .SH RETURN VALUE
-Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
+Returns CURLE_OK if the option is supported, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
 .SH "SEE ALSO"
-.BR CURLOPT_CUSTOMREQUEST "(3), " CURLOPT_HTTPGET "(3), "
+.BR CURLOPT_ACCEPT_ENCODING "(3), " CURLOPT_TRANSFER_ENCODING "(3), "
diff --git a/docs/libcurl/opts/GNURLOPT_SSL_CTX_DATA.3 
b/docs/libcurl/opts/GNURLOPT_SSL_CTX_DATA.3
index 7b6dec4b3..216bdec3a 100644
--- a/docs/libcurl/opts/GNURLOPT_SSL_CTX_DATA.3
+++ b/docs/libcurl/opts/GNURLOPT_SSL_CTX_DATA.3
@@ -24,7 +24,7 @@
 .SH NAME
 CURLOPT_SSL_CTX_DATA \- custom pointer passed to ssl_ctx callback
 .SH SYNOPSIS
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CTX_DATA, void *pointer);
 .SH DESCRIPTION
@@ -40,7 +40,7 @@ All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
 /* OpenSSL specific */
 
 #include <openssl/ssl.h>
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 #include <stdio.h>
 
 static CURLcode sslctx_function(CURL *curl, void *sslctx, void *parm)
diff --git a/docs/libcurl/opts/GNURLOPT_SUPPRESS_CONNECT_HEADERS.3 
b/docs/libcurl/opts/GNURLOPT_SUPPRESS_CONNECT_HEADERS.3
index 22f83790f..8cfec7a8f 100644
--- a/docs/libcurl/opts/GNURLOPT_SUPPRESS_CONNECT_HEADERS.3
+++ b/docs/libcurl/opts/GNURLOPT_SUPPRESS_CONNECT_HEADERS.3
@@ -25,7 +25,7 @@
 CURLOPT_SUPPRESS_CONNECT_HEADERS \- Suppress proxy CONNECT response headers 
from user callbacks
 .SH SYNOPSIS
 .nf
-#include <gnurl/curl.h>
+#include <curl/curl.h>
 
 CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SUPPRESS_CONNECT_HEADERS, long 
onoff);
 .fi
diff --git a/docs/libcurl/opts/GNURLOPT_USERPWD.3 
b/docs/libcurl/opts/GNURLOPT_USERPWD.3
index b0bd19bb0..c303d39c3 100644
--- a/docs/libcurl/opts/GNURLOPT_USERPWD.3
+++ b/docs/libcurl/opts/GNURLOPT_USERPWD.3
@@ -88,3 +88,4 @@ Returns CURLE_OK on success or
 CURLE_OUT_OF_MEMORY if there was insufficient heap space.
 .SH "SEE ALSO"
 .BR CURLOPT_USERNAME "(3), " CURLOPT_PASSWORD "(3), "
+.BR CURLOPT_PROXYUSERPWD "(3), "
diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc
index fc20ee351..4300ec1cd 100644
--- a/docs/libcurl/opts/Makefile.inc
+++ b/docs/libcurl/opts/Makefile.inc
@@ -56,21 +56,21 @@ man_MANS =                                      \
   GNURLINFO_TLS_SESSION.3                        \
   GNURLINFO_TLS_SSL_PTR.3                        \
   GNURLINFO_TOTAL_TIME.3                         \
-  GNURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3          \
-  GNURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3        \
-  GNURLMOPT_MAXCONNECTS.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                      \
+  GNURLMOPTCHUNK_LENGTH_PENALTY_SIZE.3          \
+  GNURLMOPTCONTENT_LENGTH_PENALTY_SIZE.3        \
+  GNURLMOPTMAXCONNECTS.3                        \
+  GNURLMOPTMAX_HOST_CONNECTIONS.3               \
+  GNURLMOPTMAX_PIPELINE_LENGTH.3                \
+  GNURLMOPTMAX_TOTAL_CONNECTIONS.3              \
+  GNURLMOPTPIPELINING.3                         \
+  GNURLMOPTPIPELINING_SERVER_BL.3               \
+  GNURLMOPTPIPELINING_SITE_BL.3                 \
+  GNURLMOPTPUSHDATA.3                           \
+  GNURLMOPTPUSHFUNCTION.3                       \
+  GNURLMOPTSOCKETDATA.3                         \
+  GNURLMOPTSOCKETFUNCTION.3                     \
+  GNURLMOPTTIMERDATA.3                          \
+  GNURLMOPTTIMERFUNCTION.3                      \
   GNURLOPT_ABSTRACT_UNIX_SOCKET.3                \
   GNURLOPT_ACCEPTTIMEOUT_MS.3                    \
   GNURLOPT_ACCEPT_ENCODING.3                     \
@@ -175,6 +175,7 @@ man_MANS =                                      \
   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                 \
@@ -258,6 +259,7 @@ man_MANS =                                      \
   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                     \
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index e141b6a57..f912fb719 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -160,27 +160,27 @@ CURLFINFOFLAG_KNOWN_PERM        7.21.0
 CURLFINFOFLAG_KNOWN_SIZE        7.21.0
 CURLFINFOFLAG_KNOWN_TIME        7.21.0
 CURLFINFOFLAG_KNOWN_UID         7.21.0
-CURLFORM_ARRAY                  7.9.1
+CURLFORM_ARRAY                  7.9.1         7.56.0
 CURLFORM_ARRAY_END              7.9.1         7.9.5       7.9.6
 CURLFORM_ARRAY_START            7.9.1         7.9.5       7.9.6
-CURLFORM_BUFFER                 7.9.8
-CURLFORM_BUFFERLENGTH           7.9.8
-CURLFORM_BUFFERPTR              7.9.8
-CURLFORM_CONTENTHEADER          7.9.3
-CURLFORM_CONTENTLEN             7.46.0
-CURLFORM_CONTENTSLENGTH         7.9
-CURLFORM_CONTENTTYPE            7.9
-CURLFORM_COPYCONTENTS           7.9
-CURLFORM_COPYNAME               7.9
-CURLFORM_END                    7.9
-CURLFORM_FILE                   7.9
-CURLFORM_FILECONTENT            7.9.1
-CURLFORM_FILENAME               7.9.6
-CURLFORM_NAMELENGTH             7.9
-CURLFORM_NOTHING                7.9
-CURLFORM_PTRCONTENTS            7.9
-CURLFORM_PTRNAME                7.9
-CURLFORM_STREAM                 7.18.2
+CURLFORM_BUFFER                 7.9.8         7.56.0
+CURLFORM_BUFFERLENGTH           7.9.8         7.56.0
+CURLFORM_BUFFERPTR              7.9.8         7.56.0
+CURLFORM_CONTENTHEADER          7.9.3         7.56.0
+CURLFORM_CONTENTLEN             7.46.0        7.56.0
+CURLFORM_CONTENTSLENGTH         7.9           7.56.0
+CURLFORM_CONTENTTYPE            7.9           7.56.0
+CURLFORM_COPYCONTENTS           7.9           7.56.0
+CURLFORM_COPYNAME               7.9           7.56.0
+CURLFORM_END                    7.9           7.56.0
+CURLFORM_FILE                   7.9           7.56.0
+CURLFORM_FILECONTENT            7.9.1         7.56.0
+CURLFORM_FILENAME               7.9.6         7.56.0
+CURLFORM_NAMELENGTH             7.9           7.56.0
+CURLFORM_NOTHING                7.9           7.56.0
+CURLFORM_PTRCONTENTS            7.9           7.56.0
+CURLFORM_PTRNAME                7.9           7.56.0
+CURLFORM_STREAM                 7.18.2        7.56.0
 CURLFTPAUTH_DEFAULT             7.12.2
 CURLFTPAUTH_SSL                 7.12.2
 CURLFTPAUTH_TLS                 7.12.2
@@ -406,7 +406,7 @@ CURLOPT_HTTP200ALIASES          7.10.3
 CURLOPT_HTTPAUTH                7.10.6
 CURLOPT_HTTPGET                 7.8.1
 CURLOPT_HTTPHEADER              7.1
-CURLOPT_HTTPPOST                7.1
+CURLOPT_HTTPPOST                7.1           7.56.0
 CURLOPT_HTTPPROXYTUNNEL         7.3
 CURLOPT_HTTPREQUEST             7.1           -           7.15.5
 CURLOPT_HTTP_CONTENT_DECODING   7.16.2
@@ -441,6 +441,7 @@ CURLOPT_MAXFILESIZE_LARGE       7.11.0
 CURLOPT_MAXREDIRS               7.5
 CURLOPT_MAX_RECV_SPEED_LARGE    7.15.5
 CURLOPT_MAX_SEND_SPEED_LARGE    7.15.5
+CURLOPT_MIMEPOST                7.56.0
 CURLOPT_MUTE                    7.1           7.8         7.15.5
 CURLOPT_NETRC                   7.1
 CURLOPT_NETRC_FILE              7.11.0
@@ -540,6 +541,7 @@ CURLOPT_SOURCE_QUOTE            7.13.0        -           
7.15.5
 CURLOPT_SOURCE_URL              7.13.0        -           7.15.5
 CURLOPT_SOURCE_USERPWD          7.12.1        -           7.15.5
 CURLOPT_SSH_AUTH_TYPES          7.16.1
+CURLOPT_SSH_COMPRESSION         7.56.0
 CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 7.17.1
 CURLOPT_SSH_KEYDATA             7.19.6
 CURLOPT_SSH_KEYFUNCTION         7.19.6
@@ -689,6 +691,10 @@ CURLSSLBACKEND_SCHANNEL         7.34.0
 CURLSSLBACKEND_WOLFSSL          7.49.0
 CURLSSLOPT_ALLOW_BEAST          7.25.0
 CURLSSLOPT_NO_REVOKE            7.44.0
+CURLSSLSET_NO_BACKENDS          7.56.0
+CURLSSLSET_OK                   7.56.0
+CURLSSLSET_TOO_LATE             7.56.0
+CURLSSLSET_UNKNOWN_BACKEND      7.56.0
 CURLUSESSL_ALL                  7.17.0
 CURLUSESSL_CONTROL              7.17.0
 CURLUSESSL_NONE                 7.17.0
@@ -713,14 +719,14 @@ CURL_ERROR_SIZE                 7.1
 CURL_FNMATCHFUNC_FAIL           7.21.0
 CURL_FNMATCHFUNC_MATCH          7.21.0
 CURL_FNMATCHFUNC_NOMATCH        7.21.0
-CURL_FORMADD_DISABLED           7.12.1
-CURL_FORMADD_ILLEGAL_ARRAY      7.9.8
-CURL_FORMADD_INCOMPLETE         7.9.8
-CURL_FORMADD_MEMORY             7.9.8
-CURL_FORMADD_NULL               7.9.8
-CURL_FORMADD_OK                 7.9.8
-CURL_FORMADD_OPTION_TWICE       7.9.8
-CURL_FORMADD_UNKNOWN_OPTION     7.9.8
+CURL_FORMADD_DISABLED           7.12.1        7.56.0
+CURL_FORMADD_ILLEGAL_ARRAY      7.9.8         7.56.0
+CURL_FORMADD_INCOMPLETE         7.9.8         7.56.0
+CURL_FORMADD_MEMORY             7.9.8         7.56.0
+CURL_FORMADD_NULL               7.9.8         7.56.0
+CURL_FORMADD_OK                 7.9.8         7.56.0
+CURL_FORMADD_OPTION_TWICE       7.9.8         7.56.0
+CURL_FORMADD_UNKNOWN_OPTION     7.9.8         7.56.0
 CURL_GLOBAL_ACK_EINTR           7.30.0
 CURL_GLOBAL_ALL                 7.8
 CURL_GLOBAL_DEFAULT             7.8
@@ -836,6 +842,7 @@ CURL_VERSION_KERBEROS4          7.10          7.33.0
 CURL_VERSION_KERBEROS5          7.40.0
 CURL_VERSION_LARGEFILE          7.11.1
 CURL_VERSION_LIBZ               7.10
+CURL_VERSION_MULTI_SSL          7.56.0
 CURL_VERSION_NTLM               7.10.6
 CURL_VERSION_NTLM_WB            7.22.0
 CURL_VERSION_PSL                7.47.0
@@ -848,3 +855,4 @@ CURL_WAIT_POLLIN                7.28.0
 CURL_WAIT_POLLOUT               7.28.0
 CURL_WAIT_POLLPRI               7.28.0
 CURL_WRITEFUNC_PAUSE            7.18.0
+CURL_ZERO_TERMINATED            7.56.0
diff --git a/include/README b/include/README
index 0fc8f66d9..12516ebe6 100644
--- a/include/README
+++ b/include/README
@@ -30,4 +30,4 @@ NOTE FOR LIBCURL HACKERS
 
 To figure out how to do good and portable checks for features, operating
 systems or specific hardwarare, a very good resource is Bjorn Reese's
-collection at http://predef.sf.net/
+collection at https://sourceforge.net/p/predef/wiki/
diff --git a/include/gnurl/curl.h b/include/gnurl/curl.h
index 82fb8aeb8..7139a3311 100644
--- a/include/gnurl/curl.h
+++ b/include/gnurl/curl.h
@@ -74,6 +74,7 @@
 #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \
     defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \
     defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
+    defined(__CYGWIN__) || \
    (defined(__FreeBSD_version) && (__FreeBSD_version < 800000))
 #include <sys/select.h>
 #endif
@@ -132,6 +133,27 @@ typedef int curl_socket_t;
 #define curl_socket_typedef
 #endif /* curl_socket_typedef */
 
+/* enum for the different supported SSL backends */
+typedef enum {
+  CURLSSLBACKEND_NONE = 0,
+  CURLSSLBACKEND_OPENSSL = 1,
+  CURLSSLBACKEND_GNUTLS = 2,
+  CURLSSLBACKEND_NSS = 3,
+  CURLSSLBACKEND_OBSOLETE4 = 4,  /* Was QSOSSL. */
+  CURLSSLBACKEND_GSKIT = 5,
+  CURLSSLBACKEND_POLARSSL = 6,
+  CURLSSLBACKEND_WOLFSSL = 7,
+  CURLSSLBACKEND_SCHANNEL = 8,
+  CURLSSLBACKEND_DARWINSSL = 9,
+  CURLSSLBACKEND_AXTLS = 10,
+  CURLSSLBACKEND_MBEDTLS = 11
+} curl_sslbackend;
+
+/* aliases for library clones and renames */
+#define CURLSSLBACKEND_LIBRESSL CURLSSLBACKEND_OPENSSL
+#define CURLSSLBACKEND_BORINGSSL CURLSSLBACKEND_OPENSSL
+#define CURLSSLBACKEND_CYASSL CURLSSLBACKEND_WOLFSSL
+
 struct curl_httppost {
   struct curl_httppost *next;       /* next entry in the list */
   char *name;                       /* pointer to allocated name */
@@ -335,7 +357,7 @@ typedef size_t (*curl_read_callback)(char *buffer,
                                       size_t nitems,
                                       void *instream);
 
-typedef enum  {
+typedef enum {
   CURLSOCKTYPE_IPCXN,  /* socket created for a specific IP connection */
   CURLSOCKTYPE_ACCEPT, /* socket created by accept() call */
   CURLSOCKTYPE_LAST    /* never use */
@@ -377,7 +399,7 @@ typedef enum {
   CURLIOE_LAST           /* never use */
 } curlioerr;
 
-typedef enum  {
+typedef enum {
   CURLIOCMD_NOP,         /* no operation */
   CURLIOCMD_RESTARTREAD, /* restart the read stream from start */
   CURLIOCMD_LAST         /* never use */
@@ -1788,6 +1810,12 @@ typedef enum {
   /* bitmask of allowed auth methods for connections to SOCKS5 proxies */
   CINIT(SOCKS5_AUTH, LONG, 267),
 
+  /* Enable/disable SSH compression */
+  CINIT(SSH_COMPRESSION, LONG, 268),
+
+  /* Post MIME data. */
+  CINIT(MIMEPOST, OBJECTPOINT, 269),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
@@ -1934,15 +1962,140 @@ typedef enum {
   CURL_TIMECOND_LAST
 } curl_TimeCond;
 
+/* Special size_t value signaling a zero-terminated string. */
+#define CURL_ZERO_TERMINATED ((size_t) -1)
 
 /* curl_strequal() and curl_strnequal() are subject for removal in a future
-   libcurl, see lib/README.curlx for details
+   release */
+CURL_EXTERN int curl_strequal(const char *s1, const char *s2);
+CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n);
+
+/* Mime/form handling support. */
+typedef struct curl_mime_s      curl_mime;      /* Mime context. */
+typedef struct curl_mimepart_s  curl_mimepart;  /* Mime part context. */
+
+/*
+ * NAME curl_mime_init()
+ *
+ * DESCRIPTION
+ *
+ * Create a mime context and return its handle. The easy parameter is the
+ * target handle.
+ */
+CURL_EXTERN curl_mime *curl_mime_init(CURL *easy);
+
+/*
+ * NAME curl_mime_free()
+ *
+ * DESCRIPTION
+ *
+ * release a mime handle and its substructures.
+ */
+CURL_EXTERN void curl_mime_free(curl_mime *mime);
+
+/*
+ * NAME curl_mime_addpart()
+ *
+ * DESCRIPTION
+ *
+ * Append a new empty part to the given mime context and return a handle to
+ * the created part.
+ */
+CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime);
+
+/*
+ * NAME curl_mime_name()
+ *
+ * DESCRIPTION
+ *
+ * Set mime/form part name.
+ */
+CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name);
+
+/*
+ * NAME curl_mime_filename()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part remote file name.
+ */
+CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part,
+                                        const char *filename);
+
+/*
+ * NAME curl_mime_type()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part type.
+ */
+CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype);
+
+/*
+ * NAME curl_mime_encoder()
+ *
+ * DESCRIPTION
+ *
+ * Set mime data transfer encoder.
+ */
+CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part,
+                                       const char *encoding);
+
+/*
+ * NAME curl_mime_data()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from memory data,
+ */
+CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part,
+                                    const char *data, size_t datasize);
 
-   !checksrc! disable SPACEBEFOREPAREN 2
-*/
-CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
-CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
+/*
+ * NAME curl_mime_filedata()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from named file.
+ */
+CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part,
+                                        const char *filename);
 
+/*
+ * NAME curl_mime_data_cb()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from callback function.
+ */
+CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part,
+                                       curl_off_t datasize,
+                                       curl_read_callback readfunc,
+                                       curl_seek_callback seekfunc,
+                                       curl_free_callback freefunc,
+                                       void *arg);
+
+/*
+ * NAME curl_mime_subparts()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part data source from subparts.
+ */
+CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part,
+                                        curl_mime *subparts);
+/*
+ * NAME curl_mime_headers()
+ *
+ * DESCRIPTION
+ *
+ * Set mime part headers.
+ */
+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
@@ -2185,6 +2338,47 @@ struct curl_slist {
 };
 
 /*
+ * NAME curl_global_sslset()
+ *
+ * DESCRIPTION
+ *
+ * When built with multiple SSL backends, curl_global_sslset() allows to
+ * choose one. This function can only be called once, and it must be called
+ * *before* curl_global_init().
+ *
+ * The backend can be identified by the id (e.g. CURLSSLBACKEND_OPENSSL). The
+ * backend can also be specified via the name parameter (passing -1 as id).
+ * If both id and name are specified, the name will be ignored. If neither id
+ * nor name are specified, the function will fail with
+ * CURLSSLSET_UNKNOWN_BACKEND and set the "avail" pointer to the
+ * NULL-terminated list of available backends.
+ *
+ * Upon success, the function returns CURLSSLSET_OK.
+ *
+ * If the specified SSL backend is not available, the function returns
+ * CURLSSLSET_UNKNOWN_BACKEND and sets the "avail" pointer to a NULL-terminated
+ * list of available SSL backends.
+ *
+ * The SSL backend can be set only once. If it has already been set, a
+ * subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE.
+ */
+
+typedef struct {
+  curl_sslbackend id;
+  const char *name;
+} curl_ssl_backend;
+
+typedef enum {
+  CURLSSLSET_OK = 0,
+  CURLSSLSET_UNKNOWN_BACKEND,
+  CURLSSLSET_TOO_LATE,
+  CURLSSLSET_NO_BACKENDS /* libcurl was built without any SSL support */
+} CURLsslset;
+
+CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+                                          const curl_ssl_backend ***avail);
+
+/*
  * NAME curl_slist_append()
  *
  * DESCRIPTION
@@ -2224,27 +2418,6 @@ struct curl_certinfo {
                                    format "name: value" */
 };
 
-/* enum for the different supported SSL backends */
-typedef enum {
-  CURLSSLBACKEND_NONE = 0,
-  CURLSSLBACKEND_OPENSSL = 1,
-  CURLSSLBACKEND_GNUTLS = 2,
-  CURLSSLBACKEND_NSS = 3,
-  CURLSSLBACKEND_OBSOLETE4 = 4,  /* Was QSOSSL. */
-  CURLSSLBACKEND_GSKIT = 5,
-  CURLSSLBACKEND_POLARSSL = 6,
-  CURLSSLBACKEND_CYASSL = 7,
-  CURLSSLBACKEND_SCHANNEL = 8,
-  CURLSSLBACKEND_DARWINSSL = 9,
-  CURLSSLBACKEND_AXTLS = 10,
-  CURLSSLBACKEND_MBEDTLS = 11
-} curl_sslbackend;
-
-/* aliases for library clones and renames */
-#define CURLSSLBACKEND_LIBRESSL 1
-#define CURLSSLBACKEND_BORINGSSL 1
-#define CURLSSLBACKEND_WOLFSSL 6
-
 /* Information about the SSL library used and the respective internal SSL
    handle, which can be used to obtain further information regarding the
    connection. Asked for with CURLINFO_TLS_SSL_PTR or CURLINFO_TLS_SESSION. */
@@ -2484,6 +2657,7 @@ typedef struct {
 #define CURL_VERSION_PSL          (1<<20) /* Mozilla's Public Suffix List, used
                                              for cookie domain verification */
 #define CURL_VERSION_HTTPS_PROXY  (1<<21) /* HTTPS-proxy support built-in */
+#define CURL_VERSION_MULTI_SSL    (1<<22) /* Multiple SSL backends available */
 
  /*
  * NAME curl_version_info()
diff --git a/include/gnurl/curlver.h b/include/gnurl/curlver.h
index 2165d55b1..8c9fb5e3a 100644
--- a/include/gnurl/curlver.h
+++ b/include/gnurl/curlver.h
@@ -30,13 +30,13 @@
 
 /* This is the version number of the libcurl package from which this header
    file origins: */
-#define LIBCURL_VERSION "7.55.1-DEV"
+#define LIBCURL_VERSION "7.56.0-DEV"
 
 /* The numeric version number is also available "in parts" by using these
    defines: */
 #define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 55
-#define LIBCURL_VERSION_PATCH 1
+#define LIBCURL_VERSION_MINOR 56
+#define LIBCURL_VERSION_PATCH 0
 
 /* 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 0x073701
+#define LIBCURL_VERSION_NUM 0x073800
 
 /*
  * 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 46d979853..55efae0be 100644
--- a/include/gnurl/multi.h
+++ b/include/gnurl/multi.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
diff --git a/include/gnurl/system.h b/include/gnurl/system.h
index 95c72d998..39dae754c 100644
--- a/include/gnurl/system.h
+++ b/include/gnurl/system.h
@@ -52,226 +52,171 @@
 
 #if defined(__DJGPP__) || defined(__GO32__)
 #  if defined(__DJGPP__) && (__DJGPP__ > 1)
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     long long
 #    define CURL_FORMAT_CURL_OFF_T     "lld"
 #    define CURL_FORMAT_CURL_OFF_TU    "llu"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     LL
 #    define CURL_SUFFIX_CURL_OFF_TU    ULL
 #  else
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     long
 #    define CURL_FORMAT_CURL_OFF_T     "ld"
 #    define CURL_FORMAT_CURL_OFF_TU    "lu"
-#    define CURL_SIZEOF_CURL_OFF_T     4
 #    define CURL_SUFFIX_CURL_OFF_T     L
 #    define CURL_SUFFIX_CURL_OFF_TU    UL
 #  endif
 #  define CURL_TYPEOF_CURL_SOCKLEN_T int
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 
 #elif defined(__SALFORDC__)
-#  define CURL_SIZEOF_LONG           4
 #  define CURL_TYPEOF_CURL_OFF_T     long
 #  define CURL_FORMAT_CURL_OFF_T     "ld"
 #  define CURL_FORMAT_CURL_OFF_TU    "lu"
-#  define CURL_SIZEOF_CURL_OFF_T     4
 #  define CURL_SUFFIX_CURL_OFF_T     L
 #  define CURL_SUFFIX_CURL_OFF_TU    UL
 #  define CURL_TYPEOF_CURL_SOCKLEN_T int
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 
 #elif defined(__BORLANDC__)
 #  if (__BORLANDC__ < 0x520)
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     long
 #    define CURL_FORMAT_CURL_OFF_T     "ld"
 #    define CURL_FORMAT_CURL_OFF_TU    "lu"
-#    define CURL_SIZEOF_CURL_OFF_T     4
 #    define CURL_SUFFIX_CURL_OFF_T     L
 #    define CURL_SUFFIX_CURL_OFF_TU    UL
 #  else
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     __int64
 #    define CURL_FORMAT_CURL_OFF_T     "I64d"
 #    define CURL_FORMAT_CURL_OFF_TU    "I64u"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     i64
 #    define CURL_SUFFIX_CURL_OFF_TU    ui64
 #  endif
 #  define CURL_TYPEOF_CURL_SOCKLEN_T int
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 
 #elif defined(__TURBOC__)
-#  define CURL_SIZEOF_LONG           4
 #  define CURL_TYPEOF_CURL_OFF_T     long
 #  define CURL_FORMAT_CURL_OFF_T     "ld"
 #  define CURL_FORMAT_CURL_OFF_TU    "lu"
-#  define CURL_SIZEOF_CURL_OFF_T     4
 #  define CURL_SUFFIX_CURL_OFF_T     L
 #  define CURL_SUFFIX_CURL_OFF_TU    UL
 #  define CURL_TYPEOF_CURL_SOCKLEN_T int
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 
 #elif defined(__WATCOMC__)
 #  if defined(__386__)
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     __int64
 #    define CURL_FORMAT_CURL_OFF_T     "I64d"
 #    define CURL_FORMAT_CURL_OFF_TU    "I64u"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     i64
 #    define CURL_SUFFIX_CURL_OFF_TU    ui64
 #  else
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     long
 #    define CURL_FORMAT_CURL_OFF_T     "ld"
 #    define CURL_FORMAT_CURL_OFF_TU    "lu"
-#    define CURL_SIZEOF_CURL_OFF_T     4
 #    define CURL_SUFFIX_CURL_OFF_T     L
 #    define CURL_SUFFIX_CURL_OFF_TU    UL
 #  endif
 #  define CURL_TYPEOF_CURL_SOCKLEN_T int
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 
 #elif defined(__POCC__)
 #  if (__POCC__ < 280)
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     long
 #    define CURL_FORMAT_CURL_OFF_T     "ld"
 #    define CURL_FORMAT_CURL_OFF_TU    "lu"
-#    define CURL_SIZEOF_CURL_OFF_T     4
 #    define CURL_SUFFIX_CURL_OFF_T     L
 #    define CURL_SUFFIX_CURL_OFF_TU    UL
 #  elif defined(_MSC_VER)
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     __int64
 #    define CURL_FORMAT_CURL_OFF_T     "I64d"
 #    define CURL_FORMAT_CURL_OFF_TU    "I64u"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     i64
 #    define CURL_SUFFIX_CURL_OFF_TU    ui64
 #  else
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     long long
 #    define CURL_FORMAT_CURL_OFF_T     "lld"
 #    define CURL_FORMAT_CURL_OFF_TU    "llu"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     LL
 #    define CURL_SUFFIX_CURL_OFF_TU    ULL
 #  endif
 #  define CURL_TYPEOF_CURL_SOCKLEN_T int
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 
 #elif defined(__LCC__)
-#  define CURL_SIZEOF_LONG           4
 #  define CURL_TYPEOF_CURL_OFF_T     long
 #  define CURL_FORMAT_CURL_OFF_T     "ld"
 #  define CURL_FORMAT_CURL_OFF_TU    "lu"
-#  define CURL_SIZEOF_CURL_OFF_T     4
 #  define CURL_SUFFIX_CURL_OFF_T     L
 #  define CURL_SUFFIX_CURL_OFF_TU    UL
 #  define CURL_TYPEOF_CURL_SOCKLEN_T int
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 
 #elif defined(__SYMBIAN32__)
 #  if defined(__EABI__)  /* Treat all ARM compilers equally */
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     long long
 #    define CURL_FORMAT_CURL_OFF_T     "lld"
 #    define CURL_FORMAT_CURL_OFF_TU    "llu"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     LL
 #    define CURL_SUFFIX_CURL_OFF_TU    ULL
 #  elif defined(__CW32__)
 #    pragma longlong on
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     long long
 #    define CURL_FORMAT_CURL_OFF_T     "lld"
 #    define CURL_FORMAT_CURL_OFF_TU    "llu"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     LL
 #    define CURL_SUFFIX_CURL_OFF_TU    ULL
 #  elif defined(__VC32__)
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     __int64
 #    define CURL_FORMAT_CURL_OFF_T     "lld"
 #    define CURL_FORMAT_CURL_OFF_TU    "llu"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     LL
 #    define CURL_SUFFIX_CURL_OFF_TU    ULL
 #  endif
 #  define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 
 #elif defined(__MWERKS__)
-#  define CURL_SIZEOF_LONG           4
 #  define CURL_TYPEOF_CURL_OFF_T     long long
 #  define CURL_FORMAT_CURL_OFF_T     "lld"
 #  define CURL_FORMAT_CURL_OFF_TU    "llu"
-#  define CURL_SIZEOF_CURL_OFF_T     8
 #  define CURL_SUFFIX_CURL_OFF_T     LL
 #  define CURL_SUFFIX_CURL_OFF_TU    ULL
 #  define CURL_TYPEOF_CURL_SOCKLEN_T int
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 
 #elif defined(_WIN32_WCE)
-#  define CURL_SIZEOF_LONG           4
 #  define CURL_TYPEOF_CURL_OFF_T     __int64
 #  define CURL_FORMAT_CURL_OFF_T     "I64d"
 #  define CURL_FORMAT_CURL_OFF_TU    "I64u"
-#  define CURL_SIZEOF_CURL_OFF_T     8
 #  define CURL_SUFFIX_CURL_OFF_T     i64
 #  define CURL_SUFFIX_CURL_OFF_TU    ui64
 #  define CURL_TYPEOF_CURL_SOCKLEN_T int
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 
 #elif defined(__MINGW32__)
-#  define CURL_SIZEOF_LONG           4
 #  define CURL_TYPEOF_CURL_OFF_T     long long
 #  define CURL_FORMAT_CURL_OFF_T     "I64d"
 #  define CURL_FORMAT_CURL_OFF_TU    "I64u"
-#  define CURL_SIZEOF_CURL_OFF_T     8
 #  define CURL_SUFFIX_CURL_OFF_T     LL
 #  define CURL_SUFFIX_CURL_OFF_TU    ULL
 #  define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 #  define CURL_PULL_SYS_TYPES_H      1
 #  define CURL_PULL_WS2TCPIP_H       1
 
 #elif defined(__VMS)
 #  if defined(__VAX)
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     long
 #    define CURL_FORMAT_CURL_OFF_T     "ld"
 #    define CURL_FORMAT_CURL_OFF_TU    "lu"
-#    define CURL_SIZEOF_CURL_OFF_T     4
 #    define CURL_SUFFIX_CURL_OFF_T     L
 #    define CURL_SUFFIX_CURL_OFF_TU    UL
 #  else
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     long long
 #    define CURL_FORMAT_CURL_OFF_T     "lld"
 #    define CURL_FORMAT_CURL_OFF_TU    "llu"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     LL
 #    define CURL_SUFFIX_CURL_OFF_TU    ULL
 #  endif
 #  define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 
 #elif defined(__OS400__)
 #  if defined(__ILEC400__)
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     long long
 #    define CURL_FORMAT_CURL_OFF_T     "lld"
 #    define CURL_FORMAT_CURL_OFF_TU    "llu"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     LL
 #    define CURL_SUFFIX_CURL_OFF_TU    ULL
 #    define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-#    define CURL_SIZEOF_CURL_SOCKLEN_T 4
 #    define CURL_PULL_SYS_TYPES_H      1
 #    define CURL_PULL_SYS_SOCKET_H     1
 #  endif
@@ -279,34 +224,28 @@
 #elif defined(__MVS__)
 #  if defined(__IBMC__) || defined(__IBMCPP__)
 #    if defined(_ILP32)
-#      define CURL_SIZEOF_LONG           4
 #    elif defined(_LP64)
-#      define CURL_SIZEOF_LONG           8
 #    endif
 #    if defined(_LONG_LONG)
 #      define CURL_TYPEOF_CURL_OFF_T     long long
 #      define CURL_FORMAT_CURL_OFF_T     "lld"
 #      define CURL_FORMAT_CURL_OFF_TU    "llu"
-#      define CURL_SIZEOF_CURL_OFF_T     8
 #      define CURL_SUFFIX_CURL_OFF_T     LL
 #      define CURL_SUFFIX_CURL_OFF_TU    ULL
 #    elif defined(_LP64)
 #      define CURL_TYPEOF_CURL_OFF_T     long
 #      define CURL_FORMAT_CURL_OFF_T     "ld"
 #      define CURL_FORMAT_CURL_OFF_TU    "lu"
-#      define CURL_SIZEOF_CURL_OFF_T     8
 #      define CURL_SUFFIX_CURL_OFF_T     L
 #      define CURL_SUFFIX_CURL_OFF_TU    UL
 #    else
 #      define CURL_TYPEOF_CURL_OFF_T     long
 #      define CURL_FORMAT_CURL_OFF_T     "ld"
 #      define CURL_FORMAT_CURL_OFF_TU    "lu"
-#      define CURL_SIZEOF_CURL_OFF_T     4
 #      define CURL_SUFFIX_CURL_OFF_T     L
 #      define CURL_SUFFIX_CURL_OFF_TU    UL
 #    endif
 #    define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-#    define CURL_SIZEOF_CURL_SOCKLEN_T 4
 #    define CURL_PULL_SYS_TYPES_H      1
 #    define CURL_PULL_SYS_SOCKET_H     1
 #  endif
@@ -314,56 +253,45 @@
 #elif defined(__370__)
 #  if defined(__IBMC__) || defined(__IBMCPP__)
 #    if defined(_ILP32)
-#      define CURL_SIZEOF_LONG           4
 #    elif defined(_LP64)
-#      define CURL_SIZEOF_LONG           8
 #    endif
 #    if defined(_LONG_LONG)
 #      define CURL_TYPEOF_CURL_OFF_T     long long
 #      define CURL_FORMAT_CURL_OFF_T     "lld"
 #      define CURL_FORMAT_CURL_OFF_TU    "llu"
-#      define CURL_SIZEOF_CURL_OFF_T     8
 #      define CURL_SUFFIX_CURL_OFF_T     LL
 #      define CURL_SUFFIX_CURL_OFF_TU    ULL
 #    elif defined(_LP64)
 #      define CURL_TYPEOF_CURL_OFF_T     long
 #      define CURL_FORMAT_CURL_OFF_T     "ld"
 #      define CURL_FORMAT_CURL_OFF_TU    "lu"
-#      define CURL_SIZEOF_CURL_OFF_T     8
 #      define CURL_SUFFIX_CURL_OFF_T     L
 #      define CURL_SUFFIX_CURL_OFF_TU    UL
 #    else
 #      define CURL_TYPEOF_CURL_OFF_T     long
 #      define CURL_FORMAT_CURL_OFF_T     "ld"
 #      define CURL_FORMAT_CURL_OFF_TU    "lu"
-#      define CURL_SIZEOF_CURL_OFF_T     4
 #      define CURL_SUFFIX_CURL_OFF_T     L
 #      define CURL_SUFFIX_CURL_OFF_TU    UL
 #    endif
 #    define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-#    define CURL_SIZEOF_CURL_SOCKLEN_T 4
 #    define CURL_PULL_SYS_TYPES_H      1
 #    define CURL_PULL_SYS_SOCKET_H     1
 #  endif
 
 #elif defined(TPF)
-#  define CURL_SIZEOF_LONG           8
 #  define CURL_TYPEOF_CURL_OFF_T     long
 #  define CURL_FORMAT_CURL_OFF_T     "ld"
 #  define CURL_FORMAT_CURL_OFF_TU    "lu"
-#  define CURL_SIZEOF_CURL_OFF_T     8
 #  define CURL_SUFFIX_CURL_OFF_T     L
 #  define CURL_SUFFIX_CURL_OFF_TU    UL
 #  define CURL_TYPEOF_CURL_SOCKLEN_T int
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 
 #elif defined(__TINYC__) /* also known as tcc */
 
-#  define CURL_SIZEOF_LONG           4
 #  define CURL_TYPEOF_CURL_OFF_T     long long
 #  define CURL_FORMAT_CURL_OFF_T     "lld"
 #  define CURL_FORMAT_CURL_OFF_TU    "llu"
-#  define CURL_SIZEOF_CURL_OFF_T     8
 #  define CURL_SUFFIX_CURL_OFF_T     LL
 #  define CURL_SUFFIX_CURL_OFF_TU    ULL
 #  define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
@@ -373,25 +301,20 @@
 #elif defined(__SUNPRO_C) /* Oracle Solaris Studio */
 #  if !defined(__LP64) && (defined(__ILP32) ||                          \
                            defined(__i386) || defined(__sparcv8))
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     long long
 #    define CURL_FORMAT_CURL_OFF_T     "lld"
 #    define CURL_FORMAT_CURL_OFF_TU    "llu"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     LL
 #    define CURL_SUFFIX_CURL_OFF_TU    ULL
 #  elif defined(__LP64) || \
         defined(__amd64) || defined(__sparcv9)
-#    define CURL_SIZEOF_LONG           8
 #    define CURL_TYPEOF_CURL_OFF_T     long
 #    define CURL_FORMAT_CURL_OFF_T     "ld"
 #    define CURL_FORMAT_CURL_OFF_TU    "lu"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     L
 #    define CURL_SUFFIX_CURL_OFF_TU    UL
 #  endif
 #  define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 #  define CURL_PULL_SYS_TYPES_H      1
 #  define CURL_PULL_SYS_SOCKET_H     1
 
@@ -401,62 +324,51 @@
 
 #elif defined(_MSC_VER)
 #  if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     __int64
 #    define CURL_FORMAT_CURL_OFF_T     "I64d"
 #    define CURL_FORMAT_CURL_OFF_TU    "I64u"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     i64
 #    define CURL_SUFFIX_CURL_OFF_TU    ui64
 #  else
-#    define CURL_SIZEOF_LONG           4
 #    define CURL_TYPEOF_CURL_OFF_T     long
 #    define CURL_FORMAT_CURL_OFF_T     "ld"
 #    define CURL_FORMAT_CURL_OFF_TU    "lu"
-#    define CURL_SIZEOF_CURL_OFF_T     4
 #    define CURL_SUFFIX_CURL_OFF_T     L
 #    define CURL_SUFFIX_CURL_OFF_TU    UL
 #  endif
 #  define CURL_TYPEOF_CURL_SOCKLEN_T int
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 
 /* ===================================== */
 /*    KEEP GENERIC GCC THE LAST ENTRY    */
 /* ===================================== */
 
 #elif defined(__GNUC__)
-#  if !defined(__LP64__) && (defined(__ILP32__) || \
-      defined(__i386__) || defined(__powerpc__) || defined(__arm__) || \
-      defined(__sparc__) || defined(__mips__) || defined(__sh__) || \
-      defined(__XTENSA__) || (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 
4))
-#    define CURL_SIZEOF_LONG           4
+#  if !defined(__LP64__) &&                                             \
+  (defined(__ILP32__) || defined(__i386__) || defined(__hppa__) ||      \
+   defined(__ppc__) || defined(__powerpc__) || defined(__arm__) ||      \
+   defined(__sparc__) || defined(__mips__) || defined(__sh__) ||        \
+   defined(__XTENSA__) ||                                               \
+   (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4))
 #    define CURL_TYPEOF_CURL_OFF_T     long long
 #    define CURL_FORMAT_CURL_OFF_T     "lld"
 #    define CURL_FORMAT_CURL_OFF_TU    "llu"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     LL
 #    define CURL_SUFFIX_CURL_OFF_TU    ULL
 #  elif defined(__LP64__) || \
         defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
         (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8)
-#    define CURL_SIZEOF_LONG           8
 #    define CURL_TYPEOF_CURL_OFF_T     long
 #    define CURL_FORMAT_CURL_OFF_T     "ld"
 #    define CURL_FORMAT_CURL_OFF_TU    "lu"
-#    define CURL_SIZEOF_CURL_OFF_T     8
 #    define CURL_SUFFIX_CURL_OFF_T     L
 #    define CURL_SUFFIX_CURL_OFF_TU    UL
 #  endif
 #  define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
-#  define CURL_SIZEOF_CURL_SOCKLEN_T 4
 #  define CURL_PULL_SYS_TYPES_H      1
 #  define CURL_PULL_SYS_SOCKET_H     1
 
 #else
 /* generic "safe guess" on old 32 bit style */
-# define CURL_SIZEOF_LONG 4
-# define CURL_SIZEOF_CURL_SOCKLEN_T 4
-# define CURL_SIZEOF_CURL_OFF_T 4
 # define CURL_TYPEOF_CURL_OFF_T     long
 # define CURL_FORMAT_CURL_OFF_T     "ld"
 # define CURL_FORMAT_CURL_OFF_TU    "lu"
@@ -465,6 +377,12 @@
 # define CURL_TYPEOF_CURL_SOCKLEN_T int
 #endif
 
+#ifdef _AIX
+/* AIX needs <sys/poll.h> */
+#define CURL_PULL_SYS_POLL_H
+#endif
+
+
 /* CURL_PULL_WS2TCPIP_H is defined above when inclusion of header file  */
 /* ws2tcpip.h is required here to properly make type definitions below. */
 #ifdef CURL_PULL_WS2TCPIP_H
@@ -485,6 +403,12 @@
 #  include <sys/socket.h>
 #endif
 
+/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file    */
+/* sys/poll.h is required here to properly make type definitions below.   */
+#ifdef CURL_PULL_SYS_POLL_H
+#  include <sys/poll.h>
+#endif
+
 /* Data type definition of curl_socklen_t. */
 #ifdef CURL_TYPEOF_CURL_SOCKLEN_T
   typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
diff --git a/include/gnurl/typecheck-gcc.h b/include/gnurl/typecheck-gcc.h
index 74548241b..10c74c764 100644
--- a/include/gnurl/typecheck-gcc.h
+++ b/include/gnurl/typecheck-gcc.h
@@ -96,6 +96,9 @@ __extension__ ({                                              
                \
     if((_curl_opt) == CURLOPT_HTTPPOST)                                       \
       if(!_curl_is_arr((value), struct curl_httppost))                        \
         _curl_easy_setopt_err_curl_httpost();                                 \
+    if((_curl_opt) == CURLOPT_MIMEPOST)                                       \
+      if(!_curl_is_ptr((value), curl_mime))                                   \
+        _curl_easy_setopt_err_curl_mimepost();                                \
     if(_curl_is_slist_option(_curl_opt))                                      \
       if(!_curl_is_arr((value), struct curl_slist))                           \
         _curl_easy_setopt_err_curl_slist();                                   \
@@ -200,6 +203,9 @@ _CURL_WARNING(_curl_easy_setopt_err_postfields,
 _CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
               "curl_easy_setopt expects a 'struct curl_httppost *' "
               "argument for this option")
+_CURL_WARNING(_curl_easy_setopt_err_curl_mimepost,
+              "curl_easy_setopt expects a 'curl_mime *' "
+              "argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_curl_slist,
   "curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
 _CURL_WARNING(_curl_easy_setopt_err_CURLSH,
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 2aa1bb030..d99e49cf9 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -66,21 +66,7 @@ endif
 # Prevent LIBS from being used for all link targets
 LIBS = $(BLANK_AT_MAKETIME)
 
-if SONAME_BUMP
-#
-# Bumping of SONAME conditionally may seem like a weird thing to do, and yeah
-# it is. The problem is that we try to avoid the bump as hard as possible, but
-# yet it is still necessary for a few rare situations. The configure script 
will
-# attempt to figure out these situations, and it can be forced to consider this
-# to be such a case! See README.curl_off_t for further details.
-#
-# This conditional soname bump SHOULD be removed at next "proper" bump.
-#
-VERSIONINFO=-version-info 9:0:4
-else
-VERSIONINFO=-version-info 8:0:4
-endif
-
+VERSIONINFO=-version-info 9:0:5
 # This flag accepts an argument of the form current[:revision[:age]]. So,
 # passing -version-info 3:12:1 sets current to 3, revision to 12, and age to
 # 1.
@@ -106,6 +92,10 @@ libgnurl_la_CFLAGS_EXTRA =
 libgnurl_la_LDFLAGS_EXTRA += $(CODE_COVERAGE_LDFLAGS)
 libgnurl_la_CFLAGS_EXTRA += $(CODE_COVERAGE_CFLAGS)
 
address@hidden@
+libcurl_la_LDFLAGS_EXTRA += $(CODE_COVERAGE_LDFLAGS)
+libcurl_la_CFLAGS_EXTRA += $(CODE_COVERAGE_CFLAGS)
+
 if CURL_LT_SHLIB_USE_VERSION_INFO
 libgnurl_la_LDFLAGS_EXTRA += $(VERSIONINFO)
 endif
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index 19f58000a..5c0b930cf 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -53,7 +53,8 @@ LIB_CFILES = file.c timeval.c base64.c hostip.c progress.c 
formdata.c   \
   http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c      \
   http_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_sasl.c rand.c        \
   curl_multibyte.c hostcheck.c conncache.c pipeline.c dotdot.c          \
-  x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c
+  x509asn1.c http2.c smb.c curl_endian.c curl_des.c system_win32.c      \
+  mime.c
 
 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         \
@@ -72,7 +73,7 @@ LIB_HFILES = arpa_telnet.h netrc.h file.h timeval.h hostip.h 
progress.h \
   curl_sasl.h curl_multibyte.h hostcheck.h conncache.h                  \
   curl_setup_once.h multihandle.h setup-vms.h pipeline.h dotdot.h       \
   x509asn1.h http2.h sigpipe.h smb.h curl_endian.h curl_des.h           \
-  curl_printf.h system_win32.h rand.h
+  curl_printf.h system_win32.h rand.h mime.h
 
 LIB_RCFILES = libcurl.rc
 
diff --git a/lib/Makefile.m32 b/lib/Makefile.m32
index 8e4c70333..22efbdee0 100644
--- a/lib/Makefile.m32
+++ b/lib/Makefile.m32
@@ -50,9 +50,9 @@ endif
 ifndef LIBRTMP_PATH
 LIBRTMP_PATH = ../../librtmp-2.4
 endif
-# Edit the path below to point to the base of your libidn package.
-ifndef LIBIDN_PATH
-LIBIDN_PATH = ../../libidn-1.32
+# Edit the path below to point to the base of your libidn2 package.
+ifndef LIBIDN2_PATH
+LIBIDN2_PATH = ../../libidn2-2.0.3
 endif
 # Edit the path below to point to the base of your MS IDN package.
 # Microsoft Internationalized Domain Names (IDN) Mitigation APIs 1.1
@@ -153,9 +153,7 @@ ZLIB = 1
 endif
 ifeq ($(findstring -ssh2,$(CFG)),-ssh2)
 SSH2 = 1
-ifneq ($(findstring -winssl,$(CFG)),-winssl)
 SSL = 1
-endif
 ZLIB = 1
 endif
 ifeq ($(findstring -ssl,$(CFG)),-ssl)
@@ -167,8 +165,8 @@ endif
 ifeq ($(findstring -zlib,$(CFG)),-zlib)
 ZLIB = 1
 endif
-ifeq ($(findstring -idn,$(CFG)),-idn)
-IDN = 1
+ifeq ($(findstring -idn2,$(CFG)),-idn2)
+IDN2 = 1
 endif
 ifeq ($(findstring -winidn,$(CFG)),-winidn)
 WINIDN = 1
@@ -192,6 +190,11 @@ endif
 
 INCLUDES = -I. -I../include
 CFLAGS += -DBUILDING_LIBCURL
+ifdef SSL
+  ifdef WINSSL
+    CFLAGS += -DCURL_WITH_MULTI_SSL
+  endif
+endif
 
 ifdef SYNC
   CFLAGS += -DUSE_SYNC_DNS
@@ -257,20 +260,20 @@ ifdef SSL
       CFLAGS += -DHAVE_OPENSSL_SRP -DUSE_TLS_SRP
     endif
   endif
-else
+endif
 ifdef WINSSL
+  CFLAGS += -DUSE_SCHANNEL
   DLL_LIBS += -lcrypt32
 endif
-endif
 ifdef ZLIB
   INCLUDES += -I"$(ZLIB_PATH)"
   CFLAGS += -DHAVE_LIBZ -DHAVE_ZLIB_H
   DLL_LIBS += -L"$(ZLIB_PATH)" -lz
 endif
-ifdef IDN
-  INCLUDES += -I"$(LIBIDN_PATH)/include"
-  CFLAGS += -DUSE_LIBIDN
-  DLL_LIBS += -L"$(LIBIDN_PATH)/lib" -lidn
+ifdef IDN2
+  INCLUDES += -I"$(LIBIDN2_PATH)/include"
+  CFLAGS += -DUSE_LIBIDN2
+  DLL_LIBS += -L"$(LIBIDN2_PATH)/lib" -lidn2
 else
 ifdef WINIDN
   CFLAGS += -DUSE_WIN32_IDN
@@ -280,9 +283,6 @@ endif
 endif
 ifdef SSPI
   CFLAGS += -DUSE_WINDOWS_SSPI
-  ifdef WINSSL
-    CFLAGS += -DUSE_SCHANNEL
-  endif
 endif
 ifdef SPNEGO
   CFLAGS += -DHAVE_SPNEGO
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index 9b6515cda..87e70b4d9 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -260,7 +260,7 @@ static int waitperform(struct connectdata *conn, int 
timeout_ms)
   bitmask = ares_getsock((ares_channel)data->state.resolver, socks,
                          ARES_GETSOCK_MAXNUM);
 
-  for(i=0; i < ARES_GETSOCK_MAXNUM; i++) {
+  for(i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
     pfd[i].events = 0;
     pfd[i].revents = 0;
     if(ARES_GETSOCK_READABLE(bitmask, i)) {
@@ -289,7 +289,7 @@ static int waitperform(struct connectdata *conn, int 
timeout_ms)
                     ARES_SOCKET_BAD);
   else {
     /* move through the descriptors and ask for processing on them */
-    for(i=0; i < num; i++)
+    for(i = 0; i < num; i++)
       ares_process_fd((ares_channel)data->state.resolver,
                       pfd[i].revents & (POLLRDNORM|POLLIN)?
                       pfd[i].fd:ARES_SOCKET_BAD,
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index 8936b6033..a86772965 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -210,6 +210,10 @@ int init_thread_sync_data(struct thread_data * td,
 
   tsd->td = td;
   tsd->port = port;
+  /* Treat the request as done until the thread actually starts so any early
+   * cleanup gets done properly.
+   */
+  tsd->done = 1;
 #ifdef HAVE_GETADDRINFO
   DEBUGASSERT(hints);
   tsd->hints = *hints;
@@ -380,11 +384,11 @@ static bool init_resolve_thread(struct connectdata *conn,
                                 const struct addrinfo *hints)
 {
   struct thread_data *td = calloc(1, sizeof(struct thread_data));
-  int err = RESOLVER_ENOMEM;
+  int err = ENOMEM;
 
   conn->async.os_specific = (void *)td;
   if(!td)
-    goto err_exit;
+    goto errno_exit;
 
   conn->async.port = port;
   conn->async.done = FALSE;
@@ -392,14 +396,20 @@ static bool init_resolve_thread(struct connectdata *conn,
   conn->async.dns = NULL;
   td->thread_hnd = curl_thread_t_null;
 
-  if(!init_thread_sync_data(td, hostname, port, hints))
-    goto err_exit;
+  if(!init_thread_sync_data(td, hostname, port, hints)) {
+    conn->async.os_specific = NULL;
+    free(td);
+    goto errno_exit;
+  }
 
   free(conn->async.hostname);
   conn->async.hostname = strdup(hostname);
   if(!conn->async.hostname)
     goto err_exit;
 
+  /* The thread will set this to 1 when complete. */
+  td->tsd.done = 0;
+
 #ifdef HAVE_GETADDRINFO
   td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
 #else
@@ -407,6 +417,8 @@ static bool init_resolve_thread(struct connectdata *conn,
 #endif
 
   if(!td->thread_hnd) {
+    /* The thread never started, so mark it as done here for proper cleanup. */
+    td->tsd.done = 1;
     err = errno;
     goto err_exit;
   }
@@ -416,6 +428,7 @@ static bool init_resolve_thread(struct connectdata *conn,
  err_exit:
   destroy_async_data(&conn->async);
 
+ errno_exit:
   errno = err;
   return FALSE;
 }
diff --git a/lib/checksrc.pl b/lib/checksrc.pl
index 2eff3e0cf..c1f74bebf 100755
--- a/lib/checksrc.pl
+++ b/lib/checksrc.pl
@@ -58,7 +58,11 @@ my %warnings = (
     'OPENCOMMENT'      => 'file ended with a /* comment still "open"',
     'ASTERISKSPACE'    => 'pointer declared with space after asterisk',
     'ASTERISKNOSPACE'  => 'pointer declared without space before asterisk',
-    'ASSIGNWITHINCONDITION'  => 'assignment within conditional expression'
+    'ASSIGNWITHINCONDITION'  => 'assignment within conditional expression',
+    'EQUALSNOSPACE'    => 'equals sign without following space',
+    'NOSPACEEQUALS'    => 'equals sign without preceeding space',
+    'SEMINOSPACE'      => 'semicolon without following space',
+    'MULTISPACE'       => 'multiple spaces used when not suitable',
     );
 
 sub readwhitelist {
@@ -345,6 +349,9 @@ sub scanfile {
             elsif($3 eq "return") {
                 # return must have a space
             }
+            elsif($3 eq "case") {
+                # case must have a space
+            }
             elsif($4 eq "*") {
                 # (* beginning makes the space OK!
             }
@@ -523,6 +530,52 @@ sub scanfile {
                           "wrongly placed open brace");
             }
         }
+
+        # check for equals sign without spaces next to it
+        if($nostr =~ /(.*)\=[a-z0-9]/i) {
+            checkwarn("EQUALSNOSPACE",
+                      $line, length($1)+1, $file, $ol,
+                      "no space after equals sign");
+        }
+        # check for equals sign without spaces before it
+        elsif($nostr =~ /(.*)[a-z0-9]\=/i) {
+            checkwarn("NOSPACEEQUALS",
+                      $line, length($1)+1, $file, $ol,
+                      "no space before equals sign");
+        }
+
+        # check for plus signs without spaces next to it
+        if($nostr =~ /(.*)[^+]\+[a-z0-9]/i) {
+            checkwarn("PLUSNOSPACE",
+                      $line, length($1)+1, $file, $ol,
+                      "no space after plus sign");
+        }
+        # check for plus sign without spaces before it
+        elsif($nostr =~ /(.*)[a-z0-9]\+[^+]/i) {
+            checkwarn("NOSPACEPLUS",
+                      $line, length($1)+1, $file, $ol,
+                      "no space before plus sign");
+        }
+
+        # check for semicolons without space next to it
+        if($nostr =~ /(.*)\;[a-z0-9]/i) {
+            checkwarn("SEMINOSPACE",
+                      $line, length($1)+1, $file, $ol,
+                      "no space after semilcolon");
+        }
+
+        # check for more than one consecutive space before open brace or
+        # question mark. Skip lines containing strings since they make it hard
+        # due to artificially getting multiple spaces
+        if(($l eq $nostr) &&
+           $nostr =~ /^(.*(\S)) + [{?]/i) {
+            checkwarn("MULTISPACE",
+                      $line, length($1)+1, $file, $ol,
+                      "multiple space");
+            print STDERR "L: $l\n";
+            print STDERR "nostr: $nostr\n";
+        }
+
         $line++;
         $prevl = $ol;
     }
diff --git a/lib/config-dos.h b/lib/config-dos.h
index f2c9ff403..eec7af988 100644
--- a/lib/config-dos.h
+++ b/lib/config-dos.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,8 +40,10 @@
 #define PACKAGE  "curl"
 
 #define HAVE_ARPA_INET_H       1
+#define HAVE_ASSERT_H          1
 #define HAVE_ERRNO_H           1
 #define HAVE_FCNTL_H           1
+#define HAVE_FREEADDRINFO      1
 #define HAVE_GETADDRINFO       1
 #define HAVE_GETNAMEINFO       1
 #define HAVE_GETPROTOBYNAME    1
@@ -85,9 +87,11 @@
 
 #define RETSIGTYPE             void
 #define SIZEOF_INT             4
+#define SIZEOF_LONG            4
 #define SIZEOF_LONG_DOUBLE     16
 #define SIZEOF_SHORT           2
 #define SIZEOF_SIZE_T          4
+#define SIZEOF_CURL_OFF_T      4
 #define STDC_HEADERS           1
 #define TIME_WITH_SYS_TIME     1
 
diff --git a/lib/config-tpf.h b/lib/config-tpf.h
index d1714fdfc..d1eb3d906 100644
--- a/lib/config-tpf.h
+++ b/lib/config-tpf.h
@@ -618,6 +618,9 @@
 /* The size of `short', as computed by sizeof. */
 #define SIZEOF_SHORT 2
 
+/* Define to the size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 8
+
 /* The size of `size_t', as computed by sizeof. */
 #define SIZEOF_SIZE_T 8
 
diff --git a/lib/config-win32.h b/lib/config-win32.h
index 4cac859cd..00191fe4c 100644
--- a/lib/config-win32.h
+++ b/lib/config-win32.h
@@ -399,6 +399,9 @@
 /* Define to the size of `short', as computed by sizeof. */
 #define SIZEOF_SHORT 2
 
+/* Define to the size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
 /* Define to the size of `size_t', as computed by sizeof. */
 #if defined(_WIN64)
 #  define SIZEOF_SIZE_T 8
@@ -406,6 +409,9 @@
 #  define SIZEOF_SIZE_T 4
 #endif
 
+/* Define to the size of `curl_off_t', as computed by sizeof. */
+#define SIZEOF_CURL_OFF_T 8
+
 /* ---------------------------------------------------------------- */
 /*               BSD-style lwIP TCP/IP stack SPECIFIC               */
 /* ---------------------------------------------------------------- */
diff --git a/lib/config-win32ce.h b/lib/config-win32ce.h
index eb444c585..28a15f2a1 100644
--- a/lib/config-win32ce.h
+++ b/lib/config-win32ce.h
@@ -346,6 +346,9 @@
 /* The size of `short', as computed by sizeof. */
 #define SIZEOF_SHORT 2
 
+/* Define to the size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
 /* The size of `size_t', as computed by sizeof. */
 #if defined(_WIN64)
 #  define SIZEOF_SIZE_T 8
diff --git a/lib/connect.c b/lib/connect.c
old mode 100644
new mode 100755
index 8d5d32ba6..b7d10af55
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -249,7 +249,7 @@ static CURLcode bindlocal(struct connectdata *conn,
   struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
 #endif
 
-  struct Curl_dns_entry *h=NULL;
+  struct Curl_dns_entry *h = NULL;
   unsigned short port = data->set.localport; /* use this port number, 0 for
                                                 "random" */
   /* how many port numbers to try to bind to, increasing one at a time */
@@ -319,7 +319,7 @@ static CURLcode bindlocal(struct connectdata *conn,
            * as a hostname or ip address.
            */
           if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
-                        dev, (curl_socklen_t)strlen(dev)+1) != 0) {
+                        dev, (curl_socklen_t)strlen(dev) + 1) != 0) {
             error = SOCKERRNO;
             infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
                   " will do regular bind\n",
@@ -748,7 +748,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
     return CURLE_OPERATION_TIMEDOUT;
   }
 
-  for(i=0; i<2; i++) {
+  for(i = 0; i<2; i++) {
     const int other = i ^ 1;
     if(conn->tempsock[i] == CURL_SOCKET_BAD)
       continue;
@@ -900,7 +900,7 @@ void Curl_tcpnodelay(struct connectdata *conn, 
curl_socket_t sockfd)
 static void nosigpipe(struct connectdata *conn,
                       curl_socket_t sockfd)
 {
-  struct Curl_easy *data= conn->data;
+  struct Curl_easy *data = conn->data;
   int onoff = 1;
   if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
                 sizeof(onoff)) < 0)
@@ -1059,16 +1059,25 @@ static CURLcode singleipconnect(struct connectdata 
*conn,
   if(!isconnected && (conn->socktype == SOCK_STREAM)) {
     if(conn->bits.tcp_fastopen) {
 #if defined(CONNECT_DATA_IDEMPOTENT) /* OS X */
-      sa_endpoints_t endpoints;
-      endpoints.sae_srcif = 0;
-      endpoints.sae_srcaddr = NULL;
-      endpoints.sae_srcaddrlen = 0;
-      endpoints.sae_dstaddr = &addr.sa_addr;
-      endpoints.sae_dstaddrlen = addr.addrlen;
-
-      rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
-                    CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
-                    NULL, 0, NULL, NULL);
+#ifdef HAVE_BUILTIN_AVAILABLE
+      if(__builtin_available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *)) {
+#endif /* HAVE_BUILTIN_AVAILABLE */
+        sa_endpoints_t endpoints;
+        endpoints.sae_srcif = 0;
+        endpoints.sae_srcaddr = NULL;
+        endpoints.sae_srcaddrlen = 0;
+        endpoints.sae_dstaddr = &addr.sa_addr;
+        endpoints.sae_dstaddrlen = addr.addrlen;
+
+        rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
+                      CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
+                      NULL, 0, NULL, NULL);
+#ifdef HAVE_BUILTIN_AVAILABLE
+      }
+      else {
+        rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
+      }
+#endif /* HAVE_BUILTIN_AVAILABLE */
 #elif defined(MSG_FASTOPEN) /* Linux */
       if(conn->given->flags & PROTOPT_SSL)
         rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
@@ -1152,7 +1161,6 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* 
context */
   conn->tempaddr[1] = NULL;
   conn->tempsock[0] = CURL_SOCKET_BAD;
   conn->tempsock[1] = CURL_SOCKET_BAD;
-  Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS);
 
   /* Max time for the next connection attempt */
   conn->timeoutms_per_addr =
@@ -1173,6 +1181,7 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* 
context */
   }
 
   data->info.numconnects++; /* to track the number of connections made */
+  Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS);
 
   return CURLE_OK;
 }
@@ -1324,7 +1333,7 @@ CURLcode Curl_socket(struct connectdata *conn,
 
   addr->family = ai->ai_family;
   addr->socktype = conn->socktype;
-  addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
+  addr->protocol = conn->socktype == SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
   addr->addrlen = ai->ai_addrlen;
 
   if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index cfec87c57..b1a540f03 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -227,7 +227,7 @@ static enum {
 
     extra_len = (data[1] << 8) | data[0];
 
-    if(len < (extra_len+2))
+    if(len < (extra_len + 2))
       return GZIP_UNDERFLOW;
 
     len -= (extra_len + 2);
@@ -288,7 +288,7 @@ Curl_unencode_gzip_write(struct connectdata *conn,
 
     if(strcmp(zlibVersion(), "1.2.0.4") >= 0) {
       /* zlib ver. >= 1.2.0.4 supports transparent gzip decompressing */
-      if(inflateInit2(z, MAX_WBITS+32) != Z_OK) {
+      if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) {
         return process_zlib_error(conn, z);
       }
       k->zlib_init = ZLIB_INIT_GZIP; /* Transparent gzip decompress state */
diff --git a/lib/cookie.c b/lib/cookie.c
index 6b678aeb8..271f6d49d 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -125,7 +125,7 @@ static bool tailmatch(const char *cooke_domain, const char 
*hostname)
   if(hostname_len < cookie_domain_len)
     return FALSE;
 
-  if(!strcasecompare(cooke_domain, hostname+hostname_len-cookie_domain_len))
+  if(!strcasecompare(cooke_domain, hostname + hostname_len-cookie_domain_len))
     return FALSE;
 
   /* A lead char of cookie_domain is not '.'.
@@ -375,9 +375,8 @@ Curl_cookie_add(struct Curl_easy *data,
                                        unless set */
 {
   struct Cookie *clist;
-  char name[MAX_NAME];
   struct Cookie *co;
-  struct Cookie *lastc=NULL;
+  struct Cookie *lastc = NULL;
   time_t now = time(NULL);
   bool replace_old = FALSE;
   bool badcookie = FALSE; /* cookies are good by default. mmmmm yummy */
@@ -397,17 +396,19 @@ Curl_cookie_add(struct Curl_easy *data,
 
   if(httpheader) {
     /* This line was read off a HTTP-header */
+    char name[MAX_NAME];
+    char what[MAX_NAME];
     const char *ptr;
     const char *semiptr;
-    char *what;
 
-    what = malloc(MAX_COOKIE_LINE);
-    if(!what) {
+    size_t linelength = strlen(lineptr);
+    if(linelength > MAX_COOKIE_LINE) {
+      /* discard overly long lines at once */
       free(co);
       return NULL;
     }
 
-    semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
+    semiptr = strchr(lineptr, ';'); /* first, find a semicolon */
 
     while(*lineptr && ISBLANK(*lineptr))
       lineptr++;
@@ -415,9 +416,9 @@ Curl_cookie_add(struct Curl_easy *data,
     ptr = lineptr;
     do {
       /* we have a <what>=<this> pair or a stand-alone word here */
-      name[0]=what[0]=0; /* init the buffers */
+      name[0] = what[0] = 0; /* init the buffers */
       if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n=] =%"
-                     MAX_COOKIE_LINE_TXT "[^;\r\n]",
+                     MAX_NAME_TXT "[^;\r\n]",
                      name, what)) {
         /* Use strstore() below to properly deal with received cookie
            headers that have the same string property set more than once,
@@ -425,10 +426,24 @@ Curl_cookie_add(struct Curl_easy *data,
         const char *whatptr;
         bool done = FALSE;
         bool sep;
-        size_t len=strlen(what);
+        size_t len = strlen(what);
         size_t nlen = strlen(name);
         const char *endofn = &ptr[ nlen ];
 
+        infof(data, "cookie size: name/val %d + %d bytes\n",
+              nlen, len);
+
+        if(nlen >= (MAX_NAME-1) || len >= (MAX_NAME-1) ||
+           ((nlen + len) > MAX_NAME)) {
+          /* too long individual name or contents, or too long combination of
+             name + contents. Chrome and Firefox support 4095 or 4096 bytes
+             combo. */
+          freecookie(co);
+          infof(data, "oversized cookie dropped, name/val %d + %d bytes\n",
+                nlen, len);
+          return NULL;
+        }
+
         /* name ends with a '=' ? */
         sep = (*endofn == '=')?TRUE:FALSE;
 
@@ -440,18 +455,18 @@ Curl_cookie_add(struct Curl_easy *data,
               endofn--;
               nlen--;
             }
-            name[nlen]=0; /* new end of name */
+            name[nlen] = 0; /* new end of name */
           }
         }
 
         /* Strip off trailing whitespace from the 'what' */
         while(len && ISBLANK(what[len-1])) {
-          what[len-1]=0;
+          what[len-1] = 0;
           len--;
         }
 
         /* Skip leading whitespace from the 'what' */
-        whatptr=what;
+        whatptr = what;
         while(*whatptr && ISBLANK(*whatptr))
           whatptr++;
 
@@ -484,6 +499,7 @@ Curl_cookie_add(struct Curl_easy *data,
             badcookie = TRUE; /* out of memory bad */
             break;
           }
+          free(co->spath); /* if this is set again */
           co->spath = sanitize_cookie_path(co->path);
           if(!co->spath) {
             badcookie = TRUE; /* out of memory bad */
@@ -510,7 +526,7 @@ Curl_cookie_add(struct Curl_easy *data,
             /* check for more dots */
             dotp = strchr(whatptr, '.');
             if(!dotp && !strcasecompare("localhost", whatptr))
-              domain=":";
+              domain = ":";
           }
 #endif
 
@@ -525,14 +541,14 @@ Curl_cookie_add(struct Curl_easy *data,
               break;
             }
             if(!is_ip)
-              co->tailmatch=TRUE; /* we always do that if the domain name was
-                                     given */
+              co->tailmatch = TRUE; /* we always do that if the domain name was
+                                       given */
           }
           else {
             /* we did not get a tailmatch and then the attempted set domain
                is not a domain to which the current host belongs. Mark as
                bad. */
-            badcookie=TRUE;
+            badcookie = TRUE;
             infof(data, "skipped cookie with bad tailmatch domain: %s\n",
                   whatptr);
           }
@@ -581,26 +597,32 @@ Curl_cookie_add(struct Curl_easy *data,
         continue;
       }
 
-      ptr=semiptr+1;
+      ptr = semiptr + 1;
       while(*ptr && ISBLANK(*ptr))
         ptr++;
-      semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
+      semiptr = strchr(ptr, ';'); /* now, find the next semicolon */
 
       if(!semiptr && *ptr)
         /* There are no more semicolons, but there's a final name=value pair
            coming up */
-        semiptr=strchr(ptr, '\0');
+        semiptr = strchr(ptr, '\0');
     } while(semiptr);
 
     if(co->maxage) {
-      co->expires =
-        curlx_strtoofft((*co->maxage=='\"')?
-                        &co->maxage[1]:&co->maxage[0], NULL, 10);
-      if(CURL_OFF_T_MAX - now < co->expires)
-        /* avoid overflow */
+      CURLofft offt;
+      offt = curlx_strtoofft((*co->maxage == '\"')?
+                             &co->maxage[1]:&co->maxage[0], NULL, 10,
+                             &co->expires);
+      if(offt == CURL_OFFT_FLOW)
+        /* overflow, used max value */
         co->expires = CURL_OFF_T_MAX;
-      else
-        co->expires += now;
+      else if(!offt) {
+        if(CURL_OFF_T_MAX - now < co->expires)
+          /* would overflow */
+          co->expires = CURL_OFF_T_MAX;
+        else
+          co->expires += now;
+      }
     }
     else if(co->expirestr) {
       /* Note that if the date couldn't get parsed for whatever reason,
@@ -619,7 +641,7 @@ Curl_cookie_add(struct Curl_easy *data,
     if(!badcookie && !co->domain) {
       if(domain) {
         /* no domain was given in the header line, set the default */
-        co->domain=strdup(domain);
+        co->domain = strdup(domain);
         if(!co->domain)
           badcookie = TRUE;
       }
@@ -639,11 +661,11 @@ Curl_cookie_add(struct Curl_easy *data,
       else
         endslash = memrchr(path, '/', (size_t)(queryp - path));
       if(endslash) {
-        size_t pathlen = (size_t)(endslash-path+1); /* include ending slash */
-        co->path=malloc(pathlen+1); /* one extra for the zero byte */
+        size_t pathlen = (size_t)(endslash-path + 1); /* include end slash */
+        co->path = malloc(pathlen + 1); /* one extra for the zero byte */
         if(co->path) {
           memcpy(co->path, path, pathlen);
-          co->path[pathlen]=0; /* zero terminate */
+          co->path[pathlen] = 0; /* zero terminate */
           co->spath = sanitize_cookie_path(co->path);
           if(!co->spath)
             badcookie = TRUE; /* out of memory bad */
@@ -653,8 +675,6 @@ Curl_cookie_add(struct Curl_easy *data,
       }
     }
 
-    free(what);
-
     if(badcookie || !co->name) {
       /* we didn't get a cookie name or a bad one,
          this is an illegal line, bail out */
@@ -668,7 +688,7 @@ Curl_cookie_add(struct Curl_easy *data,
        reading the odd netscape cookies-file format here */
     char *ptr;
     char *firstptr;
-    char *tok_buf=NULL;
+    char *tok_buf = NULL;
     int fields;
 
     /* IE introduced HTTP-only cookies to prevent XSS attacks. Cookies
@@ -689,19 +709,19 @@ Curl_cookie_add(struct Curl_easy *data,
       return NULL;
     }
     /* strip off the possible end-of-line characters */
-    ptr=strchr(lineptr, '\r');
+    ptr = strchr(lineptr, '\r');
     if(ptr)
-      *ptr=0; /* clear it */
-    ptr=strchr(lineptr, '\n');
+      *ptr = 0; /* clear it */
+    ptr = strchr(lineptr, '\n');
     if(ptr)
-      *ptr=0; /* clear it */
+      *ptr = 0; /* clear it */
 
-    firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
+    firstptr = strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */
 
     /* Now loop through the fields and init the struct we already have
        allocated */
-    for(ptr=firstptr, fields=0; ptr && !badcookie;
-        ptr=strtok_r(NULL, "\t", &tok_buf), fields++) {
+    for(ptr = firstptr, fields = 0; ptr && !badcookie;
+        ptr = strtok_r(NULL, "\t", &tok_buf), fields++) {
       switch(fields) {
       case 0:
         if(ptr[0]=='.') /* skip preceding dots */
@@ -753,7 +773,8 @@ Curl_cookie_add(struct Curl_easy *data,
         co->secure = strcasecompare(ptr, "TRUE")?TRUE:FALSE;
         break;
       case 4:
-        co->expires = curlx_strtoofft(ptr, NULL, 10);
+        if(curlx_strtoofft(ptr, NULL, 10, &co->expires))
+          badcookie = TRUE;
         break;
       case 5:
         co->name = strdup(ptr);
@@ -828,7 +849,7 @@ Curl_cookie_add(struct Curl_easy *data,
         if(strcasecompare(clist->domain, co->domain) &&
           (clist->tailmatch == co->tailmatch))
           /* The domains are identical */
-          replace_old=TRUE;
+          replace_old = TRUE;
       }
       else if(!clist->domain && !co->domain)
         replace_old = TRUE;
@@ -957,7 +978,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
 {
   struct CookieInfo *c;
   FILE *fp = NULL;
-  bool fromfile=TRUE;
+  bool fromfile = TRUE;
   char *line = NULL;
 
   if(NULL == inc) {
@@ -977,7 +998,7 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data,
 
   if(file && !strcmp(file, "-")) {
     fp = stdin;
-    fromfile=FALSE;
+    fromfile = FALSE;
   }
   else if(file && !*file) {
     /* points to a "" string */
@@ -998,12 +1019,12 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy 
*data,
     while(get_line(line, MAX_COOKIE_LINE, fp)) {
       if(checkprefix("Set-Cookie:", line)) {
         /* This is a cookie line, get it! */
-        lineptr=&line[11];
-        headerline=TRUE;
+        lineptr = &line[11];
+        headerline = TRUE;
       }
       else {
-        lineptr=line;
-        headerline=FALSE;
+        lineptr = line;
+        headerline = FALSE;
       }
       while(*lineptr && ISBLANK(*lineptr))
         lineptr++;
@@ -1113,7 +1134,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
   struct Cookie *newco;
   struct Cookie *co;
   time_t now = time(NULL);
-  struct Cookie *mainco=NULL;
+  struct Cookie *mainco = NULL;
   size_t matches = 0;
   bool is_ip;
 
@@ -1185,7 +1206,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
 
     co = mainco;
 
-    for(i=0; co; co = co->next)
+    for(i = 0; co; co = co->next)
       array[i++] = co;
 
     /* now sort the cookie pointers in path length order */
@@ -1194,8 +1215,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
     /* remake the linked list order according to the new order */
 
     mainco = array[0]; /* start here */
-    for(i=0; i<matches-1; i++)
-      array[i]->next = array[i+1];
+    for(i = 0; i<matches-1; i++)
+      array[i]->next = array[i + 1];
     array[matches-1]->next = NULL; /* terminate the list */
 
     free(array); /* remove the temporary data again */
@@ -1335,7 +1356,7 @@ static int cookie_output(struct CookieInfo *c, const char 
*dumphere)
 {
   struct Cookie *co;
   FILE *out;
-  bool use_stdout=FALSE;
+  bool use_stdout = FALSE;
   char *format_ptr;
 
   if((NULL == c) || (0 == c->numcookies))
@@ -1349,7 +1370,7 @@ static int cookie_output(struct CookieInfo *c, const char 
*dumphere)
   if(!strcmp("-", dumphere)) {
     /* use stdout */
     out = stdout;
-    use_stdout=TRUE;
+    use_stdout = TRUE;
   }
   else {
     out = fopen(dumphere, FOPEN_WRITETEXT);
@@ -1382,7 +1403,7 @@ static int cookie_output(struct CookieInfo *c, const char 
*dumphere)
   return 0;
 }
 
-struct curl_slist *Curl_cookie_list(struct Curl_easy *data)
+static struct curl_slist *cookie_list(struct Curl_easy *data)
 {
   struct curl_slist *list = NULL;
   struct curl_slist *beg;
@@ -1413,6 +1434,15 @@ struct curl_slist *Curl_cookie_list(struct Curl_easy 
*data)
   return list;
 }
 
+struct curl_slist *Curl_cookie_list(struct Curl_easy *data)
+{
+  struct curl_slist *list;
+  Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
+  list = cookie_list(data);
+  Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
+  return list;
+}
+
 void Curl_flush_cookies(struct Curl_easy *data, int cleanup)
 {
   if(data->set.str[STRING_COOKIEJAR]) {
diff --git a/lib/cookie.h b/lib/cookie.h
index 41c315a82..bb13dacea 100644
--- a/lib/cookie.h
+++ b/lib/cookie.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,16 @@ struct CookieInfo {
    that comprise the cookie non-terminal in the syntax description of the
    Set-Cookie header)"
 
+   We allow max 5000 bytes cookie header. Max 4095 bytes length per cookie
+   name and value. Name + value may not exceed 4096 bytes.
+
 */
 #define MAX_COOKIE_LINE 5000
 #define MAX_COOKIE_LINE_TXT "4999"
 
-/* This is the maximum length of a cookie name we deal with: */
-#define MAX_NAME 1024
-#define MAX_NAME_TXT "1023"
+/* This is the maximum length of a cookie name or content we deal with: */
+#define MAX_NAME 4096
+#define MAX_NAME_TXT "4095"
 
 struct Curl_easy;
 /*
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c
index 3da23fda9..1f0ebb813 100644
--- a/lib/curl_addrinfo.c
+++ b/lib/curl_addrinfo.c
@@ -286,7 +286,7 @@ Curl_he2ai(const struct hostent *he, int port)
 
   DEBUGASSERT((he->h_name != NULL) && (he->h_addr_list != NULL));
 
-  for(i=0; (curr = he->h_addr_list[i]) != NULL; i++) {
+  for(i = 0; (curr = he->h_addr_list[i]) != NULL; i++) {
 
     size_t ss_size;
 #ifdef ENABLE_IPV6
@@ -570,9 +570,9 @@ curl_dogetaddrinfo(const char *hostname,
                    int line, const char *source)
 {
 #ifdef USE_LWIPSOCK
-  int res=lwip_getaddrinfo(hostname, service, hints, result);
+  int res = lwip_getaddrinfo(hostname, service, hints, result);
 #else
-  int res=(getaddrinfo)(hostname, service, hints, result);
+  int res = (getaddrinfo)(hostname, service, hints, result);
 #endif
   if(0 == res)
     /* success */
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index c1452b3e7..c80484f65 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -51,9 +51,6 @@
 /* to disable RTSP */
 #cmakedefine CURL_DISABLE_RTSP 1
 
-/* to disable RTMP */
-#cmakedefine CURL_DISABLE_RTMP 1
-
 /* to disable SMB */
 #cmakedefine CURL_DISABLE_SMB 1
 
@@ -82,9 +79,6 @@
 /* when not building a shared library */
 #cmakedefine CURL_STATICLIB 1
 
-/* Set to explicitly specify we don't want to use thread-safe functions */
-#cmakedefine DISABLED_THREADSAFE 1
-
 /* your Entropy Gathering Daemon socket pathname */
 #cmakedefine EGD_SOCKET ${EGD_SOCKET}
 
@@ -894,6 +888,9 @@
 /* The size of `off_t', as computed by sizeof. */
 #cmakedefine SIZEOF_OFF_T ${SIZEOF_OFF_T}
 
+/* The size of `curl_off_t', as computed by sizeof. */
+#cmakedefine SIZEOF_CURL_OFF_T ${SIZEOF_CURL_OFF_T}
+
 /* The size of `size_t', as computed by sizeof. */
 #cmakedefine SIZEOF_SIZE_T ${SIZEOF_SIZE_T}
 
diff --git a/lib/curl_fnmatch.c b/lib/curl_fnmatch.c
index e9224ada5..6a7267d07 100644
--- a/lib/curl_fnmatch.c
+++ b/lib/curl_fnmatch.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -151,7 +151,7 @@ static int setcharset(unsigned char **p, unsigned char 
*charset)
         (*p)++;
       }
       else if(c == '[') {
-        char c2 = *((*p)+1);
+        char c2 = *((*p) + 1);
         if(c2 == ':') { /* there has to be a keyword */
           (*p) += 2;
           if(parsekeyword(p, charset)) {
@@ -319,9 +319,9 @@ static int loop(const unsigned char *pattern, const 
unsigned char *string)
     switch(state) {
     case CURLFNM_LOOP_DEFAULT:
       if(*p == '*') {
-        while(*(p+1) == '*') /* eliminate multiple stars */
+        while(*(p + 1) == '*') /* eliminate multiple stars */
           p++;
-        if(*s == '\0' && *(p+1) == '\0')
+        if(*s == '\0' && *(p + 1) == '\0')
           return CURL_FNMATCH_MATCH;
         rc = loop(p + 1, s); /* *.txt matches .txt <=> .txt matches .txt */
         if(rc == CURL_FNMATCH_MATCH)
@@ -351,7 +351,7 @@ static int loop(const unsigned char *pattern, const 
unsigned char *string)
         p++;
       }
       else if(*p == '[') {
-        unsigned char *pp = p+1; /* cannot handle with pointer to register */
+        unsigned char *pp = p + 1; /* cannot handle with pointer to register */
         if(setcharset(&pp, charset)) {
           int found = FALSE;
           if(charset[(unsigned int)*s])
@@ -381,7 +381,7 @@ static int loop(const unsigned char *pattern, const 
unsigned char *string)
             found = !found;
 
           if(found) {
-            p = pp+1;
+            p = pp + 1;
             s++;
             memset(charset, 0, CURLFNM_CHSET_SIZE);
           }
diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c
index aea545295..5154949e6 100644
--- a/lib/curl_ntlm_core.c
+++ b/lib/curl_ntlm_core.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,25 @@
  * https://www.innovation.ch/java/ntlm.html
  */
 
+/* Please keep the SSL backend-specific #if branches in this order:
+
+   1. USE_OPENSSL
+   2. USE_GNUTLS_NETTLE
+   3. USE_GNUTLS
+   4. USE_NSS
+   5. USE_MBEDTLS
+   6. USE_DARWINSSL
+   7. USE_OS400CRYPTO
+   8. 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.
+   - OpenSSL and NSS have higher priority than Windows Crypt, due
+     to issues with the latter supporting NTLM2Session responses
+     in NTLM type-3 messages.
+ */
+
 #if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
 
 #ifdef USE_OPENSSL
@@ -76,14 +95,6 @@
 #  define MD5_DIGEST_LENGTH 16
 #  define MD4_DIGEST_LENGTH 16
 
-#elif defined(USE_MBEDTLS)
-
-#  include <mbedtls/des.h>
-#  include <mbedtls/md4.h>
-#  if !defined(MBEDTLS_MD4_C)
-#    include "curl_md4.h"
-#  endif
-
 #elif defined(USE_NSS)
 
 #  include <nss.h>
@@ -92,6 +103,14 @@
 #  include "curl_md4.h"
 #  define MD5_DIGEST_LENGTH MD5_LENGTH
 
+#elif defined(USE_MBEDTLS)
+
+#  include <mbedtls/des.h>
+#  include <mbedtls/md4.h>
+#  if !defined(MBEDTLS_MD4_C)
+#    include "curl_md4.h"
+#  endif
+
 #elif defined(USE_DARWINSSL)
 
 #  include <CommonCrypto/CommonCryptor.h>
@@ -196,26 +215,6 @@ static void setup_des_key(const unsigned char *key_56,
   gcry_cipher_setkey(*des, key, sizeof(key));
 }
 
-#elif defined(USE_MBEDTLS)
-
-static bool encrypt_des(const unsigned char *in, unsigned char *out,
-                        const unsigned char *key_56)
-{
-  mbedtls_des_context ctx;
-  char key[8];
-
-  /* Expand the 56-bit key to 64-bits */
-  extend_key_56_to_64(key_56, key);
-
-  /* Set the key parity to odd */
-  mbedtls_des_key_set_parity((unsigned char *) key);
-
-  /* Perform the encryption */
-  mbedtls_des_init(&ctx);
-  mbedtls_des_setkey_enc(&ctx, (unsigned char *) key);
-  return mbedtls_des_crypt_ecb(&ctx, in, out) == 0;
-}
-
 #elif defined(USE_NSS)
 
 /*
@@ -281,6 +280,26 @@ fail:
   return rv;
 }
 
+#elif defined(USE_MBEDTLS)
+
+static bool encrypt_des(const unsigned char *in, unsigned char *out,
+                        const unsigned char *key_56)
+{
+  mbedtls_des_context ctx;
+  char key[8];
+
+  /* Expand the 56-bit key to 64-bits */
+  extend_key_56_to_64(key_56, key);
+
+  /* Set the key parity to odd */
+  mbedtls_des_key_set_parity((unsigned char *) key);
+
+  /* Perform the encryption */
+  mbedtls_des_init(&ctx);
+  mbedtls_des_setkey_enc(&ctx, (unsigned char *) key);
+  return mbedtls_des_crypt_ecb(&ctx, in, out) == 0;
+}
+
 #elif defined(USE_DARWINSSL)
 
 static bool encrypt_des(const unsigned char *in, unsigned char *out,
@@ -428,7 +447,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
   setup_des_key(keys + 14, &des);
   gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
   gcry_cipher_close(des);
-#elif defined(USE_MBEDTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) \
+#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \
   || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
   encrypt_des(plaintext, results, keys);
   encrypt_des(plaintext, results + 8, keys + 7);
@@ -492,7 +511,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
     setup_des_key(pw + 7, &des);
     gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
     gcry_cipher_close(des);
-#elif defined(USE_MBEDTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) \
+#elif defined(USE_NSS) || defined(USE_MBEDTLS) || defined(USE_DARWINSSL) \
   || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
     encrypt_des(magic, lmbuffer, pw);
     encrypt_des(magic, lmbuffer + 8, pw + 7);
@@ -571,13 +590,18 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
     gcry_md_write(MD4pw, pw, 2 * len);
     memcpy(ntbuffer, gcry_md_read(MD4pw, 0), MD4_DIGEST_LENGTH);
     gcry_md_close(MD4pw);
-#elif defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
-    (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
+#elif defined(USE_NSS)
     Curl_md4it(ntbuffer, pw, 2 * len);
 #elif defined(USE_MBEDTLS)
+#if defined(MBEDTLS_MD4_C)
     mbedtls_md4(pw, 2 * len, ntbuffer);
+#else
+    Curl_md4it(ntbuffer, pw, 2 * len);
+#endif
 #elif defined(USE_DARWINSSL)
     (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
+#elif defined(USE_OS400CRYPTO)
+    Curl_md4it(ntbuffer, pw, 2 * len);
 #elif defined(USE_WIN32_CRYPTO)
     HCRYPTPROV hprov;
     if(CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL,
@@ -780,7 +804,7 @@ CURLcode  Curl_ntlm_core_mk_lmv2_resp(unsigned char 
*ntlmv2hash,
 
   /* Concatenate the HMAC MD5 output  with the client nonce */
   memcpy(lmresp, hmac_output, 16);
-  memcpy(lmresp+16, challenge_client, 8);
+  memcpy(lmresp + 16, challenge_client, 8);
 
   return result;
 }
diff --git a/lib/curl_ntlm_core.h b/lib/curl_ntlm_core.h
index 4a83d40bc..07ef5deae 100644
--- a/lib/curl_ntlm_core.h
+++ b/lib/curl_ntlm_core.h
@@ -26,13 +26,19 @@
 
 #if defined(USE_NTLM)
 
+/* If NSS is the first available SSL backend (see order in curl_ntlm_core.c)
+   then it must be initialized to be used by NTLM. */
+#if !defined(USE_OPENSSL) && \
+    !defined(USE_GNUTLS_NETTLE) && \
+    !defined(USE_GNUTLS) && \
+    defined(USE_NSS)
+#define NTLM_NEEDS_NSS_INIT
+#endif
+
 #if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
 
 #ifdef USE_OPENSSL
-#  if !defined(OPENSSL_VERSION_NUMBER) && \
-      !defined(HEADER_SSL_H) && !defined(HEADER_MD5_H)
-#    error "curl_ntlm_core.h shall not be included before OpenSSL headers."
-#  endif
+#  include <openssl/ssl.h>
 #endif
 
 /* Define USE_NTRESPONSES in order to make the type-3 message include
diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c
index 9e9586cc3..03f47a3a5 100644
--- a/lib/curl_ntlm_wb.c
+++ b/lib/curl_ntlm_wb.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -48,6 +48,7 @@
 #include "sendf.h"
 #include "select.h"
 #include "vauth/ntlm.h"
+#include "curl_ntlm_core.h"
 #include "curl_ntlm_wb.h"
 #include "url.h"
 #include "strerror.h"
@@ -357,7 +358,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
 
   /* not set means empty */
   if(!userp)
-    userp="";
+    userp = "";
 
   switch(ntlm->state) {
   case NTLMSTATE_TYPE1:
@@ -413,7 +414,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
     /* connection is already authenticated,
      * don't send a header in future requests */
     free(*allocuserpwd);
-    *allocuserpwd=NULL;
+    *allocuserpwd = NULL;
     authp->done = TRUE;
     break;
   }
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index bd3b2be9e..10a59aa5f 100644
--- a/lib/curl_sasl.c
+++ b/lib/curl_sasl.c
@@ -331,7 +331,8 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct 
connectdata *conn,
       sasl->authused = SASL_MECH_NTLM;
 
       if(force_ir || data->set.sasl_ir)
-        result = Curl_auth_create_ntlm_type1_message(conn->user, conn->passwd,
+        result = Curl_auth_create_ntlm_type1_message(data,
+                                                     conn->user, conn->passwd,
                                                      &conn->ntlm, &resp, &len);
       }
     else
@@ -493,7 +494,8 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct 
connectdata *conn,
 #ifdef USE_NTLM
   case SASL_NTLM:
     /* Create the type-1 message */
-    result = Curl_auth_create_ntlm_type1_message(conn->user, conn->passwd,
+    result = Curl_auth_create_ntlm_type1_message(data,
+                                                 conn->user, conn->passwd,
                                                  &conn->ntlm, &resp, &len);
     newstate = SASL_NTLM_TYPE2MSG;
     break;
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index 519d8e5c4..1034b5a78 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -141,14 +141,7 @@
 
 #include <gnurl/curl.h>
 
-/*
- * Ensure that no one is using the old SIZEOF_CURL_OFF_T macro
- */
-
-#ifdef SIZEOF_CURL_OFF_T
-#  error "SIZEOF_CURL_OFF_T shall not be defined!"
-   Error Compilation_aborted_SIZEOF_CURL_OFF_T_shall_not_be_defined
-#endif
+#define CURL_SIZEOF_CURL_OFF_T SIZEOF_CURL_OFF_T
 
 /*
  * Disable other protocols when http is the only one desired.
@@ -185,9 +178,6 @@
 #  ifndef CURL_DISABLE_SMTP
 #    define CURL_DISABLE_SMTP
 #  endif
-#  ifndef CURL_DISABLE_RTMP
-#    define CURL_DISABLE_RTMP
-#  endif
 #  ifndef CURL_DISABLE_GOPHER
 #    define CURL_DISABLE_GOPHER
 #  endif
@@ -206,7 +196,7 @@
 
 /* ================================================================ */
 /* No system header file shall be included in this file before this */
-/* point. The only allowed ones are those included from gnurl/system.h */
+/* point. The only allowed ones are those included from curl/system.h */
 /* ================================================================ */
 
 /*
@@ -727,6 +717,7 @@ Therefore we specify it explicitly. 
https://github.com/curl/curl/pull/258
 #if defined(WIN32) || defined(MSDOS)
 #define FOPEN_READTEXT "rt"
 #define FOPEN_WRITETEXT "wt"
+#define FOPEN_APPENDTEXT "at"
 #elif defined(__CYGWIN__)
 /* Cygwin has specific behavior we need to address when WIN32 is not defined.
 https://cygwin.com/cygwin-ug-net/using-textbinary.html
@@ -736,9 +727,11 @@ endings either CRLF or LF so 't' is appropriate.
 */
 #define FOPEN_READTEXT "rt"
 #define FOPEN_WRITETEXT "w"
+#define FOPEN_APPENDTEXT "a"
 #else
 #define FOPEN_READTEXT "r"
 #define FOPEN_WRITETEXT "w"
+#define FOPEN_APPENDTEXT "a"
 #endif
 
 /* WinSock destroys recv() buffer when send() failed.
diff --git a/lib/dict.c b/lib/dict.c
index af0954855..e801cf704 100644
--- a/lib/dict.c
+++ b/lib/dict.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -98,7 +98,7 @@ static char *unescape_word(struct Curl_easy *data, const char 
*inputbuff)
   char *ptr;
   size_t len;
   char ch;
-  int olen=0;
+  int olen = 0;
 
   CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
   if(!newp || result)
@@ -117,7 +117,7 @@ static char *unescape_word(struct Curl_easy *data, const 
char *inputbuff)
       }
       dictp[olen++] = ch;
     }
-    dictp[olen]=0;
+    dictp[olen] = 0;
   }
   free(newp);
   return dictp;
@@ -132,8 +132,8 @@ static CURLcode dict_do(struct connectdata *conn, bool 
*done)
   char *strategy = NULL;
   char *nthdef = NULL; /* This is not part of the protocol, but required
                           by RFC 2229 */
-  CURLcode result=CURLE_OK;
-  struct Curl_easy *data=conn->data;
+  CURLcode result = CURLE_OK;
+  struct Curl_easy *data = conn->data;
   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
 
   char *path = data->state.path;
@@ -168,7 +168,7 @@ static CURLcode dict_do(struct connectdata *conn, bool 
*done)
 
     if((word == NULL) || (*word == (char)0)) {
       infof(data, "lookup word is missing\n");
-      word=(char *)"default";
+      word = (char *)"default";
     }
     if((database == NULL) || (*database == (char)0)) {
       database = (char *)"!";
@@ -222,7 +222,7 @@ static CURLcode dict_do(struct connectdata *conn, bool 
*done)
 
     if((word == NULL) || (*word == (char)0)) {
       infof(data, "lookup word is missing\n");
-      word=(char *)"default";
+      word = (char *)"default";
     }
     if((database == NULL) || (*database == (char)0)) {
       database = (char *)"!";
diff --git a/lib/dotdot.c b/lib/dotdot.c
index 818061d9f..936f1cdbd 100644
--- a/lib/dotdot.c
+++ b/lib/dotdot.c
@@ -55,7 +55,7 @@ char *Curl_dedotdotify(const char *input)
   size_t inlen = strlen(input);
   char *clone;
   size_t clen = inlen; /* the length of the cloned input */
-  char *out = malloc(inlen+1);
+  char *out = malloc(inlen + 1);
   char *outptr;
   char *orgclone;
   char *queryp;
@@ -92,25 +92,25 @@ char *Curl_dedotdotify(const char *input)
         remove that prefix from the input buffer; otherwise, */
 
     if(!strncmp("./", clone, 2)) {
-      clone+=2;
-      clen-=2;
+      clone += 2;
+      clen -= 2;
     }
     else if(!strncmp("../", clone, 3)) {
-      clone+=3;
-      clen-=3;
+      clone += 3;
+      clen -= 3;
     }
 
     /*  B.  if the input buffer begins with a prefix of "/./" or "/.", where
         "."  is a complete path segment, then replace that prefix with "/" in
         the input buffer; otherwise, */
     else if(!strncmp("/./", clone, 3)) {
-      clone+=2;
-      clen-=2;
+      clone += 2;
+      clen -= 2;
     }
     else if(!strcmp("/.", clone)) {
       clone[1]='/';
       clone++;
-      clen-=1;
+      clen -= 1;
     }
 
     /*  C.  if the input buffer begins with a prefix of "/../" or "/..", where
@@ -119,8 +119,8 @@ char *Curl_dedotdotify(const char *input)
         any) from the output buffer; otherwise, */
 
     else if(!strncmp("/../", clone, 4)) {
-      clone+=3;
-      clen-=3;
+      clone += 3;
+      clen -= 3;
       /* remove the last segment from the output buffer */
       while(outptr > out) {
         outptr--;
@@ -131,8 +131,8 @@ char *Curl_dedotdotify(const char *input)
     }
     else if(!strcmp("/..", clone)) {
       clone[2]='/';
-      clone+=2;
-      clen-=2;
+      clone += 2;
+      clen -= 2;
       /* remove the last segment from the output buffer */
       while(outptr > out) {
         outptr--;
@@ -146,8 +146,8 @@ char *Curl_dedotdotify(const char *input)
         that from the input buffer; otherwise, */
 
     else if(!strcmp(".", clone) || !strcmp("..", clone)) {
-      *clone=0;
-      *out=0;
+      *clone = 0;
+      *out = 0;
     }
 
     else {
@@ -172,7 +172,7 @@ char *Curl_dedotdotify(const char *input)
        from the correct index. */
     size_t oindex = queryp - orgclone;
     qlen = strlen(&input[oindex]);
-    memcpy(outptr, &input[oindex], qlen+1); /* include the ending zero byte */
+    memcpy(outptr, &input[oindex], qlen + 1); /* include the end zero byte */
   }
 
   free(orgclone);
diff --git a/lib/easy.c b/lib/easy.c
index a1fd22b0d..894787191 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -433,7 +433,7 @@ static int events_timer(struct Curl_multi *multi,    /* 
multi handle */
  */
 static int poll2cselect(int pollmask)
 {
-  int omask=0;
+  int omask = 0;
   if(pollmask & POLLIN)
     omask |= CURL_CSELECT_IN;
   if(pollmask & POLLOUT)
@@ -450,7 +450,7 @@ static int poll2cselect(int pollmask)
  */
 static short socketcb2poll(int pollmask)
 {
-  short omask=0;
+  short omask = 0;
   if(pollmask & CURL_POLL_IN)
     omask |= POLLIN;
   if(pollmask & CURL_POLL_OUT)
@@ -473,7 +473,7 @@ static int events_socket(struct Curl_easy *easy,      /* 
easy handle */
 {
   struct events *ev = userp;
   struct socketmonitor *m;
-  struct socketmonitor *prev=NULL;
+  struct socketmonitor *prev = NULL;
 
 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
   (void) easy;
@@ -569,14 +569,14 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, 
struct events *ev)
     struct socketmonitor *m;
     struct pollfd *f;
     struct pollfd fds[4];
-    int numfds=0;
+    int numfds = 0;
     int pollrc;
     int i;
     struct curltime before;
     struct curltime after;
 
     /* populate the fds[] array */
-    for(m = ev->list, f=&fds[0]; m; m = m->next) {
+    for(m = ev->list, f = &fds[0]; m; m = m->next) {
       f->fd = m->socket.fd;
       f->events = m->socket.events;
       f->revents = 0;
@@ -655,7 +655,7 @@ static CURLcode easy_events(struct Curl_multi *multi)
 {
   /* this struct is made static to allow it to be used after this function
      returns and curl_multi_remove_handle() is called */
-  static struct events evs= {2, FALSE, 0, NULL, 0};
+  static struct events evs = {2, FALSE, 0, NULL, 0};
 
   /* if running event-based, do some further multi inits */
   events_setup(multi, &evs);
@@ -1027,13 +1027,13 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int 
action)
     struct tempbuf writebuf[3]; /* there can only be three */
 
     /* copy the structs to allow for immediate re-pausing */
-    for(i=0; i < data->state.tempcount; i++) {
+    for(i = 0; i < data->state.tempcount; i++) {
       writebuf[i] = data->state.tempwrite[i];
       data->state.tempwrite[i].buf = NULL;
     }
     data->state.tempcount = 0;
 
-    for(i=0; i < count; i++) {
+    for(i = 0; i < count; i++) {
       /* even if one function returns error, this loops through and frees all
          buffers */
       if(!result)
diff --git a/lib/escape.c b/lib/escape.c
index 0b8b5317f..8c9449fd7 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -84,14 +84,14 @@ char *curl_easy_escape(struct Curl_easy *data, const char 
*string,
   char *testing_ptr = NULL;
   unsigned char in; /* we need to treat the characters unsigned */
   size_t newlen;
-  size_t strindex=0;
+  size_t strindex = 0;
   size_t length;
   CURLcode result;
 
   if(inlength < 0)
     return NULL;
 
-  alloc = (inlength?(size_t)inlength:strlen(string))+1;
+  alloc = (inlength?(size_t)inlength:strlen(string)) + 1;
   newlen = alloc;
 
   ns = malloc(alloc);
@@ -104,7 +104,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char 
*string,
 
     if(Curl_isunreserved(in))
       /* just copy this */
-      ns[strindex++]=in;
+      ns[strindex++] = in;
     else {
       /* encode it */
       newlen += 2; /* the size grows with two, since this'll become a %XX */
@@ -116,7 +116,7 @@ char *curl_easy_escape(struct Curl_easy *data, const char 
*string,
         ns = testing_ptr;
       }
 
-      result = Curl_convert_to_network(data, &in, 1);
+      result = Curl_convert_to_network(data, (char *)&in, 1);
       if(result) {
         /* Curl_convert_to_network calls failf if unsuccessful */
         free(ns);
@@ -125,11 +125,11 @@ char *curl_easy_escape(struct Curl_easy *data, const char 
*string,
 
       snprintf(&ns[strindex], 4, "%%%02X", in);
 
-      strindex+=3;
+      strindex += 3;
     }
     string++;
   }
-  ns[strindex]=0; /* terminate it */
+  ns[strindex] = 0; /* terminate it */
   return ns;
 }
 
@@ -148,10 +148,10 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
                         char **ostring, size_t *olen,
                         bool reject_ctrl)
 {
-  size_t alloc = (length?length:strlen(string))+1;
+  size_t alloc = (length?length:strlen(string)) + 1;
   char *ns = malloc(alloc);
   unsigned char in;
-  size_t strindex=0;
+  size_t strindex = 0;
   unsigned long hex;
   CURLcode result;
 
@@ -173,15 +173,15 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
 
       in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */
 
-      result = Curl_convert_from_network(data, &in, 1);
+      result = Curl_convert_from_network(data, (char *)&in, 1);
       if(result) {
         /* Curl_convert_from_network calls failf if unsuccessful */
         free(ns);
         return result;
       }
 
-      string+=2;
-      alloc-=2;
+      string += 2;
+      alloc -= 2;
     }
 
     if(reject_ctrl && (in < 0x20)) {
@@ -192,7 +192,7 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
     ns[strindex++] = in;
     string++;
   }
-  ns[strindex]=0; /* terminate it */
+  ns[strindex] = 0; /* terminate it */
 
   if(olen)
     /* store output size */
diff --git a/lib/file.c b/lib/file.c
index acca6ec08..25f8005af 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -133,37 +133,42 @@ static CURLcode file_setup_connection(struct connectdata 
*conn)
 static CURLcode file_range(struct connectdata *conn)
 {
   curl_off_t from, to;
-  curl_off_t totalsize=-1;
+  curl_off_t totalsize = -1;
   char *ptr;
   char *ptr2;
   struct Curl_easy *data = conn->data;
 
   if(data->state.use_range && data->state.range) {
-    from=curlx_strtoofft(data->state.range, &ptr, 0);
-    while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
+    CURLofft from_t;
+    CURLofft to_t;
+    from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
+    if(from_t == CURL_OFFT_FLOW)
+      return CURLE_RANGE_ERROR;
+    while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
       ptr++;
-    to=curlx_strtoofft(ptr, &ptr2, 0);
-    if(ptr == ptr2) {
-      /* we didn't get any digit */
-      to=-1;
-    }
-    if((-1 == to) && (from>=0)) {
+    to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
+    if(to_t == CURL_OFFT_FLOW)
+      return CURLE_RANGE_ERROR;
+    if((to_t == CURL_OFFT_INVAL) && !from_t) {
       /* X - */
       data->state.resume_from = from;
       DEBUGF(infof(data, "RANGE %" CURL_FORMAT_CURL_OFF_T " to end of file\n",
                    from));
     }
-    else if(from < 0) {
+    else if((from_t == CURL_OFFT_INVAL) && !to_t) {
       /* -Y */
-      data->req.maxdownload = -from;
-      data->state.resume_from = from;
+      data->req.maxdownload = to;
+      data->state.resume_from = -to;
       DEBUGF(infof(data, "RANGE the last %" CURL_FORMAT_CURL_OFF_T " bytes\n",
-                   -from));
+                   to));
     }
     else {
       /* X-Y */
       totalsize = to-from;
-      data->req.maxdownload = totalsize+1; /* include last byte */
+      if(totalsize == CURL_OFF_T_MAX)
+        /* this is too big to increase, so bail out */
+        return CURLE_RANGE_ERROR;
+      data->req.maxdownload = totalsize + 1; /* include last byte */
       data->state.resume_from = from;
       DEBUGF(infof(data, "RANGE from %" CURL_FORMAT_CURL_OFF_T
                    " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
@@ -226,7 +231,7 @@ static CURLcode file_connect(struct connectdata *conn, bool 
*done)
   }
 
   /* change path separators from '/' to '\\' for DOS, Windows and OS/2 */
-  for(i=0; i < real_path_len; ++i)
+  for(i = 0; i < real_path_len; ++i)
     if(actual_path[i] == '/')
       actual_path[i] = '\\';
     else if(!actual_path[i]) { /* binary zero */
@@ -428,9 +433,9 @@ static CURLcode file_do(struct connectdata *conn, bool 
*done)
   struct_stat statbuf; /* struct_stat instead of struct stat just to allow the
                           Windows version to have a different struct without
                           having to redefine the simple word 'stat' */
-  curl_off_t expected_size=0;
+  curl_off_t expected_size = 0;
   bool size_known;
-  bool fstated=FALSE;
+  bool fstated = FALSE;
   ssize_t nread;
   struct Curl_easy *data = conn->data;
   char *buf = data->state.buffer;
diff --git a/lib/formdata.c b/lib/formdata.c
index 2d7b6b627..1037d0ec8 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -32,6 +32,8 @@
 
 #include "urldata.h" /* for struct Curl_easy */
 #include "formdata.h"
+#include "mime.h"
+#include "non-ascii.h"
 #include "vtls/vtls.h"
 #include "strcase.h"
 #include "sendf.h"
@@ -42,14 +44,6 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#ifndef HAVE_BASENAME
-static char *Curl_basename(char *path);
-#define basename(x)  Curl_basename((x))
-#endif
-
-static size_t readfromfile(struct Form *form, char *buffer, size_t size);
-static CURLcode formboundary(struct Curl_easy *data, char *buffer, size_t len);
-
 /* What kind of Content-Type to use on un-specified files with unrecognized
    extensions. */
 #define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
@@ -197,7 +191,7 @@ static const char *ContentTypeForFilename(const char 
*filename,
     contenttype = HTTPPOST_CONTENTTYPE_DEFAULT;
 
   if(filename) { /* in case a NULL was passed in */
-    for(i=0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
+    for(i = 0; i<sizeof(ctts)/sizeof(ctts[0]); i++) {
       if(strlen(filename) >= strlen(ctts[i].extension)) {
         if(strcasecompare(filename +
                           strlen(filename) - strlen(ctts[i].extension),
@@ -272,7 +266,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
   struct curl_httppost *post = NULL;
   CURLformoption option;
   struct curl_forms *forms = NULL;
-  char *array_value=NULL; /* value read from an array */
+  char *array_value = NULL; /* value read from an array */
 
   /* This is a state variable, that if TRUE means that we're parsing an
      array that we got passed to us. If FALSE we're parsing the input
@@ -641,15 +635,26 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
         }
         form->contenttype_alloc = TRUE;
       }
+      if(form->name && form->namelength) {
+        /* Name should not contain nul bytes. */
+        size_t i;
+        for(i = 0; i < form->namelength; i++)
+          if(!form->name[i]) {
+            return_value = CURL_FORMADD_NULL;
+            break;
+          }
+        if(return_value != CURL_FORMADD_OK)
+          break;
+      }
       if(!(form->flags & HTTPPOST_PTRNAME) &&
          (form == first_form) ) {
         /* Note that there's small risk that form->name is NULL here if the
            app passed in a bad combo, so we better check for that first. */
         if(form->name) {
-          /* copy name (without strdup; possibly contains null characters) */
+          /* copy name (without strdup; possibly not nul-terminated) */
           form->name = Curl_memdup(form->name, form->namelength?
                                    form->namelength:
-                                   strlen(form->name)+1);
+                                   strlen(form->name) + 1);
         }
         if(!form->name) {
           return_value = CURL_FORMADD_MEMORY;
@@ -663,7 +668,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
         /* copy value (without strdup; possibly contains null characters) */
         size_t clen  = (size_t) form->contentslength;
         if(!clen)
-          clen = strlen(form->value)+1;
+          clen = strlen(form->value) + 1;
 
         form->value = Curl_memdup(form->value, clen);
 
@@ -746,211 +751,6 @@ CURLFORMcode curl_formadd(struct curl_httppost **httppost,
   return result;
 }
 
-#ifdef __VMS
-#include <fabdef.h>
-/*
- * get_vms_file_size does what it takes to get the real size of the file
- *
- * For fixed files, find out the size of the EOF block and adjust.
- *
- * For all others, have to read the entire file in, discarding the contents.
- * Most posted text files will be small, and binary files like zlib archives
- * and CD/DVD images should be either a STREAM_LF format or a fixed format.
- *
- */
-curl_off_t VmsRealFileSize(const char *name,
-                           const struct_stat *stat_buf)
-{
-  char buffer[8192];
-  curl_off_t count;
-  int ret_stat;
-  FILE * file;
-
-  file = fopen(name, FOPEN_READTEXT); /* VMS */
-  if(file == NULL)
-    return 0;
-
-  count = 0;
-  ret_stat = 1;
-  while(ret_stat > 0) {
-    ret_stat = fread(buffer, 1, sizeof(buffer), file);
-    if(ret_stat != 0)
-      count += ret_stat;
-  }
-  fclose(file);
-
-  return count;
-}
-
-/*
- *
- *  VmsSpecialSize checks to see if the stat st_size can be trusted and
- *  if not to call a routine to get the correct size.
- *
- */
-static curl_off_t VmsSpecialSize(const char *name,
-                                 const struct_stat *stat_buf)
-{
-  switch(stat_buf->st_fab_rfm) {
-  case FAB$C_VAR:
-  case FAB$C_VFC:
-    return VmsRealFileSize(name, stat_buf);
-    break;
-  default:
-    return stat_buf->st_size;
-  }
-}
-
-#endif
-
-#ifndef __VMS
-#define filesize(name, stat_data) (stat_data.st_size)
-#else
-    /* Getting the expected file size needs help on VMS */
-#define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
-#endif
-
-/*
- * AddFormData() adds a chunk of data to the FormData linked list.
- *
- * size is incremented by the chunk length, unless it is NULL
- */
-static CURLcode AddFormData(struct FormData **formp,
-                            enum formtype type,
-                            const void *line,
-                            curl_off_t length,
-                            curl_off_t *size)
-{
-  struct FormData *newform;
-  char *alloc2 = NULL;
-  CURLcode result = CURLE_OK;
-  if(length < 0 || (size && *size < 0))
-    return CURLE_BAD_FUNCTION_ARGUMENT;
-
-  newform = malloc(sizeof(struct FormData));
-  if(!newform)
-    return CURLE_OUT_OF_MEMORY;
-  newform->next = NULL;
-
-  if(type <= FORM_CONTENT) {
-    /* we make it easier for plain strings: */
-    if(!length)
-      length = strlen((char *)line);
-#if (SIZEOF_SIZE_T < CURL_SIZEOF_CURL_OFF_T)
-    else if(length >= (curl_off_t)(size_t)-1) {
-      result = CURLE_BAD_FUNCTION_ARGUMENT;
-      goto error;
-    }
-#endif
-    if(type != FORM_DATAMEM) {
-      newform->line = malloc((size_t)length+1);
-      if(!newform->line) {
-        result = CURLE_OUT_OF_MEMORY;
-        goto error;
-      }
-      alloc2 = newform->line;
-      memcpy(newform->line, line, (size_t)length);
-
-      /* zero terminate for easier debugging */
-      newform->line[(size_t)length]=0;
-    }
-    else {
-      newform->line = (char *)line;
-      type = FORM_DATA; /* in all other aspects this is just FORM_DATA */
-    }
-    newform->length = (size_t)length;
-  }
-  else
-    /* For callbacks and files we don't have any actual data so we just keep a
-       pointer to whatever this points to */
-    newform->line = (char *)line;
-
-  newform->type = type;
-
-  if(size) {
-    if(type != FORM_FILE)
-      /* for static content as well as callback data we add the size given
-         as input argument */
-      *size += length;
-    else {
-      /* Since this is a file to be uploaded here, add the size of the actual
-         file */
-      if(strcmp("-", newform->line)) {
-        struct_stat file;
-        if(!stat(newform->line, &file) && !S_ISDIR(file.st_mode))
-          *size += filesize(newform->line, file);
-        else {
-          result = CURLE_BAD_FUNCTION_ARGUMENT;
-          goto error;
-        }
-      }
-    }
-  }
-
-  if(*formp) {
-    (*formp)->next = newform;
-    *formp = newform;
-  }
-  else
-    *formp = newform;
-
-  return CURLE_OK;
-  error:
-  if(newform)
-    free(newform);
-  if(alloc2)
-    free(alloc2);
-  return result;
-}
-
-/*
- * AddFormDataf() adds printf()-style formatted data to the formdata chain.
- */
-
-static CURLcode AddFormDataf(struct FormData **formp,
-                             curl_off_t *size,
-                             const char *fmt, ...)
-{
-  char *s;
-  CURLcode result;
-  va_list ap;
-  va_start(ap, fmt);
-  s = curl_mvaprintf(fmt, ap);
-  va_end(ap);
-
-  if(!s)
-    return CURLE_OUT_OF_MEMORY;
-
-  result = AddFormData(formp, FORM_DATAMEM, s, 0, size);
-  if(result)
-    free(s);
-
-  return result;
-}
-
-/*
- * Curl_formclean() is used from http.c, this cleans a built FormData linked
- * list
- */
-void Curl_formclean(struct FormData **form_ptr)
-{
-  struct FormData *next, *form;
-
-  form = *form_ptr;
-  if(!form)
-    return;
-
-  do {
-    next=form->next;  /* the following form line */
-    if(form->type <= FORM_CONTENT)
-      free(form->line); /* free the line */
-    free(form);       /* free the struct */
-    form = next;
-  } while(form); /* continue */
-
-  *form_ptr = NULL;
-}
-
 /*
  * curl_formget()
  * Serialize a curl_httppost struct.
@@ -962,42 +762,34 @@ int curl_formget(struct curl_httppost *form, void *arg,
                  curl_formget_callback append)
 {
   CURLcode result;
-  curl_off_t size;
-  struct FormData *data, *ptr;
+  curl_mimepart toppart;
 
-  result = Curl_getformdata(NULL, &data, form, NULL, &size);
-  if(result)
-    return (int)result;
-
-  for(ptr = data; ptr; ptr = ptr->next) {
-    if((ptr->type == FORM_FILE) || (ptr->type == FORM_CALLBACK)) {
-      char buffer[8192];
-      size_t nread;
-      struct Form temp;
-
-      Curl_FormInit(&temp, ptr);
-
-      do {
-        nread = readfromfile(&temp, buffer, sizeof(buffer));
-        if((nread == (size_t) -1) ||
-           (nread > sizeof(buffer)) ||
-           (nread != append(arg, buffer, nread))) {
-          if(temp.fp)
-            fclose(temp.fp);
-          Curl_formclean(&data);
-          return -1;
-        }
-      } while(nread);
-    }
-    else {
-      if(ptr->length != append(arg, ptr->line, ptr->length)) {
-        Curl_formclean(&data);
-        return -1;
-      }
+  Curl_mime_initpart(&toppart, NULL); /* default form is empty */
+  result = Curl_getformdata(NULL, &toppart, form, NULL);
+  if(!result)
+    result = Curl_mime_prepare_headers(&toppart, "multipart/form-data",
+                                       NULL, MIMESTRATEGY_FORM);
+
+  while(!result) {
+    char buffer[8192];
+    size_t nread = Curl_mime_read(buffer, 1, sizeof buffer, &toppart);
+
+    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;
     }
   }
-  Curl_formclean(&data);
-  return 0;
+
+  Curl_mime_cleanpart(&toppart);
+  return (int) result;
 }
 
 /*
@@ -1013,7 +805,7 @@ void curl_formfree(struct curl_httppost *form)
     return;
 
   do {
-    next=form->next;  /* the following form line */
+    next = form->next;  /* the following form line */
 
     /* recurse to sub-contents */
     curl_formfree(form->more);
@@ -1031,118 +823,29 @@ void curl_formfree(struct curl_httppost *form)
   } while(form); /* continue */
 }
 
-#ifndef HAVE_BASENAME
-/*
-  (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
-  Edition)
-
-  The basename() function shall take the pathname pointed to by path and
-  return a pointer to the final component of the pathname, deleting any
-  trailing '/' characters.
 
-  If the string pointed to by path consists entirely of the '/' character,
-  basename() shall return a pointer to the string "/". If the string pointed
-  to by path is exactly "//", it is implementation-defined whether '/' or "//"
-  is returned.
-
-  If path is a null pointer or points to an empty string, basename() shall
-  return a pointer to the string ".".
-
-  The basename() function may modify the string pointed to by path, and may
-  return a pointer to static storage that may then be overwritten by a
-  subsequent call to basename().
-
-  The basename() function need not be reentrant. A function that is not
-  required to be reentrant is not required to be thread-safe.
-
-*/
-static char *Curl_basename(char *path)
+/* Set mime part name, taking care of non nul-terminated name string. */
+static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
 {
-  /* Ignore all the details above for now and make a quick and simple
-     implementaion here */
-  char *s1;
-  char *s2;
+  char *zname;
+  CURLcode res;
 
-  s1=strrchr(path, '/');
-  s2=strrchr(path, '\\');
-
-  if(s1 && s2) {
-    path = (s1 > s2? s1 : s2)+1;
-  }
-  else if(s1)
-    path = s1 + 1;
-  else if(s2)
-    path = s2 + 1;
-
-  return path;
-}
-#endif
-
-static char *strippath(const char *fullfile)
-{
-  char *filename;
-  char *base;
-  filename = strdup(fullfile); /* duplicate since basename() may ruin the
-                                  buffer it works on */
-  if(!filename)
-    return NULL;
-  base = strdup(basename(filename));
-
-  free(filename); /* free temporary buffer */
-
-  return base; /* returns an allocated string or NULL ! */
-}
-
-static CURLcode formdata_add_filename(const struct curl_httppost *file,
-                                      struct FormData **form,
-                                      curl_off_t *size)
-{
-  CURLcode result = CURLE_OK;
-  char *filename = file->showfilename;
-  char *filebasename = NULL;
-  char *filename_escaped = NULL;
-
-  if(!filename) {
-    filebasename = strippath(file->contents);
-    if(!filebasename)
-      return CURLE_OUT_OF_MEMORY;
-    filename = filebasename;
-  }
-
-  if(strchr(filename, '\\') || strchr(filename, '"')) {
-    char *p0, *p1;
-
-    /* filename need be escaped */
-    filename_escaped = malloc(strlen(filename)*2+1);
-    if(!filename_escaped) {
-      free(filebasename);
-      return CURLE_OUT_OF_MEMORY;
-    }
-    p0 = filename_escaped;
-    p1 = filename;
-    while(*p1) {
-      if(*p1 == '\\' || *p1 == '"')
-        *p0++ = '\\';
-      *p0++ = *p1++;
-    }
-    *p0 = '\0';
-    filename = filename_escaped;
-  }
-  result = AddFormDataf(form, size,
-                        "; filename=\"%s\"",
-                        filename);
-  free(filename_escaped);
-  free(filebasename);
-  return result;
+  if(!name || !len)
+    return curl_mime_name(part, name);
+  zname = malloc(len + 1);
+  if(!zname)
+    return CURLE_OUT_OF_MEMORY;
+  memcpy(zname, name, len);
+  zname[len] = '\0';
+  res = curl_mime_name(part, zname);
+  free(zname);
+  return res;
 }
 
 /*
- * Curl_getformdata() converts a linked list of "meta data" into a complete
- * (possibly huge) multipart formdata. The input list is in 'post', while the
- * output resulting linked lists gets stored in '*finalform'. *sizep will get
- * the total size of the whole POST.
- * A multipart/form_data content-type is built, unless a custom content-type
- * is passed in 'custom_content_type'.
+ * Curl_getformdata() converts a linked list of "meta data" into a mime
+ * structure. The input list is in 'post', while the output is stored in
+ * mime part at '*finalform'.
  *
  * This function will not do a failf() for the potential memory failures but
  * should for all other errors it spots. Just note that this function MAY get
@@ -1150,422 +853,123 @@ static CURLcode formdata_add_filename(const struct 
curl_httppost *file,
  */
 
 CURLcode Curl_getformdata(struct Curl_easy *data,
-                          struct FormData **finalform,
+                          curl_mimepart *finalform,
                           struct curl_httppost *post,
-                          const char *custom_content_type,
-                          curl_off_t *sizep)
+                          curl_read_callback fread_func)
 {
-  struct FormData *form = NULL;
-  struct FormData *firstform;
-  struct curl_httppost *file;
   CURLcode result = CURLE_OK;
-  curl_off_t size = 0; /* support potentially ENORMOUS formposts */
-  char fileboundary[42];
-  struct curl_slist *curList;
-  char boundary[42];
+  curl_mime *form = NULL;
+  curl_mime *multipart;
+  curl_mimepart *part;
+  struct curl_httppost *file;
 
-  *finalform = NULL; /* default form is empty */
+  Curl_mime_cleanpart(finalform); /* default form is empty */
 
   if(!post)
     return result; /* no input => no output! */
 
-  result = formboundary(data, boundary, sizeof(boundary));
-  if(result)
-    return result;
-
-  /* Make the first line of the output */
-  result = AddFormDataf(&form, NULL,
-                        "%s; boundary=%s\r\n",
-                        custom_content_type?custom_content_type:
-                        "Content-Type: multipart/form-data",
-                        boundary);
-
-  if(result) {
-    return result;
-  }
-  /* we DO NOT include that line in the total size of the POST, since it'll be
-     part of the header! */
-
-  firstform = form;
-
-  do {
-
-    if(size) {
-      result = AddFormDataf(&form, &size, "\r\n");
-      if(result)
-        break;
-    }
-
-    /* boundary */
-    result = AddFormDataf(&form, &size, "--%s\r\n", boundary);
-    if(result)
-      break;
-
-    /* Maybe later this should be disabled when a custom_content_type is
-       passed, since Content-Disposition is not meaningful for all multipart
-       types.
-    */
-    result = AddFormDataf(&form, &size,
-                          "Content-Disposition: form-data; name=\"");
-    if(result)
-      break;
-
-    result = AddFormData(&form, FORM_DATA, post->name, post->namelength,
-                         &size);
-    if(result)
-      break;
+  form = curl_mime_init(data);
+  if(!form)
+    result = CURLE_OUT_OF_MEMORY;
 
-    result = AddFormDataf(&form, &size, "\"");
-    if(result)
-      break;
+  if(!result)
+    result = curl_mime_subparts(finalform, form);
 
+  /* Process each top part. */
+  for(; !result && post; post = post->next) {
+    /* If we have more than a file here, create a mime subpart and fill it. */
+    multipart = form;
     if(post->more) {
-      /* If used, this is a link to more file names, we must then do
-         the magic to include several files with the same field name */
-
-      result = formboundary(data, fileboundary, sizeof(fileboundary));
-      if(result) {
-        break;
+      part = curl_mime_addpart(form);
+      if(!part)
+        result = CURLE_OUT_OF_MEMORY;
+      if(!result)
+        result = setname(part, post->name, post->namelength);
+      if(!result) {
+        multipart = curl_mime_init(data);
+        if(!multipart)
+          result = CURLE_OUT_OF_MEMORY;
       }
-
-      result = AddFormDataf(&form, &size,
-                            "\r\nContent-Type: multipart/mixed;"
-                            " boundary=%s\r\n",
-                            fileboundary);
-      if(result)
-        break;
+      if(!result)
+        result = curl_mime_subparts(part, multipart);
     }
 
-    file = post;
-
-    do {
-
-      /* If 'showfilename' is set, that is a faked name passed on to us
-         to use to in the formpost. If that is not set, the actually used
-         local file name should be added. */
-
-      if(post->more) {
-        /* if multiple-file */
-        result = AddFormDataf(&form, &size,
-                              "\r\n--%s\r\nContent-Disposition: "
-                              "attachment",
-                              fileboundary);
-        if(result)
-          break;
-        result = formdata_add_filename(file, &form, &size);
-        if(result)
-          break;
-      }
-      else if(post->flags & (HTTPPOST_FILENAME|HTTPPOST_BUFFER|
-                             HTTPPOST_CALLBACK)) {
-        /* it should be noted that for the HTTPPOST_FILENAME and
-           HTTPPOST_CALLBACK cases the ->showfilename struct member is always
-           assigned at this point */
-        if(post->showfilename || (post->flags & HTTPPOST_FILENAME)) {
-          result = formdata_add_filename(post, &form, &size);
-        }
+    /* Generate all the part contents. */
+    for(file = post; !result && file; file = file->more) {
+      /* Create the part. */
+      part = curl_mime_addpart(multipart);
+      if(!part)
+        result = CURLE_OUT_OF_MEMORY;
 
-        if(result)
-          break;
-      }
+      /* Set the headers. */
+      if(!result)
+        result = curl_mime_headers(part, file->contentheader, 0);
 
-      if(file->contenttype) {
-        /* we have a specified type */
-        result = AddFormDataf(&form, &size,
-                              "\r\nContent-Type: %s",
-                              file->contenttype);
-        if(result)
-          break;
-      }
+      /* Set the content type. */
+      if(!result &&file->contenttype)
+        result = curl_mime_type(part, file->contenttype);
 
-      curList = file->contentheader;
-      while(curList) {
-        /* Process the additional headers specified for this form */
-        result = AddFormDataf(&form, &size, "\r\n%s", curList->data);
-        if(result)
-          break;
-        curList = curList->next;
-      }
-      if(result)
-        break;
+      /* Set field name. */
+      if(!result && !post->more)
+        result = setname(part, post->name, post->namelength);
 
-      result = AddFormDataf(&form, &size, "\r\n\r\n");
-      if(result)
-        break;
+      /* Process contents. */
+      if(!result) {
+        curl_off_t clen = post->contentslength;
 
-      if((post->flags & HTTPPOST_FILENAME) ||
-         (post->flags & HTTPPOST_READFILE)) {
-        /* we should include the contents from the specified file */
-        FILE *fileread;
-
-        fileread = !strcmp("-", file->contents)?
-          stdin:fopen(file->contents, "rb"); /* binary read for win32  */
-
-        /*
-         * VMS: This only allows for stream files on VMS.  Stream files are
-         * OK, as are FIXED & VAR files WITHOUT implied CC For implied CC,
-         * every record needs to have a \n appended & 1 added to SIZE
-         */
-
-        if(fileread) {
-          if(fileread != stdin) {
-            /* close the file */
-            fclose(fileread);
-            /* add the file name only - for later reading from this */
-            result = AddFormData(&form, FORM_FILE, file->contents, 0, &size);
-          }
-          else {
-            /* When uploading from stdin, we can't know the size of the file,
-             * thus must read the full file as before. We *could* use chunked
-             * transfer-encoding, but that only works for HTTP 1.1 and we
-             * can't be sure we work with such a server.
-             */
-            size_t nread;
-            char buffer[512];
-            while((nread = fread(buffer, 1, sizeof(buffer), fileread)) != 0) {
-              result = AddFormData(&form, FORM_CONTENT, buffer, nread, &size);
-              if(result || feof(fileread) || ferror(fileread))
-                break;
-            }
+        if(post->flags & CURL_HTTPPOST_LARGE)
+          clen = post->contentlen;
+        if(!clen)
+          clen = -1;
+
+        if(post->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE)) {
+          if(!strcmp(file->contents, "-")) {
+            /* There are a few cases where the code below won't work; in
+               particular, freopen(stdin) by the caller is not guaranteed
+               to result as expected. This feature has been kept for backward
+               compatibility: use of "-" pseudo file name should be avoided. */
+            result = curl_mime_data_cb(part, (curl_off_t) -1,
+                                       (curl_read_callback) fread,
+                                       (curl_seek_callback) fseek,
+                                       NULL, (void *) stdin);
           }
+          else
+            result = curl_mime_filedata(part, file->contents);
+          if(!result && (post->flags & HTTPPOST_READFILE))
+            result = curl_mime_filename(part, NULL);
         }
+        else if(post->flags & HTTPPOST_BUFFER)
+          result = curl_mime_data(part, post->buffer,
+                                  post->bufferlength? post->bufferlength: -1);
+        else if(post->flags & HTTPPOST_CALLBACK)
+          /* the contents should be read with the callback and the size is set
+             with the contentslength */
+          result = curl_mime_data_cb(part, clen,
+                                     fread_func, NULL, NULL, post->userp);
         else {
-          if(data)
-            failf(data, "couldn't open file \"%s\"", file->contents);
-          *finalform = NULL;
-          result = CURLE_READ_ERROR;
+          result = curl_mime_data(part, post->contents, (ssize_t) clen);
+#ifdef CURL_DOES_CONVERSIONS
+          /* Convert textual contents now. */
+          if(!result && data && part->datasize)
+            result = Curl_convert_to_network(data, part->data, part->datasize);
+#endif
         }
       }
-      else if(post->flags & HTTPPOST_BUFFER)
-        /* include contents of buffer */
-        result = AddFormData(&form, FORM_CONTENT, post->buffer,
-                             post->bufferlength, &size);
-      else if(post->flags & HTTPPOST_CALLBACK)
-        /* the contents should be read with the callback and the size is set
-           with the contentslength */
-        result = AddFormData(&form, FORM_CALLBACK, post->userp,
-                             post->flags&CURL_HTTPPOST_LARGE?
-                             post->contentlen:post->contentslength, &size);
-      else
-        /* include the contents we got */
-        result = AddFormData(&form, FORM_CONTENT, post->contents,
-                             post->flags&CURL_HTTPPOST_LARGE?
-                             post->contentlen:post->contentslength, &size);
-      file = file->more;
-    } while(file && !result); /* for each specified file for this field */
-
-    if(result)
-      break;
 
-    if(post->more) {
-      /* this was a multiple-file inclusion, make a termination file
-         boundary: */
-      result = AddFormDataf(&form, &size,
-                           "\r\n--%s--",
-                           fileboundary);
-      if(result)
-        break;
+      /* Set fake file name. */
+      if(!result && post->showfilename)
+        if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER |
+                                        HTTPPOST_CALLBACK)))
+          result = curl_mime_filename(part, post->showfilename);
     }
-    post = post->next;
-  } while(post); /* for each field */
-
-  /* end-boundary for everything */
-  if(!result)
-    result = AddFormDataf(&form, &size, "\r\n--%s--\r\n", boundary);
-
-  if(result) {
-    Curl_formclean(&firstform);
-    return result;
   }
 
-  *sizep = size;
-  *finalform = firstform;
+  if(result)
+    Curl_mime_cleanpart(finalform);
 
   return result;
 }
 
-/*
- * Curl_FormInit() inits the struct 'form' points to with the 'formdata'
- * and resets the 'sent' counter.
- */
-int Curl_FormInit(struct Form *form, struct FormData *formdata)
-{
-  if(!formdata)
-    return 1; /* error */
-
-  form->data = formdata;
-  form->sent = 0;
-  form->fp = NULL;
-  form->fread_func = ZERO_NULL;
-
-  return 0;
-}
-
-#ifndef __VMS
-# define fopen_read fopen
-#else
-  /*
-   * vmsfopenread
-   *
-   * For upload to work as expected on VMS, different optional
-   * parameters must be added to the fopen command based on
-   * record format of the file.
-   *
-   */
-# define fopen_read vmsfopenread
-static FILE * vmsfopenread(const char *file, const char *mode)
-{
-  struct_stat statbuf;
-  int result;
-
-  result = stat(file, &statbuf);
-
-  switch(statbuf.st_fab_rfm) {
-  case FAB$C_VAR:
-  case FAB$C_VFC:
-  case FAB$C_STMCR:
-    return fopen(file, FOPEN_READTEXT); /* VMS */
-    break;
-  default:
-    return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm");
-  }
-}
-#endif
-
-/*
- * readfromfile()
- *
- * The read callback that this function may use can return a value larger than
- * 'size' (which then this function returns) that indicates a problem and it
- * must be properly dealt with
- */
-static size_t readfromfile(struct Form *form, char *buffer,
-                           size_t size)
-{
-  size_t nread;
-  bool callback = (form->data->type == FORM_CALLBACK)?TRUE:FALSE;
-
-  if(callback) {
-    if(form->fread_func == ZERO_NULL)
-      return 0;
-    nread = form->fread_func(buffer, 1, size, form->data->line);
-  }
-  else {
-    if(!form->fp) {
-      /* this file hasn't yet been opened */
-      form->fp = fopen_read(form->data->line, "rb"); /* b is for binary */
-      if(!form->fp)
-        return (size_t)-1; /* failure */
-    }
-    nread = fread(buffer, 1, size, form->fp);
-  }
-  if(!nread) {
-    /* this is the last chunk from the file, move on */
-    if(form->fp) {
-      fclose(form->fp);
-      form->fp = NULL;
-    }
-    form->data = form->data->next;
-  }
-
-  return nread;
-}
-
-/*
- * Curl_FormReader() is the fread() emulation function that will be used to
- * deliver the formdata to the transfer loop and then sent away to the peer.
- */
-size_t Curl_FormReader(char *buffer,
-                       size_t size,
-                       size_t nitems,
-                       FILE *mydata)
-{
-  struct Form *form;
-  size_t wantedsize;
-  size_t gotsize = 0;
-
-  form=(struct Form *)mydata;
-
-  wantedsize = size * nitems;
-
-  if(!form->data)
-    return 0; /* nothing, error, empty */
-
-  if((form->data->type == FORM_FILE) ||
-     (form->data->type == FORM_CALLBACK)) {
-    gotsize = readfromfile(form, buffer, wantedsize);
-
-    if(gotsize)
-      /* If positive or -1, return. If zero, continue! */
-      return gotsize;
-  }
-  do {
-
-    if((form->data->length - form->sent) > wantedsize - gotsize) {
-
-      memcpy(buffer + gotsize, form->data->line + form->sent,
-             wantedsize - gotsize);
-
-      form->sent += wantedsize-gotsize;
-
-      return wantedsize;
-    }
-
-    memcpy(buffer+gotsize,
-           form->data->line + form->sent,
-           (form->data->length - form->sent) );
-    gotsize += form->data->length - form->sent;
-
-    form->sent = 0;
-
-    form->data = form->data->next; /* advance */
-
-  } while(form->data && (form->data->type < FORM_CALLBACK));
-  /* If we got an empty line and we have more data, we proceed to the next
-     line immediately to avoid returning zero before we've reached the end. */
-
-  return gotsize;
-}
-
-/*
- * Curl_formpostheader() returns the first line of the formpost, the
- * request-header part (which is not part of the request-body like the rest of
- * the post).
- */
-char *Curl_formpostheader(void *formp, size_t *len)
-{
-  char *header;
-  struct Form *form=(struct Form *)formp;
-
-  if(!form->data)
-    return NULL; /* nothing, ERROR! */
-
-  header = form->data->line;
-  *len = form->data->length;
-
-  form->data = form->data->next; /* advance */
-
-  return header;
-}
-
-/*
- * formboundary() creates a suitable boundary string and returns an allocated
- * one.
- */
-static CURLcode formboundary(struct Curl_easy *data,
-                             char *buffer, size_t buflen)
-{
-  /* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
-     combinations */
-  if(buflen < 41)
-    return CURLE_BAD_FUNCTION_ARGUMENT;
-
-  memset(buffer, '-', 24);
-  Curl_rand_hex(data, (unsigned char *)&buffer[24], 17);
-
-  return CURLE_OK;
-}
-
 #else  /* CURL_DISABLE_HTTP */
 CURLFORMcode curl_formadd(struct curl_httppost **httppost,
                           struct curl_httppost **last_post,
diff --git a/lib/formdata.h b/lib/formdata.h
index 69629f628..1246c2bc8 100644
--- a/lib/formdata.h
+++ b/lib/formdata.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,32 +22,6 @@
  *
  ***************************************************************************/
 
-enum formtype {
-  FORM_DATAMEM, /* already allocated FORM_DATA memory */
-  FORM_DATA,    /* form metadata (convert to network encoding if necessary) */
-  FORM_CONTENT, /* form content  (never convert) */
-  FORM_CALLBACK, /* 'line' points to the custom pointer we pass to the callback
-                  */
-  FORM_FILE     /* 'line' points to a file name we should read from
-                   to create the form data (never convert) */
-};
-
-/* plain and simple linked list with lines to send */
-struct FormData {
-  struct FormData *next;
-  enum formtype type;
-  char *line;
-  size_t length;
-};
-
-struct Form {
-  struct FormData *data; /* current form line to send */
-  size_t sent;           /* number of bytes of the current line that has
-                            already been sent in a previous invoke */
-  FILE *fp;              /* file to read from */
-  curl_read_callback fread_func; /* fread callback pointer */
-};
-
 /* used by FormAdd for temporary storage */
 typedef struct FormInfo {
   char *name;
@@ -69,31 +43,9 @@ typedef struct FormInfo {
   struct FormInfo *more;
 } FormInfo;
 
-int Curl_FormInit(struct Form *form, struct FormData *formdata);
-
 CURLcode Curl_getformdata(struct Curl_easy *data,
-                          struct FormData **,
+                          curl_mimepart *,
                           struct curl_httppost *post,
-                          const char *custom_contenttype,
-                          curl_off_t *size);
-
-/* fread() emulation */
-size_t Curl_FormReader(char *buffer,
-                       size_t size,
-                       size_t nitems,
-                       FILE *mydata);
-
-/*
- * Curl_formpostheader() returns the first line of the formpost, the
- * request-header part (which is not part of the request-body like the rest of
- * the post).
- */
-char *Curl_formpostheader(void *formp, size_t *len);
-
-char *Curl_FormBoundary(void);
-
-void Curl_formclean(struct FormData **);
-
-CURLcode Curl_formconvert(struct Curl_easy *, struct FormData *);
+                          curl_read_callback fread_func);
 
 #endif /* HEADER_CURL_FORMDATA_H */
diff --git a/lib/ftp.c b/lib/ftp.c
index eebcade49..8590576f0 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -239,9 +239,9 @@ static void freedirs(struct ftp_conn *ftpc)
 {
   int i;
   if(ftpc->dirs) {
-    for(i=0; i < ftpc->dirdepth; i++) {
+    for(i = 0; i < ftpc->dirdepth; i++) {
       free(ftpc->dirs[i]);
-      ftpc->dirs[i]=NULL;
+      ftpc->dirs[i] = NULL;
     }
     free(ftpc->dirs);
     ftpc->dirs = NULL;
@@ -288,7 +288,7 @@ static CURLcode AcceptServerConnect(struct connectdata 
*conn)
   if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) {
     size = sizeof(add);
 
-    s=accept(sock, (struct sockaddr *) &add, &size);
+    s = accept(sock, (struct sockaddr *) &add, &size);
   }
   Curl_closesocket(conn, sock); /* close the first socket */
 
@@ -457,7 +457,7 @@ static CURLcode InitiateTransfer(struct connectdata *conn)
   }
 
   if(conn->proto.ftpc.state_saved == FTP_STOR) {
-    *(ftp->bytecountp)=0;
+    *(ftp->bytecountp) = 0;
 
     /* When we know we're uploading a specified file, we can get the file
        size prior to the actual upload. */
@@ -592,7 +592,7 @@ static CURLcode ftp_readresp(curl_socket_t sockfd,
 #endif
 
   /* store the latest code for later retrieval */
-  data->info.httpcode=code;
+  data->info.httpcode = code;
 
   if(ftpcode)
     *ftpcode = code;
@@ -640,8 +640,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return 
number of bytes read */
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   struct pingpong *pp = &ftpc->pp;
   size_t nread;
-  int cache_skip=0;
-  int value_to_be_ignored=0;
+  int cache_skip = 0;
+  int value_to_be_ignored = 0;
 
   if(ftpcode)
     *ftpcode = 0; /* 0 for errors */
@@ -649,13 +649,13 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return 
number of bytes read */
     /* make the pointer point to something for the rest of this function */
     ftpcode = &value_to_be_ignored;
 
-  *nreadp=0;
+  *nreadp = 0;
 
   while(!*ftpcode && !result) {
     /* check and reset timeout value every lap */
     timeout = Curl_pp_state_timeout(pp);
 
-    if(timeout <=0) {
+    if(timeout <= 0) {
       failf(data, "FTP response timeout");
       return CURLE_OPERATION_TIMEDOUT; /* already too little time */
     }
@@ -713,7 +713,7 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return 
number of bytes read */
     else
       /* when we got data or there is no cache left, we reset the cache skip
          counter */
-      cache_skip=0;
+      cache_skip = 0;
 
     *nreadp += nread;
 
@@ -848,7 +848,7 @@ static int ftp_domore_getsock(struct connectdata *conn, 
curl_socket_t *socks,
       int i;
       /* PORT is used to tell the server to connect to us, and during that we
          don't do happy eyeballs, but we do if we connect to the server */
-      for(s=1, i=0; i<2; i++) {
+      for(s = 1, i = 0; i<2; i++) {
         if(conn->tempsock[i] != CURL_SOCKET_BAD) {
           socks[s] = conn->tempsock[i];
           bits |= GETSOCK_WRITESOCK(s++);
@@ -885,7 +885,7 @@ static CURLcode ftp_state_cwd(struct connectdata *conn)
     /* count3 is set to allow a MKD to fail once. In the case when first CWD
        fails and then MKD fails (due to another session raced it to create the
        dir) this then allows for a second try to CWD to it */
-    ftpc->count3 = (conn->data->set.ftp_create_missing_dirs==2)?1:0;
+    ftpc->count3 = (conn->data->set.ftp_create_missing_dirs == 2)?1:0;
 
     if((conn->data->set.ftp_filemethod == FTPFILE_NOCWD) && !ftpc->cwdcount)
       /* No CWD necessary */
@@ -928,15 +928,15 @@ static CURLcode ftp_state_use_port(struct connectdata 
*conn,
 {
   CURLcode result = CURLE_OK;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
-  struct Curl_easy *data=conn->data;
-  curl_socket_t portsock= CURL_SOCKET_BAD;
+  struct Curl_easy *data = conn->data;
+  curl_socket_t portsock = CURL_SOCKET_BAD;
   char myhost[256] = "";
 
   struct Curl_sockaddr_storage ss;
   Curl_addrinfo *res, *ai;
   curl_socklen_t sslen;
   char hbuf[NI_MAXHOST];
-  struct sockaddr *sa=(struct sockaddr *)&ss;
+  struct sockaddr *sa = (struct sockaddr *)&ss;
   struct sockaddr_in * const sa4 = (void *)sa;
 #ifdef ENABLE_IPV6
   struct sockaddr_in6 * const sa6 = (void *)sa;
@@ -947,7 +947,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
   int error;
   char *host = NULL;
   char *string_ftpport = data->set.str[STRING_FTPPORT];
-  struct Curl_dns_entry *h=NULL;
+  struct Curl_dns_entry *h = NULL;
   unsigned short port_min = 0;
   unsigned short port_max = 0;
   unsigned short port;
@@ -975,7 +975,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
     char *port_start = NULL;
     char *port_sep = NULL;
 
-    addr = calloc(addrlen+1, 1);
+    addr = calloc(addrlen + 1, 1);
     if(!addr)
       return CURLE_OUT_OF_MEMORY;
 
@@ -1018,7 +1018,7 @@ static CURLcode ftp_state_use_port(struct connectdata 
*conn,
     if(ip_end != NULL) {
       port_start = strchr(ip_end, ':');
       if(port_start) {
-        port_min = curlx_ultous(strtoul(port_start+1, NULL, 10));
+        port_min = curlx_ultous(strtoul(port_start + 1, NULL, 10));
         port_sep = strchr(port_start, '-');
         if(port_sep) {
           port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10));
@@ -1262,7 +1262,7 @@ static CURLcode ftp_state_use_port(struct connectdata 
*conn,
       /* translate x.x.x.x to x,x,x,x */
       while(source && *source) {
         if(*source == '.')
-          *dest=',';
+          *dest = ',';
         else
           *dest = *source;
         dest++;
@@ -1469,12 +1469,12 @@ static CURLcode ftp_state_list(struct connectdata *conn)
       return CURLE_OUT_OF_MEMORY;
 
     /* Check if path does not end with /, as then we cut off the file part */
-    if(lstArg[strlen(lstArg) - 1] != '/')  {
+    if(lstArg[strlen(lstArg) - 1] != '/') {
 
       /* chop off the file part if format is dir/dir/file */
       slashPos = strrchr(lstArg, '/');
       if(slashPos)
-        *(slashPos+1) = '\0';
+        *(slashPos + 1) = '\0';
     }
   }
 
@@ -1622,7 +1622,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata 
*conn,
     }
 
     if(seekerr != CURL_SEEKFUNC_OK) {
-      curl_off_t passed=0;
+      curl_off_t passed = 0;
       if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
         failf(data, "Could not seek stream");
         return CURLE_FTP_COULDNT_USE_REST;
@@ -1684,7 +1684,7 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
   struct Curl_easy *data = conn->data;
   struct FTP *ftp = data->req.protop;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
-  bool quote=FALSE;
+  bool quote = FALSE;
   struct curl_slist *item;
 
   switch(instate) {
@@ -1821,11 +1821,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata 
*conn,
 {
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   CURLcode result;
-  struct Curl_easy *data=conn->data;
-  struct Curl_dns_entry *addr=NULL;
+  struct Curl_easy *data = conn->data;
+  struct Curl_dns_entry *addr = NULL;
   int rc;
   unsigned short connectport; /* the local port connect() should use! */
-  char *str=&data->state.buffer[4];  /* start on the first letter */
+  char *str = &data->state.buffer[4];  /* start on the first letter */
 
   /* if we come here again, make sure the former name is cleared */
   Curl_safefree(ftpc->newhost);
@@ -1849,9 +1849,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata 
*conn,
 
         /* The four separators should be identical, or else this is an oddly
            formatted reply and we bail out immediately. */
-        for(i=1; i<4; i++) {
+        for(i = 1; i<4; i++) {
           if(separator[i] != sep1) {
-            ptr=NULL; /* set to NULL to signal error */
+            ptr = NULL; /* set to NULL to signal error */
             break;
           }
         }
@@ -1867,7 +1867,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata 
*conn,
         }
       }
       else
-        ptr=NULL;
+        ptr = NULL;
     }
     if(!ptr) {
       failf(data, "Weirdly formatted EPSV reply");
@@ -2041,7 +2041,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata 
*conn,
                                     int ftpcode)
 {
   CURLcode result = CURLE_OK;
-  struct Curl_easy *data=conn->data;
+  struct Curl_easy *data = conn->data;
   struct FTP *ftp = data->req.protop;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
 
@@ -2055,7 +2055,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata 
*conn,
                      &year, &month, &day, &hour, &minute, &second)) {
         /* we have a time, reformat it */
         char timebuf[24];
-        time_t secs=time(NULL);
+        time_t secs = time(NULL);
 
         snprintf(timebuf, sizeof(timebuf),
                  "%04d%02d%02d %02d:%02d:%02d GMT",
@@ -2071,7 +2071,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata 
*conn,
       if(data->set.opt_no_body &&
          ftpc->file &&
          data->set.get_filetime &&
-         (data->info.filetime>=0) ) {
+         (data->info.filetime >= 0) ) {
         char headerbuf[128];
         time_t filetime = (time_t)data->info.filetime;
         struct tm buffer;
@@ -2147,7 +2147,7 @@ static CURLcode ftp_state_type_resp(struct connectdata 
*conn,
                                     ftpstate instate)
 {
   CURLcode result = CURLE_OK;
-  struct Curl_easy *data=conn->data;
+  struct Curl_easy *data = conn->data;
 
   if(ftpcode/100 != 2) {
     /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a
@@ -2176,7 +2176,7 @@ static CURLcode ftp_state_retr(struct connectdata *conn,
                                          curl_off_t filesize)
 {
   CURLcode result = CURLE_OK;
-  struct Curl_easy *data=conn->data;
+  struct Curl_easy *data = conn->data;
   struct FTP *ftp = data->req.protop;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
 
@@ -2259,12 +2259,14 @@ static CURLcode ftp_state_size_resp(struct connectdata 
*conn,
                                     ftpstate instate)
 {
   CURLcode result = CURLE_OK;
-  struct Curl_easy *data=conn->data;
-  curl_off_t filesize;
+  struct Curl_easy *data = conn->data;
+  curl_off_t filesize = -1;
   char *buf = data->state.buffer;
 
   /* get the size from the ascii string: */
-  filesize = (ftpcode == 213)?curlx_strtoofft(buf+4, NULL, 0):-1;
+  if(ftpcode == 213)
+    /* ignores parsing errors, which will make the size remain unknown */
+    (void)curlx_strtoofft(buf + 4, NULL, 0, &filesize);
 
   if(instate == FTP_SIZE) {
 #ifdef CURL_FTP_HTTPSTYLE_HEAD
@@ -2334,7 +2336,7 @@ static CURLcode ftp_state_stor_resp(struct connectdata 
*conn,
   CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
 
-  if(ftpcode>=400) {
+  if(ftpcode >= 400) {
     failf(data, "Failed FTP upload: %0d", ftpcode);
     state(conn, FTP_STOP);
     /* oops, we never close the sockets! */
@@ -2392,7 +2394,7 @@ static CURLcode ftp_state_get_resp(struct connectdata 
*conn,
       E:
       125 Data connection already open; Transfer starting. */
 
-    curl_off_t size=-1; /* default unknown size */
+    curl_off_t size = -1; /* default unknown size */
 
 
     /*
@@ -2416,9 +2418,9 @@ static CURLcode ftp_state_get_resp(struct connectdata 
*conn,
        * Example D above makes this parsing a little tricky */
       char *bytes;
       char *buf = data->state.buffer;
-      bytes=strstr(buf, " bytes");
+      bytes = strstr(buf, " bytes");
       if(bytes--) {
-        long in=(long)(bytes-buf);
+        long in = (long)(bytes-buf);
         /* this is a hint there is size information in there! ;-) */
         while(--in) {
           /* scan for the left parenthesis and break there */
@@ -2426,7 +2428,7 @@ static CURLcode ftp_state_get_resp(struct connectdata 
*conn,
             break;
           /* skip only digits */
           if(!ISDIGIT(*bytes)) {
-            bytes=NULL;
+            bytes = NULL;
             break;
           }
           /* one more estep backwards */
@@ -2435,7 +2437,7 @@ static CURLcode ftp_state_get_resp(struct connectdata 
*conn,
         /* if we have nothing but digits: */
         if(bytes++) {
           /* get the number! */
-          size = curlx_strtoofft(bytes, NULL, 0);
+          (void)curlx_strtoofft(bytes, NULL, 0, &size);
         }
       }
     }
@@ -2598,7 +2600,7 @@ static CURLcode ftp_statemach_act(struct connectdata 
*conn)
 {
   CURLcode result;
   curl_socket_t sock = conn->sock[FIRSTSOCKET];
-  struct Curl_easy *data=conn->data;
+  struct Curl_easy *data = conn->data;
   int ftpcode;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   struct pingpong *pp = &ftpc->pp;
@@ -2650,7 +2652,7 @@ static CURLcode ftp_statemach_act(struct connectdata 
*conn)
         /* We don't have a SSL/TLS connection yet, but FTPS is
            requested. Try a FTPS connection now */
 
-        ftpc->count3=0;
+        ftpc->count3 = 0;
         switch(data->set.ftpsslauth) {
         case CURLFTPAUTH_DEFAULT:
         case CURLFTPAUTH_SSL:
@@ -2773,10 +2775,11 @@ static CURLcode ftp_statemach_act(struct connectdata 
*conn)
 
     case FTP_PWD:
       if(ftpcode == 257) {
-        char *ptr=&data->state.buffer[4];  /* start on the first letter */
+        char *ptr = &data->state.buffer[4];  /* start on the first letter */
         const size_t buf_size = data->set.buffer_size;
         char *dir;
         char *store;
+        bool entry_extracted = FALSE;
 
         dir = malloc(nread + 1);
         if(!dir)
@@ -2808,7 +2811,7 @@ static CURLcode ftp_statemach_act(struct connectdata 
*conn)
               }
               else {
                 /* end of path */
-                *store = '\0'; /* zero terminate */
+                entry_extracted = TRUE;
                 break; /* get out of this loop */
               }
             }
@@ -2817,7 +2820,9 @@ static CURLcode ftp_statemach_act(struct connectdata 
*conn)
             store++;
             ptr++;
           }
-
+          *store = '\0'; /* zero terminate */
+        }
+        if(entry_extracted) {
           /* If the path name does not look like an absolute path (i.e.: it
              does not start with a '/'), we probably need some server-dependent
              adjustments. For example, this is the case when connecting to
@@ -2864,7 +2869,7 @@ static CURLcode ftp_statemach_act(struct connectdata 
*conn)
 
     case FTP_SYST:
       if(ftpcode == 215) {
-        char *ptr=&data->state.buffer[4];  /* start on the first letter */
+        char *ptr = &data->state.buffer[4];  /* start on the first letter */
         char *os;
         char *store;
 
@@ -2955,7 +2960,7 @@ static CURLcode ftp_statemach_act(struct connectdata 
*conn)
       }
       else {
         /* success */
-        ftpc->count2=0;
+        ftpc->count2 = 0;
         if(++ftpc->cwdcount <= ftpc->dirdepth) {
           /* send next CWD */
           PPSENDF(&ftpc->pp, "CWD %s", ftpc->dirs[ftpc->cwdcount - 1]);
@@ -3195,15 +3200,16 @@ static CURLcode ftp_done(struct connectdata *conn, 
CURLcode status,
     size_t flen = ftpc->file?strlen(ftpc->file):0; /* file is "raw" already */
     size_t dlen = strlen(path)-flen;
     if(!ftpc->cwdfail) {
+      ftpc->prevmethod = data->set.ftp_filemethod;
       if(dlen && (data->set.ftp_filemethod != FTPFILE_NOCWD)) {
         ftpc->prevpath = path;
         if(flen)
           /* if 'path' is not the whole string */
-          ftpc->prevpath[dlen]=0; /* terminate */
+          ftpc->prevpath[dlen] = 0; /* terminate */
       }
       else {
         /* we never changed dir */
-        ftpc->prevpath=strdup("");
+        ftpc->prevpath = strdup("");
         free(path);
       }
       if(ftpc->prevpath)
@@ -3466,35 +3472,36 @@ static CURLcode ftp_range(struct connectdata *conn)
 {
   curl_off_t from, to;
   char *ptr;
-  char *ptr2;
   struct Curl_easy *data = conn->data;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
 
   if(data->state.use_range && data->state.range) {
-    from=curlx_strtoofft(data->state.range, &ptr, 0);
-    while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
+    CURLofft from_t;
+    CURLofft to_t;
+    from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
+    if(from_t == CURL_OFFT_FLOW)
+      return CURLE_RANGE_ERROR;
+    while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
       ptr++;
-    to=curlx_strtoofft(ptr, &ptr2, 0);
-    if(ptr == ptr2) {
-      /* we didn't get any digit */
-      to=-1;
-    }
-    if((-1 == to) && (from>=0)) {
+    to_t = curlx_strtoofft(ptr, NULL, 0, &to);
+    if(to_t == CURL_OFFT_FLOW)
+      return CURLE_RANGE_ERROR;
+    if((to_t == CURL_OFFT_INVAL) && !from_t) {
       /* X - */
       data->state.resume_from = from;
       DEBUGF(infof(conn->data, "FTP RANGE %" CURL_FORMAT_CURL_OFF_T
                    " to end of file\n", from));
     }
-    else if(from < 0) {
+    else if(!to_t && (from_t == CURL_OFFT_INVAL)) {
       /* -Y */
-      data->req.maxdownload = -from;
-      data->state.resume_from = from;
+      data->req.maxdownload = to;
+      data->state.resume_from = -to;
       DEBUGF(infof(conn->data, "FTP RANGE the last %" CURL_FORMAT_CURL_OFF_T
-                   " bytes\n", -from));
+                   " bytes\n", to));
     }
     else {
       /* X-Y */
-      data->req.maxdownload = (to-from)+1; /* include last byte */
+      data->req.maxdownload = (to - from) + 1; /* include last byte */
       data->state.resume_from = from;
       DEBUGF(infof(conn->data, "FTP RANGE from %" CURL_FORMAT_CURL_OFF_T
                    " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n",
@@ -3525,7 +3532,7 @@ static CURLcode ftp_range(struct connectdata *conn)
 
 static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
 {
-  struct Curl_easy *data=conn->data;
+  struct Curl_easy *data = conn->data;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   CURLcode result = CURLE_OK;
   bool connected = FALSE;
@@ -3692,7 +3699,7 @@ CURLcode ftp_perform(struct connectdata *conn,
                      bool *dophase_done)
 {
   /* this is FTP and no proxy */
-  CURLcode result=CURLE_OK;
+  CURLcode result = CURLE_OK;
 
   DEBUGF(infof(conn->data, "DO phase starts\n"));
 
@@ -3985,7 +3992,7 @@ CURLcode Curl_ftpsend(struct connectdata *conn, const 
char *cmd)
 #define SBUF_SIZE 1024
   char s[SBUF_SIZE];
   size_t write_len;
-  char *sptr=s;
+  char *sptr = s;
   CURLcode result = CURLE_OK;
 #ifdef HAVE_GSSAPI
   enum protection_level data_sec = conn->data_prot;
@@ -3996,9 +4003,8 @@ CURLcode Curl_ftpsend(struct connectdata *conn, const 
char *cmd)
     return CURLE_BAD_FUNCTION_ARGUMENT;
 
   strcpy(&s[write_len], "\r\n"); /* append a trailing CRLF */
-  write_len +=2;
-
-  bytes_written=0;
+  write_len += 2;
+  bytes_written = 0;
 
   result = Curl_convert_to_network(conn->data, s, write_len);
   /* Curl_convert_to_network calls failf if unsuccessful */
@@ -4076,7 +4082,7 @@ static CURLcode ftp_quit(struct connectdata *conn)
  */
 static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection)
 {
-  struct ftp_conn *ftpc= &conn->proto.ftpc;
+  struct ftp_conn *ftpc = &conn->proto.ftpc;
   struct pingpong *pp = &ftpc->pp;
 
   /* We cannot send quit unconditionally. If this connection is stale or
@@ -4172,7 +4178,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
       ftpc->dirdepth = 0;
       break;
     }
-    slash_pos=strrchr(cur_pos, '/');
+    slash_pos = strrchr(cur_pos, '/');
     if(slash_pos || !*cur_pos) {
       size_t dirlen = slash_pos-cur_pos;
       CURLcode result;
@@ -4193,7 +4199,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
         return result;
       }
       ftpc->dirdepth = 1; /* we consider it to be a single dir */
-      filename = slash_pos ? slash_pos+1 : cur_pos; /* rest is file name */
+      filename = slash_pos ? slash_pos + 1 : cur_pos; /* rest is file name */
     }
     else
       filename = cur_pos;  /* this is a file name only */
@@ -4277,8 +4283,8 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
     }
   }
   else
-    ftpc->file=NULL; /* instead of point to a zero byte, we make it a NULL
-                       pointer */
+    ftpc->file = NULL; /* instead of point to a zero byte, we make it a NULL
+                          pointer */
 
   if(data->set.upload && !ftpc->file && (ftp->transfer == FTPTRANSFER_BODY)) {
     /* We need a file name when uploading. Return error! */
@@ -4302,7 +4308,8 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
 
     dlen -= ftpc->file?strlen(ftpc->file):0;
     if((dlen == strlen(ftpc->prevpath)) &&
-       !strncmp(path, ftpc->prevpath, dlen)) {
+       !strncmp(path, ftpc->prevpath, dlen) &&
+       (ftpc->prevmethod == data->set.ftp_filemethod)) {
       infof(data, "Request has same path as previous transfer\n");
       ftpc->cwddone = TRUE;
     }
@@ -4373,8 +4380,8 @@ static
 CURLcode ftp_regular_transfer(struct connectdata *conn,
                               bool *dophase_done)
 {
-  CURLcode result=CURLE_OK;
-  bool connected=FALSE;
+  CURLcode result = CURLE_OK;
+  bool connected = FALSE;
   struct Curl_easy *data = conn->data;
   struct ftp_conn *ftpc = &conn->proto.ftpc;
   data->req.size = -1; /* make sure this is unknown at this point */
diff --git a/lib/ftp.h b/lib/ftp.h
index 9c6c2c8de..e4aa63f17 100644
--- a/lib/ftp.h
+++ b/lib/ftp.h
@@ -135,6 +135,7 @@ struct ftp_conn {
                        caching the current directory */
   bool wait_data_conn; /* this is set TRUE if data connection is waited */
   char *prevpath;   /* conn->path from the previous transfer */
+  curl_ftpfile prevmethod; /* ftp method in previous transfer  */
   char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a
                         and others (A/I or zero) */
   int count1; /* general purpose counter for the state machine */
diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c
index 6063cee6e..ab6c50e82 100644
--- a/lib/ftplistparser.c
+++ b/lib/ftplistparser.c
@@ -421,7 +421,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t 
nmemb,
           else if(c == '\n') {
             finfo->b_data[parser->item_length - 1] = 0;
             if(strncmp("total ", finfo->b_data, 6) == 0) {
-              char *endptr = finfo->b_data+6;
+              char *endptr = finfo->b_data + 6;
               /* here we can deal with directory size, pass the leading white
                  spaces and then the digits */
               while(ISSPACE(*endptr))
@@ -609,16 +609,18 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, 
size_t nmemb,
             char *p;
             curl_off_t fsize;
             finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
-            fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10);
-            if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
-                               fsize != CURL_OFF_T_MIN) {
-              parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
-              parser->file_data->info.size = fsize;
+            if(!curlx_strtoofft(finfo->b_data + parser->item_offset,
+                                &p, 10, &fsize)) {
+              if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
+                 fsize != CURL_OFF_T_MIN) {
+                parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
+                parser->file_data->info.size = fsize;
+              }
+              parser->item_length = 0;
+              parser->item_offset = 0;
+              parser->state.UNIX.main = PL_UNIX_TIME;
+              parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1;
             }
-            parser->item_length = 0;
-            parser->item_offset = 0;
-            parser->state.UNIX.main = PL_UNIX_TIME;
-            parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1;
           }
           else if(!ISDIGIT(c)) {
             PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
@@ -935,19 +937,9 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, 
size_t nmemb,
             }
             else {
               char *endptr;
-              finfo->size = curlx_strtoofft(finfo->b_data +
-                                            parser->item_offset,
-                                            &endptr, 10);
-              if(!*endptr) {
-                if(finfo->size == CURL_OFF_T_MAX ||
-                   finfo->size == CURL_OFF_T_MIN) {
-                  if(errno == ERANGE) {
-                    PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
-                    return bufflen;
-                  }
-                }
-              }
-              else {
+              if(curlx_strtoofft(finfo->b_data +
+                                 parser->item_offset,
+                                 &endptr, 10, &finfo->size)) {
                 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
                 return bufflen;
               }
diff --git a/lib/getinfo.c b/lib/getinfo.c
index 99ba587af..b235f54ca 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -54,6 +54,7 @@ CURLcode Curl_initinfo(struct Curl_easy *data)
   pro->t_starttransfer = 0;
   pro->timespent = 0;
   pro->t_redirect = 0;
+  pro->is_t_startransfer_set = false;
 
   info->httpcode = 0;
   info->httpproxycode = 0;
@@ -279,6 +280,39 @@ static CURLcode getinfo_offt(struct Curl_easy *data, 
CURLINFO info,
   return CURLE_OK;
 }
 
+#define DOUBLE_SECS(x) (double)(x)/1000000
+
+static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
+                             curl_off_t *param_offt)
+{
+  switch(info) {
+  case CURLINFO_SIZE_UPLOAD_T:
+    *param_offt = data->progress.uploaded;
+    break;
+  case CURLINFO_SIZE_DOWNLOAD_T:
+    *param_offt = data->progress.downloaded;
+    break;
+  case CURLINFO_SPEED_DOWNLOAD_T:
+    *param_offt =  data->progress.dlspeed;
+    break;
+  case CURLINFO_SPEED_UPLOAD_T:
+    *param_offt = data->progress.ulspeed;
+    break;
+  case CURLINFO_CONTENT_LENGTH_DOWNLOAD_T:
+    *param_offt = (data->progress.flags & PGRS_DL_SIZE_KNOWN)?
+      data->progress.size_dl:-1;
+    break;
+  case CURLINFO_CONTENT_LENGTH_UPLOAD_T:
+    *param_offt = (data->progress.flags & PGRS_UL_SIZE_KNOWN)?
+      data->progress.size_ul:-1;
+    break;
+  default:
+    return CURLE_UNKNOWN_OPTION;
+  }
+
+  return CURLE_OK;
+}
+
 static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
                                double *param_doublep)
 {
@@ -359,46 +393,25 @@ static CURLcode getinfo_slist(struct Curl_easy *data, 
CURLINFO info,
       struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **)
                                           param_slistp;
       struct curl_tlssessioninfo *tsi = &data->tsi;
+#ifdef USE_SSL
       struct connectdata *conn = data->easy_conn;
+#endif
 
       *tsip = tsi;
       tsi->backend = Curl_ssl_backend();
       tsi->internals = NULL;
 
+#ifdef USE_SSL
       if(conn && tsi->backend != CURLSSLBACKEND_NONE) {
         unsigned int i;
         for(i = 0; i < (sizeof(conn->ssl) / sizeof(conn->ssl[0])); ++i) {
           if(conn->ssl[i].use) {
-#if defined(USE_AXTLS)
-            tsi->internals = (void *)conn->ssl[i].ssl;
-#elif defined(USE_CYASSL)
-            tsi->internals = (void *)conn->ssl[i].handle;
-#elif defined(USE_DARWINSSL)
-            tsi->internals = (void *)conn->ssl[i].ssl_ctx;
-#elif defined(USE_GNUTLS)
-            tsi->internals = (void *)conn->ssl[i].session;
-#elif defined(USE_GSKIT)
-            tsi->internals = (void *)conn->ssl[i].handle;
-#elif defined(USE_MBEDTLS)
-            tsi->internals = (void *)&conn->ssl[i].ssl;
-#elif defined(USE_NSS)
-            tsi->internals = (void *)conn->ssl[i].handle;
-#elif defined(USE_OPENSSL)
-            /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
-            tsi->internals = ((info == CURLINFO_TLS_SESSION) ?
-                              (void *)conn->ssl[i].ctx :
-                              (void *)conn->ssl[i].handle);
-#elif defined(USE_POLARSSL)
-            tsi->internals = (void *)&conn->ssl[i].ssl;
-#elif defined(USE_SCHANNEL)
-            tsi->internals = (void *)&conn->ssl[i].ctxt->ctxt_handle;
-#elif defined(USE_SSL)
-#error "SSL backend specific information missing for CURLINFO_TLS_SSL_PTR"
-#endif
+            tsi->internals = Curl_ssl->get_internals(&conn->ssl[i], info);
             break;
           }
         }
       }
+#endif
     }
     break;
   default:
diff --git a/lib/gopher.c b/lib/gopher.c
index 19b6d36e2..0ee3ffe00 100644
--- a/lib/gopher.c
+++ b/lib/gopher.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,8 +73,8 @@ const struct Curl_handler Curl_handler_gopher = {
 
 static CURLcode gopher_do(struct connectdata *conn, bool *done)
 {
-  CURLcode result=CURLE_OK;
-  struct Curl_easy *data=conn->data;
+  CURLcode result = CURLE_OK;
+  struct Curl_easy *data = conn->data;
   curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
 
   curl_off_t *bytecount = &data->req.bytecount;
@@ -97,11 +97,11 @@ static CURLcode gopher_do(struct connectdata *conn, bool 
*done)
 
     /* Otherwise, drop / and the first character (i.e., item type) ... */
     newp = path;
-    newp+=2;
+    newp += 2;
 
     /* ... then turn ? into TAB for search servers, Veronica, etc. ... */
     j = strlen(newp);
-    for(i=0; i<j; i++)
+    for(i = 0; i<j; i++)
       if(newp[i] == '?')
         newp[i] = '\x09';
 
diff --git a/lib/hash.c b/lib/hash.c
index 552022443..5733d975b 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -300,10 +300,10 @@ Curl_hash_next_element(struct curl_hash_iterator *iter)
 
   /* If we have reached the end of the list, find the next one */
   if(!iter->current_element) {
-    for(i = iter->slot_index;i < h->slots;i++) {
+    for(i = iter->slot_index; i < h->slots; i++) {
       if(h->table[i].head) {
         iter->current_element = h->table[i].head;
-        iter->slot_index = i+1;
+        iter->slot_index = i + 1;
         break;
       }
     }
diff --git a/lib/hostcheck.c b/lib/hostcheck.c
index 156091ca8..23dc3d2a7 100644
--- a/lib/hostcheck.c
+++ b/lib/hostcheck.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,10 +73,10 @@ static int hostmatch(char *hostname, char *pattern)
   /* normalize pattern and hostname by stripping off trailing dots */
   size_t len = strlen(hostname);
   if(hostname[len-1]=='.')
-    hostname[len-1]=0;
+    hostname[len-1] = 0;
   len = strlen(pattern);
   if(pattern[len-1]=='.')
-    pattern[len-1]=0;
+    pattern[len-1] = 0;
 
   pattern_wildcard = strchr(pattern, '*');
   if(pattern_wildcard == NULL)
@@ -95,7 +95,7 @@ static int hostmatch(char *hostname, char *pattern)
      match. */
   wildcard_enabled = 1;
   pattern_label_end = strchr(pattern, '.');
-  if(pattern_label_end == NULL || strchr(pattern_label_end+1, '.') == NULL ||
+  if(pattern_label_end == NULL || strchr(pattern_label_end + 1, '.') == NULL ||
      pattern_wildcard > pattern_label_end ||
      strncasecompare(pattern, "xn--", 4)) {
     wildcard_enabled = 0;
@@ -116,9 +116,9 @@ static int hostmatch(char *hostname, char *pattern)
     return CURL_HOST_NOMATCH;
 
   prefixlen = pattern_wildcard - pattern;
-  suffixlen = pattern_label_end - (pattern_wildcard+1);
+  suffixlen = pattern_label_end - (pattern_wildcard + 1);
   return strncasecompare(pattern, hostname, prefixlen) &&
-    strncasecompare(pattern_wildcard+1, hostname_label_end - suffixlen,
+    strncasecompare(pattern_wildcard + 1, hostname_label_end - suffixlen,
                     suffixlen) ?
     CURL_HOST_MATCH : CURL_HOST_NOMATCH;
 }
@@ -137,7 +137,7 @@ int Curl_cert_hostcheck(const char *match_pattern, const 
char *hostname)
       hostp = strdup(hostname);
       if(hostp) {
         if(hostmatch(hostp, matchp) == CURL_HOST_MATCH)
-          res= 1;
+          res = 1;
         free(hostp);
       }
       free(matchp);
diff --git a/lib/hostip.c b/lib/hostip.c
index 619ec84b5..1a18a3ed7 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -304,9 +304,9 @@ fetch_addr(struct connectdata *conn,
   entry_len = strlen(entry_id);
 
   /* See if its already in our dns cache */
-  dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1);
+  dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
 
-  if(dns && (data->set.dns_cache_timeout != -1))  {
+  if(dns && (data->set.dns_cache_timeout != -1)) {
     /* See whether the returned entry is stale. Done before we release lock */
     struct hostcache_prune_data user;
 
@@ -316,7 +316,7 @@ fetch_addr(struct connectdata *conn,
     if(hostcache_timestamp_remove(&user, dns)) {
       infof(data, "Hostname in DNS cache was stale, zapped\n");
       dns = NULL; /* the memory deallocation is being handled by the hash */
-      Curl_hash_delete(data->dns.hostcache, entry_id, entry_len+1);
+      Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
     }
   }
 
@@ -403,7 +403,7 @@ Curl_cache_addr(struct Curl_easy *data,
     dns->timestamp = 1;   /* zero indicates CURLOPT_RESOLVE entry */
 
   /* Store the resolved data in our DNS cache. */
-  dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len+1,
+  dns2 = Curl_hash_add(data->dns.hostcache, entry_id, entry_len + 1,
                        (void *)dns);
   if(!dns2) {
     free(dns);
@@ -807,7 +807,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
         Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
 
       /* delete entry, ignore if it didn't exist */
-      Curl_hash_delete(data->dns.hostcache, entry_id, entry_len+1);
+      Curl_hash_delete(data->dns.hostcache, entry_id, entry_len + 1);
 
       if(data->share)
         Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
@@ -848,7 +848,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
         Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
 
       /* See if its already in our dns cache */
-      dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1);
+      dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len + 1);
 
       /* free the allocated entry_id again */
       free(entry_id);
diff --git a/lib/hostip4.c b/lib/hostip4.c
index e459328ac..6a7c6e576 100644
--- a/lib/hostip4.c
+++ b/lib/hostip4.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -249,7 +249,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
      */
 
     if(CURL_HOSTENT_SIZE >=
-       (sizeof(struct hostent)+sizeof(struct hostent_data))) {
+       (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
diff --git a/lib/hostip6.c b/lib/hostip6.c
index 4ebfc2dcf..edeebec9e 100644
--- a/lib/hostip6.c
+++ b/lib/hostip6.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -212,7 +212,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
 
   if(port) {
     snprintf(sbuf, sizeof(sbuf), "%d", port);
-    sbufptr=sbuf;
+    sbufptr = sbuf;
   }
 
   error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res);
diff --git a/lib/http.c b/lib/http.c
index 741098e84..b5164f758 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -50,6 +50,7 @@
 #include "transfer.h"
 #include "sendf.h"
 #include "formdata.h"
+#include "mime.h"
 #include "progress.h"
 #include "curl_base64.h"
 #include "cookie.h"
@@ -162,6 +163,7 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
   if(!http)
     return CURLE_OUT_OF_MEMORY;
 
+  Curl_mime_initpart(&http->form, conn->data);
   conn->data->req.protop = http;
 
   Curl_http2_setup_conn(conn);
@@ -170,26 +172,6 @@ CURLcode Curl_http_setup_conn(struct connectdata *conn)
   return CURLE_OK;
 }
 
-/*
- * checkheaders() checks the linked list of custom HTTP headers for a
- * particular header (prefix).
- *
- * Returns a pointer to the first matching header or NULL if none matched.
- */
-char *Curl_checkheaders(const struct connectdata *conn,
-                        const char *thisheader)
-{
-  struct curl_slist *head;
-  size_t thislen = strlen(thisheader);
-  struct Curl_easy *data = conn->data;
-
-  for(head = data->set.headers;head; head=head->next) {
-    if(strncasecompare(head->data, thisheader, thislen))
-      return head->data;
-  }
-
-  return NULL;
-}
 
 /*
  * checkProxyHeaders() checks the linked list of custom proxy headers
@@ -209,7 +191,7 @@ char *Curl_checkProxyheaders(const struct connectdata *conn,
 
   for(head = (conn->bits.proxy && data->set.sep_headers) ?
         data->set.proxyheaders : data->set.headers;
-      head; head=head->next) {
+      head; head = head->next) {
     if(strncasecompare(head->data, thisheader, thislen))
       return head->data;
   }
@@ -427,6 +409,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
         expectsend = data->state.infilesize;
       break;
     case HTTPREQ_POST_FORM:
+    case HTTPREQ_POST_MIME:
       expectsend = http->postsize;
       break;
     default:
@@ -610,7 +593,7 @@ output_auth_headers(struct connectdata *conn,
 #endif
 #if defined(USE_NTLM) && defined(NTLM_WB_ENABLED)
   if(authstatus->picked == CURLAUTH_NTLM_WB) {
-    auth="NTLM_WB";
+    auth = "NTLM_WB";
     result = Curl_output_ntlm_wb(conn, proxy);
     if(result)
       return result;
@@ -1022,7 +1005,7 @@ static size_t readmoredata(char *buffer,
 
       http->sending++; /* move one step up */
 
-      http->backup.postsize=0;
+      http->backup.postsize = 0;
     }
     else
       http->postsize = 0;
@@ -1150,7 +1133,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
         /* there was body data sent beyond the initial header part, pass that
            on to the debug callback too */
         Curl_debug(conn->data, CURLINFO_DATA_OUT,
-                   ptr+headlen, bodylen, conn);
+                   ptr + headlen, bodylen, conn);
       }
     }
 
@@ -1262,7 +1245,7 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void 
*inptr, size_t size)
        (~(size * 2) < (in->size_used * 2)))
       new_size = (size_t)-1;
     else
-      new_size = (in->size_used+size) * 2;
+      new_size = (in->size_used + size) * 2;
 
     if(in->buffer)
       /* we have a buffer, enlarge the existing one */
@@ -1339,7 +1322,7 @@ Curl_compareheader(const char *headerline, /* line to 
check */
   clen = strlen(content); /* length of the word to find */
 
   /* find the content string in the rest of the line */
-  for(;len>=clen;len--, start++) {
+  for(; len >= clen; len--, start++) {
     if(strncasecompare(start, content, clen))
       return TRUE; /* match! */
   }
@@ -1371,7 +1354,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool 
*done)
   if(CONNECT_FIRSTSOCKET_PROXY_SSL())
     return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */
 
-  if(!Curl_connect_complete(conn))
+  if(Curl_connect_ongoing(conn))
     /* nothing else to do except wait right now - we're not done here. */
     return CURLE_OK;
 
@@ -1470,18 +1453,17 @@ CURLcode Curl_http_done(struct connectdata *conn,
 
   Curl_http2_done(conn, premature);
 
-  if(HTTPREQ_POST_FORM == data->set.httpreq) {
-    data->req.bytecount = http->readbytecount + http->writebytecount;
+  Curl_mime_cleanpart(&http->form);
 
-    Curl_formclean(&http->sendit); /* Now free that whole lot */
-    if(http->form.fp) {
-      /* a file being uploaded was left opened, close it! */
-      fclose(http->form.fp);
-      http->form.fp = NULL;
-    }
-  }
-  else if(HTTPREQ_PUT == data->set.httpreq)
+  switch(data->set.httpreq) {
+  case HTTPREQ_PUT:
+  case HTTPREQ_POST_FORM:
+  case HTTPREQ_POST_MIME:
     data->req.bytecount = http->readbytecount + http->writebytecount;
+    break;
+  default:
+    break;
+  }
 
   if(status)
     return status;
@@ -1581,7 +1563,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
   char *ptr;
   struct curl_slist *h[2];
   struct curl_slist *headers;
-  int numlists=1; /* by default */
+  int numlists = 1; /* by default */
   struct Curl_easy *data = conn->data;
   int i;
 
@@ -1613,7 +1595,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
   }
 
   /* loop through one or two lists */
-  for(i=0; i < numlists; i++) {
+  for(i = 0; i < numlists; i++) {
     headers = h[i];
 
     while(headers) {
@@ -1637,15 +1619,23 @@ CURLcode Curl_add_custom_headers(struct connectdata 
*conn,
                   /* this header (extended by formdata.c) is sent later */
                   checkprefix("Content-Type:", headers->data))
             ;
+          else if(data->set.httpreq == HTTPREQ_POST_MIME &&
+                  /* this header is sent later */
+                  checkprefix("Content-Type:", headers->data))
+            ;
           else if(conn->bits.authneg &&
                   /* while doing auth neg, don't allow the custom length since
                      we will force length zero then */
-                  checkprefix("Content-Length", headers->data))
+                  checkprefix("Content-Length:", headers->data))
             ;
           else if(conn->allocptr.te &&
                   /* when asking for Transfer-Encoding, don't pass on a custom
                      Connection: */
-                  checkprefix("Connection", headers->data))
+                  checkprefix("Connection:", headers->data))
+            ;
+          else if((conn->httpversion == 20) &&
+                  checkprefix("Transfer-Encoding:", headers->data))
+            /* HTTP/2 doesn't support chunked requests */
             ;
           else if((conn->httpversion == 20) &&
                   checkprefix("Transfer-Encoding:", headers->data))
@@ -1678,6 +1668,10 @@ CURLcode Curl_add_custom_headers(struct connectdata 
*conn,
               *ptr = ':';
               result = Curl_add_bufferf(req_buffer, "%s\r\n",
                                         headers->data);
+
+              /* restore the previous value */
+              *ptr = ';';
+
               if(result)
                 return result;
             }
@@ -1775,7 +1769,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   const char *httpstring;
   Curl_send_buffer *req_buffer;
   curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
-  int seekerr = CURL_SEEKFUNC_OK;
+  int seekerr = CURL_SEEKFUNC_CANTSEEK;
 
   /* Always consider the DO phase done after this function call, even if there
      may be parts of the request that is not yet sent, since we can deal with
@@ -1848,6 +1842,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       switch(httpreq) {
       case HTTPREQ_POST:
       case HTTPREQ_POST_FORM:
+      case HTTPREQ_POST_MIME:
         request = "POST";
         break;
       case HTTPREQ_PUT:
@@ -1873,7 +1868,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
      here. */
   if(Curl_checkheaders(conn, "User-Agent:")) {
     free(conn->allocptr.uagent);
-    conn->allocptr.uagent=NULL;
+    conn->allocptr.uagent = NULL;
   }
 
   /* setup the authentication headers */
@@ -1942,6 +1937,48 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   }
 #endif
 
+  switch(httpreq) {
+  case HTTPREQ_POST_MIME:
+    http->sendit = &data->set.mimepost;
+    break;
+  case HTTPREQ_POST_FORM:
+    /* Convert the form structure into a mime structure. */
+    Curl_mime_cleanpart(&http->form);
+    result = Curl_getformdata(data, &http->form, data->set.httppost,
+                              data->state.fread_func);
+    if(result)
+      return result;
+    http->sendit = &http->form;
+    break;
+  default:
+    http->sendit = NULL;
+  }
+
+  if(http->sendit) {
+    const char *cthdr = Curl_checkheaders(conn, "Content-Type:");
+
+    /* Read and seek body only. */
+    http->sendit->flags |= MIME_BODY_ONLY;
+
+    /* Prepare the mime structure headers & set content type. */
+
+    if(cthdr)
+      for(cthdr += 13; *cthdr == ' '; cthdr++)
+        ;
+    else if(http->sendit->kind == MIMEKIND_MULTIPART)
+      cthdr = "multipart/form-data";
+
+    curl_mime_headers(http->sendit, data->set.headers, 0);
+    result = Curl_mime_prepare_headers(http->sendit, cthdr,
+                                       NULL, MIMESTRATEGY_FORM);
+    curl_mime_headers(http->sendit, NULL, 0);
+    if(!result)
+      result = Curl_mime_rewind(http->sendit);
+    if(result)
+      return result;
+    http->postsize = Curl_mime_size(http->sendit);
+  }
+
   ptr = Curl_checkheaders(conn, "Transfer-Encoding:");
   if(ptr) {
     /* Some kind of TE is requested, check if 'chunked' is chosen */
@@ -1949,9 +1986,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       Curl_compareheader(ptr, "Transfer-Encoding:", "chunked");
   }
   else {
-    if((conn->handler->protocol&PROTO_FAMILY_HTTP) &&
-       data->set.upload &&
-       (data->state.infilesize == -1)) {
+    if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
+       (((httpreq == HTTPREQ_POST_MIME || httpreq == HTTPREQ_POST_FORM) &&
+       http->postsize < 0) ||
+       (data->set.upload && data->state.infilesize == -1))) {
       if(conn->bits.authneg)
         /* don't enable chunked during auth neg */
         ;
@@ -2049,7 +2087,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   }
 
 #ifndef CURL_DISABLE_PROXY
-  if(conn->bits.httpproxy && !conn->bits.tunnel_proxy)  {
+  if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
     /* Using a proxy but does not tunnel through it */
 
     /* The path sent to the proxy is in fact the entire URL. But if the remote
@@ -2123,21 +2161,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
   }
 #endif /* CURL_DISABLE_PROXY */
 
-  if(HTTPREQ_POST_FORM == httpreq) {
-    /* we must build the whole post sequence first, so that we have a size of
-       the whole transfer before we start to send it */
-    result = Curl_getformdata(data, &http->sendit, data->set.httppost,
-                              Curl_checkheaders(conn, "Content-Type:"),
-                              &http->postsize);
-    if(result)
-      return result;
-  }
-
   http->p_accept = Curl_checkheaders(conn, "Accept:")?NULL:"Accept: */*\r\n";
 
-  if(( (HTTPREQ_POST == httpreq) ||
-       (HTTPREQ_POST_FORM == httpreq) ||
-       (HTTPREQ_PUT == httpreq) ) &&
+  if((HTTPREQ_POST == httpreq || HTTPREQ_PUT == httpreq) &&
      data->state.resume_from) {
     /**********************************************************************
      * Resuming upload in HTTP means that we PUT or POST and that we have
@@ -2145,6 +2171,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
      * a Range: header that will be passed along. We need to "fast forward"
      * the file the given number of bytes and decrease the assume upload
      * file size before we continue this venture in the dark lands of HTTP.
+     * Resuming mime/form posting at an offset > 0 has no sense and is ignored.
      *********************************************************************/
 
     if(data->state.resume_from < 0) {
@@ -2166,7 +2193,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       }
 
       if(seekerr != CURL_SEEKFUNC_OK) {
-        curl_off_t passed=0;
+        curl_off_t passed = 0;
 
         if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
           failf(data, "Could not seek stream");
@@ -2219,7 +2246,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
                                          data->state.range);
     }
-    else if((httpreq != HTTPREQ_GET) &&
+    else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) &&
             !Curl_checkheaders(conn, "Content-Range:")) {
 
       /* if a line like this was already allocated, free the previous one */
@@ -2237,7 +2264,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       }
       else if(data->state.resume_from) {
         /* This is because "resume" was selected */
-        curl_off_t total_expected_size=
+        curl_off_t total_expected_size =
           data->state.resume_from + data->state.infilesize;
         conn->allocptr.rangeline =
           aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
@@ -2347,8 +2374,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
 
 #if !defined(CURL_DISABLE_COOKIES)
   if(data->cookies || addcookies) {
-    struct Cookie *co=NULL; /* no cookies from start */
-    int count=0;
+    struct Cookie *co = NULL; /* no cookies from start */
+    int count = 0;
 
     if(data->cookies) {
       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
@@ -2361,7 +2388,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
     }
     if(co) {
-      struct Cookie *store=co;
+      struct Cookie *store = co;
       /* now loop through all cookies that matched */
       while(co) {
         if(co->value) {
@@ -2415,117 +2442,79 @@ CURLcode Curl_http(struct connectdata *conn, bool 
*done)
 
   switch(httpreq) {
 
-  case HTTPREQ_POST_FORM:
-    if(!http->sendit || conn->bits.authneg) {
-      /* nothing to post! */
-      result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
-      if(result)
-        return result;
-
-      result = Curl_add_buffer_send(req_buffer, conn,
-                                    &data->info.request_size, 0, FIRSTSOCKET);
-      if(result)
-        failf(data, "Failed sending POST request");
-      else
-        /* setup variables for the upcoming transfer */
-        Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
-                            -1, NULL);
-      break;
-    }
-
-    if(Curl_FormInit(&http->form, http->sendit)) {
-      failf(data, "Internal HTTP POST error!");
-      return CURLE_HTTP_POST_ERROR;
-    }
-
-    /* Get the currently set callback function pointer and store that in the
-       form struct since we might want the actual user-provided callback later
-       on. The data->set.fread_func pointer itself will be changed for the
-       multipart case to the function that returns a multipart formatted
-       stream. */
-    http->form.fread_func = data->state.fread_func;
-
-    /* Set the read function to read from the generated form data */
-    data->state.fread_func = (curl_read_callback)Curl_FormReader;
-    data->state.in = &http->form;
+  case HTTPREQ_PUT: /* Let's PUT the data to the server! */
 
-    http->sending = HTTPSEND_BODY;
+    if(conn->bits.authneg)
+      postsize = 0;
+    else
+      postsize = data->state.infilesize;
 
-    if(!data->req.upload_chunky &&
-       !Curl_checkheaders(conn, "Content-Length:")) {
+    if((postsize != -1) && !data->req.upload_chunky &&
+       (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
       /* only add Content-Length if not uploading chunked */
       result = Curl_add_bufferf(req_buffer,
                                 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
-                                "\r\n", http->postsize);
+                                "\r\n", postsize);
       if(result)
         return result;
     }
 
-    result = expect100(data, conn, req_buffer);
-    if(result)
-      return result;
-
-    {
-
-      /* Get Content-Type: line from Curl_formpostheader.
-       */
-      char *contentType;
-      size_t linelength=0;
-      contentType = Curl_formpostheader((void *)&http->form,
-                                        &linelength);
-      if(!contentType) {
-        failf(data, "Could not get Content-Type header line!");
-        return CURLE_HTTP_POST_ERROR;
-      }
-
-      result = Curl_add_buffer(req_buffer, contentType, linelength);
+    if(postsize != 0) {
+      result = expect100(data, conn, req_buffer);
       if(result)
         return result;
     }
 
-    /* make the request end in a true CRLF */
-    result = Curl_add_buffer(req_buffer, "\r\n", 2);
+    result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
     if(result)
       return result;
 
-    /* set upload size to the progress meter */
-    Curl_pgrsSetUploadSize(data, http->postsize);
+    /* set the upload size to the progress meter */
+    Curl_pgrsSetUploadSize(data, postsize);
 
-    /* fire away the whole request to the server */
+    /* this sends the buffer and frees all the buffer resources */
     result = Curl_add_buffer_send(req_buffer, conn,
                                   &data->info.request_size, 0, FIRSTSOCKET);
     if(result)
-      failf(data, "Failed sending POST request");
+      failf(data, "Failed sending PUT request");
     else
-      /* setup variables for the upcoming transfer */
+      /* prepare for transfer */
       Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
-                          &http->readbytecount, FIRSTSOCKET,
-                          &http->writebytecount);
-
-    if(result) {
-      Curl_formclean(&http->sendit); /* free that whole lot */
-      return result;
-    }
-
-    /* convert the form data */
-    result = Curl_convert_form(data, http->sendit);
-    if(result) {
-      Curl_formclean(&http->sendit); /* free that whole lot */
+                          &http->readbytecount, postsize?FIRSTSOCKET:-1,
+                          postsize?&http->writebytecount:NULL);
+    if(result)
       return result;
-    }
-
     break;
 
-  case HTTPREQ_PUT: /* Let's PUT the data to the server! */
+  case HTTPREQ_POST_FORM:
+  case HTTPREQ_POST_MIME:
+    /* This is form posting using mime data. */
+    if(conn->bits.authneg) {
+      /* nothing to post! */
+      result = Curl_add_bufferf(req_buffer, "Content-Length: 0\r\n\r\n");
+      if(result)
+        return result;
 
-    if(conn->bits.authneg)
-      postsize = 0;
-    else
-      postsize = data->state.infilesize;
+      result = Curl_add_buffer_send(req_buffer, conn,
+                                    &data->info.request_size, 0, FIRSTSOCKET);
+      if(result)
+        failf(data, "Failed sending POST request");
+      else
+        /* setup variables for the upcoming transfer */
+        Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
+                            -1, NULL);
+      break;
+    }
 
-    if((postsize != -1) && !data->req.upload_chunky &&
+    postsize = http->postsize;
+
+    /* We only set Content-Length and allow a custom Content-Length if
+       we don't upload data chunked, as RFC2616 forbids us to set both
+       kinds of headers (Transfer-Encoding: chunked and Content-Length) */
+    if(postsize != -1 && !data->req.upload_chunky &&
        (conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length:"))) {
-      /* only add Content-Length if not uploading chunked */
+      /* we allow replacing this header if not during auth negotiation,
+         although it isn't very wise to actually set your own */
       result = Curl_add_bufferf(req_buffer,
                                 "Content-Length: %" CURL_FORMAT_CURL_OFF_T
                                 "\r\n", postsize);
@@ -2533,24 +2522,52 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
         return result;
     }
 
-    if(postsize != 0) {
+    /* Output mime-generated headers. */
+    {
+      struct curl_slist *hdr;
+
+      for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
+        result = Curl_add_bufferf(req_buffer, "%s\r\n", hdr->data);
+        if(result)
+          return result;
+      }
+    }
+
+    /* For really small posts we don't use Expect: headers at all, and for
+       the somewhat bigger ones we allow the app to disable it. Just make
+       sure that the expect100header is always set to the preferred value
+       here. */
+    ptr = Curl_checkheaders(conn, "Expect:");
+    if(ptr) {
+      data->state.expect100header =
+        Curl_compareheader(ptr, "Expect:", "100-continue");
+    }
+    else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) {
       result = expect100(data, conn, req_buffer);
       if(result)
         return result;
     }
+    else
+      data->state.expect100header = FALSE;
 
-    result = Curl_add_buffer(req_buffer, "\r\n", 2); /* end of headers */
+    /* make the request end in a true CRLF */
+    result = Curl_add_buffer(req_buffer, "\r\n", 2);
     if(result)
       return result;
 
     /* set the upload size to the progress meter */
     Curl_pgrsSetUploadSize(data, postsize);
 
+    /* Read from mime structure. */
+    data->state.fread_func = (curl_read_callback) Curl_mime_read;
+    data->state.in = (void *) http->sendit;
+    http->sending = HTTPSEND_BODY;
+
     /* this sends the buffer and frees all the buffer resources */
     result = Curl_add_buffer_send(req_buffer, conn,
                                   &data->info.request_size, 0, FIRSTSOCKET);
     if(result)
-      failf(data, "Failed sending PUT request");
+      failf(data, "Failed sending POST request");
     else
       /* prepare for transfer */
       Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
@@ -2558,6 +2575,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
                           postsize?&http->writebytecount:NULL);
     if(result)
       return result;
+
     break;
 
   case HTTPREQ_POST:
@@ -2614,7 +2632,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
          its size. */
       if(conn->httpversion != 20 &&
          !data->state.expect100header &&
-         (postsize < MAX_INITIAL_POST_SIZE))  {
+         (postsize < MAX_INITIAL_POST_SIZE)) {
         /* if we don't use expect: 100  AND
            postsize is less than MAX_INITIAL_POST_SIZE
 
@@ -2779,7 +2797,7 @@ checkhttpprefix(struct Curl_easy *data,
     failf(data, "Failed to allocate memory for conversion!");
     return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
   }
-  if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
+  if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s) + 1)) {
     /* Curl_convert_from_network calls failf if unsuccessful */
     free(scratch);
     return FALSE; /* can't return CURLE_foobar so return FALSE */
@@ -2809,6 +2827,7 @@ static bool
 checkrtspprefix(struct Curl_easy *data,
                 const char *s)
 {
+  bool result = FALSE;
 
 #ifdef CURL_DOES_CONVERSIONS
   /* convert from the network encoding using a scratch area */
@@ -2817,18 +2836,19 @@ checkrtspprefix(struct Curl_easy *data,
     failf(data, "Failed to allocate memory for conversion!");
     return FALSE; /* can't return CURLE_OUT_OF_MEMORY so return FALSE */
   }
-  if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s)+1)) {
+  if(CURLE_OK != Curl_convert_from_network(data, scratch, strlen(s) + 1)) {
     /* Curl_convert_from_network calls failf if unsuccessful */
-    free(scratch);
-    return FALSE; /* can't return CURLE_foobar so return FALSE */
+    result = FALSE; /* can't return CURLE_foobar so return FALSE */
   }
-  s = scratch;
+  else
+    result = checkprefix("RTSP/", scratch)? TRUE: FALSE;
+  free(scratch);
 #else
   (void)data; /* unused */
+  result = checkprefix("RTSP/", s)? TRUE: FALSE;
 #endif /* CURL_DOES_CONVERSIONS */
-  if(checkprefix("RTSP/", s))
-    return TRUE;
-  return FALSE;
+
+  return result;
 }
 #endif /* CURL_DISABLE_RTSP */
 
@@ -2870,14 +2890,14 @@ static CURLcode header_append(struct Curl_easy *data,
       return CURLE_OUT_OF_MEMORY;
     }
 
-    newsize=CURLMAX((k->hbuflen+ length)*3/2, data->state.headersize*2);
+    newsize = CURLMAX((k->hbuflen + length) * 3 / 2, data->state.headersize*2);
     hbufp_index = k->hbufp - data->state.headerbuff;
     newbuff = realloc(data->state.headerbuff, newsize);
     if(!newbuff) {
       failf(data, "Failed to alloc memory for big header!");
       return CURLE_OUT_OF_MEMORY;
     }
-    data->state.headersize=newsize;
+    data->state.headersize = newsize;
     data->state.headerbuff = newbuff;
     k->hbufp = data->state.headerbuff + hbufp_index;
   }
@@ -2970,7 +2990,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy 
*data,
     }
 
     /* decrease the size of the remaining (supposed) header line */
-    rest_length = (k->end_ptr - k->str)+1;
+    rest_length = (k->end_ptr - k->str) + 1;
     *nread -= (ssize_t)rest_length;
 
     k->str = k->end_ptr + 1; /* move past new line */
@@ -3169,6 +3189,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy 
*data,
           case HTTPREQ_PUT:
           case HTTPREQ_POST:
           case HTTPREQ_POST_FORM:
+          case HTTPREQ_POST_MIME:
             /* We got an error response. If this happened before the whole
              * request body has been sent we stop sending and mark the
              * connection for closure after we've read the entire response.
@@ -3296,7 +3317,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy 
*data,
 #define HEADER1 scratch
 #define SCRATCHSIZE 21
       CURLcode res;
-      char scratch[SCRATCHSIZE+1]; /* "HTTP/major.minor 123" */
+      char scratch[SCRATCHSIZE + 1]; /* "HTTP/major.minor 123" */
       /* We can't really convert this yet because we
          don't know if it's the 1st header line or the body.
          So we do a partial conversion into a scratch area,
@@ -3337,7 +3358,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy 
*data,
           separator = ' ';
         }
 
-        if((nc==4) && (' ' == separator)) {
+        if((nc == 4) && (' ' == separator)) {
           conn->httpversion += 10 * httpversion_major;
 
           if(k->upgr101 == UPGR101_RECEIVED) {
@@ -3350,7 +3371,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy 
*data,
           /* this is the real world, not a Nirvana
              NCSA 1.5.x returns this crap when asked for HTTP/1.1
           */
-          nc=sscanf(HEADER1, " HTTP %3d", &k->httpcode);
+          nc = sscanf(HEADER1, " HTTP %3d", &k->httpcode);
           conn->httpversion = 10;
 
           /* If user has set option HTTP200ALIASES,
@@ -3375,7 +3396,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy 
*data,
                     &rtspversion_major,
                     &conn->rtspversion,
                     &k->httpcode);
-        if(nc==3) {
+        if(nc == 3) {
           conn->rtspversion += 10 * rtspversion_major;
           conn->httpversion = 11; /* For us, RTSP acts like HTTP 1.1 */
         }
@@ -3407,7 +3428,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy 
*data,
            ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
 
           if(data->state.resume_from &&
-             (data->set.httpreq==HTTPREQ_GET) &&
+             (data->set.httpreq == HTTPREQ_GET) &&
              (k->httpcode == 416)) {
             /* "Requested Range Not Satisfiable", just proceed and
                pretend this is no error */
@@ -3463,8 +3484,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy 
*data,
            * fields.  */
           if(data->set.timecondition)
             data->info.timecond = TRUE;
-          k->size=0;
-          k->maxdownload=0;
+          k->size = 0;
+          k->maxdownload = 0;
           k->ignorecl = TRUE; /* ignore Content-Length headers */
           break;
         default:
@@ -3486,28 +3507,32 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy 
*data,
     /* Check for Content-Length: header lines to get size */
     if(!k->ignorecl && !data->set.ignorecl &&
        checkprefix("Content-Length:", k->p)) {
-      curl_off_t contentlength = curlx_strtoofft(k->p+15, NULL, 10);
-      if(data->set.max_filesize &&
-         contentlength > data->set.max_filesize) {
-        failf(data, "Maximum file size exceeded");
-        return CURLE_FILESIZE_EXCEEDED;
-      }
-      if(contentlength >= 0) {
-        k->size = contentlength;
-        k->maxdownload = k->size;
-        /* we set the progress download size already at this point
-           just to make it easier for apps/callbacks to extract this
-           info as soon as possible */
-        Curl_pgrsSetDownloadSize(data, k->size);
-      }
-      else {
-        /* Negative Content-Length is really odd, and we know it
-           happens for example when older Apache servers send large
-           files */
-        streamclose(conn, "negative content-length");
-        infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
-              ", closing after transfer\n", contentlength);
+      curl_off_t contentlength;
+      if(!curlx_strtoofft(k->p + 15, NULL, 10, &contentlength)) {
+        if(data->set.max_filesize &&
+           contentlength > data->set.max_filesize) {
+          failf(data, "Maximum file size exceeded");
+          return CURLE_FILESIZE_EXCEEDED;
+        }
+        if(contentlength >= 0) {
+          k->size = contentlength;
+          k->maxdownload = k->size;
+          /* we set the progress download size already at this point
+             just to make it easier for apps/callbacks to extract this
+             info as soon as possible */
+          Curl_pgrsSetDownloadSize(data, k->size);
+        }
+        else {
+          /* Negative Content-Length is really odd, and we know it
+             happens for example when older Apache servers send large
+             files */
+          streamclose(conn, "negative content-length");
+          infof(data, "Negative content-length: %" CURL_FORMAT_CURL_OFF_T
+                ", closing after transfer\n", contentlength);
+        }
       }
+      else
+        infof(data, "Illegal Content-Length: header\n");
     }
     /* check for Content-Type: header lines to get the MIME-type */
     else if(checkprefix("Content-Type:", k->p)) {
@@ -3682,11 +3707,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy 
*data,
 
       /* if it truly stopped on a digit */
       if(ISDIGIT(*ptr)) {
-        k->offset = curlx_strtoofft(ptr, NULL, 10);
-
-        if(data->state.resume_from == k->offset)
-          /* we asked for a resume and we got it */
-          k->content_range = TRUE;
+        if(!curlx_strtoofft(ptr, NULL, 10, &k->offset)) {
+          if(data->state.resume_from == k->offset)
+            /* we asked for a resume and we got it */
+            k->content_range = TRUE;
+        }
       }
       else
         data->state.resume_from = 0; /* get everything */
@@ -3697,7 +3722,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy 
*data,
       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
                       CURL_LOCK_ACCESS_SINGLE);
       Curl_cookie_add(data,
-                      data->cookies, TRUE, k->p+11,
+                      data->cookies, TRUE, k->p + 11,
                       /* If there is a custom-set Host: name, use it
                          here, or else use real peer host name. */
                       conn->allocptr.cookiehost?
@@ -3708,8 +3733,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy 
*data,
 #endif
     else if(checkprefix("Last-Modified:", k->p) &&
             (data->set.timecondition || data->set.get_filetime) ) {
-      time_t secs=time(NULL);
-      k->timeofdoc = curl_getdate(k->p+strlen("Last-Modified:"),
+      time_t secs = time(NULL);
+      k->timeofdoc = curl_getdate(k->p + strlen("Last-Modified:"),
                                   &secs);
       if(data->set.get_filetime)
         data->info.filetime = (long)k->timeofdoc;
diff --git a/lib/http.h b/lib/http.h
index c5c7a125d..0252f63db 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -40,8 +40,6 @@ bool Curl_compareheader(const char *headerline,  /* line to 
check */
                         const char *header,   /* header keyword _with_ colon */
                         const char *content); /* content string to find */
 
-char *Curl_checkheaders(const struct connectdata *conn,
-                        const char *thisheader);
 char *Curl_copy_header_value(const char *header);
 
 char *Curl_checkProxyheaders(const struct connectdata *conn,
@@ -130,7 +128,7 @@ CURLcode Curl_http_perhapsrewind(struct connectdata *conn);
  * HTTP unique setup
  ***************************************************************************/
 struct HTTP {
-  struct FormData *sendit;
+  curl_mimepart *sendit;
   curl_off_t postsize; /* off_t to handle large file sizes */
   const char *postdata;
 
@@ -140,7 +138,7 @@ struct HTTP {
   curl_off_t writebytecount;
 
   /* For FORM posting */
-  struct Form form;
+  curl_mimepart form;
 
   struct back {
     curl_read_callback fread_func; /* backup storage for fread pointer */
diff --git a/lib/http2.c b/lib/http2.c
index 6b52171f6..4c8d2e529 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -384,12 +384,12 @@ char *curl_pushheader_byname(struct curl_pushheaders *h, 
const char *header)
     struct HTTP *stream = h->data->req.protop;
     size_t len = strlen(header);
     size_t i;
-    for(i=0; i<stream->push_headers_used; i++) {
+    for(i = 0; i<stream->push_headers_used; i++) {
       if(!strncmp(header, stream->push_headers[i], len)) {
         /* sub-match, make sure that it is followed by a colon */
         if(stream->push_headers[i][len] != ':')
           continue;
-        return &stream->push_headers[i][len+1];
+        return &stream->push_headers[i][len + 1];
       }
     }
   }
@@ -464,7 +464,7 @@ static int push_promise(struct Curl_easy *data,
                               data->multi->push_userp);
 
     /* free the headers again */
-    for(i=0; i<stream->push_headers_used; i++)
+    for(i = 0; i<stream->push_headers_used; i++)
       free(stream->push_headers[i]);
     free(stream->push_headers);
     stream->push_headers = NULL;
@@ -1582,7 +1582,7 @@ static ssize_t http2_recv(struct connectdata *conn, int 
sockindex,
       failf(data, "nghttp2_session_mem_recv() returned %d:%s\n",
             rv, nghttp2_strerror((int)rv));
       *err = CURLE_RECV_ERROR;
-      return 0;
+      return -1;
     }
     DEBUGF(infof(data, "nghttp2_session_mem_recv() returns %zd\n", rv));
     if(nread == rv) {
@@ -1600,7 +1600,7 @@ static ssize_t http2_recv(struct connectdata *conn, int 
sockindex,
     rv = h2_session_send(data, httpc->h2);
     if(rv != 0) {
       *err = CURLE_SEND_ERROR;
-      return 0;
+      return -1;
     }
 
     if(should_close_session(httpc)) {
@@ -1955,6 +1955,7 @@ static ssize_t http2_send(struct connectdata *conn, int 
sockindex,
   switch(conn->data->set.httpreq) {
   case HTTPREQ_POST:
   case HTTPREQ_POST_FORM:
+  case HTTPREQ_POST_MIME:
   case HTTPREQ_PUT:
     if(conn->data->state.infilesize != -1)
       stream->upload_left = conn->data->state.infilesize;
diff --git a/lib/http_chunks.c b/lib/http_chunks.c
index 1bdf6974c..92d773112 100644
--- a/lib/http_chunks.c
+++ b/lib/http_chunks.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -86,8 +86,8 @@ static bool Curl_isxdigit(char digit)
 void Curl_httpchunk_init(struct connectdata *conn)
 {
   struct Curl_chunker *chunk = &conn->chunk;
-  chunk->hexindex=0;        /* start at 0 */
-  chunk->dataleft=0;        /* no data left yet! */
+  chunk->hexindex = 0;      /* start at 0 */
+  chunk->dataleft = 0;      /* no data left yet! */
   chunk->state = CHUNK_HEX; /* we get hex first! */
 }
 
@@ -107,7 +107,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
                               ssize_t datalen,
                               ssize_t *wrotep)
 {
-  CURLcode result=CURLE_OK;
+  CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
   struct Curl_chunker *ch = &conn->chunk;
   struct SingleRequest *k = &data->req;
@@ -147,7 +147,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
           return CHUNKE_ILLEGAL_HEX;
 
         /* length and datap are unmodified */
-        ch->hexbuffer[ch->hexindex]=0;
+        ch->hexbuffer[ch->hexindex] = 0;
 
         /* convert to host encoding before calling strtoul */
         result = Curl_convert_from_network(conn->data, ch->hexbuffer,
@@ -158,9 +158,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
           return CHUNKE_ILLEGAL_HEX;
         }
 
-        ch->datasize=curlx_strtoofft(ch->hexbuffer, &endptr, 16);
-        if((ch->datasize == CURL_OFF_T_MAX) && (errno == ERANGE))
-          /* overflow is an error */
+        if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize))
           return CHUNKE_ILLEGAL_HEX;
         ch->state = CHUNK_LF; /* now wait for the CRLF */
       }
@@ -172,7 +170,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
         /* we're now expecting data to come, unless size was zero! */
         if(0 == ch->datasize) {
           ch->state = CHUNK_TRAILER; /* now check for trailers */
-          conn->trlPos=0;
+          conn->trlPos = 0;
         }
         else
           ch->state = CHUNK_DATA;
@@ -259,9 +257,9 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
 
         if(conn->trlPos) {
           /* we allocate trailer with 3 bytes extra room to fit this */
-          conn->trailer[conn->trlPos++]=0x0d;
-          conn->trailer[conn->trlPos++]=0x0a;
-          conn->trailer[conn->trlPos]=0;
+          conn->trailer[conn->trlPos++] = 0x0d;
+          conn->trailer[conn->trlPos++] = 0x0a;
+          conn->trailer[conn->trlPos] = 0;
 
           /* Convert to host encoding before calling Curl_client_write */
           result = Curl_convert_from_network(conn->data, conn->trailer,
@@ -277,7 +275,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
             if(result)
               return CHUNKE_WRITE_ERROR;
           }
-          conn->trlPos=0;
+          conn->trlPos = 0;
           ch->state = CHUNK_TRAILER_CR;
           if(*datap == 0x0a)
             /* already on the LF */
@@ -301,7 +299,7 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
             ptr = realloc(conn->trailer, conn->trlMax + 3);
           }
           else {
-            conn->trlMax=128;
+            conn->trlMax = 128;
             ptr = malloc(conn->trlMax + 3);
           }
           if(!ptr)
diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c
index 8a78bd293..0f1edcf65 100644
--- a/lib/http_ntlm.c
+++ b/lib/http_ntlm.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,11 +37,14 @@
 #include "sendf.h"
 #include "strcase.h"
 #include "http_ntlm.h"
+#include "curl_ntlm_core.h"
 #include "curl_ntlm_wb.h"
 #include "vauth/vauth.h"
 #include "url.h"
 
-#if defined(USE_NSS)
+/* SSL backend-specific #if branches in this file must be kept in the order
+   documented in curl_ntlm_core. */
+#if defined(NTLM_NEEDS_NSS_INIT)
 #include "vtls/nssg.h"
 #elif defined(USE_WINDOWS_SSPI)
 #include "curl_sspi.h"
@@ -129,7 +132,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool 
proxy)
   DEBUGASSERT(conn);
   DEBUGASSERT(conn->data);
 
-#ifdef USE_NSS
+#if defined(NTLM_NEEDS_NSS_INIT)
   if(CURLE_OK != Curl_nss_force_init(conn->data))
     return CURLE_OUT_OF_MEMORY;
 #endif
@@ -170,8 +173,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool 
proxy)
   case NTLMSTATE_TYPE1:
   default: /* for the weird cases we (re)start here */
     /* Create a type-1 message */
-    result = Curl_auth_create_ntlm_type1_message(userp, passwdp, ntlm, &base64,
-                                                 &len);
+    result = Curl_auth_create_ntlm_type1_message(conn->data, userp, passwdp,
+                                                 ntlm, &base64, &len);
     if(result)
       return result;
 
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index 834733960..26da33788 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -137,7 +137,7 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int 
sockindex)
 
 bool Curl_connect_complete(struct connectdata *conn)
 {
-  return conn->connect_state &&
+  return !conn->connect_state ||
     (conn->connect_state->tunnel_state == TUNNEL_COMPLETE);
 }
 
@@ -163,10 +163,10 @@ static CURLcode connect_init(struct connectdata *conn, 
bool reinit)
     s = conn->connect_state;
   }
   s->tunnel_state = TUNNEL_INIT;
-  s->keepon=TRUE;
+  s->keepon = TRUE;
   s->line_start = s->connect_buffer;
   s->ptr = s->line_start;
-  s->cl=0;
+  s->cl = 0;
   return CURLE_OK;
 }
 
@@ -182,8 +182,8 @@ static CURLcode CONNECT(struct connectdata *conn,
                         const char *hostname,
                         int remote_port)
 {
-  int subversion=0;
-  struct Curl_easy *data=conn->data;
+  int subversion = 0;
+  struct Curl_easy *data = conn->data;
   struct SingleRequest *k = &data->req;
   CURLcode result;
   curl_socket_t tunnelsocket = conn->sock[sockindex];
@@ -234,8 +234,8 @@ static CURLcode CONNECT(struct connectdata *conn,
 
       if(!result) {
         char *host = NULL;
-        const char *proxyconn="";
-        const char *useragent="";
+        const char *proxyconn = "";
+        const char *useragent = "";
         const char *http = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ?
           "1.0" : "1.1";
         bool ipv6_ip = conn->bits.ipv6_ip;
@@ -244,7 +244,7 @@ static CURLcode CONNECT(struct connectdata *conn,
         /* the hostname may be different */
         if(hostname != conn->host.name)
           ipv6_ip = (strchr(hostname, ':') != NULL);
-        hostheader= /* host:port with IPv6 support */
+        hostheader = /* host:port with IPv6 support */
           aprintf("%s%s%s:%hu", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
                   remote_port);
         if(!hostheader) {
@@ -410,7 +410,8 @@ static CURLcode CONNECT(struct connectdata *conn,
         }
 
         /* convert from the network encoding */
-        result = Curl_convert_from_network(data, line_start, perline);
+        result = Curl_convert_from_network(data, s->line_start,
+                                           (size_t)s->perline);
         /* Curl_convert_from_network calls failf if unsuccessful */
         if(result)
           return result;
@@ -523,8 +524,8 @@ static CURLcode CONNECT(struct connectdata *conn,
                   k->httpcode);
           }
           else {
-            s->cl = curlx_strtoofft(s->line_start +
-                                    strlen("Content-Length:"), NULL, 10);
+            (void)curlx_strtoofft(s->line_start +
+                                  strlen("Content-Length:"), NULL, 10, &s->cl);
           }
         }
         else if(Curl_compareheader(s->line_start, "Connection:", "close"))
@@ -566,7 +567,7 @@ static CURLcode CONNECT(struct connectdata *conn,
       if(error)
         return CURLE_RECV_ERROR;
 
-      if(data->info.httpproxycode != 200) {
+      if(data->info.httpproxycode/100 != 2) {
         /* Deal with the possibly already received authenticate
            headers. 'newurl' is set to a new URL if we must loop. */
         result = Curl_http_auth_act(conn);
@@ -597,7 +598,7 @@ static CURLcode CONNECT(struct connectdata *conn,
 
   } while(data->req.newurl);
 
-  if(200 != data->req.httpcode) {
+  if(data->info.httpproxycode/100 != 2) {
     if(closeConnection && data->req.newurl) {
       conn->bits.proxy_connect_closed = TRUE;
       infof(data, "Connect me again please\n");
@@ -633,7 +634,8 @@ static CURLcode CONNECT(struct connectdata *conn,
 
   data->state.authproxy.done = TRUE;
 
-  infof(data, "Proxy replied OK to CONNECT request\n");
+  infof(data, "Proxy replied %d to CONNECT request\n",
+        data->info.httpproxycode);
   data->req.ignorebody = FALSE; /* put it (back) to non-ignore state */
   conn->bits.rewindaftersend = FALSE; /* make sure this isn't set for the
                                          document request  */
diff --git a/lib/if2ip.c b/lib/if2ip.c
index a91b6d2ab..ce38ea117 100644
--- a/lib/if2ip.c
+++ b/lib/if2ip.c
@@ -103,7 +103,7 @@ bool Curl_if_is_interface_name(const char *interf)
   struct ifaddrs *iface, *head;
 
   if(getifaddrs(&head) >= 0) {
-    for(iface=head; iface != NULL; iface=iface->ifa_next) {
+    for(iface = head; iface != NULL; iface = iface->ifa_next) {
       if(strcasecompare(iface->ifa_name, interf)) {
         result = TRUE;
         break;
@@ -131,7 +131,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
 #endif
 
   if(getifaddrs(&head) >= 0) {
-    for(iface = head; iface != NULL; iface=iface->ifa_next) {
+    for(iface = head; iface != NULL; iface = iface->ifa_next) {
       if(iface->ifa_addr != NULL) {
         if(iface->ifa_addr->sa_family == af) {
           if(strcasecompare(iface->ifa_name, interf)) {
@@ -230,7 +230,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
     return IF2IP_NOT_FOUND;
 
   memset(&req, 0, sizeof(req));
-  memcpy(req.ifr_name, interf, len+1);
+  memcpy(req.ifr_name, interf, len + 1);
   req.ifr_addr.sa_family = AF_INET;
 
   if(ioctl(dummy, SIOCGIFADDR, &req) < 0) {
diff --git a/lib/imap.c b/lib/imap.c
index 8fa598f88..9cf2bf86a 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -68,6 +68,7 @@
 #include "http.h" /* for HTTP proxy tunnel stuff */
 #include "socks.h"
 #include "imap.h"
+#include "mime.h"
 #include "strtoofft.h"
 #include "strcase.h"
 #include "vtls/vtls.h"
@@ -162,11 +163,15 @@ const struct Curl_handler Curl_handler_imaps = {
 };
 #endif
 
+#define IMAP_RESP_OK       1
+#define IMAP_RESP_NOT_OK   2
+#define IMAP_RESP_PREAUTH  3
+
 /* SASL parameters for the imap protocol */
 static const struct SASLproto saslimap = {
   "imap",                     /* The service name */
   '+',                        /* Code received when continuation is expected */
-  'O',                        /* Code to receive upon authentication success */
+  IMAP_RESP_OK,               /* Code to receive upon authentication success */
   0,                          /* Maximum initial response length (no max) */
   imap_perform_authenticate,  /* Send authentication command */
   imap_continue_authenticate, /* Send authentication continuation */
@@ -249,15 +254,11 @@ static bool imap_endofresp(struct connectdata *conn, char 
*line, size_t len,
     len -= id_len + 1;
 
     if(len >= 2 && !memcmp(line, "OK", 2))
-      *resp = 'O';
-    else if(len >= 2 && !memcmp(line, "NO", 2))
-      *resp = 'N';
-    else if(len >= 3 && !memcmp(line, "BAD", 3))
-      *resp = 'B';
-    else {
-      failf(conn->data, "Bad tagged response");
-      *resp = -1;
-    }
+      *resp = IMAP_RESP_OK;
+    else if(len >= 7 && !memcmp(line, "PREAUTH", 7))
+      *resp = IMAP_RESP_PREAUTH;
+    else
+      *resp = IMAP_RESP_NOT_OK;
 
     return TRUE;
   }
@@ -563,9 +564,10 @@ static CURLcode imap_perform_authentication(struct 
connectdata *conn)
   struct imap_conn *imapc = &conn->proto.imapc;
   saslprogress progress;
 
-  /* Check we have enough data to authenticate with and end the
-     connect phase if we don't */
-  if(!Curl_sasl_can_authenticate(&imapc->sasl, conn)) {
+  /* Check if already authenticated OR if there is enough data to authenticate
+     with and end the connect phase if we don't */
+  if(imapc->preauth ||
+     !Curl_sasl_can_authenticate(&imapc->sasl, conn)) {
     state(conn, IMAP_STOP);
     return result;
   }
@@ -707,18 +709,48 @@ static CURLcode imap_perform_fetch(struct connectdata 
*conn)
 static CURLcode imap_perform_append(struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
-  struct IMAP *imap = conn->data->req.protop;
+  struct Curl_easy *data = conn->data;
+  struct IMAP *imap = data->req.protop;
   char *mailbox;
 
   /* Check we have a mailbox */
   if(!imap->mailbox) {
-    failf(conn->data, "Cannot APPEND without a mailbox.");
+    failf(data, "Cannot APPEND without a mailbox.");
     return CURLE_URL_MALFORMAT;
   }
 
+  /* Prepare the mime data if some. */
+  if(data->set.mimepost.kind != MIMEKIND_NONE) {
+    /* Use the whole structure as data. */
+    data->set.mimepost.flags &= ~MIME_BODY_ONLY;
+
+    /* Add external headers and mime version. */
+    curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
+    result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
+                                       NULL, MIMESTRATEGY_MAIL);
+
+    if(!result)
+      if(!Curl_checkheaders(conn, "Mime-Version"))
+        result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
+                                      "Mime-Version: 1.0");
+
+    /* Make sure we will read the entire mime structure. */
+    if(!result)
+      result = Curl_mime_rewind(&data->set.mimepost);
+
+    if(result)
+      return result;
+
+    data->state.infilesize = Curl_mime_size(&data->set.mimepost);
+
+    /* Read from mime structure. */
+    data->state.fread_func = (curl_read_callback) Curl_mime_read;
+    data->state.in = (void *) &data->set.mimepost;
+  }
+
   /* Check we know the size of the upload */
-  if(conn->data->state.infilesize < 0) {
-    failf(conn->data, "Cannot APPEND with unknown input file size\n");
+  if(data->state.infilesize < 0) {
+    failf(data, "Cannot APPEND with unknown input file size\n");
     return CURLE_UPLOAD_FAILED;
   }
 
@@ -729,7 +761,7 @@ static CURLcode imap_perform_append(struct connectdata 
*conn)
 
   /* Send the APPEND command */
   result = imap_sendf(conn, "APPEND %s (\\Seen) {%" CURL_FORMAT_CURL_OFF_T "}",
-                      mailbox, conn->data->state.infilesize);
+                      mailbox, data->state.infilesize);
 
   free(mailbox);
 
@@ -789,19 +821,21 @@ static CURLcode imap_state_servergreet_resp(struct 
connectdata *conn,
                                             int imapcode,
                                             imapstate instate)
 {
-  CURLcode result = CURLE_OK;
   struct Curl_easy *data = conn->data;
-
   (void)instate; /* no use for this yet */
 
-  if(imapcode != 'O') {
+  if(imapcode == IMAP_RESP_PREAUTH) {
+    /* PREAUTH */
+    struct imap_conn *imapc = &conn->proto.imapc;
+    imapc->preauth = TRUE;
+    infof(data, "PREAUTH connection, already authenticated!\n");
+  }
+  else if(imapcode != IMAP_RESP_OK) {
     failf(data, "Got unexpected imap-server response");
-    result = CURLE_WEIRD_SERVER_REPLY;
+    return CURLE_WEIRD_SERVER_REPLY;
   }
-  else
-    result = imap_perform_capability(conn);
 
-  return result;
+  return imap_perform_capability(conn);
 }
 
 /* For CAPABILITY responses */
@@ -868,7 +902,7 @@ static CURLcode imap_state_capability_resp(struct 
connectdata *conn,
       line += wordlen;
     }
   }
-  else if(imapcode == 'O') {
+  else if(imapcode == IMAP_RESP_OK) {
     if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
       /* We don't have a SSL/TLS connection yet, but SSL is requested */
       if(imapc->tls_supported)
@@ -901,7 +935,7 @@ static CURLcode imap_state_starttls_resp(struct connectdata 
*conn,
 
   (void)instate; /* no use for this yet */
 
-  if(imapcode != 'O') {
+  if(imapcode != IMAP_RESP_OK) {
     if(data->set.use_ssl != CURLUSESSL_TRY) {
       failf(data, "STARTTLS denied");
       result = CURLE_USE_SSL_FAILED;
@@ -959,7 +993,7 @@ static CURLcode imap_state_login_resp(struct connectdata 
*conn,
 
   (void)instate; /* no use for this yet */
 
-  if(imapcode != 'O') {
+  if(imapcode != IMAP_RESP_OK) {
     failf(data, "Access denied. %c", imapcode);
     result = CURLE_LOGIN_DENIED;
   }
@@ -987,7 +1021,7 @@ static CURLcode imap_state_listsearch_resp(struct 
connectdata *conn,
     result = Curl_client_write(conn, CLIENTWRITE_BODY, line, len + 1);
     line[len] = '\0';
   }
-  else if(imapcode != 'O')
+  else if(imapcode != IMAP_RESP_OK)
     result = CURLE_QUOTE_ERROR; /* TODO: Fix error code */
   else
     /* End of DO phase */
@@ -1016,7 +1050,7 @@ static CURLcode imap_state_select_resp(struct connectdata 
*conn, int imapcode,
       imapc->mailbox_uidvalidity = strdup(tmp);
     }
   }
-  else if(imapcode == 'O') {
+  else if(imapcode == IMAP_RESP_OK) {
     /* Check if the UIDVALIDITY has been specified and matches */
     if(imap->uidvalidity && imapc->mailbox_uidvalidity &&
        strcmp(imap->uidvalidity, imapc->mailbox_uidvalidity)) {
@@ -1070,10 +1104,11 @@ static CURLcode imap_state_fetch_resp(struct 
connectdata *conn, int imapcode,
 
   if(*ptr == '{') {
     char *endptr;
-    size = curlx_strtoofft(ptr + 1, &endptr, 10);
-    if(endptr - ptr > 1 && endptr[0] == '}' &&
-       endptr[1] == '\r' && endptr[2] == '\0')
-      parsed = TRUE;
+    if(!curlx_strtoofft(ptr + 1, &endptr, 10, &size)) {
+      if(endptr - ptr > 1 && endptr[0] == '}' &&
+         endptr[1] == '\r' && endptr[2] == '\0')
+        parsed = TRUE;
+    }
   }
 
   if(parsed) {
@@ -1147,7 +1182,7 @@ static CURLcode imap_state_fetch_final_resp(struct 
connectdata *conn,
 
   (void)instate; /* No use for this yet */
 
-  if(imapcode != 'O')
+  if(imapcode != IMAP_RESP_OK)
     result = CURLE_WEIRD_SERVER_REPLY;
   else
     /* End of DONE phase */
@@ -1191,7 +1226,7 @@ static CURLcode imap_state_append_final_resp(struct 
connectdata *conn,
 
   (void)instate; /* No use for this yet */
 
-  if(imapcode != 'O')
+  if(imapcode != IMAP_RESP_OK)
     result = CURLE_UPLOAD_FAILED;
   else
     /* End of DONE phase */
@@ -1419,9 +1454,10 @@ static CURLcode imap_done(struct connectdata *conn, 
CURLcode status,
     result = status;         /* use the already set error code */
   }
   else if(!data->set.connect_only && !imap->custom &&
-          (imap->uid || data->set.upload)) {
+          (imap->uid || data->set.upload ||
+          data->set.mimepost.kind != MIMEKIND_NONE)) {
     /* Handle responses after FETCH or APPEND transfer has finished */
-    if(!data->set.upload)
+    if(!data->set.upload && data->set.mimepost.kind == MIMEKIND_NONE)
       state(conn, IMAP_FETCH_FINAL);
     else {
       /* End the APPEND command first by sending an empty line */
@@ -1491,7 +1527,7 @@ static CURLcode imap_perform(struct connectdata *conn, 
bool *connected,
     selected = TRUE;
 
   /* Start the first command in the DO phase */
-  if(conn->data->set.upload)
+  if(conn->data->set.upload || data->set.mimepost.kind != MIMEKIND_NONE)
     /* APPEND can be executed directly */
     result = imap_perform_append(conn);
   else if(imap->custom && (selected || !imap->mailbox))
@@ -1761,7 +1797,7 @@ static char *imap_atom(const char *str, bool escape_only)
     return strdup(str);
 
   /* Calculate the new string length */
-  newlen = strlen(str) + backsp_count + quote_count + (others_exists ? 2 : 0);
+  newlen = strlen(str) + backsp_count + quote_count + (escape_only ? 0 : 2);
 
   /* Allocate the new string */
   newstr = (char *) malloc((newlen + 1) * sizeof(char));
@@ -1770,7 +1806,7 @@ static char *imap_atom(const char *str, bool escape_only)
 
   /* Surround the string in quotes if necessary */
   p2 = newstr;
-  if(others_exists) {
+  if(!escape_only) {
     newstr[0] = '"';
     newstr[newlen - 1] = '"';
     p2++;
diff --git a/lib/imap.h b/lib/imap.h
index 5e0e228f5..9fc4ff5a3 100644
--- a/lib/imap.h
+++ b/lib/imap.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2009 - 2015, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2009 - 2017, 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,6 +71,7 @@ struct imap_conn {
   struct pingpong pp;
   imapstate state;            /* Always use imap.c:state() to change state! */
   bool ssldone;               /* Is connect() over SSL done? */
+  bool preauth;               /* Is this connection PREAUTH? */
   struct SASL sasl;           /* SASL-related parameters */
   unsigned int preftype;      /* Preferred authentication type */
   int cmdid;                  /* Last used command ID */
diff --git a/lib/inet_ntop.c b/lib/inet_ntop.c
index 22f08e84d..fb91a505d 100644
--- a/lib/inet_ntop.c
+++ b/lib/inet_ntop.c
@@ -141,7 +141,7 @@ static char *inet_ntop6 (const unsigned char *src, char 
*dst, size_t size)
      */
     if(i == 6 && best.base == 0 &&
         (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
-      if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp))) {
+      if(!inet_ntop4(src + 12, tp, sizeof(tmp) - (tp - tmp))) {
         errno = ENOSPC;
         return (NULL);
       }
diff --git a/lib/ldap.c b/lib/ldap.c
index 9b85a4815..4059d5d87 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -5,7 +5,7 @@
  *                | (__| |_| |  _ <| |___
  *                 \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -267,7 +267,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool 
*done)
   LDAPMessage *ldapmsg = NULL;
   LDAPMessage *entryIterator;
   int num = 0;
-  struct Curl_easy *data=conn->data;
+  struct Curl_easy *data = conn->data;
   int ldap_proto = LDAP_VERSION3;
   int ldap_ssl = 0;
   char *val_b64 = NULL;
diff --git a/lib/memdebug.c b/lib/memdebug.c
index 65b20e5d0..c12910ef6 100644
--- a/lib/memdebug.c
+++ b/lib/memdebug.c
@@ -170,7 +170,7 @@ void *curl_domalloc(size_t wantedsize, int line, const char 
*source)
     return NULL;
 
   /* alloc at least 64 bytes */
-  size = sizeof(struct memdebug)+wantedsize;
+  size = sizeof(struct memdebug) + wantedsize;
 
   mem = (Curl_cmalloc)(size);
   if(mem) {
@@ -225,9 +225,9 @@ char *curl_dostrdup(const char *str, int line, const char 
*source)
   if(countcheck("strdup", line, source))
     return NULL;
 
-  len=strlen(str)+1;
+  len = strlen(str) + 1;
 
-  mem=curl_domalloc(len, 0, NULL); /* NULL prevents logging */
+  mem = curl_domalloc(len, 0, NULL); /* NULL prevents logging */
   if(mem)
     memcpy(mem, str, len);
 
@@ -269,9 +269,9 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const 
char *source)
 void *curl_dorealloc(void *ptr, size_t wantedsize,
                      int line, const char *source)
 {
-  struct memdebug *mem=NULL;
+  struct memdebug *mem = NULL;
 
-  size_t size = sizeof(struct memdebug)+wantedsize;
+  size_t size = sizeof(struct memdebug) + wantedsize;
 
   DEBUGASSERT(wantedsize != 0);
 
@@ -407,7 +407,7 @@ void curl_mark_sclose(curl_socket_t sockfd, int line, const 
char *source)
 /* this is our own defined way to close sockets on *ALL* platforms */
 int curl_sclose(curl_socket_t sockfd, int line, const char *source)
 {
-  int res=sclose(sockfd);
+  int res = sclose(sockfd);
   curl_mark_sclose(sockfd, line, source);
   return res;
 }
@@ -415,7 +415,7 @@ int curl_sclose(curl_socket_t sockfd, int line, const char 
*source)
 FILE *curl_fopen(const char *file, const char *mode,
                  int line, const char *source)
 {
-  FILE *res=fopen(file, mode);
+  FILE *res = fopen(file, mode);
 
   if(source)
     curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
@@ -428,7 +428,7 @@ FILE *curl_fopen(const char *file, const char *mode,
 FILE *curl_fdopen(int filedes, const char *mode,
                   int line, const char *source)
 {
-  FILE *res=fdopen(filedes, mode);
+  FILE *res = fdopen(filedes, mode);
 
   if(source)
     curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
@@ -444,7 +444,7 @@ int curl_fclose(FILE *file, int line, const char *source)
 
   DEBUGASSERT(file != NULL);
 
-  res=fclose(file);
+  res = fclose(file);
 
   if(source)
     curl_memlog("FILE %s:%d fclose(%p)\n",
diff --git a/lib/mime.c b/lib/mime.c
new file mode 100644
index 000000000..0aa12d1eb
--- /dev/null
+++ b/lib/mime.c
@@ -0,0 +1,1860 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, 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"
+
+#include <gnurl/curl.h>
+
+#include "mime.h"
+#include "non-ascii.h"
+
+#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
+    !defined(CURL_DISABLE_IMAP)
+
+#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
+#include <libgen.h>
+#endif
+
+#include "rand.h"
+#include "slist.h"
+#include "strcase.h"
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#ifdef WIN32
+# ifndef R_OK
+#  define R_OK 4
+# endif
+#endif
+
+
+#define FILE_CONTENTTYPE_DEFAULT        "application/octet-stream"
+#define MULTIPART_CONTENTTYPE_DEFAULT   "multipart/mixed"
+#define DISPOSITION_DEFAULT             "attachment"
+
+#define READ_ERROR                      ((size_t) -1)
+
+/* Encoders. */
+static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
+                                curl_mimepart *part);
+static curl_off_t encoder_nop_size(curl_mimepart *part);
+static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof,
+                                curl_mimepart *part);
+static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
+                                curl_mimepart *part);
+static curl_off_t encoder_base64_size(curl_mimepart *part);
+static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
+                              curl_mimepart *part);
+static curl_off_t encoder_qp_size(curl_mimepart *part);
+
+static const mime_encoder encoders[] = {
+  {"binary", encoder_nop_read, encoder_nop_size},
+  {"8bit", encoder_nop_read, encoder_nop_size},
+  {"7bit", encoder_7bit_read, encoder_nop_size},
+  {"base64", encoder_base64_read, encoder_base64_size},
+  {"quoted-printable", encoder_qp_read, encoder_qp_size},
+  {ZERO_NULL, ZERO_NULL, ZERO_NULL}
+};
+
+/* Base64 encoding table */
+static const char base64[] =
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* Quoted-printable character class table.
+ *
+ * We cannot rely on ctype functions since quoted-printable input data
+ * is assumed to be ascii-compatible, even on non-ascii platforms. */
+#define QP_OK           1       /* Can be represented by itself. */
+#define QP_SP           2       /* Space or tab. */
+#define QP_CR           3       /* Carriage return. */
+#define QP_LF           4       /* Line-feed. */
+static const unsigned char qp_class[] = {
+ 0,     0,     0,     0,     0,     0,     0,     0,            /* 00 - 07 */
+ 0,     QP_SP, QP_LF, 0,     0,     QP_CR, 0,     0,            /* 08 - 0F */
+ 0,     0,     0,     0,     0,     0,     0,     0,            /* 10 - 17 */
+ 0,     0,     0,     0,     0,     0,     0,     0,            /* 18 - 1F */
+ QP_SP, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 20 - 27 */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 28 - 2F */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 30 - 37 */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0    , QP_OK, QP_OK,        /* 38 - 3F */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 40 - 47 */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 48 - 4F */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 50 - 57 */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 58 - 5F */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 60 - 67 */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 68 - 6F */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK,        /* 70 - 77 */
+ QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, QP_OK, 0,            /* 78 - 7F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* 80 - 8F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* 90 - 9F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* A0 - AF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* B0 - BF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* C0 - CF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* D0 - DF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                /* E0 - EF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0                 /* F0 - FF */
+};
+
+
+/* Binary --> hexadecimal ASCII table. */
+static const char aschex[] =
+  "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x41\x42\x43\x44\x45\x46";
+
+
+
+#ifndef __VMS
+#define filesize(name, stat_data) (stat_data.st_size)
+#define fopen_read fopen
+
+#else
+
+#include <fabdef.h>
+/*
+ * get_vms_file_size does what it takes to get the real size of the file
+ *
+ * For fixed files, find out the size of the EOF block and adjust.
+ *
+ * For all others, have to read the entire file in, discarding the contents.
+ * Most posted text files will be small, and binary files like zlib archives
+ * and CD/DVD images should be either a STREAM_LF format or a fixed format.
+ *
+ */
+curl_off_t VmsRealFileSize(const char *name,
+                           const struct_stat *stat_buf)
+{
+  char buffer[8192];
+  curl_off_t count;
+  int ret_stat;
+  FILE * file;
+
+  file = fopen(name, FOPEN_READTEXT); /* VMS */
+  if(file == NULL)
+    return 0;
+
+  count = 0;
+  ret_stat = 1;
+  while(ret_stat > 0) {
+    ret_stat = fread(buffer, 1, sizeof(buffer), file);
+    if(ret_stat != 0)
+      count += ret_stat;
+  }
+  fclose(file);
+
+  return count;
+}
+
+/*
+ *
+ *  VmsSpecialSize checks to see if the stat st_size can be trusted and
+ *  if not to call a routine to get the correct size.
+ *
+ */
+static curl_off_t VmsSpecialSize(const char *name,
+                                 const struct_stat *stat_buf)
+{
+  switch(stat_buf->st_fab_rfm) {
+  case FAB$C_VAR:
+  case FAB$C_VFC:
+    return VmsRealFileSize(name, stat_buf);
+    break;
+  default:
+    return stat_buf->st_size;
+  }
+}
+
+#define filesize(name, stat_data) VmsSpecialSize(name, &stat_data)
+
+/*
+ * vmsfopenread
+ *
+ * For upload to work as expected on VMS, different optional
+ * parameters must be added to the fopen command based on
+ * record format of the file.
+ *
+ */
+static FILE * vmsfopenread(const char *file, const char *mode)
+{
+  struct_stat statbuf;
+  int result;
+
+  result = stat(file, &statbuf);
+
+  switch(statbuf.st_fab_rfm) {
+  case FAB$C_VAR:
+  case FAB$C_VFC:
+  case FAB$C_STMCR:
+    return fopen(file, FOPEN_READTEXT); /* VMS */
+    break;
+  default:
+    return fopen(file, FOPEN_READTEXT, "rfm=stmlf", "ctx=stm");
+  }
+}
+
+#define fopen_read vmsfopenread
+#endif
+
+
+#ifndef HAVE_BASENAME
+/*
+  (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
+  Edition)
+
+  The basename() function shall take the pathname pointed to by path and
+  return a pointer to the final component of the pathname, deleting any
+  trailing '/' characters.
+
+  If the string pointed to by path consists entirely of the '/' character,
+  basename() shall return a pointer to the string "/". If the string pointed
+  to by path is exactly "//", it is implementation-defined whether '/' or "//"
+  is returned.
+
+  If path is a null pointer or points to an empty string, basename() shall
+  return a pointer to the string ".".
+
+  The basename() function may modify the string pointed to by path, and may
+  return a pointer to static storage that may then be overwritten by a
+  subsequent call to basename().
+
+  The basename() function need not be reentrant. A function that is not
+  required to be reentrant is not required to be thread-safe.
+
+*/
+static char *Curl_basename(char *path)
+{
+  /* Ignore all the details above for now and make a quick and simple
+     implementaion here */
+  char *s1;
+  char *s2;
+
+  s1 = strrchr(path, '/');
+  s2 = strrchr(path, '\\');
+
+  if(s1 && s2) {
+    path = (s1 > s2? s1 : s2) + 1;
+  }
+  else if(s1)
+    path = s1 + 1;
+  else if(s2)
+    path = s2 + 1;
+
+  return path;
+}
+
+#define basename(x)  Curl_basename((x))
+#endif
+
+
+/* Set readback state. */
+static void mimesetstate(mime_state *state, enum mimestate tok, void *ptr)
+{
+  state->state = tok;
+  state->ptr = ptr;
+  state->offset = 0;
+}
+
+
+/* Escape header string into allocated memory. */
+static char *escape_string(const char *src)
+{
+  size_t bytecount = 0;
+  size_t i;
+  char *dst;
+
+  for(i = 0; src[i]; i++)
+    if(src[i] == '"' || src[i] == '\\')
+      bytecount++;
+
+  bytecount += i;
+  dst = malloc(bytecount + 1);
+  if(!dst)
+    return NULL;
+
+  for(i = 0; *src; src++) {
+    if(*src == '"' || *src == '\\')
+      dst[i++] = '\\';
+    dst[i++] = *src;
+  }
+
+  dst[i] = '\0';
+  return dst;
+}
+
+/* Check if header matches. */
+static char *match_header(struct curl_slist *hdr, const char *lbl, size_t len)
+{
+  char *value = NULL;
+
+  if(strncasecompare(hdr->data, lbl, len) && hdr->data[len] == ':')
+    for(value = hdr->data + len + 1; *value == ' '; value++)
+      ;
+  return value;
+}
+
+/* Get a header from an slist. */
+static char *search_header(struct curl_slist *hdrlist, const char *hdr)
+{
+  size_t len = strlen(hdr);
+  char *value = NULL;
+
+  for(; !value && hdrlist; hdrlist = hdrlist->next)
+    value = match_header(hdrlist, hdr, len);
+
+  return value;
+}
+
+static char *strippath(const char *fullfile)
+{
+  char *filename;
+  char *base;
+  filename = strdup(fullfile); /* duplicate since basename() may ruin the
+                                  buffer it works on */
+  if(!filename)
+    return NULL;
+  base = strdup(basename(filename));
+
+  free(filename); /* free temporary buffer */
+
+  return base; /* returns an allocated string or NULL ! */
+}
+
+/* Initialize data encoder state. */
+static void cleanup_encoder_state(mime_encoder_state *p)
+{
+  p->pos = 0;
+  p->bufbeg = 0;
+  p->bufend = 0;
+}
+
+
+/* Dummy encoder. This is used for 8bit and binary content encodings. */
+static size_t encoder_nop_read(char *buffer, size_t size, bool ateof,
+                               curl_mimepart *part)
+{
+  mime_encoder_state *st = &part->encstate;
+  size_t insize = st->bufend - st->bufbeg;
+
+  (void) ateof;
+
+  if(size > insize)
+    size = insize;
+  if(size)
+    memcpy(buffer, st->buf, size);
+  st->bufbeg += size;
+  return size;
+}
+
+static curl_off_t encoder_nop_size(curl_mimepart *part)
+{
+  return part->datasize;
+}
+
+
+/* 7bit encoder: the encoder is just a data validity check. */
+static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof,
+                                curl_mimepart *part)
+{
+  mime_encoder_state *st = &part->encstate;
+  size_t cursize = st->bufend - st->bufbeg;
+
+  (void) ateof;
+
+  if(size > cursize)
+    size = cursize;
+
+  for(cursize = 0; cursize < size; cursize++) {
+    *buffer = st->buf[st->bufbeg];
+    if(*buffer++ & 0x80)
+      return cursize? cursize: READ_ERROR;
+    st->bufbeg++;
+  }
+
+  return cursize;
+}
+
+
+/* Base64 content encoder. */
+static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
+                                curl_mimepart *part)
+{
+  mime_encoder_state *st = &part->encstate;
+  size_t cursize = 0;
+  int i;
+  char *ptr = buffer;
+
+  while(st->bufbeg < st->bufend) {
+    /* Line full ? */
+    if(st->pos >= MAX_ENCODED_LINE_LENGTH - 4) {
+      /* Yes, we need 2 characters for CRLF. */
+      if(size < 2)
+        break;
+      *ptr++ = '\r';
+      *ptr++ = '\n';
+      st->pos = 0;
+      cursize += 2;
+      size -= 2;
+    }
+
+    /* Be sure there is enough space and input data for a base64 group. */
+    if(size < 4 || st->bufend - st->bufbeg < 3)
+      break;
+
+    /* Encode three bytes a four characters. */
+    i = st->buf[st->bufbeg++] & 0xFF;
+    i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
+    i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF);
+    *ptr++ = base64[(i >> 18) & 0x3F];
+    *ptr++ = base64[(i >> 12) & 0x3F];
+    *ptr++ = base64[(i >> 6) & 0x3F];
+    *ptr++ = base64[i & 0x3F];
+    cursize += 4;
+    st->pos += 4;
+    size -= 4;
+  }
+
+  /* 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++;
+      }
+      cursize += 4;
+      st->pos += 4;
+      break;
+    }
+  }
+
+#ifdef CURL_DOES_CONVERSIONS
+  /* This is now textual data, Convert character codes. */
+  if(part->easy && cursize) {
+    CURLcode result = Curl_convert_to_network(part->easy, buffer, cursize);
+    if(result)
+      return READ_ERROR;
+  }
+#endif
+
+  return cursize;
+}
+
+static curl_off_t encoder_base64_size(curl_mimepart *part)
+{
+  curl_off_t size = part->datasize;
+
+  if(size <= 0)
+    return size;    /* Unknown size or no data. */
+
+  /* Compute base64 character count. */
+  size = 4 * (1 + (size - 1) / 3);
+
+  /* Effective character count must include CRLFs. */
+  return size + 2 * ((size - 1) / MAX_ENCODED_LINE_LENGTH);
+}
+
+
+/* Quoted-printable lookahead.
+ *
+ * Check if a CRLF or end of data is in input buffer at current position + n.
+ * Return -1 if more data needed, 1 if CRLF or end of data, else 0.
+ */
+static int qp_lookahead_eol(mime_encoder_state *st, int ateof, size_t n)
+{
+  n += st->bufbeg;
+  if(n >= st->bufend && ateof)
+    return 1;
+  if(n + 2 > st->bufend)
+    return ateof? 0: -1;
+  if(qp_class[st->buf[n] & 0xFF] == QP_CR &&
+     qp_class[st->buf[n + 1] & 0xFF] == QP_LF)
+    return 1;
+  return 0;
+}
+
+/* Quoted-printable encoder. */
+static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
+                              curl_mimepart *part)
+{
+  mime_encoder_state *st = &part->encstate;
+  char *ptr = buffer;
+  size_t cursize = 0;
+  int i;
+  size_t len;
+  size_t consumed;
+  int softlinebreak;
+  char buf[4];
+
+  /* On all platforms, input is supposed to be ASCII compatible: for this
+     reason, we use hexadecimal ASCII codes in this function rather than
+     character constants that can be interpreted as non-ascii on some
+     platforms. Preserve ASCII encoding on output too. */
+  while(st->bufbeg < st->bufend) {
+    len = 1;
+    consumed = 1;
+    i = st->buf[st->bufbeg];
+    buf[0] = (char) i;
+    buf[1] = aschex[(i >> 4) & 0xF];
+    buf[2] = aschex[i & 0xF];
+
+    switch(qp_class[st->buf[st->bufbeg] & 0xFF]) {
+    case QP_OK:          /* Not a special character. */
+      break;
+    case QP_SP:          /* Space or tab. */
+      /* Spacing must be escaped if followed by CRLF. */
+      switch(qp_lookahead_eol(st, ateof, 1)) {
+      case -1:          /* More input data needed. */
+        return cursize;
+      case 0:           /* No encoding needed. */
+        break;
+      default:          /* CRLF after space or tab. */
+        buf[0] = '\x3D';    /* '=' */
+        len = 3;
+        break;
+      }
+      break;
+    case QP_CR:         /* Carriage return. */
+      /* If followed by a line-feed, output the CRLF pair.
+         Else escape it. */
+      switch(qp_lookahead_eol(st, ateof, 0)) {
+      case -1:          /* Need more data. */
+        return cursize;
+      case 1:           /* CRLF found. */
+        buf[len++] = '\x0A';    /* Append '\n'. */
+        consumed = 2;
+        break;
+      default:          /* Not followed by LF: escape. */
+        buf[0] = '\x3D';    /* '=' */
+        len = 3;
+        break;
+      }
+      break;
+    default:            /* Character must be escaped. */
+      buf[0] = '\x3D';    /* '=' */
+      len = 3;
+      break;
+    }
+
+    /* Be sure the encoded character fits within maximum line length. */
+    if(buf[len - 1] != '\x0A') {    /* '\n' */
+      softlinebreak = st->pos + len > MAX_ENCODED_LINE_LENGTH;
+      if(!softlinebreak && st->pos + len == MAX_ENCODED_LINE_LENGTH) {
+        /* We may use the current line only if end of data or followed by
+           a CRLF. */
+        switch(qp_lookahead_eol(st, ateof, consumed)) {
+        case -1:        /* Need more data. */
+          return cursize;
+          break;
+        case 0:         /* Not followed by a CRLF. */
+          softlinebreak = 1;
+          break;
+        }
+      }
+      if(softlinebreak) {
+        strcpy(buf, "\x3D\x0D\x0A");    /* "=\r\n" */
+        len = 3;
+        consumed = 0;
+      }
+    }
+
+    /* If the output buffer would overflow, do not store. */
+    if(len > size)
+      break;
+
+    /* Append to output buffer. */
+    memcpy(ptr, buf, len);
+    cursize += len;
+    ptr += len;
+    size -= len;
+    st->pos += len;
+    if(buf[len - 1] == '\x0A')    /* '\n' */
+      st->pos = 0;
+    st->bufbeg += consumed;
+  }
+
+  return cursize;
+}
+
+static curl_off_t encoder_qp_size(curl_mimepart *part)
+{
+  /* Determining the size can only be done by reading the data: unless the
+     data size is 0, we return it as unknown (-1). */
+  return part->datasize? -1: 0;
+}
+
+
+/* In-memory data callbacks. */
+/* Argument is a pointer to the mime part. */
+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;
+
+  (void) size;   /* Always 1.*/
+
+  if(sz > nitems)
+    sz = nitems;
+
+  if(sz)
+    memcpy(buffer, (char *) part->data, sz);
+
+  part->state.offset += sz;
+  return sz;
+}
+
+static int mime_mem_seek(void *instream, curl_off_t offset, int whence)
+{
+  curl_mimepart *part = (curl_mimepart *) instream;
+
+  switch(whence) {
+  case SEEK_CUR:
+    offset += part->state.offset;
+    break;
+  case SEEK_END:
+    offset += part->datasize;
+    break;
+  }
+
+  if(offset < 0 || offset > part->datasize)
+    return CURL_SEEKFUNC_FAIL;
+
+  part->state.offset = (size_t) offset;
+  return CURL_SEEKFUNC_OK;
+}
+
+static void mime_mem_free(void *ptr)
+{
+  Curl_safefree(((curl_mimepart *) ptr)->data);
+}
+
+
+/* Named file callbacks. */
+/* Argument is a pointer to the mime part. */
+static int mime_open_file(curl_mimepart * part)
+{
+  /* Open a MIMEKIND_FILE part. */
+
+  if(part->fp)
+    return 0;
+  part->fp = fopen_read(part->data, "rb");
+  return part->fp? 0: -1;
+}
+
+static size_t mime_file_read(char *buffer, size_t size, size_t nitems,
+                             void *instream)
+{
+  curl_mimepart *part = (curl_mimepart *) instream;
+
+  if(mime_open_file(part))
+    return READ_ERROR;
+
+  return fread(buffer, size, nitems, part->fp);
+}
+
+static int mime_file_seek(void *instream, curl_off_t offset, int whence)
+{
+  curl_mimepart *part = (curl_mimepart *) instream;
+
+  if(whence == SEEK_SET && !offset && !part->fp)
+    return CURL_SEEKFUNC_OK;   /* Not open: implicitly already at BOF. */
+
+  if(mime_open_file(part))
+    return CURL_SEEKFUNC_FAIL;
+
+  return fseek(part->fp, (long) offset, whence)?
+               CURL_SEEKFUNC_CANTSEEK: CURL_SEEKFUNC_OK;
+}
+
+static void mime_file_free(void *ptr)
+{
+  curl_mimepart *part = (curl_mimepart *) ptr;
+
+  if(part->fp) {
+    fclose(part->fp);
+    part->fp = NULL;
+  }
+  Curl_safefree(part->data);
+  part->data = NULL;
+}
+
+
+/* Subparts callbacks. */
+/* Argument is a pointer to the mime structure. */
+
+/* Readback a byte string segment. */
+static size_t readback_bytes(mime_state *state,
+                             char *buffer, size_t bufsize,
+                             const char *bytes, size_t numbytes,
+                             const char *trail)
+{
+  size_t sz;
+
+  sz = numbytes - state->offset;
+
+  if(numbytes > state->offset) {
+    sz = numbytes - state->offset;
+    bytes += state->offset;
+  }
+  else {
+    size_t tsz = strlen(trail);
+
+    sz = state->offset - numbytes;
+    if(sz >= tsz)
+      return 0;
+    bytes = trail + sz;
+    sz = tsz - sz;
+  }
+
+  if(sz > bufsize)
+    sz = bufsize;
+
+  memcpy(buffer, bytes, sz);
+  state->offset += sz;
+  return sz;
+}
+
+/* Read a non-encoded part content. */
+static size_t read_part_content(curl_mimepart *part,
+                                char *buffer, size_t bufsize)
+{
+  size_t sz = 0;
+
+  if(part->readfunc)
+    sz = part->readfunc(buffer, 1, bufsize, part->arg);
+  return sz;
+}
+
+/* Read and encode part content. */
+static size_t read_encoded_part_content(curl_mimepart *part,
+                                        char *buffer, size_t bufsize)
+{
+  mime_encoder_state *st = &part->encstate;
+  size_t cursize = 0;
+  size_t sz;
+  bool ateof = FALSE;
+
+  while(bufsize) {
+    if(st->bufbeg < st->bufend || ateof) {
+      /* Encode buffered data. */
+      sz = part->encoder->encodefunc(buffer, bufsize, ateof, part);
+      switch(sz) {
+      case 0:
+        if(ateof)
+          return cursize;
+        break;
+      case CURL_READFUNC_ABORT:
+      case CURL_READFUNC_PAUSE:
+      case READ_ERROR:
+        return cursize? cursize: sz;
+      default:
+        cursize += sz;
+        buffer += sz;
+        bufsize -= sz;
+        continue;
+      }
+    }
+
+    /* We need more data in input buffer. */
+    if(st->bufbeg) {
+      size_t len = st->bufend - st->bufbeg;
+
+      if(len)
+        memmove(st->buf, st->buf + st->bufbeg, len);
+      st->bufbeg = 0;
+      st->bufend = len;
+    }
+    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);
+    switch(sz) {
+    case 0:
+      ateof = TRUE;
+      break;
+    case CURL_READFUNC_ABORT:
+    case CURL_READFUNC_PAUSE:
+    case READ_ERROR:
+      return cursize? cursize: sz;
+    default:
+      st->bufend += sz;
+      break;
+    }
+  }
+
+  return cursize;
+}
+
+/* Readback a mime part. */
+static size_t readback_part(curl_mimepart *part,
+                            char *buffer, size_t bufsize)
+{
+  size_t cursize = 0;
+  size_t sz;
+  struct curl_slist *hdr;
+#ifdef CURL_DOES_CONVERSIONS
+  char *convbuf = buffer;
+#endif
+
+  /* Readback from part. */
+
+  while(bufsize) {
+    sz = 0;
+    hdr = (struct curl_slist *) part->state.ptr;
+    switch(part->state.state) {
+    case MIMESTATE_BEGIN:
+      mimesetstate(&part->state, part->flags & MIME_BODY_ONLY? MIMESTATE_BODY:
+                                 MIMESTATE_CURLHEADERS, part->curlheaders);
+      break;
+    case MIMESTATE_USERHEADERS:
+      if(!hdr) {
+        mimesetstate(&part->state, MIMESTATE_EOH, NULL);
+        break;
+      }
+      if(match_header(hdr, "Content-Type", 12)) {
+        mimesetstate(&part->state, MIMESTATE_USERHEADERS, hdr->next);
+        break;
+      }
+      /* FALLTHROUGH */
+    case MIMESTATE_CURLHEADERS:
+      if(!hdr)
+        mimesetstate(&part->state, MIMESTATE_USERHEADERS, part->userheaders);
+      else {
+        sz = readback_bytes(&part->state, buffer, bufsize,
+                            hdr->data, strlen(hdr->data), "\r\n");
+        if(!sz)
+          mimesetstate(&part->state, part->state.state, hdr->next);
+      }
+      break;
+    case MIMESTATE_EOH:
+      sz = readback_bytes(&part->state, buffer, bufsize, "\r\n", 2, "");
+      if(!sz)
+        mimesetstate(&part->state, MIMESTATE_BODY, NULL);
+      break;
+    case MIMESTATE_BODY:
+#ifdef CURL_DOES_CONVERSIONS
+      if(part->easy && convbuf < buffer) {
+        CURLcode result = Curl_convert_to_network(part->easy, convbuf,
+                                                  buffer - convbuf);
+        if(result)
+          return READ_ERROR;
+        convbuf = buffer;
+      }
+#endif
+      cleanup_encoder_state(&part->encstate);
+      mimesetstate(&part->state, MIMESTATE_CONTENT, NULL);
+      break;
+    case MIMESTATE_CONTENT:
+      if(part->encoder)
+        sz = read_encoded_part_content(part, buffer, bufsize);
+      else
+        sz = read_part_content(part, buffer, bufsize);
+      switch(sz) {
+      case 0:
+        mimesetstate(&part->state, MIMESTATE_END, NULL);
+        /* Try sparing open file descriptors. */
+        if(part->kind == MIMEKIND_FILE && part->fp) {
+          fclose(part->fp);
+          part->fp = NULL;
+        }
+        /* FALLTHROUGH */
+      case CURL_READFUNC_ABORT:
+      case CURL_READFUNC_PAUSE:
+      case READ_ERROR:
+        return cursize? cursize: sz;
+      }
+      break;
+    case MIMESTATE_END:
+      return cursize;
+    default:
+      break;    /* Other values not in part state. */
+    }
+
+    /* Bump buffer and counters according to read size. */
+    cursize += sz;
+    buffer += sz;
+    bufsize -= sz;
+  }
+
+#ifdef CURL_DOES_CONVERSIONS
+      if(part->easy && convbuf < buffer &&
+         part->state.state < MIMESTATE_BODY) {
+        CURLcode result = Curl_convert_to_network(part->easy, convbuf,
+                                                  buffer - convbuf);
+        if(result)
+          return READ_ERROR;
+      }
+#endif
+
+  return cursize;
+}
+
+/* Readback from mime. */
+static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems,
+                                 void *instream)
+{
+  curl_mime *mime = (curl_mime *) instream;
+  size_t cursize = 0;
+  size_t sz;
+  curl_mimepart *part;
+#ifdef CURL_DOES_CONVERSIONS
+  char *convbuf = buffer;
+#endif
+
+  (void) size;   /* Always 1. */
+
+  while(nitems) {
+    sz = 0;
+    part = mime->state.ptr;
+    switch(mime->state.state) {
+    case MIMESTATE_BEGIN:
+    case MIMESTATE_BODY:
+#ifdef CURL_DOES_CONVERSIONS
+      convbuf = buffer;
+#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
+         by skipping the leading CRLF in boundary. */
+      mime->state.offset += 2;
+      break;
+    case MIMESTATE_BOUNDARY1:
+      sz = readback_bytes(&mime->state, buffer, nitems, "\r\n--", 4, "");
+      if(!sz)
+        mimesetstate(&mime->state, MIMESTATE_BOUNDARY2, part);
+      break;
+    case MIMESTATE_BOUNDARY2:
+      sz = readback_bytes(&mime->state, buffer, nitems, mime->boundary,
+                          strlen(mime->boundary), part? "\r\n": "--\r\n");
+      if(!sz) {
+#ifdef CURL_DOES_CONVERSIONS
+        if(mime->easy && convbuf < buffer) {
+          CURLcode result = Curl_convert_to_network(mime->easy, convbuf,
+                                                    buffer - convbuf);
+          if(result)
+            return READ_ERROR;
+          convbuf = buffer;
+        }
+#endif
+        mimesetstate(&mime->state, MIMESTATE_CONTENT, part);
+      }
+      break;
+    case MIMESTATE_CONTENT:
+      if(!part) {
+        mimesetstate(&mime->state, MIMESTATE_END, NULL);
+        break;
+      }
+      sz = readback_part(part, buffer, nitems);
+      switch(sz) {
+      case CURL_READFUNC_ABORT:
+      case CURL_READFUNC_PAUSE:
+      case READ_ERROR:
+        return cursize? cursize: sz;
+      case 0:
+#ifdef CURL_DOES_CONVERSIONS
+        convbuf = buffer;
+#endif
+        mimesetstate(&mime->state, MIMESTATE_BOUNDARY1, part->nextpart);
+        break;
+      }
+      break;
+    case MIMESTATE_END:
+      return cursize;
+    default:
+      break;    /* other values not used in mime state. */
+    }
+
+    /* Bump buffer and counters according to read size. */
+    cursize += sz;
+    buffer += sz;
+    nitems -= sz;
+  }
+
+#ifdef CURL_DOES_CONVERSIONS
+      if(mime->easy && convbuf < buffer &&
+         mime->state.state <= MIMESTATE_CONTENT) {
+        CURLcode result = Curl_convert_to_network(mime->easy, convbuf,
+                                                  buffer - convbuf);
+        if(result)
+          return READ_ERROR;
+      }
+#endif
+
+  return cursize;
+}
+
+static int mime_part_rewind(curl_mimepart *part)
+{
+  int res = CURL_SEEKFUNC_OK;
+  enum mimestate targetstate = MIMESTATE_BEGIN;
+
+  if(part->flags & MIME_BODY_ONLY)
+    targetstate = MIMESTATE_BODY;
+  cleanup_encoder_state(&part->encstate);
+  if(part->state.state > targetstate) {
+    res = CURL_SEEKFUNC_CANTSEEK;
+    if(part->seekfunc) {
+      res = part->seekfunc(part->arg, (curl_off_t) 0, SEEK_SET);
+      switch(res) {
+      case CURL_SEEKFUNC_OK:
+      case CURL_SEEKFUNC_FAIL:
+      case CURL_SEEKFUNC_CANTSEEK:
+        break;
+      case -1:    /* For fseek() error. */
+        res = CURL_SEEKFUNC_CANTSEEK;
+        break;
+      default:
+        res = CURL_SEEKFUNC_FAIL;
+        break;
+      }
+    }
+  }
+
+  if(res == CURL_SEEKFUNC_OK)
+    mimesetstate(&part->state, targetstate, NULL);
+
+  return res;
+}
+
+static int mime_subparts_seek(void *instream, curl_off_t offset, int whence)
+{
+  curl_mime *mime = (curl_mime *) instream;
+  curl_mimepart *part;
+  int result = CURL_SEEKFUNC_OK;
+  int res;
+
+  if(whence != SEEK_SET || offset)
+    return CURL_SEEKFUNC_CANTSEEK;    /* Only support full rewind. */
+
+  if(mime->state.state == MIMESTATE_BEGIN)
+   return CURL_SEEKFUNC_OK;           /* Already rewound. */
+
+  for(part = mime->firstpart; part; part = part->nextpart) {
+    res = mime_part_rewind(part);
+    if(res != CURL_SEEKFUNC_OK)
+      result = res;
+  }
+
+  if(result == CURL_SEEKFUNC_OK)
+    mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL);
+
+  return result;
+}
+
+static void mime_subparts_free(void *ptr)
+{
+  curl_mime *mime = (curl_mime *) ptr;
+  curl_mime_free(mime);
+}
+
+
+/* Release part content. */
+static void cleanup_part_content(curl_mimepart *part)
+{
+  if(part->freefunc)
+    part->freefunc(part->arg);
+
+  part->readfunc = NULL;
+  part->seekfunc = NULL;
+  part->freefunc = NULL;
+  part->arg = (void *) part;          /* Defaults to part itself. */
+  part->data = NULL;
+  part->fp = NULL;
+  part->datasize = (curl_off_t) 0;    /* No size yet. */
+  part->encoder = NULL;
+  cleanup_encoder_state(&part->encstate);
+  part->kind = MIMEKIND_NONE;
+}
+
+void Curl_mime_cleanpart(curl_mimepart *part)
+{
+  cleanup_part_content(part);
+  curl_slist_free_all(part->curlheaders);
+  if(part->flags & MIME_USERHEADERS_OWNER)
+    curl_slist_free_all(part->userheaders);
+  Curl_safefree(part->mimetype);
+  Curl_safefree(part->name);
+  Curl_safefree(part->filename);
+  Curl_mime_initpart(part, part->easy);
+}
+
+/* Recursively delete a mime handle and its parts. */
+void curl_mime_free(curl_mime *mime)
+{
+  curl_mimepart *part;
+
+  if(mime) {
+    while(mime->firstpart) {
+      part = mime->firstpart;
+      mime->firstpart = part->nextpart;
+      Curl_mime_cleanpart(part);
+      free(part);
+    }
+
+    free(mime->boundary);
+    free(mime);
+  }
+}
+
+/*
+ * Mime build functions.
+ */
+
+/* Create a mime handle. */
+curl_mime *curl_mime_init(struct Curl_easy *easy)
+{
+  curl_mime *mime;
+
+  mime = (curl_mime *) malloc(sizeof *mime);
+
+  if(mime) {
+    mime->easy = easy;
+    mime->parent = NULL;
+    mime->firstpart = NULL;
+    mime->lastpart = NULL;
+
+    /* Get a part boundary. */
+    mime->boundary = malloc(24 + MIME_RAND_BOUNDARY_CHARS + 1);
+    if(!mime->boundary) {
+      free(mime);
+      return NULL;
+    }
+
+    memset(mime->boundary, '-', 24);
+    Curl_rand_hex(easy, (unsigned char *) mime->boundary + 24,
+                  MIME_RAND_BOUNDARY_CHARS + 1);
+    mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL);
+  }
+
+  return mime;
+}
+
+/* Initialize a mime part. */
+void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
+{
+  memset((char *) part, 0, sizeof *part);
+  part->easy = easy;
+  mimesetstate(&part->state, MIMESTATE_BEGIN, NULL);
+}
+
+/* Create a mime part and append it to a mime handle's part list. */
+curl_mimepart *curl_mime_addpart(curl_mime *mime)
+{
+  curl_mimepart *part;
+
+  if(!mime)
+    return NULL;
+
+  part = (curl_mimepart *) malloc(sizeof *part);
+
+  if(part) {
+    Curl_mime_initpart(part, mime->easy);
+    part->parent = mime;
+
+    if(mime->lastpart)
+      mime->lastpart->nextpart = part;
+    else
+      mime->firstpart = part;
+
+    mime->lastpart = part;
+  }
+
+  return part;
+}
+
+/* Set mime part name. */
+CURLcode curl_mime_name(curl_mimepart *part, const char *name)
+{
+  if(!part)
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  Curl_safefree(part->name);
+  part->name = NULL;
+
+  if(name) {
+    part->name = strdup(name);
+    if(!part->name)
+      return CURLE_OUT_OF_MEMORY;
+  }
+
+  return CURLE_OK;
+}
+
+/* Set mime part remote file name. */
+CURLcode curl_mime_filename(curl_mimepart *part, const char *filename)
+{
+  if(!part)
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  Curl_safefree(part->filename);
+  part->filename = NULL;
+
+  if(filename) {
+    part->filename = strdup(filename);
+    if(!part->filename)
+      return CURLE_OUT_OF_MEMORY;
+  }
+
+  return CURLE_OK;
+}
+
+/* Set mime part content from memory data. */
+CURLcode curl_mime_data(curl_mimepart *part,
+                        const char *data, size_t datasize)
+{
+  if(!part)
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  cleanup_part_content(part);
+
+  if(data) {
+    if(datasize == CURL_ZERO_TERMINATED)
+      datasize = strlen(data);
+
+    part->data = malloc(datasize + 1);
+    if(!part->data)
+      return CURLE_OUT_OF_MEMORY;
+
+    part->datasize = datasize;
+
+    if(datasize)
+      memcpy(part->data, data, datasize);
+    part->data[datasize] = '\0';    /* Set a nul terminator as sentinel. */
+
+    part->readfunc = mime_mem_read;
+    part->seekfunc = mime_mem_seek;
+    part->freefunc = mime_mem_free;
+    part->kind = MIMEKIND_DATA;
+  }
+
+  return CURLE_OK;
+}
+
+/* Set mime part content from named local file. */
+CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
+{
+  CURLcode result = CURLE_OK;
+  char *base;
+
+  if(!part)
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  cleanup_part_content(part);
+
+  if(filename) {
+    struct_stat sbuf;
+
+    if(stat(filename, &sbuf) || access(filename, R_OK))
+      result = CURLE_READ_ERROR;
+
+    part->data = strdup(filename);
+    if(!part->data)
+      result = CURLE_OUT_OF_MEMORY;
+
+    part->datasize = -1;
+    if(!result && S_ISREG(sbuf.st_mode)) {
+      part->datasize = filesize(filename, sbuf);
+      part->seekfunc = mime_file_seek;
+    }
+
+    part->readfunc = mime_file_read;
+    part->freefunc = mime_file_free;
+    part->kind = MIMEKIND_FILE;
+
+    /* As a side effect, set the filename to the current file's base name.
+       It is possible to withdraw this by explicitly calling
+       curl_mime_filename() with a NULL filename argument after the current
+       call. */
+    base = strippath(filename);
+    if(!base)
+      result = CURLE_OUT_OF_MEMORY;
+    else {
+      CURLcode res = curl_mime_filename(part, base);
+
+      if(res)
+        result = res;
+      free(base);
+    }
+  }
+  return result;
+}
+
+/* Set mime part type. */
+CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype)
+{
+  if(!part)
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  Curl_safefree(part->mimetype);
+  part->mimetype = NULL;
+
+  if(mimetype) {
+    part->mimetype = strdup(mimetype);
+    if(!part->mimetype)
+      return CURLE_OUT_OF_MEMORY;
+  }
+
+  return CURLE_OK;
+}
+
+/* Set mime data transfer encoder. */
+CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding)
+{
+  CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
+  const mime_encoder *mep;
+
+  if(!part)
+    return result;
+
+  part->encoder = NULL;
+
+  if(!encoding)
+    return CURLE_OK;    /* Removing current encoder. */
+
+  for(mep = encoders; mep->name; mep++)
+    if(strcasecompare(encoding, mep->name)) {
+      part->encoder = mep;
+      result = CURLE_OK;
+    }
+
+  return result;
+}
+
+/* Set mime part headers. */
+CURLcode curl_mime_headers(curl_mimepart *part,
+                           struct curl_slist *headers, int take_ownership)
+{
+  if(!part)
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  if(part->flags & MIME_USERHEADERS_OWNER) {
+    curl_slist_free_all(part->userheaders);
+    part->flags &= ~MIME_USERHEADERS_OWNER;
+  }
+  part->userheaders = headers;
+  if(headers && take_ownership)
+    part->flags |= MIME_USERHEADERS_OWNER;
+  return CURLE_OK;
+}
+
+/* Set mime part content from callback. */
+CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize,
+                           curl_read_callback readfunc,
+                           curl_seek_callback seekfunc,
+                           curl_free_callback freefunc, void *arg)
+{
+  if(!part)
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  cleanup_part_content(part);
+
+  if(readfunc) {
+    part->readfunc = readfunc;
+    part->seekfunc = seekfunc;
+    part->freefunc = freefunc;
+    part->arg = arg;
+    part->datasize = datasize;
+    part->kind = MIMEKIND_CALLBACK;
+  }
+
+  return CURLE_OK;
+}
+
+/* Set mime part content from subparts. */
+CURLcode curl_mime_subparts(curl_mimepart *part,
+                            curl_mime *subparts)
+{
+  if(!part)
+    return CURLE_BAD_FUNCTION_ARGUMENT;
+
+  /* Accept setting twice the same subparts. */
+  if(part->kind == MIMEKIND_MULTIPART && part->arg == subparts)
+    return CURLE_OK;
+
+  cleanup_part_content(part);
+
+  if(subparts) {
+    /* Must belong to the same data handle. */
+    if(part->easy && subparts->easy && part->easy != subparts->easy)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+
+    /* Should not have been attached already. */
+    if(subparts->parent)
+      return CURLE_BAD_FUNCTION_ARGUMENT;
+
+    subparts->parent = part;
+    part->readfunc = mime_subparts_read;
+    part->seekfunc = mime_subparts_seek;
+    part->freefunc = mime_subparts_free;
+    part->arg = subparts;
+    part->datasize = -1;
+    part->kind = MIMEKIND_MULTIPART;
+  }
+
+  return CURLE_OK;
+}
+
+
+/* Readback from top mime. */
+/* Argument is the dummy top part. */
+size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
+{
+  curl_mimepart *part = (curl_mimepart *) instream;
+
+  (void) size;   /* Always 1. */
+  return readback_part(part, buffer, nitems);
+}
+
+/* Rewind mime stream. */
+CURLcode Curl_mime_rewind(curl_mimepart *part)
+{
+  return mime_part_rewind(part) == CURL_SEEKFUNC_OK?
+         CURLE_OK: CURLE_SEND_FAIL_REWIND;
+}
+
+/* Compute header list size. */
+static size_t slist_size(struct curl_slist *s,
+                         size_t overhead, const char *skip)
+{
+  size_t size = 0;
+  size_t skiplen = skip? strlen(skip): 0;
+
+  for(; s; s = s->next)
+    if(!skip || !match_header(s, skip, skiplen))
+      size += strlen(s->data) + overhead;
+  return size;
+}
+
+/* Get/compute multipart size. */
+static curl_off_t multipart_size(curl_mime *mime)
+{
+  curl_off_t size;
+  curl_off_t sz;
+  size_t boundarysize;
+  curl_mimepart *part;
+
+  if(!mime)
+    return 0;           /* Not present -> empty. */
+
+  boundarysize = 4 + strlen(mime->boundary) + 2;
+  size = boundarysize;  /* Final boundary - CRLF after headers. */
+
+  for(part = mime->firstpart; part; part = part->nextpart) {
+    sz = Curl_mime_size(part);
+
+    if(sz < 0)
+      size = sz;
+
+    if(size >= 0)
+      size += boundarysize + sz;
+  }
+
+  return size;
+}
+
+/* Get/compute mime size. */
+curl_off_t Curl_mime_size(curl_mimepart *part)
+{
+  curl_off_t size;
+
+  if(part->datasize < 0 && part->kind == MIMEKIND_MULTIPART)
+    part->datasize = multipart_size(part->arg);
+
+  size = part->datasize;
+
+  if(part->encoder)
+    size = part->encoder->sizefunc(part);
+
+  if(size >= 0 && !(part->flags & MIME_BODY_ONLY)) {
+    /* Compute total part size. */
+    size += slist_size(part->curlheaders, 2, NULL);
+    size += slist_size(part->userheaders, 2, "Content-Type");
+    size += 2;    /* CRLF after headers. */
+  }
+  return size;
+}
+
+/* Add a header. */
+/* VARARGS2 */
+CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
+{
+  struct curl_slist *hdr = NULL;
+  char *s = NULL;
+  va_list ap;
+
+  va_start(ap, fmt);
+  s = curl_mvaprintf(fmt, ap);
+  va_end(ap);
+
+  if(s) {
+    hdr = Curl_slist_append_nodup(*slp, s);
+    if(hdr)
+      *slp = hdr;
+    else
+      free(s);
+  }
+
+  return hdr? CURLE_OK: CURLE_OUT_OF_MEMORY;
+}
+
+/* Add a content type header. */
+static CURLcode add_content_type(struct curl_slist **slp,
+                                 const char *type, const char *boundary)
+{
+  return Curl_mime_add_header(slp, "Content-Type: %s%s%s", type,
+                              boundary? "; boundary=": "",
+                              boundary? boundary: "");
+}
+
+
+static const char *ContentTypeForFilename(const char *filename)
+{
+  unsigned int i;
+
+  /*
+   * If no content type was specified, we scan through a few well-known
+   * extensions and pick the first we match!
+   */
+  struct ContentType {
+    const char *extension;
+    const char *type;
+  };
+  static const struct ContentType ctts[] = {
+    {".gif",  "image/gif"},
+    {".jpg",  "image/jpeg"},
+    {".jpeg", "image/jpeg"},
+    {".png",  "image/png"},
+    {".svg",  "image/svg+xml"},
+    {".txt",  "text/plain"},
+    {".htm",  "text/html"},
+    {".html", "text/html"},
+    {".pdf",  "application/pdf"},
+    {".xml",  "application/xml"}
+  };
+
+  if(filename) {
+    size_t len1 = strlen(filename);
+    const char *nameend = filename + len1;
+
+    for(i = 0; i < sizeof ctts / sizeof ctts[0]; i++) {
+      size_t len2 = strlen(ctts[i].extension);
+
+      if(len1 >= len2 && strcasecompare(nameend - len2, ctts[i].extension))
+          return ctts[i].type;
+    }
+  }
+  return NULL;
+}
+
+CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
+                                   const char *contenttype,
+                                   const char *disposition,
+                                   enum mimestrategy strategy)
+{
+  curl_mime *mime = NULL;
+  const char *boundary = NULL;
+  char *s;
+  const char *cte = NULL;
+  CURLcode ret = CURLE_OK;
+
+  /* Get rid of previously prepared headers. */
+  curl_slist_free_all(part->curlheaders);
+  part->curlheaders = NULL;
+
+  /* Be sure we won't access old headers later. */
+  if(part->state.state == MIMESTATE_CURLHEADERS)
+    mimesetstate(&part->state, MIMESTATE_CURLHEADERS, NULL);
+
+  /* Build the content-type header. */
+  s = search_header(part->userheaders, "Content-Type");
+  if(s)
+    contenttype = s;
+  if(part->mimetype)
+    contenttype = part->mimetype;
+  if(!contenttype) {
+    switch(part->kind) {
+    case MIMEKIND_MULTIPART:
+      contenttype = MULTIPART_CONTENTTYPE_DEFAULT;
+      break;
+    case MIMEKIND_FILE:
+      contenttype = ContentTypeForFilename(part->filename);
+      if(!contenttype)
+        contenttype = ContentTypeForFilename(part->data);
+      if(!contenttype && part->filename)
+        contenttype = FILE_CONTENTTYPE_DEFAULT;
+      break;
+    default:
+      contenttype = ContentTypeForFilename(part->filename);
+      break;
+    }
+  }
+
+  if(part->kind == MIMEKIND_MULTIPART) {
+    mime = (curl_mime *) part->arg;
+    if(mime)
+      boundary = mime->boundary;
+  }
+  else if(contenttype && strcasecompare(contenttype, "text/plain"))
+    if(strategy == MIMESTRATEGY_MAIL || !part->filename)
+      contenttype = NULL;
+
+  /* Issue content-disposition header only if not already set by caller. */
+  if(!search_header(part->userheaders, "Content-Disposition")) {
+    if(!disposition)
+      if(part->filename || part->name ||
+        (contenttype && !strncasecompare(contenttype, "multipart/", 10)))
+          disposition = DISPOSITION_DEFAULT;
+    if(disposition && curl_strequal(disposition, "attachment") &&
+     !part->name && !part->filename)
+      disposition = NULL;
+    if(disposition) {
+      char *name = NULL;
+      char *filename = NULL;
+
+      if(part->name) {
+        name = escape_string(part->name);
+        if(!name)
+          ret = CURLE_OUT_OF_MEMORY;
+      }
+      if(!ret && part->filename) {
+        filename = escape_string(part->filename);
+        if(!filename)
+          ret = CURLE_OUT_OF_MEMORY;
+      }
+      if(!ret)
+        ret = Curl_mime_add_header(&part->curlheaders,
+                                   "Content-Disposition: %s%s%s%s%s%s%s",
+                                   disposition,
+                                   name? "; name=\"": "",
+                                   name? name: "",
+                                   name? "\"": "",
+                                   filename? "; filename=\"": "",
+                                   filename? filename: "",
+                                   filename? "\"": "");
+      Curl_safefree(name);
+      Curl_safefree(filename);
+      if(ret)
+        return ret;
+      }
+    }
+
+  /* Issue Content-Type header. */
+  if(contenttype) {
+    ret = add_content_type(&part->curlheaders, contenttype, boundary);
+    if(ret)
+      return ret;
+  }
+
+  /* Content-Transfer-Encoding header. */
+  if(!search_header(part->userheaders, "Content-Transfer-Encoding")) {
+    if(part->encoder)
+      cte = part->encoder->name;
+    else if(contenttype && strategy == MIMESTRATEGY_MAIL &&
+     part->kind != MIMEKIND_MULTIPART)
+      cte = "8bit";
+    if(cte) {
+      ret = Curl_mime_add_header(&part->curlheaders,
+                                 "Content-Transfer-Encoding: %s", cte);
+      if(ret)
+        return ret;
+    }
+  }
+
+  /* If we were reading curl-generated headers, restart with new ones (this
+     should not occur). */
+  if(part->state.state == MIMESTATE_CURLHEADERS)
+    mimesetstate(&part->state, MIMESTATE_CURLHEADERS, part->curlheaders);
+
+  /* Process subparts. */
+  if(part->kind == MIMEKIND_MULTIPART && mime) {
+    curl_mimepart *subpart;
+
+    disposition = NULL;
+    if(strcasecompare(contenttype, "multipart/form-data"))
+      disposition = "form-data";
+    for(subpart = mime->firstpart; subpart; subpart = subpart->nextpart) {
+      ret = Curl_mime_prepare_headers(subpart, NULL, disposition, strategy);
+      if(ret)
+        return ret;
+    }
+  }
+  return ret;
+}
+
+#else /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
+
+/* Mime not compiled in: define stubs for externally-referenced functions. */
+curl_mime *curl_mime_init(CURL *easy)
+{
+  (void) easy;
+  return NULL;
+}
+
+void curl_mime_free(curl_mime *mime)
+{
+  (void) mime;
+}
+
+curl_mimepart *curl_mime_addpart(curl_mime *mime)
+{
+  (void) mime;
+  return NULL;
+}
+
+CURLcode curl_mime_name(curl_mimepart *part, const char *name)
+{
+  (void) part;
+  (void) name;
+  return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_filename(curl_mimepart *part, const char *filename)
+{
+  (void) part;
+  (void) filename;
+  return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype)
+{
+  (void) part;
+  (void) mimetype;
+  return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding)
+{
+  (void) part;
+  (void) encoding;
+  return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_data(curl_mimepart *part,
+                        const char *data, size_t datasize)
+{
+  (void) part;
+  (void) data;
+  (void) datasize;
+  return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename)
+{
+  (void) part;
+  (void) filename;
+  return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_data_cb(curl_mimepart *part,
+                           curl_off_t datasize,
+                           curl_read_callback readfunc,
+                           curl_seek_callback seekfunc,
+                           curl_free_callback freefunc,
+                           void *arg)
+{
+  (void) part;
+  (void) datasize;
+  (void) readfunc;
+  (void) seekfunc;
+  (void) freefunc;
+  (void) arg;
+  return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts)
+{
+  (void) part;
+  (void) subparts;
+  return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode curl_mime_headers(curl_mimepart *part,
+                           struct curl_slist *headers, int take_ownership)
+{
+  (void) part;
+  (void) headers;
+  (void) take_ownership;
+  return CURLE_NOT_BUILT_IN;
+}
+
+void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy)
+{
+  (void) part;
+  (void) easy;
+}
+
+void Curl_mime_cleanpart(curl_mimepart *part)
+{
+  (void) part;
+}
+
+CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
+                                   const char *contenttype,
+                                   const char *disposition,
+                                   enum mimestrategy strategy)
+{
+  (void) part;
+  (void) contenttype;
+  (void) disposition;
+  (void) strategy;
+  return CURLE_NOT_BUILT_IN;
+}
+
+curl_off_t Curl_mime_size(curl_mimepart *part)
+{
+  (void) part;
+  return (curl_off_t) -1;
+}
+
+size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream)
+{
+  (void) buffer;
+  (void) size;
+  (void) nitems;
+  (void) instream;
+  return 0;
+}
+
+CURLcode Curl_mime_rewind(curl_mimepart *part)
+{
+  (void) part;
+  return CURLE_NOT_BUILT_IN;
+}
+
+/* VARARGS2 */
+CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...)
+{
+  (void) slp;
+  (void) fmt;
+  return CURLE_NOT_BUILT_IN;
+}
+
+#endif /* !CURL_DISABLE_HTTP || !CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
diff --git a/lib/mime.h b/lib/mime.h
new file mode 100644
index 000000000..a14485707
--- /dev/null
+++ b/lib/mime.h
@@ -0,0 +1,135 @@
+#ifndef HEADER_CURL_MIME_H
+#define HEADER_CURL_MIME_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, 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.
+ *
+ ***************************************************************************/
+
+#define MIME_RAND_BOUNDARY_CHARS        16  /* Nb. of random boundary chars. */
+#define MAX_ENCODED_LINE_LENGTH         76  /* Maximum encoded line length. */
+#define ENCODING_BUFFER_SIZE            256 /* Encoding temp buffers size. */
+
+/* Part flags. */
+#define MIME_USERHEADERS_OWNER  (1 << 0)
+#define MIME_BODY_ONLY          (1 << 1)
+
+/* Part source kinds. */
+enum mimekind {
+  MIMEKIND_NONE = 0,            /* Part not set. */
+  MIMEKIND_DATA,                /* Allocated mime data. */
+  MIMEKIND_FILE,                /* Data from file. */
+  MIMEKIND_CALLBACK,            /* Data from `read' callback. */
+  MIMEKIND_MULTIPART,           /* Data is a mime subpart. */
+  MIMEKIND_LAST
+};
+
+/* Readback state tokens. */
+enum mimestate {
+  MIMESTATE_BEGIN,              /* Readback has not yet started. */
+  MIMESTATE_CURLHEADERS,        /* In curl-generated headers. */
+  MIMESTATE_USERHEADERS,        /* In caller's supplied headers. */
+  MIMESTATE_EOH,                /* End of headers. */
+  MIMESTATE_BODY,               /* Placeholder. */
+  MIMESTATE_BOUNDARY1,          /* In boundary prefix. */
+  MIMESTATE_BOUNDARY2,          /* In boundary. */
+  MIMESTATE_CONTENT,            /* In content. */
+  MIMESTATE_END,                /* End of part reached. */
+  MIMESTATE_LAST
+};
+
+/* Mime headers strategies. */
+enum mimestrategy {
+  MIMESTRATEGY_MAIL,            /* Mime mail. */
+  MIMESTRATEGY_FORM,            /* HTTP post form. */
+  MIMESTRATEGY_LAST
+};
+
+/* Content transfer encoder. */
+typedef struct {
+  const char *   name;          /* Encoding name. */
+  size_t         (*encodefunc)(char *buffer, size_t size, bool ateof,
+                             curl_mimepart *part);  /* Encoded read. */
+  curl_off_t     (*sizefunc)(curl_mimepart *part);  /* Encoded size. */
+}  mime_encoder;
+
+/* Content transfer encoder state. */
+typedef struct {
+  size_t         pos;           /* Position on output line. */
+  size_t         bufbeg;        /* Next data index in input buffer. */
+  size_t         bufend;        /* First unused byte index in input buffer. */
+  char           buf[ENCODING_BUFFER_SIZE]; /* Input buffer. */
+}  mime_encoder_state;
+
+/* Mime readback state. */
+typedef struct {
+  enum mimestate state;       /* Current state token. */
+  void *ptr;                  /* State-dependent pointer. */
+  size_t offset;              /* State-dependent offset. */
+}  mime_state;
+
+/* A mime multipart. */
+struct curl_mime_s {
+  struct Curl_easy *easy;          /* The associated easy handle. */
+  curl_mimepart *parent;           /* Parent part. */
+  curl_mimepart *firstpart;        /* First part. */
+  curl_mimepart *lastpart;         /* Last part. */
+  char *boundary;                  /* The part boundary. */
+  mime_state state;                /* Current readback state. */
+};
+
+/* A mime part. */
+struct curl_mimepart_s {
+  struct Curl_easy *easy;          /* The associated easy handle. */
+  curl_mime *parent;               /* Parent mime structure. */
+  curl_mimepart *nextpart;         /* Forward linked list. */
+  enum mimekind kind;              /* The part kind. */
+  char *data;                      /* Memory data or file name. */
+  curl_read_callback readfunc;     /* Read function. */
+  curl_seek_callback seekfunc;     /* Seek function. */
+  curl_free_callback freefunc;     /* Argument free function. */
+  void *arg;                       /* Argument to callback functions. */
+  FILE *fp;                        /* File pointer. */
+  struct curl_slist *curlheaders;  /* Part headers. */
+  struct curl_slist *userheaders;  /* Part headers. */
+  char *mimetype;                  /* Part mime type. */
+  char *filename;                  /* Remote file name. */
+  char *name;                      /* Data name. */
+  curl_off_t datasize;             /* Expected data size. */
+  unsigned int flags;              /* Flags. */
+  mime_state state;                /* Current readback state. */
+  const mime_encoder *encoder;     /* Content data encoder. */
+  mime_encoder_state encstate;     /* Data encoder state. */
+};
+
+
+/* Prototypes. */
+void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy);
+void Curl_mime_cleanpart(curl_mimepart *part);
+CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
+                                   const char *contenttype,
+                                   const char *disposition,
+                                   enum mimestrategy strategy);
+curl_off_t Curl_mime_size(curl_mimepart *part);
+size_t Curl_mime_read(char *buffer, size_t size, size_t nitems,
+                      void *instream);
+CURLcode Curl_mime_rewind(curl_mimepart *part);
+CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
+
+#endif /* HEADER_CURL_MIME_H */
diff --git a/lib/mprintf.c b/lib/mprintf.c
index 68545bfac..0def1b0a5 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -46,10 +46,6 @@
  * If SIZEOF_SIZE_T has not been defined, default to the size of long.
  */
 
-#ifndef SIZEOF_SIZE_T
-#  define SIZEOF_SIZE_T CURL_SIZEOF_LONG
-#endif
-
 #ifdef HAVE_LONGLONG
 #  define LONG_LONG_TYPE long long
 #  define HAVE_LONG_LONG_TYPE
@@ -111,7 +107,7 @@ static const char upper_digits[] = 
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   } WHILE_FALSE
 
 /* Data type to read from the arglist */
-typedef enum  {
+typedef enum {
   FORMAT_UNKNOWN = 0,
   FORMAT_STRING,
   FORMAT_PTR,
@@ -181,7 +177,7 @@ struct asprintf {
 
 static long dprintf_DollarString(char *input, char **end)
 {
-  int number=0;
+  int number = 0;
   while(ISDIGIT(*input)) {
     number *= 10;
     number += *input-'0';
@@ -237,7 +233,7 @@ static int dprintf_Pass1(const char *format, va_stack_t 
*vto, char **endpos,
   long width;
   long precision;
   int flags;
-  long max_param=0;
+  long max_param = 0;
   long i;
 
   while(*fmt) {
@@ -326,7 +322,7 @@ static int dprintf_Pass1(const char *format, va_stack_t 
*vto, char **endpos,
           break;
 #if defined(MP_HAVE_INT_EXTENSIONS)
         case 'I':
-#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
           flags |= FLAGS_LONGLONG;
 #else
           flags |= FLAGS_LONG;
@@ -348,14 +344,14 @@ static int dprintf_Pass1(const char *format, va_stack_t 
*vto, char **endpos,
         case 'z':
           /* the code below generates a warning if -Wunreachable-code is
              used */
-#if (SIZEOF_SIZE_T > CURL_SIZEOF_LONG)
+#if (SIZEOF_SIZE_T > SIZEOF_LONG)
           flags |= FLAGS_LONGLONG;
 #else
           flags |= FLAGS_LONG;
 #endif
           break;
         case 'O':
-#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
           flags |= FLAGS_LONGLONG;
 #else
           flags |= FLAGS_LONG;
@@ -380,7 +376,7 @@ static int dprintf_Pass1(const char *format, va_stack_t 
*vto, char **endpos,
           else
             width = param_num;
           if(width > max_param)
-            max_param=width;
+            max_param = width;
           break;
         default:
           break;
@@ -486,7 +482,7 @@ static int dprintf_Pass1(const char *format, va_stack_t 
*vto, char **endpos,
   }
 
   /* Read the arg list parameters into our data list */
-  for(i=0; i<max_param; i++) {
+  for(i = 0; i<max_param; i++) {
     /* Width/precision arguments must be read before the main argument
        they are attached to */
     if(vto[i].flags & FLAGS_WIDTHPARAM) {
@@ -573,7 +569,7 @@ static int dprintf_formatf(
   int done = 0;
 
   long param; /* current parameter to read */
-  long param_num=0; /* parameter counter */
+  long param_num = 0; /* parameter counter */
 
   va_stack_t vto[MAX_PARAMETERS];
   char *endpos[MAX_PARAMETERS];
@@ -643,7 +639,7 @@ static int dprintf_formatf(
 
     /* If this is a positional parameter, the position must follow immediately
        after the %, thus create a %<num>$ sequence */
-    param=dprintf_DollarString(f, &f);
+    param = dprintf_DollarString(f, &f);
 
     if(!param)
       param = param_num;
@@ -952,7 +948,7 @@ static int dprintf_formatf(
            output characters */
         (sprintf)(work, formatbuf, p->data.dnum);
         DEBUGASSERT(strlen(work) <= sizeof(work));
-        for(fptr=work; *fptr; fptr++)
+        for(fptr = work; *fptr; fptr++)
           OUTCHAR(*fptr);
       }
       break;
@@ -984,7 +980,7 @@ static int dprintf_formatf(
 /* fputc() look-alike */
 static int addbyter(int output, FILE *data)
 {
-  struct nsprintf *infop=(struct nsprintf *)data;
+  struct nsprintf *infop = (struct nsprintf *)data;
   unsigned char outc = (unsigned char)output;
 
   if(infop->length < infop->max) {
@@ -1032,7 +1028,7 @@ int curl_msnprintf(char *buffer, size_t maxlength, const 
char *format, ...)
 /* fputc() look-alike */
 static int alloc_addbyter(int output, FILE *data)
 {
-  struct asprintf *infop=(struct asprintf *)data;
+  struct asprintf *infop = (struct asprintf *)data;
   unsigned char outc = (unsigned char)output;
 
   if(!infop->buffer) {
@@ -1042,9 +1038,9 @@ static int alloc_addbyter(int output, FILE *data)
       return -1; /* fail */
     }
     infop->alloc = 32;
-    infop->len =0;
+    infop->len = 0;
   }
-  else if(infop->len+1 >= infop->alloc) {
+  else if(infop->len + 1 >= infop->alloc) {
     char *newptr = NULL;
     size_t newsize = infop->alloc*2;
 
@@ -1133,7 +1129,7 @@ int curl_msprintf(char *buffer, const char *format, ...)
   va_start(ap_save, format);
   retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
   va_end(ap_save);
-  *buffer=0; /* we terminate this with a zero byte */
+  *buffer = 0; /* we terminate this with a zero byte */
   return retcode;
 }
 
@@ -1162,7 +1158,7 @@ int curl_mvsprintf(char *buffer, const char *format, 
va_list ap_save)
 {
   int retcode;
   retcode = dprintf_formatf(&buffer, storebuffer, format, ap_save);
-  *buffer=0; /* we terminate this with a zero byte */
+  *buffer = 0; /* we terminate this with a zero byte */
   return retcode;
 }
 
diff --git a/lib/multi.c b/lib/multi.c
index 1f8dfc5ce..e2596801f 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -592,7 +592,7 @@ static CURLcode multi_done(struct connectdata **connp,
 
   /* if the transfer was completed in a paused state there can be buffered
      data left to free */
-  for(i=0; i < data->state.tempcount; i++) {
+  for(i = 0; i < data->state.tempcount; i++) {
     free(data->state.tempwrite[i].buf);
   }
   data->state.tempcount = 0;
@@ -802,8 +802,8 @@ static int waitconnect_getsock(struct connectdata *conn,
                                int numsocks)
 {
   int i;
-  int s=0;
-  int rc=0;
+  int s = 0;
+  int rc = 0;
 
   if(!numsocks)
     return GETSOCK_BLANK;
@@ -813,7 +813,7 @@ static int waitconnect_getsock(struct connectdata *conn,
     return Curl_ssl_getsock(conn, sock, numsocks);
 #endif
 
-  for(i=0; i<2; i++) {
+  for(i = 0; i<2; i++) {
     if(conn->tempsock[i] != CURL_SOCKET_BAD) {
       sock[s] = conn->tempsock[i];
       rc |= GETSOCK_WRITESOCK(s++);
@@ -924,7 +924,7 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
      Some easy handles may not have connected to the remote host yet,
      and then we must make sure that is done. */
   struct Curl_easy *data;
-  int this_max_fd=-1;
+  int this_max_fd = -1;
   curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE];
   int bitmap;
   int i;
@@ -933,11 +933,11 @@ CURLMcode curl_multi_fdset(struct Curl_multi *multi,
   if(!GOOD_MULTI_HANDLE(multi))
     return CURLM_BAD_HANDLE;
 
-  data=multi->easyp;
+  data = multi->easyp;
   while(data) {
     bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
 
-    for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+    for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
       curl_socket_t s = CURL_SOCKET_BAD;
 
       if((bitmap & GETSOCK_READSOCK(i)) && VALID_SOCK((sockbunch[i]))) {
@@ -994,11 +994,11 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
     timeout_ms = (int)timeout_internal;
 
   /* Count up how many fds we have from the multi handle */
-  data=multi->easyp;
+  data = multi->easyp;
   while(data) {
     bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
 
-    for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+    for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
       curl_socket_t s = CURL_SOCKET_BAD;
 
       if(bitmap & GETSOCK_READSOCK(i)) {
@@ -1041,11 +1041,11 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
 
   if(curlfds) {
     /* Add the curl handles to our pollfds first */
-    data=multi->easyp;
+    data = multi->easyp;
     while(data) {
       bitmap = multi_getsock(data, sockbunch, MAX_SOCKSPEREASYHANDLE);
 
-      for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) {
+      for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++) {
         curl_socket_t s = CURL_SOCKET_BAD;
 
         if(bitmap & GETSOCK_READSOCK(i)) {
@@ -1229,15 +1229,15 @@ static CURLcode multi_reconnect_request(struct 
connectdata **connp)
  */
 static void do_complete(struct connectdata *conn)
 {
-  conn->data->req.chunk=FALSE;
+  conn->data->req.chunk = FALSE;
   conn->data->req.maxfd = (conn->sockfd>conn->writesockfd?
-                           conn->sockfd:conn->writesockfd)+1;
+                           conn->sockfd:conn->writesockfd) + 1;
   Curl_pgrsTime(conn->data, TIMER_PRETRANSFER);
 }
 
 static CURLcode multi_do(struct connectdata **connp, bool *done)
 {
-  CURLcode result=CURLE_OK;
+  CURLcode result = CURLE_OK;
   struct connectdata *conn = *connp;
   struct Curl_easy *data = conn->data;
 
@@ -1286,7 +1286,7 @@ static CURLcode multi_do(struct connectdata **connp, bool 
*done)
 
 static CURLcode multi_do_more(struct connectdata *conn, int *complete)
 {
-  CURLcode result=CURLE_OK;
+  CURLcode result = CURLE_OK;
 
   *complete = 0;
 
@@ -1415,7 +1415,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
     switch(data->mstate) {
     case CURLM_STATE_INIT:
       /* init this transfer. */
-      result=Curl_pretransfer(data);
+      result = Curl_pretransfer(data);
 
       if(!result) {
         /* after init, go CONNECT */
@@ -1697,7 +1697,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
            * back to the CONNECT phase so we can try again.
            */
           char *newurl = NULL;
-          followtype follow=FOLLOW_NONE;
+          followtype follow = FOLLOW_NONE;
           CURLcode drc;
           bool retry = FALSE;
 
@@ -1783,7 +1783,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         if(control) {
           /* if positive, advance to DO_DONE
              if negative, go back to DOING */
-          multistate(data, control==1?
+          multistate(data, control == 1?
                      CURLM_STATE_DO_DONE:
                      CURLM_STATE_DOING);
           rc = CURLM_CALL_MULTI_PERFORM;
@@ -1938,7 +1938,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
         multi_done(&data->easy_conn, result, TRUE);
       }
       else if(done) {
-        followtype follow=FOLLOW_NONE;
+        followtype follow = FOLLOW_NONE;
 
         /* call this even if the readwrite function returned error */
         Curl_posttransfer(data);
@@ -2144,14 +2144,14 @@ static CURLMcode multi_runsingle(struct Curl_multi 
*multi,
 CURLMcode curl_multi_perform(struct Curl_multi *multi, int *running_handles)
 {
   struct Curl_easy *data;
-  CURLMcode returncode=CURLM_OK;
+  CURLMcode returncode = CURLM_OK;
   struct Curl_tree *t;
   struct curltime now = Curl_tvnow();
 
   if(!GOOD_MULTI_HANDLE(multi))
     return CURLM_BAD_HANDLE;
 
-  data=multi->easyp;
+  data = multi->easyp;
   while(data) {
     CURLMcode result;
     SIGPIPE_VARIABLE(pipe_st);
@@ -2246,7 +2246,7 @@ CURLMcode curl_multi_cleanup(struct Curl_multi *multi)
     /* remove all easy handles */
     data = multi->easyp;
     while(data) {
-      nextdata=data->next;
+      nextdata = data->next;
       if(data->dns.hostcachetype == HCACHE_MULTI) {
         /* clear out the usage of the shared DNS cache */
         Curl_hostcache_clean(data, data->dns.hostcache);
@@ -2326,7 +2326,7 @@ static void singlesocket(struct Curl_multi *multi,
   int num;
   unsigned int curraction;
 
-  for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++)
+  for(i = 0; i< MAX_SOCKSPEREASYHANDLE; i++)
     socks[i] = CURL_SOCKET_BAD;
 
   /* Fill in the 'current' struct with the state as it is now: what sockets to
@@ -2338,7 +2338,7 @@ static void singlesocket(struct Curl_multi *multi,
      longer supervised ones and add new ones */
 
   /* walk over the sockets we got right now */
-  for(i=0; (i< MAX_SOCKSPEREASYHANDLE) &&
+  for(i = 0; (i< MAX_SOCKSPEREASYHANDLE) &&
         (curraction & (GETSOCK_READSOCK(i) | GETSOCK_WRITESOCK(i)));
       i++) {
     int action = CURL_POLL_NONE;
@@ -2382,10 +2382,10 @@ static void singlesocket(struct Curl_multi *multi,
 
   /* when we've walked over all the sockets we should have right now, we must
      make sure to detect sockets that are removed */
-  for(i=0; i< data->numsocks; i++) {
+  for(i = 0; i< data->numsocks; i++) {
     int j;
     s = data->sockets[i];
-    for(j=0; j<num; j++) {
+    for(j = 0; j<num; j++) {
       if(s == socks[j]) {
         /* this is still supervised */
         s = CURL_SOCKET_BAD;
@@ -2558,7 +2558,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
     /* walk through each easy handle and do the socket state change magic
        and callbacks */
     if(result != CURLM_BAD_HANDLE) {
-      data=multi->easyp;
+      data = multi->easyp;
       while(data) {
         singlesocket(multi, data);
         data = data->next;
@@ -2795,7 +2795,7 @@ static CURLMcode multi_timeout(struct Curl_multi *multi,
          * processors while the diff is still present but less than one
          * millisecond! instead we return 1 until the time is ripe.
          */
-        *timeout_ms=1;
+        *timeout_ms = 1;
     }
     else
       /* 0 means immediately */
@@ -2831,7 +2831,7 @@ static int update_timer(struct Curl_multi *multi)
     return -1;
   }
   if(timeout_ms < 0) {
-    static const struct curltime none={0, 0};
+    static const struct curltime none = {0, 0};
     if(Curl_splaycomparekeys(none, multi->timer_lastcall)) {
       multi->timer_lastcall = none;
       /* there's no timeout now but there was one previously, tell the app to
@@ -3115,13 +3115,13 @@ void Curl_multi_dump(struct Curl_multi *multi)
   int i;
   fprintf(stderr, "* Multi status: %d handles, %d alive\n",
           multi->num_easy, multi->num_alive);
-  for(data=multi->easyp; data; data = data->next) {
+  for(data = multi->easyp; data; data = data->next) {
     if(data->mstate < CURLM_STATE_COMPLETED) {
       /* only display handles that are not completed */
       fprintf(stderr, "handle %p, state %s, %d sockets\n",
               (void *)data,
               statename[data->mstate], data->numsocks);
-      for(i=0; i < data->numsocks; i++) {
+      for(i = 0; i < data->numsocks; i++) {
         curl_socket_t s = data->sockets[i];
         struct Curl_sh_entry *entry = sh_getentry(&multi->sockhash, s);
 
diff --git a/lib/netrc.c b/lib/netrc.c
index e7afdbd44..084908ac7 100644
--- a/lib/netrc.c
+++ b/lib/netrc.c
@@ -56,14 +56,15 @@ int Curl_parsenetrc(const char *host,
                     char *netrcfile)
 {
   FILE *file;
-  int retcode=1;
+  int retcode = 1;
   int specific_login = (*loginp && **loginp != 0);
   bool netrc_alloc = FALSE;
-  enum host_lookup_state state=NOTHING;
+  enum host_lookup_state state = NOTHING;
 
-  char state_login=0;      /* Found a login keyword */
-  char state_password=0;   /* Found a password keyword */
-  int state_our_login=FALSE;  /* With specific_login, found *our* login name */
+  char state_login = 0;      /* Found a login keyword */
+  char state_password = 0;   /* Found a password keyword */
+  int state_our_login = FALSE;  /* With specific_login, found *our* login
+                                   name */
 
 #define NETRC DOT_CHAR "netrc"
 
@@ -88,7 +89,7 @@ int Curl_parsenetrc(const char *host,
     }
     else {
       struct passwd *pw;
-      pw= getpwuid(geteuid());
+      pw = getpwuid(geteuid());
       if(pw) {
         home = pw->pw_dir;
       }
@@ -113,19 +114,19 @@ int Curl_parsenetrc(const char *host,
   if(file) {
     char *tok;
     char *tok_buf;
-    bool done=FALSE;
+    bool done = FALSE;
     char netrcbuffer[256];
     int  netrcbuffsize = (int)sizeof(netrcbuffer);
 
     while(!done && fgets(netrcbuffer, netrcbuffsize, file)) {
-      tok=strtok_r(netrcbuffer, " \t\n", &tok_buf);
+      tok = strtok_r(netrcbuffer, " \t\n", &tok_buf);
       if(tok && *tok == '#')
         /* treat an initial hash as a comment line */
         continue;
       while(!done && tok) {
 
         if((*loginp && **loginp) && (*passwordp && **passwordp)) {
-          done=TRUE;
+          done = TRUE;
           break;
         }
 
@@ -136,22 +137,22 @@ int Curl_parsenetrc(const char *host,
                delimiter that starts the stuff entered for this machine,
                after this we need to search for 'login' and
                'password'. */
-            state=HOSTFOUND;
+            state = HOSTFOUND;
           }
           else if(strcasecompare("default", tok)) {
-            state=HOSTVALID;
-            retcode=0; /* we did find our host */
+            state = HOSTVALID;
+            retcode = 0; /* we did find our host */
           }
           break;
         case HOSTFOUND:
           if(strcasecompare(host, tok)) {
             /* and yes, this is our host! */
-            state=HOSTVALID;
-            retcode=0; /* we did find our host */
+            state = HOSTVALID;
+            retcode = 0; /* we did find our host */
           }
           else
             /* not our host */
-            state=NOTHING;
+            state = NOTHING;
           break;
         case HOSTVALID:
           /* we are now parsing sub-keywords concerning "our" host */
@@ -167,7 +168,7 @@ int Curl_parsenetrc(const char *host,
                 goto out;
               }
             }
-            state_login=0;
+            state_login = 0;
           }
           else if(state_password) {
             if(state_our_login || !specific_login) {
@@ -178,12 +179,12 @@ int Curl_parsenetrc(const char *host,
                 goto out;
               }
             }
-            state_password=0;
+            state_password = 0;
           }
           else if(strcasecompare("login", tok))
-            state_login=1;
+            state_login = 1;
           else if(strcasecompare("password", tok))
-            state_password=1;
+            state_password = 1;
           else if(strcasecompare("machine", tok)) {
             /* ok, there's machine here go => */
             state = HOSTFOUND;
diff --git a/lib/non-ascii.c b/lib/non-ascii.c
index 8fd0437dc..b9ac225e2 100644
--- a/lib/non-ascii.c
+++ b/lib/non-ascii.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -82,7 +82,7 @@ CURLcode Curl_convert_clone(struct Curl_easy *data,
 CURLcode Curl_convert_to_network(struct Curl_easy *data,
                                  char *buffer, size_t length)
 {
-  if(data->set.convtonetwork) {
+  if(data && data->set.convtonetwork) {
     /* use translation callback */
     CURLcode result = data->set.convtonetwork(buffer, length);
     if(result) {
@@ -96,14 +96,18 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
   else {
 #ifdef HAVE_ICONV
     /* do the translation ourselves */
+    iconv_t tmpcd = (iconv_t) -1;
+    iconv_t *cd = &tmpcd;
     char *input_ptr, *output_ptr;
     size_t in_bytes, out_bytes, rc;
 
     /* open an iconv conversion descriptor if necessary */
-    if(data->outbound_cd == (iconv_t)-1) {
-      data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
-                                     CURL_ICONV_CODESET_OF_HOST);
-      if(data->outbound_cd == (iconv_t)-1) {
+    if(data)
+      cd = &data->outbound_cd;
+    if(*cd == (iconv_t)-1) {
+      *cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
+                       CURL_ICONV_CODESET_OF_HOST);
+      if(*cd == (iconv_t)-1) {
         failf(data,
               "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
               CURL_ICONV_CODESET_OF_NETWORK,
@@ -115,8 +119,10 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
     /* call iconv */
     input_ptr = output_ptr = buffer;
     in_bytes = out_bytes = length;
-    rc = iconv(data->outbound_cd, (const char **)&input_ptr, &in_bytes,
+    rc = iconv(*cd, &input_ptr, &in_bytes,
                &output_ptr, &out_bytes);
+    if(!data)
+      iconv_close(tmpcd);
     if((rc == ICONV_ERROR) || (in_bytes != 0)) {
       failf(data,
             "The Curl_convert_to_network iconv call failed with errno %i: %s",
@@ -139,7 +145,7 @@ CURLcode Curl_convert_to_network(struct Curl_easy *data,
 CURLcode Curl_convert_from_network(struct Curl_easy *data,
                                    char *buffer, size_t length)
 {
-  if(data->set.convfromnetwork) {
+  if(data && data->set.convfromnetwork) {
     /* use translation callback */
     CURLcode result = data->set.convfromnetwork(buffer, length);
     if(result) {
@@ -153,14 +159,18 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
   else {
 #ifdef HAVE_ICONV
     /* do the translation ourselves */
+    iconv_t tmpcd = (iconv_t) -1;
+    iconv_t *cd = &tmpcd;
     char *input_ptr, *output_ptr;
     size_t in_bytes, out_bytes, rc;
 
     /* open an iconv conversion descriptor if necessary */
-    if(data->inbound_cd == (iconv_t)-1) {
-      data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
-                                    CURL_ICONV_CODESET_OF_NETWORK);
-      if(data->inbound_cd == (iconv_t)-1) {
+    if(data)
+      cd = &data->inbound_cd;
+    if(*cd == (iconv_t)-1) {
+      *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
+                       CURL_ICONV_CODESET_OF_NETWORK);
+      if(*cd == (iconv_t)-1) {
         failf(data,
               "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
               CURL_ICONV_CODESET_OF_HOST,
@@ -172,8 +182,10 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
     /* call iconv */
     input_ptr = output_ptr = buffer;
     in_bytes = out_bytes = length;
-    rc = iconv(data->inbound_cd, (const char **)&input_ptr, &in_bytes,
+    rc = iconv(*cd, &input_ptr, &in_bytes,
                &output_ptr, &out_bytes);
+    if(!data)
+      iconv_close(tmpcd);
     if((rc == ICONV_ERROR) || (in_bytes != 0)) {
       failf(data,
             "Curl_convert_from_network iconv call failed with errno %i: %s",
@@ -196,7 +208,7 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
 CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
                                 char *buffer, size_t length)
 {
-  if(data->set.convfromutf8) {
+  if(data && data->set.convfromutf8) {
     /* use translation callback */
     CURLcode result = data->set.convfromutf8(buffer, length);
     if(result) {
@@ -210,15 +222,19 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
   else {
 #ifdef HAVE_ICONV
     /* do the translation ourselves */
-    const char *input_ptr;
+    iconv_t tmpcd = (iconv_t) -1;
+    iconv_t *cd = &tmpcd;
+    char *input_ptr;
     char *output_ptr;
     size_t in_bytes, out_bytes, rc;
 
     /* open an iconv conversion descriptor if necessary */
-    if(data->utf8_cd == (iconv_t)-1) {
-      data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
-                                 CURL_ICONV_CODESET_FOR_UTF8);
-      if(data->utf8_cd == (iconv_t)-1) {
+    if(data)
+      cd = &data->utf8_cd;
+    if(*cd == (iconv_t)-1) {
+      *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
+                       CURL_ICONV_CODESET_FOR_UTF8);
+      if(*cd == (iconv_t)-1) {
         failf(data,
               "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
               CURL_ICONV_CODESET_OF_HOST,
@@ -230,8 +246,10 @@ CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
     /* call iconv */
     input_ptr = output_ptr = buffer;
     in_bytes = out_bytes = length;
-    rc = iconv(data->utf8_cd, &input_ptr, &in_bytes,
+    rc = iconv(*cd, &input_ptr, &in_bytes,
                &output_ptr, &out_bytes);
+    if(!data)
+      iconv_close(tmpcd);
     if((rc == ICONV_ERROR) || (in_bytes != 0)) {
       failf(data,
             "The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
@@ -301,29 +319,4 @@ void Curl_convert_close(struct Curl_easy *data)
 #endif /* HAVE_ICONV */
 }
 
-/*
- * Curl_convert_form() is used from http.c, this converts any form items that
-   need to be sent in the network encoding.  Returns CURLE_OK on success.
- */
-CURLcode Curl_convert_form(struct Curl_easy *data, struct FormData *form)
-{
-  CURLcode result;
-
-  if(!data)
-    return CURLE_BAD_FUNCTION_ARGUMENT;
-
-  while(form) {
-    if(form->type == FORM_DATA) {
-      result = Curl_convert_to_network(data, form->line, form->length);
-      /* Curl_convert_to_network calls failf if unsuccessful */
-      if(result)
-        return result;
-    }
-
-    form = form->next;
-  }
-
-  return CURLE_OK;
-}
-
 #endif /* CURL_DOES_CONVERSIONS */
diff --git a/lib/non-ascii.h b/lib/non-ascii.h
index e27f1f41f..5fb5771e0 100644
--- a/lib/non-ascii.h
+++ b/lib/non-ascii.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -48,7 +48,6 @@ CURLcode Curl_convert_from_network(struct Curl_easy *data,
                                  char *buffer, size_t length);
 CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
                                  char *buffer, size_t length);
-CURLcode Curl_convert_form(struct Curl_easy *data, struct FormData *form);
 #else
 #define Curl_convert_clone(a,b,c,d) ((void)a, CURLE_OK)
 #define Curl_convert_init(x) Curl_nop_stmt
@@ -57,7 +56,6 @@ CURLcode Curl_convert_form(struct Curl_easy *data, struct 
FormData *form);
 #define Curl_convert_to_network(a,b,c) ((void)a, CURLE_OK)
 #define Curl_convert_from_network(a,b,c) ((void)a, CURLE_OK)
 #define Curl_convert_from_utf8(a,b,c) ((void)a, CURLE_OK)
-#define Curl_convert_form(a,b) CURLE_OK
 #endif
 
 #endif /* HEADER_CURL_NON_ASCII_H */
diff --git a/lib/openldap.c b/lib/openldap.c
index 1b32d1f22..931719f97 100644
--- a/lib/openldap.c
+++ b/lib/openldap.c
@@ -5,7 +5,7 @@
  *                | (__| |_| |  _ <| |___
  *                 \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2010, Howard Chu, <address@hidden>
+ * Copyright (C) 2010, 2017, Howard Chu, <address@hidden>
  * Copyright (C) 2011 - 2016, Daniel Stenberg, <address@hidden>, et al.
  *
  * This software is licensed as described in the file COPYING, which
@@ -152,7 +152,7 @@ static CURLcode ldap_setup_connection(struct connectdata 
*conn)
 {
   ldapconninfo *li;
   LDAPURLDesc *lud;
-  struct Curl_easy *data=conn->data;
+  struct Curl_easy *data = conn->data;
   int rc, proto;
   CURLcode status;
 
@@ -198,7 +198,7 @@ static CURLcode ldap_connect(struct connectdata *conn, bool 
*done)
   (void)done;
 
   strcpy(hosturl, "ldap");
-  ptr = hosturl+4;
+  ptr = hosturl + 4;
   if(conn->handler->flags & PROTOPT_SSL)
     *ptr++ = 's';
   snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
@@ -354,7 +354,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool 
*done)
   int rc = 0;
   LDAPURLDesc *ludp = NULL;
   int msgid;
-  struct Curl_easy *data=conn->data;
+  struct Curl_easy *data = conn->data;
 
   connkeep(conn, "OpenLDAP do");
 
@@ -519,7 +519,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int 
sockindex, char *buf,
       else
         binary = 0;
 
-      for(i=0; bvals[i].bv_val != NULL; i++) {
+      for(i = 0; bvals[i].bv_val != NULL; i++) {
         int binval = 0;
         writeerr = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
         if(writeerr) {
@@ -549,7 +549,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int 
sockindex, char *buf,
           else {
             /* check for unprintable characters */
             unsigned int j;
-            for(j=0; j<bvals[i].bv_len; j++)
+            for(j = 0; j<bvals[i].bv_len; j++)
               if(!ISPRINT(bvals[i].bv_val[j])) {
                 binval = 1;
                 break;
diff --git a/lib/parsedate.c b/lib/parsedate.c
index c39add846..9ba5b94ad 100644
--- a/lib/parsedate.c
+++ b/lib/parsedate.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,20 +167,20 @@ static const struct tzinfo tz[]= {
      RFC 1123) had their signs wrong. Here we use the correct signs to match
      actual military usage.
    */
-  {"A",  +1 * 60},         /* Alpha */
-  {"B",  +2 * 60},         /* Bravo */
-  {"C",  +3 * 60},         /* Charlie */
-  {"D",  +4 * 60},         /* Delta */
-  {"E",  +5 * 60},         /* Echo */
-  {"F",  +6 * 60},         /* Foxtrot */
-  {"G",  +7 * 60},         /* Golf */
-  {"H",  +8 * 60},         /* Hotel */
-  {"I",  +9 * 60},         /* India */
+  {"A",  1 * 60},         /* Alpha */
+  {"B",  2 * 60},         /* Bravo */
+  {"C",  3 * 60},         /* Charlie */
+  {"D",  4 * 60},         /* Delta */
+  {"E",  5 * 60},         /* Echo */
+  {"F",  6 * 60},         /* Foxtrot */
+  {"G",  7 * 60},         /* Golf */
+  {"H",  8 * 60},         /* Hotel */
+  {"I",  9 * 60},         /* India */
   /* "J", Juliet is not used as a timezone, to indicate the observer's local
      time */
-  {"K", +10 * 60},         /* Kilo */
-  {"L", +11 * 60},         /* Lima */
-  {"M", +12 * 60},         /* Mike */
+  {"K", 10 * 60},         /* Kilo */
+  {"L", 11 * 60},         /* Lima */
+  {"M", 12 * 60},         /* Mike */
   {"N",  -1 * 60},         /* November */
   {"O",  -2 * 60},         /* Oscar */
   {"P",  -3 * 60},         /* Papa */
@@ -205,14 +205,14 @@ static int checkday(const char *check, size_t len)
 {
   int i;
   const char * const *what;
-  bool found= FALSE;
+  bool found = FALSE;
   if(len > 3)
     what = &weekday[0];
   else
     what = &Curl_wkday[0];
-  for(i=0; i<7; i++) {
+  for(i = 0; i<7; i++) {
     if(strcasecompare(check, what[0])) {
-      found=TRUE;
+      found = TRUE;
       break;
     }
     what++;
@@ -224,12 +224,12 @@ static int checkmonth(const char *check)
 {
   int i;
   const char * const *what;
-  bool found= FALSE;
+  bool found = FALSE;
 
   what = &Curl_month[0];
-  for(i=0; i<12; i++) {
+  for(i = 0; i<12; i++) {
     if(strcasecompare(check, what[0])) {
-      found=TRUE;
+      found = TRUE;
       break;
     }
     what++;
@@ -244,12 +244,12 @@ static int checktz(const char *check)
 {
   unsigned int i;
   const struct tzinfo *what;
-  bool found= FALSE;
+  bool found = FALSE;
 
   what = tz;
-  for(i=0; i< sizeof(tz)/sizeof(tz[0]); i++) {
+  for(i = 0; i< sizeof(tz)/sizeof(tz[0]); i++) {
     if(strcasecompare(check, what->name)) {
-      found=TRUE;
+      found = TRUE;
       break;
     }
     what++;
@@ -331,21 +331,21 @@ static time_t my_timegm(struct my_tm *tm)
 static int parsedate(const char *date, time_t *output)
 {
   time_t t = 0;
-  int wdaynum=-1;  /* day of the week number, 0-6 (mon-sun) */
-  int monnum=-1;   /* month of the year number, 0-11 */
-  int mdaynum=-1; /* day of month, 1 - 31 */
-  int hournum=-1;
-  int minnum=-1;
-  int secnum=-1;
-  int yearnum=-1;
-  int tzoff=-1;
+  int wdaynum = -1;  /* day of the week number, 0-6 (mon-sun) */
+  int monnum = -1;   /* month of the year number, 0-11 */
+  int mdaynum = -1; /* day of month, 1 - 31 */
+  int hournum = -1;
+  int minnum = -1;
+  int secnum = -1;
+  int yearnum = -1;
+  int tzoff = -1;
   struct my_tm tm;
   enum assume dignext = DATE_MDAY;
   const char *indate = date; /* save the original pointer */
   int part = 0; /* max 6 parts */
 
   while(*date && (part < 6)) {
-    bool found=FALSE;
+    bool found = FALSE;
 
     skip(&date);
 
@@ -386,7 +386,7 @@ static int parsedate(const char *date, time_t *output)
       /* a digit */
       int val;
       char *end;
-      int len=0;
+      int len = 0;
       if((secnum == -1) &&
          (3 == sscanf(date, "%02d:%02d:%02d%n",
                       &hournum, &minnum, &secnum, &len))) {
diff --git a/lib/pingpong.c b/lib/pingpong.c
index 5ed79b718..b8f214005 100644
--- a/lib/pingpong.c
+++ b/lib/pingpong.c
@@ -47,10 +47,10 @@
 time_t Curl_pp_state_timeout(struct pingpong *pp)
 {
   struct connectdata *conn = pp->conn;
-  struct Curl_easy *data=conn->data;
+  struct Curl_easy *data = conn->data;
   time_t timeout_ms; /* in milliseconds */
   time_t timeout2_ms; /* in milliseconds */
-  long response_time= (data->set.server_response_timeout)?
+  long response_time = (data->set.server_response_timeout)?
     data->set.server_response_timeout: pp->response_time;
 
   /* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine
@@ -85,10 +85,10 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block)
   int rc;
   time_t interval_ms;
   time_t timeout_ms = Curl_pp_state_timeout(pp);
-  struct Curl_easy *data=conn->data;
+  struct Curl_easy *data = conn->data;
   CURLcode result = CURLE_OK;
 
-  if(timeout_ms <=0) {
+  if(timeout_ms <= 0) {
     failf(data, "server response timeout");
     return CURLE_OPERATION_TIMEDOUT; /* already too little time */
   }
@@ -270,7 +270,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
                           size_t *size) /* size of the response */
 {
   ssize_t perline; /* count bytes per line */
-  bool keepon=TRUE;
+  bool keepon = TRUE;
   ssize_t gotbytes;
   char *ptr;
   struct connectdata *conn = pp->conn;
@@ -281,7 +281,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
   *code = 0; /* 0 for errors or not done */
   *size = 0;
 
-  ptr=buf + pp->nread_resp;
+  ptr = buf + pp->nread_resp;
 
   /* number of bytes in the current line, so far */
   perline = (ssize_t)(ptr-pp->linestart_resp);
@@ -297,7 +297,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
        * it would have been populated with something of size int to begin
        * with, even though its datatype may be larger than an int.
        */
-      DEBUGASSERT((ptr+pp->cache_size) <= (buf+data->set.buffer_size+1));
+      DEBUGASSERT((ptr + pp->cache_size) <= (buf + data->set.buffer_size + 1));
       memcpy(ptr, pp->cache, pp->cache_size);
       gotbytes = (ssize_t)pp->cache_size;
       free(pp->cache);    /* free the cache */
@@ -351,7 +351,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
       pp->nread_resp += gotbytes;
       for(i = 0; i < gotbytes; ptr++, i++) {
         perline++;
-        if(*ptr=='\n') {
+        if(*ptr == '\n') {
           /* a newline is CRLF in pp-talk, so the CR is ignored as
              the line isn't really terminated until the LF comes */
 
@@ -378,17 +378,17 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
                start of the buffer and zero terminate, for old times sake */
             size_t n = ptr - pp->linestart_resp;
             memmove(buf, pp->linestart_resp, n);
-            buf[n]=0; /* zero terminate */
-            keepon=FALSE;
-            pp->linestart_resp = ptr+1; /* advance pointer */
+            buf[n] = 0; /* zero terminate */
+            keepon = FALSE;
+            pp->linestart_resp = ptr + 1; /* advance pointer */
             i++; /* skip this before getting out */
 
             *size = pp->nread_resp; /* size of the response */
             pp->nread_resp = 0; /* restart */
             break;
           }
-          perline=0; /* line starts over here */
-          pp->linestart_resp = ptr+1;
+          perline = 0; /* line starts over here */
+          pp->linestart_resp = ptr + 1;
         }
       }
 
@@ -490,7 +490,7 @@ CURLcode Curl_pp_flushsend(struct pingpong *pp)
   }
   else {
     free(pp->sendthis);
-    pp->sendthis=NULL;
+    pp->sendthis = NULL;
     pp->sendleft = pp->sendsize = 0;
     pp->response = Curl_tvnow();
   }
diff --git a/lib/progress.c b/lib/progress.c
index 740ff2887..00609d9ee 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -134,7 +134,7 @@ int Curl_pgrsDone(struct connectdata *conn)
 {
   int rc;
   struct Curl_easy *data = conn->data;
-  data->progress.lastshow=0;
+  data->progress.lastshow = 0;
   rc = Curl_pgrsUpdate(conn); /* the final (forced) update */
   if(rc)
     return rc;
@@ -149,14 +149,9 @@ int Curl_pgrsDone(struct connectdata *conn)
   return 0;
 }
 
-/* reset all times except redirect, and reset the known transfer sizes */
-void Curl_pgrsResetTimesSizes(struct Curl_easy *data)
+/* reset the known transfer sizes */
+void Curl_pgrsResetTransferSizes(struct Curl_easy *data)
 {
-  data->progress.t_nslookup = 0;
-  data->progress.t_connect = 0;
-  data->progress.t_pretransfer = 0;
-  data->progress.t_starttransfer = 0;
-
   Curl_pgrsSetDownloadSize(data, -1);
   Curl_pgrsSetUploadSize(data, -1);
 }
@@ -181,6 +176,7 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
   case TIMER_STARTSINGLE:
     /* This is set at the start of each single fetch */
     data->progress.t_startsingle = now;
+    data->progress.is_t_startransfer_set = false;
     break;
   case TIMER_STARTACCEPT:
     data->progress.t_acceptdata = now;
@@ -205,10 +201,11 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
      * This prevents repeated invocations of the function from incorrectly
      * changing the t_starttransfer time.
      */
-    if (*delta > data->progress.t_redirect) {
+    if(data->progress.is_t_startransfer_set) {
       return;
     }
     else {
+      data->progress.is_t_startransfer_set = true;
       break;
     }
   case TIMER_POSTRANSFER:
@@ -222,7 +219,7 @@ void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
     time_t us = Curl_tvdiff_us(now, data->progress.t_startsingle);
     if(!us)
       us++; /* make sure at least one microsecond passed */
-    *delta = us;
+    *delta += us;
   }
 }
 
@@ -230,6 +227,7 @@ void Curl_pgrsStartNow(struct Curl_easy *data)
 {
   data->progress.speeder_c = 0; /* reset the progress meter display */
   data->progress.start = Curl_tvnow();
+  data->progress.is_t_startransfer_set = false;
   data->progress.ul_limit_start.tv_sec = 0;
   data->progress.ul_limit_start.tv_usec = 0;
   data->progress.dl_limit_start.tv_sec = 0;
@@ -354,9 +352,9 @@ int Curl_pgrsUpdate(struct connectdata *conn)
   struct curltime now;
   int result;
   char max5[6][10];
-  curl_off_t dlpercen=0;
-  curl_off_t ulpercen=0;
-  curl_off_t total_percen=0;
+  curl_off_t dlpercen = 0;
+  curl_off_t ulpercen = 0;
+  curl_off_t total_percen = 0;
   curl_off_t total_transfer;
   curl_off_t total_expected_transfer;
   curl_off_t timespent;
@@ -367,10 +365,10 @@ int Curl_pgrsUpdate(struct connectdata *conn)
   char time_left[10];
   char time_total[10];
   char time_spent[10];
-  curl_off_t ulestimate=0;
-  curl_off_t dlestimate=0;
+  curl_off_t ulestimate = 0;
+  curl_off_t dlestimate = 0;
   curl_off_t total_estimate;
-  bool shownow=FALSE;
+  bool shownow = FALSE;
 
   now = Curl_tvnow(); /* what time is it */
 
@@ -410,7 +408,7 @@ int Curl_pgrsUpdate(struct connectdata *conn)
        array. With N_ENTRIES filled in, we have about N_ENTRIES-1 seconds of
        transfer. Imagine, after one second we have filled in two entries,
        after two seconds we've filled in three entries etc. */
-    countindex = ((data->progress.speeder_c>=CURR_TIME)?
+    countindex = ((data->progress.speeder_c >= CURR_TIME)?
                   CURR_TIME:data->progress.speeder_c) - 1;
 
     /* first of all, we don't do this if there's no counted seconds yet */
@@ -420,14 +418,14 @@ int Curl_pgrsUpdate(struct connectdata *conn)
       /* Get the index position to compare with the 'nowindex' position.
          Get the oldest entry possible. While we have less than CURR_TIME
          entries, the first entry will remain the oldest. */
-      checkindex = (data->progress.speeder_c>=CURR_TIME)?
+      checkindex = (data->progress.speeder_c >= CURR_TIME)?
         data->progress.speeder_c%CURR_TIME:0;
 
       /* Figure out the exact time for the time span */
       span_ms = Curl_tvdiff(now,
                             data->progress.speeder_time[checkindex]);
       if(0 == span_ms)
-        span_ms=1; /* at least one millisecond MUST have passed */
+        span_ms = 1; /* at least one millisecond MUST have passed */
 
       /* Calculate the average speed the last 'span_ms' milliseconds */
       {
@@ -457,22 +455,22 @@ int Curl_pgrsUpdate(struct connectdata *conn)
 
     if(data->set.fxferinfo) {
       /* There's a callback set, call that */
-      result= data->set.fxferinfo(data->set.progress_client,
-                                  data->progress.size_dl,
-                                  data->progress.downloaded,
-                                  data->progress.size_ul,
-                                  data->progress.uploaded);
+      result = data->set.fxferinfo(data->set.progress_client,
+                                   data->progress.size_dl,
+                                   data->progress.downloaded,
+                                   data->progress.size_ul,
+                                   data->progress.uploaded);
       if(result)
         failf(data, "Callback aborted");
       return result;
     }
     if(data->set.fprogress) {
       /* The older deprecated callback is set, call that */
-      result= data->set.fprogress(data->set.progress_client,
-                                  (double)data->progress.size_dl,
-                                  (double)data->progress.downloaded,
-                                  (double)data->progress.size_ul,
-                                  (double)data->progress.uploaded);
+      result = data->set.fprogress(data->set.progress_client,
+                                   (double)data->progress.size_dl,
+                                   (double)data->progress.downloaded,
+                                   (double)data->progress.size_ul,
+                                   (double)data->progress.uploaded);
       if(result)
         failf(data, "Callback aborted");
       return result;
diff --git a/lib/progress.h b/lib/progress.h
index ed57e3368..9333ab25c 100644
--- a/lib/progress.h
+++ b/lib/progress.h
@@ -47,7 +47,7 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, 
curl_off_t size);
 void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size);
 void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size);
 int Curl_pgrsUpdate(struct connectdata *);
-void Curl_pgrsResetTimesSizes(struct Curl_easy *data);
+void Curl_pgrsResetTransferSizes(struct Curl_easy *data);
 void Curl_pgrsTime(struct Curl_easy *data, timerid timer);
 long Curl_pgrsLimitWaitTime(curl_off_t cursize,
                             curl_off_t startsize,
diff --git a/lib/rtsp.c b/lib/rtsp.c
index 8b895ed64..d3e62aada 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -250,7 +250,7 @@ static CURLcode rtsp_done(struct connectdata *conn,
 static CURLcode rtsp_do(struct connectdata *conn, bool *done)
 {
   struct Curl_easy *data = conn->data;
-  CURLcode result=CURLE_OK;
+  CURLcode result = CURLE_OK;
   Curl_RtspReq rtspreq = data->set.rtspreq;
   struct RTSP *rtsp = data->req.protop;
   struct HTTP *http;
@@ -749,14 +749,28 @@ CURLcode rtp_client_write(struct connectdata *conn, char 
*ptr, size_t len)
   struct Curl_easy *data = conn->data;
   size_t wrote;
   curl_write_callback writeit;
+  void *user_ptr;
 
   if(len == 0) {
     failf(data, "Cannot write a 0 size RTP packet.");
     return CURLE_WRITE_ERROR;
   }
 
-  writeit = data->set.fwrite_rtp?data->set.fwrite_rtp:data->set.fwrite_func;
-  wrote = writeit(ptr, 1, len, data->set.rtp_out);
+  /* If the user has configured CURLOPT_INTERLEAVEFUNCTION then use that
+     function and any configured CURLOPT_INTERLEAVEDATA to write out the RTP
+     data. Otherwise, use the CURLOPT_WRITEFUNCTION with the CURLOPT_WRITEDATA
+     pointer to write out the RTP data. */
+  if(data->set.fwrite_rtp) {
+    writeit = data->set.fwrite_rtp;
+    user_ptr = data->set.rtp_out;
+  }
+  else
+  {
+    writeit = data->set.fwrite_func;
+    user_ptr = data->set.out;
+  }
+
+  wrote = writeit(ptr, 1, len, user_ptr);
 
   if(CURL_WRITEFUNC_PAUSE == wrote) {
     failf(data, "Cannot pause RTP");
diff --git a/lib/security.c b/lib/security.c
index f4a876341..9b989681f 100644
--- a/lib/security.c
+++ b/lib/security.c
@@ -7,7 +7,7 @@
  * rewrite to work around the paragraph 2 in the BSD licenses as explained
  * below.
  *
- * Copyright (c) 1998, 1999 Kungliga Tekniska H�gskolan
+ * Copyright (c) 1998, 1999, 2017 Kungliga Tekniska H�gskolan
  * (Royal Institute of Technology, Stockholm, Sweden).
  *
  * Copyright (C) 2001 - 2015, Daniel Stenberg, <address@hidden>, et al.
@@ -115,7 +115,7 @@ static char level_to_char(int level)
 static int ftp_send_command(struct connectdata *conn, const char *message, ...)
 {
   int ftp_code;
-  ssize_t nread=0;
+  ssize_t nread = 0;
   va_list args;
   char print_buffer[50];
 
diff --git a/lib/sendf.c b/lib/sendf.c
index 6a472fb47..d2bc10b46 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -63,7 +63,7 @@ static size_t convert_lineends(struct Curl_easy *data,
     if(*startPtr == '\n') {
       /* This block of incoming data starts with the
          previous block's LF so get rid of it */
-      memmove(startPtr, startPtr+1, size-1);
+      memmove(startPtr, startPtr + 1, size-1);
       size--;
       /* and it wasn't a bare CR but a CRLF conversion instead */
       data->state.crlf_conversions++;
@@ -75,7 +75,7 @@ static size_t convert_lineends(struct Curl_easy *data,
   inPtr = outPtr = memchr(startPtr, '\r', size);
   if(inPtr) {
     /* at least one CR, now look for CRLF */
-    while(inPtr < (startPtr+size-1)) {
+    while(inPtr < (startPtr + size-1)) {
       /* note that it's size-1, so we'll never look past the last byte */
       if(memcmp(inPtr, "\r\n", 2) == 0) {
         /* CRLF found, bump past the CR and copy the NL */
@@ -98,7 +98,7 @@ static size_t convert_lineends(struct Curl_easy *data,
       inPtr++;
     } /* end of while loop */
 
-    if(inPtr < startPtr+size) {
+    if(inPtr < startPtr + size) {
       /* handle last byte */
       if(*inPtr == '\r') {
         /* deal with a CR at the end of the buffer */
@@ -112,7 +112,7 @@ static size_t convert_lineends(struct Curl_easy *data,
       }
       outPtr++;
     }
-    if(outPtr < startPtr+size)
+    if(outPtr < startPtr + size)
       /* tidy up by null terminating the now shorter data */
       *outPtr = '\0';
 
@@ -279,7 +279,7 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct 
connectdata *conn,
   if(!s)
     return CURLE_OUT_OF_MEMORY; /* failure */
 
-  bytes_written=0;
+  bytes_written = 0;
   write_len = strlen(s);
   sptr = s;
 
@@ -387,7 +387,7 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
 #endif
       ) {
       /* this is just a case of EWOULDBLOCK */
-      bytes_written=0;
+      bytes_written = 0;
       *code = CURLE_AGAIN;
     }
     else {
@@ -480,7 +480,7 @@ static CURLcode pausewrite(struct Curl_easy *data,
   bool newtype = TRUE;
 
   if(s->tempcount) {
-    for(i=0; i< s->tempcount; i++) {
+    for(i = 0; i< s->tempcount; i++) {
       if(s->tempwrite[i].type == type) {
         /* data for this type exists */
         newtype = FALSE;
@@ -704,7 +704,7 @@ CURLcode Curl_read(struct connectdata *conn, /* connection 
data */
      us use the correct ssl handle. */
   int num = (sockfd == conn->sock[SECONDARYSOCKET]);
 
-  *n=0; /* reset amount to zero */
+  *n = 0; /* reset amount to zero */
 
   /* If session can pipeline, check connection buffer  */
   if(pipelining) {
@@ -823,8 +823,8 @@ int Curl_debug(struct Curl_easy *data, curl_infotype type,
   int rc;
   if(data->set.printhost && conn && conn->host.dispname) {
     char buffer[160];
-    const char *t=NULL;
-    const char *w="Data";
+    const char *t = NULL;
+    const char *w = "Data";
     switch(type) {
     case CURLINFO_HEADER_IN:
       w = "Header";
diff --git a/lib/smtp.c b/lib/smtp.c
index 9f9bd1485..971236db7 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -67,6 +67,7 @@
 #include "transfer.h"
 #include "escape.h"
 #include "http.h" /* for HTTP proxy tunnel stuff */
+#include "mime.h"
 #include "socks.h"
 #include "smtp.h"
 #include "strtoofft.h"
@@ -530,8 +531,40 @@ static CURLcode smtp_perform_mail(struct connectdata *conn)
     }
   }
 
+  /* Prepare the mime data if some. */
+  if(data->set.mimepost.kind != MIMEKIND_NONE) {
+    /* Use the whole structure as data. */
+    data->set.mimepost.flags &= ~MIME_BODY_ONLY;
+
+    /* Add external headers and mime version. */
+    curl_mime_headers(&data->set.mimepost, data->set.headers, 0);
+    result = Curl_mime_prepare_headers(&data->set.mimepost, NULL,
+                                       NULL, MIMESTRATEGY_MAIL);
+
+    if(!result)
+      if(!Curl_checkheaders(conn, "Mime-Version"))
+        result = Curl_mime_add_header(&data->set.mimepost.curlheaders,
+                                      "Mime-Version: 1.0");
+
+    /* Make sure we will read the entire mime structure. */
+    if(!result)
+      result = Curl_mime_rewind(&data->set.mimepost);
+
+    if(result) {
+      free(from);
+      free(auth);
+      return result;
+    }
+
+    data->state.infilesize = Curl_mime_size(&data->set.mimepost);
+
+    /* Read from mime structure. */
+    data->state.fread_func = (curl_read_callback) Curl_mime_read;
+    data->state.in = (void *) &data->set.mimepost;
+  }
+
   /* Calculate the optional SIZE parameter */
-  if(conn->proto.smtpc.size_supported && conn->data->state.infilesize > 0) {
+  if(conn->proto.smtpc.size_supported && data->state.infilesize > 0) {
     size = aprintf("%" CURL_FORMAT_CURL_OFF_T, data->state.infilesize);
 
     if(!size) {
@@ -1159,7 +1192,8 @@ static CURLcode smtp_done(struct connectdata *conn, 
CURLcode status,
     connclose(conn, "SMTP done with bad status"); /* marked for closure */
     result = status;         /* use the already set error code */
   }
-  else if(!data->set.connect_only && data->set.upload && data->set.mail_rcpt) {
+  else if(!data->set.connect_only && data->set.mail_rcpt &&
+          (data->set.upload || data->set.mimepost.kind)) {
     /* Calculate the EOB taking into account any terminating CRLF from the
        previous line of the email or the CRLF of the DATA command when there
        is "no mail data". RFC-5321, sect. 4.1.1.4.
@@ -1249,7 +1283,7 @@ static CURLcode smtp_perform(struct connectdata *conn, 
bool *connected,
   smtp->rcpt = data->set.mail_rcpt;
 
   /* Start the first command in the DO phase */
-  if(data->set.upload && data->set.mail_rcpt)
+  if((data->set.upload || data->set.mimepost.kind) && data->set.mail_rcpt)
     /* MAIL transfer */
     result = smtp_perform_mail(conn);
   else
diff --git a/lib/socks.c b/lib/socks.c
index 000cd9c2d..e64cb98d4 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -154,7 +154,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
   /* DNS resolve only for SOCKS4, not SOCKS4a */
   if(!protocol4a) {
     struct Curl_dns_entry *dns;
-    Curl_addrinfo *hp=NULL;
+    Curl_addrinfo *hp = NULL;
     int rc;
 
     rc = Curl_resolv(conn, hostname, remote_port, &dns);
@@ -171,7 +171,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
      * returns a Curl_addrinfo pointer that may not always look the same.
      */
     if(dns)
-      hp=dns->addr;
+      hp = dns->addr;
     if(hp) {
       char buf[64];
       Curl_printable_address(hp, buf, sizeof(buf));
@@ -213,7 +213,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
       return CURLE_COULDNT_CONNECT;
     }
     /* copy the proxy name WITH trailing zero */
-    memcpy(socksreq + 8, proxy_user, plen+1);
+    memcpy(socksreq + 8, proxy_user, plen + 1);
   }
 
   /*
@@ -306,7 +306,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
             ", request rejected or failed.",
             (unsigned char)socksreq[4], (unsigned char)socksreq[5],
             (unsigned char)socksreq[6], (unsigned char)socksreq[7],
-            (((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
+            (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
             (unsigned char)socksreq[1]);
       return CURLE_COULDNT_CONNECT;
     case 92:
@@ -316,7 +316,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
             "identd on the client.",
             (unsigned char)socksreq[4], (unsigned char)socksreq[5],
             (unsigned char)socksreq[6], (unsigned char)socksreq[7],
-            (((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
+            (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
             (unsigned char)socksreq[1]);
       return CURLE_COULDNT_CONNECT;
     case 93:
@@ -326,7 +326,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
             "report different user-ids.",
             (unsigned char)socksreq[4], (unsigned char)socksreq[5],
             (unsigned char)socksreq[6], (unsigned char)socksreq[7],
-            (((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
+            (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
             (unsigned char)socksreq[1]);
       return CURLE_COULDNT_CONNECT;
     default:
@@ -335,7 +335,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
             ", Unknown.",
             (unsigned char)socksreq[4], (unsigned char)socksreq[5],
             (unsigned char)socksreq[6], (unsigned char)socksreq[7],
-            (((unsigned char)socksreq[8] << 8) | (unsigned char)socksreq[9]),
+            (((unsigned char)socksreq[2] << 8) | (unsigned char)socksreq[3]),
             (unsigned char)socksreq[1]);
       return CURLE_COULDNT_CONNECT;
     }
@@ -483,7 +483,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
 
   (void)curlx_nonblock(sock, FALSE);
 
-  result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
+  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;
@@ -542,7 +542,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
       return CURLE_COULDNT_CONNECT;
     }
 
-    result=Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
+    result = Curl_blockread_all(conn, sock, (char *)socksreq, 2, &actualread);
     if(result || (actualread != 2)) {
       failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
       return CURLE_COULDNT_CONNECT;
@@ -615,7 +615,7 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
      * returns a Curl_addrinfo pointer that may not always look the same.
      */
     if(dns)
-      hp=dns->addr;
+      hp = dns->addr;
     if(hp) {
       int i;
       char buf[64];
diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c
index 54d063504..96948ac4b 100644
--- a/lib/socks_gssapi.c
+++ b/lib/socks_gssapi.c
@@ -5,8 +5,8 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2009, 2011, Markus Moeller, <address@hidden>
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2009, Markus Moeller, <address@hidden>
+ * Copyright (C) 2012 - 2017, 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
@@ -65,7 +65,7 @@ static int check_gss_err(struct Curl_easy *data,
                                     &msg_ctx, &status_string);
       if(maj_stat == GSS_S_COMPLETE) {
         if(sizeof(buf) > len + status_string.length + 1) {
-          strcpy(buf+len, (char *) status_string.value);
+          strcpy(buf + len, (char *) status_string.value);
           len += status_string.length;
         }
         gss_release_buffer(&min_stat, &status_string);
@@ -74,7 +74,7 @@ static int check_gss_err(struct Curl_easy *data,
       gss_release_buffer(&min_stat, &status_string);
     }
     if(sizeof(buf) > len + 3) {
-      strcpy(buf+len, ".\n");
+      strcpy(buf + len, ".\n");
       len += 2;
     }
     msg_ctx = 0;
@@ -86,7 +86,7 @@ static int check_gss_err(struct Curl_easy *data,
                                     &msg_ctx, &status_string);
       if(maj_stat == GSS_S_COMPLETE) {
         if(sizeof(buf) > len + status_string.length)
-          strcpy(buf+len, (char *) status_string.value);
+          strcpy(buf + len, (char *) status_string.value);
         gss_release_buffer(&min_stat, &status_string);
         break;
       }
@@ -119,7 +119,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
   gss_name_t       server = GSS_C_NO_NAME;
   gss_name_t       gss_client_name = GSS_C_NO_NAME;
   unsigned short   us_length;
-  char             *user=NULL;
+  char             *user = NULL;
   unsigned char socksreq[4]; /* room for GSS-API exchange header only */
   const char *serviceptr = data->set.str[STRING_PROXY_SERVICE_NAME] ?
                            data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
@@ -146,11 +146,12 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
   }
   else {
     service.value = malloc(serviceptr_length +
-                           strlen(conn->socks_proxy.host.name)+2);
+                           strlen(conn->socks_proxy.host.name) + 2);
     if(!service.value)
       return CURLE_OUT_OF_MEMORY;
-    service.length = serviceptr_length + strlen(conn->socks_proxy.host.name)+1;
-    snprintf(service.value, service.length+1, "address@hidden",
+    service.length = serviceptr_length +
+      strlen(conn->socks_proxy.host.name) + 1;
+    snprintf(service.value, service.length + 1, "address@hidden",
              serviceptr, conn->socks_proxy.host.name);
 
     gss_major_status = gss_import_name(&gss_minor_status, &service,
@@ -196,7 +197,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
       socksreq[0] = 1;    /* GSS-API subnegotiation version */
       socksreq[1] = 1;    /* authentication message type */
       us_length = htons((short)gss_send_token.length);
-      memcpy(socksreq+2, &us_length, sizeof(short));
+      memcpy(socksreq + 2, &us_length, sizeof(short));
 
       code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
       if(code || (4 != written)) {
@@ -236,7 +237,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
      * +----+------+-----+----------------+
      */
 
-    result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+    result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
     if(result || (actualread != 4)) {
       failf(data, "Failed to receive GSS-API authentication response.");
       gss_release_name(&gss_status, &server);
@@ -261,11 +262,11 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
       return CURLE_COULDNT_CONNECT;
     }
 
-    memcpy(&us_length, socksreq+2, sizeof(short));
+    memcpy(&us_length, socksreq + 2, sizeof(short));
     us_length = ntohs(us_length);
 
-    gss_recv_token.length=us_length;
-    gss_recv_token.value=malloc(us_length);
+    gss_recv_token.length = us_length;
+    gss_recv_token.value = malloc(us_length);
     if(!gss_recv_token.value) {
       failf(data,
             "Could not allocate memory for GSS-API authentication "
@@ -275,8 +276,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
       return CURLE_OUT_OF_MEMORY;
     }
 
-    result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
-                              gss_recv_token.length, &actualread);
+    result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
+                                gss_recv_token.length, &actualread);
 
     if(result || (actualread != us_length)) {
       failf(data, "Failed to receive GSS-API authentication token.");
@@ -312,7 +313,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     failf(data, "Failed to determine user name.");
     return CURLE_COULDNT_CONNECT;
   }
-  user=malloc(gss_send_token.length+1);
+  user = malloc(gss_send_token.length + 1);
   if(!user) {
     gss_delete_sec_context(&gss_status, &gss_context, NULL);
     gss_release_name(&gss_status, &gss_client_name);
@@ -326,7 +327,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
   gss_release_buffer(&gss_status, &gss_send_token);
   infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",user);
   free(user);
-  user=NULL;
+  user = NULL;
 
   /* Do encryption */
   socksreq[0] = 1;    /* GSS-API subnegotiation version */
@@ -341,7 +342,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     gss_enc = 1;
 
   infof(data, "SOCKS5 server supports GSS-API %s data protection.\n",
-        (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality"));
+        (gss_enc == 0)?"no":((gss_enc==1)?"integrity":"confidentiality"));
   /* force for the moment to no data protection */
   gss_enc = 0;
   /*
@@ -376,7 +377,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
    */
   if(data->set.socks5_gssapi_nec) {
     us_length = htons((short)1);
-    memcpy(socksreq+2, &us_length, sizeof(short));
+    memcpy(socksreq + 2, &us_length, sizeof(short));
   }
   else {
     gss_send_token.length = 1;
@@ -401,7 +402,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     gss_release_buffer(&gss_status, &gss_send_token);
 
     us_length = htons((short)gss_w_token.length);
-    memcpy(socksreq+2, &us_length, sizeof(short));
+    memcpy(socksreq + 2, &us_length, sizeof(short));
   }
 
   code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
@@ -433,7 +434,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     gss_release_buffer(&gss_status, &gss_w_token);
   }
 
-  result=Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
+  result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
   if(result || (actualread != 4)) {
     failf(data, "Failed to receive GSS-API encryption response.");
     gss_delete_sec_context(&gss_status, &gss_context, NULL);
@@ -455,17 +456,17 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     return CURLE_COULDNT_CONNECT;
   }
 
-  memcpy(&us_length, socksreq+2, sizeof(short));
+  memcpy(&us_length, socksreq + 2, sizeof(short));
   us_length = ntohs(us_length);
 
-  gss_recv_token.length= us_length;
-  gss_recv_token.value=malloc(gss_recv_token.length);
+  gss_recv_token.length = us_length;
+  gss_recv_token.value = malloc(gss_recv_token.length);
   if(!gss_recv_token.value) {
     gss_delete_sec_context(&gss_status, &gss_context, NULL);
     return CURLE_OUT_OF_MEMORY;
   }
-  result=Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
-                            gss_recv_token.length, &actualread);
+  result = Curl_blockread_all(conn, sock, (char *)gss_recv_token.value,
+                              gss_recv_token.length, &actualread);
 
   if(result || (actualread != us_length)) {
     failf(data, "Failed to receive GSS-API encryptrion type.");
@@ -513,8 +514,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
   }
 
   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"));
+        (socksreq[0] == 0)?"out GSS-API data":
+        ((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality"));
 
   conn->socks5_gssapi_enctype = socksreq[0];
   if(socksreq[0] == 0)
diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c
index edc73ad2e..34699d374 100644
--- a/lib/socks_sspi.c
+++ b/lib/socks_sspi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2012 - 2017, 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
@@ -108,7 +108,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     if(!service_name)
       return CURLE_OUT_OF_MEMORY;
     snprintf(service_name, service_length +
-             strlen(conn->socks_proxy.host.name)+2, "%s/%s",
+             strlen(conn->socks_proxy.host.name) + 2, "%s/%s",
              service, conn->socks_proxy.host.name);
   }
 
@@ -199,7 +199,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
       socksreq[0] = 1;    /* GSS-API subnegotiation version */
       socksreq[1] = 1;    /* authentication message type */
       us_length = htons((short)sspi_send_token.cbBuffer);
-      memcpy(socksreq+2, &us_length, sizeof(short));
+      memcpy(socksreq + 2, &us_length, sizeof(short));
 
       code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
       if(code || (4 != written)) {
@@ -283,7 +283,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
       return CURLE_COULDNT_CONNECT;
     }
 
-    memcpy(&us_length, socksreq+2, sizeof(short));
+    memcpy(&us_length, socksreq + 2, sizeof(short));
     us_length = ntohs(us_length);
 
     sspi_recv_token.cbBuffer = us_length;
@@ -341,7 +341,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     gss_enc = 1;
 
   infof(data, "SOCKS5 server supports GSS-API %s data protection.\n",
-        (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality") );
+        (gss_enc == 0)?"no":((gss_enc == 1)?"integrity":"confidentiality") );
   /* force to no data protection, avoid encryption/decryption for now */
   gss_enc = 0;
   /*
@@ -377,7 +377,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
 
   if(data->set.socks5_gssapi_nec) {
     us_length = htons((short)1);
-    memcpy(socksreq+2, &us_length, sizeof(short));
+    memcpy(socksreq + 2, &us_length, sizeof(short));
   }
   else {
     status = s_pSecFn->QueryContextAttributes(&sspi_context,
@@ -445,8 +445,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     memcpy((PUCHAR) sspi_send_token.pvBuffer +(int)sspi_w_token[0].cbBuffer,
            sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
     memcpy((PUCHAR) sspi_send_token.pvBuffer
-           +sspi_w_token[0].cbBuffer
-           +sspi_w_token[1].cbBuffer,
+           + sspi_w_token[0].cbBuffer
+           + sspi_w_token[1].cbBuffer,
            sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer);
 
     s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
@@ -460,7 +460,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     sspi_w_token[2].cbBuffer = 0;
 
     us_length = htons((short)sspi_send_token.cbBuffer);
-    memcpy(socksreq+2, &us_length, sizeof(short));
+    memcpy(socksreq + 2, &us_length, sizeof(short));
   }
 
   code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
@@ -517,7 +517,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
     return CURLE_COULDNT_CONNECT;
   }
 
-  memcpy(&us_length, socksreq+2, sizeof(short));
+  memcpy(&us_length, socksreq + 2, sizeof(short));
   us_length = ntohs(us_length);
 
   sspi_w_token[0].cbBuffer = us_length;
@@ -588,8 +588,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
   }
 
   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"));
+        (socksreq[0] == 0)?"out GSS-API data":
+        ((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality"));
 
   /* For later use if encryption is required
      conn->socks5_gssapi_enctype = socksreq[0];
diff --git a/lib/splay.c b/lib/splay.c
index 68ff9c5db..69af446eb 100644
--- a/lib/splay.c
+++ b/lib/splay.c
@@ -110,7 +110,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i,
 
   if(t != NULL) {
     t = Curl_splay(i, t);
-    if(compare(i, t->key)==0) {
+    if(compare(i, t->key) == 0) {
       /* There already exists a node in the tree with the very same key. Build
          a doubly-linked circular list of nodes. We add the new 'node' struct
          to the end of this list. */
diff --git a/lib/splay.h b/lib/splay.h
index 0273bad38..4612ec271 100644
--- a/lib/splay.h
+++ b/lib/splay.h
@@ -54,8 +54,8 @@ int Curl_splayremovebyaddr(struct Curl_tree *t,
                            struct Curl_tree *removenode,
                            struct Curl_tree **newroot);
 
-#define Curl_splaycomparekeys(i,j) ( ((i.tv_sec)  < (j.tv_sec))  ? -1 : \
-                                   ( ((i.tv_sec)  > (j.tv_sec))  ?  1 : \
+#define Curl_splaycomparekeys(i,j) ( ((i.tv_sec)  < (j.tv_sec)) ? -1 : \
+                                   ( ((i.tv_sec)  > (j.tv_sec)) ?  1 : \
                                    ( ((i.tv_usec) < (j.tv_usec)) ? -1 : \
                                    ( ((i.tv_usec) > (j.tv_usec)) ?  1 : 0))))
 
diff --git a/lib/ssh.c b/lib/ssh.c
index 3831f71a7..ae717f9cc 100644
--- a/lib/ssh.c
+++ b/lib/ssh.c
@@ -428,14 +428,14 @@ static CURLcode ssh_getworkingpath(struct connectdata 
*conn,
 
   /* Check for /~/, indicating relative to the user's home directory */
   if(conn->handler->protocol & CURLPROTO_SCP) {
-    real_path = malloc(working_path_len+1);
+    real_path = malloc(working_path_len + 1);
     if(real_path == NULL) {
       free(working_path);
       return CURLE_OUT_OF_MEMORY;
     }
     if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3)))
       /* It is referenced to the home directory, so strip the leading '/~/' */
-      memcpy(real_path, working_path+3, 4 + working_path_len-3);
+      memcpy(real_path, working_path + 3, 4 + working_path_len-3);
     else
       memcpy(real_path, working_path, 1 + working_path_len);
   }
@@ -451,19 +451,19 @@ static CURLcode ssh_getworkingpath(struct connectdata 
*conn,
          leading '/' */
       memcpy(real_path, homedir, homelen);
       real_path[homelen] = '/';
-      real_path[homelen+1] = '\0';
+      real_path[homelen + 1] = '\0';
       if(working_path_len > 3) {
-        memcpy(real_path+homelen+1, working_path + 3,
+        memcpy(real_path + homelen + 1, working_path + 3,
                1 + working_path_len -3);
       }
     }
     else {
-      real_path = malloc(working_path_len+1);
+      real_path = malloc(working_path_len + 1);
       if(real_path == NULL) {
         free(working_path);
         return CURLE_OUT_OF_MEMORY;
       }
-      memcpy(real_path, working_path, 1+working_path_len);
+      memcpy(real_path, working_path, 1 + working_path_len);
     }
   }
 
@@ -1813,7 +1813,7 @@ static CURLcode ssh_statemach_act(struct connectdata 
*conn, bool *block)
              zero even though libssh2_sftp_open() failed previously! We need
              to work around that! */
           sshc->actualcode = CURLE_SSH;
-          err=-1;
+          err = -1;
         }
         failf(data, "Upload failed: %s (%d/%d)",
               err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error",
@@ -1831,7 +1831,7 @@ static CURLcode ssh_statemach_act(struct connectdata 
*conn, bool *block)
         }
 
         if(seekerr != CURL_SEEKFUNC_OK) {
-          curl_off_t passed=0;
+          curl_off_t passed = 0;
 
           if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
             failf(data, "Could not seek stream");
@@ -1983,13 +1983,13 @@ static CURLcode ssh_statemach_act(struct connectdata 
*conn, bool *block)
         sshc->actualcode = result?result:CURLE_SSH;
         break;
       }
-      sshc->readdir_filename = malloc(PATH_MAX+1);
+      sshc->readdir_filename = malloc(PATH_MAX + 1);
       if(!sshc->readdir_filename) {
         state(conn, SSH_SFTP_CLOSE);
         sshc->actualcode = CURLE_OUT_OF_MEMORY;
         break;
       }
-      sshc->readdir_longentry = malloc(PATH_MAX+1);
+      sshc->readdir_longentry = malloc(PATH_MAX + 1);
       if(!sshc->readdir_longentry) {
         Curl_safefree(sshc->readdir_filename);
         state(conn, SSH_SFTP_CLOSE);
@@ -2023,7 +2023,7 @@ static CURLcode ssh_statemach_act(struct connectdata 
*conn, bool *block)
             break;
           }
           result = Curl_client_write(conn, CLIENTWRITE_BODY,
-                                     tmpLine, sshc->readdir_len+1);
+                                     tmpLine, sshc->readdir_len + 1);
           free(tmpLine);
 
           if(result) {
@@ -2032,7 +2032,7 @@ static CURLcode ssh_statemach_act(struct connectdata 
*conn, bool *block)
           }
           /* since this counts what we send to the client, we include the
              newline in this counter */
-          data->req.bytecount += sshc->readdir_len+1;
+          data->req.bytecount += sshc->readdir_len + 1;
 
           /* output debug output if that is requested */
           if(data->set.verbose) {
@@ -2233,18 +2233,25 @@ static CURLcode ssh_statemach_act(struct connectdata 
*conn, bool *block)
           curl_off_t from, to;
           char *ptr;
           char *ptr2;
+          CURLofft to_t;
+          CURLofft from_t;
 
-          from=curlx_strtoofft(conn->data->state.range, &ptr, 0);
-          while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
+          from_t = curlx_strtoofft(conn->data->state.range, &ptr, 0, &from);
+          if(from_t == CURL_OFFT_FLOW)
+            return CURLE_RANGE_ERROR;
+          while(*ptr && (ISSPACE(*ptr) || (*ptr == '-')))
             ptr++;
-          to=curlx_strtoofft(ptr, &ptr2, 0);
-          if((ptr == ptr2) /* no "to" value given */
+          to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
+          if(to_t == CURL_OFFT_FLOW)
+            return CURLE_RANGE_ERROR;
+          if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
              || (to >= size)) {
             to = size - 1;
           }
-          if(from < 0) {
+          if(from_t) {
             /* from is relative to end of file */
-            from += size;
+            from = size - to;
+            to = size - 1;
           }
           if(from > size) {
             failf(data, "Offset (%"
@@ -2935,6 +2942,13 @@ static CURLcode ssh_connect(struct connectdata *conn, 
bool *done)
     return CURLE_FAILED_INIT;
   }
 
+  if(data->set.ssh_compression) {
+#if LIBSSH2_VERSION_NUM >= 0x010208
+    if(libssh2_session_flag(ssh->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0)
+#endif
+      infof(data, "Failed to enable compression for ssh session\n");
+  }
+
 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
   if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
     int rc;
@@ -3031,8 +3045,8 @@ static CURLcode ssh_do(struct connectdata *conn, bool 
*done)
   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 */
+  sshc->secondCreateDirs = 0;   /* reset the create dir attempt state
+                                   variable */
 
   Curl_pgrsSetUploadCounter(data, 0);
   Curl_pgrsSetDownloadCounter(data, 0);
diff --git a/lib/strcase.c b/lib/strcase.c
index c4a06bedb..c6732ff78 100644
--- a/lib/strcase.c
+++ b/lib/strcase.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -94,10 +94,11 @@ char Curl_raw_toupper(char in)
 }
 
 /*
- * Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant
- * to be locale independent and only compare strings we know are safe for
- * this.  See https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
- * some further explanation to why this function is necessary.
+ * Curl_strcasecompare() is for doing "raw" case insensitive strings. This is
+ * meant to be locale independent and only compare strings we know are safe
+ * for this.  See
+ * https://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for some
+ * further explanation to why this function is necessary.
  *
  * The function is capable of comparing a-z case insensitively even for
  * non-ascii.
diff --git a/lib/strdup.c b/lib/strdup.c
index 8d6258e81..a671f5c55 100644
--- a/lib/strdup.c
+++ b/lib/strdup.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -44,11 +44,11 @@ char *curlx_strdup(const char *str)
   if(len >= ((size_t)-1) / sizeof(char))
     return (char *)NULL;
 
-  newstr = malloc((len+1)*sizeof(char));
+  newstr = malloc((len + 1)*sizeof(char));
   if(!newstr)
     return (char *)NULL;
 
-  memcpy(newstr, str, (len+1)*sizeof(char));
+  memcpy(newstr, str, (len + 1)*sizeof(char));
 
   return newstr;
 
diff --git a/lib/strtoofft.c b/lib/strtoofft.c
index c2adc7280..807fc5454 100644
--- a/lib/strtoofft.c
+++ b/lib/strtoofft.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 @@
  *
  ***************************************************************************/
 
+#include <errno.h>
 #include "curl_setup.h"
 
 #include "strtoofft.h"
@@ -32,7 +33,29 @@
  * https://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html
  */
 
-#ifdef NEED_CURL_STRTOLL
+#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
+#  ifdef HAVE_STRTOLL
+#    define strtooff strtoll
+#  else
+#    if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_INTEGRAL_MAX_BITS >= 64)
+#      if defined(_SAL_VERSION)
+         _Check_return_ _CRTIMP __int64 __cdecl _strtoi64(
+             _In_z_ const char *_String,
+             _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix);
+#      else
+         _CRTIMP __int64 __cdecl _strtoi64(const char *_String,
+                                           char **_EndPtr, int _Radix);
+#      endif
+#      define strtooff _strtoi64
+#    else
+#      define PRIVATE_STRTOOFF 1
+#    endif
+#  endif
+#else
+#  define strtooff strtol
+#endif
+
+#ifdef PRIVATE_STRTOOFF
 
 /* Range tests can be used for alphanum decoding if characters are consecutive,
    like in ASCII. Else an array is scanned. Determine this condition now. */
@@ -48,11 +71,10 @@ static const char valchars[] =
 static int get_char(char c, int base);
 
 /**
- * Emulated version of the strtoll function.  This extracts a long long
+ * Custom version of the strtooff function.  This extracts a curl_off_t
  * value from the given input string and returns it.
  */
-curl_off_t
-curlx_strtoll(const char *nptr, char **endptr, int base)
+static curl_off_t strtooff(const char *nptr, char **endptr, int base)
 {
   char *end;
   int is_negative = 0;
@@ -186,3 +208,34 @@ static int get_char(char c, int base)
   return value;
 }
 #endif  /* Only present if we need strtoll, but don't have it. */
+
+/*
+ * Parse a *positive* up to 64 bit number written in ascii.
+ */
+CURLofft curlx_strtoofft(const char *str, char **endp, int base,
+                         curl_off_t *num)
+{
+  char *end;
+  curl_off_t number;
+  errno = 0;
+  *num = 0; /* clear by default */
+  while(str && *str && ISSPACE(*str))
+    str++;
+  if('-' == *str) {
+    if(endp)
+      *endp = (char *)str; /* didn't actually move */
+    return CURL_OFFT_INVAL; /* nothing parsed */
+  }
+  number = strtooff(str, &end, base);
+  if(endp)
+    *endp = end;
+  if(errno == ERANGE)
+    /* overflow/underflow */
+    return CURL_OFFT_FLOW;
+  else if(str == end)
+    /* nothing parsed */
+    return CURL_OFFT_INVAL;
+
+  *num = number;
+  return CURL_OFFT_OK;
+}
diff --git a/lib/strtoofft.h b/lib/strtoofft.h
index f4039f3a3..244411a87 100644
--- a/lib/strtoofft.h
+++ b/lib/strtoofft.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,31 +40,7 @@
  * of 'long' the conversion function to use is strtol().
  */
 
-#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
-#  ifdef HAVE_STRTOLL
-#    define curlx_strtoofft strtoll
-#  else
-#    if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_INTEGRAL_MAX_BITS >= 64)
-#      if defined(_SAL_VERSION)
-         _Check_return_ _CRTIMP __int64 __cdecl _strtoi64(
-             _In_z_ const char *_String,
-             _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix);
-#      else
-         _CRTIMP __int64 __cdecl _strtoi64(const char *_String,
-                                           char **_EndPtr, int _Radix);
-#      endif
-#      define curlx_strtoofft _strtoi64
-#    else
-       curl_off_t curlx_strtoll(const char *nptr, char **endptr, int base);
-#      define curlx_strtoofft curlx_strtoll
-#      define NEED_CURL_STRTOLL 1
-#    endif
-#  endif
-#else
-#  define curlx_strtoofft strtol
-#endif
-
-#if (CURL_SIZEOF_CURL_OFF_T == 4)
+#if (SIZEOF_CURL_OFF_T == 4)
 #  define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF)
 #else
    /* assume CURL_SIZEOF_CURL_OFF_T == 8 */
@@ -72,4 +48,13 @@
 #endif
 #define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1))
 
+typedef enum {
+  CURL_OFFT_OK,    /* parsed fine */
+  CURL_OFFT_FLOW,  /* over or underflow */
+  CURL_OFFT_INVAL  /* nothing was parsed */
+} CURLofft;
+
+CURLofft curlx_strtoofft(const char *str, char **endp, int base,
+                         curl_off_t *num);
+
 #endif /* HEADER_CURL_STRTOOFFT_H */
diff --git a/lib/telnet.c b/lib/telnet.c
index 8ef121fec..37458fa42 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -76,7 +76,7 @@
   } WHILE_FALSE
 #define CURL_SB_ACCUM(x,c)                                   \
   do {                                                       \
-    if(x->subpointer < (x->subbuffer+sizeof x->subbuffer))   \
+    if(x->subpointer < (x->subbuffer + sizeof x->subbuffer)) \
       *x->subpointer++ = (c);                                \
   } WHILE_FALSE
 
@@ -295,8 +295,8 @@ static void negotiate(struct connectdata *conn)
   int i;
   struct TELNET *tn = (struct TELNET *) conn->data->req.protop;
 
-  for(i = 0;i < CURL_NTELOPTS;i++) {
-    if(i==CURL_TELOPT_ECHO)
+  for(i = 0; i < CURL_NTELOPTS; i++) {
+    if(i == CURL_TELOPT_ECHO)
       continue;
 
     if(tn->us_preferred[i] == CURL_YES)
@@ -792,7 +792,7 @@ static void printsub(struct Curl_easy *data,
       case CURL_TELOPT_NEW_ENVIRON:
         if(pointer[1] == CURL_TELQUAL_IS) {
           infof(data, " ");
-          for(i = 3;i < length;i++) {
+          for(i = 3; i < length; i++) {
             switch(pointer[i]) {
             case CURL_NEW_ENV_VAR:
               infof(data, ", ");
@@ -843,7 +843,7 @@ static CURLcode check_telnet_options(struct connectdata 
*conn)
     tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
   }
 
-  for(head = data->set.telnet_options; head; head=head->next) {
+  for(head = data->set.telnet_options; head; head = head->next) {
     if(sscanf(head->data, "%127[^= ]%*[ =]%255s",
               option_keyword, option_arg) == 2) {
 
@@ -890,8 +890,8 @@ static CURLcode check_telnet_options(struct connectdata 
*conn)
 
       /* To take care or not of the 8th bit in data exchange */
       if(strcasecompare(option_keyword, "BINARY")) {
-        binary_option=atoi(option_arg);
-        if(binary_option!=1) {
+        binary_option = atoi(option_arg);
+        if(binary_option != 1) {
           tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO;
           tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO;
         }
@@ -935,7 +935,7 @@ static void suboption(struct connectdata *conn)
   struct Curl_easy *data = conn->data;
   struct TELNET *tn = (struct TELNET *)data->req.protop;
 
-  printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn)+2);
+  printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn) + 2);
   switch(CURL_SB_GET(tn)) {
     case CURL_TELOPT_TTYPE:
       len = strlen(tn->subopt_ttype) + 4 + 2;
@@ -967,7 +967,7 @@ static void suboption(struct connectdata *conn)
                CURL_TELQUAL_IS);
       len = 4;
 
-      for(v = tn->telnet_vars;v;v = v->next) {
+      for(v = tn->telnet_vars; v; v = v->next) {
         tmplen = (strlen(v->data) + 1);
         /* Add the variable only if it fits */
         if(len + tmplen < (int)sizeof(temp)-6) {
@@ -1019,8 +1019,8 @@ static void sendsuboption(struct connectdata *conn, int 
option)
     CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS);
     /* We must deal either with litte or big endian processors */
     /* Window size must be sent according to the 'network order' */
-    x=htons(tn->subopt_wsx);
-    y=htons(tn->subopt_wsy);
+    x = htons(tn->subopt_wsx);
+    y = htons(tn->subopt_wsy);
     uc1 = (unsigned char *)&x;
     uc2 = (unsigned char *)&y;
     CURL_SB_ACCUM(tn, uc1[0]);
@@ -1033,7 +1033,7 @@ static void sendsuboption(struct connectdata *conn, int 
option)
     CURL_SB_TERM(tn);
     /* data suboption is now ready */
 
-    printsub(data, '>', (unsigned char *)tn->subbuffer+2,
+    printsub(data, '>', (unsigned char *)tn->subbuffer + 2,
              CURL_SB_LEN(tn)-2);
 
     /* we send the header of the suboption... */
@@ -1044,9 +1044,9 @@ static void sendsuboption(struct connectdata *conn, int 
option)
     }
     /* ... then the window size with the send_telnet_data() function
        to deal with 0xFF cases ... */
-    send_telnet_data(conn, (char *)tn->subbuffer+3, 4);
+    send_telnet_data(conn, (char *)tn->subbuffer + 3, 4);
     /* ... and the footer */
-    bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer+7, 2);
+    bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer + 7, 2);
     if(bytes_written < 0) {
       err = SOCKERRNO;
       failf(data, "Sending data failed (%d)", err);
@@ -1064,7 +1064,7 @@ CURLcode telrcv(struct connectdata *conn,
   unsigned char c;
   CURLcode result;
   int in = 0;
-  int startwrite=-1;
+  int startwrite = -1;
   struct Curl_easy *data = conn->data;
   struct TELNET *tn = (struct TELNET *)data->req.protop;
 
diff --git a/lib/tftp.c b/lib/tftp.c
index 51642c9b9..caa767127 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -76,12 +76,12 @@
 #define TFTP_OPTION_INTERVAL "timeout"
 
 typedef enum {
-  TFTP_MODE_NETASCII=0,
+  TFTP_MODE_NETASCII = 0,
   TFTP_MODE_OCTET
 } tftp_mode_t;
 
 typedef enum {
-  TFTP_STATE_START=0,
+  TFTP_STATE_START = 0,
   TFTP_STATE_RX,
   TFTP_STATE_TX,
   TFTP_STATE_FIN
@@ -100,7 +100,7 @@ typedef enum {
 } tftp_event_t;
 
 typedef enum {
-  TFTP_ERR_UNDEF=0,
+  TFTP_ERR_UNDEF = 0,
   TFTP_ERR_NOTFOUND,
   TFTP_ERR_PERM,
   TFTP_ERR_DISKFULL,
@@ -217,7 +217,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
   if(start) {
 
     maxtime = (time_t)(timeout_ms + 500) / 1000;
-    state->max_time = state->start_time+maxtime;
+    state->max_time = state->start_time + maxtime;
 
     /* Set per-block timeout to total */
     timeout = maxtime;
@@ -232,7 +232,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
     /* Compute the re-start interval to suit the timeout */
     state->retry_time = (int)timeout/state->retry_max;
     if(state->retry_time<1)
-      state->retry_time=1;
+      state->retry_time = 1;
 
   }
   else {
@@ -241,7 +241,7 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
     else
       maxtime = 3600;
 
-    state->max_time = state->start_time+maxtime;
+    state->max_time = state->start_time + maxtime;
 
     /* Set per-block timeout to total */
     timeout = maxtime;
@@ -251,15 +251,15 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t 
*state)
   }
   /* But bound the total number */
   if(state->retry_max<3)
-    state->retry_max=3;
+    state->retry_max = 3;
 
   if(state->retry_max>50)
-    state->retry_max=50;
+    state->retry_max = 50;
 
   /* Compute the re-ACK interval to suit the timeout */
   state->retry_time = (int)(timeout/state->retry_max);
   if(state->retry_time<1)
-    state->retry_time=1;
+    state->retry_time = 1;
 
   infof(state->conn->data,
         "set timeouts for state %d; Total %ld, retry %d maxtry %d\n",
@@ -321,7 +321,7 @@ static const char *tftp_option_get(const char *buf, size_t 
len,
     return NULL;
   *option = buf;
 
-  loc += Curl_strnlen(buf+loc, len-loc);
+  loc += Curl_strnlen(buf + loc, len-loc);
   loc++; /* NULL term */
 
   if(loc > len)
@@ -475,7 +475,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, 
tftp_event_t event)
       /* If we are uploading, send an WRQ */
       setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
       state->conn->data->req.upload_fromhere =
-        (char *)state->spacket.data+4;
+        (char *)state->spacket.data + 4;
       if(data->state.infilesize != -1)
         Curl_pgrsSetUploadSize(data, data->state.infilesize);
     }
@@ -493,10 +493,11 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, 
tftp_event_t event)
 
     if(strlen(filename) > (state->blksize - strlen(mode) - 4)) {
       failf(data, "TFTP file name too long\n");
+      free(filename);
       return CURLE_TFTP_ILLEGAL; /* too long file name field */
     }
 
-    snprintf((char *)state->spacket.data+2,
+    snprintf((char *)state->spacket.data + 2,
              state->blksize,
              "%s%c%s%c", filename, '\0',  mode, '\0');
     sbytes = 4 + strlen(filename) + strlen(mode);
@@ -511,25 +512,25 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, 
tftp_event_t event)
         strcpy(buf, "0"); /* the destination is large enough */
 
       sbytes += tftp_option_add(state, sbytes,
-                                (char *)state->spacket.data+sbytes,
+                                (char *)state->spacket.data + sbytes,
                                 TFTP_OPTION_TSIZE);
       sbytes += tftp_option_add(state, sbytes,
-                                (char *)state->spacket.data+sbytes, buf);
+                                (char *)state->spacket.data + sbytes, buf);
       /* add blksize option */
       snprintf(buf, sizeof(buf), "%d", state->requested_blksize);
       sbytes += tftp_option_add(state, sbytes,
-                                (char *)state->spacket.data+sbytes,
+                                (char *)state->spacket.data + sbytes,
                                 TFTP_OPTION_BLKSIZE);
       sbytes += tftp_option_add(state, sbytes,
-                                (char *)state->spacket.data+sbytes, buf);
+                                (char *)state->spacket.data + sbytes, buf);
 
       /* add timeout option */
       snprintf(buf, sizeof(buf), "%d", state->retry_time);
       sbytes += tftp_option_add(state, sbytes,
-                                (char *)state->spacket.data+sbytes,
+                                (char *)state->spacket.data + sbytes,
                                 TFTP_OPTION_INTERVAL);
       sbytes += tftp_option_add(state, sbytes,
-                                (char *)state->spacket.data+sbytes, buf);
+                                (char *)state->spacket.data + sbytes, buf);
     }
 
     /* the typecase for the 3rd argument is mostly for systems that do
@@ -575,7 +576,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, 
tftp_event_t event)
 
 /* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit
    boundary */
-#define NEXT_BLOCKNUM(x) (((x)+1)&0xffff)
+#define NEXT_BLOCKNUM(x) (((x) + 1)&0xffff)
 
 /**********************************************************
  *
@@ -626,7 +627,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, 
tftp_event_t event)
     }
 
     /* Check if completed (That is, a less than full packet is received) */
-    if(state->rbytes < (ssize_t)state->blksize+4) {
+    if(state->rbytes < (ssize_t)state->blksize + 4) {
       state->state = TFTP_STATE_FIN;
     }
     else {
@@ -742,7 +743,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, 
tftp_event_t event)
         else {
           /* Re-send the data packet */
           sbytes = sendto(state->sockfd, (void *)state->spacket.data,
-                          4+state->sbytes, SEND_4TH_ARG,
+                          4 + state->sbytes, SEND_4TH_ARG,
                           (struct sockaddr *)&state->remote_addr,
                           state->remote_addrlen);
           /* Check all sbytes were sent */
@@ -775,7 +776,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, 
tftp_event_t event)
      * data block.
      * */
     state->sbytes = 0;
-    state->conn->data->req.upload_fromhere = (char *)state->spacket.data+4;
+    state->conn->data->req.upload_fromhere = (char *)state->spacket.data + 4;
     do {
       result = Curl_fillreadbuffer(state->conn, state->blksize - state->sbytes,
                                    &cb);
@@ -812,7 +813,7 @@ static CURLcode tftp_tx(tftp_state_data_t *state, 
tftp_event_t event)
     else {
       /* Re-send the data packet */
       sbytes = sendto(state->sockfd, (void *)state->spacket.data,
-                      4+state->sbytes, SEND_4TH_ARG,
+                      4 + state->sbytes, SEND_4TH_ARG,
                       (struct sockaddr *)&state->remote_addr,
                       state->remote_addrlen);
       /* Check all sbytes were sent */
@@ -1108,11 +1109,11 @@ static CURLcode tftp_receive_packet(struct connectdata 
*conn)
   fromlen = sizeof(fromaddr);
   state->rbytes = (int)recvfrom(state->sockfd,
                                 (void *)state->rpacket.data,
-                                state->blksize+4,
+                                state->blksize + 4,
                                 0,
                                 (struct sockaddr *)&fromaddr,
                                 &fromlen);
-  if(state->remote_addrlen==0) {
+  if(state->remote_addrlen == 0) {
     memcpy(&state->remote_addr, &fromaddr, fromlen);
     state->remote_addrlen = fromlen;
   }
@@ -1134,7 +1135,7 @@ static CURLcode tftp_receive_packet(struct connectdata 
*conn)
       if(state->rbytes > 4 &&
          (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) {
         result = Curl_client_write(conn, CLIENTWRITE_BODY,
-                                   (char *)state->rpacket.data+4,
+                                   (char *)state->rpacket.data + 4,
                                    state->rbytes-4);
         if(result) {
           tftp_state_machine(state, TFTP_EVENT_ERROR);
@@ -1148,14 +1149,14 @@ static CURLcode tftp_receive_packet(struct connectdata 
*conn)
     {
       unsigned short error = getrpacketblock(&state->rpacket);
       state->error = (tftp_error_t)error;
-      infof(data, "%s\n", (const char *)state->rpacket.data+4);
+      infof(data, "%s\n", (const char *)state->rpacket.data + 4);
       break;
     }
     case TFTP_EVENT_ACK:
       break;
     case TFTP_EVENT_OACK:
       result = tftp_parse_option_ack(state,
-                                     (const char *)state->rpacket.data+2,
+                                     (const char *)state->rpacket.data + 2,
                                      state->rbytes-2);
       if(result)
         return result;
@@ -1199,7 +1200,7 @@ static long tftp_state_timeout(struct connectdata *conn, 
tftp_event_t *event)
     state->state = TFTP_STATE_FIN;
     return 0;
   }
-  if(current > state->rx_time+state->retry_time) {
+  if(current > state->rx_time + state->retry_time) {
     if(event)
       *event = TFTP_EVENT_TIMEOUT;
     time(&state->rx_time); /* update even though we received nothing */
diff --git a/lib/transfer.c b/lib/transfer.c
index f09985def..30e936407 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -73,12 +73,38 @@
 #include "connect.h"
 #include "non-ascii.h"
 #include "http2.h"
+#include "mime.h"
+#include "strcase.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
 #include "memdebug.h"
 
+#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
+    !defined(CURL_DISABLE_IMAP)
+/*
+ * checkheaders() checks the linked list of custom headers for a
+ * particular header (prefix).
+ *
+ * Returns a pointer to the first matching header or NULL if none matched.
+ */
+char *Curl_checkheaders(const struct connectdata *conn,
+                        const char *thisheader)
+{
+  struct curl_slist *head;
+  size_t thislen = strlen(thisheader);
+  struct Curl_easy *data = conn->data;
+
+  for(head = data->set.headers; head; head = head->next) {
+    if(strncasecompare(head->data, thisheader, thislen))
+      return head->data;
+  }
+
+  return NULL;
+}
+#endif
+
 /*
  * This function will call the read callback to fill our buffer with data
  * to upload.
@@ -195,27 +221,28 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, 
int bytes, int *nreadp)
            strlen(endofline_network));
 
 #ifdef CURL_DOES_CONVERSIONS
-    CURLcode result;
-    int length;
-    if(data->set.prefer_ascii) {
-      /* translate the protocol and data */
-      length = nread;
-    }
-    else {
-      /* just translate the protocol portion */
-      length = strlen(hexbuffer);
+    {
+      CURLcode result;
+      int length;
+      if(data->set.prefer_ascii)
+        /* translate the protocol and data */
+        length = nread;
+      else
+        /* just translate the protocol portion */
+        length = (int)strlen(hexbuffer);
+      result = Curl_convert_to_network(data, data->req.upload_fromhere,
+                                       length);
+      /* Curl_convert_to_network calls failf if unsuccessful */
+      if(result)
+        return result;
     }
-    result = Curl_convert_to_network(data, data->req.upload_fromhere, length);
-    /* Curl_convert_to_network calls failf if unsuccessful */
-    if(result)
-      return result;
 #endif /* CURL_DOES_CONVERSIONS */
 
     if((nread - hexlen) == 0)
       /* mark this as done once this chunk is transferred */
       data->req.upload_done = TRUE;
 
-    nread+=(int)strlen(endofline_native); /* for the added end of line */
+    nread += (int)strlen(endofline_native); /* for the added end of line */
   }
 #ifdef CURL_DOES_CONVERSIONS
   else if((data->set.prefer_ascii) && (!sending_http_headers)) {
@@ -241,6 +268,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, int 
bytes, int *nreadp)
 CURLcode Curl_readrewind(struct connectdata *conn)
 {
   struct Curl_easy *data = conn->data;
+  curl_mimepart *mimepart = &data->set.mimepost;
 
   conn->bits.rewindaftersend = FALSE; /* we rewind now */
 
@@ -253,9 +281,21 @@ CURLcode Curl_readrewind(struct connectdata *conn)
   /* We have sent away data. If not using CURLOPT_POSTFIELDS or
      CURLOPT_HTTPPOST, call app to rewind
   */
-  if(data->set.postfields ||
-     (data->set.httpreq == HTTPREQ_POST_FORM))
+  if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
+    struct HTTP *http = data->req.protop;
+
+    if(http->sendit)
+      mimepart = http->sendit;
+  }
+  if(data->set.postfields)
     ; /* do nothing */
+  else if(data->set.httpreq == HTTPREQ_POST_MIME ||
+          data->set.httpreq == HTTPREQ_POST_FORM) {
+    if(Curl_mime_rewind(mimepart)) {
+      failf(data, "Cannot rewind mime/post data");
+      return CURLE_SEND_FAIL_REWIND;
+    }
+  }
   else {
     if(data->set.seek_func) {
       int err;
@@ -560,7 +600,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
             infof(data, "Ignoring the response-body\n");
           }
           if(data->state.resume_from && !k->content_range &&
-             (data->set.httpreq==HTTPREQ_GET) &&
+             (data->set.httpreq == HTTPREQ_GET) &&
              !k->ignorebody) {
 
             if(k->size == data->state.resume_from) {
@@ -915,7 +955,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
         /* this is a paused transfer */
         break;
       }
-      if(nread<=0) {
+      if(nread <= 0) {
         result = done_sending(conn, k);
         if(result)
           return result;
@@ -1055,7 +1095,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
 {
   struct SingleRequest *k = &data->req;
   CURLcode result;
-  int didwhat=0;
+  int didwhat = 0;
 
   curl_socket_t fd_read;
   curl_socket_t fd_write;
@@ -1303,7 +1343,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
   if(result)
     return result;
 
-  data->set.followlocation=0; /* reset the location-follow counter */
+  data->set.followlocation = 0; /* reset the location-follow counter */
   data->state.this_is_a_follow = FALSE; /* reset this */
   data->state.errorbuf = FALSE; /* no error has occurred */
   data->state.httpversion = 0; /* don't assume any particular server version */
@@ -1345,7 +1385,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
 #endif
 
     Curl_initinfo(data); /* reset session-specific information "variables" */
-    Curl_pgrsResetTimesSizes(data);
+    Curl_pgrsResetTransferSizes(data);
     Curl_pgrsStartNow(data);
 
     if(data->set.timeout)
@@ -1427,14 +1467,14 @@ static const char *find_host_sep(const char *url)
 static size_t strlen_url(const char *url, bool relative)
 {
   const unsigned char *ptr;
-  size_t newlen=0;
-  bool left=TRUE; /* left side of the ? */
+  size_t newlen = 0;
+  bool left = TRUE; /* left side of the ? */
   const unsigned char *host_sep = (const unsigned char *) url;
 
   if(!relative)
     host_sep = (const unsigned char *) find_host_sep(url);
 
-  for(ptr=(unsigned char *)url; *ptr; ptr++) {
+  for(ptr = (unsigned char *)url; *ptr; ptr++) {
 
     if(ptr < host_sep) {
       ++newlen;
@@ -1443,7 +1483,7 @@ static size_t strlen_url(const char *url, bool relative)
 
     switch(*ptr) {
     case '?':
-      left=FALSE;
+      left = FALSE;
       /* fall through */
     default:
       if(*ptr >= 0x80)
@@ -1452,7 +1492,7 @@ static size_t strlen_url(const char *url, bool relative)
       break;
     case ' ':
       if(left)
-        newlen+=3;
+        newlen += 3;
       else
         newlen++;
       break;
@@ -1469,7 +1509,7 @@ static size_t strlen_url(const char *url, bool relative)
 static void strcpy_url(char *output, const char *url, bool relative)
 {
   /* we must add this with whitespace-replacing */
-  bool left=TRUE;
+  bool left = TRUE;
   const unsigned char *iptr;
   char *optr = output;
   const unsigned char *host_sep = (const unsigned char *) url;
@@ -1488,7 +1528,7 @@ static void strcpy_url(char *output, const char *url, 
bool relative)
 
     switch(*iptr) {
     case '?':
-      left=FALSE;
+      left = FALSE;
       /* fall through */
     default:
       if(*iptr >= 0x80) {
@@ -1509,7 +1549,7 @@ static void strcpy_url(char *output, const char *url, 
bool relative)
       break;
     }
   }
-  *optr=0; /* zero terminate output buffer */
+  *optr = 0; /* zero terminate output buffer */
 
 }
 
@@ -1548,26 +1588,26 @@ static char *concat_url(const char *base, const char 
*relurl)
 
   /* we must make our own copy of the URL to play with, as it may
      point to read-only data */
-  char *url_clone=strdup(base);
+  char *url_clone = strdup(base);
 
   if(!url_clone)
     return NULL; /* skip out of this NOW */
 
   /* protsep points to the start of the host name */
-  protsep=strstr(url_clone, "//");
+  protsep = strstr(url_clone, "//");
   if(!protsep)
-    protsep=url_clone;
+    protsep = url_clone;
   else
-    protsep+=2; /* pass the slashes */
+    protsep += 2; /* pass the slashes */
 
   if('/' != relurl[0]) {
-    int level=0;
+    int level = 0;
 
     /* First we need to find out if there's a ?-letter in the URL,
        and cut it and the right-side of that off */
     pathsep = strchr(protsep, '?');
     if(pathsep)
-      *pathsep=0;
+      *pathsep = 0;
 
     /* we have a relative path to append to the last slash if there's one
        available, or if the new URL is just a query string (starts with a
@@ -1576,14 +1616,14 @@ static char *concat_url(const char *base, const char 
*relurl)
     if(useurl[0] != '?') {
       pathsep = strrchr(protsep, '/');
       if(pathsep)
-        *pathsep=0;
+        *pathsep = 0;
     }
 
     /* Check if there's any slash after the host name, and if so, remember
        that position instead */
     pathsep = strchr(protsep, '/');
     if(pathsep)
-      protsep = pathsep+1;
+      protsep = pathsep + 1;
     else
       protsep = NULL;
 
@@ -1591,13 +1631,13 @@ static char *concat_url(const char *base, const char 
*relurl)
        and act accordingly */
 
     if((useurl[0] == '.') && (useurl[1] == '/'))
-      useurl+=2; /* just skip the "./" */
+      useurl += 2; /* just skip the "./" */
 
     while((useurl[0] == '.') &&
           (useurl[1] == '.') &&
           (useurl[2] == '/')) {
       level++;
-      useurl+=3; /* pass the "../" */
+      useurl += 3; /* pass the "../" */
     }
 
     if(protsep) {
@@ -1605,9 +1645,9 @@ static char *concat_url(const char *base, const char 
*relurl)
         /* cut off one more level from the right of the original URL */
         pathsep = strrchr(protsep, '/');
         if(pathsep)
-          *pathsep=0;
+          *pathsep = 0;
         else {
-          *protsep=0;
+          *protsep = 0;
           break;
         }
       }
@@ -1619,7 +1659,7 @@ static char *concat_url(const char *base, const char 
*relurl)
     if((relurl[0] == '/') && (relurl[1] == '/')) {
       /* the new URL starts with //, just keep the protocol part from the
          original one */
-      *protsep=0;
+      *protsep = 0;
       useurl = &relurl[2]; /* we keep the slashes from the original, so we
                               skip the new ones */
       host_changed = TRUE;
@@ -1635,7 +1675,7 @@ static char *concat_url(const char *base, const char 
*relurl)
         char *sep = strchr(protsep, '?');
         if(sep && (sep < pathsep))
           pathsep = sep;
-        *pathsep=0;
+        *pathsep = 0;
       }
       else {
         /* There was no slash. Now, since we might be operating on a badly
@@ -1644,7 +1684,7 @@ static char *concat_url(const char *base, const char 
*relurl)
            ?-letter as well! */
         pathsep = strchr(protsep, '?');
         if(pathsep)
-          *pathsep=0;
+          *pathsep = 0;
       }
     }
   }
@@ -1735,7 +1775,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
     }
   }
 
-  if(!is_absolute_url(newurl))  {
+  if(!is_absolute_url(newurl)) {
     /***
      *DANG* this is an RFC 2068 violation. The URL is supposed
      to be absolute and this doesn't seem to be that!
@@ -1754,7 +1794,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
     /* This is an absolute URL, don't allow the custom port number */
     disallowport = TRUE;
 
-    newest = malloc(newlen+1); /* get memory for this */
+    newest = malloc(newlen + 1); /* get memory for this */
     if(!newest)
       return CURLE_OUT_OF_MEMORY;
 
@@ -1826,7 +1866,8 @@ CURLcode Curl_follow(struct Curl_easy *data,
      * can be overridden with CURLOPT_POSTREDIR.
      */
     if((data->set.httpreq == HTTPREQ_POST
-        || data->set.httpreq == HTTPREQ_POST_FORM)
+        || data->set.httpreq == HTTPREQ_POST_FORM
+        || data->set.httpreq == HTTPREQ_POST_MIME)
        && !(data->set.keep_post & CURL_REDIR_POST_301)) {
       infof(data, "Switch from POST to GET\n");
       data->set.httpreq = HTTPREQ_GET;
@@ -1850,7 +1891,8 @@ CURLcode Curl_follow(struct Curl_easy *data,
      * can be overridden with CURLOPT_POSTREDIR.
      */
     if((data->set.httpreq == HTTPREQ_POST
-        || data->set.httpreq == HTTPREQ_POST_FORM)
+        || data->set.httpreq == HTTPREQ_POST_FORM
+        || data->set.httpreq == HTTPREQ_POST_MIME)
        && !(data->set.keep_post & CURL_REDIR_POST_302)) {
       infof(data, "Switch from POST to GET\n");
       data->set.httpreq = HTTPREQ_GET;
@@ -1883,7 +1925,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
     break;
   }
   Curl_pgrsTime(data, TIMER_REDIRECT);
-  Curl_pgrsResetTimesSizes(data);
+  Curl_pgrsResetTransferSizes(data);
 
   return CURLE_OK;
 #endif /* CURL_DISABLE_HTTP */
diff --git a/lib/transfer.h b/lib/transfer.h
index 518967260..72526a834 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,6 +22,9 @@
  *
  ***************************************************************************/
 
+char *Curl_checkheaders(const struct connectdata *conn,
+                        const char *thisheader);
+
 void Curl_init_CONNECT(struct Curl_easy *data);
 
 CURLcode Curl_pretransfer(struct Curl_easy *data);
diff --git a/lib/url.c b/lib/url.c
index acaf913da..55884c982 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -71,6 +71,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
 #include "netrc.h"
 
 #include "formdata.h"
+#include "mime.h"
 #include "vtls/vtls.h"
 #include "hostip.h"
 #include "transfer.h"
@@ -284,7 +285,7 @@ void Curl_freeset(struct Curl_easy *data)
 {
   /* Free all dynamic strings stored in the data->set substructure. */
   enum dupstring i;
-  for(i=(enum dupstring)0; i < STRING_LAST; i++) {
+  for(i = (enum dupstring)0; i < STRING_LAST; i++) {
     Curl_safefree(data->set.str[i]);
   }
 
@@ -371,7 +372,7 @@ CURLcode Curl_dupset(struct Curl_easy *dst, struct 
Curl_easy *src)
   memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
 
   /* duplicate all strings */
-  for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
+  for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
     result = setstropt(&dst->set.str[i], src->set.str[i]);
     if(result)
       return result;
@@ -479,6 +480,8 @@ CURLcode Curl_close(struct Curl_easy *data)
   Curl_http2_cleanup_dependencies(data);
   Curl_convert_close(data);
 
+  Curl_mime_cleanpart(&data->set.mimepost);
+
   /* No longer a dirty share, if it exists */
   if(data->share) {
     Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
@@ -668,6 +671,8 @@ CURLcode Curl_open(struct Curl_easy **curl)
     result = CURLE_OUT_OF_MEMORY;
   }
 
+  Curl_mime_initpart(&data->set.mimepost, data);
+
   data->state.headerbuff = malloc(HEADERSIZE);
   if(!data->state.headerbuff) {
     DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
@@ -676,7 +681,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
   else {
     result = Curl_init_userdefined(&data->set);
 
-    data->state.headersize=HEADERSIZE;
+    data->state.headersize = HEADERSIZE;
 
     Curl_convert_init(data);
 
@@ -1147,6 +1152,20 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption 
option,
     data->set.httpreq = HTTPREQ_POST_FORM;
     data->set.opt_no_body = FALSE; /* this is implied */
     break;
+#endif   /* CURL_DISABLE_HTTP */
+
+  case CURLOPT_MIMEPOST:
+    /*
+     * Set to make us do MIME/form POST
+     */
+    result = curl_mime_subparts(&data->set.mimepost,
+                                va_arg(param, curl_mime *));
+    if(!result) {
+      data->set.mimepost.freefunc = NULL; /* Avoid free upon easy cleanup. */
+      data->set.httpreq = HTTPREQ_POST_MIME;
+      data->set.opt_no_body = FALSE; /* this is implied */
+    }
+    break;
 
   case CURLOPT_REFERER:
     /*
@@ -1176,6 +1195,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption 
option,
     data->set.headers = va_arg(param, struct curl_slist *);
     break;
 
+#ifndef CURL_DISABLE_HTTP
   case CURLOPT_PROXYHEADER:
     /*
      * Set a list with proxy headers to use (or replace internals with)
@@ -1327,7 +1347,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption 
option,
     }
 
     break;
-#endif /* CURL_DISABLE_COOKIES */
+#endif /* !CURL_DISABLE_COOKIES */
 
   case CURLOPT_HTTPGET:
     /*
@@ -1353,6 +1373,16 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption 
option,
     data->set.httpversion = arg;
     break;
 
+  case CURLOPT_EXPECT_100_TIMEOUT_MS:
+    /*
+     * Time to wait for a response to a HTTP request containing an
+     * Expect: 100-continue header before sending the data anyway.
+     */
+    data->set.expect_100_timeout = va_arg(param, long);
+    break;
+
+#endif   /* CURL_DISABLE_HTTP */
+
   case CURLOPT_HTTPAUTH:
     /*
      * Set HTTP Authentication type BITMASK.
@@ -1404,16 +1434,6 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption 
option,
   }
   break;
 
-  case CURLOPT_EXPECT_100_TIMEOUT_MS:
-    /*
-     * Time to wait for a response to a HTTP request containing an
-     * Expect: 100-continue header before sending the data anyway.
-     */
-    data->set.expect_100_timeout = va_arg(param, long);
-    break;
-
-#endif   /* CURL_DISABLE_HTTP */
-
   case CURLOPT_CUSTOMREQUEST:
     /*
      * Set a custom string to use as request
@@ -1659,28 +1679,28 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption 
option,
      * The low speed limit that if transfers are below this for
      * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
      */
-    data->set.low_speed_limit=va_arg(param, long);
+    data->set.low_speed_limit = va_arg(param, long);
     break;
   case CURLOPT_MAX_SEND_SPEED_LARGE:
     /*
      * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
      * bytes per second the transfer is throttled..
      */
-    data->set.max_send_speed=va_arg(param, curl_off_t);
+    data->set.max_send_speed = va_arg(param, curl_off_t);
     break;
   case CURLOPT_MAX_RECV_SPEED_LARGE:
     /*
      * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
      * second the transfer is throttled..
      */
-    data->set.max_recv_speed=va_arg(param, curl_off_t);
+    data->set.max_recv_speed = va_arg(param, curl_off_t);
     break;
   case CURLOPT_LOW_SPEED_TIME:
     /*
      * The low speed time that if transfers are below the set
      * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
      */
-    data->set.low_speed_time=va_arg(param, long);
+    data->set.low_speed_time = va_arg(param, long);
     break;
   case CURLOPT_URL:
     /*
@@ -1875,13 +1895,13 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption 
option,
     break;
   case CURLOPT_RESUME_FROM:
     /*
-     * Resume transfer at the give file position
+     * Resume transfer at the given file position
      */
     data->set.set_resume_from = va_arg(param, long);
     break;
   case CURLOPT_RESUME_FROM_LARGE:
     /*
-     * Resume transfer at the give file position
+     * Resume transfer at the given file position
      */
     data->set.set_resume_from = va_arg(param, curl_off_t);
     break;
@@ -2179,24 +2199,26 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption 
option,
                                          TRUE : FALSE;
     break;
   case CURLOPT_SSL_CTX_FUNCTION:
-#ifdef have_curlssl_ssl_ctx
     /*
      * Set a SSL_CTX callback
      */
-    data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
-#else
-    result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+    if(Curl_ssl->have_ssl_ctx)
+      data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
+    else
 #endif
+      result = CURLE_NOT_BUILT_IN;
     break;
   case CURLOPT_SSL_CTX_DATA:
-#ifdef have_curlssl_ssl_ctx
     /*
      * Set a SSL_CTX callback parameter pointer
      */
-    data->set.ssl.fsslctxp = va_arg(param, void *);
-#else
-    result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+    if(Curl_ssl->have_ssl_ctx)
+      data->set.ssl.fsslctxp = va_arg(param, void *);
+    else
 #endif
+      result = CURLE_NOT_BUILT_IN;
     break;
   case CURLOPT_SSL_FALSESTART:
     /*
@@ -2210,35 +2232,38 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption 
option,
     data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
     break;
   case CURLOPT_CERTINFO:
-#ifdef have_curlssl_certinfo
-    data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
-#else
-    result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+    if(Curl_ssl->have_certinfo)
+      data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
+    else
 #endif
+      result = CURLE_NOT_BUILT_IN;
     break;
   case CURLOPT_PINNEDPUBLICKEY:
-#ifdef have_curlssl_pinnedpubkey /* only by supported backends */
     /*
      * Set pinned public key for SSL connection.
      * Specify file name of the public key in DER format.
      */
-    result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
-                       va_arg(param, char *));
-#else
-    result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+    if(Curl_ssl->have_pinnedpubkey)
+      result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
+                         va_arg(param, char *));
+    else
 #endif
+      result = CURLE_NOT_BUILT_IN;
     break;
   case CURLOPT_PROXY_PINNEDPUBLICKEY:
-#ifdef have_curlssl_pinnedpubkey /* only by supported backends */
     /*
      * Set pinned public key for SSL connection.
      * Specify file name of the public key in DER format.
      */
-    result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
-                       va_arg(param, char *));
-#else
-    result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+    if(Curl_ssl->have_pinnedpubkey)
+      result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
+                         va_arg(param, char *));
+    else
 #endif
+      result = CURLE_NOT_BUILT_IN;
     break;
   case CURLOPT_CAINFO:
     /*
@@ -2256,30 +2281,32 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption 
option,
                        va_arg(param, char *));
     break;
   case CURLOPT_CAPATH:
-#ifdef have_curlssl_ca_path /* not supported by all backends */
     /*
      * Set CA path info for SSL connection. Specify directory name of the CA
      * certificates which have been prepared using openssl c_rehash utility.
      */
-    /* This does not work on windows. */
-    result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
-                       va_arg(param, char *));
-#else
-    result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+    if(Curl_ssl->have_ca_path)
+      /* This does not work on windows. */
+      result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
+                         va_arg(param, char *));
+    else
 #endif
+      result = CURLE_NOT_BUILT_IN;
     break;
   case CURLOPT_PROXY_CAPATH:
-#ifdef have_curlssl_ca_path /* not supported by all backends */
     /*
      * Set CA path info for SSL connection proxy. Specify directory name of the
      * CA certificates which have been prepared using openssl c_rehash utility.
      */
-    /* This does not work on windows. */
-    result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
-                       va_arg(param, char *));
-#else
-    result = CURLE_NOT_BUILT_IN;
+#ifdef USE_SSL
+    if(Curl_ssl->have_ca_path)
+      /* This does not work on windows. */
+      result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
+                         va_arg(param, char *));
+    else
 #endif
+      result = CURLE_NOT_BUILT_IN;
     break;
   case CURLOPT_CRLFILE:
     /*
@@ -2910,7 +2937,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption 
option,
     return CURLE_NOT_BUILT_IN;
 #else
     arg = va_arg(param, long);
-    if((arg>=1) && (arg <= 256))
+    if((arg >= 1) && (arg <= 256))
       data->set.stream_weight = (int)arg;
     break;
 #endif
@@ -2936,6 +2963,9 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption 
option,
   case CURLOPT_SUPPRESS_CONNECT_HEADERS:
     data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
     break;
+  case CURLOPT_SSH_COMPRESSION:
+    data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
+    break;
   default:
     /* unknown tag and its companion, just ignore: */
     result = CURLE_UNKNOWN_OPTION;
@@ -3273,7 +3303,7 @@ Curl_oldest_idle_connection(struct Curl_easy *data)
   struct curl_hash_iterator iter;
   struct curl_llist_element *curr;
   struct curl_hash_element *he;
-  time_t highscore=-1;
+  time_t highscore =- 1;
   time_t score;
   struct curltime now;
   struct connectdata *conn_candidate = NULL;
@@ -3336,7 +3366,7 @@ find_oldest_idle_connection_in_bundle(struct Curl_easy 
*data,
                                       struct connectbundle *bundle)
 {
   struct curl_llist_element *curr;
-  time_t highscore=-1;
+  time_t highscore = -1;
   time_t score;
   struct curltime now;
   struct connectdata *conn_candidate = NULL;
@@ -3967,7 +3997,7 @@ int Curl_doing_getsock(struct connectdata *conn,
 CURLcode Curl_protocol_connecting(struct connectdata *conn,
                                   bool *done)
 {
-  CURLcode result=CURLE_OK;
+  CURLcode result = CURLE_OK;
 
   if(conn && conn->handler->connecting) {
     *done = FALSE;
@@ -3986,7 +4016,7 @@ CURLcode Curl_protocol_connecting(struct connectdata 
*conn,
 
 CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done)
 {
-  CURLcode result=CURLE_OK;
+  CURLcode result = CURLE_OK;
 
   if(conn && conn->handler->doing) {
     *done = FALSE;
@@ -4006,7 +4036,7 @@ CURLcode Curl_protocol_doing(struct connectdata *conn, 
bool *done)
 CURLcode Curl_protocol_connect(struct connectdata *conn,
                                bool *protocol_done)
 {
-  CURLcode result=CURLE_OK;
+  CURLcode result = CURLE_OK;
 
   *protocol_done = FALSE;
 
@@ -4093,7 +4123,7 @@ static void fix_hostname(struct connectdata *conn, struct 
hostname *host)
   if(len && (host->name[len-1] == '.'))
     /* strip off a single trailing dot if present, primarily for SNI but
        there's no use for it */
-    host->name[len-1]=0;
+    host->name[len-1] = 0;
 
   /* Check name for non-ASCII and convert hostname to ACE form if we can */
   if(!is_ASCII_name(host->name)) {
@@ -4146,7 +4176,7 @@ static void free_fixed_hostname(struct hostname *host)
     host->encalloc = NULL;
   }
 #elif defined(USE_WIN32_IDN)
-  free(host->encalloc); /* must be freed withidn_free() since this was
+  free(host->encalloc); /* must be freed with free() since this was
                            allocated by curl_win32_idn_to_ascii */
   host->encalloc = NULL;
 #else
@@ -4166,7 +4196,12 @@ static void llist_dtor(void *user, void *element)
  */
 static struct connectdata *allocate_conn(struct Curl_easy *data)
 {
-  struct connectdata *conn = calloc(1, sizeof(struct connectdata));
+#ifdef USE_SSL
+#define SSL_EXTRA + 4 * Curl_ssl->sizeof_ssl_backend_data - sizeof(long long)
+#else
+#define SSL_EXTRA 0
+#endif
+  struct connectdata *conn = calloc(1, sizeof(struct connectdata) + SSL_EXTRA);
   if(!conn)
     return NULL;
 
@@ -4249,6 +4284,23 @@ static struct connectdata *allocate_conn(struct 
Curl_easy *data)
 
   conn->ip_version = data->set.ipver;
 
+#ifdef USE_SSL
+  /*
+   * To save on malloc()s, the SSL backend-specific data has been allocated
+   * at the end of the connectdata struct.
+   */
+  {
+    char *p = (char *)&conn->align_data__do_not_use;
+    conn->ssl[0].backend = (struct ssl_backend_data *)p;
+    conn->ssl[1].backend =
+      (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data);
+    conn->proxy_ssl[0].backend =
+      (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data * 2);
+    conn->proxy_ssl[1].backend =
+      (struct ssl_backend_data *)(p + Curl_ssl->sizeof_ssl_backend_data * 3);
+  }
+#endif
+
 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
     defined(NTLM_WB_ENABLED)
   conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
@@ -4430,7 +4482,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy 
*data,
 
       /* This cannot be done with strcpy() in a portable manner, since the
          memory areas overlap! */
-      memmove(path, path + 2, strlen(path + 2)+1);
+      memmove(path, path + 2, strlen(path + 2) + 1);
     }
 
     /*
@@ -4471,8 +4523,9 @@ static CURLcode parseurlandfillconn(struct Curl_easy 
*data,
         ptr++;
 
       /* This cannot be made with strcpy, as the memory chunks overlap! */
-      memmove(path, ptr, strlen(ptr)+1);
+      memmove(path, ptr, strlen(ptr) + 1);
     }
+#endif
 
 #if !defined(MSDOS) && !defined(WIN32) && !defined(__CYGWIN__)
     if(STARTS_WITH_DRIVE_PREFIX(path)) {
@@ -4487,7 +4540,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy 
*data,
   else {
     /* clear path */
     char slashbuf[4];
-    path[0]=0;
+    path[0] = 0;
 
     rc = sscanf(data->change.url,
                 "%15[^\n/:]:%3[/]%[^\n/?#]%[^\n]",
@@ -4572,7 +4625,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy 
*data,
    */
   at = strchr(conn->host.name, '@');
   if(at)
-    query = strchr(at+1, '?');
+    query = strchr(at + 1, '?');
   else
     query = strchr(conn->host.name, '?');
 
@@ -4590,15 +4643,15 @@ static CURLcode parseurlandfillconn(struct Curl_easy 
*data,
 
     /* move the existing path plus the zero byte forward, to make room for
        the host-name part */
-    memmove(path+hostlen+1, path, pathlen+1);
+    memmove(path + hostlen + 1, path, pathlen + 1);
 
      /* now copy the trailing host part in front of the existing path */
-    memcpy(path+1, query, hostlen);
+    memcpy(path + 1, query, hostlen);
 
     path[0]='/'; /* prepend the missing slash */
     rebuild_url = TRUE;
 
-    *query=0; /* now cut off the hostname at the ? */
+    *query = 0; /* now cut off the hostname at the ? */
   }
   else if(!path[0]) {
     /* if there's no path set, use a single slash */
@@ -4614,7 +4667,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy 
*data,
     /* We need this function to deal with overlapping memory areas. We know
        that the memory area 'path' points to is 'urllen' bytes big and that
        is bigger than the path. Use +1 to move the zero byte too. */
-    memmove(&path[1], path, strlen(path)+1);
+    memmove(&path[1], path, strlen(path) + 1);
     path[0] = '/';
     rebuild_url = TRUE;
   }
@@ -4720,7 +4773,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy 
*data,
       if(*endp == ']') {
         /* The address scope was well formed.  Knock it out of the
            hostname. */
-        memmove(percent, endp, strlen(endp)+1);
+        memmove(percent, endp, strlen(endp) + 1);
         conn->scope_id = (unsigned int)scope;
       }
       else {
@@ -4990,7 +5043,7 @@ static char *detect_proxy(struct connectdata *conn)
   strcpy(envp, "_proxy");
 
   /* read the protocol proxy: */
-  prox=curl_getenv(proxy_env);
+  prox = curl_getenv(proxy_env);
 
   /*
    * We don't try the uppercase version of HTTP_PROXY because of
@@ -5007,7 +5060,7 @@ static char *detect_proxy(struct connectdata *conn)
   if(!prox && !strcasecompare("http_proxy", proxy_env)) {
     /* There was no lowercase variable, try the uppercase version: */
     Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
-    prox=curl_getenv(proxy_env);
+    prox = curl_getenv(proxy_env);
   }
 
   if(prox)
@@ -5015,7 +5068,7 @@ static char *detect_proxy(struct connectdata *conn)
   else {
     proxy = curl_getenv("all_proxy"); /* default proxy to use */
     if(!proxy)
-      proxy=curl_getenv("ALL_PROXY");
+      proxy = curl_getenv("ALL_PROXY");
   }
 
   return proxy;
@@ -5050,7 +5103,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   /* Parse the protocol part if present */
   endofprot = strstr(proxy, "://");
   if(endofprot) {
-    proxyptr = endofprot+3;
+    proxyptr = endofprot + 3;
     if(checkprefix("https", proxy))
       proxytype = CURLPROXY_HTTPS;
     else if(checkprefix("socks5h", proxy))
@@ -5072,13 +5125,14 @@ static CURLcode parse_proxy(struct Curl_easy *data,
   else
     proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
 
-#ifndef HTTPS_PROXY_SUPPORT
-  if(proxytype == CURLPROXY_HTTPS) {
-    failf(data, "Unsupported proxy \'%s\'"
-                ", libcurl is built without the HTTPS-proxy support.", proxy);
-    return CURLE_NOT_BUILT_IN;
-  }
+#ifdef USE_SSL
+  if(!Curl_ssl->support_https_proxy)
 #endif
+    if(proxytype == CURLPROXY_HTTPS) {
+      failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
+                  "HTTPS-proxy support.", proxy);
+      return CURLE_NOT_BUILT_IN;
+    }
 
   sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
               proxytype == CURLPROXY_SOCKS5 ||
@@ -5299,22 +5353,21 @@ static CURLcode create_conn_helper_init_proxy(struct 
connectdata *conn)
     }
   }
 
-  no_proxy = curl_getenv("no_proxy");
-  if(!no_proxy)
-    no_proxy = curl_getenv("NO_PROXY");
+  if(!data->set.str[STRING_NOPROXY]) {
+    no_proxy = curl_getenv("no_proxy");
+    if(!no_proxy)
+      no_proxy = curl_getenv("NO_PROXY");
+  }
 
-  if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY]) ||
-     (!data->set.str[STRING_NOPROXY] &&
-      check_noproxy(conn->host.name, no_proxy))) {
+  if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
+      data->set.str[STRING_NOPROXY] : no_proxy)) {
     Curl_safefree(proxy);
     Curl_safefree(socksproxy);
   }
-  else if(!proxy && !socksproxy)
 #ifndef CURL_DISABLE_HTTP
+  else if(!proxy && !socksproxy)
     /* if the host is not in the noproxy list, detect proxy. */
     proxy = detect_proxy(conn);
-#else  /* !CURL_DISABLE_HTTP */
-    proxy = NULL;
 #endif /* CURL_DISABLE_HTTP */
 
   Curl_safefree(no_proxy);
@@ -5762,7 +5815,7 @@ static CURLcode parse_remote_port(struct Curl_easy *data,
     char *rest;
     long port;
 
-    port=strtol(portptr+1, &rest, 10);  /* Port number must be decimal */
+    port = strtol(portptr + 1, &rest, 10);  /* Port number must be decimal */
 
     if((port < 0) || (port > 0xffff)) {
       /* Single unix standard says port numbers are 16 bits long */
@@ -6118,7 +6171,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
                                struct connectdata *conn,
                                bool *async)
 {
-  CURLcode result=CURLE_OK;
+  CURLcode result = CURLE_OK;
   time_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
 
   /*************************************************************
@@ -6281,11 +6334,10 @@ static void reuse_conn(struct connectdata *old_conn,
   free_fixed_hostname(&conn->conn_to_host);
   Curl_safefree(conn->host.rawalloc);
   Curl_safefree(conn->conn_to_host.rawalloc);
-  conn->host=old_conn->host;
-  conn->bits.conn_to_host = old_conn->bits.conn_to_host;
+  conn->host = old_conn->host;
   conn->conn_to_host = old_conn->conn_to_host;
-  conn->bits.conn_to_port = old_conn->bits.conn_to_port;
   conn->conn_to_port = old_conn->conn_to_port;
+  conn->remote_port = old_conn->remote_port;
 
   /* persist connection info in session handle */
   Curl_persistconninfo(conn);
@@ -6384,9 +6436,9 @@ static CURLcode create_conn(struct Curl_easy *data,
    * other parts of the code will rely on this fact
    ***********************************************************/
 #define LEAST_PATH_ALLOC 256
-  urllen=strlen(data->change.url);
+  urllen = strlen(data->change.url);
   if(urllen < LEAST_PATH_ALLOC)
-    urllen=LEAST_PATH_ALLOC;
+    urllen = LEAST_PATH_ALLOC;
 
   /*
    * We malloc() the buffers below urllen+2 to make room for 2 possibilities:
@@ -6397,14 +6449,14 @@ static CURLcode create_conn(struct Curl_easy *data,
   Curl_safefree(data->state.pathbuffer);
   data->state.path = NULL;
 
-  data->state.pathbuffer = malloc(urllen+2);
+  data->state.pathbuffer = malloc(urllen + 2);
   if(NULL == data->state.pathbuffer) {
     result = CURLE_OUT_OF_MEMORY; /* really bad error */
     goto out;
   }
   data->state.path = data->state.pathbuffer;
 
-  conn->host.rawalloc = malloc(urllen+2);
+  conn->host.rawalloc = malloc(urllen + 2);
   if(NULL == conn->host.rawalloc) {
     Curl_safefree(data->state.pathbuffer);
     data->state.path = NULL;
@@ -7037,7 +7089,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct 
connectdata *conn)
 
   k->buf = data->state.buffer;
   k->hbufp = data->state.headerbuff;
-  k->ignorebody=FALSE;
+  k->ignorebody = FALSE;
 
   Curl_speedinit(data);
 
diff --git a/lib/urldata.h b/lib/urldata.h
index bde643b46..6dc715394 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -82,75 +82,6 @@
 #include "cookie.h"
 #include "formdata.h"
 
-#ifdef USE_OPENSSL
-#include <openssl/ssl.h>
-#ifdef HAVE_OPENSSL_ENGINE_H
-#include <openssl/engine.h>
-#endif
-#endif /* USE_OPENSSL */
-
-#ifdef USE_GNUTLS
-#include <gnutls/gnutls.h>
-#endif
-
-#ifdef USE_MBEDTLS
-
-#include <mbedtls/ssl.h>
-#include <mbedtls/version.h>
-#include <mbedtls/entropy.h>
-#include <mbedtls/ctr_drbg.h>
-
-#elif defined USE_POLARSSL
-
-#include <polarssl/ssl.h>
-#include <polarssl/version.h>
-#if POLARSSL_VERSION_NUMBER<0x01010000
-#include <polarssl/havege.h>
-#else
-#include <polarssl/entropy.h>
-#include <polarssl/ctr_drbg.h>
-#endif /* POLARSSL_VERSION_NUMBER<0x01010000 */
-
-#endif /* USE_POLARSSL */
-
-#ifdef USE_CYASSL
-#undef OCSP_REQUEST  /* avoid cyassl/openssl/ssl.h clash with wincrypt.h */
-#undef OCSP_RESPONSE /* avoid cyassl/openssl/ssl.h clash with wincrypt.h */
-#include <cyassl/openssl/ssl.h>
-#endif
-
-#ifdef USE_NSS
-#include <nspr.h>
-#include <pk11pub.h>
-#endif
-
-#ifdef USE_GSKIT
-#include <gskssl.h>
-#endif
-
-#ifdef USE_AXTLS
-#include <axTLS/config.h>
-#include <axTLS/ssl.h>
-#undef malloc
-#undef calloc
-#undef realloc
-#endif /* USE_AXTLS */
-
-#if defined(USE_SCHANNEL) || defined(USE_WINDOWS_SSPI)
-#include "curl_sspi.h"
-#endif
-#ifdef USE_SCHANNEL
-#include <schnlsp.h>
-#include <schannel.h>
-#endif
-
-#ifdef USE_DARWINSSL
-#include <Security/Security.h>
-/* For some reason, when building for iOS, the omnibus header above does
- * not include SecureTransport.h as of iOS SDK 5.1. */
-#include <Security/SecureTransport.h>
-#endif
-
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -172,6 +103,7 @@
 #include "hash.h"
 #include "splay.h"
 
+#include "mime.h"
 #include "imap.h"
 #include "pop3.h"
 #include "smtp.h"
@@ -240,20 +172,6 @@ enum protection_level {
 };
 #endif
 
-#ifdef USE_SCHANNEL
-/* Structs to store Schannel handles */
-struct curl_schannel_cred {
-  CredHandle cred_handle;
-  TimeStamp time_stamp;
-  int refcount;
-};
-
-struct curl_schannel_ctxt {
-  CtxtHandle ctxt_handle;
-  TimeStamp time_stamp;
-};
-#endif
-
 /* enum for the nonblocking SSL connection state machine */
 typedef enum {
   ssl_connect_1,
@@ -270,6 +188,9 @@ typedef enum {
   ssl_connection_complete
 } ssl_connection_state;
 
+/* SSL backend-specific data; declared differently by each SSL backend */
+struct ssl_backend_data;
+
 /* struct for data related to each SSL connection */
 struct ssl_connect_data {
   /* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm
@@ -278,78 +199,9 @@ struct ssl_connect_data {
   bool use;
   ssl_connection_state state;
   ssl_connect_state connecting_state;
-#if defined(USE_OPENSSL)
-  /* these ones requires specific SSL-types */
-  SSL_CTX* ctx;
-  SSL*     handle;
-  X509*    server_cert;
-#elif defined(USE_GNUTLS)
-  gnutls_session_t session;
-  gnutls_certificate_credentials_t cred;
-#ifdef USE_TLS_SRP
-  gnutls_srp_client_credentials_t srp_client_cred;
-#endif
-#elif defined(USE_MBEDTLS)
-  mbedtls_ctr_drbg_context ctr_drbg;
-  mbedtls_entropy_context entropy;
-  mbedtls_ssl_context ssl;
-  int server_fd;
-  mbedtls_x509_crt cacert;
-  mbedtls_x509_crt clicert;
-  mbedtls_x509_crl crl;
-  mbedtls_pk_context pk;
-  mbedtls_ssl_config config;
-  const char *protocols[3];
-#elif defined(USE_POLARSSL)
-  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;
-#elif defined(USE_CYASSL)
-  SSL_CTX* ctx;
-  SSL*     handle;
-#elif defined(USE_NSS)
-  PRFileDesc *handle;
-  char *client_nickname;
-  struct Curl_easy *data;
-  struct curl_llist obj_list;
-  PK11GenericObject *obj_clicert;
-#elif defined(USE_GSKIT)
-  gsk_handle handle;
-  int iocport;
-  int localfd;
-  int remotefd;
-#elif defined(USE_AXTLS)
-  SSL_CTX* ssl_ctx;
-  SSL*     ssl;
-#elif defined(USE_SCHANNEL)
-  struct curl_schannel_cred *cred;
-  struct curl_schannel_ctxt *ctxt;
-  SecPkgContext_StreamSizes stream_sizes;
-  size_t encdata_length, decdata_length;
-  size_t encdata_offset, decdata_offset;
-  unsigned char *encdata_buffer, *decdata_buffer;
-  /* encdata_is_incomplete: if encdata contains only a partial record that
-     can't be decrypted without another Curl_read_plain (that is, status is
-     SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
-     more bytes into encdata then set this back to false. */
-  bool encdata_is_incomplete;
-  unsigned long req_flags, ret_flags;
-  CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
-  bool recv_sspi_close_notify; /* true if connection closed by close_notify */
-  bool recv_connection_closed; /* true if connection closed, regardless how */
-  bool use_alpn; /* true if ALPN is used for this connection */
-#elif defined(USE_DARWINSSL)
-  SSLContextRef ssl_ctx;
-  curl_socket_t ssl_sockfd;
-  bool ssl_direction; /* true if writing, false if reading */
-  size_t ssl_write_buffered_length;
-#elif defined(USE_SSL)
-#error "SSL backend specific information missing from ssl_connect_data"
+
+#if defined(USE_SSL)
+  struct ssl_backend_data *backend;
 #endif
 };
 
@@ -359,13 +211,13 @@ struct ssl_primary_config {
   bool verifypeer;       /* set TRUE if this is desired */
   bool verifyhost;       /* set TRUE if CN/SAN must match hostname */
   bool verifystatus;     /* set TRUE if certificate status must be checked */
+  bool sessionid;        /* cache session IDs or not */
   char *CApath;          /* certificate dir (doesn't work on windows) */
   char *CAfile;          /* certificate to verify peer against */
   char *clientcert;
   char *random_file;     /* path to file containing "random" data */
   char *egdsocket;       /* path to file containing the EGD daemon socket */
   char *cipher_list;     /* list of ciphers to use */
-  bool sessionid;        /* cache session IDs or not */
 };
 
 struct ssl_config_data {
@@ -411,6 +263,10 @@ struct curl_ssl_session {
   struct ssl_primary_config ssl_config; /* setup for this session */
 };
 
+#ifdef USE_WINDOWS_SSPI
+#include "curl_sspi.h"
+#endif
+
 /* Struct used for Digest challenge-response authentication */
 struct digestdata {
 #if defined(USE_WINDOWS_SSPI)
@@ -442,10 +298,6 @@ typedef enum {
   NTLMSTATE_LAST
 } curlntlm;
 
-#ifdef USE_WINDOWS_SSPI
-#include "curl_sspi.h"
-#endif
-
 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
 #include <iconv.h>
 #endif
@@ -1179,6 +1031,16 @@ struct connectdata {
   char *unix_domain_socket;
   bool abstract_unix_socket;
 #endif
+
+#ifdef USE_SSL
+  /*
+   * To avoid multiple malloc() calls, the ssl_connect_data structures
+   * associated with a connectdata struct are allocated in the same block
+   * as the latter. This field forces alignment to an 8-byte boundary so
+   * that this all works.
+   */
+  long long *align_data__do_not_use;
+#endif
 };
 
 /* The end of connectdata. */
@@ -1259,6 +1121,8 @@ struct Progress {
   struct curltime t_startop;
   struct curltime t_acceptdata;
 
+  bool is_t_startransfer_set;
+
   /* upload speed limit */
   struct curltime ul_limit_start;
   curl_off_t ul_limit_size;
@@ -1266,7 +1130,7 @@ struct Progress {
   struct curltime dl_limit_start;
   curl_off_t dl_limit_size;
 
-#define CURR_TIME (5+1) /* 6 entries for 5 seconds */
+#define CURR_TIME (5 + 1) /* 6 entries for 5 seconds */
 
   curl_off_t speeder[ CURR_TIME ];
   struct curltime speeder_time[ CURR_TIME ];
@@ -1278,6 +1142,7 @@ typedef enum {
   HTTPREQ_GET,
   HTTPREQ_POST,
   HTTPREQ_POST_FORM, /* we make a difference internally */
+  HTTPREQ_POST_MIME, /* we make a difference internally */
   HTTPREQ_PUT,
   HTTPREQ_HEAD,
   HTTPREQ_OPTIONS,
@@ -1387,7 +1252,7 @@ struct UrlState {
   size_t headersize;   /* size of the allocation */
 
   char *buffer; /* download buffer */
-  char uploadbuffer[UPLOAD_BUFSIZE+1]; /* upload buffer */
+  char uploadbuffer[UPLOAD_BUFSIZE + 1]; /* upload buffer */
   curl_off_t current_speed;  /* the ProgressShow() function sets this,
                                 bytes / second */
   bool this_is_a_follow; /* this is a followed Location: request */
@@ -1431,7 +1296,8 @@ struct UrlState {
                      ares_channel f.e. */
 
 #if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
-  ENGINE *engine;
+  /* void instead of ENGINE to avoid bleeding OpenSSL into this header */
+  void *engine;
 #endif /* USE_OPENSSL */
   struct curltime expiretime; /* set this with Curl_expire() only */
   struct Curl_tree timenode; /* for the splay stuff */
@@ -1694,7 +1560,8 @@ struct UserDefined {
   curl_off_t set_resume_from;  /* continue [ftp] transfer from here */
   struct curl_slist *headers; /* linked list of extra headers */
   struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */
-  struct curl_httppost *httppost;  /* linked list of POST data */
+  struct curl_httppost *httppost;  /* linked list of old POST data */
+  curl_mimepart mimepost;  /* MIME/POST data. */
   bool sep_headers;     /* handle host and proxy headers separately */
   bool cookiesession;   /* new cookie session? */
   bool crlf;            /* convert crlf on ftp upload(?) */
@@ -1740,6 +1607,7 @@ struct UserDefined {
 
   curl_sshkeycallback ssh_keyfunc; /* key matching callback */
   void *ssh_keyfunc_userp;         /* custom pointer to callback */
+  bool ssh_compression;            /* enable SSH compression */
 
 /* Here follows boolean settings that define how to behave during
    this session. They are STATIC, set by libcurl users or at least initially
diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c
index 3d583e417..b40239931 100644
--- a/lib/vauth/digest_sspi.c
+++ b/lib/vauth/digest_sspi.c
@@ -352,8 +352,8 @@ CURLcode Curl_auth_decode_digest_http_message(const char 
*chlg,
       if(!Curl_auth_digest_get_pair(p, value, content, &p))
         break;
 
-      if(Curl_strcasecompare(value, "stale")
-         && Curl_strcasecompare(content, "true")) {
+      if(strcasecompare(value, "stale") &&
+         strcasecompare(content, "true")) {
         stale = true;
         break;
       }
diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c
index 42196455f..50d922208 100644
--- a/lib/vauth/ntlm.c
+++ b/lib/vauth/ntlm.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -44,7 +44,9 @@
 #include "rand.h"
 #include "vtls/vtls.h"
 
-#ifdef USE_NSS
+/* SSL backend-specific #if branches in this file must be kept in the order
+   documented in curl_ntlm_core. */
+#if defined(NTLM_NEEDS_NSS_INIT)
 #include "vtls/nssg.h" /* for Curl_nss_force_init() */
 #endif
 
@@ -272,7 +274,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct 
Curl_easy *data,
   unsigned char *type2 = NULL;
   size_t type2_len = 0;
 
-#if defined(USE_NSS)
+#if defined(NTLM_NEEDS_NSS_INIT)
   /* Make sure the crypto backend is initialized */
   result = Curl_nss_force_init(data);
   if(result)
@@ -350,6 +352,7 @@ static void unicodecpy(unsigned char *dest, const char 
*src, size_t length)
  *
  * Parameters:
  *
+ * data    [in]     - The session handle.
  * userp   [in]     - The user name in the format User or Domain\User.
  * passdwp [in]     - The user's password.
  * ntlm    [in/out] - The NTLM data struct being used and modified.
@@ -359,7 +362,8 @@ static void unicodecpy(unsigned char *dest, const char 
*src, size_t length)
  *
  * Returns CURLE_OK on success.
  */
-CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
+CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
+                                             const char *userp,
                                              const char *passwdp,
                                              struct ntlmdata *ntlm,
                                              char **outptr, size_t *outlen)
@@ -458,7 +462,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(const char 
*userp,
   });
 
   /* Return with binary blob encoded into base64 */
-  return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
+  return Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen);
 }
 
 /*
@@ -827,7 +831,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct 
Curl_easy *data,
     return CURLE_CONV_FAILED;
 
   /* Return with binary blob encoded into base64 */
-  result = Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
+  result = Curl_base64_encode(data, (char *)ntlmbuf, size, outptr, outlen);
 
   Curl_auth_ntlm_cleanup(ntlm);
 
diff --git a/lib/vauth/ntlm_sspi.c b/lib/vauth/ntlm_sspi.c
index 227d6de50..c955b69ea 100644
--- a/lib/vauth/ntlm_sspi.c
+++ b/lib/vauth/ntlm_sspi.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,6 +29,7 @@
 #include "vauth/vauth.h"
 #include "urldata.h"
 #include "curl_base64.h"
+#include "curl_ntlm_core.h"
 #include "warnless.h"
 #include "curl_multibyte.h"
 #include "sendf.h"
@@ -66,6 +67,7 @@ bool Curl_auth_is_ntlm_supported(void)
  *
  * Parameters:
  *
+ * data    [in]     - The session handle.
  * userp   [in]     - The user name in the format User or Domain\User.
  * passdwp [in]     - The user's password.
  * ntlm    [in/out] - The NTLM data struct being used and modified.
@@ -75,7 +77,8 @@ bool Curl_auth_is_ntlm_supported(void)
  *
  * Returns CURLE_OK on success.
  */
-CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
+CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
+                                             const char *userp,
                                              const char *passwdp,
                                              struct ntlmdata *ntlm,
                                              char **outptr, size_t *outlen)
@@ -166,7 +169,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(const char 
*userp,
     return CURLE_RECV_ERROR;
 
   /* Base64 encode the response */
-  return Curl_base64_encode(NULL, (char *) ntlm->output_token,
+  return Curl_base64_encode(data, (char *) ntlm->output_token,
                             type_1_buf.cbBuffer, outptr, outlen);
 }
 
diff --git a/lib/vauth/vauth.h b/lib/vauth/vauth.h
index 24b7d24d8..15abea520 100644
--- a/lib/vauth/vauth.h
+++ b/lib/vauth/vauth.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2014 - 2016, Steve Holme, <address@hidden>.
+ * Copyright (C) 2014 - 2017, 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
@@ -119,7 +119,8 @@ void Curl_auth_digest_cleanup(struct digestdata *digest);
 bool Curl_auth_is_ntlm_supported(void);
 
 /* This is used to generate a base64 encoded NTLM type-1 message */
-CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
+CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
+                                             const char *userp,
                                              const char *passwdp,
                                              struct ntlmdata *ntlm,
                                              char **outptr,
diff --git a/lib/version.c b/lib/version.c
index 9207c3384..33e5fee3c 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -324,8 +324,8 @@ static curl_version_info_data version_info = {
 #if defined(USE_LIBPSL)
   | CURL_VERSION_PSL
 #endif
-#if defined(HTTPS_PROXY_SUPPORT)
-  | CURL_VERSION_HTTPS_PROXY
+#if defined(CURL_WITH_MULTI_SSL)
+  | CURL_VERSION_MULTI_SSL
 #endif
   ,
   NULL, /* ssl_version */
@@ -355,6 +355,10 @@ curl_version_info_data *curl_version_info(CURLversion 
stamp)
 #ifdef USE_SSL
   Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
   version_info.ssl_version = ssl_buffer;
+  if(Curl_ssl->support_https_proxy)
+    version_info.features |= CURL_VERSION_HTTPS_PROXY;
+  else
+    version_info.features &= ~CURL_VERSION_HTTPS_PROXY;
 #endif
 
 #ifdef HAVE_LIBZ
diff --git a/lib/vtls/axtls.c b/lib/vtls/axtls.c
index f0e376640..6b42708d8 100644
--- a/lib/vtls/axtls.c
+++ b/lib/vtls/axtls.c
@@ -47,21 +47,12 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
+struct ssl_backend_data {
+  SSL_CTX* ssl_ctx;
+  SSL*     ssl;
+};
 
-/* Global axTLS init, called from Curl_ssl_init() */
-int Curl_axtls_init(void)
-{
-/* axTLS has no global init.  Everything is done through SSL and SSL_CTX
- * structs stored in connectdata structure.  Perhaps can move to axtls.h.
- */
-  return 1;
-}
-
-int Curl_axtls_cleanup(void)
-{
-  /* axTLS has no global cleanup.  Perhaps can move this to axtls.h. */
-  return 1;
-}
+#define BACKEND connssl->backend
 
 static CURLcode map_error_to_curl(int axtls_err)
 {
@@ -120,13 +111,13 @@ static Curl_send axtls_send;
 
 static void free_ssl_structs(struct ssl_connect_data *connssl)
 {
-  if(connssl->ssl) {
-    ssl_free(connssl->ssl);
-    connssl->ssl = NULL;
+  if(BACKEND->ssl) {
+    ssl_free(BACKEND->ssl);
+    BACKEND->ssl = NULL;
   }
-  if(connssl->ssl_ctx) {
-    ssl_ctx_free(connssl->ssl_ctx);
-    connssl->ssl_ctx = NULL;
+  if(BACKEND->ssl_ctx) {
+    ssl_ctx_free(BACKEND->ssl_ctx);
+    BACKEND->ssl_ctx = NULL;
   }
 }
 
@@ -137,6 +128,7 @@ static void free_ssl_structs(struct ssl_connect_data 
*connssl)
  */
 static CURLcode connect_prep(struct connectdata *conn, int sockindex)
 {
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct Curl_easy *data = conn->data;
   SSL_CTX *ssl_ctx;
   SSL *ssl = NULL;
@@ -151,7 +143,7 @@ static CURLcode connect_prep(struct connectdata *conn, int 
sockindex)
     SSL_SERVER_VERIFY_LATER |
     SSL_CONNECT_IN_PARTS;
 
-  if(conn->ssl[sockindex].state == ssl_connection_complete)
+  if(connssl->state == ssl_connection_complete)
     /* to make us tolerant against being called more than once for the
        same connection */
     return CURLE_OK;
@@ -185,8 +177,8 @@ static CURLcode connect_prep(struct connectdata *conn, int 
sockindex)
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  conn->ssl[sockindex].ssl_ctx = ssl_ctx;
-  conn->ssl[sockindex].ssl = NULL;
+  BACKEND->ssl_ctx = ssl_ctx;
+  BACKEND->ssl = NULL;
 
   /* Load the trusted CA cert bundle file */
   if(SSL_CONN_CONFIG(CAfile)) {
@@ -212,7 +204,7 @@ static CURLcode connect_prep(struct connectdata *conn, int 
sockindex)
 
   /* Load client certificate */
   if(SSL_SET_OPTION(cert)) {
-    i=0;
+    i = 0;
     /* Instead of trying to analyze cert type here, let axTLS try them all. */
     while(cert_types[i] != 0) {
       ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
@@ -236,7 +228,7 @@ static CURLcode connect_prep(struct connectdata *conn, int 
sockindex)
      If a pkcs12 file successfully loaded a cert, then there's nothing to do
      because the key has already been loaded. */
   if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) {
-    i=0;
+    i = 0;
     /* Instead of trying to analyze key type here, let axTLS try them all. */
     while(key_types[i] != 0) {
       ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
@@ -281,10 +273,26 @@ static CURLcode connect_prep(struct connectdata *conn, 
int sockindex)
   if(!ssl)
     ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL);
 
-  conn->ssl[sockindex].ssl = ssl;
+  BACKEND->ssl = ssl;
   return CURLE_OK;
 }
 
+static void Curl_axtls_close(struct connectdata *conn, int sockindex)
+{
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+
+  infof(conn->data, "  Curl_axtls_close\n");
+
+    /* line from openssl.c: (void)SSL_shutdown(BACKEND->ssl);
+       axTLS compat layer does nothing for SSL_shutdown */
+
+    /* The following line is from openssl.c.  There seems to be no axTLS
+       equivalent.  ssl_free and ssl_ctx_free close things.
+       SSL_set_connect_state(connssl->handle); */
+
+  free_ssl_structs(connssl);
+}
+
 /*
  * For both blocking and non-blocking connects, this function finalizes the
  * SSL connection.
@@ -292,7 +300,8 @@ static CURLcode connect_prep(struct connectdata *conn, int 
sockindex)
 static CURLcode connect_finish(struct connectdata *conn, int sockindex)
 {
   struct Curl_easy *data = conn->data;
-  SSL *ssl = conn->ssl[sockindex].ssl;
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  SSL *ssl = BACKEND->ssl;
   const char *peer_CN;
   uint32_t dns_altname_index;
   const char *dns_altname;
@@ -387,7 +396,7 @@ static CURLcode connect_finish(struct connectdata *conn, 
int sockindex)
   }
 
   /* General housekeeping */
-  conn->ssl[sockindex].state = ssl_connection_complete;
+  connssl->state = ssl_connection_complete;
   conn->recv[sockindex] = axtls_recv;
   conn->send[sockindex] = axtls_send;
 
@@ -409,11 +418,10 @@ static CURLcode connect_finish(struct connectdata *conn, 
int sockindex)
  * Use axTLS's non-blocking connection feature to open an SSL connection.
  * This is called after a TCP connection is already established.
  */
-CURLcode Curl_axtls_connect_nonblocking(
-    struct connectdata *conn,
-    int sockindex,
-    bool *done)
+static CURLcode Curl_axtls_connect_nonblocking(struct connectdata *conn,
+                                               int sockindex, bool *done)
 {
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   CURLcode conn_step;
   int ssl_fcn_return;
   int i;
@@ -421,23 +429,23 @@ CURLcode Curl_axtls_connect_nonblocking(
  *done = FALSE;
   /* connectdata is calloc'd and connecting_state is only changed in this
      function, so this is safe, as the state is effectively initialized. */
-  if(conn->ssl[sockindex].connecting_state == ssl_connect_1) {
+  if(connssl->connecting_state == ssl_connect_1) {
     conn_step = connect_prep(conn, sockindex);
     if(conn_step != CURLE_OK) {
       Curl_axtls_close(conn, sockindex);
       return conn_step;
     }
-    conn->ssl[sockindex].connecting_state = ssl_connect_2;
+    connssl->connecting_state = ssl_connect_2;
   }
 
-  if(conn->ssl[sockindex].connecting_state == ssl_connect_2) {
+  if(connssl->connecting_state == ssl_connect_2) {
     /* Check to make sure handshake was ok. */
-    if(ssl_handshake_status(conn->ssl[sockindex].ssl) != SSL_OK) {
+    if(ssl_handshake_status(BACKEND->ssl) != SSL_OK) {
       /* Loop to perform more work in between sleeps. This is work around the
          fact that axtls does not expose any knowledge about when work needs
          to be performed. This can save ~25% of time on SSL handshakes. */
-      for(i=0; i<5; i++) {
-        ssl_fcn_return = ssl_read(conn->ssl[sockindex].ssl, NULL);
+      for(i = 0; i<5; i++) {
+        ssl_fcn_return = ssl_read(BACKEND->ssl, NULL);
         if(ssl_fcn_return < 0) {
           Curl_axtls_close(conn, sockindex);
           ssl_display_error(ssl_fcn_return); /* goes to stdout. */
@@ -447,10 +455,10 @@ CURLcode Curl_axtls_connect_nonblocking(
       }
     }
     infof(conn->data, "handshake completed successfully\n");
-    conn->ssl[sockindex].connecting_state = ssl_connect_3;
+    connssl->connecting_state = ssl_connect_3;
   }
 
-  if(conn->ssl[sockindex].connecting_state == ssl_connect_3) {
+  if(connssl->connecting_state == ssl_connect_3) {
     conn_step = connect_finish(conn, sockindex);
     if(conn_step != CURLE_OK) {
       Curl_axtls_close(conn, sockindex);
@@ -458,15 +466,15 @@ CURLcode Curl_axtls_connect_nonblocking(
     }
 
     /* Reset connect state */
-    conn->ssl[sockindex].connecting_state = ssl_connect_1;
+    connssl->connecting_state = ssl_connect_1;
 
     *done = TRUE;
     return CURLE_OK;
   }
 
   /* Unrecognized state.  Things are very bad. */
-  conn->ssl[sockindex].state  = ssl_connection_none;
-  conn->ssl[sockindex].connecting_state = ssl_connect_1;
+  connssl->state  = ssl_connection_none;
+  connssl->connecting_state = ssl_connect_1;
   /* Return value perhaps not strictly correct, but distinguishes the issue.*/
   return CURLE_BAD_FUNCTION_ARGUMENT;
 }
@@ -476,15 +484,13 @@ CURLcode Curl_axtls_connect_nonblocking(
  * This function is called after the TCP connect has completed. Setup the TLS
  * layer and do all necessary magic for a blocking connect.
  */
-CURLcode
-Curl_axtls_connect(struct connectdata *conn,
-                  int sockindex)
-
+static CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex)
 {
   struct Curl_easy *data = conn->data;
   CURLcode conn_step = connect_prep(conn, sockindex);
   int ssl_fcn_return;
-  SSL *ssl = conn->ssl[sockindex].ssl;
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  SSL *ssl = BACKEND->ssl;
   long timeout_ms;
 
   if(conn_step != CURLE_OK) {
@@ -530,8 +536,9 @@ static ssize_t axtls_send(struct connectdata *conn,
                           size_t len,
                           CURLcode *err)
 {
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   /* ssl_write() returns 'int' while write() and send() returns 'size_t' */
-  int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len);
+  int rc = ssl_write(BACKEND->ssl, mem, (int)len);
 
   infof(conn->data, "  axtls_send\n");
 
@@ -544,27 +551,11 @@ static ssize_t axtls_send(struct connectdata *conn,
   return rc;
 }
 
-void Curl_axtls_close(struct connectdata *conn, int sockindex)
-{
-  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-
-  infof(conn->data, "  Curl_axtls_close\n");
-
-    /* line from openssl.c: (void)SSL_shutdown(connssl->ssl);
-       axTLS compat layer does nothing for SSL_shutdown */
-
-    /* The following line is from openssl.c.  There seems to be no axTLS
-       equivalent.  ssl_free and ssl_ctx_free close things.
-       SSL_set_connect_state(connssl->handle); */
-
-  free_ssl_structs(connssl);
-}
-
 /*
  * This function is called to shut down the SSL layer but keep the
  * socket open (CCC - Clear Command Channel)
  */
-int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
 {
   /* Outline taken from openssl.c since functions are in axTLS compat layer.
      axTLS's error set is much smaller, so a lot of error-handling was removed.
@@ -584,17 +575,17 @@ int Curl_axtls_shutdown(struct connectdata *conn, int 
sockindex)
 
   /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
-      (void)SSL_shutdown(connssl->ssl);
+      (void)SSL_shutdown(BACKEND->ssl);
   */
 
-  if(connssl->ssl) {
+  if(BACKEND->ssl) {
     int what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
     if(what > 0) {
       /* Something to read, let's do it and hope that it is the close
          notify alert from the server.  buf is managed internally by
          axTLS and will be released upon calling ssl_free via
          free_ssl_structs. */
-      nread = (ssize_t)ssl_read(connssl->ssl, &buf);
+      nread = (ssize_t)ssl_read(BACKEND->ssl, &buf);
 
       if(nread < SSL_OK) {
         failf(data, "close notify alert not received during shutdown");
@@ -630,7 +621,7 @@ static ssize_t axtls_recv(struct connectdata *conn, /* 
connection data */
 
   *err = CURLE_OK;
   if(connssl) {
-    ret = ssl_read(connssl->ssl, &read_buf);
+    ret = ssl_read(BACKEND->ssl, &read_buf);
     if(ret > SSL_OK) {
       /* ssl_read returns SSL_OK if there is more data to read, so if it is
          larger, then all data has been read already.  */
@@ -663,9 +654,10 @@ static ssize_t axtls_recv(struct connectdata *conn, /* 
connection data */
  *     0 means the connection has been closed
  *    -1 means the connection status is unknown
  */
-int Curl_axtls_check_cxn(struct connectdata *conn)
+static int Curl_axtls_check_cxn(struct connectdata *conn)
 {
-  /* openssl.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1);
+  /* openssl.c line:
+     rc = SSL_peek(conn->ssl[FIRSTSOCKET].backend->ssl, (void*)&buf, 1);
      axTLS compat layer always returns the last argument, so connection is
      always alive? */
 
@@ -673,7 +665,7 @@ int Curl_axtls_check_cxn(struct connectdata *conn)
    return 1; /* connection still in place */
 }
 
-void Curl_axtls_session_free(void *ptr)
+static void Curl_axtls_session_free(void *ptr)
 {
   (void)ptr;
   /* free the ID */
@@ -681,14 +673,13 @@ void Curl_axtls_session_free(void *ptr)
      compatibility layer does nothing, so we do nothing too. */
 }
 
-size_t Curl_axtls_version(char *buffer, size_t size)
+static size_t Curl_axtls_version(char *buffer, size_t size)
 {
   return snprintf(buffer, size, "axTLS/%s", ssl_version());
 }
 
-CURLcode Curl_axtls_random(struct Curl_easy *data,
-                           unsigned char *entropy,
-                           size_t length)
+static CURLcode Curl_axtls_random(struct Curl_easy *data,
+                                  unsigned char *entropy, size_t length)
 {
   static bool ssl_seeded = FALSE;
   (void)data;
@@ -703,4 +694,49 @@ CURLcode Curl_axtls_random(struct Curl_easy *data,
   return CURLE_OK;
 }
 
+static void *Curl_axtls_get_internals(struct ssl_connect_data *connssl,
+                                      CURLINFO info UNUSED_PARAM)
+{
+  (void)info;
+  return BACKEND->ssl;
+}
+
+const struct Curl_ssl Curl_ssl_axtls = {
+  { CURLSSLBACKEND_AXTLS, "axtls" }, /* info */
+
+  0, /* have_ca_path */
+  0, /* have_certinfo */
+  0, /* have_pinnedpubkey */
+  0, /* have_ssl_ctx */
+  0, /* support_https_proxy */
+
+  sizeof(struct ssl_backend_data),
+
+  /*
+   * axTLS has no global init.  Everything is done through SSL and SSL_CTX
+   * structs stored in connectdata structure.
+   */
+  Curl_none_init,                 /* init */
+  /* axTLS has no global cleanup. */
+  Curl_none_cleanup,              /* cleanup */
+  Curl_axtls_version,             /* version */
+  Curl_axtls_check_cxn,           /* check_cxn */
+  Curl_axtls_shutdown,            /* shutdown */
+  Curl_none_data_pending,         /* data_pending */
+  Curl_axtls_random,              /* random */
+  Curl_none_cert_status_request,  /* cert_status_request */
+  Curl_axtls_connect,             /* connect */
+  Curl_axtls_connect_nonblocking, /* connect_nonblocking */
+  Curl_axtls_get_internals,       /* get_internals */
+  Curl_axtls_close,               /* close */
+  Curl_none_close_all,            /* close_all */
+  Curl_axtls_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 */
+  NULL                            /* sha256sum */
+};
+
 #endif /* USE_AXTLS */
diff --git a/lib/vtls/axtls.h b/lib/vtls/axtls.h
index 4e5994666..5f518e4b7 100644
--- a/lib/vtls/axtls.h
+++ b/lib/vtls/axtls.h
@@ -27,44 +27,7 @@
 #include "gnurl/curl.h"
 #include "urldata.h"
 
-int Curl_axtls_init(void);
-int Curl_axtls_cleanup(void);
-CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex);
-CURLcode Curl_axtls_connect_nonblocking(
-    struct connectdata *conn,
-    int sockindex,
-    bool *done);
-
- /* close a SSL connection */
-void Curl_axtls_close(struct connectdata *conn, int sockindex);
-
-void Curl_axtls_session_free(void *ptr);
-size_t Curl_axtls_version(char *buffer, size_t size);
-int Curl_axtls_shutdown(struct connectdata *conn, int sockindex);
-int Curl_axtls_check_cxn(struct connectdata *conn);
-CURLcode Curl_axtls_random(struct Curl_easy *data,
-                           unsigned char *entropy,
-                           size_t length);
-
-/* Set the API backend definition to axTLS */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_AXTLS
-
-/* API setup for axTLS */
-#define curlssl_init Curl_axtls_init
-#define curlssl_cleanup Curl_axtls_cleanup
-#define curlssl_connect Curl_axtls_connect
-#define curlssl_connect_nonblocking Curl_axtls_connect_nonblocking
-#define curlssl_session_free(x)  Curl_axtls_session_free(x)
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_axtls_close
-#define curlssl_shutdown(x,y) Curl_axtls_shutdown(x,y)
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_axtls_version
-#define curlssl_check_cxn(x) Curl_axtls_check_cxn(x)
-#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
-#define curlssl_random(x,y,z) Curl_axtls_random(x,y,z)
+extern const struct Curl_ssl Curl_ssl_axtls;
 
 #endif /* USE_AXTLS */
 #endif /* HEADER_CURL_AXTLS_H */
diff --git a/lib/vtls/cyassl.c b/lib/vtls/cyassl.c
index 01bfdabd1..ba5ee1548 100644
--- a/lib/vtls/cyassl.c
+++ b/lib/vtls/cyassl.c
@@ -91,6 +91,7 @@ and that's a problem since options.h hasn't been included 
yet. */
 #include "x509asn1.h"
 #include "curl_printf.h"
 
+#include <cyassl/openssl/ssl.h>
 #include <cyassl/ssl.h>
 #ifdef HAVE_CYASSL_ERROR_SSL_H
 #include <cyassl/error-ssl.h>
@@ -110,6 +111,25 @@ and that's a problem since options.h hasn't been included 
yet. */
 #define CYASSL_MAX_ERROR_SZ 80
 #endif
 
+/* KEEP_PEER_CERT is a product of the presence of build time symbol
+   OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
+   in wolfSSL's settings.h, and the latter two are build time symbols in
+   options.h. */
+#ifndef KEEP_PEER_CERT
+#if defined(HAVE_CYASSL_GET_PEER_CERTIFICATE) || \
+    defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
+    (defined(OPENSSL_EXTRA) && !defined(NO_CERTS))
+#define KEEP_PEER_CERT
+#endif
+#endif
+
+struct ssl_backend_data {
+  SSL_CTX* ctx;
+  SSL*     handle;
+};
+
+#define BACKEND connssl->backend
+
 static Curl_recv cyassl_recv;
 static Curl_send cyassl_send;
 
@@ -136,7 +156,7 @@ cyassl_connect_step1(struct connectdata *conn,
   char error_buffer[CYASSL_MAX_ERROR_SZ];
   char *ciphers;
   struct Curl_easy *data = conn->data;
-  struct ssl_connect_data* conssl = &conn->ssl[sockindex];
+  struct ssl_connect_data* connssl = &conn->ssl[sockindex];
   SSL_METHOD* req_method = NULL;
   curl_socket_t sockfd = conn->sock[sockindex];
 #ifdef HAVE_SNI
@@ -146,7 +166,7 @@ cyassl_connect_step1(struct connectdata *conn,
 #define use_sni(x)  Curl_nop_stmt
 #endif
 
-  if(conssl->state == ssl_connection_complete)
+  if(connssl->state == ssl_connection_complete)
     return CURLE_OK;
 
   if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
@@ -205,11 +225,11 @@ cyassl_connect_step1(struct connectdata *conn,
     return CURLE_OUT_OF_MEMORY;
   }
 
-  if(conssl->ctx)
-    SSL_CTX_free(conssl->ctx);
-  conssl->ctx = SSL_CTX_new(req_method);
+  if(BACKEND->ctx)
+    SSL_CTX_free(BACKEND->ctx);
+  BACKEND->ctx = SSL_CTX_new(req_method);
 
-  if(!conssl->ctx) {
+  if(!BACKEND->ctx) {
     failf(data, "SSL: couldn't create a context!");
     return CURLE_OUT_OF_MEMORY;
   }
@@ -225,9 +245,9 @@ cyassl_connect_step1(struct connectdata *conn,
     version. We use wolfSSL_CTX_SetMinVersion and not CyaSSL_SetMinVersion
     because only the former will work before the user's CTX callback is called.
     */
-    if((wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1) != 1) &&
-       (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_1) != 1) &&
-       (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_2) != 1)) {
+    if((wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1) != 1) &&
+       (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_1) != 1) &&
+       (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1)) {
       failf(data, "SSL: couldn't set the minimum protocol version");
       return CURLE_SSL_CONNECT_ERROR;
     }
@@ -237,7 +257,7 @@ cyassl_connect_step1(struct connectdata *conn,
 
   ciphers = SSL_CONN_CONFIG(cipher_list);
   if(ciphers) {
-    if(!SSL_CTX_set_cipher_list(conssl->ctx, ciphers)) {
+    if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) {
       failf(data, "failed setting cipher list: %s", ciphers);
       return CURLE_SSL_CIPHER;
     }
@@ -247,7 +267,7 @@ cyassl_connect_step1(struct connectdata *conn,
 #ifndef NO_FILESYSTEM
   /* load trusted cacert */
   if(SSL_CONN_CONFIG(CAfile)) {
-    if(1 != SSL_CTX_load_verify_locations(conssl->ctx,
+    if(1 != SSL_CTX_load_verify_locations(BACKEND->ctx,
                                       SSL_CONN_CONFIG(CAfile),
                                       SSL_CONN_CONFIG(CApath))) {
       if(SSL_CONN_CONFIG(verifypeer)) {
@@ -284,7 +304,7 @@ cyassl_connect_step1(struct connectdata *conn,
   if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
     int file_type = do_file_type(SSL_SET_OPTION(cert_type));
 
-    if(SSL_CTX_use_certificate_file(conssl->ctx, SSL_SET_OPTION(cert),
+    if(SSL_CTX_use_certificate_file(BACKEND->ctx, SSL_SET_OPTION(cert),
                                      file_type) != 1) {
       failf(data, "unable to use client certificate (no key or wrong pass"
             " phrase?)");
@@ -292,7 +312,7 @@ cyassl_connect_step1(struct connectdata *conn,
     }
 
     file_type = do_file_type(SSL_SET_OPTION(key_type));
-    if(SSL_CTX_use_PrivateKey_file(conssl->ctx, SSL_SET_OPTION(key),
+    if(SSL_CTX_use_PrivateKey_file(BACKEND->ctx, SSL_SET_OPTION(key),
                                     file_type) != 1) {
       failf(data, "unable to set private key");
       return CURLE_SSL_CONNECT_ERROR;
@@ -304,7 +324,7 @@ cyassl_connect_step1(struct connectdata *conn,
    * fail to connect if the verification fails, or if it should continue
    * anyway. In the latter case the result of the verification is checked with
    * SSL_get_verify_result() below. */
-  SSL_CTX_set_verify(conssl->ctx,
+  SSL_CTX_set_verify(BACKEND->ctx,
                      SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER:
                                                  SSL_VERIFY_NONE,
                      NULL);
@@ -323,7 +343,7 @@ cyassl_connect_step1(struct connectdata *conn,
 #ifdef ENABLE_IPV6
        (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
 #endif
-       (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, hostname,
+       (CyaSSL_CTX_UseSNI(BACKEND->ctx, CYASSL_SNI_HOST_NAME, hostname,
                           (unsigned short)hostname_len) != 1)) {
       infof(data, "WARNING: failed to configure server name indication (SNI) "
             "TLS extension\n");
@@ -336,15 +356,15 @@ cyassl_connect_step1(struct connectdata *conn,
      https://github.com/wolfSSL/wolfssl/issues/366
      The supported curves below are those also supported by OpenSSL 1.0.2 and
      in the same order. */
-  CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x17); /* secp256r1 */
-  CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x19); /* secp521r1 */
-  CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x18); /* secp384r1 */
+  CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x17); /* secp256r1 */
+  CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x19); /* secp521r1 */
+  CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x18); /* secp384r1 */
 #endif
 
   /* give application a chance to interfere with SSL set up. */
   if(data->set.ssl.fsslctx) {
     CURLcode result = CURLE_OK;
-    result = (*data->set.ssl.fsslctx)(data, conssl->ctx,
+    result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx,
                                       data->set.ssl.fsslctxp);
     if(result) {
       failf(data, "error signaled by ssl ctx callback");
@@ -362,10 +382,10 @@ cyassl_connect_step1(struct connectdata *conn,
 #endif
 
   /* Let's make an SSL structure */
-  if(conssl->handle)
-    SSL_free(conssl->handle);
-  conssl->handle = SSL_new(conssl->ctx);
-  if(!conssl->handle) {
+  if(BACKEND->handle)
+    SSL_free(BACKEND->handle);
+  BACKEND->handle = SSL_new(BACKEND->ctx);
+  if(!BACKEND->handle) {
     failf(data, "SSL: couldn't create a context (handle)!");
     return CURLE_OUT_OF_MEMORY;
   }
@@ -388,7 +408,7 @@ cyassl_connect_step1(struct connectdata *conn,
     strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1);
     infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
 
-    if(wolfSSL_UseALPN(conssl->handle, protocols,
+    if(wolfSSL_UseALPN(BACKEND->handle, protocols,
                        (unsigned)strlen(protocols),
                        WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {
       failf(data, "SSL: failed setting ALPN protocols");
@@ -404,10 +424,10 @@ cyassl_connect_step1(struct connectdata *conn,
     Curl_ssl_sessionid_lock(conn);
     if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
       /* we got a session id, use it! */
-      if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
+      if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
         Curl_ssl_sessionid_unlock(conn);
         failf(data, "SSL: SSL_set_session failed: %s",
-              ERR_error_string(SSL_get_error(conssl->handle, 0),
+              ERR_error_string(SSL_get_error(BACKEND->handle, 0),
               error_buffer));
         return CURLE_SSL_CONNECT_ERROR;
       }
@@ -418,12 +438,12 @@ cyassl_connect_step1(struct connectdata *conn,
   }
 
   /* pass the raw socket into the SSL layer */
-  if(!SSL_set_fd(conssl->handle, (int)sockfd)) {
+  if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) {
     failf(data, "SSL: SSL_set_fd failed");
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  conssl->connecting_state = ssl_connect_2;
+  connssl->connecting_state = ssl_connect_2;
   return CURLE_OK;
 }
 
@@ -434,7 +454,7 @@ cyassl_connect_step2(struct connectdata *conn,
 {
   int ret = -1;
   struct Curl_easy *data = conn->data;
-  struct ssl_connect_data* conssl = &conn->ssl[sockindex];
+  struct ssl_connect_data* connssl = &conn->ssl[sockindex];
   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
     conn->host.name;
   const char * const dispname = SSL_IS_PROXY() ?
@@ -448,22 +468,22 @@ cyassl_connect_step2(struct connectdata *conn,
 
   /* Enable RFC2818 checks */
   if(SSL_CONN_CONFIG(verifyhost)) {
-    ret = CyaSSL_check_domain_name(conssl->handle, hostname);
+    ret = CyaSSL_check_domain_name(BACKEND->handle, hostname);
     if(ret == SSL_FAILURE)
       return CURLE_OUT_OF_MEMORY;
   }
 
-  ret = SSL_connect(conssl->handle);
+  ret = SSL_connect(BACKEND->handle);
   if(ret != 1) {
     char error_buffer[CYASSL_MAX_ERROR_SZ];
-    int  detail = SSL_get_error(conssl->handle, ret);
+    int  detail = SSL_get_error(BACKEND->handle, ret);
 
     if(SSL_ERROR_WANT_READ == detail) {
-      conssl->connecting_state = ssl_connect_2_reading;
+      connssl->connecting_state = ssl_connect_2_reading;
       return CURLE_OK;
     }
     else if(SSL_ERROR_WANT_WRITE == detail) {
-      conssl->connecting_state = ssl_connect_2_writing;
+      connssl->connecting_state = ssl_connect_2_writing;
       return CURLE_OK;
     }
     /* There is no easy way to override only the CN matching.
@@ -524,7 +544,7 @@ cyassl_connect_step2(struct connectdata *conn,
     curl_asn1Element *pubkey;
     CURLcode result;
 
-    x509 = SSL_get_peer_certificate(conssl->handle);
+    x509 = SSL_get_peer_certificate(BACKEND->handle);
     if(!x509) {
       failf(data, "SSL: failed retrieving server certificate");
       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
@@ -566,7 +586,7 @@ cyassl_connect_step2(struct connectdata *conn,
     char *protocol = NULL;
     unsigned short protocol_len = 0;
 
-    rc = wolfSSL_ALPN_GetProtocol(conssl->handle, &protocol, &protocol_len);
+    rc = wolfSSL_ALPN_GetProtocol(BACKEND->handle, &protocol, &protocol_len);
 
     if(rc == SSL_SUCCESS) {
       infof(data, "ALPN, server accepted to use %.*s\n", protocol_len,
@@ -595,11 +615,11 @@ cyassl_connect_step2(struct connectdata *conn,
   }
 #endif /* HAVE_ALPN */
 
-  conssl->connecting_state = ssl_connect_3;
+  connssl->connecting_state = ssl_connect_3;
 #if (LIBCYASSL_VERSION_HEX >= 0x03009010)
   infof(data, "SSL connection using %s / %s\n",
-        wolfSSL_get_version(conssl->handle),
-        wolfSSL_get_cipher_name(conssl->handle));
+        wolfSSL_get_version(BACKEND->handle),
+        wolfSSL_get_cipher_name(BACKEND->handle));
 #else
   infof(data, "SSL connected\n");
 #endif
@@ -623,7 +643,7 @@ cyassl_connect_step3(struct connectdata *conn,
     SSL_SESSION *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
 
-    our_ssl_sessionid = SSL_get_session(connssl->handle);
+    our_ssl_sessionid = SSL_get_session(BACKEND->handle);
 
     Curl_ssl_sessionid_lock(conn);
     incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
@@ -660,12 +680,13 @@ static ssize_t cyassl_send(struct connectdata *conn,
                            size_t len,
                            CURLcode *curlcode)
 {
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   char error_buffer[CYASSL_MAX_ERROR_SZ];
   int  memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
-  int  rc     = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
+  int  rc     = SSL_write(BACKEND->handle, mem, memlen);
 
   if(rc < 0) {
-    int err = SSL_get_error(conn->ssl[sockindex].handle, rc);
+    int err = SSL_get_error(BACKEND->handle, rc);
 
     switch(err) {
     case SSL_ERROR_WANT_READ:
@@ -684,18 +705,18 @@ static ssize_t cyassl_send(struct connectdata *conn,
   return rc;
 }
 
-void Curl_cyassl_close(struct connectdata *conn, int sockindex)
+static void Curl_cyassl_close(struct connectdata *conn, int sockindex)
 {
-  struct ssl_connect_data *conssl = &conn->ssl[sockindex];
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
-  if(conssl->handle) {
-    (void)SSL_shutdown(conssl->handle);
-    SSL_free(conssl->handle);
-    conssl->handle = NULL;
+  if(BACKEND->handle) {
+    (void)SSL_shutdown(BACKEND->handle);
+    SSL_free(BACKEND->handle);
+    BACKEND->handle = NULL;
   }
-  if(conssl->ctx) {
-    SSL_CTX_free(conssl->ctx);
-    conssl->ctx = NULL;
+  if(BACKEND->ctx) {
+    SSL_CTX_free(BACKEND->ctx);
+    BACKEND->ctx = NULL;
   }
 }
 
@@ -705,12 +726,13 @@ static ssize_t cyassl_recv(struct connectdata *conn,
                            size_t buffersize,
                            CURLcode *curlcode)
 {
+  struct ssl_connect_data *connssl = &conn->ssl[num];
   char error_buffer[CYASSL_MAX_ERROR_SZ];
   int  buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
-  int  nread    = SSL_read(conn->ssl[num].handle, buf, buffsize);
+  int  nread    = SSL_read(BACKEND->handle, buf, buffsize);
 
   if(nread < 0) {
-    int err = SSL_get_error(conn->ssl[num].handle, nread);
+    int err = SSL_get_error(BACKEND->handle, nread);
 
     switch(err) {
     case SSL_ERROR_ZERO_RETURN: /* no more data */
@@ -732,14 +754,14 @@ static ssize_t cyassl_recv(struct connectdata *conn,
 }
 
 
-void Curl_cyassl_session_free(void *ptr)
+static void Curl_cyassl_session_free(void *ptr)
 {
   (void)ptr;
   /* CyaSSL reuses sessions on own, no free */
 }
 
 
-size_t Curl_cyassl_version(char *buffer, size_t size)
+static size_t Curl_cyassl_version(char *buffer, size_t size)
 {
 #if LIBCYASSL_VERSION_HEX >= 0x03006000
   return snprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
@@ -753,16 +775,18 @@ size_t Curl_cyassl_version(char *buffer, size_t size)
 }
 
 
-int Curl_cyassl_init(void)
+static int Curl_cyassl_init(void)
 {
   return (CyaSSL_Init() == SSL_SUCCESS);
 }
 
 
-bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex)
+static bool Curl_cyassl_data_pending(const struct connectdata* conn,
+                                     int connindex)
 {
-  if(conn->ssl[connindex].handle)   /* SSL is in use */
-    return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
+  const struct ssl_connect_data *connssl = &conn->ssl[connindex];
+  if(BACKEND->handle)   /* SSL is in use */
+    return (0 != SSL_pending(BACKEND->handle)) ? TRUE : FALSE;
   else
     return FALSE;
 }
@@ -772,14 +796,14 @@ bool Curl_cyassl_data_pending(const struct connectdata* 
conn, int connindex)
  * This function is called to shut down the SSL layer but keep the
  * socket open (CCC - Clear Command Channel)
  */
-int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
 {
   int retval = 0;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
-  if(connssl->handle) {
-    SSL_free(connssl->handle);
-    connssl->handle = NULL;
+  if(BACKEND->handle) {
+    SSL_free(BACKEND->handle);
+    BACKEND->handle = NULL;
   }
   return retval;
 }
@@ -804,7 +828,7 @@ cyassl_connect_common(struct connectdata *conn,
     return CURLE_OK;
   }
 
-  if(ssl_connect_1==connssl->connecting_state) {
+  if(ssl_connect_1 == connssl->connecting_state) {
     /* Find out how much more time we're allowed */
     timeout_ms = Curl_timeleft(data, NULL, TRUE);
 
@@ -836,9 +860,9 @@ cyassl_connect_common(struct connectdata *conn,
     if(connssl->connecting_state == ssl_connect_2_reading
        || connssl->connecting_state == ssl_connect_2_writing) {
 
-      curl_socket_t writefd = 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==
+      curl_socket_t readfd = ssl_connect_2_reading ==
         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
 
       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
@@ -899,18 +923,14 @@ cyassl_connect_common(struct connectdata *conn,
 }
 
 
-CURLcode
-Curl_cyassl_connect_nonblocking(struct connectdata *conn,
-                                int sockindex,
-                                bool *done)
+static CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn,
+                                                int sockindex, bool *done)
 {
   return cyassl_connect_common(conn, sockindex, TRUE, done);
 }
 
 
-CURLcode
-Curl_cyassl_connect(struct connectdata *conn,
-                    int sockindex)
+static CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex)
 {
   CURLcode result;
   bool done = FALSE;
@@ -924,9 +944,8 @@ Curl_cyassl_connect(struct connectdata *conn,
   return CURLE_OK;
 }
 
-CURLcode Curl_cyassl_random(struct Curl_easy *data,
-                            unsigned char *entropy,
-                            size_t length)
+static CURLcode Curl_cyassl_random(struct Curl_easy *data,
+                                   unsigned char *entropy, size_t length)
 {
   RNG rng;
   (void)data;
@@ -939,10 +958,10 @@ CURLcode Curl_cyassl_random(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
-                      size_t tmplen,
-                      unsigned char *sha256sum /* output */,
-                      size_t unused)
+static void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
+                                  size_t tmplen,
+                                  unsigned char *sha256sum /* output */,
+                                  size_t unused)
 {
   Sha256 SHA256pw;
   (void)unused;
@@ -951,4 +970,48 @@ void Curl_cyassl_sha256sum(const unsigned char *tmp, /* 
input */
   Sha256Final(&SHA256pw, sha256sum);
 }
 
+static void *Curl_cyassl_get_internals(struct ssl_connect_data *connssl,
+                                       CURLINFO info UNUSED_PARAM)
+{
+  (void)info;
+  return BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_cyassl = {
+  { CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */
+
+  0, /* have_ca_path */
+  0, /* have_certinfo */
+#ifdef KEEP_PEER_CERT
+  1, /* have_pinnedpubkey */
+#else
+  0, /* have_pinnedpubkey */
+#endif
+  1, /* have_ssl_ctx */
+  0, /* support_https_proxy */
+
+  sizeof(struct ssl_backend_data),
+
+  Curl_cyassl_init,                /* init */
+  Curl_none_cleanup,               /* cleanup */
+  Curl_cyassl_version,             /* version */
+  Curl_none_check_cxn,             /* check_cxn */
+  Curl_cyassl_shutdown,            /* shutdown */
+  Curl_cyassl_data_pending,        /* data_pending */
+  Curl_cyassl_random,              /* random */
+  Curl_none_cert_status_request,   /* cert_status_request */
+  Curl_cyassl_connect,             /* connect */
+  Curl_cyassl_connect_nonblocking, /* connect_nonblocking */
+  Curl_cyassl_get_internals,       /* get_internals */
+  Curl_cyassl_close,               /* close */
+  Curl_none_close_all,             /* close_all */
+  Curl_cyassl_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_cyassl_sha256sum            /* sha256sum */
+};
+
 #endif
diff --git a/lib/vtls/cyassl.h b/lib/vtls/cyassl.h
index f47719e4e..01e11cc23 100644
--- a/lib/vtls/cyassl.h
+++ b/lib/vtls/cyassl.h
@@ -25,68 +25,7 @@
 
 #ifdef USE_CYASSL
 
-/* KEEP_PEER_CERT is a product of the presence of build time symbol
-   OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
-   in wolfSSL's settings.h, and the latter two are build time symbols in
-   options.h. */
-#ifndef KEEP_PEER_CERT
-#if defined(HAVE_CYASSL_GET_PEER_CERTIFICATE) || \
-    defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
-    (defined(OPENSSL_EXTRA) && !defined(NO_CERTS))
-#define KEEP_PEER_CERT
-#endif
-#endif
-
-CURLcode Curl_cyassl_connect(struct connectdata *conn, int sockindex);
-bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex);
-int Curl_cyassl_shutdown(struct connectdata* conn, int sockindex);
-
- /* close a SSL connection */
-void Curl_cyassl_close(struct connectdata *conn, int sockindex);
-
-void Curl_cyassl_session_free(void *ptr);
-size_t Curl_cyassl_version(char *buffer, size_t size);
-int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex);
-int Curl_cyassl_init(void);
-CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn,
-                                         int sockindex,
-                                         bool *done);
-CURLcode Curl_cyassl_random(struct Curl_easy *data,
-                            unsigned char *entropy,
-                            size_t length);
-void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
-                     size_t tmplen,
-                     unsigned char *sha256sum, /* output */
-                     size_t unused);
-
-/* Set the API backend definition to CyaSSL */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL
-
-/* this backend supports CURLOPT_SSL_CTX_* */
-#define have_curlssl_ssl_ctx 1
-
-#ifdef KEEP_PEER_CERT
-/* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-#endif
-
-/* API setup for CyaSSL */
-#define curlssl_init Curl_cyassl_init
-#define curlssl_cleanup() Curl_nop_stmt
-#define curlssl_connect Curl_cyassl_connect
-#define curlssl_connect_nonblocking Curl_cyassl_connect_nonblocking
-#define curlssl_session_free(x)  Curl_cyassl_session_free(x)
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_cyassl_close
-#define curlssl_shutdown(x,y) Curl_cyassl_shutdown(x,y)
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_cyassl_version
-#define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending(x,y) Curl_cyassl_data_pending(x,y)
-#define curlssl_random(x,y,z) Curl_cyassl_random(x,y,z)
-#define curlssl_sha256sum(a,b,c,d) Curl_cyassl_sha256sum(a,b,c,d)
+extern const struct Curl_ssl Curl_ssl_cyassl;
 
 #endif /* USE_CYASSL */
 #endif /* HEADER_CURL_CYASSL_H */
diff --git a/lib/vtls/darwinssl.c b/lib/vtls/darwinssl.c
index 6f9c6012e..a98f43307 100644
--- a/lib/vtls/darwinssl.c
+++ b/lib/vtls/darwinssl.c
@@ -44,6 +44,8 @@
 #endif
 
 #include <Security/Security.h>
+/* For some reason, when building for iOS, the omnibus header above does
+ * not include SecureTransport.h as of iOS SDK 5.1. */
 #include <Security/SecureTransport.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <CommonCrypto/CommonDigest.h>
@@ -118,6 +120,33 @@
 #define ioErr -36
 #define paramErr -50
 
+struct ssl_backend_data {
+  SSLContextRef ssl_ctx;
+  curl_socket_t ssl_sockfd;
+  bool ssl_direction; /* true if writing, false if reading */
+  size_t ssl_write_buffered_length;
+};
+
+#define BACKEND connssl->backend
+
+/* pinned public key support tests */
+
+/* version 1 supports macOS 10.12+ and iOS 10+ */
+#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
+    (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED  >= 101200))
+#define DARWIN_SSL_PINNEDPUBKEY_V1 1
+#endif
+
+/* version 2 supports MacOSX 10.7+ */
+#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
+#define DARWIN_SSL_PINNEDPUBKEY_V2 1
+#endif
+
+#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2)
+/* this backend supports CURLOPT_PINNEDPUBLICKEY */
+#define DARWIN_SSL_PINNEDPUBKEY 1
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+
 #ifdef DARWIN_SSL_PINNEDPUBKEY
 /* both new and old APIs return rsa keys missing the spki header (not DER) */
 static const unsigned char rsa4096SpkiHeader[] = {
@@ -161,7 +190,7 @@ static OSStatus SocketRead(SSLConnectionRef connection,
   UInt8 *currData = (UInt8 *)data;
   /*int sock = *(int *)connection;*/
   struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
-  int sock = connssl->ssl_sockfd;
+  int sock = BACKEND->ssl_sockfd;
   OSStatus rtn = noErr;
   size_t bytesRead;
   ssize_t rrtn;
@@ -190,7 +219,7 @@ static OSStatus SocketRead(SSLConnectionRef connection,
             break;
           case EAGAIN:
             rtn = errSSLWouldBlock;
-            connssl->ssl_direction = false;
+            BACKEND->ssl_direction = false;
             break;
           default:
             rtn = ioErr;
@@ -221,7 +250,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
   size_t bytesSent = 0;
   /*int sock = *(int *)connection;*/
   struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
-  int sock = connssl->ssl_sockfd;
+  int sock = BACKEND->ssl_sockfd;
   ssize_t length;
   size_t dataLen = *dataLength;
   const UInt8 *dataPtr = (UInt8 *)data;
@@ -241,7 +270,7 @@ static OSStatus SocketWrite(SSLConnectionRef connection,
     theErr = errno;
     if(theErr == EAGAIN) {
       ortn = errSSLWouldBlock;
-      connssl->ssl_direction = true;
+      BACKEND->ssl_direction = true;
     }
     else {
       ortn = ioErr;
@@ -849,7 +878,7 @@ CF_INLINE void GetDarwinVersionNumber(int *major, int 
*minor)
    into a string. Some aren't available under iOS or newer cats. So here's
    a unified function for getting a string describing the certificate that
    ought to work in all cats starting with Leopard. */
-CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef cert)
+CF_INLINE CFStringRef getsubject(SecCertificateRef cert)
 {
   CFStringRef server_cert_summary = CFSTR("(null)");
 
@@ -876,6 +905,54 @@ CF_INLINE CFStringRef CopyCertSubject(SecCertificateRef 
cert)
   return server_cert_summary;
 }
 
+static CURLcode CopyCertSubject(struct Curl_easy *data,
+                                SecCertificateRef cert, char **certp)
+{
+  CFStringRef c = getsubject(cert);
+  CURLcode result = CURLE_OK;
+  const char *direct;
+  char *cbuf = NULL;
+  *certp = NULL;
+
+  if(!c) {
+    failf(data, "SSL: invalid CA certificate subject");
+    return CURLE_OUT_OF_MEMORY;
+  }
+
+  /* If the subject is already available as UTF-8 encoded (ie 'direct') then
+     use that, else convert it. */
+  direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8);
+  if(direct) {
+    *certp = strdup(direct);
+    if(!*certp) {
+      failf(data, "SSL: out of memory");
+      result = CURLE_OUT_OF_MEMORY;
+    }
+  }
+  else {
+    size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
+    cbuf = calloc(cbuf_size, 1);
+    if(cbuf) {
+      if(!CFStringGetCString(c, cbuf, cbuf_size,
+                             kCFStringEncodingUTF8)) {
+        failf(data, "SSL: invalid CA certificate subject");
+        result = CURLE_SSL_CACERT;
+      }
+      else
+        /* pass back the buffer */
+        *certp = cbuf;
+    }
+    else {
+      failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size);
+      result = CURLE_OUT_OF_MEMORY;
+    }
+  }
+  if(result)
+    free(cbuf);
+  CFRelease(c);
+  return result;
+}
+
 #if CURL_SUPPORT_MAC_10_6
 /* The SecKeychainSearch API was deprecated in Lion, and using it will raise
    deprecation warnings, so let's not compile this unless it's necessary: */
@@ -968,7 +1045,7 @@ static OSStatus CopyIdentityWithLabel(char *label,
       keys_list_count = CFArrayGetCount(keys_list);
       *out_cert_and_key = NULL;
       status = 1;
-      for(i=0; i<keys_list_count; i++) {
+      for(i = 0; i<keys_list_count; i++) {
         OSStatus err = noErr;
         SecCertificateRef cert = NULL;
         SecIdentityRef identity =
@@ -1142,30 +1219,30 @@ set_ssl_version_min_max(struct connectdata *conn, int 
sockindex)
       return result;
     }
 
-    (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, darwin_ver_min);
-    (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, darwin_ver_max);
+    (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, darwin_ver_min);
+    (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, darwin_ver_max);
     return result;
   }
   else {
 #if CURL_SUPPORT_MAC_10_8
     long i = ssl_version;
-    (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+    (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
                                        kSSLProtocolAll,
                                        false);
     for(; i <= (ssl_version_max >> 16); i++) {
       switch(i) {
         case CURL_SSLVERSION_TLSv1_0:
-          (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+          (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
                                             kTLSProtocol1,
                                             true);
           break;
         case CURL_SSLVERSION_TLSv1_1:
-          (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+          (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
                                             kTLSProtocol11,
                                             true);
           break;
         case CURL_SSLVERSION_TLSv1_2:
-          (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+          (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
                                             kTLSProtocol12,
                                             true);
           break;
@@ -1211,10 +1288,10 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
 
 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
   if(SSLCreateContext != NULL) {  /* use the newer API if avaialble */
-    if(connssl->ssl_ctx)
-      CFRelease(connssl->ssl_ctx);
-    connssl->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
-    if(!connssl->ssl_ctx) {
+    if(BACKEND->ssl_ctx)
+      CFRelease(BACKEND->ssl_ctx);
+    BACKEND->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
+    if(!BACKEND->ssl_ctx) {
       failf(data, "SSL: couldn't create a context!");
       return CURLE_OUT_OF_MEMORY;
     }
@@ -1222,9 +1299,9 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
   else {
   /* The old ST API does not exist under iOS, so don't compile it: */
 #if CURL_SUPPORT_MAC_10_8
-    if(connssl->ssl_ctx)
-      (void)SSLDisposeContext(connssl->ssl_ctx);
-    err = SSLNewContext(false, &(connssl->ssl_ctx));
+    if(BACKEND->ssl_ctx)
+      (void)SSLDisposeContext(BACKEND->ssl_ctx);
+    err = SSLNewContext(false, &(BACKEND->ssl_ctx));
     if(err != noErr) {
       failf(data, "SSL: couldn't create a context: OSStatus %d", err);
       return CURLE_OUT_OF_MEMORY;
@@ -1232,15 +1309,15 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
 #endif /* CURL_SUPPORT_MAC_10_8 */
   }
 #else
-  if(connssl->ssl_ctx)
-    (void)SSLDisposeContext(connssl->ssl_ctx);
-  err = SSLNewContext(false, &(connssl->ssl_ctx));
+  if(BACKEND->ssl_ctx)
+    (void)SSLDisposeContext(BACKEND->ssl_ctx);
+  err = SSLNewContext(false, &(BACKEND->ssl_ctx));
   if(err != noErr) {
     failf(data, "SSL: couldn't create a context: OSStatus %d", err);
     return CURLE_OUT_OF_MEMORY;
   }
 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
-  connssl->ssl_write_buffered_length = 0UL; /* reset buffered write length */
+  BACKEND->ssl_write_buffered_length = 0UL; /* reset buffered write length */
 
   /* check to see if we've been told to use an explicit SSL/TLS version */
 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
@@ -1248,8 +1325,8 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
     switch(conn->ssl_config.version) {
     case CURL_SSLVERSION_DEFAULT:
     case CURL_SSLVERSION_TLSv1:
-      (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1);
-      (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12);
+      (void)SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kTLSProtocol1);
+      (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kTLSProtocol12);
       break;
     case CURL_SSLVERSION_TLSv1_0:
     case CURL_SSLVERSION_TLSv1_1:
@@ -1262,20 +1339,20 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
         break;
       }
     case CURL_SSLVERSION_SSLv3:
-      err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3);
+      err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol3);
       if(err != noErr) {
         failf(data, "Your version of the OS does not support SSLv3");
         return CURLE_SSL_CONNECT_ERROR;
       }
-      (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3);
+      (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol3);
       break;
     case CURL_SSLVERSION_SSLv2:
-      err = SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol2);
+      err = SSLSetProtocolVersionMin(BACKEND->ssl_ctx, kSSLProtocol2);
       if(err != noErr) {
         failf(data, "Your version of the OS does not support SSLv2");
         return CURLE_SSL_CONNECT_ERROR;
       }
-      (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol2);
+      (void)SSLSetProtocolVersionMax(BACKEND->ssl_ctx, kSSLProtocol2);
       break;
     default:
       failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
@@ -1284,19 +1361,19 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
   }
   else {
 #if CURL_SUPPORT_MAC_10_8
-    (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+    (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
                                        kSSLProtocolAll,
                                        false);
     switch(conn->ssl_config.version) {
     case CURL_SSLVERSION_DEFAULT:
     case CURL_SSLVERSION_TLSv1:
-      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+      (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
                                          kTLSProtocol1,
                                          true);
-      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+      (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
                                          kTLSProtocol11,
                                          true);
-      (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+      (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
                                          kTLSProtocol12,
                                          true);
       break;
@@ -1311,7 +1388,7 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
         break;
       }
     case CURL_SSLVERSION_SSLv3:
-      err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+      err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
                                          kSSLProtocol3,
                                          true);
       if(err != noErr) {
@@ -1320,7 +1397,7 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
       }
       break;
     case CURL_SSLVERSION_SSLv2:
-      err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+      err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
                                          kSSLProtocol2,
                                          true);
       if(err != noErr) {
@@ -1340,12 +1417,12 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
                 " SSL/TLS version");
     return CURLE_SSL_CONNECT_ERROR;
   }
-  (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, kSSLProtocolAll, false);
+  (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx, kSSLProtocolAll, false);
   switch(conn->ssl_config.version) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
   case CURL_SSLVERSION_TLSv1_0:
-    (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+    (void)SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
                                        kTLSProtocol1,
                                        true);
     break;
@@ -1359,7 +1436,7 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
     failf(data, "Your version of the OS does not support TLSv1.3");
     return CURLE_SSL_CONNECT_ERROR;
   case CURL_SSLVERSION_SSLv2:
-    err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+    err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
                                        kSSLProtocol2,
                                        true);
     if(err != noErr) {
@@ -1368,7 +1445,7 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
     }
     break;
   case CURL_SSLVERSION_SSLv3:
-    err = SSLSetProtocolVersionEnabled(connssl->ssl_ctx,
+    err = SSLSetProtocolVersionEnabled(BACKEND->ssl_ctx,
                                        kSSLProtocol3,
                                        true);
     if(err != noErr) {
@@ -1418,25 +1495,21 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
       /* If we found one, print it out: */
       err = SecIdentityCopyCertificate(cert_and_key, &cert);
       if(err == noErr) {
-        CFStringRef cert_summary = CopyCertSubject(cert);
-        char cert_summary_c[128];
-
-        if(cert_summary) {
-          memset(cert_summary_c, 0, 128);
-          if(CFStringGetCString(cert_summary,
-                                cert_summary_c,
-                                128,
-                                kCFStringEncodingUTF8)) {
-            infof(data, "Client certificate: %s\n", cert_summary_c);
-          }
-          CFRelease(cert_summary);
-          CFRelease(cert);
+        char *certp;
+        CURLcode result = CopyCertSubject(data, cert, &certp);
+        if(!result) {
+          infof(data, "Client certificate: %s\n", certp);
+          free(certp);
         }
+
+        CFRelease(cert);
+        if(result)
+          return result;
       }
       certs_c[0] = cert_and_key;
       certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
                             &kCFTypeArrayCallBacks);
-      err = SSLSetCertificate(connssl->ssl_ctx, certs);
+      err = SSLSetCertificate(BACKEND->ssl_ctx, certs);
       if(certs)
         CFRelease(certs);
       if(err != noErr) {
@@ -1499,7 +1572,7 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
   if(SSLSetSessionOption != NULL) {
 #endif /* CURL_BUILD_MAC */
     bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile;
-    err = SSLSetSessionOption(connssl->ssl_ctx,
+    err = SSLSetSessionOption(BACKEND->ssl_ctx,
                               kSSLSessionOptionBreakOnServerAuth,
                               break_on_auth);
     if(err != noErr) {
@@ -1509,7 +1582,7 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
   }
   else {
 #if CURL_SUPPORT_MAC_10_8
-    err = SSLSetEnableCertVerify(connssl->ssl_ctx,
+    err = SSLSetEnableCertVerify(BACKEND->ssl_ctx,
                                  conn->ssl_config.verifypeer?true:false);
     if(err != noErr) {
       failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
@@ -1518,7 +1591,7 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
 #endif /* CURL_SUPPORT_MAC_10_8 */
   }
 #else
-  err = SSLSetEnableCertVerify(connssl->ssl_ctx,
+  err = SSLSetEnableCertVerify(BACKEND->ssl_ctx,
                                conn->ssl_config.verifypeer?true:false);
   if(err != noErr) {
     failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
@@ -1539,7 +1612,7 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
    * Both hostname check and SNI require SSLSetPeerDomainName().
    * Also: the verifyhost setting influences SNI usage */
   if(conn->ssl_config.verifyhost) {
-    err = SSLSetPeerDomainName(connssl->ssl_ctx, hostname,
+    err = SSLSetPeerDomainName(BACKEND->ssl_ctx, hostname,
     strlen(hostname));
 
     if(err != noErr) {
@@ -1565,11 +1638,11 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
      higher priority, but it's probably better that we not connect at all than
      to give the user a false sense of security if the server only supports
      insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */
-  (void)SSLGetNumberSupportedCiphers(connssl->ssl_ctx, &all_ciphers_count);
+  (void)SSLGetNumberSupportedCiphers(BACKEND->ssl_ctx, &all_ciphers_count);
   all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
   allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
   if(all_ciphers && allowed_ciphers &&
-     SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers,
+     SSLGetSupportedCiphers(BACKEND->ssl_ctx, all_ciphers,
        &all_ciphers_count) == noErr) {
     for(i = 0UL ; i < all_ciphers_count ; i++) {
 #if CURL_BUILD_MAC
@@ -1651,7 +1724,7 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
           break;
       }
     }
-    err = SSLSetEnabledCiphers(connssl->ssl_ctx, allowed_ciphers,
+    err = SSLSetEnabledCiphers(BACKEND->ssl_ctx, allowed_ciphers,
                                allowed_ciphers_count);
     if(err != noErr) {
       failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
@@ -1672,9 +1745,9 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
      specifically doesn't want us doing that: */
   if(SSLSetSessionOption != NULL) {
     /* TODO s/data->set.ssl.enable_beast/SSL_SET_OPTION(enable_beast)/g */
-    SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
+    SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
                       !data->set.ssl.enable_beast);
-    SSLSetSessionOption(connssl->ssl_ctx, kSSLSessionOptionFalseStart,
+    SSLSetSessionOption(BACKEND->ssl_ctx, kSSLSessionOptionFalseStart,
                       data->set.ssl.falsestart); /* false start support */
   }
 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
@@ -1688,7 +1761,7 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
     if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
                               &ssl_sessionid_len, sockindex)) {
       /* we got a session id, use it! */
-      err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
+      err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
       Curl_ssl_sessionid_unlock(conn);
       if(err != noErr) {
         failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
@@ -1706,7 +1779,7 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
                 verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
       ssl_sessionid_len = strlen(ssl_sessionid);
 
-      err = SSLSetPeerID(connssl->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
+      err = SSLSetPeerID(BACKEND->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
       if(err != noErr) {
         Curl_ssl_sessionid_unlock(conn);
         failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
@@ -1723,7 +1796,7 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
     }
   }
 
-  err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite);
+  err = SSLSetIOFuncs(BACKEND->ssl_ctx, SocketRead, SocketWrite);
   if(err != noErr) {
     failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
     return CURLE_SSL_CONNECT_ERROR;
@@ -1733,8 +1806,8 @@ static CURLcode darwinssl_connect_step1(struct 
connectdata *conn,
   /* We need to store the FD in a constant memory address, because
    * SSLSetConnection() will not copy that address. I've found that
    * conn->sock[sockindex] may change on its own. */
-  connssl->ssl_sockfd = sockfd;
-  err = SSLSetConnection(connssl->ssl_ctx, connssl);
+  BACKEND->ssl_sockfd = sockfd;
+  err = SSLSetConnection(BACKEND->ssl_ctx, connssl);
   if(err != noErr) {
     failf(data, "SSL: SSLSetConnection() failed: %d", err);
     return CURLE_SSL_CONNECT_ERROR;
@@ -1797,7 +1870,7 @@ static int read_cert(const char *file, unsigned char 
**out, size_t *outlen)
 {
   int fd;
   ssize_t n, len = 0, cap = 512;
-  unsigned char buf[cap], *data;
+  unsigned char buf[512], *data;
 
   fd = open(file, 0);
   if(fd < 0)
@@ -1875,6 +1948,8 @@ static int append_cert_to_array(struct Curl_easy *data,
                                 CFMutableArrayRef array)
 {
     CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
+    char *certp;
+    CURLcode result;
     if(!certdata) {
       failf(data, "SSL: failed to allocate array for CA certificate");
       return CURLE_OUT_OF_MEMORY;
@@ -1889,25 +1964,10 @@ static int append_cert_to_array(struct Curl_easy *data,
     }
 
     /* Check if cacert is valid. */
-    CFStringRef subject = CopyCertSubject(cacert);
-    if(subject) {
-      char subject_cbuf[128];
-      memset(subject_cbuf, 0, 128);
-      if(!CFStringGetCString(subject,
-                            subject_cbuf,
-                            128,
-                            kCFStringEncodingUTF8)) {
-        CFRelease(cacert);
-        failf(data, "SSL: invalid CA certificate subject");
-        return CURLE_SSL_CACERT;
-      }
-      CFRelease(subject);
-    }
-    else {
-      CFRelease(cacert);
-      failf(data, "SSL: invalid CA certificate");
-      return CURLE_SSL_CACERT;
-    }
+    result = CopyCertSubject(data, cacert, &certp);
+    if(result)
+      return result;
+    free(certp);
 
     CFArrayAppendValue(array, cacert);
     CFRelease(cacert);
@@ -2155,12 +2215,12 @@ darwinssl_connect_step2(struct connectdata *conn, int 
sockindex)
               || ssl_connect_2_writing == connssl->connecting_state);
 
   /* Here goes nothing: */
-  err = SSLHandshake(connssl->ssl_ctx);
+  err = SSLHandshake(BACKEND->ssl_ctx);
 
   if(err != noErr) {
     switch(err) {
       case errSSLWouldBlock:  /* they're not done with us yet */
-        connssl->connecting_state = connssl->ssl_direction ?
+        connssl->connecting_state = BACKEND->ssl_direction ?
             ssl_connect_2_writing : ssl_connect_2_reading;
         return CURLE_OK;
 
@@ -2169,7 +2229,7 @@ darwinssl_connect_step2(struct connectdata *conn, int 
sockindex)
       case -9841:
         if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
           int res = verify_cert(SSL_CONN_CONFIG(CAfile), data,
-                                connssl->ssl_ctx);
+                                BACKEND->ssl_ctx);
           if(res != CURLE_OK)
             return res;
         }
@@ -2247,7 +2307,7 @@ darwinssl_connect_step2(struct connectdata *conn, int 
sockindex)
 
 #ifdef DARWIN_SSL_PINNEDPUBKEY
     if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) {
-      CURLcode result = pkp_pin_peer_pubkey(data, connssl->ssl_ctx,
+      CURLcode result = pkp_pin_peer_pubkey(data, BACKEND->ssl_ctx,
                             data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]);
       if(result) {
         failf(data, "SSL: public key does not match pinned public key!");
@@ -2257,8 +2317,8 @@ darwinssl_connect_step2(struct connectdata *conn, int 
sockindex)
 #endif /* DARWIN_SSL_PINNEDPUBKEY */
 
     /* Informational message */
-    (void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
-    (void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol);
+    (void)SSLGetNegotiatedCipher(BACKEND->ssl_ctx, &cipher);
+    (void)SSLGetNegotiatedProtocolVersion(BACKEND->ssl_ctx, &protocol);
     switch(protocol) {
       case kSSLProtocol2:
         infof(data, "SSL 2.0 connection using %s\n",
@@ -2299,36 +2359,32 @@ show_verbose_server_cert(struct connectdata *conn,
 {
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  CFStringRef server_cert_summary;
-  char server_cert_summary_c[128];
   CFArrayRef server_certs = NULL;
   SecCertificateRef server_cert;
   OSStatus err;
   CFIndex i, count;
   SecTrustRef trust = NULL;
 
-  if(!connssl->ssl_ctx)
+  if(!BACKEND->ssl_ctx)
     return;
 
 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
 #if CURL_BUILD_IOS
 #pragma unused(server_certs)
-  err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
+  err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust);
   /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
      a null trust, so be on guard for that: */
   if(err == noErr && trust) {
     count = SecTrustGetCertificateCount(trust);
     for(i = 0L ; i < count ; i++) {
+      CURLcode result;
+      char *certp;
       server_cert = SecTrustGetCertificateAtIndex(trust, i);
-      server_cert_summary = CopyCertSubject(server_cert);
-      memset(server_cert_summary_c, 0, 128);
-      if(CFStringGetCString(server_cert_summary,
-                            server_cert_summary_c,
-                            128,
-                            kCFStringEncodingUTF8)) {
-        infof(data, "Server certificate: %s\n", server_cert_summary_c);
+      result = CopyCertSubject(data, server_cert, &certp);
+      if(!result) {
+        infof(data, "Server certificate: %s\n", certp);
+        free(certp);
       }
-      CFRelease(server_cert_summary);
     }
     CFRelease(trust);
   }
@@ -2341,45 +2397,40 @@ show_verbose_server_cert(struct connectdata *conn,
      Lion or later. */
   if(SecTrustEvaluateAsync != NULL) {
 #pragma unused(server_certs)
-    err = SSLCopyPeerTrust(connssl->ssl_ctx, &trust);
+    err = SSLCopyPeerTrust(BACKEND->ssl_ctx, &trust);
     /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
        a null trust, so be on guard for that: */
     if(err == noErr && trust) {
       count = SecTrustGetCertificateCount(trust);
       for(i = 0L ; i < count ; i++) {
+        char *certp;
+        CURLcode result;
         server_cert = SecTrustGetCertificateAtIndex(trust, i);
-        server_cert_summary = CopyCertSubject(server_cert);
-        memset(server_cert_summary_c, 0, 128);
-        if(CFStringGetCString(server_cert_summary,
-                              server_cert_summary_c,
-                              128,
-                              kCFStringEncodingUTF8)) {
-          infof(data, "Server certificate: %s\n", server_cert_summary_c);
+        result = CopyCertSubject(data, server_cert, &certp);
+        if(!result) {
+          infof(data, "Server certificate: %s\n", certp);
+          free(certp);
         }
-        CFRelease(server_cert_summary);
       }
       CFRelease(trust);
     }
   }
   else {
 #if CURL_SUPPORT_MAC_10_8
-    err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
+    err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs);
     /* Just in case SSLCopyPeerCertificates() returns null too... */
     if(err == noErr && server_certs) {
       count = CFArrayGetCount(server_certs);
       for(i = 0L ; i < count ; i++) {
+        char *certp;
+        CURLcode result;
         server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
                                                                 i);
-
-        server_cert_summary = CopyCertSubject(server_cert);
-        memset(server_cert_summary_c, 0, 128);
-        if(CFStringGetCString(server_cert_summary,
-                              server_cert_summary_c,
-                              128,
-                              kCFStringEncodingUTF8)) {
-          infof(data, "Server certificate: %s\n", server_cert_summary_c);
+        result = CopyCertSubject(data, server_cert, &certp);
+        if(!result) {
+          infof(data, "Server certificate: %s\n", certp);
+          free(certp);
         }
-        CFRelease(server_cert_summary);
       }
       CFRelease(server_certs);
     }
@@ -2388,20 +2439,18 @@ show_verbose_server_cert(struct connectdata *conn,
 #endif /* CURL_BUILD_IOS */
 #else
 #pragma unused(trust)
-  err = SSLCopyPeerCertificates(connssl->ssl_ctx, &server_certs);
+  err = SSLCopyPeerCertificates(BACKEND->ssl_ctx, &server_certs);
   if(err == noErr) {
     count = CFArrayGetCount(server_certs);
     for(i = 0L ; i < count ; i++) {
+      CURLcode result;
+      char *certp;
       server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
-      server_cert_summary = CopyCertSubject(server_cert);
-      memset(server_cert_summary_c, 0, 128);
-      if(CFStringGetCString(server_cert_summary,
-                            server_cert_summary_c,
-                            128,
-                            kCFStringEncodingUTF8)) {
-        infof(data, "Server certificate: %s\n", server_cert_summary_c);
+      result = CopyCertSubject(data, server_cert, &certp);
+      if(!result) {
+        infof(data, "Server certificate: %s\n", certp);
+        free(certp);
       }
-      CFRelease(server_cert_summary);
     }
     CFRelease(server_certs);
   }
@@ -2450,7 +2499,7 @@ darwinssl_connect_common(struct connectdata *conn,
     return CURLE_OK;
   }
 
-  if(ssl_connect_1==connssl->connecting_state) {
+  if(ssl_connect_1 == connssl->connecting_state) {
     /* Find out how much more time we're allowed */
     timeout_ms = Curl_timeleft(data, NULL, TRUE);
 
@@ -2545,17 +2594,13 @@ darwinssl_connect_common(struct connectdata *conn,
   return CURLE_OK;
 }
 
-CURLcode
-Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
-                                   int sockindex,
-                                   bool *done)
+static CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
+                                                   int sockindex, bool *done)
 {
   return darwinssl_connect_common(conn, sockindex, TRUE, done);
 }
 
-CURLcode
-Curl_darwinssl_connect(struct connectdata *conn,
-                       int sockindex)
+static CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex)
 {
   CURLcode result;
   bool done = FALSE;
@@ -2570,28 +2615,28 @@ Curl_darwinssl_connect(struct connectdata *conn,
   return CURLE_OK;
 }
 
-void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
+static void Curl_darwinssl_close(struct connectdata *conn, int sockindex)
 {
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
-  if(connssl->ssl_ctx) {
-    (void)SSLClose(connssl->ssl_ctx);
+  if(BACKEND->ssl_ctx) {
+    (void)SSLClose(BACKEND->ssl_ctx);
 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
     if(SSLCreateContext != NULL)
-      CFRelease(connssl->ssl_ctx);
+      CFRelease(BACKEND->ssl_ctx);
 #if CURL_SUPPORT_MAC_10_8
     else
-      (void)SSLDisposeContext(connssl->ssl_ctx);
+      (void)SSLDisposeContext(BACKEND->ssl_ctx);
 #endif  /* CURL_SUPPORT_MAC_10_8 */
 #else
-    (void)SSLDisposeContext(connssl->ssl_ctx);
+    (void)SSLDisposeContext(BACKEND->ssl_ctx);
 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
-    connssl->ssl_ctx = NULL;
+    BACKEND->ssl_ctx = NULL;
   }
-  connssl->ssl_sockfd = 0;
+  BACKEND->ssl_sockfd = 0;
 }
 
-int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex)
 {
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct Curl_easy *data = conn->data;
@@ -2600,7 +2645,7 @@ int Curl_darwinssl_shutdown(struct connectdata *conn, int 
sockindex)
   int rc;
   char buf[120];
 
-  if(!connssl->ssl_ctx)
+  if(!BACKEND->ssl_ctx)
     return 0;
 
   if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
@@ -2644,7 +2689,7 @@ int Curl_darwinssl_shutdown(struct connectdata *conn, int 
sockindex)
   return rc;
 }
 
-void Curl_darwinssl_session_free(void *ptr)
+static void Curl_darwinssl_session_free(void *ptr)
 {
   /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
      cached session ID inside the Security framework. There is a private
@@ -2655,7 +2700,7 @@ void Curl_darwinssl_session_free(void *ptr)
   Curl_safefree(ptr);
 }
 
-size_t Curl_darwinssl_version(char *buffer, size_t size)
+static size_t Curl_darwinssl_version(char *buffer, size_t size)
 {
   return snprintf(buffer, size, "SecureTransport");
 }
@@ -2668,14 +2713,14 @@ size_t Curl_darwinssl_version(char *buffer, size_t size)
  *     0 means the connection has been closed
  *    -1 means the connection status is unknown
  */
-int Curl_darwinssl_check_cxn(struct connectdata *conn)
+static int Curl_darwinssl_check_cxn(struct connectdata *conn)
 {
   struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
   OSStatus err;
   SSLSessionState state;
 
-  if(connssl->ssl_ctx) {
-    err = SSLGetSessionState(connssl->ssl_ctx, &state);
+  if(BACKEND->ssl_ctx) {
+    err = SSLGetSessionState(BACKEND->ssl_ctx, &state);
     if(err == noErr)
       return state == kSSLConnected || state == kSSLHandshake;
     return -1;
@@ -2683,15 +2728,15 @@ int Curl_darwinssl_check_cxn(struct connectdata *conn)
   return 0;
 }
 
-bool Curl_darwinssl_data_pending(const struct connectdata *conn,
-                                 int connindex)
+static bool Curl_darwinssl_data_pending(const struct connectdata *conn,
+                                        int connindex)
 {
   const struct ssl_connect_data *connssl = &conn->ssl[connindex];
   OSStatus err;
   size_t buffer;
 
-  if(connssl->ssl_ctx) {  /* SSL is in use */
-    err = SSLGetBufferedReadSize(connssl->ssl_ctx, &buffer);
+  if(BACKEND->ssl_ctx) {  /* SSL is in use */
+    err = SSLGetBufferedReadSize(BACKEND->ssl_ctx, &buffer);
     if(err == noErr)
       return buffer > 0UL;
     return false;
@@ -2700,14 +2745,16 @@ bool Curl_darwinssl_data_pending(const struct 
connectdata *conn,
     return false;
 }
 
-CURLcode Curl_darwinssl_random(unsigned char *entropy,
-                               size_t length)
+static CURLcode Curl_darwinssl_random(struct Curl_easy *data UNUSED_PARAM,
+                                      unsigned char *entropy, size_t length)
 {
   /* arc4random_buf() isn't available on cats older than Lion, so let's
      do this manually for the benefit of the older cats. */
   size_t i;
   u_int32_t random_number = 0;
 
+  (void)data;
+
   for(i = 0 ; i < length ; i++) {
     if(i % sizeof(u_int32_t) == 0)
       random_number = arc4random();
@@ -2718,25 +2765,26 @@ CURLcode Curl_darwinssl_random(unsigned char *entropy,
   return CURLE_OK;
 }
 
-void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
-                           size_t tmplen,
-                           unsigned char *md5sum, /* output */
-                           size_t md5len)
+static CURLcode Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
+                                      size_t tmplen,
+                                      unsigned char *md5sum, /* output */
+                                      size_t md5len)
 {
   (void)md5len;
   (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
+  return CURLE_OK;
 }
 
-void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */
-                              size_t tmplen,
-                              unsigned char *sha256sum, /* output */
-                              size_t sha256len)
+static void Curl_darwinssl_sha256sum(const unsigned char *tmp, /* input */
+                                     size_t tmplen,
+                                     unsigned char *sha256sum, /* output */
+                                     size_t sha256len)
 {
-  assert(sha256len >= SHA256_DIGEST_LENGTH);
+  assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
   (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
 }
 
-bool Curl_darwinssl_false_start(void)
+static bool Curl_darwinssl_false_start(void)
 {
 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
   if(SSLSetSessionOption != NULL)
@@ -2771,15 +2819,15 @@ static ssize_t darwinssl_send(struct connectdata *conn,
      over again with no new data until it quits returning errSSLWouldBlock. */
 
   /* Do we have buffered data to write from the last time we were called? */
-  if(connssl->ssl_write_buffered_length) {
+  if(BACKEND->ssl_write_buffered_length) {
     /* Write the buffered data: */
-    err = SSLWrite(connssl->ssl_ctx, NULL, 0UL, &processed);
+    err = SSLWrite(BACKEND->ssl_ctx, NULL, 0UL, &processed);
     switch(err) {
       case noErr:
         /* processed is always going to be 0 because we didn't write to
            the buffer, so return how much was written to the socket */
-        processed = connssl->ssl_write_buffered_length;
-        connssl->ssl_write_buffered_length = 0UL;
+        processed = BACKEND->ssl_write_buffered_length;
+        BACKEND->ssl_write_buffered_length = 0UL;
         break;
       case errSSLWouldBlock: /* argh, try again */
         *curlcode = CURLE_AGAIN;
@@ -2792,13 +2840,13 @@ static ssize_t darwinssl_send(struct connectdata *conn,
   }
   else {
     /* We've got new data to write: */
-    err = SSLWrite(connssl->ssl_ctx, mem, len, &processed);
+    err = SSLWrite(BACKEND->ssl_ctx, mem, len, &processed);
     if(err != noErr) {
       switch(err) {
         case errSSLWouldBlock:
           /* Data was buffered but not sent, we have to tell the caller
              to try sending again, and remember how much was buffered */
-          connssl->ssl_write_buffered_length = len;
+          BACKEND->ssl_write_buffered_length = len;
           *curlcode = CURLE_AGAIN;
           return -1L;
         default:
@@ -2820,7 +2868,7 @@ static ssize_t darwinssl_recv(struct connectdata *conn,
   /*struct Curl_easy *data = conn->data;*/
   struct ssl_connect_data *connssl = &conn->ssl[num];
   size_t processed = 0UL;
-  OSStatus err = SSLRead(connssl->ssl_ctx, buf, buffersize, &processed);
+  OSStatus err = SSLRead(BACKEND->ssl_ctx, buf, buffersize, &processed);
 
   if(err != noErr) {
     switch(err) {
@@ -2851,6 +2899,50 @@ static ssize_t darwinssl_recv(struct connectdata *conn,
   return (ssize_t)processed;
 }
 
+static void *Curl_darwinssl_get_internals(struct ssl_connect_data *connssl,
+                                          CURLINFO info UNUSED_PARAM)
+{
+  (void)info;
+  return BACKEND->ssl_ctx;
+}
+
+const struct Curl_ssl Curl_ssl_darwinssl = {
+  { CURLSSLBACKEND_DARWINSSL, "darwinssl" }, /* info */
+
+  0, /* have_ca_path */
+  0, /* have_certinfo */
+#ifdef DARWIN_SSL_PINNEDPUBKEY
+  1, /* have_pinnedpubkey */
+#else
+  0, /* have_pinnedpubkey */
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+  0, /* have_ssl_ctx */
+  0, /* support_https_proxy */
+
+  sizeof(struct ssl_backend_data),
+
+  Curl_none_init,                     /* init */
+  Curl_none_cleanup,                  /* cleanup */
+  Curl_darwinssl_version,             /* version */
+  Curl_darwinssl_check_cxn,           /* check_cxn */
+  Curl_darwinssl_shutdown,            /* shutdown */
+  Curl_darwinssl_data_pending,        /* data_pending */
+  Curl_darwinssl_random,              /* random */
+  Curl_none_cert_status_request,      /* cert_status_request */
+  Curl_darwinssl_connect,             /* connect */
+  Curl_darwinssl_connect_nonblocking, /* connect_nonblocking */
+  Curl_darwinssl_get_internals,       /* get_internals */
+  Curl_darwinssl_close,               /* close */
+  Curl_none_close_all,                /* close_all */
+  Curl_darwinssl_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_darwinssl_false_start,         /* false_start */
+  Curl_darwinssl_md5sum,              /* md5sum */
+  Curl_darwinssl_sha256sum            /* sha256sum */
+};
+
 #ifdef __clang__
 #pragma clang diagnostic pop
 #endif
diff --git a/lib/vtls/darwinssl.h b/lib/vtls/darwinssl.h
index 13e78515a..23c7f705c 100644
--- a/lib/vtls/darwinssl.h
+++ b/lib/vtls/darwinssl.h
@@ -26,76 +26,7 @@
 
 #ifdef USE_DARWINSSL
 
-CURLcode Curl_darwinssl_connect(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_darwinssl_connect_nonblocking(struct connectdata *conn,
-                                            int sockindex,
-                                            bool *done);
-
-/* close a SSL connection */
-void Curl_darwinssl_close(struct connectdata *conn, int sockindex);
-
-void Curl_darwinssl_session_free(void *ptr);
-size_t Curl_darwinssl_version(char *buffer, size_t size);
-int Curl_darwinssl_shutdown(struct connectdata *conn, int sockindex);
-int Curl_darwinssl_check_cxn(struct connectdata *conn);
-bool Curl_darwinssl_data_pending(const struct connectdata *conn,
-                                 int connindex);
-
-CURLcode Curl_darwinssl_random(unsigned char *entropy,
-                               size_t length);
-void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
-                           size_t tmplen,
-                           unsigned char *md5sum, /* output */
-                           size_t md5len);
-void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */
-                              size_t tmplen,
-                              unsigned char *sha256sum, /* output */
-                              size_t sha256len);
-bool Curl_darwinssl_false_start(void);
-
-/* Set the API backend definition to SecureTransport */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL
-
-/* pinned public key support tests */
-
-/* version 1 supports macOS 10.12+ and iOS 10+ */
-#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
-    (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED  >= 101200))
-#define DARWIN_SSL_PINNEDPUBKEY_V1 1
-#endif
-
-/* version 2 supports MacOSX 10.7+ */
-#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
-#define DARWIN_SSL_PINNEDPUBKEY_V2 1
-#endif
-
-#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2)
-/* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define DARWIN_SSL_PINNEDPUBKEY 1
-#define have_curlssl_pinnedpubkey 1
-#endif /* DARWIN_SSL_PINNEDPUBKEY */
-
-/* API setup for SecureTransport */
-#define curlssl_init() (1)
-#define curlssl_cleanup() Curl_nop_stmt
-#define curlssl_connect Curl_darwinssl_connect
-#define curlssl_connect_nonblocking Curl_darwinssl_connect_nonblocking
-#define curlssl_session_free(x) Curl_darwinssl_session_free(x)
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_darwinssl_close
-#define curlssl_shutdown(x,y) 0
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_darwinssl_version
-#define curlssl_check_cxn Curl_darwinssl_check_cxn
-#define curlssl_data_pending(x,y) Curl_darwinssl_data_pending(x, y)
-#define curlssl_random(x,y,z) ((void)x, Curl_darwinssl_random(y,z))
-#define curlssl_md5sum(a,b,c,d) Curl_darwinssl_md5sum(a,b,c,d)
-#define curlssl_sha256sum(a,b,c,d) \
-  Curl_darwinssl_sha256sum((unsigned char *)a, b, c, d)
-#define curlssl_false_start() Curl_darwinssl_false_start()
+extern const struct Curl_ssl Curl_ssl_darwinssl;
 
 #endif /* USE_DARWINSSL */
 #endif /* HEADER_CURL_DARWINSSL_H */
diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
index 565f10f07..ec142fb9e 100644
--- a/lib/vtls/gskit.c
+++ b/lib/vtls/gskit.c
@@ -98,6 +98,14 @@
 #define CURL_GSKPROTO_TLSV12_MASK        (1 << CURL_GSKPROTO_TLSV12)
 #define CURL_GSKPROTO_LAST      5
 
+struct ssl_backend_data {
+  gsk_handle handle;
+  int iocport;
+  int localfd;
+  int remotefd;
+};
+
+#define BACKEND connssl->backend
 
 /* Supported ciphers. */
 typedef struct {
@@ -427,7 +435,7 @@ static CURLcode set_ciphers(struct connectdata *conn,
 }
 
 
-int Curl_gskit_init(void)
+static int Curl_gskit_init(void)
 {
   /* No initialisation needed. */
 
@@ -435,7 +443,7 @@ int Curl_gskit_init(void)
 }
 
 
-void Curl_gskit_cleanup(void)
+static void Curl_gskit_cleanup(void)
 {
   /* Nothing to do. */
 }
@@ -495,14 +503,14 @@ static void cancel_async_handshake(struct connectdata 
*conn, int sockindex)
   Qso_OverlappedIO_t cstat;
 
   if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
-    QsoWaitForIOCompletion(connssl->iocport, &cstat, (struct timeval *) NULL);
+    QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL);
 }
 
 
 static void close_async_handshake(struct ssl_connect_data *connssl)
 {
-  QsoDestroyIOCompletionPort(connssl->iocport);
-  connssl->iocport = -1;
+  QsoDestroyIOCompletionPort(BACKEND->iocport);
+  BACKEND->iocport = -1;
 }
 
 /* SSL over SSL
@@ -620,12 +628,12 @@ static int pipe_ssloverssl(struct connectdata *conn, int 
sockindex,
   FD_ZERO(&fds_write);
   n = -1;
   if(directions & SOS_READ) {
-    FD_SET(connssl->remotefd, &fds_write);
-    n = connssl->remotefd;
+    FD_SET(BACKEND->remotefd, &fds_write);
+    n = BACKEND->remotefd;
   }
   if(directions & SOS_WRITE) {
-    FD_SET(connssl->remotefd, &fds_read);
-    n = connssl->remotefd;
+    FD_SET(BACKEND->remotefd, &fds_read);
+    n = BACKEND->remotefd;
     FD_SET(conn->sock[sockindex], &fds_write);
     if(n < conn->sock[sockindex])
       n = conn->sock[sockindex];
@@ -634,14 +642,15 @@ static int pipe_ssloverssl(struct connectdata *conn, int 
sockindex,
   if(i < 0)
     return -1;  /* Select error. */
 
-  if(FD_ISSET(connssl->remotefd, &fds_write)) {
+  if(FD_ISSET(BACKEND->remotefd, &fds_write)) {
     /* Try getting data from HTTPS proxy and pipe it upstream. */
     n = 0;
-    i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n);
+    i = gsk_secure_soc_read(connproxyssl->backend->handle,
+                            buf, sizeof buf, &n);
     switch(i) {
     case GSK_OK:
       if(n) {
-        i = write(connssl->remotefd, buf, n);
+        i = write(BACKEND->remotefd, buf, n);
         if(i < 0)
           return -1;
         ret = 1;
@@ -655,14 +664,14 @@ static int pipe_ssloverssl(struct connectdata *conn, int 
sockindex,
     }
   }
 
-  if(FD_ISSET(connssl->remotefd, &fds_read) &&
+  if(FD_ISSET(BACKEND->remotefd, &fds_read) &&
      FD_ISSET(conn->sock[sockindex], &fds_write)) {
     /* Pipe data to HTTPS proxy. */
-    n = read(connssl->remotefd, buf, sizeof buf);
+    n = read(BACKEND->remotefd, buf, sizeof buf);
     if(n < 0)
       return -1;
     if(n) {
-      i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m);
+      i = gsk_secure_soc_write(connproxyssl->backend->handle, buf, n, &m);
       if(i != GSK_OK || n != m)
         return -1;
       ret = 1;
@@ -676,23 +685,23 @@ static int pipe_ssloverssl(struct connectdata *conn, int 
sockindex,
 static void close_one(struct ssl_connect_data *connssl,
                       struct connectdata *conn, int sockindex)
 {
-  if(connssl->handle) {
-    gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle),
+  if(BACKEND->handle) {
+    gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle),
               "gsk_secure_soc_close()", 0);
     /* Last chance to drain output. */
     while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
       ;
-    connssl->handle = (gsk_handle) NULL;
-    if(connssl->localfd >= 0) {
-      close(connssl->localfd);
-      connssl->localfd = -1;
+    BACKEND->handle = (gsk_handle) NULL;
+    if(BACKEND->localfd >= 0) {
+      close(BACKEND->localfd);
+      BACKEND->localfd = -1;
     }
-    if(connssl->remotefd >= 0) {
-      close(connssl->remotefd);
-      connssl->remotefd = -1;
+    if(BACKEND->remotefd >= 0) {
+      close(BACKEND->remotefd);
+      BACKEND->remotefd = -1;
     }
   }
-  if(connssl->iocport >= 0)
+  if(BACKEND->iocport >= 0)
     close_async_handshake(connssl);
 }
 
@@ -700,13 +709,14 @@ static void close_one(struct ssl_connect_data *connssl,
 static ssize_t gskit_send(struct connectdata *conn, int sockindex,
                            const void *mem, size_t len, CURLcode *curlcode)
 {
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct Curl_easy *data = conn->data;
   CURLcode cc = CURLE_SEND_ERROR;
   int written;
 
   if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
     cc = gskit_status(data,
-                      gsk_secure_soc_write(conn->ssl[sockindex].handle,
+                      gsk_secure_soc_write(BACKEND->handle,
                                            (char *) mem, (int) len, &written),
                       "gsk_secure_soc_write()", CURLE_SEND_ERROR);
     if(cc == CURLE_OK)
@@ -724,6 +734,7 @@ static ssize_t gskit_send(struct connectdata *conn, int 
sockindex,
 static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
                            size_t buffersize, CURLcode *curlcode)
 {
+  struct ssl_connect_data *connssl = &conn->ssl[num];
   struct Curl_easy *data = conn->data;
   int buffsize;
   int nread;
@@ -731,7 +742,7 @@ static ssize_t gskit_recv(struct connectdata *conn, int 
num, char *buf,
 
   if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
     buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
-    cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
+    cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle,
                                                 buf, buffsize, &nread),
                       "gsk_secure_soc_read()", CURLE_RECV_ERROR);
   }
@@ -806,10 +817,10 @@ static CURLcode gskit_connect_step1(struct connectdata 
*conn, int sockindex)
 
   /* Create SSL environment, start (preferably asynchronous) handshake. */
 
-  connssl->handle = (gsk_handle) NULL;
-  connssl->iocport = -1;
-  connssl->localfd = -1;
-  connssl->remotefd = -1;
+  BACKEND->handle = (gsk_handle) NULL;
+  BACKEND->iocport = -1;
+  BACKEND->localfd = -1;
+  BACKEND->remotefd = -1;
 
   /* GSKit supports two ways of specifying an SSL context: either by
    *  application identifier (that should have been defined at the system
@@ -842,7 +853,7 @@ static CURLcode gskit_connect_step1(struct connectdata 
*conn, int sockindex)
   }
 
   /* Create secure session. */
-  result = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle),
+  result = gskit_status(data, gsk_secure_soc_open(envir, &BACKEND->handle),
                         "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
   gsk_environment_close(&envir);
   if(result)
@@ -852,18 +863,18 @@ static CURLcode gskit_connect_step1(struct connectdata 
*conn, int sockindex)
   if(conn->proxy_ssl[sockindex].use) {
     if(inetsocketpair(sockpair))
       return CURLE_SSL_CONNECT_ERROR;
-    connssl->localfd = sockpair[0];
-    connssl->remotefd = sockpair[1];
-    setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF,
+    BACKEND->localfd = sockpair[0];
+    BACKEND->remotefd = sockpair[1];
+    setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
                (void *) sobufsize, sizeof sobufsize);
-    setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF,
+    setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
                (void *) sobufsize, sizeof sobufsize);
-    setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF,
+    setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
                (void *) sobufsize, sizeof sobufsize);
-    setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF,
+    setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
                (void *) sobufsize, sizeof sobufsize);
-    curlx_nonblock(connssl->localfd, TRUE);
-    curlx_nonblock(connssl->remotefd, TRUE);
+    curlx_nonblock(BACKEND->localfd, TRUE);
+    curlx_nonblock(BACKEND->remotefd, TRUE);
   }
 
   /* Determine which SSL/TLS version should be enabled. */
@@ -897,7 +908,7 @@ static CURLcode gskit_connect_step1(struct connectdata 
*conn, int sockindex)
 
   /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
   if(sni) {
-    result = set_buffer(data, connssl->handle,
+    result = set_buffer(data, BACKEND->handle,
                         GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
     if(result == CURLE_UNSUPPORTED_PROTOCOL)
       result = CURLE_OK;
@@ -911,34 +922,34 @@ static CURLcode gskit_connect_step1(struct connectdata 
*conn, int sockindex)
     if(timeout < 0)
       result = CURLE_OPERATION_TIMEDOUT;
     else
-      result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT,
+      result = set_numeric(data, BACKEND->handle, GSK_HANDSHAKE_TIMEOUT,
                            (timeout + 999) / 1000);
   }
   if(!result)
-    result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1);
+    result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
   if(!result)
-    result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0?
-                         connssl->localfd: conn->sock[sockindex]);
+    result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
+                         BACKEND->localfd: conn->sock[sockindex]);
   if(!result)
-    result = set_ciphers(conn, connssl->handle, &protoflags);
+    result = set_ciphers(conn, BACKEND->handle, &protoflags);
   if(!protoflags) {
     failf(data, "No SSL protocol/cipher combination enabled");
     result = CURLE_SSL_CIPHER;
   }
   if(!result)
-    result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
+    result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2,
                       (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
                       GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
   if(!result)
-    result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
+    result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV3,
                       (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
                       GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
   if(!result)
-    result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
+    result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV1,
                       (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
                       GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
   if(!result) {
-    result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11,
+    result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV11,
                       (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
                       GSK_TRUE: GSK_FALSE, TRUE);
     if(result == CURLE_UNSUPPORTED_PROTOCOL) {
@@ -950,7 +961,7 @@ static CURLcode gskit_connect_step1(struct connectdata 
*conn, int sockindex)
     }
   }
   if(!result) {
-    result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12,
+    result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV12,
                       (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
                       GSK_TRUE: GSK_FALSE, TRUE);
     if(result == CURLE_UNSUPPORTED_PROTOCOL) {
@@ -962,18 +973,18 @@ static CURLcode gskit_connect_step1(struct connectdata 
*conn, int sockindex)
     }
   }
   if(!result)
-    result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
+    result = set_enum(data, BACKEND->handle, GSK_SERVER_AUTH_TYPE,
                       verifypeer? GSK_SERVER_AUTH_FULL:
                       GSK_SERVER_AUTH_PASSTHRU, FALSE);
 
   if(!result) {
     /* Start handshake. Try asynchronous first. */
     memset(&commarea, 0, sizeof commarea);
-    connssl->iocport = QsoCreateIOCompletionPort();
-    if(connssl->iocport != -1) {
+    BACKEND->iocport = QsoCreateIOCompletionPort();
+    if(BACKEND->iocport != -1) {
       result = gskit_status(data,
-                            gsk_secure_soc_startInit(connssl->handle,
-                                                     connssl->iocport,
+                            gsk_secure_soc_startInit(BACKEND->handle,
+                                                     BACKEND->iocport,
                                                      &commarea),
                             "gsk_secure_soc_startInit()",
                             CURLE_SSL_CONNECT_ERROR);
@@ -993,7 +1004,7 @@ static CURLcode gskit_connect_step1(struct connectdata 
*conn, int sockindex)
     }
     else {
       /* No more completion port available. Use synchronous IO. */
-      result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
+      result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle),
                             "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
       if(!result) {
         connssl->connecting_state = ssl_connect_3;
@@ -1026,7 +1037,7 @@ static CURLcode gskit_connect_step2(struct connectdata 
*conn, int sockindex,
       timeout_ms = 0;
     stmv.tv_sec = timeout_ms / 1000;
     stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
-    switch(QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
+    switch(QsoWaitForIOCompletion(BACKEND->iocport, &cstat, &stmv)) {
     case 1:             /* Operation complete. */
       break;
     case -1:            /* An error occurred: handshake still in progress. */
@@ -1075,7 +1086,7 @@ static CURLcode gskit_connect_step3(struct connectdata 
*conn, int sockindex)
 
   /* SSL handshake done: gather certificate info and verify host. */
 
-  if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle,
+  if(gskit_status(data, gsk_attribute_get_cert_info(BACKEND->handle,
                                                     GSK_PARTNER_CERT_INFO,
                                                     &cdev, &cdec),
                   "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
@@ -1216,9 +1227,8 @@ static CURLcode gskit_connect_common(struct connectdata 
*conn, int sockindex,
 }
 
 
-CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
-                                        int sockindex,
-                                        bool *done)
+static CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
+                                               int sockindex, bool *done)
 {
   CURLcode result;
 
@@ -1229,7 +1239,7 @@ CURLcode Curl_gskit_connect_nonblocking(struct 
connectdata *conn,
 }
 
 
-CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
+static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
 {
   CURLcode result;
   bool done;
@@ -1245,14 +1255,14 @@ CURLcode Curl_gskit_connect(struct connectdata *conn, 
int sockindex)
 }
 
 
-void Curl_gskit_close(struct connectdata *conn, int sockindex)
+static void Curl_gskit_close(struct connectdata *conn, int sockindex)
 {
   close_one(&conn->ssl[sockindex], conn, sockindex);
   close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
 }
 
 
-int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
 {
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct Curl_easy *data = conn->data;
@@ -1261,7 +1271,7 @@ int Curl_gskit_shutdown(struct connectdata *conn, int 
sockindex)
   int rc;
   char buf[120];
 
-  if(!connssl->handle)
+  if(!BACKEND->handle)
     return 0;
 
   if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
@@ -1306,21 +1316,22 @@ int Curl_gskit_shutdown(struct connectdata *conn, int 
sockindex)
 }
 
 
-size_t Curl_gskit_version(char *buffer, size_t size)
+static size_t Curl_gskit_version(char *buffer, size_t size)
 {
   strncpy(buffer, "GSKit", size);
   return strlen(buffer);
 }
 
 
-int Curl_gskit_check_cxn(struct connectdata *cxn)
+static int Curl_gskit_check_cxn(struct connectdata *cxn)
 {
+  struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET];
   int err;
   int errlen;
 
   /* The only thing that can be tested here is at the socket level. */
 
-  if(!cxn->ssl[FIRSTSOCKET].handle)
+  if(!BACKEND->handle)
     return 0; /* connection has been closed */
 
   err = 0;
@@ -1334,4 +1345,46 @@ int Curl_gskit_check_cxn(struct connectdata *cxn)
   return -1;  /* connection status unknown */
 }
 
+static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl,
+                                      CURLINFO info UNUSED_PARAM)
+{
+  (void)info;
+  return BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_gskit = {
+  { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */
+
+  0, /* have_ca_path */
+  1, /* have_certinfo */
+  0, /* have_pinnedpubkey */
+  0, /* have_ssl_ctx */
+  /* TODO: convert to 1 and fix test #1014 (if need) */
+  0, /* support_https_proxy */
+
+  sizeof(struct ssl_backend_data),
+
+  Curl_gskit_init,                /* init */
+  Curl_gskit_cleanup,             /* cleanup */
+  Curl_gskit_version,             /* version */
+  Curl_gskit_check_cxn,           /* check_cxn */
+  Curl_gskit_shutdown,            /* shutdown */
+  Curl_none_data_pending,         /* data_pending */
+  Curl_none_random,               /* random */
+  Curl_none_cert_status_request,  /* cert_status_request */
+  Curl_gskit_connect,             /* connect */
+  Curl_gskit_connect_nonblocking, /* connect_nonblocking */
+  Curl_gskit_get_internals,       /* get_internals */
+  Curl_gskit_close,               /* close */
+  Curl_none_close_all,            /* close_all */
+  /* No session handling for GSKit */
+  Curl_none_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 */
+  NULL                            /* sha256sum */
+};
+
 #endif /* USE_GSKIT */
diff --git a/lib/vtls/gskit.h b/lib/vtls/gskit.h
index 229759217..466ee4d9d 100644
--- a/lib/vtls/gskit.h
+++ b/lib/vtls/gskit.h
@@ -30,44 +30,8 @@
 #include "urldata.h"
 
 #ifdef USE_GSKIT
-int Curl_gskit_init(void);
-void Curl_gskit_cleanup(void);
-CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex);
-CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
-                                        int sockindex, bool *done);
-void Curl_gskit_close(struct connectdata *conn, int sockindex);
-int Curl_gskit_shutdown(struct connectdata *conn, int sockindex);
 
-size_t Curl_gskit_version(char *buffer, size_t size);
-int Curl_gskit_check_cxn(struct connectdata *cxn);
-
-/* Support HTTPS-proxy */
-/* TODO: add '#define HTTPS_PROXY_SUPPORT 1' and fix test #1014 (if need) */
-
-/* Set the API backend definition to GSKit */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_GSKIT
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* API setup for GSKit */
-#define curlssl_init Curl_gskit_init
-#define curlssl_cleanup Curl_gskit_cleanup
-#define curlssl_connect Curl_gskit_connect
-#define curlssl_connect_nonblocking Curl_gskit_connect_nonblocking
-
-/*  No session handling for GSKit */
-#define curlssl_session_free(x) Curl_nop_stmt
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_gskit_close
-#define curlssl_shutdown(x,y) Curl_gskit_shutdown(x,y)
-#define curlssl_set_engine(x,y) CURLE_NOT_BUILT_IN
-#define curlssl_set_engine_default(x) CURLE_NOT_BUILT_IN
-#define curlssl_engines_list(x) NULL
-#define curlssl_version Curl_gskit_version
-#define curlssl_check_cxn(x) Curl_gskit_check_cxn(x)
-#define curlssl_data_pending(x,y) 0
-#define curlssl_random(x,y,z) (x=x, y=y, z=z, CURLE_NOT_BUILT_IN)
+extern const struct Curl_ssl Curl_ssl_gskit;
 
 #endif /* USE_GSKIT */
 
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index d55f995e8..a844915ef 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -107,6 +107,16 @@ static bool gtls_inited = FALSE;
 # include <gnutls/ocsp.h>
 #endif
 
+struct ssl_backend_data {
+  gnutls_session_t session;
+  gnutls_certificate_credentials_t cred;
+#ifdef USE_TLS_SRP
+  gnutls_srp_client_credentials_t srp_client_cred;
+#endif
+};
+
+#define BACKEND connssl->backend
+
 /*
  * Custom push and pull callback functions used by GNU TLS to read and write
  * to the socket.  These functions are simple wrappers to send() and recv()
@@ -186,7 +196,7 @@ static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, 
size_t len)
  * must only be called from within curl_global_init() to keep the thread
  * situation under control!
  */
-int Curl_gtls_init(void)
+static int Curl_gtls_init(void)
 {
   int ret = 1;
   if(!gtls_inited) {
@@ -200,13 +210,12 @@ int Curl_gtls_init(void)
   return ret;
 }
 
-int Curl_gtls_cleanup(void)
+static void Curl_gtls_cleanup(void)
 {
   if(gtls_inited) {
     gnutls_global_deinit();
     gtls_inited = FALSE;
   }
-  return 1;
 }
 
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
@@ -277,7 +286,7 @@ static CURLcode handshake(struct connectdata *conn,
 {
   struct Curl_easy *data = conn->data;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-  gnutls_session_t session = conn->ssl[sockindex].session;
+  gnutls_session_t session = BACKEND->session;
   curl_socket_t sockfd = conn->sock[sockindex];
   time_t timeout_ms;
   int rc;
@@ -297,9 +306,9 @@ static CURLcode handshake(struct connectdata *conn,
     if(connssl->connecting_state == ssl_connect_2_reading
        || connssl->connecting_state == ssl_connect_2_writing) {
 
-      curl_socket_t writefd = 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==
+      curl_socket_t readfd = ssl_connect_2_reading ==
         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
 
       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
@@ -475,6 +484,7 @@ gtls_connect_step1(struct connectdata *conn,
                    int sockindex)
 {
   struct Curl_easy *data = conn->data;
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   unsigned int init_flags;
   gnutls_session_t session;
   int rc;
@@ -510,7 +520,7 @@ gtls_connect_step1(struct connectdata *conn,
   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
     conn->host.name;
 
-  if(conn->ssl[sockindex].state == ssl_connection_complete)
+  if(connssl->state == ssl_connection_complete)
     /* to make us tolerant against being called more than once for the
        same connection */
     return CURLE_OK;
@@ -526,7 +536,7 @@ gtls_connect_step1(struct connectdata *conn,
     sni = FALSE; /* SSLv3 has no SNI */
 
   /* allocate a cred struct */
-  rc = gnutls_certificate_allocate_credentials(&conn->ssl[sockindex].cred);
+  rc = gnutls_certificate_allocate_credentials(&BACKEND->cred);
   if(rc != GNUTLS_E_SUCCESS) {
     failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
     return CURLE_SSL_CONNECT_ERROR;
@@ -537,15 +547,14 @@ gtls_connect_step1(struct connectdata *conn,
     infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
 
     rc = gnutls_srp_allocate_client_credentials(
-           &conn->ssl[sockindex].srp_client_cred);
+           &BACKEND->srp_client_cred);
     if(rc != GNUTLS_E_SUCCESS) {
       failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
             gnutls_strerror(rc));
       return CURLE_OUT_OF_MEMORY;
     }
 
-    rc = gnutls_srp_set_client_credentials(conn->ssl[sockindex].
-                                           srp_client_cred,
+    rc = gnutls_srp_set_client_credentials(BACKEND->srp_client_cred,
                                            SSL_SET_OPTION(username),
                                            SSL_SET_OPTION(password));
     if(rc != GNUTLS_E_SUCCESS) {
@@ -558,10 +567,10 @@ gtls_connect_step1(struct connectdata *conn,
 
   if(SSL_CONN_CONFIG(CAfile)) {
     /* set the trusted CA cert bundle file */
-    gnutls_certificate_set_verify_flags(conn->ssl[sockindex].cred,
+    gnutls_certificate_set_verify_flags(BACKEND->cred,
                                         GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
 
-    rc = gnutls_certificate_set_x509_trust_file(conn->ssl[sockindex].cred,
+    rc = gnutls_certificate_set_x509_trust_file(BACKEND->cred,
                                                 SSL_CONN_CONFIG(CAfile),
                                                 GNUTLS_X509_FMT_PEM);
     if(rc < 0) {
@@ -578,7 +587,7 @@ gtls_connect_step1(struct connectdata *conn,
 #ifdef HAS_CAPATH
   if(SSL_CONN_CONFIG(CApath)) {
     /* set the trusted CA cert directory */
-    rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
+    rc = gnutls_certificate_set_x509_trust_dir(BACKEND->cred,
                                                SSL_CONN_CONFIG(CApath),
                                                GNUTLS_X509_FMT_PEM);
     if(rc < 0) {
@@ -597,13 +606,13 @@ gtls_connect_step1(struct connectdata *conn,
   /* use system ca certificate store as fallback */
   if(SSL_CONN_CONFIG(verifypeer) &&
      !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
-    gnutls_certificate_set_x509_system_trust(conn->ssl[sockindex].cred);
+    gnutls_certificate_set_x509_system_trust(BACKEND->cred);
   }
 #endif
 
   if(SSL_SET_OPTION(CRLfile)) {
     /* set the CRL list file */
-    rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
+    rc = gnutls_certificate_set_x509_crl_file(BACKEND->cred,
                                               SSL_SET_OPTION(CRLfile),
                                               GNUTLS_X509_FMT_PEM);
     if(rc < 0) {
@@ -624,14 +633,14 @@ gtls_connect_step1(struct connectdata *conn,
   init_flags |= GNUTLS_NO_TICKETS;
 #endif
 
-  rc = gnutls_init(&conn->ssl[sockindex].session, init_flags);
+  rc = gnutls_init(&BACKEND->session, init_flags);
   if(rc != GNUTLS_E_SUCCESS) {
     failf(data, "gnutls_init() failed: %d", rc);
     return CURLE_SSL_CONNECT_ERROR;
   }
 
   /* convenient assign */
-  session = conn->ssl[sockindex].session;
+  session = BACKEND->session;
 
   if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
 #ifdef ENABLE_IPV6
@@ -788,7 +797,7 @@ gtls_connect_step1(struct connectdata *conn,
         GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
         GNUTLS_PKCS_USE_PBES2_AES_256;
       rc = gnutls_certificate_set_x509_key_file2(
-           conn->ssl[sockindex].cred,
+           BACKEND->cred,
            SSL_SET_OPTION(cert),
            SSL_SET_OPTION(key) ?
            SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
@@ -808,7 +817,7 @@ gtls_connect_step1(struct connectdata *conn,
     }
     else {
       if(gnutls_certificate_set_x509_key_file(
-           conn->ssl[sockindex].cred,
+           BACKEND->cred,
            SSL_SET_OPTION(cert),
            SSL_SET_OPTION(key) ?
            SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
@@ -824,7 +833,7 @@ gtls_connect_step1(struct connectdata *conn,
   /* put the credentials to the current session */
   if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
     rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
-                                conn->ssl[sockindex].srp_client_cred);
+                                BACKEND->srp_client_cred);
     if(rc != GNUTLS_E_SUCCESS) {
       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
       return CURLE_SSL_CONNECT_ERROR;
@@ -834,7 +843,7 @@ gtls_connect_step1(struct connectdata *conn,
 #endif
   {
     rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
-                                conn->ssl[sockindex].cred);
+                                BACKEND->cred);
     if(rc != GNUTLS_E_SUCCESS) {
       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
       return CURLE_SSL_CONNECT_ERROR;
@@ -842,7 +851,7 @@ gtls_connect_step1(struct connectdata *conn,
   }
 
   if(conn->proxy_ssl[sockindex].use) {
-    transport_ptr = conn->proxy_ssl[sockindex].session;
+    transport_ptr = conn->proxy_ssl[sockindex].backend->session;
     gnutls_transport_push = Curl_gtls_push_ssl;
     gnutls_transport_pull = Curl_gtls_pull_ssl;
   }
@@ -967,7 +976,8 @@ gtls_connect_step3(struct connectdata *conn,
   time_t certclock;
   const char *ptr;
   struct Curl_easy *data = conn->data;
-  gnutls_session_t session = conn->ssl[sockindex].session;
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  gnutls_session_t session = BACKEND->session;
   int rc;
 #ifdef HAS_ALPN
   gnutls_datum_t proto;
@@ -1198,7 +1208,7 @@ gtls_connect_step3(struct connectdata *conn,
           SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
   }
 
-  size=sizeof(certbuf);
+  size = sizeof(certbuf);
   rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
                                      0, /* the first and only one */
                                      FALSE,
@@ -1238,7 +1248,7 @@ gtls_connect_step3(struct connectdata *conn,
 #endif
 
     if(addrlen) {
-      for(i=0; ; i++) {
+      for(i = 0; ; i++) {
         certaddrlen = sizeof(certaddr);
         ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
                                                    &certaddrlen, NULL);
@@ -1471,7 +1481,7 @@ gtls_connect_common(struct connectdata *conn,
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
   /* Initiate the connection, if not already done */
-  if(ssl_connect_1==connssl->connecting_state) {
+  if(ssl_connect_1 == connssl->connecting_state) {
     rc = gtls_connect_step1(conn, sockindex);
     if(rc)
       return rc;
@@ -1483,29 +1493,24 @@ gtls_connect_common(struct connectdata *conn,
     return rc;
 
   /* Finish connecting once the handshake is done */
-  if(ssl_connect_1==connssl->connecting_state) {
+  if(ssl_connect_1 == connssl->connecting_state) {
     rc = gtls_connect_step3(conn, sockindex);
     if(rc)
       return rc;
   }
 
-  *done = ssl_connect_1==connssl->connecting_state;
+  *done = ssl_connect_1 == connssl->connecting_state;
 
   return CURLE_OK;
 }
 
-CURLcode
-Curl_gtls_connect_nonblocking(struct connectdata *conn,
-                              int sockindex,
-                              bool *done)
+static CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
+                                              int sockindex, bool *done)
 {
   return gtls_connect_common(conn, sockindex, TRUE, done);
 }
 
-CURLcode
-Curl_gtls_connect(struct connectdata *conn,
-                  int sockindex)
-
+static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex)
 {
   CURLcode result;
   bool done = FALSE;
@@ -1519,15 +1524,18 @@ Curl_gtls_connect(struct connectdata *conn,
   return CURLE_OK;
 }
 
-bool Curl_gtls_data_pending(const struct connectdata *conn, int connindex)
+static bool Curl_gtls_data_pending(const struct connectdata *conn,
+                                   int connindex)
 {
+  const struct ssl_connect_data *connssl = &conn->ssl[connindex];
   bool res = FALSE;
-  if(conn->ssl[connindex].session &&
-     0 != gnutls_record_check_pending(conn->ssl[connindex].session))
+  if(BACKEND->session &&
+     0 != gnutls_record_check_pending(BACKEND->session))
     res = TRUE;
 
-  if(conn->proxy_ssl[connindex].session &&
-     0 != gnutls_record_check_pending(conn->proxy_ssl[connindex].session))
+  connssl = &conn->proxy_ssl[connindex];
+  if(BACKEND->session &&
+     0 != gnutls_record_check_pending(BACKEND->session))
     res = TRUE;
 
   return res;
@@ -1539,7 +1547,8 @@ static ssize_t gtls_send(struct connectdata *conn,
                          size_t len,
                          CURLcode *curlcode)
 {
-  ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  ssize_t rc = gnutls_record_send(BACKEND->session, mem, len);
 
   if(rc < 0) {
     *curlcode = (rc == GNUTLS_E_AGAIN)
@@ -1552,26 +1561,26 @@ static ssize_t gtls_send(struct connectdata *conn,
   return rc;
 }
 
-static void close_one(struct ssl_connect_data *ssl)
+static void close_one(struct ssl_connect_data *connssl)
 {
-  if(ssl->session) {
-    gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR);
-    gnutls_deinit(ssl->session);
-    ssl->session = NULL;
+  if(BACKEND->session) {
+    gnutls_bye(BACKEND->session, GNUTLS_SHUT_RDWR);
+    gnutls_deinit(BACKEND->session);
+    BACKEND->session = NULL;
   }
-  if(ssl->cred) {
-    gnutls_certificate_free_credentials(ssl->cred);
-    ssl->cred = NULL;
+  if(BACKEND->cred) {
+    gnutls_certificate_free_credentials(BACKEND->cred);
+    BACKEND->cred = NULL;
   }
 #ifdef USE_TLS_SRP
-  if(ssl->srp_client_cred) {
-    gnutls_srp_free_client_credentials(ssl->srp_client_cred);
-    ssl->srp_client_cred = NULL;
+  if(BACKEND->srp_client_cred) {
+    gnutls_srp_free_client_credentials(BACKEND->srp_client_cred);
+    BACKEND->srp_client_cred = NULL;
   }
 #endif
 }
 
-void Curl_gtls_close(struct connectdata *conn, int sockindex)
+static void Curl_gtls_close(struct connectdata *conn, int sockindex)
 {
   close_one(&conn->ssl[sockindex]);
   close_one(&conn->proxy_ssl[sockindex]);
@@ -1581,8 +1590,9 @@ void Curl_gtls_close(struct connectdata *conn, int 
sockindex)
  * This function is called to shut down the SSL layer but keep the
  * socket open (CCC - Clear Command Channel)
  */
-int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
 {
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   ssize_t result;
   int retval = 0;
   struct Curl_easy *data = conn->data;
@@ -1595,16 +1605,16 @@ int Curl_gtls_shutdown(struct connectdata *conn, int 
sockindex)
      we do not send one. Let's hope other servers do the same... */
 
   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
-      gnutls_bye(conn->ssl[sockindex].session, GNUTLS_SHUT_WR);
+      gnutls_bye(BACKEND->session, GNUTLS_SHUT_WR);
 
-  if(conn->ssl[sockindex].session) {
+  if(BACKEND->session) {
     while(!done) {
       int what = SOCKET_READABLE(conn->sock[sockindex],
                                  SSL_SHUTDOWN_TIMEOUT);
       if(what > 0) {
         /* Something to read, let's do it and hope that it is the close
            notify alert from the server */
-        result = gnutls_record_recv(conn->ssl[sockindex].session,
+        result = gnutls_record_recv(BACKEND->session,
                                     buf, sizeof(buf));
         switch(result) {
         case 0:
@@ -1635,18 +1645,18 @@ int Curl_gtls_shutdown(struct connectdata *conn, int 
sockindex)
         done = 1;
       }
     }
-    gnutls_deinit(conn->ssl[sockindex].session);
+    gnutls_deinit(BACKEND->session);
   }
-  gnutls_certificate_free_credentials(conn->ssl[sockindex].cred);
+  gnutls_certificate_free_credentials(BACKEND->cred);
 
 #ifdef USE_TLS_SRP
   if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
      && SSL_SET_OPTION(username) != NULL)
-    gnutls_srp_free_client_credentials(conn->ssl[sockindex].srp_client_cred);
+    gnutls_srp_free_client_credentials(BACKEND->srp_client_cred);
 #endif
 
-  conn->ssl[sockindex].cred = NULL;
-  conn->ssl[sockindex].session = NULL;
+  BACKEND->cred = NULL;
+  BACKEND->session = NULL;
 
   return retval;
 }
@@ -1657,9 +1667,10 @@ static ssize_t gtls_recv(struct connectdata *conn, /* 
connection data */
                          size_t buffersize,        /* max amount to read */
                          CURLcode *curlcode)
 {
+  struct ssl_connect_data *connssl = &conn->ssl[num];
   ssize_t ret;
 
-  ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
+  ret = gnutls_record_recv(BACKEND->session, buf, buffersize);
   if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
     *curlcode = CURLE_AGAIN;
     return -1;
@@ -1679,6 +1690,7 @@ static ssize_t gtls_recv(struct connectdata *conn, /* 
connection data */
 
   if(ret < 0) {
     failf(conn->data, "GnuTLS recv error (%d): %s",
+
           (int)ret, gnutls_strerror((int)ret));
     *curlcode = CURLE_RECV_ERROR;
     return -1;
@@ -1687,12 +1699,12 @@ static ssize_t gtls_recv(struct connectdata *conn, /* 
connection data */
   return ret;
 }
 
-void Curl_gtls_session_free(void *ptr)
+static void Curl_gtls_session_free(void *ptr)
 {
   free(ptr);
 }
 
-size_t Curl_gtls_version(char *buffer, size_t size)
+static size_t Curl_gtls_version(char *buffer, size_t size)
 {
   return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
 }
@@ -1722,9 +1734,8 @@ static int Curl_gtls_seed(struct Curl_easy *data)
 #endif
 
 /* data might be NULL! */
-CURLcode Curl_gtls_random(struct Curl_easy *data,
-                          unsigned char *entropy,
-                          size_t length)
+static CURLcode Curl_gtls_random(struct Curl_easy *data,
+                                 unsigned char *entropy, size_t length)
 {
 #if defined(USE_GNUTLS_NETTLE)
   int rc;
@@ -1739,10 +1750,10 @@ CURLcode Curl_gtls_random(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-void Curl_gtls_md5sum(unsigned char *tmp, /* input */
-                      size_t tmplen,
-                      unsigned char *md5sum, /* output */
-                      size_t md5len)
+static CURLcode Curl_gtls_md5sum(unsigned char *tmp, /* input */
+                                 size_t tmplen,
+                                 unsigned char *md5sum, /* output */
+                                 size_t md5len)
 {
 #if defined(USE_GNUTLS_NETTLE)
   struct md5_ctx MD5pw;
@@ -1756,12 +1767,13 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */
   memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
   gcry_md_close(MD5pw);
 #endif
+  return CURLE_OK;
 }
 
-void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
-                      size_t tmplen,
-                      unsigned char *sha256sum, /* output */
-                      size_t sha256len)
+static void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
+                                size_t tmplen,
+                                unsigned char *sha256sum, /* output */
+                                size_t sha256len)
 {
 #if defined(USE_GNUTLS_NETTLE)
   struct sha256_ctx SHA256pw;
@@ -1777,7 +1789,7 @@ void Curl_gtls_sha256sum(const unsigned char *tmp, /* 
input */
 #endif
 }
 
-bool Curl_gtls_cert_status_request(void)
+static bool Curl_gtls_cert_status_request(void)
 {
 #ifdef HAS_OCSP
   return TRUE;
@@ -1786,4 +1798,44 @@ bool Curl_gtls_cert_status_request(void)
 #endif
 }
 
+static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl,
+                                     CURLINFO info UNUSED_PARAM)
+{
+  (void)info;
+  return BACKEND->session;
+}
+
+const struct Curl_ssl Curl_ssl_gnutls = {
+  { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
+
+  1, /* have_ca_path */
+  1, /* have_certinfo */
+  1, /* have_pinnedpubkey */
+  0, /* have_ssl_ctx */
+  1, /* support_https_proxy */
+
+  sizeof(struct ssl_backend_data),
+
+  Curl_gtls_init,                /* init */
+  Curl_gtls_cleanup,             /* cleanup */
+  Curl_gtls_version,             /* version */
+  Curl_none_check_cxn,           /* check_cxn */
+  Curl_gtls_shutdown,            /* shutdown */
+  Curl_gtls_data_pending,        /* data_pending */
+  Curl_gtls_random,              /* random */
+  Curl_gtls_cert_status_request, /* cert_status_request */
+  Curl_gtls_connect,             /* connect */
+  Curl_gtls_connect_nonblocking, /* connect_nonblocking */
+  Curl_gtls_get_internals,       /* get_internals */
+  Curl_gtls_close,               /* close */
+  Curl_none_close_all,           /* close_all */
+  Curl_gtls_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_gtls_md5sum,              /* md5sum */
+  Curl_gtls_sha256sum            /* sha256sum */
+};
+
 #endif /* USE_GNUTLS */
diff --git a/lib/vtls/gtls.h b/lib/vtls/gtls.h
index 462c04853..780fc109d 100644
--- a/lib/vtls/gtls.h
+++ b/lib/vtls/gtls.h
@@ -28,69 +28,7 @@
 
 #include "urldata.h"
 
-int Curl_gtls_init(void);
-int Curl_gtls_cleanup(void);
-CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
-CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
-                                       int sockindex,
-                                       bool *done);
-bool Curl_gtls_data_pending(const struct connectdata *conn,
-                            int connindex);
-
- /* close a SSL connection */
-void Curl_gtls_close(struct connectdata *conn, int sockindex);
-
-void Curl_gtls_session_free(void *ptr);
-size_t Curl_gtls_version(char *buffer, size_t size);
-int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
-CURLcode Curl_gtls_random(struct Curl_easy *data,
-                          unsigned char *entropy,
-                          size_t length);
-void Curl_gtls_md5sum(unsigned char *tmp, /* input */
-                      size_t tmplen,
-                      unsigned char *md5sum, /* output */
-                      size_t md5len);
-void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
-                      size_t tmplen,
-                      unsigned char *sha256sum, /* output */
-                      size_t sha256len);
-
-bool Curl_gtls_cert_status_request(void);
-
-/* Support HTTPS-proxy */
-#define HTTPS_PROXY_SUPPORT 1
-
-/* Set the API backend definition to GnuTLS */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_GNUTLS
-
-/* this backend supports the CAPATH option */
-#define have_curlssl_ca_path 1
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-
-/* API setup for GnuTLS */
-#define curlssl_init Curl_gtls_init
-#define curlssl_cleanup Curl_gtls_cleanup
-#define curlssl_connect Curl_gtls_connect
-#define curlssl_connect_nonblocking Curl_gtls_connect_nonblocking
-#define curlssl_session_free(x)  Curl_gtls_session_free(x)
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_gtls_close
-#define curlssl_shutdown(x,y) Curl_gtls_shutdown(x,y)
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_gtls_version
-#define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending(x,y) Curl_gtls_data_pending(x,y)
-#define curlssl_random(x,y,z) Curl_gtls_random(x,y,z)
-#define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d)
-#define curlssl_sha256sum(a,b,c,d) Curl_gtls_sha256sum(a,b,c,d)
-#define curlssl_cert_status_request() Curl_gtls_cert_status_request()
+extern const struct Curl_ssl Curl_ssl_gnutls;
 
 #endif /* USE_GNUTLS */
 #endif /* HEADER_CURL_GTLS_H */
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index 037babe38..ce1f8eba8 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -61,6 +61,21 @@
 #include "curl_memory.h"
 #include "memdebug.h"
 
+struct ssl_backend_data {
+  mbedtls_ctr_drbg_context ctr_drbg;
+  mbedtls_entropy_context entropy;
+  mbedtls_ssl_context ssl;
+  int server_fd;
+  mbedtls_x509_crt cacert;
+  mbedtls_x509_crt clicert;
+  mbedtls_x509_crl crl;
+  mbedtls_pk_context pk;
+  mbedtls_ssl_config config;
+  const char *protocols[3];
+};
+
+#define BACKEND connssl->backend
+
 /* apply threading? */
 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
 #define THREADING_SUPPORT
@@ -214,9 +229,9 @@ set_ssl_version_min_max(struct connectdata *conn, int 
sockindex)
     return result;
   }
 
-  mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+  mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                mbedtls_ver_min);
-  mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+  mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                mbedtls_ver_max);
 
   return result;
@@ -238,7 +253,7 @@ mbed_connect_step1(struct connectdata *conn,
   const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
   int ret = -1;
   char errorbuf[128];
-  errorbuf[0]=0;
+  errorbuf[0] = 0;
 
   /* mbedTLS only supports SSLv3 and TLSv1 */
   if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
@@ -248,9 +263,9 @@ mbed_connect_step1(struct connectdata *conn,
 
 #ifdef THREADING_SUPPORT
   entropy_init_mutex(&ts_entropy);
-  mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
+  mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg);
 
-  ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex,
+  ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, entropy_func_mutex,
                               &ts_entropy, NULL, 0);
   if(ret) {
 #ifdef MBEDTLS_ERROR_C
@@ -260,11 +275,11 @@ mbed_connect_step1(struct connectdata *conn,
           -ret, errorbuf);
   }
 #else
-  mbedtls_entropy_init(&connssl->entropy);
-  mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
+  mbedtls_entropy_init(&BACKEND->entropy);
+  mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg);
 
-  ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, mbedtls_entropy_func,
-                              &connssl->entropy, NULL, 0);
+  ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, mbedtls_entropy_func,
+                              &BACKEND->entropy, NULL, 0);
   if(ret) {
 #ifdef MBEDTLS_ERROR_C
     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
@@ -275,10 +290,10 @@ mbed_connect_step1(struct connectdata *conn,
 #endif /* THREADING_SUPPORT */
 
   /* Load the trusted CA */
-  mbedtls_x509_crt_init(&connssl->cacert);
+  mbedtls_x509_crt_init(&BACKEND->cacert);
 
   if(ssl_cafile) {
-    ret = mbedtls_x509_crt_parse_file(&connssl->cacert, ssl_cafile);
+    ret = mbedtls_x509_crt_parse_file(&BACKEND->cacert, ssl_cafile);
 
     if(ret<0) {
 #ifdef MBEDTLS_ERROR_C
@@ -293,7 +308,7 @@ mbed_connect_step1(struct connectdata *conn,
   }
 
   if(ssl_capath) {
-    ret = mbedtls_x509_crt_parse_path(&connssl->cacert, ssl_capath);
+    ret = mbedtls_x509_crt_parse_path(&BACKEND->cacert, ssl_capath);
 
     if(ret<0) {
 #ifdef MBEDTLS_ERROR_C
@@ -308,10 +323,10 @@ mbed_connect_step1(struct connectdata *conn,
   }
 
   /* Load the client certificate */
-  mbedtls_x509_crt_init(&connssl->clicert);
+  mbedtls_x509_crt_init(&BACKEND->clicert);
 
   if(ssl_cert) {
-    ret = mbedtls_x509_crt_parse_file(&connssl->clicert, ssl_cert);
+    ret = mbedtls_x509_crt_parse_file(&BACKEND->clicert, ssl_cert);
 
     if(ret) {
 #ifdef MBEDTLS_ERROR_C
@@ -325,12 +340,12 @@ mbed_connect_step1(struct connectdata *conn,
   }
 
   /* Load the client private key */
-  mbedtls_pk_init(&connssl->pk);
+  mbedtls_pk_init(&BACKEND->pk);
 
   if(SSL_SET_OPTION(key)) {
-    ret = mbedtls_pk_parse_keyfile(&connssl->pk, SSL_SET_OPTION(key),
+    ret = mbedtls_pk_parse_keyfile(&BACKEND->pk, SSL_SET_OPTION(key),
                                    SSL_SET_OPTION(key_passwd));
-    if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA))
+    if(ret == 0 && !mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_RSA))
       ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
 
     if(ret) {
@@ -345,10 +360,10 @@ mbed_connect_step1(struct connectdata *conn,
   }
 
   /* Load the CRL */
-  mbedtls_x509_crl_init(&connssl->crl);
+  mbedtls_x509_crl_init(&BACKEND->crl);
 
   if(ssl_crlfile) {
-    ret = mbedtls_x509_crl_parse_file(&connssl->crl, ssl_crlfile);
+    ret = mbedtls_x509_crl_parse_file(&BACKEND->crl, ssl_crlfile);
 
     if(ret) {
 #ifdef MBEDTLS_ERROR_C
@@ -363,14 +378,14 @@ mbed_connect_step1(struct connectdata *conn,
 
   infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port);
 
-  mbedtls_ssl_config_init(&connssl->config);
+  mbedtls_ssl_config_init(&BACKEND->config);
 
-  mbedtls_ssl_init(&connssl->ssl);
-  if(mbedtls_ssl_setup(&connssl->ssl, &connssl->config)) {
+  mbedtls_ssl_init(&BACKEND->ssl);
+  if(mbedtls_ssl_setup(&BACKEND->ssl, &BACKEND->config)) {
     failf(data, "mbedTLS: ssl_init failed");
     return CURLE_SSL_CONNECT_ERROR;
   }
-  ret = mbedtls_ssl_config_defaults(&connssl->config,
+  ret = mbedtls_ssl_config_defaults(&BACKEND->config,
                                     MBEDTLS_SSL_IS_CLIENT,
                                     MBEDTLS_SSL_TRANSPORT_STREAM,
                                     MBEDTLS_SSL_PRESET_DEFAULT);
@@ -380,20 +395,20 @@ mbed_connect_step1(struct connectdata *conn,
   }
 
   /* new profile with RSA min key len = 1024 ... */
-  mbedtls_ssl_conf_cert_profile(&connssl->config,
+  mbedtls_ssl_conf_cert_profile(&BACKEND->config,
                                 &mbedtls_x509_crt_profile_fr);
 
   switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
-    mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+    mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                  MBEDTLS_SSL_MINOR_VERSION_1);
     infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n");
     break;
   case CURL_SSLVERSION_SSLv3:
-    mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+    mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                  MBEDTLS_SSL_MINOR_VERSION_0);
-    mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
+    mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                  MBEDTLS_SSL_MINOR_VERSION_0);
     infof(data, "mbedTLS: Set SSL version to SSLv3\n");
     break;
@@ -412,25 +427,25 @@ mbed_connect_step1(struct connectdata *conn,
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  mbedtls_ssl_conf_authmode(&connssl->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
+  mbedtls_ssl_conf_authmode(&BACKEND->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
 
-  mbedtls_ssl_conf_rng(&connssl->config, mbedtls_ctr_drbg_random,
-                       &connssl->ctr_drbg);
-  mbedtls_ssl_set_bio(&connssl->ssl, &conn->sock[sockindex],
+  mbedtls_ssl_conf_rng(&BACKEND->config, mbedtls_ctr_drbg_random,
+                       &BACKEND->ctr_drbg);
+  mbedtls_ssl_set_bio(&BACKEND->ssl, &conn->sock[sockindex],
                       mbedtls_net_send,
                       mbedtls_net_recv,
                       NULL /*  rev_timeout() */);
 
-  mbedtls_ssl_conf_ciphersuites(&connssl->config,
+  mbedtls_ssl_conf_ciphersuites(&BACKEND->config,
                                 mbedtls_ssl_list_ciphersuites());
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
-  mbedtls_ssl_conf_renegotiation(&connssl->config,
+  mbedtls_ssl_conf_renegotiation(&BACKEND->config,
                                  MBEDTLS_SSL_RENEGOTIATION_ENABLED);
 #endif
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
-  mbedtls_ssl_conf_session_tickets(&connssl->config,
+  mbedtls_ssl_conf_session_tickets(&BACKEND->config,
                                    MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
 #endif
 
@@ -440,7 +455,7 @@ mbed_connect_step1(struct connectdata *conn,
 
     Curl_ssl_sessionid_lock(conn);
     if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
-      ret = mbedtls_ssl_set_session(&connssl->ssl, old_session);
+      ret = mbedtls_ssl_set_session(&BACKEND->ssl, old_session);
       if(ret) {
         Curl_ssl_sessionid_unlock(conn);
         failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
@@ -451,15 +466,15 @@ mbed_connect_step1(struct connectdata *conn,
     Curl_ssl_sessionid_unlock(conn);
   }
 
-  mbedtls_ssl_conf_ca_chain(&connssl->config,
-                            &connssl->cacert,
-                            &connssl->crl);
+  mbedtls_ssl_conf_ca_chain(&BACKEND->config,
+                            &BACKEND->cacert,
+                            &BACKEND->crl);
 
   if(SSL_SET_OPTION(key)) {
-    mbedtls_ssl_conf_own_cert(&connssl->config,
-                              &connssl->clicert, &connssl->pk);
+    mbedtls_ssl_conf_own_cert(&BACKEND->config,
+                              &BACKEND->clicert, &BACKEND->pk);
   }
-  if(mbedtls_ssl_set_hostname(&connssl->ssl, hostname)) {
+  if(mbedtls_ssl_set_hostname(&BACKEND->ssl, hostname)) {
     /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
        the name to set in the SNI extension. So even if curl connects to a
        host specified as an IP address, this function must be used. */
@@ -469,7 +484,7 @@ mbed_connect_step1(struct connectdata *conn,
 
 #ifdef HAS_ALPN
   if(conn->bits.tls_enable_alpn) {
-    const char **p = &connssl->protocols[0];
+    const char **p = &BACKEND->protocols[0];
 #ifdef USE_NGHTTP2
     if(data->set.httpversion >= CURL_HTTP_VERSION_2)
       *p++ = NGHTTP2_PROTO_VERSION_ID;
@@ -478,19 +493,19 @@ mbed_connect_step1(struct connectdata *conn,
     *p = NULL;
     /* this function doesn't clone the protocols array, which is why we need
        to keep it around */
-    if(mbedtls_ssl_conf_alpn_protocols(&connssl->config,
-                                       &connssl->protocols[0])) {
+    if(mbedtls_ssl_conf_alpn_protocols(&BACKEND->config,
+                                       &BACKEND->protocols[0])) {
       failf(data, "Failed setting ALPN protocols");
       return CURLE_SSL_CONNECT_ERROR;
     }
-    for(p = &connssl->protocols[0]; *p; ++p)
+    for(p = &BACKEND->protocols[0]; *p; ++p)
       infof(data, "ALPN, offering %s\n", *p);
   }
 #endif
 
 #ifdef MBEDTLS_DEBUG
   /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */
-  mbedtls_ssl_conf_dbg(&connssl->config, mbed_debug, data);
+  mbedtls_ssl_conf_dbg(&BACKEND->config, mbed_debug, data);
   /* - 0 No debug
    * - 1 Error
    * - 2 State change
@@ -502,7 +517,7 @@ mbed_connect_step1(struct connectdata *conn,
 
   /* give application a chance to interfere with mbedTLS set up. */
   if(data->set.ssl.fsslctx) {
-    ret = (*data->set.ssl.fsslctx)(data, &connssl->config,
+    ret = (*data->set.ssl.fsslctx)(data, &BACKEND->config,
                                    data->set.ssl.fsslctxp);
     if(ret) {
       failf(data, "error signaled by ssl ctx callback");
@@ -537,7 +552,7 @@ mbed_connect_step2(struct connectdata *conn,
   conn->recv[sockindex] = mbed_recv;
   conn->send[sockindex] = mbed_send;
 
-  ret = mbedtls_ssl_handshake(&connssl->ssl);
+  ret = mbedtls_ssl_handshake(&BACKEND->ssl);
 
   if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
     connssl->connecting_state = ssl_connect_2_reading;
@@ -557,10 +572,10 @@ mbed_connect_step2(struct connectdata *conn,
   }
 
   infof(data, "mbedTLS: Handshake complete, cipher is %s\n",
-        mbedtls_ssl_get_ciphersuite(&conn->ssl[sockindex].ssl)
+        mbedtls_ssl_get_ciphersuite(&BACKEND->ssl)
     );
 
-  ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl);
+  ret = mbedtls_ssl_get_verify_result(&BACKEND->ssl);
 
   if(ret && SSL_CONN_CONFIG(verifypeer)) {
     if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
@@ -580,7 +595,7 @@ mbed_connect_step2(struct connectdata *conn,
     return CURLE_PEER_FAILED_VERIFICATION;
   }
 
-  peercert = mbedtls_ssl_get_peer_cert(&connssl->ssl);
+  peercert = mbedtls_ssl_get_peer_cert(&BACKEND->ssl);
 
   if(peercert && data->set.verbose) {
     const size_t bufsize = 16384;
@@ -650,7 +665,7 @@ mbed_connect_step2(struct connectdata *conn,
 
 #ifdef HAS_ALPN
   if(conn->bits.tls_enable_alpn) {
-    next_protocol = mbedtls_ssl_get_alpn_protocol(&connssl->ssl);
+    next_protocol = mbedtls_ssl_get_alpn_protocol(&BACKEND->ssl);
 
     if(next_protocol) {
       infof(data, "ALPN, server accepted to use %s\n", next_protocol);
@@ -700,7 +715,7 @@ mbed_connect_step3(struct connectdata *conn,
 
     mbedtls_ssl_session_init(our_ssl_sessionid);
 
-    ret = mbedtls_ssl_get_session(&connssl->ssl, our_ssl_sessionid);
+    ret = mbedtls_ssl_get_session(&BACKEND->ssl, our_ssl_sessionid);
     if(ret) {
       free(our_ssl_sessionid);
       failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
@@ -730,9 +745,10 @@ static ssize_t mbed_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 = mbedtls_ssl_write(&conn->ssl[sockindex].ssl,
+  ret = mbedtls_ssl_write(&BACKEND->ssl,
                           (unsigned char *)mem, len);
 
   if(ret < 0) {
@@ -744,22 +760,23 @@ static ssize_t mbed_send(struct connectdata *conn, int 
sockindex,
   return ret;
 }
 
-void Curl_mbedtls_close_all(struct Curl_easy *data)
+static void Curl_mbedtls_close_all(struct Curl_easy *data)
 {
   (void)data;
 }
 
-void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
+static void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
 {
-  mbedtls_pk_free(&conn->ssl[sockindex].pk);
-  mbedtls_x509_crt_free(&conn->ssl[sockindex].clicert);
-  mbedtls_x509_crt_free(&conn->ssl[sockindex].cacert);
-  mbedtls_x509_crl_free(&conn->ssl[sockindex].crl);
-  mbedtls_ssl_config_free(&conn->ssl[sockindex].config);
-  mbedtls_ssl_free(&conn->ssl[sockindex].ssl);
-  mbedtls_ctr_drbg_free(&conn->ssl[sockindex].ctr_drbg);
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  mbedtls_pk_free(&BACKEND->pk);
+  mbedtls_x509_crt_free(&BACKEND->clicert);
+  mbedtls_x509_crt_free(&BACKEND->cacert);
+  mbedtls_x509_crl_free(&BACKEND->crl);
+  mbedtls_ssl_config_free(&BACKEND->config);
+  mbedtls_ssl_free(&BACKEND->ssl);
+  mbedtls_ctr_drbg_free(&BACKEND->ctr_drbg);
 #ifndef THREADING_SUPPORT
-  mbedtls_entropy_free(&conn->ssl[sockindex].entropy);
+  mbedtls_entropy_free(&BACKEND->entropy);
 #endif /* THREADING_SUPPORT */
 }
 
@@ -767,11 +784,12 @@ static ssize_t mbed_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 = mbedtls_ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf,
+  ret = mbedtls_ssl_read(&BACKEND->ssl, (unsigned char *)buf,
                          buffersize);
 
   if(ret <= 0) {
@@ -788,21 +806,21 @@ static ssize_t mbed_recv(struct connectdata *conn, int 
num,
   return len;
 }
 
-void Curl_mbedtls_session_free(void *ptr)
+static void Curl_mbedtls_session_free(void *ptr)
 {
   mbedtls_ssl_session_free(ptr);
   free(ptr);
 }
 
-size_t Curl_mbedtls_version(char *buffer, size_t size)
+static size_t Curl_mbedtls_version(char *buffer, size_t size)
 {
   unsigned int version = mbedtls_version_get_number();
   return snprintf(buffer, size, "mbedTLS/%d.%d.%d", version>>24,
                   (version>>16)&0xff, (version>>8)&0xff);
 }
 
-CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
-                             size_t length)
+static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
+                                    unsigned char *entropy, size_t length)
 {
 #if defined(MBEDTLS_CTR_DRBG_C)
   int ret = -1;
@@ -811,7 +829,7 @@ CURLcode Curl_mbedtls_random(struct Curl_easy *data, 
unsigned char *entropy,
   mbedtls_ctr_drbg_context ctr_drbg;
   mbedtls_entropy_init(&ctr_entropy);
   mbedtls_ctr_drbg_init(&ctr_drbg);
-  errorbuf[0]=0;
+  errorbuf[0] = 0;
 
   ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
                               &ctr_entropy, NULL, 0);
@@ -869,7 +887,7 @@ mbed_connect_common(struct connectdata *conn,
     return CURLE_OK;
   }
 
-  if(ssl_connect_1==connssl->connecting_state) {
+  if(ssl_connect_1 == connssl->connecting_state) {
     /* Find out how much more time we're allowed */
     timeout_ms = Curl_timeleft(data, NULL, TRUE);
 
@@ -900,9 +918,9 @@ mbed_connect_common(struct connectdata *conn,
     if(connssl->connecting_state == ssl_connect_2_reading
        || connssl->connecting_state == ssl_connect_2_writing) {
 
-      curl_socket_t writefd = 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==
+      curl_socket_t readfd = ssl_connect_2_reading ==
         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
 
       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
@@ -942,13 +960,13 @@ mbed_connect_common(struct connectdata *conn,
 
   } /* repeat step2 until all transactions are done. */
 
-  if(ssl_connect_3==connssl->connecting_state) {
+  if(ssl_connect_3 == connssl->connecting_state) {
     retcode = mbed_connect_step3(conn, sockindex);
     if(retcode)
       return retcode;
   }
 
-  if(ssl_connect_done==connssl->connecting_state) {
+  if(ssl_connect_done == connssl->connecting_state) {
     connssl->state = ssl_connection_complete;
     conn->recv[sockindex] = mbed_recv;
     conn->send[sockindex] = mbed_send;
@@ -963,18 +981,14 @@ mbed_connect_common(struct connectdata *conn,
   return CURLE_OK;
 }
 
-CURLcode
-Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
-                                 int sockindex,
-                                 bool *done)
+static CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
+                                                 int sockindex, bool *done)
 {
   return mbed_connect_common(conn, sockindex, TRUE, done);
 }
 
 
-CURLcode
-Curl_mbedtls_connect(struct connectdata *conn,
-                     int sockindex)
+static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex)
 {
   CURLcode retcode;
   bool done = FALSE;
@@ -992,19 +1006,70 @@ Curl_mbedtls_connect(struct connectdata *conn,
  * return 0 error initializing SSL
  * return 1 SSL initialized successfully
  */
-int Curl_mbedtls_init(void)
+static int Curl_mbedtls_init(void)
 {
   return Curl_polarsslthreadlock_thread_setup();
 }
 
-void Curl_mbedtls_cleanup(void)
+static void Curl_mbedtls_cleanup(void)
 {
   (void)Curl_polarsslthreadlock_thread_cleanup();
 }
 
-int Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex)
+static bool Curl_mbedtls_data_pending(const struct connectdata *conn,
+                                      int sockindex)
 {
-  return mbedtls_ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0;
+  const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+  return mbedtls_ssl_get_bytes_avail(&BACKEND->ssl) != 0;
 }
 
+static void Curl_mbedtls_sha256sum(const unsigned char *input,
+                                    size_t inputlen,
+                                    unsigned char *sha256sum,
+                                    size_t sha256len UNUSED_PARAM)
+{
+  (void)sha256len;
+  mbedtls_sha256(input, inputlen, sha256sum, 0);
+}
+
+static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl,
+                                        CURLINFO info UNUSED_PARAM)
+{
+  (void)info;
+  return &BACKEND->ssl;
+}
+
+const struct Curl_ssl Curl_ssl_mbedtls = {
+  { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */
+
+  1, /* have_ca_path */
+  0, /* have_certinfo */
+  1, /* have_pinnedpubkey */
+  1, /* have_ssl_ctx */
+  0, /* support_https_proxy */
+
+  sizeof(struct ssl_backend_data),
+
+  Curl_mbedtls_init,                /* init */
+  Curl_mbedtls_cleanup,             /* cleanup */
+  Curl_mbedtls_version,             /* version */
+  Curl_none_check_cxn,              /* check_cxn */
+  Curl_none_shutdown,               /* shutdown */
+  Curl_mbedtls_data_pending,        /* data_pending */
+  Curl_mbedtls_random,              /* random */
+  Curl_none_cert_status_request,    /* cert_status_request */
+  Curl_mbedtls_connect,             /* connect */
+  Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */
+  Curl_mbedtls_get_internals,       /* get_internals */
+  Curl_mbedtls_close,               /* close */
+  Curl_mbedtls_close_all,           /* close_all */
+  Curl_mbedtls_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_mbedtls_sha256sum            /* sha256sum */
+};
+
 #endif /* USE_MBEDTLS */
diff --git a/lib/vtls/mbedtls.h b/lib/vtls/mbedtls.h
index 71d17a491..4a938605b 100644
--- a/lib/vtls/mbedtls.h
+++ b/lib/vtls/mbedtls.h
@@ -26,57 +26,7 @@
 
 #ifdef USE_MBEDTLS
 
-#include <mbedtls/sha256.h>
-
-/* Called on first use mbedTLS, setup threading if supported */
-int  Curl_mbedtls_init(void);
-void Curl_mbedtls_cleanup(void);
-int Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex);
-
-CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
-                                           int sockindex,
-                                           bool *done);
-
-/* tell mbedTLS to close down all open information regarding connections (and
-   thus session ID caching etc) */
-void Curl_mbedtls_close_all(struct Curl_easy *data);
-
- /* close a SSL connection */
-void Curl_mbedtls_close(struct connectdata *conn, int sockindex);
-
-void Curl_mbedtls_session_free(void *ptr);
-size_t Curl_mbedtls_version(char *buffer, size_t size);
-int Curl_mbedtls_shutdown(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_mbedtls_random(struct Curl_easy *data, unsigned char *entropy,
-                     size_t length);
-
-/* this backends supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-
-/* this backend supports CURLOPT_SSL_CTX_* */
-#define have_curlssl_ssl_ctx 1
-
-/* API setup for mbedTLS */
-#define curlssl_init() Curl_mbedtls_init()
-#define curlssl_cleanup() Curl_mbedtls_cleanup()
-#define curlssl_connect Curl_mbedtls_connect
-#define curlssl_connect_nonblocking Curl_mbedtls_connect_nonblocking
-#define curlssl_session_free(x)  Curl_mbedtls_session_free(x)
-#define curlssl_close_all Curl_mbedtls_close_all
-#define curlssl_close Curl_mbedtls_close
-#define curlssl_shutdown(x,y) 0
-#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) (x=x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_mbedtls_version
-#define curlssl_check_cxn(x) (x=x, -1)
-#define curlssl_data_pending(x,y) Curl_mbedtls_data_pending(x, y)
-#define CURL_SSL_BACKEND CURLSSLBACKEND_MBEDTLS
-#define curlssl_sha256sum(a,b,c,d) mbedtls_sha256(a,b,c,0)
-#define curlssl_random(x,y,z) Curl_mbedtls_random(x, y, z)
+extern const struct Curl_ssl Curl_ssl_mbedtls;
 
 #endif /* USE_MBEDTLS */
 #endif /* HEADER_CURL_MBEDTLS_H */
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index d1711d6a1..c0b7e63ab 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -78,6 +78,16 @@
 /* enough to fit the string "PEM Token #[0|1]" */
 #define SLOTSIZE 13
 
+struct ssl_backend_data {
+  PRFileDesc *handle;
+  char *client_nickname;
+  struct Curl_easy *data;
+  struct curl_llist obj_list;
+  PK11GenericObject *obj_clicert;
+};
+
+#define BACKEND connssl->backend
+
 static PRLock *nss_initlock = NULL;
 static PRLock *nss_crllock = NULL;
 static PRLock *nss_findslot_lock = NULL;
@@ -271,7 +281,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, 
PRFileDesc * model,
 
     found = PR_FALSE;
 
-    for(i=0; i<NUM_OF_CIPHERS; i++) {
+    for(i = 0; i<NUM_OF_CIPHERS; i++) {
       if(strcasecompare(cipher, cipherlist[i].name)) {
         cipher_state[i] = PR_TRUE;
         found = PR_TRUE;
@@ -290,7 +300,7 @@ static SECStatus set_ciphers(struct Curl_easy *data, 
PRFileDesc * model,
   }
 
   /* Finally actually enable the selected ciphers */
-  for(i=0; i<NUM_OF_CIPHERS; i++) {
+  for(i = 0; i<NUM_OF_CIPHERS; i++) {
     if(!cipher_state[i])
       continue;
 
@@ -311,7 +321,7 @@ static bool any_cipher_enabled(void)
 {
   unsigned int i;
 
-  for(i=0; i<NUM_OF_CIPHERS; i++) {
+  for(i = 0; i<NUM_OF_CIPHERS; i++) {
     PRInt32 policy = 0;
     SSL_CipherPolicyGet(cipherlist[i].num, &policy);
     if(policy)
@@ -396,7 +406,7 @@ static CURLcode insert_wrapped_ptr(struct curl_llist *list, 
void *ptr)
 /* Call PK11_CreateGenericObject() with the given obj_class and filename.  If
  * the call succeeds, append the object handle to the list of objects so that
  * the object can be destroyed in Curl_nss_close(). */
-static CURLcode nss_create_object(struct ssl_connect_data *ssl,
+static CURLcode nss_create_object(struct ssl_connect_data *connssl,
                                   CK_OBJECT_CLASS obj_class,
                                   const char *filename, bool cacert)
 {
@@ -435,14 +445,14 @@ static CURLcode nss_create_object(struct ssl_connect_data 
*ssl,
   if(!obj)
     return result;
 
-  if(insert_wrapped_ptr(&ssl->obj_list, obj) != CURLE_OK) {
+  if(insert_wrapped_ptr(&BACKEND->obj_list, obj) != CURLE_OK) {
     PK11_DestroyGenericObject(obj);
     return CURLE_OUT_OF_MEMORY;
   }
 
   if(!cacert && CKO_CERTIFICATE == obj_class)
     /* store reference to a client certificate */
-    ssl->obj_clicert = obj;
+    BACKEND->obj_clicert = obj;
 
   return CURLE_OK;
 }
@@ -992,7 +1002,7 @@ static SECStatus check_issuer_cert(PRFileDesc *sock,
                                    char *issuer_nickname)
 {
   CERTCertificate *cert, *cert_issuer, *issuer;
-  SECStatus res=SECSuccess;
+  SECStatus res = SECSuccess;
   void *proto_win = NULL;
 
   cert = SSL_PeerCertificate(sock);
@@ -1004,7 +1014,7 @@ static SECStatus check_issuer_cert(PRFileDesc *sock,
   if((!cert_issuer) || (!issuer))
     res = SECFailure;
   else if(SECITEM_CompareItem(&cert_issuer->derCert,
-                              &issuer->derCert)!=SECEqual)
+                              &issuer->derCert) != SECEqual)
     res = SECFailure;
 
   CERT_DestroyCertificate(cert);
@@ -1017,7 +1027,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data 
*connssl,
                                 const char *pinnedpubkey)
 {
   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
-  struct Curl_easy *data = connssl->data;
+  struct Curl_easy *data = BACKEND->data;
   CERTCertificate *cert;
 
   if(!pinnedpubkey)
@@ -1025,7 +1035,7 @@ static CURLcode cmp_peer_pubkey(struct ssl_connect_data 
*connssl,
     return CURLE_OK;
 
   /* get peer certificate */
-  cert = SSL_PeerCertificate(connssl->handle);
+  cert = SSL_PeerCertificate(BACKEND->handle);
   if(cert) {
     /* extract public key from peer certificate */
     SECKEYPublicKey *pubkey = CERT_ExtractPublicKey(cert);
@@ -1069,11 +1079,11 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc 
*sock,
                                   struct SECKEYPrivateKeyStr **pRetKey)
 {
   struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
-  struct Curl_easy *data = connssl->data;
-  const char *nickname = connssl->client_nickname;
+  struct Curl_easy *data = BACKEND->data;
+  const char *nickname = BACKEND->client_nickname;
   static const char pem_slotname[] = "PEM Token #1";
 
-  if(connssl->obj_clicert) {
+  if(BACKEND->obj_clicert) {
     /* use the cert/key provided by PEM reader */
     SECItem cert_der = { 0, NULL, 0 };
     void *proto_win = SSL_RevealPinArg(sock);
@@ -1086,7 +1096,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc 
*sock,
       return SECFailure;
     }
 
-    if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE,
+    if(PK11_ReadRawAttribute(PK11_TypeGeneric, BACKEND->obj_clicert, CKA_VALUE,
                              &cert_der) != SECSuccess) {
       failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
       PK11_FreeSlot(slot);
@@ -1351,7 +1361,7 @@ static CURLcode nss_init(struct Curl_easy *data)
  * @retval 0 error initializing SSL
  * @retval 1 SSL initialized successfully
  */
-int Curl_nss_init(void)
+static int Curl_nss_init(void)
 {
   /* curl_global_init() is not thread-safe so this test is ok */
   if(nss_initlock == NULL) {
@@ -1386,7 +1396,7 @@ CURLcode Curl_nss_force_init(struct Curl_easy *data)
 }
 
 /* Global cleanup */
-void Curl_nss_cleanup(void)
+static void Curl_nss_cleanup(void)
 {
   /* This function isn't required to be threadsafe and this is only done
    * as a safety feature.
@@ -1426,14 +1436,14 @@ void Curl_nss_cleanup(void)
  *     0 means the connection has been closed
  *    -1 means the connection status is unknown
  */
-int
-Curl_nss_check_cxn(struct connectdata *conn)
+static int Curl_nss_check_cxn(struct connectdata *conn)
 {
+  struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
   int rc;
   char buf;
 
   rc =
-    PR_Recv(conn->ssl[FIRSTSOCKET].handle, (void *)&buf, 1, PR_MSG_PEEK,
+    PR_Recv(BACKEND->handle, (void *)&buf, 1, PR_MSG_PEEK,
             PR_SecondsToInterval(1));
   if(rc > 0)
     return 1; /* connection still in place */
@@ -1447,48 +1457,49 @@ Curl_nss_check_cxn(struct connectdata *conn)
 static void nss_close(struct ssl_connect_data *connssl)
 {
   /* before the cleanup, check whether we are using a client certificate */
-  const bool client_cert = (connssl->client_nickname != NULL)
-    || (connssl->obj_clicert != NULL);
+  const bool client_cert = (BACKEND->client_nickname != NULL)
+    || (BACKEND->obj_clicert != NULL);
 
-  free(connssl->client_nickname);
-  connssl->client_nickname = NULL;
+  free(BACKEND->client_nickname);
+  BACKEND->client_nickname = NULL;
 
   /* destroy all NSS objects in order to avoid failure of NSS shutdown */
-  Curl_llist_destroy(&connssl->obj_list, NULL);
-  connssl->obj_clicert = NULL;
+  Curl_llist_destroy(&BACKEND->obj_list, NULL);
+  BACKEND->obj_clicert = NULL;
 
-  if(connssl->handle) {
+  if(BACKEND->handle) {
     if(client_cert)
       /* A server might require different authentication based on the
        * particular path being requested by the client.  To support this
        * scenario, we must ensure that a connection will never reuse the
        * authentication data from a previous connection. */
-      SSL_InvalidateSession(connssl->handle);
+      SSL_InvalidateSession(BACKEND->handle);
 
-    PR_Close(connssl->handle);
-    connssl->handle = NULL;
+    PR_Close(BACKEND->handle);
+    BACKEND->handle = NULL;
   }
 }
 
 /*
  * This function is called when an SSL connection is closed.
  */
-void Curl_nss_close(struct connectdata *conn, int sockindex)
+static void Curl_nss_close(struct connectdata *conn, int sockindex)
 {
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   struct ssl_connect_data *connssl_proxy = &conn->proxy_ssl[sockindex];
 
-  if(connssl->handle || connssl_proxy->handle) {
+  if(BACKEND->handle || connssl_proxy->backend->handle) {
     /* NSS closes the socket we previously handed to it, so we must mark it
        as closed to avoid double close */
     fake_sclose(conn->sock[sockindex]);
     conn->sock[sockindex] = CURL_SOCKET_BAD;
   }
 
-  if(connssl->handle)
-    /* nss_close(connssl) will transitively close also connssl_proxy->handle
-       if both are used. Clear it to avoid a double close leading to crash. */
-    connssl_proxy->handle = NULL;
+  if(BACKEND->handle)
+    /* nss_close(connssl) will transitively close also
+       connssl_proxy->backend->handle if both are used. Clear it to avoid
+       a double close leading to crash. */
+    connssl_proxy->backend->handle = NULL;
 
   nss_close(connssl);
   nss_close(connssl_proxy);
@@ -1732,7 +1743,7 @@ static CURLcode nss_fail_connect(struct ssl_connect_data 
*connssl,
   }
 
   /* cleanup on connection failure */
-  Curl_llist_destroy(&connssl->obj_list, NULL);
+  Curl_llist_destroy(&BACKEND->obj_list, NULL);
 
   return curlerr;
 }
@@ -1746,7 +1757,7 @@ static CURLcode nss_set_blocking(struct ssl_connect_data 
*connssl,
   sock_opt.option = PR_SockOpt_Nonblocking;
   sock_opt.value.non_blocking = !blocking;
 
-  if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS)
+  if(PR_SetSocketOption(BACKEND->handle, &sock_opt) != PR_SUCCESS)
     return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR);
 
   return CURLE_OK;
@@ -1770,10 +1781,10 @@ static CURLcode nss_setup_connect(struct connectdata 
*conn, int sockindex)
     SSL_LIBRARY_VERSION_TLS_1_0   /* max */
   };
 
-  connssl->data = data;
+  BACKEND->data = data;
 
   /* list of all NSS objects we need to destroy in Curl_nss_close() */
-  Curl_llist_init(&connssl->obj_list, nss_destroy_object);
+  Curl_llist_init(&BACKEND->obj_list, nss_destroy_object);
 
   /* FIXME. NSS doesn't support multiple databases open at the same time. */
   PR_Lock(nss_initlock);
@@ -1882,7 +1893,7 @@ static CURLcode nss_setup_connect(struct connectdata 
*conn, int sockindex)
     char *nickname = dup_nickname(data, SSL_SET_OPTION(cert));
     if(nickname) {
       /* we are not going to use libnsspem.so to read the client cert */
-      connssl->obj_clicert = NULL;
+      BACKEND->obj_clicert = NULL;
     }
     else {
       CURLcode rv = cert_stuff(conn, sockindex, SSL_SET_OPTION(cert),
@@ -1895,10 +1906,10 @@ static CURLcode nss_setup_connect(struct connectdata 
*conn, int sockindex)
     }
 
     /* store the nickname for SelectClientCert() called during handshake */
-    connssl->client_nickname = nickname;
+    BACKEND->client_nickname = nickname;
   }
   else
-    connssl->client_nickname = NULL;
+    BACKEND->client_nickname = NULL;
 
   if(SSL_GetClientAuthDataHook(model, SelectClientCert,
                                (void *)connssl) != SECSuccess) {
@@ -1908,8 +1919,8 @@ static CURLcode nss_setup_connect(struct connectdata 
*conn, int sockindex)
 
   if(conn->proxy_ssl[sockindex].use) {
     DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
-    DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
-    nspr_io = conn->proxy_ssl[sockindex].handle;
+    DEBUGASSERT(conn->proxy_ssl[sockindex].backend->handle != NULL);
+    nspr_io = conn->proxy_ssl[sockindex].backend->handle;
     second_layer = TRUE;
   }
   else {
@@ -1939,8 +1950,8 @@ static CURLcode nss_setup_connect(struct connectdata 
*conn, int sockindex)
   }
 
   /* import our model socket onto the current I/O stack */
-  connssl->handle = SSL_ImportFD(model, nspr_io);
-  if(!connssl->handle) {
+  BACKEND->handle = SSL_ImportFD(model, nspr_io);
+  if(!BACKEND->handle) {
     if(!second_layer)
       PR_Close(nspr_io);
     goto error;
@@ -1951,36 +1962,36 @@ static CURLcode nss_setup_connect(struct connectdata 
*conn, int sockindex)
 
   /* This is the password associated with the cert that we're using */
   if(SSL_SET_OPTION(key_passwd)) {
-    SSL_SetPKCS11PinArg(connssl->handle, SSL_SET_OPTION(key_passwd));
+    SSL_SetPKCS11PinArg(BACKEND->handle, SSL_SET_OPTION(key_passwd));
   }
 
 #ifdef SSL_ENABLE_OCSP_STAPLING
   if(SSL_CONN_CONFIG(verifystatus)) {
-    if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
+    if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
         != SECSuccess)
       goto error;
   }
 #endif
 
 #ifdef SSL_ENABLE_NPN
-  if(SSL_OptionSet(connssl->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn
+  if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_NPN, conn->bits.tls_enable_npn
                    ? PR_TRUE : PR_FALSE) != SECSuccess)
     goto error;
 #endif
 
 #ifdef SSL_ENABLE_ALPN
-  if(SSL_OptionSet(connssl->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn
+  if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_ALPN, conn->bits.tls_enable_alpn
                    ? PR_TRUE : PR_FALSE) != SECSuccess)
     goto error;
 #endif
 
 #if NSSVERNUM >= 0x030f04 /* 3.15.4 */
   if(data->set.ssl.falsestart) {
-    if(SSL_OptionSet(connssl->handle, SSL_ENABLE_FALSE_START, PR_TRUE)
+    if(SSL_OptionSet(BACKEND->handle, SSL_ENABLE_FALSE_START, PR_TRUE)
         != SECSuccess)
       goto error;
 
-    if(SSL_SetCanFalseStartCallback(connssl->handle, CanFalseStartCallback,
+    if(SSL_SetCanFalseStartCallback(BACKEND->handle, CanFalseStartCallback,
         conn) != SECSuccess)
       goto error;
   }
@@ -2004,24 +2015,24 @@ static CURLcode nss_setup_connect(struct connectdata 
*conn, int sockindex)
     memcpy(&protocols[cur], ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH);
     cur += ALPN_HTTP_1_1_LENGTH;
 
-    if(SSL_SetNextProtoNego(connssl->handle, protocols, cur) != SECSuccess)
+    if(SSL_SetNextProtoNego(BACKEND->handle, protocols, cur) != SECSuccess)
       goto error;
   }
 #endif
 
 
   /* Force handshake on next I/O */
-  if(SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE)
+  if(SSL_ResetHandshake(BACKEND->handle, /* asServer */ PR_FALSE)
       != SECSuccess)
     goto error;
 
   /* propagate hostname to the TLS layer */
-  if(SSL_SetURL(connssl->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name :
+  if(SSL_SetURL(BACKEND->handle, SSL_IS_PROXY() ? conn->http_proxy.host.name :
                 conn->host.name) != SECSuccess)
     goto error;
 
   /* prevent NSS from re-using the session for a different hostname */
-  if(SSL_SetSockPeerID(connssl->handle, SSL_IS_PROXY() ?
+  if(SSL_SetSockPeerID(BACKEND->handle, SSL_IS_PROXY() ?
                        conn->http_proxy.host.name : conn->host.name)
      != SECSuccess)
     goto error;
@@ -2058,7 +2069,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, 
int sockindex)
 
   /* Force the handshake now */
   timeout = PR_MillisecondsToInterval((PRUint32) time_left);
-  if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) {
+  if(SSL_ForceHandshakeWithTimeout(BACKEND->handle, timeout) != SECSuccess) {
     if(PR_GetError() == PR_WOULD_BLOCK_ERROR)
       /* blocking direction is updated by nss_update_connecting_state() */
       return CURLE_AGAIN;
@@ -2069,7 +2080,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, 
int sockindex)
     goto error;
   }
 
-  result = display_conn_info(conn, connssl->handle);
+  result = display_conn_info(conn, BACKEND->handle);
   if(result)
     goto error;
 
@@ -2078,7 +2089,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, 
int sockindex)
     char *nickname = dup_nickname(data, SSL_SET_OPTION(issuercert));
     if(nickname) {
       /* we support only nicknames in case of issuercert for now */
-      ret = check_issuer_cert(connssl->handle, nickname);
+      ret = check_issuer_cert(BACKEND->handle, nickname);
       free(nickname);
     }
 
@@ -2164,13 +2175,13 @@ static CURLcode nss_connect_common(struct connectdata 
*conn, int sockindex,
   return CURLE_OK;
 }
 
-CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
+static CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
 {
   return nss_connect_common(conn, sockindex, /* blocking */ NULL);
 }
 
-CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
-                                      int sockindex, bool *done)
+static CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
+                                             int sockindex, bool *done)
 {
   return nss_connect_common(conn, sockindex, done);
 }
@@ -2186,9 +2197,9 @@ static ssize_t nss_send(struct connectdata *conn,  /* 
connection data */
 
   /* The SelectClientCert() hook uses this for infof() and failf() but the
      handle stored in nss_setup_connect() could have already been freed. */
-  connssl->data = conn->data;
+  BACKEND->data = conn->data;
 
-  rc = PR_Send(connssl->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT);
+  rc = PR_Send(BACKEND->handle, mem, (int)len, 0, PR_INTERVAL_NO_WAIT);
   if(rc < 0) {
     PRInt32 err = PR_GetError();
     if(err == PR_WOULD_BLOCK_ERROR)
@@ -2223,9 +2234,9 @@ static ssize_t nss_recv(struct connectdata *conn,  /* 
connection data */
 
   /* The SelectClientCert() hook uses this for infof() and failf() but the
      handle stored in nss_setup_connect() could have already been freed. */
-  connssl->data = conn->data;
+  BACKEND->data = conn->data;
 
-  nread = PR_Recv(connssl->handle, buf, (int)buffersize, 0,
+  nread = PR_Recv(BACKEND->handle, buf, (int)buffersize, 0,
                   PR_INTERVAL_NO_WAIT);
   if(nread < 0) {
     /* failed SSL read */
@@ -2252,22 +2263,22 @@ static ssize_t nss_recv(struct connectdata *conn,  /* 
connection data */
   return nread;
 }
 
-size_t Curl_nss_version(char *buffer, size_t size)
+static size_t Curl_nss_version(char *buffer, size_t size)
 {
   return snprintf(buffer, size, "NSS/%s", NSS_VERSION);
 }
 
 /* data might be NULL */
-int Curl_nss_seed(struct Curl_easy *data)
+static int Curl_nss_seed(struct Curl_easy *data)
 {
   /* make sure that NSS is initialized */
   return !!Curl_nss_force_init(data);
 }
 
 /* data might be NULL */
-CURLcode Curl_nss_random(struct Curl_easy *data,
-                         unsigned char *entropy,
-                         size_t length)
+static CURLcode Curl_nss_random(struct Curl_easy *data,
+                                unsigned char *entropy,
+                                size_t length)
 {
   Curl_nss_seed(data);  /* Initiate the seed if not already done */
 
@@ -2278,10 +2289,10 @@ CURLcode Curl_nss_random(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-void Curl_nss_md5sum(unsigned char *tmp, /* input */
-                     size_t tmplen,
-                     unsigned char *md5sum, /* output */
-                     size_t md5len)
+static CURLcode Curl_nss_md5sum(unsigned char *tmp, /* input */
+                                size_t tmplen,
+                                unsigned char *md5sum, /* output */
+                                size_t md5len)
 {
   PK11Context *MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
   unsigned int MD5out;
@@ -2289,12 +2300,14 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
   PK11_DigestOp(MD5pw, tmp, curlx_uztoui(tmplen));
   PK11_DigestFinal(MD5pw, md5sum, &MD5out, curlx_uztoui(md5len));
   PK11_DestroyContext(MD5pw, PR_TRUE);
+
+  return CURLE_OK;
 }
 
-void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
-                     size_t tmplen,
-                     unsigned char *sha256sum, /* output */
-                     size_t sha256len)
+static void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
+                               size_t tmplen,
+                               unsigned char *sha256sum, /* output */
+                               size_t sha256len)
 {
   PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256);
   unsigned int SHA256out;
@@ -2304,7 +2317,7 @@ void Curl_nss_sha256sum(const unsigned char *tmp, /* 
input */
   PK11_DestroyContext(SHA256pw, PR_TRUE);
 }
 
-bool Curl_nss_cert_status_request(void)
+static bool Curl_nss_cert_status_request(void)
 {
 #ifdef SSL_ENABLE_OCSP_STAPLING
   return TRUE;
@@ -2313,7 +2326,7 @@ bool Curl_nss_cert_status_request(void)
 #endif
 }
 
-bool Curl_nss_false_start(void)
+static bool Curl_nss_false_start(void)
 {
 #if NSSVERNUM >= 0x030f04 /* 3.15.4 */
   return TRUE;
@@ -2322,4 +2335,46 @@ bool Curl_nss_false_start(void)
 #endif
 }
 
+static void *Curl_nss_get_internals(struct ssl_connect_data *connssl,
+                                    CURLINFO info UNUSED_PARAM)
+{
+  (void)info;
+  return BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_nss = {
+  { CURLSSLBACKEND_NSS, "nss" }, /* info */
+
+  1, /* have_ca_path */
+  1, /* have_certinfo */
+  1, /* have_pinnedpubkey */
+  0, /* have_ssl_ctx */
+  1, /* support_https_proxy */
+
+  sizeof(struct ssl_backend_data),
+
+  Curl_nss_init,                /* init */
+  Curl_nss_cleanup,             /* cleanup */
+  Curl_nss_version,             /* version */
+  Curl_nss_check_cxn,           /* check_cxn */
+  /* NSS has no shutdown function provided and thus always fail */
+  Curl_none_shutdown,           /* shutdown */
+  Curl_none_data_pending,       /* data_pending */
+  Curl_nss_random,              /* random */
+  Curl_nss_cert_status_request, /* cert_status_request */
+  Curl_nss_connect,             /* connect */
+  Curl_nss_connect_nonblocking, /* connect_nonblocking */
+  Curl_nss_get_internals,       /* get_internals */
+  Curl_nss_close,               /* close */
+  Curl_none_close_all,          /* close_all */
+  /* NSS has its own session ID cache */
+  Curl_none_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_nss_false_start,         /* false_start */
+  Curl_nss_md5sum,              /* md5sum */
+  Curl_nss_sha256sum            /* sha256sum */
+};
+
 #endif /* USE_NSS */
diff --git a/lib/vtls/nssg.h b/lib/vtls/nssg.h
index 8c46929ff..41e51b021 100644
--- a/lib/vtls/nssg.h
+++ b/lib/vtls/nssg.h
@@ -30,79 +30,10 @@
 
 #include "urldata.h"
 
-CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex);
-CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn,
-                                      int sockindex,
-                                      bool *done);
-/* close a SSL connection */
-void Curl_nss_close(struct connectdata *conn, int sockindex);
-
-int Curl_nss_init(void);
-void Curl_nss_cleanup(void);
-
-size_t Curl_nss_version(char *buffer, size_t size);
-int Curl_nss_check_cxn(struct connectdata *cxn);
-int Curl_nss_seed(struct Curl_easy *data);
-
 /* initialize NSS library if not already */
 CURLcode Curl_nss_force_init(struct Curl_easy *data);
 
-CURLcode Curl_nss_random(struct Curl_easy *data,
-                         unsigned char *entropy,
-                         size_t length);
-
-void Curl_nss_md5sum(unsigned char *tmp, /* input */
-                     size_t tmplen,
-                     unsigned char *md5sum, /* output */
-                     size_t md5len);
-
-void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
-                     size_t tmplen,
-                     unsigned char *sha256sum, /* output */
-                     size_t sha256len);
-
-bool Curl_nss_cert_status_request(void);
-
-bool Curl_nss_false_start(void);
-
-/* Support HTTPS-proxy */
-#define HTTPS_PROXY_SUPPORT 1
-
-/* Set the API backend definition to NSS */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_NSS
-
-/* this backend supports the CAPATH option */
-#define have_curlssl_ca_path 1
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* this backends supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-
-/* API setup for NSS */
-#define curlssl_init Curl_nss_init
-#define curlssl_cleanup Curl_nss_cleanup
-#define curlssl_connect Curl_nss_connect
-#define curlssl_connect_nonblocking Curl_nss_connect_nonblocking
-
-/* NSS has its own session ID cache */
-#define curlssl_session_free(x) Curl_nop_stmt
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_nss_close
-/* NSS has no shutdown function provided and thus always fail */
-#define curlssl_shutdown(x,y) ((void)x, (void)y, 1)
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_nss_version
-#define curlssl_check_cxn(x) Curl_nss_check_cxn(x)
-#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
-#define curlssl_random(x,y,z) Curl_nss_random(x,y,z)
-#define curlssl_md5sum(a,b,c,d) Curl_nss_md5sum(a,b,c,d)
-#define curlssl_sha256sum(a,b,c,d) Curl_nss_sha256sum(a,b,c,d)
-#define curlssl_cert_status_request() Curl_nss_cert_status_request()
-#define curlssl_false_start() Curl_nss_false_start()
+extern const struct Curl_ssl Curl_ssl_nss;
 
 #endif /* USE_NSS */
 #endif /* HEADER_CURL_NSSG_H */
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 8c1d5a8e5..4253160aa 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -51,8 +51,10 @@
 #include "strcase.h"
 #include "hostcheck.h"
 #include "curl_printf.h"
-
 #include <openssl/ssl.h>
+#ifdef HAVE_OPENSSL_ENGINE_H
+#include <openssl/engine.h>
+#endif
 #include <openssl/rand.h>
 #include <openssl/x509v3.h>
 #ifndef OPENSSL_NO_DSA
@@ -64,6 +66,8 @@
 #include <openssl/conf.h>
 #include <openssl/bn.h>
 #include <openssl/rsa.h>
+#include <openssl/bio.h>
+#include <openssl/buffer.h>
 
 #ifdef HAVE_OPENSSL_PKCS12_H
 #include <openssl/pkcs12.h>
@@ -144,6 +148,20 @@ static unsigned long OpenSSL_version_num(void)
 #define OPENSSL_load_builtin_modules(x)
 #endif
 
+/*
+ * Whether SSL_CTX_set_keylog_callback is available.
+ * OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287
+ * BoringSSL: supported since d28f59c27bac (committed 2015-11-19), the
+ *            BORINGSSL_201512 macro from 2016-01-21 should be close enough.
+ * LibreSSL: unsupported in at least 2.5.1 (explicitly check for it since it
+ *           lies and pretends to be OpenSSL 2.0.0).
+ */
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \
+     !defined(LIBRESSL_VERSION_NUMBER)) || \
+    defined(BORINGSSL_201512)
+#define HAVE_KEYLOG_CALLBACK
+#endif
+
 #if defined(LIBRESSL_VERSION_NUMBER)
 #define OSSL_PACKAGE "LibreSSL"
 #elif defined(OPENSSL_IS_BORINGSSL)
@@ -152,6 +170,38 @@ static unsigned long OpenSSL_version_num(void)
 #define OSSL_PACKAGE "OpenSSL"
 #endif
 
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+/* up2date versions of OpenSSL maintain the default reasonably secure without
+ * breaking compatibility, so it is better not to override the default by curl
+ */
+#define DEFAULT_CIPHER_SELECTION NULL
+#else
+/* ... but it is not the case with old versions of OpenSSL */
+#define DEFAULT_CIPHER_SELECTION \
+  "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH"
+#endif
+
+#ifdef ENABLE_SSLKEYLOGFILE
+typedef struct ssl_tap_state {
+  int master_key_length;
+  unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
+  unsigned char client_random[SSL3_RANDOM_SIZE];
+} ssl_tap_state_t;
+#endif /* ENABLE_SSLKEYLOGFILE */
+
+struct ssl_backend_data {
+  /* these ones requires specific SSL-types */
+  SSL_CTX* ctx;
+  SSL*     handle;
+  X509*    server_cert;
+#ifdef ENABLE_SSLKEYLOGFILE
+  /* tap_state holds the last seen master key if we're logging them */
+  ssl_tap_state_t tap_state;
+#endif
+};
+
+#define BACKEND connssl->backend
+
 /*
  * Number of bytes to read from the random number seed file. This must be
  * a finite value (because some entropy "files" like /dev/urandom have
@@ -160,6 +210,112 @@ static unsigned long OpenSSL_version_num(void)
  */
 #define RAND_LOAD_LENGTH 1024
 
+#ifdef ENABLE_SSLKEYLOGFILE
+/* The fp for the open SSLKEYLOGFILE, or NULL if not open */
+static FILE *keylog_file_fp;
+
+#ifdef HAVE_KEYLOG_CALLBACK
+static void ossl_keylog_callback(const SSL *ssl, const char *line)
+{
+  (void)ssl;
+
+  /* Using fputs here instead of fprintf since libcurl's fprintf replacement
+     may not be thread-safe. */
+  if(keylog_file_fp && line && *line) {
+    char stackbuf[256];
+    char *buf;
+    size_t linelen = strlen(line);
+
+    if(linelen <= sizeof(stackbuf) - 2)
+      buf = stackbuf;
+    else {
+      buf = malloc(linelen + 2);
+      if(!buf)
+        return;
+    }
+    strncpy(buf, line, linelen);
+    buf[linelen] = '\n';
+    buf[linelen + 1] = '\0';
+
+    fputs(buf, keylog_file_fp);
+    if(buf != stackbuf)
+      free(buf);
+  }
+}
+#else
+#define KEYLOG_PREFIX      "CLIENT_RANDOM "
+#define KEYLOG_PREFIX_LEN  (sizeof(KEYLOG_PREFIX) - 1)
+/*
+ * tap_ssl_key is called by libcurl to make the CLIENT_RANDOMs if the OpenSSL
+ * being used doesn't have native support for doing that.
+ */
+static void tap_ssl_key(const SSL *ssl, ssl_tap_state_t *state)
+{
+  const char *hex = "0123456789ABCDEF";
+  int pos, i;
+  char line[KEYLOG_PREFIX_LEN + 2 * SSL3_RANDOM_SIZE + 1 +
+            2 * SSL_MAX_MASTER_KEY_LENGTH + 1 + 1];
+  const SSL_SESSION *session = SSL_get_session(ssl);
+  unsigned char client_random[SSL3_RANDOM_SIZE];
+  unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
+  int master_key_length = 0;
+
+  if(!session || !keylog_file_fp)
+    return;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+  /* ssl->s3 is not checked in openssl 1.1.0-pre6, but let's assume that
+   * we have a valid SSL context if we have a non-NULL session. */
+  SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE);
+  master_key_length =
+    SSL_SESSION_get_master_key(session, master_key, SSL_MAX_MASTER_KEY_LENGTH);
+#else
+  if(ssl->s3 && session->master_key_length > 0) {
+    master_key_length = session->master_key_length;
+    memcpy(master_key, session->master_key, session->master_key_length);
+    memcpy(client_random, ssl->s3->client_random, SSL3_RANDOM_SIZE);
+  }
+#endif
+
+  if(master_key_length <= 0)
+    return;
+
+  /* Skip writing keys if there is no key or it did not change. */
+  if(state->master_key_length == master_key_length &&
+     !memcmp(state->master_key, master_key, master_key_length) &&
+     !memcmp(state->client_random, client_random, SSL3_RANDOM_SIZE)) {
+    return;
+  }
+
+  state->master_key_length = master_key_length;
+  memcpy(state->master_key, master_key, master_key_length);
+  memcpy(state->client_random, client_random, SSL3_RANDOM_SIZE);
+
+  memcpy(line, KEYLOG_PREFIX, KEYLOG_PREFIX_LEN);
+  pos = KEYLOG_PREFIX_LEN;
+
+  /* Client Random for SSLv3/TLS */
+  for(i = 0; i < SSL3_RANDOM_SIZE; i++) {
+    line[pos++] = hex[client_random[i] >> 4];
+    line[pos++] = hex[client_random[i] & 0xF];
+  }
+  line[pos++] = ' ';
+
+  /* Master Secret (size is at most SSL_MAX_MASTER_KEY_LENGTH) */
+  for(i = 0; i < master_key_length; i++) {
+    line[pos++] = hex[master_key[i] >> 4];
+    line[pos++] = hex[master_key[i] & 0xF];
+  }
+  line[pos++] = '\n';
+  line[pos] = '\0';
+
+  /* Using fputs here instead of fprintf since libcurl's fprintf replacement
+     may not be thread-safe. */
+  fputs(line, keylog_file_fp);
+}
+#endif /* !HAVE_KEYLOG_CALLBACK */
+#endif /* ENABLE_SSLKEYLOGFILE */
+
 static const char *SSL_ERROR_to_str(int err)
 {
   switch(err) {
@@ -214,7 +370,7 @@ static int passwd_callback(char *buf, int num, int 
encrypting,
   if(!encrypting) {
     int klen = curlx_uztosi(strlen((char *)global_passwd));
     if(num > klen) {
-      memcpy(buf, global_passwd, klen+1);
+      memcpy(buf, global_passwd, klen + 1);
       return klen;
     }
   }
@@ -305,7 +461,7 @@ static CURLcode Curl_ossl_seed(struct Curl_easy *data)
   } while(!rand_enough());
 
   /* generates a default path for the random seed file */
-  fname[0]=0; /* blank it first */
+  fname[0] = 0; /* blank it first */
   RAND_file_name(fname, sizeof(fname));
   if(fname[0]) {
     /* we got a file name to try */
@@ -393,6 +549,7 @@ int cert_stuff(struct connectdata *conn,
 {
   struct Curl_easy *data = conn->data;
   char error_buffer[256];
+  bool check_privkey = TRUE;
 
   int file_type = do_file_type(cert_type);
 
@@ -601,7 +758,7 @@ int cert_stuff(struct connectdata *conn,
         break;
       if(!key_file)
         /* cert & key can only be in PEM case in the same file */
-        key_file=cert_file;
+        key_file = cert_file;
       /* FALLTHROUGH */
     case SSL_FILETYPE_ASN1:
       if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) {
@@ -664,13 +821,13 @@ int cert_stuff(struct connectdata *conn,
       return 0;
     }
 
-    ssl=SSL_new(ctx);
+    ssl = SSL_new(ctx);
     if(!ssl) {
       failf(data, "unable to create an SSL structure");
       return 0;
     }
 
-    x509=SSL_get_certificate(ssl);
+    x509 = SSL_get_certificate(ssl);
 
     /* This version was provided by Evan Jordan and is supposed to not
        leak memory as the previous version: */
@@ -680,17 +837,32 @@ int cert_stuff(struct connectdata *conn,
       EVP_PKEY_free(pktmp);
     }
 
+#ifndef OPENSSL_NO_RSA
+    {
+      /* If RSA is used, don't check the private key if its flags indicate
+       * it doesn't support it. */
+      EVP_PKEY *priv_key = SSL_get_privatekey(ssl);
+      if(EVP_PKEY_id(priv_key) == EVP_PKEY_RSA) {
+        RSA *rsa = EVP_PKEY_get1_RSA(priv_key);
+        if(RSA_flags(rsa) & RSA_METHOD_FLAG_NO_CHECK)
+          check_privkey = FALSE;
+        RSA_free(rsa); /* Decrement reference count */
+      }
+    }
+#endif
+
     SSL_free(ssl);
 
     /* If we are using DSA, we can copy the parameters from
      * the private key */
 
-
-    /* Now we know that a key and cert have been set against
-     * the SSL context */
-    if(!SSL_CTX_check_private_key(ctx)) {
-      failf(data, "Private key does not match the certificate public key");
-      return 0;
+    if(check_privkey == TRUE) {
+      /* Now we know that a key and cert have been set against
+       * the SSL context */
+      if(!SSL_CTX_check_private_key(ctx)) {
+        failf(data, "Private key does not match the certificate public key");
+        return 0;
+      }
     }
   }
   return 1;
@@ -718,7 +890,7 @@ static int x509_name_oneline(X509_NAME *a, char *buf, 
size_t size)
     size--; /* don't overwrite the buffer end */
 
   memcpy(buf, biomem->data, size);
-  buf[size]=0;
+  buf[size] = 0;
 
   BIO_free(bio_out);
 
@@ -732,8 +904,12 @@ static int x509_name_oneline(X509_NAME *a, char *buf, 
size_t size)
  * @retval 0 error initializing SSL
  * @retval 1 SSL initialized successfully
  */
-int Curl_ossl_init(void)
+static int Curl_ossl_init(void)
 {
+#ifdef ENABLE_SSLKEYLOGFILE
+  const char *keylog_file_name;
+#endif
+
   OPENSSL_load_builtin_modules();
 
 #ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES
@@ -770,11 +946,24 @@ int Curl_ossl_init(void)
   OpenSSL_add_all_algorithms();
 #endif
 
+#ifdef ENABLE_SSLKEYLOGFILE
+  keylog_file_name = curl_getenv("SSLKEYLOGFILE");
+  if(keylog_file_name && !keylog_file_fp) {
+    keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT);
+    if(keylog_file_fp) {
+      if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096)) {
+        fclose(keylog_file_fp);
+        keylog_file_fp = NULL;
+      }
+    }
+  }
+#endif
+
   return 1;
 }
 
 /* Global cleanup */
-void Curl_ossl_cleanup(void)
+static void Curl_ossl_cleanup(void)
 {
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \
     !defined(LIBRESSL_VERSION_NUMBER)
@@ -806,6 +995,13 @@ void Curl_ossl_cleanup(void)
   SSL_COMP_free_compression_methods();
 #endif
 #endif
+
+#ifdef ENABLE_SSLKEYLOGFILE
+  if(keylog_file_fp) {
+    fclose(keylog_file_fp);
+    keylog_file_fp = NULL;
+  }
+#endif
 }
 
 /*
@@ -816,7 +1012,7 @@ void Curl_ossl_cleanup(void)
  *     0 means the connection has been closed
  *    -1 means the connection status is unknown
  */
-int Curl_ossl_check_cxn(struct connectdata *conn)
+static int Curl_ossl_check_cxn(struct connectdata *conn)
 {
   /* SSL_peek takes data out of the raw recv buffer without peeking so we use
      recv MSG_PEEK instead. Bug #795 */
@@ -862,7 +1058,8 @@ int Curl_ossl_check_cxn(struct connectdata *conn)
 
 /* Selects an OpenSSL crypto engine
  */
-CURLcode Curl_ossl_set_engine(struct Curl_easy *data, const char *engine)
+static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
+                                     const char *engine)
 {
 #if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
   ENGINE *e;
@@ -907,7 +1104,7 @@ CURLcode Curl_ossl_set_engine(struct Curl_easy *data, 
const char *engine)
 
 /* Sets engine as default for all SSL operations
  */
-CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
+static CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data)
 {
 #ifdef HAVE_OPENSSL_ENGINE_H
   if(data->state.engine) {
@@ -929,7 +1126,7 @@ CURLcode Curl_ossl_set_engine_default(struct Curl_easy 
*data)
 
 /* Return list of OpenSSL crypto engine names.
  */
-struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
+static struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data)
 {
   struct curl_slist *list = NULL;
 #if defined(USE_OPENSSL) && defined(HAVE_OPENSSL_ENGINE_H)
@@ -952,23 +1149,23 @@ struct curl_slist *Curl_ossl_engines_list(struct 
Curl_easy *data)
 
 static void ossl_close(struct ssl_connect_data *connssl)
 {
-  if(connssl->handle) {
-    (void)SSL_shutdown(connssl->handle);
-    SSL_set_connect_state(connssl->handle);
+  if(BACKEND->handle) {
+    (void)SSL_shutdown(BACKEND->handle);
+    SSL_set_connect_state(BACKEND->handle);
 
-    SSL_free(connssl->handle);
-    connssl->handle = NULL;
+    SSL_free(BACKEND->handle);
+    BACKEND->handle = NULL;
   }
-  if(connssl->ctx) {
-    SSL_CTX_free(connssl->ctx);
-    connssl->ctx = NULL;
+  if(BACKEND->ctx) {
+    SSL_CTX_free(BACKEND->ctx);
+    BACKEND->ctx = NULL;
   }
 }
 
 /*
  * This function is called when an SSL connection is closed.
  */
-void Curl_ossl_close(struct connectdata *conn, int sockindex)
+static void Curl_ossl_close(struct connectdata *conn, int sockindex)
 {
   ossl_close(&conn->ssl[sockindex]);
   ossl_close(&conn->proxy_ssl[sockindex]);
@@ -978,7 +1175,7 @@ void Curl_ossl_close(struct connectdata *conn, int 
sockindex)
  * This function is called to shut down the SSL layer but keep the
  * socket open (CCC - Clear Command Channel)
  */
-int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
+static int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
 {
   int retval = 0;
   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@@ -997,9 +1194,9 @@ int Curl_ossl_shutdown(struct connectdata *conn, int 
sockindex)
      we do not send one. Let's hope other servers do the same... */
 
   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
-      (void)SSL_shutdown(connssl->handle);
+      (void)SSL_shutdown(BACKEND->handle);
 
-  if(connssl->handle) {
+  if(BACKEND->handle) {
     buffsize = (int)sizeof(buf);
     while(!done) {
       int what = SOCKET_READABLE(conn->sock[sockindex],
@@ -1009,9 +1206,8 @@ int Curl_ossl_shutdown(struct connectdata *conn, int 
sockindex)
 
         /* Something to read, let's do it and hope that it is the close
            notify alert from the server */
-        nread = (ssize_t)SSL_read(conn->ssl[sockindex].handle, buf,
-                                  buffsize);
-        err = SSL_get_error(conn->ssl[sockindex].handle, (int)nread);
+        nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize);
+        err = SSL_get_error(BACKEND->handle, (int)nread);
 
         switch(err) {
         case SSL_ERROR_NONE: /* this is not an error */
@@ -1056,7 +1252,7 @@ int Curl_ossl_shutdown(struct connectdata *conn, int 
sockindex)
 
     if(data->set.verbose) {
 #ifdef HAVE_SSL_GET_SHUTDOWN
-      switch(SSL_get_shutdown(connssl->handle)) {
+      switch(SSL_get_shutdown(BACKEND->handle)) {
       case SSL_SENT_SHUTDOWN:
         infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN\n");
         break;
@@ -1071,13 +1267,13 @@ int Curl_ossl_shutdown(struct connectdata *conn, int 
sockindex)
 #endif
     }
 
-    SSL_free(connssl->handle);
-    connssl->handle = NULL;
+    SSL_free(BACKEND->handle);
+    BACKEND->handle = NULL;
   }
   return retval;
 }
 
-void Curl_ossl_session_free(void *ptr)
+static void Curl_ossl_session_free(void *ptr)
 {
   /* free the ID */
   SSL_SESSION_free(ptr);
@@ -1087,7 +1283,7 @@ void Curl_ossl_session_free(void *ptr)
  * This function is called when the 'data' struct is going away. Close
  * down everything and free all resources!
  */
-void Curl_ossl_close_all(struct Curl_easy *data)
+static void Curl_ossl_close_all(struct Curl_easy *data)
 {
 #ifdef HAVE_OPENSSL_ENGINE_H
   if(data->state.engine) {
@@ -1179,7 +1375,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 
*server_cert)
     numalts = sk_GENERAL_NAME_num(altnames);
 
     /* loop through all alternatives - until a dnsmatch */
-    for(i=0; (i < numalts) && !dnsmatched; i++) {
+    for(i = 0; (i < numalts) && !dnsmatched; i++) {
       /* get a handle to alternative name number i */
       const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
 
@@ -1248,7 +1444,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 
*server_cert)
   else {
     /* we have to look to the last occurrence of a commonName in the
        distinguished one to get the most significant one. */
-    int j, i=-1;
+    int j, i = -1;
 
     /* The following is done because of a bug in 0.9.6b */
 
@@ -1257,14 +1453,14 @@ static CURLcode verifyhost(struct connectdata *conn, 
X509 *server_cert)
 
     X509_NAME *name = X509_get_subject_name(server_cert);
     if(name)
-      while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i))>=0)
-        i=j;
+      while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0)
+        i = j;
 
     /* we have the name entry and we will now convert this to a string
        that we can use for comparison. Doing this we support BMPstring,
        UTF8 etc. */
 
-    if(i>=0) {
+    if(i >= 0) {
       ASN1_STRING *tmp =
         X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
 
@@ -1277,7 +1473,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 
*server_cert)
         if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
           j = ASN1_STRING_length(tmp);
           if(j >= 0) {
-            peer_CN = OPENSSL_malloc(j+1);
+            peer_CN = OPENSSL_malloc(j + 1);
             if(peer_CN) {
               memcpy(peer_CN, ASN1_STRING_get0_data(tmp), j);
               peer_CN[j] = '\0';
@@ -1300,7 +1496,8 @@ static CURLcode verifyhost(struct connectdata *conn, X509 
*server_cert)
        peer_CN = NULL;
     else {
       /* convert peer_CN from UTF8 */
-      CURLcode rc = Curl_convert_from_utf8(data, peer_CN, strlen(peer_CN));
+      CURLcode rc = Curl_convert_from_utf8(data, (char *)peer_CN,
+                                           strlen((char *)peer_CN));
       /* Curl_convert_from_utf8 calls failf if unsuccessful */
       if(rc) {
         OPENSSL_free(peer_CN);
@@ -1346,7 +1543,7 @@ static CURLcode verifystatus(struct connectdata *conn,
   X509_STORE     *st = NULL;
   STACK_OF(X509) *ch = NULL;
 
-  long len = SSL_get_tlsext_status_ocsp_resp(connssl->handle, &p);
+  long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &p);
 
   if(!p) {
     failf(data, "No OCSP response received");
@@ -1376,8 +1573,8 @@ static CURLcode verifystatus(struct connectdata *conn,
     goto end;
   }
 
-  ch = SSL_get_peer_cert_chain(connssl->handle);
-  st = SSL_CTX_get_cert_store(connssl->ctx);
+  ch = SSL_get_peer_cert_chain(BACKEND->handle);
+  st = SSL_CTX_get_cert_store(BACKEND->ctx);
 
 #if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \
      (defined(LIBRESSL_VERSION_NUMBER) &&                               \
@@ -1768,7 +1965,7 @@ set_ssl_version_min_max(long *ctx_options, struct 
connectdata *conn,
 #ifdef TLS1_3_VERSION
     {
       struct ssl_connect_data *connssl = &conn->ssl[sockindex];
-      SSL_CTX_set_max_proto_version(connssl->ctx, TLS1_3_VERSION);
+      SSL_CTX_set_max_proto_version(BACKEND->ctx, TLS1_3_VERSION);
       *ctx_options |= SSL_OP_NO_TLSv1_2;
     }
 #else
@@ -1919,25 +2116,25 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  if(connssl->ctx)
-    SSL_CTX_free(connssl->ctx);
-  connssl->ctx = SSL_CTX_new(req_method);
+  if(BACKEND->ctx)
+    SSL_CTX_free(BACKEND->ctx);
+  BACKEND->ctx = SSL_CTX_new(req_method);
 
-  if(!connssl->ctx) {
+  if(!BACKEND->ctx) {
     failf(data, "SSL: couldn't create a context: %s",
           ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer)));
     return CURLE_OUT_OF_MEMORY;
   }
 
 #ifdef SSL_MODE_RELEASE_BUFFERS
-  SSL_CTX_set_mode(connssl->ctx, SSL_MODE_RELEASE_BUFFERS);
+  SSL_CTX_set_mode(BACKEND->ctx, SSL_MODE_RELEASE_BUFFERS);
 #endif
 
 #ifdef SSL_CTRL_SET_MSG_CALLBACK
   if(data->set.fdebug && data->set.verbose) {
     /* the SSL trace callback is only used for verbose logging */
-    SSL_CTX_set_msg_callback(connssl->ctx, ssl_tls_trace);
-    SSL_CTX_set_msg_callback_arg(connssl->ctx, conn);
+    SSL_CTX_set_msg_callback(BACKEND->ctx, ssl_tls_trace);
+    SSL_CTX_set_msg_callback_arg(BACKEND->ctx, conn);
   }
 #endif
 
@@ -2054,11 +2251,11 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  SSL_CTX_set_options(connssl->ctx, ctx_options);
+  SSL_CTX_set_options(BACKEND->ctx, ctx_options);
 
 #ifdef HAS_NPN
   if(conn->bits.tls_enable_npn)
-    SSL_CTX_set_next_proto_select_cb(connssl->ctx, select_next_proto_cb, conn);
+    SSL_CTX_set_next_proto_select_cb(BACKEND->ctx, select_next_proto_cb, conn);
 #endif
 
 #ifdef HAS_ALPN
@@ -2086,12 +2283,12 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
     /* expects length prefixed preference ordered list of protocols in wire
      * format
      */
-    SSL_CTX_set_alpn_protos(connssl->ctx, protocols, cur);
+    SSL_CTX_set_alpn_protos(BACKEND->ctx, protocols, cur);
   }
 #endif
 
   if(ssl_cert || ssl_cert_type) {
-    if(!cert_stuff(conn, connssl->ctx, ssl_cert, ssl_cert_type,
+    if(!cert_stuff(conn, BACKEND->ctx, ssl_cert, ssl_cert_type,
                    SSL_SET_OPTION(key), SSL_SET_OPTION(key_type),
                    SSL_SET_OPTION(key_passwd))) {
       /* failf() is already done in cert_stuff() */
@@ -2102,11 +2299,13 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
   ciphers = SSL_CONN_CONFIG(cipher_list);
   if(!ciphers)
     ciphers = (char *)DEFAULT_CIPHER_SELECTION;
-  if(!SSL_CTX_set_cipher_list(connssl->ctx, ciphers)) {
-    failf(data, "failed setting cipher list: %s", ciphers);
-    return CURLE_SSL_CIPHER;
+  if(ciphers) {
+    if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) {
+      failf(data, "failed setting cipher list: %s", ciphers);
+      return CURLE_SSL_CIPHER;
+    }
+    infof(data, "Cipher selection: %s\n", ciphers);
   }
-  infof(data, "Cipher selection: %s\n", ciphers);
 
 #ifdef USE_TLS_SRP
   if(ssl_authtype == CURL_TLSAUTH_SRP) {
@@ -2114,18 +2313,18 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
 
     infof(data, "Using TLS-SRP username: %s\n", ssl_username);
 
-    if(!SSL_CTX_set_srp_username(connssl->ctx, ssl_username)) {
+    if(!SSL_CTX_set_srp_username(BACKEND->ctx, ssl_username)) {
       failf(data, "Unable to set SRP user name");
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
-    if(!SSL_CTX_set_srp_password(connssl->ctx, SSL_SET_OPTION(password))) {
+    if(!SSL_CTX_set_srp_password(BACKEND->ctx, SSL_SET_OPTION(password))) {
       failf(data, "failed setting SRP password");
       return CURLE_BAD_FUNCTION_ARGUMENT;
     }
     if(!SSL_CONN_CONFIG(cipher_list)) {
       infof(data, "Setting cipher list SRP\n");
 
-      if(!SSL_CTX_set_cipher_list(connssl->ctx, "SRP")) {
+      if(!SSL_CTX_set_cipher_list(BACKEND->ctx, "SRP")) {
         failf(data, "failed setting SRP cipher list");
         return CURLE_SSL_CIPHER;
       }
@@ -2136,7 +2335,7 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
   if(ssl_cafile || ssl_capath) {
     /* tell SSL where to find CA certificates that are used to verify
        the servers certificate. */
-    if(!SSL_CTX_load_verify_locations(connssl->ctx, ssl_cafile, ssl_capath)) {
+    if(!SSL_CTX_load_verify_locations(BACKEND->ctx, ssl_cafile, ssl_capath)) {
       if(verifypeer) {
         /* Fail if we insist on successfully verifying the server. */
         failf(data, "error setting certificate verify locations:\n"
@@ -2164,14 +2363,14 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
   else if(verifypeer) {
     /* verfying the peer without any CA certificates won't
        work so use openssl's built in default as fallback */
-    SSL_CTX_set_default_verify_paths(connssl->ctx);
+    SSL_CTX_set_default_verify_paths(BACKEND->ctx);
   }
 #endif
 
   if(ssl_crlfile) {
     /* tell SSL where to find CRL file that is used to check certificate
      * revocation */
-    lookup=X509_STORE_add_lookup(SSL_CTX_get_cert_store(connssl->ctx),
+    lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(BACKEND->ctx),
                                  X509_LOOKUP_file());
     if(!lookup ||
        (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) {
@@ -2180,7 +2379,7 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
     }
     /* Everything is fine. */
     infof(data, "successfully load CRL file:\n");
-    X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
+    X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx),
                          X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
 
     infof(data, "  CRLfile: %s\n", ssl_crlfile);
@@ -2195,7 +2394,7 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
   */
 #if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS)
   if(verifypeer) {
-    X509_STORE_set_flags(SSL_CTX_get_cert_store(connssl->ctx),
+    X509_STORE_set_flags(SSL_CTX_get_cert_store(BACKEND->ctx),
                          X509_V_FLAG_TRUSTED_FIRST);
   }
 #endif
@@ -2204,12 +2403,19 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
    * fail to connect if the verification fails, or if it should continue
    * anyway. In the latter case the result of the verification is checked with
    * SSL_get_verify_result() below. */
-  SSL_CTX_set_verify(connssl->ctx,
+  SSL_CTX_set_verify(BACKEND->ctx,
                      verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL);
 
+  /* Enable logging of secrets to the file specified in env SSLKEYLOGFILE. */
+#if defined(ENABLE_SSLKEYLOGFILE) && defined(HAVE_KEYLOG_CALLBACK)
+  if(keylog_file) {
+    SSL_CTX_set_keylog_callback(connssl->ctx, ossl_keylog_callback);
+  }
+#endif
+
   /* give application a chance to interfere with SSL set up. */
   if(data->set.ssl.fsslctx) {
-    result = (*data->set.ssl.fsslctx)(data, connssl->ctx,
+    result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx,
                                       data->set.ssl.fsslctxp);
     if(result) {
       failf(data, "error signaled by ssl ctx callback");
@@ -2218,10 +2424,10 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
   }
 
   /* Lets make an SSL structure */
-  if(connssl->handle)
-    SSL_free(connssl->handle);
-  connssl->handle = SSL_new(connssl->ctx);
-  if(!connssl->handle) {
+  if(BACKEND->handle)
+    SSL_free(BACKEND->handle);
+  BACKEND->handle = SSL_new(BACKEND->ctx);
+  if(!BACKEND->handle) {
     failf(data, "SSL: couldn't create a context (handle)!");
     return CURLE_OUT_OF_MEMORY;
   }
@@ -2229,19 +2435,19 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
     !defined(OPENSSL_NO_OCSP)
   if(SSL_CONN_CONFIG(verifystatus))
-    SSL_set_tlsext_status_type(connssl->handle, TLSEXT_STATUSTYPE_ocsp);
+    SSL_set_tlsext_status_type(BACKEND->handle, TLSEXT_STATUSTYPE_ocsp);
 #endif
 
-  SSL_set_connect_state(connssl->handle);
+  SSL_set_connect_state(BACKEND->handle);
 
-  connssl->server_cert = 0x0;
+  BACKEND->server_cert = 0x0;
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
   if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
 #ifdef ENABLE_IPV6
      (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
 #endif
      sni &&
-     !SSL_set_tlsext_host_name(connssl->handle, hostname))
+     !SSL_set_tlsext_host_name(BACKEND->handle, hostname))
     infof(data, "WARNING: failed to configure server name indication (SNI) "
           "TLS extension\n");
 #endif
@@ -2253,7 +2459,7 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
     Curl_ssl_sessionid_lock(conn);
     if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
       /* we got a session id, use it! */
-      if(!SSL_set_session(connssl->handle, ssl_sessionid)) {
+      if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) {
         Curl_ssl_sessionid_unlock(conn);
         failf(data, "SSL: SSL_set_session failed: %s",
               ossl_strerror(ERR_get_error(), error_buffer,
@@ -2268,13 +2474,14 @@ static CURLcode ossl_connect_step1(struct connectdata 
*conn, int sockindex)
 
   if(conn->proxy_ssl[sockindex].use) {
     BIO *const bio = BIO_new(BIO_f_ssl());
+    SSL *handle = conn->proxy_ssl[sockindex].backend->handle;
     DEBUGASSERT(ssl_connection_complete == conn->proxy_ssl[sockindex].state);
-    DEBUGASSERT(conn->proxy_ssl[sockindex].handle != NULL);
+    DEBUGASSERT(handle != NULL);
     DEBUGASSERT(bio != NULL);
-    BIO_set_ssl(bio, conn->proxy_ssl[sockindex].handle, FALSE);
-    SSL_set_bio(connssl->handle, bio, bio);
+    BIO_set_ssl(bio, handle, FALSE);
+    SSL_set_bio(BACKEND->handle, bio, bio);
   }
-  else if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
+  else if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) {
     /* pass the raw socket into the SSL layers */
     failf(data, "SSL: SSL_set_fd failed: %s",
           ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)));
@@ -2299,13 +2506,18 @@ static CURLcode ossl_connect_step2(struct connectdata 
*conn, int sockindex)
 
   ERR_clear_error();
 
-  err = SSL_connect(connssl->handle);
+  err = SSL_connect(BACKEND->handle);
+  /* If keylogging is enabled but the keylog callback is not supported then log
+     secrets here, immediately after SSL_connect by using tap_ssl_key. */
+#if defined(ENABLE_SSLKEYLOGFILE) && !defined(HAVE_KEYLOG_CALLBACK)
+  tap_ssl_key(BACKEND->handle, &BACKEND->tap_state);
+#endif
 
   /* 1  is fine
      0  is "not successful but was shut down controlled"
      <0 is "handshake was not successful, because a fatal error occurred" */
   if(1 != err) {
-    int detail = SSL_get_error(connssl->handle, err);
+    int detail = SSL_get_error(BACKEND->handle, err);
 
     if(SSL_ERROR_WANT_READ == detail) {
       connssl->connecting_state = ssl_connect_2_reading;
@@ -2339,7 +2551,7 @@ static CURLcode ossl_connect_step2(struct connectdata 
*conn, int sockindex)
          (reason == SSL_R_CERTIFICATE_VERIFY_FAILED)) {
         result = CURLE_SSL_CACERT;
 
-        lerr = SSL_get_verify_result(connssl->handle);
+        lerr = SSL_get_verify_result(BACKEND->handle);
         if(lerr != X509_V_OK) {
           *certverifyresult = lerr;
           snprintf(error_buffer, sizeof(error_buffer),
@@ -2383,8 +2595,8 @@ static CURLcode ossl_connect_step2(struct connectdata 
*conn, int sockindex)
 
     /* Informational message */
     infof(data, "SSL connection using %s / %s\n",
-          get_ssl_version_txt(connssl->handle),
-          SSL_get_cipher(connssl->handle));
+          get_ssl_version_txt(BACKEND->handle),
+          SSL_get_cipher(BACKEND->handle));
 
 #ifdef HAS_ALPN
     /* Sets data and len to negotiated protocol, len is 0 if no protocol was
@@ -2393,7 +2605,7 @@ static CURLcode ossl_connect_step2(struct connectdata 
*conn, int sockindex)
     if(conn->bits.tls_enable_alpn) {
       const unsigned char *neg_protocol;
       unsigned int len;
-      SSL_get0_alpn_selected(connssl->handle, &neg_protocol, &len);
+      SSL_get0_alpn_selected(BACKEND->handle, &neg_protocol, &len);
       if(len != 0) {
         infof(data, "ALPN, server accepted to use %.*s\n", len, neg_protocol);
 
@@ -2438,7 +2650,7 @@ static int asn1_object_dump(ASN1_OBJECT *a, char *buf, 
size_t len)
 do {                              \
   long info_len = BIO_get_mem_data(mem, &ptr); \
   Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \
-  if(1!=BIO_reset(mem))                                          \
+  if(1 != BIO_reset(mem))                                        \
     break;                                                       \
 } WHILE_FALSE
 
@@ -2486,12 +2698,12 @@ static int X509V3_ext(struct Curl_easy *data,
     /* no extensions, bail out */
     return 1;
 
-  for(i=0; i < (int)sk_X509_EXTENSION_num(exts); i++) {
+  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 *ptr = buf;
     char namebuf[128];
     BIO *bio_out = BIO_new(BIO_s_mem());
 
@@ -2508,16 +2720,16 @@ static int X509V3_ext(struct Curl_easy *data,
     BIO_get_mem_ptr(bio_out, &biomem);
 
     for(j = 0; j < (size_t)biomem->length; j++) {
-      const char *sep="";
+      const char *sep = "";
       if(biomem->data[j] == '\n') {
-        sep=", ";
+        sep = ", ";
         j++; /* skip the newline */
       };
       while((j<(size_t)biomem->length) && (biomem->data[j] == ' '))
         j++;
       if(j<(size_t)biomem->length)
-        ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep,
-                      biomem->data[j]);
+        ptr += snprintf(ptr, sizeof(buf)-(ptr-buf), "%s%c", sep,
+                        biomem->data[j]);
     }
 
     Curl_ssl_push_certinfo(data, certnum, namebuf, buf);
@@ -2539,7 +2751,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
   int numcerts;
   BIO *mem;
 
-  sk = SSL_get_peer_cert_chain(connssl->handle);
+  sk = SSL_get_peer_cert_chain(BACKEND->handle);
   if(!sk) {
     return CURLE_OUT_OF_MEMORY;
   }
@@ -2556,7 +2768,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
   for(i = 0; i < numcerts; i++) {
     ASN1_INTEGER *num;
     X509 *x = sk_X509_value(sk, i);
-    EVP_PKEY *pubkey=NULL;
+    EVP_PKEY *pubkey = NULL;
     int j;
     char *ptr;
     const ASN1_BIT_STRING *psig = NULL;
@@ -2829,8 +3041,8 @@ static CURLcode servercert(struct connectdata *conn,
     /* we've been asked to gather certificate info! */
     (void)get_cert_chain(conn, connssl);
 
-  connssl->server_cert = SSL_get_peer_certificate(connssl->handle);
-  if(!connssl->server_cert) {
+  BACKEND->server_cert = SSL_get_peer_certificate(BACKEND->handle);
+  if(!BACKEND->server_cert) {
     BIO_free(mem);
     if(!strict)
       return CURLE_OK;
@@ -2841,16 +3053,16 @@ static CURLcode servercert(struct connectdata *conn,
 
   infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server");
 
-  rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
+  rc = x509_name_oneline(X509_get_subject_name(BACKEND->server_cert),
                          buffer, sizeof(buffer));
   infof(data, " subject: %s\n", rc?"[NONE]":buffer);
 
-  ASN1_TIME_print(mem, X509_get0_notBefore(connssl->server_cert));
+  ASN1_TIME_print(mem, X509_get0_notBefore(BACKEND->server_cert));
   len = BIO_get_mem_data(mem, (char **) &ptr);
   infof(data, " start date: %.*s\n", len, ptr);
   rc = BIO_reset(mem);
 
-  ASN1_TIME_print(mem, X509_get0_notAfter(connssl->server_cert));
+  ASN1_TIME_print(mem, X509_get0_notAfter(BACKEND->server_cert));
   len = BIO_get_mem_data(mem, (char **) &ptr);
   infof(data, " expire date: %.*s\n", len, ptr);
   rc = BIO_reset(mem);
@@ -2858,15 +3070,15 @@ static CURLcode servercert(struct connectdata *conn,
   BIO_free(mem);
 
   if(SSL_CONN_CONFIG(verifyhost)) {
-    result = verifyhost(conn, connssl->server_cert);
+    result = verifyhost(conn, BACKEND->server_cert);
     if(result) {
-      X509_free(connssl->server_cert);
-      connssl->server_cert = NULL;
+      X509_free(BACKEND->server_cert);
+      BACKEND->server_cert = NULL;
       return result;
     }
   }
 
-  rc = x509_name_oneline(X509_get_issuer_name(connssl->server_cert),
+  rc = x509_name_oneline(X509_get_issuer_name(BACKEND->server_cert),
                          buffer, sizeof(buffer));
   if(rc) {
     if(strict)
@@ -2886,8 +3098,8 @@ static CURLcode servercert(struct connectdata *conn,
         if(strict)
           failf(data, "SSL: Unable to open issuer cert (%s)",
                 SSL_SET_OPTION(issuercert));
-        X509_free(connssl->server_cert);
-        connssl->server_cert = NULL;
+        X509_free(BACKEND->server_cert);
+        BACKEND->server_cert = NULL;
         return CURLE_SSL_ISSUER_ERROR;
       }
 
@@ -2896,7 +3108,7 @@ static CURLcode servercert(struct connectdata *conn,
         if(strict)
           failf(data, "SSL: Unable to read issuer cert (%s)",
                 SSL_SET_OPTION(issuercert));
-        X509_free(connssl->server_cert);
+        X509_free(BACKEND->server_cert);
         X509_free(issuer);
         fclose(fp);
         return CURLE_SSL_ISSUER_ERROR;
@@ -2904,13 +3116,13 @@ static CURLcode servercert(struct connectdata *conn,
 
       fclose(fp);
 
-      if(X509_check_issued(issuer, connssl->server_cert) != X509_V_OK) {
+      if(X509_check_issued(issuer, BACKEND->server_cert) != X509_V_OK) {
         if(strict)
           failf(data, "SSL: Certificate issuer check failed (%s)",
                 SSL_SET_OPTION(issuercert));
-        X509_free(connssl->server_cert);
+        X509_free(BACKEND->server_cert);
         X509_free(issuer);
-        connssl->server_cert = NULL;
+        BACKEND->server_cert = NULL;
         return CURLE_SSL_ISSUER_ERROR;
       }
 
@@ -2919,7 +3131,7 @@ static CURLcode servercert(struct connectdata *conn,
       X509_free(issuer);
     }
 
-    lerr = *certverifyresult = SSL_get_verify_result(connssl->handle);
+    lerr = *certverifyresult = SSL_get_verify_result(BACKEND->handle);
 
     if(*certverifyresult != X509_V_OK) {
       if(SSL_CONN_CONFIG(verifypeer)) {
@@ -2944,8 +3156,8 @@ static CURLcode servercert(struct connectdata *conn,
   if(SSL_CONN_CONFIG(verifystatus)) {
     result = verifystatus(conn, connssl);
     if(result) {
-      X509_free(connssl->server_cert);
-      connssl->server_cert = NULL;
+      X509_free(BACKEND->server_cert);
+      BACKEND->server_cert = NULL;
       return result;
     }
   }
@@ -2958,13 +3170,13 @@ static CURLcode servercert(struct connectdata *conn,
   ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
                          data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
   if(!result && ptr) {
-    result = pkp_pin_peer_pubkey(data, connssl->server_cert, ptr);
+    result = pkp_pin_peer_pubkey(data, BACKEND->server_cert, ptr);
     if(result)
       failf(data, "SSL: public key does not match pinned public key!");
   }
 
-  X509_free(connssl->server_cert);
-  connssl->server_cert = NULL;
+  X509_free(BACKEND->server_cert);
+  BACKEND->server_cert = NULL;
   connssl->connecting_state = ssl_connect_done;
 
   return result;
@@ -2983,7 +3195,7 @@ static CURLcode ossl_connect_step3(struct connectdata 
*conn, int sockindex)
     SSL_SESSION *our_ssl_sessionid;
     void *old_ssl_sessionid = NULL;
 
-    our_ssl_sessionid = SSL_get1_session(connssl->handle);
+    our_ssl_sessionid = SSL_get1_session(BACKEND->handle);
 
     /* SSL_get1_session() will increment the reference count and the session
         will stay in memory until explicitly freed with SSL_SESSION_free(3),
@@ -3088,9 +3300,9 @@ static CURLcode ossl_connect_common(struct connectdata 
*conn,
     if(connssl->connecting_state == ssl_connect_2_reading ||
        connssl->connecting_state == ssl_connect_2_writing) {
 
-      curl_socket_t writefd = 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==
+      curl_socket_t readfd = ssl_connect_2_reading ==
         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
 
       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
@@ -3148,14 +3360,14 @@ static CURLcode ossl_connect_common(struct connectdata 
*conn,
   return CURLE_OK;
 }
 
-CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
-                                       int sockindex,
-                                       bool *done)
+static CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
+                                              int sockindex,
+                                              bool *done)
 {
   return ossl_connect_common(conn, sockindex, TRUE, done);
 }
 
-CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex)
+static CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex)
 {
   CURLcode result;
   bool done = FALSE;
@@ -3169,17 +3381,22 @@ CURLcode Curl_ossl_connect(struct connectdata *conn, 
int sockindex)
   return CURLE_OK;
 }
 
-bool Curl_ossl_data_pending(const struct connectdata *conn, int connindex)
+static bool Curl_ossl_data_pending(const struct connectdata *conn,
+                                   int connindex)
 {
-  if(conn->ssl[connindex].handle)
+  const struct ssl_connect_data *connssl = &conn->ssl[connindex];
+  const struct ssl_connect_data *proxyssl = &conn->proxy_ssl[connindex];
+  if(BACKEND->handle)
     /* SSL is in use */
-    return (0 != SSL_pending(conn->ssl[connindex].handle) ||
-           (conn->proxy_ssl[connindex].handle &&
-            0 != SSL_pending(conn->proxy_ssl[connindex].handle))) ?
+    return (0 != SSL_pending(BACKEND->handle) ||
+           (proxyssl->backend->handle &&
+            0 != SSL_pending(proxyssl->backend->handle))) ?
            TRUE : FALSE;
   return FALSE;
 }
 
+static size_t Curl_ossl_version(char *buffer, size_t size);
+
 static ssize_t ossl_send(struct connectdata *conn,
                          int sockindex,
                          const void *mem,
@@ -3193,14 +3410,15 @@ static ssize_t ossl_send(struct connectdata *conn,
   unsigned long sslerror;
   int memlen;
   int rc;
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
   ERR_clear_error();
 
   memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
-  rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
+  rc = SSL_write(BACKEND->handle, mem, memlen);
 
   if(rc <= 0) {
-    err = SSL_get_error(conn->ssl[sockindex].handle, rc);
+    err = SSL_get_error(BACKEND->handle, rc);
 
     switch(err) {
     case SSL_ERROR_WANT_READ:
@@ -3254,14 +3472,15 @@ static ssize_t ossl_recv(struct connectdata *conn, /* 
connection data */
   unsigned long sslerror;
   ssize_t nread;
   int buffsize;
+  struct ssl_connect_data *connssl = &conn->ssl[num];
 
   ERR_clear_error();
 
   buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
-  nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, buffsize);
+  nread = (ssize_t)SSL_read(BACKEND->handle, buf, buffsize);
   if(nread <= 0) {
     /* failed SSL_read */
-    int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
+    int err = SSL_get_error(BACKEND->handle, (int)nread);
 
     switch(err) {
     case SSL_ERROR_NONE: /* this is not an error */
@@ -3293,7 +3512,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* 
connection data */
   return nread;
 }
 
-size_t Curl_ossl_version(char *buffer, size_t size)
+static size_t Curl_ossl_version(char *buffer, size_t size)
 {
 #ifdef OPENSSL_IS_BORINGSSL
   return snprintf(buffer, size, OSSL_PACKAGE);
@@ -3302,9 +3521,9 @@ size_t Curl_ossl_version(char *buffer, size_t size)
   unsigned long ssleay_value;
   sub[2]='\0';
   sub[1]='\0';
-  ssleay_value=OpenSSL_version_num();
+  ssleay_value = OpenSSL_version_num();
   if(ssleay_value < 0x906000) {
-    ssleay_value=SSLEAY_VERSION_NUMBER;
+    ssleay_value = SSLEAY_VERSION_NUMBER;
     sub[0]='\0';
   }
   else {
@@ -3333,8 +3552,8 @@ size_t Curl_ossl_version(char *buffer, size_t size)
 }
 
 /* can be called with data == NULL */
-CURLcode Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
-                          size_t length)
+static CURLcode Curl_ossl_random(struct Curl_easy *data,
+                                 unsigned char *entropy, size_t length)
 {
   int rc;
   if(data) {
@@ -3350,23 +3569,24 @@ CURLcode Curl_ossl_random(struct Curl_easy *data, 
unsigned char *entropy,
   return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT);
 }
 
-void Curl_ossl_md5sum(unsigned char *tmp, /* input */
-                      size_t tmplen,
-                      unsigned char *md5sum /* output */,
-                      size_t unused)
+static CURLcode Curl_ossl_md5sum(unsigned char *tmp, /* input */
+                                 size_t tmplen,
+                                 unsigned char *md5sum /* output */,
+                                 size_t unused)
 {
   MD5_CTX MD5pw;
   (void)unused;
   MD5_Init(&MD5pw);
   MD5_Update(&MD5pw, tmp, tmplen);
   MD5_Final(md5sum, &MD5pw);
+  return CURLE_OK;
 }
 
 #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
-void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
-                      size_t tmplen,
-                      unsigned char *sha256sum /* output */,
-                      size_t unused)
+static void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
+                                size_t tmplen,
+                                unsigned char *sha256sum /* output */,
+                                size_t unused)
 {
   SHA256_CTX SHA256pw;
   (void)unused;
@@ -3376,7 +3596,7 @@ void Curl_ossl_sha256sum(const unsigned char *tmp, /* 
input */
 }
 #endif
 
-bool Curl_ossl_cert_status_request(void)
+static bool Curl_ossl_cert_status_request(void)
 {
 #if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
     !defined(OPENSSL_NO_OCSP)
@@ -3385,4 +3605,50 @@ bool Curl_ossl_cert_status_request(void)
   return FALSE;
 #endif
 }
+
+static void *Curl_ossl_get_internals(struct ssl_connect_data *connssl,
+                                     CURLINFO info)
+{
+  /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */
+  return info == CURLINFO_TLS_SESSION ?
+         (void *)BACKEND->ctx : (void *)BACKEND->handle;
+}
+
+const struct Curl_ssl Curl_ssl_openssl = {
+  { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */
+
+  1, /* have_ca_path */
+  1, /* have_certinfo */
+  1, /* have_pinnedpubkey */
+  1, /* have_ssl_ctx */
+  1, /* support_https_proxy */
+
+  sizeof(struct ssl_backend_data),
+
+  Curl_ossl_init,                /* init */
+  Curl_ossl_cleanup,             /* cleanup */
+  Curl_ossl_version,             /* version */
+  Curl_ossl_check_cxn,           /* check_cxn */
+  Curl_ossl_shutdown,            /* shutdown */
+  Curl_ossl_data_pending,        /* data_pending */
+  Curl_ossl_random,              /* random */
+  Curl_ossl_cert_status_request, /* cert_status_request */
+  Curl_ossl_connect,             /* connect */
+  Curl_ossl_connect_nonblocking, /* connect_nonblocking */
+  Curl_ossl_get_internals,       /* get_internals */
+  Curl_ossl_close,               /* close */
+  Curl_ossl_close_all,           /* close_all */
+  Curl_ossl_session_free,        /* session_free */
+  Curl_ossl_set_engine,          /* set_engine */
+  Curl_ossl_set_engine_default,  /* set_engine_default */
+  Curl_ossl_engines_list,        /* engines_list */
+  Curl_none_false_start,         /* false_start */
+  Curl_ossl_md5sum,              /* md5sum */
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
+  Curl_ossl_sha256sum            /* sha256sum */
+#else
+  NULL                           /* sha256sum */
+#endif
+};
+
 #endif /* USE_OPENSSL */
diff --git a/lib/vtls/openssl.h b/lib/vtls/openssl.h
index b9648d514..114dc4bae 100644
--- a/lib/vtls/openssl.h
+++ b/lib/vtls/openssl.h
@@ -31,96 +31,7 @@
 
 #include "urldata.h"
 
-CURLcode Curl_ossl_connect(struct connectdata *conn, int sockindex);
-CURLcode Curl_ossl_connect_nonblocking(struct connectdata *conn,
-                                       int sockindex,
-                                       bool *done);
-
-/* close a SSL connection */
-void Curl_ossl_close(struct connectdata *conn, int sockindex);
-
-/* tell OpenSSL to close down all open information regarding connections (and
-   thus session ID caching etc) */
-void Curl_ossl_close_all(struct Curl_easy *data);
-
-/* Sets an OpenSSL engine */
-CURLcode Curl_ossl_set_engine(struct Curl_easy *data, const char *engine);
-
-/* function provided for the generic SSL-layer, called when a session id
-   should be freed */
-void Curl_ossl_session_free(void *ptr);
-
-/* Sets engine as default for all SSL operations */
-CURLcode Curl_ossl_set_engine_default(struct Curl_easy *data);
-
-/* Build list of OpenSSL engines */
-struct curl_slist *Curl_ossl_engines_list(struct Curl_easy *data);
-
-int Curl_ossl_init(void);
-void Curl_ossl_cleanup(void);
-
-size_t Curl_ossl_version(char *buffer, size_t size);
-int Curl_ossl_check_cxn(struct connectdata *cxn);
-int Curl_ossl_shutdown(struct connectdata *conn, int sockindex);
-bool Curl_ossl_data_pending(const struct connectdata *conn,
-                            int connindex);
-
-/* return 0 if a find random is filled in */
-CURLcode Curl_ossl_random(struct Curl_easy *data, unsigned char *entropy,
-                          size_t length);
-void Curl_ossl_md5sum(unsigned char *tmp, /* input */
-                      size_t tmplen,
-                      unsigned char *md5sum /* output */,
-                      size_t unused);
-void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
-                      size_t tmplen,
-                      unsigned char *sha256sum /* output */,
-                      size_t unused);
-
-bool Curl_ossl_cert_status_request(void);
-
-/* Support HTTPS-proxy */
-#define HTTPS_PROXY_SUPPORT 1
-
-/* Set the API backend definition to OpenSSL */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_OPENSSL
-
-/* this backend supports the CAPATH option */
-#define have_curlssl_ca_path 1
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* this backend supports CURLOPT_SSL_CTX_* */
-#define have_curlssl_ssl_ctx 1
-
-/* this backend supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-
-/* API setup for OpenSSL */
-#define curlssl_init Curl_ossl_init
-#define curlssl_cleanup Curl_ossl_cleanup
-#define curlssl_connect Curl_ossl_connect
-#define curlssl_connect_nonblocking Curl_ossl_connect_nonblocking
-#define curlssl_session_free(x) Curl_ossl_session_free(x)
-#define curlssl_close_all Curl_ossl_close_all
-#define curlssl_close Curl_ossl_close
-#define curlssl_shutdown(x,y) Curl_ossl_shutdown(x,y)
-#define curlssl_set_engine(x,y) Curl_ossl_set_engine(x,y)
-#define curlssl_set_engine_default(x) Curl_ossl_set_engine_default(x)
-#define curlssl_engines_list(x) Curl_ossl_engines_list(x)
-#define curlssl_version Curl_ossl_version
-#define curlssl_check_cxn Curl_ossl_check_cxn
-#define curlssl_data_pending(x,y) Curl_ossl_data_pending(x,y)
-#define curlssl_random(x,y,z) Curl_ossl_random(x,y,z)
-#define curlssl_md5sum(a,b,c,d) Curl_ossl_md5sum(a,b,c,d)
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256)
-#define curlssl_sha256sum(a,b,c,d) Curl_ossl_sha256sum(a,b,c,d)
-#endif
-#define curlssl_cert_status_request() Curl_ossl_cert_status_request()
-
-#define DEFAULT_CIPHER_SELECTION \
-  "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH"
+extern const struct Curl_ssl Curl_ssl_openssl;
 
 #endif /* USE_OPENSSL */
 #endif /* HEADER_CURL_SSLUSE_H */
diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c
index 669091cb5..fc0644f89 100644
--- a/lib/vtls/polarssl.c
+++ b/lib/vtls/polarssl.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2012 - 2017, 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
@@ -30,7 +30,6 @@
 #include "curl_setup.h"
 
 #ifdef USE_POLARSSL
-
 #include <polarssl/net.h>
 #include <polarssl/ssl.h>
 #include <polarssl/certs.h>
@@ -70,6 +69,19 @@
 #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
@@ -197,8 +209,8 @@ set_ssl_version_min_max(struct connectdata *conn, int 
sockindex)
     return result;
   }
 
-  ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver);
-  ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver);
+  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;
 }
@@ -215,7 +227,7 @@ polarssl_connect_step1(struct connectdata *conn,
   const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
   int ret = -1;
   char errorbuf[128];
-  errorbuf[0]=0;
+  errorbuf[0] = 0;
 
   /* PolarSSL only supports SSLv3 and TLSv1 */
   if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
@@ -226,16 +238,16 @@ polarssl_connect_step1(struct connectdata *conn,
 #ifdef THREADING_SUPPORT
   entropy_init_mutex(&entropy);
 
-  if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_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(&connssl->entropy);
+  entropy_init(&BACKEND->entropy);
 
-  if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->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",
@@ -244,10 +256,10 @@ polarssl_connect_step1(struct connectdata *conn,
 #endif /* THREADING_SUPPORT */
 
   /* Load the trusted CA */
-  memset(&connssl->cacert, 0, sizeof(x509_crt));
+  memset(&BACKEND->cacert, 0, sizeof(x509_crt));
 
   if(SSL_CONN_CONFIG(CAfile)) {
-    ret = x509_crt_parse_file(&connssl->cacert,
+    ret = x509_crt_parse_file(&BACKEND->cacert,
                               SSL_CONN_CONFIG(CAfile));
 
     if(ret<0) {
@@ -261,7 +273,7 @@ polarssl_connect_step1(struct connectdata *conn,
   }
 
   if(capath) {
-    ret = x509_crt_parse_path(&connssl->cacert, capath);
+    ret = x509_crt_parse_path(&BACKEND->cacert, capath);
 
     if(ret<0) {
       error_strerror(ret, errorbuf, sizeof(errorbuf));
@@ -274,10 +286,10 @@ polarssl_connect_step1(struct connectdata *conn,
   }
 
   /* Load the client certificate */
-  memset(&connssl->clicert, 0, sizeof(x509_crt));
+  memset(&BACKEND->clicert, 0, sizeof(x509_crt));
 
   if(SSL_SET_OPTION(cert)) {
-    ret = x509_crt_parse_file(&connssl->clicert,
+    ret = x509_crt_parse_file(&BACKEND->clicert,
                               SSL_SET_OPTION(cert));
 
     if(ret) {
@@ -298,9 +310,9 @@ polarssl_connect_step1(struct connectdata *conn,
     if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
       ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
     if(ret == 0)
-      rsa_copy(&connssl->rsa, pk_rsa(pk));
+      rsa_copy(&BACKEND->rsa, pk_rsa(pk));
     else
-      rsa_free(&connssl->rsa);
+      rsa_free(&BACKEND->rsa);
     pk_free(&pk);
 
     if(ret) {
@@ -313,10 +325,10 @@ polarssl_connect_step1(struct connectdata *conn,
   }
 
   /* Load the CRL */
-  memset(&connssl->crl, 0, sizeof(x509_crl));
+  memset(&BACKEND->crl, 0, sizeof(x509_crl));
 
   if(SSL_SET_OPTION(CRLfile)) {
-    ret = x509_crl_parse_file(&connssl->crl,
+    ret = x509_crl_parse_file(&BACKEND->crl,
                               SSL_SET_OPTION(CRLfile));
 
     if(ret) {
@@ -330,7 +342,7 @@ polarssl_connect_step1(struct connectdata *conn,
 
   infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port);
 
-  if(ssl_init(&connssl->ssl)) {
+  if(ssl_init(&BACKEND->ssl)) {
     failf(data, "PolarSSL: ssl_init failed");
     return CURLE_SSL_CONNECT_ERROR;
   }
@@ -338,13 +350,13 @@ polarssl_connect_step1(struct connectdata *conn,
   switch(SSL_CONN_CONFIG(version)) {
   case CURL_SSLVERSION_DEFAULT:
   case CURL_SSLVERSION_TLSv1:
-    ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+    ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
                         SSL_MINOR_VERSION_1);
     break;
   case CURL_SSLVERSION_SSLv3:
-    ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+    ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
                         SSL_MINOR_VERSION_0);
-    ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
+    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;
@@ -363,16 +375,16 @@ polarssl_connect_step1(struct connectdata *conn,
     return CURLE_SSL_CONNECT_ERROR;
   }
 
-  ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
-  ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL);
+  ssl_set_endpoint(&BACKEND->ssl, SSL_IS_CLIENT);
+  ssl_set_authmode(&BACKEND->ssl, SSL_VERIFY_OPTIONAL);
 
-  ssl_set_rng(&connssl->ssl, ctr_drbg_random,
-              &connssl->ctr_drbg);
-  ssl_set_bio(&connssl->ssl,
+  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(&connssl->ssl, ssl_list_ciphersuites());
+  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)) {
@@ -380,7 +392,7 @@ polarssl_connect_step1(struct connectdata *conn,
 
     Curl_ssl_sessionid_lock(conn);
     if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
-      ret = ssl_set_session(&connssl->ssl, old_session);
+      ret = ssl_set_session(&BACKEND->ssl, old_session);
       if(ret) {
         Curl_ssl_sessionid_unlock(conn);
         failf(data, "ssl_set_session returned -0x%x", -ret);
@@ -391,15 +403,15 @@ polarssl_connect_step1(struct connectdata *conn,
     Curl_ssl_sessionid_unlock(conn);
   }
 
-  ssl_set_ca_chain(&connssl->ssl,
-                   &connssl->cacert,
-                   &connssl->crl,
+  ssl_set_ca_chain(&BACKEND->ssl,
+                   &BACKEND->cacert,
+                   &BACKEND->crl,
                    hostname);
 
-  ssl_set_own_cert_rsa(&connssl->ssl,
-                       &connssl->clicert, &connssl->rsa);
+  ssl_set_own_cert_rsa(&BACKEND->ssl,
+                       &BACKEND->clicert, &BACKEND->rsa);
 
-  if(ssl_set_hostname(&connssl->ssl, hostname)) {
+  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. */
@@ -424,12 +436,12 @@ polarssl_connect_step1(struct connectdata *conn,
 
     protocols[cur] = NULL;
 
-    ssl_set_alpn_protocols(&connssl->ssl, protocols);
+    ssl_set_alpn_protocols(&BACKEND->ssl, protocols);
   }
 #endif
 
 #ifdef POLARSSL_DEBUG
-  ssl_set_dbg(&connssl->ssl, polarssl_debug, data);
+  ssl_set_dbg(&BACKEND->ssl, polarssl_debug, data);
 #endif
 
   connssl->connecting_state = ssl_connect_2;
@@ -456,7 +468,7 @@ polarssl_connect_step2(struct connectdata *conn,
   conn->recv[sockindex] = polarssl_recv;
   conn->send[sockindex] = polarssl_send;
 
-  ret = ssl_handshake(&connssl->ssl);
+  ret = ssl_handshake(&BACKEND->ssl);
 
   switch(ret) {
   case 0:
@@ -478,9 +490,9 @@ polarssl_connect_step2(struct connectdata *conn,
   }
 
   infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
-        ssl_get_ciphersuite(&conn->ssl[sockindex].ssl) );
+        ssl_get_ciphersuite(&BACKEND->ssl) );
 
-  ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
+  ret = ssl_get_verify_result(&BACKEND->ssl);
 
   if(ret && SSL_CONN_CONFIG(verifypeer)) {
     if(ret & BADCERT_EXPIRED)
@@ -500,12 +512,12 @@ polarssl_connect_step2(struct connectdata *conn,
     return CURLE_PEER_FAILED_VERIFICATION;
   }
 
-  if(ssl_get_peer_cert(&(connssl->ssl))) {
+  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(&(connssl->ssl))) != -1)
+                     ssl_get_peer_cert(&(BACKEND->ssl))) != -1)
       infof(data, "Dumping cert info:\n%s\n", buffer);
   }
 
@@ -517,7 +529,7 @@ polarssl_connect_step2(struct connectdata *conn,
     unsigned char pubkey[PUB_DER_MAX_BYTES];
     const x509_crt *peercert;
 
-    peercert = ssl_get_peer_cert(&connssl->ssl);
+    peercert = ssl_get_peer_cert(&BACKEND->ssl);
 
     if(!peercert || !peercert->raw.p || !peercert->raw.len) {
       failf(data, "Failed due to missing peer certificate");
@@ -566,7 +578,7 @@ polarssl_connect_step2(struct connectdata *conn,
 
 #ifdef HAS_ALPN
   if(conn->bits.tls_enable_alpn) {
-    const char *next_protocol = ssl_get_alpn_protocol(&connssl->ssl);
+    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);
@@ -614,7 +626,7 @@ polarssl_connect_step3(struct connectdata *conn,
 
     memset(our_ssl_sessionid, 0, sizeof(ssl_session));
 
-    ret = ssl_get_session(&connssl->ssl, our_ssl_sessionid);
+    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;
@@ -645,9 +657,10 @@ static ssize_t polarssl_send(struct connectdata *conn,
                              size_t len,
                              CURLcode *curlcode)
 {
+  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
   int ret = -1;
 
-  ret = ssl_write(&conn->ssl[sockindex].ssl,
+  ret = ssl_write(&BACKEND->ssl,
                   (unsigned char *)mem, len);
 
   if(ret < 0) {
@@ -659,13 +672,14 @@ static ssize_t polarssl_send(struct connectdata *conn,
   return ret;
 }
 
-void Curl_polarssl_close(struct connectdata *conn, int sockindex)
+static void Curl_polarssl_close(struct connectdata *conn, int sockindex)
 {
-  rsa_free(&conn->ssl[sockindex].rsa);
-  x509_crt_free(&conn->ssl[sockindex].clicert);
-  x509_crt_free(&conn->ssl[sockindex].cacert);
-  x509_crl_free(&conn->ssl[sockindex].crl);
-  ssl_free(&conn->ssl[sockindex].ssl);
+  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,
@@ -674,11 +688,12 @@ static ssize_t polarssl_recv(struct connectdata *conn,
                              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(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize);
+  ret = ssl_read(&BACKEND->ssl, (unsigned char *)buf, buffersize);
 
   if(ret <= 0) {
     if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
@@ -694,7 +709,7 @@ static ssize_t polarssl_recv(struct connectdata *conn,
   return len;
 }
 
-void Curl_polarssl_session_free(void *ptr)
+static void Curl_polarssl_session_free(void *ptr)
 {
   ssl_session_free(ptr);
   free(ptr);
@@ -703,7 +718,7 @@ void Curl_polarssl_session_free(void *ptr)
 /* 1.3.10 was the first rebranded version. All new releases (in 1.3 branch and
    higher) will be mbed TLS branded.. */
 
-size_t Curl_polarssl_version(char *buffer, size_t size)
+static size_t Curl_polarssl_version(char *buffer, size_t size)
 {
   unsigned int version = version_get_number();
   return snprintf(buffer, size, "%s/%d.%d.%d",
@@ -762,9 +777,9 @@ polarssl_connect_common(struct connectdata *conn,
     if(connssl->connecting_state == ssl_connect_2_reading ||
        connssl->connecting_state == ssl_connect_2_writing) {
 
-      curl_socket_t writefd = 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==
+      curl_socket_t readfd = ssl_connect_2_reading ==
         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
 
       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
@@ -825,18 +840,14 @@ polarssl_connect_common(struct connectdata *conn,
   return CURLE_OK;
 }
 
-CURLcode
-Curl_polarssl_connect_nonblocking(struct connectdata *conn,
-                                  int sockindex,
-                                  bool *done)
+static CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn,
+                                                  int sockindex, bool *done)
 {
   return polarssl_connect_common(conn, sockindex, TRUE, done);
 }
 
 
-CURLcode
-Curl_polarssl_connect(struct connectdata *conn,
-                      int sockindex)
+static CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex)
 {
   CURLcode result;
   bool done = FALSE;
@@ -854,20 +865,73 @@ Curl_polarssl_connect(struct connectdata *conn,
  * return 0 error initializing SSL
  * return 1 SSL initialized successfully
  */
-int Curl_polarssl_init(void)
+static int Curl_polarssl_init(void)
 {
   return Curl_polarsslthreadlock_thread_setup();
 }
 
-void Curl_polarssl_cleanup(void)
+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 void 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);
+}
 
-int Curl_polarssl_data_pending(const struct connectdata *conn, int sockindex)
+static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl,
+                                         CURLINFO info UNUSED_PARAM)
 {
-  return ssl_get_bytes_avail(&conn->ssl[sockindex].ssl) != 0;
+  (void)info;
+  return &BACKEND->ssl;
 }
 
+const struct Curl_ssl Curl_ssl_polarssl = {
+  { CURLSSLBACKEND_POLARSSL, "polarssl" }, /* info */
+
+  1, /* have_ca_path */
+  0, /* have_certinfo */
+  1, /* have_pinnedpubkey */
+  0, /* have_ssl_ctx */
+  0, /* support_https_proxy */
+
+  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!
+   * TODO: use Polarssl's CTR-DRBG or HMAC-DRBG
+  */
+  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 */
+  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/polarssl.h b/lib/vtls/polarssl.h
index 47af7b417..23c3636ee 100644
--- a/lib/vtls/polarssl.h
+++ b/lib/vtls/polarssl.h
@@ -26,57 +26,7 @@
 
 #ifdef USE_POLARSSL
 
-#include <polarssl/sha256.h>
-
-/* Called on first use PolarSSL, setup threading if supported */
-int  Curl_polarssl_init(void);
-void Curl_polarssl_cleanup(void);
-int Curl_polarssl_data_pending(const struct connectdata *conn, int sockindex);
-
-
-CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn,
-                                           int sockindex,
-                                           bool *done);
-
- /* close a SSL connection */
-void Curl_polarssl_close(struct connectdata *conn, int sockindex);
-
-void Curl_polarssl_session_free(void *ptr);
-size_t Curl_polarssl_version(char *buffer, size_t size);
-int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex);
-
-/* Set the API backend definition to PolarSSL */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_POLARSSL
-
-/* this backend supports the CAPATH option */
-#define have_curlssl_ca_path 1
-
-/* this backends supports CURLOPT_PINNEDPUBLICKEY */
-#define have_curlssl_pinnedpubkey 1
-
-/* API setup for PolarSSL */
-#define curlssl_init() Curl_polarssl_init()
-#define curlssl_cleanup() Curl_polarssl_cleanup()
-#define curlssl_connect Curl_polarssl_connect
-#define curlssl_connect_nonblocking Curl_polarssl_connect_nonblocking
-#define curlssl_session_free(x)  Curl_polarssl_session_free(x)
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_polarssl_close
-#define curlssl_shutdown(x,y) 0
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_polarssl_version
-#define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending(x,y) Curl_polarssl_data_pending(x, y)
-#define curlssl_sha256sum(a,b,c,d) sha256(a,b,c,0)
-
-/* This might cause libcurl to use a weeker random!
-   TODO: implement proper use of Polarssl's CTR-DRBG or HMAC-DRBG and use that
-*/
-#define curlssl_random(x,y,z) ((void)x, (void)y, (void)z, CURLE_NOT_BUILT_IN)
+extern const struct Curl_ssl Curl_ssl_polarssl;
 
 #endif /* USE_POLARSSL */
 #endif /* HEADER_CURL_POLARSSL_H */
diff --git a/lib/vtls/polarssl_threadlock.c b/lib/vtls/polarssl_threadlock.c
index b1eb7b746..dd5fbd7ec 100644
--- a/lib/vtls/polarssl_threadlock.c
+++ b/lib/vtls/polarssl_threadlock.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2013-2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2013-2017, 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
@@ -114,7 +114,7 @@ int Curl_polarsslthreadlock_lock_function(int n)
   }
 #elif defined(HAVE_PROCESS_H)
   if(n < NUMT) {
-    ret = (WaitForSingleObject(mutex_buf[n], INFINITE)==WAIT_FAILED?1:0);
+    ret = (WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED?1:0);
     if(ret) {
       DEBUGF(fprintf(stderr,
                      "Error: polarsslthreadlock_lock_function failed\n"));
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index 94603018b..9ca1431bd 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -46,6 +46,8 @@
 #  error "Can't compile SCHANNEL support without SSPI."
 #endif
 
+#include <schnlsp.h>
+#include <schannel.h>
 #include "curl_sspi.h"
 #include "schannel.h"
 #include "vtls.h"
@@ -74,11 +76,92 @@
 #  define HAS_ALPN 1
 #endif
 
+#ifndef UNISP_NAME_A
+#define UNISP_NAME_A "Microsoft Unified Security Protocol Provider"
+#endif
+
+#ifndef UNISP_NAME_W
+#define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider"
+#endif
+
+#ifndef UNISP_NAME
+#ifdef UNICODE
+#define UNISP_NAME  UNISP_NAME_W
+#else
+#define UNISP_NAME  UNISP_NAME_A
+#endif
+#endif
+
+#ifndef SP_PROT_SSL2_CLIENT
+#define SP_PROT_SSL2_CLIENT             0x00000008
+#endif
+
+#ifndef SP_PROT_SSL3_CLIENT
+#define SP_PROT_SSL3_CLIENT             0x00000008
+#endif
+
+#ifndef SP_PROT_TLS1_CLIENT
+#define SP_PROT_TLS1_CLIENT             0x00000080
+#endif
+
+#ifndef SP_PROT_TLS1_0_CLIENT
+#define SP_PROT_TLS1_0_CLIENT           SP_PROT_TLS1_CLIENT
+#endif
+
+#ifndef SP_PROT_TLS1_1_CLIENT
+#define SP_PROT_TLS1_1_CLIENT           0x00000200
+#endif
+
+#ifndef SP_PROT_TLS1_2_CLIENT
+#define SP_PROT_TLS1_2_CLIENT           0x00000800
+#endif
+
+#ifndef SECBUFFER_ALERT
+#define SECBUFFER_ALERT                 17
+#endif
+
+/* Both schannel buffer sizes must be > 0 */
+#define CURL_SCHANNEL_BUFFER_INIT_SIZE   4096
+#define CURL_SCHANNEL_BUFFER_FREE_SIZE   1024
+
 /* Uncomment to force verbose output
  * #define infof(x, y, ...) printf(y, __VA_ARGS__)
  * #define failf(x, y, ...) printf(y, __VA_ARGS__)
  */
 
+/* Structs to store Schannel handles */
+struct curl_schannel_cred {
+  CredHandle cred_handle;
+  TimeStamp time_stamp;
+  int refcount;
+};
+
+struct curl_schannel_ctxt {
+  CtxtHandle ctxt_handle;
+  TimeStamp time_stamp;
+};
+
+struct ssl_backend_data {
+  struct curl_schannel_cred *cred;
+  struct curl_schannel_ctxt *ctxt;
+  SecPkgContext_StreamSizes stream_sizes;
+  size_t encdata_length, decdata_length;
+  size_t encdata_offset, decdata_offset;
+  unsigned char *encdata_buffer, *decdata_buffer;
+  /* encdata_is_incomplete: if encdata contains only a partial record that
+     can't be decrypted without another Curl_read_plain (that is, status is
+     SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
+     more bytes into encdata then set this back to false. */
+  bool encdata_is_incomplete;
+  unsigned long req_flags, ret_flags;
+  CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
+  bool recv_sspi_close_notify; /* true if connection closed by close_notify */
+  bool recv_connection_closed; /* true if connection closed, regardless how */
+  bool use_alpn; /* true if ALPN is used for this connection */
+};
+
+#define BACKEND connssl->backend
+
 static Curl_recv schannel_recv;
 static Curl_send schannel_send;
 
@@ -176,33 +259,33 @@ schannel_connect_step1(struct connectdata *conn, int 
sockindex)
 #ifdef HAS_ALPN
   /* ALPN is only supported on Windows 8.1 / Server 2012 R2 and above.
      Also it doesn't seem to be supported for Wine, see curl bug #983. */
-  connssl->use_alpn = conn->bits.tls_enable_alpn &&
+  BACKEND->use_alpn = conn->bits.tls_enable_alpn &&
                       !GetProcAddress(GetModuleHandleA("ntdll"),
                                       "wine_get_version") &&
                       Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
                                                   VERSION_GREATER_THAN_EQUAL);
 #else
-  connssl->use_alpn = false;
+  BACKEND->use_alpn = false;
 #endif
 
-  connssl->cred = NULL;
+  BACKEND->cred = NULL;
 
   /* check for an existing re-usable credential handle */
   if(SSL_SET_OPTION(primary.sessionid)) {
     Curl_ssl_sessionid_lock(conn);
     if(!Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL, sockindex)) {
-      connssl->cred = old_cred;
+      BACKEND->cred = old_cred;
       infof(data, "schannel: re-using existing credential handle\n");
 
       /* increment the reference counter of the credential/session handle */
-      connssl->cred->refcount++;
+      BACKEND->cred->refcount++;
       infof(data, "schannel: incremented credential handle refcount = %d\n",
-            connssl->cred->refcount);
+            BACKEND->cred->refcount);
     }
     Curl_ssl_sessionid_unlock(conn);
   }
 
-  if(!connssl->cred) {
+  if(!BACKEND->cred) {
     /* setup Schannel API options */
     memset(&schannel_cred, 0, sizeof(schannel_cred));
     schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
@@ -272,14 +355,14 @@ schannel_connect_step1(struct connectdata *conn, int 
sockindex)
     }
 
     /* allocate memory for the re-usable credential handle */
-    connssl->cred = (struct curl_schannel_cred *)
+    BACKEND->cred = (struct curl_schannel_cred *)
       malloc(sizeof(struct curl_schannel_cred));
-    if(!connssl->cred) {
+    if(!BACKEND->cred) {
       failf(data, "schannel: unable to allocate memory");
       return CURLE_OUT_OF_MEMORY;
     }
-    memset(connssl->cred, 0, sizeof(struct curl_schannel_cred));
-    connssl->cred->refcount = 1;
+    memset(BACKEND->cred, 0, sizeof(struct curl_schannel_cred));
+    BACKEND->cred->refcount = 1;
 
     /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx
        */
@@ -287,8 +370,8 @@ schannel_connect_step1(struct connectdata *conn, int 
sockindex)
       s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
                                          SECPKG_CRED_OUTBOUND, NULL,
                                          &schannel_cred, NULL, NULL,
-                                         &connssl->cred->cred_handle,
-                                         &connssl->cred->time_stamp);
+                                         &BACKEND->cred->cred_handle,
+                                         &BACKEND->cred->time_stamp);
 
     if(sspi_status != SEC_E_OK) {
       if(sspi_status == SEC_E_WRONG_PRINCIPAL)
@@ -297,7 +380,7 @@ schannel_connect_step1(struct connectdata *conn, int 
sockindex)
       else
         failf(data, "schannel: AcquireCredentialsHandle failed: %s",
               Curl_sspi_strerror(conn, sspi_status));
-      Curl_safefree(connssl->cred);
+      Curl_safefree(BACKEND->cred);
       return CURLE_SSL_CONNECT_ERROR;
     }
   }
@@ -312,7 +395,7 @@ schannel_connect_step1(struct connectdata *conn, int 
sockindex)
   }
 
 #ifdef HAS_ALPN
-  if(connssl->use_alpn) {
+  if(BACKEND->use_alpn) {
     int cur = 0;
     int list_start_index = 0;
     unsigned int *extension_len = NULL;
@@ -370,18 +453,18 @@ schannel_connect_step1(struct connectdata *conn, int 
sockindex)
   InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
 
   /* setup request flags */
-  connssl->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
+  BACKEND->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
     ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY |
     ISC_REQ_STREAM;
 
   /* allocate memory for the security context handle */
-  connssl->ctxt = (struct curl_schannel_ctxt *)
+  BACKEND->ctxt = (struct curl_schannel_ctxt *)
     malloc(sizeof(struct curl_schannel_ctxt));
-  if(!connssl->ctxt) {
+  if(!BACKEND->ctxt) {
     failf(data, "schannel: unable to allocate memory");
     return CURLE_OUT_OF_MEMORY;
   }
-  memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt));
+  memset(BACKEND->ctxt, 0, sizeof(struct curl_schannel_ctxt));
 
   host_name = Curl_convert_UTF8_to_tchar(hostname);
   if(!host_name)
@@ -395,10 +478,10 @@ schannel_connect_step1(struct connectdata *conn, int 
sockindex)
      us problems with inbuf regardless. https://github.com/curl/curl/issues/983
   */
   sspi_status = s_pSecFn->InitializeSecurityContext(
-    &connssl->cred->cred_handle, NULL, host_name, connssl->req_flags, 0, 0,
-    (connssl->use_alpn ? &inbuf_desc : NULL),
-    0, &connssl->ctxt->ctxt_handle,
-    &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp);
+    &BACKEND->cred->cred_handle, NULL, host_name, BACKEND->req_flags, 0, 0,
+    (BACKEND->use_alpn ? &inbuf_desc : NULL),
+    0, &BACKEND->ctxt->ctxt_handle,
+    &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
 
   Curl_unicodefree(host_name);
 
@@ -409,7 +492,7 @@ schannel_connect_step1(struct connectdata *conn, int 
sockindex)
     else
       failf(data, "schannel: initial InitializeSecurityContext failed: %s",
             Curl_sspi_strerror(conn, sspi_status));
-    Curl_safefree(connssl->ctxt);
+    Curl_safefree(BACKEND->ctxt);
     return CURLE_SSL_CONNECT_ERROR;
   }
 
@@ -429,10 +512,10 @@ schannel_connect_step1(struct connectdata *conn, int 
sockindex)
   infof(data, "schannel: sent initial handshake data: "
         "sent %zd bytes\n", written);
 
-  connssl->recv_unrecoverable_err = CURLE_OK;
-  connssl->recv_sspi_close_notify = false;
-  connssl->recv_connection_closed = false;
-  connssl->encdata_is_incomplete = false;
+  BACKEND->recv_unrecoverable_err = CURLE_OK;
+  BACKEND->recv_sspi_close_notify = false;
+  BACKEND->recv_connection_closed = false;
+  BACKEND->encdata_is_incomplete = false;
 
   /* continue to second handshake step */
   connssl->connecting_state = ssl_connect_2;
@@ -465,39 +548,39 @@ schannel_connect_step2(struct connectdata *conn, int 
sockindex)
   infof(data, "schannel: SSL/TLS connection with %s port %hu (step 2/3)\n",
         hostname, conn->remote_port);
 
-  if(!connssl->cred || !connssl->ctxt)
+  if(!BACKEND->cred || !BACKEND->ctxt)
     return CURLE_SSL_CONNECT_ERROR;
 
   /* buffer to store previously received and decrypted data */
-  if(connssl->decdata_buffer == NULL) {
-    connssl->decdata_offset = 0;
-    connssl->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
-    connssl->decdata_buffer = malloc(connssl->decdata_length);
-    if(connssl->decdata_buffer == NULL) {
+  if(BACKEND->decdata_buffer == NULL) {
+    BACKEND->decdata_offset = 0;
+    BACKEND->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
+    BACKEND->decdata_buffer = malloc(BACKEND->decdata_length);
+    if(BACKEND->decdata_buffer == NULL) {
       failf(data, "schannel: unable to allocate memory");
       return CURLE_OUT_OF_MEMORY;
     }
   }
 
   /* buffer to store previously received and encrypted data */
-  if(connssl->encdata_buffer == NULL) {
-    connssl->encdata_is_incomplete = false;
-    connssl->encdata_offset = 0;
-    connssl->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
-    connssl->encdata_buffer = malloc(connssl->encdata_length);
-    if(connssl->encdata_buffer == NULL) {
+  if(BACKEND->encdata_buffer == NULL) {
+    BACKEND->encdata_is_incomplete = false;
+    BACKEND->encdata_offset = 0;
+    BACKEND->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
+    BACKEND->encdata_buffer = malloc(BACKEND->encdata_length);
+    if(BACKEND->encdata_buffer == NULL) {
       failf(data, "schannel: unable to allocate memory");
       return CURLE_OUT_OF_MEMORY;
     }
   }
 
   /* if we need a bigger buffer to read a full message, increase buffer now */
-  if(connssl->encdata_length - connssl->encdata_offset <
+  if(BACKEND->encdata_length - BACKEND->encdata_offset <
      CURL_SCHANNEL_BUFFER_FREE_SIZE) {
     /* increase internal encrypted data buffer */
-    reallocated_length = connssl->encdata_offset +
+    reallocated_length = BACKEND->encdata_offset +
       CURL_SCHANNEL_BUFFER_FREE_SIZE;
-    reallocated_buffer = realloc(connssl->encdata_buffer,
+    reallocated_buffer = realloc(BACKEND->encdata_buffer,
                                  reallocated_length);
 
     if(reallocated_buffer == NULL) {
@@ -505,8 +588,8 @@ schannel_connect_step2(struct connectdata *conn, int 
sockindex)
       return CURLE_OUT_OF_MEMORY;
     }
     else {
-      connssl->encdata_buffer = reallocated_buffer;
-      connssl->encdata_length = reallocated_length;
+      BACKEND->encdata_buffer = reallocated_buffer;
+      BACKEND->encdata_length = reallocated_length;
     }
   }
 
@@ -514,10 +597,10 @@ schannel_connect_step2(struct connectdata *conn, int 
sockindex)
     if(doread) {
       /* read encrypted handshake data from socket */
       result = Curl_read_plain(conn->sock[sockindex],
-                               (char *) (connssl->encdata_buffer +
-                                         connssl->encdata_offset),
-                               connssl->encdata_length -
-                               connssl->encdata_offset,
+                               (char *) (BACKEND->encdata_buffer +
+                                         BACKEND->encdata_offset),
+                               BACKEND->encdata_length -
+                               BACKEND->encdata_offset,
                                &nread);
       if(result == CURLE_AGAIN) {
         if(connssl->connecting_state != ssl_connect_2_writing)
@@ -533,17 +616,17 @@ schannel_connect_step2(struct connectdata *conn, int 
sockindex)
       }
 
       /* increase encrypted data buffer offset */
-      connssl->encdata_offset += nread;
-      connssl->encdata_is_incomplete = false;
+      BACKEND->encdata_offset += nread;
+      BACKEND->encdata_is_incomplete = false;
       infof(data, "schannel: encrypted data got %zd\n", nread);
     }
 
     infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
-          connssl->encdata_offset, connssl->encdata_length);
+          BACKEND->encdata_offset, BACKEND->encdata_length);
 
     /* setup input buffers */
-    InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(connssl->encdata_offset),
-                  curlx_uztoul(connssl->encdata_offset));
+    InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(BACKEND->encdata_offset),
+                  curlx_uztoul(BACKEND->encdata_offset));
     InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
     InitSecBufferDesc(&inbuf_desc, inbuf, 2);
 
@@ -559,8 +642,8 @@ schannel_connect_step2(struct connectdata *conn, int 
sockindex)
     }
 
     /* copy received handshake data into input buffer */
-    memcpy(inbuf[0].pvBuffer, connssl->encdata_buffer,
-           connssl->encdata_offset);
+    memcpy(inbuf[0].pvBuffer, BACKEND->encdata_buffer,
+           BACKEND->encdata_offset);
 
     host_name = Curl_convert_UTF8_to_tchar(hostname);
     if(!host_name)
@@ -569,9 +652,9 @@ schannel_connect_step2(struct connectdata *conn, int 
sockindex)
     /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx
        */
     sspi_status = s_pSecFn->InitializeSecurityContext(
-      &connssl->cred->cred_handle, &connssl->ctxt->ctxt_handle,
-      host_name, connssl->req_flags, 0, 0, &inbuf_desc, 0, NULL,
-      &outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp);
+      &BACKEND->cred->cred_handle, &BACKEND->ctxt->ctxt_handle,
+      host_name, BACKEND->req_flags, 0, 0, &inbuf_desc, 0, NULL,
+      &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
 
     Curl_unicodefree(host_name);
 
@@ -580,7 +663,7 @@ schannel_connect_step2(struct connectdata *conn, int 
sockindex)
 
     /* check if the handshake was incomplete */
     if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
-      connssl->encdata_is_incomplete = true;
+      BACKEND->encdata_is_incomplete = true;
       connssl->connecting_state = ssl_connect_2_reading;
       infof(data, "schannel: received incomplete message, need more data\n");
       return CURLE_OK;
@@ -590,8 +673,8 @@ schannel_connect_step2(struct connectdata *conn, int 
sockindex)
        the handshake without one. This will allow connections to servers which
        request a client certificate but do not require it. */
     if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS &&
-       !(connssl->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
-      connssl->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
+       !(BACKEND->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) {
+      BACKEND->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS;
       connssl->connecting_state = ssl_connect_2_writing;
       infof(data, "schannel: a client certificate has been requested\n");
       return CURLE_OK;
@@ -631,7 +714,7 @@ schannel_connect_step2(struct connectdata *conn, int 
sockindex)
         failf(data, "schannel: next InitializeSecurityContext failed: %s",
               Curl_sspi_strerror(conn, sspi_status));
       return sspi_status == SEC_E_UNTRUSTED_ROOT ?
-          CURLE_SSL_CACERT_BADFILE : CURLE_SSL_CONNECT_ERROR;
+          CURLE_SSL_CACERT : CURLE_SSL_CONNECT_ERROR;
     }
 
     /* check if there was additional remaining encrypted data */
@@ -649,11 +732,11 @@ schannel_connect_step2(struct connectdata *conn, int 
sockindex)
       */
       /* check if the remaining data is less than the total amount
          and therefore begins after the already processed data */
-      if(connssl->encdata_offset > inbuf[1].cbBuffer) {
-        memmove(connssl->encdata_buffer,
-                (connssl->encdata_buffer + connssl->encdata_offset) -
+      if(BACKEND->encdata_offset > inbuf[1].cbBuffer) {
+        memmove(BACKEND->encdata_buffer,
+                (BACKEND->encdata_buffer + BACKEND->encdata_offset) -
                 inbuf[1].cbBuffer, inbuf[1].cbBuffer);
-        connssl->encdata_offset = inbuf[1].cbBuffer;
+        BACKEND->encdata_offset = inbuf[1].cbBuffer;
         if(sspi_status == SEC_I_CONTINUE_NEEDED) {
           doread = FALSE;
           continue;
@@ -661,7 +744,7 @@ schannel_connect_step2(struct connectdata *conn, int 
sockindex)
       }
     }
     else {
-      connssl->encdata_offset = 0;
+      BACKEND->encdata_offset = 0;
     }
     break;
   }
@@ -709,27 +792,27 @@ schannel_connect_step3(struct connectdata *conn, int 
sockindex)
   infof(data, "schannel: SSL/TLS connection with %s port %hu (step 3/3)\n",
         hostname, conn->remote_port);
 
-  if(!connssl->cred)
+  if(!BACKEND->cred)
     return CURLE_SSL_CONNECT_ERROR;
 
   /* check if the required context attributes are met */
-  if(connssl->ret_flags != connssl->req_flags) {
-    if(!(connssl->ret_flags & ISC_RET_SEQUENCE_DETECT))
+  if(BACKEND->ret_flags != BACKEND->req_flags) {
+    if(!(BACKEND->ret_flags & ISC_RET_SEQUENCE_DETECT))
       failf(data, "schannel: failed to setup sequence detection");
-    if(!(connssl->ret_flags & ISC_RET_REPLAY_DETECT))
+    if(!(BACKEND->ret_flags & ISC_RET_REPLAY_DETECT))
       failf(data, "schannel: failed to setup replay detection");
-    if(!(connssl->ret_flags & ISC_RET_CONFIDENTIALITY))
+    if(!(BACKEND->ret_flags & ISC_RET_CONFIDENTIALITY))
       failf(data, "schannel: failed to setup confidentiality");
-    if(!(connssl->ret_flags & ISC_RET_ALLOCATED_MEMORY))
+    if(!(BACKEND->ret_flags & ISC_RET_ALLOCATED_MEMORY))
       failf(data, "schannel: failed to setup memory allocation");
-    if(!(connssl->ret_flags & ISC_RET_STREAM))
+    if(!(BACKEND->ret_flags & ISC_RET_STREAM))
       failf(data, "schannel: failed to setup stream orientation");
     return CURLE_SSL_CONNECT_ERROR;
   }
 
 #ifdef HAS_ALPN
-  if(connssl->use_alpn) {
-    sspi_status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
+  if(BACKEND->use_alpn) {
+    sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
       SECPKG_ATTR_APPLICATION_PROTOCOL, &alpn_result);
 
     if(sspi_status != SEC_E_OK) {
@@ -771,7 +854,7 @@ schannel_connect_step3(struct connectdata *conn, int 
sockindex)
     incache = !(Curl_ssl_getsessionid(conn, (void **)&old_cred, NULL,
                                       sockindex));
     if(incache) {
-      if(old_cred != connssl->cred) {
+      if(old_cred != BACKEND->cred) {
         infof(data, "schannel: old credential handle is stale, removing\n");
         /* we're not taking old_cred ownership here, no refcount++ is needed */
         Curl_ssl_delsessionid(conn, (void *)old_cred);
@@ -779,7 +862,7 @@ schannel_connect_step3(struct connectdata *conn, int 
sockindex)
       }
     }
     if(!incache) {
-      result = Curl_ssl_addsessionid(conn, (void *)connssl->cred,
+      result = Curl_ssl_addsessionid(conn, (void *)BACKEND->cred,
                                      sizeof(struct curl_schannel_cred),
                                      sockindex);
       if(result) {
@@ -789,7 +872,7 @@ schannel_connect_step3(struct connectdata *conn, int 
sockindex)
       }
       else {
         /* this cred session is now also referenced by sessionid cache */
-        connssl->cred->refcount++;
+        BACKEND->cred->refcount++;
         infof(data, "schannel: stored credential handle in session cache\n");
       }
     }
@@ -797,7 +880,7 @@ schannel_connect_step3(struct connectdata *conn, int 
sockindex)
   }
 
   if(data->set.ssl.certinfo) {
-    sspi_status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
+    sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
       SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context);
 
     if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) {
@@ -951,11 +1034,11 @@ schannel_send(struct connectdata *conn, int sockindex,
   CURLcode result;
 
   /* check if the maximum stream sizes were queried */
-  if(connssl->stream_sizes.cbMaximumMessage == 0) {
+  if(BACKEND->stream_sizes.cbMaximumMessage == 0) {
     sspi_status = s_pSecFn->QueryContextAttributes(
-      &connssl->ctxt->ctxt_handle,
+      &BACKEND->ctxt->ctxt_handle,
       SECPKG_ATTR_STREAM_SIZES,
-      &connssl->stream_sizes);
+      &BACKEND->stream_sizes);
     if(sspi_status != SEC_E_OK) {
       *err = CURLE_SEND_ERROR;
       return -1;
@@ -963,14 +1046,13 @@ schannel_send(struct connectdata *conn, int sockindex,
   }
 
   /* check if the buffer is longer than the maximum message length */
-  if(len > connssl->stream_sizes.cbMaximumMessage) {
-    *err = CURLE_SEND_ERROR;
-    return -1;
+  if(len > BACKEND->stream_sizes.cbMaximumMessage) {
+    len = BACKEND->stream_sizes.cbMaximumMessage;
   }
 
   /* calculate the complete message length and allocate a buffer for it */
-  data_len = connssl->stream_sizes.cbHeader + len +
-    connssl->stream_sizes.cbTrailer;
+  data_len = BACKEND->stream_sizes.cbHeader + len +
+    BACKEND->stream_sizes.cbTrailer;
   data = (unsigned char *) malloc(data_len);
   if(data == NULL) {
     *err = CURLE_OUT_OF_MEMORY;
@@ -979,12 +1061,12 @@ schannel_send(struct connectdata *conn, int sockindex,
 
   /* setup output buffers (header, data, trailer, empty) */
   InitSecBuffer(&outbuf[0], SECBUFFER_STREAM_HEADER,
-                data, connssl->stream_sizes.cbHeader);
+                data, BACKEND->stream_sizes.cbHeader);
   InitSecBuffer(&outbuf[1], SECBUFFER_DATA,
-                data + connssl->stream_sizes.cbHeader, curlx_uztoul(len));
+                data + BACKEND->stream_sizes.cbHeader, curlx_uztoul(len));
   InitSecBuffer(&outbuf[2], SECBUFFER_STREAM_TRAILER,
-                data + connssl->stream_sizes.cbHeader + len,
-                connssl->stream_sizes.cbTrailer);
+                data + BACKEND->stream_sizes.cbHeader + len,
+                BACKEND->stream_sizes.cbTrailer);
   InitSecBuffer(&outbuf[3], SECBUFFER_EMPTY, NULL, 0);
   InitSecBufferDesc(&outbuf_desc, outbuf, 4);
 
@@ -992,7 +1074,7 @@ schannel_send(struct connectdata *conn, int sockindex,
   memcpy(outbuf[1].pvBuffer, buf, len);
 
   /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375390.aspx */
-  sspi_status = s_pSecFn->EncryptMessage(&connssl->ctxt->ctxt_handle, 0,
+  sspi_status = s_pSecFn->EncryptMessage(&BACKEND->ctxt->ctxt_handle, 0,
                                          &outbuf_desc, 0);
 
   /* check if the message was encrypted */
@@ -1102,7 +1184,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
   size_t min_encdata_length = len + CURL_SCHANNEL_BUFFER_FREE_SIZE;
 
   /****************************************************************************
-   * Don't return or set connssl->recv_unrecoverable_err unless in the cleanup.
+   * Don't return or set BACKEND->recv_unrecoverable_err unless in the cleanup.
    * The pattern for return error is set *err, optional infof, goto cleanup.
    *
    * Our priority is to always return as much decrypted data to the caller as
@@ -1114,16 +1196,16 @@ schannel_recv(struct connectdata *conn, int sockindex,
   infof(data, "schannel: client wants to read %zu bytes\n", len);
   *err = CURLE_OK;
 
-  if(len && len <= connssl->decdata_offset) {
+  if(len && len <= BACKEND->decdata_offset) {
     infof(data, "schannel: enough decrypted data is already available\n");
     goto cleanup;
   }
-  else if(connssl->recv_unrecoverable_err) {
-    *err = connssl->recv_unrecoverable_err;
+  else if(BACKEND->recv_unrecoverable_err) {
+    *err = BACKEND->recv_unrecoverable_err;
     infof(data, "schannel: an unrecoverable error occurred in a prior call\n");
     goto cleanup;
   }
-  else if(connssl->recv_sspi_close_notify) {
+  else if(BACKEND->recv_sspi_close_notify) {
     /* once a server has indicated shutdown there is no more encrypted data */
     infof(data, "schannel: server indicated shutdown in a prior call\n");
     goto cleanup;
@@ -1135,17 +1217,17 @@ schannel_recv(struct connectdata *conn, int sockindex,
     */
     ; /* do nothing */
   }
-  else if(!connssl->recv_connection_closed) {
+  else if(!BACKEND->recv_connection_closed) {
     /* increase enc buffer in order to fit the requested amount of data */
-    size = connssl->encdata_length - connssl->encdata_offset;
+    size = BACKEND->encdata_length - BACKEND->encdata_offset;
     if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE ||
-       connssl->encdata_length < min_encdata_length) {
-      reallocated_length = connssl->encdata_offset +
+       BACKEND->encdata_length < min_encdata_length) {
+      reallocated_length = BACKEND->encdata_offset +
                            CURL_SCHANNEL_BUFFER_FREE_SIZE;
       if(reallocated_length < min_encdata_length) {
         reallocated_length = min_encdata_length;
       }
-      reallocated_buffer = realloc(connssl->encdata_buffer,
+      reallocated_buffer = realloc(BACKEND->encdata_buffer,
                                    reallocated_length);
       if(reallocated_buffer == NULL) {
         *err = CURLE_OUT_OF_MEMORY;
@@ -1153,20 +1235,20 @@ schannel_recv(struct connectdata *conn, int sockindex,
         goto cleanup;
       }
 
-      connssl->encdata_buffer = reallocated_buffer;
-      connssl->encdata_length = reallocated_length;
-      size = connssl->encdata_length - connssl->encdata_offset;
+      BACKEND->encdata_buffer = reallocated_buffer;
+      BACKEND->encdata_length = reallocated_length;
+      size = BACKEND->encdata_length - BACKEND->encdata_offset;
       infof(data, "schannel: encdata_buffer resized %zu\n",
-            connssl->encdata_length);
+            BACKEND->encdata_length);
     }
 
     infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
-          connssl->encdata_offset, connssl->encdata_length);
+          BACKEND->encdata_offset, BACKEND->encdata_length);
 
     /* read encrypted data from socket */
     *err = Curl_read_plain(conn->sock[sockindex],
-                           (char *)(connssl->encdata_buffer +
-                                    connssl->encdata_offset),
+                           (char *)(BACKEND->encdata_buffer +
+                                    BACKEND->encdata_offset),
                            size, &nread);
     if(*err) {
       nread = -1;
@@ -1178,26 +1260,26 @@ schannel_recv(struct connectdata *conn, int sockindex,
         infof(data, "schannel: Curl_read_plain returned error %d\n", *err);
     }
     else if(nread == 0) {
-      connssl->recv_connection_closed = true;
+      BACKEND->recv_connection_closed = true;
       infof(data, "schannel: server closed the connection\n");
     }
     else if(nread > 0) {
-      connssl->encdata_offset += (size_t)nread;
-      connssl->encdata_is_incomplete = false;
+      BACKEND->encdata_offset += (size_t)nread;
+      BACKEND->encdata_is_incomplete = false;
       infof(data, "schannel: encrypted data got %zd\n", nread);
     }
   }
 
   infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
-        connssl->encdata_offset, connssl->encdata_length);
+        BACKEND->encdata_offset, BACKEND->encdata_length);
 
   /* decrypt loop */
-  while(connssl->encdata_offset > 0 && sspi_status == SEC_E_OK &&
-        (!len || connssl->decdata_offset < len ||
-         connssl->recv_connection_closed)) {
+  while(BACKEND->encdata_offset > 0 && sspi_status == SEC_E_OK &&
+        (!len || BACKEND->decdata_offset < len ||
+         BACKEND->recv_connection_closed)) {
     /* prepare data buffer for DecryptMessage call */
-    InitSecBuffer(&inbuf[0], SECBUFFER_DATA, connssl->encdata_buffer,
-                  curlx_uztoul(connssl->encdata_offset));
+    InitSecBuffer(&inbuf[0], SECBUFFER_DATA, BACKEND->encdata_buffer,
+                  curlx_uztoul(BACKEND->encdata_offset));
 
     /* we need 3 more empty input buffers for possible output */
     InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0);
@@ -1207,7 +1289,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
 
     /* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx
        */
-    sspi_status = s_pSecFn->DecryptMessage(&connssl->ctxt->ctxt_handle,
+    sspi_status = s_pSecFn->DecryptMessage(&BACKEND->ctxt->ctxt_handle,
                                            &inbuf_desc, 0, NULL);
 
     /* check if everything went fine (server may want to renegotiate
@@ -1223,36 +1305,36 @@ schannel_recv(struct connectdata *conn, int sockindex,
         /* increase buffer in order to fit the received amount of data */
         size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_FREE_SIZE ?
                inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE;
-        if(connssl->decdata_length - connssl->decdata_offset < size ||
-           connssl->decdata_length < len) {
+        if(BACKEND->decdata_length - BACKEND->decdata_offset < size ||
+           BACKEND->decdata_length < len) {
           /* increase internal decrypted data buffer */
-          reallocated_length = connssl->decdata_offset + size;
+          reallocated_length = BACKEND->decdata_offset + size;
           /* make sure that the requested amount of data fits */
           if(reallocated_length < len) {
             reallocated_length = len;
           }
-          reallocated_buffer = realloc(connssl->decdata_buffer,
+          reallocated_buffer = realloc(BACKEND->decdata_buffer,
                                        reallocated_length);
           if(reallocated_buffer == NULL) {
             *err = CURLE_OUT_OF_MEMORY;
             failf(data, "schannel: unable to re-allocate memory");
             goto cleanup;
           }
-          connssl->decdata_buffer = reallocated_buffer;
-          connssl->decdata_length = reallocated_length;
+          BACKEND->decdata_buffer = reallocated_buffer;
+          BACKEND->decdata_length = reallocated_length;
         }
 
         /* copy decrypted data to internal buffer */
         size = inbuf[1].cbBuffer;
         if(size) {
-          memcpy(connssl->decdata_buffer + connssl->decdata_offset,
+          memcpy(BACKEND->decdata_buffer + BACKEND->decdata_offset,
                  inbuf[1].pvBuffer, size);
-          connssl->decdata_offset += size;
+          BACKEND->decdata_offset += size;
         }
 
         infof(data, "schannel: decrypted data added: %zu\n", size);
         infof(data, "schannel: decrypted data cached: offset %zu length %zu\n",
-              connssl->decdata_offset, connssl->decdata_length);
+              BACKEND->decdata_offset, BACKEND->decdata_length);
       }
 
       /* check for remaining encrypted data */
@@ -1263,21 +1345,21 @@ schannel_recv(struct connectdata *conn, int sockindex,
         /* check if the remaining data is less than the total amount
          * and therefore begins after the already processed data
          */
-        if(connssl->encdata_offset > inbuf[3].cbBuffer) {
+        if(BACKEND->encdata_offset > inbuf[3].cbBuffer) {
           /* move remaining encrypted data forward to the beginning of
              buffer */
-          memmove(connssl->encdata_buffer,
-                  (connssl->encdata_buffer + connssl->encdata_offset) -
+          memmove(BACKEND->encdata_buffer,
+                  (BACKEND->encdata_buffer + BACKEND->encdata_offset) -
                   inbuf[3].cbBuffer, inbuf[3].cbBuffer);
-          connssl->encdata_offset = inbuf[3].cbBuffer;
+          BACKEND->encdata_offset = inbuf[3].cbBuffer;
         }
 
         infof(data, "schannel: encrypted data cached: offset %zu length %zu\n",
-              connssl->encdata_offset, connssl->encdata_length);
+              BACKEND->encdata_offset, BACKEND->encdata_length);
       }
       else {
         /* reset encrypted buffer offset, because there is no data remaining */
-        connssl->encdata_offset = 0;
+        BACKEND->encdata_offset = 0;
       }
 
       /* check if server wants to renegotiate the connection context */
@@ -1287,7 +1369,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
           infof(data, "schannel: can't renogotiate, an error is pending\n");
           goto cleanup;
         }
-        if(connssl->encdata_offset) {
+        if(BACKEND->encdata_offset) {
           *err = CURLE_RECV_ERROR;
           infof(data, "schannel: can't renogotiate, "
                       "encrypted data available\n");
@@ -1311,16 +1393,16 @@ schannel_recv(struct connectdata *conn, int sockindex,
       else if(sspi_status == SEC_I_CONTEXT_EXPIRED) {
         /* In Windows 2000 SEC_I_CONTEXT_EXPIRED (close_notify) is not
            returned so we have to work around that in cleanup. */
-        connssl->recv_sspi_close_notify = true;
-        if(!connssl->recv_connection_closed) {
-          connssl->recv_connection_closed = true;
+        BACKEND->recv_sspi_close_notify = true;
+        if(!BACKEND->recv_connection_closed) {
+          BACKEND->recv_connection_closed = true;
           infof(data, "schannel: server closed the connection\n");
         }
         goto cleanup;
       }
     }
     else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
-      connssl->encdata_is_incomplete = true;
+      BACKEND->encdata_is_incomplete = true;
       if(!*err)
         *err = CURLE_AGAIN;
       infof(data, "schannel: failed to decrypt data, need more data\n");
@@ -1335,10 +1417,10 @@ schannel_recv(struct connectdata *conn, int sockindex,
   }
 
   infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
-        connssl->encdata_offset, connssl->encdata_length);
+        BACKEND->encdata_offset, BACKEND->encdata_length);
 
   infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
-        connssl->decdata_offset, connssl->decdata_length);
+        BACKEND->decdata_offset, BACKEND->decdata_length);
 
 cleanup:
   /* Warning- there is no guarantee the encdata state is valid at this point */
@@ -1352,13 +1434,13 @@ cleanup:
   return close_notify. In that case if the connection was closed we assume it
   was graceful (close_notify) since there doesn't seem to be a way to tell.
   */
-  if(len && !connssl->decdata_offset && connssl->recv_connection_closed &&
-     !connssl->recv_sspi_close_notify) {
+  if(len && !BACKEND->decdata_offset && BACKEND->recv_connection_closed &&
+     !BACKEND->recv_sspi_close_notify) {
     bool isWin2k = Curl_verify_windows_version(5, 0, PLATFORM_WINNT,
                                                VERSION_EQUAL);
 
     if(isWin2k && sspi_status == SEC_E_OK)
-      connssl->recv_sspi_close_notify = true;
+      BACKEND->recv_sspi_close_notify = true;
     else {
       *err = CURLE_RECV_ERROR;
       infof(data, "schannel: server closed abruptly (missing close_notify)\n");
@@ -1367,23 +1449,23 @@ cleanup:
 
   /* Any error other than CURLE_AGAIN is an unrecoverable error. */
   if(*err && *err != CURLE_AGAIN)
-      connssl->recv_unrecoverable_err = *err;
+      BACKEND->recv_unrecoverable_err = *err;
 
-  size = len < connssl->decdata_offset ? len : connssl->decdata_offset;
+  size = len < BACKEND->decdata_offset ? len : BACKEND->decdata_offset;
   if(size) {
-    memcpy(buf, connssl->decdata_buffer, size);
-    memmove(connssl->decdata_buffer, connssl->decdata_buffer + size,
-            connssl->decdata_offset - size);
-    connssl->decdata_offset -= size;
+    memcpy(buf, BACKEND->decdata_buffer, size);
+    memmove(BACKEND->decdata_buffer, BACKEND->decdata_buffer + size,
+            BACKEND->decdata_offset - size);
+    BACKEND->decdata_offset -= size;
 
     infof(data, "schannel: decrypted data returned %zu\n", size);
     infof(data, "schannel: decrypted data buffer: offset %zu length %zu\n",
-          connssl->decdata_offset, connssl->decdata_length);
+          BACKEND->decdata_offset, BACKEND->decdata_length);
     *err = CURLE_OK;
     return (ssize_t)size;
   }
 
-  if(!*err && !connssl->recv_connection_closed)
+  if(!*err && !BACKEND->recv_connection_closed)
       *err = CURLE_AGAIN;
 
   /* It's debatable what to return when !len. We could return whatever error we
@@ -1395,15 +1477,13 @@ cleanup:
   return *err ? -1 : 0;
 }
 
-CURLcode
-Curl_schannel_connect_nonblocking(struct connectdata *conn, int sockindex,
-                                  bool *done)
+static CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn,
+                                                  int sockindex, bool *done)
 {
   return schannel_connect_common(conn, sockindex, TRUE, done);
 }
 
-CURLcode
-Curl_schannel_connect(struct connectdata *conn, int sockindex)
+static CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex)
 {
   CURLcode result;
   bool done = FALSE;
@@ -1417,25 +1497,38 @@ Curl_schannel_connect(struct connectdata *conn, int 
sockindex)
   return CURLE_OK;
 }
 
-bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex)
+static bool Curl_schannel_data_pending(const struct connectdata *conn,
+                                       int sockindex)
 {
   const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
   if(connssl->use) /* SSL/TLS is in use */
-    return (connssl->decdata_offset > 0 ||
-            (connssl->encdata_offset > 0 && !connssl->encdata_is_incomplete));
+    return (BACKEND->decdata_offset > 0 ||
+            (BACKEND->encdata_offset > 0 && !BACKEND->encdata_is_incomplete));
   else
     return FALSE;
 }
 
-void Curl_schannel_close(struct connectdata *conn, int sockindex)
+static void Curl_schannel_close(struct connectdata *conn, int sockindex)
 {
   if(conn->ssl[sockindex].use)
     /* if the SSL/TLS channel hasn't been shut down yet, do that now. */
     Curl_ssl_shutdown(conn, sockindex);
 }
 
-int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
+static void Curl_schannel_session_free(void *ptr)
+{
+  /* this is expected to be called under sessionid lock */
+  struct curl_schannel_cred *cred = ptr;
+
+  cred->refcount--;
+  if(cred->refcount == 0) {
+    s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
+    Curl_safefree(cred);
+  }
+}
+
+static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
 {
   /* See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380138.aspx
    * Shutting Down an Schannel Connection
@@ -1448,7 +1541,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int 
sockindex)
   infof(data, "schannel: shutting down SSL/TLS connection with %s port %hu\n",
         hostname, conn->remote_port);
 
-  if(connssl->cred && connssl->ctxt) {
+  if(BACKEND->cred && BACKEND->ctxt) {
     SecBufferDesc BuffDesc;
     SecBuffer Buffer;
     SECURITY_STATUS sspi_status;
@@ -1461,7 +1554,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int 
sockindex)
     InitSecBuffer(&Buffer, SECBUFFER_TOKEN, &dwshut, sizeof(dwshut));
     InitSecBufferDesc(&BuffDesc, &Buffer, 1);
 
-    sspi_status = s_pSecFn->ApplyControlToken(&connssl->ctxt->ctxt_handle,
+    sspi_status = s_pSecFn->ApplyControlToken(&BACKEND->ctxt->ctxt_handle,
                                               &BuffDesc);
 
     if(sspi_status != SEC_E_OK)
@@ -1477,18 +1570,18 @@ int Curl_schannel_shutdown(struct connectdata *conn, 
int sockindex)
     InitSecBufferDesc(&outbuf_desc, &outbuf, 1);
 
     sspi_status = s_pSecFn->InitializeSecurityContext(
-      &connssl->cred->cred_handle,
-      &connssl->ctxt->ctxt_handle,
+      &BACKEND->cred->cred_handle,
+      &BACKEND->ctxt->ctxt_handle,
       host_name,
-      connssl->req_flags,
+      BACKEND->req_flags,
       0,
       0,
       NULL,
       0,
-      &connssl->ctxt->ctxt_handle,
+      &BACKEND->ctxt->ctxt_handle,
       &outbuf_desc,
-      &connssl->ret_flags,
-      &connssl->ctxt->time_stamp);
+      &BACKEND->ret_flags,
+      &BACKEND->ctxt->time_stamp);
 
     Curl_unicodefree(host_name);
 
@@ -1507,71 +1600,62 @@ int Curl_schannel_shutdown(struct connectdata *conn, 
int sockindex)
   }
 
   /* free SSPI Schannel API security context handle */
-  if(connssl->ctxt) {
+  if(BACKEND->ctxt) {
     infof(data, "schannel: clear security context handle\n");
-    s_pSecFn->DeleteSecurityContext(&connssl->ctxt->ctxt_handle);
-    Curl_safefree(connssl->ctxt);
+    s_pSecFn->DeleteSecurityContext(&BACKEND->ctxt->ctxt_handle);
+    Curl_safefree(BACKEND->ctxt);
   }
 
   /* free SSPI Schannel API credential handle */
-  if(connssl->cred) {
+  if(BACKEND->cred) {
     Curl_ssl_sessionid_lock(conn);
-    Curl_schannel_session_free(connssl->cred);
+    Curl_schannel_session_free(BACKEND->cred);
     Curl_ssl_sessionid_unlock(conn);
-    connssl->cred = NULL;
+    BACKEND->cred = NULL;
   }
 
   /* free internal buffer for received encrypted data */
-  if(connssl->encdata_buffer != NULL) {
-    Curl_safefree(connssl->encdata_buffer);
-    connssl->encdata_length = 0;
-    connssl->encdata_offset = 0;
-    connssl->encdata_is_incomplete = false;
+  if(BACKEND->encdata_buffer != NULL) {
+    Curl_safefree(BACKEND->encdata_buffer);
+    BACKEND->encdata_length = 0;
+    BACKEND->encdata_offset = 0;
+    BACKEND->encdata_is_incomplete = false;
   }
 
   /* free internal buffer for received decrypted data */
-  if(connssl->decdata_buffer != NULL) {
-    Curl_safefree(connssl->decdata_buffer);
-    connssl->decdata_length = 0;
-    connssl->decdata_offset = 0;
+  if(BACKEND->decdata_buffer != NULL) {
+    Curl_safefree(BACKEND->decdata_buffer);
+    BACKEND->decdata_length = 0;
+    BACKEND->decdata_offset = 0;
   }
 
   return CURLE_OK;
 }
 
-void Curl_schannel_session_free(void *ptr)
-{
-  /* this is expected to be called under sessionid lock */
-  struct curl_schannel_cred *cred = ptr;
-
-  cred->refcount--;
-  if(cred->refcount == 0) {
-    s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
-    Curl_safefree(cred);
-  }
-}
-
-int Curl_schannel_init(void)
+static int Curl_schannel_init(void)
 {
   return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
 }
 
-void Curl_schannel_cleanup(void)
+static void Curl_schannel_cleanup(void)
 {
   Curl_sspi_global_cleanup();
 }
 
-size_t Curl_schannel_version(char *buffer, size_t size)
+static size_t Curl_schannel_version(char *buffer, size_t size)
 {
   size = snprintf(buffer, size, "WinSSL");
 
   return size;
 }
 
-CURLcode Curl_schannel_random(unsigned char *entropy, size_t length)
+static CURLcode Curl_schannel_random(struct Curl_easy *data UNUSED_PARAM,
+                                     unsigned char *entropy, size_t length)
 {
   HCRYPTPROV hCryptProv = 0;
 
+  (void)data;
+
   if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
                           CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
     return CURLE_FAILED_INIT;
@@ -1598,7 +1682,7 @@ static CURLcode verify_certificate(struct connectdata 
*conn, int sockindex)
     conn->http_proxy.host.name :
     conn->host.name;
 
-  status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
+  status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
                                             SECPKG_ATTR_REMOTE_CERT_CONTEXT,
                                             &pCertContextServer);
 
@@ -1725,4 +1809,44 @@ static CURLcode verify_certificate(struct connectdata 
*conn, int sockindex)
 }
 #endif /* _WIN32_WCE */
 
+static void *Curl_schannel_get_internals(struct ssl_connect_data *connssl,
+                                         CURLINFO info UNUSED_PARAM)
+{
+  (void)info;
+  return &BACKEND->ctxt->ctxt_handle;
+}
+
+const struct Curl_ssl Curl_ssl_schannel = {
+  { CURLSSLBACKEND_SCHANNEL, "schannel" }, /* info */
+
+  0, /* have_ca_path */
+  1, /* have_certinfo */
+  0, /* have_pinnedpubkey */
+  0, /* have_ssl_ctx */
+  0, /* support_https_proxy */
+
+  sizeof(struct ssl_backend_data),
+
+  Curl_schannel_init,                /* init */
+  Curl_schannel_cleanup,             /* cleanup */
+  Curl_schannel_version,             /* version */
+  Curl_none_check_cxn,               /* check_cxn */
+  Curl_schannel_shutdown,            /* shutdown */
+  Curl_schannel_data_pending,        /* data_pending */
+  Curl_schannel_random,              /* random */
+  Curl_none_cert_status_request,     /* cert_status_request */
+  Curl_schannel_connect,             /* connect */
+  Curl_schannel_connect_nonblocking, /* connect_nonblocking */
+  Curl_schannel_get_internals,       /* get_internals */
+  Curl_schannel_close,               /* close */
+  Curl_none_close_all,               /* close_all */
+  Curl_schannel_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 */
+  NULL                               /* sha256sum */
+};
+
 #endif /* USE_SCHANNEL */
diff --git a/lib/vtls/schannel.h b/lib/vtls/schannel.h
index 8627c63c9..932103da4 100644
--- a/lib/vtls/schannel.h
+++ b/lib/vtls/schannel.h
@@ -28,94 +28,7 @@
 
 #include "urldata.h"
 
-#ifndef UNISP_NAME_A
-#define UNISP_NAME_A "Microsoft Unified Security Protocol Provider"
-#endif
-
-#ifndef UNISP_NAME_W
-#define UNISP_NAME_W L"Microsoft Unified Security Protocol Provider"
-#endif
-
-#ifndef UNISP_NAME
-#ifdef UNICODE
-#define UNISP_NAME  UNISP_NAME_W
-#else
-#define UNISP_NAME  UNISP_NAME_A
-#endif
-#endif
-
-#ifndef SP_PROT_SSL2_CLIENT
-#define SP_PROT_SSL2_CLIENT             0x00000008
-#endif
-
-#ifndef SP_PROT_SSL3_CLIENT
-#define SP_PROT_SSL3_CLIENT             0x00000008
-#endif
-
-#ifndef SP_PROT_TLS1_CLIENT
-#define SP_PROT_TLS1_CLIENT             0x00000080
-#endif
-
-#ifndef SP_PROT_TLS1_0_CLIENT
-#define SP_PROT_TLS1_0_CLIENT           SP_PROT_TLS1_CLIENT
-#endif
-
-#ifndef SP_PROT_TLS1_1_CLIENT
-#define SP_PROT_TLS1_1_CLIENT           0x00000200
-#endif
-
-#ifndef SP_PROT_TLS1_2_CLIENT
-#define SP_PROT_TLS1_2_CLIENT           0x00000800
-#endif
-
-#ifndef SECBUFFER_ALERT
-#define SECBUFFER_ALERT                 17
-#endif
-
-/* Both schannel buffer sizes must be > 0 */
-#define CURL_SCHANNEL_BUFFER_INIT_SIZE   4096
-#define CURL_SCHANNEL_BUFFER_FREE_SIZE   1024
-
-
-CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex);
-
-CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn,
-                                           int sockindex,
-                                           bool *done);
-
-bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex);
-void Curl_schannel_close(struct connectdata *conn, int sockindex);
-int Curl_schannel_shutdown(struct connectdata *conn, int sockindex);
-void Curl_schannel_session_free(void *ptr);
-
-int Curl_schannel_init(void);
-void Curl_schannel_cleanup(void);
-size_t Curl_schannel_version(char *buffer, size_t size);
-
-CURLcode Curl_schannel_random(unsigned char *entropy, size_t length);
-
-/* Set the API backend definition to Schannel */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_SCHANNEL
-
-/* this backend supports CURLOPT_CERTINFO */
-#define have_curlssl_certinfo 1
-
-/* API setup for Schannel */
-#define curlssl_init Curl_schannel_init
-#define curlssl_cleanup Curl_schannel_cleanup
-#define curlssl_connect Curl_schannel_connect
-#define curlssl_connect_nonblocking Curl_schannel_connect_nonblocking
-#define curlssl_session_free Curl_schannel_session_free
-#define curlssl_close_all(x) ((void)x)
-#define curlssl_close Curl_schannel_close
-#define curlssl_shutdown Curl_schannel_shutdown
-#define curlssl_set_engine(x,y) ((void)x, (void)y, CURLE_NOT_BUILT_IN)
-#define curlssl_set_engine_default(x) ((void)x, CURLE_NOT_BUILT_IN)
-#define curlssl_engines_list(x) ((void)x, (struct curl_slist *)NULL)
-#define curlssl_version Curl_schannel_version
-#define curlssl_check_cxn(x) ((void)x, -1)
-#define curlssl_data_pending Curl_schannel_data_pending
-#define curlssl_random(x,y,z) ((void)x, Curl_schannel_random(y,z))
+extern const struct Curl_ssl Curl_ssl_schannel;
 
 #endif /* USE_SCHANNEL */
 #endif /* HEADER_CURL_SCHANNEL_H */
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index d5d0971c4..1be646e8e 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -28,17 +28,9 @@
    to any specific SSL-layer.
 
    Curl_ssl_ - prefix for generic ones
-   Curl_ossl_ - prefix for OpenSSL ones
-   Curl_gtls_ - prefix for GnuTLS ones
-   Curl_nss_ - prefix for NSS ones
-   Curl_gskit_ - prefix for GSKit ones
-   Curl_polarssl_ - prefix for PolarSSL ones
-   Curl_cyassl_ - prefix for CyaSSL ones
-   Curl_schannel_ - prefix for Schannel SSPI ones
-   Curl_darwinssl_ - prefix for SecureTransport (Darwin) ones
-
-   Note that this source code uses curlssl_* functions, and they are all
-   defines/macros #defined by the lib-specific header files.
+
+   Note that this source code uses the functions of the configured SSL
+   backend via the global Curl_ssl instance.
 
    "SSL/TLS Strong Encryption: An Introduction"
    https://httpd.apache.org/docs/2.0/ssl/ssl_intro.html
@@ -98,9 +90,12 @@ Curl_ssl_config_matches(struct ssl_primary_config* data,
      (data->version_max == needle->version_max) &&
      (data->verifypeer == needle->verifypeer) &&
      (data->verifyhost == needle->verifyhost) &&
+     (data->verifystatus == needle->verifystatus) &&
      Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
      Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
      Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
+     Curl_safe_strcasecompare(data->random_file, needle->random_file) &&
+     Curl_safe_strcasecompare(data->egdsocket, needle->egdsocket) &&
      Curl_safe_strcasecompare(data->cipher_list, needle->cipher_list))
     return TRUE;
 
@@ -111,17 +106,19 @@ bool
 Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
                               struct ssl_primary_config *dest)
 {
-  dest->verifyhost = source->verifyhost;
-  dest->verifypeer = source->verifypeer;
   dest->version = source->version;
   dest->version_max = source->version_max;
+  dest->verifypeer = source->verifypeer;
+  dest->verifyhost = source->verifyhost;
+  dest->verifystatus = source->verifystatus;
+  dest->sessionid = source->sessionid;
 
-  CLONE_STRING(CAfile);
   CLONE_STRING(CApath);
-  CLONE_STRING(cipher_list);
-  CLONE_STRING(egdsocket);
-  CLONE_STRING(random_file);
+  CLONE_STRING(CAfile);
   CLONE_STRING(clientcert);
+  CLONE_STRING(random_file);
+  CLONE_STRING(egdsocket);
+  CLONE_STRING(cipher_list);
 
   /* Disable dest sessionid cache if a client cert is used, CVE-2016-5419. */
   dest->sessionid = (dest->clientcert ? false : source->sessionid);
@@ -130,23 +127,32 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config 
*source,
 
 void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
 {
-  Curl_safefree(sslc->CAfile);
   Curl_safefree(sslc->CApath);
-  Curl_safefree(sslc->cipher_list);
-  Curl_safefree(sslc->egdsocket);
-  Curl_safefree(sslc->random_file);
+  Curl_safefree(sslc->CAfile);
   Curl_safefree(sslc->clientcert);
+  Curl_safefree(sslc->random_file);
+  Curl_safefree(sslc->egdsocket);
+  Curl_safefree(sslc->cipher_list);
 }
 
+#ifdef USE_SSL
+static int multissl_init(const struct Curl_ssl *backend);
+#endif
+
 int Curl_ssl_backend(void)
 {
-  return (int)CURL_SSL_BACKEND;
+#ifdef USE_SSL
+  multissl_init(NULL);
+  return Curl_ssl->info.id;
+#else
+  return (int)CURLSSLBACKEND_NONE;
+#endif
 }
 
 #ifdef USE_SSL
 
 /* "global" init done? */
-static bool init_ssl=FALSE;
+static bool init_ssl = FALSE;
 
 /**
  * Global SSL init
@@ -161,7 +167,7 @@ int Curl_ssl_init(void)
     return 1;
   init_ssl = TRUE; /* never again */
 
-  return curlssl_init();
+  return Curl_ssl->init();
 }
 
 
@@ -170,7 +176,7 @@ void Curl_ssl_cleanup(void)
 {
   if(init_ssl) {
     /* only cleanup if we did a previous init */
-    curlssl_cleanup();
+    Curl_ssl->cleanup();
     init_ssl = FALSE;
   }
 }
@@ -205,12 +211,20 @@ ssl_connect_init_proxy(struct connectdata *conn, int 
sockindex)
   DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
   if(ssl_connection_complete == conn->ssl[sockindex].state &&
      !conn->proxy_ssl[sockindex].use) {
-#if defined(HTTPS_PROXY_SUPPORT)
+    struct ssl_backend_data *pbdata;
+
+    if(!Curl_ssl->support_https_proxy)
+      return CURLE_NOT_BUILT_IN;
+
+    /* The pointers to the ssl backend data, which is opaque here, are swapped
+       rather than move the contents. */
+    pbdata = conn->proxy_ssl[sockindex].backend;
     conn->proxy_ssl[sockindex] = conn->ssl[sockindex];
+
     memset(&conn->ssl[sockindex], 0, sizeof(conn->ssl[sockindex]));
-#else
-    return CURLE_NOT_BUILT_IN;
-#endif
+    memset(pbdata, 0, Curl_ssl->sizeof_ssl_backend_data);
+
+    conn->ssl[sockindex].backend = pbdata;
   }
   return CURLE_OK;
 }
@@ -233,7 +247,7 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex)
   conn->ssl[sockindex].use = TRUE;
   conn->ssl[sockindex].state = ssl_connection_negotiating;
 
-  result = curlssl_connect(conn, sockindex);
+  result = Curl_ssl->connect(conn, sockindex);
 
   if(!result)
     Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
@@ -257,12 +271,7 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int 
sockindex,
 
   /* mark this is being ssl requested from here on. */
   conn->ssl[sockindex].use = TRUE;
-#ifdef curlssl_connect_nonblocking
-  result = curlssl_connect_nonblocking(conn, sockindex, done);
-#else
-  *done = TRUE; /* fallback to BLOCKING */
-  result = curlssl_connect(conn, sockindex);
-#endif /* non-blocking connect support */
+  result = Curl_ssl->connect_nonblocking(conn, sockindex, done);
   if(!result && *done)
     Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSL is connected */
   return result;
@@ -361,7 +370,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
     /* defensive check */
 
     /* free the ID the SSL-layer specific way */
-    curlssl_session_free(session->sessionid);
+    Curl_ssl->session_free(session->sessionid);
 
     session->sessionid = NULL;
     session->age = 0; /* fresh */
@@ -379,7 +388,7 @@ void Curl_ssl_kill_session(struct curl_ssl_session *session)
 void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid)
 {
   size_t i;
-  struct Curl_easy *data=conn->data;
+  struct Curl_easy *data = conn->data;
 
   for(i = 0; i < data->set.general_ssl.max_ssl_sessions; i++) {
     struct curl_ssl_session *check = &data->state.session[i];
@@ -403,9 +412,9 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
                                int sockindex)
 {
   size_t i;
-  struct Curl_easy *data=conn->data; /* the mother of all structs */
+  struct Curl_easy *data = conn->data; /* the mother of all structs */
   struct curl_ssl_session *store = &data->state.session[0];
-  long oldest_age=data->state.session[0].age; /* zero if unused */
+  long oldest_age = data->state.session[0].age; /* zero if unused */
   char *clone_host;
   char *clone_conn_to_host;
   int conn_to_port;
@@ -499,7 +508,7 @@ void Curl_ssl_close_all(struct Curl_easy *data)
     Curl_safefree(data->state.session);
   }
 
-  curlssl_close_all(data);
+  Curl_ssl->close_all(data);
 }
 
 #if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
@@ -542,12 +551,12 @@ int Curl_ssl_getsock(struct connectdata *conn,
 void Curl_ssl_close(struct connectdata *conn, int sockindex)
 {
   DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
-  curlssl_close(conn, sockindex);
+  Curl_ssl->close(conn, sockindex);
 }
 
 CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
 {
-  if(curlssl_shutdown(conn, sockindex))
+  if(Curl_ssl->shutdown(conn, sockindex))
     return CURLE_SSL_SHUTDOWN_FAILED;
 
   conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
@@ -563,20 +572,20 @@ CURLcode Curl_ssl_shutdown(struct connectdata *conn, int 
sockindex)
  */
 CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine)
 {
-  return curlssl_set_engine(data, engine);
+  return Curl_ssl->set_engine(data, engine);
 }
 
 /* Selects the default SSL crypto engine
  */
 CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data)
 {
-  return curlssl_set_engine_default(data);
+  return Curl_ssl->set_engine_default(data);
 }
 
 /* Return list of OpenSSL crypto engine names. */
 struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data)
 {
-  return curlssl_engines_list(data);
+  return Curl_ssl->engines_list(data);
 }
 
 /*
@@ -602,9 +611,15 @@ CURLcode Curl_ssl_initsessions(struct Curl_easy *data, 
size_t amount)
   return CURLE_OK;
 }
 
+static size_t Curl_multissl_version(char *buffer, size_t size);
+
 size_t Curl_ssl_version(char *buffer, size_t size)
 {
-  return curlssl_version(buffer, size);
+#ifdef CURL_WITH_MULTI_SSL
+  return Curl_multissl_version(buffer, size);
+#else
+  return Curl_ssl->version(buffer, size);
+#endif
 }
 
 /*
@@ -617,13 +632,13 @@ size_t Curl_ssl_version(char *buffer, size_t size)
  */
 int Curl_ssl_check_cxn(struct connectdata *conn)
 {
-  return curlssl_check_cxn(conn);
+  return Curl_ssl->check_cxn(conn);
 }
 
 bool Curl_ssl_data_pending(const struct connectdata *conn,
                            int connindex)
 {
-  return curlssl_data_pending(conn, connindex);
+  return Curl_ssl->data_pending(conn, connindex);
 }
 
 void Curl_ssl_free_certinfo(struct Curl_easy *data)
@@ -633,7 +648,7 @@ void Curl_ssl_free_certinfo(struct Curl_easy *data)
 
   if(ci->num_of_certs) {
     /* free all individual lists used */
-    for(i=0; i<ci->num_of_certs; i++) {
+    for(i = 0; i<ci->num_of_certs; i++) {
       curl_slist_free_all(ci->certinfo[i]);
       ci->certinfo[i] = NULL;
     }
@@ -687,7 +702,7 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
   snprintf(output, outlen, "%s:", label);
 
   /* memcpy the value (it might not be zero terminated) */
-  memcpy(&output[labellen+1], value, valuelen);
+  memcpy(&output[labellen + 1], value, valuelen);
 
   /* zero terminate the output */
   output[labellen + 1 + valuelen] = 0;
@@ -721,7 +736,7 @@ CURLcode Curl_ssl_random(struct Curl_easy *data,
                          unsigned char *entropy,
                          size_t length)
 {
-  return curlssl_random(data, entropy, length);
+  return Curl_ssl->random(data, entropy, length);
 }
 
 /*
@@ -796,12 +811,10 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
   size_t size, pem_len;
   CURLcode pem_read;
   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
-#ifdef curlssl_sha256sum
   CURLcode encode;
   size_t encodedlen, pinkeylen;
   char *encoded, *pinkeycopy, *begin_pos, *end_pos;
   unsigned char *sha256sumdigest = NULL;
-#endif
 
   /* if a path wasn't specified, don't pin */
   if(!pinnedpubkey)
@@ -811,15 +824,20 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
 
   /* only do this if pinnedpubkey starts with "sha256//", length 8 */
   if(strncmp(pinnedpubkey, "sha256//", 8) == 0) {
-#ifdef curlssl_sha256sum
+    if(!Curl_ssl->sha256sum) {
+      /* without sha256 support, this cannot match */
+      return result;
+    }
+
     /* compute sha256sum of public key */
-    sha256sumdigest = malloc(SHA256_DIGEST_LENGTH);
+    sha256sumdigest = malloc(CURL_SHA256_DIGEST_LENGTH);
     if(!sha256sumdigest)
       return CURLE_OUT_OF_MEMORY;
-    curlssl_sha256sum(pubkey, pubkeylen,
-                      sha256sumdigest, SHA256_DIGEST_LENGTH);
+    Curl_ssl->sha256sum(pubkey, pubkeylen,
+                        sha256sumdigest, CURL_SHA256_DIGEST_LENGTH);
     encode = Curl_base64_encode(data, (char *)sha256sumdigest,
-                                SHA256_DIGEST_LENGTH, &encoded, &encodedlen);
+                                CURL_SHA256_DIGEST_LENGTH, &encoded,
+                                &encodedlen);
     Curl_safefree(sha256sumdigest);
 
     if(encode)
@@ -864,10 +882,6 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
     } while(end_pos && begin_pos);
     Curl_safefree(encoded);
     Curl_safefree(pinkeycopy);
-#else
-    /* without sha256 support, this cannot match */
-    (void)data;
-#endif
     return result;
   }
 
@@ -943,20 +957,7 @@ CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
                          unsigned char *md5sum, /* output */
                          size_t md5len)
 {
-#ifdef curlssl_md5sum
-  curlssl_md5sum(tmp, tmplen, md5sum, md5len);
-#else
-  MD5_context *MD5pw;
-
-  (void) md5len;
-
-  MD5pw = Curl_MD5_init(Curl_DIGEST_MD5);
-  if(!MD5pw)
-    return CURLE_OUT_OF_MEMORY;
-  Curl_MD5_update(MD5pw, tmp, curlx_uztoui(tmplen));
-  Curl_MD5_final(MD5pw, md5sum);
-#endif
-  return CURLE_OK;
+  return Curl_ssl->md5sum(tmp, tmplen, md5sum, md5len);
 }
 #endif
 
@@ -965,11 +966,7 @@ CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */
  */
 bool Curl_ssl_cert_status_request(void)
 {
-#ifdef curlssl_cert_status_request
-  return curlssl_cert_status_request();
-#else
-  return FALSE;
-#endif
+  return Curl_ssl->cert_status_request();
 }
 
 /*
@@ -977,11 +974,341 @@ bool Curl_ssl_cert_status_request(void)
  */
 bool Curl_ssl_false_start(void)
 {
-#ifdef curlssl_false_start
-  return curlssl_false_start();
-#else
+  return Curl_ssl->false_start();
+}
+
+/*
+ * Default implementations for unsupported functions.
+ */
+
+int Curl_none_init(void)
+{
+  return 1;
+}
+
+void Curl_none_cleanup(void)
+{ }
+
+int Curl_none_shutdown(struct connectdata *conn UNUSED_PARAM,
+                       int sockindex UNUSED_PARAM)
+{
+  (void)conn;
+  (void)sockindex;
+  return 0;
+}
+
+int Curl_none_check_cxn(struct connectdata *conn UNUSED_PARAM)
+{
+  (void)conn;
+  return -1;
+}
+
+CURLcode Curl_none_random(struct Curl_easy *data UNUSED_PARAM,
+                          unsigned char *entropy UNUSED_PARAM,
+                          size_t length UNUSED_PARAM)
+{
+  (void)data;
+  (void)entropy;
+  (void)length;
+  return CURLE_NOT_BUILT_IN;
+}
+
+void Curl_none_close_all(struct Curl_easy *data UNUSED_PARAM)
+{
+  (void)data;
+}
+
+void Curl_none_session_free(void *ptr UNUSED_PARAM)
+{
+  (void)ptr;
+}
+
+bool Curl_none_data_pending(const struct connectdata *conn UNUSED_PARAM,
+                            int connindex UNUSED_PARAM)
+{
+  (void)conn;
+  (void)connindex;
+  return 0;
+}
+
+bool Curl_none_cert_status_request(void)
+{
   return FALSE;
+}
+
+CURLcode Curl_none_set_engine(struct Curl_easy *data UNUSED_PARAM,
+                              const char *engine UNUSED_PARAM)
+{
+  (void)data;
+  (void)engine;
+  return CURLE_NOT_BUILT_IN;
+}
+
+CURLcode Curl_none_set_engine_default(struct Curl_easy *data UNUSED_PARAM)
+{
+  (void)data;
+  return CURLE_NOT_BUILT_IN;
+}
+
+struct curl_slist *Curl_none_engines_list(struct Curl_easy *data UNUSED_PARAM)
+{
+  (void)data;
+  return (struct curl_slist *)NULL;
+}
+
+bool Curl_none_false_start(void)
+{
+  return FALSE;
+}
+
+CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
+                          unsigned char *md5sum, size_t md5len UNUSED_PARAM)
+{
+  MD5_context *MD5pw;
+
+  (void)md5len;
+
+  MD5pw = Curl_MD5_init(Curl_DIGEST_MD5);
+  if(!MD5pw)
+    return CURLE_OUT_OF_MEMORY;
+  Curl_MD5_update(MD5pw, input, curlx_uztoui(inputlen));
+  Curl_MD5_final(MD5pw, md5sum);
+  return CURLE_OK;
+}
+
+static int Curl_multissl_init(void)
+{
+  if(multissl_init(NULL))
+    return 1;
+  return Curl_ssl->init();
+}
+
+static CURLcode Curl_multissl_connect(struct connectdata *conn, int sockindex)
+{
+  if(multissl_init(NULL))
+    return CURLE_FAILED_INIT;
+  return Curl_ssl->connect(conn, sockindex);
+}
+
+static CURLcode Curl_multissl_connect_nonblocking(struct connectdata *conn,
+                                                  int sockindex, bool *done)
+{
+  if(multissl_init(NULL))
+    return CURLE_FAILED_INIT;
+  return Curl_ssl->connect_nonblocking(conn, sockindex, done);
+}
+
+static void *Curl_multissl_get_internals(struct ssl_connect_data *connssl,
+                                         CURLINFO info)
+{
+  if(multissl_init(NULL))
+    return NULL;
+  return Curl_ssl->get_internals(connssl, info);
+}
+
+static void Curl_multissl_close(struct connectdata *conn, int sockindex)
+{
+  if(multissl_init(NULL))
+    return;
+  Curl_ssl->close(conn, sockindex);
+}
+
+static const struct Curl_ssl Curl_ssl_multi = {
+  { CURLSSLBACKEND_NONE, "multi" },  /* info */
+
+  0, /* have_ca_path */
+  0, /* have_certinfo */
+  0, /* have_pinnedpubkey */
+  0, /* have_ssl_ctx */
+  0, /* support_https_proxy */
+
+  (size_t)-1, /* something insanely large to be on the safe side */
+
+  Curl_multissl_init,                /* init */
+  Curl_none_cleanup,                 /* cleanup */
+  Curl_multissl_version,             /* version */
+  Curl_none_check_cxn,               /* check_cxn */
+  Curl_none_shutdown,                /* shutdown */
+  Curl_none_data_pending,            /* data_pending */
+  Curl_none_random,                  /* random */
+  Curl_none_cert_status_request,     /* cert_status_request */
+  Curl_multissl_connect,             /* connect */
+  Curl_multissl_connect_nonblocking, /* connect_nonblocking */
+  Curl_multissl_get_internals,       /* get_internals */
+  Curl_multissl_close,               /* close */
+  Curl_none_close_all,               /* close_all */
+  Curl_none_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 */
+  NULL                               /* sha256sum */
+};
+
+const struct Curl_ssl *Curl_ssl =
+#if defined(CURL_WITH_MULTI_SSL)
+  &Curl_ssl_multi;
+#elif defined(USE_AXTLS)
+  &Curl_ssl_axtls;
+#elif defined(USE_CYASSL)
+  &Curl_ssl_cyassl;
+#elif defined(USE_DARWINSSL)
+  &Curl_ssl_darwinssl;
+#elif defined(USE_GNUTLS)
+  &Curl_ssl_gnutls;
+#elif defined(USE_GSKIT)
+  &Curl_ssl_gskit;
+#elif defined(USE_MBEDTLS)
+  &Curl_ssl_mbedtls;
+#elif defined(USE_NSS)
+  &Curl_ssl_nss;
+#elif defined(USE_OPENSSL)
+  &Curl_ssl_openssl;
+#elif defined(USE_POLARSSL)
+  &Curl_ssl_polarssl;
+#elif defined(USE_SCHANNEL)
+  &Curl_ssl_schannel;
+#else
+#error "Missing struct Curl_ssl for selected SSL backend"
+#endif
+
+static const struct Curl_ssl *available_backends[] = {
+#if defined(USE_AXTLS)
+  &Curl_ssl_axtls,
+#endif
+#if defined(USE_CYASSL)
+  &Curl_ssl_cyassl,
 #endif
+#if defined(USE_DARWINSSL)
+  &Curl_ssl_darwinssl,
+#endif
+#if defined(USE_GNUTLS)
+  &Curl_ssl_gnutls,
+#endif
+#if defined(USE_GSKIT)
+  &Curl_ssl_gskit,
+#endif
+#if defined(USE_MBEDTLS)
+  &Curl_ssl_mbedtls,
+#endif
+#if defined(USE_NSS)
+  &Curl_ssl_nss,
+#endif
+#if defined(USE_OPENSSL)
+  &Curl_ssl_openssl,
+#endif
+#if defined(USE_POLARSSL)
+  &Curl_ssl_polarssl,
+#endif
+#if defined(USE_SCHANNEL)
+  &Curl_ssl_schannel,
+#endif
+  NULL
+};
+
+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;
+  const struct Curl_ssl *current;
+
+  current = Curl_ssl == &Curl_ssl_multi ? available_backends[0] : Curl_ssl;
+
+  if(current != selected) {
+    char *p = backends;
+    int i;
+
+    selected = current;
+
+    for(i = 0; available_backends[i]; i++) {
+      if(i)
+        *(p++) = ' ';
+      if(selected != available_backends[i])
+        *(p++) = '(';
+      p += available_backends[i]->version(p, backends + sizeof(backends) - p);
+      if(selected != available_backends[i])
+        *(p++) = ')';
+    }
+    *p = '\0';
+    total = p - backends;
+  }
+
+  if(size < total)
+    memcpy(buffer, backends, total + 1);
+  else {
+    memcpy(buffer, backends, size - 1);
+    buffer[size - 1] = '\0';
+  }
+
+  return total;
+}
+
+static int multissl_init(const struct Curl_ssl *backend)
+{
+  const char *env;
+  int i;
+
+  if(Curl_ssl != &Curl_ssl_multi)
+    return 1;
+
+  if(backend) {
+    Curl_ssl = backend;
+    return 0;
+  }
+
+  if(!available_backends[0])
+    return 1;
+
+  env = getenv("CURL_SSL_BACKEND");
+#ifdef CURL_DEFAULT_SSL_BACKEND
+  if(!env)
+    env = CURL_DEFAULT_SSL_BACKEND;
+#endif
+  if(env) {
+    for(i = 0; available_backends[i]; i++) {
+      if(strcasecompare(env, available_backends[i]->info.name)) {
+        Curl_ssl = available_backends[i];
+        return 0;
+      }
+    }
+  }
+
+  /* Fall back to first available backend */
+  Curl_ssl = available_backends[0];
+  return 0;
+}
+
+CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+                              const curl_ssl_backend ***avail)
+{
+  int i;
+
+  if(Curl_ssl != &Curl_ssl_multi)
+    return id == Curl_ssl->info.id ? CURLSSLSET_OK : CURLSSLSET_TOO_LATE;
+
+  for(i = 0; available_backends[i]; i++) {
+    if(available_backends[i]->info.id == id ||
+       (name && strcasecompare(available_backends[i]->info.name, name))) {
+      multissl_init(available_backends[i]);
+      return CURLSSLSET_OK;
+    }
+  }
+
+  if(avail)
+    *avail = (const curl_ssl_backend **)&available_backends;
+  return CURLSSLSET_UNKNOWN_BACKEND;
+}
+
+#else /* USE_SSL */
+CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+                              const curl_ssl_backend ***avail)
+{
+  (void)id;
+  (void)name;
+  (void)avail;
+  return CURLSSLSET_NO_BACKENDS;
 }
 
-#endif /* USE_SSL */
+#endif /* !USE_SSL */
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index 2aabeda20..f1a11ea58 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,6 +23,80 @@
  ***************************************************************************/
 #include "curl_setup.h"
 
+struct connectdata;
+struct ssl_connect_data;
+
+struct Curl_ssl {
+  /*
+   * This *must* be the first entry to allow returning the list of available
+   * backends in curl_global_sslset().
+   */
+  curl_ssl_backend info;
+
+  unsigned have_ca_path:1;      /* supports CAPATH */
+  unsigned have_certinfo:1;     /* supports CURLOPT_CERTINFO */
+  unsigned have_pinnedpubkey:1; /* supports CURLOPT_PINNEDPUBLICKEY */
+  unsigned have_ssl_ctx:1;      /* supports CURLOPT_SSL_CTX_* */
+
+  unsigned support_https_proxy:1; /* supports access via HTTPS proxies */
+
+  size_t sizeof_ssl_backend_data;
+
+  int (*init)(void);
+  void (*cleanup)(void);
+
+  size_t (*version)(char *buffer, size_t size);
+  int (*check_cxn)(struct connectdata *cxn);
+  int (*shutdown)(struct connectdata *conn, int sockindex);
+  bool (*data_pending)(const struct connectdata *conn,
+                       int connindex);
+
+  /* return 0 if a find random is filled in */
+  CURLcode (*random)(struct Curl_easy *data, unsigned char *entropy,
+                     size_t length);
+  bool (*cert_status_request)(void);
+
+  CURLcode (*connect)(struct connectdata *conn, int sockindex);
+  CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex,
+                                  bool *done);
+  void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
+  void (*close)(struct connectdata *conn, int sockindex);
+  void (*close_all)(struct Curl_easy *data);
+  void (*session_free)(void *ptr);
+
+  CURLcode (*set_engine)(struct Curl_easy *data, const char *engine);
+  CURLcode (*set_engine_default)(struct Curl_easy *data);
+  struct curl_slist *(*engines_list)(struct Curl_easy *data);
+
+  bool (*false_start)(void);
+
+  CURLcode (*md5sum)(unsigned char *input, size_t inputlen,
+                     unsigned char *md5sum, size_t md5sumlen);
+  void (*sha256sum)(const unsigned char *input, size_t inputlen,
+                    unsigned char *sha256sum, size_t sha256sumlen);
+};
+
+#ifdef USE_SSL
+extern const struct Curl_ssl *Curl_ssl;
+#endif
+
+int Curl_none_init(void);
+void Curl_none_cleanup(void);
+int Curl_none_shutdown(struct connectdata *conn, int sockindex);
+int Curl_none_check_cxn(struct connectdata *conn);
+CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy,
+                          size_t length);
+void Curl_none_close_all(struct Curl_easy *data);
+void Curl_none_session_free(void *ptr);
+bool Curl_none_data_pending(const struct connectdata *conn, int connindex);
+bool Curl_none_cert_status_request(void);
+CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
+CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
+struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
+bool Curl_none_false_start(void);
+CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
+                          unsigned char *md5sum, size_t md5len);
+
 #include "openssl.h"        /* OpenSSL versions */
 #include "gtls.h"           /* GnuTLS versions */
 #include "nssg.h"           /* NSS versions */
@@ -42,8 +116,8 @@
 #define MD5_DIGEST_LENGTH 16 /* fixed size */
 #endif
 
-#ifndef SHA256_DIGEST_LENGTH
-#define SHA256_DIGEST_LENGTH 32 /* fixed size */
+#ifndef CURL_SHA256_DIGEST_LENGTH
+#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
 #endif
 
 /* see https://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */
@@ -172,8 +246,6 @@ bool Curl_ssl_false_start(void);
 #define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
 
 #else
-/* Set the API backend definition to none */
-#define CURL_SSL_BACKEND CURLSSLBACKEND_NONE
 
 /* When SSL support is not present, just define away these function calls */
 #define Curl_ssl_init() 1
diff --git a/lib/warnless.c b/lib/warnless.c
index fb085c86d..05d9038dc 100644
--- a/lib/warnless.c
+++ b/lib/warnless.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,36 +69,36 @@
 #  error "SIZEOF_INT not defined"
 #endif
 
-#if (CURL_SIZEOF_LONG == 2)
+#if (SIZEOF_LONG == 2)
 #  define CURL_MASK_SLONG  0x7FFFL
 #  define CURL_MASK_ULONG  0xFFFFUL
-#elif (CURL_SIZEOF_LONG == 4)
+#elif (SIZEOF_LONG == 4)
 #  define CURL_MASK_SLONG  0x7FFFFFFFL
 #  define CURL_MASK_ULONG  0xFFFFFFFFUL
-#elif (CURL_SIZEOF_LONG == 8)
+#elif (SIZEOF_LONG == 8)
 #  define CURL_MASK_SLONG  0x7FFFFFFFFFFFFFFFL
 #  define CURL_MASK_ULONG  0xFFFFFFFFFFFFFFFFUL
-#elif (CURL_SIZEOF_LONG == 16)
+#elif (SIZEOF_LONG == 16)
 #  define CURL_MASK_SLONG  0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL
 #  define CURL_MASK_ULONG  0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFUL
 #else
-#  error "CURL_SIZEOF_LONG not defined"
+#  error "SIZEOF_LONG not defined"
 #endif
 
-#if (CURL_SIZEOF_CURL_OFF_T == 2)
+#if (SIZEOF_CURL_OFF_T == 2)
 #  define CURL_MASK_SCOFFT  CURL_OFF_T_C(0x7FFF)
 #  define CURL_MASK_UCOFFT  CURL_OFF_TU_C(0xFFFF)
-#elif (CURL_SIZEOF_CURL_OFF_T == 4)
+#elif (SIZEOF_CURL_OFF_T == 4)
 #  define CURL_MASK_SCOFFT  CURL_OFF_T_C(0x7FFFFFFF)
 #  define CURL_MASK_UCOFFT  CURL_OFF_TU_C(0xFFFFFFFF)
-#elif (CURL_SIZEOF_CURL_OFF_T == 8)
+#elif (SIZEOF_CURL_OFF_T == 8)
 #  define CURL_MASK_SCOFFT  CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF)
 #  define CURL_MASK_UCOFFT  CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFF)
-#elif (CURL_SIZEOF_CURL_OFF_T == 16)
+#elif (SIZEOF_CURL_OFF_T == 16)
 #  define CURL_MASK_SCOFFT  CURL_OFF_T_C(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
 #  define CURL_MASK_UCOFFT  CURL_OFF_TU_C(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
 #else
-#  error "CURL_SIZEOF_CURL_OFF_T not defined"
+#  error "SIZEOF_CURL_OFF_T not defined"
 #endif
 
 #if (SIZEOF_SIZE_T == SIZEOF_SHORT)
@@ -107,10 +107,10 @@
 #elif (SIZEOF_SIZE_T == SIZEOF_INT)
 #  define CURL_MASK_SSIZE_T  CURL_MASK_SINT
 #  define CURL_MASK_USIZE_T  CURL_MASK_UINT
-#elif (SIZEOF_SIZE_T == CURL_SIZEOF_LONG)
+#elif (SIZEOF_SIZE_T == SIZEOF_LONG)
 #  define CURL_MASK_SSIZE_T  CURL_MASK_SLONG
 #  define CURL_MASK_USIZE_T  CURL_MASK_ULONG
-#elif (SIZEOF_SIZE_T == CURL_SIZEOF_CURL_OFF_T)
+#elif (SIZEOF_SIZE_T == SIZEOF_CURL_OFF_T)
 #  define CURL_MASK_SSIZE_T  CURL_MASK_SCOFFT
 #  define CURL_MASK_USIZE_T  CURL_MASK_UCOFFT
 #else
@@ -226,7 +226,7 @@ unsigned long curlx_uztoul(size_t uznum)
 # pragma warning(disable:810) /* conversion may lose significant bits */
 #endif
 
-#if (CURL_SIZEOF_LONG < SIZEOF_SIZE_T)
+#if (SIZEOF_LONG < SIZEOF_SIZE_T)
   DEBUGASSERT(uznum <= (size_t) CURL_MASK_ULONG);
 #endif
   return (unsigned long)(uznum & (size_t) CURL_MASK_ULONG);
@@ -269,7 +269,7 @@ int curlx_sltosi(long slnum)
 #endif
 
   DEBUGASSERT(slnum >= 0);
-#if (SIZEOF_INT < CURL_SIZEOF_LONG)
+#if (SIZEOF_INT < SIZEOF_LONG)
   DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_SINT);
 #endif
   return (int)(slnum & (long) CURL_MASK_SINT);
@@ -291,7 +291,7 @@ unsigned int curlx_sltoui(long slnum)
 #endif
 
   DEBUGASSERT(slnum >= 0);
-#if (SIZEOF_INT < CURL_SIZEOF_LONG)
+#if (SIZEOF_INT < SIZEOF_LONG)
   DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_UINT);
 #endif
   return (unsigned int)(slnum & (long) CURL_MASK_UINT);
diff --git a/lib/wildcard.h b/lib/wildcard.h
index 89d965ccf..198b70b86 100644
--- a/lib/wildcard.h
+++ b/lib/wildcard.h
@@ -26,6 +26,8 @@
 
 #include "llist.h"
 
+#include "llist.h"
+
 /* list of wildcard process states */
 typedef enum {
   CURLWC_CLEAR = 0,
diff --git a/m4/curl-compilers.m4 b/m4/curl-compilers.m4
index 3c87efa09..422946e26 100644
--- a/m4/curl-compilers.m4
+++ b/m4/curl-compilers.m4
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2013, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1998 - 2017, 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
@@ -89,7 +89,7 @@ AC_DEFUN([CURL_CHECK_COMPILER_CLANG], [
     if test -z "$clangver"; then
       if echo $fullclangver | grep "Apple LLVM version " >/dev/null; then
         dnl Starting with XCode 7 / clang 3.7, Apple clang won't tell its 
upstream version
-        clangver=`3.7`
+        clangver="3.7"
       else
         clangver=`echo $fullclangver | "$SED" 's/.*version 
\(@<:@0-9@:>@*\.@<:@0-9@:>@*\).*/\1/'`
       fi
@@ -922,6 +922,11 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [
           dnl Only clang 3.9 or later
           if test "$compiler_num" -ge "309"; then
             tmp_CFLAGS="$tmp_CFLAGS -Wcomma"
+            # avoid the varargs warning, fixed in 4.0
+            # https://bugs.llvm.org/show_bug.cgi?id=29140
+            if test "$compiler_num" -lt "400"; then
+              tmp_CFLAGS="$tmp_CFLAGS -Wno-varargs"
+            fi
           fi
         fi
         ;;
diff --git a/m4/curl-confopts.m4 b/m4/curl-confopts.m4
index d77a884d5..6dcd0f1a6 100644
--- a/m4/curl-confopts.m4
+++ b/m4/curl-confopts.m4
@@ -37,14 +37,14 @@ AC_HELP_STRING([--enable-threaded-resolver],[Enable 
threaded resolver])
 AC_HELP_STRING([--disable-threaded-resolver],[Disable threaded resolver]),
   OPT_THRES=$enableval)
   case "$OPT_THRES" in
-    *)
-      dnl configure option not specified
-      want_thres="yes"
-      ;;
     no)
       dnl --disable-threaded-resolver option used
       want_thres="no"
       ;;
+    *)
+      dnl configure option not specified
+      want_thres="yes"
+      ;;
   esac
   AC_MSG_RESULT([$want_thres])
 ])
diff --git a/packages/OS400/curl.inc.in b/packages/OS400/curl.inc.in
index e4d2d30ca..ff5e28eec 100644
--- a/packages/OS400/curl.inc.in
+++ b/packages/OS400/curl.inc.in
@@ -129,6 +129,8 @@
      d                 c                   X'00100000'
      d CURL_VERSION_HTTPS_PROXY...
      d                 c                   X'00200000'
+     d CURL_VERSION_MULTI_SSL...
+     d                 c                   X'00400000'
       *
      d CURL_HTTPPOST_FILENAME...
      d                 c                   X'00000001'
@@ -1312,6 +1314,8 @@
      d                 c                   10264
      d  CURLOPT_SUPPRESS_CONNECT_HEADERS...
      d                 c                   00265
+     d  CURLOPT_SSH_COMPRESSION...
+     d                 c                   00268
       *
       /if not defined(CURL_NO_OLDIES)
      d  CURLOPT_FILE   c                   10001
diff --git a/projects/build-openssl.bat b/projects/build-openssl.bat
index 0773e07db..33da17401 100644
--- a/projects/build-openssl.bat
+++ b/projects/build-openssl.bat
@@ -138,6 +138,9 @@ rem 
***************************************************************************
   rem Check the start directory exists
   if not exist "%START_DIR%" goto noopenssl
 
+  rem Check that OpenSSL is not unsupported version 1.1.0
+  if not exist "%START_DIR%\ms\do_ms.bat" goto unsupported
+
 :configure
   if "%BUILD_PLATFORM%" == "" (
     if "%VC_VER%" == "6.0" (
@@ -355,6 +358,14 @@ rem 
***************************************************************************
   echo Error: Cannot locate OpenSSL source directory
   goto error
 
+:unsupported
+  echo.
+  echo Error: Unsupported OpenSSL version.
+  echo The pre-generated project files and this build script only support the
+  echo LTS version of OpenSSL ^(v1.0.2^). The next version of this build script
+  echo will support OpenSSL v1.1.0.
+  goto error
+
 :error
   if "%OS%" == "Windows_NT" endlocal
   exit /B 1
diff --git a/scripts/contributors.sh b/scripts/contributors.sh
index fcaaff878..db7aab8e0 100755
--- a/scripts/contributors.sh
+++ b/scripts/contributors.sh
@@ -44,7 +44,7 @@ fi
 # sort all unique names
 # awk them into RELEASE-NOTES format
 (
-git log $start..HEAD | \
+git log --use-mailmap $start..HEAD | \
 egrep -ai '(^Author|^Commit|by):' | \
 cut -d: -f2- | \
 cut '-d(' -f1 | \
diff --git a/scripts/contrithanks.sh b/scripts/contrithanks.sh
index 4d6d47a80..d3dad3e90 100755
--- a/scripts/contrithanks.sh
+++ b/scripts/contrithanks.sh
@@ -35,7 +35,7 @@ fi
 cat ./docs/THANKS
 
 (
-git log $start..HEAD | \
+git log --use-mailmap $start..HEAD | \
 egrep -ai '(^Author|^Commit|by):' | \
 cut -d: -f2- | \
 cut '-d(' -f1 | \
diff --git a/scripts/updatemanpages.pl b/scripts/updatemanpages.pl
index e144bad11..6a58dbd42 100755
--- a/scripts/updatemanpages.pl
+++ b/scripts/updatemanpages.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/env perl
+#!/usr/bin/perl
 #***************************************************************************
 #                                  _   _ ____  _
 #  Project                     ___| | | |  _ \| |
diff --git a/scripts/zsh.pl b/scripts/zsh.pl
index 5b5ad13e7..fbafde164 100755
--- a/scripts/zsh.pl
+++ b/scripts/zsh.pl
@@ -54,10 +54,11 @@ sub parse_main_opts {
         $option .= '}' if defined $short;
         $option .= '\'[' . trim($desc) . ']\'' if defined $desc;
 
-        $option .= ":$arg" if defined $arg;
+        $option .= ":'$arg'" if defined $arg;
 
         $option .= ':_files'
-            if defined $arg and ($arg eq 'FILE' || $arg eq 'DIR');
+            if defined $arg and ($arg eq '<file>' || $arg eq '<filename>'
+                || $arg eq '<dir>');
 
         push @list, $option;
     }
diff --git a/src/Makefile.am b/src/Makefile.am
index a6bab6bdc..f436524bd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,6 +45,8 @@ bin_PROGRAMS = gnurl
 
 SUBDIRS = ../docs
 
+SUBDIRS = ../docs
+
 if USE_CPPFLAG_CURL_STATICLIB
 AM_CPPFLAGS += -DCURL_STATICLIB
 endif
@@ -95,7 +97,6 @@ EXTRA_DIST = mkhelp.pl makefile.dj Makefile.b32               
\
 
 # Use absolute directory to disable VPATH
 MANPAGE=$(abs_top_builddir)/docs/gnurl.1
-
 README=$(top_srcdir)/docs/MANUAL
 MKHELP=$(top_srcdir)/src/mkhelp.pl
 HUGE=tool_hugehelp.c
diff --git a/src/Makefile.inc b/src/Makefile.inc
index 5074f8fc6..45b4967f6 100644
--- a/src/Makefile.inc
+++ b/src/Makefile.inc
@@ -45,7 +45,6 @@ CURL_CFILES = \
        tool_libinfo.c \
        tool_main.c \
        tool_metalink.c \
-       tool_mfiles.c \
        tool_msgs.c \
        tool_operate.c \
        tool_operhlp.c \
@@ -86,7 +85,6 @@ CURL_HFILES = \
        tool_libinfo.h \
        tool_main.h \
        tool_metalink.h \
-       tool_mfiles.h \
        tool_msgs.h \
        tool_operate.h \
        tool_operhlp.h \
diff --git a/src/Makefile.m32 b/src/Makefile.m32
index 22e11e8e0..836fa2738 100644
--- a/src/Makefile.m32
+++ b/src/Makefile.m32
@@ -5,7 +5,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1999 - 2015, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1999 - 2017, 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,9 +62,9 @@ endif
 ifndef LIBXML2_PATH
 LIBXML2_PATH = ../../libxml2-2.9.2
 endif
-# Edit the path below to point to the base of your libidn package.
-ifndef LIBIDN_PATH
-LIBIDN_PATH = ../../libidn-1.32
+# Edit the path below to point to the base of your libidn2 package.
+ifndef LIBIDN2_PATH
+LIBIDN2_PATH = ../../libidn2-2.0.3
 endif
 # Edit the path below to point to the base of your MS IDN package.
 # Microsoft Internationalized Domain Names (IDN) Mitigation APIs 1.1
@@ -168,9 +168,7 @@ ZLIB = 1
 endif
 ifeq ($(findstring -ssh2,$(CFG)),-ssh2)
 SSH2 = 1
-ifneq ($(findstring -winssl,$(CFG)),-winssl)
 SSL = 1
-endif
 ZLIB = 1
 endif
 ifeq ($(findstring -ssl,$(CFG)),-ssl)
@@ -179,8 +177,8 @@ endif
 ifeq ($(findstring -zlib,$(CFG)),-zlib)
 ZLIB = 1
 endif
-ifeq ($(findstring -idn,$(CFG)),-idn)
-IDN = 1
+ifeq ($(findstring -idn2,$(CFG)),-idn2)
+IDN2 = 1
 endif
 ifeq ($(findstring -winidn,$(CFG)),-winidn)
 WINIDN = 1
@@ -206,6 +204,11 @@ NGHTTP2 = 1
 endif
 
 INCLUDES = -I. -I../include -I../lib
+ifdef SSL
+  ifdef WINSSL
+    CFLAGS += -DCURL_WITH_MULTI_SSL
+  endif
+endif
 
 ifdef DYN
   curl_DEPENDENCIES = $(PROOT)/lib/libgnurldll.a $(PROOT)/lib/libgnurl.dll
@@ -274,19 +277,19 @@ ifdef SSL
   INCLUDES += -I"$(OPENSSL_INCLUDE)"
   CFLAGS += -DUSE_OPENSSL
   curl_LDADD += -L"$(OPENSSL_LIBPATH)" $(OPENSSL_LIBS)
-else
+endif
 ifdef WINSSL
+  CFLAGS += -DUSE_SCHANNEL
   curl_LDADD += -lcrypt32
 endif
-endif
 ifdef ZLIB
   INCLUDES += -I"$(ZLIB_PATH)"
   CFLAGS += -DHAVE_LIBZ -DHAVE_ZLIB_H
   curl_LDADD += -L"$(ZLIB_PATH)" -lz
 endif
-ifdef IDN
-  CFLAGS += -DUSE_LIBIDN
-  curl_LDADD += -L"$(LIBIDN_PATH)/lib" -lidn
+ifdef IDN2
+  CFLAGS += -DUSE_LIBIDN2
+  curl_LDADD += -L"$(LIBIDN2_PATH)/lib" -lidn2
 else
 ifdef WINIDN
   CFLAGS += -DUSE_WIN32_IDN
@@ -307,9 +310,6 @@ ifdef METALINK
 endif
 ifdef SSPI
   CFLAGS += -DUSE_WINDOWS_SSPI
-  ifdef WINSSL
-    CFLAGS += -DUSE_SCHANNEL
-  endif
 endif
 ifdef IPV6
   CFLAGS += -DENABLE_IPV6 -D_WIN32_WINNT=0x0501
diff --git a/src/tool_cb_dbg.c b/src/tool_cb_dbg.c
index b4fbe0bb9..aa1ef857c 100644
--- a/src/tool_cb_dbg.c
+++ b/src/tool_cb_dbg.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -238,37 +238,40 @@ static void dump(const char *timebuf, const char *text,
     if(tracetype == TRACE_BIN) {
       /* hex not disabled, show it */
       for(c = 0; c < width; c++)
-        if(i+c < size)
-          fprintf(stream, "%02x ", ptr[i+c]);
+        if(i + c < size)
+          fprintf(stream, "%02x ", ptr[i + c]);
         else
           fputs("   ", stream);
     }
 
-    for(c = 0; (c < width) && (i+c < size); c++) {
+    for(c = 0; (c < width) && (i + c < size); c++) {
       /* check for 0D0A; if found, skip past and start a new line of output */
       if((tracetype == TRACE_ASCII) &&
-         (i+c+1 < size) && (ptr[i+c] == 0x0D) && (ptr[i+c+1] == 0x0A)) {
-        i += (c+2-width);
+         (i + c + 1 < size) && (ptr[i + c] == 0x0D) &&
+         (ptr[i + c + 1] == 0x0A)) {
+        i += (c + 2 - width);
         break;
       }
 #ifdef CURL_DOES_CONVERSIONS
       /* repeat the 0D0A check above but use the host encoding for CRLF */
       if((tracetype == TRACE_ASCII) &&
-         (i+c+1 < size) && (ptr[i+c] == '\r') && (ptr[i+c+1] == '\n')) {
-        i += (c+2-width);
+         (i + c + 1 < size) && (ptr[i + c] == '\r') &&
+         (ptr[i + c + 1] == '\n')) {
+        i += (c + 2 - width);
         break;
       }
       /* convert to host encoding and print this character */
-      fprintf(stream, "%c", convert_char(infotype, ptr[i+c]));
+      fprintf(stream, "%c", convert_char(infotype, ptr[i + c]));
 #else
       (void)infotype;
-      fprintf(stream, "%c", ((ptr[i+c] >= 0x20) && (ptr[i+c] < 0x80)) ?
-              ptr[i+c] : UNPRINTABLE_CHAR);
+      fprintf(stream, "%c", ((ptr[i + c] >= 0x20) && (ptr[i + c] < 0x80)) ?
+              ptr[i + c] : UNPRINTABLE_CHAR);
 #endif /* CURL_DOES_CONVERSIONS */
       /* check again for 0D0A, to avoid an extra \n if it's at width */
       if((tracetype == TRACE_ASCII) &&
-         (i+c+2 < size) && (ptr[i+c+1] == 0x0D) && (ptr[i+c+2] == 0x0A)) {
-        i += (c+3-width);
+         (i + c + 2 < size) && (ptr[i + c + 1] == 0x0D) &&
+         (ptr[i + c + 2] == 0x0A)) {
+        i += (c + 3 - width);
         break;
       }
     }
diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c
index 0e13eec50..bb982d2e4 100644
--- a/src/tool_cb_hdr.c
+++ b/src/tool_cb_hdr.c
@@ -146,7 +146,7 @@ static char *parse_filename(const char *ptr, size_t len)
   char  stop = '\0';
 
   /* simple implementation of strndup() */
-  copy = malloc(len+1);
+  copy = malloc(len + 1);
   if(!copy)
     return NULL;
   memcpy(copy, ptr, len);
diff --git a/src/tool_cb_prg.c b/src/tool_cb_prg.c
index d4ecb3cef..992b96d97 100644
--- a/src/tool_cb_prg.c
+++ b/src/tool_cb_prg.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2014, 2017, 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
@@ -44,7 +44,7 @@ int tool_progress_cb(void *clientp,
   /* The original progress-bar source code was written for curl by Lars Aas,
      and this new edition inherits some of his concepts. */
 
-  char line[MAX_BARLENGTH+1];
+  char line[MAX_BARLENGTH + 1];
   char format[40];
   double frac;
   double percent;
diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c
index 675e88b45..755195ced 100644
--- a/src/tool_cfgable.c
+++ b/src/tool_cfgable.c
@@ -140,11 +140,11 @@ static void free_config_fields(struct OperationConfig 
*config)
   curl_slist_free_all(config->headers);
   curl_slist_free_all(config->proxyheaders);
 
-  if(config->httppost) {
-    curl_formfree(config->httppost);
-    config->httppost = NULL;
+  if(config->mimepost) {
+    curl_mime_free(config->mimepost);
+    config->mimepost = NULL;
   }
-  config->last_post = NULL;
+  config->mimecurrent = NULL;
 
   curl_slist_free_all(config->telnet_options);
   curl_slist_free_all(config->resolve);
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index 254805c8c..23943fe7b 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -170,8 +170,8 @@ struct OperationConfig {
   time_t condtime;
   struct curl_slist *headers;
   struct curl_slist *proxyheaders;
-  struct curl_httppost *httppost;
-  struct curl_httppost *last_post;
+  curl_mime *mimepost;
+  curl_mime *mimecurrent;
   struct curl_slist *telnet_options;
   struct curl_slist *resolve;
   struct curl_slist *connect_to;
@@ -247,6 +247,7 @@ struct OperationConfig {
                                      from user callbacks */
   curl_error synthetic_error;     /* if non-zero, it overrides any libcurl
                                      error */
+  bool ssh_compression;           /* enable/disable SSH compression */
   struct GlobalConfig *global;
   struct OperationConfig *prev;
   struct OperationConfig *next;   /* Always last in the struct */
diff --git a/src/tool_easysrc.c b/src/tool_easysrc.c
index e3c9d1aa1..fc6600261 100644
--- a/src/tool_easysrc.c
+++ b/src/tool_easysrc.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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 @@ struct slist_wc *easysrc_data = NULL; /* Build slists, forms 
etc. */
 struct slist_wc *easysrc_code = NULL; /* Setopt calls */
 struct slist_wc *easysrc_toohard = NULL; /* Unconvertible setopt */
 struct slist_wc *easysrc_clean = NULL;  /* Clean up allocated data */
-int easysrc_form_count = 0;
+int easysrc_mime_count = 0;
 int easysrc_slist_count = 0;
 
 static const char *const srchead[]={
@@ -141,11 +141,11 @@ CURLcode easysrc_perform(void)
     const char *c;
     CHKRET(easysrc_add(&easysrc_code, ""));
     /* Preamble comment */
-    for(i=0; ((c = srchard[i]) != NULL); i++)
+    for(i = 0; ((c = srchard[i]) != NULL); i++)
       CHKRET(easysrc_add(&easysrc_code, c));
     /* Each unconverted option */
     if(easysrc_toohard) {
-      for(ptr=easysrc_toohard->first; ptr; ptr = ptr->next)
+      for(ptr = easysrc_toohard->first; ptr; ptr = ptr->next)
         CHKRET(easysrc_add(&easysrc_code, ptr->data));
     }
     CHKRET(easysrc_add(&easysrc_code, ""));
@@ -189,12 +189,12 @@ void dumpeasysrc(struct GlobalConfig *config)
     int i;
     const char *c;
 
-    for(i=0; ((c = srchead[i]) != NULL); i++)
+    for(i = 0; ((c = srchead[i]) != NULL); i++)
       fprintf(out, "%s\n", c);
 
     /* Declare variables used for complex setopt values */
     if(easysrc_decl) {
-      for(ptr=easysrc_decl->first; ptr; ptr = ptr->next)
+      for(ptr = easysrc_decl->first; ptr; ptr = ptr->next)
         fprintf(out, "  %s\n", ptr->data);
     }
 
@@ -202,13 +202,13 @@ void dumpeasysrc(struct GlobalConfig *config)
     if(easysrc_data) {
       fprintf(out, "\n");
 
-      for(ptr=easysrc_data->first; ptr; ptr = ptr->next)
+      for(ptr = easysrc_data->first; ptr; ptr = ptr->next)
         fprintf(out, "  %s\n", ptr->data);
     }
 
     fprintf(out, "\n");
     if(easysrc_code) {
-      for(ptr=easysrc_code->first; ptr; ptr = ptr->next) {
+      for(ptr = easysrc_code->first; ptr; ptr = ptr->next) {
         if(ptr->data[0]) {
           fprintf(out, "  %s\n", ptr->data);
         }
@@ -219,11 +219,11 @@ void dumpeasysrc(struct GlobalConfig *config)
     }
 
     if(easysrc_clean) {
-      for(ptr=easysrc_clean->first; ptr; ptr = ptr->next)
+      for(ptr = easysrc_clean->first; ptr; ptr = ptr->next)
         fprintf(out, "  %s\n", ptr->data);
     }
 
-    for(i=0; ((c = srcend[i]) != NULL); i++)
+    for(i = 0; ((c = srcend[i]) != NULL); i++)
       fprintf(out, "%s\n", c);
 
     if(fopened)
diff --git a/src/tool_easysrc.h b/src/tool_easysrc.h
index 54607b861..fd799ab84 100644
--- a/src/tool_easysrc.h
+++ b/src/tool_easysrc.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -32,7 +32,7 @@ extern struct slist_wc *easysrc_code; /* Setopt calls etc. */
 extern struct slist_wc *easysrc_toohard; /* Unconvertible setopt */
 extern struct slist_wc *easysrc_clean;  /* Clean up (reverse order) */
 
-extern int easysrc_form_count;  /* Number of curl_httppost variables */
+extern int easysrc_mime_count;  /* Number of curl_mime variables */
 extern int easysrc_slist_count; /* Number of curl_slist variables */
 
 extern CURLcode easysrc_init(void);
diff --git a/src/tool_formparse.c b/src/tool_formparse.c
index 952377c49..4645a761e 100644
--- a/src/tool_formparse.c
+++ b/src/tool_formparse.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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 "tool_setup.h"
 
+#include "mime.h"
 #include "strcase.h"
 
 #define ENABLE_CURLX_PRINTF
@@ -29,7 +30,6 @@
 
 #include "tool_cfgable.h"
 #include "tool_convert.h"
-#include "tool_mfiles.h"
 #include "tool_msgs.h"
 #include "tool_formparse.h"
 
@@ -77,10 +77,10 @@ static char *get_param_word(char **str, char **end_pos)
           while(ptr < *end_pos);
           *end_pos = ptr2;
         }
-        while(*ptr && NULL==strchr(end_chars, *ptr))
+        while(*ptr && NULL == strchr(end_chars, *ptr))
           ++ptr;
         *str = ptr;
-        return word_begin+1;
+        return word_begin + 1;
       }
       ++ptr;
     }
@@ -88,12 +88,303 @@ static char *get_param_word(char **str, char **end_pos)
     ptr = word_begin;
   }
 
-  while(*ptr && NULL==strchr(end_chars, *ptr))
+  while(*ptr && NULL == strchr(end_chars, *ptr))
     ++ptr;
   *str = *end_pos = ptr;
   return word_begin;
 }
 
+/* Append slist item and return -1 if failed. */
+static int slist_append(struct curl_slist **plist, const char *data)
+{
+  struct curl_slist *s = curl_slist_append(*plist, data);
+
+  if(!s)
+    return -1;
+
+  *plist = s;
+  return 0;
+}
+
+/* Read headers from a file and append to list. */
+static int read_field_headers(struct OperationConfig *config,
+                              const char *filename, FILE *fp,
+                              struct curl_slist **pheaders)
+{
+  size_t hdrlen = 0;
+  size_t pos = 0;
+  int c;
+  bool incomment = FALSE;
+  int lineno = 1;
+  char hdrbuf[999]; /* Max. header length + 1. */
+
+  for(;;) {
+    c = getc(fp);
+    if(c == EOF || (!pos && !ISSPACE(c))) {
+      /* Strip and flush the current header. */
+      while(hdrlen && ISSPACE(hdrbuf[hdrlen - 1]))
+        hdrlen--;
+      if(hdrlen) {
+        hdrbuf[hdrlen] = '\0';
+        if(slist_append(pheaders, hdrbuf)) {
+          fprintf(config->global->errors,
+                  "Out of memory for field headers!\n");
+          return -1;
+        }
+        hdrlen = 0;
+      }
+    }
+
+    switch(c) {
+    case EOF:
+      if(ferror(fp)) {
+        fprintf(config->global->errors,
+                "Header file %s read error: %s\n", filename, strerror(errno));
+        return -1;
+      }
+      return 0;    /* Done. */
+    case '\r':
+      continue;    /* Ignore. */
+    case '\n':
+      pos = 0;
+      incomment = FALSE;
+      lineno++;
+      continue;
+    case '#':
+      if(!pos)
+        incomment = TRUE;
+      break;
+    }
+
+    pos++;
+    if(!incomment) {
+      if(hdrlen == sizeof hdrbuf - 1) {
+        warnf(config->global, "File %s line %d: header too long (truncated)\n",
+              filename, lineno);
+        c = ' ';
+      }
+      if(hdrlen <= sizeof hdrbuf - 1)
+        hdrbuf[hdrlen++] = (char) c;
+    }
+  }
+  /* NOTREACHED */
+}
+
+static int get_param_part(struct OperationConfig *config, char **str,
+                          char **pdata, char **ptype, char **pfilename,
+                          char **pencoder, struct curl_slist **pheaders)
+{
+  char *p = *str;
+  char *type = NULL;
+  char *filename = NULL;
+  char *encoder = NULL;
+  char *endpos;
+  char *tp;
+  char sep;
+  char type_major[128] = "";
+  char type_minor[128] = "";
+  char *endct = NULL;
+  struct curl_slist *headers = NULL;
+
+  if(ptype)
+    *ptype = NULL;
+  if(pfilename)
+    *pfilename = NULL;
+  if(pheaders)
+    *pheaders = NULL;
+  if(pencoder)
+    *pencoder = NULL;
+  while(ISSPACE(*p))
+    p++;
+  tp = p;
+  *pdata = get_param_word(&p, &endpos);
+  /* If not quoted, strip trailing spaces. */
+  if(*pdata == tp)
+    while(endpos > *pdata && ISSPACE(endpos[-1]))
+      endpos--;
+  sep = *p;
+  *endpos = '\0';
+  while(sep == ';') {
+    while(ISSPACE(*++p))
+      ;
+
+    if(!endct && checkprefix("type=", p)) {
+      for(p += 5; ISSPACE(*p); p++)
+        ;
+      /* set type pointer */
+      type = p;
+
+      /* verify that this is a fine type specifier */
+      if(2 != sscanf(type, "%127[^/ ]/%127[^;, \n]", type_major, type_minor)) {
+        warnf(config->global, "Illegally formatted content-type field!\n");
+        curl_slist_free_all(headers);
+        return -1; /* illegal content-type syntax! */
+      }
+
+      /* now point beyond the content-type specifier */
+      endpos = type + strlen(type_major) + strlen(type_minor) + 1;
+      for(p = endpos; ISSPACE(*p); p++)
+        ;
+      while(*p && *p != ';' && *p != ',')
+        p++;
+      endct = p;
+      sep = *p;
+    }
+    else if(checkprefix("filename=", p)) {
+      if(endct) {
+        *endct = '\0';
+        endct = NULL;
+      }
+      for(p += 9; ISSPACE(*p); p++)
+        ;
+      tp = p;
+      filename = get_param_word(&p, &endpos);
+      /* If not quoted, strip trailing spaces. */
+      if(filename == tp)
+        while(endpos > filename && ISSPACE(endpos[-1]))
+          endpos--;
+      sep = *p;
+      *endpos = '\0';
+    }
+    else if(checkprefix("headers=", p)) {
+      if(endct) {
+        *endct = '\0';
+        endct = NULL;
+      }
+      p += 8;
+      if(*p == '@' || *p == '<') {
+        char *hdrfile;
+        FILE *fp;
+        /* Read headers from a file. */
+
+        do {
+          p++;
+        } while(ISSPACE(*p));
+        tp = p;
+        hdrfile = get_param_word(&p, &endpos);
+        /* If not quoted, strip trailing spaces. */
+        if(hdrfile == tp)
+          while(endpos > hdrfile && ISSPACE(endpos[-1]))
+            endpos--;
+        sep = *p;
+        *endpos = '\0';
+        /* TODO: maybe special fopen for VMS? */
+        fp = fopen(hdrfile, FOPEN_READTEXT);
+        if(!fp)
+          warnf(config->global, "Cannot read from %s: %s\n", hdrfile,
+                strerror(errno));
+        else {
+          int i = read_field_headers(config, hdrfile, fp, &headers);
+
+          fclose(fp);
+          if(i) {
+            curl_slist_free_all(headers);
+            return -1;
+          }
+        }
+      }
+      else {
+        char *hdr;
+
+        while(ISSPACE(*p))
+          p++;
+        tp = p;
+        hdr = get_param_word(&p, &endpos);
+        /* If not quoted, strip trailing spaces. */
+        if(hdr == tp)
+          while(endpos > hdr && ISSPACE(endpos[-1]))
+            endpos--;
+        sep = *p;
+        *endpos = '\0';
+        if(slist_append(&headers, hdr)) {
+          fprintf(config->global->errors, "Out of memory for field header!\n");
+          curl_slist_free_all(headers);
+          return -1;
+        }
+      }
+    }
+    else if(checkprefix("encoder=", p)) {
+      if(endct) {
+        *endct = '\0';
+        endct = NULL;
+      }
+      for(p += 8; ISSPACE(*p); p++)
+        ;
+      tp = p;
+      encoder = get_param_word(&p, &endpos);
+      /* If not quoted, strip trailing spaces. */
+      if(encoder == tp)
+        while(endpos > encoder && ISSPACE(endpos[-1]))
+          endpos--;
+      sep = *p;
+      *endpos = '\0';
+    }
+    else {
+      /* unknown prefix, skip to next block */
+      char *unknown = get_param_word(&p, &endpos);
+
+      sep = *p;
+      if(endct)
+        endct = p;
+      else {
+        *endpos = '\0';
+         if(*unknown)
+           warnf(config->global, "skip unknown form field: %s\n", unknown);
+      }
+    }
+  }
+
+  /* Terminate and strip content type. */
+  if(type) {
+    if(!endct)
+      endct = type + strlen(type);
+    while(endct > type && ISSPACE(endct[-1]))
+      endct--;
+    *endct = '\0';
+  }
+
+  if(ptype)
+    *ptype = type;
+  else if(type)
+    warnf(config->global, "Field content type not allowed here: %s\n", type);
+
+  if(pfilename)
+    *pfilename = filename;
+  else if(filename)
+    warnf(config->global,
+          "Field file name not allowed here: %s\n", filename);
+
+  if(pencoder)
+    *pencoder = encoder;
+  else if(encoder)
+    warnf(config->global,
+          "Field encoder not allowed here: %s\n", encoder);
+
+  if(pheaders)
+    *pheaders = headers;
+  else if(headers) {
+    warnf(config->global,
+          "Field headers not allowed here: %s\n", headers->data);
+    curl_slist_free_all(headers);
+  }
+
+  *str = p;
+  return sep & 0xFF;
+}
+
+/* Check if file is "-". If so, use a callback to read OUR stdin (to
+ * workaround Windows DLL file handle caveat).
+ * Else use curl_mime_filedata(). */
+static CURLcode file_or_stdin(curl_mimepart *part, const char *file)
+{
+  if(strcmp(file, "-"))
+    return curl_mime_filedata(part, file);
+
+  return curl_mime_data_cb(part, -1, (curl_read_callback) fread,
+                           (curl_seek_callback) fseek, NULL, stdin);
+}
+
+
 /***************************************************************************
  *
  * formparse()
@@ -143,219 +434,315 @@ static char *get_param_word(char **str, char **end_pos)
 
 int formparse(struct OperationConfig *config,
               const char *input,
-              struct curl_httppost **httppost,
-              struct curl_httppost **last_post,
+              curl_mime **mimepost,
+              curl_mime **mimecurrent,
               bool literal_value)
 {
-  /* nextarg MUST be a string in the format 'name=contents' and we'll
+  /* input MUST be a string in the format 'name=contents' and we'll
      build a linked list with the info */
-  char name[256];
+  char *name = NULL;
   char *contents = NULL;
-  char type_major[128] = "";
-  char type_minor[128] = "";
   char *contp;
+  char *data;
   char *type = NULL;
-  char *sep;
-
-  if((1 == sscanf(input, "%255[^=]=", name)) &&
-     ((contp = strchr(input, '=')) != NULL)) {
-    /* the input was using the correct format */
-
-    /* Allocate the contents */
-    contents = strdup(contp+1);
-    if(!contents) {
-      fprintf(config->global->errors, "out of memory\n");
+  char *filename = NULL;
+  char *encoder = NULL;
+  struct curl_slist *headers = NULL;
+  curl_mimepart *part = NULL;
+  CURLcode res;
+  int sep = '\0';
+
+  /* Allocate the main mime structure if needed. */
+  if(!*mimepost) {
+    *mimepost = curl_mime_init(config->easy);
+    if(!*mimepost) {
+      warnf(config->global, "curl_mime_init failed!\n");
       return 1;
     }
-    contp = contents;
+    *mimecurrent = *mimepost;
+  }
 
-    if('@' == contp[0] && !literal_value) {
+  /* Make a copy we can overwrite. */
+  contents = strdup(input);
+  if(!contents) {
+    fprintf(config->global->errors, "out of memory\n");
+    return 2;
+  }
 
-      /* we use the @-letter to indicate file name(s) */
+  /* Scan for the end of the name. */
+  contp = strchr(contents, '=');
+  if(contp) {
+    if(contp > contents)
+      name = contents;
+    *contp++ = '\0';
+
+    if(*contp == '(' && !literal_value) {
+      curl_mime *subparts;
+
+      /* Starting a multipart. */
+      sep = get_param_part(config, &contp, &data, &type, NULL, NULL, &headers);
+      if(sep < 0) {
+        Curl_safefree(contents);
+        return 3;
+      }
+      subparts = curl_mime_init(config->easy);
+      if(!subparts) {
+        warnf(config->global, "curl_mime_init failed!\n");
+        curl_slist_free_all(headers);
+        Curl_safefree(contents);
+        return 4;
+      }
+      part = curl_mime_addpart(*mimecurrent);
+      if(!part) {
+        warnf(config->global, "curl_mime_addpart failed!\n");
+        curl_mime_free(subparts);
+        curl_slist_free_all(headers);
+        Curl_safefree(contents);
+        return 5;
+      }
+      if(curl_mime_subparts(part, subparts)) {
+        warnf(config->global, "curl_mime_subparts failed!\n");
+        curl_mime_free(subparts);
+        curl_slist_free_all(headers);
+        Curl_safefree(contents);
+        return 6;
+      }
+      *mimecurrent = subparts;
+      if(curl_mime_headers(part, headers, 1)) {
+        warnf(config->global, "curl_mime_headers failed!\n");
+        curl_slist_free_all(headers);
+        Curl_safefree(contents);
+        return 7;
+      }
+      if(curl_mime_type(part, type)) {
+        warnf(config->global, "curl_mime_type failed!\n");
+        Curl_safefree(contents);
+        return 8;
+      }
+    }
+    else if(!name && !strcmp(contp, ")") && !literal_value) {
+      /* Ending a mutipart. */
+      if(*mimecurrent == *mimepost) {
+        warnf(config->global, "no multipart to terminate!\n");
+        Curl_safefree(contents);
+        return 9;
+        }
+      *mimecurrent = (*mimecurrent)->parent->parent;
+    }
+    else if('@' == contp[0] && !literal_value) {
 
-      struct multi_files *multi_start = NULL;
-      struct multi_files *multi_current = NULL;
+      /* we use the @-letter to indicate file name(s) */
 
-      char *ptr = contp;
-      char *end = ptr + strlen(ptr);
+      curl_mime *subparts = NULL;
 
       do {
         /* since this was a file, it may have a content-type specifier
            at the end too, or a filename. Or both. */
-        char *filename = NULL;
-        char *word_end;
-        bool semicolon;
-
-        type = NULL;
-
-        ++ptr;
-        contp = get_param_word(&ptr, &word_end);
-        semicolon = (';' == *ptr) ? TRUE : FALSE;
-        *word_end = '\0'; /* terminate the contp */
-
-        /* have other content, continue parse */
-        while(semicolon) {
-          /* have type or filename field */
-          ++ptr;
-          while(*ptr && (ISSPACE(*ptr)))
-            ++ptr;
-
-          if(checkprefix("type=", ptr)) {
-            /* set type pointer */
-            type = &ptr[5];
-
-            /* verify that this is a fine type specifier */
-            if(2 != sscanf(type, "%127[^/]/%127[^;,\n]",
-                           type_major, type_minor)) {
-              warnf(config->global,
-                    "Illegally formatted content-type field!\n");
-              Curl_safefree(contents);
-              FreeMultiInfo(&multi_start, &multi_current);
-              return 2; /* illegal content-type syntax! */
-            }
-
-            /* now point beyond the content-type specifier */
-            sep = type + strlen(type_major)+strlen(type_minor)+1;
-
-            /* there's a semicolon following - we check if it is a filename
-               specified and if not we simply assume that it is text that
-               the user wants included in the type and include that too up
-               to the next sep. */
-            ptr = sep;
-            if(*sep==';') {
-              if(!checkprefix(";filename=", sep)) {
-                ptr = sep + 1;
-                (void)get_param_word(&ptr, &sep);
-                semicolon = (';' == *ptr) ? TRUE : FALSE;
-              }
-            }
-            else
-              semicolon = FALSE;
+        ++contp;
+        sep = get_param_part(config, &contp,
+                             &data, &type, &filename, &encoder, &headers);
+        if(sep < 0) {
+          if(subparts != *mimecurrent)
+            curl_mime_free(subparts);
+          Curl_safefree(contents);
+          return 10;
+        }
 
-            if(*sep)
-              *sep = '\0'; /* zero terminate type string */
-          }
-          else if(checkprefix("filename=", ptr)) {
-            ptr += 9;
-            filename = get_param_word(&ptr, &word_end);
-            semicolon = (';' == *ptr) ? TRUE : FALSE;
-            *word_end = '\0';
-          }
+        /* now contp point to comma or string end.
+           If more files to come, make sure we have multiparts. */
+        if(!subparts) {
+          if(sep != ',')    /* If there is a single file. */
+            subparts = *mimecurrent;
           else {
-            /* unknown prefix, skip to next block */
-            char *unknown = NULL;
-            unknown = get_param_word(&ptr, &word_end);
-            semicolon = (';' == *ptr) ? TRUE : FALSE;
-            if(*unknown) {
-              *word_end = '\0';
-              warnf(config->global, "skip unknown form field: %s\n", unknown);
+            subparts = curl_mime_init(config->easy);
+            if(!subparts) {
+              warnf(config->global, "curl_mime_init failed!\n");
+              curl_slist_free_all(headers);
+              Curl_safefree(contents);
+              return 11;
             }
           }
         }
-        /* now ptr point to comma or string end */
 
+        /* Allocate a part for that file. */
+        part = curl_mime_addpart(subparts);
+        if(!part) {
+          warnf(config->global, "curl_mime_addpart failed!\n");
+          if(subparts != *mimecurrent)
+            curl_mime_free(subparts);
+          curl_slist_free_all(headers);
+          Curl_safefree(contents);
+          return 12;
+        }
 
-        /* if type == NULL curl_formadd takes care of the problem */
+        /* Set part headers. */
+        if(curl_mime_headers(part, headers, 1)) {
+          warnf(config->global, "curl_mime_headers failed!\n");
+          if(subparts != *mimecurrent)
+            curl_mime_free(subparts);
+          curl_slist_free_all(headers);
+          Curl_safefree(contents);
+          return 13;
+        }
 
-        if(*contp && !AddMultiFiles(contp, type, filename, &multi_start,
-                          &multi_current)) {
-          warnf(config->global, "Error building form post!\n");
+        /* Setup file in part. */
+        res = file_or_stdin(part, data);
+        if(res) {
+          warnf(config->global, "setting file %s  failed!\n", data);
+          if(res != CURLE_READ_ERROR) {
+            if(subparts != *mimecurrent)
+              curl_mime_free(subparts);
+            Curl_safefree(contents);
+            return 14;
+          }
+        }
+        if(filename && curl_mime_filename(part, filename)) {
+          warnf(config->global, "curl_mime_filename failed!\n");
+          if(subparts != *mimecurrent)
+            curl_mime_free(subparts);
           Curl_safefree(contents);
-          FreeMultiInfo(&multi_start, &multi_current);
-          return 3;
+          return 15;
+        }
+        if(curl_mime_type(part, type)) {
+          warnf(config->global, "curl_mime_type failed!\n");
+          if(subparts != *mimecurrent)
+            curl_mime_free(subparts);
+          Curl_safefree(contents);
+          return 16;
+        }
+        if(curl_mime_encoder(part, encoder)) {
+          warnf(config->global, "curl_mime_encoder failed!\n");
+          if(subparts != *mimecurrent)
+            curl_mime_free(subparts);
+          Curl_safefree(contents);
+          return 17;
         }
 
-        /* *ptr could be '\0', so we just check with the string end */
-      } while(ptr < end); /* loop if there's another file name */
+        /* *contp could be '\0', so we just check with the delimiter */
+      } while(sep); /* loop if there's another file name */
 
       /* now we add the multiple files section */
-      if(multi_start) {
-        struct curl_forms *forms = NULL;
-        struct multi_files *start = multi_start;
-        unsigned int i, count = 0;
-        while(start) {
-          start = start->next;
-          ++count;
-        }
-        forms = malloc((count+1)*sizeof(struct curl_forms));
-        if(!forms) {
-          fprintf(config->global->errors, "Error building form post!\n");
+      if(subparts != *mimecurrent) {
+        part = curl_mime_addpart(*mimecurrent);
+        if(!part) {
+          warnf(config->global, "curl_mime_addpart failed!\n");
+          curl_mime_free(subparts);
           Curl_safefree(contents);
-          FreeMultiInfo(&multi_start, &multi_current);
-          return 4;
-        }
-        for(i = 0, start = multi_start; i < count; ++i, start = start->next) {
-          forms[i].option = start->form.option;
-          forms[i].value = start->form.value;
+          return 18;
         }
-        forms[count].option = CURLFORM_END;
-        FreeMultiInfo(&multi_start, &multi_current);
-        if(curl_formadd(httppost, last_post,
-                        CURLFORM_COPYNAME, name,
-                        CURLFORM_ARRAY, forms, CURLFORM_END) != 0) {
-          warnf(config->global, "curl_formadd failed!\n");
-          Curl_safefree(forms);
+        if(curl_mime_subparts(part, subparts)) {
+          warnf(config->global, "curl_mime_subparts failed!\n");
+          curl_mime_free(subparts);
           Curl_safefree(contents);
-          return 5;
+          return 19;
         }
-        Curl_safefree(forms);
       }
     }
     else {
-      struct curl_forms info[4];
-      int i = 0;
-      char *ct = literal_value ? NULL : strstr(contp, ";type=");
-
-      info[i].option = CURLFORM_COPYNAME;
-      info[i].value = name;
-      i++;
-
-      if(ct) {
-        info[i].option = CURLFORM_CONTENTTYPE;
-        info[i].value = &ct[6];
-        i++;
-        ct[0] = '\0'; /* zero terminate here */
-      }
+        /* Allocate a mime part. */
+        part = curl_mime_addpart(*mimecurrent);
+        if(!part) {
+          warnf(config->global, "curl_mime_addpart failed!\n");
+          Curl_safefree(contents);
+          return 20;
+        }
 
-      if(contp[0]=='<' && !literal_value) {
-        info[i].option = CURLFORM_FILECONTENT;
-        info[i].value = contp+1;
-        i++;
-        info[i].option = CURLFORM_END;
+      if(*contp == '<' && !literal_value) {
+        ++contp;
+        sep = get_param_part(config, &contp,
+                             &data, &type, &filename, &encoder, &headers);
+        if(sep < 0) {
+          Curl_safefree(contents);
+          return 21;
+        }
 
-        if(curl_formadd(httppost, last_post,
-                        CURLFORM_ARRAY, info, CURLFORM_END) != 0) {
-          warnf(config->global, "curl_formadd failed, possibly the file %s is "
-                "bad!\n", contp + 1);
+        /* Set part headers. */
+        if(curl_mime_headers(part, headers, 1)) {
+          warnf(config->global, "curl_mime_headers failed!\n");
+          curl_slist_free_all(headers);
           Curl_safefree(contents);
-          return 6;
+          return 22;
+        }
+
+        /* Setup file in part. */
+        res = file_or_stdin(part, data);
+        if(res) {
+          warnf(config->global, "setting file %s failed!\n", data);
+          if(res != CURLE_READ_ERROR) {
+            Curl_safefree(contents);
+            return 23;
+          }
         }
       }
       else {
+        if(literal_value)
+          data = contp;
+        else {
+          sep = get_param_part(config, &contp,
+                               &data, &type, &filename, &encoder, &headers);
+          if(sep < 0) {
+            Curl_safefree(contents);
+            return 24;
+          }
+        }
+
+        /* Set part headers. */
+        if(curl_mime_headers(part, headers, 1)) {
+          warnf(config->global, "curl_mime_headers failed!\n");
+          curl_slist_free_all(headers);
+          Curl_safefree(contents);
+          return 25;
+        }
+
 #ifdef CURL_DOES_CONVERSIONS
-        if(convert_to_network(contp, strlen(contp))) {
+        if(convert_to_network(data, strlen(data))) {
           warnf(config->global, "curl_formadd failed!\n");
           Curl_safefree(contents);
-          return 7;
+          return 26;
         }
 #endif
-        info[i].option = CURLFORM_COPYCONTENTS;
-        info[i].value = contp;
-        i++;
-        info[i].option = CURLFORM_END;
-        if(curl_formadd(httppost, last_post,
-                        CURLFORM_ARRAY, info, CURLFORM_END) != 0) {
-          warnf(config->global, "curl_formadd failed!\n");
+
+        if(curl_mime_data(part, data, CURL_ZERO_TERMINATED)) {
+          warnf(config->global, "curl_mime_data failed!\n");
           Curl_safefree(contents);
-          return 8;
+          return 27;
         }
       }
+
+      if(curl_mime_filename(part, filename)) {
+        warnf(config->global, "curl_mime_filename failed!\n");
+        Curl_safefree(contents);
+        return 28;
+      }
+      if(curl_mime_type(part, type)) {
+        warnf(config->global, "curl_mime_type failed!\n");
+        Curl_safefree(contents);
+        return 29;
+      }
+      if(curl_mime_encoder(part, encoder)) {
+        warnf(config->global, "curl_mime_encoder failed!\n");
+        Curl_safefree(contents);
+        return 30;
+      }
+
+      if(sep) {
+        *contp = (char) sep;
+        warnf(config->global,
+              "garbage at end of field specification: %s\n", contp);
+      }
     }
 
+    /* Set part name. */
+    if(name && curl_mime_name(part, name)) {
+      warnf(config->global, "curl_mime_name failed!\n");
+      Curl_safefree(contents);
+      return 31;
+    }
   }
   else {
     warnf(config->global, "Illegally formatted input field!\n");
-    return 1;
+    Curl_safefree(contents);
+    return 32;
   }
   Curl_safefree(contents);
   return 0;
diff --git a/src/tool_formparse.h b/src/tool_formparse.h
index ce7a29256..a52b98d39 100644
--- a/src/tool_formparse.h
+++ b/src/tool_formparse.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,8 +25,8 @@
 
 int formparse(struct OperationConfig *config,
               const char *input,
-              struct curl_httppost **httppost,
-              struct curl_httppost **last_post,
+              curl_mime **mimepost,
+              curl_mime **mimecurrent,
               bool literal_value);
 
 #endif /* HEADER_CURL_TOOL_FORMPARSE_H */
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index b7ee519b3..b65c45732 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -188,6 +188,7 @@ static const struct LongShort aliases[]= {
   {"$W", "abstract-unix-socket",     ARG_STRING},
   {"$X", "tls-max",                  ARG_STRING},
   {"$Y", "suppress-connect-headers", ARG_BOOL},
+  {"$Z", "compressed-ssh",           ARG_BOOL},
   {"0",   "http1.0",                 ARG_NONE},
   {"01",  "http1.1",                 ARG_NONE},
   {"02",  "http2",                   ARG_NONE},
@@ -448,7 +449,7 @@ ParameterError getparameter(const char *flag, /* f or 
-long-flag */
   if(('-' != flag[0]) ||
      (('-' == flag[0]) && ('-' == flag[1]))) {
     /* this should be a long name */
-    const char *word = ('-' == flag[0]) ? flag+2 : flag;
+    const char *word = ('-' == flag[0]) ? flag + 2 : flag;
     size_t fnam = strlen(word);
     int numhits = 0;
 
@@ -491,7 +492,7 @@ ParameterError getparameter(const char *flag, /* f or 
-long-flag */
 
     if(!longopt) {
       letter = (char)*parse;
-      subletter='\0';
+      subletter = '\0';
     }
     else {
       letter = parse[0];
@@ -590,7 +591,11 @@ ParameterError getparameter(const char *flag, /* f or 
-long-flag */
       {
         /* We support G, M, K too */
         char *unit;
-        curl_off_t value = curlx_strtoofft(nextarg, &unit, 0);
+        curl_off_t value;
+        if(curlx_strtoofft(nextarg, &unit, 0, &value)) {
+          warnf(global, "unsupported rate\n");
+          return PARAM_BAD_USE;
+        }
 
         if(!*unit)
           unit = (char *)"b";
@@ -999,7 +1004,7 @@ ParameterError getparameter(const char *flag, /* f or 
-long-flag */
 #ifdef USE_METALINK
           int mlmaj, mlmin, mlpatch;
           metalink_get_version(&mlmaj, &mlmin, &mlpatch);
-          if((mlmaj*10000)+(mlmin*100)+mlpatch < CURL_REQ_LIBMETALINK_VERS) {
+          if((mlmaj*10000)+(mlmin*100) + mlpatch < CURL_REQ_LIBMETALINK_VERS) {
             warnf(global,
                   "--metalink option cannot be used because the version of "
                   "the linked libmetalink library is too old. "
@@ -1072,6 +1077,9 @@ ParameterError getparameter(const char *flag, /* f or 
-long-flag */
       case 'Y': /* --suppress-connect-headers */
         config->suppress_connect_headers = toggle;
         break;
+      case 'Z': /* --compressed-ssh */
+        config->ssh_compression = toggle;
+        break;
       }
       break;
     case '#': /* --progress-bar */
@@ -1182,7 +1190,7 @@ ParameterError getparameter(const char *flag, /* f or 
-long-flag */
         config->resume_from_current = TRUE;
         config->resume_from = 0;
       }
-      config->use_resume=TRUE;
+      config->use_resume = TRUE;
       break;
     case 'd':
       /* postfield data */
@@ -1346,11 +1354,11 @@ ParameterError getparameter(const char *flag, /* f or 
-long-flag */
         memcpy(config->postfields, oldpost, (size_t)oldlen);
         /* use byte value 0x26 for '&' to accommodate non-ASCII platforms */
         config->postfields[oldlen] = '\x26';
-        memcpy(&config->postfields[oldlen+1], postdata, size);
-        config->postfields[oldlen+1+size] = '\0';
+        memcpy(&config->postfields[oldlen + 1], postdata, size);
+        config->postfields[oldlen + 1 + size] = '\0';
         Curl_safefree(oldpost);
         Curl_safefree(postdata);
-        config->postfieldsize += size+1;
+        config->postfieldsize += size + 1;
       }
       else {
         config->postfields = postdata;
@@ -1598,11 +1606,11 @@ ParameterError getparameter(const char *flag, /* f or 
-long-flag */
          to sort this out slowly and carefully */
       if(formparse(config,
                    nextarg,
-                   &config->httppost,
-                   &config->last_post,
-                   (subletter=='s')?TRUE:FALSE)) /* 's' means literal string */
+                   &config->mimepost,
+                   &config->mimecurrent,
+                   (subletter == 's')?TRUE:FALSE)) /* 's' is literal string */
         return PARAM_BAD_USE;
-      if(SetHTTPrequest(config, HTTPREQ_FORMPOST, &config->httpreq))
+      if(SetHTTPrequest(config, HTTPREQ_MIMEPOST, &config->httpreq))
         return PARAM_BAD_USE;
       break;
 
@@ -1843,10 +1851,13 @@ ParameterError getparameter(const char *flag, /* f or 
-long-flag */
       if(ISDIGIT(*nextarg) && !strchr(nextarg, '-')) {
         char buffer[32];
         curl_off_t off;
+        if(curlx_strtoofft(nextarg, NULL, 10, &off)) {
+          warnf(global, "unsupported range point\n");
+          return PARAM_BAD_USE;
+        }
         warnf(global,
               "A specified range MUST include at least one dash (-). "
               "Appending one for you!\n");
-        off = curlx_strtoofft(nextarg, NULL, 10);
         snprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-", off);
         Curl_safefree(config->range);
         config->range = strdup(buffer);
@@ -2042,7 +2053,7 @@ ParameterError getparameter(const char *flag, /* f or 
-long-flag */
         break;
       }
       now = time(NULL);
-      config->condtime=curl_getdate(nextarg, &now);
+      config->condtime = curl_getdate(nextarg, &now);
       if(-1 == (int)config->condtime) {
         /* now let's see if it is a file name to get the time from instead! */
         struct_stat statbuf;
diff --git a/src/tool_help.c b/src/tool_help.c
index 42dc77959..486f65dc8 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -54,7 +54,7 @@ static const struct helptxt helptext[] = {
    "Append to target file when uploading"},
   {"    --basic",
    "Use HTTP Basic Authentication"},
-  {"    --cacert <CA certificate>",
+  {"    --cacert <file>",
    "CA certificate to verify peer against"},
   {"    --capath <dir>",
    "CA directory to verify peer against"},
@@ -68,6 +68,8 @@ static const struct helptxt helptext[] = {
    "SSL ciphers to use"},
   {"    --compressed",
    "Request compressed response"},
+  {"    --compressed-ssh",
+   "Enable SSH compression"},
   {"-K, --config <file>",
    "Read config from a file"},
   {"    --connect-timeout <seconds>",
@@ -129,9 +131,9 @@ static const struct helptxt helptext[] = {
   {"    --false-start",
    "Enable TLS False Start"},
   {"-F, --form <name=content>",
-   "Specify HTTP multipart POST data"},
+   "Specify multipart MIME data"},
   {"    --form-string <name=string>",
-   "Specify HTTP multipart POST data"},
+   "Specify multipart MIME data"},
   {"    --ftp-account <data>",
    "Account data string"},
   {"    --ftp-alternative-to-user <command>",
@@ -501,7 +503,8 @@ static const struct feat feats[] = {
   {"TLS-SRP",        CURL_VERSION_TLSAUTH_SRP},
   {"HTTP2",          CURL_VERSION_HTTP2},
   {"UnixSockets",    CURL_VERSION_UNIX_SOCKETS},
-  {"HTTPS-proxy",    CURL_VERSION_HTTPS_PROXY}
+  {"HTTPS-proxy",    CURL_VERSION_HTTPS_PROXY},
+  {"MultiSSL",       CURL_VERSION_MULTI_SSL}
 };
 
 void tool_help(void)
diff --git a/src/tool_main.c b/src/tool_main.c
index 089a317d4..4e78d3321 100644
--- a/src/tool_main.c
+++ b/src/tool_main.c
@@ -62,6 +62,15 @@
 int vms_show = 0;
 #endif
 
+#ifdef __MINGW32__
+/*
+ * There seems to be no way to escape "*" in command-line arguments with MinGW
+ * when command-line argument globbing is enabled under the MSYS shell, so turn
+ * it off.
+ */
+int _CRT_glob = 0;
+#endif /* __MINGW32__ */
+
 /* if we build a static library for unit tests, there is no main() function */
 #ifndef UNITTESTS
 
diff --git a/src/tool_metalink.c b/src/tool_metalink.c
index 3f66c7470..270345547 100644
--- a/src/tool_metalink.c
+++ b/src/tool_metalink.c
@@ -30,6 +30,8 @@
 #  include <fcntl.h>
 #endif
 
+#undef HAVE_NSS_CONTEXT
+
 #ifdef USE_OPENSSL
 #  include <openssl/md5.h>
 #  include <openssl/sha.h>
@@ -50,6 +52,7 @@
 #  define MD5_CTX    void *
 #  define SHA_CTX    void *
 #  define SHA256_CTX void *
+#  define HAVE_NSS_CONTEXT
    static NSSInitContext *nss_context;
 #elif defined(USE_POLARSSL)
 #  include <polarssl/md5.h>
@@ -117,7 +120,9 @@ struct win32_crypto_hash {
     return PARAM_NO_MEM; \
 } WHILE_FALSE
 
-#ifdef USE_GNUTLS_NETTLE
+#if defined(USE_OPENSSL)
+/* Functions are already defined */
+#elif defined(USE_GNUTLS_NETTLE)
 
 static int MD5_Init(MD5_CTX *ctx)
 {
@@ -375,7 +380,7 @@ static void SHA256_Final(unsigned char digest[32], 
SHA256_CTX *ctx)
   sha256_finish(ctx, digest);
 }
 
-#elif defined(_WIN32) && !defined(USE_OPENSSL)
+#elif defined(_WIN32)
 
 static void win32_crypto_final(struct win32_crypto_hash *ctx,
                                unsigned char *digest,
@@ -678,7 +683,7 @@ static metalink_checksum 
*new_metalink_checksum_from_hex_digest
     return 0;
 
   for(i = 0; i < len; i += 2) {
-    digest[i/2] = hex_to_uint(hex_digest+i);
+    digest[i/2] = hex_to_uint(hex_digest + i);
   }
   chksum = malloc(sizeof(metalink_checksum));
   if(chksum) {
@@ -880,7 +885,7 @@ size_t metalink_write_cb(void *buffer, size_t sz, size_t 
nmemb,
   if(!config)
     return failure;
 
-  rv = metalink_parse_update(outs->metalink_parser, buffer, sz *nmemb);
+  rv = metalink_parse_update(outs->metalink_parser, buffer, sz * nmemb);
   if(rv == 0)
     return sz * nmemb;
   else {
@@ -901,8 +906,8 @@ static int check_content_type(const char *content_type, 
const char *media_type)
     return 0;
   }
   return curl_strnequal(ptr, media_type, media_type_len) &&
-    (*(ptr+media_type_len) == '\0' || *(ptr+media_type_len) == ' ' ||
-     *(ptr+media_type_len) == '\t' || *(ptr+media_type_len) == ';');
+    (*(ptr + media_type_len) == '\0' || *(ptr + media_type_len) == ' ' ||
+     *(ptr + media_type_len) == '\t' || *(ptr + media_type_len) == ';');
 }
 
 int check_metalink_content_type(const char *content_type)
@@ -965,7 +970,7 @@ void clean_metalink(struct OperationConfig *config)
 
 void metalink_cleanup(void)
 {
-#ifdef USE_NSS
+#ifdef HAVE_NSS_CONTEXT
   if(nss_context) {
     NSS_ShutdownContext(nss_context);
     nss_context = NULL;
diff --git a/src/tool_mfiles.c b/src/tool_mfiles.c
deleted file mode 100644
index d862d4140..000000000
--- a/src/tool_mfiles.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/***************************************************************************
- *                                  _   _ ____  _
- *  Project                     ___| | | |  _ \| |
- *                             / __| | | | |_) | |
- *                            | (__| |_| |  _ <| |___
- *                             \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2012, 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 "tool_setup.h"
-
-#include "tool_mfiles.h"
-
-#include "memdebug.h" /* keep this as LAST include */
-
-static void AppendNode(struct multi_files **first,
-                       struct multi_files **last,
-                       struct multi_files  *new)
-{
-  DEBUGASSERT(((*first) && (*last)) || ((!*first) && (!*last)));
-
-  if(*last)
-    (*last)->next = new;
-  else
-    *first = new;
-  *last = new;
-}
-
-/*
- * AddMultiFiles: Add a new list node possibly followed with a type_name.
- *
- * multi_first argument is the address of a pointer to the first element
- * of the multi_files linked list. A NULL pointer indicates empty list.
- *
- * multi_last argument is the address of a pointer to the last element
- * of the multi_files linked list. A NULL pointer indicates empty list.
- *
- * Pointers stored in multi_first and multi_last are modified while
- * function is executed. An out of memory condition free's the whole
- * list and returns with pointers stored in multi_first and multi_last
- * set to NULL and a NULL function result.
- *
- * Function returns same pointer as stored at multi_last.
- */
-
-struct multi_files *AddMultiFiles(const char *file_name,
-                                  const char *type_name,
-                                  const char *show_filename,
-                                  struct multi_files **multi_first,
-                                  struct multi_files **multi_last)
-{
-  struct multi_files *multi;
-  struct multi_files *multi_type;
-  struct multi_files *multi_name;
-
-  multi = calloc(1, sizeof(struct multi_files));
-  if(multi) {
-    multi->form.option = CURLFORM_FILE;
-    multi->form.value = file_name;
-    AppendNode(multi_first, multi_last, multi);
-  }
-  else {
-    FreeMultiInfo(multi_first, multi_last);
-    return NULL;
-  }
-
-  if(type_name) {
-    multi_type = calloc(1, sizeof(struct multi_files));
-    if(multi_type) {
-      multi_type->form.option = CURLFORM_CONTENTTYPE;
-      multi_type->form.value = type_name;
-      AppendNode(multi_first, multi_last, multi_type);
-    }
-    else {
-      FreeMultiInfo(multi_first, multi_last);
-      return NULL;
-    }
-  }
-
-  if(show_filename) {
-    multi_name = calloc(1, sizeof(struct multi_files));
-    if(multi_name) {
-      multi_name->form.option = CURLFORM_FILENAME;
-      multi_name->form.value = show_filename;
-      AppendNode(multi_first, multi_last, multi_name);
-    }
-    else {
-      FreeMultiInfo(multi_first, multi_last);
-      return NULL;
-    }
-  }
-
-  return *multi_last;
-}
-
-/*
- * FreeMultiInfo: Free the items of the list.
- */
-
-void FreeMultiInfo(struct multi_files **multi_first,
-                   struct multi_files **multi_last)
-{
-  struct multi_files *next;
-  struct multi_files *item = *multi_first;
-
-  while(item) {
-    next = item->next;
-    Curl_safefree(item);
-    item = next;
-  }
-  *multi_first = NULL;
-  if(multi_last)
-    *multi_last = NULL;
-}
-
diff --git a/src/tool_mfiles.h b/src/tool_mfiles.h
deleted file mode 100644
index 827f40065..000000000
--- a/src/tool_mfiles.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef HEADER_CURL_TOOL_MFILES_H
-#define HEADER_CURL_TOOL_MFILES_H
-/***************************************************************************
- *                                  _   _ ____  _
- *  Project                     ___| | | |  _ \| |
- *                             / __| | | | |_) | |
- *                            | (__| |_| |  _ <| |___
- *                             \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2012, 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 "tool_setup.h"
-
-/*
- * Structure for storing the information needed to build
- * a multiple files section.
- */
-
-struct multi_files {
-  struct curl_forms   form;
-  struct multi_files *next;
-};
-
-struct multi_files *AddMultiFiles(const char *file_name,
-                                  const char *type_name,
-                                  const char *show_filename,
-                                  struct multi_files **multi_first,
-                                  struct multi_files **multi_last);
-
-void FreeMultiInfo(struct multi_files **multi_first,
-                   struct multi_files **multi_last);
-
-#endif /* HEADER_CURL_TOOL_MFILES_H */
-
diff --git a/src/tool_msgs.c b/src/tool_msgs.c
index d06708a18..07bf81292 100644
--- a/src/tool_msgs.c
+++ b/src/tool_msgs.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2015, 2017, 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,7 +63,7 @@ static void voutf(struct GlobalConfig *config,
 
         (void)fwrite(ptr, cut + 1, 1, config->errors);
         fputs("\n", config->errors);
-        ptr += cut+1; /* skip the space too */
+        ptr += cut + 1; /* skip the space too */
         len -= cut;
       }
       else {
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 1e8d0073c..5401955af 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -92,21 +92,12 @@ CURLcode curl_easy_perform_ev(CURL *easy);
 #  define O_BINARY 0
 #endif
 
-#define CURL_CA_CERT_ERRORMSG1                                              \
-  "More details here: https://curl.haxx.se/docs/sslcerts.html\n\n";           \
-  "curl performs SSL certificate verification by default, "                 \
-  "using a \"bundle\"\n"                                                    \
-  " of Certificate Authority (CA) public keys (CA certs). If the default\n" \
-  " bundle file isn't adequate, you can specify an alternate file\n"        \
-  " using the --cacert option.\n"
-
-#define CURL_CA_CERT_ERRORMSG2                                              \
-  "If this HTTPS server uses a certificate signed by a CA represented in\n" \
-  " the bundle, the certificate verification probably failed due to a\n"    \
-  " problem with the certificate (it might be expired, or the name might\n" \
-  " not match the domain name in the URL).\n"                               \
-  "If you'd like to turn off curl's verification of the certificate, use\n" \
-  " the -k (or --insecure) option.\n"
+#define CURL_CA_CERT_ERRORMSG                                               \
+  "More details here: https://curl.haxx.se/docs/sslcerts.html\n\n";          \
+  "curl failed to verify the legitimacy of the server and therefore "       \
+  "could not\nestablish a secure connection to it. To learn more about "    \
+  "this situation and\nhow to fix it, please visit the web page mentioned " \
+  "above.\n"
 
 static bool is_fatal_error(CURLcode code)
 {
@@ -184,7 +175,7 @@ static curl_off_t VmsSpecialSize(const char *name,
 #endif /* __VMS */
 
 #if defined(HAVE_UTIME) || \
-    (defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8))
+    (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8))
 static void setfiletime(long filetime, const char *filename,
                         FILE *error_stream)
 {
@@ -192,10 +183,10 @@ static void setfiletime(long filetime, const char 
*filename,
 /* Windows utime() may attempt to adjust our unix gmt 'filetime' by a daylight
    saving time offset and since it's GMT that is bad behavior. When we have
    access to a 64-bit type we can bypass utime and set the times directly. */
-#if defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8)
+#if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)
     HANDLE hfile;
 
-#if (CURL_SIZEOF_LONG >= 8)
+#if (SIZEOF_LONG >= 8)
     /* 910670515199 is the maximum unix filetime that can be used as a
        Windows FILETIME without overflow: 30827-12-31T23:59:59. */
     if(filetime > CURL_OFF_T_C(910670515199)) {
@@ -204,7 +195,7 @@ static void setfiletime(long filetime, const char *filename,
               filetime);
       return;
     }
-#endif /* CURL_SIZEOF_LONG >= 8 */
+#endif /* SIZEOF_LONG >= 8 */
 
     hfile = CreateFileA(filename, FILE_WRITE_ATTRIBUTES,
                         (FILE_SHARE_READ | FILE_SHARE_WRITE |
@@ -254,7 +245,7 @@ static void setfiletime(long filetime, const char *filename,
   }
 }
 #endif /* defined(HAVE_UTIME) || \
-          (defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8)) */
+          (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */
 
 #define BUFFER_SIZE (100*1024)
 
@@ -534,7 +525,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
         urlnum = 1; /* without globbing, this is a single URL */
 
       /* if multiple files extracted to stdout, insert separators! */
-      separator= ((!outfiles || !strcmp(outfiles, "-")) && urlnum > 1);
+      separator = ((!outfiles || !strcmp(outfiles, "-")) && urlnum > 1);
 
       /* Here's looping around each globbed URL */
       for(li = 0 ; li < urlnum; li++) {
@@ -809,7 +800,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
 
         if(urlnum > 1 && !global->mute) {
           fprintf(global->errors, "\n[%lu/%lu]: %s --> %s\n",
-                  li+1, urlnum, this_url, outfile ? outfile : "<stdout>");
+                  li + 1, urlnum, this_url, outfile ? outfile : "<stdout>");
           if(separator)
             printf("%s%s\n", CURLseparator, this_url);
         }
@@ -831,7 +822,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
             if(strchr(pc, '?'))
               /* Ouch, there's already a question mark in the URL string, we
                  then append the data with an ampersand separator instead! */
-              sep='&';
+              sep = '&';
           }
           /*
            * Then append ? followed by the get fields to the url.
@@ -995,6 +986,31 @@ static CURLcode operate_do(struct GlobalConfig *global,
         my_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
         my_setopt(curl, CURLOPT_TIMEOUT_MS, (long)(config->timeout * 1000));
 
+        switch(config->httpreq) {
+        case HTTPREQ_SIMPLEPOST:
+          my_setopt_str(curl, CURLOPT_POSTFIELDS,
+                        config->postfields);
+          my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
+                    config->postfieldsize);
+          break;
+        case HTTPREQ_MIMEPOST:
+          my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
+          break;
+        default:
+          break;
+        }
+
+        /* new in libcurl 7.10.6 (default is Basic) */
+        if(config->authtype)
+          my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, (long)config->authtype);
+
+        my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers);
+
+        if(built_in_protos & (CURLPROTO_HTTP | CURLPROTO_RTSP)) {
+          my_setopt_str(curl, CURLOPT_REFERER, config->referer);
+          my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent);
+        }
+
         if(built_in_protos & CURLPROTO_HTTP) {
 
           long postRedir = 0;
@@ -1004,24 +1020,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
           my_setopt(curl, CURLOPT_UNRESTRICTED_AUTH,
                     config->unrestricted_auth?1L:0L);
 
-          switch(config->httpreq) {
-          case HTTPREQ_SIMPLEPOST:
-            my_setopt_str(curl, CURLOPT_POSTFIELDS,
-                          config->postfields);
-            my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
-                      config->postfieldsize);
-            break;
-          case HTTPREQ_FORMPOST:
-            my_setopt_httppost(curl, CURLOPT_HTTPPOST, config->httppost);
-            break;
-          default:
-            break;
-          }
-
-          my_setopt_str(curl, CURLOPT_REFERER, config->referer);
           my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer?1L:0L);
-          my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent);
-          my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers);
 
           /* new in libcurl 7.36.0 */
           if(config->proxyheaders) {
@@ -1038,10 +1037,6 @@ static CURLcode operate_do(struct GlobalConfig *global,
             my_setopt_enum(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
           }
 
-          /* new in libcurl 7.10.6 (default is Basic) */
-          if(config->authtype)
-            my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, (long)config->authtype);
-
           /* curl 7.19.1 (the 301 version existed in 7.18.2),
              303 was added in 7.26.0 */
           if(config->post301)
@@ -1091,6 +1086,10 @@ static CURLcode operate_do(struct GlobalConfig *global,
              to fail if we are not talking to who we think we should */
           my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
                         config->hostpubmd5);
+
+          /* new in libcurl 7.56.0 */
+          if(config->ssh_compression)
+            my_setopt(curl, CURLOPT_SSH_COMPRESSION, 1L);
         }
 
         if(config->cacert)
@@ -1673,6 +1672,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
                   retry_sleep = RETRY_SLEEP_MAX;
               }
               if(outs.bytes && outs.filename && outs.stream) {
+                int rc;
                 /* We have written data to a output file, we truncate file
                  */
                 if(!global->mute)
@@ -1693,14 +1693,21 @@ static CURLcode operate_do(struct GlobalConfig *global,
                 }
                 /* now seek to the end of the file, the position where we
                    just truncated the file in a large file-safe way */
-                fseek(outs.stream, 0, SEEK_END);
+                rc = fseek(outs.stream, 0, SEEK_END);
 #else
                 /* ftruncate is not available, so just reposition the file
                    to the location we would have truncated it. This won't
                    work properly with large files on 32-bit systems, but
                    most of those will have ftruncate. */
-                fseek(outs.stream, (long)outs.init, SEEK_SET);
+                rc = fseek(outs.stream, (long)outs.init, SEEK_SET);
 #endif
+                if(rc) {
+                  if(!global->mute)
+                    fprintf(global->errors,
+                            "failed seeking to end of file, exiting\n");
+                  result = CURLE_WRITE_ERROR;
+                  goto quit_urls;
+                }
                 outs.bytes = 0; /* clear for next round */
               }
               continue; /* curl_easy_perform loop */
@@ -1780,12 +1787,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
           fprintf(global->errors, "curl: (%d) %s\n", result, (errorbuffer[0]) ?
                   errorbuffer : curl_easy_strerror(result));
           if(result == CURLE_SSL_CACERT)
-            fprintf(global->errors, "%s%s%s",
-                    CURL_CA_CERT_ERRORMSG1, CURL_CA_CERT_ERRORMSG2,
-                    ((curlinfo->features & CURL_VERSION_HTTPS_PROXY) ?
-                     "HTTPS-proxy has similar options --proxy-cacert "
-                     "and --proxy-insecure.\n" :
-                     ""));
+            fputs(CURL_CA_CERT_ERRORMSG, global->errors);
         }
 
         /* Fall through comment to 'quit_urls' label */
@@ -1840,7 +1842,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
 #endif
 
 #if defined(HAVE_UTIME) || \
-    (defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8))
+    (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8))
         /* File time can only be set _after_ the file has been closed */
         if(!result && config->remote_time && outs.s_isreg && outs.filename) {
           /* Ask libcurl if we got a remote file time */
@@ -1850,7 +1852,7 @@ static CURLcode operate_do(struct GlobalConfig *global,
             setfiletime(filetime, outs.filename, config->global->errors);
         }
 #endif /* defined(HAVE_UTIME) || \
-          (defined(WIN32) && (CURL_SIZEOF_CURL_OFF_T >= 8)) */
+          (defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8)) */
 
 #ifdef USE_METALINK
         if(!metalink && config->use_metalink && result == CURLE_OK) {
diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c
index 85c5e79a7..7cddf51ce 100644
--- a/src/tool_paramhlp.c
+++ b/src/tool_paramhlp.c
@@ -73,13 +73,13 @@ ParameterError file2string(char **bufp, FILE *file)
       if(ptr)
         *ptr = '\0';
       buflen = strlen(buffer);
-      ptr = realloc(string, stringlen+buflen+1);
+      ptr = realloc(string, stringlen + buflen + 1);
       if(!ptr) {
         Curl_safefree(string);
         return PARAM_NO_MEM;
       }
       string = ptr;
-      strcpy(string+stringlen, buffer);
+      strcpy(string + stringlen, buffer);
       stringlen += buflen;
     }
   }
@@ -99,27 +99,27 @@ ParameterError file2memory(char **bufp, size_t *size, FILE 
*file)
     do {
       if(!buffer || (alloc == nused)) {
         /* size_t overflow detection for huge files */
-        if(alloc+1 > ((size_t)-1)/2) {
+        if(alloc + 1 > ((size_t)-1)/2) {
           Curl_safefree(buffer);
           return PARAM_NO_MEM;
         }
         alloc *= 2;
         /* allocate an extra char, reserved space, for null termination */
-        newbuf = realloc(buffer, alloc+1);
+        newbuf = realloc(buffer, alloc + 1);
         if(!newbuf) {
           Curl_safefree(buffer);
           return PARAM_NO_MEM;
         }
         buffer = newbuf;
       }
-      nread = fread(buffer+nused, 1, alloc-nused, file);
+      nread = fread(buffer + nused, 1, alloc-nused, file);
       nused += nread;
     } while(nread);
     /* null terminate the buffer in case it's used as a string later */
     buffer[nused] = '\0';
     /* free trailing slack space, if possible */
     if(alloc != nused) {
-      newbuf = realloc(buffer, nused+1);
+      newbuf = realloc(buffer, nused + 1);
       if(!newbuf) {
         Curl_safefree(buffer);
         return PARAM_NO_MEM;
@@ -242,14 +242,16 @@ static ParameterError str2double(double *val, const char 
*str, long max)
  * data.
  */
 
-ParameterError str2udouble(double *val, const char *str, long max)
+ParameterError str2udouble(double *valp, const char *str, long max)
 {
-  ParameterError result = str2double(val, str, max);
+  double value;
+  ParameterError result = str2double(&value, str, max);
   if(result != PARAM_OK)
     return result;
-  if(*val < 0)
+  if(value < 0)
     return PARAM_NEGATIVE_NUMERIC;
 
+  *valp = value;
   return PARAM_OK;
 }
 
@@ -334,7 +336,7 @@ long proto2num(struct OperationConfig *config, long *val, 
const char *str)
       }
     }
 
-    for(pp=protos; pp->name; pp++) {
+    for(pp = protos; pp->name; pp++) {
       if(curl_strequal(token, pp->name)) {
         switch(action) {
         case deny:
@@ -399,10 +401,14 @@ ParameterError str2offset(curl_off_t *val, const char 
*str)
     /* offsets aren't negative, this indicates weird input */
     return PARAM_NEGATIVE_NUMERIC;
 
-#if(CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
-  *val = curlx_strtoofft(str, &endptr, 0);
-  if((*val == CURL_OFF_T_MAX || *val == CURL_OFF_T_MIN) && (errno == ERANGE))
-    return PARAM_NUMBER_TOO_LARGE;
+#if(SIZEOF_CURL_OFF_T > SIZEOF_LONG)
+  {
+    CURLofft offt = curlx_strtoofft(str, &endptr, 0, val);
+    if(CURL_OFFT_FLOW == offt)
+      return PARAM_NUMBER_TOO_LARGE;
+    else if(CURL_OFFT_INVAL == offt)
+      return PARAM_BAD_NUMERIC;
+  }
 #else
   errno = 0;
   *val = strtol(str, &endptr, 0);
@@ -470,7 +476,7 @@ static CURLcode checkpasswd(const char *kind, /* for what 
purpose */
 
     /* append the password separated with a colon */
     passptr[userlen] = ':';
-    memcpy(&passptr[userlen+1], passwd, passwdlen+1);
+    memcpy(&passptr[userlen + 1], passwd, passwdlen + 1);
     *userpwd = passptr;
   }
 
diff --git a/src/tool_parsecfg.c b/src/tool_parsecfg.c
index 93814f454..540bdb18a 100644
--- a/src/tool_parsecfg.c
+++ b/src/tool_parsecfg.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -131,7 +131,7 @@ int parseconfig(const char *filename, struct GlobalConfig 
*global)
     while(NULL != (aline = my_get_line(file))) {
       lineno++;
       line = aline;
-      alloced_param=FALSE;
+      alloced_param = FALSE;
 
       /* line with # in the first non-blank column is a comment! */
       while(*line && ISSPACE(*line))
diff --git a/src/tool_sdecls.h b/src/tool_sdecls.h
index a56390e59..48dd4aed9 100644
--- a/src/tool_sdecls.h
+++ b/src/tool_sdecls.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -135,7 +135,7 @@ typedef enum {
   HTTPREQ_UNSPEC,  /* first in list */
   HTTPREQ_GET,
   HTTPREQ_HEAD,
-  HTTPREQ_FORMPOST,
+  HTTPREQ_MIMEPOST,
   HTTPREQ_SIMPLEPOST
 } HttpReq;
 
diff --git a/src/tool_setopt.c b/src/tool_setopt.c
index 694d3ffa5..fb2cb66d3 100644
--- a/src/tool_setopt.c
+++ b/src/tool_setopt.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,9 @@
 #include "tool_cfgable.h"
 #include "tool_easysrc.h"
 #include "tool_setopt.h"
+#include "tool_convert.h"
 
+#include "mime.h"
 #include "memdebug.h" /* keep this as LAST include */
 
 /* Lookup tables for converting setopt values back to symbols */
@@ -208,37 +210,43 @@ static const NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
 
 /* Escape string to C string syntax.  Return NULL if out of memory.
  * Is this correct for those wacky EBCDIC guys? */
-static char *c_escape(const char *str)
+static char *c_escape(const char *str, size_t len)
 {
-  size_t len = 0;
   const char *s;
   unsigned char c;
   char *escaped, *e;
+
+  if(len == CURL_ZERO_TERMINATED)
+    len = strlen(str);
+
+  /* Check for possible overflow. */
+  if(len > (~(size_t) 0) / 4)
+    return NULL;
+
   /* Allocate space based on worst-case */
-  len = strlen(str);
   escaped = malloc(4 * len + 1);
   if(!escaped)
     return NULL;
 
   e = escaped;
-  for(s=str; (c=*s) != '\0'; s++) {
-    if(c=='\n') {
+  for(s = str; (c = *s) != '\0'; s++) {
+    if(c == '\n') {
       strcpy(e, "\\n");
       e += 2;
     }
-    else if(c=='\r') {
+    else if(c == '\r') {
       strcpy(e, "\\r");
       e += 2;
     }
-    else if(c=='\t') {
+    else if(c == '\t') {
       strcpy(e, "\\t");
       e += 2;
     }
-    else if(c=='\\') {
+    else if(c == '\\') {
       strcpy(e, "\\\\");
       e += 2;
     }
-    else if(c=='"') {
+    else if(c == '"') {
       strcpy(e, "\\\"");
       e += 2;
     }
@@ -268,7 +276,7 @@ CURLcode tool_setopt_enum(CURL *curl, struct GlobalConfig 
*config,
   if(config->libcurl && !skip && !ret) {
     /* we only use this for real if --libcurl was used */
     const NameValue *nv = NULL;
-    for(nv=nvlist; nv->name; nv++) {
+    for(nv = nvlist; nv->name; nv++) {
       if(nv->value == lval) break; /* found it */
     }
     if(! nv->name) {
@@ -305,7 +313,7 @@ CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig 
*config,
     const NameValue *nv = NULL;
     snprintf(preamble, sizeof(preamble),
              "curl_easy_setopt(hnd, %s, ", name);
-    for(nv=nvlist; nv->name; nv++) {
+    for(nv = nvlist; nv->name; nv++) {
       if((nv->value & ~ rest) == 0) {
         /* all value flags contained in rest */
         rest &= ~ nv->value;    /* remove bits handled here */
@@ -348,7 +356,7 @@ CURLcode tool_setopt_bitmask(CURL *curl, struct 
GlobalConfig *config,
     const NameValueUnsigned *nv = NULL;
     snprintf(preamble, sizeof(preamble),
              "curl_easy_setopt(hnd, %s, ", name);
-    for(nv=nvlist; nv->name; nv++) {
+    for(nv = nvlist; nv->name; nv++) {
       if((nv->value & ~ rest) == 0) {
         /* all value flags contained in rest */
         rest &= ~ nv->value;    /* remove bits handled here */
@@ -371,118 +379,225 @@ CURLcode tool_setopt_bitmask(CURL *curl, struct 
GlobalConfig *config,
   return ret;
 }
 
-/* setopt wrapper for CURLOPT_HTTPPOST */
-CURLcode tool_setopt_httppost(CURL *curl, struct GlobalConfig *config,
-                              const char *name, CURLoption tag,
-                              struct curl_httppost *post)
+/* Generate code for a struct curl_slist. */
+static CURLcode libcurl_generate_slist(struct curl_slist *slist, int *slistno)
 {
   CURLcode ret = CURLE_OK;
   char *escaped = NULL;
-  bool skip = FALSE;
 
-  ret = curl_easy_setopt(curl, tag, post);
-  if(!post)
-    skip = TRUE;
+  /* May need several slist variables, so invent name */
+  *slistno = ++easysrc_slist_count;
+
+  DECL1("struct curl_slist *slist%d;", *slistno);
+  DATA1("slist%d = NULL;", *slistno);
+  CLEAN1("curl_slist_free_all(slist%d);", *slistno);
+  CLEAN1("slist%d = NULL;", *slistno);
+  for(; slist; slist = slist->next) {
+    Curl_safefree(escaped);
+    escaped = c_escape(slist->data, CURL_ZERO_TERMINATED);
+    if(!escaped)
+      return CURLE_OUT_OF_MEMORY;
+    DATA3("slist%d = curl_slist_append(slist%d, \"%s\");",
+                                       *slistno, *slistno, escaped);
+  }
 
-  if(config->libcurl && !skip && !ret) {
-    struct curl_httppost *pp, *p;
-    int i;
-    /* May use several httppost lists, if multiple POST actions */
-    i = ++ easysrc_form_count;
-    DECL1("struct curl_httppost *post%d;", i);
-    DATA1("post%d = NULL;", i);
-    CLEAN1("curl_formfree(post%d);", i);
-    CLEAN1("post%d = NULL;", i);
-    if(i == 1)
-      DECL0("struct curl_httppost *postend;");
-    DATA0("postend = NULL;");
-    for(p=post; p; p=p->next) {
-      DATA1("curl_formadd(&post%d, &postend,", i);
-      DATA1("             CURLFORM_COPYNAME, \"%s\",", p->name);
-      for(pp=p; pp; pp=pp->more) {
-        /* May be several files uploaded for one name;
-         * these are linked through the 'more' pointer */
+ nomem:
+  Curl_safefree(escaped);
+  return ret;
+}
+
+/* Generate source code for a mime structure. */
+static CURLcode libcurl_generate_mime(curl_mime *mime, int *mimeno)
+{
+  CURLcode ret = CURLE_OK;
+  int i;
+  curl_off_t size;
+  curl_mimepart *part;
+  char *filename;
+  char *escaped = NULL;
+  char *cp;
+  char *data;
+
+  /* May need several mime variables, so invent name */
+  *mimeno = ++easysrc_mime_count;
+
+  DECL1("curl_mime *mime%d;", *mimeno);
+  DATA1("mime%d = NULL;", *mimeno);
+  CODE1("mime%d = curl_mime_init(hnd);", *mimeno);
+  CLEAN1("curl_mime_free(mime%d);", *mimeno);
+  CLEAN1("mime%d = NULL;", *mimeno);
+  if(mime->firstpart) {
+    DECL1("curl_mimepart *part%d;", *mimeno);
+    for(part = mime->firstpart; part; part = part->nextpart) {
+      CODE2("part%d = curl_mime_addpart(mime%d);", *mimeno, *mimeno);
+      filename = part->filename;
+      switch(part->kind) {
+      case MIMEKIND_FILE:
         Curl_safefree(escaped);
-        escaped = c_escape(pp->contents);
-        if(!escaped) {
-          ret = CURLE_OUT_OF_MEMORY;
-          goto nomem;
-        }
-        if(pp->flags & CURL_HTTPPOST_FILENAME) {
-          /* file upload as for -F @filename */
-          DATA1("             CURLFORM_FILE, \"%s\",", escaped);
+        escaped = c_escape(part->data, CURL_ZERO_TERMINATED);
+        if(!escaped)
+          return CURLE_OUT_OF_MEMORY;
+        CODE2("curl_mime_filedata(part%d, \"%s\");", *mimeno, escaped);
+        if(!filename)
+          CODE1("curl_mime_filename(part%d, NULL);", *mimeno);
+        else {
+          /* Fast check to see if remote file name is base name. */
+          filename = part->data;
+          for(cp = filename; *cp; cp++)
+            if(*cp == '/' || *cp == '\\')
+              filename = cp + 1;
+          if(!part->filename || !strcmp(filename, part->filename))
+            filename = NULL;
+          else
+            filename = part->filename;
         }
-        else if(pp->flags & CURL_HTTPPOST_READFILE) {
-          /* content from file as for -F <filename */
-          DATA1("             CURLFORM_FILECONTENT, \"%s\",", escaped);
-        }
-        else
-          DATA1("             CURLFORM_COPYCONTENTS, \"%s\",", escaped);
-        if(pp->showfilename) {
-          Curl_safefree(escaped);
-          escaped = c_escape(pp->showfilename);
-          if(!escaped) {
+        break;
+      case MIMEKIND_CALLBACK:
+        /* Can only be reading stdin in the current context. */
+        CODE1("curl_mime_data_cb(part%d, -1, (curl_read_callback) fread, \\",
+              *mimeno);
+        CODE0("                  (curl_seek_callback) fseek, NULL, stdin);");
+        break;
+      case MIMEKIND_DATA:
+#ifdef CURL_DOES_CONVERSIONS
+          /* Data is stored in ASCII and we want in in the host character
+             code. Convert it back for output. */
+          data = malloc(part->datasize + 1);
+          if(!data) {
             ret = CURLE_OUT_OF_MEMORY;
             goto nomem;
           }
-          DATA1("             CURLFORM_FILENAME, \"%s\",", escaped);
-        }
-        if(pp->contenttype) {
-          Curl_safefree(escaped);
-          escaped = c_escape(pp->contenttype);
-          if(!escaped) {
-            ret = CURLE_OUT_OF_MEMORY;
+          memcpy(data, part->data, part->datasize + 1);
+          ret = convert_from_network(data, strlen(data));
+          if(ret) {
+            Curl_safefree(data);
             goto nomem;
           }
-          DATA1("             CURLFORM_CONTENTTYPE, \"%s\",", escaped);
-        }
+#else
+        data = part->data;
+#endif
+
+        /* Are there any nul byte in data? */
+        for(cp = data; *cp; cp++)
+          ;
+        size = (cp == data + part->datasize)? (curl_off_t) -1: part->datasize;
+        Curl_safefree(escaped);
+        escaped = c_escape(data, (size_t) part->datasize);
+#ifdef CURL_DOES_CONVERSIONS
+        Curl_safefree(data);
+#endif
+        if(!escaped)
+          return CURLE_OUT_OF_MEMORY;
+        if(size >= 0)
+          CODE3("curl_mime_data(part%d, \"%s\", %" CURL_FORMAT_CURL_OFF_T ");",
+                                *mimeno, escaped, size);
+        else
+          CODE2("curl_mime_data(part%d, \"%s\", CURL_ZERO_TERMINATED);",
+                                *mimeno, escaped);
+        break;
+      case MIMEKIND_MULTIPART:
+        ret = libcurl_generate_mime(part->arg, &i);
+        if(ret)
+          goto nomem;
+        CODE2("curl_mime_subparts(part%d, mime%d);", *mimeno, i);
+        CODE1("mime%d = NULL;", i);   /* Avoid freeing in CLEAN sequence. */
+        break;
+      default:
+        /* Other cases not possible in this context. */
+        break;
+      }
+
+      if(part->encoder) {
+        Curl_safefree(escaped);
+        escaped = c_escape(part->encoder->name, CURL_ZERO_TERMINATED);
+        if(!escaped)
+          return CURLE_OUT_OF_MEMORY;
+        CODE2("curl_mime_encoder(part%d, \"%s\");", *mimeno, escaped);
+      }
+
+      if(filename) {
+        Curl_safefree(escaped);
+        escaped = c_escape(filename, CURL_ZERO_TERMINATED);
+        if(!escaped)
+          return CURLE_OUT_OF_MEMORY;
+        CODE2("curl_mime_filename(part%d, \"%s\");", *mimeno, escaped);
+      }
+
+      if(part->name) {
+        Curl_safefree(escaped);
+        escaped = c_escape(part->name, CURL_ZERO_TERMINATED);
+        if(!escaped)
+          return CURLE_OUT_OF_MEMORY;
+        CODE2("curl_mime_name(part%d, \"%s\");", *mimeno, escaped);
+      }
+
+      if(part->mimetype) {
+        Curl_safefree(escaped);
+        escaped = c_escape(part->mimetype, CURL_ZERO_TERMINATED);
+        if(!escaped)
+          return CURLE_OUT_OF_MEMORY;
+        CODE2("curl_mime_type(part%d, \"%s\");", *mimeno, escaped);
+      }
+
+      if(part->userheaders) {
+        int ownership = part->flags & MIME_USERHEADERS_OWNER? 1: 0;
+
+        ret = libcurl_generate_slist(part->userheaders, &i);
+        if(ret)
+          goto nomem;
+        CODE3("curl_mime_headers(part%d, slist%d, %d);",
+              *mimeno, i, ownership);
+        if(ownership)
+          CODE1("slist%d = NULL;", i); /* Prevent freeing in CLEAN sequence. */
       }
-      DATA0("             CURLFORM_END);");
     }
-    CODE2("curl_easy_setopt(hnd, %s, post%d);", name, i);
   }
 
- nomem:
+nomem:
   Curl_safefree(escaped);
   return ret;
 }
 
+/* setopt wrapper for CURLOPT_MIMEPOST */
+CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config,
+                              const char *name, CURLoption tag,
+                              curl_mime *mimepost)
+{
+  CURLcode ret = CURLE_OK;
+
+  ret = curl_easy_setopt(curl, tag, mimepost);
+
+  if(config->libcurl && mimepost && !ret) {
+    int i;
+
+    ret = libcurl_generate_mime(mimepost, &i);
+
+    if(!ret)
+      CODE2("curl_easy_setopt(hnd, %s, mime%d);", name, i);
+  }
+
+nomem:
+  return ret;
+}
+
 /* setopt wrapper for curl_slist options */
 CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config,
                            const char *name, CURLoption tag,
                            struct curl_slist *list)
 {
   CURLcode ret = CURLE_OK;
-  char *escaped = NULL;
-  bool skip = FALSE;
 
   ret = curl_easy_setopt(curl, tag, list);
-  if(!list)
-    skip = TRUE;
 
-  if(config->libcurl && !skip && !ret) {
-    struct curl_slist *s;
+  if(config->libcurl && list && !ret) {
     int i;
-    /* May need several slist variables, so invent name */
-    i = ++ easysrc_slist_count;
-    DECL1("struct curl_slist *slist%d;", i);
-    DATA1("slist%d = NULL;", i);
-    CLEAN1("curl_slist_free_all(slist%d);", i);
-    CLEAN1("slist%d = NULL;", i);
-    for(s=list; s; s=s->next) {
-      Curl_safefree(escaped);
-      escaped = c_escape(s->data);
-      if(!escaped) {
-        ret = CURLE_OUT_OF_MEMORY;
-        goto nomem;
-      }
-      DATA3("slist%d = curl_slist_append(slist%d, \"%s\");", i, i, escaped);
-    }
-    CODE2("curl_easy_setopt(hnd, %s, slist%d);", name, i);
+
+    ret = libcurl_generate_slist(list, &i);
+    if(!ret)
+      CODE2("curl_easy_setopt(hnd, %s, slist%d);", name, i);
   }
 
  nomem:
-  Curl_safefree(escaped);
   return ret;
 }
 
@@ -507,7 +622,7 @@ CURLcode tool_setopt(CURL *curl, bool str, struct 
GlobalConfig *config,
     long lval = va_arg(arg, long);
     long defval = 0L;
     const NameValue *nv = NULL;
-    for(nv=setopt_nv_CURLNONZERODEFAULTS; nv->name; nv++) {
+    for(nv = setopt_nv_CURLNONZERODEFAULTS; nv->name; nv++) {
       if(!strcmp(name, nv->name)) {
         defval = nv->value;
         break; /* found it */
@@ -569,7 +684,7 @@ CURLcode tool_setopt(CURL *curl, bool str, struct 
GlobalConfig *config,
       REM2("%s set to a %s", name, value);
     else {
       if(escape) {
-        escaped = c_escape(value);
+        escaped = c_escape(value, CURL_ZERO_TERMINATED);
         if(!escaped) {
           ret = CURLE_OUT_OF_MEMORY;
           goto nomem;
diff --git a/src/tool_setopt.h b/src/tool_setopt.h
index da67deeb6..f8a52cd75 100644
--- a/src/tool_setopt.h
+++ b/src/tool_setopt.h
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,9 +85,9 @@ CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig 
*config,
 CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
                              const char *name, CURLoption tag,
                              const NameValueUnsigned *nv, long lval);
-CURLcode tool_setopt_httppost(CURL *curl, struct GlobalConfig *config,
+CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config,
                               const char *name, CURLoption tag,
-                              struct curl_httppost *httppost);
+                              curl_mime *mimepost);
 CURLcode tool_setopt_slist(CURL *curl, struct GlobalConfig *config,
                            const char *name, CURLoption tag,
                            struct curl_slist *list);
@@ -109,8 +109,8 @@ CURLcode tool_setopt(CURL *curl, bool str, struct 
GlobalConfig *config,
 #define my_setopt_bitmask(x,y,z) \
   SETOPT_CHECK(tool_setopt_bitmask(x, global, #y, y, setopt_nv_ ## y, z))
 
-#define my_setopt_httppost(x,y,z) \
-  SETOPT_CHECK(tool_setopt_httppost(x, global, #y, y, z))
+#define my_setopt_mimepost(x,y,z) \
+  SETOPT_CHECK(tool_setopt_mimepost(x, global, #y, y, z))
 
 #define my_setopt_slist(x,y,z) \
   SETOPT_CHECK(tool_setopt_slist(x, global, #y, y, z))
@@ -138,7 +138,7 @@ CURLcode tool_setopt(CURL *curl, bool str, struct 
GlobalConfig *config,
 #define my_setopt_bitmask(x,y,z) \
   SETOPT_CHECK(curl_easy_setopt(x, y, z))
 
-#define my_setopt_httppost(x,y,z) \
+#define my_setopt_mimepost(x,y,z) \
   SETOPT_CHECK(curl_easy_setopt(x, y, z))
 
 #define my_setopt_slist(x,y,z) \
diff --git a/src/tool_strdup.c b/src/tool_strdup.c
index cb4a1c5f6..e6e151bd6 100644
--- a/src/tool_strdup.c
+++ b/src/tool_strdup.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2015, 2017, 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,11 +35,11 @@ char *strdup(const char *str)
   if(len >= ((size_t)-1) / sizeof(char))
     return (char *)NULL;
 
-  newstr = malloc((len+1)*sizeof(char));
+  newstr = malloc((len + 1)*sizeof(char));
   if(!newstr)
     return (char *)NULL;
 
-  memcpy(newstr, str, (len+1)*sizeof(char));
+  memcpy(newstr, str, (len + 1)*sizeof(char));
 
   return newstr;
 
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index d56dcd912..df85d7129 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -49,7 +49,7 @@ static CURLcode glob_fixed(URLGlob *glob, char *fixed, size_t 
len)
   if(!pat->content.Set.elements)
     return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
 
-  pat->content.Set.elements[0] = malloc(len+1);
+  pat->content.Set.elements[0] = malloc(len + 1);
   if(!pat->content.Set.elements[0])
     return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
 
@@ -113,7 +113,7 @@ static CURLcode glob_set(URLGlob *glob, char **patternp,
                          CURLE_URL_MALFORMAT);
 
       /* add 1 to size since it'll be incremented below */
-      if(multiply(amount, pat->content.Set.size+1))
+      if(multiply(amount, pat->content.Set.size + 1))
         return GLOBERROR("range overflow", 0, CURLE_URL_MALFORMAT);
 
       /* fall-through */
@@ -207,7 +207,7 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
         if(errno || &pattern[4] == endp || *endp != ']')
           step = 0;
         else
-          pattern = endp+1;
+          pattern = endp + 1;
       }
       else if(end_c != ']')
         /* then this is wrong */
@@ -259,12 +259,12 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
     errno = 0;
     min_n = strtoul(pattern, &endp, 10);
     if(errno || (endp == pattern))
-      endp=NULL;
+      endp = NULL;
     else {
       if(*endp != '-')
         endp = NULL;
       else {
-        pattern = endp+1;
+        pattern = endp + 1;
         while(*pattern && ISBLANK(*pattern))
           pattern++;
         if(!ISDIGIT(*pattern)) {
@@ -277,7 +277,7 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
           /* overflow */
           endp = NULL;
         else if(*endp == ':') {
-          pattern = endp+1;
+          pattern = endp + 1;
           errno = 0;
           step_n = strtoul(pattern, &endp, 10);
           if(errno)
@@ -287,7 +287,7 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
         else
           step_n = 1;
         if(endp && (*endp == ']')) {
-          pattern= endp+1;
+          pattern = endp + 1;
         }
         else
           endp = NULL;
@@ -384,8 +384,8 @@ static CURLcode glob_parse(URLGlob *glob, char *pattern,
 
       /* only allow \ to escape known "special letters" */
       if(*pattern == '\\' &&
-         (*(pattern+1) == '{' || *(pattern+1) == '[' ||
-          *(pattern+1) == '}' || *(pattern+1) == ']') ) {
+         (*(pattern + 1) == '{' || *(pattern + 1) == '[' ||
+          *(pattern + 1) == '}' || *(pattern + 1) == ']') ) {
 
         /* escape character, skip '\' */
         ++pattern;
@@ -444,7 +444,7 @@ CURLcode glob_url(URLGlob **glob, char *url, unsigned long 
*urlnum,
   glob_buffer = malloc(strlen(url) + 1);
   if(!glob_buffer)
     return CURLE_OUT_OF_MEMORY;
-  glob_buffer[0]=0;
+  glob_buffer[0] = 0;
 
   glob_expand = calloc(1, sizeof(URLGlob));
   if(!glob_expand) {
@@ -623,12 +623,12 @@ CURLcode glob_match_url(char **result, char *filename, 
URLGlob *glob)
       unsigned long i;
       char *ptr = filename;
       unsigned long num = strtoul(&filename[1], &filename, 10);
-      URLPattern *pat =NULL;
+      URLPattern *pat = NULL;
 
       if(num < glob->size) {
         num--; /* make it zero based */
         /* find the correct glob entry */
-        for(i=0; i<glob->size; i++) {
+        for(i = 0; i<glob->size; i++) {
           if(glob->pattern[i].globindex == (int)num) {
             pat = &glob->pattern[i];
             break;
diff --git a/tests/FILEFORMAT b/tests/FILEFORMAT
index 75e561ae8..fbeee2a7e 100644
--- a/tests/FILEFORMAT
+++ b/tests/FILEFORMAT
@@ -74,6 +74,8 @@ B) The request was HTTP and included digest details, which 
adds 1000 to NUM
 C) If a HTTP request is NTLM type-1, it adds 1001 to num
 D) If a HTTP request is NTLM type-3, it adds 1002 to num
 E) If a HTTP request is Basic and num is already >=1000, it adds 1 to num
+F) If a HTTP request is Negotiate, num gets incremented by one for each
+request with Negotiate authorization header on the same test case.
 
 Dynamically changing num in this way allows the test harness to be used to
 test authentication negotiation where several different requests must be sent
@@ -243,6 +245,7 @@ threaded-resolver
 unittest
 unix-sockets
 WinSSL
+ld_preload
 
 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
diff --git a/tests/curl_test_data.py b/tests/curl_test_data.py
index bfe1287d8..21747407d 100755
--- a/tests/curl_test_data.py
+++ b/tests/curl_test_data.py
@@ -24,12 +24,15 @@
 from __future__ import (absolute_import, division, print_function,
                         unicode_literals)
 import os
-import xml.etree.ElementTree as ET
+import re
 import logging
 
 log = logging.getLogger(__name__)
 
 
+REPLY_DATA = re.compile("<reply>\s*<data>(.*?)</data>", re.MULTILINE | 
re.DOTALL)
+
+
 class TestData(object):
     def __init__(self, data_folder):
         self.data_folder = data_folder
@@ -39,15 +42,17 @@ class TestData(object):
         filename = os.path.join(self.data_folder,
                                 "test{0}".format(test_number))
 
-        # The user should handle the exception from failing to find the file.
-        tree = ET.parse(filename)
+        log.debug("Parsing file %s", filename)
+
+        with open(filename, "rb") as f:
+            contents = f.read().decode("utf-8")
 
-        # We need the <reply><data> text.
-        reply = tree.find("reply")
-        data = reply.find("data")
+        m = REPLY_DATA.search(contents)
+        if not m:
+            raise Exception("Couldn't find a <reply><data> section")
 
-        # Return the text contents of the data
-        return data.text
+        # Left-strip the data so we don't get a newline before our data.
+        return m.group(1).lstrip()
 
 
 if __name__ == '__main__':
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 103036040..4243c2183 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -71,13 +71,14 @@ test545 test546 test547 test548 test549 test550 test551 
test552 test553 \
 test554 test555 test556 test557 test558 test559 test560 test561 test562 \
 test563 test564 test565 test566 test567 test568 test569 test570 test571 \
 test572 test573 test574 test575 test576         test578 test579 test580 \
-test581 test582 test583 test584 test585 test586 test587 test588         \
+test581 test582 test583 test584 test585 test586 test587 test588 test589 \
 test590 test591 test592 test593 test594 test595 test596 test597 test598 \
 test599 test600 test601 test602 test603 test604 test605 test606 test607 \
 test608 test609 test610 test611 test612 test613 test614 test615 test616 \
 test617 test618 test619 test620 test621 test622 test623 test624 test625 \
 test626 test627 test628 test629 test630 test631 test632 test633 test634 \
-test635 test636 test637 test638 test639 test640 test641 \
+test635 test636 test637 test638 test639 test640 test641 test642 \
+test643 test644 test645 test646 test647 test648 test649 test650 \
 \
 test700 test701 test702 test703 test704 test705 test706 test707 test708 \
 test709 test710 test711 test712 test713 test714 test715 \
@@ -87,7 +88,7 @@ test809 test810 test811 test812 test813 test814 test815 
test816 test817 \
 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 \
+test845 test846 \
 \
 test850 test851 test852 test853 test854 test855 test856 test857 test858 \
 test859 test860 test861 test862 test863 test864 test865 test866 test867 \
@@ -119,8 +120,11 @@ test1104 test1105 test1106 test1107 test1108 test1109 
test1110 test1111 \
 test1112 test1113 test1114 test1115 test1116 test1117 test1118 test1119 \
 test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 \
 test1128 test1129 test1130 test1131 test1132 test1133 test1134 test1135 \
-test1136 test1137 test1138 test1140 test1141 test1142 test1143 \
-test1144 test1145 test1146 test1147 test1148 \
+test1136 test1137 test1138 test1139 test1140 test1141 test1142 test1143 \
+test1144 test1145 test1146 test1147 test1148 test1149 test1150 test1151 \
+test1152 test1153 \
+\
+test1160 test1161 \
 test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
 test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
 test1216 test1217 test1218 test1219 \
@@ -154,8 +158,8 @@ test1416 test1417 test1418 test1419 test1420 test1421 
test1422 test1423 \
 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          test1450 test1451 \
-test1452 \
+test1444 test1445 test1446 test1447 test1448 test1449 test1450 test1451 \
+test1452 test1453 \
 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
 test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \
 test1516 test1517 \
@@ -172,7 +176,7 @@ test1700 test1701 test1702 \
 \
 test1800 test1801 \
 \
-test1900 test1901 test1902 test1903 \
+test1900 test1901 test1902 test1903 test1904 \
 \
 test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
 test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \
@@ -180,4 +184,5 @@ test2016 test2017 test2018 test2019 test2020 test2021 
test2022 test2023 \
 test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
 test2032 test2033 test2034 test2035 test2036 test2037 test2038 test2039 \
 test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 \
-test2048 test2049 test2050 test2051 test2052 test2053 test2054 test2055
+test2048 test2049 test2050 test2051 test2052 test2053 test2054 test2055 \
+test2056 test2057
diff --git a/tests/data/test1053 b/tests/data/test1053
index 8c60e5ce3..239a1100f 100644
--- a/tests/data/test1053
+++ b/tests/data/test1053
@@ -79,7 +79,6 @@ User-Agent: curl/7.18.2 (i686-pc-linux-gnu) libcurl/7.18.2 
OpenSSL/0.9.7a ipv6 z
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 410
-Expect: 100-continue
 Content-Type: multipart/form-data; 
boundary=----------------------------9ef8d6205763
 
 ------------------------------9ef8d6205763
@@ -104,7 +103,6 @@ User-Agent: curl/7.18.2 (i686-pc-linux-gnu) libcurl/7.18.2 
OpenSSL/0.9.7a ipv6 z
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 410
-Expect: 100-continue
 Content-Type: multipart/form-data; 
boundary=----------------------------9ef8d6205763
 
 ------------------------------9ef8d6205763
diff --git a/tests/data/test1133 b/tests/data/test1133
index 8b016fc14..2238b9c07 100644
--- a/tests/data/test1133
+++ b/tests/data/test1133
@@ -47,8 +47,7 @@ POST /we/want/1133 HTTP/1.1
 User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 OpenSSL/0.9.7a ipv6 
zlib/1.1.3
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 967
-Expect: 100-continue
+Content-Length: 969
 Content-Type: multipart/form-data; 
boundary=----------------------------24e78000bd32
 
 ------------------------------24e78000bd32
@@ -89,6 +88,7 @@ This is a bar foo
 bar
 foo
 
+
 ------------------------------24e78000bd32--
 </protocol>
 </verify>
diff --git a/tests/data/test1135 b/tests/data/test1135
index f7c6a7ae2..6a80ddf69 100644
--- a/tests/data/test1135
+++ b/tests/data/test1135
@@ -28,8 +28,20 @@ Verify CURL_EXTERN order
 
 <verify>
 <stdout>
-CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2);
-CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n);
+CURL_EXTERN int curl_strequal(const char *s1, const char *s2);
+CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n);
+CURL_EXTERN curl_mime *curl_mime_init(CURL *easy);
+CURL_EXTERN void curl_mime_free(curl_mime *mime);
+CURL_EXTERN curl_mimepart *curl_mime_addpart(curl_mime *mime);
+CURL_EXTERN CURLcode curl_mime_name(curl_mimepart *part, const char *name);
+CURL_EXTERN CURLcode curl_mime_filename(curl_mimepart *part,
+CURL_EXTERN CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype);
+CURL_EXTERN CURLcode curl_mime_encoder(curl_mimepart *part,
+CURL_EXTERN CURLcode curl_mime_data(curl_mimepart *part,
+CURL_EXTERN CURLcode curl_mime_filedata(curl_mimepart *part,
+CURL_EXTERN CURLcode curl_mime_data_cb(curl_mimepart *part,
+CURL_EXTERN CURLcode curl_mime_subparts(curl_mimepart *part,
+CURL_EXTERN CURLcode curl_mime_headers(curl_mimepart *part,
 CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost,
 CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg,
 CURL_EXTERN void curl_formfree(struct curl_httppost *form);
@@ -43,6 +55,7 @@ CURL_EXTERN void curl_free(void *p);
 CURL_EXTERN CURLcode curl_global_init(long flags);
 CURL_EXTERN CURLcode curl_global_init_mem(long flags,
 CURL_EXTERN void curl_global_cleanup(void);
+CURL_EXTERN CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
 CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *,
 CURL_EXTERN void curl_slist_free_all(struct curl_slist *);
 CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused);
diff --git a/tests/data/test1139 b/tests/data/test1139
new file mode 100644
index 000000000..72761c670
--- /dev/null
+++ b/tests/data/test1139
@@ -0,0 +1,27 @@
+<testcase>
+<info>
+<keywords>
+source analysis
+symbols-in-versions
+documentation
+--manual
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+
+ <name>
+Verify that all libcurl options have man pages
+ </name>
+
+<command type="perl">
+%SRCDIR/manpage-scan.pl %SRCDIR/.. %PWD/..
+</command>
+</client>
+
+</testcase>
diff --git a/tests/data/test1149 b/tests/data/test1149
new file mode 100644
index 000000000..ae081a8a9
--- /dev/null
+++ b/tests/data/test1149
@@ -0,0 +1,64 @@
+# based on test1010
+<testcase>
+<info>
+<keywords>
+FTP
+PASV
+LIST
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+# When doing LIST, we get the default list output hard-coded in the test
+# FTP server
+<datacheck mode="text">
+total 20
+drwxr-xr-x   8 98       98           512 Oct 22 13:06 .
+drwxr-xr-x   8 98       98           512 Oct 22 13:06 ..
+drwxr-xr-x   2 98       98           512 May  2  1996 .NeXT
+-r--r--r--   1 0        1             35 Jul 16  1996 README
+lrwxrwxrwx   1 0        1              7 Dec  9  1999 bin -> usr/bin
+dr-xr-xr-x   2 0        1            512 Oct  1  1997 dev
+drwxrwxrwx   2 98       98           512 May 29 16:04 download.html
+dr-xr-xr-x   2 0        1            512 Nov 30  1995 etc
+drwxrwxrwx   2 98       1            512 Oct 30 14:33 pub
+dr-xr-xr-x   5 0        1            512 Oct  1  1997 usr
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+ftp
+</server>
+ <name>
+FTP dir list multicwd then again nocwd
+ </name>
+ <command>
+ftp://%HOSTIP:%FTPPORT/list/this/path/1149/ --ftp-method multicwd --next 
ftp://%HOSTIP:%FTPPORT/list/this/path/1149/ --ftp-method nocwd
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous
+PASS address@hidden
+PWD
+CWD list
+CWD this
+CWD path
+CWD 1149
+EPSV
+TYPE A
+LIST
+CWD /
+EPSV
+LIST list/this/path/1149/
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1150 b/tests/data/test1150
new file mode 100644
index 000000000..ecd95d57e
--- /dev/null
+++ b/tests/data/test1150
@@ -0,0 +1,55 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP proxy
+</keywords>
+</info>
+# Server-side
+<reply>
+
+# this is returned when we get a GET!
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Content-Length: 7
+Content-Type: text/html
+Funny-head: yesyes
+
+daniel
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP proxy with URLs using different ports
+ </name>
+ <command>
+--proxy http://%HOSTIP:%HTTPPORT http://test.remote.example.com.1150:150/path 
http://test.remote.example.com.1150:1234/path/
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent: curl/.*
+</strip>
+<protocol>
+GET http://test.remote.example.com.1150:150/path HTTP/1.1
+Host: test.remote.example.com.1150:150
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+GET http://test.remote.example.com.1150:1234/path/ HTTP/1.1
+Host: test.remote.example.com.1150:1234
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1151 b/tests/data/test1151
new file mode 100644
index 000000000..08658d8db
--- /dev/null
+++ b/tests/data/test1151
@@ -0,0 +1,66 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+cookies
+</keywords>
+</info>
+
+# Server-side
+<reply>
+
+# reject cookies with too long name (instead of capping)
+# 3000 bytes name + 1096 bytes content is fine
+# 3000 bytes name + 1097 bytes content is NOT OK
+# 4096 bytes name + 1 byte content is NOT OK
+# 4094 bytes name + 1 byte content is fine
+<data>
+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
+Set-Cookie: foobar=name; domain=127.0.0.1; path=/;
+Set-Cookie: 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 [...]
+Set-Cookie: 
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
 [...]
+Set-Cookie: 
DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
 [...]
+Set-Cookie: 
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
 [...]
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP with too long cookies
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/1151 -c log/cookies1151.txt
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /1151 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+<file name="log/cookies1151.txt">
+# Netscape HTTP Cookie File
+# https://curl.haxx.se/docs/http-cookies.html
+# This file was generated by libcurl! Edit at your own risk.
+
+127.0.0.1      FALSE   /       FALSE   0       foobar  name
+127.0.0.1      FALSE   /       FALSE   0       
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 [...]
+127.0.0.1      FALSE   /       FALSE   0       
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
 [...]
+</file>
+</verify>
+</testcase>
diff --git a/tests/data/test1152 b/tests/data/test1152
new file mode 100644
index 000000000..aa8c0a7e4
--- /dev/null
+++ b/tests/data/test1152
@@ -0,0 +1,61 @@
+<testcase>
+<info>
+<keywords>
+FTP
+PASV
+LIST
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY PWD 257 "just one
+</servercmd>
+
+# When doing LIST, we get the default list output hard-coded in the test
+# FTP server
+<data mode="text">
+total 20
+drwxr-xr-x   8 98       98           512 Oct 22 13:06 .
+drwxr-xr-x   8 98       98           512 Oct 22 13:06 ..
+drwxr-xr-x   2 98       98           512 May  2  1996 curl-releases
+-r--r--r--   1 0        1             35 Jul 16  1996 README
+lrwxrwxrwx   1 0        1              7 Dec  9  1999 bin -> usr/bin
+dr-xr-xr-x   2 0        1            512 Oct  1  1997 dev
+drwxrwxrwx   2 98       98           512 May 29 16:04 download.html
+dr-xr-xr-x   2 0        1            512 Nov 30  1995 etc
+drwxrwxrwx   2 98       1            512 Oct 30 14:33 pub
+dr-xr-xr-x   5 0        1            512 Oct  1  1997 usr
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+ftp
+</server>
+ <name>
+FTP with uneven quote in PWD response
+ </name>
+ <command>
+ftp://%HOSTIP:%FTPPORT/test-1152/
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous
+PASS address@hidden
+PWD
+CWD test-1152
+EPSV
+TYPE A
+LIST
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1153 b/tests/data/test1153
new file mode 100644
index 000000000..c0e37c133
--- /dev/null
+++ b/tests/data/test1153
@@ -0,0 +1,61 @@
+<testcase>
+<info>
+<keywords>
+FTP
+PASV
+LIST
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY PWD 257 "/""hello"""
+</servercmd>
+
+# When doing LIST, we get the default list output hard-coded in the test
+# FTP server
+<data mode="text">
+total 20
+drwxr-xr-x   8 98       98           512 Oct 22 13:06 .
+drwxr-xr-x   8 98       98           512 Oct 22 13:06 ..
+drwxr-xr-x   2 98       98           512 May  2  1996 curl-releases
+-r--r--r--   1 0        1             35 Jul 16  1996 README
+lrwxrwxrwx   1 0        1              7 Dec  9  1999 bin -> usr/bin
+dr-xr-xr-x   2 0        1            512 Oct  1  1997 dev
+drwxrwxrwx   2 98       98           512 May 29 16:04 download.html
+dr-xr-xr-x   2 0        1            512 Nov 30  1995 etc
+drwxrwxrwx   2 98       1            512 Oct 30 14:33 pub
+dr-xr-xr-x   5 0        1            512 Oct  1  1997 usr
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+ftp
+</server>
+ <name>
+FTP with quoted double quotes
+ </name>
+ <command>
+ftp://%HOSTIP:%FTPPORT/test-1153/
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous
+PASS address@hidden
+PWD
+CWD test-1153
+EPSV
+TYPE A
+LIST
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1160 b/tests/data/test1160
new file mode 100644
index 000000000..26a758c4e
--- /dev/null
+++ b/tests/data/test1160
@@ -0,0 +1,49 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+cookies
+</keywords>
+</info>
+
+# Server-side
+<reply>
+
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Content-Length: 0
+Set-Cookie:             �=         ;                                           
                                                                          �     
                                                                                
                                                                                
                                                                                
                                                                                
              [...]
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP with long funny format cookie
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/1160 -c log/cookies1160.txt
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /1160 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+<file name="log/cookies1160.txt">
+</file>
+</verify>
+</testcase>
diff --git a/tests/data/test1161 b/tests/data/test1161
new file mode 100644
index 000000000..179531314
--- /dev/null
+++ b/tests/data/test1161
@@ -0,0 +1,54 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+cookies
+</keywords>
+</info>
+
+# Server-side
+<reply>
+
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Content-Length: 0
+Set-Cookie: ckyPersistent=permanent;path=;path=/
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP cookie with path set twice
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/1161 -c log/cookies1161.txt
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /1161 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+<file name="log/cookies1161.txt">
+# Netscape HTTP Cookie File
+# https://curl.haxx.se/docs/http-cookies.html
+# This file was generated by libcurl! Edit at your own risk.
+
+127.0.0.1      FALSE   /       FALSE   0       ckyPersistent   permanent
+</file>
+</verify>
+</testcase>
diff --git a/tests/data/test1315 b/tests/data/test1315
index c2f158a95..888ddc5c1 100644
--- a/tests/data/test1315
+++ b/tests/data/test1315
@@ -47,8 +47,7 @@ POST /we/want/1315 HTTP/1.1
 User-Agent: curl/7.18.2 (i686-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.7a ipv6 
zlib/1.1.4
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 795
-Expect: 100-continue
+Content-Length: 797
 Content-Type: multipart/form-data; 
boundary=----------------------------9ef8d6205763
 
 ------------------------------9ef8d6205763
@@ -77,6 +76,7 @@ Content-Type: text/plain
 dummy data
 
 ------------------------------aaaaaaaaaaaa--
+
 ------------------------------9ef8d6205763--
 </protocol>
 </verify>
diff --git a/tests/data/test1401 b/tests/data/test1401
index deb1b5ed8..940cf8eba 100644
--- a/tests/data/test1401
+++ b/tests/data/test1401
@@ -84,10 +84,10 @@ int main(int argc, char *argv[])
   curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1401";);
   curl_easy_setopt(hnd, CURLOPT_HEADER, 1L);
   curl_easy_setopt(hnd, CURLOPT_USERPWD, "fake:user");
-  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "MyUA");
+  curl_easy_setopt(hnd, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC);
   curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, slist1);
+  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "MyUA");
   curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
-  curl_easy_setopt(hnd, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC);
   curl_easy_setopt(hnd, CURLOPT_COOKIE, "chocolate=chip");
   curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
   curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
diff --git a/tests/data/test1404 b/tests/data/test1404
index 4265bf882..a26f477bd 100644
--- a/tests/data/test1404
+++ b/tests/data/test1404
@@ -27,13 +27,13 @@ Connection: close
 http
 </server>
  <name>
---libcurl for HTTP RFC1867-type formposting - -F with three files, one with 
explicit type
+--libcurl for HTTP RFC1867-type formposting - -F with 3 files, one with 
explicit type & encoder
  </name>
 <setenv>
 SSL_CERT_FILE=
 </setenv>
  <command>
-http://%HOSTIP:%HTTPPORT/we/want/1404 -F name=value -F 
'address@hidden/test1404.txt,log/test1404.txt;type=magic/content,log/test1404.txt'
 --libcurl log/test1404.c
+http://%HOSTIP:%HTTPPORT/we/want/1404 -F name=value -F 
'address@hidden/test1404.txt,log/test1404.txt;type=magic/content;encoder=8bit,log/test1404.txt;headers=X-testheader-1:
 header 1;headers=X-testheader-2: header 2' --libcurl log/test1404.c
 </command>
 # We create this file before the command is invoked!
 <file name="log/test1404.txt">
@@ -51,8 +51,7 @@ POST /we/want/1404 HTTP/1.1
 User-Agent: curl/7.18.2 (i686-pc-linux-gnu) libcurl/7.18.2 OpenSSL/0.9.7a ipv6 
zlib/1.1.4
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 795
-Expect: 100-continue
+Content-Length: 882
 Content-Type: multipart/form-data; 
boundary=----------------------------9ef8d6205763
 
 ------------------------------9ef8d6205763
@@ -71,16 +70,20 @@ dummy data
 ------------------------------9ef8d6205763
 Content-Disposition: attachment; filename="test1404.txt"
 Content-Type: magic/content
+Content-Transfer-Encoding: 8bit
 
 dummy data
 
 ------------------------------9ef8d6205763
 Content-Disposition: attachment; filename="test1404.txt"
 Content-Type: text/plain
+X-testheader-1: header 1
+X-testheader-2: header 2
 
 dummy data
 
 ------------------------------aaaaaaaaaaaa--
+
 ------------------------------9ef8d6205763--
 </protocol>
 <stripfile>
@@ -103,30 +106,42 @@ int main(int argc, char *argv[])
 {
   CURLcode ret;
   CURL *hnd;
-  struct curl_httppost *post1;
-  struct curl_httppost *postend;
+  curl_mime *mime1;
+  curl_mimepart *part1;
+  curl_mime *mime2;
+  curl_mimepart *part2;
+  struct curl_slist *slist1;
 
-  post1 = NULL;
-  postend = NULL;
-  curl_formadd(&post1, &postend,
-               CURLFORM_COPYNAME, "name",
-               CURLFORM_COPYCONTENTS, "value",
-               CURLFORM_END);
-  curl_formadd(&post1, &postend,
-               CURLFORM_COPYNAME, "file",
-               CURLFORM_FILE, "log/test1404.txt",
-               CURLFORM_CONTENTTYPE, "text/plain",
-               CURLFORM_FILE, "log/test1404.txt",
-               CURLFORM_CONTENTTYPE, "magic/content",
-               CURLFORM_FILE, "log/test1404.txt",
-               CURLFORM_CONTENTTYPE, "text/plain",
-               CURLFORM_END);
+  mime1 = NULL;
+  mime2 = NULL;
+  slist1 = NULL;
+  slist1 = curl_slist_append(slist1, "X-testheader-1: header 1");
+  slist1 = curl_slist_append(slist1, "X-testheader-2: header 2");
 
   hnd = curl_easy_init();
   curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
   curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1404";);
   curl_easy_setopt(hnd, CURLOPT_HEADER, 1L);
-  curl_easy_setopt(hnd, CURLOPT_HTTPPOST, post1);
+  mime1 = curl_mime_init(hnd);
+  part1 = curl_mime_addpart(mime1);
+  curl_mime_data(part1, "value", CURL_ZERO_TERMINATED);
+  curl_mime_name(part1, "name");
+  part1 = curl_mime_addpart(mime1);
+  mime2 = curl_mime_init(hnd);
+  part2 = curl_mime_addpart(mime2);
+  curl_mime_filedata(part2, "log/test1404.txt");
+  part2 = curl_mime_addpart(mime2);
+  curl_mime_filedata(part2, "log/test1404.txt");
+  curl_mime_encoder(part2, "8bit");
+  curl_mime_type(part2, "magic/content");
+  part2 = curl_mime_addpart(mime2);
+  curl_mime_filedata(part2, "log/test1404.txt");
+  curl_mime_headers(part2, slist1, 1);
+  slist1 = NULL;
+  curl_mime_subparts(part1, mime2);
+  mime2 = NULL;
+  curl_mime_name(part1, "file");
+  curl_easy_setopt(hnd, CURLOPT_MIMEPOST, mime1);
   curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
   curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
   curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
@@ -156,8 +171,12 @@ int main(int argc, char *argv[])
 
   curl_easy_cleanup(hnd);
   hnd = NULL;
-  curl_formfree(post1);
-  post1 = NULL;
+  curl_mime_free(mime1);
+  mime1 = NULL;
+  curl_mime_free(mime2);
+  mime2 = NULL;
+  curl_slist_free_all(slist1);
+  slist1 = NULL;
 
   return (int)ret;
 }
diff --git a/tests/data/test1449 b/tests/data/test1449
new file mode 100644
index 000000000..d30c13c68
--- /dev/null
+++ b/tests/data/test1449
@@ -0,0 +1,38 @@
+# initially based on test110
+<testcase>
+<info>
+<keywords>
+FTP
+PASV
+RETR
+Resume
+</keywords>
+</info>
+# Server-side
+<reply>
+</reply>
+
+# Client-side
+<client>
+<server>
+ftp
+</server>
+ <name>
+FTP download range with integer overflow
+ </name>
+ <command>
+ftp://%HOSTIP:%FTPPORT/1449 -r 36893488147419103232-
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+USER anonymous
+PASS address@hidden
+PWD
+EPSV
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1453 b/tests/data/test1453
new file mode 100644
index 000000000..eaf9dd3b9
--- /dev/null
+++ b/tests/data/test1453
@@ -0,0 +1,38 @@
+<testcase>
+<info>
+<keywords>
+Too long tftp filename
+FAILURE
+</keywords>
+</info>
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+<features>
+tftp
+</features>
+ <name>
+Too long tftp filename
+ </name>
+ <command>
+tftp://%HOSTIP:%TFTPPORT/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 [...]
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# TFTP file name too long
+<errorcode>
+71
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test158 b/tests/data/test158
index 9c4b22f70..dca51b163 100644
--- a/tests/data/test158
+++ b/tests/data/test158
@@ -41,7 +41,6 @@ User-Agent: curl/7.11.2-CVS (i686-pc-linux-gnu) 
libcurl/7.11.2-CVS OpenSSL/0.9.6
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 145
-Expect: 100-continue
 Content-Type: multipart/form-data; 
boundary=----------------------------4f12fcdaa3bc
 
 ------------------------------4f12fcdaa3bc
diff --git a/tests/data/test163 b/tests/data/test163
index 22341c045..b4e2d260f 100644
--- a/tests/data/test163
+++ b/tests/data/test163
@@ -54,7 +54,6 @@ User-Agent: curl/7.11.2-CVS (i686-pc-linux-gnu) 
libcurl/7.11.2-CVS OpenSSL/0.9.6
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 304
-Expect: 100-continue
 Content-Type: multipart/form-data; 
boundary=----------------------------c2d1767eb6ac
 
 ------------------------------c2d1767eb6ac
diff --git a/tests/data/test166 b/tests/data/test166
index 2036773f8..f170752e6 100644
--- a/tests/data/test166
+++ b/tests/data/test166
@@ -46,7 +46,6 @@ User-Agent: curl/7.12.0-CVS (i686-pc-linux-gnu) 
libcurl/7.12.0-CVS OpenSSL/0.9.6
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 223
-Expect: 100-continue
 Content-Type: multipart/form-data; 
boundary=----------------------------b0b3d6d23991
 
 ------------------------------b0b3d6d23991
diff --git a/tests/data/test173 b/tests/data/test173
index bf6af0007..754950105 100644
--- a/tests/data/test173
+++ b/tests/data/test173
@@ -53,10 +53,11 @@ POST /we/want/173 HTTP/1.1
 User-Agent: curl/7.12.1-CVS (i686-pc-linux-gnu) libcurl/7.12.1-CVS 
OpenSSL/0.9.6b ipv6 zlib/1.1.4 GSS libidn/0.4.6
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 360
+Transfer-Encoding: chunked
 Expect: 100-continue
 Content-Type: multipart/form-data; 
boundary=----------------------------5dbea401cd8c
 
+168
 ------------------------------5dbea401cd8c
 Content-Disposition: form-data; name="field1"
 
@@ -75,6 +76,9 @@ line7
 line8
 
 ------------------------------5dbea401cd8c--
+
+0
+
 </protocol>
 </verify>
 </testcase>
diff --git a/tests/data/test186 b/tests/data/test186
index b07736cbc..4abc74a2b 100644
--- a/tests/data/test186
+++ b/tests/data/test186
@@ -43,8 +43,7 @@ POST /we/want/186 HTTP/1.1
 User-Agent: curl/7.12.2-CVS (i686-pc-linux-gnu) libcurl/7.12.2-CVS 
OpenSSL/0.9.7d zlib/1.2.1.1 c-ares/1.2.0 libidn/0.5.2
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 321
-Expect: 100-continue
+Content-Length: 320
 Content-Type: multipart/form-data; 
boundary=----------------------------212d9006ceb5
 
 ------------------------------212d9006ceb5
@@ -56,7 +55,7 @@ daniel
 Content-Disposition: form-data; name="html"
 Content-Type: text/html;charset=verymoo
 
- <body>hello</body>
+<body>hello</body>
 ------------------------------212d9006ceb5--
 </protocol>
 </verify>
diff --git a/tests/data/test1904 b/tests/data/test1904
new file mode 100644
index 000000000..08ad534a6
--- /dev/null
+++ b/tests/data/test1904
@@ -0,0 +1,79 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP CONNECT
+HTTP proxy
+proxytunnel
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Content-Type: text/html
+Funny-head: yesyes
+Content-Length: 9
+
+contents
+</data>
+<connect>
+HTTP/1.1 204 Sure go ahead
+
+</connect>
+<datacheck>
+HTTP/1.1 204 Sure go ahead
+
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake swsclose
+Content-Type: text/html
+Funny-head: yesyes
+Content-Length: 9
+
+contents
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+http-proxy
+</server>
+ <name>
+HTTP CONNECT with 204 response
+ </name>
+ <command>
+http://test.1904:%HTTPPORT/we/want/that/page/1904 -p --proxy %HOSTIP:%PROXYPORT
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<proxy>
+CONNECT test.1904:%HTTPPORT HTTP/1.1
+Host: test.1904:%HTTPPORT
+User-Agent: curl/7.10.7-pre2 (i686-pc-linux-gnu) libcurl/7.10.7-pre2 
OpenSSL/0.9.7a zlib/1.1.3
+Proxy-Connection: Keep-Alive
+
+</proxy>
+<protocol>
+GET /we/want/that/page/1904 HTTP/1.1
+Host: test.1904:%HTTPPORT
+User-Agent: curl/7.10.7-pre2 (i686-pc-linux-gnu) libcurl/7.10.7-pre2 
OpenSSL/0.9.7a zlib/1.1.3
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test2056 b/tests/data/test2056
new file mode 100644
index 000000000..f00e21204
--- /dev/null
+++ b/tests/data/test2056
@@ -0,0 +1,87 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP Negotiate auth (stub krb5)
+</keywords>
+</info>
+# Server-side
+<reply>
+<!-- First request, expect 401 Negotiate -->
+<data>
+HTTP/1.1 401 Authorization Required
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate
+Content-Length: 13
+
+Not yet sir!
+</data>
+<!-- Second request, expect success in one shot -->
+<data1>
+HTTP/1.1 200 Things are fine in server land
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate RA==
+Content-Length: 15
+
+Nice auth sir!
+</data1>
+<datacheck>
+HTTP/1.1 401 Authorization Required
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate
+Content-Length: 13
+
+HTTP/1.1 200 Things are fine in server land
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate RA==
+Content-Length: 15
+
+Nice auth sir!
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+HTTP Negotiate authentication (stub krb5)
+</name>
+<features>
+GSS-API
+ld_preload
+!debug
+</features>
+<setenv>
+LD_PRELOAD=%PWD/libtest/.libs/libstubgss.so
+CURL_STUB_GSS_CREDS="KRB5_Alice"
+</setenv>
+<command>
+-u: --negotiate http://%HOSTIP:%HTTPPORT/2056
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /2056 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /2056 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Negotiate 
IktSQjVfQWxpY2UiOkhUVFBAMTI3LjAuMC4xOjE6QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test2057 b/tests/data/test2057
new file mode 100644
index 000000000..562505168
--- /dev/null
+++ b/tests/data/test2057
@@ -0,0 +1,108 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP Negotiate auth (stub ntlm)
+</keywords>
+</info>
+# Server-side
+<reply>
+<!-- First request, expect 401 Negotiate -->
+<data>
+HTTP/1.1 401 Authorization Required
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate
+Content-Length: 13
+
+Not yet sir!
+</data>
+<!-- Second request, expect 401 (ntlm challenge) -->
+<data1>
+HTTP/1.1 401 Authorization Required
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate Qw==
+Content-Length: 19
+
+Still not yet sir!
+</data1>
+<!-- Third request, expect success  -->
+<data2>
+HTTP/1.1 200 Things are fine in server land
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate RA==
+Content-Length: 15
+
+Nice auth sir!
+</data2>
+<datacheck>
+HTTP/1.1 401 Authorization Required
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate
+Content-Length: 13
+
+HTTP/1.1 401 Authorization Required
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate Qw==
+Content-Length: 19
+
+HTTP/1.1 200 Things are fine in server land
+Server: Microsoft-IIS/7.0
+Content-Type: text/html; charset=iso-8859-1
+WWW-Authenticate: Negotiate RA==
+Content-Length: 15
+
+Nice auth sir!
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+HTTP Negotiate authentication (stub ntlm)
+</name>
+<features>
+GSS-API
+ld_preload
+!debug
+</features>
+<setenv>
+LD_PRELOAD=%PWD/libtest/.libs/libstubgss.so
+CURL_STUB_GSS_CREDS="NTLM_Alice"
+</setenv>
+<command>
+-u: --negotiate http://%HOSTIP:%HTTPPORT/2057
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /2057 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /2057 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Negotiate 
Ik5UTE1fQWxpY2UiOkhUVFBAMTI3LjAuMC4xOjI6QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==
+Accept: */*
+
+GET /2057 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Negotiate 
Ik5UTE1fQWxpY2UiOkhUVFBAMTI3LjAuMC4xOjM6QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test259 b/tests/data/test259
index 9532887a9..6e1853601 100644
--- a/tests/data/test259
+++ b/tests/data/test259
@@ -59,7 +59,7 @@ crypto
 HTTP POST multipart with Expect: header using proxy anyauth (Digest)
  </name>
  <command>
--x http://%HOSTIP:%HTTPPORT http://remotehost:54321/we/want/259 -F name=daniel 
-F tool=curl -F address@hidden/test259.txt -U uuuser:pppassword --proxy-anyauth
+-x http://%HOSTIP:%HTTPPORT http://remotehost:54321/we/want/259 -F name=daniel 
-F tool=curl -F address@hidden/test259.txt -U uuuser:pppassword --proxy-anyauth 
-H "Expect: 100-continue"
 </command>
 # We create this file before the command is invoked!
 <file name="log/test259.txt">
@@ -80,8 +80,8 @@ Host: remotehost:54321
 User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 OpenSSL/0.9.7a ipv6 
zlib/1.1.3
 Accept: */*
 Proxy-Connection: Keep-Alive
-Content-Length: 409
 Expect: 100-continue
+Content-Length: 409
 Content-Type: multipart/form-data; 
boundary=----------------------------7c633d5c27ce
 
 ------------------------------7c633d5c27ce
@@ -107,8 +107,8 @@ User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 
OpenSSL/0.9.7a ipv6 z
 Proxy-Authorization: Digest username="uuuser", realm="many secrets", 
nonce="911", uri="/we/want/259", response="b479994d13e60f3aa192a67c5892ddc5"
 Accept: */*
 Proxy-Connection: Keep-Alive
-Content-Length: 409
 Expect: 100-continue
+Content-Length: 409
 Content-Type: multipart/form-data; 
boundary=----------------------------7c633d5c27ce
 
 ------------------------------7c633d5c27ce
diff --git a/tests/data/test277 b/tests/data/test277
index a509b40ec..d3e9d0fa4 100644
--- a/tests/data/test277
+++ b/tests/data/test277
@@ -45,12 +45,11 @@ POST /want/277 HTTP/1.1
 User-Agent: curl/7.10.4 (i686-pc-linux-gnu) libcurl/7.10.4 OpenSSL/0.9.7a ipv6 
zlib/1.1.3
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 145
-Expect: 100-continue
+Content-Length: 146
 Content-Type: text/info; boundary=------------------------
 
 --------------------------
-Content-Disposition: form-data; name="name"
+Content-Disposition: attachment; name="name"
 
 daniel
 ----------------------------
diff --git a/tests/data/test4 b/tests/data/test4
index df69d3274..542347db5 100644
--- a/tests/data/test4
+++ b/tests/data/test4
@@ -30,7 +30,7 @@ http
 Replaced internal and added custom HTTP headers
  </name>
  <command>
- -H "extra-header: here" -H "Accept: replaced" -H "X-Custom-Header;" -H 
"X-Test: foo; " -H "X-Test:" -H "X-Test2: foo;" -H "X-Test3:  " -H "X-Test4;  " 
-H "X-Test5;ignored" http://%HOSTIP:%HTTPPORT/4
+ -H "extra-header: here" -H "Accept: replaced" -H "X-Custom-Header;" -H 
"X-Test: foo; " -H "X-Test:" -H "X-Test2: foo;" -H "X-Test3:  " -H "X-Test4;  " 
-H "X-Test5;ignored" http://%HOSTIP:%HTTPPORT/4 http://%HOSTIP:%HTTPPORT/4
 </command>
 </client>
 
@@ -49,6 +49,14 @@ X-Custom-Header:
 X-Test: foo; 
 X-Test2: foo;
 
+GET /4 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+extra-header: here
+Accept: replaced
+X-Custom-Header:
+X-Test: foo; 
+X-Test2: foo;
+
 </protocol>
 </verify>
 </testcase>
diff --git a/tests/data/test46 b/tests/data/test46
index d1045b331..abcbda8e6 100644
--- a/tests/data/test46
+++ b/tests/data/test46
@@ -19,7 +19,7 @@ Set-Cookie: ckyPersistent=permanent; expires=Fri, 02-Feb-2035 
11:56:27 GMT; path
 Set-Cookie: ckySession=temporary; path=/
 Set-Cookie: ASPSESSIONIDQGGQQSJJ=GKNBDIFAAOFDPDAIEAKDIBKE; path=/
 Set-Cookie: justaname=; path=/;
-Set-Cookie: 
simplyhuge=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
 [...]
+Set-Cookie: 
simplyhuge=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
 [...]
 Cache-control: private
 Content-Length: 41
 
@@ -83,7 +83,7 @@ www.loser.com FALSE   /       FALSE   2139150993      UID     
99
 %HOSTIP        FALSE   /       FALSE   0       ckySession      temporary
 %HOSTIP        FALSE   /       FALSE   0       ASPSESSIONIDQGGQQSJJ    
GKNBDIFAAOFDPDAIEAKDIBKE
 %HOSTIP        FALSE   /       FALSE   0       justaname       
-%HOSTIP        FALSE   /want/  FALSE   0       simplyhuge      
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
 [...]
+%HOSTIP        FALSE   /want/  FALSE   0       simplyhuge      
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
 [...]
 </file>
 </verify>
 </testcase>
diff --git a/tests/data/test506 b/tests/data/test506
index 40eee2532..70d2daada 100644
--- a/tests/data/test506
+++ b/tests/data/test506
@@ -195,6 +195,8 @@ CURLOPT_COOKIEJAR
 CURLOPT_COOKIELIST RELOAD
 lock:   cookie [Pigs in space]: 78
 unlock: cookie [Pigs in space]: 79
+lock:   cookie [Pigs in space]: 80
+unlock: cookie [Pigs in space]: 81
 loaded cookies:
 -----------------
   .host.foo.com        TRUE    /       FALSE   1896263787      injected        
yes
@@ -207,17 +209,17 @@ loaded cookies:
   www.host.foo.com     FALSE   /       FALSE   1993463787      test6   six_more
 -----------------
 try SHARE_CLEANUP...
-lock:   share  [Pigs in space]: 80
-unlock: share  [Pigs in space]: 81
+lock:   share  [Pigs in space]: 82
+unlock: share  [Pigs in space]: 83
 SHARE_CLEANUP failed, correct
 CLEANUP
-lock:   cookie [Pigs in space]: 82
-unlock: cookie [Pigs in space]: 83
-lock:   share  [Pigs in space]: 84
-unlock: share  [Pigs in space]: 85
-SHARE_CLEANUP
+lock:   cookie [Pigs in space]: 84
+unlock: cookie [Pigs in space]: 85
 lock:   share  [Pigs in space]: 86
 unlock: share  [Pigs in space]: 87
+SHARE_CLEANUP
+lock:   share  [Pigs in space]: 88
+unlock: share  [Pigs in space]: 89
 GLOBAL_CLEANUP
 </stdout>
 <stderr>
diff --git a/tests/data/test554 b/tests/data/test554
index 3419e5e0f..ce4a14dc4 100644
--- a/tests/data/test554
+++ b/tests/data/test554
@@ -69,7 +69,6 @@ POST /554 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 718
-Expect: 100-continue
 Content-Type: multipart/form-data; boundary=----------------------------
 
 ------------------------------
@@ -100,7 +99,6 @@ POST /554 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 732
-Expect: 100-continue
 Content-Type: multipart/form-data; boundary=----------------------------
 
 ------------------------------
diff --git a/tests/data/test564 b/tests/data/test564
index 72bf12919..4c9ecd466 100644
--- a/tests/data/test564
+++ b/tests/data/test564
@@ -1,4 +1,6 @@
 <testcase>
+# Warning: if this test fails to start the SSH server, check that none of
+# the user's shell profiles sends output to stdout of a non-interactive shell.
 <info>
 <keywords>
 FTP
diff --git a/tests/data/test587 b/tests/data/test587
index 69cbe1ed7..689a877db 100644
--- a/tests/data/test587
+++ b/tests/data/test587
@@ -43,7 +43,6 @@ POST /587 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 718
-Expect: 100-continue
 Content-Type: multipart/form-data; boundary=----------------------------
 
 ------------------------------
diff --git a/tests/data/test589 b/tests/data/test589
new file mode 100644
index 000000000..451bb15bd
--- /dev/null
+++ b/tests/data/test589
@@ -0,0 +1,55 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+HTTP 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>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# tool is what to use instead of 'curl'
+<tool>
+lib589
+</tool>
+
+ <name>
+make a HTTP MIME POST set to NULL
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/589
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+POST /589 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 0
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test642 b/tests/data/test642
new file mode 100644
index 000000000..41fd444fc
--- /dev/null
+++ b/tests/data/test642
@@ -0,0 +1,42 @@
+<testcase>
+<info>
+<keywords>
+SFTP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+Test data
+for ssh test
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+sftp
+</server>
+ <name>
+SFTP retrieval
+ </name>
+ <command>
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: --compressed-ssh 
sftp://%HOSTIP:%SSHPORT%PWD/log/file642.txt --insecure
+</command>
+<file name="log/file642.txt">
+Test data
+for ssh test
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<valgrind>
+disable
+</valgrind>
+</verify>
+</testcase>
diff --git a/tests/data/test554 b/tests/data/test643
similarity index 91%
copy from tests/data/test554
copy to tests/data/test643
index 3419e5e0f..0eaf22c5f 100644
--- a/tests/data/test554
+++ b/tests/data/test643
@@ -3,6 +3,7 @@
 <keywords>
 HTTP
 HTTP POST
+HTTP MIME POST
 </keywords>
 </info>
 
@@ -43,14 +44,14 @@ http
 </server>
 # tool is what to use instead of 'curl'
 <tool>
-lib554
+lib643
 </tool>
 
  <name>
-HTTP multi-part formpost using read callback for the file part
+HTTP multi-part mimepost using read callback for the file part
  </name>
  <command>
-http://%HOSTIP:%HTTPPORT/554
+http://%HOSTIP:%HTTPPORT/643
 </command>
 </client>
 
@@ -65,11 +66,10 @@ 
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 /554 HTTP/1.1
+POST /643 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 718
-Expect: 100-continue
 Content-Type: multipart/form-data; boundary=----------------------------
 
 ------------------------------
@@ -96,11 +96,10 @@ Content-Type: text/plain
 
 blah blah
 --------------------------------
-POST /554 HTTP/1.1
+POST /643 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 732
-Expect: 100-continue
 Content-Type: multipart/form-data; boundary=----------------------------
 
 ------------------------------
diff --git a/tests/data/test587 b/tests/data/test644
similarity index 91%
copy from tests/data/test587
copy to tests/data/test644
index 69cbe1ed7..6ac37ce54 100644
--- a/tests/data/test587
+++ b/tests/data/test644
@@ -3,6 +3,7 @@
 <keywords>
 HTTP
 HTTP POST
+HTTP MIME POST
 </keywords>
 </info>
 
@@ -20,14 +21,14 @@ http
 </server>
 # tool is what to use instead of 'curl'
 <tool>
-lib587
+lib644
 </tool>
 
  <name>
 HTTP multi-part formpost with aborted read callback
  </name>
  <command>
-http://%HOSTIP:%HTTPPORT/587
+http://%HOSTIP:%HTTPPORT/644
 </command>
 </client>
 
@@ -39,11 +40,10 @@ 
s/^--------------------------[a-z0-9]*/------------------------------/
 
s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
 </strippart>
 <protocol>
-POST /587 HTTP/1.1
+POST /644 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 718
-Expect: 100-continue
 Content-Type: multipart/form-data; boundary=----------------------------
 
 ------------------------------
diff --git a/tests/data/test554 b/tests/data/test645
similarity index 89%
copy from tests/data/test554
copy to tests/data/test645
index 3419e5e0f..6533944b4 100644
--- a/tests/data/test554
+++ b/tests/data/test645
@@ -3,6 +3,7 @@
 <keywords>
 HTTP
 HTTP POST
+HTTP MIME POST
 </keywords>
 </info>
 
@@ -43,14 +44,14 @@ http
 </server>
 # tool is what to use instead of 'curl'
 <tool>
-lib554
+lib645
 </tool>
 
  <name>
-HTTP multi-part formpost using read callback for the file part
+HTTP multi-part chunked mimepost using read callback for the file part
  </name>
  <command>
-http://%HOSTIP:%HTTPPORT/554
+http://%HOSTIP:%HTTPPORT/645
 </command>
 </client>
 
@@ -65,13 +66,14 @@ 
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 /554 HTTP/1.1
+POST /645 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 718
-Expect: 100-continue
+Transfer-Encoding: chunked
 Content-Type: multipart/form-data; boundary=----------------------------
+Expect: 100-continue
 
+2ce
 ------------------------------
 Content-Disposition: form-data; name="sendfile"; filename="postit2.c"
 
@@ -96,13 +98,17 @@ Content-Type: text/plain
 
 blah blah
 --------------------------------
-POST /554 HTTP/1.1
+
+0
+
+POST /645 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
-Content-Length: 732
-Expect: 100-continue
+Transfer-Encoding: chunked
 Content-Type: multipart/form-data; boundary=----------------------------
+Expect: 100-continue
 
+2dc
 ------------------------------
 Content-Disposition: form-data; name="sendfile alternative"; filename="file 
name 2"
 
@@ -127,6 +133,9 @@ Content-Type: text/plain
 
 blah blah
 --------------------------------
+
+0
+
 </protocol>
 </verify>
 </testcase>
diff --git a/tests/data/test646 b/tests/data/test646
new file mode 100644
index 000000000..a53c34090
--- /dev/null
+++ b/tests/data/test646
@@ -0,0 +1,98 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+MULTIPART
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+ <name>
+SMTP multipart using mime API
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/646 --mail-rcpt address@hidden --mail-from 
address@hidden -F "=(;type=multipart/alternative" -F "= <body>This is the html 
version</body>;headers=X-test1: this is a 
header;type=text/html;headers=X-test2: this is another header " -F "=This is 
the plain text version;address@hidden/headers646" -F "=)" -F 
"address@hidden/test646.txt;headers=<log/headers646" -H "From: different" -H 
"To: another" -H "Reply-To: <address@hidden>"
+</command>
+<file1 name="log/test646.txt">
+This is an attached file.
+
+It may contain any type of data.
+</file1>
+<file2 name="log/headers646">
+# This line is a comment
+X-fileheader1: This is a header from a file 
+
+# This line is another comment. It precedes a folded header.
+X-fileheader2: This is 
#a
+ folded header
+</file2>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+<protocol>
+EHLO 646
+MAIL FROM:<address@hidden>
+RCPT TO:<address@hidden>
+DATA
+QUIT
+</protocol>
+<upload>
+Content-Type: multipart/mixed; boundary=----------------------------
+Mime-Version: 1.0
+From: different
+To: another
+Reply-To: <address@hidden>
+
+------------------------------
+Content-Type: multipart/alternative; boundary=----------------------------
+
+------------------------------
+Content-Type: text/html
+Content-Transfer-Encoding: 8bit
+X-test1: this is a header
+X-test2: this is another header
+
+<body>This is the html version</body>
+------------------------------
+X-fileheader1: This is a header from a file
+X-fileheader2: This is #a folded header
+
+This is the plain text version
+--------------------------------
+
+------------------------------
+Content-Disposition: attachment; filename="test646.txt"
+X-fileheader1: This is a header from a file
+X-fileheader2: This is #a folded header
+
+This is an attached file.
+
+It may contain any type of data.
+
+--------------------------------
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test647 b/tests/data/test647
new file mode 100644
index 000000000..de2b467fc
--- /dev/null
+++ b/tests/data/test647
@@ -0,0 +1,79 @@
+<testcase>
+<info>
+<keywords>
+IMAP
+APPEND
+MULTIPART
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+imap
+</server>
+ <name>
+IMAP APPEND multipart using mime API
+ </name>
+ <command>
+imap://%HOSTIP:%IMAPPORT/647 -F "=(;type=multipart/alternative" -F "= 
<body>This is the html version</body>;type=text/html" -F "=This is the plain 
text version" -F "=)" -F "address@hidden/test647.txt" -H "Date: Mon, 7 Feb 1994 
21:52:25 -0800 (PST)" -H "From: Fred Foobar <address@hidden>" -H "To: 
address@hidden" -H "Message-Id: <address@hidden>" -H "Subject: afternoon 
meeting" -u user:secret
+</command>
+<file name="log/test647.txt">
+This is an attached file.
+
+It may contain any type of data.
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+<protocol>
+A001 CAPABILITY
+A002 LOGIN user secret
+A003 APPEND 647 (\Seen) {892}
+A004 LOGOUT
+</protocol>
+<upload>
+Content-Type: multipart/mixed; boundary=----------------------------
+Mime-Version: 1.0
+Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
+From: Fred Foobar <address@hidden>
+To: address@hidden
+Message-Id: <address@hidden>
+Subject: afternoon meeting
+
+------------------------------
+Content-Type: multipart/alternative; boundary=----------------------------
+
+------------------------------
+Content-Type: text/html
+Content-Transfer-Encoding: 8bit
+
+<body>This is the html version</body>
+------------------------------
+
+This is the plain text version
+--------------------------------
+
+------------------------------
+Content-Disposition: attachment; filename="test647.txt"
+
+This is an attached file.
+
+It may contain any type of data.
+
+--------------------------------
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test648 b/tests/data/test648
new file mode 100644
index 000000000..cd8f02085
--- /dev/null
+++ b/tests/data/test648
@@ -0,0 +1,75 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+MULTIPART
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+ <name>
+SMTP multipart with transfer content encoders
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/648 --mail-rcpt address@hidden --mail-from 
address@hidden -F '=This is the e-mail inline text with a very long line 
containing the special character = and that should be split by 
encoder.;headers=Content-disposition: "inline";encoder=quoted-printable' -F 
"address@hidden/test648.txt;encoder=base64" -H "From: different" -H "To: 
another"
+</command>
+<file name="log/test648.txt">
+This is an attached file.
+
+It may contain any type of data and will be encoded in base64 for transfer.
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+<protocol>
+EHLO 648
+MAIL FROM:<address@hidden>
+RCPT TO:<address@hidden>
+DATA
+QUIT
+</protocol>
+<upload>
+Content-Type: multipart/mixed; boundary=----------------------------
+Mime-Version: 1.0
+From: different
+To: another
+
+------------------------------
+Content-Transfer-Encoding: quoted-printable
+Content-disposition: "inline"
+
+This is the e-mail inline text with a very long line containing the special=
+ character =3D and that should be split by encoder.
+------------------------------
+Content-Disposition: attachment; filename="test648.txt"
+Content-Transfer-Encoding: base64
+
+VGhpcyBpcyBhbiBhdHRhY2hlZCBmaWxlLgoKSXQgbWF5IGNvbnRhaW4gYW55IHR5cGUgb2Yg
+ZGF0YSBhbmQgd2lsbCBiZSBlbmNvZGVkIGluIGJhc2U2NCBmb3IgdHJhbnNmZXIuCg==
+--------------------------------
+.
+</upload>
+</verify>
+</testcase>
diff --git a/tests/data/test649 b/tests/data/test649
new file mode 100644
index 000000000..46c01cd00
--- /dev/null
+++ b/tests/data/test649
@@ -0,0 +1,72 @@
+<testcase>
+<info>
+<keywords>
+SMTP
+MULTIPART
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+smtp
+</server>
+ <name>
+SMTP multipart with 7bit encoder error
+ </name>
+<stdin>
+From: different
+To: another
+
+body
+</stdin>
+ <command>
+smtp://%HOSTIP:%SMTPPORT/649 --mail-rcpt address@hidden --mail-from 
address@hidden -F '=This is valid;encoder=7bit' -F 
"address@hidden/test649.txt;encoder=7bit" -H "From: different" -H "To: another"
+</command>
+<file name="log/test649.txt">
+This is an attached file (in french: pièce jointe).
+
+It contains at least an 8-bit byte value.
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+<protocol>
+EHLO 649
+MAIL FROM:<address@hidden>
+RCPT TO:<address@hidden>
+DATA
+</protocol>
+<upload nonewline="yes">
+Content-Type: multipart/mixed; boundary=----------------------------
+Mime-Version: 1.0
+From: different
+To: another
+
+------------------------------
+Content-Transfer-Encoding: 7bit
+
+This is valid
+------------------------------
+Content-Disposition: attachment; filename="test649.txt"
+Content-Transfer-Encoding: 7bit
+
+This is an attached file (in french: pi
+</upload>
+<errorcode>
+26
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test650 b/tests/data/test650
new file mode 100644
index 000000000..e07d4c10b
--- /dev/null
+++ b/tests/data/test650
@@ -0,0 +1,122 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+FORM
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<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>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+# tool is what to use instead of 'curl'
+<tool>
+lib650
+</tool>
+
+ <name>
+HTTP formpost using form API
+ </name>
+<stdin>
+ Some data from stdin
+</stdin>
+ <command>
+http://%HOSTIP:%HTTPPORT/650 log/test650.filedata
+</command>
+<file name="log/test650.filedata">
+This is data from a file.
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strippart>
+s/^--------------------------[a-z0-9]*/------------------------------/
+s/boundary=------------------------[a-z0-9]*/boundary=----------------------------/
+</strippart>
+# Note that the stripping above removes 12 bytes from every occurrence of the
+# boundary string and since 5 of them are in the body contents, we see
+# (5*12) == 60 bytes less
+<protocol>
+POST /650 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Transfer-Encoding: chunked
+Content-Type: multipart/form-data; boundary=----------------------------
+Expect: 100-continue
+
+5f0
+------------------------------
+Content-Disposition: form-data; name="fieldname"
+
+this is what we post to the silly web server
+------------------------------
+Content-Disposition: form-data; name="fieldnam"
+
+uhis is what we post to the silly web serve
+------------------------------
+Content-Disposition: form-data; name="multifile"
+Content-Type: multipart/mixed; boundary=----------------------------
+
+------------------------------
+Content-Disposition: attachment; filename="test650.filedata"
+Content-Type: application/octet-stream
+
+This is data from a file.
+
+------------------------------
+Content-Disposition: attachment; filename="test650.filedata"
+Content-Type: text/whatever
+
+This is data from a file.
+
+------------------------------
+Content-Disposition: attachment; filename="test650.filedata"
+Content-Type: text/whatever
+
+This is data from a file.
+
+--------------------------------
+
+------------------------------
+Content-Disposition: form-data; name="filecontents"
+X-customheader-1: Header 1 data
+X-customheader-2: Header 2 data
+
+This is data from a file.
+
+------------------------------
+Content-Disposition: form-data; name="formlength"
+
+1341
+------------------------------
+Content-Disposition: form-data; name="standardinput"
+Content-Type: application/octet-stream
+
+ Some data from stdin
+
+--------------------------------
+
+0
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test71 b/tests/data/test71
index 341a0033f..0bc76fc03 100644
--- a/tests/data/test71
+++ b/tests/data/test71
@@ -54,7 +54,6 @@ POST /we/want/71 HTTP/1.1
 Host: %HOSTIP:%HTTPPORT
 Accept: */*
 Content-Length: 408
-Expect: 100-continue
 Content-Type: multipart/form-data; 
boundary=----------------------------9ef8d6205763
 
 ------------------------------9ef8d6205763
diff --git a/tests/data/test800 b/tests/data/test800
index 6b29f7a2b..360206b43 100644
--- a/tests/data/test800
+++ b/tests/data/test800
@@ -31,7 +31,7 @@ imap
 IMAP FETCH message
  </name>
  <command>
-'imap://%HOSTIP:%IMAPPORT/800/;UID=1' -u user:secret
+'imap://%HOSTIP:%IMAPPORT/800/;UID=1' -u '"user:sec"ret{'
 </command>
 </client>
 
@@ -40,7 +40,7 @@ IMAP FETCH message
 <verify>
 <protocol>
 A001 CAPABILITY
-A002 LOGIN user secret
+A002 LOGIN "\"user" "sec\"ret{"
 A003 SELECT 800
 A004 FETCH 1 BODY[]
 A005 LOGOUT
diff --git a/tests/data/test846 b/tests/data/test846
new file mode 100644
index 000000000..b363ffd18
--- /dev/null
+++ b/tests/data/test846
@@ -0,0 +1,50 @@
+<testcase>
+<info>
+<keywords>
+IMAP
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<servercmd>
+REPLY welcome * PREAUTH ready to serve already!
+REPLY CAPABILITY * CAPABILITY IMAP4REV1 I18NLEVEL=1 LITERAL+ IDLE UIDPLUS 
NAMESPACE CHILDREN MAILBOX-REFERRALS BINARY UNSELECT ESEARCH WITHIN SCAN SORT 
THREAD=REFERENCES THREAD=ORDEREDSUBJECT MULTIAPPEND SASL-IR LOGIN-REFERRALS 
STARTTLS LOGINDISABLED\r\nA001 OK CAPABILITY completed
+</servercmd>
+<data>
+From: address@hidden
+To: address@hidden
+
+body
+
+--
+  yours sincerely
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+imap
+</server>
+ <name>
+IMAP PREAUTH response
+ </name>
+ <command>
+'imap://%HOSTIP:%IMAPPORT/846/;UID=1' -u notused:still-provided
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+A001 CAPABILITY
+A002 SELECT 846
+A003 FETCH 1 BODY[]
+A004 LOGOUT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test856 b/tests/data/test856
index 4d8d7ed61..dcb07c5a9 100644
--- a/tests/data/test856
+++ b/tests/data/test856
@@ -10,6 +10,9 @@ FAILURE
 #
 # Server-side
 <reply>
+<servercmd>
+REPLY PASS -ERR Login failure
+</servercmd>
 </reply>
 
 #
diff --git a/tests/data/test9 b/tests/data/test9
index 7905ac838..53fe25eda 100644
--- a/tests/data/test9
+++ b/tests/data/test9
@@ -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: 407
-Expect: 100-continue
 Content-Type: multipart/form-data; 
boundary=----------------------------9ef8d6205763
 
 ------------------------------9ef8d6205763
diff --git a/tests/ftpserver.pl b/tests/ftpserver.pl
index 081298f1b..2aba4263a 100755
--- a/tests/ftpserver.pl
+++ b/tests/ftpserver.pl
@@ -6,7 +6,7 @@
 #                            | (__| |_| |  _ <| |___
 #                             \___|\___/|_| \_\_____|
 #
-# Copyright (C) 1998 - 2014, Daniel Stenberg, <address@hidden>, et al.
+# Copyright (C) 1998 - 2014, 2017, 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
@@ -174,7 +174,6 @@ my $exit_signal;         # first signal handled in 
exit_signal_handler
 #**********************************************************************
 # Mail related definitions
 #
-my $TEXT_USERNAME = "user";
 my $TEXT_PASSWORD = "secret";
 my $POP3_TIMESTAMP = "<address@hidden>";
 
@@ -1121,9 +1120,6 @@ sub LOGIN_imap {
     if ($user eq "") {
         sendcontrol "$cmdid BAD Command Argument\r\n";
     }
-    elsif (($user ne $TEXT_USERNAME) || ($password ne $TEXT_PASSWORD)) {
-        sendcontrol "$cmdid NO LOGIN failed\r\n";
-    }
     else {
         sendcontrol "$cmdid OK LOGIN completed\r\n";
     }
@@ -1681,7 +1677,7 @@ sub APOP_pop3 {
     else {
         my $digest = Digest::MD5::md5_hex($POP3_TIMESTAMP, $TEXT_PASSWORD);
 
-        if (($user ne $TEXT_USERNAME) || ($secret ne $digest)) {
+        if ($secret ne $digest) {
             sendcontrol "-ERR Login failure\r\n";
         }
         else {
@@ -1740,12 +1736,7 @@ sub PASS_pop3 {
 
     logmsg "PASS_pop3 got $password\n";
 
-    if (($username ne $TEXT_USERNAME) || ($password ne $TEXT_PASSWORD)) {
-        sendcontrol "-ERR Login failure\r\n";
-    }
-    else {
-        sendcontrol "+OK Login successful\r\n";
-    }
+    sendcontrol "+OK Login successful\r\n";
 
     return 0;
 }
diff --git a/tests/fuzz/Makefile.am b/tests/fuzz/Makefile.am
index 259b86c4f..dcea6d576 100644
--- a/tests/fuzz/Makefile.am
+++ b/tests/fuzz/Makefile.am
@@ -26,30 +26,31 @@ AUTOMAKE_OPTIONS = foreign nostdinc
 # being currently built and tested are searched before the library which
 # might possibly already be installed in the system.
 #
-
-
 # $(top_srcdir)/include is for libcurl's external include files
 # $(top_builddir)/lib is for libcurl's generated lib/curl_config.h file
 # $(top_srcdir)/lib for libcurl's lib/curl_setup.h and other "borrowed" files
 
-AM_CPPFLAGS = -I$(top_srcdir)/include        \
+AM_CXXFLAGS = -I$(top_srcdir)/include        \
               -I$(top_builddir)/lib          \
               -I$(top_srcdir)/lib            \
               -I$(top_srcdir)/tests/fuzz
 
-EXTRA_DIST = Makefile.inc CMakeLists.txt
+LIBS = -lpthread -lm
 
-LIBS = -lpthread -lFuzzer -lstdc++ -lm
-LDFLAGS = -L/usr/lib/llvm-5.0/lib
+# Run e.g. "make all LIB_FUZZING_ENGINE=/path/to/libFuzzer.a"
+# to link the fuzzer(s) against a real fuzzing engine.
+#
+# OSS-Fuzz will define its own value for LIB_FUZZING_ENGINE.
+LIB_FUZZING_ENGINE ?= libstandaloneengine.a
 
 LDADD = $(top_builddir)/lib/libgnurl.la      \
-        @LDFLAGS@ @LIBCURL_LIBS@
+        $(LIB_FUZZING_ENGINE) @LDFLAGS@ @LIBCURL_LIBS@
 
 # Makefile.inc provides neat definitions
 include Makefile.inc
 
 checksrc:
-       @PERL@ $(top_srcdir)/lib/checksrc.pl $(srcdir)/*.c
+       @PERL@ $(top_srcdir)/lib/checksrc.pl $(srcdir)/*.cc
 
 noinst_PROGRAMS = $(FUZZPROGS)
-
+noinst_LIBRARIES = $(FUZZLIBS)
diff --git a/tests/fuzz/Makefile.inc b/tests/fuzz/Makefile.inc
index fb6cdb11a..f52adb89c 100644
--- a/tests/fuzz/Makefile.inc
+++ b/tests/fuzz/Makefile.inc
@@ -1,19 +1,15 @@
-FUZZPROGS = http11 ftp imap pop3 httpupload http2
+FUZZPROGS = curl_fuzzer
+FUZZLIBS = libstandaloneengine.a
 
-http11_SOURCES = curl_fuzzer.c
-http11_CPPFLAGS = $(AM_CPPFLAGS)
+curl_fuzzer_SOURCES = curl_fuzzer.cc
+curl_fuzzer_CXXFLAGS = $(AM_CXXFLAGS)
 
-ftp_SOURCES = curl_fuzzer.c
-ftp_CPPFLAGS = -DFUZZER_FTP $(AM_CPPFLAGS)
+libstandaloneengine_a_SOURCES = standalone_fuzz_target_runner.cc
+libstandaloneengine_a_CXXFLAGS = $(AM_CXXFLAGS)
 
-imap_SOURCES = curl_fuzzer.c
-imap_CPPFLAGS = -DFUZZER_IMAP $(AM_CPPFLAGS)
+# Some more targets.
+zip:
+       zip -q -r curl_fuzzer_seed_corpus.zip curl_fuzz_data
 
-pop3_SOURCES = curl_fuzzer.c
-pop3_CPPFLAGS = -DFUZZER_POP3 $(AM_CPPFLAGS)
-
-httpupload_SOURCES = curl_fuzzer.c
-httpupload_CPPFLAGS = -DFUZZER_HTTP_UPLOAD $(AM_CPPFLAGS)
-
-http2_SOURCES = curl_fuzzer.c
-http2_CPPFLAGS = -DFUZZER_HTTP2 $(AM_CPPFLAGS)
+check: all
+       ./curl_fuzzer curl_fuzz_data/*
diff --git a/tests/fuzz/README b/tests/fuzz/README
index 459bda46b..8b5fcd011 100644
--- a/tests/fuzz/README
+++ b/tests/fuzz/README
@@ -2,13 +2,20 @@ Fuzz tests
 ==========
 
 The goal is to add tests for *ALL* protocols supported in libcurl.
-We will need some additional patches in the future, to increase coverage.
 
 Building the fuzz target
 ========================
+From the CURL root directory:
 
-CC=clang-5.0 CFLAGS="-fsanitize=address -fsanitize-address-use-after-scope 
-fsanitize-coverage=trace-pc-guard,trace-cmp" ./configure --disable-shared 
--enable-debug --enable-maintainer-mode
+export CC=clang-5.0
+export CXX=clang++-5.0
+export CFLAGS="-fsanitize=address -fsanitize-address-use-after-scope 
-fsanitize-coverage=trace-pc-guard,trace-cmp"
+export CXXFLAGS="-fsanitize=address -fsanitize-address-use-after-scope 
-fsanitize-coverage=trace-pc-guard,trace-cmp -stdlib=libc++"
+./configure --disable-shared --enable-debug --enable-maintainer-mode
 make -sj
 
 cd tests/fuzz
-make
+
+(optional) export LIB_FUZZING_ENGINE=<path to libFuzzer.a>
+
+make check
diff --git a/tests/fuzz/corpus.py b/tests/fuzz/corpus.py
new file mode 100644
index 000000000..5474c99af
--- /dev/null
+++ b/tests/fuzz/corpus.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+#
+# Common corpus functions
+import logging
+import struct
+log = logging.getLogger(__name__)
+
+
+class BaseType(object):
+    TYPE_URL = 1
+    TYPE_RSP1 = 2
+    TYPE_USERNAME = 3
+    TYPE_PASSWORD = 4
+    TYPE_POSTFIELDS = 5
+    TYPE_HEADER = 6
+    TYPE_COOKIE = 7
+    TYPE_UPLOAD1 = 8
+    TYPE_RANGE = 9
+    TYPE_CUSTOMREQUEST = 10
+    TYPE_MAIL_RECIPIENT = 11
+    TYPE_MAIL_FROM = 12
+
+
+class TLVEncoder(BaseType):
+    def __init__(self, output):
+        self.output = output
+
+    def write_string(self, tlv_type, wstring):
+        data = wstring.encode("utf-8")
+        self.write_tlv(tlv_type, len(data), data)
+
+    def write_bytes(self, tlv_type, bytedata):
+        self.write_tlv(tlv_type, len(bytedata), bytedata)
+
+    def maybe_write_string(self, tlv_type, wstring):
+        if wstring is not None:
+            self.write_string(tlv_type, wstring)
+
+    def write_tlv(self, tlv_type, tlv_length, tlv_data=None):
+        log.debug("Writing TLV %d, length %d, data %r",
+                  tlv_type,
+                  tlv_length,
+                  tlv_data)
+
+        data = struct.pack("!H", tlv_type)
+        self.output.write(data)
+
+        data = struct.pack("!L", tlv_length)
+        self.output.write(data)
+
+        if tlv_data:
+            self.output.write(tlv_data)
+
+
+class TLVDecoder(BaseType):
+    def __init__(self, inputdata):
+        self.inputdata = inputdata
+        self.pos = 0
+        self.tlv = None
+
+    def __iter__(self):
+        self.pos = 0
+        self.tlv = None
+        return self
+
+    def __next__(self):
+        if self.tlv:
+            self.pos += self.tlv.total_length()
+
+        if (self.pos + TLVHeader.TLV_DECODE_FMT_LEN) > len(self.inputdata):
+            raise StopIteration
+
+        # Get the next TLV
+        self.tlv = TLVHeader(self.inputdata[self.pos:])
+        return self.tlv
+
+    next = __next__
+
+
+class TLVHeader(BaseType):
+    TLV_DECODE_FMT = "!HL"
+    TLV_DECODE_FMT_LEN = struct.calcsize(TLV_DECODE_FMT)
+
+    def __init__(self, data):
+        # Parse the data to populate the TLV fields
+        (self.type, self.length) = struct.unpack(self.TLV_DECODE_FMT, 
data[0:self.TLV_DECODE_FMT_LEN])
+
+        # Get the remaining data and store it.
+        self.data = data[self.TLV_DECODE_FMT_LEN:self.TLV_DECODE_FMT_LEN + 
self.length]
+
+    def __repr__(self):
+        return ("{self.__class__.__name__}(type={self.type!r}, 
length={self.length!r}, data={self.data!r})"
+                .format(self=self))
+
+    def total_length(self):
+        return self.TLV_DECODE_FMT_LEN + self.length
\ No newline at end of file
diff --git a/tests/fuzz/curl_fuzz_data/oss-fuzz-3327 
b/tests/fuzz/curl_fuzz_data/oss-fuzz-3327
new file mode 100644
index 000000000..064cc623a
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/oss-fuzz-3327 differ
diff --git a/tests/fuzz/curl_fuzz_data/test1 b/tests/fuzz/curl_fuzz_data/test1
new file mode 100644
index 000000000..f7b734a9c
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test1 differ
diff --git a/tests/fuzz/curl_fuzz_data/test10 b/tests/fuzz/curl_fuzz_data/test10
new file mode 100644
index 000000000..af1ed53ca
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test10 differ
diff --git a/tests/fuzz/curl_fuzz_data/test100 
b/tests/fuzz/curl_fuzz_data/test100
new file mode 100644
index 000000000..b58d9335a
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test100 differ
diff --git a/tests/fuzz/curl_fuzz_data/test12 b/tests/fuzz/curl_fuzz_data/test12
new file mode 100644
index 000000000..9ad91dc07
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test12 differ
diff --git a/tests/fuzz/curl_fuzz_data/test13 b/tests/fuzz/curl_fuzz_data/test13
new file mode 100644
index 000000000..448077dde
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test13 differ
diff --git a/tests/fuzz/curl_fuzz_data/test1326 
b/tests/fuzz/curl_fuzz_data/test1326
new file mode 100644
index 000000000..8801fac96
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test1326 differ
diff --git a/tests/fuzz/curl_fuzz_data/test1450 
b/tests/fuzz/curl_fuzz_data/test1450
new file mode 100644
index 000000000..601236168
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test1450 differ
diff --git a/tests/fuzz/curl_fuzz_data/test2 b/tests/fuzz/curl_fuzz_data/test2
new file mode 100644
index 000000000..8b44d6719
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test2 differ
diff --git a/tests/fuzz/curl_fuzz_data/test271 
b/tests/fuzz/curl_fuzz_data/test271
new file mode 100644
index 000000000..3a26767f7
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test271 differ
diff --git a/tests/fuzz/curl_fuzz_data/test3 b/tests/fuzz/curl_fuzz_data/test3
new file mode 100644
index 000000000..81c6670aa
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test3 differ
diff --git a/tests/fuzz/curl_fuzz_data/test4 b/tests/fuzz/curl_fuzz_data/test4
new file mode 100644
index 000000000..3fa395a29
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test4 differ
diff --git a/tests/fuzz/curl_fuzz_data/test5 b/tests/fuzz/curl_fuzz_data/test5
new file mode 100644
index 000000000..bdaac4e66
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test5 differ
diff --git a/tests/fuzz/curl_fuzz_data/test6 b/tests/fuzz/curl_fuzz_data/test6
new file mode 100644
index 000000000..98d9be216
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test6 differ
diff --git a/tests/fuzz/curl_fuzz_data/test800 
b/tests/fuzz/curl_fuzz_data/test800
new file mode 100644
index 000000000..a5899be43
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test800 differ
diff --git a/tests/fuzz/curl_fuzz_data/test850 
b/tests/fuzz/curl_fuzz_data/test850
new file mode 100644
index 000000000..22c08dcfc
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test850 differ
diff --git a/tests/fuzz/curl_fuzz_data/test900 
b/tests/fuzz/curl_fuzz_data/test900
new file mode 100644
index 000000000..eecf0cbaf
Binary files /dev/null and b/tests/fuzz/curl_fuzz_data/test900 differ
diff --git a/tests/fuzz/curl_fuzzer.cc b/tests/fuzz/curl_fuzzer.cc
new file mode 100644
index 000000000..dd0298f36
--- /dev/null
+++ b/tests/fuzz/curl_fuzzer.cc
@@ -0,0 +1,447 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017, Max Dymond, <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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <curl/curl.h>
+#include "curl_fuzzer.h"
+
+/**
+ * Fuzzing entry point. This function is passed a buffer containing a test
+ * case.  This test case should drive the CURL API into making a request.
+ */
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+  int rc = 0;
+  int tlv_rc;
+  FUZZ_DATA fuzz;
+  TLV tlv;
+
+  /* Have to set all fields to zero before getting to the terminate function */
+  memset(&fuzz, 0, sizeof(FUZZ_DATA));
+
+  if(size < sizeof(TLV_RAW)) {
+    /* Not enough data for a single TLV - don't continue */
+    goto EXIT_LABEL;
+  }
+
+  /* Try to initialize the fuzz data */
+  FTRY(fuzz_initialize_fuzz_data(&fuzz, data, size));
+
+  for(tlv_rc = fuzz_get_first_tlv(&fuzz, &tlv);
+      tlv_rc == 0;
+      tlv_rc = fuzz_get_next_tlv(&fuzz, &tlv)) {
+
+    /* Have the TLV in hand. Parse the TLV. */
+    rc = fuzz_parse_tlv(&fuzz, &tlv);
+
+    if(rc != 0) {
+      /* Failed to parse the TLV. Can't continue. */
+      goto EXIT_LABEL;
+    }
+  }
+
+  if(tlv_rc != TLV_RC_NO_MORE_TLVS) {
+    /* A TLV call failed. Can't continue. */
+    goto EXIT_LABEL;
+  }
+
+  /* Do the CURL stuff! */
+  if(fuzz.header_list != NULL) {
+    curl_easy_setopt(fuzz.easy, CURLOPT_HTTPHEADER, fuzz.header_list);
+  }
+
+  if(fuzz.mail_recipients_list != NULL) {
+    curl_easy_setopt(fuzz.easy, CURLOPT_MAIL_RCPT, fuzz.mail_recipients_list);
+  }
+
+  curl_easy_perform(fuzz.easy);
+
+EXIT_LABEL:
+
+  fuzz_terminate_fuzz_data(&fuzz);
+
+  /* This function must always return 0. Non-zero codes are reserved. */
+  return 0;
+}
+
+/**
+ * Utility function to convert 4 bytes to a u32 predictably.
+ */
+uint32_t to_u32(uint8_t b[4])
+{
+  uint32_t u;
+  u = (b[0] << 24) + (b[1] << 16) + (b[2] << 8) + b[3];
+  return u;
+}
+
+/**
+ * Utility function to convert 2 bytes to a u16 predictably.
+ */
+uint16_t to_u16(uint8_t b[2])
+{
+  uint16_t u;
+  u = (b[0] << 8) + b[1];
+  return u;
+}
+
+/**
+ * Initialize the local fuzz data structure.
+ */
+int fuzz_initialize_fuzz_data(FUZZ_DATA *fuzz,
+                              const uint8_t *data,
+                              size_t data_len)
+{
+  int rc = 0;
+
+  /* Initialize the fuzz data. */
+  memset(fuzz, 0, sizeof(FUZZ_DATA));
+
+  /* Create an easy handle. This will have all of the settings configured on
+     it. */
+  fuzz->easy = curl_easy_init();
+  FCHECK(fuzz->easy != NULL);
+
+  /* Set some standard options on the CURL easy handle. We need to override the
+     socket function so that we create our own sockets to present to CURL. */
+  FTRY(curl_easy_setopt(fuzz->easy,
+                        CURLOPT_OPENSOCKETFUNCTION,
+                        fuzz_open_socket));
+  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_OPENSOCKETDATA, fuzz));
+
+  /* In case something tries to set a socket option, intercept this. */
+  FTRY(curl_easy_setopt(fuzz->easy,
+                        CURLOPT_SOCKOPTFUNCTION,
+                        fuzz_sockopt_callback));
+
+  /* Set the standard read function callback. */
+  FTRY(curl_easy_setopt(fuzz->easy,
+                        CURLOPT_READFUNCTION,
+                        fuzz_read_callback));
+  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_READDATA, fuzz));
+
+  /* Set the standard write function callback. */
+  FTRY(curl_easy_setopt(fuzz->easy,
+                        CURLOPT_WRITEFUNCTION,
+                        fuzz_write_callback));
+  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_WRITEDATA, fuzz));
+
+  /* Can enable verbose mode by changing 0L to 1L */
+  FTRY(curl_easy_setopt(fuzz->easy, CURLOPT_VERBOSE, 0L));
+
+  /* Set up the state parser */
+  fuzz->state.data = data;
+  fuzz->state.data_len = data_len;
+
+EXIT_LABEL:
+
+  return rc;
+}
+
+/**
+ * Terminate the fuzz data structure, including freeing any allocated memory.
+ */
+void fuzz_terminate_fuzz_data(FUZZ_DATA *fuzz)
+{
+  fuzz_free((void **)&fuzz->url);
+  fuzz_free((void **)&fuzz->username);
+  fuzz_free((void **)&fuzz->password);
+  fuzz_free((void **)&fuzz->postfields);
+  fuzz_free((void **)&fuzz->cookie);
+  fuzz_free((void **)&fuzz->range);
+  fuzz_free((void **)&fuzz->customrequest);
+  fuzz_free((void **)&fuzz->mail_from);
+
+  if(fuzz->header_list != NULL) {
+    curl_slist_free_all(fuzz->header_list);
+    fuzz->header_list = NULL;
+  }
+
+  if(fuzz->mail_recipients_list != NULL) {
+    curl_slist_free_all(fuzz->mail_recipients_list);
+    fuzz->mail_recipients_list = NULL;
+  }
+
+  if(fuzz->easy != NULL) {
+    curl_easy_cleanup(fuzz->easy);
+    fuzz->easy = NULL;
+  }
+}
+
+/**
+ * If a pointer has been allocated, free that pointer.
+ */
+void fuzz_free(void **ptr)
+{
+  if(*ptr != NULL) {
+    free(*ptr);
+    *ptr = NULL;
+  }
+}
+
+/**
+ * Function for providing a socket to CURL already primed with data.
+ */
+static curl_socket_t fuzz_open_socket(void *ptr,
+                                      curlsocktype purpose,
+                                      struct curl_sockaddr *address)
+{
+  FUZZ_DATA *fuzz = (FUZZ_DATA *)ptr;
+  int fds[2];
+  curl_socket_t server_fd;
+  curl_socket_t client_fd;
+
+  /* Handle unused parameters */
+  (void)purpose;
+  (void)address;
+
+  if(socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) {
+    /* Failed to create a pair of sockets. */
+    return CURL_SOCKET_BAD;
+  }
+
+  server_fd = fds[0];
+  client_fd = fds[1];
+
+  /* Try and write the response data to the server file descriptor so the
+     client can read it. */
+  if(write(server_fd,
+           fuzz->rsp1_data,
+           fuzz->rsp1_data_len) != (ssize_t)fuzz->rsp1_data_len) {
+    /* Failed to write the data. */
+    return CURL_SOCKET_BAD;
+  }
+
+  if(shutdown(server_fd, SHUT_WR)) {
+    return CURL_SOCKET_BAD;
+  }
+
+  return client_fd;
+}
+
+/**
+ * Callback function for setting socket options on the sockets created by
+ * fuzz_open_socket. In our testbed the sockets are "already connected".
+ */
+static int fuzz_sockopt_callback(void *ptr,
+                                 curl_socket_t curlfd,
+                                 curlsocktype purpose)
+{
+  (void)ptr;
+  (void)curlfd;
+  (void)purpose;
+
+  return CURL_SOCKOPT_ALREADY_CONNECTED;
+}
+
+/**
+ * Callback function for doing data uploads.
+ */
+static size_t fuzz_read_callback(char *buffer,
+                                 size_t size,
+                                 size_t nitems,
+                                 void *ptr)
+{
+  FUZZ_DATA *fuzz = (FUZZ_DATA *)ptr;
+  curl_off_t nread;
+
+  /* If no upload data has been specified, then return an error code. */
+  if(fuzz->upload1_data_len == 0) {
+    /* No data to upload */
+    return CURL_READFUNC_ABORT;
+  }
+
+  /* Send the upload data. */
+  memcpy(buffer,
+         fuzz->upload1_data,
+         fuzz->upload1_data_len);
+
+  return fuzz->upload1_data_len;
+}
+
+/**
+ * Callback function for handling data output quietly.
+ */
+static size_t fuzz_write_callback(void *contents,
+                                  size_t size,
+                                  size_t nmemb,
+                                  void *ptr)
+{
+  size_t total = size * nmemb;
+  FUZZ_DATA *fuzz = (FUZZ_DATA *)ptr;
+  size_t copy_len = total;
+
+  /* Restrict copy_len to at most TEMP_WRITE_ARRAY_SIZE. */
+  if(copy_len > TEMP_WRITE_ARRAY_SIZE) {
+    copy_len = TEMP_WRITE_ARRAY_SIZE;
+  }
+
+  /* Copy bytes to the temp store just to ensure the parameters are
+     exercised. */
+  memcpy(fuzz->write_array, contents, copy_len);
+
+  return total;
+}
+
+/**
+ * TLV access function - gets the first TLV from a data stream.
+ */
+int fuzz_get_first_tlv(FUZZ_DATA *fuzz,
+                       TLV *tlv)
+{
+  /* Reset the cursor. */
+  fuzz->state.data_pos = 0;
+  return fuzz_get_tlv_comn(fuzz, tlv);
+}
+
+/**
+ * TLV access function - gets the next TLV from a data stream.
+*/
+int fuzz_get_next_tlv(FUZZ_DATA *fuzz,
+                      TLV *tlv)
+{
+  /* Advance the cursor by the full length of the previous TLV. */
+  fuzz->state.data_pos += sizeof(TLV_RAW) + tlv->length;
+
+  /* Work out if there's a TLV's worth of data to read */
+  if(fuzz->state.data_pos + sizeof(TLV_RAW) > fuzz->state.data_len) {
+    /* No more TLVs to parse */
+    return TLV_RC_NO_MORE_TLVS;
+  }
+
+  return fuzz_get_tlv_comn(fuzz, tlv);
+}
+
+/**
+ * Common TLV function for accessing TLVs in a data stream.
+ */
+int fuzz_get_tlv_comn(FUZZ_DATA *fuzz,
+                      TLV *tlv)
+{
+  int rc = 0;
+  size_t data_offset;
+  TLV_RAW *raw;
+
+  /* Start by casting the data stream to a TLV. */
+  raw = (TLV_RAW *)&fuzz->state.data[fuzz->state.data_pos];
+  data_offset = fuzz->state.data_pos + sizeof(TLV_RAW);
+
+  /* Set the TLV values. */
+  tlv->type = to_u16(raw->raw_type);
+  tlv->length = to_u32(raw->raw_length);
+  tlv->value = &fuzz->state.data[data_offset];
+
+  /* Sanity check that the TLV length is ok. */
+  if(data_offset + tlv->length > fuzz->state.data_len) {
+    rc = TLV_RC_SIZE_ERROR;
+  }
+
+  return rc;
+}
+
+/**
+ * Do different actions on the CURL handle for different received TLVs.
+ */
+int fuzz_parse_tlv(FUZZ_DATA *fuzz, TLV *tlv)
+{
+  int rc;
+  char *tmp;
+
+  switch(tlv->type) {
+    case TLV_TYPE_RESPONSE1:
+      /* The pointers in the TLV will always be valid as long as the fuzz data
+         is in scope, which is the entirety of this file. */
+      fuzz->rsp1_data = tlv->value;
+      fuzz->rsp1_data_len = tlv->length;
+      break;
+
+    case TLV_TYPE_UPLOAD1:
+      /* The pointers in the TLV will always be valid as long as the fuzz data
+         is in scope, which is the entirety of this file. */
+      fuzz->upload1_data = tlv->value;
+      fuzz->upload1_data_len = tlv->length;
+
+      curl_easy_setopt(fuzz->easy, CURLOPT_UPLOAD, 1L);
+      curl_easy_setopt(fuzz->easy,
+                       CURLOPT_INFILESIZE_LARGE,
+                       (curl_off_t)fuzz->upload1_data_len);
+      break;
+
+    case TLV_TYPE_HEADER:
+      tmp = fuzz_tlv_to_string(tlv);
+      fuzz->header_list = curl_slist_append(fuzz->header_list, tmp);
+      fuzz_free((void **)&tmp);
+      break;
+
+    case TLV_TYPE_MAIL_RECIPIENT:
+      tmp = fuzz_tlv_to_string(tlv);
+      fuzz->mail_recipients_list =
+                             curl_slist_append(fuzz->mail_recipients_list, 
tmp);
+      fuzz_free((void **)&tmp);
+      break;
+
+    /* Define a set of singleton TLVs - they can only have their value set once
+       and all follow the same pattern. */
+    FSINGLETONTLV(TLV_TYPE_URL, url, CURLOPT_URL);
+    FSINGLETONTLV(TLV_TYPE_USERNAME, username, CURLOPT_USERNAME);
+    FSINGLETONTLV(TLV_TYPE_PASSWORD, password, CURLOPT_PASSWORD);
+    FSINGLETONTLV(TLV_TYPE_POSTFIELDS, postfields, CURLOPT_POSTFIELDS);
+    FSINGLETONTLV(TLV_TYPE_COOKIE, cookie, CURLOPT_COOKIE);
+    FSINGLETONTLV(TLV_TYPE_RANGE, range, CURLOPT_RANGE);
+    FSINGLETONTLV(TLV_TYPE_CUSTOMREQUEST, customrequest, 
CURLOPT_CUSTOMREQUEST);
+    FSINGLETONTLV(TLV_TYPE_MAIL_FROM, mail_from, CURLOPT_MAIL_FROM);
+
+    default:
+      /* The fuzzer generates lots of unknown TLVs - we don't want these in the
+         corpus so we reject any unknown TLVs. */
+      rc = 255;
+      goto EXIT_LABEL;
+      break;
+  }
+
+  rc = 0;
+
+EXIT_LABEL:
+
+  return rc;
+}
+
+/**
+ * Converts a TLV data and length into an allocated string.
+ */
+char *fuzz_tlv_to_string(TLV *tlv)
+{
+  char *tlvstr;
+
+  /* Allocate enough space, plus a null terminator */
+  tlvstr = (char *)malloc(tlv->length + 1);
+
+  if(tlvstr != NULL) {
+    memcpy(tlvstr, tlv->value, tlv->length);
+    tlvstr[tlv->length] = 0;
+  }
+
+  return tlvstr;
+}
diff --git a/tests/fuzz/curl_fuzzer.h b/tests/fuzz/curl_fuzzer.h
new file mode 100644
index 000000000..219ac3ee3
--- /dev/null
+++ b/tests/fuzz/curl_fuzzer.h
@@ -0,0 +1,186 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017, Max Dymond, <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/curl.h>
+#include <testinput.h>
+
+/**
+ * TLV types.
+ */
+#define TLV_TYPE_URL                    1
+#define TLV_TYPE_RESPONSE1              2
+#define TLV_TYPE_USERNAME               3
+#define TLV_TYPE_PASSWORD               4
+#define TLV_TYPE_POSTFIELDS             5
+#define TLV_TYPE_HEADER                 6
+#define TLV_TYPE_COOKIE                 7
+#define TLV_TYPE_UPLOAD1                8
+#define TLV_TYPE_RANGE                  9
+#define TLV_TYPE_CUSTOMREQUEST          10
+#define TLV_TYPE_MAIL_RECIPIENT         11
+#define TLV_TYPE_MAIL_FROM              12
+
+/**
+ * TLV function return codes.
+ */
+#define TLV_RC_NO_ERROR                 0
+#define TLV_RC_NO_MORE_TLVS             1
+#define TLV_RC_SIZE_ERROR               2
+
+/* Temporary write array size */
+#define TEMP_WRITE_ARRAY_SIZE           10
+
+/**
+ * Byte stream representation of the TLV header. Casting the byte stream
+ * to a TLV_RAW allows us to examine the type and length.
+ */
+typedef struct tlv_raw
+{
+  /* Type of the TLV - 16 bits. */
+  uint8_t raw_type[2];
+
+  /* Length of the TLV data - 32 bits. */
+  uint8_t raw_length[4];
+
+} TLV_RAW;
+
+typedef struct tlv
+{
+  /* Type of the TLV */
+  uint16_t type;
+
+  /* Length of the TLV data */
+  uint32_t length;
+
+  /* Pointer to data if length > 0. */
+  const uint8_t *value;
+
+} TLV;
+
+/**
+ * Internal state when parsing a TLV data stream.
+ */
+typedef struct fuzz_parse_state
+{
+  /* Data stream */
+  const uint8_t *data;
+  size_t data_len;
+
+  /* Current position of our "cursor" in processing the data stream. */
+  size_t data_pos;
+
+} FUZZ_PARSE_STATE;
+
+/**
+ * Data local to a fuzzing run.
+ */
+typedef struct fuzz_data
+{
+  /* CURL easy object */
+  CURL *easy;
+
+  /* Parser state */
+  FUZZ_PARSE_STATE state;
+
+  /* Temporary writefunction state */
+  char write_array[TEMP_WRITE_ARRAY_SIZE];
+
+  /* Response data and length */
+  const uint8_t *rsp1_data;
+  size_t rsp1_data_len;
+
+  /* Upload data and length; */
+  const uint8_t *upload1_data;
+  size_t upload1_data_len;
+
+  /* Singleton string fields. */
+  char *url;
+  char *username;
+  char *password;
+  char *postfields;
+  char *cookie;
+  char *range;
+  char *customrequest;
+  char *mail_from;
+
+  /* List of headers */
+  struct curl_slist *header_list;
+
+  /* List of mail recipients */
+  struct curl_slist *mail_recipients_list;
+
+} FUZZ_DATA;
+
+/* Function prototypes */
+uint32_t to_u32(uint8_t b[4]);
+uint16_t to_u16(uint8_t b[2]);
+int fuzz_initialize_fuzz_data(FUZZ_DATA *fuzz,
+                              const uint8_t *data,
+                              size_t data_len);
+void fuzz_terminate_fuzz_data(FUZZ_DATA *fuzz);
+void fuzz_free(void **ptr);
+static curl_socket_t fuzz_open_socket(void *ptr,
+                                      curlsocktype purpose,
+                                      struct curl_sockaddr *address);
+static int fuzz_sockopt_callback(void *ptr,
+                                 curl_socket_t curlfd,
+                                 curlsocktype purpose);
+static size_t fuzz_read_callback(char *buffer,
+                                 size_t size,
+                                 size_t nitems,
+                                 void *ptr);
+static size_t fuzz_write_callback(void *contents,
+                                  size_t size,
+                                  size_t nmemb,
+                                  void *ptr);
+int fuzz_get_first_tlv(FUZZ_DATA *fuzz, TLV *tlv);
+int fuzz_get_next_tlv(FUZZ_DATA *fuzz, TLV *tlv);
+int fuzz_get_tlv_comn(FUZZ_DATA *fuzz, TLV *tlv);
+int fuzz_parse_tlv(FUZZ_DATA *fuzz, TLV *tlv);
+char *fuzz_tlv_to_string(TLV *tlv);
+
+/* Macros */
+#define FTRY(FUNC)                                                             
\
+        {                                                                      
\
+          int _func_rc = (FUNC);                                               
\
+          if (_func_rc)                                                        
\
+          {                                                                    
\
+            rc = _func_rc;                                                     
\
+            goto EXIT_LABEL;                                                   
\
+          }                                                                    
\
+        }
+
+#define FCHECK(COND)                                                           
\
+        {                                                                      
\
+          if (!(COND))                                                         
\
+          {                                                                    
\
+            rc = 255;                                                          
\
+            goto EXIT_LABEL;                                                   
\
+          }                                                                    
\
+        }
+
+#define FSINGLETONTLV(TLVNAME, FIELDNAME, OPTNAME)                             
\
+    case TLVNAME:                                                              
\
+      FCHECK(fuzz->FIELDNAME == NULL);                                         
\
+      fuzz->FIELDNAME = fuzz_tlv_to_string(tlv);                               
\
+      FTRY(curl_easy_setopt(fuzz->easy, OPTNAME, fuzz->FIELDNAME));            
\
+      break
\ No newline at end of file
diff --git a/tests/fuzz/generate_corpus.py b/tests/fuzz/generate_corpus.py
new file mode 100755
index 000000000..cffdd37bf
--- /dev/null
+++ b/tests/fuzz/generate_corpus.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+#
+# Simple script which generates corpus files.
+
+import argparse
+import logging
+import corpus
+import sys
+sys.path.append("..")
+import curl_test_data
+log = logging.getLogger(__name__)
+
+
+def generate_corpus(options):
+    td = curl_test_data.TestData("../data")
+
+    with open(options.output, "wb") as f:
+        enc = corpus.TLVEncoder(f)
+
+        # Write the URL to the file.
+        enc.write_string(enc.TYPE_URL, options.url)
+
+        # Write the first response to the file.
+        if options.rsp1:
+            enc.write_bytes(enc.TYPE_RSP1, options.rsp1.encode("utf-8"))
+
+        elif options.rsp1file:
+            with open(options.rsp1file, "rb") as g:
+                enc.write_bytes(enc.TYPE_RSP1, g.read())
+
+        elif options.rsp1test:
+            wstring = td.get_test_data(options.rsp1test)
+            enc.write_bytes(enc.TYPE_RSP1, wstring.encode("utf-8"))
+
+        # Write other options to file.
+        enc.maybe_write_string(enc.TYPE_USERNAME, options.username)
+        enc.maybe_write_string(enc.TYPE_PASSWORD, options.password)
+        enc.maybe_write_string(enc.TYPE_POSTFIELDS, options.postfields)
+        enc.maybe_write_string(enc.TYPE_COOKIE, options.cookie)
+        enc.maybe_write_string(enc.TYPE_RANGE, options.range)
+        enc.maybe_write_string(enc.TYPE_CUSTOMREQUEST, options.customrequest)
+        enc.maybe_write_string(enc.TYPE_MAIL_FROM, options.mailfrom)
+
+        # Write the first upload to the file.
+        if options.upload1:
+            enc.write_bytes(enc.TYPE_UPLOAD1, options.upload1.encode("utf-8"))
+        elif options.upload1file:
+            with open(options.upload1file, "rb") as g:
+                enc.write_bytes(enc.TYPE_UPLOAD1, g.read())
+
+        # Write an array of headers to the file.
+        if options.header:
+            for header in options.header:
+                enc.write_string(enc.TYPE_HEADER, header)
+
+        # Write an array of headers to the file.
+        if options.mailrecipient:
+            for mailrecipient in options.mailrecipient:
+                enc.write_string(enc.TYPE_MAIL_RECIPIENT, mailrecipient)
+
+    return ScriptRC.SUCCESS
+
+
+def get_options():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--output", required=True)
+    parser.add_argument("--url", required=True)
+    parser.add_argument("--username")
+    parser.add_argument("--password")
+    parser.add_argument("--postfields")
+    parser.add_argument("--header", action="append")
+    parser.add_argument("--cookie")
+    parser.add_argument("--range")
+    parser.add_argument("--customrequest")
+    parser.add_argument("--mailfrom")
+    parser.add_argument("--mailrecipient", action="append")
+
+    rsp1 = parser.add_mutually_exclusive_group(required=True)
+    rsp1.add_argument("--rsp1")
+    rsp1.add_argument("--rsp1file")
+    rsp1.add_argument("--rsp1test", type=int)
+
+    upload1 = parser.add_mutually_exclusive_group()
+    upload1.add_argument("--upload1")
+    upload1.add_argument("--upload1file")
+
+    return parser.parse_args()
+
+
+def setup_logging():
+    """
+    Set up logging from the command line options
+    """
+    root_logger = logging.getLogger()
+    formatter = logging.Formatter("%(asctime)s %(levelname)-5.5s %(message)s")
+    stdout_handler = logging.StreamHandler(sys.stdout)
+    stdout_handler.setFormatter(formatter)
+    stdout_handler.setLevel(logging.DEBUG)
+    root_logger.addHandler(stdout_handler)
+    root_logger.setLevel(logging.DEBUG)
+
+
+class ScriptRC(object):
+    """Enum for script return codes"""
+    SUCCESS = 0
+    FAILURE = 1
+    EXCEPTION = 2
+
+
+class ScriptException(Exception):
+    pass
+
+
+def main():
+    # Get the options from the user.
+    options = get_options()
+
+    setup_logging()
+
+    # Run main script.
+    try:
+        rc = generate_corpus(options)
+    except Exception as e:
+        log.exception(e)
+        rc = ScriptRC.EXCEPTION
+
+    log.info("Returning %d", rc)
+    return rc
+
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/tests/fuzz/read_corpus.py b/tests/fuzz/read_corpus.py
new file mode 100755
index 000000000..bb8fcedcd
--- /dev/null
+++ b/tests/fuzz/read_corpus.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+#
+# Simple script which reads corpus files.
+
+import argparse
+import logging
+import sys
+import corpus
+log = logging.getLogger(__name__)
+
+
+def read_corpus(options):
+    with open(options.input, "rb") as f:
+        dec = corpus.TLVDecoder(f.read())
+        for tlv in dec:
+            print(tlv)
+
+    return ScriptRC.SUCCESS
+
+
+def get_options():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--input", required=True)
+    return parser.parse_args()
+
+
+def setup_logging():
+    """
+    Set up logging from the command line options
+    """
+    root_logger = logging.getLogger()
+    formatter = logging.Formatter("%(asctime)s %(levelname)-5.5s %(message)s")
+    stdout_handler = logging.StreamHandler(sys.stdout)
+    stdout_handler.setFormatter(formatter)
+    stdout_handler.setLevel(logging.DEBUG)
+    root_logger.addHandler(stdout_handler)
+    root_logger.setLevel(logging.DEBUG)
+
+
+class ScriptRC(object):
+    """Enum for script return codes"""
+    SUCCESS = 0
+    FAILURE = 1
+    EXCEPTION = 2
+
+
+class ScriptException(Exception):
+    pass
+
+
+def main():
+    # Get the options from the user.
+    options = get_options()
+
+    setup_logging()
+
+    # Run main script.
+    try:
+        rc = read_corpus(options)
+    except Exception as e:
+        log.exception(e)
+        rc = ScriptRC.EXCEPTION
+
+    log.info("Returning %d", rc)
+    return rc
+
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/tests/fuzz/standalone_fuzz_target_runner.cc 
b/tests/fuzz/standalone_fuzz_target_runner.cc
new file mode 100644
index 000000000..9b2316ed6
--- /dev/null
+++ b/tests/fuzz/standalone_fuzz_target_runner.cc
@@ -0,0 +1,89 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017, Max Dymond, <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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "testinput.h"
+
+/**
+ * Main procedure for standalone fuzzing engine.
+ *
+ * Reads filenames from the argument array. For each filename, read the file
+ * into memory and then call the fuzzing interface with the data.
+ */
+int main(int argc, char **argv)
+{
+  int ii;
+  FILE *infile;
+  uint8_t *buffer = NULL;
+  size_t buffer_len;
+
+  for(ii = 1; ii < argc; ii++) {
+    /* Try and open the file. */
+    infile = fopen(argv[ii], "rb");
+    if(infile) {
+      printf("[%s] Open succeeded! \n", argv[ii]);
+
+      /* Get the length of the file. */
+      fseek(infile, 0L, SEEK_END);
+      buffer_len = ftell(infile);
+
+      /* Reset the file indicator to the beginning of the file. */
+      fseek(infile, 0L, SEEK_SET);
+
+      /* Allocate a buffer for the file contents. */
+      buffer = (uint8_t *)calloc(buffer_len, sizeof(uint8_t));
+      if(buffer) {
+        /* Read all the text from the file into the buffer. */
+        fread(buffer, sizeof(uint8_t), buffer_len, infile);
+        printf("[%s] Read %zu bytes, calling fuzzer\n", argv[ii], buffer_len);
+
+        /* Call the fuzzer with the data. */
+        LLVMFuzzerTestOneInput(buffer, buffer_len);
+
+        printf("[%s] Fuzzing complete\n", argv[ii]);
+
+        /* Free the buffer as it's no longer needed. */
+        free(buffer);
+        buffer = NULL;
+      }
+      else
+      {
+        fprintf(stderr,
+                "[%s] Failed to allocate %zu bytes \n",
+                argv[ii],
+                buffer_len);
+      }
+
+      /* Close the file as it's no longer needed. */
+      fclose(infile);
+      infile = NULL;
+    }
+    else
+    {
+      /* Failed to open the file. Maybe wrong name or wrong permissions? */
+      fprintf(stderr, "[%s] Open failed. \n", argv[ii]);
+    }
+  }
+}
diff --git a/src/tool_formparse.h b/tests/fuzz/testinput.h
similarity index 69%
copy from src/tool_formparse.h
copy to tests/fuzz/testinput.h
index ce7a29256..0746cba73 100644
--- a/src/tool_formparse.h
+++ b/tests/fuzz/testinput.h
@@ -1,5 +1,3 @@
-#ifndef HEADER_CURL_TOOL_FORMPARSE_H
-#define HEADER_CURL_TOOL_FORMPARSE_H
 /***************************************************************************
  *                                  _   _ ____  _
  *  Project                     ___| | | |  _ \| |
@@ -7,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2014, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 2017, Max Dymond, <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,13 +19,5 @@
  * KIND, either express or implied.
  *
  ***************************************************************************/
-#include "tool_setup.h"
-
-int formparse(struct OperationConfig *config,
-              const char *input,
-              struct curl_httppost **httppost,
-              struct curl_httppost **last_post,
-              bool literal_value);
-
-#endif /* HEADER_CURL_TOOL_FORMPARSE_H */
 
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
\ No newline at end of file
diff --git a/tests/libtest/.gitignore b/tests/libtest/.gitignore
index ab8b8db67..863e50e28 100644
--- a/tests/libtest/.gitignore
+++ b/tests/libtest/.gitignore
@@ -1,7 +1,10 @@
 chkhostname
 lib15[0-9][0-9]
+lib1521.c
 lib19[0-9][0-9]
 lib2033
 lib5[0-9][0-9]
+lib64[3-5]
+lib650
 libauthretry
 libntlmconnect
diff --git a/tests/libtest/Makefile.am b/tests/libtest/Makefile.am
index 6ebad89c8..f4c705e41 100644
--- a/tests/libtest/Makefile.am
+++ b/tests/libtest/Makefile.am
@@ -109,6 +109,21 @@ libhostname_la_SOURCES = sethostname.c sethostname.h
 libhostname_la_LIBADD =
 libhostname_la_DEPENDENCIES =
 
+# Build a stub gssapi implementation for testing
+if BUILD_STUB_GSS
+noinst_LTLIBRARIES += libstubgss.la
+
+libstubgss_la_CPPFLAGS = $(AM_CPPFLAGS)
+libstubgss_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version -rpath /nowhere
+libstubgss_la_CFLAGS = $(AM_CFLAGS) -g -Wno-unused-parameter
+
+libstubgss_la_SOURCES = stub_gssapi.c stub_gssapi.h
+
+libstubgss_la_LIBADD =
+libstubgss_la_DEPENDENCIES =
+endif
+
+
 lib1521.c: $(top_srcdir)/tests/libtest/mk-lib1521.pl 
$(top_srcdir)/include/gnurl/curl.h
        @PERL@ $(top_srcdir)/tests/libtest/mk-lib1521.pl < 
$(top_srcdir)/include/gnurl/curl.h > lib1521.c
 
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
index 727582bd0..065899276 100644
--- a/tests/libtest/Makefile.inc
+++ b/tests/libtest/Makefile.inc
@@ -19,7 +19,8 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect     
           \
  lib547 lib548 lib549 lib552 lib553 lib554 lib555 lib556 lib557 lib558   \
  lib559 lib560 lib562 lib564 lib565 lib566 lib567 lib568 lib569 lib570   \
  lib571 lib572 lib573 lib574 lib575 lib576        lib578 lib579 lib582   \
- lib583 lib585 lib586 lib587        lib590 lib591 lib597 lib598 lib599   \
+ lib583 lib585 lib586 lib587 lib589 lib590 lib591 lib597 lib598 lib599   \
+ lib643 lib644 lib645 lib650 \
  lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1507 lib1508 \
  lib1509 lib1510 lib1511 lib1512 lib1513 lib1514 lib1515         lib1517 \
  lib1520 lib1521 \
@@ -282,6 +283,9 @@ lib586_CPPFLAGS = $(AM_CPPFLAGS)
 lib587_SOURCES = lib554.c $(SUPPORTFILES)
 lib587_CPPFLAGS = $(AM_CPPFLAGS) -DLIB587
 
+lib589_SOURCES = lib589.c $(SUPPORTFILES)
+lib589_CPPFLAGS = $(AM_CPPFLAGS)
+
 lib590_SOURCES = lib590.c $(SUPPORTFILES)
 lib590_CPPFLAGS = $(AM_CPPFLAGS)
 
@@ -299,6 +303,18 @@ lib598_CPPFLAGS = $(AM_CPPFLAGS)
 lib599_SOURCES = lib599.c $(SUPPORTFILES)
 lib599_CPPFLAGS = $(AM_CPPFLAGS)
 
+lib643_SOURCES = lib643.c $(SUPPORTFILES)
+lib643_CPPFLAGS = $(AM_CPPFLAGS)
+
+lib644_SOURCES = lib643.c $(SUPPORTFILES)
+lib644_CPPFLAGS = $(AM_CPPFLAGS) -DLIB644
+
+lib645_SOURCES = lib643.c $(SUPPORTFILES)
+lib645_CPPFLAGS = $(AM_CPPFLAGS) -DLIB645
+
+lib650_SOURCES = lib650.c $(SUPPORTFILES)
+lib650_CPPFLAGS = $(AM_CPPFLAGS)
+
 lib1500_SOURCES = lib1500.c $(SUPPORTFILES) $(TESTUTIL)
 lib1500_LDADD = $(TESTUTIL_LIBS)
 lib1500_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/tests/libtest/first.c b/tests/libtest/first.c
index 72140e314..86d84cacd 100644
--- a/tests/libtest/first.c
+++ b/tests/libtest/first.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -72,8 +72,8 @@ void wait_ms(int ms)
   select_wrapper(0, NULL, NULL, NULL, &t);
 }
 
-char *libtest_arg2=NULL;
-char *libtest_arg3=NULL;
+char *libtest_arg2 = NULL;
+char *libtest_arg3 = NULL;
 int test_argc;
 char **test_argv;
 
@@ -118,12 +118,12 @@ static void memory_tracking_init(void)
 /* returns a hexdump in a static memory area */
 char *hexdump(const unsigned char *buffer, size_t len)
 {
-  static char dump[200*3+1];
+  static char dump[200 * 3 + 1];
   char *p = dump;
   size_t i;
   if(len > 200)
     return NULL;
-  for(i=0; i<len; i++, p += 3)
+  for(i = 0; i<len; i++, p += 3)
     snprintf(p, 4, "%02x ", buffer[i]);
   return dump;
 }
@@ -162,10 +162,10 @@ int main(int argc, char **argv)
   test_argv = argv;
 
   if(argc>2)
-    libtest_arg2=argv[2];
+    libtest_arg2 = argv[2];
 
   if(argc>3)
-    libtest_arg3=argv[3];
+    libtest_arg3 = argv[3];
 
   URL = argv[1]; /* provide this to the rest */
 
diff --git a/tests/libtest/lib1501.c b/tests/libtest/lib1501.c
index 8a6ef5172..96094d699 100644
--- a/tests/libtest/lib1501.c
+++ b/tests/libtest/lib1501.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -78,7 +78,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     abort_on_test_timeout();
 
diff --git a/tests/libtest/lib1502.c b/tests/libtest/lib1502.c
index bd555cbaf..188c120f8 100644
--- a/tests/libtest/lib1502.c
+++ b/tests/libtest/lib1502.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -99,7 +99,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     abort_on_test_timeout();
 
diff --git a/tests/libtest/lib1506.c b/tests/libtest/lib1506.c
index 47fc335ce..d456bc95c 100644
--- a/tests/libtest/lib1506.c
+++ b/tests/libtest/lib1506.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2013, Linus Nielsen Feltzing <address@hidden>
+ * Copyright (C) 2013, 2017, 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
@@ -45,7 +45,7 @@ int test(char *URL)
   (void)URL;
 
   /* Create fake DNS entries for serverX.example.com for all handles */
-  for(i=0; i < NUM_HANDLES; i++) {
+  for(i = 0; i < NUM_HANDLES; i++) {
     snprintf(dnsentry, sizeof(dnsentry), "server%d.example.com:%s:%s",
              i + 1, port, address);
     printf("%s\n", dnsentry);
@@ -66,7 +66,7 @@ int test(char *URL)
   multi_setopt(m, CURLMOPT_MAXCONNECTS, 3L);
 
   /* get NUM_HANDLES easy handles */
-  for(i=0; i < NUM_HANDLES; i++) {
+  for(i = 0; i < NUM_HANDLES; i++) {
     /* get an easy handle */
     easy_init(curl[i]);
     /* specify target */
@@ -85,7 +85,7 @@ int test(char *URL)
 
   fprintf(stderr, "Start at URL 0\n");
 
-  for(i=0; i < NUM_HANDLES; i++) {
+  for(i = 0; i < NUM_HANDLES; i++) {
     /* add handle to multi */
     multi_add_handle(m, curl[i]);
 
@@ -112,7 +112,7 @@ int test(char *URL)
 
       /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-      select_test(maxfd+1, &rd, &wr, &exc, &interval);
+      select_test(maxfd + 1, &rd, &wr, &exc, &interval);
 
       abort_on_test_timeout();
     }
@@ -123,7 +123,7 @@ test_cleanup:
 
   /* proper cleanup sequence - type PB */
 
-  for(i=0; i < NUM_HANDLES; i++) {
+  for(i = 0; i < NUM_HANDLES; i++) {
     curl_multi_remove_handle(m, curl[i]);
     curl_easy_cleanup(curl[i]);
   }
diff --git a/tests/libtest/lib1507.c b/tests/libtest/lib1507.c
index cd8500195..5e3a5926a 100644
--- a/tests/libtest/lib1507.c
+++ b/tests/libtest/lib1507.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +118,7 @@ int test(char *URL)
        case of (maxfd == -1), we call select(0, ...), which is basically equal
        to sleep. */
 
-    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     if(tutil_tvdiff(tutil_tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
       fprintf(stderr, "ABORTING TEST, since it seems "
diff --git a/tests/libtest/lib1510.c b/tests/libtest/lib1510.c
index 25e9fed31..d72749b24 100644
--- a/tests/libtest/lib1510.c
+++ b/tests/libtest/lib1510.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2013, Linus Nielsen Feltzing <address@hidden>
+ * Copyright (C) 2013, 2017, 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
@@ -43,7 +43,7 @@ int test(char *URL)
   (void)URL;
 
   /* Create fake DNS entries for serverX.example.com for all handles */
-  for(i=0; i < NUM_URLS; i++) {
+  for(i = 0; i < NUM_URLS; i++) {
     snprintf(dnsentry, sizeof(dnsentry), "server%d.example.com:%s:%s", i + 1,
              port, address);
     printf("%s\n", dnsentry);
@@ -72,7 +72,7 @@ int test(char *URL)
   easy_setopt(curl, CURLOPT_MAXCONNECTS, 3L);
 
   /* get NUM_HANDLES easy handles */
-  for(i=0; i < NUM_URLS; i++) {
+  for(i = 0; i < NUM_URLS; i++) {
     /* specify target */
     snprintf(target_url, sizeof(target_url),
              "http://server%d.example.com:%s/path/1510%04i";,
diff --git a/tests/libtest/lib1512.c b/tests/libtest/lib1512.c
index f4091b45a..5e794b293 100644
--- a/tests/libtest/lib1512.c
+++ b/tests/libtest/lib1512.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2013 - 2016, Linus Nielsen Feltzing <address@hidden>
+ * Copyright (C) 2013 - 2017, 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
@@ -55,7 +55,7 @@ int test(char *URL)
   slist = curl_slist_append(slist, dnsentry);
 
   /* get NUM_HANDLES easy handles */
-  for(i=0; i < NUM_HANDLES; i++) {
+  for(i = 0; i < NUM_HANDLES; i++) {
     /* get an easy handle */
     easy_init(curl[i]);
     /* specify target */
@@ -76,7 +76,7 @@ int test(char *URL)
   easy_setopt(curl[0], CURLOPT_RESOLVE, slist);
 
   /* run NUM_HANDLES transfers */
-  for(i=0; (i < NUM_HANDLES) && !res; i++)
+  for(i = 0; (i < NUM_HANDLES) && !res; i++)
     res = curl_easy_perform(curl[i]);
 
 test_cleanup:
diff --git a/tests/libtest/lib1513.c b/tests/libtest/lib1513.c
index d0123f1f6..932ca7208 100644
--- a/tests/libtest/lib1513.c
+++ b/tests/libtest/lib1513.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2015, 2017, 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
@@ -48,7 +48,7 @@ static int progressKiller(void *arg,
 int test(char *URL)
 {
   CURL *curl;
-  int res=0;
+  int res = 0;
 
   global_init(CURL_GLOBAL_ALL);
 
diff --git a/tests/libtest/lib1515.c b/tests/libtest/lib1515.c
index c1499381a..39bccc59b 100644
--- a/tests/libtest/lib1515.c
+++ b/tests/libtest/lib1515.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +87,7 @@ static int do_one_request(CURLM *m, char *URL, char *resolve)
     timeout.tv_usec = 0;
 
     multi_fdset(m, &fdread, &fdwrite, &fdexcep, &maxfd);
-    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     abort_on_test_timeout();
     multi_perform(m, &still_running);
@@ -148,6 +148,7 @@ int test(char *URL)
 test_cleanup:
 
   curl_multi_cleanup(multi);
+  curl_global_cleanup();
 
   return (int) res;
 }
diff --git a/tests/libtest/lib1517.c b/tests/libtest/lib1517.c
index e270ed74d..ea622b046 100644
--- a/tests/libtest/lib1517.c
+++ b/tests/libtest/lib1517.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 @@ static size_t read_callback(void *ptr, size_t size, size_t 
nmemb, void *userp)
 int test(char *URL)
 {
   CURL *curl;
-  CURLcode res=CURLE_OK;
+  CURLcode res = CURLE_OK;
 
   struct WriteThis pooh;
 
diff --git a/tests/libtest/lib1531.c b/tests/libtest/lib1531.c
index 287acd6c6..5ee617e52 100644
--- a/tests/libtest/lib1531.c
+++ b/tests/libtest/lib1531.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,6 +37,9 @@ int test(char *URL)
   int still_running; /* keep number of running handles */
   CURLMsg *msg; /* for picking up messages with the transfer status */
   int msgs_left; /* how many messages are left */
+  int res = CURLE_OK;
+
+  global_init(CURL_GLOBAL_ALL);
 
   /* Allocate one CURL handle per transfer */
   easy = curl_easy_init();
@@ -112,7 +115,7 @@ int test(char *URL)
     else {
       /* Note that on some platforms 'timeout' may be modified by select().
          If you need access to the original value save a copy beforehand. */
-      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+      rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
     }
 
     switch(rc) {
@@ -139,6 +142,7 @@ int test(char *URL)
 
   /* Free the CURL handles */
   curl_easy_cleanup(easy);
+  curl_global_cleanup();
 
   return 0;
 }
diff --git a/tests/libtest/lib1538.c b/tests/libtest/lib1538.c
index e4e16f203..91481e88d 100644
--- a/tests/libtest/lib1538.c
+++ b/tests/libtest/lib1538.c
@@ -37,13 +37,14 @@ int test(char *URL)
   curl_easy_strerror(-INT_MAX);
   curl_multi_strerror(-INT_MAX);
   curl_share_strerror(-INT_MAX);
-  for(easyret=CURLE_OK; easyret <= CURL_LAST; easyret++) {
+  for(easyret = CURLE_OK; easyret <= CURL_LAST; easyret++) {
     printf("e%d: %s\n", (int)easyret, curl_easy_strerror(easyret));
   }
-  for(multiret=CURLM_CALL_MULTI_PERFORM; multiret <= CURLM_LAST; multiret++) {
+  for(multiret = CURLM_CALL_MULTI_PERFORM; multiret <= CURLM_LAST;
+      multiret++) {
     printf("m%d: %s\n", (int)multiret, curl_multi_strerror(multiret));
   }
-  for(shareret=CURLSHE_OK; shareret <= CURLSHE_LAST; shareret++) {
+  for(shareret = CURLSHE_OK; shareret <= CURLSHE_LAST; shareret++) {
     printf("s%d: %s\n", (int)shareret, curl_share_strerror(shareret));
   }
 
diff --git a/tests/libtest/lib1550.c b/tests/libtest/lib1550.c
index 5c2fb6f6a..1df5503fd 100644
--- a/tests/libtest/lib1550.c
+++ b/tests/libtest/lib1550.c
@@ -27,13 +27,20 @@
 
 int test(char *URL)
 {
-  CURLM *handle = curl_multi_init();
-  const char *bl_servers[] = {"Microsoft-IIS/6.0", "nginx/0.8.54", NULL};
-  const char *bl_sites[] = {"curl.haxx.se:443", "example.com:80", NULL};
+  CURLM *handle;
+  int res = CURLE_OK;
+  static const char * const bl_servers[] =
+     {"Microsoft-IIS/6.0", "nginx/0.8.54", NULL};
+  static const char * const bl_sites[] =
+     {"curl.haxx.se:443", "example.com:80", NULL};
+
+  global_init(CURL_GLOBAL_ALL);
+  handle = curl_multi_init();
   (void)URL; /* unused */
 
   curl_multi_setopt(handle, CURLMOPT_PIPELINING_SERVER_BL, bl_servers);
   curl_multi_setopt(handle, CURLMOPT_PIPELINING_SITE_BL, bl_sites);
   curl_multi_cleanup(handle);
+  curl_global_cleanup();
   return 0;
 }
diff --git a/tests/libtest/lib1551.c b/tests/libtest/lib1551.c
index e3ff3b313..edd6e9c8f 100644
--- a/tests/libtest/lib1551.c
+++ b/tests/libtest/lib1551.c
@@ -30,6 +30,7 @@ int test(char *URL)
   CURL *curl;
   CURLcode res = CURLE_OK;
 
+  global_init(CURL_GLOBAL_ALL);
   curl = curl_easy_init();
   if(curl) {
     curl_easy_setopt(curl, CURLOPT_URL, URL);
@@ -41,5 +42,6 @@ int test(char *URL)
     res = curl_easy_perform(curl);
     curl_easy_cleanup(curl);
   }
+  curl_global_cleanup();
   return (int)res;
 }
diff --git a/tests/libtest/lib1900.c b/tests/libtest/lib1900.c
index cac1dd1d9..109c57062 100644
--- a/tests/libtest/lib1900.c
+++ b/tests/libtest/lib1900.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 2013 - 2016, Linus Nielsen Feltzing, <address@hidden>
+ * Copyright (C) 2013 - 2017, 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
@@ -88,13 +88,13 @@ static int parse_url_file(const char *filename)
 static void free_urls(void)
 {
   int i;
-  for(i = 0;i < num_handles;i++) {
+  for(i = 0; i < num_handles; i++) {
     Curl_safefree(urlstring[i]);
   }
-  for(i = 0;i < blacklist_num_servers;i++) {
+  for(i = 0; i < blacklist_num_servers; i++) {
     Curl_safefree(server_blacklist[i]);
   }
-  for(i = 0;i < blacklist_num_sites;i++) {
+  for(i = 0; i < blacklist_num_sites; i++) {
     Curl_safefree(site_blacklist[i]);
   }
 }
@@ -103,7 +103,7 @@ static int create_handles(void)
 {
   int i;
 
-  for(i = 0;i < num_handles;i++) {
+  for(i = 0; i < num_handles; i++) {
     handles[i] = curl_easy_init();
   }
   return 0;
@@ -126,7 +126,7 @@ static void remove_handles(void)
 {
   int i;
 
-  for(i = 0;i < num_handles;i++) {
+  for(i = 0; i < num_handles; i++) {
     if(handles[i])
       curl_easy_cleanup(handles[i]);
   }
@@ -229,7 +229,7 @@ int test(char *URL)
     interval.tv_sec = 0;
     interval.tv_usec = 1000;
 
-    select_test(maxfd+1, &rd, &wr, &exc, &interval);
+    select_test(maxfd + 1, &rd, &wr, &exc, &interval);
 
     abort_on_test_timeout();
   }
diff --git a/tests/libtest/lib500.c b/tests/libtest/lib500.c
index d17b24b20..677ab73a7 100644
--- a/tests/libtest/lib500.c
+++ b/tests/libtest/lib500.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +61,7 @@ int test(char *URL)
 {
   CURLcode res;
   CURL *curl;
-  char *ipstr=NULL;
+  char *ipstr = NULL;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
     fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib502.c b/tests/libtest/lib502.c
index 7cf6415a6..ce4bc47d1 100644
--- a/tests/libtest/lib502.c
+++ b/tests/libtest/lib502.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2011, 2017, 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,7 +73,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     abort_on_test_timeout();
   }
diff --git a/tests/libtest/lib503.c b/tests/libtest/lib503.c
index 2eb287483..15b45f95b 100644
--- a/tests/libtest/lib503.c
+++ b/tests/libtest/lib503.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2012, 2017, 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
@@ -83,7 +83,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &rd, &wr, &exc, &interval);
+    select_test(maxfd + 1, &rd, &wr, &exc, &interval);
 
     abort_on_test_timeout();
   }
diff --git a/tests/libtest/lib504.c b/tests/libtest/lib504.c
index 3466dc948..771b2038a 100644
--- a/tests/libtest/lib504.c
+++ b/tests/libtest/lib504.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +95,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &rd, &wr, &exc, &interval);
+    select_test(maxfd + 1, &rd, &wr, &exc, &interval);
 
     abort_on_test_timeout();
   }
diff --git a/tests/libtest/lib505.c b/tests/libtest/lib505.c
index ad5d214c6..cc7463bde 100644
--- a/tests/libtest/lib505.c
+++ b/tests/libtest/lib505.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +43,7 @@ int test(char *URL)
   struct_stat file_info;
   struct curl_slist *hl;
 
-  struct curl_slist *headerlist=NULL;
+  struct curl_slist *headerlist = NULL;
   const char *buf_1 = "RNFR 505";
   const char *buf_2 = "RNTO 505-forreal";
 
diff --git a/tests/libtest/lib506.c b/tests/libtest/lib506.c
index d26252b6f..1b522be64 100644
--- a/tests/libtest/lib506.c
+++ b/tests/libtest/lib506.c
@@ -131,7 +131,7 @@ static void *fire(void *ptr)
   struct curl_slist *headers;
   struct Tdata *tdata = (struct Tdata*)ptr;
   CURL *curl;
-  int i=0;
+  int i = 0;
 
   curl = curl_easy_init();
   if(!curl) {
@@ -261,7 +261,7 @@ int test(char *URL)
   res = 0;
 
   /* start treads */
-  for(i=1; i<=THREADS; i++) {
+  for(i = 1; i <= THREADS; i++) {
 
     /* set thread data */
     tdata.url   = suburl(URL, i); /* must be curl_free()d */
@@ -349,7 +349,7 @@ int test(char *URL)
   /* try to free share, expect to fail because share is in use*/
   printf("try SHARE_CLEANUP...\n");
   scode = curl_share_cleanup(share);
-  if(scode==CURLSHE_OK) {
+  if(scode == CURLSHE_OK) {
     fprintf(stderr, "curl_share_cleanup succeed but error expected\n");
     share = NULL;
   }
@@ -368,7 +368,7 @@ test_cleanup:
   /* free share */
   printf("SHARE_CLEANUP\n");
   scode = curl_share_cleanup(share);
-  if(scode!=CURLSHE_OK)
+  if(scode != CURLSHE_OK)
     fprintf(stderr, "curl_share_cleanup failed, code errno %d\n",
             (int)scode);
 
diff --git a/tests/libtest/lib507.c b/tests/libtest/lib507.c
index ebe897ac8..9cd47ccd5 100644
--- a/tests/libtest/lib507.c
+++ b/tests/libtest/lib507.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -70,7 +70,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     abort_on_test_timeout();
 
diff --git a/tests/libtest/lib508.c b/tests/libtest/lib508.c
index 1f6c6838a..30705e46a 100644
--- a/tests/libtest/lib508.c
+++ b/tests/libtest/lib508.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -50,7 +50,7 @@ static size_t read_callback(void *ptr, size_t size, size_t 
nmemb, void *userp)
 int test(char *URL)
 {
   CURL *curl;
-  CURLcode res=CURLE_OK;
+  CURLcode res = CURLE_OK;
 
   struct WriteThis pooh;
 
diff --git a/tests/libtest/lib510.c b/tests/libtest/lib510.c
index 4c290f1ef..4d568df44 100644
--- a/tests/libtest/lib510.c
+++ b/tests/libtest/lib510.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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 @@ static size_t read_callback(void *ptr, size_t size, size_t 
nmemb, void *userp)
 int test(char *URL)
 {
   CURL *curl;
-  CURLcode res=CURLE_OK;
+  CURLcode res = CURLE_OK;
   struct curl_slist *slist = NULL;
   struct WriteThis pooh;
   pooh.counter = 0;
diff --git a/tests/libtest/lib513.c b/tests/libtest/lib513.c
index 7c34bc4db..c6a98cca2 100644
--- a/tests/libtest/lib513.c
+++ b/tests/libtest/lib513.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +35,7 @@ static size_t read_callback(void *ptr, size_t size, size_t 
nmemb, void *userp)
 int test(char *URL)
 {
   CURL *curl;
-  CURLcode res=CURLE_OK;
+  CURLcode res = CURLE_OK;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
     fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib514.c b/tests/libtest/lib514.c
index 7b33d52f9..702058b19 100644
--- a/tests/libtest/lib514.c
+++ b/tests/libtest/lib514.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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 @@
 int test(char *URL)
 {
   CURL *curl;
-  CURLcode res=CURLE_OK;
+  CURLcode res = CURLE_OK;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
     fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib515.c b/tests/libtest/lib515.c
index 6fb178720..9f29d43c9 100644
--- a/tests/libtest/lib515.c
+++ b/tests/libtest/lib515.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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 @@
 int test(char *URL)
 {
   CURL *curl;
-  CURLcode res=CURLE_OK;
+  CURLcode res = CURLE_OK;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
     fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib516.c b/tests/libtest/lib516.c
index 00c54c450..6d83e218c 100644
--- a/tests/libtest/lib516.c
+++ b/tests/libtest/lib516.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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 @@
 int test(char *URL)
 {
   CURL *curl;
-  CURLcode res=CURLE_OK;
+  CURLcode res = CURLE_OK;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
     fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib517.c b/tests/libtest/lib517.c
index 22162ff1e..af7b2aa7a 100644
--- a/tests/libtest/lib517.c
+++ b/tests/libtest/lib517.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -131,7 +131,7 @@ int test(char *URL)
 
   (void)URL; /* not used */
 
-  for(i=0; dates[i]; i++) {
+  for(i = 0; dates[i]; i++) {
     printf("%d: %s => %ld\n", i, dates[i], (long)curl_getdate(dates[i], NULL));
   }
 
diff --git a/tests/libtest/lib525.c b/tests/libtest/lib525.c
index 715b7fbe2..c179960c1 100644
--- a/tests/libtest/lib525.c
+++ b/tests/libtest/lib525.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -132,7 +132,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &rd, &wr, &exc, &interval);
+    select_test(maxfd + 1, &rd, &wr, &exc, &interval);
 
     abort_on_test_timeout();
   }
diff --git a/tests/libtest/lib526.c b/tests/libtest/lib526.c
index 522cd7422..42eb7cb18 100644
--- a/tests/libtest/lib526.c
+++ b/tests/libtest/lib526.c
@@ -59,7 +59,7 @@ int test(char *URL)
   int current = 0;
   int i;
 
-  for(i=0; i < NUM_HANDLES; i++)
+  for(i = 0; i < NUM_HANDLES; i++)
     curl[i] = NULL;
 
   start_test_timing();
@@ -67,7 +67,7 @@ int test(char *URL)
   global_init(CURL_GLOBAL_ALL);
 
   /* get NUM_HANDLES easy handles */
-  for(i=0; i < NUM_HANDLES; i++) {
+  for(i = 0; i < NUM_HANDLES; i++) {
     easy_init(curl[i]);
     /* specify target */
     easy_setopt(curl[i], CURLOPT_URL, URL);
@@ -133,7 +133,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &rd, &wr, &exc, &interval);
+    select_test(maxfd + 1, &rd, &wr, &exc, &interval);
 
     abort_on_test_timeout();
   }
@@ -145,7 +145,7 @@ test_cleanup:
   /* test 526 and 528 */
   /* proper cleanup sequence - type PB */
 
-  for(i=0; i < NUM_HANDLES; i++) {
+  for(i = 0; i < NUM_HANDLES; i++) {
     curl_multi_remove_handle(m, curl[i]);
     curl_easy_cleanup(curl[i]);
   }
@@ -162,7 +162,7 @@ test_cleanup:
      will be leaked, let's use undocumented cleanup sequence - type UB */
 
   if(res)
-    for(i=0; i < NUM_HANDLES; i++)
+    for(i = 0; i < NUM_HANDLES; i++)
       curl_easy_cleanup(curl[i]);
 
   curl_multi_cleanup(m);
@@ -173,7 +173,7 @@ test_cleanup:
   /* test 532 */
   /* undocumented cleanup sequence - type UB */
 
-  for(i=0; i < NUM_HANDLES; i++)
+  for(i = 0; i < NUM_HANDLES; i++)
     curl_easy_cleanup(curl[i]);
   curl_multi_cleanup(m);
   curl_global_cleanup();
diff --git a/tests/libtest/lib530.c b/tests/libtest/lib530.c
index 82bfab36c..7b71fa5e8 100644
--- a/tests/libtest/lib530.c
+++ b/tests/libtest/lib530.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +39,7 @@ int test(char *URL)
   char target_url[256];
   int handles_added = 0;
 
-  for(i=0; i < NUM_HANDLES; i++)
+  for(i = 0; i < NUM_HANDLES; i++)
     curl[i] = NULL;
 
   start_test_timing();
@@ -49,7 +49,7 @@ int test(char *URL)
   multi_init(m);
 
   /* get NUM_HANDLES easy handles */
-  for(i=0; i < NUM_HANDLES; i++) {
+  for(i = 0; i < NUM_HANDLES; i++) {
     /* get an easy handle */
     easy_init(curl[i]);
     /* specify target */
@@ -101,7 +101,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &rd, &wr, &exc, &interval);
+    select_test(maxfd + 1, &rd, &wr, &exc, &interval);
 
     abort_on_test_timeout();
   }
@@ -110,7 +110,7 @@ test_cleanup:
 
   /* proper cleanup sequence - type PB */
 
-  for(i=0; i < NUM_HANDLES; i++) {
+  for(i = 0; i < NUM_HANDLES; i++) {
     curl_multi_remove_handle(m, curl[i]);
     curl_easy_cleanup(curl[i]);
   }
diff --git a/tests/libtest/lib533.c b/tests/libtest/lib533.c
index 706b269fe..7dd0fb59c 100644
--- a/tests/libtest/lib533.c
+++ b/tests/libtest/lib533.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2011, 2017, 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 @@ int test(char *URL)
   CURL *curl = NULL;
   int running;
   CURLM *m = NULL;
-  int current=0;
+  int current = 0;
 
   start_test_timing();
 
@@ -95,7 +95,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &rd, &wr, &exc, &interval);
+    select_test(maxfd + 1, &rd, &wr, &exc, &interval);
 
     abort_on_test_timeout();
   }
diff --git a/tests/libtest/lib536.c b/tests/libtest/lib536.c
index f3ba5734c..e6943626d 100644
--- a/tests/libtest/lib536.c
+++ b/tests/libtest/lib536.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2011, 2017, 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,7 +63,7 @@ static int perform(CURLM *multi)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    res_select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval);
+    res_select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &interval);
     if(res)
       return res;
 
diff --git a/tests/libtest/lib540.c b/tests/libtest/lib540.c
index ac862092f..a13653ce6 100644
--- a/tests/libtest/lib540.c
+++ b/tests/libtest/lib540.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -152,7 +152,7 @@ static int loop(int num, CURLM *cm, const char *url, const 
char *userpwd,
         T.tv_usec = 0;
       }
 
-      res_select_test(M+1, &R, &W, &E, &T);
+      res_select_test(M + 1, &R, &W, &E, &T);
       if(res)
         return res;
     }
@@ -165,7 +165,7 @@ static int loop(int num, CURLM *cm, const char *url, const 
char *userpwd,
                 curl_easy_strerror(msg->data.result));
         curl_multi_remove_handle(cm, e);
         curl_easy_cleanup(e);
-        for(i=0; i < NUM_HANDLES; i++) {
+        for(i = 0; i < NUM_HANDLES; i++) {
           if(eh[i] == e) {
             eh[i] = NULL;
             break;
@@ -192,7 +192,7 @@ int test(char *URL)
   int res = 0;
   int i;
 
-  for(i=0; i < NUM_HANDLES; i++)
+  for(i = 0; i < NUM_HANDLES; i++)
     eh[i] = NULL;
 
   start_test_timing();
@@ -234,7 +234,7 @@ test_cleanup:
 
   /* proper cleanup sequence - type PB */
 
-  for(i=0; i < NUM_HANDLES; i++) {
+  for(i = 0; i < NUM_HANDLES; i++) {
     curl_multi_remove_handle(cm, eh[i]);
     curl_easy_cleanup(eh[i]);
   }
diff --git a/tests/libtest/lib543.c b/tests/libtest/lib543.c
index 6d2532d12..957839f7a 100644
--- a/tests/libtest/lib543.c
+++ b/tests/libtest/lib543.c
@@ -27,15 +27,18 @@
 
 int test(char *URL)
 {
-  unsigned char a[] = {0x9c, 0x26, 0x4b, 0x3d, 0x49, 0x4, 0xa1, 0x1,
-                       0xe0, 0xd8, 0x7c,  0x20, 0xb7, 0xef, 0x53, 0x29, 0xfa,
-                       0x1d, 0x57, 0xe1};
+  static const unsigned char a[] = {
+      0x9c, 0x26, 0x4b, 0x3d, 0x49, 0x4, 0xa1, 0x1,
+      0xe0, 0xd8, 0x7c,  0x20, 0xb7, 0xef, 0x53, 0x29, 0xfa,
+      0x1d, 0x57, 0xe1};
 
   CURL *easy;
   int asize;
   char *s;
+  CURLcode res = CURLE_OK;
   (void)URL;
 
+  global_init(CURL_GLOBAL_ALL);
   easy = curl_easy_init();
   if(!easy) {
     fprintf(stderr, "curl_easy_init() failed\n");
@@ -44,7 +47,7 @@ int test(char *URL)
 
   asize = (int)sizeof(a);
 
-  s = curl_easy_escape(easy, (char *)a, asize);
+  s = curl_easy_escape(easy, (const char *)a, asize);
 
   if(s)
     printf("%s\n", s);
@@ -53,6 +56,7 @@ int test(char *URL)
     curl_free(s);
 
   curl_easy_cleanup(easy);
+  curl_global_cleanup();
 
   return 0;
 }
diff --git a/tests/libtest/lib544.c b/tests/libtest/lib544.c
index 28eacdaf6..1f832d2a6 100644
--- a/tests/libtest/lib544.c
+++ b/tests/libtest/lib544.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 @@ static char teststring[] =
 int test(char *URL)
 {
   CURL *curl;
-  CURLcode res=CURLE_OK;
+  CURLcode res = CURLE_OK;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
     fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib547.c b/tests/libtest/lib547.c
index ce967c085..3db4890de 100644
--- a/tests/libtest/lib547.c
+++ b/tests/libtest/lib547.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -82,7 +82,7 @@ int test(char *URL)
   CURLcode res;
   CURL *curl;
 #ifndef LIB548
-  int counter=0;
+  int counter = 0;
 #endif
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
diff --git a/tests/libtest/lib552.c b/tests/libtest/lib552.c
index 3a93dafaf..5082eb044 100644
--- a/tests/libtest/lib552.c
+++ b/tests/libtest/lib552.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 @@ void dump(const char *text,
   size_t i;
   size_t c;
 
-  unsigned int width=0x10;
+  unsigned int width = 0x10;
 
   if(nohex)
     /* without the hex output, we can fit more on screen */
@@ -48,30 +48,32 @@ void dump(const char *text,
 
   fprintf(stream, "%s, %d bytes (0x%x)\n", text, (int)size, (int)size);
 
-  for(i=0; i<size; i+= width) {
+  for(i = 0; i<size; i += width) {
 
     fprintf(stream, "%04x: ", (int)i);
 
     if(!nohex) {
       /* hex not disabled, show it */
       for(c = 0; c < width; c++)
-        if(i+c < size)
-          fprintf(stream, "%02x ", ptr[i+c]);
+        if(i + c < size)
+          fprintf(stream, "%02x ", ptr[i + c]);
         else
           fputs("   ", stream);
     }
 
-    for(c = 0; (c < width) && (i+c < size); c++) {
+    for(c = 0; (c < width) && (i + c < size); c++) {
       /* check for 0D0A; if found, skip past and start a new line of output */
-      if(nohex && (i+c+1 < size) && ptr[i+c]==0x0D && ptr[i+c+1]==0x0A) {
-        i+=(c+2-width);
+      if(nohex && (i + c + 1 < size) && ptr[i + c] == 0x0D &&
+         ptr[i + c + 1] == 0x0A) {
+        i += (c + 2 - width);
         break;
       }
       fprintf(stream, "%c",
-              (ptr[i+c]>=0x20) && (ptr[i+c]<0x80)?ptr[i+c]:'.');
+              (ptr[i + c] >= 0x20) && (ptr[i + c]<0x80)? ptr[i + c] : '.');
       /* check again for 0D0A, to avoid an extra \n if it's at width */
-      if(nohex && (i+c+2 < size) && ptr[i+c+1]==0x0D && ptr[i+c+2]==0x0A) {
-        i+=(c+3-width);
+      if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D &&
+         ptr[i + c + 2] == 0x0A) {
+        i += (c + 3 - width);
         break;
       }
     }
@@ -166,19 +168,15 @@ static curlioerr ioctl_callback(CURL *handle, int cmd, 
void *clientp)
 int test(char *URL)
 {
   CURL *curl;
-  CURLcode res = CURLE_OUT_OF_MEMORY;
+  CURLcode res = CURLE_OK;
   struct data config;
   size_t i;
   static const char fill[] = "test data";
 
   config.trace_ascii = 1; /* enable ascii tracing */
 
-  curl = curl_easy_init();
-  if(!curl) {
-    fprintf(stderr, "curl_easy_init() failed\n");
-    curl_global_cleanup();
-    return TEST_ERR_MAJOR_BAD;
-  }
+  global_init(CURL_GLOBAL_ALL);
+  easy_init(curl);
 
   test_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
   test_setopt(curl, CURLOPT_DEBUGDATA, &config);
@@ -186,7 +184,7 @@ int test(char *URL)
   test_setopt(curl, CURLOPT_VERBOSE, 1L);
 
   /* setup repeated data string */
-  for(i=0; i < sizeof(databuf); ++i)
+  for(i = 0; i < sizeof(databuf); ++i)
       databuf[i] = fill[i % sizeof fill];
 
   /* Post */
diff --git a/tests/libtest/lib553.c b/tests/libtest/lib553.c
index 288f4c1d1..c06561e1d 100644
--- a/tests/libtest/lib553.c
+++ b/tests/libtest/lib553.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -32,7 +32,7 @@
 
 static size_t myreadfunc(void *ptr, size_t size, size_t nmemb, void *stream)
 {
-  static size_t total=POSTLEN;
+  static size_t total = POSTLEN;
   static char buf[1024];
   (void)stream;
 
@@ -60,7 +60,7 @@ int test(char *URL)
   CURL *curl;
   CURLcode res = CURLE_FAILED_INIT;
   int i;
-  struct curl_slist *headerlist=NULL, *hl;
+  struct curl_slist *headerlist = NULL, *hl;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
     fprintf(stderr, "curl_global_init() failed\n");
@@ -77,7 +77,7 @@ int test(char *URL)
   for(i = 0; i < NUM_HEADERS; i++) {
     int len = snprintf(buf, sizeof(buf), "Header%d: ", i);
     memset(&buf[len], 'A', SIZE_HEADERS);
-    buf[len + SIZE_HEADERS]=0; /* zero terminate */
+    buf[len + SIZE_HEADERS] = 0; /* zero terminate */
     hl = curl_slist_append(headerlist,  buf);
     if(!hl)
       goto test_cleanup;
diff --git a/tests/libtest/lib554.c b/tests/libtest/lib554.c
index 083746243..936d0a10a 100644
--- a/tests/libtest/lib554.c
+++ b/tests/libtest/lib554.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -67,11 +67,11 @@ static size_t read_callback(void *ptr, size_t size, size_t 
nmemb, void *userp)
 static int once(char *URL, bool oldstyle)
 {
   CURL *curl;
-  CURLcode res=CURLE_OK;
+  CURLcode res = CURLE_OK;
   CURLFORMcode formrc;
 
-  struct curl_httppost *formpost=NULL;
-  struct curl_httppost *lastptr=NULL;
+  struct curl_httppost *formpost = NULL;
+  struct curl_httppost *lastptr = NULL;
   struct WriteThis pooh;
   struct WriteThis pooh2;
 
diff --git a/tests/libtest/lib555.c b/tests/libtest/lib555.c
index 8156a95e7..fc71bb643 100644
--- a/tests/libtest/lib555.c
+++ b/tests/libtest/lib555.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -77,9 +77,9 @@ int test(char *URL)
 {
   int res = 0;
   CURL *curl = NULL;
-  int counter=0;
+  int counter = 0;
   CURLM *m = NULL;
-  int running=1;
+  int running = 1;
 
   start_test_timing();
 
@@ -141,7 +141,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     abort_on_test_timeout();
   }
diff --git a/tests/libtest/lib557.c b/tests/libtest/lib557.c
index 4a598f22d..9a87fbda9 100644
--- a/tests/libtest/lib557.c
+++ b/tests/libtest/lib557.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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 @@
 
 #include "memdebug.h"
 
-#if (CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
+#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
 #  define MPRNT_SUFFIX_CURL_OFF_T  LL
 #else
 #  define MPRNT_SUFFIX_CURL_OFF_T  L
@@ -129,7 +129,7 @@ static int test_unsigned_short_formatting(void)
 
 #if (SIZEOF_SHORT == 1)
 
-  i=1; us_test[i].num = 0xFFU; us_test[i].expected = "256";
+  i = 1; us_test[i].num = 0xFFU; us_test[i].expected = "256";
   i++; us_test[i].num = 0xF0U; us_test[i].expected = "240";
   i++; us_test[i].num = 0x0FU; us_test[i].expected = "15";
 
@@ -146,7 +146,7 @@ static int test_unsigned_short_formatting(void)
 
 #elif (SIZEOF_SHORT == 2)
 
-  i=1; us_test[i].num = 0xFFFFU; us_test[i].expected = "65535";
+  i = 1; us_test[i].num = 0xFFFFU; us_test[i].expected = "65535";
   i++; us_test[i].num = 0xFF00U; us_test[i].expected = "65280";
   i++; us_test[i].num = 0x00FFU; us_test[i].expected = "255";
 
@@ -167,7 +167,7 @@ static int test_unsigned_short_formatting(void)
 
 #elif (SIZEOF_SHORT == 4)
 
-  i=1; us_test[i].num = 0xFFFFFFFFU; us_test[i].expected = "4294967295";
+  i = 1; us_test[i].num = 0xFFFFFFFFU; us_test[i].expected = "4294967295";
   i++; us_test[i].num = 0xFFFF0000U; us_test[i].expected = "4294901760";
   i++; us_test[i].num = 0x0000FFFFU; us_test[i].expected = "65535";
 
@@ -201,9 +201,9 @@ static int test_unsigned_short_formatting(void)
 
 #endif
 
-  for(i=1; i<=num_ushort_tests; i++) {
+  for(i = 1; i <= num_ushort_tests; i++) {
 
-    for(j=0; j<BUFSZ; j++)
+    for(j = 0; j<BUFSZ; j++)
       us_test[i].result[j] = 'X';
     us_test[i].result[BUFSZ-1] = '\0';
 
@@ -236,7 +236,7 @@ static int test_signed_short_formatting(void)
 
 #if (SIZEOF_SHORT == 1)
 
-  i=1; ss_test[i].num = 0x7F; ss_test[i].expected = "127";
+  i = 1; ss_test[i].num = 0x7F; ss_test[i].expected = "127";
 
   i++; ss_test[i].num = 0x70; ss_test[i].expected = "112";
   i++; ss_test[i].num = 0x07; ss_test[i].expected = "7";
@@ -261,7 +261,7 @@ static int test_signed_short_formatting(void)
 
 #elif (SIZEOF_SHORT == 2)
 
-  i=1; ss_test[i].num = 0x7FFF; ss_test[i].expected = "32767";
+  i = 1; ss_test[i].num = 0x7FFF; ss_test[i].expected = "32767";
   i++; ss_test[i].num = 0x7FFE; ss_test[i].expected = "32766";
   i++; ss_test[i].num = 0x7FFD; ss_test[i].expected = "32765";
   i++; ss_test[i].num = 0x7F00; ss_test[i].expected = "32512";
@@ -304,7 +304,7 @@ static int test_signed_short_formatting(void)
 
 #elif (SIZEOF_SHORT == 4)
 
-  i=1; ss_test[i].num = 0x7FFFFFFF; ss_test[i].expected = "2147483647";
+  i = 1; ss_test[i].num = 0x7FFFFFFF; ss_test[i].expected = "2147483647";
   i++; ss_test[i].num = 0x7FFFFFFE; ss_test[i].expected = "2147483646";
   i++; ss_test[i].num = 0x7FFFFFFD; ss_test[i].expected = "2147483645";
   i++; ss_test[i].num = 0x7FFF0000; ss_test[i].expected = "2147418112";
@@ -371,9 +371,9 @@ static int test_signed_short_formatting(void)
 
 #endif
 
-  for(i=1; i<=num_sshort_tests; i++) {
+  for(i = 1; i <= num_sshort_tests; i++) {
 
-    for(j=0; j<BUFSZ; j++)
+    for(j = 0; j<BUFSZ; j++)
       ss_test[i].result[j] = 'X';
     ss_test[i].result[BUFSZ-1] = '\0';
 
@@ -406,7 +406,7 @@ static int test_unsigned_int_formatting(void)
 
 #if (SIZEOF_INT == 2)
 
-  i=1; ui_test[i].num = 0xFFFFU; ui_test[i].expected = "65535";
+  i = 1; ui_test[i].num = 0xFFFFU; ui_test[i].expected = "65535";
   i++; ui_test[i].num = 0xFF00U; ui_test[i].expected = "65280";
   i++; ui_test[i].num = 0x00FFU; ui_test[i].expected = "255";
 
@@ -427,7 +427,7 @@ static int test_unsigned_int_formatting(void)
 
 #elif (SIZEOF_INT == 4)
 
-  i=1; ui_test[i].num = 0xFFFFFFFFU; ui_test[i].expected = "4294967295";
+  i = 1; ui_test[i].num = 0xFFFFFFFFU; ui_test[i].expected = "4294967295";
   i++; ui_test[i].num = 0xFFFF0000U; ui_test[i].expected = "4294901760";
   i++; ui_test[i].num = 0x0000FFFFU; ui_test[i].expected = "65535";
 
@@ -462,7 +462,7 @@ static int test_unsigned_int_formatting(void)
 #elif (SIZEOF_INT == 8)
 
   /* !checksrc! disable LONGLINE all */
-  i=1; ui_test[i].num = 0xFFFFFFFFFFFFFFFFU; ui_test[i].expected = 
"18446744073709551615";
+  i = 1; ui_test[i].num = 0xFFFFFFFFFFFFFFFFU; ui_test[i].expected = 
"18446744073709551615";
   i++; ui_test[i].num = 0xFFFFFFFF00000000U; ui_test[i].expected = 
"18446744069414584320";
   i++; ui_test[i].num = 0x00000000FFFFFFFFU; ui_test[i].expected = 
"4294967295";
 
@@ -521,9 +521,9 @@ static int test_unsigned_int_formatting(void)
 
 #endif
 
-  for(i=1; i<=num_uint_tests; i++) {
+  for(i = 1; i <= num_uint_tests; i++) {
 
-    for(j=0; j<BUFSZ; j++)
+    for(j = 0; j<BUFSZ; j++)
       ui_test[i].result[j] = 'X';
     ui_test[i].result[BUFSZ-1] = '\0';
 
@@ -556,7 +556,7 @@ static int test_signed_int_formatting(void)
 
 #if (SIZEOF_INT == 2)
 
-  i=1; si_test[i].num = 0x7FFF; si_test[i].expected = "32767";
+  i = 1; si_test[i].num = 0x7FFF; si_test[i].expected = "32767";
   i++; si_test[i].num = 0x7FFE; si_test[i].expected = "32766";
   i++; si_test[i].num = 0x7FFD; si_test[i].expected = "32765";
   i++; si_test[i].num = 0x7F00; si_test[i].expected = "32512";
@@ -599,7 +599,7 @@ static int test_signed_int_formatting(void)
 
 #elif (SIZEOF_INT == 4)
 
-  i=1; si_test[i].num = 0x7FFFFFFF; si_test[i].expected = "2147483647";
+  i = 1; si_test[i].num = 0x7FFFFFFF; si_test[i].expected = "2147483647";
   i++; si_test[i].num = 0x7FFFFFFE; si_test[i].expected = "2147483646";
   i++; si_test[i].num = 0x7FFFFFFD; si_test[i].expected = "2147483645";
   i++; si_test[i].num = 0x7FFF0000; si_test[i].expected = "2147418112";
@@ -666,7 +666,7 @@ static int test_signed_int_formatting(void)
 
 #elif (SIZEOF_INT == 8)
 
-  i=1; si_test[i].num = 0x7FFFFFFFFFFFFFFF; si_test[i].expected = 
"9223372036854775807";
+  i = 1; si_test[i].num = 0x7FFFFFFFFFFFFFFF; si_test[i].expected = 
"9223372036854775807";
   i++; si_test[i].num = 0x7FFFFFFFFFFFFFFE; si_test[i].expected = 
"9223372036854775806";
   i++; si_test[i].num = 0x7FFFFFFFFFFFFFFD; si_test[i].expected = 
"9223372036854775805";
   i++; si_test[i].num = 0x7FFFFFFF00000000; si_test[i].expected = 
"9223372032559808512";
@@ -749,9 +749,9 @@ static int test_signed_int_formatting(void)
 
 #endif
 
-  for(i=1; i<=num_sint_tests; i++) {
+  for(i = 1; i <= num_sint_tests; i++) {
 
-    for(j=0; j<BUFSZ; j++)
+    for(j = 0; j<BUFSZ; j++)
       si_test[i].result[j] = 'X';
     si_test[i].result[BUFSZ-1] = '\0';
 
@@ -782,9 +782,9 @@ static int test_unsigned_long_formatting(void)
   int num_ulong_tests;
   int failed = 0;
 
-#if (CURL_SIZEOF_LONG == 2)
+#if (SIZEOF_LONG == 2)
 
-  i=1; ul_test[i].num = 0xFFFFUL; ul_test[i].expected = "65535";
+  i = 1; ul_test[i].num = 0xFFFFUL; ul_test[i].expected = "65535";
   i++; ul_test[i].num = 0xFF00UL; ul_test[i].expected = "65280";
   i++; ul_test[i].num = 0x00FFUL; ul_test[i].expected = "255";
 
@@ -803,9 +803,9 @@ static int test_unsigned_long_formatting(void)
 
   num_ulong_tests = i;
 
-#elif (CURL_SIZEOF_LONG == 4)
+#elif (SIZEOF_LONG == 4)
 
-  i=1; ul_test[i].num = 0xFFFFFFFFUL; ul_test[i].expected = "4294967295";
+  i = 1; ul_test[i].num = 0xFFFFFFFFUL; ul_test[i].expected = "4294967295";
   i++; ul_test[i].num = 0xFFFF0000UL; ul_test[i].expected = "4294901760";
   i++; ul_test[i].num = 0x0000FFFFUL; ul_test[i].expected = "65535";
 
@@ -837,9 +837,9 @@ static int test_unsigned_long_formatting(void)
 
   num_ulong_tests = i;
 
-#elif (CURL_SIZEOF_LONG == 8)
+#elif (SIZEOF_LONG == 8)
 
-  i=1; ul_test[i].num = 0xFFFFFFFFFFFFFFFFUL; ul_test[i].expected = 
"18446744073709551615";
+  i = 1; ul_test[i].num = 0xFFFFFFFFFFFFFFFFUL; ul_test[i].expected = 
"18446744073709551615";
   i++; ul_test[i].num = 0xFFFFFFFF00000000UL; ul_test[i].expected = 
"18446744069414584320";
   i++; ul_test[i].num = 0x00000000FFFFFFFFUL; ul_test[i].expected = 
"4294967295";
 
@@ -898,9 +898,9 @@ static int test_unsigned_long_formatting(void)
 
 #endif
 
-  for(i=1; i<=num_ulong_tests; i++) {
+  for(i = 1; i <= num_ulong_tests; i++) {
 
-    for(j=0; j<BUFSZ; j++)
+    for(j = 0; j<BUFSZ; j++)
       ul_test[i].result[j] = 'X';
     ul_test[i].result[BUFSZ-1] = '\0';
 
@@ -931,9 +931,9 @@ static int test_signed_long_formatting(void)
   int num_slong_tests;
   int failed = 0;
 
-#if (CURL_SIZEOF_LONG == 2)
+#if (SIZEOF_LONG == 2)
 
-  i=1; sl_test[i].num = 0x7FFFL; sl_test[i].expected = "32767";
+  i = 1; sl_test[i].num = 0x7FFFL; sl_test[i].expected = "32767";
   i++; sl_test[i].num = 0x7FFEL; sl_test[i].expected = "32766";
   i++; sl_test[i].num = 0x7FFDL; sl_test[i].expected = "32765";
   i++; sl_test[i].num = 0x7F00L; sl_test[i].expected = "32512";
@@ -974,9 +974,9 @@ static int test_signed_long_formatting(void)
 
   num_slong_tests = i;
 
-#elif (CURL_SIZEOF_LONG == 4)
+#elif (SIZEOF_LONG == 4)
 
-  i=1; sl_test[i].num = 0x7FFFFFFFL; sl_test[i].expected = "2147483647";
+  i = 1; sl_test[i].num = 0x7FFFFFFFL; sl_test[i].expected = "2147483647";
   i++; sl_test[i].num = 0x7FFFFFFEL; sl_test[i].expected = "2147483646";
   i++; sl_test[i].num = 0x7FFFFFFDL; sl_test[i].expected = "2147483645";
   i++; sl_test[i].num = 0x7FFF0000L; sl_test[i].expected = "2147418112";
@@ -1041,9 +1041,9 @@ static int test_signed_long_formatting(void)
 
   num_slong_tests = i;
 
-#elif (CURL_SIZEOF_LONG == 8)
+#elif (SIZEOF_LONG == 8)
 
-  i=1; sl_test[i].num = 0x7FFFFFFFFFFFFFFFL; sl_test[i].expected = 
"9223372036854775807";
+  i = 1; sl_test[i].num = 0x7FFFFFFFFFFFFFFFL; sl_test[i].expected = 
"9223372036854775807";
   i++; sl_test[i].num = 0x7FFFFFFFFFFFFFFEL; sl_test[i].expected = 
"9223372036854775806";
   i++; sl_test[i].num = 0x7FFFFFFFFFFFFFFDL; sl_test[i].expected = 
"9223372036854775805";
   i++; sl_test[i].num = 0x7FFFFFFF00000000L; sl_test[i].expected = 
"9223372032559808512";
@@ -1126,9 +1126,9 @@ static int test_signed_long_formatting(void)
 
 #endif
 
-  for(i=1; i<=num_slong_tests; i++) {
+  for(i = 1; i <= num_slong_tests; i++) {
 
-    for(j=0; j<BUFSZ; j++)
+    for(j = 0; j<BUFSZ; j++)
       sl_test[i].result[j] = 'X';
     sl_test[i].result[BUFSZ-1] = '\0';
 
@@ -1159,9 +1159,9 @@ static int test_curl_off_t_formatting(void)
   int num_cofft_tests;
   int failed = 0;
 
-#if (CURL_SIZEOF_CURL_OFF_T == 2)
+#if (SIZEOF_CURL_OFF_T == 2)
 
-  i=1; co_test[i].num = MPRNT_OFF_T_C(0x7FFF); co_test[i].expected = "32767";
+  i = 1; co_test[i].num = MPRNT_OFF_T_C(0x7FFF); co_test[i].expected = "32767";
   i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFE); co_test[i].expected = "32766";
   i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFD); co_test[i].expected = "32765";
   i++; co_test[i].num = MPRNT_OFF_T_C(0x7F00); co_test[i].expected = "32512";
@@ -1202,9 +1202,9 @@ static int test_curl_off_t_formatting(void)
 
   num_cofft_tests = i;
 
-#elif (CURL_SIZEOF_CURL_OFF_T == 4)
+#elif (SIZEOF_CURL_OFF_T == 4)
 
-  i=1; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFF); co_test[i].expected = 
"2147483647";
+  i = 1; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFF); co_test[i].expected = 
"2147483647";
   i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFE); co_test[i].expected = 
"2147483646";
   i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFD); co_test[i].expected = 
"2147483645";
   i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFF0000); co_test[i].expected = 
"2147418112";
@@ -1269,9 +1269,9 @@ static int test_curl_off_t_formatting(void)
 
   num_cofft_tests = i;
 
-#elif (CURL_SIZEOF_CURL_OFF_T == 8)
+#elif (SIZEOF_CURL_OFF_T == 8)
 
-  i=1; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFFFFFFFFFF); co_test[i].expected 
= "9223372036854775807";
+  i = 1; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFFFFFFFFFF); 
co_test[i].expected = "9223372036854775807";
   i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFFFFFFFFFE); co_test[i].expected 
= "9223372036854775806";
   i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFFFFFFFFFD); co_test[i].expected 
= "9223372036854775805";
   i++; co_test[i].num = MPRNT_OFF_T_C(0x7FFFFFFF00000000); co_test[i].expected 
= "9223372032559808512";
@@ -1354,9 +1354,9 @@ static int test_curl_off_t_formatting(void)
 
 #endif
 
-  for(i=1; i<=num_cofft_tests; i++) {
+  for(i = 1; i <= num_cofft_tests; i++) {
 
-    for(j=0; j<BUFSZ; j++)
+    for(j = 0; j<BUFSZ; j++)
       co_test[i].result[j] = 'X';
     co_test[i].result[BUFSZ-1] = '\0';
 
@@ -1546,6 +1546,7 @@ static int test_weird_arguments(void)
 }
 
 /* DBL_MAX value from Linux */
+/* !checksrc! disable PLUSNOSPACE 1 */
 #define MAXIMIZE -1.7976931348623157081452E+308
 
 static int test_float_formatting(void)
diff --git a/tests/libtest/lib560.c b/tests/libtest/lib560.c
index 8fa0c2de2..0093ea113 100644
--- a/tests/libtest/lib560.c
+++ b/tests/libtest/lib560.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2011, 2017, 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
@@ -91,7 +91,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     abort_on_test_timeout();
 
diff --git a/tests/libtest/lib564.c b/tests/libtest/lib564.c
index 1822931bc..f959f2043 100644
--- a/tests/libtest/lib564.c
+++ b/tests/libtest/lib564.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2013, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2013, 2017, 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,7 +76,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &rd, &wr, &exc, &interval);
+    select_test(maxfd + 1, &rd, &wr, &exc, &interval);
 
     abort_on_test_timeout();
   }
diff --git a/tests/libtest/lib567.c b/tests/libtest/lib567.c
index f9f55e3c0..64fb29afb 100644
--- a/tests/libtest/lib567.c
+++ b/tests/libtest/lib567.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 @@ int test(char *URL)
 {
   CURLcode res;
   CURL *curl;
-  struct curl_slist *custom_headers=NULL;
+  struct curl_slist *custom_headers = NULL;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
     fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib568.c b/tests/libtest/lib568.c
index 0cdef812b..3bb53f61e 100644
--- a/tests/libtest/lib568.c
+++ b/tests/libtest/lib568.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,8 +47,8 @@ int test(char *URL)
   FILE *sdpf = NULL;
   struct_stat file_info;
   char *stream_uri = NULL;
-  int request=1;
-  struct curl_slist *custom_headers=NULL;
+  int request = 1;
+  struct curl_slist *custom_headers = NULL;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
     fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib569.c b/tests/libtest/lib569.c
index d7381d9a2..c18c882b9 100644
--- a/tests/libtest/lib569.c
+++ b/tests/libtest/lib569.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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 @@ int test(char *URL)
   CURL *curl;
   char *stream_uri = NULL;
   char *rtsp_session_id;
-  int request=1;
+  int request = 1;
   int i;
   FILE *idfile = NULL;
 
diff --git a/tests/libtest/lib570.c b/tests/libtest/lib570.c
index 9d9b5a134..1756a8615 100644
--- a/tests/libtest/lib570.c
+++ b/tests/libtest/lib570.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -32,7 +32,7 @@ int test(char *URL)
 {
   int res;
   CURL *curl;
-  int request=1;
+  int request = 1;
   char *stream_uri = NULL;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
diff --git a/tests/libtest/lib571.c b/tests/libtest/lib571.c
index f19b643ff..70524f2f2 100644
--- a/tests/libtest/lib571.c
+++ b/tests/libtest/lib571.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -70,7 +70,7 @@ static size_t rtp_write(void *ptr, size_t size, size_t nmemb, 
void *stream)
   }
 
   data += 4;
-  for(i = 0; i < message_size; i+= RTP_DATA_SIZE) {
+  for(i = 0; i < message_size; i += RTP_DATA_SIZE) {
     if(message_size - i > RTP_DATA_SIZE) {
       if(memcmp(RTP_DATA, data + i, RTP_DATA_SIZE) != 0) {
         printf("RTP PAYLOAD CORRUPTED [%s]\n", data + i);
@@ -103,7 +103,7 @@ int test(char *URL)
   int res;
   CURL *curl;
   char *stream_uri = NULL;
-  int request=1;
+  int request = 1;
   FILE *protofile = NULL;
 
   protofile = fopen(libtest_arg2, "wb");
diff --git a/tests/libtest/lib572.c b/tests/libtest/lib572.c
index 47a9da535..a78c9358d 100644
--- a/tests/libtest/lib572.c
+++ b/tests/libtest/lib572.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,8 +47,8 @@ int test(char *URL)
   FILE *paramsf = NULL;
   struct_stat file_info;
   char *stream_uri = NULL;
-  int request=1;
-  struct curl_slist *custom_headers=NULL;
+  int request = 1;
+  struct curl_slist *custom_headers = NULL;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
     fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib573.c b/tests/libtest/lib573.c
index dce198b50..eb817b1ed 100644
--- a/tests/libtest/lib573.c
+++ b/tests/libtest/lib573.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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 test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     abort_on_test_timeout();
   }
diff --git a/tests/libtest/lib575.c b/tests/libtest/lib575.c
index 186170cfc..6baa12229 100644
--- a/tests/libtest/lib575.c
+++ b/tests/libtest/lib575.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2011, 2017, 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
@@ -93,7 +93,7 @@ int test(char *URL)
 
     /* At this point, maxfd is guaranteed to be greater or equal than -1. */
 
-    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     abort_on_test_timeout();
 
diff --git a/tests/libtest/lib578.c b/tests/libtest/lib578.c
index 41b23db34..1b4ee526c 100644
--- a/tests/libtest/lib578.c
+++ b/tests/libtest/lib578.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -51,7 +51,7 @@ static int progress_callback(void *clientp, double dltotal, 
double dlnow,
 int test(char *URL)
 {
   CURL *curl;
-  CURLcode res=CURLE_OK;
+  CURLcode res = CURLE_OK;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
     fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/lib579.c b/tests/libtest/lib579.c
index 61aa4f5df..cba4b1cb4 100644
--- a/tests/libtest/lib579.c
+++ b/tests/libtest/lib579.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 +87,7 @@ static size_t read_callback(void *ptr, size_t size, size_t 
nmemb, void *userp)
 int test(char *URL)
 {
   CURL *curl;
-  CURLcode res=CURLE_OK;
+  CURLcode res = CURLE_OK;
   struct curl_slist *slist = NULL;
   struct WriteThis pooh;
   pooh.counter = 0;
diff --git a/tests/libtest/lib586.c b/tests/libtest/lib586.c
index 859ef3430..669f71c15 100644
--- a/tests/libtest/lib586.c
+++ b/tests/libtest/lib586.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -99,7 +99,7 @@ static void *fire(void *ptr)
   CURLcode code;
   struct Tdata *tdata = (struct Tdata*)ptr;
   CURL *curl;
-  int i=0;
+  int i = 0;
 
   curl = curl_easy_init();
   if(!curl) {
@@ -185,7 +185,7 @@ int test(char *URL)
   res = 0;
 
   /* start treads */
-  for(i=1; i<=THREADS; i++) {
+  for(i = 1; i <= THREADS; i++) {
 
     /* set thread data */
     tdata.url   = URL;
@@ -218,7 +218,7 @@ int test(char *URL)
   /* try to free share, expect to fail because share is in use*/
   printf("try SHARE_CLEANUP...\n");
   scode = curl_share_cleanup(share);
-  if(scode==CURLSHE_OK) {
+  if(scode == CURLSHE_OK) {
     fprintf(stderr, "curl_share_cleanup succeed but error expected\n");
     share = NULL;
   }
@@ -235,7 +235,7 @@ test_cleanup:
   /* free share */
   printf("SHARE_CLEANUP\n");
   scode = curl_share_cleanup(share);
-  if(scode!=CURLSHE_OK)
+  if(scode != CURLSHE_OK)
     fprintf(stderr, "curl_share_cleanup failed, code errno %d\n",
             (int)scode);
 
diff --git a/tests/libtest/lib516.c b/tests/libtest/lib589.c
similarity index 92%
copy from tests/libtest/lib516.c
copy to tests/libtest/lib589.c
index 00c54c450..667459d0d 100644
--- a/tests/libtest/lib516.c
+++ b/tests/libtest/lib589.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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 @@
 int test(char *URL)
 {
   CURL *curl;
-  CURLcode res=CURLE_OK;
+  CURLcode res = CURLE_OK;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
     fprintf(stderr, "curl_global_init() failed\n");
@@ -42,7 +42,7 @@ int test(char *URL)
 
   /* First set the URL that is about to receive our POST. */
   test_setopt(curl, CURLOPT_URL, URL);
-  test_setopt(curl, CURLOPT_HTTPPOST, NULL);
+  test_setopt(curl, CURLOPT_MIMEPOST, NULL);
   test_setopt(curl, CURLOPT_VERBOSE, 1L); /* show verbose for debug */
   test_setopt(curl, CURLOPT_HEADER, 1L); /* include header */
 
diff --git a/tests/libtest/lib591.c b/tests/libtest/lib591.c
index 53ede3fcd..f25cc4d73 100644
--- a/tests/libtest/lib591.c
+++ b/tests/libtest/lib591.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2012, 2017, 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
@@ -123,7 +123,7 @@ int test(char *URL)
       interval.tv_usec = 100000L; /* 100 ms */
     }
 
-    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval);
+    select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &interval);
 
     abort_on_test_timeout();
   }
diff --git a/tests/libtest/lib597.c b/tests/libtest/lib597.c
index 813af7541..c8529743e 100644
--- a/tests/libtest/lib597.c
+++ b/tests/libtest/lib597.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,10 +60,7 @@ int test(char *URL)
 
   start_test_timing();
 
-  res_global_init(CURL_GLOBAL_ALL);
-  if(res) {
-    return res;
-  }
+  global_init(CURL_GLOBAL_ALL);
 
   easy_init(easy);
 
@@ -123,11 +120,11 @@ int test(char *URL)
         interval.tv_usec = (itimeout%1000)*1000;
       }
       else {
-        interval.tv_sec = TEST_HANG_TIMEOUT/1000+1;
+        interval.tv_sec = TEST_HANG_TIMEOUT/1000 + 1;
         interval.tv_usec = 0;
       }
 
-      select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval);
+      select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &interval);
 
       abort_on_test_timeout();
     }
diff --git a/tests/libtest/lib599.c b/tests/libtest/lib599.c
index 843fb2121..0e05977b5 100644
--- a/tests/libtest/lib599.c
+++ b/tests/libtest/lib599.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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 @@ static int progress_callback(void *clientp, double dltotal,
 int test(char *URL)
 {
   CURL *curl;
-  CURLcode res=CURLE_OK;
+  CURLcode res = CURLE_OK;
   double content_length = 0.0;
 
   if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
diff --git a/tests/libtest/lib643.c b/tests/libtest/lib643.c
new file mode 100644
index 000000000..e26a2515f
--- /dev/null
+++ b/tests/libtest/lib643.c
@@ -0,0 +1,270 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, 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 */
+  "\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";
+#else
+  "this is what we post to the silly web server\n";
+#endif
+
+struct WriteThis {
+  char *readptr;
+  curl_off_t sizeleft;
+};
+
+static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp)
+{
+#ifdef LIB644
+  (void)ptr;
+  (void)size;
+  (void)nmemb;
+  (void)userp;
+  return CURL_READFUNC_ABORT;
+#else
+
+  struct WriteThis *pooh = (struct WriteThis *)userp;
+  int eof = !*pooh->readptr;
+
+  if(size*nmemb < 1)
+    return 0;
+
+#ifndef LIB645
+  eof = pooh->sizeleft <= 0;
+  if(!eof)
+    pooh->sizeleft--;
+#endif
+
+  if(!eof) {
+    *ptr = *pooh->readptr;           /* copy one single byte */
+    pooh->readptr++;                 /* advance pointer */
+    return 1;                        /* we return 1 byte at a time! */
+  }
+
+  return 0;                         /* no more data left to deliver */
+#endif
+}
+
+static int once(char *URL, bool oldstyle)
+{
+  CURL *curl;
+  CURLcode res = CURLE_OK;
+
+  curl_mime *mime = NULL;
+  curl_mimepart *part = NULL;
+  struct WriteThis pooh;
+  struct WriteThis pooh2;
+  curl_off_t datasize = -1;
+
+  pooh.readptr = data;
+#ifndef LIB645
+  datasize = (curl_off_t)strlen(data);
+#endif
+  pooh.sizeleft = datasize;
+
+  curl = curl_easy_init();
+  if(!curl) {
+    fprintf(stderr, "curl_easy_init() failed\n");
+    curl_global_cleanup();
+    return TEST_ERR_MAJOR_BAD;
+  }
+
+  mime = curl_mime_init(curl);
+  if(!mime) {
+    fprintf(stderr, "curl_mime_init() failed\n");
+    curl_easy_cleanup(curl);
+    curl_global_cleanup();
+    return TEST_ERR_MAJOR_BAD;
+  }
+
+  part = curl_mime_addpart(mime);
+  if(!part) {
+    fprintf(stderr, "curl_mime_addpart(1) failed\n");
+    curl_mime_free(mime);
+    curl_easy_cleanup(curl);
+    curl_global_cleanup();
+    return TEST_ERR_MAJOR_BAD;
+  }
+
+  /* Fill in the file upload part */
+  if(oldstyle) {
+    res = curl_mime_name(part, "sendfile");
+    if(!res)
+      res = curl_mime_data_cb(part, datasize, read_callback,
+                              NULL, NULL, &pooh);
+    if(!res)
+      res = curl_mime_filename(part, "postit2.c");
+  }
+  else {
+    /* new style */
+    res = curl_mime_name(part, "sendfile alternative");
+    if(!res)
+      res = curl_mime_data_cb(part, datasize, read_callback,
+                              NULL, NULL, &pooh);
+    if(!res)
+      res = curl_mime_filename(part, "file name 2");
+  }
+
+  if(res)
+    printf("curl_mime_xxx(1) = %s\n", curl_easy_strerror(res));
+
+  /* Now add the same data with another name and make it not look like
+     a file upload but still using the callback */
+
+  pooh2.readptr = data;
+#ifndef LIB645
+  datasize = (curl_off_t)strlen(data);
+#endif
+  pooh2.sizeleft = datasize;
+
+  part = curl_mime_addpart(mime);
+  if(!part) {
+    fprintf(stderr, "curl_mime_addpart(2) failed\n");
+    curl_mime_free(mime);
+    curl_easy_cleanup(curl);
+    curl_global_cleanup();
+    return TEST_ERR_MAJOR_BAD;
+  }
+  /* Fill in the file upload part */
+  res = curl_mime_name(part, "callbackdata");
+  if(!res)
+    res = curl_mime_data_cb(part, datasize, read_callback,
+                            NULL, NULL, &pooh2);
+
+  if(res)
+    printf("curl_mime_xxx(2) = %s\n", curl_easy_strerror(res));
+
+  part = curl_mime_addpart(mime);
+  if(!part) {
+    fprintf(stderr, "curl_mime_addpart(3) failed\n");
+    curl_mime_free(mime);
+    curl_easy_cleanup(curl);
+    curl_global_cleanup();
+    return TEST_ERR_MAJOR_BAD;
+  }
+
+  /* Fill in the filename field */
+  res = curl_mime_name(part, "filename");
+  if(!res)
+    res = curl_mime_data(part,
+#ifdef CURL_DOES_CONVERSIONS
+                         /* ASCII representation with escape
+                            sequences for non-ASCII platforms */
+                         "\x70\x6f\x73\x74\x69\x74\x32\x2e\x63",
+#else
+                          "postit2.c",
+#endif
+                          CURL_ZERO_TERMINATED);
+
+  if(res)
+    printf("curl_mime_xxx(3) = %s\n", curl_easy_strerror(res));
+
+  /* Fill in a submit field too */
+  part = curl_mime_addpart(mime);
+  if(!part) {
+    fprintf(stderr, "curl_mime_addpart(4) failed\n");
+    curl_mime_free(mime);
+    curl_easy_cleanup(curl);
+    curl_global_cleanup();
+    return TEST_ERR_MAJOR_BAD;
+  }
+  res = curl_mime_name(part, "submit");
+  if(!res)
+    res = curl_mime_data(part,
+#ifdef CURL_DOES_CONVERSIONS
+                         /* ASCII representation with escape
+                            sequences for non-ASCII platforms */
+                         "\x73\x65\x6e\x64",
+#else
+                          "send",
+#endif
+                          CURL_ZERO_TERMINATED);
+
+  if(res)
+    printf("curl_mime_xxx(4) = %s\n", curl_easy_strerror(res));
+
+  part = curl_mime_addpart(mime);
+  if(!part) {
+    fprintf(stderr, "curl_mime_addpart(5) failed\n");
+    curl_mime_free(mime);
+    curl_easy_cleanup(curl);
+    curl_global_cleanup();
+    return TEST_ERR_MAJOR_BAD;
+  }
+  res = curl_mime_name(part, "somename");
+  if(!res)
+    res = curl_mime_filename(part, "somefile.txt");
+  if(!res)
+    res = curl_mime_data(part, "blah blah", 9);
+
+  if(res)
+    printf("curl_mime_xxx(5) = %s\n", curl_easy_strerror(res));
+
+  /* First set the URL that is about to receive our POST. */
+  test_setopt(curl, CURLOPT_URL, URL);
+
+  /* send a multi-part mimepost */
+  test_setopt(curl, CURLOPT_MIMEPOST, mime);
+
+  /* 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);
+
+test_cleanup:
+
+  /* always cleanup */
+  curl_easy_cleanup(curl);
+
+  /* now cleanup the mimepost structure */
+  curl_mime_free(mime);
+
+  return res;
+}
+
+int test(char *URL)
+{
+  int res;
+
+  if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+    fprintf(stderr, "curl_global_init() failed\n");
+    return TEST_ERR_MAJOR_BAD;
+  }
+
+  res = once(URL, TRUE); /* old */
+  if(!res)
+    res = once(URL, FALSE); /* new */
+
+  curl_global_cleanup();
+
+  return res;
+}
diff --git a/tests/libtest/lib650.c b/tests/libtest/lib650.c
new file mode 100644
index 000000000..130ef1e77
--- /dev/null
+++ b/tests/libtest/lib650.c
@@ -0,0 +1,189 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2017, 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 */
+  "\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";
+#else
+  "this is what we post to the silly web server";
+#endif
+
+static char name[] = "fieldname";
+
+
+/* This test attempts to use all form API features that are not
+ * used elsewhere.
+ */
+
+/* curl_formget callback to count characters. */
+static size_t count_chars(void *userp, const char *buf, size_t len)
+{
+  size_t *pcounter = (size_t *) userp;
+
+  (void) buf;
+  *pcounter += len;
+  return len;
+}
+
+
+int test(char *URL)
+{
+  CURL *curl;
+  CURLcode res = CURLE_OK;
+  CURLFORMcode formrc;
+  struct curl_slist *headers = NULL;
+  struct curl_httppost *formpost = NULL;
+  struct curl_httppost *lastptr = NULL;
+  struct curl_forms formarray[3];
+  size_t formlength = 0;
+  char flbuf[32];
+
+  if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
+    fprintf(stderr, "curl_global_init() failed\n");
+    return TEST_ERR_MAJOR_BAD;
+  }
+
+  /* Check proper name and data copying. */
+  formrc = curl_formadd(&formpost, &lastptr,
+                        CURLFORM_COPYNAME, &name,
+                        CURLFORM_COPYCONTENTS, &data,
+                        CURLFORM_END);
+
+  if(formrc)
+    printf("curl_formadd(1) = %d\n", (int) formrc);
+
+  /* Use a form array for the non-copy test. */
+  formarray[0].option = CURLFORM_PTRCONTENTS;
+  formarray[0].value = data;
+  formarray[1].option = CURLFORM_CONTENTSLENGTH;
+  formarray[1].value = (char *) strlen(data) - 1;
+  formarray[2].option = CURLFORM_END;
+  formarray[2].value = NULL;
+  formrc = curl_formadd(&formpost,
+                        &lastptr,
+                        CURLFORM_PTRNAME, name,
+                        CURLFORM_NAMELENGTH, strlen(name) - 1,
+                        CURLFORM_ARRAY, formarray,
+                        CURLFORM_FILENAME, "remotefile.txt",
+                        CURLFORM_END);
+
+  if(formrc)
+    printf("curl_formadd(2) = %d\n", (int) formrc);
+
+  /* Now change in-memory data to affect CURLOPT_PTRCONTENTS value.
+     Copied values (first field) must not be affected.
+     CURLOPT_PTRNAME actually copies the name thus we do not test this here. */
+  data[0]++;
+
+  /* Check multi-files and content type propagation. */
+  formrc = curl_formadd(&formpost,
+                        &lastptr,
+                        CURLFORM_COPYNAME, "multifile",
+                        CURLFORM_FILE, libtest_arg2,    /* Set in first.c. */
+                        CURLFORM_FILE, libtest_arg2,
+                        CURLFORM_CONTENTTYPE, "text/whatever",
+                        CURLFORM_FILE, libtest_arg2,
+                        CURLFORM_END);
+
+  if(formrc)
+    printf("curl_formadd(3) = %d\n", (int) formrc);
+
+  /* Check data from file content and headers. */
+  headers = curl_slist_append(headers, "X-customheader-1: Header 1 data");
+  headers = curl_slist_append(headers, "X-customheader-2: Header 2 data");
+  formrc = curl_formadd(&formpost,
+                        &lastptr,
+                        CURLFORM_COPYNAME, "filecontents",
+                        CURLFORM_FILECONTENT, libtest_arg2,
+                        CURLFORM_CONTENTHEADER, headers,
+                        CURLFORM_END);
+
+  if(formrc)
+    printf("curl_formadd(3) = %d\n", (int) formrc);
+
+  /* Measure the current form length.
+   * This is done before including stdin data because we want to reuse it
+   * and stdin cannot be rewound.
+   */
+  curl_formget(formpost, (void *) &formlength, count_chars);
+
+  /* Include length in data for external check. */
+  curl_msnprintf(flbuf, sizeof flbuf, "%lu", (unsigned long) formlength);
+  formrc = curl_formadd(&formpost,
+                        &lastptr,
+                        CURLFORM_COPYNAME, "formlength",
+                        CURLFORM_COPYCONTENTS, &flbuf,
+                        CURLFORM_END);
+
+  /* Check stdin (may be problematic on some platforms). */
+  formrc = curl_formadd(&formpost,
+                        &lastptr,
+                        CURLFORM_COPYNAME, "standardinput",
+                        CURLFORM_FILE, "-",
+                        CURLFORM_END);
+
+  if(formrc)
+    printf("curl_formadd(4) = %d\n", (int) formrc);
+
+  curl = curl_easy_init();
+  if(!curl) {
+    fprintf(stderr, "curl_easy_init() failed\n");
+    curl_slist_free_all(headers);
+    curl_formfree(formpost);
+    curl_global_cleanup();
+    return TEST_ERR_MAJOR_BAD;
+  }
+
+  /* First set the URL that is about to receive our POST. */
+  test_setopt(curl, CURLOPT_URL, URL);
+
+  /* send a multi-part formpost */
+  test_setopt(curl, CURLOPT_HTTPPOST, formpost);
+
+  /* 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);
+
+test_cleanup:
+
+  /* always cleanup */
+  curl_easy_cleanup(curl);
+
+  /* now cleanup the formpost chain */
+  curl_formfree(formpost);
+  curl_slist_free_all(headers);
+
+  curl_global_cleanup();
+
+  return res;
+}
diff --git a/tests/libtest/libntlmconnect.c b/tests/libtest/libntlmconnect.c
index ad20e8b8f..0d527a779 100644
--- a/tests/libtest/libntlmconnect.c
+++ b/tests/libtest/libntlmconnect.c
@@ -196,7 +196,7 @@ int test(char *url)
       interval.tv_usec = (itimeout%1000)*1000;
     }
     else {
-      interval.tv_sec = TEST_HANG_TIMEOUT/1000+1;
+      interval.tv_sec = TEST_HANG_TIMEOUT/1000 + 1;
       interval.tv_usec = 0;
 
       /* if there's no timeout and we get here on the last handle, we may
@@ -207,7 +207,7 @@ int test(char *url)
       }
     }
 
-    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &interval);
+    select_test(maxfd + 1, &fdread, &fdwrite, &fdexcep, &interval);
 
     abort_on_test_timeout();
   }
diff --git a/tests/libtest/mk-lib1521.pl b/tests/libtest/mk-lib1521.pl
index a75fad928..0b1d10d46 100644
--- a/tests/libtest/mk-lib1521.pl
+++ b/tests/libtest/mk-lib1521.pl
@@ -143,9 +143,10 @@ int test(char *URL)
   void *conv_to_network_cb = NULL;
   void *conv_from_utf8_cb = NULL;
   void *interleavecb = NULL;
-  char *stringpointerextra=(char *)"moooo";
-  struct curl_slist *slist=NULL;
-  struct curl_httppost *httppost=NULL;
+  char *stringpointerextra = (char *)"moooo";
+  struct curl_slist *slist = NULL;
+  struct curl_httppost *httppost = NULL;
+  curl_mime *mimepost = NULL;
   FILE *stream = stderr;
   struct data object;
   char *charp;
@@ -157,6 +158,7 @@ int test(char *URL)
   struct curl_tlssessioninfo *tlssession;
   CURLcode res = CURLE_OK;
   (void)URL; /* not used */
+  global_init(CURL_GLOBAL_ALL);
   easy_init(dep);
   easy_init(curl);
   share = curl_share_init();
@@ -215,6 +217,9 @@ while(<STDIN>) {
             elsif($name eq "HTTPPOST") {
               print "${pref} httppost);\n$check";
             }
+            elsif($name eq "MIMEPOST") {
+              print "${pref} mimepost);\n$check";
+            }
             elsif($name eq "STDERR") {
               print "${pref} stream);\n$check";
             }
@@ -296,6 +301,7 @@ test_cleanup:
   curl_easy_cleanup(curl);
   curl_easy_cleanup(dep);
   curl_share_cleanup(share);
+  curl_global_cleanup();
 
   return (int)res;
 }
diff --git a/tests/libtest/stub_gssapi.c b/tests/libtest/stub_gssapi.c
new file mode 100644
index 000000000..168becf88
--- /dev/null
+++ b/tests/libtest/stub_gssapi.c
@@ -0,0 +1,397 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017, 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.
+ *
+ ***************************************************************************/
+
+/* Only provides the bare minimum to link with libcurl */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "stub_gssapi.h"
+
+#define MAX_CREDS_LENGTH 250
+#define APPROX_TOKEN_LEN 250
+
+enum min_err_code {
+    GSS_OK = 0,
+    GSS_NO_MEMORY,
+    GSS_INVALID_ARGS,
+    GSS_INVALID_CREDS,
+    GSS_INVALID_CTX,
+    GSS_SERVER_ERR,
+    GSS_NO_MECH,
+    GSS_LAST
+};
+
+const char *min_err_table[] = {
+    "stub-gss: no error",
+    "stub-gss: no memory",
+    "stub-gss: invalid arguments",
+    "stub-gss: invalid credentials",
+    "stub-gss: invalid context",
+    "stub-gss: server returned error",
+    "stub-gss: cannot find a mechanism",
+    NULL
+};
+
+struct gss_ctx_id_t_desc_struct {
+  enum { NONE, KRB5, NTLM1, NTLM3 } sent;
+  int have_krb5;
+  int have_ntlm;
+  OM_uint32 flags;
+  char creds[MAX_CREDS_LENGTH];
+};
+
+OM_uint32 gss_init_sec_context(OM_uint32 *min,
+            gss_const_cred_id_t initiator_cred_handle,
+            gss_ctx_id_t *context_handle,
+            gss_const_name_t target_name,
+            const gss_OID mech_type,
+            OM_uint32 req_flags,
+            OM_uint32 time_req,
+            const gss_channel_bindings_t input_chan_bindings,
+            const gss_buffer_t input_token,
+            gss_OID *actual_mech_type,
+            gss_buffer_t output_token,
+            OM_uint32 *ret_flags,
+            OM_uint32 *time_rec)
+{
+  /* The token will be encoded in base64 */
+  int length = APPROX_TOKEN_LEN * 3 / 4;
+  int used = 0;
+  char *token = NULL;
+  const char *creds = NULL;
+  gss_ctx_id_t ctx = NULL;
+
+  if(!min)
+    return GSS_S_FAILURE;
+
+  *min = 0;
+
+  if(!context_handle || !target_name || !output_token) {
+    *min = GSS_INVALID_ARGS;
+    return GSS_S_FAILURE;
+  }
+
+  creds = getenv("CURL_STUB_GSS_CREDS");
+  if(!creds || strlen(creds) >= MAX_CREDS_LENGTH) {
+    *min = GSS_INVALID_CREDS;
+    return GSS_S_FAILURE;
+  }
+
+  ctx = *context_handle;
+  if(ctx && strcmp(ctx->creds, creds)) {
+    *min = GSS_INVALID_CREDS;
+    return GSS_S_FAILURE;
+  }
+
+  output_token->length = 0;
+  output_token->value = NULL;
+
+  if(input_token && input_token->length) {
+    if(!ctx) {
+      *min = GSS_INVALID_CTX;
+      return GSS_S_FAILURE;
+    }
+
+    /* Server response, either D (RA==) or C (Qw==) */
+    if(((char *) input_token->value)[0] == 'D') {
+      /* Done */
+      switch(ctx->sent) {
+      case KRB5:
+      case NTLM3:
+        if(ret_flags)
+          *ret_flags = ctx->flags;
+        if(time_rec)
+          *time_rec = GSS_C_INDEFINITE;
+        return GSS_S_COMPLETE;
+      default:
+        *min = GSS_SERVER_ERR;
+        return GSS_S_FAILURE;
+      }
+    }
+
+    if(((char *) input_token->value)[0] != 'C') {
+      /* We only support Done or Continue */
+      *min = GSS_SERVER_ERR;
+      return GSS_S_FAILURE;
+    }
+
+    /* Continue */
+    switch(ctx->sent) {
+    case KRB5:
+      /* We sent KRB5 and it failed, let's try NTLM */
+      if(ctx->have_ntlm) {
+        ctx->sent = NTLM1;
+        break;
+      }
+      else {
+        *min = GSS_SERVER_ERR;
+        return GSS_S_FAILURE;
+      }
+    case NTLM1:
+      ctx->sent = NTLM3;
+      break;
+    default:
+      *min = GSS_SERVER_ERR;
+      return GSS_S_FAILURE;
+    }
+  }
+  else {
+    if(ctx) {
+      *min = GSS_INVALID_CTX;
+      return GSS_S_FAILURE;
+    }
+
+    ctx = (gss_ctx_id_t) calloc(sizeof(*ctx), 1);
+    if(!ctx) {
+      *min = GSS_NO_MEMORY;
+      return GSS_S_FAILURE;
+    }
+
+    if(strstr(creds, "KRB5"))
+      ctx->have_krb5 = 1;
+
+    if(strstr(creds, "NTLM"))
+      ctx->have_ntlm = 1;
+
+    if(ctx->have_krb5)
+      ctx->sent = KRB5;
+    else if(ctx->have_ntlm)
+      ctx->sent = NTLM1;
+    else {
+      free(ctx);
+      *min = GSS_NO_MECH;
+      return GSS_S_FAILURE;
+    }
+
+    strcpy(ctx->creds, creds);
+    ctx->flags = req_flags;
+  }
+
+  token = malloc(length);
+  if(!token) {
+    free(ctx);
+    *min = GSS_NO_MEMORY;
+    return GSS_S_FAILURE;
+  }
+
+  /* Token format: creds:target:type:padding */
+  used = snprintf(token, length, "%s:%s:%d:", creds,
+                  (char *) target_name, ctx->sent);
+
+  if(used >= length) {
+    free(token);
+    free(ctx);
+    *min = GSS_NO_MEMORY;
+    return GSS_S_FAILURE;
+  }
+
+  /* Overwrite null terminator */
+  memset(token + used, 'A', length - used);
+
+  *context_handle = ctx;
+
+  output_token->value = token;
+  output_token->length = length;
+
+  return GSS_S_CONTINUE_NEEDED;
+}
+
+OM_uint32 gss_delete_sec_context(OM_uint32 *min,
+                                 gss_ctx_id_t *context_handle,
+                                 gss_buffer_t output_token)
+{
+  if(!min)
+    return GSS_S_FAILURE;
+
+  if(!context_handle) {
+    *min = GSS_INVALID_CTX;
+    return GSS_S_FAILURE;
+  }
+
+  free(*context_handle);
+  *context_handle = NULL;
+  *min = 0;
+
+  return GSS_S_COMPLETE;
+}
+
+OM_uint32 gss_release_buffer(OM_uint32 *min,
+                             gss_buffer_t buffer)
+{
+  if(min)
+    *min = 0;
+
+  if(buffer && buffer->length) {
+    free(buffer->value);
+    buffer->length = 0;
+  }
+
+  return GSS_S_COMPLETE;
+}
+
+OM_uint32 gss_import_name(OM_uint32 *min,
+                          const gss_buffer_t input_name_buffer,
+                          const gss_OID input_name_type,
+                          gss_name_t *output_name)
+{
+  char *name = NULL;
+
+  if(!min)
+    return GSS_S_FAILURE;
+
+  if(!input_name_buffer || !output_name) {
+    *min = GSS_INVALID_ARGS;
+    return GSS_S_FAILURE;
+  }
+
+  name = strndup(input_name_buffer->value, input_name_buffer->length);
+  if(!name) {
+    *min = GSS_NO_MEMORY;
+    return GSS_S_FAILURE;
+  }
+
+  *output_name = (gss_name_t) name;
+  *min = 0;
+
+  return GSS_S_COMPLETE;
+}
+
+OM_uint32 gss_release_name(OM_uint32 *min,
+                           gss_name_t *input_name)
+{
+  if(min)
+    *min = 0;
+
+  if(input_name)
+    free(*input_name);
+
+  return GSS_S_COMPLETE;
+}
+
+OM_uint32 gss_display_status(OM_uint32 *min,
+                             OM_uint32 status_value,
+                             int status_type,
+                             const gss_OID mech_type,
+                             OM_uint32 *message_context,
+                             gss_buffer_t status_string)
+{
+  const char maj_str[] = "Stub GSS error";
+  if(min)
+    *min = 0;
+
+  if(message_context)
+    *message_context = 0;
+
+  if(status_string) {
+    status_string->value = NULL;
+    status_string->length = 0;
+
+    if(status_value >= GSS_LAST)
+      return GSS_S_FAILURE;
+
+    switch(status_type) {
+      case GSS_C_GSS_CODE:
+        status_string->value = strdup(maj_str);
+        break;
+      case GSS_C_MECH_CODE:
+        status_string->value = strdup(min_err_table[status_value]);
+        break;
+      default:
+        return GSS_S_FAILURE;
+    }
+
+    if(status_string->value)
+      status_string->length = strlen(status_string->value);
+    else
+       return GSS_S_FAILURE;
+  }
+
+  return GSS_S_COMPLETE;
+}
+
+/* Stubs returning error */
+
+OM_uint32 gss_display_name(OM_uint32 *min,
+                           gss_const_name_t input_name,
+                           gss_buffer_t output_name_buffer,
+                           gss_OID *output_name_type)
+{
+  return GSS_S_FAILURE;
+}
+
+OM_uint32 gss_inquire_context(OM_uint32 *min,
+                              gss_const_ctx_id_t context_handle,
+                              gss_name_t *src_name,
+                              gss_name_t *targ_name,
+                              OM_uint32 *lifetime_rec,
+                              gss_OID *mech_type,
+                              OM_uint32 *ctx_flags,
+                              int *locally_initiated,
+                              int *open_context)
+{
+  return GSS_S_FAILURE;
+}
+
+OM_uint32 gss_wrap(OM_uint32 *min,
+                   gss_const_ctx_id_t context_handle,
+                   int conf_req_flag,
+                   gss_qop_t qop_req,
+                   const gss_buffer_t input_message_buffer,
+                   int *conf_state,
+                   gss_buffer_t output_message_buffer)
+{
+  return GSS_S_FAILURE;
+}
+
+OM_uint32 gss_unwrap(OM_uint32 *min,
+                     gss_const_ctx_id_t context_handle,
+                     const gss_buffer_t input_message_buffer,
+                     gss_buffer_t output_message_buffer,
+                     int *conf_state,
+                     gss_qop_t *qop_state)
+{
+  return GSS_S_FAILURE;
+}
+
+OM_uint32 gss_seal(OM_uint32 *min,
+                   gss_ctx_id_t context_handle,
+                   int conf_req_flag,
+                   int qop_req,
+                   gss_buffer_t input_message_buffer,
+                   int *conf_state,
+                   gss_buffer_t output_message_buffer)
+{
+  return GSS_S_FAILURE;
+}
+
+OM_uint32 gss_unseal(OM_uint32 *min,
+                     gss_ctx_id_t context_handle,
+                     gss_buffer_t input_message_buffer,
+                     gss_buffer_t output_message_buffer,
+                     int *conf_state,
+                     int *qop_state)
+{
+  return GSS_S_FAILURE;
+}
+
diff --git a/tests/libtest/stub_gssapi.h b/tests/libtest/stub_gssapi.h
new file mode 100644
index 000000000..9a302f0f5
--- /dev/null
+++ b/tests/libtest/stub_gssapi.h
@@ -0,0 +1,183 @@
+#ifndef HEADER_CURL_GSSAPI_STUBS_H
+#define HEADER_CURL_GSSAPI_STUBS_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2017, 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.
+ *
+ ***************************************************************************/
+
+/* Roughly based on Heimdal's gssapi.h */
+
+#include <stdint.h>
+#include <stddef.h>
+
+#define GSS_ERROR(status) (status & 0x80000000)
+
+#define GSS_S_COMPLETE 0
+#define GSS_S_FAILURE (0x80000000)
+#define GSS_S_CONTINUE_NEEDED (1ul)
+
+#define GSS_C_QOP_DEFAULT 0
+#define GSS_C_NO_OID ((gss_OID) 0)
+#define GSS_C_NO_NAME ((gss_name_t) 0)
+#define GSS_C_NO_BUFFER ((gss_buffer_t) 0)
+#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0)
+#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0)
+#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0)
+
+#define GSS_C_NULL_OID GSS_C_NO_OID
+
+#define GSS_C_EMPTY_BUFFER {0, NULL}
+
+#define GSS_C_AF_INET 2
+
+#define GSS_C_GSS_CODE 1
+#define GSS_C_MECH_CODE 2
+
+#define GSS_C_DELEG_FLAG 1
+#define GSS_C_MUTUAL_FLAG 2
+#define GSS_C_REPLAY_FLAG 4
+#define GSS_C_CONF_FLAG 16
+#define GSS_C_INTEG_FLAG 32
+
+/*
+ * Expiration time of 2^32-1 seconds means infinite lifetime for a
+ * credential or security context
+ */
+#define GSS_C_INDEFINITE 0xfffffffful
+
+#define GSS_C_NT_HOSTBASED_SERVICE NULL
+
+typedef uint32_t OM_uint32;
+
+typedef OM_uint32 gss_qop_t;
+
+typedef struct gss_buffer_desc_struct {
+  size_t length;
+  void *value;
+} gss_buffer_desc, *gss_buffer_t;
+
+struct gss_cred_id_t_desc_struct;
+typedef struct gss_cred_id_t_desc_struct *gss_cred_id_t;
+typedef const struct gss_cred_id_t_desc_struct *gss_const_cred_id_t;
+
+struct gss_ctx_id_t_desc_struct;
+typedef struct gss_ctx_id_t_desc_struct *gss_ctx_id_t;
+typedef const struct gss_ctx_id_t_desc_struct *gss_const_ctx_id_t;
+
+struct gss_name_t_desc_struct;
+typedef struct gss_name_t_desc_struct *gss_name_t;
+typedef const struct gss_name_t_desc_struct *gss_const_name_t;
+
+typedef struct gss_OID_desc_struct {
+  OM_uint32 length;
+  void      *elements;
+} gss_OID_desc, *gss_OID;
+
+typedef struct gss_channel_bindings_struct {
+  OM_uint32 initiator_addrtype;
+  gss_buffer_desc initiator_address;
+  OM_uint32 acceptor_addrtype;
+  gss_buffer_desc acceptor_address;
+  gss_buffer_desc application_data;
+} *gss_channel_bindings_t;
+
+OM_uint32 gss_release_buffer(OM_uint32 * /*minor_status*/,
+                             gss_buffer_t /*buffer*/);
+
+OM_uint32 gss_init_sec_context(OM_uint32 * /*minor_status*/,
+            gss_const_cred_id_t /*initiator_cred_handle*/,
+            gss_ctx_id_t * /*context_handle*/,
+            gss_const_name_t /*target_name*/,
+            const gss_OID /*mech_type*/,
+            OM_uint32 /*req_flags*/,
+            OM_uint32 /*time_req*/,
+            const gss_channel_bindings_t /*input_chan_bindings*/,
+            const gss_buffer_t /*input_token*/,
+            gss_OID * /*actual_mech_type*/,
+            gss_buffer_t /*output_token*/,
+            OM_uint32 * /*ret_flags*/,
+            OM_uint32 * /*time_rec*/);
+
+OM_uint32 gss_delete_sec_context(OM_uint32 * /*minor_status*/,
+                                 gss_ctx_id_t * /*context_handle*/,
+                                 gss_buffer_t /*output_token*/);
+
+OM_uint32 gss_inquire_context(OM_uint32 * /*minor_status*/,
+                              gss_const_ctx_id_t /*context_handle*/,
+                              gss_name_t * /*src_name*/,
+                              gss_name_t * /*targ_name*/,
+                              OM_uint32 * /*lifetime_rec*/,
+                              gss_OID * /*mech_type*/,
+                              OM_uint32 * /*ctx_flags*/,
+                              int * /*locally_initiated*/,
+                              int * /*open_context*/);
+
+OM_uint32 gss_wrap(OM_uint32 * /*minor_status*/,
+                   gss_const_ctx_id_t /*context_handle*/,
+                   int /*conf_req_flag*/,
+                   gss_qop_t /*qop_req*/,
+                   const gss_buffer_t /*input_message_buffer*/,
+                   int * /*conf_state*/,
+                   gss_buffer_t /*output_message_buffer*/);
+
+OM_uint32 gss_unwrap(OM_uint32 * /*minor_status*/,
+                     gss_const_ctx_id_t /*context_handle*/,
+                     const gss_buffer_t /*input_message_buffer*/,
+                     gss_buffer_t /*output_message_buffer*/,
+                     int * /*conf_state*/,
+                     gss_qop_t * /*qop_state*/);
+
+OM_uint32 gss_seal(OM_uint32 * /*minor_status*/,
+                   gss_ctx_id_t /*context_handle*/,
+                   int /*conf_req_flag*/,
+                   int /*qop_req*/,
+                   gss_buffer_t /*input_message_buffer*/,
+                   int * /*conf_state*/,
+                   gss_buffer_t /*output_message_buffer*/);
+
+OM_uint32 gss_unseal(OM_uint32 * /*minor_status*/,
+                     gss_ctx_id_t /*context_handle*/,
+                     gss_buffer_t /*input_message_buffer*/,
+                     gss_buffer_t /*output_message_buffer*/,
+                     int * /*conf_state*/,
+                     int * /*qop_state*/);
+
+OM_uint32 gss_import_name(OM_uint32 * /*minor_status*/,
+                          const gss_buffer_t /*input_name_buffer*/,
+                          const gss_OID /*input_name_type*/,
+                          gss_name_t * /*output_name*/);
+
+OM_uint32 gss_release_name(OM_uint32 * /*minor_status*/,
+                           gss_name_t * /*input_name*/);
+
+OM_uint32 gss_display_name(OM_uint32 * /*minor_status*/,
+                           gss_const_name_t /*input_name*/,
+                           gss_buffer_t /*output_name_buffer*/,
+                           gss_OID * /*output_name_type*/);
+
+OM_uint32 gss_display_status(OM_uint32 * /*minor_status*/,
+                             OM_uint32 /*status_value*/,
+                             int /*status_type*/,
+                             const gss_OID /*mech_type*/,
+                             OM_uint32 * /*message_context*/,
+                             gss_buffer_t /*status_string*/);
+
+#endif /* HEADER_CURL_GSSAPI_STUBS_H */
+
diff --git a/tests/libtest/testtrace.c b/tests/libtest/testtrace.c
index 62641e15c..5c68b3b1b 100644
--- a/tests/libtest/testtrace.c
+++ b/tests/libtest/testtrace.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,25 +53,27 @@ void libtest_debug_dump(const char *timebuf, const char 
*text, FILE *stream,
     if(!nohex) {
       /* hex not disabled, show it */
       for(c = 0; c < width; c++)
-        if(i+c < size)
-          fprintf(stream, "%02x ", ptr[i+c]);
+        if(i + c < size)
+          fprintf(stream, "%02x ", ptr[i + c]);
         else
           fputs("   ", stream);
     }
 
-    for(c = 0; (c < width) && (i+c < size); c++) {
+    for(c = 0; (c < width) && (i + c < size); c++) {
       /* check for 0D0A; if found, skip past and start a new line of output */
       if(nohex &&
-         (i+c+1 < size) && (ptr[i+c] == 0x0D) && (ptr[i+c+1] == 0x0A)) {
-        i += (c+2-width);
+         (i + c + 1 < size) && (ptr[i + c] == 0x0D) &&
+         (ptr[i + c + 1] == 0x0A)) {
+        i += (c + 2 - width);
         break;
       }
-      fprintf(stream, "%c", ((ptr[i+c] >= 0x20) && (ptr[i+c] < 0x80)) ?
-              ptr[i+c] : '.');
+      fprintf(stream, "%c", ((ptr[i + c] >= 0x20) && (ptr[i + c] < 0x80)) ?
+              ptr[i + c] : '.');
       /* check again for 0D0A, to avoid an extra \n if it's at width */
       if(nohex &&
-         (i+c+2 < size) && (ptr[i+c+1] == 0x0D) && (ptr[i+c+2] == 0x0A)) {
-        i += (c+3-width);
+         (i + c + 2 < size) && (ptr[i + c + 1] == 0x0D) &&
+         (ptr[i + c + 2] == 0x0A)) {
+        i += (c + 3 - width);
         break;
       }
     }
diff --git a/tests/runtests.pl b/tests/runtests.pl
index c67673fbd..66919bcd7 100755
--- a/tests/runtests.pl
+++ b/tests/runtests.pl
@@ -232,6 +232,7 @@ my $has_crypto;     # set if libcurl is built with 
cryptographic support
 my $has_cares;      # set if built with c-ares
 my $has_threadedres;# set if built with threaded resolver
 my $has_psl;        # set if libcurl is built with PSL support
+my $has_ldpreload;  # set if curl is built for systems supporting LD_PRELOAD
 
 # this version is decided by the particular nghttp2 library that is being used
 my $h2cver = "h2c";
@@ -2731,6 +2732,9 @@ sub checksystem {
             $curl =~ s/^(.*)(libcurl.*)/$1/g;
 
             $libcurl = $2;
+            if($curl =~ /linux|bsd|solaris|darwin/) {
+                $has_ldpreload = 1;
+            }
             if($curl =~ /win32|mingw(32|64)/) {
                 # This is a Windows MinGW build or native build, we need to use
                 # Win32-style path.
@@ -3315,6 +3319,11 @@ sub singletest {
                     next;
                 }
             }
+            elsif($1 eq "ld_preload") {
+                if($has_ldpreload && !$debug_build) {
+                    next;
+                }
+            }
             elsif($1 eq "unittest") {
                 if($debug_build) {
                     next;
@@ -3585,9 +3594,9 @@ sub singletest {
 
         for $k (@keywords) {
             chomp $k;
-            if ($disabled_keywords{$k}) {
+            if ($disabled_keywords{lc($k)}) {
                 $why = "disabled by keyword";
-            } elsif ($enabled_keywords{$k}) {
+            } elsif ($enabled_keywords{lc($k)}) {
                 $match = 1;
             }
         }
@@ -3755,6 +3764,13 @@ sub singletest {
 
     # if this section exists, we verify upload
     my @upload = getpart("verify", "upload");
+    if(@upload) {
+      my %hash = getpartattr("verify", "upload");
+      if($hash{'nonewline'}) {
+          # cut off the final newline from the final line of the upload data
+          chomp($upload[$#upload]);
+      }
+    }
 
     # if this section exists, it might be FTP server instructions:
     my @ftpservercmd = getpart("reply", "servercmd");
@@ -3808,23 +3824,25 @@ sub singletest {
         unlink($memdump);
     }
 
-    # create a (possibly-empty) file before starting the test
-    my @inputfile=getpart("client", "file");
-    my %fileattr = getpartattr("client", "file");
-    my $filename=$fileattr{'name'};
-    if(@inputfile || $filename) {
-        if(!$filename) {
-            logmsg "ERROR: section client=>file has no name attribute\n";
-            timestampskippedevents($testnum);
-            return -1;
+    # create (possibly-empty) files before starting the test
+    for my $partsuffix (('', '1', '2', '3', '4')) {
+        my @inputfile=getpart("client", "file".$partsuffix);
+        my %fileattr = getpartattr("client", "file".$partsuffix);
+        my $filename=$fileattr{'name'};
+        if(@inputfile || $filename) {
+            if(!$filename) {
+                logmsg "ERROR: section client=>file has no name attribute\n";
+                timestampskippedevents($testnum);
+                return -1;
+            }
+            my $fileContent = join('', @inputfile);
+            subVariables \$fileContent;
+#            logmsg "DEBUG: writing file " . $filename . "\n";
+            open(OUTFILE, ">$filename");
+            binmode OUTFILE; # for crapage systems, use binary
+            print OUTFILE $fileContent;
+            close(OUTFILE);
         }
-        my $fileContent = join('', @inputfile);
-        subVariables \$fileContent;
-#        logmsg "DEBUG: writing file " . $filename . "\n";
-        open(OUTFILE, ">$filename");
-        binmode OUTFILE; # for crapage systems, use binary
-        print OUTFILE $fileContent;
-        close(OUTFILE);
     }
 
     my %cmdhash = getpartattr("client", "command");
@@ -4289,6 +4307,17 @@ sub singletest {
     if(@upload) {
         # verify uploaded data
         my @out = loadarray("$LOGDIR/upload.$testnum");
+
+        # what parts to cut off from the upload
+        my @strippart = getpart("verify", "strippart");
+        my $strip;
+        for $strip (@strippart) {
+            chomp $strip;
+            for(@out) {
+                eval $strip;
+            }
+        }
+
         $res = compare($testnum, $testname, "upload", address@hidden, 
address@hidden);
         if ($res) {
             return 1;
@@ -5379,10 +5408,10 @@ EOHELP
         $disabled{$1}=$1;
     }
     elsif($ARGV[0] =~ /^!(.+)/) {
-        $disabled_keywords{$1}=$1;
+        $disabled_keywords{lc($1)}=$1;
     }
     elsif($ARGV[0] =~ /^([-[{a-zA-Z].*)/) {
-        $enabled_keywords{$1}=$1;
+        $enabled_keywords{lc($1)}=$1;
     }
     else {
         print "Unknown option: $ARGV[0]\n";
diff --git a/tests/server/fake_ntlm.c b/tests/server/fake_ntlm.c
index 0d1b3e1b6..ca2b438b6 100644
--- a/tests/server/fake_ntlm.c
+++ b/tests/server/fake_ntlm.c
@@ -63,7 +63,8 @@ static char *printable(char *inbuf, size_t inlength)
     inlength = strlen(inbuf);
 
   if(inlength) {
-    outincr = ((inlength/2) < (HEX_STR_LEN+1)) ? HEX_STR_LEN+1 : inlength/2;
+    outincr = ((inlength/2) < (HEX_STR_LEN + 1)) ?
+      HEX_STR_LEN + 1 : inlength/2;
     outsize = inlength + outincr;
   }
   else
@@ -78,7 +79,7 @@ static char *printable(char *inbuf, size_t inlength)
     return outbuf;
   }
 
-  for(i=0; i<inlength; i++) {
+  for(i = 0; i<inlength; i++) {
 
     if(o > outsize - (HEX_STR_LEN + 1)) {
       newsize = outsize + outincr;
@@ -186,7 +187,7 @@ int main(int argc, char *argv[])
   }
 
   filename = test2file(testnum);
-  stream=fopen(filename, "rb");
+  stream = fopen(filename, "rb");
   if(!stream) {
     error = errno;
     logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -204,7 +205,7 @@ int main(int argc, char *argv[])
     }
   }
 
-  stream=fopen(filename, "rb");
+  stream = fopen(filename, "rb");
   if(!stream) {
     error = errno;
     logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -224,7 +225,7 @@ int main(int argc, char *argv[])
 
   while(fgets(buf, sizeof(buf), stdin)) {
     if(strcmp(buf, type1_input) == 0) {
-      stream=fopen(filename, "rb");
+      stream = fopen(filename, "rb");
       if(!stream) {
         error = errno;
         logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -246,7 +247,7 @@ int main(int argc, char *argv[])
       fflush(stdout);
     }
     else if(strncmp(buf, type3_input, strlen(type3_input)) == 0) {
-      stream=fopen(filename, "rb");
+      stream = fopen(filename, "rb");
       if(!stream) {
         error = errno;
         logmsg("fopen() failed with error: %d %s", error, strerror(error));
diff --git a/tests/server/getpart.c b/tests/server/getpart.c
index bb8351bc3..d434ba289 100644
--- a/tests/server/getpart.c
+++ b/tests/server/getpart.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,6 +66,35 @@ curl_wcsdup_callback Curl_cwcsdup = 
(curl_wcsdup_callback)_wcsdup;
 #  pragma warning(default:4232) /* MSVC extension, dllimport identity */
 #endif
 
+
+/*
+ * Curl_convert_clone() returns a malloced copy of the source string (if
+ * returning CURLE_OK), with the data converted to network format. This
+ * function is used by base64 code in libcurl built to support data
+ * conversion. This is a DUMMY VERSION that returns data unmodified - for
+ * use by the test server only.
+ */
+CURLcode Curl_convert_clone(struct Curl_easy *data,
+                            const char *indata,
+                            size_t insize,
+                            char **outbuf);
+CURLcode Curl_convert_clone(struct Curl_easy *data,
+                            const char *indata,
+                            size_t insize,
+                            char **outbuf)
+{
+  char *convbuf;
+  (void)data;
+
+  convbuf = malloc(insize);
+  if(!convbuf)
+    return CURLE_OUT_OF_MEMORY;
+
+  memcpy(convbuf, indata, insize);
+  *outbuf = convbuf;
+  return CURLE_OK;
+}
+
 /*
  * readline()
  *
@@ -250,11 +279,11 @@ int getpart(char **outbuf, size_t *outlen,
             const char *main, const char *sub, FILE *stream)
 {
 # define MAX_TAG_LEN 79
-  char couter[MAX_TAG_LEN+1]; /* current outermost section */
-  char cmain[MAX_TAG_LEN+1];  /* current main section */
-  char csub[MAX_TAG_LEN+1];   /* current sub section */
-  char ptag[MAX_TAG_LEN+1];   /* potential tag */
-  char patt[MAX_TAG_LEN+1];   /* potential attributes */
+  char couter[MAX_TAG_LEN + 1]; /* current outermost section */
+  char cmain[MAX_TAG_LEN + 1];  /* current main section */
+  char csub[MAX_TAG_LEN + 1];   /* current sub section */
+  char ptag[MAX_TAG_LEN + 1];   /* potential tag */
+  char patt[MAX_TAG_LEN + 1];   /* potential attributes */
   char *buffer = NULL;
   char *ptr;
   char *end;
@@ -451,4 +480,3 @@ int getpart(char **outbuf, size_t *outlen,
 
   return error;
 }
-
diff --git a/tests/server/resolve.c b/tests/server/resolve.c
index 34f14e066..4cbdba6ec 100644
--- a/tests/server/resolve.c
+++ b/tests/server/resolve.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -57,11 +57,11 @@
 static bool use_ipv6 = FALSE;
 static const char *ipv_inuse = "IPv4";
 
-const char *serverlogfile=""; /* for a util.c function we don't use */
+const char *serverlogfile = ""; /* for a util.c function we don't use */
 
 int main(int argc, char *argv[])
 {
-  int arg=1;
+  int arg = 1;
   const char *host = NULL;
   int rc = 0;
 
diff --git a/tests/server/rtspd.c b/tests/server/rtspd.c
index 120d65d52..53ffeb6e1 100644
--- a/tests/server/rtspd.c
+++ b/tests/server/rtspd.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -70,11 +70,11 @@ static int serverlogslocked = 0;
 #define REQBUFSIZ 150000
 #define REQBUFSIZ_TXT "149999"
 
-static long prevtestno=-1;    /* previous test number we served */
-static long prevpartno=-1;    /* previous part number we served */
-static bool prevbounce=FALSE; /* instructs the server to increase the part
-                                 number for a test in case the identical
-                                 testno+partno request shows up again */
+static long prevtestno = -1;    /* previous test number we served */
+static long prevpartno = -1;    /* previous part number we served */
+static bool prevbounce = FALSE; /* instructs the server to increase the part
+                                   number for a test in case the identical
+                                   testno+partno request shows up again */
 
 #define RCMD_NORMALREQ 0 /* default request, use the tests file normally */
 #define RCMD_IDLE      1 /* told to sit idle */
@@ -156,7 +156,7 @@ enum {
   DOCNUMBER_NOTHING = -7,
   DOCNUMBER_QUIT    = -6,
   DOCNUMBER_BADCONNECT = -5,
-  DOCNUMBER_INTERNAL= -4,
+  DOCNUMBER_INTERNAL = -4,
   DOCNUMBER_CONNECT = -3,
   DOCNUMBER_WERULEZ = -2,
   DOCNUMBER_404     = -1
@@ -332,7 +332,7 @@ static void restore_signal_handlers(void)
 
 static int ProcessRequest(struct httprequest *req)
 {
-  char *line=&req->reqbuf[req->checkindex];
+  char *line = &req->reqbuf[req->checkindex];
   bool chunked = FALSE;
   static char request[REQUEST_KEYWORD_SIZE];
   static char doc[MAXDOCNAMELEN];
@@ -421,7 +421,7 @@ static int ProcessRequest(struct httprequest *req)
 
       filename = test2file(req->testno);
 
-      stream=fopen(filename, "rb");
+      stream = fopen(filename, "rb");
       if(!stream) {
         error = errno;
         logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -433,7 +433,7 @@ static int ProcessRequest(struct httprequest *req)
       else {
         char *cmd = NULL;
         size_t cmdsize = 0;
-        int num=0;
+        int num = 0;
 
         int rtp_channel = 0;
         int rtp_size = 0;
@@ -500,7 +500,7 @@ static int ProcessRequest(struct httprequest *req)
                 SET_RTP_PKT_LEN(rtp_scratch, rtp_size);
 
                 /* Fill it with junk data */
-                for(i = 0; i < rtp_size; i+= RTP_DATA_SIZE) {
+                for(i = 0; i < rtp_size; i += RTP_DATA_SIZE) {
                   memcpy(rtp_scratch + 4 + i, RTP_DATA, RTP_DATA_SIZE);
                 }
 
@@ -554,8 +554,8 @@ static int ProcessRequest(struct httprequest *req)
           /* if the host name starts with test, the port number used in the
              CONNECT line will be used as test number! */
           char *portp = strchr(doc, ':');
-          if(portp && (*(portp+1) != '\0') && ISDIGIT(*(portp+1)))
-            req->testno = strtol(portp+1, NULL, 10);
+          if(portp && (*(portp + 1) != '\0') && ISDIGIT(*(portp + 1)))
+            req->testno = strtol(portp + 1, NULL, 10);
           else
             req->testno = DOCNUMBER_CONNECT;
         }
@@ -596,7 +596,7 @@ static int ProcessRequest(struct httprequest *req)
     if(got_exit_signal)
       return 1; /* done */
 
-    if((req->cl==0) && strncasecompare("Content-Length:", line, 15)) {
+    if((req->cl == 0) && strncasecompare("Content-Length:", line, 15)) {
       /* If we don't ignore content-length, we read it and we read the whole
          request including the body before we return. If we've been told to
          ignore the content-length, we will return as soon as all headers
@@ -896,10 +896,10 @@ static int send_doc(curl_socket_t sock, struct 
httprequest *req)
   ssize_t written;
   size_t count;
   const char *buffer;
-  char *ptr=NULL;
+  char *ptr = NULL;
   FILE *stream;
-  char *cmd=NULL;
-  size_t cmdsize=0;
+  char *cmd = NULL;
+  size_t cmdsize = 0;
   FILE *dump;
   bool persistant = TRUE;
   bool sendfailure = FALSE;
@@ -988,7 +988,7 @@ static int send_doc(curl_socket_t sock, struct httprequest 
*req)
     if(0 != req->partno)
       snprintf(partbuf, sizeof(partbuf), "data%ld", req->partno);
 
-    stream=fopen(filename, "rb");
+    stream = fopen(filename, "rb");
     if(!stream) {
       error = errno;
       logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -1012,7 +1012,7 @@ static int send_doc(curl_socket_t sock, struct 
httprequest *req)
     }
 
     /* re-open the same file again */
-    stream=fopen(filename, "rb");
+    stream = fopen(filename, "rb");
     if(!stream) {
       error = errno;
       logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -1140,7 +1140,7 @@ static int send_doc(curl_socket_t sock, struct 
httprequest *req)
     char command[32];
     int quarters;
     int num;
-    ptr=cmd;
+    ptr = cmd;
     do {
       if(2 == sscanf(ptr, "%31s %d", command, &num)) {
         if(!strcmp("wait", command)) {
@@ -1194,7 +1194,7 @@ int main(int argc, char *argv[])
   struct httprequest req;
   int rc;
   int error;
-  int arg=1;
+  int arg = 1;
   long pid;
 
   memset(&req, 0, sizeof(req));
diff --git a/tests/server/sockfilt.c b/tests/server/sockfilt.c
index 6695d8486..f13ef208d 100644
--- a/tests/server/sockfilt.c
+++ b/tests/server/sockfilt.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -478,26 +478,26 @@ static void lograw(unsigned char *buffer, ssize_t len)
   ssize_t i;
   unsigned char *ptr = buffer;
   char *optr = data;
-  ssize_t width=0;
+  ssize_t width = 0;
   int left = sizeof(data);
 
-  for(i=0; i<len; i++) {
+  for(i = 0; i<len; i++) {
     switch(ptr[i]) {
     case '\n':
       snprintf(optr, left, "\\n");
       width += 2;
       optr += 2;
-      left-=2;
+      left -= 2;
       break;
     case '\r':
       snprintf(optr, left, "\\r");
       width += 2;
       optr += 2;
-      left-=2;
+      left -= 2;
       break;
     default:
       snprintf(optr, left, "%c", (ISGRAPH(ptr[i]) ||
-                                  ptr[i]==0x20) ?ptr[i]:'.');
+                                  ptr[i] == 0x20) ?ptr[i]:'.');
       width++;
       optr++;
       left--;
@@ -1200,7 +1200,7 @@ static curl_socket_t sockdaemon(curl_socket_t sock,
   int rc;
   int totdelay = 0;
   int maxretr = 10;
-  int delay= 20;
+  int delay = 20;
   int attempt = 0;
   int error = 0;
 
@@ -1343,7 +1343,7 @@ int main(int argc, char *argv[])
   bool juggle_again;
   int rc;
   int error;
-  int arg=1;
+  int arg = 1;
   enum sockmode mode = PASSIVE_LISTEN; /* default */
   const char *addr = NULL;
 
diff --git a/tests/server/sws.c b/tests/server/sws.c
index bff30f212..821497068 100644
--- a/tests/server/sws.c
+++ b/tests/server/sws.c
@@ -81,11 +81,11 @@ static bool is_proxy = FALSE;
 #define REQBUFSIZ 150000
 #define REQBUFSIZ_TXT "149999"
 
-static long prevtestno=-1;    /* previous test number we served */
-static long prevpartno=-1;    /* previous part number we served */
-static bool prevbounce=FALSE; /* instructs the server to increase the part
-                                 number for a test in case the identical
-                                 testno+partno request shows up again */
+static long prevtestno = -1;    /* previous test number we served */
+static long prevpartno = -1;    /* previous part number we served */
+static bool prevbounce = FALSE; /* instructs the server to increase the part
+                                   number for a test in case the identical
+                                   testno+partno request shows up again */
 
 #define RCMD_NORMALREQ 0 /* default request, use the tests file normally */
 #define RCMD_IDLE      1 /* told to sit idle */
@@ -359,7 +359,7 @@ static int parse_servercmd(struct httprequest *req)
 
   filename = test2file(req->testno);
 
-  stream=fopen(filename, "rb");
+  stream = fopen(filename, "rb");
   if(!stream) {
     error = errno;
     logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -372,7 +372,7 @@ static int parse_servercmd(struct httprequest *req)
     char *orgcmd = NULL;
     char *cmd = NULL;
     size_t cmdsize = 0;
-    int num=0;
+    int num = 0;
 
     /* get the custom server control "commands" */
     error = getpart(&orgcmd, &cmdsize, "reply", "servercmd", stream);
@@ -456,7 +456,7 @@ static int parse_servercmd(struct httprequest *req)
 
 static int ProcessRequest(struct httprequest *req)
 {
-  char *line=&req->reqbuf[req->checkindex];
+  char *line = &req->reqbuf[req->checkindex];
   bool chunked = FALSE;
   static char request[REQUEST_KEYWORD_SIZE];
   static char doc[MAXDOCNAMELEN];
@@ -552,7 +552,7 @@ static int ProcessRequest(struct httprequest *req)
       if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
                 doc, &prot_major, &prot_minor) == 3) {
         char *portp = NULL;
-        unsigned long part=0;
+        unsigned long part = 0;
 
         snprintf(logbuf, sizeof(logbuf),
                  "Received a CONNECT %s HTTP/%d.%d request",
@@ -578,18 +578,18 @@ static int ProcessRequest(struct httprequest *req)
           }
           if(*p != ']')
             logmsg("Invalid CONNECT IPv6 address format");
-          else if(*(p+1) != ':')
+          else if(*(p + 1) != ':')
             logmsg("Invalid CONNECT IPv6 port format");
           else
-            portp = p+1;
+            portp = p + 1;
 
           req->testno = part;
         }
         else
           portp = strchr(doc, ':');
 
-        if(portp && (*(portp+1) != '\0') && ISDIGIT(*(portp+1))) {
-          unsigned long ulnum = strtoul(portp+1, NULL, 10);
+        if(portp && (*(portp + 1) != '\0') && ISDIGIT(*(portp + 1))) {
+          unsigned long ulnum = strtoul(portp + 1, NULL, 10);
           if(!ulnum || (ulnum > 65535UL))
             logmsg("Invalid CONNECT port received");
           else
@@ -711,7 +711,7 @@ static int ProcessRequest(struct httprequest *req)
     if(got_exit_signal)
       return 1; /* done */
 
-    if((req->cl==0) && strncasecompare("Content-Length:", line, 15)) {
+    if((req->cl == 0) && strncasecompare("Content-Length:", line, 15)) {
       /* If we don't ignore content-length, we read it and we read the whole
          request including the body before we return. If we've been told to
          ignore the content-length, we will return as soon as all headers
@@ -763,7 +763,20 @@ static int ProcessRequest(struct httprequest *req)
       logmsg("Authorization header found, as required");
   }
 
-  if(!req->digest && strstr(req->reqbuf, "Authorization: Digest")) {
+  if(strstr(req->reqbuf, "Authorization: Negotiate")) {
+    /* Negotiate iterations */
+    static long prev_testno = -1;
+    static long prev_partno = -1;
+    logmsg("Negotiate: prev_testno: %d, prev_partno: %d",
+            prev_testno, prev_partno);
+    if(req->testno != prev_testno) {
+      prev_testno = req->testno;
+      prev_partno = req->partno;
+    }
+    prev_partno += 1;
+    req->partno = prev_partno;
+  }
+  else if(!req->digest && strstr(req->reqbuf, "Authorization: Digest")) {
     /* If the client is passing this Digest-header, we set the part number
        to 1000. Not only to spice up the complexity of this, but to make
        Digest stuff to work in the test suite. */
@@ -858,7 +871,7 @@ static void storerequest(const char *reqbuf, size_t 
totalsize)
   size_t written;
   size_t writeleft;
   FILE *dump;
-  const char *dumpfile=is_proxy?REQUEST_PROXY_DUMP:REQUEST_DUMP;
+  const char *dumpfile = is_proxy?REQUEST_PROXY_DUMP:REQUEST_DUMP;
 
   if(reqbuf == NULL)
     return;
@@ -1044,10 +1057,10 @@ static int send_doc(curl_socket_t sock, struct 
httprequest *req)
   ssize_t written;
   size_t count;
   const char *buffer;
-  char *ptr=NULL;
+  char *ptr = NULL;
   FILE *stream;
-  char *cmd=NULL;
-  size_t cmdsize=0;
+  char *cmd = NULL;
+  size_t cmdsize = 0;
   FILE *dump;
   bool persistant = TRUE;
   bool sendfailure = FALSE;
@@ -1118,7 +1131,7 @@ static int send_doc(curl_socket_t sock, struct 
httprequest *req)
 
     /* select the <data> tag for "normal" requests and the <connect> one
        for CONNECT requests (within the <reply> section) */
-    const char *section= req->connect_request?"connect":"data";
+    const char *section = req->connect_request?"connect":"data";
 
     if(req->partno)
       snprintf(partbuf, sizeof(partbuf), "%s%ld", section, req->partno);
@@ -1127,7 +1140,7 @@ static int send_doc(curl_socket_t sock, struct 
httprequest *req)
 
     logmsg("Send response test%ld section <%s>", req->testno, partbuf);
 
-    stream=fopen(filename, "rb");
+    stream = fopen(filename, "rb");
     if(!stream) {
       error = errno;
       logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -1150,7 +1163,7 @@ static int send_doc(curl_socket_t sock, struct 
httprequest *req)
     }
 
     /* re-open the same file again */
-    stream=fopen(filename, "rb");
+    stream = fopen(filename, "rb");
     if(!stream) {
       error = errno;
       logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -1266,7 +1279,7 @@ static int send_doc(curl_socket_t sock, struct 
httprequest *req)
     char command[32];
     int quarters;
     int num;
-    ptr=cmd;
+    ptr = cmd;
     do {
       if(2 == sscanf(ptr, "%31s %d", command, &num)) {
         if(!strcmp("wait", command)) {
@@ -1436,7 +1449,7 @@ static void http_connect(curl_socket_t *infdp,
   int max_tunnel_idx; /* CTRL or DATA */
   int loop;
   int i;
-  int timeout_count=0;
+  int timeout_count = 0;
 
   /* primary tunnel client endpoint already connected */
   clientfd[CTRL] = *infdp;
@@ -1526,7 +1539,7 @@ static void http_connect(curl_socket_t *infdp,
     if(rc > 0) {
       /* socket action */
       bool tcp_fin_wr;
-      timeout_count=0;
+      timeout_count = 0;
 
       if(got_exit_signal)
         break;
@@ -1974,7 +1987,7 @@ int main(int argc, char *argv[])
   struct httprequest req;
   int rc = 0;
   int error;
-  int arg=1;
+  int arg = 1;
   long pid;
   const char *connecthost = "127.0.0.1";
   const char *socket_type = "IPv4";
@@ -2319,7 +2332,7 @@ int main(int argc, char *argv[])
             logmsg("====> Client disconnect %d", req.connmon);
 
             if(req.connmon) {
-              const char *keepopen="[DISCONNECT]\n";
+              const char *keepopen = "[DISCONNECT]\n";
               storerequest(keepopen, strlen(keepopen));
             }
 
diff --git a/tests/server/tftpd.c b/tests/server/tftpd.c
index df01eb782..a8b565197 100644
--- a/tests/server/tftpd.c
+++ b/tests/server/tftpd.c
@@ -515,7 +515,7 @@ static void read_ahead(struct testcase *test,
     }
     else {
       if(test->rcount) {
-        c=test->rptr[0];
+        c = test->rptr[0];
         test->rptr++;
         test->rcount--;
       }
@@ -571,9 +571,9 @@ static ssize_t write_behind(struct testcase *test, int 
convert)
     char outfile[256];
     snprintf(outfile, sizeof(outfile), "log/upload.%ld", test->testno);
 #ifdef WIN32
-    test->ofile=open(outfile, O_CREAT|O_RDWR|O_BINARY, 0777);
+    test->ofile = open(outfile, O_CREAT|O_RDWR|O_BINARY, 0777);
 #else
-    test->ofile=open(outfile, O_CREAT|O_RDWR, 0777);
+    test->ofile = open(outfile, O_CREAT|O_RDWR, 0777);
 #endif
     if(test->ofile == -1) {
       logmsg("Couldn't create and/or open file %s for upload!", outfile);
@@ -992,7 +992,7 @@ static int do_tftp(struct testcase *test, struct tftphdr 
*tp, ssize_t size)
 
     /* before increasing pointer, make sure it is still within the legal
        space */
-    if((cp+1) < &buf.storage[size]) {
+    if((cp + 1) < &buf.storage[size]) {
       ++cp;
       if(first) {
         /* store the mode since we need it later */
@@ -1074,7 +1074,7 @@ static int parse_servercmd(struct testcase *req)
 
   filename = test2file(req->testno);
 
-  stream=fopen(filename, "rb");
+  stream = fopen(filename, "rb");
   if(!stream) {
     error = errno;
     logmsg("fopen() failed with error: %d %s", error, strerror(error));
@@ -1086,7 +1086,7 @@ static int parse_servercmd(struct testcase *req)
     char *orgcmd = NULL;
     char *cmd = NULL;
     size_t cmdsize = 0;
-    int num=0;
+    int num = 0;
 
     /* get the custom server control "commands" */
     error = getpart(&orgcmd, &cmdsize, "reply", "servercmd", stream);
@@ -1192,7 +1192,7 @@ static int validate_access(struct testcase *test,
       snprintf(partbuf, sizeof(partbuf), "data%ld", partno);
 
     if(file) {
-      FILE *stream=fopen(file, "rb");
+      FILE *stream = fopen(file, "rb");
       if(!stream) {
         error = errno;
         logmsg("fopen() failed with error: %d %s", error, strerror(error));
diff --git a/tests/server/util.c b/tests/server/util.c
index 42e585349..1bbd89a3c 100644
--- a/tests/server/util.c
+++ b/tests/server/util.c
@@ -81,15 +81,15 @@ char *data_to_hex(char *data, size_t len)
   if(len > 255)
     len = 255;
 
-  for(i=0; i < len; i++) {
+  for(i = 0; i < len; i++) {
     if((data[i] >= 0x20) && (data[i] < 0x7f))
       *optr++ = *iptr++;
     else {
       snprintf(optr, 4, "%%%02x", *iptr++);
-      optr+=3;
+      optr += 3;
     }
   }
-  *optr=0; /* in case no sprintf was used */
+  *optr = 0; /* in case no sprintf was used */
 
   return buf;
 }
@@ -189,7 +189,7 @@ void win32_cleanup(void)
 #endif  /* USE_WINSOCK */
 
 /* set by the main code to point to where the test dir is */
-const char *path=".";
+const char *path = ".";
 
 char *test2file(long testno)
 {
diff --git a/tests/unit/unit1300.c b/tests/unit/unit1300.c
index 8ec32a8c9..c64fadef9 100644
--- a/tests/unit/unit1300.c
+++ b/tests/unit/unit1300.c
@@ -145,7 +145,7 @@ UNITTEST_START
    * 3: "new" head's previous will be NULL
    */
 
-  head=llist.head;
+  head = llist.head;
   abort_unless(head, "llist.head is NULL");
   element_next = head->next;
   llist_size = Curl_llist_count(&llist);
diff --git a/tests/unit/unit1301.c b/tests/unit/unit1301.c
index aa8610113..2af60bef4 100644
--- a/tests/unit/unit1301.c
+++ b/tests/unit/unit1301.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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 @@ UNITTEST_START
 int rc;
 
 rc = curl_strequal("iii", "III");
-fail_unless(rc != 0, "return code should be zero");
+fail_unless(rc != 0, "return code should be non-zero");
 
 rc = curl_strequal("iiia", "III");
 fail_unless(rc == 0, "return code should be zero");
diff --git a/tests/unit/unit1302.c b/tests/unit/unit1302.c
index 8dae5aad1..e6f94b24e 100644
--- a/tests/unit/unit1302.c
+++ b/tests/unit/unit1302.c
@@ -30,15 +30,19 @@ static struct Curl_easy *data;
 
 static CURLcode unit_setup(void)
 {
+  int res = CURLE_OK;
+
+  global_init(CURL_GLOBAL_ALL);
   data = curl_easy_init();
   if(!data)
     return CURLE_OUT_OF_MEMORY;
-  return CURLE_OK;
+  return res;
 }
 
 static void unit_stop(void)
 {
   curl_easy_cleanup(data);
+  curl_global_cleanup();
 }
 
 UNITTEST_START
diff --git a/tests/unit/unit1303.c b/tests/unit/unit1303.c
index 143ccd034..75a8e59c2 100644
--- a/tests/unit/unit1303.c
+++ b/tests/unit/unit1303.c
@@ -29,15 +29,19 @@ static struct Curl_easy *data;
 
 static CURLcode unit_setup(void)
 {
+  int res = CURLE_OK;
+
+  global_init(CURL_GLOBAL_ALL);
   data = curl_easy_init();
   if(!data)
     return CURLE_OUT_OF_MEMORY;
-  return CURLE_OK;
+  return res;
 }
 
 static void unit_stop(void)
 {
   curl_easy_cleanup(data);
+  curl_global_cleanup();
 }
 
 /* BASE is just a define to make us fool around with decently large number so
@@ -134,7 +138,7 @@ UNITTEST_START
   data->progress.t_startop.tv_sec = BASE;
   data->progress.t_startop.tv_usec = 0;
 
-  for(i=0; i < sizeof(run)/sizeof(run[0]); i++) {
+  for(i = 0; i < sizeof(run)/sizeof(run[0]); i++) {
     NOW(run[i].now_s, run[i].now_us);
     TIMEOUTS(run[i].timeout_ms, run[i].connecttimeout_ms);
     timeout =  Curl_timeleft(data, &now, run[i].connecting);
diff --git a/tests/unit/unit1305.c b/tests/unit/unit1305.c
index b958d0434..6e4bbb861 100644
--- a/tests/unit/unit1305.c
+++ b/tests/unit/unit1305.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -130,7 +130,7 @@ UNITTEST_START
     key_len = strlen(data_key);
 
     data_node->inuse = 1; /* hash will hold the reference */
-    nodep = Curl_hash_add(&hp, data_key, key_len+1, data_node);
+    nodep = Curl_hash_add(&hp, data_key, key_len + 1, data_node);
     abort_unless(nodep, "insertion into hash failed");
     /* Freeing will now be done by Curl_hash_destroy */
     data_node = NULL;
diff --git a/tests/unit/unit1308.c b/tests/unit/unit1308.c
index 4cd384877..27624a648 100644
--- a/tests/unit/unit1308.c
+++ b/tests/unit/unit1308.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 @@ UNITTEST_START
 
   fail_unless(rc == 0, "curl_formget returned error");
 
-  fail_unless(total_size == 486, "curl_formget got wrong size back");
+  fail_unless(total_size == 488, "curl_formget got wrong size back");
 
   curl_formfree(post);
 
@@ -88,7 +88,7 @@ UNITTEST_START
 
   rc = curl_formget(post, &total_size, print_httppost_callback);
   fail_unless(rc == 0, "curl_formget returned error");
-  fail_unless(total_size == 847, "curl_formget got wrong size back");
+  fail_unless(total_size == 851, "curl_formget got wrong size back");
 
   curl_formfree(post);
 
diff --git a/tests/unit/unit1309.c b/tests/unit/unit1309.c
index 9d1e70d27..c53cbcbce 100644
--- a/tests/unit/unit1309.c
+++ b/tests/unit/unit1309.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2011, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2011, 2017, 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,8 +42,8 @@ static void splayprint(struct Curl_tree * t, int d, char 
output)
   if(t == NULL)
     return;
 
-  splayprint(t->larger, d+1, output);
-  for(i=0; i<d; i++)
+  splayprint(t->larger, d + 1, output);
+  for(i = 0; i<d; i++)
     if(output)
       printf("  ");
 
@@ -52,7 +52,7 @@ static void splayprint(struct Curl_tree * t, int d, char 
output)
            (long)t->key.tv_usec, i);
   }
 
-  for(count=0, node = t->samen; node != t; node = node->samen, count++)
+  for(count = 0, node = t->samen; node != t; node = node->samen, count++)
     ;
 
   if(output) {
@@ -62,7 +62,7 @@ static void splayprint(struct Curl_tree * t, int d, char 
output)
       printf("\n");
   }
 
-  splayprint(t->smaller, d+1, output);
+  splayprint(t->smaller, d + 1, output);
 }
 
 UNITTEST_START
@@ -94,7 +94,7 @@ UNITTEST_START
   splayprint(root, 0, 1);
 
   for(i = 0; i < NUM_NODES; i++) {
-    int rem = (i+7)%NUM_NODES;
+    int rem = (i + 7)%NUM_NODES;
     printf("Tree look:\n");
     splayprint(root, 0, 1);
     printf("remove pointer %d, payload %ld\n", rem,
@@ -119,13 +119,13 @@ UNITTEST_START
     /* add some nodes with the same key */
     for(j = 0; j <= i % 3; j++) {
       size_t payload = key.tv_usec*10 + j;
-      nodes[i*3+j].payload = (void *)payload; /* for simplicity */
-      root = Curl_splayinsert(key, root, &nodes[i*3+j]);
+      nodes[i * 3 + j].payload = (void *)payload; /* for simplicity */
+      root = Curl_splayinsert(key, root, &nodes[i * 3 + j]);
     }
   }
 
   removed = NULL;
-  for(i = 0; i <= 1100; i+= 100) {
+  for(i = 0; i <= 1100; i += 100) {
     printf("Removing nodes not larger than %d\n", i);
     tv_now.tv_usec = i;
     root = Curl_splaygetbest(tv_now, root, &removed);
diff --git a/tests/unit/unit1323.c b/tests/unit/unit1323.c
index 65dd3d287..7bb4cca40 100644
--- a/tests/unit/unit1323.c
+++ b/tests/unit/unit1323.c
@@ -49,7 +49,7 @@ UNITTEST_START
   };
   size_t i;
 
-  for(i=0; i < sizeof(tests)/sizeof(tests[0]); i++) {
+  for(i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
     time_t result = curlx_tvdiff(tests[i].first, tests[i].second);
     if(result != tests[i].result) {
       printf("%d.%06u to %d.%06u got %d, but expected %d\n",
diff --git a/tests/unit/unit1395.c b/tests/unit/unit1395.c
index 13ea97bc4..527f28142 100644
--- a/tests/unit/unit1395.c
+++ b/tests/unit/unit1395.c
@@ -43,7 +43,7 @@ struct dotdot {
 UNITTEST_START
 
   unsigned int i;
-  int fails=0;
+  int fails = 0;
   const struct dotdot pairs[] = {
     { "/a/b/c/./../../g", "/a/g" },
     { "mid/content=5/../6", "mid/6" },
@@ -74,7 +74,7 @@ UNITTEST_START
     { ".", "" },
   };
 
-  for(i=0; i < sizeof(pairs)/sizeof(pairs[0]); i++) {
+  for(i = 0; i < sizeof(pairs)/sizeof(pairs[0]); i++) {
     char *out = Curl_dedotdotify(pairs[i].input);
     abort_unless(out != NULL, "returned NULL!");
 
diff --git a/tests/unit/unit1396.c b/tests/unit/unit1396.c
index f3275fdb6..4dd25b40d 100644
--- a/tests/unit/unit1396.c
+++ b/tests/unit/unit1396.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,13 +25,17 @@ static CURL *hnd;
 
 static CURLcode unit_setup(void)
 {
-  return CURLE_OK;
+  int res = CURLE_OK;
+
+  global_init(CURL_GLOBAL_ALL);
+  return res;
 }
 
 static void unit_stop(void)
 {
   if(hnd)
     curl_easy_cleanup(hnd);
+  curl_global_cleanup();
 }
 
 struct test {
@@ -77,7 +81,7 @@ UNITTEST_START
 
   hnd = curl_easy_init();
   abort_unless(hnd != NULL, "returned NULL!");
-  for(i=0; list1[i].in; i++) {
+  for(i = 0; list1[i].in; i++) {
     int outlen;
     char *out = curl_easy_unescape(hnd,
                                    list1[i].in, list1[i].inlen,
@@ -93,7 +97,7 @@ UNITTEST_START
     curl_free(out);
   }
 
-  for(i=0; list2[i].in; i++) {
+  for(i = 0; list2[i].in; i++) {
     int outlen;
     char *out = curl_easy_escape(hnd, list2[i].in, list2[i].inlen);
     abort_unless(out != NULL, "returned NULL!");
diff --git a/tests/unit/unit1398.c b/tests/unit/unit1398.c
index 095242b07..7e6761c65 100644
--- a/tests/unit/unit1398.c
+++ b/tests/unit/unit1398.c
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <address@hidden>, et al.
+ * Copyright (C) 1998 - 2017, 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,7 @@ UNITTEST_START
 
 int rc;
 char buf[3] = {'b', 'u', 'g'};
-const char *str="bug";
+const char *str = "bug";
 int width = 3;
 char output[24];
 
diff --git a/tests/unit/unit1399.c b/tests/unit/unit1399.c
index 82e0dc27e..91fd3dae1 100644
--- a/tests/unit/unit1399.c
+++ b/tests/unit/unit1399.c
@@ -36,6 +36,20 @@ static void unit_stop(void)
 
 }
 
+/*
+ * Invoke Curl_pgrsTime for TIMER_STARTSINGLE to trigger the behavior that
+ * manages is_t_startransfer_set, but fake the t_startsingle time for purposes
+ * of the test.
+ */
+static void fake_t_startsingle_time(struct Curl_easy *data,
+                                    struct curltime fake_now,
+                                    int seconds_offset)
+{
+  Curl_pgrsTime(data, TIMER_STARTSINGLE);
+  data->progress.t_startsingle.tv_sec = fake_now.tv_sec + seconds_offset;
+  data->progress.t_startsingle.tv_usec = fake_now.tv_usec;
+}
+
 static bool usec_matches_seconds(time_t time_usec, int expected_seconds)
 {
   int time_sec = (int)(time_usec / usec_magnitude);
@@ -46,55 +60,58 @@ static bool usec_matches_seconds(time_t time_usec, int 
expected_seconds)
   return same;
 }
 
+static void expect_timer_seconds(struct Curl_easy *data, int seconds)
+{
+  char msg[64];
+  snprintf(msg, sizeof(msg), "about %d seconds should have passed", seconds);
+  fail_unless(usec_matches_seconds(data->progress.t_nslookup, seconds), msg);
+  fail_unless(usec_matches_seconds(data->progress.t_connect, seconds), msg);
+  fail_unless(usec_matches_seconds(data->progress.t_appconnect, seconds), msg);
+  fail_unless(usec_matches_seconds(data->progress.t_pretransfer, seconds),
+              msg);
+  fail_unless(usec_matches_seconds(data->progress.t_starttransfer, seconds),
+              msg);
+}
+
+/* Scenario: simulate a redirect. When a redirect occurs, t_nslookup,
+ * t_connect, t_appconnect, t_pretransfer, and t_starttransfer are addative.
+ * E.g., if t_starttransfer took 2 seconds initially and took another 1
+ * second for the redirect request, then the resulting t_starttransfer should
+ * be 3 seconds. */
 UNITTEST_START
   struct Curl_easy data;
   struct curltime now = Curl_tvnow();
 
+  data.progress.t_nslookup = 0;
+  data.progress.t_connect = 0;
+  data.progress.t_appconnect = 0;
+  data.progress.t_pretransfer = 0;
   data.progress.t_starttransfer = 0;
   data.progress.t_redirect = 0;
-
-  /*
-  * Set the startsingle time to a second ago. This time is used by
-  * Curl_pgrsTime to calculate how much time the events takes.
-  * t_starttransfer should be updated to reflect the difference from this time
-  * when `Curl_pgrsTime is invoked.
-  */
-  data.progress.t_startsingle.tv_sec = now.tv_sec - 1;
-  data.progress.t_startsingle.tv_usec = now.tv_usec;
-
+  data.progress.start.tv_sec = now.tv_sec - 2;
+  data.progress.start.tv_usec = now.tv_usec;
+  fake_t_startsingle_time(&data, now, -2);
+
+  Curl_pgrsTime(&data, TIMER_NAMELOOKUP);
+  Curl_pgrsTime(&data, TIMER_CONNECT);
+  Curl_pgrsTime(&data, TIMER_APPCONNECT);
+  Curl_pgrsTime(&data, TIMER_PRETRANSFER);
   Curl_pgrsTime(&data, TIMER_STARTTRANSFER);
 
-  fail_unless(usec_matches_seconds(data.progress.t_starttransfer, 1),
-              "about 1 second should have passed");
-
-  /*
-  * Update the startsingle time to a second ago to simulate another second has
-  * passed.
-  * Now t_starttransfer should not be changed, as t_starttransfer has already
-  * occurred and another invocation of `Curl_pgrsTime` for TIMER_STARTTRANSFER
-  * is superfluous.
-  */
-  data.progress.t_startsingle.tv_sec = now.tv_sec - 2;
-  data.progress.t_startsingle.tv_usec = now.tv_usec;
-
-  Curl_pgrsTime(&data, TIMER_STARTTRANSFER);
+  expect_timer_seconds(&data, 2);
 
-  fail_unless(usec_matches_seconds(data.progress.t_starttransfer, 1),
-              "about 1 second should have passed");
-
-  /*
-  * Simulate what happens after a redirect has occurred.
-  *
-  * Since the value of t_starttransfer is set to the value from the first
-  * request, it should be updated when a transfer occurs such that
-  * t_starttransfer is the starttransfer time of the redirect request.
-  */
-  data.progress.t_startsingle.tv_sec = now.tv_sec - 3;
-  data.progress.t_startsingle.tv_usec = now.tv_usec;
+  /* now simulate the redirect */
   data.progress.t_redirect = data.progress.t_starttransfer + 1;
-
+  fake_t_startsingle_time(&data, now, -1);
+
+  Curl_pgrsTime(&data, TIMER_NAMELOOKUP);
+  Curl_pgrsTime(&data, TIMER_CONNECT);
+  Curl_pgrsTime(&data, TIMER_APPCONNECT);
+  Curl_pgrsTime(&data, TIMER_PRETRANSFER);
+  /* ensure t_starttransfer is only set on the first invocation by attempting
+   * to set it twice */
+  Curl_pgrsTime(&data, TIMER_STARTTRANSFER);
   Curl_pgrsTime(&data, TIMER_STARTTRANSFER);
 
-  fail_unless(usec_matches_seconds(data.progress.t_starttransfer, 3),
-              "about 3 second should have passed");
+  expect_timer_seconds(&data, 3);
 UNITTEST_STOP
diff --git a/tests/unit/unit1600.c b/tests/unit/unit1600.c
index 11d718d35..190cf0f0a 100644
--- a/tests/unit/unit1600.c
+++ b/tests/unit/unit1600.c
@@ -28,13 +28,19 @@ static CURL *easy;
 
 static CURLcode unit_setup(void)
 {
+  int res = CURLE_OK;
+
+  global_init(CURL_GLOBAL_ALL);
   easy = curl_easy_init();
-  return easy ? CURLE_OK : CURLE_OUT_OF_MEMORY;
+  if(!easy)
+    return CURLE_OUT_OF_MEMORY;
+  return res;
 }
 
 static void unit_stop(void)
 {
   curl_easy_cleanup(easy);
+  curl_global_cleanup();
 }
 
 UNITTEST_START
diff --git a/tests/unit/unit1605.c b/tests/unit/unit1605.c
index 2fe3a5aca..dd5372225 100644
--- a/tests/unit/unit1605.c
+++ b/tests/unit/unit1605.c
@@ -23,14 +23,23 @@
 
 #include "llist.h"
 
+static CURL *easy;
+
 static CURLcode unit_setup(void)
 {
-  return CURLE_OK;
+  int res = CURLE_OK;
+
+  global_init(CURL_GLOBAL_ALL);
+  easy = curl_easy_init();
+  if(!easy)
+    return CURLE_OUT_OF_MEMORY;
+  return res;
 }
 
 static void unit_stop(void)
 {
-
+  curl_easy_cleanup(easy);
+  curl_global_cleanup();
 }
 
 UNITTEST_START
@@ -45,6 +54,4 @@ UNITTEST_START
   esc = curl_easy_unescape(easy, "%41%41%41%41", -1, &len);
   fail_unless(esc == NULL, "negative string length can't work");
 
-  curl_easy_cleanup(easy);
-
 UNITTEST_STOP
diff --git a/tests/unit/unit1606.c b/tests/unit/unit1606.c
index eca8f3c38..9640ce2c7 100644
--- a/tests/unit/unit1606.c
+++ b/tests/unit/unit1606.c
@@ -24,18 +24,27 @@
 #include "speedcheck.h"
 #include "urldata.h"
 
+static CURL *easy;
+
 static CURLcode unit_setup(void)
 {
-  return CURLE_OK;
+  int res = CURLE_OK;
+
+  global_init(CURL_GLOBAL_ALL);
+  easy = curl_easy_init();
+  if(!easy)
+    return CURLE_OUT_OF_MEMORY;
+  return res;
 }
 
 static void unit_stop(void)
 {
 
+  curl_easy_cleanup(easy);
+  curl_global_cleanup();
 }
 
-static int runawhile(struct Curl_easy *easy,
-                     long time_limit,
+static int runawhile(long time_limit,
                      long speed_limit,
                      curl_off_t speed,
                      int dec)
@@ -66,25 +75,16 @@ static int runawhile(struct Curl_easy *easy,
 }
 
 UNITTEST_START
-{
-  struct Curl_easy *easy = curl_easy_init();
-  abort_unless(easy, "out of memory");
-
-  fail_unless(runawhile(easy, 41, 41, 40, 0) == 41,
+  fail_unless(runawhile(41, 41, 40, 0) == 41,
               "wrong low speed timeout");
-  fail_unless(runawhile(easy, 21, 21, 20, 0) == 21,
+  fail_unless(runawhile(21, 21, 20, 0) == 21,
               "wrong low speed timeout");
-  fail_unless(runawhile(easy, 60, 60, 40, 0) == 60,
+  fail_unless(runawhile(60, 60, 40, 0) == 60,
               "wrong log speed timeout");
-  fail_unless(runawhile(easy, 50, 50, 40, 0) == 50,
+  fail_unless(runawhile(50, 50, 40, 0) == 50,
               "wrong log speed timeout");
-  fail_unless(runawhile(easy, 40, 40, 40, 0) == 99,
+  fail_unless(runawhile(40, 40, 40, 0) == 99,
               "should not time out");
-  fail_unless(runawhile(easy, 10, 50, 100, 2) == 36,
+  fail_unless(runawhile(10, 50, 100, 2) == 36,
               "bad timeout");
-
-  curl_easy_cleanup(easy);
-
-  return 0;
-}
 UNITTEST_STOP
diff --git a/winbuild/MakefileBuild.vc b/winbuild/MakefileBuild.vc
index 36ad4681c..524926a02 100644
--- a/winbuild/MakefileBuild.vc
+++ b/winbuild/MakefileBuild.vc
@@ -267,7 +267,7 @@ GEN_PDB = true
 
 
 !IFDEF EMBED_MANIFEST
-MANIFESTTOOL = mt -manifest $(DIRDIST)\$(PROGRAM_NAME).manifest 
-outputresource:$(DIRDIST)\$(PROGRAM_NAME);1
+MANIFESTTOOL = mt -manifest $(DIRDIST)\bin\$(PROGRAM_NAME).manifest 
-outputresource:$(DIRDIST)\bin\$(PROGRAM_NAME);1
 !ENDIF
 
 # Runtime library configuration

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



reply via email to

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