summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornikita <nikita@NetBSD.org>2020-09-14 20:38:16 +0200
committernikita <nikita@NetBSD.org>2020-09-14 20:38:16 +0200
commitea5627408e41592ac8750032de41b97038811d88 (patch)
tree851007eaf0e4e3ec6b97756e209b512792933b88
parentb8e9ccfa48a0b35e2c9dd560334237e591175be8 (diff)
parent5a1fc8d33808d7b22f57bdf9403cda7ff07b0670 (diff)
downloadgnurl-ea5627408e41592ac8750032de41b97038811d88.tar.gz
gnurl-ea5627408e41592ac8750032de41b97038811d88.tar.bz2
gnurl-ea5627408e41592ac8750032de41b97038811d88.zip
Merge tag 'curl-7_71_1'
curl 7.71.1
-rw-r--r--.azure-pipelines.yml421
-rw-r--r--.cirrus.yml8
-rw-r--r--.dcignore3
-rw-r--r--.gitignore1
-rw-r--r--.mailmap3
-rw-r--r--.travis.yml24
-rw-r--r--CMake/FindNGHTTP3.cmake76
-rw-r--r--CMake/FindNGTCP2.cmake113
-rw-r--r--CMake/FindQUICHE.cmake68
-rw-r--r--CMakeLists.txt102
-rw-r--r--Makefile.am6
-rw-r--r--RELEASE-NOTES317
-rw-r--r--appveyor.yml31
-rwxr-xr-xbuildconf2
-rwxr-xr-xconfigure.ac133
-rw-r--r--docs/CHECKSRC.md4
-rw-r--r--docs/CODE_REVIEW.md168
-rw-r--r--docs/CODE_STYLE.md19
-rw-r--r--docs/DYNBUF.md80
-rw-r--r--docs/EXPERIMENTAL.md1
-rw-r--r--docs/FAQ5
-rw-r--r--docs/GOVERNANCE.md2
-rw-r--r--docs/HELP-US.md17
-rw-r--r--docs/HTTP3.md25
-rw-r--r--docs/INSTALL.cmake3
-rw-r--r--docs/KNOWN_BUGS86
-rw-r--r--docs/Makefile.am5
-rw-r--r--docs/ROADMAP.md20
-rw-r--r--docs/SSL-PROBLEMS.md2
-rw-r--r--docs/THANKS41
-rw-r--r--docs/THANKS-filter1
-rw-r--r--docs/TODO128
-rw-r--r--docs/VERSIONS.md (renamed from docs/VERSIONS)0
-rw-r--r--docs/cmdline-opts/Makefile.inc1
-rw-r--r--docs/cmdline-opts/cert-type.d2
-rw-r--r--docs/cmdline-opts/happy-eyeballs-timeout-ms.d2
-rw-r--r--docs/cmdline-opts/list-only.d2
-rw-r--r--docs/cmdline-opts/page-footer17
-rw-r--r--docs/cmdline-opts/page-header19
-rw-r--r--docs/cmdline-opts/resolve.d2
-rw-r--r--docs/cmdline-opts/retry-all-errors.d19
-rw-r--r--docs/cmdline-opts/sasl-authzid.d3
-rw-r--r--docs/cmdline-opts/ssl-revoke-best-effort.d2
-rw-r--r--docs/cmdline-opts/tls13-ciphers.d2
-rw-r--r--docs/cmdline-opts/user-agent.d4
-rw-r--r--docs/cmdline-opts/version.d64
-rw-r--r--docs/cmdline-opts/write-out.d4
-rw-r--r--docs/examples/.checksrc2
-rw-r--r--docs/examples/Makefile.am4
-rw-r--r--docs/examples/Makefile.inc4
-rw-r--r--docs/examples/anyauthput.c6
-rw-r--r--docs/examples/asiohiper.cpp496
-rw-r--r--docs/examples/curlx.c6
-rw-r--r--docs/examples/ephiperfifo.c8
-rw-r--r--docs/examples/http2-download.c11
-rw-r--r--docs/examples/http2-upload.c29
-rw-r--r--docs/examples/multi-event.c4
-rw-r--r--docs/examples/multi-uv.c4
-rw-r--r--docs/examples/multithread.c4
-rw-r--r--docs/libcurl/ABI.md (renamed from docs/libcurl/ABI)29
-rw-r--r--docs/libcurl/Makefile.am6
-rw-r--r--docs/libcurl/gnurl_easy_escape.34
-rw-r--r--docs/libcurl/gnurl_easy_setopt.314
-rw-r--r--docs/libcurl/gnurl_easy_strerror.32
-rw-r--r--docs/libcurl/gnurl_easy_unescape.34
-rw-r--r--docs/libcurl/gnurl_escape.32
-rw-r--r--docs/libcurl/gnurl_getenv.32
-rw-r--r--docs/libcurl/gnurl_mime_data.34
-rw-r--r--docs/libcurl/gnurl_mime_encoder.34
-rw-r--r--docs/libcurl/gnurl_mime_filedata.38
-rw-r--r--docs/libcurl/gnurl_mime_filename.36
-rw-r--r--docs/libcurl/gnurl_mime_name.34
-rw-r--r--docs/libcurl/gnurl_mime_type.32
-rw-r--r--docs/libcurl/gnurl_multi_strerror.32
-rw-r--r--docs/libcurl/gnurl_share_strerror.32
-rw-r--r--docs/libcurl/gnurl_unescape.32
-rw-r--r--docs/libcurl/gnurl_url_set.34
-rw-r--r--docs/libcurl/gnurl_version.32
-rw-r--r--docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.379
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.373
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.385
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.372
-rw-r--r--docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.373
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.369
-rw-r--r--docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.375
-rw-r--r--docs/libcurl/opts/GNURLINFO_ACTIVESOCKET.320
-rw-r--r--docs/libcurl/opts/GNURLINFO_LOCAL_IP.32
-rw-r--r--docs/libcurl/opts/GNURLINFO_PRIMARY_IP.32
-rw-r--r--docs/libcurl/opts/GNURLINFO_SCHEME.32
-rw-r--r--docs/libcurl/opts/GNURLINFO_SSL_VERIFYRESULT.34
-rw-r--r--docs/libcurl/opts/GNURLMOPT_PIPELINING_SERVER_BL.320
-rw-r--r--docs/libcurl/opts/GNURLMOPT_PIPELINING_SITE_BL.314
-rw-r--r--docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_CAINFO.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_CAPATH.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_COOKIE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_COOKIEFILE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_COOKIEJAR.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_COPYPOSTFIELDS.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_CRLFILE.315
-rw-r--r--docs/libcurl/opts/GNURLOPT_CUSTOMREQUEST.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_DEBUGFUNCTION.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_DOH_URL.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_EGDSOCKET.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_FTPPORT.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_FTP_ACCOUNT.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_HEADERFUNCTION.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_ISSUERCERT.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_KEYPASSWD.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_LOGIN_OPTIONS.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_MAIL_AUTH.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_MAIL_FROM.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_NETRC_FILE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_NOPROXY.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_OPENSOCKETFUNCTION.34
-rw-r--r--docs/libcurl/opts/GNURLOPT_PASSWORD.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PINNEDPUBLICKEY.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PRE_PROXY.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXYPASSWORD.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXYUSERNAME.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_TLS13_CIPHERS.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_RANDOM_FILE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_READFUNCTION.3133
-rw-r--r--docs/libcurl/opts/GNURLOPT_REFERER.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_SASL_AUTHZID.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_SSH_KEYFUNCTION.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_SSH_KNOWNHOSTS.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_SSLCERT.312
-rw-r--r--docs/libcurl/opts/GNURLOPT_SSLCERTTYPE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_SSLENGINE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_SSLKEY.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_SSLKEYTYPE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_SSL_CIPHER_LIST.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_SSL_OPTIONS.37
-rw-r--r--docs/libcurl/opts/GNURLOPT_TLS13_CIPHERS.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_TLSAUTH_PASSWORD.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_TLSAUTH_TYPE.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_TLSAUTH_USERNAME.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_URL.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_USERAGENT.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_USERNAME.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_USERPWD.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_WRITEFUNCTION.32
-rw-r--r--docs/libcurl/opts/GNURLOPT_XOAUTH2_BEARER.32
-rw-r--r--docs/libcurl/opts/Makefile.inc709
-rw-r--r--docs/libcurl/symbols-in-versions9
-rw-r--r--docs/options-in-versions244
-rw-r--r--gnurl-config.in4
-rw-r--r--include/gnurl/curl.h36
-rw-r--r--include/gnurl/curlver.h10
-rw-r--r--include/gnurl/easy.h13
-rw-r--r--include/gnurl/multi.h8
-rw-r--r--include/gnurl/typecheck-gcc.h9
-rw-r--r--lib/Makefile.inc22
-rw-r--r--lib/altsvc.c19
-rw-r--r--lib/altsvc.h1
-rw-r--r--lib/asyn-ares.c57
-rw-r--r--lib/asyn-thread.c43
-rw-r--r--lib/asyn.h10
-rwxr-xr-xlib/checksrc.pl41
-rw-r--r--lib/config-win32.h1
-rw-r--r--lib/conncache.c100
-rw-r--r--lib/conncache.h9
-rw-r--r--lib/connect.c124
-rw-r--r--lib/connect.h4
-rw-r--r--lib/content_encoding.c130
-rw-r--r--lib/content_encoding.h26
-rw-r--r--lib/cookie.c2
-rw-r--r--lib/curl_addrinfo.c97
-rw-r--r--lib/curl_addrinfo.h19
-rw-r--r--lib/curl_config.h.cmake21
-rw-r--r--lib/curl_hmac.h28
-rw-r--r--lib/curl_md5.h20
-rw-r--r--lib/curl_multibyte.c99
-rw-r--r--lib/curl_multibyte.h49
-rw-r--r--lib/curl_ntlm_core.c17
-rw-r--r--lib/curl_ntlm_core.h6
-rw-r--r--lib/curl_ntlm_wb.c67
-rw-r--r--lib/curl_path.c4
-rw-r--r--lib/curl_sasl.c18
-rw-r--r--lib/curl_setup.h23
-rw-r--r--lib/curl_setup_once.h4
-rw-r--r--lib/curl_sspi.c16
-rw-r--r--lib/curl_threads.c4
-rw-r--r--lib/curlx.h12
-rw-r--r--lib/dict.c3
-rw-r--r--lib/doh.c128
-rw-r--r--lib/doh.h21
-rw-r--r--lib/dotdot.c10
-rw-r--r--lib/dynbuf.c227
-rw-r--r--lib/dynbuf.h63
-rw-r--r--lib/easy.c50
-rw-r--r--lib/easyif.h2
-rw-r--r--lib/escape.c78
-rw-r--r--lib/escape.h11
-rw-r--r--lib/file.c2
-rw-r--r--lib/formdata.c20
-rw-r--r--lib/formdata.h6
-rw-r--r--lib/ftp.c82
-rw-r--r--lib/getinfo.c8
-rw-r--r--lib/gopher.c2
-rw-r--r--lib/hmac.c17
-rw-r--r--lib/hostasyn.c10
-rw-r--r--lib/hostip.c100
-rw-r--r--lib/hostip.h22
-rw-r--r--lib/hostip4.c16
-rw-r--r--lib/hostip6.c22
-rw-r--r--lib/http.c811
-rw-r--r--lib/http.h48
-rw-r--r--lib/http2.c223
-rw-r--r--lib/http2.h2
-rw-r--r--lib/http_chunks.c49
-rw-r--r--lib/http_digest.c10
-rw-r--r--lib/http_digest.h2
-rw-r--r--lib/http_negotiate.c19
-rw-r--r--lib/http_negotiate.h6
-rw-r--r--lib/http_ntlm.c14
-rw-r--r--lib/http_ntlm.h6
-rw-r--r--lib/http_proxy.c173
-rw-r--r--lib/http_proxy.h3
-rw-r--r--lib/idn_win32.c10
-rw-r--r--lib/if2ip.c13
-rw-r--r--lib/imap.c16
-rw-r--r--lib/ldap.c67
-rw-r--r--lib/md4.c15
-rw-r--r--lib/md5.c22
-rw-r--r--lib/mime.c30
-rw-r--r--lib/mime.h44
-rw-r--r--lib/mprintf.c85
-rw-r--r--lib/mqtt.c5
-rw-r--r--lib/multi.c151
-rw-r--r--lib/multiif.h2
-rw-r--r--lib/nwlib.c39
-rw-r--r--lib/openldap.c14
-rw-r--r--lib/pingpong.c22
-rw-r--r--lib/pingpong.h9
-rw-r--r--lib/pop3.c12
-rw-r--r--lib/progress.c6
-rw-r--r--lib/quic.h4
-rw-r--r--lib/rtsp.c135
-rw-r--r--lib/select.c136
-rw-r--r--lib/select.h8
-rw-r--r--lib/sendf.c38
-rw-r--r--lib/setopt.c128
-rw-r--r--lib/setopt.h4
-rw-r--r--lib/setup-os400.h8
-rw-r--r--lib/setup-vms.h8
-rw-r--r--lib/sha256.c12
-rw-r--r--lib/share.c8
-rw-r--r--lib/smb.c4
-rw-r--r--lib/smtp.c9
-rw-r--r--lib/socks.c63
-rw-r--r--lib/socks_gssapi.c4
-rw-r--r--lib/socks_sspi.c6
-rw-r--r--lib/strerror.c2
-rw-r--r--lib/strtok.c4
-rw-r--r--lib/telnet.c4
-rw-r--r--lib/tftp.c74
-rw-r--r--lib/transfer.c98
-rw-r--r--lib/url.c471
-rw-r--r--lib/url.h7
-rw-r--r--lib/urlapi.c15
-rw-r--r--lib/urldata.h193
-rw-r--r--lib/vauth/cleartext.c5
-rw-r--r--lib/vauth/cram.c4
-rw-r--r--lib/vauth/digest.c2
-rw-r--r--lib/vauth/digest_sspi.c21
-rw-r--r--lib/vauth/krb5_sspi.c11
-rw-r--r--lib/vauth/ntlm.c5
-rw-r--r--lib/vauth/ntlm_sspi.c8
-rw-r--r--lib/vauth/spnego_sspi.c8
-rw-r--r--lib/vauth/vauth.c6
-rw-r--r--lib/vquic/ngtcp2.c372
-rw-r--r--lib/vquic/ngtcp2.h1
-rw-r--r--lib/vquic/quiche.c70
-rw-r--r--lib/vquic/vquic.c85
-rw-r--r--lib/vquic/vquic.h34
-rw-r--r--lib/vssh/libssh2.c299
-rw-r--r--lib/vssh/ssh.h6
-rw-r--r--lib/vssh/wolfssh.c8
-rw-r--r--lib/vtls/bearssl.c2
-rw-r--r--lib/vtls/gskit.c12
-rw-r--r--lib/vtls/gtls.c25
-rw-r--r--lib/vtls/keylog.c156
-rw-r--r--lib/vtls/keylog.h56
-rw-r--r--lib/vtls/mbedtls.c16
-rw-r--r--lib/vtls/mesalink.c7
-rw-r--r--lib/vtls/nss.c6
-rw-r--r--lib/vtls/openssl.c700
-rw-r--r--lib/vtls/schannel.c465
-rw-r--r--lib/vtls/schannel_verify.c22
-rw-r--r--lib/vtls/sectransp.c70
-rw-r--r--lib/vtls/vtls.c88
-rw-r--r--lib/vtls/vtls.h35
-rw-r--r--lib/vtls/wolfssl.c174
-rw-r--r--lib/x509asn1.c75
-rw-r--r--lib/x509asn1.h71
-rw-r--r--libgnurl.pc.in2
-rw-r--r--packages/OS400/makefile.sh2
-rw-r--r--packages/vms/build_vms.com2
-rwxr-xr-xscripts/copyright.pl17
-rwxr-xr-xscripts/release-notes.pl2
-rwxr-xr-xscripts/travis/script.sh11
-rw-r--r--src/Makefile.inc6
-rw-r--r--src/tool_cb_hdr.c30
-rw-r--r--src/tool_cfgable.c5
-rw-r--r--src/tool_cfgable.h15
-rw-r--r--src/tool_formparse.c43
-rw-r--r--src/tool_formparse.h17
-rw-r--r--src/tool_getparam.c33
-rw-r--r--src/tool_getpass.c4
-rw-r--r--src/tool_help.c31
-rw-r--r--src/tool_main.c8
-rw-r--r--src/tool_metalink.c79
-rw-r--r--src/tool_metalink.h52
-rw-r--r--src/tool_operate.c145
-rw-r--r--src/tool_operate.h6
-rw-r--r--src/tool_paramhlp.c2
-rw-r--r--src/tool_parsecfg.c6
-rw-r--r--src/tool_setopt.c61
-rw-r--r--src/tool_setopt.h40
-rw-r--r--src/tool_urlglob.c77
-rw-r--r--src/tool_urlglob.h20
-rw-r--r--src/tool_vms.c8
-rw-r--r--src/tool_writeout.c2
-rw-r--r--tests/CMakeLists.txt26
-rw-r--r--tests/FILEFORMAT.md161
-rw-r--r--tests/Makefile.am9
-rwxr-xr-xtests/badsymbols.pl.in6
-rw-r--r--tests/data/Makefile.inc36
-rw-r--r--tests/data/test10342
-rw-r--r--tests/data/test10352
-rw-r--r--tests/data/test10842
-rw-r--r--tests/data/test10852
-rw-r--r--tests/data/test10971
-rw-r--r--tests/data/test116878
-rw-r--r--tests/data/test11772
-rw-r--r--tests/data/test117855
-rw-r--r--tests/data/test117943
-rw-r--r--tests/data/test12342
-rw-r--r--tests/data/test12362
-rw-r--r--tests/data/test12388
-rw-r--r--tests/data/test12449
-rw-r--r--tests/data/test12482
-rw-r--r--tests/data/test12492
-rw-r--r--tests/data/test12602
-rw-r--r--tests/data/test12632
-rw-r--r--tests/data/test12692
-rw-r--r--tests/data/test129656
-rw-r--r--tests/data/test13404
-rw-r--r--tests/data/test13414
-rw-r--r--tests/data/test14092
-rw-r--r--tests/data/test14102
-rw-r--r--tests/data/test14272
-rw-r--r--tests/data/test14462
-rw-r--r--tests/data/test14472
-rw-r--r--tests/data/test14532
-rw-r--r--tests/data/test146062
-rw-r--r--tests/data/test15082
-rw-r--r--tests/data/test153943
-rw-r--r--tests/data/test15504
-rw-r--r--tests/data/test155414
-rw-r--r--tests/data/test163056
-rw-r--r--tests/data/test163187
-rw-r--r--tests/data/test1632105
-rw-r--r--tests/data/test163397
-rw-r--r--tests/data/test19014
-rw-r--r--tests/data/test190965
-rw-r--r--tests/data/test191068
-rw-r--r--tests/data/test20042
-rw-r--r--tests/data/test20362
-rw-r--r--tests/data/test20471
-rw-r--r--tests/data/test2192
-rw-r--r--tests/data/test2882
-rw-r--r--tests/data/test3021
-rw-r--r--tests/data/test3332
-rw-r--r--tests/data/test34660
-rw-r--r--tests/data/test5012
-rw-r--r--tests/data/test5042
-rw-r--r--tests/data/test5095
-rw-r--r--tests/data/test5432
-rw-r--r--tests/data/test552bin142941 -> 142947 bytes
-rw-r--r--tests/data/test5581
-rw-r--r--tests/data/test5822
-rw-r--r--tests/data/test5832
-rw-r--r--tests/data/test6002
-rw-r--r--tests/data/test6012
-rw-r--r--tests/data/test6022
-rw-r--r--tests/data/test6032
-rw-r--r--tests/data/test6042
-rw-r--r--tests/data/test6052
-rw-r--r--tests/data/test6062
-rw-r--r--tests/data/test6072
-rw-r--r--tests/data/test6082
-rw-r--r--tests/data/test6092
-rw-r--r--tests/data/test6102
-rw-r--r--tests/data/test6112
-rw-r--r--tests/data/test6122
-rw-r--r--tests/data/test6134
-rw-r--r--tests/data/test6144
-rw-r--r--tests/data/test6152
-rw-r--r--tests/data/test6162
-rw-r--r--tests/data/test6172
-rw-r--r--tests/data/test6182
-rw-r--r--tests/data/test6192
-rw-r--r--tests/data/test6202
-rw-r--r--tests/data/test6212
-rw-r--r--tests/data/test6222
-rw-r--r--tests/data/test6232
-rw-r--r--tests/data/test6242
-rw-r--r--tests/data/test6252
-rw-r--r--tests/data/test6262
-rw-r--r--tests/data/test6282
-rw-r--r--tests/data/test6292
-rw-r--r--tests/data/test6302
-rw-r--r--tests/data/test6312
-rw-r--r--tests/data/test6322
-rw-r--r--tests/data/test6332
-rw-r--r--tests/data/test6342
-rw-r--r--tests/data/test6352
-rw-r--r--tests/data/test6362
-rw-r--r--tests/data/test6372
-rw-r--r--tests/data/test6382
-rw-r--r--tests/data/test6392
-rw-r--r--tests/data/test6402
-rw-r--r--tests/data/test6412
-rw-r--r--tests/data/test6422
-rw-r--r--tests/data/test6562
-rw-r--r--tests/data/test6642
-rw-r--r--tests/data/test6652
-rw-r--r--tests/data/test755
-rw-r--r--tests/data/test762
-rw-r--r--tests/data/test89550
-rw-r--r--tests/data/test89638
-rw-r--r--tests/data/test9701
-rw-r--r--tests/data/test97125
-rw-r--r--tests/libtest/.checksrc1
-rw-r--r--tests/libtest/CMakeLists.txt82
-rw-r--r--tests/libtest/Makefile.am5
-rw-r--r--tests/libtest/Makefile.inc55
-rw-r--r--tests/libtest/lib1156.c10
-rw-r--r--tests/libtest/lib1514.c4
-rw-r--r--tests/libtest/lib1560.c37
-rw-r--r--tests/libtest/lib1900.c38
-rw-r--r--tests/libtest/lib1910.c47
-rw-r--r--tests/libtest/lib509.c63
-rw-r--r--tests/libtest/lib543.c14
-rw-r--r--tests/libtest/lib547.c2
-rw-r--r--tests/libtest/lib553.c4
-rw-r--r--tests/libtest/lib576.c12
-rw-r--r--tests/libtest/lib582.c12
-rw-r--r--tests/libtest/lib651.c4
-rwxr-xr-xtests/libtest/mk-lib1521.pl5
-rwxr-xr-xtests/libtest/test613.pl20
-rwxr-xr-xtests/libtest/test75.pl34
-rwxr-xr-xtests/manpage-scan.pl.in4
-rw-r--r--tests/options-scan.pl120
-rw-r--r--tests/runtests.12
-rwxr-xr-xtests/runtests.pl.in446
-rwxr-xr-xtests/secureserver.pl.in2
-rw-r--r--tests/server/CMakeLists.txt3
-rw-r--r--tests/server/Makefile.inc10
-rw-r--r--tests/server/sockfilt.c18
-rw-r--r--tests/server/sws.c76
-rw-r--r--tests/server/tftpd.c14
-rw-r--r--tests/server/util.c38
-rw-r--r--tests/server/util.h7
-rw-r--r--tests/sshserver.pl.in2
-rw-r--r--tests/unit/CMakeLists.txt18
-rw-r--r--tests/unit/unit1305.c27
-rw-r--r--tests/unit/unit1309.c4
-rw-r--r--tests/unit/unit1604.c7
-rw-r--r--tests/unit/unit1608.c6
-rw-r--r--tests/unit/unit1620.c6
-rw-r--r--tests/unit/unit1650.c5
-rw-r--r--tests/unit/unit1654.c37
491 files changed, 10013 insertions, 6411 deletions
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 29f278c65..1435bf1e1 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -44,100 +44,43 @@ stages:
- stage: linux
dependsOn: []
jobs:
- - job: vanilla
- displayName: ubuntu default
- timeoutInMinutes: 20
- pool:
- vmImage: 'ubuntu-latest'
- steps:
- - script: sudo apt install stunnel4 python-impacket
- displayName: 'apt install'
-
- - script: ./buildconf && ./configure --enable-debug --enable-werror
- displayName: 'configure debug'
-
- - script: make
- displayName: 'make'
-
- - script: make test-nonflaky
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: ""
-
- - job: disable_ipv6
- displayName: ubuntu w/o IPv6
- timeoutInMinutes: 20
- pool:
- vmImage: 'ubuntu-latest'
- steps:
- - script: sudo apt install stunnel4 python-impacket
- displayName: 'apt install'
-
- - script: ./buildconf && ./configure --disable-ipv6
- displayName: 'configure disable ipv6'
-
- - script: make
- displayName: 'make'
-
- - script: make test-nonflaky
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: ""
-
- - job: disable_http_smtp_imap
- displayName: ubuntu w/o HTTP/SMTP/IMAP
- timeoutInMinutes: 20
- pool:
- vmImage: 'ubuntu-latest'
- steps:
- - script: sudo apt install stunnel4 python-impacket
- displayName: 'apt install'
-
- - script: ./buildconf && ./configure --disable-http --disable-smtp --disable-imap
- displayName: 'configure disable http/smtp/imap'
-
- - script: make
- displayName: 'make'
-
- - script: make test-nonflaky
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
-
- - job: disable_thredres
- displayName: ubuntu sync resolver
- timeoutInMinutes: 20
- pool:
- vmImage: 'ubuntu-latest'
- steps:
- - script: sudo apt install stunnel4 python-impacket
- displayName: 'apt install'
-
- - script: ./buildconf && ./configure --disable-threaded-resolver
- displayName: 'configure disable threaded-resolver'
-
- - script: make
- displayName: 'make'
-
- - script: make test-nonflaky
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: ""
-
- - job: http_only
- displayName: ubuntu HTTP only
- timeoutInMinutes: 20
+ - job: ubuntu
+ # define defaults to make sure variables are always expanded/replaced
+ variables:
+ install: ''
+ configure: ''
+ tflags: ''
+ timeoutInMinutes: 60
pool:
vmImage: 'ubuntu-latest'
- steps:
- - script: sudo apt install stunnel4 python-impacket
+ strategy:
+ matrix:
+ default:
+ name: default
+ configure: --enable-debug --enable-werror
+ disable_ipv6:
+ name: w/o IPv6
+ configure: --disable-ipv6
+ disable_http_smtp_imap:
+ name: w/o HTTP/SMTP/IMAP
+ configure: --disable-http --disable-smtp --disable-imap
+ disable_thredres:
+ name: sync resolver
+ configure: --disable-threaded-resolver
+ http_only:
+ name: HTTP only
+ configure: --disable-dict --disable-file --disable-ftp --disable-gopher --disable-imap --disable-ldap --disable-pop3 --disable-rtmp --disable-rtsp --disable-scp --disable-sftp --disable-smb --disable-smtp --disable-telnet --disable-tftp
+ torture:
+ name: torture
+ install: libnghttp2-dev
+ configure: --enable-debug --disable-shared --disable-threaded-resolver --enable-alt-svc
+ tflags: -n -t --shallow=40 !FTP
+ steps:
+ - script: sudo apt-get update && sudo apt-get install -y stunnel4 python-impacket $(install)
displayName: 'apt install'
- - script: ./buildconf && ./configure --disable-dict --disable-file --disable-ftp --disable-gopher --disable-imap --disable-ldap --disable-pop3 --disable-rtmp --disable-rtsp --disable-scp --disable-sftp --disable-smb --disable-smtp --disable-telnet --disable-tftp
- displayName: 'configure disable non-http'
+ - script: ./buildconf && ./configure $(configure)
+ displayName: 'configure $(name)'
- script: make
displayName: 'make'
@@ -146,30 +89,7 @@ stages:
displayName: 'test'
env:
AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: ""
-
-- stage: linux_torture
- dependsOn: linux
- jobs:
- - job: torture
- displayName: ubuntu torture tests
- timeoutInMinutes: 60
- pool:
- vmImage: 'ubuntu-latest'
- steps:
- - script: sudo apt install stunnel4 python-impacket libnghttp2-dev
- displayName: 'apt install'
-
- - script: ./buildconf && ./configure --enable-debug --disable-shared --disable-threaded-resolver --enable-alt-svc
- displayName: 'configure torture'
-
- - script: make
- displayName: 'make'
-
- - script: make test-nonflaky
- displayName: 'torture test'
- env:
- TFLAGS: "-n -t --shallow=40 !FTP"
+ TFLAGS: "$(tflags)"
##########################################
### Windows jobs below
@@ -180,214 +100,91 @@ stages:
variables:
agent.preferPowerShellOnContainers: true
jobs:
- - job: windows_msys2_mingw32_debug_openssl
- displayName: msys2 mingw32 debug openssl
- timeoutInMinutes: 90
- pool:
- vmImage: 'windows-2019'
- container:
- image: mback2k/curl-docker-winbuildenv-msys2-mingw32:ltsc2019
- env:
- MSYSTEM: MINGW32
- MSYS2_PATH_TYPE: inherit
- steps:
- - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && ./configure --host=i686-w64-mingw32 --build=i686-w64-mingw32 --enable-debug --enable-werror"
- displayName: 'configure debug'
-
- - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make"
- displayName: 'make'
-
- - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make test-nonflaky"
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "~1056 ~1299"
-
- - job: windows_msys2_mingw64_debug_openssl
- displayName: msys2 mingw64 debug openssl
- timeoutInMinutes: 90
- pool:
- vmImage: 'windows-2019'
- container:
- image: mback2k/curl-docker-winbuildenv-msys2-mingw64:ltsc2019
- env:
- MSYSTEM: MINGW64
- MSYS2_PATH_TYPE: inherit
- steps:
- - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && ./configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --enable-debug --enable-werror"
- displayName: 'configure debug'
-
- - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make"
- displayName: 'make'
-
- - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make test-nonflaky"
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "~1056 ~1299"
-
- - job: windows_msys1_mingw_debug_openssl
- displayName: msys1 mingw debug openssl
- timeoutInMinutes: 90
- pool:
- vmImage: 'windows-2019'
- container:
- image: mback2k/curl-docker-winbuildenv-msys1-mingw:ltsc2019
- steps:
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && ./configure --host=i686-pc-mingw32 --build=i686-pc-mingw32 --prefix=/mingw --enable-debug"
- displayName: 'configure debug'
-
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make"
- displayName: 'make'
-
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make test-nonflaky"
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "~203 ~1056 ~1143"
-
- - job: windows_msys1_mingw32_debug_openssl
- displayName: msys1 mingw32 debug openssl
+ - job: windows
+ # define defaults to make sure variables are always expanded/replaced
+ variables:
+ container_img: ''
+ container_cmd: ''
+ configure: ''
+ tflags: ''
timeoutInMinutes: 90
pool:
vmImage: 'windows-2019'
+ strategy:
+ matrix:
+ msys2_mingw32_debug_openssl:
+ name: 32-bit OpenSSL and MQTT
+ container_img: mback2k/curl-docker-winbuildenv-msys2-mingw32:ltsc2019
+ container_cmd: C:\msys64\usr\bin\sh
+ configure: --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-debug --enable-werror --enable-mqtt
+ tflags: ~1056 ~1299
+ msys2_mingw64_debug_openssl:
+ name: 64-bit OpenSSL and MQTT
+ container_img: mback2k/curl-docker-winbuildenv-msys2-mingw64:ltsc2019
+ container_cmd: C:\msys64\usr\bin\sh
+ configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-debug --enable-werror --enable-mqtt
+ tflags: ~1056 ~1299
+ msys1_mingw_debug_openssl:
+ name: 32-bit OpenSSL (legacy)
+ container_img: mback2k/curl-docker-winbuildenv-msys1-mingw:ltsc2019
+ container_cmd: C:\MinGW\msys\1.0\bin\sh
+ configure: --host=i686-pc-mingw32 --build=i686-pc-mingw32 --prefix=/mingw --enable-debug
+ tflags: ~203 ~1056 ~1143
+ msys1_mingw32_debug_openssl:
+ name: 32-bit OpenSSL w/o zlib
+ container_img: mback2k/curl-docker-winbuildenv-msys1-mingw32:ltsc2019
+ container_cmd: C:\MinGW\msys\1.0\bin\sh
+ configure: --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-debug --enable-werror --without-zlib
+ tflags: ~203 ~1056 ~1143 ~1299
+ msys1_mingw64_debug_openssl:
+ name: 64-bit OpenSSL w/o zlib
+ container_img: mback2k/curl-docker-winbuildenv-msys1-mingw64:ltsc2019
+ container_cmd: C:\MinGW\msys\1.0\bin\sh
+ configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-debug --enable-werror --without-zlib
+ tflags: ~203 ~1056 ~1143 ~1299
+ msys2_mingw32_debug_schannel:
+ name: 32-bit Schannel/SSPI/WinIDN
+ container_img: mback2k/curl-docker-winbuildenv-msys2-mingw32:ltsc2019
+ container_cmd: C:\msys64\usr\bin\sh
+ configure: --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-debug --enable-werror --enable-sspi --without-ssl --with-schannel --with-winidn
+ tflags: ~165 ~310 ~1013 ~1056 ~1299 ~1448 ~2034 ~2037 ~2041 ~2046 ~2047 ~3000 ~3001
+ msys2_mingw64_debug_schannel:
+ name: 64-bit Schannel/SSPI/WinIDN
+ container_img: mback2k/curl-docker-winbuildenv-msys2-mingw64:ltsc2019
+ container_cmd: C:\msys64\usr\bin\sh
+ configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-debug --enable-werror --enable-sspi --without-ssl --with-schannel --with-winidn
+ tflags: ~165 ~310 ~1013 ~1056 ~1299 ~1448 ~2034 ~2037 ~2041 ~2046 ~2047 ~3000 ~3001
+ msys1_mingw_debug_schannel:
+ name: 32-bit Schannel/SSPI/WinIDN (legacy)
+ container_img: mback2k/curl-docker-winbuildenv-msys1-mingw:ltsc2019
+ container_cmd: C:\MinGW\msys\1.0\bin\sh
+ configure: --host=i686-pc-mingw32 --build=i686-pc-mingw32 --prefix=/mingw --enable-debug --enable-sspi --without-ssl --with-schannel --with-winidn
+ tflags: ~203 ~305 ~310 ~311 ~312 ~313 ~404 ~1013 ~1056 ~1143 ~2034 ~2035 ~2037 ~2038 ~2041 ~2042 ~2048 ~3000 ~3001
+ msys1_mingw32_debug_schannel:
+ name: 32-bit Schannel/SSPI/WinIDN w/o zlib
+ container_img: mback2k/curl-docker-winbuildenv-msys1-mingw32:ltsc2019
+ container_cmd: C:\MinGW\msys\1.0\bin\sh
+ configure: --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-debug --enable-werror --enable-sspi --without-ssl --with-schannel --with-winidn --without-zlib
+ tflags: ~203 ~310 ~1013 ~1056 ~1143 ~1299 ~2034 ~2037 ~2041 ~3000 ~3001
+ msys1_mingw64_debug_schannel:
+ name: 64-bit Schannel/SSPI/WinIDN w/o zlib
+ container_img: mback2k/curl-docker-winbuildenv-msys1-mingw64:ltsc2019
+ container_cmd: C:\MinGW\msys\1.0\bin\sh
+ configure: --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-debug --enable-werror --enable-sspi --without-ssl --with-schannel --with-winidn --without-zlib
+ tflags: ~203 ~310 ~1013 ~1056 ~1143 ~1299 ~2034 ~2037 ~2041 ~3000 ~3001
container:
- image: mback2k/curl-docker-winbuildenv-msys1-mingw32:ltsc2019
- steps:
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && ./configure --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-debug --enable-werror --without-zlib --enable-mqtt"
- displayName: 'configure debug without zlib'
-
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make"
- displayName: 'make'
-
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make test-nonflaky"
- displayName: 'test'
+ image: $(container_img)
env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "~203 ~1056 ~1143 ~1299"
-
- - job: windows_msys1_mingw64_debug_openssl
- displayName: msys1 mingw64 debug openssl
- timeoutInMinutes: 90
- pool:
- vmImage: 'windows-2019'
- container:
- image: mback2k/curl-docker-winbuildenv-msys1-mingw64:ltsc2019
- steps:
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && ./configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-debug --enable-werror --without-zlib"
- displayName: 'configure debug without zlib'
-
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make"
- displayName: 'make'
-
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make test-nonflaky"
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "~203 ~1056 ~1143 ~1299"
-
- - job: windows_msys2_mingw32_debug_schannel
- displayName: msys2 mingw32 debug schannel
- timeoutInMinutes: 90
- pool:
- vmImage: 'windows-2019'
- container:
- image: mback2k/curl-docker-winbuildenv-msys2-mingw32:ltsc2019
- env:
- MSYSTEM: MINGW32
MSYS2_PATH_TYPE: inherit
steps:
- - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && ./configure --host=i686-w64-mingw32 --build=i686-w64-mingw32 --enable-debug --enable-werror --enable-sspi --without-ssl --with-schannel --with-winidn"
- displayName: 'configure debug with sspi/schannel/winidn'
-
- - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make"
- displayName: 'make'
-
- - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make test-nonflaky"
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "~165 ~310 ~1013 ~1056 ~1299 ~1448 ~2034 ~2037 ~2041 ~2046 ~2047 ~3000 ~3001"
-
- - job: windows_msys2_mingw64_debug_schannel
- displayName: msys2 mingw64 debug schannel
- timeoutInMinutes: 90
- pool:
- vmImage: 'windows-2019'
- container:
- image: mback2k/curl-docker-winbuildenv-msys2-mingw64:ltsc2019
- env:
- MSYSTEM: MINGW64
- MSYS2_PATH_TYPE: inherit
- steps:
- - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && ./configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --enable-debug --enable-werror --enable-sspi --without-ssl --with-schannel --with-winidn"
- displayName: 'configure debug with sspi/schannel/winidn'
-
- - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make"
- displayName: 'make'
-
- - script: C:\msys64\usr\bin\sh -l -c "cd $(echo '%cd%') && make test-nonflaky"
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "~165 ~310 ~1013 ~1056 ~1299 ~1448 ~2034 ~2037 ~2041 ~2046 ~2047 ~3000 ~3001"
-
- - job: windows_msys1_mingw_debug_schannel
- displayName: msys1 mingw debug schannel
- timeoutInMinutes: 90
- pool:
- vmImage: 'windows-2019'
- container:
- image: mback2k/curl-docker-winbuildenv-msys1-mingw:ltsc2019
- steps:
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && ./configure --host=i686-pc-mingw32 --build=i686-pc-mingw32 --prefix=/mingw --enable-debug --enable-sspi --without-ssl --with-schannel --with-winidn"
- displayName: 'configure debug with sspi/schannel/winidn'
-
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make"
- displayName: 'make'
-
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make test-nonflaky"
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "~203 ~305 ~310 ~311 ~312 ~313 ~404 ~1013 ~1056 ~1143 ~2034 ~2035 ~2037 ~2038 ~2041 ~2042 ~2048 ~3000 ~3001"
-
- - job: windows_msys1_mingw32_debug_schannel
- displayName: msys1 mingw32 debug schannel
- timeoutInMinutes: 90
- pool:
- vmImage: 'windows-2019'
- container:
- image: mback2k/curl-docker-winbuildenv-msys1-mingw32:ltsc2019
- steps:
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && ./configure --host=i686-w64-mingw32 --build=i686-w64-mingw32 --prefix=/mingw32 --enable-debug --enable-werror --enable-sspi --without-ssl --with-schannel --with-winidn --without-zlib"
- displayName: 'configure debug with sspi/schannel/winidn without zlib'
-
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make"
- displayName: 'make'
-
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make test-nonflaky"
- displayName: 'test'
- env:
- AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "~203 ~310 ~1013 ~1056 ~1143 ~1299 ~2034 ~2037 ~2041 ~3000 ~3001"
-
- - job: windows_msys1_mingw64_debug_schannel
- displayName: msys1 mingw64 debug schannel
- timeoutInMinutes: 90
- pool:
- vmImage: 'windows-2019'
- container:
- image: mback2k/curl-docker-winbuildenv-msys1-mingw64:ltsc2019
- steps:
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && ./buildconf && ./configure --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --prefix=/mingw64 --enable-debug --enable-werror --enable-sspi --without-ssl --with-schannel --with-winidn --without-zlib"
- displayName: 'configure debug with sspi/schannel/winidn without zlib'
+ - script: $(container_cmd) -l -c "cd $(echo '%cd%') && ./buildconf && ./configure $(configure)"
+ displayName: 'configure $(name)'
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make"
+ - script: $(container_cmd) -l -c "cd $(echo '%cd%') && make"
displayName: 'make'
- - script: C:\MinGW\msys\1.0\bin\sh -l -c "cd $(echo '%cd%') && make test-nonflaky"
+ - script: $(container_cmd) -l -c "cd $(echo '%cd%') && make test-nonflaky"
displayName: 'test'
env:
AZURE_ACCESS_TOKEN: "$(System.AccessToken)"
- TFLAGS: "~203 ~310 ~1013 ~1056 ~1143 ~1299 ~2034 ~2037 ~2041 ~3000 ~3001"
+ TFLAGS: "$(tflags)"
diff --git a/.cirrus.yml b/.cirrus.yml
index 5456395ef..0cff11b4c 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -27,7 +27,7 @@ task:
freebsd_instance:
matrix:
# A stable 13.0 image likely won't be available before early 2021
- image_family: freebsd-13-0-snap
+ # image_family: freebsd-13-0-snap
image_family: freebsd-12-1
# The stable 11.3 image causes "Agent is not responding" so use a snapshot
image_family: freebsd-11-3-snap
@@ -69,9 +69,9 @@ task:
- SKIP_TESTS=''
- uname -r
- case `uname -r` in
- 13.0*) SKIP_TESTS='~1242 ~1243 ~2002 ~2003';;
- 12.1*) SKIP_TESTS='~1242 ~1243 ~2002 ~2003';;
- 11.3*) SKIP_TESTS='~1242 ~1243 ~2002 ~2003';;
+ 13.0*) SKIP_TESTS='!SFTP !SCP';;
+ 12.1*) SKIP_TESTS='!SFTP !SCP';;
+ 11.3*) SKIP_TESTS='!SFTP !SCP';;
esac
- sudo -u nobody make V=1 TFLAGS="-n -a -p !flaky ${SKIP_TESTS}" test-nonflaky
install_script:
diff --git a/.dcignore b/.dcignore
new file mode 100644
index 000000000..73b1e7169
--- /dev/null
+++ b/.dcignore
@@ -0,0 +1,3 @@
+tests/**
+docs/**
+docs/examples/**
diff --git a/.gitignore b/.gitignore
index 1b7666f43..22013a8ed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@
/.vs
/build/
/builds/
+/stats/
__pycache__
CHANGES.dist
Debug
diff --git a/.mailmap b/.mailmap
index 468b90992..15024a240 100644
--- a/.mailmap
+++ b/.mailmap
@@ -69,3 +69,6 @@ Jessa Chandler <jessachandler@gmail.com>
Gökhan Şengün <gsengun@linux-5d7d.site> <gokhansengun@gmai.com>
Svyatoslav Mishyn <juef@openmailbox.org>
Douglas Steinwand <dzs-curl@dzs.fx.org>
+James Fuller <jim@webcomposite.com>
+Don J Olmstead <don.j.olmstead@gmail.com>
+Nicolas Sterchele <sterchelen@gmail.com>
diff --git a/.travis.yml b/.travis.yml
index 1ec40d1a9..420b94ba4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,11 +23,11 @@ language: c
sudo: required
env:
- global:
- - LD_LIBRARY_PATH=/usr/local/lib
+ global:
+ - LD_LIBRARY_PATH=/usr/local/lib
addons:
- apt:
+ apt: &common_apt
config:
retries: true
sources: &common_sources
@@ -254,25 +254,25 @@ matrix:
- zlib1g-dev
before_install:
- - export "${OVERRIDE_CC-blank=}"
- - export "${OVERRIDE_CXX-blank=}"
+- export "${OVERRIDE_CC-blank=}"
+- export "${OVERRIDE_CXX-blank=}"
install:
- - if [ "$T" = "coverage" ]; then pip2 install --user cpp-coveralls; fi
+- if [ "$T" = "coverage" ]; then pip2 install --user cpp-coveralls; fi
# before_script and script:
# Travis isn't reliable catching errors in inline script commands (#3730).
# Do not add anything here, instead add to the respective script.
before_script:
- - ./scripts/travis/before_script.sh || travis_terminate 1
+- ./scripts/travis/before_script.sh || travis_terminate 1
script:
- - ./scripts/travis/script.sh || travis_terminate 1
+- ./scripts/travis/script.sh || travis_terminate 1
-# whitelist branches to avoid testing feature branches twice (as branch and as pull request)
+# select branches to avoid testing feature branches twice (as branch and as pull request)
branches:
- only:
- - master
- - /\/ci$/
+ only:
+ - master
+ - /\/ci$/
notifications:
email: false
diff --git a/CMake/FindNGHTTP3.cmake b/CMake/FindNGHTTP3.cmake
new file mode 100644
index 000000000..73ce9e188
--- /dev/null
+++ b/CMake/FindNGHTTP3.cmake
@@ -0,0 +1,76 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.haxx.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+###########################################################################
+
+#[=======================================================================[.rst:
+FindNGHTTP3
+----------
+
+Find the nghttp3 library
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+``NGHTTP3_FOUND``
+ System has nghttp3
+``NGHTTP3_INCLUDE_DIRS``
+ The nghttp3 include directories.
+``NGHTTP3_LIBRARIES``
+ The libraries needed to use nghttp3
+``NGHTTP3_VERSION``
+ version of nghttp3.
+#]=======================================================================]
+
+if(UNIX)
+ find_package(PkgConfig QUIET)
+ pkg_search_module(PC_NGHTTP3 libnghttp3)
+endif()
+
+find_path(NGHTTP3_INCLUDE_DIR nghttp3/nghttp3.h
+ HINTS
+ ${PC_NGHTTP3_INCLUDEDIR}
+ ${PC_NGHTTP3_INCLUDE_DIRS}
+)
+
+find_library(NGHTTP3_LIBRARY NAMES nghttp3
+ HINTS
+ ${PC_NGHTTP3_LIBDIR}
+ ${PC_NGHTTP3_LIBRARY_DIRS}
+)
+
+if(PC_NGHTTP3_VERSION)
+ set(NGHTTP3_VERSION ${PC_NGHTTP3_VERSION})
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(NGHTTP3
+ REQUIRED_VARS
+ NGHTTP3_LIBRARY
+ NGHTTP3_INCLUDE_DIR
+ VERSION_VAR NGHTTP3_VERSION
+)
+
+if(NGHTTP3_FOUND)
+ set(NGHTTP3_LIBRARIES ${NGHTTP3_LIBRARY})
+ set(NGHTTP3_INCLUDE_DIRS ${NGHTTP3_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(NGHTTP3_INCLUDE_DIRS NGHTTP3_LIBRARIES)
diff --git a/CMake/FindNGTCP2.cmake b/CMake/FindNGTCP2.cmake
new file mode 100644
index 000000000..a1ed8cd4b
--- /dev/null
+++ b/CMake/FindNGTCP2.cmake
@@ -0,0 +1,113 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.haxx.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+###########################################################################
+
+#[=======================================================================[.rst:
+FindNGTCP2
+----------
+
+Find the ngtcp2 library
+
+This module accepts optional COMPONENTS to control the crypto library (these are
+mutually exclusive)::
+
+ OpenSSL: Use libngtcp2_crypto_openssl
+ GnuTLS: Use libngtcp2_crypto_gnutls
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+``NGTCP2_FOUND``
+ System has ngtcp2
+``NGTCP2_INCLUDE_DIRS``
+ The ngtcp2 include directories.
+``NGTCP2_LIBRARIES``
+ The libraries needed to use ngtcp2
+``NGTCP2_VERSION``
+ version of ngtcp2.
+#]=======================================================================]
+
+if(UNIX)
+ find_package(PkgConfig QUIET)
+ pkg_search_module(PC_NGTCP2 libngtcp2)
+endif()
+
+find_path(NGTCP2_INCLUDE_DIR ngtcp2/ngtcp2.h
+ HINTS
+ ${PC_NGTCP2_INCLUDEDIR}
+ ${PC_NGTCP2_INCLUDE_DIRS}
+)
+
+find_library(NGTCP2_LIBRARY NAMES ngtcp2
+ HINTS
+ ${PC_NGTCP2_LIBDIR}
+ ${PC_NGTCP2_LIBRARY_DIRS}
+)
+
+if(PC_NGTCP2_VERSION)
+ set(NGTCP2_VERSION ${PC_NGTCP2_VERSION})
+endif()
+
+if(NGTCP2_FIND_COMPONENTS)
+ set(NGTCP2_CRYPTO_BACKEND "")
+ foreach(component IN LISTS NGTCP2_FIND_COMPONENTS)
+ if(component MATCHES "^(OpenSSL|GnuTLS)")
+ if(NGTCP2_CRYPTO_BACKEND)
+ message(FATAL_ERROR "NGTCP2: Only one crypto library can be selected")
+ endif()
+ set(NGTCP2_CRYPTO_BACKEND ${component})
+ endif()
+ endforeach()
+
+ if(NGTCP2_CRYPTO_BACKEND)
+ string(TOLOWER "ngtcp2_crypto_${NGTCP2_CRYPTO_BACKEND}" _crypto_library)
+ if(UNIX)
+ pkg_search_module(PC_${_crypto_library} lib${_crypto_library})
+ endif()
+ find_library(${_crypto_library}_LIBRARY
+ NAMES
+ ${_crypto_library}
+ HINTS
+ ${PC_${_crypto_library}_LIBDIR}
+ ${PC_${_crypto_library}_LIBRARY_DIRS}
+ )
+ if(${_crypto_library}_LIBRARY)
+ set(NGTCP2_${NGTCP2_CRYPTO_BACKEND}_FOUND TRUE)
+ set(NGTCP2_CRYPTO_LIBRARY ${${_crypto_library}_LIBRARY})
+ endif()
+ endif()
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(NGTCP2
+ REQUIRED_VARS
+ NGTCP2_LIBRARY
+ NGTCP2_INCLUDE_DIR
+ VERSION_VAR NGTCP2_VERSION
+ HANDLE_COMPONENTS
+)
+
+if(NGTCP2_FOUND)
+ set(NGTCP2_LIBRARIES ${NGTCP2_LIBRARY} ${NGTCP2_CRYPTO_LIBRARY})
+ set(NGTCP2_INCLUDE_DIRS ${NGTCP2_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(NGTCP2_INCLUDE_DIRS NGTCP2_LIBRARIES)
diff --git a/CMake/FindQUICHE.cmake b/CMake/FindQUICHE.cmake
new file mode 100644
index 000000000..01d17582b
--- /dev/null
+++ b/CMake/FindQUICHE.cmake
@@ -0,0 +1,68 @@
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.haxx.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+###########################################################################
+
+#[=======================================================================[.rst:
+FindQUICHE
+----------
+
+Find the quiche library
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+``QUICHE_FOUND``
+ System has quiche
+``QUICHE_INCLUDE_DIRS``
+ The quiche include directories.
+``QUICHE_LIBRARIES``
+ The libraries needed to use quiche
+#]=======================================================================]
+if(UNIX)
+ find_package(PkgConfig QUIET)
+ pkg_search_module(PC_QUICHE quiche)
+endif()
+
+find_path(QUICHE_INCLUDE_DIR quiche.h
+ HINTS
+ ${PC_QUICHE_INCLUDEDIR}
+ ${PC_QUICHE_INCLUDE_DIRS}
+)
+
+find_library(QUICHE_LIBRARY NAMES quiche
+ HINTS
+ ${PC_QUICHE_LIBDIR}
+ ${PC_QUICHE_LIBRARY_DIRS}
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(QUICHE
+ REQUIRED_VARS
+ QUICHE_LIBRARY
+ QUICHE_INCLUDE_DIR
+)
+
+if(QUICHE_FOUND)
+ set(QUICHE_LIBRARIES ${QUICHE_LIBRARY})
+ set(QUICHE_INCLUDE_DIRS ${QUICHE_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(QUICHE_INCLUDE_DIRS QUICHE_LIBRARIES)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a499d25d2..0eebda4ad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -26,7 +26,6 @@
# The output .so file lacks the soname number which we currently have within the lib/Makefile.am file
# Add full (4 or 5 libs) SSL support
# Add INSTALL target (EXTRA_DIST variables in Makefile.am may be moved to Makefile.inc so that CMake/CPack is aware of what's to include).
-# Add CTests(?)
# Check on all possible platforms
# Test with as many configurations possible (With or without any option)
# Create scripts that help keeping the CMake build system up to date (to reduce maintenance). According to Tetetest:
@@ -38,7 +37,7 @@
# To check:
# (From Daniel Stenberg) The cmake build selected to run gcc with -fPIC on my box while the plain configure script did not.
# (From Daniel Stenberg) The gcc command line use neither -g nor any -O options. As a developer, I also treasure our configure scripts's --enable-debug option that sets a long range of "picky" compiler options.
-cmake_minimum_required(VERSION 3.0...3.16 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.2...3.16 FATAL_ERROR)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake;${CMAKE_MODULE_PATH}")
include(Utilities)
@@ -478,6 +477,56 @@ if(USE_NGHTTP2)
list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES})
endif()
+function(CheckQuicSupportInOpenSSL)
+ # Be sure that the OpenSSL library actually supports QUIC.
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}")
+ set(CMAKE_REQUIRED_LIBRARIES "${OPENSSL_LIBRARIES}")
+ check_symbol_exists(SSL_CTX_set_quic_method "openssl/ssl.h" HAVE_SSL_CTX_SET_QUIC_METHOD)
+ if(NOT HAVE_SSL_CTX_SET_QUIC_METHOD)
+ message(FATAL_ERROR "QUIC support is missing in OpenSSL/boringssl. Try setting -DOPENSSL_ROOT_DIR")
+ endif()
+ cmake_pop_check_state()
+endfunction()
+
+option(USE_NGTCP2 "Use ngtcp2 and nghttp3 libraries for HTTP/3 support" OFF)
+if(USE_NGTCP2)
+ if(USE_OPENSSL)
+ find_package(NGTCP2 REQUIRED OpenSSL)
+ CheckQuicSupportInOpenSSL()
+ elseif(USE_GNUTLS)
+ # TODO add GnuTLS support as vtls library.
+ find_package(NGTCP2 REQUIRED GnuTLS)
+ else()
+ message(FATAL_ERROR "ngtcp2 requires OpenSSL or GnuTLS")
+ endif()
+ set(USE_NGTCP2 ON)
+ include_directories(${NGTCP2_INCLUDE_DIRS})
+ list(APPEND CURL_LIBS ${NGTCP2_LIBRARIES})
+
+ find_package(NGHTTP3 REQUIRED)
+ set(USE_NGHTTP3 ON)
+ include_directories(${NGHTTP3_INCLUDE_DIRS})
+ list(APPEND CURL_LIBS ${NGHTTP3_LIBRARIES})
+endif()
+
+option(USE_QUICHE "Use quiche library for HTTP/3 support" OFF)
+if(USE_QUICHE)
+ if(USE_NGTCP2)
+ message(FATAL_ERROR "Only one HTTP/3 backend can be selected!")
+ endif()
+ find_package(QUICHE REQUIRED)
+ CheckQuicSupportInOpenSSL()
+ set(USE_QUICHE ON)
+ include_directories(${QUICHE_INCLUDE_DIRS})
+ list(APPEND CURL_LIBS ${QUICHE_LIBRARIES})
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_INCLUDES "${QUICHE_INCLUDE_DIRS}")
+ set(CMAKE_REQUIRED_LIBRARIES "${QUICHE_LIBRARIES}")
+ check_symbol_exists(quiche_conn_set_qlog_fd "quiche.h" HAVE_QUICHE_CONN_SET_QLOG_FD)
+ cmake_pop_check_state()
+endif()
+
if(WIN32)
set(USE_WIN32_CRYPTO ON)
endif()
@@ -702,6 +751,9 @@ else()
unset(USE_UNIX_SOCKETS CACHE)
endif()
+option(ENABLE_ALT_SVC "Enable alt-svc support" OFF)
+set(USE_ALTSVC ${ENABLE_ALT_SVC})
+
#
# CA handling
#
@@ -1213,6 +1265,7 @@ function(transform_makefile_inc INPUT_FILE OUTPUT_FILE)
string(REGEX REPLACE "\\$\\(([a-zA-Z_][a-zA-Z0-9_]*)\\)" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) # Replace $() with ${}
string(REGEX REPLACE "@([a-zA-Z_][a-zA-Z0-9_]*)@" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT}) # Replace @@ with ${}, even if that may not be read by CMake scripts.
file(WRITE ${OUTPUT_FILE} ${MAKEFILE_INC_TEXT})
+ set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${INPUT_FILE}")
endfunction()
include(GNUInstallDirs)
@@ -1233,8 +1286,10 @@ if(BUILD_GNURL_EXE)
add_subdirectory(src)
endif()
-include(CTest)
-if(BUILD_TESTING)
+option(BUILD_TESTING "Build tests" "${PERL_FOUND}")
+if(NOT PERL_FOUND)
+ message(STATUS "Perl not found, testing disabled.")
+elseif(BUILD_TESTING)
add_subdirectory(tests)
endif()
@@ -1268,6 +1323,7 @@ _add_if("Largefile" (CURL_SIZEOF_CURL_OFF_T GREATER 4) AND
# TODO SSP1 (WinSSL) check is missing
_add_if("SSPI" USE_WINDOWS_SSPI)
_add_if("GSS-API" HAVE_GSSAPI)
+_add_if("alt-svc" ENABLE_ALT_SVC)
# TODO SSP1 missing for SPNEGO
_add_if("SPNEGO" NOT CURL_DISABLE_CRYPTO_AUTH AND
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
@@ -1289,6 +1345,8 @@ _add_if("NTLM_WB" use_ntlm AND NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
_add_if("TLS-SRP" USE_TLS_SRP)
# TODO option --with-nghttp2 tests for nghttp2 lib and nghttp2/nghttp2.h header
_add_if("HTTP2" USE_NGHTTP2)
+_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE)
+_add_if("MultiSSL" CURL_WITH_MULTI_SSL)
_add_if("HTTPS-proxy" SSL_ENABLED AND (USE_OPENSSL OR USE_GNUTLS OR USE_NSS))
string(REPLACE ";" " " SUPPORT_FEATURES "${_items}")
message(STATUS "Enabled features: ${SUPPORT_FEATURES}")
@@ -1318,8 +1376,8 @@ _add_if("SMB" NOT CURL_DISABLE_SMB AND use_ntlm)
_add_if("SMBS" NOT CURL_DISABLE_SMB AND SSL_ENABLED AND use_ntlm)
_add_if("SMTP" NOT CURL_DISABLE_SMTP)
_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND SSL_ENABLED)
-_add_if("SCP" USE_LIBSSH2)
-_add_if("SFTP" USE_LIBSSH2)
+_add_if("SCP" USE_LIBSSH2 OR USE_LIBSSH)
+_add_if("SFTP" USE_LIBSSH2 OR USE_LIBSSH)
_add_if("RTSP" NOT CURL_DISABLE_RTSP)
_add_if("RTMP" USE_LIBRTMP)
_add_if("MQTT" CURL_ENABLE_MQTT)
@@ -1351,25 +1409,43 @@ set(CONFIGURE_OPTIONS "")
# TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB?
set(CPPFLAG_CURL_STATICLIB "")
set(CURLVERSION "${CURL_VERSION}")
-if(BUILD_SHARED_LIBS)
- set(ENABLE_SHARED "yes")
- set(ENABLE_STATIC "no")
-else()
- set(ENABLE_SHARED "no")
- set(ENABLE_STATIC "yes")
-endif()
set(exec_prefix "\${prefix}")
set(includedir "\${prefix}/include")
set(LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
set(LIBGNURL_LIBS "")
set(libdir "${CMAKE_INSTALL_PREFIX}/lib")
foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${GNURL_LIBS})
+ if(TARGET "${_lib}")
+ set(_libname "${_lib}")
+ get_target_property(_libtype "${_libname}" TYPE)
+ if(_libtype STREQUAL INTERFACE_LIBRARY)
+ # Interface libraries can occur when an external project embeds curl and
+ # defined targets such as ZLIB::ZLIB by themselves. Ignore these as
+ # reading the LOCATION property will error out. Assume the user won't need
+ # this information in the .pc file.
+ continue()
+ endif()
+ get_target_property(_lib "${_libname}" LOCATION)
+ if(NOT _lib)
+ message(WARNING "Bad lib in library list: ${_libname}")
+ continue()
+ endif()
+ endif()
if(_lib MATCHES ".*/.*" OR _lib MATCHES "^-")
set(LIBGNURL_LIBS "${LIBGNURL_LIBS} ${_lib}")
else()
set(LIBGNURL_LIBS "${LIBGNURL_LIBS} -l${_lib}")
endif()
endforeach()
+if(BUILD_SHARED_LIBS)
+ set(ENABLE_SHARED "yes")
+ set(ENABLE_STATIC "no")
+ set(LIBCURL_NO_SHARED "")
+else()
+ set(ENABLE_SHARED "no")
+ set(ENABLE_STATIC "yes")
+ set(LIBCURL_NO_SHARED "${LIBCURL_LIBS}")
+endif()
# "a" (Linux) or "lib" (Windows)
string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(prefix "${CMAKE_INSTALL_PREFIX}")
diff --git a/Makefile.am b/Makefile.am
index 089e5a193..e514ea8d3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -35,6 +35,12 @@ CMAKE_DIST = \
CMake/CurlTests.c \
CMake/FindBearSSL.cmake \
CMake/FindGSS.cmake \
+ CMake/FindLibSSH2.cmake \
+ CMake/FindMbedTLS.cmake \
+ CMake/FindNGHTTP2.cmake \
+ CMake/FindNGHTTP3.cmake \
+ CMake/FindNGTCP2.cmake \
+ CMake/FindQUICHE.cmake \
CMake/FindWolfSSL.cmake \
CMake/Macros.cmake \
CMake/OtherTests.cmake \
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 6880318d6..04aa18bb4 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -1,155 +1,31 @@
-curl and libcurl 7.70.0
+curl and libcurl 7.71.1
- Public curl releases: 191
- Command line options: 231
- curl_easy_setopt() options: 270
+ Public curl releases: 193
+ Command line options: 232
+ curl_easy_setopt() options: 277
Public functions in libcurl: 82
- Contributors: 2169
-
-This release includes the following changes:
-
- o curl: add --ssl-revoke-best-effort to allow a "best effort" revocation check [5]
- o mqtt: add new experimental protocol [57]
- o schannel: add "best effort" revocation check option: CURLSSLOPT_REVOKE_BEST_EFFORT [5]
- o writeout: support to generate JSON output with '%{json}' [8]
+ Contributors: 2210
This release includes the following bugfixes:
- o appveyor: add Unicode winbuild jobs [88]
- o appveyor: completely disable tests that fail to timeout early
- o appveyor: show failed tests in log even if test is ignored
- o appveyor: sort builds by type and add two new variants
- o appveyor: turn disabled tests into ignored result tests
- o appveyor: use random test server ports based upon APPVEYOR_API_URL [52]
- o build: fixed build for systems with select() in unistd.h [43]
- o buildconf: avoid using tempfile when removing files [90]
- o checksrc: warn on obvious conditional blocks on the same line as if() [44]
- o CI-fuzz: increase fuzz time to 40 minutes [59]
- o ci/tests: fix Azure Pipelines not running Windows containers [25]
- o CI: add build with ngtcp2 + gnutls on Travis CI
- o CI: bring GitHub Actions fuzzing job in line with macOS jobs
- o CI: migrate macOS jobs from Azure and Travis CI to GitHub Actions [36]
- o CI: remove default Ubuntu build from GitHub Actions
- o cirrus: no longer ignore test 504 which is working again
- o cirrus: re-enable the FreeBSD 13 CI builds [29]
- o cleanup: insert newline after if() conditions
- o cmake: add aliases so exported target names are available in tree [73]
- o cmake: add CMAKE_MSVC_RUNTIME_LIBRARY [45]
- o cmake: add support for building with wolfSSL [9]
- o cmake: Avoid MSVC C4273 warnings in send/recv checks [92]
- o cmdline: fix handling of OperationConfig linked list (--next) [24]
- o compressed.d: stress that the headers are not modified [80]
- o config: remove all defines of HAVE_DES_H [37]
- o configure: convert -I to -isystem as a last step [2]
- o configure: document 'compiler_num' for gcc [4]
- o configure: don't check for Security.framework when cross-compiling [47]
- o configure: fix -pedantic-errors for GCC 5 and later [3]
- o configure: remove use of -vec-report0 from CFLAGS with icc [71]
- o connect: happy eyeballs cleanup [15]
- o connect: store connection info for QUIC connections [68]
- o copyright: fix out-of-date copyright ranges and missing headers [38]
- o curl-functions.m4: remove inappropriate AC_REQUIRE [26]
- o curl.h: remnove CURL_VERSION_ESNI. Never supported nor documented [49]
- o curl.h: update comment typo [61]
- o curl: allow both --etag-compare and --etag-save with same file name [56]
- o curl_setup: define _WIN32_WINNT_[OS] symbols [27]
- o CURLINFO_CONDITION_UNMET: return true for 304 http status code [54]
- o CURLINFO_NUM_CONNECTS: improve accuracy [28]
- o CURLOPT_WRITEFUNCTION.3: add inline example and new see-also [70]
- o dist: add mail-rcpt-allowfails.d to the tarball [35]
- o docs/make: generate curl.1 from listed files only [33]
- o docs: add warnings about FILE: URLs on Windows [19]
- o easy: fix curl_easy_duphandle for builds missing IPv6 that use c-ares [18]
- o examples/sessioninfo.c: add include to fix compiler warning [42]
- o github actions: run when pushed to master or */ci + PRs [64]
- o gnutls: bump lowest supported version to 3.1.10 [89]
- o gnutls: Don't skip really long certificate fields [86]
- o gnutls: ensure TLS 1.3 when SRP isn't requested [79]
- o gopher: check remaining time left during write busy loop [78]
- o gskit: use our internal select wrapper for portability [12]
- o http2: Fix erroneous debug message that h2 connection closed [21]
- o http: don't consider upload done if the request isn't completely sent off [67]
- o http: free memory when Alt-Used header creation fails due to OOM [98]
- o lib/mk-ca-bundle: skip empty certs [112]
- o lib670: use the same Win32 API check as all other lib tests
- o lib: fix typos in comments and errormessages
- o lib: never define CURL_CA_BUNDLE with a getenv [51]
- o libcurl-multi.3: added missing full stop [110]
- o libssh: avoid options override by configuration files [104]
- o libssh: Use new ECDSA key types to check known hosts [87]
- o mailmap: fixup a few author names/fields
- o Makefile.m32: Improve windres parameter compatibility [17]
- o Makefile: run the cd commands in a subshell [1]
- o memdebug: don't log free(NULL)
- o mime: properly check Content-Type even if it has parameters [83]
- o multi-ssl: reset the SSL backend on `Curl_global_cleanup()` [100]
- o multi: improve parameter check for curl_multi_remove_handle [6]
- o nghttp2: 1.12.0 required [40]
- o ngtcp2: update to git master for the key installation API change [46]
- o nss: check for PK11_CreateDigestContext() returning NULL [96]
- o openssl: adapt to functions marked as deprecated since version 3 [34]
- o OS400: update strings for ccsid-ifier (fixes the build) [30]
- o output.d: quote the URL when globbing [48]
- o packages: add OS400/chkstrings.c to the dist [39]
- o RELEASE-PROCEDURE.md: run the copyright.pl script!
- o Revert "file: on Windows, refuse paths that start with \\" [50]
- o runtests: always put test number in servercmd file
- o runtests: provide nicer errormsg when protocol "dump" file is empty
- o schannel: Fix blocking timeout logic [76]
- o schannel: support .P12 or .PFX client certificates [65]
- o scripts/release-notes.pl: add helper script for RELEASE-NOTES maintenance
- o select: make Curl_socket_check take timediff_t timeout [109]
- o select: move duplicate select preparation code into Curl_select [14]
- o select: remove typecast from SOCKET_WRITABLE/READABLE macros [69]
- o server/getpart: make the "XML-parser" stricter [20]
- o server/resolve: remove AI_CANONNAME to make macos tell the truth [63]
- o smtp: set auth correctly [103]
- o sockfilt: add logmsg output to select_ws_wait_thread on Windows [32]
- o sockfilt: fix broken pipe on Windows to be ready in select_ws [95]
- o sockfilt: fix handling of ready closed sockets on Windows
- o sockfilt: fix race-condition of waiting threads and event handling [58]
- o socks: Fix blocking timeout logic [77]
- o src: Remove C99 constructs to ensure C89 compliance [82]
- o SSLCERTS.md: Fix example code for setting CA cert file [31]
- o test1148: tolerate progress updates better (again) [60]
- o test1154: set a proper name
- o test1177: verify that all the CURL_VERSION_ bits are documented
- o test1566: verify --etag-compare that gets a 304 back [53]
- o test1908: avoid using fixed port number in test data [75]
- o test2043: use revoked.badssl.com instead of revoked.grc.com [94]
- o test2100: fix static port instead of dynamic value being used
- o tests/data: fix some XML formatting issues in test cases
- o tests/FILEFORMAT: converted to markdown and extended [84]
- o tests/server/util.c: use curl_off_t instead of long for pid
- o tests: add %NOLISTENPORT and use it [93]
- o tests: add Windows compatible pidwait like pidkill and pidterm
- o tests: fix conflict between Cygwin/msys and Windows PIDs [81]
- o tests: introduce preprocessed test cases
- o tests: make Python-based servers compatible with Python 2 and 3 [22]
- o tests: make runtests check that disabled tests exists [108]
- o tests: move pingpong server to dynamic listening port
- o tests: remove python_dependencies for smbserver from our tree [16]
- o tests: run the RTSP test server on a dynamic port number [91]
- o tests: run the SOCKS test server on a dynamic port number [99]
- o tests: run the sws server on "any port" [85]
- o tests: run the TFTP test server on a dynamic port number [101]
- o tests: use Cygwin/msys PIDs for stunnel and sshd on Windows
- o tls: remove the BACKEND define kludge from most backends [23]
- o tool: do not declare functions with Curl_ prefix [66]
- o tool_operate: fix add_parallel_transfers when more are in queue [10]
- o transfer: cap retries of "dead connections" to 5 [13]
- o transfer: Switch PUT to GET/HEAD on 303 redirect [111]
- o travis: bump the wolfssl CI build to use 4.4.0 [97]
- o travis: update the ngtcp2 build to use the latest OpenSSL patch
- o url: allow non-HTTPS altsvc-matching for debug builds [62]
- o version: add 'cainfo' and 'capath' to version info struct [55]
- o version: increase buffer space for ssl version output [74]
- o version: skip idn2_check_version() check and add precaution [113]
- o vquic: add support for GnuTLS backend of ngtcp2 [41]
- o vtls: fix ssl_config memory-leak on out-of-memory [11]
- o warnless: remove code block for icc that didn't work [72]
- o windows: enable UnixSockets with all build toolchains
- o windows: suppress UI in all CryptAcquireContext() calls [7]
+ o cirrus-ci: disable FreeBSD 13 (again) [14]
+ o Curl_inet_ntop: always check the return code [12]
+ o CURLOPT_READFUNCTION.3: provide the upload data size up front [5]
+ o DYNBUF.md: fix a typo: trail => tail [2]
+ o escape: make the URL decode able to reject only %00-bytes
+ o escape: zero length input should return a zero length output [11]
+ o examples/multithread.c: call curl_global_cleanup() [16]
+ o http2: set the correct URL in pushed transfers [9]
+ o http: fix proxy auth with blank password [3]
+ o mbedtls: fix build with disabled proxy support [7]
+ o ngtcp2: sync with current master [15]
+ o openssl: Fix compilation on Windows when ngtcp2 is enabled [10]
+ o Revert "multi: implement wait using winsock events" [6]
+ o sendf: improve the message on client write errors [13]
+ o terminology: call them null-terminated strings [1]
+ o tool_cb_hdr: Fix etag warning output and return code [4]
+ o url: allow user + password to contain "control codes" for HTTP(S) [8]
+ o vtls: compare cert blob when finding a connection to reuse [17]
This release includes the following known bugs:
@@ -158,133 +34,30 @@ 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:
- Alain Miniussi, Alexander V. Tikhonov, Alex Gaynor,
- Anderson Toshiyuki Sasaki, Andrew Kurushin, Ashwin Metpalli, Björn Stenberg,
- Brad King, Brian Bergeron, Calvin Buckley, Chris Roberts, Christoph Krey,
- Clément Notin, Daiki Ueno, Dan Fandrich, Daniel Gustafsson, Daniel Stenberg,
- davidedec on github, Dennis Felsing, Dima Tisnek, Dirkjan Bussink,
- Emil Engler, Eric Sauvageau, Eylem Ugurel, Frank Gevaerts,
- FuccDucc on github, Gavin Wong, Gilles Vollant, Gisle Vanem, Hao Wu,
- Harry Sintonen, hydra3333 on github, James Fuller, Johannes Schindelin,
- Jon Rumsey, JP Mens, Kamil Dudka, Karl Chen, Kwon-Young Choi, Leo Neat,
- Maksim Stsepanenka, Marcel Raad, Marc Hörsken, Markus Olsson, Mathias Gumz,
- Michael Kaufmann, Michael Osipov, Muhammad Herdiansyah, Nathaniel R. Lewis,
- Patrick Monnerat, Paul Vixie, Ray Satiro, Rici Lake, Rikard Falkeborn,
- Roger Orr, Ross Burton, Simon Chalifoux, Stepan Efremov, Steven Penny,
- thanhchungbtc on github, Timothe Litt, Tim Sedlmeyer, Tommy Petty,
- Viktor Szakats, Yuri Slobodyanyuk,
- (65 contributors)
+ Alexandre Pion, Baruch Siach, coinhubs on github, Daniel Stenberg,
+ Denis BaruÄić, Gergely Nagy, Javier Blazquez, Jonathan Cardoso Machado,
+ Jon Johnson Jr, Kristoffer Gleditsch, Lucien Zürcher, Nicolas Sterchele,
+ qiandu2006 on github, Ray Satiro, Siva Sivaraman, tmkk on github,
+ (16 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=5073
- [2] = https://curl.haxx.se/bug/?i=5060
- [3] = https://curl.haxx.se/bug/?i=5067
- [4] = https://curl.haxx.se/bug/?i=5069
- [5] = https://curl.haxx.se/bug/?i=4981
- [6] = https://curl.haxx.se/bug/?i=5116
- [7] = https://curl.haxx.se/bug/?i=5088
- [8] = https://curl.haxx.se/bug/?i=4870
- [9] = https://curl.haxx.se/bug/?i=5095
- [10] = https://curl.haxx.se/bug/?i=4937
- [11] = https://curl.haxx.se/bug/?i=5108
- [12] = https://curl.haxx.se/bug/?i=5106
- [13] = https://curl.haxx.se/mail/lib-2020-03/0044.html
- [14] = https://curl.haxx.se/bug/?i=5078
- [15] = https://curl.haxx.se/bug/?i=4954
- [16] = https://curl.haxx.se/bug/?i=5094
- [17] = https://curl.haxx.se/bug/?i=5099
- [18] = https://curl.haxx.se/bug/?i=5097
- [19] = https://curl.haxx.se/bug/?i=5066
- [20] = https://curl.haxx.se/bug/?i=5071
- [21] = https://curl.haxx.se/bug/?i=5118
- [22] = https://curl.haxx.se/bug/?i=5104
- [23] = https://curl.haxx.se/bug/?i=5122
- [24] = https://curl.haxx.se/bug/?i=5120
- [25] = https://curl.haxx.se/bug/?i=5117
- [26] = https://curl.haxx.se/bug/?i=5126
- [27] = https://curl.haxx.se/bug/?i=4995
- [28] = https://curl.haxx.se/bug/?i=5135
- [29] = https://curl.haxx.se/bug/?i=5091
- [30] = https://curl.haxx.se/bug/?i=5132
- [31] = https://curl.haxx.se/mail/lib-2020-03/0121.html
- [32] = https://curl.haxx.se/bug/?i=5086
- [33] = https://curl.haxx.se/bug/?i=5149
- [34] = https://curl.haxx.se/bug/?i=5139
- [35] = https://curl.haxx.se/bug/?i=5146
- [36] = https://curl.haxx.se/bug/?i=5124
- [37] = https://curl.haxx.se/bug/?i=5144
- [38] = https://curl.haxx.se/bug/?i=5141
- [39] = https://curl.haxx.se/bug/?i=5142
- [40] = https://curl.haxx.se/bug/?i=5140
- [41] = https://curl.haxx.se/bug/?i=5148
- [42] = https://curl.haxx.se/bug/?i=5171
- [43] = https://curl.haxx.se/bug/?i=5169
- [44] = https://curl.haxx.se/bug/?i=5164
- [45] = https://curl.haxx.se/bug/?i=5165
- [46] = https://curl.haxx.se/bug/?i=5166
- [47] = https://curl.haxx.se/bug/?i=5189
- [48] = https://curl.haxx.se/bug/?i=5160
- [49] = https://curl.haxx.se/bug/?i=5157
- [50] = https://curl.haxx.se/mail/archive-2020-04/0013.html
- [51] = https://github.com/curl/curl/commit/6de756c#r38127030
- [52] = https://curl.haxx.se/bug/?i=5034
- [53] = https://curl.haxx.se/bug/?i=5186
- [54] = https://curl.haxx.se/bug/?i=5181
- [55] = https://curl.haxx.se/bug/?i=5150
- [56] = https://curl.haxx.se/bug/?i=5179
- [57] = https://curl.haxx.se/bug/?i=5173
- [58] = https://curl.haxx.se/bug/?i=5156
- [59] = https://curl.haxx.se/bug/?i=5174
- [60] = https://curl.haxx.se/bug/?i=5194
- [61] = https://curl.haxx.se/bug/?i=5279
- [62] = https://curl.haxx.se/bug/?i=5205
- [63] = https://curl.haxx.se/bug/?i=5202
- [64] = https://curl.haxx.se/bug/?i=5201
- [65] = https://curl.haxx.se/bug/?i=5193
- [66] = https://curl.haxx.se/bug/?i=5219
- [67] = https://curl.haxx.se/bug/?i=4919
- [68] = https://curl.haxx.se/bug/?i=5196
- [69] = https://curl.haxx.se/bug/?i=5190
- [70] = https://curl.haxx.se/bug/?i=5192
- [71] = https://curl.haxx.se/bug/?i=5096
- [72] = https://curl.haxx.se/bug/?i=5096
- [73] = https://curl.haxx.se/bug/?i=5206
- [74] = https://curl.haxx.se/bug/?i=5222
- [75] = https://curl.haxx.se/bug/?i=5225
- [76] = https://curl.haxx.se/bug/?i=5177
- [77] = https://curl.haxx.se/bug/?i=5220
- [78] = https://curl.haxx.se/bug/?i=5214
- [79] = https://curl.haxx.se/bug/?i=5223
- [80] = https://github.com/curl/curl/issues/5182#issuecomment-611638008
- [81] = https://curl.haxx.se/bug/?i=5188
- [82] = https://curl.haxx.se/bug/?i=5254
- [83] = https://curl.haxx.se/bug/?i=5256
- [84] = https://curl.haxx.se/bug/?i=5261
- [85] = https://curl.haxx.se/bug/?i=5247
- [86] = https://curl.haxx.se/bug/?i=5271
- [87] = https://curl.haxx.se/bug/?i=5252
- [88] = https://curl.haxx.se/bug/?i=5063
- [89] = https://curl.haxx.se/bug/?i=5276
- [90] = https://curl.haxx.se/bug/?i=5213
- [91] = https://curl.haxx.se/bug/?i=5272
- [92] = https://curl.haxx.se/bug/?i=4764
- [93] = https://curl.haxx.se/bug/?i=5270
- [94] = https://curl.haxx.se/bug/?i=5233
- [95] = https://curl.haxx.se/bug/?i=5228
- [96] = https://curl.haxx.se/bug/?i=5302
- [97] = https://curl.haxx.se/bug/?i=5301
- [98] = https://curl.haxx.se/bug/?i=5268
- [99] = https://curl.haxx.se/bug/?i=5266
- [100] = https://curl.haxx.se/bug/?i=5255
- [101] = https://curl.haxx.se/bug/?i=5265
- [103] = https://curl.haxx.se/bug/?i=5294
- [104] = https://curl.haxx.se/bug/?i=4972
- [108] = https://curl.haxx.se/bug/?i=5288
- [109] = https://curl.haxx.se/bug/?i=5240
- [110] = https://curl.haxx.se/bug/?i=5285
- [111] = https://curl.haxx.se/bug/?i=5237
- [112] = https://curl.haxx.se/bug/?i=5278
- [113] = https://curl.haxx.se/bug/?i=5281
+ [1] = https://curl.haxx.se/bug/?i=5598
+ [2] = https://curl.haxx.se/bug/?i=5599
+ [3] = https://curl.haxx.se/bug/?i=5613
+ [4] = https://curl.haxx.se/bug/?i=5612
+ [5] = https://curl.haxx.se/bug/?i=5607
+ [6] = https://curl.haxx.se/bug/?i=5631
+ [7] = https://curl.haxx.se/bug/?i=5615
+ [8] = https://curl.haxx.se/bug/?i=5582
+ [9] = https://curl.haxx.se/bug/?i=5589
+ [10] = https://curl.haxx.se/bug/?i=5606
+ [11] = https://curl.haxx.se/bug/?i=5601
+ [12] = https://curl.haxx.se/bug/?i=5412
+ [13] = https://curl.haxx.se/bug/?i=5594
+ [14] = https://curl.haxx.se/bug/?i=5628
+ [15] = https://curl.haxx.se/bug/?i=5624
+ [16] = https://curl.haxx.se/bug/?i=5622
+ [17] = https://curl.haxx.se/bug/?i=5617
diff --git a/appveyor.yml b/appveyor.yml
index b092480c5..c810e456a 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -70,7 +70,7 @@ environment:
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "~1139"
+ DISABLED_TESTS: "!1139 !1501"
COMPILER_PATH: ""
- APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2019"
BUILD_SYSTEM: CMake
@@ -82,7 +82,7 @@ environment:
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "~1139"
+ DISABLED_TESTS: "!1139 !1501"
COMPILER_PATH: ""
- APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2019"
BUILD_SYSTEM: CMake
@@ -94,7 +94,7 @@ environment:
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "~1139"
+ DISABLED_TESTS: "!1139 !1501"
COMPILER_PATH: ""
- APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2019"
BUILD_SYSTEM: CMake
@@ -106,9 +106,9 @@ environment:
HTTP_ONLY: ON
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "~1139"
+ DISABLED_TESTS: "!1139 !1501"
COMPILER_PATH: ""
- # generated CMake-based MSYS Makefiles builds
+ # generated CMake-based MSYS Makefiles builds (mingw cross-compiling)
- APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
BUILD_SYSTEM: CMake
PRJ_GEN: "MSYS Makefiles"
@@ -118,7 +118,7 @@ environment:
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "~1139"
+ DISABLED_TESTS: "!1139 !1501"
COMPILER_PATH: "C:\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin"
MSYS2_ARG_CONV_EXCL: "/*"
BUILD_OPT: -k
@@ -131,7 +131,7 @@ environment:
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "~1139"
+ DISABLED_TESTS: "!1139 !1501"
COMPILER_PATH: "C:\\mingw-w64\\x86_64-7.2.0-posix-seh-rt_v5-rev1\\mingw64\\bin"
MSYS2_ARG_CONV_EXCL: "/*"
BUILD_OPT: -k
@@ -144,7 +144,7 @@ environment:
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "~1139"
+ DISABLED_TESTS: "!1139 !1501"
COMPILER_PATH: "C:\\mingw-w64\\i686-6.3.0-posix-dwarf-rt_v5-rev1\\mingw32\\bin"
MSYS2_ARG_CONV_EXCL: "/*"
BUILD_OPT: -k
@@ -157,7 +157,7 @@ environment:
HTTP_ONLY: OFF
TESTING: ON
SHARED: OFF
- DISABLED_TESTS: "~1139"
+ DISABLED_TESTS: "!1139 !1501"
COMPILER_PATH: "C:\\MinGW\\bin"
MSYS2_ARG_CONV_EXCL: "/*"
BUILD_OPT: -k
@@ -216,17 +216,22 @@ environment:
PRJ_CFG: "DLL Debug - DLL Windows SSPI - DLL WinIDN"
TESTING: OFF
VC_VERSION: VC15
- # autotools-based builds
+ # autotools-based builds (NOT mingw cross-compiling, but msys2 native)
- APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
BUILD_SYSTEM: autotools
TESTING: ON
- DISABLED_TESTS: "!19 !1233 ~1242 ~1243 ~2002 ~2003"
+ DISABLED_TESTS: "!19 ~1056 !1233"
CONFIG_ARGS: "--enable-debug --enable-werror --enable-alt-svc --disable-threaded-resolver --disable-proxy"
- APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2019"
BUILD_SYSTEM: autotools
TESTING: ON
- DISABLED_TESTS: "!19 !504 !704 !705 !1233 ~1242 ~1243 ~2002 ~2003"
+ DISABLED_TESTS: "!19 !504 !704 !705 ~1056 !1233"
CONFIG_ARGS: "--enable-debug --enable-werror --enable-alt-svc --disable-threaded-resolver"
+ - APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2019"
+ BUILD_SYSTEM: autotools
+ TESTING: ON
+ DISABLED_TESTS: "!19 !504 !704 !705 ~1056 !1233"
+ CONFIG_ARGS: "--enable-warnings --enable-werror"
install:
- set "PATH=C:\msys64\usr\bin;%PATH%"
@@ -280,7 +285,7 @@ test_script:
echo APPVEYOR_API_URL=%APPVEYOR_API_URL% &&
bash.exe -e -l -c "cd /c/projects/curl/tests && ./runtests.pl -a -b$(($(echo '%APPVEYOR_API_URL%' | cut -d'/' -f3 | cut -d':' -f2)+1)) -p !flaky %DISABLED_TESTS%" )
-# whitelist branches to avoid testing feature branches twice (as branch and as pull request)
+# select branches to avoid testing feature branches twice (as branch and as pull request)
branches:
only:
- master
diff --git a/buildconf b/buildconf
index c9c8a8e8a..2d4c21a25 100755
--- a/buildconf
+++ b/buildconf
@@ -64,7 +64,7 @@ findtool(){
#
removethis(){
if test "$#" = "1"; then
- find . -depth -name $1 -execdir rm -rf {} \;
+ find . -depth -name $1 -exec rm -rf {} \;
fi
}
diff --git a/configure.ac b/configure.ac
index 741b4249b..cddd3303a 100755
--- a/configure.ac
+++ b/configure.ac
@@ -1137,7 +1137,7 @@ if test X"$OPT_BROTLI" != Xno; then
LD_BROTLI=`$PKGCONFIG --libs-only-L libbrotlidec`
CPP_BROTLI=`$PKGCONFIG --cflags-only-I libbrotlidec`
version=`$PKGCONFIG --modversion libbrotlidec`
- DIR_BROTLI=`echo $LD_BROTLI | $SED -e 's/-L//'`
+ DIR_BROTLI=`echo $LD_BROTLI | $SED -e 's/^-L//'`
fi
;;
@@ -1363,12 +1363,14 @@ dnl Check if the operating system allows programs to write to their own argv[]
dnl **********************************************************************
AC_MSG_CHECKING([if argv can be written to])
-CURL_RUN_IFELSE([
-int main(int argc, char ** argv) {
- argv[0][0] = ' ';
- return (argv[0][0] == ' ')?0:1;
+CURL_RUN_IFELSE([[
+int main(int argc, char **argv)
+{
+ (void)argc;
+ argv[0][0] = ' ';
+ return (argv[0][0] == ' ')?0:1;
}
-],[
+]],[
curl_cv_writable_argv=yes
],[
curl_cv_writable_argv=no
@@ -1805,7 +1807,7 @@ if test -z "$ssl_backends" -o "x$OPT_SSL" != xno &&
AC_MSG_NOTICE([pkg-config: SSL_LDFLAGS: "$SSL_LDFLAGS"])
AC_MSG_NOTICE([pkg-config: SSL_CPPFLAGS: "$SSL_CPPFLAGS"])
- LIB_OPENSSL=`echo $SSL_LDFLAGS | sed -e 's/-L//g'`
+ LIB_OPENSSL=`echo $SSL_LDFLAGS | sed -e 's/^-L//'`
dnl use the values pkg-config reported. This is here
dnl instead of below with CPPFLAGS and LDFLAGS because we only
@@ -1830,6 +1832,8 @@ if test -z "$ssl_backends" -o "x$OPT_SSL" != xno &&
# only set this if pkg-config wasn't used
CPPFLAGS="$CLEANCPPFLAGS -I$PREFIX_OPENSSL/include/openssl -I$PREFIX_OPENSSL/include"
fi
+ # Linking previously failed, try extra paths from --with-ssl or pkg-config.
+ # Use a different function name to avoid reusing the earlier cached result.
AC_CHECK_LIB(crypto, HMAC_Init_ex,[
HAVECRYPTO="yes"
LIBS="-lcrypto $LIBS"], [
@@ -1851,6 +1855,7 @@ if test -z "$ssl_backends" -o "x$OPT_SSL" != xno &&
[
AC_MSG_RESULT(no)
dnl ok, so what about both -ldl and -lpthread?
+ dnl This may be necessary for static libraries.
AC_MSG_CHECKING([OpenSSL linking with -ldl and -lpthread])
LIBS="$CLEANLIBS -lcrypto -ldl -lpthread"
@@ -2122,7 +2127,7 @@ if test -z "$ssl_backends" -o "x$OPT_GNUTLS" != xno; then
addld=`$PKGCONFIG --libs-only-L gnutls`
addcflags=`$PKGCONFIG --cflags-only-I gnutls`
version=`$PKGCONFIG --modversion gnutls`
- gtlslib=`echo $addld | $SED -e 's/-L//'`
+ gtlslib=`echo $addld | $SED -e 's/^-L//'`
else
dnl without pkg-config, we try libgnutls-config as that was how it
dnl used to be done
@@ -2357,6 +2362,15 @@ AC_HELP_STRING([--with-wolfssl=PATH],[where to look for WolfSSL, PATH points to
AC_HELP_STRING([--without-wolfssl], [disable WolfSSL detection]),
OPT_WOLFSSL=$withval)
+case "$OPT_WOLFSSL" in
+ yes|no)
+ wolfpkg=""
+ ;;
+ *)
+ wolfpkg="$withval/lib/pkgconfig"
+ ;;
+esac
+
if test -z "$ssl_backends" -o "x$OPT_WOLFSSL" != xno; then
ssl_msg=
@@ -2366,22 +2380,41 @@ if test -z "$ssl_backends" -o "x$OPT_WOLFSSL" != xno; then
OPT_WOLFSSL=""
fi
+ CURL_CHECK_PKGCONFIG(wolfssl, [$wolfpkg])
+ AC_MSG_NOTICE([Check dir $wolfpkg])
+
addld=""
addlib=""
addcflags=""
-
- if test "x$USE_WOLFSSL" != "xyes"; then
+ if test "$PKGCONFIG" != "no" ; then
+ addlib=`CURL_EXPORT_PCDIR([$wolfpkg])
+ $PKGCONFIG --libs-only-l wolfssl`
+ addld=`CURL_EXPORT_PCDIR([$wolfpkg])
+ $PKGCONFIG --libs-only-L wolfssl`
+ addcflags=`CURL_EXPORT_PCDIR([$wolfpkg])
+ $PKGCONFIG --cflags-only-I wolfssl`
+ version=`CURL_EXPORT_PCDIR([$wolfpkg])
+ $PKGCONFIG --modversion wolfssl`
+ wolfssllibpath=`echo $addld | $SED -e 's/^-L//'`
+ else
+ addlib=-lwolfssl
addld=-L$OPT_WOLFSSL/lib$libsuff
addcflags=-I$OPT_WOLFSSL/include
wolfssllibpath=$OPT_WOLFSSL/lib$libsuff
+ fi
+
+ if test "x$USE_WOLFSSL" != "xyes"; then
LDFLAGS="$LDFLAGS $addld"
+ AC_MSG_NOTICE([Add $addld to LDFLAGS])
if test "$addcflags" != "-I/usr/include"; then
CPPFLAGS="$CPPFLAGS $addcflags"
+ AC_MSG_NOTICE([Add $addcflags to CPPFLAGS])
fi
my_ac_save_LIBS="$LIBS"
- LIBS="-lwolfssl -lm $LIBS"
+ LIBS="$addlib $LIBS"
+ AC_MSG_NOTICE([Add $addlib to LIBS])
AC_MSG_CHECKING([for wolfSSL_Init in -lwolfssl])
AC_LINK_IFELSE([
@@ -2423,9 +2456,23 @@ if test -z "$ssl_backends" -o "x$OPT_WOLFSSL" != xno; then
dnl Recent WolfSSL versions build without SSLv3 by default
dnl WolfSSL needs configure --enable-opensslextra to have *get_peer*
+ dnl DES* is needed for NTLM support and lives in the OpenSSL compatibility
+ dnl layer
AC_CHECK_FUNCS(wolfSSLv3_client_method \
wolfSSL_get_peer_certificate \
- wolfSSL_UseALPN)
+ wolfSSL_UseALPN )
+
+ dnl if this symbol is present, we want the include path to include the
+ dnl OpenSSL API root as well
+ AC_CHECK_FUNC(wolfSSL_DES_set_odd_parity,
+ [
+ AC_DEFINE(HAVE_WOLFSSL_DES_SET_ODD_PARITY, 1,
+ [if you have wolfSSL_DES_set_odd_parity])
+ CPPFLAGS="$addcflags/wolfssl $CPPFLAGS"
+ AC_MSG_NOTICE([Add $addcflags/wolfssl to CPPFLAGS])
+ WOLFSSL_NTLM=1
+ ]
+ )
if test -n "$wolfssllibpath"; then
dnl when shared libs were found in a path that the run-time
@@ -2874,7 +2921,7 @@ if test X"$OPT_LIBMETALINK" != Xno; then
$PKGCONFIG --cflags-only-I libmetalink`
version=`CURL_EXPORT_PCDIR([$LIBMETALINK_PCDIR]) dnl
$PKGCONFIG --modversion libmetalink`
- libmetalinklib=`echo $addld | $SED -e 's/-L//'`
+ libmetalinklib=`echo $addld | $SED -e 's/^-L//'`
fi
if test -n "$addlib"; then
@@ -2965,7 +3012,7 @@ if test X"$OPT_LIBSSH2" != Xno; then
LD_SSH2=`$PKGCONFIG --libs-only-L libssh2`
CPP_SSH2=`$PKGCONFIG --cflags-only-I libssh2`
version=`$PKGCONFIG --modversion libssh2`
- DIR_SSH2=`echo $LD_SSH2 | $SED -e 's/-L//'`
+ DIR_SSH2=`echo $LD_SSH2 | $SED -e 's/^-L//'`
fi
;;
@@ -3039,7 +3086,7 @@ elif test X"$OPT_LIBSSH" != Xno; then
LD_SSH=`$PKGCONFIG --libs-only-L libssh`
CPP_SSH=`$PKGCONFIG --cflags-only-I libssh`
version=`$PKGCONFIG --modversion libssh`
- DIR_SSH=`echo $LD_SSH | $SED -e 's/-L//'`
+ DIR_SSH=`echo $LD_SSH | $SED -e 's/^-L//'`
fi
;;
@@ -3149,7 +3196,7 @@ if test X"$OPT_LIBRTMP" != Xno; then
LD_RTMP=`$PKGCONFIG --libs-only-L librtmp`
CPP_RTMP=`$PKGCONFIG --cflags-only-I librtmp`
version=`$PKGCONFIG --modversion librtmp`
- DIR_RTMP=`echo $LD_RTMP | $SED -e 's/-L//'`
+ DIR_RTMP=`echo $LD_RTMP | $SED -e 's/^-L//'`
else
dnl To avoid link errors, we do not allow --librtmp without
dnl a pkgconfig file
@@ -3387,7 +3434,7 @@ if test "$want_idn" = "yes"; then
$PKGCONFIG --libs-only-L libidn2 2>/dev/null`
IDN_CPPFLAGS=`CURL_EXPORT_PCDIR([$IDN_PCDIR]) dnl
$PKGCONFIG --cflags-only-I libidn2 2>/dev/null`
- IDN_DIR=`echo $IDN_LDFLAGS | $SED -e 's/-L//'`
+ IDN_DIR=`echo $IDN_LDFLAGS | $SED -e 's/^-L//'`
else
dnl pkg-config not available or provides no info
IDN_LIBS="-lidn2"
@@ -3402,7 +3449,7 @@ if test "$want_idn" = "yes"; then
IDN_LIBS=`$PKGCONFIG --libs-only-l libidn2 2>/dev/null`
IDN_LDFLAGS=`$PKGCONFIG --libs-only-L libidn2 2>/dev/null`
IDN_CPPFLAGS=`$PKGCONFIG --cflags-only-I libidn2 2>/dev/null`
- IDN_DIR=`echo $IDN_LDFLAGS | $SED -e 's/-L//'`
+ IDN_DIR=`echo $IDN_LDFLAGS | $SED -e 's/^-L//'`
else
dnl pkg-config not available or provides no info
IDN_LIBS="-lidn2"
@@ -3611,7 +3658,7 @@ if test X"$want_tcp2" != Xno; then
LIBS="$LIB_TCP2 $LIBS"
if test "x$cross_compiling" != "xyes"; then
- DIR_TCP2=`echo $LD_TCP2 | $SED -e 's/-L//'`
+ DIR_TCP2=`echo $LD_TCP2 | $SED -e 's/^-L//'`
fi
AC_CHECK_LIB(ngtcp2, ngtcp2_conn_client_new,
[
@@ -3667,7 +3714,7 @@ if test "x$NGTCP2_ENABLED" = "x1" -a "x$OPENSSL_ENABLED" = "x1"; then
LIBS="$LIB_NGTCP2_CRYPTO_OPENSSL $LIBS"
if test "x$cross_compiling" != "xyes"; then
- DIR_NGTCP2_CRYPTO_OPENSSL=`echo $LD_NGTCP2_CRYPTO_OPENSSL | $SED -e 's/-L//'`
+ DIR_NGTCP2_CRYPTO_OPENSSL=`echo $LD_NGTCP2_CRYPTO_OPENSSL | $SED -e 's/^-L//'`
fi
AC_CHECK_LIB(ngtcp2_crypto_openssl, ngtcp2_crypto_ctx_initial,
[
@@ -3722,7 +3769,7 @@ if test "x$NGTCP2_ENABLED" = "x1" -a "x$GNUTLS_ENABLED" = "x1"; then
LIBS="$LIB_NGTCP2_CRYPTO_GNUTLS $LIBS"
if test "x$cross_compiling" != "xyes"; then
- DIR_NGTCP2_CRYPTO_GNUTLS=`echo $LD_NGTCP2_CRYPTO_GNUTLS | $SED -e 's/-L//'`
+ DIR_NGTCP2_CRYPTO_GNUTLS=`echo $LD_NGTCP2_CRYPTO_GNUTLS | $SED -e 's/^-L//'`
fi
AC_CHECK_LIB(ngtcp2_crypto_gnutls, ngtcp2_crypto_ctx_initial,
[
@@ -3810,7 +3857,7 @@ if test X"$want_nghttp3" != Xno; then
LIBS="$LIB_NGHTTP3 $LIBS"
if test "x$cross_compiling" != "xyes"; then
- DIR_NGHTTP3=`echo $LD_NGHTTP3 | $SED -e 's/-L//'`
+ DIR_NGHTTP3=`echo $LD_NGHTTP3 | $SED -e 's/^-L//'`
fi
AC_CHECK_LIB(nghttp3, nghttp3_conn_client_new,
[
@@ -3900,7 +3947,7 @@ if test X"$want_quiche" != Xno; then
LIBS="$LIB_QUICHE $LIBS"
if test "x$cross_compiling" != "xyes"; then
- DIR_QUICHE=`echo $LD_QUICHE | $SED -e 's/-L//'`
+ DIR_QUICHE=`echo $LD_QUICHE | $SED -e 's/^-L//'`
fi
AC_CHECK_LIB(quiche, quiche_connect,
[
@@ -3911,6 +3958,7 @@ if test X"$want_quiche" != Xno; then
QUICHE_ENABLED=1
AC_DEFINE(USE_QUICHE, 1, [if quiche is in use])
AC_SUBST(USE_QUICHE, [1])
+ AC_CHECK_FUNCS([quiche_conn_set_qlog_fd])
CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_QUICHE"
export CURL_LIBRARY_PATH
AC_MSG_NOTICE([Added $DIR_QUICHE to CURL_LIBRARY_PATH]),
@@ -4155,6 +4203,19 @@ AC_CHECK_TYPE(sa_family_t,
#endif
])
+# check for suseconds_t
+AC_CHECK_TYPE([suseconds_t],[
+ AC_DEFINE(HAVE_SUSECONDS_T, 1,
+ [Define to 1 if suseconds_t is an available type.])
+], ,[
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+])
+
AC_MSG_CHECKING([if time_t is unsigned])
CURL_RUN_IFELSE(
[
@@ -4415,9 +4476,17 @@ if test "$want_pthreads" != "no"; then
AC_CHECK_HEADER(pthread.h,
[ AC_DEFINE(HAVE_PTHREAD_H, 1, [if you have <pthread.h>])
save_CFLAGS="$CFLAGS"
-
- dnl first check for function without lib
+ dnl When statically linking against boringssl, -lpthread is added to LIBS.
+ dnl Make sure to that this does not pass the check below, we really want
+ dnl -pthread in CFLAGS as recommended for GCC. This also ensures that
+ dnl lib1541 and lib1565 tests are built with these options. Otherwise
+ dnl they fail the build since tests/libtest/Makefile.am clears LIBS.
+ save_LIBS="$LIBS"
+
+ LIBS=
+ dnl Check for libc variants without a separate pthread lib like bionic
AC_CHECK_FUNC(pthread_create, [USE_THREADS_POSIX=1] )
+ LIBS="$save_LIBS"
dnl on HPUX, life is more complicated...
case $host in
@@ -4830,6 +4899,13 @@ dnl to let curl-config output the static libraries correctly
ENABLE_STATIC="$enable_static"
AC_SUBST(ENABLE_STATIC)
+dnl merge the pkg-config Libs.private field into Libs when static-only
+if test "x$enable_shared" = "xno"; then
+ LIBCURL_NO_SHARED=$LIBCURL_LIBS
+else
+ LIBCURL_NO_SHARED=
+fi
+AC_SUBST(LIBCURL_NO_SHARED)
dnl
dnl For keeping supported features and protocols also in pkg-config file
@@ -4889,7 +4965,8 @@ fi
if test "x$CURL_DISABLE_CRYPTO_AUTH" != "x1"; then
if test "x$OPENSSL_ENABLED" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" \
-o "x$GNUTLS_ENABLED" = "x1" -o "x$MBEDTLS_ENABLED" = "x1" \
- -o "x$NSS_ENABLED" = "x1" -o "x$SECURETRANSPORT_ENABLED" = "x1"; then
+ -o "x$NSS_ENABLED" = "x1" -o "x$SECURETRANSPORT_ENABLED" = "x1" \
+ -o "x$WOLFSSL_NTLM" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES NTLM"
if test "x$CURL_DISABLE_HTTP" != "x1" -a \
@@ -4982,7 +5059,8 @@ if test "x$CURL_DISABLE_SMB" != "x1" \
-a "x$CURL_DISABLE_CRYPTO_AUTH" != "x1" \
-a \( "x$OPENSSL_ENABLED" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" \
-o "x$GNUTLS_ENABLED" = "x1" -o "x$MBEDTLS_ENABLED" = "x1" \
- -o "x$NSS_ENABLED" = "x1" -o "x$SECURETRANSPORT_ENABLED" = "x1" \); then
+ -o "x$NSS_ENABLED" = "x1" -o "x$SECURETRANSPORT_ENABLED" = "x1" \
+ -o "x$WOLFSSL_NTLM" = "x1" \); then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SMB"
if test "x$SSL_ENABLED" = "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SMBS"
@@ -5003,7 +5081,6 @@ if test "x$USE_LIBSSH" = "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SFTP"
fi
if test "x$USE_WOLFSSH" = "x1"; then
- SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SCP"
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SFTP"
fi
if test "x$CURL_DISABLE_RTSP" != "x1"; then
diff --git a/docs/CHECKSRC.md b/docs/CHECKSRC.md
index 10e2f4d73..96150922b 100644
--- a/docs/CHECKSRC.md
+++ b/docs/CHECKSRC.md
@@ -9,7 +9,7 @@ check that it adheres to our [Source Code Style guide](CODE_STYLE.md).
## Command line options
-`-W[file]` whitelists that file and excludes it from being checked. Helpful
+`-W[file]` skip that file and excludes it from being checked. Helpful
when, for example, one of the files is generated.
`-D[dir]` directory name to prepend to file names when accessing them.
@@ -158,5 +158,5 @@ instances are ignored and nothing extra.
This is a method we've transitioned away from. Use inline ignores as far as
possible.
-Make a `checksrc.whitelist` file in the directory of the source code with the
+Make a `checksrc.skip` file in the directory of the source code with the
false positive, and include the full offending line into this file.
diff --git a/docs/CODE_REVIEW.md b/docs/CODE_REVIEW.md
new file mode 100644
index 000000000..f55cb0985
--- /dev/null
+++ b/docs/CODE_REVIEW.md
@@ -0,0 +1,168 @@
+# How to do code reviews for curl
+
+Anyone and everyone is encouraged and welcome to review code submissions in
+curl. This is a guide on what to check for and how to perform a successful
+code review.
+
+## All submissions should get reviewed
+
+All pull requests and patches submitted to the project should be reviewed by
+at least one experienced curl maintainer before that code is accepted and
+merged.
+
+## Let the tools and tests take the first rounds
+
+On initial pull requests, let the tools and tests do their job first and then
+start out by helping the submitter understand the test failures and tool
+alerts.
+
+## How to provide feedback to author
+
+Be nice. Ask questions. Provide examples or suggestions of improvements.
+Assume best intentions. Remember language barriers.
+
+All first-time contributors can become regulars. Let's help them go there.
+
+## Is this a change we want?
+
+If this is not a change that seems to be aligned with the project's path
+forward and as such cannot be accepted, inform the author about this sooner
+rather than later. Do it gently and explain why and possibly what could be
+done to make it more acceptable.
+
+## API/ABI stability or changed behavior
+
+Changing the API and the ABI may be fine in a change but it needs to be done
+deliberately and carefully. If not, a reviewer must help the author to realize
+the mistake.
+
+curl and libcurl are similarly very strict on not modifying existing
+behavior. API and ABI stability is not enough, the behavior should also remain
+intact as far as possible.
+
+## Code style
+
+Most code style nits are detected by checksrc but not all. Only leave remarks
+on style deviation once checksrc doesn't find any more.
+
+Minor nits from fresh submitters can also be handled by the maintainer when
+merging, in case it seems like the submitter isn't clear on what to do. We
+want to make the process fun and exciting for new contributors.
+
+## Encourage consistency
+
+Make sure new code is written in a similar style as existing code. Naming,
+logic, conditions, etc.
+
+## Are pointers always non-NULL?
+
+If a function or code rely on pointers being non-NULL, take an extra look if
+that seems to be a fair assessment.
+
+## Asserts
+
+Conditions that should never be false can be verified with `DEBUGASSERT()`
+calls to get caught in tests and debugging easier, while not having an impact
+on final or release builds.
+
+## Memory allocation
+
+Can the mallocs be avoided? Do not introduce mallocs in any hot paths. If
+there are (new) mallocs, can they be combined into fewer calls?
+
+Are all allocations handled in errorpaths to avoid leaks and crashes?
+
+## Thread-safety
+
+We do not like static variables as they break thread-safety and prevent
+functions from being reentrant.
+
+## Should features be `#ifdef`ed?
+
+Features and functionality may not be present everywhere and should therefore
+be `#ifdef`ed. Additionally, some features should be possible to switch on/off
+in the build.
+
+Write `#ifdef`s to be as little of a "maze" as possible.
+
+## Does it look portable enough?
+
+curl runs "everywhere". Does the code take a reasonable stance and enough
+precautions to be possible to build and run on most platforms?
+
+Remember that we live by C89 restrictions.
+
+## Tests and testability
+
+New features should be added in conjunction with one or more test cases.
+Ideally, functions should also be written so that unit tests can be done to
+test individual functions.
+
+## Documentation
+
+New features or changes to existing functionality **must** be accompanied with
+updated documentation. Submitting that in a separate follow-up pull request is
+not OK. A code review must also verify that the submitted documentation update
+matches the code submission.
+
+English isn't everyone's first language, be mindful of this and help the
+submitter improve the text if it needs a rewrite to read better.
+
+## Code shouldn't be hard to understand
+
+Source code should be written to maximize readability and be easy to
+understand.
+
+## Functions shouldn't be large
+
+A single function should never be large as that makes it hard to follow and
+understand all the exit points and state changes. Some existing functions in
+curl certainly violate this ground rule but when reviewing new code we should
+propose splitting into smaller functions.
+
+## Duplication is evil
+
+Anything that looks like duplicated code is a red flag. Anything that seems to
+introduce code that we *should* already have or provide needs a closer check.
+
+## Sensitive data
+
+When credentials are involved, take an extra look at what happens with this
+data. Where it comes from and where it goes.
+
+## Variable types differ
+
+`size_t` is not a fixed size. `time_t` can be signed or unsigned and have
+different sizes. Relying on variable sizes is a red flag.
+
+Also remember that endianness and >= 32 bit accesses to unaligned addresses
+are problematic areas.
+
+## Integer overflows
+
+Be careful about integer overflows. Some variable types can be either 32 bit
+or 64 bit. Integer overflows must be detected and acted on *before* they
+happen.
+
+## Dangerous use of functions
+
+Maybe use of `realloc()` should rather use the dynbuf functions?
+
+Do not allow new code that grows buffers without using dynbuf.
+
+Use of C functions that rely on a terminating zero must only be used on data
+that really do have a zero terminating zero.
+
+## Dangerous "data styles"
+
+Make extra precautions and verify that memory buffers that need a terminating
+zero always have exactly that. Buffers *without* a zero terminator must not be
+used as input to string functions.
+
+# Commit messages
+
+Tightly coupled with a code review is making sure that the commit message is
+good. It is the responsibilitiy of the person who merges the code to make sure
+that the commit message follows our standard (detailed in the
+[CONTRIBUTE.md](CONTRIBUTE.md) document). This includes making sure the PR
+identifies related issues and giving credit to reporters and helpers.
diff --git a/docs/CODE_STYLE.md b/docs/CODE_STYLE.md
index 0ceb5b9ad..561343752 100644
--- a/docs/CODE_STYLE.md
+++ b/docs/CODE_STYLE.md
@@ -244,3 +244,22 @@ depending on a build-time conditional:
#endif
int content = magic(3);
+
+## No typedefed structs
+
+Use structs by all means, but do not typedef them. Use the `struct name` way
+of identifying them:
+
+ struct something {
+ void *valid;
+ size_t way_to_write;
+ };
+ struct something instance;
+
+**Not okay**:
+
+ typedef struct {
+ void *wrong;
+ size_t way_to_write;
+ } something;
+ something instance;
diff --git a/docs/DYNBUF.md b/docs/DYNBUF.md
new file mode 100644
index 000000000..382c1365d
--- /dev/null
+++ b/docs/DYNBUF.md
@@ -0,0 +1,80 @@
+# dynbuf
+
+This is the internal module for creating and handling "dynamic buffers". This
+means buffers that can be appended to, dynamically and grow in size to adapt.
+
+There will always be a terminating zero put at the end of the dynamic buffer.
+
+The `struct dynbuf` is used to hold data for each instance of a dynamic
+buffer. The members of that struct **MUST NOT** be accessed or modified
+without using the dedicated dynbuf API.
+
+## init
+
+ void Curl_dyn_init(struct dynbuf *s, size_t toobig);
+
+This inits a struct to use for dynbuf and it can't fail. The `toobig` value
+**must** be set to the maximum size we allow this buffer instance to grow to.
+The functions below will return `CURLE_OUT_OF_MEMORY` when hitting this limit.
+
+## free
+
+ void Curl_dyn_free(struct dynbuf *s);
+
+Free the associated memory and clean up. After a free, the `dynbuf` struct can
+be re-used to start appending new data to.
+
+## addn
+
+ CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len);
+
+Append arbitrary data of a given length to the end of the buffer.
+
+## add
+
+ CURLcode Curl_dyn_add(struct dynbuf *s, const char *str);
+
+Append a C string to the end of the buffer.
+
+## addf
+
+ CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...);
+
+Append a `printf()`-style string to the end of the buffer.
+
+## reset
+
+ void Curl_dyn_reset(struct dynbuf *s);
+
+Reset the buffer length, but leave the allocation.
+
+## tail
+
+ CURLcode Curl_dyn_tail(struct dynbuf *s, size_t length)
+
+Keep `length` bytes of the buffer tail (the last `length` bytes of the
+buffer). The rest of the buffer is dropped. The specified `length` must not be
+larger than the buffer length.
+
+## ptr
+
+ char *Curl_dyn_ptr(const struct dynbuf *s);
+
+Returns a `char *` to the buffer if it has a length, otherwise a NULL. Since
+the buffer may be reallocated, this pointer should not be trusted or used
+anymore after the next buffer manipulation call.
+
+## uptr
+
+ unsigned char *Curl_dyn_uptr(const struct dynbuf *s);
+
+Returns an `unsigned char *` to the buffer if it has a length, otherwise a
+NULL. Since the buffer may be reallocated, this pointer should not be trusted
+or used anymore after the next buffer manipulation call.
+
+## len
+
+ size_t Curl_dyn_len(const struct dynbuf *s);
+
+Returns the length of the buffer in bytes. Does not include the terminating
+zero byte.
diff --git a/docs/EXPERIMENTAL.md b/docs/EXPERIMENTAL.md
index 34974fba8..bca2bd910 100644
--- a/docs/EXPERIMENTAL.md
+++ b/docs/EXPERIMENTAL.md
@@ -21,3 +21,4 @@ Experimental support in curl means:
- HTTP/3 support and options
- alt-svc support and options
- MQTT
+ - CURLSSLOPT_NATIVE_CA (No configure option, feature built in when supported)
diff --git a/docs/FAQ b/docs/FAQ
index 53f1c9e7a..7bd121cef 100644
--- a/docs/FAQ
+++ b/docs/FAQ
@@ -136,8 +136,9 @@ FAQ
libcurl
A free and easy-to-use client-side URL transfer library, supporting DICT,
- FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3,
- POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET and TFTP.
+ FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT,
+ POP3, POP3S, RTMP, RTMPS, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET
+ and TFTP.
libcurl supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading,
Kerberos, SPNEGO, HTTP form based upload, proxies, cookies, user+password
diff --git a/docs/GOVERNANCE.md b/docs/GOVERNANCE.md
index 81747179b..30df155b5 100644
--- a/docs/GOVERNANCE.md
+++ b/docs/GOVERNANCE.md
@@ -49,7 +49,7 @@ Donations to the project can also come in form of server hosting, providing
services and paying for people to work on curl related code etc. Usually, such
donations are services paid for directly by the sponsors.
-We grade sponsors in a few different levels and if they meet the criterias,
+We grade sponsors in a few different levels and if they meet the criteria,
they can be mentioned on the Sponsors page on the curl web site.
## Commercial Support
diff --git a/docs/HELP-US.md b/docs/HELP-US.md
index aae2b9f59..54744346a 100644
--- a/docs/HELP-US.md
+++ b/docs/HELP-US.md
@@ -15,6 +15,23 @@ 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.
+## Smaller tasks
+
+Some projects mark small issues as "beginner friendly", "bite-sized" or
+similar. We don't do that in curl since such issues never linger around long
+enough. Simple issues get handled very fast.
+
+If you're looking for a smaller or simpler task in the project to help out
+with as an entry-point into the project, perhaps because you are a newcomer or
+even maybe not a terribly experienced developer, here's our advice:
+
+ - Read through this document to get a grasp on a general approach to use
+ - Consider adding a test case for something not currentled tested (correctly)
+ - Consider updating or adding documentation
+ - One way to get your feet wet gently in the project, is to participate in an
+ existing issue/PR and help out by reproducing the issue, review the code in
+ the PR etc.
+
## Help wanted
In the issue tracker we occasionally mark bugs with [help
diff --git a/docs/HTTP3.md b/docs/HTTP3.md
index 2769439d6..e54e5d028 100644
--- a/docs/HTTP3.md
+++ b/docs/HTTP3.md
@@ -112,26 +112,13 @@ Build curl
## build
-Clone quiche and BoringSSL:
+Build quiche and BoringSSL:
% git clone --recursive https://github.com/cloudflare/quiche
-
-Build BoringSSL (it needs to be built manually so it can be reused with curl):
-
- % cd quiche/deps/boringssl
- % mkdir build
- % cd build
- % cmake -DCMAKE_POSITION_INDEPENDENT_CODE=on ..
- % make
- % cd ..
- % mkdir -p .openssl/lib
- % cp build/crypto/libcrypto.a build/ssl/libssl.a .openssl/lib
- % ln -s $PWD/include .openssl
-
-Build quiche:
-
- % cd ../..
- % QUICHE_BSSL_PATH=$PWD/deps/boringssl cargo build --release --features pkg-config-meta
+ % cd quiche
+ % cargo build --release --features pkg-config-meta,qlog
+ % mkdir deps/boringssl/lib
+ % ln -vnf $(find target/release -name libcrypto.a -o -name libssl.a) deps/boringssl/lib/
Build curl:
@@ -139,7 +126,7 @@ Build curl:
% git clone https://github.com/curl/curl
% cd curl
% ./buildconf
- % ./configure LDFLAGS="-Wl,-rpath,$PWD/../quiche/target/release" --with-ssl=$PWD/../quiche/deps/boringssl/.openssl --with-quiche=$PWD/../quiche/target/release --enable-alt-svc
+ % ./configure LDFLAGS="-Wl,-rpath,$PWD/../quiche/target/release" --with-ssl=$PWD/../quiche/deps/boringssl --with-quiche=$PWD/../quiche/target/release --enable-alt-svc
% make
## Run
diff --git a/docs/INSTALL.cmake b/docs/INSTALL.cmake
index 03328cbcd..c967b0851 100644
--- a/docs/INSTALL.cmake
+++ b/docs/INSTALL.cmake
@@ -25,8 +25,7 @@ Current flaws in the curl CMake build
- Builds libcurl without large file support
- Does not support all SSL libraries (only OpenSSL, WinSSL, DarwinSSL, and
- mbed TLS)
- - Doesn't build with SCP and SFTP support (libssh2) (see issue #1155)
+ mbed TLS, NSS, WolfSSL)
- Doesn't allow different resolver backends (no c-ares build support)
- No RTMP support built
- Doesn't allow build curl and libcurl debug enabled
diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS
index 93cb36902..606983bb8 100644
--- a/docs/KNOWN_BUGS
+++ b/docs/KNOWN_BUGS
@@ -43,19 +43,18 @@ problems may have been fixed or changed somewhat since this was written!
4.1 -J and -O with %-encoded file names
4.2 -J with -C - fails
4.3 --retry and transfer timeouts
- 4.4 --upload-file . hang if delay in STDIN
- 4.5 Improve --data-urlencode space encoding
+ 4.4 Improve --data-urlencode space encoding
5. Build and portability issues
+ 5.1 OS400 port requires deprecated IBM library
5.2 curl-config --libs contains private details
5.3 curl compiled on OSX 10.13 failed to run on OSX 10.10
- 5.4 Cannot compile against a static build of OpenLDAP
- 5.5 can't handle Unicode arguments in Windows
+ 5.4 Build with statically built dependency
+ 5.5 can't handle Unicode arguments in non-Unicode builds on Windows
5.6 cmake support gaps
5.7 Visual Studio project gaps
5.8 configure finding libs in wrong directory
5.9 Utilize Requires.private directives in libcurl.pc
- 5.10 IDN tests failing on Windows / MSYS2
5.11 configure --with-gssapi with Heimdal is ignored on macOS
6. Authentication
@@ -66,6 +65,7 @@ problems may have been fixed or changed somewhat since this was written!
6.5 NTLM doesn't support password with § character
6.6 libcurl can fail to try alternatives with --proxy-any
6.7 Don't clear digest for single realm
+ 6.8 RTSP authentication breaks without redirect support
7. FTP
7.1 FTP without or slow 220 response
@@ -85,6 +85,7 @@ problems may have been fixed or changed somewhat since this was written!
9. SFTP and SCP
9.1 SFTP doesn't do CURLOPT_POSTQUOTE correct
+ 9.2 wolfssh: publickey auth doesn't work
10. SOCKS
10.3 FTPS over SOCKS
@@ -200,8 +201,8 @@ problems may have been fixed or changed somewhat since this was written!
2.1 CURLINFO_SSL_VERIFYRESULT has limited support
- CURLINFO_SSL_VERIFYRESULT is only implemented for the OpenSSL and NSS
- backends, so relying on this information in a generic app is flaky.
+ CURLINFO_SSL_VERIFYRESULT is only implemented for the OpenSSL, NSS and
+ GnuTLS backends, so relying on this information in a generic app is flaky.
2.2 DER in keychain
@@ -337,15 +338,7 @@ problems may have been fixed or changed somewhat since this was written!
https://curl.haxx.se/mail/lib-2008-01/0080.html and Mandriva bug report
https://qa.mandriva.com/show_bug.cgi?id=22565
-4.4 --upload-file . hangs if delay in STDIN
-
- "(echo start; sleep 1; echo end) | curl --upload-file . http://mywebsite -vv"
-
- ... causes a hang when it shouldn't.
-
- See https://github.com/curl/curl/issues/2051
-
-4.5 Improve --data-urlencode space encoding
+4.4 Improve --data-urlencode space encoding
ASCII space characters in --data-urlencode are currently encoded as %20
rather than +, which RFC 1866 says should be used.
@@ -354,6 +347,14 @@ problems may have been fixed or changed somewhat since this was written!
5. Build and portability issues
+5.1 OS400 port requires deprecated IBM library
+
+ curl for OS400 requires QADRT to build, which provides ASCII wrappers for
+ libc/POSIX functions in the ILE, but IBM no longer supports or even offers
+ this library to download.
+
+ See https://github.com/curl/curl/issues/5176
+
5.2 curl-config --libs contains private details
"curl-config --libs" will include details set in LDFLAGS when configure is
@@ -364,20 +365,40 @@ problems may have been fixed or changed somewhat since this was written!
See https://github.com/curl/curl/issues/2905
-5.4 Cannot compile against a static build of OpenLDAP
+5.4 Build with statically built dependency
+
+ The build scripts in curl (autotools, cmake and others) are primarily done to
+ work with shared/dynamic third party dependencies. When linking with shared
+ libraries, the dependency "chain" is handled automatically by the library
+ loader - on all modern systems.
+
+ If you instead link with a static library, we need to provide all the
+ dependency libraries already at the link command line.
+
+ Figuring out all the dependency libraries for a given library is hard, as it
+ might also involve figuring out the dependencies of the dependencies and they
+ may vary between platforms and even change between versions.
- See https://github.com/curl/curl/issues/2367
+ When using static dependencies, the build scripts will mostly assume that
+ you, the user, will provide all the necessary additional dependency libraries
+ as additional arguments in the build. With configure, by setting LIBS/LDFLAGS
+ on the command line.
-5.5 can't handle Unicode arguments in Windows
+ We welcome help to improve curl's ability to link with static libraries, but
+ it is likely a task that we can never fully support.
+
+5.5 can't handle Unicode arguments in non-Unicode builds on Windows
If a URL or filename can't be encoded using the user's current codepage then
it can only be encoded properly in the Unicode character set. Windows uses
UTF-16 encoding for Unicode and stores it in wide characters, however curl
- and libcurl are not equipped for that at the moment. And, except for Cygwin,
- Windows can't use UTF-8 as a locale.
+ and libcurl are not equipped for that at the moment except when built with
+ _UNICODE and UNICODE defined. And, except for Cygwin, Windows can't use UTF-8
+ as a locale.
https://curl.haxx.se/bug/?i=345
https://curl.haxx.se/bug/?i=731
+ https://curl.haxx.se/bug/?i=3747
5.6 cmake support gaps
@@ -430,13 +451,6 @@ problems may have been fixed or changed somewhat since this was written!
https://github.com/curl/curl/issues/864
-5.10 IDN tests failing on Windows / MSYS2
-
- It seems like MSYS2 does some UTF-8-to-something-else conversion for Windows
- compatibility.
-
- https://github.com/curl/curl/issues/3747
-
5.11 configure --with-gssapi with Heimdal is ignored on macOS
... unless you also pass --with-gssapi-libs
@@ -499,6 +513,15 @@ problems may have been fixed or changed somewhat since this was written!
https://github.com/curl/curl/issues/3267
+6.8 RTSP authentication breaks without redirect support
+
+ RTSP authentication broke in 7.66.0. A work-around is to enable RTSP in
+ CURLOPT_REDIR_PROTOCOLS. Authentication should however not be considered an
+ actual redirect so a "proper" fix needs to be different and not require users
+ to allow redirects to RTSP to work.
+
+ See https://github.com/curl/curl/pull/4750
+
7. FTP
7.1 FTP without or slow 220 response
@@ -620,6 +643,13 @@ problems may have been fixed or changed somewhat since this was written!
report but it cannot be accepted as-is. See
https://curl.haxx.se/bug/view.cgi?id=748
+9.2 wolfssh: publickey auth doesn't work
+
+ When building curl to use the wolfSSH backend for SFTP, the publickey
+ authentication doesn't work. This is simply functionality not written for curl
+ yet, the necessary API for make this work is provided by wolfSSH.
+
+ See https://github.com/curl/curl/issues/4820
10. SOCKS
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 63460b1ff..820764528 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -45,10 +45,12 @@ EXTRA_DIST = \
CHECKSRC.md \
CIPHERS.md \
CODE_OF_CONDUCT.md \
+ CODE_REVIEW.md \
CODE_STYLE.md \
CONTRIBUTE.md \
CURL-DISABLE.md \
DEPRECATE.md \
+ DYNBUF.md \
ESNI.md \
EXPERIMENTAL.md \
FAQ \
@@ -67,6 +69,7 @@ EXTRA_DIST = \
LICENSE-MIXING.md \
MAIL-ETIQUETTE \
MQTT.md \
+ options-in-versions \
PARALLEL-TRANSFERS.md \
README.md \
RELEASE-PROCEDURE.md \
@@ -78,7 +81,7 @@ EXTRA_DIST = \
THANKS \
TODO \
TheArtOfHttpScripting \
- VERSIONS
+ VERSIONS.md
SUFFIXES = .1
diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md
index 7bd07196f..dae72a917 100644
--- a/docs/ROADMAP.md
+++ b/docs/ROADMAP.md
@@ -34,19 +34,6 @@ thread-safe `curl_global_init()`
it can be thread-safe if built with thread-safe 3rd party libraries.
(probably can't include `curl_global_init_mem()` for obvious reasons)
-tiny-curl
----------
-
- There's no immediate action for this but users seem keen on being able to
- building custom minimized versions of libcurl for their products. Make sure
- new features that are "niche" can still be disabled at build-time.
-
-MQTT
-----
-
- Support receiving and sending MQTT messages. Initial work exists in
- https://github.com/curl/curl/pull/3514
-
Hardcode “localhostâ€
--------------------
@@ -54,10 +41,3 @@ Hardcode “localhostâ€
and actually responds with something else than a local address. Some
operating systems already do this. Also:
https://tools.ietf.org/html/draft-ietf-dnsop-let-localhost-be-localhost-02
-
-"menu config"-style build feature selection
--------------------------------------------
-
- Allow easier building of custom libcurl versions with only a selected feature
- where the available features are easily browsable and toggle-able ON/OFF or
- similar.
diff --git a/docs/SSL-PROBLEMS.md b/docs/SSL-PROBLEMS.md
index aaf7bdb59..35000cf76 100644
--- a/docs/SSL-PROBLEMS.md
+++ b/docs/SSL-PROBLEMS.md
@@ -78,7 +78,7 @@
depending on the OS or build configuration. The --ssl-no-revoke option was
introduced in 7.44.0 to disable revocation checking but currently is only
supported for Schannel (the native Windows SSL library), with an exception
- in the case of Windows' Untrusted Publishers blacklist which it seems can't
+ in the case of Windows' Untrusted Publishers block list which it seems can't
be bypassed. This option may have broader support to accommodate other SSL
backends in the future.
diff --git a/docs/THANKS b/docs/THANKS
index d39deffbf..76587bddf 100644
--- a/docs/THANKS
+++ b/docs/THANKS
@@ -24,6 +24,7 @@ Adam Marcionek
Adam Piggott
Adam Sampson
Adam Tkac
+Adnan Khan
adnn on github
Adrian Burcea
Adrian Peniak
@@ -82,6 +83,7 @@ Alexander Sinditskiy
Alexander Traud
Alexander V. Tikhonov
Alexander Zhuravlev
+Alexandre Pion
Alexey Borzov
Alexey Eremikhin
Alexey Melnichuk
@@ -203,6 +205,7 @@ Balint Szilakszi
Barry Abrahamson
Barry Pollard
Bart Whiteley
+Baruch Siach
Bas Mevissen
Bas van Schaik
Bastien Bouclet
@@ -243,6 +246,7 @@ Bill Hoffman
Bill Middlecamp
Bill Nagel
Bill Pyne
+Billyzou0741326 on github
Bjarni Ingi Gislason
Bjoern Franke
Bjoern Sikora
@@ -318,6 +322,7 @@ Chandrakant Bagul
Charles Kerr
Charles Romestant
Chen Prog
+Cherish98 on github
Chester Liu
Chih-Chung Chang
Chih-Hsuan Yen
@@ -372,6 +377,7 @@ cmfrolick on github
codesniffer13 on github
Cody Jones
Cody Mack
+coinhubs on github
Colby Ranger
Colin Blair
Colin Hogben
@@ -498,6 +504,7 @@ David Yan
davidedec on github
dbrowndan on github
Dengminwen
+Denis BaruÄić
Denis Chaplygin
Denis Feklushkin
Denis Ollier
@@ -633,6 +640,7 @@ Ernest Beinrohr
Ernst Sjöstrand
Erwan Legrand
Erwin Authried
+Estanislau Augé-Pujadas
Ethan Glasser Camp
Etienne Simard
Eugene Kotlyarov
@@ -684,6 +692,7 @@ Frank Ticheler
Frank Van Uffelen
FrantiÅ¡ek KuÄera
François Charlier
+François Rigault
Fred Machado
Fred New
Fred Noz
@@ -744,6 +753,7 @@ Greg Onufer
Greg Pratt
Greg Rowe
Greg Zavertnik
+Gregory Jefferis
Gregory Nicholls
Gregory Szorc
Griffin Downs
@@ -802,7 +812,9 @@ Howard Blaise
Howard Chu
hsiao yi
Hubert Kario
+Hugo van Kemenade
Huzaifa Sidhpurwala
+huzunhao on github
hydra3333 on github
Hzhijun
Ian D Allen
@@ -865,6 +877,7 @@ James Gallagher
James Griffiths
James Housley
James Knight
+James Le Cuirot
James MacMillan
James Slaughter
Jamie Lokier
@@ -993,6 +1006,7 @@ John Marshall
John McGowan
John P. McCaskey
John Schroeder
+John Simpson
John Starks
John Suprock
John V. Chow
@@ -1004,6 +1018,7 @@ Johnny Luong
Jojojov on github
Jon DeVree
Jon Grubbs
+Jon Johnson Jr
Jon Nelson
Jon Rumsey
Jon Sargeant
@@ -1078,6 +1093,7 @@ Kai Sommerfeld
Kai-Uwe Rommel
Kalle Vahlman
Kamil Dudka
+Kane York
Kang Lin
Kang-Jin Lee
Karl Chen
@@ -1119,6 +1135,7 @@ Kobi Gurkan
Koen Dergent
Konstantin Isakov
Konstantin Kushnir
+kotoriã®ã­ã“
kouzhudong on github
kreshano on github
Kris Kennaway
@@ -1199,6 +1216,7 @@ Luca Boccassi
Lucas Adamski
Lucas Pardue
Lucas Severo
+Lucien Zürcher
Ludek Finstrle
Ludovico Cavedon
Ludwig Nussel
@@ -1296,6 +1314,7 @@ Martin Lemke
Martin Skinner
Martin Staael
Martin Storsjö
+Martin V
Martin Vejnár
Marty Kuhrt
Maruko
@@ -1333,6 +1352,7 @@ Max Dymond
Max Katsev
Max Kellermann
Max Khon
+Max Peal
Max Savenkov
Maxim Ivanov
Maxim Perenesenko
@@ -1418,6 +1438,7 @@ Mischa Salle
Mitz Wark
mkzero on github
Mohamed Lrhazi
+Mohamed Osama
Mohammad AlSaleh
Mohammad Hasbini
Mohun Biswas
@@ -1428,6 +1449,7 @@ Moti Avrahami
MrdUkk on github
MrSorcus on github
Muhammad Herdiansyah
+Murugan Balraj
Muz Dima
Myk Taylor
Nach M. S.
@@ -1471,6 +1493,7 @@ Nicolas François
Nicolas Grekas
Nicolas Guillier
Nicolas Morey-Chaisemartin
+Nicolas Sterchele
Niels van Tongeren
Nikita Schmidt
Nikitinskit Dmitriy
@@ -1642,11 +1665,14 @@ Praveen Pvs
Priyanka Shah
Przemysław Tomaszewski
pszemus on github
+puckipedia on github
Puneet Pawaia
+qiandu2006 on github
Quagmire
Quanah Gibson-Mount
Quinn Slack
R. Dennis Steed
+Radoslav Georgiev
Radu Simionescu
Rafa Muyo
Rafael Antonio
@@ -1695,6 +1721,7 @@ Rich Burridge
Rich Gray
Rich Mirch
Rich Rauenzahn
+Rich Salz
Rich Turner
Richard Adams
Richard Alcock
@@ -1725,6 +1752,7 @@ Ricky Leverence
Ricky-Tigg on github
Rider Linden
Rikard Falkeborn
+rl1987 on github
Rob Cotrone
Rob Crittenden
Rob Davies
@@ -1792,6 +1820,7 @@ Ryuichi KAWAMATA
Rémy Léone
S. Moonesamy
Salah-Eddin Shaban
+Saleem Abdulrasool
Salvador Dávila
Salvatore Sorrentino
Sam Deane
@@ -1801,6 +1830,7 @@ Sam Schanken
Sampo Kellomaki
Samuel Díaz García
Samuel Listopad
+Samuel Marks
Samuel Surtees
Samuel Thibault
Sander Gates
@@ -1868,8 +1898,10 @@ Simon Josefsson
Simon Legner
Simon Liu
Simon Warta
+Siva Sivaraman
SLDiggie on github
smuellerDD on github
+sn on hackerone
Somnath Kundu
Song Ma
Sonia Subramanian
@@ -1960,7 +1992,9 @@ thanhchungbtc on github
The Infinnovation team
TheAssassin on github
Theodore Dubois
+therealhirudo on github
tholin on github
+Thomas Bouzerar
Thomas Braun
Thomas Gamper
Thomas Glanzmann
@@ -1999,6 +2033,7 @@ Timothe Litt
Timothy Polich
Tinus van den Berg
TJ Saunders
+tmkk on github
Tobias Blomberg
Tobias Hieta
Tobias Hintze
@@ -2067,6 +2102,7 @@ Ulrich Doehner
Ulrich Telle
Ulrich Zadow
Valentin David
+Valentyn Korniienko
Valerii Zapodovnikov
vanillajonathan on github
Vasiliy Faronov
@@ -2102,6 +2138,7 @@ Vojtěch Král
Volker Schmid
Vsevolod Novikov
vshmuk on hackerone
+Vyron Tsingaras
W. Mark Kubacki
Waldek Kozba
Walter J. Mack
@@ -2111,6 +2148,7 @@ Wayne Haigh
Wenchao Li
Wenxiang Qian
Werner Koch
+Werner Stolz
wesinator on github
Wesley Laxton
Wesley Miaw
@@ -2118,6 +2156,7 @@ Wez Furlong
Wham Bang
Wilfredo Sanchez
Will Dietz
+Will Roberts
Willem Sparreboom
William A. Rowe Jr
William Ahern
@@ -2165,11 +2204,13 @@ Zhao Yisha
Zhaoyang Wu
Zhibiao Wu
Zhouyihai Ding
+zloi-user on github
Zmey Petroff
Zvi Har'El
zzq1015 on github
İsmail Dönmez
Åukasz Domeradzki
Štefan Kremeň
+Коваленко Ðнатолий Викторович
Ðикита Дорохин
加藤éƒä¹‹
diff --git a/docs/THANKS-filter b/docs/THANKS-filter
index 6a036acc1..e11ad6d27 100644
--- a/docs/THANKS-filter
+++ b/docs/THANKS-filter
@@ -121,3 +121,4 @@ s/Ale Vesely/Alessandro Vesely/
s/Yamada Yasuharu/Yasuharu Yamada/
s/Jim Gallagher/James Gallagher/
s/Steve Brokenshire/Stephen Brokenshire/
+s/wangp on github/Peter Wang/
diff --git a/docs/TODO b/docs/TODO
index dfc36b8cf..11e01e04d 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -22,6 +22,7 @@
1.3 struct lifreq
1.4 alt-svc sharing
1.5 get rid of PATH_MAX
+ 1.6 native IDN support on macOS
1.7 Support HTTP/2 for HTTP(S) proxies
1.8 CURLOPT_RESOLVE for any port number
1.9 Cache negative name resolves
@@ -35,6 +36,7 @@
1.17 Add support for IRIs
1.18 try next proxy if one doesn't work
1.20 SRV and URI DNS records
+ 1.21 Add return code to CURLMOPT_PUSHFUNCTION to fail the connection
1.22 CURLINFO_PAUSE_STATE
1.23 Offer API to flush the connection pool
1.24 TCP Fast Open for windows
@@ -108,18 +110,20 @@
13.6 Provide callback for cert verification
13.7 improve configure --with-ssl
13.8 Support DANE
+ 13.9 TLS record padding
13.10 Support Authority Information Access certificate extension (AIA)
13.11 Support intermediate & root pinning for PINNEDPUBLICKEY
13.12 Support HSTS
+ 13.13 Make sure we forbid TLS 1.3 post-handshake authentication
13.14 Support the clienthello extension
14. GnuTLS
14.2 check connection
- 15. WinSSL/SChannel
- 15.1 Add support for client certificate authentication
- 15.3 Add support for the --ciphers option
- 15.4 Add option to disable client certificate auto-send
+ 15. Schannel
+ 15.1 Extend support for client certificate authentication
+ 15.2 Extend support for the --ciphers option
+ 15.3 Add option to disable client certificate auto-send
16. SASL
16.1 Other authentication mechanisms
@@ -145,17 +149,20 @@
18.10 improve how curl works in a windows console window
18.11 Windows: set attribute 'archive' for completed downloads
18.12 keep running, read instructions from pipe/socket
+ 18.13 Ratelimit or wait between serial requests
+ 18.14 --dry-run
18.15 --retry should resume
18.16 send only part of --data
18.17 consider file name from the redirected URL with -O ?
18.18 retry on network is unreachable
18.19 expand ~/ in config files
18.20 host name sections in config files
+ 18.21 retry on the redirected-to URL
+ 18.22 Add flag to specify download directory
19. Build
19.1 roffit
19.2 Enable PIE and RELRO by default
- 19.3 cmake test suite improvements
20. Test suite
20.1 SSL tunnel
@@ -221,6 +228,14 @@
there we need libssh2 to properly tell us when we pass in a too small buffer
and its current API (as of libssh2 1.2.7) doesn't.
+1.6 native IDN support on macOS
+
+ On recent macOS versions, the getaddrinfo() function itself has built-in IDN
+ support. By setting the AI_CANONNAME flag, the function will return the
+ encoded name in the ai_canonname struct field in the returned information.
+ This could be used by curl on macOS when built without a separate IDN library
+ and an IDN host name is used in a URL.
+
1.7 Support HTTP/2 for HTTP(S) proxies
Support for doing HTTP/2 to HTTP and HTTPS proxies is still missing.
@@ -343,6 +358,13 @@
Offer support for resolving SRV and URI DNS records for libcurl to know which
server to connect to for various protocols (including HTTP!).
+1.21 Add return code to CURLMOPT_PUSHFUNCTION to fail the connection
+
+ Allow the callback to return a value that would stop the entire operation,
+ like it can be done from most other callbacks.
+
+ See https://curl.haxx.se/mail/lib-2020-06/0099.html
+
1.22 CURLINFO_PAUSE_STATE
Return information about the transfer's current pause state, in both
@@ -422,7 +444,7 @@
- GSSAPI authentication for FTP transfers
- The "DONE" operation (post transfer protocol-specific actions) for the
- protocols SFTP, SMTP, FTP. Fixing Curl_done() for this is a worthy task.
+ protocols SFTP, SMTP, FTP. Fixing multi_done() for this is a worthy task.
- curl_multi_remove_handle for any of the above. See section 2.3.
@@ -735,6 +757,14 @@ that doesn't exist on the server, just like --ftp-create-dirs.
Björn Stenberg wrote a separate initial take on DANE that was never
completed.
+13.9 TLS record padding
+
+ TLS (1.3) offers optional record padding and OpenSSL provides an API for it.
+ I could make sense for libcurl to offer this ability to applications to make
+ traffic patterns harder to figure out by network traffic observers.
+
+ See https://github.com/curl/curl/issues/5398
+
13.10 Support Authority Information Access certificate extension (AIA)
AIA can provide various things like CRLs but more importantly information
@@ -750,23 +780,30 @@ that doesn't exist on the server, just like --ftp-create-dirs.
CURLOPT_PINNEDPUBLICKEY does not consider the hashes of intermediate & root
certificates when comparing the pinned keys. Therefore it is not compatible
- with "HTTP Public Key Pinning" as there also intermediate and root certificates
- can be pinned. This is very useful as it prevents webadmins from "locking
- themself out of their servers".
+ with "HTTP Public Key Pinning" as there also intermediate and root
+ certificates can be pinned. This is very useful as it prevents webadmins from
+ "locking themself out of their servers".
- Adding this feature would make curls pinning 100% compatible to HPKP and allow
- more flexible pinning.
+ Adding this feature would make curls pinning 100% compatible to HPKP and
+ allow more flexible pinning.
13.12 Support HSTS
"HTTP Strict Transport Security" is TOFU (trust on first use), time-based
features indicated by a HTTP header send by the webserver. It is widely used
- in browsers and it's purpose is to prevent insecure HTTP connections after
- a previous HTTPS connection. It protects against SSLStripping attacks.
+ in browsers and it's purpose is to prevent insecure HTTP connections after a
+ previous HTTPS connection. It protects against SSLStripping attacks.
Doc: https://developer.mozilla.org/en-US/docs/Web/Security/HTTP_strict_transport_security
RFC 6797: https://tools.ietf.org/html/rfc6797
+13.13 Make sure we forbid TLS 1.3 post-handshake authentication
+
+ RFC 8740 explains how using HTTP/2 must forbid the use of TLS 1.3
+ post-handshake authentication. We should make sure to live up to that.
+
+ See https://github.com/curl/curl/issues/5396
+
13.14 Support the clienthello extension
Certain stupid networks and middle boxes have a problem with SSL handshake
@@ -784,31 +821,23 @@ that doesn't exist on the server, just like --ftp-create-dirs.
Add a way to check if the connection seems to be alive, to correspond to the
SSL_peak() way we use with OpenSSL.
-15. WinSSL/SChannel
-
-15.1 Add support for client certificate authentication
+15. Schannel
- WinSSL/SChannel currently makes use of the OS-level system and user
- certificate and private key stores. This does not allow the application
- or the user to supply a custom client certificate using curl or libcurl.
+15.1 Extend support for client certificate authentication
- Therefore support for the existing -E/--cert and --key options should be
- implemented by supplying a custom certificate to the SChannel APIs, see:
+ The existing support for the -E/--cert and --key options could be
+ extended by supplying a custom certificate and key in PEM format, see:
- Getting a Certificate for Schannel
https://msdn.microsoft.com/en-us/library/windows/desktop/aa375447.aspx
-15.3 Add support for the --ciphers option
-
- The cipher suites used by WinSSL/SChannel are configured on an OS-level
- instead of an application-level. This does not allow the application or
- the user to customize the configured cipher suites using curl or libcurl.
+15.2 Extend support for the --ciphers option
- Therefore support for the existing --ciphers option should be implemented
- by mapping the OpenSSL/GnuTLS cipher suites to the SChannel APIs, see
+ The existing support for the --ciphers option could be extended
+ by mapping the OpenSSL/GnuTLS cipher suites to the Schannel APIs, see
- Specifying Schannel Ciphers and Cipher Strengths
https://msdn.microsoft.com/en-us/library/windows/desktop/aa380161.aspx
-15.4 Add option to disable client certificate auto-send
+15.3 Add option to disable client certificate auto-send
Microsoft says "By default, Schannel will, with no notification to the client,
attempt to locate a client certificate and send it to the server." That could
@@ -988,6 +1017,23 @@ that doesn't exist on the server, just like --ftp-create-dirs.
invoke can talk to the still running instance and ask for transfers to get
done, and thus maintain its connection pool, DNS cache and more.
+18.13 Ratelimit or wait between serial requests
+
+ Consider a command line option that can make curl do multiple serial requests
+ slow, potentially with a (random) wait between transfers. There's also a
+ propsed set of standard HTTP headers to let servers let the client adapt to
+ its rate limits:
+ https://www.ietf.org/id/draft-polli-ratelimit-headers-02.html
+
+ See https://github.com/curl/curl/issues/5406
+
+18.14 --dry-run
+
+ A command line option that makes curl show exactly what it would do and send
+ if it would run for real.
+
+ See https://github.com/curl/curl/issues/5426
+
18.15 --retry should resume
When --retry is used and curl actually retries transfer, it should use the
@@ -1050,6 +1096,23 @@ that doesn't exist on the server, just like --ftp-create-dirs.
default .curlrc could a specific user-agent only when doing requests against
a certain site.
+18.21 retry on the redirected-to URL
+
+ When curl is told to --retry a failed transfer and follows redirects, it
+ might get a HTTP 429 response from the redirected-to URL and not the original
+ one, which then could make curl decide to rather retry the transfer on that
+ URL only instead of the original operation to the original URL.
+
+ Perhaps extra emphasized if the original transfer is a large POST that
+ redirects to a separate GET, and that GET is what gets the 529
+
+ See https://github.com/curl/curl/issues/5462
+
+18.22 Add flag to specify download directory
+
+ A directory name to basically prepend to the file name -O and -o use. Saves
+ user from having to manually "cd" to the directory. Especially useful for
+ command lines with multiple -O and different download directories.
19. Build
@@ -1070,13 +1133,6 @@ that doesn't exist on the server, just like --ftp-create-dirs.
to no impact, neither on the performance nor on the general functionality of
curl.
-19.3 cmake test suite improvements
-
- The cmake build doesn't support 'make show' so it doesn't know which tests
- are in the makefile or not (making appveyor builds do many false warnings
- about it) nor does it support running the test suite if building out-of-tree.
-
- See https://github.com/curl/curl/issues/3109
20. Test suite
diff --git a/docs/VERSIONS b/docs/VERSIONS.md
index 72a45474d..72a45474d 100644
--- a/docs/VERSIONS
+++ b/docs/VERSIONS.md
diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc
index 5b7439e4a..6a7b953bc 100644
--- a/docs/cmdline-opts/Makefile.inc
+++ b/docs/cmdline-opts/Makefile.inc
@@ -180,6 +180,7 @@ DPAGES = \
request-target.d \
request.d \
resolve.d \
+ retry-all-errors.d \
retry-connrefused.d \
retry-delay.d \
retry-max-time.d \
diff --git a/docs/cmdline-opts/cert-type.d b/docs/cmdline-opts/cert-type.d
index 55d8033b4..1232ec10d 100644
--- a/docs/cmdline-opts/cert-type.d
+++ b/docs/cmdline-opts/cert-type.d
@@ -1,7 +1,7 @@
Long: cert-type
Protocols: TLS
Arg: <type>
-Help: Certificate file type
+Help: Certificate type (DER/PEM/ENG)
See-also: cert key key-type
---
Tells curl what type the provided client certificate is using. PEM, DER, ENG
diff --git a/docs/cmdline-opts/happy-eyeballs-timeout-ms.d b/docs/cmdline-opts/happy-eyeballs-timeout-ms.d
index ec9a8c228..611a8f1d8 100644
--- a/docs/cmdline-opts/happy-eyeballs-timeout-ms.d
+++ b/docs/cmdline-opts/happy-eyeballs-timeout-ms.d
@@ -1,6 +1,6 @@
Long: happy-eyeballs-timeout-ms
Arg: <milliseconds>
-Help: How long to wait in milliseconds for IPv6 before trying IPv4
+Help: Time for IPv6 before trying IPv4
Added: 7.59.0
---
Happy eyeballs is an algorithm that attempts to connect to both IPv4 and IPv6
diff --git a/docs/cmdline-opts/list-only.d b/docs/cmdline-opts/list-only.d
index 4c56304a0..63b2851f4 100644
--- a/docs/cmdline-opts/list-only.d
+++ b/docs/cmdline-opts/list-only.d
@@ -2,7 +2,7 @@ Long: list-only
Short: l
Protocols: FTP POP3
Help: List only mode
-Added: 7.21.5
+Added: 4.0
---
(FTP)
When listing an FTP directory, this switch forces a name-only view. This is
diff --git a/docs/cmdline-opts/page-footer b/docs/cmdline-opts/page-footer
index 2969e2dad..53fdf2561 100644
--- a/docs/cmdline-opts/page-footer
+++ b/docs/cmdline-opts/page-footer
@@ -39,6 +39,23 @@ accesses the target URL through the proxy.
The list of host names can also be include numerical IP addresses, and IPv6
versions should then be given without enclosing brackets.
+.IP "CURL_SSL_BACKEND <TLS backend>"
+If curl was built with support for "MultiSSL", meaning that it has built-in
+support for more than one TLS backend, this environment variable can be set to
+the case insensitive name of the particular backend to use when curl is
+invokved. Setting a name that isn't a built-in alternative, will make curl
+stay with the default.
+.IP "QLOGDIR <directory name>"
+If curl was built with HTTP/3 support, setting this environment variable to a
+local directory will make curl produce qlogs in that directory, using file
+names named after the destination connection id (in hex). Do note that these
+files can become rather large. Works with both QUIC backends.
+.IP "SSLKEYLOGFILE <file name>"
+If you set this environment variable to a file name, curl will store TLS
+secrets from its connections in that file when invoked to enable you to
+analyze the TLS traffic in real time using network analyzing tools such as
+Wireshark. This works with the following TLS backends: OpenSSL, libressl,
+BoringSSL, GnuTLS, NSS and wolfSSL.
.Sh "PROXY PROTOCOL PREFIXES"
Since curl version 7.21.7, the proxy string may be specified with a
protocol:// prefix to specify alternative proxy protocols.
diff --git a/docs/cmdline-opts/page-header b/docs/cmdline-opts/page-header
index 60c3b07fe..c38698c6b 100644
--- a/docs/cmdline-opts/page-header
+++ b/docs/cmdline-opts/page-header
@@ -31,8 +31,9 @@ curl \- transfer a URL
.B curl
is a tool to transfer data from or to a server, using one of the supported
protocols (DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP,
-LDAPS, MQTT, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS,
-TELNET and TFTP). The command is designed to work without user interaction.
+LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP, SCP, SFTP, SMB, SMBS, SMTP,
+SMTPS, TELNET and TFTP). The command is designed to work without user
+interaction.
curl offers a busload of useful tricks like proxy support, user
authentication, FTP upload, HTTP post, SSL connections, cookies, file transfer
@@ -52,16 +53,16 @@ braces and quoting the URL as in:
or you can get sequences of alphanumeric series by using [] as in:
- ftp://ftp.example.com/file[1-100].txt
+ "ftp://ftp.example.com/file[1-100].txt"
- ftp://ftp.example.com/file[001-100].txt (with leading zeros)
+ "ftp://ftp.example.com/file[001-100].txt" (with leading zeros)
- ftp://ftp.example.com/file[a-z].txt
+ "ftp://ftp.example.com/file[a-z].txt"
Nested sequences are not supported, but you can use several ones next to each
other:
- http://example.com/archive[1996-1999]/vol[1-4]/part{a,b,c}.html
+ "http://example.com/archive[1996-1999]/vol[1-4]/part{a,b,c}.html"
You can specify any amount of URLs on the command line. They will be fetched
in a sequential manner in the specified order. You can specify command line
@@ -70,9 +71,9 @@ options and URLs mixed and in any order on the command line.
You can specify a step counter for the ranges to get every Nth number or
letter:
- http://example.com/file[1-100:10].txt
+ "http://example.com/file[1-100:10].txt"
- http://example.com/file[a-z:2].txt
+ "http://example.com/file[a-z:2].txt"
When using [] or {} sequences when invoked from a command line prompt, you
probably have to put the full URL within double quotes to avoid the shell from
@@ -82,7 +83,7 @@ for example '&', '?' and '*'.
Provide the IPv6 zone index in the URL with an escaped percentage sign and the
interface name. Like in
- http://[fe80::3%25eth0]/
+ "http://[fe80::3%25eth0]/"
If you specify URL without protocol:// prefix, curl will attempt to guess what
protocol you might want. It will then default to HTTP but try other protocols
diff --git a/docs/cmdline-opts/resolve.d b/docs/cmdline-opts/resolve.d
index 9c37525bd..c1692f0f8 100644
--- a/docs/cmdline-opts/resolve.d
+++ b/docs/cmdline-opts/resolve.d
@@ -1,5 +1,5 @@
Long: resolve
-Arg: <host:port:address[,address]...>
+Arg: <host:port:addr[,addr]...>
Help: Resolve the host+port to this address
Added: 7.21.3
---
diff --git a/docs/cmdline-opts/retry-all-errors.d b/docs/cmdline-opts/retry-all-errors.d
new file mode 100644
index 000000000..4554f5938
--- /dev/null
+++ b/docs/cmdline-opts/retry-all-errors.d
@@ -0,0 +1,19 @@
+Long: retry-all-errors
+Help: Retry all errors (use with --retry)
+Added: 7.71.0
+---
+Retry on any error. This option is used together with --retry.
+
+This option is the "sledgehammer" of retrying. Do not use this option by
+default (eg in curlrc), there may be unintended consequences such as sending or
+receiving duplicate data. Do not use with redirected input or output. You'd be
+much better off handling your unique problems in shell script. Please read the
+example below.
+
+Warning: For server compatibility curl attempts to retry failed flaky transfers
+as close as possible to how they were started, but this is not possible with
+redirected input or output. For example, before retrying it removes output data
+from a failed partial transfer that was written to an output file. However this
+is not true of data redirected to a | pipe or > file, which are not reset. We
+strongly suggest don't parse or record output via redirect in combination with
+this option, since you may receive duplicate data.
diff --git a/docs/cmdline-opts/sasl-authzid.d b/docs/cmdline-opts/sasl-authzid.d
index b34db97fc..a3bd46e70 100644
--- a/docs/cmdline-opts/sasl-authzid.d
+++ b/docs/cmdline-opts/sasl-authzid.d
@@ -1,5 +1,6 @@
Long: sasl-authzid
-Help: Use this identity to act as during SASL PLAIN authentication
+Arg: <identity>
+Help: Identity for SASL PLAIN authentication
Added: 7.66.0
---
Use this authorisation identity (authzid), during SASL PLAIN authentication,
diff --git a/docs/cmdline-opts/ssl-revoke-best-effort.d b/docs/cmdline-opts/ssl-revoke-best-effort.d
index 9b55699db..e339b8af0 100644
--- a/docs/cmdline-opts/ssl-revoke-best-effort.d
+++ b/docs/cmdline-opts/ssl-revoke-best-effort.d
@@ -1,5 +1,5 @@
Long: ssl-revoke-best-effort
-Help: Ignore missing/offline cert CRL distribution points (Schannel)
+Help: Ignore missing/offline cert CRL dist points
Added: 7.70.0
---
(Schannel) This option tells curl to ignore certificate revocation checks when
diff --git a/docs/cmdline-opts/tls13-ciphers.d b/docs/cmdline-opts/tls13-ciphers.d
index 654a25b4c..db8033525 100644
--- a/docs/cmdline-opts/tls13-ciphers.d
+++ b/docs/cmdline-opts/tls13-ciphers.d
@@ -1,5 +1,5 @@
Long: tls13-ciphers
-Arg: <list of TLS 1.3 ciphersuites>
+Arg: <ciphersuite list>
help: TLS 1.3 cipher suites to use
Protocols: TLS
---
diff --git a/docs/cmdline-opts/user-agent.d b/docs/cmdline-opts/user-agent.d
index de73f723f..c6dd2e584 100644
--- a/docs/cmdline-opts/user-agent.d
+++ b/docs/cmdline-opts/user-agent.d
@@ -9,4 +9,8 @@ Specify the User-Agent string to send to the HTTP server. To encode blanks in
the string, surround the string with single quote marks. This header can also
be set with the --header or the --proxy-header options.
+If you give an empty argument to --user-agent (""), it will remove the header
+completely from the request. If you prefer a blank header, you can set it to a
+single space (" ").
+
If this option is used several times, the last one will be used.
diff --git a/docs/cmdline-opts/version.d b/docs/cmdline-opts/version.d
index cd35f27fb..16c1843f1 100644
--- a/docs/cmdline-opts/version.d
+++ b/docs/cmdline-opts/version.d
@@ -13,48 +13,56 @@ reports to support.
The third line (starts with "Features:") shows specific features libcurl
reports to offer. Available features include:
.RS
+.IP "alt-svc"
+Support for the Alt-Svc: header is provided.
+.IP "AsynchDNS"
+This curl uses asynchronous name resolves. Asynchronous name resolves can be
+done using either the c-ares or the threaded resolver backends.
+.IP "brotli"
+Support for automatic brotli compression over HTTP(S).
+.IP "CharConv"
+curl was built with support for character set conversions (like EBCDIC)
+.IP "Debug"
+This curl uses a libcurl built with Debug. This enables more error-tracking
+and memory debugging etc. For curl-developers only!
+.IP "GSS-API"
+GSS-API is supported.
+.IP "HTTP2"
+HTTP/2 support has been built-in.
+.IP "HTTP3"
+HTTP/3 support has been built-in.
+.IP "HTTPS-proxy"
+This curl is built to support HTTPS proxy.
+.IP "IDN"
+This curl supports IDN - international domain names.
.IP "IPv6"
You can use IPv6 with this.
.IP "krb4"
Krb4 for FTP is supported.
-.IP "SSL"
-SSL versions of various protocols are supported, such as HTTPS, FTPS, POP3S
-and so on.
+.IP "Largefile"
+This curl supports transfers of large files, files larger than 2GB.
.IP "libz"
Automatic decompression of compressed files over HTTP is supported.
+.IP "Metalink"
+This curl supports Metalink
+.IP "MultiSSL"
+This curl supports multiple TLS backends.
.IP "NTLM"
NTLM authentication is supported.
-.IP "Debug"
-This curl uses a libcurl built with Debug. This enables more error-tracking
-and memory debugging etc. For curl-developers only!
-.IP "AsynchDNS"
-This curl uses asynchronous name resolves. Asynchronous name resolves can be
-done using either the c-ares or the threaded resolver backends.
+.IP "NTLM"
+NTLM authentication is supported.
+.IP "PSL"
+PSL is short for Public Suffix List and means that this curl has been built
+with knowledge about "public suffixes".
.IP "SPNEGO"
SPNEGO authentication is supported.
-.IP "Largefile"
-This curl supports transfers of large files, files larger than 2GB.
-.IP "IDN"
-This curl supports IDN - international domain names.
-.IP "GSS-API"
-GSS-API is supported.
+.IP "SSL"
+SSL versions of various protocols are supported, such as HTTPS, FTPS, POP3S
+and so on.
.IP "SSPI"
SSPI is supported.
.IP "TLS-SRP"
SRP (Secure Remote Password) authentication is supported for TLS.
-.IP "HTTP2"
-HTTP/2 support has been built-in.
.IP "UnixSockets"
Unix sockets support is provided.
-.IP "HTTPS-proxy"
-This curl is built to support HTTPS proxy.
-.IP "Metalink"
-This curl supports Metalink (both version 3 and 4 (RFC 5854)), which
-describes mirrors and hashes. curl will use mirrors for failover if
-there are errors (such as the file or server not being available).
-.IP "PSL"
-PSL is short for Public Suffix List and means that this curl has been built
-with knowledge about "public suffixes".
-.IP "MultiSSL"
-This curl supports multiple TLS backends.
.RE
diff --git a/docs/cmdline-opts/write-out.d b/docs/cmdline-opts/write-out.d
index 9024d32e0..9786a9af4 100644
--- a/docs/cmdline-opts/write-out.d
+++ b/docs/cmdline-opts/write-out.d
@@ -82,6 +82,10 @@ IPv4 or IPv6 (Added in 7.29.0)
.B remote_port
The remote port number of the most recently done connection (Added in 7.29.0)
.TP
+.B response_code
+The numerical response code that was found in the last transfer (formerly
+known as "http_code"). (Added in 7.18.2)
+.TP
.B scheme
The URL scheme (sometimes called protocol) that was effectively used (Added in 7.52.0)
.TP
diff --git a/docs/examples/.checksrc b/docs/examples/.checksrc
new file mode 100644
index 000000000..c45678aae
--- /dev/null
+++ b/docs/examples/.checksrc
@@ -0,0 +1,2 @@
+disable TYPEDEFSTRUCT
+disable SNPRINTF
diff --git a/docs/examples/Makefile.am b/docs/examples/Makefile.am
index 105f78b1d..fbafbbf59 100644
--- a/docs/examples/Makefile.am
+++ b/docs/examples/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -67,4 +67,4 @@ CS_1 =
CS_ = $(CS_0)
checksrc:
- $(CHECKSRC)(@PERL@ $(top_srcdir)/lib/checksrc.pl -ASNPRINTF $(srcdir)/*.c)
+ $(CHECKSRC)(@PERL@ $(top_srcdir)/lib/checksrc.pl $(srcdir)/*.c)
diff --git a/docs/examples/Makefile.inc b/docs/examples/Makefile.inc
index b588b5fee..79c9e509a 100644
--- a/docs/examples/Makefile.inc
+++ b/docs/examples/Makefile.inc
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -43,6 +43,6 @@ check_PROGRAMS = 10-at-a-time anyauthput cookie_interface debug fileupload \
COMPLICATED_EXAMPLES = curlgtk.c curlx.c htmltitle.cpp cacertinmem.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 \
+ smooth-gtk-thread.c version-check.pl href_extractor.c \
multi-uv.c xmlstream.c usercertinmem.c sessioninfo.c \
threaded-shared-conn.c crawler.c ephiperfifo.c multi-event.c
diff --git a/docs/examples/anyauthput.c b/docs/examples/anyauthput.c
index 908f59997..fe742c96d 100644
--- a/docs/examples/anyauthput.c
+++ b/docs/examples/anyauthput.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,7 +20,7 @@
*
***************************************************************************/
/* <DESC>
- * HTTP PUT upload with authentiction using "any" method. libcurl picks the
+ * HTTP PUT upload with authentication using "any" method. libcurl picks the
* one the server supports/wants.
* </DESC>
*/
@@ -44,7 +44,7 @@
#endif
/*
- * This example shows a HTTP PUT operation with authentiction using "any"
+ * This example shows a HTTP PUT operation with authentication using "any"
* type. It PUTs a file given as a command line argument to the URL also given
* on the command line.
*
diff --git a/docs/examples/asiohiper.cpp b/docs/examples/asiohiper.cpp
deleted file mode 100644
index 88eeafb59..000000000
--- a/docs/examples/asiohiper.cpp
+++ /dev/null
@@ -1,496 +0,0 @@
-/***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * 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>
- * demonstrate the use of multi socket interface with boost::asio
- * </DESC>
- */
-/*
- * This program is in c++ and uses boost::asio instead of libevent/libev.
- * Requires boost::asio, boost::bind and boost::system
- *
- * This is an adaptation of libcurl's "hiperfifo.c" and "evhiperfifo.c"
- * sample programs. This example implements a subset of the functionality from
- * hiperfifo.c, for full functionality refer hiperfifo.c or evhiperfifo.c
- *
- * Written by Lijo Antony based on hiperfifo.c by Jeff Pohlmeyer
- *
- * When running, the program creates an easy handle for a URL and
- * uses the curl_multi API to fetch it.
- *
- * Note:
- * For the sake of simplicity, URL is hard coded to "www.google.com"
- *
- * This is purely a demo app, all retrieved data is simply discarded by the
- * write callback.
- *
- * ===========================================================================
- * WARNING: This example program is known to have flaws:
- * https://github.com/curl/curl/issues/2407
- *
- * It still kept in the example repository with the hope that it might be
- * useful, and maybe some day someone who knows enough about boost::asio will
- * read this text, accept the challenge and make the example code work
- * correctly. Until then: expect this example program to fail occasionally.
- * ===========================================================================
- */
-
-
-#include <gnurl/curl.h>
-#include <boost/asio.hpp>
-#include <boost/bind.hpp>
-#include <iostream>
-
-#define MSG_OUT stdout /* Send info to stdout, change to stderr if you want */
-
-/* boost::asio related objects
- * using global variables for simplicity
- */
-boost::asio::io_service io_service;
-boost::asio::deadline_timer timer(io_service);
-std::map<curl_socket_t, boost::asio::ip::tcp::socket *> socket_map;
-
-/* Global information, common to all connections */
-typedef struct _GlobalInfo
-{
- CURLM *multi;
- int still_running;
-} GlobalInfo;
-
-/* Information associated with a specific easy handle */
-typedef struct _ConnInfo
-{
- CURL *easy;
- char *url;
- GlobalInfo *global;
- char error[CURL_ERROR_SIZE];
-} ConnInfo;
-
-static void timer_cb(const boost::system::error_code & error, GlobalInfo *g);
-
-/* Update the event timer after curl_multi library calls */
-static int multi_timer_cb(CURLM *multi, long timeout_ms, GlobalInfo *g)
-{
- fprintf(MSG_OUT, "\nmulti_timer_cb: timeout_ms %ld", timeout_ms);
-
- /* cancel running timer */
- timer.cancel();
-
- if(timeout_ms > 0) {
- /* update timer */
- timer.expires_from_now(boost::posix_time::millisec(timeout_ms));
- timer.async_wait(boost::bind(&timer_cb, _1, g));
- }
- else if(timeout_ms == 0) {
- /* call timeout function immediately */
- boost::system::error_code error; /*success*/
- timer_cb(error, g);
- }
-
- return 0;
-}
-
-/* Die if we get a bad CURLMcode somewhere */
-static void mcode_or_die(const char *where, CURLMcode code)
-{
- if(CURLM_OK != code) {
- const char *s;
- switch(code) {
- case CURLM_CALL_MULTI_PERFORM:
- s = "CURLM_CALL_MULTI_PERFORM";
- break;
- 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";
- fprintf(MSG_OUT, "\nERROR: %s returns %s", where, s);
- /* ignore this error */
- return;
- }
-
- fprintf(MSG_OUT, "\nERROR: %s returns %s", where, s);
-
- exit(code);
- }
-}
-
-/* Check for completed transfers, and remove their easy handles */
-static void check_multi_info(GlobalInfo *g)
-{
- char *eff_url;
- CURLMsg *msg;
- int msgs_left;
- ConnInfo *conn;
- CURL *easy;
- CURLcode res;
-
- fprintf(MSG_OUT, "\nREMAINING: %d", g->still_running);
-
- while((msg = curl_multi_info_read(g->multi, &msgs_left))) {
- if(msg->msg == CURLMSG_DONE) {
- easy = msg->easy_handle;
- res = msg->data.result;
- curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn);
- curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url);
- fprintf(MSG_OUT, "\nDONE: %s => (%d) %s", eff_url, res, conn->error);
- curl_multi_remove_handle(g->multi, easy);
- free(conn->url);
- curl_easy_cleanup(easy);
- free(conn);
- }
- }
-}
-
-/* Called by asio when there is an action on a socket */
-static void event_cb(GlobalInfo *g, curl_socket_t s,
- int action, const boost::system::error_code & error,
- int *fdp)
-{
- fprintf(MSG_OUT, "\nevent_cb: action=%d", action);
-
- if(socket_map.find(s) == socket_map.end()) {
- fprintf(MSG_OUT, "\nevent_cb: socket already closed");
- return;
- }
-
- /* make sure the event matches what are wanted */
- if(*fdp == action || *fdp == CURL_POLL_INOUT) {
- CURLMcode rc;
- if(error)
- action = CURL_CSELECT_ERR;
- rc = curl_multi_socket_action(g->multi, s, action, &g->still_running);
-
- mcode_or_die("event_cb: curl_multi_socket_action", rc);
- check_multi_info(g);
-
- if(g->still_running <= 0) {
- fprintf(MSG_OUT, "\nlast transfer done, kill timeout");
- timer.cancel();
- }
-
- /* keep on watching.
- * the socket may have been closed and/or fdp may have been changed
- * in curl_multi_socket_action(), so check them both */
- if(!error && socket_map.find(s) != socket_map.end() &&
- (*fdp == action || *fdp == CURL_POLL_INOUT)) {
- boost::asio::ip::tcp::socket *tcp_socket = socket_map.find(s)->second;
-
- if(action == CURL_POLL_IN) {
- tcp_socket->async_read_some(boost::asio::null_buffers(),
- boost::bind(&event_cb, g, s,
- action, _1, fdp));
- }
- if(action == CURL_POLL_OUT) {
- tcp_socket->async_write_some(boost::asio::null_buffers(),
- boost::bind(&event_cb, g, s,
- action, _1, fdp));
- }
- }
- }
-}
-
-/* Called by asio when our timeout expires */
-static void timer_cb(const boost::system::error_code & error, GlobalInfo *g)
-{
- if(!error) {
- fprintf(MSG_OUT, "\ntimer_cb: ");
-
- CURLMcode rc;
- rc = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0,
- &g->still_running);
-
- mcode_or_die("timer_cb: curl_multi_socket_action", rc);
- check_multi_info(g);
- }
-}
-
-/* Clean up any data */
-static void remsock(int *f, GlobalInfo *g)
-{
- fprintf(MSG_OUT, "\nremsock: ");
-
- if(f) {
- free(f);
- }
-}
-
-static void setsock(int *fdp, curl_socket_t s, CURL *e, int act, int oldact,
- GlobalInfo *g)
-{
- fprintf(MSG_OUT, "\nsetsock: socket=%d, act=%d, fdp=%p", s, act, fdp);
-
- std::map<curl_socket_t, boost::asio::ip::tcp::socket *>::iterator it =
- socket_map.find(s);
-
- if(it == socket_map.end()) {
- fprintf(MSG_OUT, "\nsocket %d is a c-ares socket, ignoring", s);
- return;
- }
-
- boost::asio::ip::tcp::socket * tcp_socket = it->second;
-
- *fdp = act;
-
- if(act == CURL_POLL_IN) {
- fprintf(MSG_OUT, "\nwatching for socket to become readable");
- if(oldact != CURL_POLL_IN && oldact != CURL_POLL_INOUT) {
- tcp_socket->async_read_some(boost::asio::null_buffers(),
- boost::bind(&event_cb, g, s,
- CURL_POLL_IN, _1, fdp));
- }
- }
- else if(act == CURL_POLL_OUT) {
- fprintf(MSG_OUT, "\nwatching for socket to become writable");
- if(oldact != CURL_POLL_OUT && oldact != CURL_POLL_INOUT) {
- tcp_socket->async_write_some(boost::asio::null_buffers(),
- boost::bind(&event_cb, g, s,
- CURL_POLL_OUT, _1, fdp));
- }
- }
- else if(act == CURL_POLL_INOUT) {
- fprintf(MSG_OUT, "\nwatching for socket to become readable & writable");
- if(oldact != CURL_POLL_IN && oldact != CURL_POLL_INOUT) {
- tcp_socket->async_read_some(boost::asio::null_buffers(),
- boost::bind(&event_cb, g, s,
- CURL_POLL_IN, _1, fdp));
- }
- if(oldact != CURL_POLL_OUT && oldact != CURL_POLL_INOUT) {
- tcp_socket->async_write_some(boost::asio::null_buffers(),
- boost::bind(&event_cb, g, s,
- CURL_POLL_OUT, _1, fdp));
- }
- }
-}
-
-static void addsock(curl_socket_t s, CURL *easy, int action, GlobalInfo *g)
-{
- /* fdp is used to store current action */
- int *fdp = (int *) calloc(sizeof(int), 1);
-
- setsock(fdp, s, easy, action, 0, g);
- curl_multi_assign(g->multi, s, fdp);
-}
-
-/* CURLMOPT_SOCKETFUNCTION */
-static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp)
-{
- fprintf(MSG_OUT, "\nsock_cb: socket=%d, what=%d, sockp=%p", s, what, sockp);
-
- GlobalInfo *g = (GlobalInfo*) cbp;
- int *actionp = (int *) sockp;
- const char *whatstr[] = { "none", "IN", "OUT", "INOUT", "REMOVE"};
-
- fprintf(MSG_OUT,
- "\nsocket callback: s=%d e=%p what=%s ", s, e, whatstr[what]);
-
- if(what == CURL_POLL_REMOVE) {
- fprintf(MSG_OUT, "\n");
- remsock(actionp, g);
- }
- else {
- if(!actionp) {
- fprintf(MSG_OUT, "\nAdding data: %s", whatstr[what]);
- addsock(s, e, what, g);
- }
- else {
- fprintf(MSG_OUT,
- "\nChanging action from %s to %s",
- whatstr[*actionp], whatstr[what]);
- setsock(actionp, s, e, what, *actionp, g);
- }
- }
-
- return 0;
-}
-
-/* CURLOPT_WRITEFUNCTION */
-static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *data)
-{
- size_t written = size * nmemb;
- char *pBuffer = (char *)malloc(written + 1);
-
- strncpy(pBuffer, (const char *)ptr, written);
- pBuffer[written] = '\0';
-
- fprintf(MSG_OUT, "%s", pBuffer);
-
- free(pBuffer);
-
- return written;
-}
-
-/* CURLOPT_PROGRESSFUNCTION */
-static int prog_cb(void *p, double dltotal, double dlnow, double ult,
- double uln)
-{
- ConnInfo *conn = (ConnInfo *)p;
-
- (void)ult;
- (void)uln;
-
- fprintf(MSG_OUT, "\nProgress: %s (%g/%g)", conn->url, dlnow, dltotal);
- fprintf(MSG_OUT, "\nProgress: %s (%g)", conn->url, ult);
-
- return 0;
-}
-
-/* CURLOPT_OPENSOCKETFUNCTION */
-static curl_socket_t opensocket(void *clientp, curlsocktype purpose,
- struct curl_sockaddr *address)
-{
- fprintf(MSG_OUT, "\nopensocket :");
-
- curl_socket_t sockfd = CURL_SOCKET_BAD;
-
- /* restrict to IPv4 */
- if(purpose == CURLSOCKTYPE_IPCXN && address->family == AF_INET) {
- /* create a tcp socket object */
- boost::asio::ip::tcp::socket *tcp_socket =
- new boost::asio::ip::tcp::socket(io_service);
-
- /* open it and get the native handle*/
- boost::system::error_code ec;
- tcp_socket->open(boost::asio::ip::tcp::v4(), ec);
-
- if(ec) {
- /* An error occurred */
- std::cout << std::endl << "Couldn't open socket [" << ec << "][" <<
- ec.message() << "]";
- fprintf(MSG_OUT, "\nERROR: Returning CURL_SOCKET_BAD to signal error");
- }
- else {
- sockfd = tcp_socket->native_handle();
- fprintf(MSG_OUT, "\nOpened socket %d", sockfd);
-
- /* save it for monitoring */
- socket_map.insert(std::pair<curl_socket_t,
- boost::asio::ip::tcp::socket *>(sockfd, tcp_socket));
- }
- }
-
- return sockfd;
-}
-
-/* CURLOPT_CLOSESOCKETFUNCTION */
-static int close_socket(void *clientp, curl_socket_t item)
-{
- fprintf(MSG_OUT, "\nclose_socket : %d", item);
-
- std::map<curl_socket_t, boost::asio::ip::tcp::socket *>::iterator it =
- socket_map.find(item);
-
- if(it != socket_map.end()) {
- delete it->second;
- socket_map.erase(it);
- }
-
- return 0;
-}
-
-/* Create a new easy handle, and add it to the global curl_multi */
-static void new_conn(char *url, GlobalInfo *g)
-{
- ConnInfo *conn;
- CURLMcode rc;
-
- conn = (ConnInfo *) calloc(1, sizeof(ConnInfo));
-
- conn->easy = curl_easy_init();
- if(!conn->easy) {
- fprintf(MSG_OUT, "\ncurl_easy_init() failed, exiting!");
- exit(2);
- }
-
- conn->global = g;
- conn->url = strdup(url);
- curl_easy_setopt(conn->easy, CURLOPT_URL, conn->url);
- curl_easy_setopt(conn->easy, CURLOPT_WRITEFUNCTION, write_cb);
- curl_easy_setopt(conn->easy, CURLOPT_WRITEDATA, &conn);
- curl_easy_setopt(conn->easy, CURLOPT_VERBOSE, 1L);
- curl_easy_setopt(conn->easy, CURLOPT_ERRORBUFFER, conn->error);
- curl_easy_setopt(conn->easy, CURLOPT_PRIVATE, conn);
- curl_easy_setopt(conn->easy, CURLOPT_NOPROGRESS, 1L);
- curl_easy_setopt(conn->easy, CURLOPT_PROGRESSFUNCTION, prog_cb);
- curl_easy_setopt(conn->easy, CURLOPT_PROGRESSDATA, conn);
- curl_easy_setopt(conn->easy, CURLOPT_LOW_SPEED_TIME, 3L);
- curl_easy_setopt(conn->easy, CURLOPT_LOW_SPEED_LIMIT, 10L);
-
- /* call this function to get a socket */
- curl_easy_setopt(conn->easy, CURLOPT_OPENSOCKETFUNCTION, opensocket);
-
- /* call this function to close a socket */
- curl_easy_setopt(conn->easy, CURLOPT_CLOSESOCKETFUNCTION, close_socket);
-
- fprintf(MSG_OUT,
- "\nAdding easy %p to multi %p (%s)", conn->easy, g->multi, url);
- 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
- that the necessary socket_action() call will be called by this app */
-}
-
-int main(int argc, char **argv)
-{
- GlobalInfo g;
-
- (void)argc;
- (void)argv;
-
- memset(&g, 0, sizeof(GlobalInfo));
- g.multi = curl_multi_init();
-
- curl_multi_setopt(g.multi, CURLMOPT_SOCKETFUNCTION, sock_cb);
- curl_multi_setopt(g.multi, CURLMOPT_SOCKETDATA, &g);
- curl_multi_setopt(g.multi, CURLMOPT_TIMERFUNCTION, multi_timer_cb);
- curl_multi_setopt(g.multi, CURLMOPT_TIMERDATA, &g);
-
- new_conn((char *)"www.google.com", &g); /* add a URL */
-
- /* enter io_service run loop */
- io_service.run();
-
- curl_multi_cleanup(g.multi);
-
- fprintf(MSG_OUT, "\ndone.\n");
-
- return 0;
-}
diff --git a/docs/examples/curlx.c b/docs/examples/curlx.c
index 6a3645621..843d67050 100644
--- a/docs/examples/curlx.c
+++ b/docs/examples/curlx.c
@@ -15,7 +15,7 @@
*/
/*
- * Copyright (c) 2003 - 2019 The OpenEvidence Project. All rights reserved.
+ * Copyright (c) 2003 - 2020 The OpenEvidence Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -459,7 +459,7 @@ int main(int argc, char **argv)
if(!serverurl) {
int j = 0;
BIO_printf(p.errorbio, "no service URL in user cert "
- "cherching in others certificats\n");
+ "searching in others certificates\n");
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);
@@ -474,7 +474,7 @@ int main(int argc, char **argv)
}
if(!serverurl) {
- BIO_printf(p.errorbio, "no service URL in certificats,"
+ BIO_printf(p.errorbio, "no service URL in certificates,"
" check '-accesstype (AD_DVCS | ad_timestamping)'"
" or use '-connect'\n");
goto err;
diff --git a/docs/examples/ephiperfifo.c b/docs/examples/ephiperfifo.c
index 9f89125a9..c0c972a6b 100644
--- a/docs/examples/ephiperfifo.c
+++ b/docs/examples/ephiperfifo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -146,7 +146,7 @@ static int multi_timer_cb(CURLM *multi, long timeout_ms, GlobalInfo *g)
fprintf(MSG_OUT, "multi_timer_cb: Setting timeout to %ld ms\n", timeout_ms);
if(timeout_ms > 0) {
- its.it_interval.tv_sec = 1;
+ its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
its.it_value.tv_sec = timeout_ms / 1000;
its.it_value.tv_nsec = (timeout_ms % 1000) * 1000 * 1000;
@@ -155,7 +155,7 @@ static int multi_timer_cb(CURLM *multi, long timeout_ms, GlobalInfo *g)
/* libcurl wants us to timeout now, however setting both fields of
* new_value.it_value to zero disarms the timer. The closest we can
* do is to schedule the timer to fire in 1 ns. */
- its.it_interval.tv_sec = 1;
+ its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 1;
@@ -488,7 +488,7 @@ int main(int argc, char **argv)
}
memset(&its, 0, sizeof(struct itimerspec));
- its.it_interval.tv_sec = 1;
+ its.it_interval.tv_sec = 0;
its.it_value.tv_sec = 1;
timerfd_settime(g.tfd, 0, &its, NULL);
diff --git a/docs/examples/http2-download.c b/docs/examples/http2-download.c
index e550f6020..3504c5af2 100644
--- a/docs/examples/http2-download.c
+++ b/docs/examples/http2-download.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,6 +26,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
/* somewhat unix-specific */
#include <sys/time.h>
@@ -33,6 +34,7 @@
/* curl stuff */
#include <gnurl/curl.h>
+#include <gnurl/mprintf.h>
#ifndef CURLPIPE_MULTIPLEX
/* This little trick will just make sure that we don't enable pipelining for
@@ -146,9 +148,14 @@ static void setup(struct transfer *t, int num)
hnd = t->easy = curl_easy_init();
- snprintf(filename, 128, "dl-%d", num);
+ curl_msnprintf(filename, 128, "dl-%d", num);
t->out = fopen(filename, "wb");
+ if(!t->out) {
+ fprintf(stderr, "error: could not open file %s for writing: %s\n",
+ filename, strerror(errno));
+ exit(1);
+ }
/* write to this file */
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, t->out);
diff --git a/docs/examples/http2-upload.c b/docs/examples/http2-upload.c
index 5f32faaba..6aa48ecbc 100644
--- a/docs/examples/http2-upload.c
+++ b/docs/examples/http2-upload.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -28,6 +28,7 @@
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
+#include <errno.h>
/* somewhat unix-specific */
#include <sys/time.h>
@@ -35,6 +36,7 @@
/* curl stuff */
#include <gnurl/curl.h>
+#include <gnurl/mprintf.h>
#ifndef CURLPIPE_MULTIPLEX
/* This little trick will just make sure that we don't enable pipelining for
@@ -123,8 +125,8 @@ int my_trace(CURL *handle, curl_infotype type,
}
secs = epoch_offset + tv.tv_sec;
now = localtime(&secs); /* not thread safe but we don't care */
- snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld",
- now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec);
+ curl_msnprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld",
+ now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec);
switch(type) {
case CURLINFO_TEXT:
@@ -176,16 +178,31 @@ static void setup(struct input *i, int num, const char *upload)
hnd = i->hnd = curl_easy_init();
i->num = num;
- snprintf(filename, 128, "dl-%d", num);
+ curl_msnprintf(filename, 128, "dl-%d", num);
out = fopen(filename, "wb");
+ if(!out) {
+ fprintf(stderr, "error: could not open file %s for writing: %s\n", upload,
+ strerror(errno));
+ exit(1);
+ }
- snprintf(url, 256, "https://localhost:8443/upload-%d", num);
+ curl_msnprintf(url, 256, "https://localhost:8443/upload-%d", num);
/* get the file size of the local file */
- stat(upload, &file_info);
+ if(stat(upload, &file_info)) {
+ fprintf(stderr, "error: could not stat file %s: %s\n", upload,
+ strerror(errno));
+ exit(1);
+ }
+
uploadsize = file_info.st_size;
i->in = fopen(upload, "rb");
+ if(!i->in) {
+ fprintf(stderr, "error: could not open file %s for reading: %s\n", upload,
+ strerror(errno));
+ exit(1);
+ }
/* write to this file */
curl_easy_setopt(hnd, CURLOPT_WRITEDATA, out);
diff --git a/docs/examples/multi-event.c b/docs/examples/multi-event.c
index 3ec16b157..307b316af 100644
--- a/docs/examples/multi-event.c
+++ b/docs/examples/multi-event.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -41,7 +41,7 @@ typedef struct curl_context_s {
static void curl_perform(int fd, short event, void *arg);
-static curl_context_t* create_curl_context(curl_socket_t sockfd)
+static curl_context_t *create_curl_context(curl_socket_t sockfd)
{
curl_context_t *context;
diff --git a/docs/examples/multi-uv.c b/docs/examples/multi-uv.c
index a76201496..e9cc7b125 100644
--- a/docs/examples/multi-uv.c
+++ b/docs/examples/multi-uv.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -46,7 +46,7 @@ typedef struct curl_context_s {
curl_socket_t sockfd;
} curl_context_t;
-static curl_context_t* create_curl_context(curl_socket_t sockfd)
+static curl_context_t *create_curl_context(curl_socket_t sockfd)
{
curl_context_t *context;
diff --git a/docs/examples/multithread.c b/docs/examples/multithread.c
index 4ab844bb5..f25407e69 100644
--- a/docs/examples/multithread.c
+++ b/docs/examples/multithread.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -89,6 +89,6 @@ int main(int argc, char **argv)
pthread_join(tid[i], NULL);
fprintf(stderr, "Thread %d terminated\n", i);
}
-
+ curl_global_cleanup();
return 0;
}
diff --git a/docs/libcurl/ABI b/docs/libcurl/ABI.md
index c7c914202..39134a1ae 100644
--- a/docs/libcurl/ABI
+++ b/docs/libcurl/ABI.md
@@ -7,8 +7,7 @@ ABI - Application Binary Interface
[Wikipedia has a longer description](https://en.wikipedia.org/wiki/Application_binary_interface)
-Upgrades
---------
+## Upgrades
In the vast majority of all cases, a typical libcurl upgrade does not break
the ABI at all. Your application can remain using libcurl just as before,
@@ -17,14 +16,12 @@ Upgrades
to verify that your application still builds fine and uses libcurl as it now
is defined to work.
-Version Numbers
----------------
+## Version Numbers
In libcurl land, you really can't tell by the libcurl version number if that
libcurl is binary compatible or not with another libcurl version.
-Soname Bumps
-------------
+## Soname Bumps
Whenever there are changes done to the library that will cause an ABI
breakage, that may require your application to get attention or possibly be
@@ -40,8 +37,7 @@ Soname Bumps
We are determined to bump the SONAME as rarely as possible. Ideally, we
never do it again.
-Downgrades
-----------
+## Downgrades
Going to an older libcurl version from one you're currently using can be a
tricky thing. Mostly we add features and options to newer libcurls as that
@@ -51,18 +47,17 @@ Downgrades
downgrade so far so you cross an ABI break border and thus a different
soname, and then your application may need to adapt to the modified ABI.
-History
--------
+## History
- The previous major library soname number bumps (breaking backwards
- compatibility) have happened the following times:
+ The previous major library soname number bumps (breaking backwards
+ compatibility) have happened the following times:
- 0 - libcurl 7.1, August 2000
+ 0 - libcurl 7.1, August 2000
- 1 - libcurl 7.5 December 2000
+ 1 - libcurl 7.5 December 2000
- 2 - libcurl 7.7 March 2001
+ 2 - libcurl 7.7 March 2001
- 3 - libcurl 7.12.0 June 2004
+ 3 - libcurl 7.12.0 June 2004
- 4 - libcurl 7.16.0 October 2006
+ 4 - libcurl 7.16.0 October 2006
diff --git a/docs/libcurl/Makefile.am b/docs/libcurl/Makefile.am
index 54c3e7e6f..224eff1c2 100644
--- a/docs/libcurl/Makefile.am
+++ b/docs/libcurl/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -38,8 +38,8 @@ dist_m4macro_DATA = libgnurl.m4
CLEANFILES = $(HTMLPAGES) $(PDFPAGES) $(TESTS) $(man_DISTMANS) \
libgnurl-symbols.3
-EXTRA_DIST = $(man_MANS) ABI symbols-in-versions symbols.pl \
- mksymbolsmanpage.pl
+EXTRA_DIST = $(man_MANS) ABI.md symbols-in-versions symbols.pl \
+ mksymbolsmanpage.pl CMakeLists.txt
MAN2HTML= roffit --mandir=. $< >$@
SUFFIXES = .3 .html
diff --git a/docs/libcurl/gnurl_easy_escape.3 b/docs/libcurl/gnurl_easy_escape.3
index 1065a5c67..8430ea1c2 100644
--- a/docs/libcurl/gnurl_easy_escape.3
+++ b/docs/libcurl/gnurl_easy_escape.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -51,7 +51,7 @@ to the function is encoded correctly.
.SH AVAILABILITY
Added in 7.15.4 and replaces the old \fIcurl_escape(3)\fP function.
.SH RETURN VALUE
-A pointer to a zero terminated string or NULL if it failed.
+A pointer to a null-terminated string or NULL if it failed.
.SH EXAMPLE
.nf
CURL *curl = curl_easy_init();
diff --git a/docs/libcurl/gnurl_easy_setopt.3 b/docs/libcurl/gnurl_easy_setopt.3
index 196899fab..6d6e3f842 100644
--- a/docs/libcurl/gnurl_easy_setopt.3
+++ b/docs/libcurl/gnurl_easy_setopt.3
@@ -506,16 +506,24 @@ Sets the interval at which connection upkeep are performed. See
.SH SSL and SECURITY OPTIONS
.IP CURLOPT_SSLCERT
Client cert. See \fICURLOPT_SSLCERT(3)\fP
+.IP CURLOPT_SSLCERT_BLOB
+Client cert memory buffer. See \fICURLOPT_SSLCERT_BLOB(3)\fP
.IP CURLOPT_PROXY_SSLCERT
Proxy client cert. See \fICURLOPT_PROXY_SSLCERT(3)\fP
+.IP CURLOPT_PROXY_SSLCERT_BLOB
+Proxy client cert memory buffer. See \fICURLOPT_PROXY_SSLCERT_BLOB(3)\fP
.IP CURLOPT_SSLCERTTYPE
Client cert type. See \fICURLOPT_SSLCERTTYPE(3)\fP
.IP CURLOPT_PROXY_SSLCERTTYPE
Proxy client cert type. See \fICURLOPT_PROXY_SSLCERTTYPE(3)\fP
.IP CURLOPT_SSLKEY
Client key. See \fICURLOPT_SSLKEY(3)\fP
+.IP CURLOPT_SSLKEY_BLOB
+Client key memory buffer. See \fICURLOPT_SSLKEY_BLOB(3)\fP
.IP CURLOPT_PROXY_SSLKEY
Proxy client key. See \fICURLOPT_PROXY_SSLKEY(3)\fP
+.IP CURLOPT_PROXY_SSLKEY_BLOB
+Proxy client key. See \fICURLOPT_PROXY_SSLKEY_BLOB(3)\fP
.IP CURLOPT_SSLKEYTYPE
Client key type. See \fICURLOPT_SSLKEYTYPE(3)\fP
.IP CURLOPT_PROXY_SSLKEYTYPE
@@ -554,6 +562,12 @@ CA cert bundle. See \fICURLOPT_CAINFO(3)\fP
Proxy CA cert bundle. See \fICURLOPT_PROXY_CAINFO(3)\fP
.IP CURLOPT_ISSUERCERT
Issuer certificate. See \fICURLOPT_ISSUERCERT(3)\fP
+.IP CURLOPT_ISSUERCERT_BLOB
+Issuer certificate memory buffer. See \fICURLOPT_ISSUERCERT_BLOB(3)\fP
+.IP CURLOPT_PROXY_ISSUERCERT
+Proxy issuer certificate. See \fICURLOPT_PROXY_ISSUERCERT(3)\fP
+.IP CURLOPT_PROXY_ISSUERCERT_BLOB
+Proxy issuer certificate memory buffer. See \fICURLOPT_PROXY_ISSUERCERT_BLOB(3)\fP
.IP CURLOPT_CAPATH
Path to CA cert bundle. See \fICURLOPT_CAPATH(3)\fP
.IP CURLOPT_PROXY_CAPATH
diff --git a/docs/libcurl/gnurl_easy_strerror.3 b/docs/libcurl/gnurl_easy_strerror.3
index c20bcb9d3..ec49d2cc0 100644
--- a/docs/libcurl/gnurl_easy_strerror.3
+++ b/docs/libcurl/gnurl_easy_strerror.3
@@ -35,6 +35,6 @@ specific error descriptions generated at run-time.
.SH AVAILABILITY
This function was added in libcurl 7.12.0
.SH RETURN VALUE
-A pointer to a zero terminated string.
+A pointer to a null-terminated string.
.SH "SEE ALSO"
.BR libcurl-errors "(3), " curl_multi_strerror "(3), " curl_share_strerror "(3)"
diff --git a/docs/libcurl/gnurl_easy_unescape.3 b/docs/libcurl/gnurl_easy_unescape.3
index 397ae1ab1..9841b4435 100644
--- a/docs/libcurl/gnurl_easy_unescape.3
+++ b/docs/libcurl/gnurl_easy_unescape.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -49,6 +49,6 @@ You must \fIcurl_free(3)\fP the returned string when you're done with it.
.SH AVAILABILITY
Added in 7.15.4 and replaces the old \fIcurl_unescape(3)\fP function.
.SH RETURN VALUE
-A pointer to a zero terminated string or NULL if it failed.
+A pointer to a null-terminated string or NULL if it failed.
.SH "SEE ALSO"
.BR curl_easy_escape "(3), " curl_free "(3)," RFC 3986
diff --git a/docs/libcurl/gnurl_escape.3 b/docs/libcurl/gnurl_escape.3
index 8017ca7c9..c65392801 100644
--- a/docs/libcurl/gnurl_escape.3
+++ b/docs/libcurl/gnurl_escape.3
@@ -43,6 +43,6 @@ You must \fIcurl_free(3)\fP the returned string when you're done with it.
Since 7.15.4, \fIcurl_easy_escape(3)\fP should be used. This function will
be removed in a future release.
.SH RETURN VALUE
-A pointer to a zero terminated string or NULL if it failed.
+A pointer to a null-terminated string or NULL if it failed.
.SH "SEE ALSO"
.BR curl_unescape "(3), " curl_free "(3), " RFC 2396
diff --git a/docs/libcurl/gnurl_getenv.3 b/docs/libcurl/gnurl_getenv.3
index 2d84a727f..a953eba35 100644
--- a/docs/libcurl/gnurl_getenv.3
+++ b/docs/libcurl/gnurl_getenv.3
@@ -38,7 +38,7 @@ This function will be removed from the public libcurl API in a near future. It
will instead be made "available" by source code access only, and then as
curlx_getenv().
.SH RETURN VALUE
-A pointer to a zero terminated string or NULL if it failed to find the
+A pointer to a null-terminated string or NULL if it failed to find the
specified name.
.SH NOTE
Under unix operating systems, there isn't any point in returning an allocated
diff --git a/docs/libcurl/gnurl_mime_data.3 b/docs/libcurl/gnurl_mime_data.3
index a14617cea..728826ab0 100644
--- a/docs/libcurl/gnurl_mime_data.3
+++ b/docs/libcurl/gnurl_mime_data.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -34,7 +34,7 @@ curl_mime_data - set a mime part's body data from memory
\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
+\fICURL_ZERO_TERMINATED\fP to indicate \fIdata\fP is a null-terminated
character string.
\fIpart\fP is the part's to assign contents to.
diff --git a/docs/libcurl/gnurl_mime_encoder.3 b/docs/libcurl/gnurl_mime_encoder.3
index 08c65c3e7..d0546b6b0 100644
--- a/docs/libcurl/gnurl_mime_encoder.3
+++ b/docs/libcurl/gnurl_mime_encoder.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -33,7 +33,7 @@ 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
+\fIencoding\fP is a pointer to a null-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.
diff --git a/docs/libcurl/gnurl_mime_filedata.3 b/docs/libcurl/gnurl_mime_filedata.3
index 1481174db..e89d22fea 100644
--- a/docs/libcurl/gnurl_mime_filedata.3
+++ b/docs/libcurl/gnurl_mime_filedata.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -35,9 +35,9 @@ 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 the previous part contents settings. Filename storage can be
-safely be reused after this call.
+\fIfilename\fP points to the null-terminated file's path name. The pointer can
+be NULL to detach the 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
diff --git a/docs/libcurl/gnurl_mime_filename.3 b/docs/libcurl/gnurl_mime_filename.3
index b0c20791e..6534a9ce5 100644
--- a/docs/libcurl/gnurl_mime_filename.3
+++ b/docs/libcurl/gnurl_mime_filename.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -36,8 +36,8 @@ 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.
+\fIfilename\fP points to the null-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
diff --git a/docs/libcurl/gnurl_mime_name.3 b/docs/libcurl/gnurl_mime_name.3
index ad5ff4788..79afe7515 100644
--- a/docs/libcurl/gnurl_mime_name.3
+++ b/docs/libcurl/gnurl_mime_name.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -33,7 +33,7 @@ fields are named.
\fIpart\fP is the part's handle to assign a name to.
-\fIname\fP points to the zero-terminated name string.
+\fIname\fP points to the null-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:
diff --git a/docs/libcurl/gnurl_mime_type.3 b/docs/libcurl/gnurl_mime_type.3
index eeb688aba..1c1daae9b 100644
--- a/docs/libcurl/gnurl_mime_type.3
+++ b/docs/libcurl/gnurl_mime_type.3
@@ -33,7 +33,7 @@ curl_mime_type - set 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
+\fImimetype\fP points to the null-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
diff --git a/docs/libcurl/gnurl_multi_strerror.3 b/docs/libcurl/gnurl_multi_strerror.3
index c2ee1e4e2..feb6cd684 100644
--- a/docs/libcurl/gnurl_multi_strerror.3
+++ b/docs/libcurl/gnurl_multi_strerror.3
@@ -32,6 +32,6 @@ error code passed in the argument \fIerrornum\fP.
.SH AVAILABILITY
This function was added in libcurl 7.12.0
.SH RETURN VALUE
-A pointer to a zero terminated string.
+A pointer to a null-terminated string.
.SH "SEE ALSO"
.BR libcurl-errors "(3), " curl_easy_strerror "(3), " curl_share_strerror "(3)"
diff --git a/docs/libcurl/gnurl_share_strerror.3 b/docs/libcurl/gnurl_share_strerror.3
index bbb0a0d00..5cb755742 100644
--- a/docs/libcurl/gnurl_share_strerror.3
+++ b/docs/libcurl/gnurl_share_strerror.3
@@ -32,6 +32,6 @@ error code passed in the argument \fIerrornum\fP.
.SH AVAILABILITY
This function was added in libcurl 7.12.0
.SH RETURN VALUE
-A pointer to a zero terminated string.
+A pointer to a null-terminated string.
.SH "SEE ALSO"
.BR libcurl-errors "(3), " curl_multi_strerror "(3), " curl_easy_strerror "(3)"
diff --git a/docs/libcurl/gnurl_unescape.3 b/docs/libcurl/gnurl_unescape.3
index 60c337816..c88b3947f 100644
--- a/docs/libcurl/gnurl_unescape.3
+++ b/docs/libcurl/gnurl_unescape.3
@@ -43,6 +43,6 @@ You must \fIcurl_free(3)\fP the returned string when you're done with it.
Since 7.15.4, \fIcurl_easy_unescape(3)\fP should be used. This function will
be removed in a future release.
.SH RETURN VALUE
-A pointer to a zero terminated string or NULL if it failed.
+A pointer to a null-terminated string or NULL if it failed.
.SH "SEE ALSO"
.br curl_easy_escape "(3)," curl_easy_unescape "(3)," curl_free "(3)," RFC 2396
diff --git a/docs/libcurl/gnurl_url_set.3 b/docs/libcurl/gnurl_url_set.3
index efee8cc5a..043ec38fb 100644
--- a/docs/libcurl/gnurl_url_set.3
+++ b/docs/libcurl/gnurl_url_set.3
@@ -35,7 +35,7 @@ Given the \fIurl\fP handle of an already parsed URL, this function lets the
user set/update individual pieces of it.
The \fIpart\fP argument should identify the particular URL part (see list
-below) to set or change, with \fIcontent\fP pointing to a zero terminated
+below) to set or change, with \fIcontent\fP pointing to a null-terminated
string with the new contents for that URL part. The contents should be in the
form and encoding they'd use in a URL: URL encoded.
@@ -51,7 +51,7 @@ populated with a URL, the new URL can be relative to the previous.
When successfully setting a new URL, relative or absolute, the handle contents
will be replaced with the information of the newly set URL.
-Pass a pointer to a zero terminated string to the \fIurl\fP parameter. The
+Pass a pointer to a null-terminated string to the \fIurl\fP parameter. The
string must point to a correctly formatted "RFC 3986+" URL or be a NULL
pointer.
.IP CURLUPART_SCHEME
diff --git a/docs/libcurl/gnurl_version.3 b/docs/libcurl/gnurl_version.3
index 56ea8051f..d08ef0bdc 100644
--- a/docs/libcurl/gnurl_version.3
+++ b/docs/libcurl/gnurl_version.3
@@ -33,7 +33,7 @@ its important components (like OpenSSL version).
We recommend using \fIcurl_version_info(3)\fP instead!
.SH RETURN VALUE
-A pointer to a zero terminated string. The string resides in a statically
+A pointer to a null-terminated string. The string resides in a statically
allocated buffer and must not be freed by the caller.
.SH "SEE ALSO"
.BR curl_version_info "(3)"
diff --git a/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.3 b/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.3
new file mode 100644
index 000000000..5fbf86df4
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.3
@@ -0,0 +1,79 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_ISSUERCERT_BLOB 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_ISSUERCERT_BLOB \- issuer SSL certificate from memory blob
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ISSUERCERT_BLOB, struct curl_blob *stblob);
+.SH DESCRIPTION
+Pass a pointer to a curl_blob structure, which contains information (pointer
+and size) about a memory block with binary data of a CA certificate in PEM
+format. If the option is set, an additional check against the peer certificate
+is performed to verify the issuer is indeed the one associated with the
+certificate provided by the option. This additional check is useful in
+multi-level PKI where one needs to enforce that the peer certificate is from a
+specific branch of the tree.
+
+This option should be used in combination with the
+\fICURLOPT_SSL_VERIFYPEER(3)\fP option. Otherwise, the result of the check is
+not considered as failure.
+
+A specific error code (CURLE_SSL_ISSUER_ERROR) is defined with the option,
+which is returned if the setup of the SSL/TLS session has failed due to a
+mismatch with the issuer of peer certificate (\fICURLOPT_SSL_VERIFYPEER(3)\fP
+has to be set too for the check to fail).
+
+If the blob is initialized with the flags member of struct curl_blob set to
+CURL_BLOB_COPY, the application does not have to keep the buffer around after
+setting this.
+
+This option is an alternative to \fICURLOPT_ISSUERCERT(3)\fP which instead
+expects a file name as input.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS-based protocols
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ struct curl_blob blob;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ blob.data = certificateData;
+ blob.len = filesize;
+ blob.flags = CURL_BLOB_COPY;
+ curl_easy_setopt(curl, CURLOPT_ISSUERCERT_BLOB, &blob);
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in libcurl 7.71.0. This option is supported by the OpenSSL backends.
+.SH RETURN VALUE
+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_ISSUERCERT "(3),"
+.BR CURLOPT_CRLFILE "(3), " CURLOPT_SSL_VERIFYPEER "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.3 b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.3
new file mode 100644
index 000000000..f2add8163
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.3
@@ -0,0 +1,73 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_ISSUERCERT 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_ISSUERCERT \- proxy issuer SSL certificate filename
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_ISSUERCERT, char *file);
+.SH DESCRIPTION
+Pass a char * to a null-terminated string naming a \fIfile\fP holding a CA
+certificate in PEM format. If the option is set, an additional check against
+the peer certificate is performed to verify the issuer of the the HTTPS proxy
+is indeed the one associated with the certificate provided by the option.
+This additional check is useful in multi-level PKI where one needs to enforce
+that the peer certificate is from a specific branch of the tree.
+
+This option makes sense only when used in combination with the
+\fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP option. Otherwise, the result of the
+check is not considered as failure.
+
+A specific error code (CURLE_SSL_ISSUER_ERROR) is defined with the option,
+which is returned if the setup of the SSL/TLS session has failed due to a
+mismatch with the issuer of peer certificate
+(\fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP has to be set too for the check to
+fail).
+
+The application does not have to keep the string around after setting this
+option.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS-based protocols
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* using an HTTPS proxy */
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://localhost:443");
+ curl_easy_setopt(curl, CURLOPT_PROXY_ISSUERCERT, "/etc/certs/cacert.pem");
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in libcurl 7.71.0. This option is supported by the OpenSSL backends.
+.SH RETURN VALUE
+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_SSL_VERIFYPEER "(3), " CURLOPT_PROXY_SSL_VERIFYHOST "(3), "
+.BR CURLOPT_SSL_VERIFYPEER "(3), " CURLOPT_SSL_VERIFYHOST "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.3 b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.3
new file mode 100644
index 000000000..857fffde9
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.3
@@ -0,0 +1,85 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_ISSUERCERT_BLOB 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_ISSUERCERT_BLOB \- proxy issuer SSL certificate from memory blob
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_ISSUERCERT_BLOB,
+ struct curl_blob *blob);
+.fi
+.SH DESCRIPTION
+Pass a pointer to a curl_blob struct, which contains information (pointer and
+size) about a memory block with binary data of a CA certificate in PEM
+format. If the option is set, an additional check against the peer certificate
+is performed to verify the issuer of the the HTTPS proxy is indeed the one
+associated with the certificate provided by the option. This additional check
+is useful in multi-level PKI where one needs to enforce that the peer
+certificate is from a specific branch of the tree.
+
+This option should be used in combination with the
+\fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP option. Otherwise, the result of the
+check is not considered as failure.
+
+A specific error code (CURLE_SSL_ISSUER_ERROR) is defined with the option,
+which is returned if the setup of the SSL/TLS session has failed due to a
+mismatch with the issuer of peer certificate
+(\fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP has to be set too for the check to
+fail).
+
+If the blob is initialized with the flags member of struct curl_blob set to
+CURL_BLOB_COPY, the application does not have to keep the buffer around after
+setting this.
+
+This option is an alternative to \fICURLOPT_PROXY_ISSUERCERT(3)\fP which
+instead expects a file name as input.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS-based protocols
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ struct curl_blob blob;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ /* using an HTTPS proxy */
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://localhost:443");
+ blob.data = certificateData;
+ blob.len = filesize;
+ blob.flags = CURL_BLOB_COPY;
+ curl_easy_setopt(curl, CURLOPT_PROXY_ISSUERCERT_BLOB, &blob);
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in libcurl 7.71.0. This option is supported by the OpenSSL backends.
+.SH RETURN VALUE
+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_SSL_VERIFYPEER "(3), " CURLOPT_PROXY_SSL_VERIFYHOST "(3), "
+.BR CURLOPT_SSL_VERIFYPEER "(3), " CURLOPT_SSL_VERIFYHOST "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.3
new file mode 100644
index 000000000..8b5a1336d
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.3
@@ -0,0 +1,72 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_SSLCERT_BLOB 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_SSLCERT_BLOB \- SSL proxy client certificate from memory blob
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT_BLOB, struct curl_blob *blob);
+.SH DESCRIPTION
+Pass a pointer to a curl_blob structure, which contains information (pointer
+and size) about a memory block with binary data of the certificate used to
+connect to the HTTPS proxy. The format must be "P12" on Secure Transport or
+Schannel. The format must be "P12" or "PEM" on OpenSSL. The string "P12" or
+"PEM" must be specified with \fICURLOPT_PROXY_SSLCERTTYPE(3)\fP.
+
+If the blob is initialized with the flags member of struct curl_blob set to
+CURL_BLOB_COPY, the application does not have to keep the buffer around after
+setting this.
+
+This option is an alternative to \fICURLOPT_PROXY_SSLCERT(3)\fP which instead
+expects a file name as input.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ struct curl_blob blob;
+ blob.data = certificateData;
+ blob.len = filesize;
+ blob.flags = CURL_BLOB_COPY;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLKEY, "key.pem");
+ curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "s3cret");
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERT_BLOB, &blob);
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in libcurl 7.71.0. This option is supported by the OpenSSL, Secure
+Transport and Schannel backends.
+.SH RETURN VALUE
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_PROXY_SSLCERTTYPE "(3), " CURLOPT_PROXY_SSLKEY "(3), "
+.BR CURLOPT_PROXY_SSLCERT "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.3 b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.3
new file mode 100644
index 000000000..daaff0df0
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.3
@@ -0,0 +1,73 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_PROXY_SSLKEY_BLOB 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_PROXY_SSLKEY_BLOB \- private key for proxy cert from memory blob
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEY_BLOB,
+ struct curl_blob *blob);
+.fi
+.SH DESCRIPTION
+Pass a pointer to a curl_blob structure that contains information (pointer and
+size) about the private key for connecting to the HTTPS proxy. Compatible with
+OpenSSL. The format (like "PEM") must be specified with
+\fICURLOPT_PROXY_SSLKEYTYPE(3)\fP.
+
+If the blob is initialized with the flags member of struct curl_blob set to
+CURL_BLOB_COPY, the application does not have to keep the buffer around after
+setting this.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ struct curl_blob blob;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy");
+ blob.data = certificateData;
+ blob.len = filesize;
+ blob.flags = CURL_BLOB_COPY;
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERT_BLOB, &blob);
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLCERTTYPE, "PEM");
+
+ blob.data = privateKeyData;
+ blob.len = privateKeySize;
+ curl_easy_setopt(curl, CURLOPT_PROXY_SSLKEY_BLOB, &blob);
+ curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "s3cret");
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in libcurl 7.71.0. This option is supported by the OpenSSL backends.
+.SH RETURN VALUE
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_SSLKEYTYPE "(3), " CURLOPT_SSLKEY "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.3 b/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.3
new file mode 100644
index 000000000..ed13d6cfc
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.3
@@ -0,0 +1,69 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_SSLCERT_BLOB 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_SSLCERT_BLOB \- SSL client certificate from memory blob
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERT_BLOB, struct curl_blob *stblob);
+.SH DESCRIPTION
+Pass a pointer to a curl_blob structure, which contains (pointer and size) a
+client certificate. The format must be "P12" on Secure Transport or
+Schannel. The format must be "P12" or "PEM" on OpenSSL. The string "P12" or
+"PEM" must be specified with \fICURLOPT_SSLCERTTYPE(3)\fP.
+
+If the blob is initialized with the flags member of struct curl_blob set to
+CURL_BLOB_COPY, the application does not have to keep the buffer around after
+setting this.
+
+This option is an alternative to \fICURLOPT_SSLCERT(3)\fP which instead
+expects a file name as input.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ struct curl_blob stblob;
+ stblob.data = certificateData;
+ stblob.len = filesize;
+ stblob.flags = CURL_BLOB_COPY;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_SSLCERT_BLOB, &stblob);
+ curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "P12");
+ curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "s3cret");
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in libcurl 7.71.0. This option is supported by the OpenSSL, Secure
+Transport and Schannel backends.
+.SH RETURN VALUE
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_SSLCERTTYPE "(3), " CURLOPT_SSLKEY "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.3 b/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.3
new file mode 100644
index 000000000..1f657c8ec
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.3
@@ -0,0 +1,75 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_SSLKEY_BLOB 3 "24 Jun 2020" "libcurl 7.71.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_SSLKEY_BLOB \- private key for client cert from memory blob
+.SH SYNOPSIS
+.nf
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLKEY_BLOB,
+ struct curl_blob *blob);
+.fi
+.SH DESCRIPTION
+Pass a pointer to a curl_blob structure, which contains information (pointer
+and size) for a private key. Compatible with OpenSSL. The format (like "PEM")
+must be specified with \fICURLOPT_SSLKEYTYPE(3)\fP.
+
+If the blob is initialized with the flags member of struct curl_blob set to
+CURL_BLOB_COPY, the application does not have to keep the buffer around after
+setting this.
+
+This option is an alternative to \fICURLOPT_SSLKEY(3)\fP which instead expects
+a file name as input.
+.SH DEFAULT
+NULL
+.SH PROTOCOLS
+All TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ struct curl_blob blob;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ blob.data = certificateData;
+ blob.len = filesize;
+ blob.flags = CURL_BLOB_COPY;
+ curl_easy_setopt(curl, CURLOPT_SSLCERT_BLOB, &blob);
+ curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
+
+ blob.data = privateKeyData;
+ blob.len = privateKeySize;
+ curl_easy_setopt(curl, CURLOPT_SSLKEY_BLOB, &blob);
+ curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "s3cret");
+ curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM");
+ ret = curl_easy_perform(curl);
+ curl_easy_cleanup(curl);
+}
+.fi
+.SH AVAILABILITY
+Added in libcurl 7.71.0. This option is supported by the OpenSSL backends.
+.SH RETURN VALUE
+Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
+CURLE_OUT_OF_MEMORY if there was insufficient heap space.
+.SH "SEE ALSO"
+.BR CURLOPT_SSLKEYTYPE "(3), " CURLOPT_SSLKEY "(3), "
diff --git a/docs/libcurl/opts/GNURLINFO_ACTIVESOCKET.3 b/docs/libcurl/opts/GNURLINFO_ACTIVESOCKET.3
index 0d9179024..3a3d54fa3 100644
--- a/docs/libcurl/opts/GNURLINFO_ACTIVESOCKET.3
+++ b/docs/libcurl/opts/GNURLINFO_ACTIVESOCKET.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -29,15 +29,17 @@ CURLINFO_ACTIVESOCKET \- get the active socket
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_ACTIVESOCKET,
curl_socket_t *socket);
.SH DESCRIPTION
-Pass a pointer to a curl_socket_t to receive the active socket used by this
-curl session. If the socket is no longer valid, \fICURL_SOCKET_BAD\fP is
-returned. When you finish working with the socket, you must call
-\fIcurl_easy_cleanup(3)\fP as usual on the easy handle and let libcurl close
-the socket and cleanup other resources associated with the handle. This is
-typically used in combination with \fICURLOPT_CONNECT_ONLY(3)\fP.
+Pass a pointer to a curl_socket_t to receive the most recently active socket
+used for the transfer connection by this curl session. If the socket is no
+longer valid, \fICURL_SOCKET_BAD\fP is returned. When you are finished working
+with the socket, you must call \fIcurl_easy_cleanup(3)\fP as usual on the easy
+handle and let libcurl close the socket and cleanup other resources associated
+with the handle. This option returns the active socket only after the transfer
+is complete, and is typically used in combination with
+\fICURLOPT_CONNECT_ONLY(3)\fP, which skips the transfer phase.
-This option was added as a replacement for \fICURLINFO_LASTSOCKET(3)\fP since
-that one isn't working on all platforms.
+\fICURLINFO_ACTIVESOCKET(3)\fP was added as a replacement for
+\fICURLINFO_LASTSOCKET(3)\fP since that one isn't working on all platforms.
.SH PROTOCOLS
All
.SH EXAMPLE
diff --git a/docs/libcurl/opts/GNURLINFO_LOCAL_IP.3 b/docs/libcurl/opts/GNURLINFO_LOCAL_IP.3
index 65df84137..a2fe9b736 100644
--- a/docs/libcurl/opts/GNURLINFO_LOCAL_IP.3
+++ b/docs/libcurl/opts/GNURLINFO_LOCAL_IP.3
@@ -28,7 +28,7 @@ CURLINFO_LOCAL_IP \- get local IP address of last connection
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_LOCAL_IP, char **ip);
.SH DESCRIPTION
-Pass a pointer to a char pointer to receive the pointer to a zero-terminated
+Pass a pointer to a char pointer to receive the pointer to a null-terminated
string holding the IP address of the local end of most recent connection done
with this \fBcurl\fP handle. This string may be IPv6 when that is
enabled. Note that you get a pointer to a memory area that will be re-used at
diff --git a/docs/libcurl/opts/GNURLINFO_PRIMARY_IP.3 b/docs/libcurl/opts/GNURLINFO_PRIMARY_IP.3
index 2d700569d..3100c2086 100644
--- a/docs/libcurl/opts/GNURLINFO_PRIMARY_IP.3
+++ b/docs/libcurl/opts/GNURLINFO_PRIMARY_IP.3
@@ -28,7 +28,7 @@ CURLINFO_PRIMARY_IP \- get IP address of last connection
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_PRIMARY_IP, char **ip);
.SH DESCRIPTION
-Pass a pointer to a char pointer to receive the pointer to a zero-terminated
+Pass a pointer to a char pointer to receive the pointer to a null-terminated
string holding the IP address of the most recent connection done with this
\fBcurl\fP handle. This string may be IPv6 when that is enabled. Note that you
get a pointer to a memory area that will be re-used at next request so you
diff --git a/docs/libcurl/opts/GNURLINFO_SCHEME.3 b/docs/libcurl/opts/GNURLINFO_SCHEME.3
index 69f20a9f4..13f0a023a 100644
--- a/docs/libcurl/opts/GNURLINFO_SCHEME.3
+++ b/docs/libcurl/opts/GNURLINFO_SCHEME.3
@@ -28,7 +28,7 @@ CURLINFO_SCHEME \- get the URL scheme (sometimes called protocol) used in the co
CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SCHEME, char **scheme);
.SH DESCRIPTION
-Pass a pointer to a char pointer to receive the pointer to a zero-terminated
+Pass a pointer to a char pointer to receive the pointer to a null-terminated
string holding the URL scheme used for the most recent connection done with
this CURL \fBhandle\fP.
diff --git a/docs/libcurl/opts/GNURLINFO_SSL_VERIFYRESULT.3 b/docs/libcurl/opts/GNURLINFO_SSL_VERIFYRESULT.3
index af82908c9..5b4d64341 100644
--- a/docs/libcurl/opts/GNURLINFO_SSL_VERIFYRESULT.3
+++ b/docs/libcurl/opts/GNURLINFO_SSL_VERIFYRESULT.3
@@ -30,7 +30,7 @@ CURLcode curl_easy_getinfo(CURL *handle, CURLINFO_SSL_VERIFYRESULT, long *result
.SH DESCRIPTION
Pass a pointer to a long to receive the result of the server SSL certificate
verification that was requested (using the \fICURLOPT_SSL_VERIFYPEER(3)\fP
-option.
+option).
0 is a positive result. Non-zero is an error.
.SH PROTOCOLS
@@ -50,7 +50,7 @@ if(curl) {
}
.fi
.SH AVAILABILITY
-Added in 7.5. Only set by the OpenSSL/libressl/boringssl and NSS backends.
+Added in 7.5. Only set by the OpenSSL/libressl/boringssl, NSS and GnuTLS backends.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
diff --git a/docs/libcurl/opts/GNURLMOPT_PIPELINING_SERVER_BL.3 b/docs/libcurl/opts/GNURLMOPT_PIPELINING_SERVER_BL.3
index 70a1826c5..46bce5f63 100644
--- a/docs/libcurl/opts/GNURLMOPT_PIPELINING_SERVER_BL.3
+++ b/docs/libcurl/opts/GNURLMOPT_PIPELINING_SERVER_BL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\"
.TH GNURLMOPT_PIPELINING_SERVER_BL 3 "4 Nov 2014" "libcurl 7.39.0" "curl_multi_setopt options"
.SH NAME
-CURLMOPT_PIPELINING_SERVER_BL \- pipelining server blacklist
+CURLMOPT_PIPELINING_SERVER_BL \- pipelining server block list
.SH SYNOPSIS
#include <gnurl/curl.h>
@@ -31,28 +31,28 @@ CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING_SERVER_BL, char *
No function since pipelining was removed in 7.62.0.
Pass a \fBservers\fP array of char *, ending with a NULL entry. This is a list
-of server types prefixes (in the Server: HTTP header) that are blacklisted
-from pipelining, i.e server types that are known to not support HTTP
+of server types prefixes (in the Server: HTTP header) that are blocked from
+pipelining, i.e server types that are known to not support HTTP
pipelining. The array is copied by libcurl.
Note that the comparison matches if the Server: header begins with the string
-in the blacklist, i.e "Server: Ninja 1.2.3" and "Server: Ninja 1.4.0" can
-both be blacklisted by having "Ninja" in the backlist.
+in the block list, i.e "Server: Ninja 1.2.3" and "Server: Ninja 1.4.0" can
+both be blocked by having "Ninja" in the list.
-Pass a NULL pointer to clear the blacklist.
+Pass a NULL pointer to clear the block list.
.SH DEFAULT
-The default value is NULL, which means that there is no blacklist.
+The default value is NULL, which means that there is no block list.
.SH PROTOCOLS
.SH EXAMPLE
.nf
- server_blacklist[] =
+ char *server_block_list[] =
{
"Microsoft-IIS/6.0",
"nginx/0.8.54",
NULL
};
- curl_multi_setopt(m, CURLMOPT_PIPELINING_SERVER_BL, server_blacklist);
+ curl_multi_setopt(m, CURLMOPT_PIPELINING_SERVER_BL, server_block_list);
.fi
.SH AVAILABILITY
Added in 7.30.0
diff --git a/docs/libcurl/opts/GNURLMOPT_PIPELINING_SITE_BL.3 b/docs/libcurl/opts/GNURLMOPT_PIPELINING_SITE_BL.3
index 89cb1b0ed..ab42861e3 100644
--- a/docs/libcurl/opts/GNURLMOPT_PIPELINING_SITE_BL.3
+++ b/docs/libcurl/opts/GNURLMOPT_PIPELINING_SITE_BL.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -22,7 +22,7 @@
.\"
.TH GNURLMOPT_PIPELINING_SITE_BL 3 "4 Nov 2014" "libcurl 7.39.0" "curl_multi_setopt options"
.SH NAME
-CURLMOPT_PIPELINING_SITE_BL \- pipelining host blacklist
+CURLMOPT_PIPELINING_SITE_BL \- pipelining host block list
.SH SYNOPSIS
#include <gnurl/curl.h>
@@ -31,24 +31,24 @@ CURLMcode curl_multi_setopt(CURLM *handle, CURLMOPT_PIPELINING_SITE_BL, char **h
No function since pipelining was removed in 7.62.0.
Pass a \fBhosts\fP array of char *, ending with a NULL entry. This is a list
-of sites that are blacklisted from pipelining, i.e sites that are known to not
+of sites that are blocked from pipelining, i.e sites that are known to not
support HTTP pipelining. The array is copied by libcurl.
-Pass a NULL pointer to clear the blacklist.
+Pass a NULL pointer to clear the block list.
.SH DEFAULT
-The default value is NULL, which means that there is no blacklist.
+The default value is NULL, which means that there is no block list.
.SH PROTOCOLS
HTTP(S)
.SH EXAMPLE
.nf
- site_blacklist[] =
+ char *site_block_list[] =
{
"www.haxx.se",
"www.example.com:1234",
NULL
};
- curl_multi_setopt(m, CURLMOPT_PIPELINING_SITE_BL, site_blacklist);
+ curl_multi_setopt(m, CURLMOPT_PIPELINING_SITE_BL, site_block_list);
.fi
.SH AVAILABILITY
Added in 7.30.0
diff --git a/docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.3 b/docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.3
index 4f98f4b1b..fbb25c4f6 100644
--- a/docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.3
+++ b/docs/libcurl/opts/GNURLOPT_ABSTRACT_UNIX_SOCKET.3
@@ -29,7 +29,7 @@ CURLOPT_ABSTRACT_UNIX_SOCKET \- set an abstract Unix domain socket
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ABSTRACT_UNIX_SOCKET, char *path);
.SH DESCRIPTION
Enables the use of an abstract Unix domain socket instead of establishing a TCP
-connection to a host. The parameter should be a char * to a zero terminated string
+connection to a host. The parameter should be a char * to a null-terminated string
holding the path of the socket. The path will be set to \fIpath\fP prefixed by a
NULL byte (this is the convention for abstract sockets, however it should be stressed
that the path passed to this function should not contain a leading NULL).
diff --git a/docs/libcurl/opts/GNURLOPT_CAINFO.3 b/docs/libcurl/opts/GNURLOPT_CAINFO.3
index 1a3ca4319..83a86a643 100644
--- a/docs/libcurl/opts/GNURLOPT_CAINFO.3
+++ b/docs/libcurl/opts/GNURLOPT_CAINFO.3
@@ -28,7 +28,7 @@ CURLOPT_CAINFO \- path to Certificate Authority (CA) bundle
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAINFO, char *path);
.SH DESCRIPTION
-Pass a char * to a zero terminated string naming a file holding one or more
+Pass a char * to a null-terminated string naming a file holding one or more
certificates to verify the peer with.
If \fICURLOPT_SSL_VERIFYPEER(3)\fP is zero and you avoid verifying the
diff --git a/docs/libcurl/opts/GNURLOPT_CAPATH.3 b/docs/libcurl/opts/GNURLOPT_CAPATH.3
index 8436e2746..17ff2fb47 100644
--- a/docs/libcurl/opts/GNURLOPT_CAPATH.3
+++ b/docs/libcurl/opts/GNURLOPT_CAPATH.3
@@ -28,7 +28,7 @@ CURLOPT_CAPATH \- specify directory holding CA certificates
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CAPATH, char *capath);
.SH DESCRIPTION
-Pass a char * to a zero terminated string naming a directory holding multiple
+Pass a char * to a null-terminated string naming a directory holding multiple
CA certificates to verify the peer with. If libcurl is built against OpenSSL,
the certificate directory must be prepared using the openssl c_rehash utility.
This makes sense only when used in combination with the
diff --git a/docs/libcurl/opts/GNURLOPT_COOKIE.3 b/docs/libcurl/opts/GNURLOPT_COOKIE.3
index d38dd2c07..3a2a1967e 100644
--- a/docs/libcurl/opts/GNURLOPT_COOKIE.3
+++ b/docs/libcurl/opts/GNURLOPT_COOKIE.3
@@ -28,7 +28,7 @@ CURLOPT_COOKIE \- set contents of HTTP Cookie header
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIE, char *cookie);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. It will be used to
+Pass a pointer to a null-terminated string as parameter. It will be used to
set a cookie in the HTTP request. The format of the string should be
NAME=CONTENTS, where NAME is the cookie name and CONTENTS is what the cookie
should contain.
diff --git a/docs/libcurl/opts/GNURLOPT_COOKIEFILE.3 b/docs/libcurl/opts/GNURLOPT_COOKIEFILE.3
index 71e0d2c5f..50298e550 100644
--- a/docs/libcurl/opts/GNURLOPT_COOKIEFILE.3
+++ b/docs/libcurl/opts/GNURLOPT_COOKIEFILE.3
@@ -28,7 +28,7 @@ CURLOPT_COOKIEFILE \- file name to read cookies from
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIEFILE, char *filename);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. It should point to
+Pass a pointer to a null-terminated string as parameter. It should point to
the file name of your file holding cookie data to read. The cookie data can be
in either the old Netscape / Mozilla cookie data format or just regular HTTP
headers (Set-Cookie style) dumped to a file.
diff --git a/docs/libcurl/opts/GNURLOPT_COOKIEJAR.3 b/docs/libcurl/opts/GNURLOPT_COOKIEJAR.3
index b062e26e1..0a6f60ba0 100644
--- a/docs/libcurl/opts/GNURLOPT_COOKIEJAR.3
+++ b/docs/libcurl/opts/GNURLOPT_COOKIEJAR.3
@@ -28,7 +28,7 @@ CURLOPT_COOKIEJAR \- file name to store cookies to
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_COOKIEJAR, char *filename);
.SH DESCRIPTION
-Pass a \fIfilename\fP as char *, zero terminated. This will make libcurl write
+Pass a \fIfilename\fP as char *, null-terminated. This will make libcurl write
all internally known cookies to the specified file when
\fIcurl_easy_cleanup(3)\fP is called. If no cookies are known, no file will be
created. Specify "-" as filename to instead have the cookies written to
diff --git a/docs/libcurl/opts/GNURLOPT_COPYPOSTFIELDS.3 b/docs/libcurl/opts/GNURLOPT_COPYPOSTFIELDS.3
index 16f12f28a..9a6940663 100644
--- a/docs/libcurl/opts/GNURLOPT_COPYPOSTFIELDS.3
+++ b/docs/libcurl/opts/GNURLOPT_COPYPOSTFIELDS.3
@@ -36,7 +36,7 @@ to overwrite the original data after setting this option.
Because data are copied, care must be taken when using this option in
conjunction with \fICURLOPT_POSTFIELDSIZE(3)\fP or
\fICURLOPT_POSTFIELDSIZE_LARGE(3)\fP: If the size has not been set prior to
-\fICURLOPT_COPYPOSTFIELDS(3)\fP, the data is assumed to be a zero terminated
+\fICURLOPT_COPYPOSTFIELDS(3)\fP, the data is assumed to be a null-terminated
string; else the stored size informs the library about the byte count to
copy. In any case, the size must not be changed after
\fICURLOPT_COPYPOSTFIELDS(3)\fP, unless another \fICURLOPT_POSTFIELDS(3)\fP or
diff --git a/docs/libcurl/opts/GNURLOPT_CRLFILE.3 b/docs/libcurl/opts/GNURLOPT_CRLFILE.3
index 1abcead85..bffc55b8a 100644
--- a/docs/libcurl/opts/GNURLOPT_CRLFILE.3
+++ b/docs/libcurl/opts/GNURLOPT_CRLFILE.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -28,15 +28,18 @@ CURLOPT_CRLFILE \- specify a Certificate Revocation List file
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CRLFILE, char *file);
.SH DESCRIPTION
-Pass a char * to a zero terminated string naming a \fIfile\fP with the
+Pass a char * to a null-terminated string naming a \fIfile\fP with the
concatenation of CRL (in PEM format) to use in the certificate validation that
occurs during the SSL exchange.
When curl is built to use NSS or GnuTLS, there is no way to influence the use
-of CRL passed to help in the verification process. When libcurl is built with
-OpenSSL support, X509_V_FLAG_CRL_CHECK and X509_V_FLAG_CRL_CHECK_ALL are both
-set, requiring CRL check against all the elements of the certificate chain if
-a CRL file is passed.
+of CRL passed to help in the verification process.
+
+When libcurl is built with OpenSSL support, X509_V_FLAG_CRL_CHECK and
+X509_V_FLAG_CRL_CHECK_ALL are both set, requiring CRL check against all the
+elements of the certificate chain if a CRL file is passed. Also note that
+\fICURLOPT_CRLFILE(3)\fP will imply \fBCURLSSLOPT_NO_PARTIALCHAIN\fP (see
+\fICURLOPT_SSL_OPTIONS(3)\fP) since curl 7.71.0 due to an OpenSSL bug.
This option makes sense only when used in combination with the
\fICURLOPT_SSL_VERIFYPEER(3)\fP option.
diff --git a/docs/libcurl/opts/GNURLOPT_CUSTOMREQUEST.3 b/docs/libcurl/opts/GNURLOPT_CUSTOMREQUEST.3
index 84064876e..1bd5020c5 100644
--- a/docs/libcurl/opts/GNURLOPT_CUSTOMREQUEST.3
+++ b/docs/libcurl/opts/GNURLOPT_CUSTOMREQUEST.3
@@ -28,7 +28,7 @@ CURLOPT_CUSTOMREQUEST \- custom string for request
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_CUSTOMREQUEST, char *request);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter.
+Pass a pointer to a null-terminated string as parameter.
When you change the request method by setting \fICURLOPT_CUSTOMREQUEST(3)\fP
to something, you don't actually change how libcurl behaves or acts in regards
diff --git a/docs/libcurl/opts/GNURLOPT_DEBUGFUNCTION.3 b/docs/libcurl/opts/GNURLOPT_DEBUGFUNCTION.3
index 7479034e3..c470cdac1 100644
--- a/docs/libcurl/opts/GNURLOPT_DEBUGFUNCTION.3
+++ b/docs/libcurl/opts/GNURLOPT_DEBUGFUNCTION.3
@@ -54,7 +54,7 @@ shown above.
\fICURLOPT_VERBOSE(3)\fP is in effect. This callback receives debug
information, as specified in the \fItype\fP argument. This function must
return 0. The \fIdata\fP pointed to by the char * passed to this function WILL
-NOT be zero terminated, but will be exactly of the \fIsize\fP as told by the
+NOT be null-terminated, but will be exactly of the \fIsize\fP as told by the
\fIsize\fP argument.
The \fIuserptr\fP argument is the pointer set with \fICURLOPT_DEBUGDATA(3)\fP.
diff --git a/docs/libcurl/opts/GNURLOPT_DOH_URL.3 b/docs/libcurl/opts/GNURLOPT_DOH_URL.3
index 1a463044c..2af19959c 100644
--- a/docs/libcurl/opts/GNURLOPT_DOH_URL.3
+++ b/docs/libcurl/opts/GNURLOPT_DOH_URL.3
@@ -29,7 +29,7 @@ CURLOPT_DOH_URL \- provide the DNS-over-HTTPS URL
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DOH_URL, char *URL);
.SH DESCRIPTION
Pass in a pointer to a \fIURL\fP for the DOH server to use for name
-resolving. The parameter should be a char * to a zero terminated string which
+resolving. The parameter should be a char * to a null-terminated string which
must be URL-encoded in the following format: "https://host:port/path". It MUST
specify a HTTPS URL.
diff --git a/docs/libcurl/opts/GNURLOPT_EGDSOCKET.3 b/docs/libcurl/opts/GNURLOPT_EGDSOCKET.3
index a008aa954..466091c5c 100644
--- a/docs/libcurl/opts/GNURLOPT_EGDSOCKET.3
+++ b/docs/libcurl/opts/GNURLOPT_EGDSOCKET.3
@@ -28,7 +28,7 @@ CURLOPT_EGDSOCKET \- set EGD socket path
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_EGDSOCKET, char *path);
.SH DESCRIPTION
-Pass a char * to the zero terminated path name to the Entropy Gathering Daemon
+Pass a char * to the null-terminated path name to the Entropy Gathering Daemon
socket. It will be used to seed the random engine for SSL.
The application does not have to keep the string around after setting this
diff --git a/docs/libcurl/opts/GNURLOPT_FTPPORT.3 b/docs/libcurl/opts/GNURLOPT_FTPPORT.3
index 41911540f..e217fcde4 100644
--- a/docs/libcurl/opts/GNURLOPT_FTPPORT.3
+++ b/docs/libcurl/opts/GNURLOPT_FTPPORT.3
@@ -28,7 +28,7 @@ CURLOPT_FTPPORT \- make FTP transfer active
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTPPORT, char *spec);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. It specifies that the
+Pass a pointer to a null-terminated string as parameter. It specifies that the
FTP transfer will be made actively and the given string will be used to get
the IP address to use for the FTP PORT instruction.
diff --git a/docs/libcurl/opts/GNURLOPT_FTP_ACCOUNT.3 b/docs/libcurl/opts/GNURLOPT_FTP_ACCOUNT.3
index ae16ddc6e..d3b16a6ef 100644
--- a/docs/libcurl/opts/GNURLOPT_FTP_ACCOUNT.3
+++ b/docs/libcurl/opts/GNURLOPT_FTP_ACCOUNT.3
@@ -28,7 +28,7 @@ CURLOPT_FTP_ACCOUNT \- set account info for FTP
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_FTP_ACCOUNT, char *account);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string (or NULL to disable). When an FTP
+Pass a pointer to a null-terminated string (or NULL to disable). When an FTP
server asks for "account data" after user name and password has been provided,
this data is sent off using the ACCT command.
diff --git a/docs/libcurl/opts/GNURLOPT_HEADERFUNCTION.3 b/docs/libcurl/opts/GNURLOPT_HEADERFUNCTION.3
index 9eb7a9873..c62390b5d 100644
--- a/docs/libcurl/opts/GNURLOPT_HEADERFUNCTION.3
+++ b/docs/libcurl/opts/GNURLOPT_HEADERFUNCTION.3
@@ -41,7 +41,7 @@ data. The header callback will be called once for each header and only
complete header lines are passed on to the callback. Parsing headers is very
easy using this. \fIbuffer\fP points to the delivered data, and the size of
that data is \fInitems\fP; \fIsize\fP is always 1. Do not assume that the
-header line is zero terminated!
+header line is null-terminated!
The pointer named \fIuserdata\fP is the one you set with the
\fICURLOPT_HEADERDATA(3)\fP option.
diff --git a/docs/libcurl/opts/GNURLOPT_ISSUERCERT.3 b/docs/libcurl/opts/GNURLOPT_ISSUERCERT.3
index 55ff3bbf8..30f0c756a 100644
--- a/docs/libcurl/opts/GNURLOPT_ISSUERCERT.3
+++ b/docs/libcurl/opts/GNURLOPT_ISSUERCERT.3
@@ -28,7 +28,7 @@ CURLOPT_ISSUERCERT \- issuer SSL certificate filename
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_ISSUERCERT, char *file);
.SH DESCRIPTION
-Pass a char * to a zero terminated string naming a \fIfile\fP holding a CA
+Pass a char * to a null-terminated string naming a \fIfile\fP holding a CA
certificate in PEM format. If the option is set, an additional check against
the peer certificate is performed to verify the issuer is indeed the one
associated with the certificate provided by the option. This additional check
diff --git a/docs/libcurl/opts/GNURLOPT_KEYPASSWD.3 b/docs/libcurl/opts/GNURLOPT_KEYPASSWD.3
index 704dc2bec..9145b0554 100644
--- a/docs/libcurl/opts/GNURLOPT_KEYPASSWD.3
+++ b/docs/libcurl/opts/GNURLOPT_KEYPASSWD.3
@@ -28,7 +28,7 @@ CURLOPT_KEYPASSWD \- set passphrase to private key
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_KEYPASSWD, char *pwd);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. It will be used as
+Pass a pointer to a null-terminated string as parameter. It will be used as
the password required to use the \fICURLOPT_SSLKEY(3)\fP or
\fICURLOPT_SSH_PRIVATE_KEYFILE(3)\fP private key. You never needed a pass
phrase to load a certificate but you need one to load your private key.
diff --git a/docs/libcurl/opts/GNURLOPT_LOGIN_OPTIONS.3 b/docs/libcurl/opts/GNURLOPT_LOGIN_OPTIONS.3
index d28ec512d..5a41a00c1 100644
--- a/docs/libcurl/opts/GNURLOPT_LOGIN_OPTIONS.3
+++ b/docs/libcurl/opts/GNURLOPT_LOGIN_OPTIONS.3
@@ -28,7 +28,7 @@ CURLOPT_LOGIN_OPTIONS \- set login options
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_LOGIN_OPTIONS, char *options);
.SH DESCRIPTION
-Pass a char * as parameter, which should be pointing to the zero terminated
+Pass a char * as parameter, which should be pointing to the null-terminated
\fIoptions\fP string to use for the transfer.
For more information about the login options please see RFC2384, RFC5092 and
diff --git a/docs/libcurl/opts/GNURLOPT_MAIL_AUTH.3 b/docs/libcurl/opts/GNURLOPT_MAIL_AUTH.3
index 46bbc86b4..cebafbcec 100644
--- a/docs/libcurl/opts/GNURLOPT_MAIL_AUTH.3
+++ b/docs/libcurl/opts/GNURLOPT_MAIL_AUTH.3
@@ -28,7 +28,7 @@ CURLOPT_MAIL_AUTH \- SMTP authentication address
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_AUTH, char *auth);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. This will be used to
+Pass a pointer to a null-terminated string as parameter. This will be used to
specify the authentication address (identity) of a submitted message that is
being relayed to another server.
diff --git a/docs/libcurl/opts/GNURLOPT_MAIL_FROM.3 b/docs/libcurl/opts/GNURLOPT_MAIL_FROM.3
index 1161feea1..c2d0d2851 100644
--- a/docs/libcurl/opts/GNURLOPT_MAIL_FROM.3
+++ b/docs/libcurl/opts/GNURLOPT_MAIL_FROM.3
@@ -28,7 +28,7 @@ CURLOPT_MAIL_FROM \- SMTP sender address
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MAIL_FROM, char *from);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. This should be used
+Pass a pointer to a null-terminated string as parameter. This should be used
to specify the sender's email address when sending SMTP mail with libcurl.
An originator email address should be specified with angled brackets (<>)
diff --git a/docs/libcurl/opts/GNURLOPT_NETRC_FILE.3 b/docs/libcurl/opts/GNURLOPT_NETRC_FILE.3
index 8d08c8fe9..d2a89da87 100644
--- a/docs/libcurl/opts/GNURLOPT_NETRC_FILE.3
+++ b/docs/libcurl/opts/GNURLOPT_NETRC_FILE.3
@@ -28,7 +28,7 @@ CURLOPT_NETRC_FILE \- file name to read .netrc info from
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NETRC_FILE, char *file);
.SH DESCRIPTION
-Pass a char * as parameter, pointing to a zero terminated string containing
+Pass a char * as parameter, pointing to a null-terminated string containing
the full path name to the \fIfile\fP you want libcurl to use as .netrc
file. If this option is omitted, and \fICURLOPT_NETRC(3)\fP is set, libcurl
will attempt to find a .netrc file in the current user's home
diff --git a/docs/libcurl/opts/GNURLOPT_NOPROXY.3 b/docs/libcurl/opts/GNURLOPT_NOPROXY.3
index b4be88fb5..bf46a839b 100644
--- a/docs/libcurl/opts/GNURLOPT_NOPROXY.3
+++ b/docs/libcurl/opts/GNURLOPT_NOPROXY.3
@@ -28,7 +28,7 @@ CURLOPT_NOPROXY \- disable proxy use for specific hosts
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_NOPROXY, char *noproxy);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string. The string consists of a comma
+Pass a pointer to a null-terminated string. The string consists of a comma
separated list of host names that do not require a proxy to get reached, even
if one is specified. The only wildcard available is a single * character,
which matches all hosts, and effectively disables the proxy. Each name in this
diff --git a/docs/libcurl/opts/GNURLOPT_OPENSOCKETFUNCTION.3 b/docs/libcurl/opts/GNURLOPT_OPENSOCKETFUNCTION.3
index 1197f8170..32e75b79b 100644
--- a/docs/libcurl/opts/GNURLOPT_OPENSOCKETFUNCTION.3
+++ b/docs/libcurl/opts/GNURLOPT_OPENSOCKETFUNCTION.3
@@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
-.\" * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@@ -65,7 +65,7 @@ additional \fIsetsockopt(2)\fP calls can of course be done on the socket at
the user's discretion. A \fICURL_SOCKET_BAD\fP return value from the callback
function will signal an unrecoverable error to libcurl and it will return
\fICURLE_COULDNT_CONNECT\fP from the function that triggered this callback.
-This return code can be used for IP address blacklisting.
+This return code can be used for IP address block listing.
If you want to pass in a socket with an already established connection, pass
the socket back with this callback and then use
diff --git a/docs/libcurl/opts/GNURLOPT_PASSWORD.3 b/docs/libcurl/opts/GNURLOPT_PASSWORD.3
index 01b7cf7c6..928903f0a 100644
--- a/docs/libcurl/opts/GNURLOPT_PASSWORD.3
+++ b/docs/libcurl/opts/GNURLOPT_PASSWORD.3
@@ -28,7 +28,7 @@ CURLOPT_PASSWORD \- password to use in authentication
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PASSWORD, char *pwd);
.SH DESCRIPTION
-Pass a char * as parameter, which should be pointing to the zero terminated
+Pass a char * as parameter, which should be pointing to the null-terminated
password to use for the transfer.
The \fICURLOPT_PASSWORD(3)\fP option should be used in conjunction with the
diff --git a/docs/libcurl/opts/GNURLOPT_PINNEDPUBLICKEY.3 b/docs/libcurl/opts/GNURLOPT_PINNEDPUBLICKEY.3
index e056f4b13..da2d3b581 100644
--- a/docs/libcurl/opts/GNURLOPT_PINNEDPUBLICKEY.3
+++ b/docs/libcurl/opts/GNURLOPT_PINNEDPUBLICKEY.3
@@ -28,7 +28,7 @@ CURLOPT_PINNEDPUBLICKEY \- set pinned public key
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PINNEDPUBLICKEY, char *pinnedpubkey);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. The string can be the
+Pass a pointer to a null-terminated string as parameter. The string can be the
file name of your pinned public key. The file format expected is "PEM" or "DER".
The string can also be any number of base64 encoded sha256 hashes preceded by
"sha256//" and separated by ";"
diff --git a/docs/libcurl/opts/GNURLOPT_PRE_PROXY.3 b/docs/libcurl/opts/GNURLOPT_PRE_PROXY.3
index f1640e444..28a3b2be7 100644
--- a/docs/libcurl/opts/GNURLOPT_PRE_PROXY.3
+++ b/docs/libcurl/opts/GNURLOPT_PRE_PROXY.3
@@ -29,7 +29,7 @@ CURLOPT_PRE_PROXY \- set pre-proxy to use
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PRE_PROXY, char *preproxy);
.SH DESCRIPTION
Set the \fIpreproxy\fP to use for the upcoming request. The parameter
-should be a char * to a zero terminated string holding the host name or dotted
+should be a char * to a null-terminated string holding the host name or dotted
numerical IP address. A numerical IPv6 address must be written within
[brackets].
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY.3 b/docs/libcurl/opts/GNURLOPT_PROXY.3
index 6d1175c17..677b038d0 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY.3
@@ -29,7 +29,7 @@ CURLOPT_PROXY \- set proxy to use
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY, char *proxy);
.SH DESCRIPTION
Set the \fIproxy\fP to use for the upcoming request. The parameter should be a
-char * to a zero terminated string holding the host name or dotted numerical
+char * to a null-terminated string holding the host name or dotted numerical
IP address. A numerical IPv6 address must be written within [brackets].
To specify port number in this string, append :[port] to the end of the host
diff --git a/docs/libcurl/opts/GNURLOPT_PROXYPASSWORD.3 b/docs/libcurl/opts/GNURLOPT_PROXYPASSWORD.3
index 0856081e8..04dfbbc96 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXYPASSWORD.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXYPASSWORD.3
@@ -28,7 +28,7 @@ CURLOPT_PROXYPASSWORD \- password to use with proxy authentication
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYPASSWORD, char *pwd);
.SH DESCRIPTION
-Pass a char * as parameter, which should be pointing to the zero terminated
+Pass a char * as parameter, which should be pointing to the null-terminated
password to use for authentication with the proxy.
The \fICURLOPT_PROXYPASSWORD(3)\fP option should be used in conjunction with
diff --git a/docs/libcurl/opts/GNURLOPT_PROXYUSERNAME.3 b/docs/libcurl/opts/GNURLOPT_PROXYUSERNAME.3
index d6cf85a99..4d85aaa63 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXYUSERNAME.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXYUSERNAME.3
@@ -30,7 +30,7 @@ CURLOPT_PROXYUSERNAME \- user name to use for proxy authentication
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXYUSERNAME,
char *username);
.SH DESCRIPTION
-Pass a char * as parameter, which should be pointing to the zero terminated
+Pass a char * as parameter, which should be pointing to the null-terminated
user name to use for the transfer.
\fICURLOPT_PROXYUSERNAME(3)\fP sets the user name to be used in protocol
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.3 b/docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.3
index bcff39f75..1fb4ca30d 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_CAINFO.3
@@ -30,7 +30,7 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAINFO, char *path);
.SH DESCRIPTION
This option is for connecting to an HTTPS proxy, not an HTTPS server.
-Pass a char * to a zero terminated string naming a file holding one or more
+Pass a char * to a null-terminated string naming a file holding one or more
certificates to verify the HTTPS proxy with.
If \fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP is zero and you avoid verifying the
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.3 b/docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.3
index 693609f02..aed464146 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_CAPATH.3
@@ -28,7 +28,7 @@ CURLOPT_PROXY_CAPATH \- specify directory holding proxy CA certificates
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CAPATH, char *capath);
.SH DESCRIPTION
-Pass a char * to a zero terminated string naming a directory holding multiple
+Pass a char * to a null-terminated string naming a directory holding multiple
CA certificates to verify the HTTPS proxy with. If libcurl is built against
OpenSSL, the certificate directory must be prepared using the openssl c_rehash
utility. This makes sense only when \fICURLOPT_PROXY_SSL_VERIFYPEER(3)\fP is
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.3 b/docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.3
index 68451777b..499435c58 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_CRLFILE.3
@@ -30,7 +30,7 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_CRLFILE, char *file);
.SH DESCRIPTION
This option is for connecting to an HTTPS proxy, not an HTTPS server.
-Pass a char * to a zero terminated string naming a \fIfile\fP with the
+Pass a char * to a null-terminated string naming a \fIfile\fP with the
concatenation of CRL (in PEM format) to use in the certificate validation that
occurs during the SSL exchange.
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.3 b/docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.3
index b5134f5b4..3da1669da 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_KEYPASSWD.3
@@ -30,7 +30,7 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_KEYPASSWD, char *pwd);
.SH DESCRIPTION
This option is for connecting to an HTTPS proxy, not an HTTPS server.
-Pass a pointer to a zero terminated string as parameter. It will be used as
+Pass a pointer to a null-terminated string as parameter. It will be used as
the password required to use the \fICURLOPT_PROXY_SSLKEY(3)\fP private key.
You never needed a pass phrase to load a certificate but you need one to load
your private key.
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.3 b/docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.3
index c362e24f0..f0b344630 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_PINNEDPUBLICKEY.3
@@ -28,7 +28,7 @@ CURLOPT_PROXY_PINNEDPUBLICKEY \- set pinned public key for https proxy
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_PINNEDPUBLICKEY, char *pinnedpubkey);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. The string can be the
+Pass a pointer to a null-terminated string as parameter. The string can be the
file name of your pinned public key. The file format expected is "PEM" or "DER".
The string can also be any number of base64 encoded sha256 hashes preceded by
"sha256//" and separated by ";"
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.3
index 38f558349..677225eef 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERT.3
@@ -30,7 +30,7 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERT, char *cert);
.SH DESCRIPTION
This option is for connecting to an HTTPS proxy, not an HTTPS server.
-Pass a pointer to a zero terminated string as parameter. The string should be
+Pass a pointer to a null-terminated string as parameter. The string should be
the file name of your client certificate used to connect to the HTTPS proxy.
The default format is "P12" on Secure Transport and "PEM" on other engines,
and can be changed with \fICURLOPT_PROXY_SSLCERTTYPE(3)\fP.
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.3
index 6c6cb5e38..b0ecc2b15 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLCERTTYPE.3
@@ -28,7 +28,7 @@ CURLOPT_PROXY_SSLCERTTYPE \- specify type of the proxy client SSL certificate
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLCERTTYPE, char *type);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. The string should be
+Pass a pointer to a null-terminated string as parameter. The string should be
the format of your client certificate used when connecting to an HTTPS proxy.
Supported formats are "PEM" and "DER", except with Secure Transport. OpenSSL
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.3
index 7610d804c..e8bcaab66 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEY.3
@@ -28,7 +28,7 @@ CURLOPT_PROXY_SSLKEY \- specify private keyfile for TLS and SSL proxy client cer
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEY, char *keyfile);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. The string should be
+Pass a pointer to a null-terminated string as parameter. The string should be
the file name of your private key used for connecting to the HTTPS proxy. The
default format is "PEM" and can be changed with
\fICURLOPT_PROXY_SSLKEYTYPE(3)\fP.
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.3
index 7826e1d44..344db1223 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSLKEYTYPE.3
@@ -30,7 +30,7 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSLKEYTYPE, char *type);
.SH DESCRIPTION
This option is for connecting to an HTTPS proxy, not an HTTPS server.
-Pass a pointer to a zero terminated string as parameter. The string should be
+Pass a pointer to a null-terminated string as parameter. The string should be
the format of your private key. Supported formats are "PEM", "DER" and "ENG".
The application does not have to keep the string around after setting this
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.3
index 59440c8c4..bf40f318a 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_CIPHER_LIST.3
@@ -28,7 +28,7 @@ CURLOPT_PROXY_SSL_CIPHER_LIST \- specify ciphers to use for proxy TLS
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_SSL_CIPHER_LIST, char *list);
.SH DESCRIPTION
-Pass a char *, pointing to a zero terminated string holding the list of
+Pass a char *, pointing to a null-terminated string holding the list of
ciphers to use for the connection to the HTTPS proxy. The list must be
syntactically correct, it consists of one or more cipher strings separated by
colons. Commas or spaces are also acceptable separators but colons are
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3 b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3
index 46e926c97..67161c986 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_SSL_OPTIONS.3
@@ -42,7 +42,7 @@ supported for DarwinSSL, NSS and OpenSSL.
Tells libcurl to disable certificate revocation checks for those SSL backends
where such behavior is present. This option is only supported for Schannel
(the native Windows SSL library), with an exception in the case of Windows'
-Untrusted Publishers blacklist which it seems can't be bypassed. (Added in
+Untrusted Publishers block list which it seems can't be bypassed. (Added in
7.44.0)
.IP CURLSSLOPT_NO_PARTIALCHAIN
Tells libcurl to not accept "partial" certificate chains, which it otherwise
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_TLS13_CIPHERS.3 b/docs/libcurl/opts/GNURLOPT_PROXY_TLS13_CIPHERS.3
index 38b363ab7..eb6ee937d 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_TLS13_CIPHERS.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_TLS13_CIPHERS.3
@@ -28,7 +28,7 @@ CURLOPT_PROXY_TLS13_CIPHERS \- ciphers suites for proxy TLS 1.3
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLS13_CIPHERS, char *list);
.SH DESCRIPTION
-Pass a char *, pointing to a zero terminated string holding the list of cipher
+Pass a char *, pointing to a null-terminated string holding the list of cipher
suites to use for the TLS 1.3 connection to a proxy. The list must be
syntactically correct, it consists of one or more cipher suite strings
separated by colons.
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.3 b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.3
index 839a051a6..464916e81 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_PASSWORD.3
@@ -28,7 +28,7 @@ CURLOPT_PROXY_TLSAUTH_PASSWORD \- password to use for proxy TLS authentication
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_PASSWORD, char *pwd);
.SH DESCRIPTION
-Pass a char * as parameter, which should point to the zero terminated password
+Pass a char * as parameter, which should point to the null-terminated password
to use for the TLS authentication method specified with the
\fICURLOPT_PROXY_TLSAUTH_TYPE(3)\fP option. Requires that the
\fICURLOPT_PROXY_TLSAUTH_USERNAME(3)\fP option also be set.
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.3 b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.3
index 303fcd2d9..dc4bfa90f 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_TYPE.3
@@ -28,7 +28,7 @@ CURLOPT_PROXY_TLSAUTH_TYPE \- set proxy TLS authentication methods
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_TYPE, char *type);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. The string should be
+Pass a pointer to a null-terminated string as parameter. The string should be
the method of the TLS authentication used for the HTTPS connection. Supported
method is "SRP".
diff --git a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.3 b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.3
index 531b2f0c5..742f206c4 100644
--- a/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.3
+++ b/docs/libcurl/opts/GNURLOPT_PROXY_TLSAUTH_USERNAME.3
@@ -28,7 +28,7 @@ CURLOPT_PROXY_TLSAUTH_USERNAME \- user name to use for proxy TLS authentication
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PROXY_TLSAUTH_USERNAME, char *user);
.SH DESCRIPTION
-Pass a char * as parameter, which should point to the zero terminated username
+Pass a char * as parameter, which should point to the null-terminated username
to use for the HTTPS proxy TLS authentication method specified with the
\fICURLOPT_PROXY_TLSAUTH_TYPE(3)\fP option. Requires that the
\fICURLOPT_PROXY_TLSAUTH_PASSWORD(3)\fP option also be set.
diff --git a/docs/libcurl/opts/GNURLOPT_RANDOM_FILE.3 b/docs/libcurl/opts/GNURLOPT_RANDOM_FILE.3
index b73aa8902..f5939d21d 100644
--- a/docs/libcurl/opts/GNURLOPT_RANDOM_FILE.3
+++ b/docs/libcurl/opts/GNURLOPT_RANDOM_FILE.3
@@ -28,7 +28,7 @@ CURLOPT_RANDOM_FILE \- specify a source for random data
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_RANDOM_FILE, char *path);
.SH DESCRIPTION
-Pass a char * to a zero terminated file name. The file might be used to read
+Pass a char * to a null-terminated file name. The file might be used to read
from to seed the random engine for SSL and more.
The application does not have to keep the string around after setting this
diff --git a/docs/libcurl/opts/GNURLOPT_READFUNCTION.3 b/docs/libcurl/opts/GNURLOPT_READFUNCTION.3
index ff07c5212..e0e3b255f 100644
--- a/docs/libcurl/opts/GNURLOPT_READFUNCTION.3
+++ b/docs/libcurl/opts/GNURLOPT_READFUNCTION.3
@@ -20,56 +20,84 @@
.\" *
.\" **************************************************************************
.\"
-.TH GNURLOPT_READFUNCTION 3 "16 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options"
-.SH NAME
-CURLOPT_READFUNCTION \- read callback for data uploads
-.SH SYNOPSIS
-#include <gnurl/curl.h>
-
-size_t read_callback(char *buffer, size_t size, size_t nitems, void *userdata);
-
-CURLcode curl_easy_setopt(CURL *handle, CURLOPT_READFUNCTION, read_callback);
-
-.SH DESCRIPTION
+.Dd June 25, 2020
+.Dt GNURLOPT_READFUNCTION 3
+.Os
+.Sh NAME
+.Nm CURLOPT_READFUNCTION
+.Nd read callback for data uploads
+.Sh SYNOPSIS
+.In gnurl/curl.h
+.Ft size_t
+.Fn read_callback "char *buffer" "size_t size" "size_t nitems" "void *userdata"
+.Ft CURLcode
+.Fn curl_easy_setopt "CURL *handle" "CURLOPT_READFUNCTION" "read_callback"
+.Sh DESCRIPTION
Pass a pointer to your callback function, as the prototype shows above.
-This 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 \fInitems\fP number of bytes
-by your function.
-
-Set the \fIuserdata\fP argument with the \fICURLOPT_READDATA(3)\fP option.
-
-Your function must return the actual number of bytes that it stored in the data
-area pointed at by the pointer \fIbuffer\fP. 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.
-
-\fBBugs\fP: when doing TFTP uploads, you must return the exact amount of data
-that the callback wants, or it will be considered the final packet by the
+This 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
+.Fa buffer
+should be filled up with at most
+.Fa size
+multiplied with
+.Fa nitems
+number of bytes by your function.
+
+Set the
+.Fa userdata
+argument with the
+.Xr CURLOPT_READDATA 3
+option.
+
+Your function must return the actual number of bytes that it stored in
+the data area pointed at by the pointer
+.Fa buffer .
+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
+.Dv CURL_READFUNC_ABORT
+to stop the current operation immediately, resulting in a
+.Dv CURLE_ABORTED_BY_CALLBACK
+error code from the transfer.
+
+The callback can return
+.Dv CURL_READFUNC_PAUSE
+to cause reading from this connection to pause.
+See
+.Xr curl_easy_pause 3
+for further details.
+
+.Sh BUGS
+when doing TFTP uploads, you must return the exact amount of data that
+the callback wants, or it will be considered the final packet by the
server end and the transfer will end there.
-If you set this callback pointer to NULL, or don't set it at all, the default
-internal read function will be used. It is doing an fread() on the FILE *
-userdata set with \fICURLOPT_READDATA(3)\fP.
-.SH DEFAULT
+If you set this callback pointer to NULL, or don't set it at all, the
+default internal read function will be used. It is doing an fread() on
+the FILE * userdata set with
+.Xr CURLOPT_READDATA 3 .
+
+You can set the total size of the data you are sending by using
+.Xr CURLOPT_INFILESIZE_LARGE 3
+or
+.Xr CURLOPT_POSTFIELDSIZE_LARGE 3 ,
+depending on the type of transfer. For some transfer types it may be
+required and it allows for better error checking.
+.Sh DEFAULT
The default internal read callback is fread().
-.SH PROTOCOLS
+.Sh PROTOCOLS
This is used for all protocols when doing uploads.
-.SH EXAMPLE
-.nf
+.Sh EXAMPLE
+.Bd -literal
size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userdata)
{
FILE *readhere = (FILE *)userdata;
@@ -99,13 +127,16 @@ void setup(char *uploadthis)
result = curl_easy_perform(curl);
}
-.fi
-.SH AVAILABILITY
+.Ed
+.Sh AVAILABILITY
CURL_READFUNC_PAUSE return code was added in 7.18.0 and CURL_READFUNC_ABORT
was added in 7.12.1.
-.SH RETURN VALUE
+.Sh RETURN VALUE
This will return CURLE_OK.
-.SH "SEE ALSO"
-.BR CURLOPT_READDATA "(3), " CURLOPT_WRITEFUNCTION "(3), "
-.BR CURLOPT_SEEKFUNCTION "(3), " CURLOPT_UPLOAD "(3), " CURLOPT_POST "(3), "
-.BR CURLOPT_UPLOAD_BUFFERSIZE "(3), "
+.Sh SEE ALSO
+.Xr CURLOPT_READDATA 3 ,
+.Xr CURLOPT_WRITEFUNCTION 3 ,
+.Xr CURLOPT_SEEKFUNCTION 3 ,
+.Xr CURLOPT_UPLOAD 3 ,
+.Xr CURLOPT_POST 3 ,
+.Xr CURLOPT_UPLOAD_BUFFERSIZE 3 .
diff --git a/docs/libcurl/opts/GNURLOPT_REFERER.3 b/docs/libcurl/opts/GNURLOPT_REFERER.3
index 26ce192aa..059a9d3e4 100644
--- a/docs/libcurl/opts/GNURLOPT_REFERER.3
+++ b/docs/libcurl/opts/GNURLOPT_REFERER.3
@@ -28,7 +28,7 @@ CURLOPT_REFERER \- set the HTTP referer header
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_REFERER, char *where);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. It will be used to
+Pass a pointer to a null-terminated string as parameter. It will be used to
set the Referer: header in the http request sent to the remote server. This
can be used to fool servers or scripts. You can also set any custom header
with \fICURLOPT_HTTPHEADER(3)\fP.
diff --git a/docs/libcurl/opts/GNURLOPT_SASL_AUTHZID.3 b/docs/libcurl/opts/GNURLOPT_SASL_AUTHZID.3
index 50e0d3371..86aa7901f 100644
--- a/docs/libcurl/opts/GNURLOPT_SASL_AUTHZID.3
+++ b/docs/libcurl/opts/GNURLOPT_SASL_AUTHZID.3
@@ -28,7 +28,7 @@ CURLOPT_SASL_AUTHZID \- authorisation identity (identity to act as)
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SASL_AUTHZID, char *authzid);
.SH DESCRIPTION
-Pass a char * as parameter, which should be pointing to the zero terminated
+Pass a char * as parameter, which should be pointing to the null-terminated
authorisation identity (authzid) for the transfer. Only applicable to the PLAIN
SASL authentication mechanism where it is optional.
diff --git a/docs/libcurl/opts/GNURLOPT_SSH_KEYFUNCTION.3 b/docs/libcurl/opts/GNURLOPT_SSH_KEYFUNCTION.3
index 6cc1e58c5..76119c34a 100644
--- a/docs/libcurl/opts/GNURLOPT_SSH_KEYFUNCTION.3
+++ b/docs/libcurl/opts/GNURLOPT_SSH_KEYFUNCTION.3
@@ -44,7 +44,7 @@ enum curl_khmatch {
};
struct curl_khkey {
- const char *key; /* points to a zero-terminated string encoded with
+ const char *key; /* points to a null-terminated string encoded with
base64 if len is zero, otherwise to the "raw"
data */
size_t len;
diff --git a/docs/libcurl/opts/GNURLOPT_SSH_KNOWNHOSTS.3 b/docs/libcurl/opts/GNURLOPT_SSH_KNOWNHOSTS.3
index d9c273057..86be0617c 100644
--- a/docs/libcurl/opts/GNURLOPT_SSH_KNOWNHOSTS.3
+++ b/docs/libcurl/opts/GNURLOPT_SSH_KNOWNHOSTS.3
@@ -28,7 +28,7 @@ CURLOPT_SSH_KNOWNHOSTS \- file name holding the SSH known hosts
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSH_KNOWNHOSTS, char *fname);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string holding the file name of the
+Pass a pointer to a null-terminated string holding the file name of the
known_host file to use. The known_hosts file should use the OpenSSH file
format as supported by libssh2. If this file is specified, libcurl will only
accept connections with hosts that are known and present in that file, with a
diff --git a/docs/libcurl/opts/GNURLOPT_SSLCERT.3 b/docs/libcurl/opts/GNURLOPT_SSLCERT.3
index 2580307db..ce462280c 100644
--- a/docs/libcurl/opts/GNURLOPT_SSLCERT.3
+++ b/docs/libcurl/opts/GNURLOPT_SSLCERT.3
@@ -28,7 +28,7 @@ CURLOPT_SSLCERT \- set SSL client certificate
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERT, char *cert);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. The string should be
+Pass a pointer to a null-terminated string as parameter. The string should be
the file name of your client certificate. The default format is "P12" on
Secure Transport and "PEM" on other engines, and can be changed with
\fICURLOPT_SSLCERTTYPE(3)\fP.
@@ -38,15 +38,17 @@ you wish to authenticate with as it is named in the security database. If you
want to use a file from the current directory, please precede it with "./"
prefix, in order to avoid confusion with a nickname.
-(Schannel only) Client certificates must be specified by a path expression to
-a certificate store. (Loading PFX is not supported; you can import it to a
-store first). You can use "<store location>\\<store name>\\<thumbprint>" to
-refer to a certificate in the system certificates store, for example,
+(Schannel only) Client certificates can be specified by a path expression to
+a certificate store. (You can import PFX to a store first). You can use
+"<store location>\\<store name>\\<thumbprint>" to refer to a certificate
+in the system certificates store, for example,
"CurrentUser\\MY\\934a7ac6f8a5d579285a74fa61e19f23ddfe8d7a". Thumbprint is
usually a SHA-1 hex string which you can see in certificate details. Following
store locations are supported: CurrentUser, LocalMachine, CurrentService,
Services, CurrentUserGroupPolicy, LocalMachineGroupPolicy,
LocalMachineEnterprise.
+Schannel also support P12 certificate file, with the string "P12" specified
+with \fICURLOPT_SSLCERTTYPE(3)\fP.
When using a client certificate, you most likely also need to provide a
private key with \fICURLOPT_SSLKEY(3)\fP.
diff --git a/docs/libcurl/opts/GNURLOPT_SSLCERTTYPE.3 b/docs/libcurl/opts/GNURLOPT_SSLCERTTYPE.3
index 517671eb6..3947324fa 100644
--- a/docs/libcurl/opts/GNURLOPT_SSLCERTTYPE.3
+++ b/docs/libcurl/opts/GNURLOPT_SSLCERTTYPE.3
@@ -28,7 +28,7 @@ CURLOPT_SSLCERTTYPE \- specify type of the client SSL certificate
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLCERTTYPE, char *type);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. The string should be
+Pass a pointer to a null-terminated string as parameter. The string should be
the format of your certificate. Supported formats are "PEM" and "DER", except
with Secure Transport. OpenSSL (versions 0.9.3 and later) and Secure Transport
(on iOS 5 or later, or OS X 10.7 or later) also support "P12" for
diff --git a/docs/libcurl/opts/GNURLOPT_SSLENGINE.3 b/docs/libcurl/opts/GNURLOPT_SSLENGINE.3
index d88b42a76..ba3e3007c 100644
--- a/docs/libcurl/opts/GNURLOPT_SSLENGINE.3
+++ b/docs/libcurl/opts/GNURLOPT_SSLENGINE.3
@@ -28,7 +28,7 @@ CURLOPT_SSLENGINE \- set SSL engine identifier
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLENGINE, char *id);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. It will be used as
+Pass a pointer to a null-terminated string as parameter. It will be used as
the identifier for the crypto engine you want to use for your private key.
The application does not have to keep the string around after setting this
diff --git a/docs/libcurl/opts/GNURLOPT_SSLKEY.3 b/docs/libcurl/opts/GNURLOPT_SSLKEY.3
index 54ed5b572..cc54f6b83 100644
--- a/docs/libcurl/opts/GNURLOPT_SSLKEY.3
+++ b/docs/libcurl/opts/GNURLOPT_SSLKEY.3
@@ -28,7 +28,7 @@ CURLOPT_SSLKEY \- specify private keyfile for TLS and SSL client cert
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLKEY, char *keyfile);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. The string should be
+Pass a pointer to a null-terminated string as parameter. The string should be
the file name of your private key. The default format is "PEM" and can be
changed with \fICURLOPT_SSLKEYTYPE(3)\fP.
diff --git a/docs/libcurl/opts/GNURLOPT_SSLKEYTYPE.3 b/docs/libcurl/opts/GNURLOPT_SSLKEYTYPE.3
index 827ebda45..1ec2db1a1 100644
--- a/docs/libcurl/opts/GNURLOPT_SSLKEYTYPE.3
+++ b/docs/libcurl/opts/GNURLOPT_SSLKEYTYPE.3
@@ -28,7 +28,7 @@ CURLOPT_SSLKEYTYPE \- set type of the private key file
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSLKEYTYPE, char *type);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. The string should be
+Pass a pointer to a null-terminated string as parameter. The string should be
the format of your private key. Supported formats are "PEM", "DER" and "ENG".
The format "ENG" enables you to load the private key from a crypto engine. In
diff --git a/docs/libcurl/opts/GNURLOPT_SSL_CIPHER_LIST.3 b/docs/libcurl/opts/GNURLOPT_SSL_CIPHER_LIST.3
index 05e42fa47..2fb8a52d6 100644
--- a/docs/libcurl/opts/GNURLOPT_SSL_CIPHER_LIST.3
+++ b/docs/libcurl/opts/GNURLOPT_SSL_CIPHER_LIST.3
@@ -28,7 +28,7 @@ CURLOPT_SSL_CIPHER_LIST \- specify ciphers to use for TLS
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_SSL_CIPHER_LIST, char *list);
.SH DESCRIPTION
-Pass a char *, pointing to a zero terminated string holding the list of
+Pass a char *, pointing to a null-terminated string holding the list of
ciphers to use for the SSL connection. The list must be syntactically correct,
it consists of one or more cipher strings separated by colons. Commas or
spaces are also acceptable separators but colons are normally used, \&!, \&-
diff --git a/docs/libcurl/opts/GNURLOPT_SSL_OPTIONS.3 b/docs/libcurl/opts/GNURLOPT_SSL_OPTIONS.3
index 19bfbd910..d7fa241ed 100644
--- a/docs/libcurl/opts/GNURLOPT_SSL_OPTIONS.3
+++ b/docs/libcurl/opts/GNURLOPT_SSL_OPTIONS.3
@@ -42,7 +42,7 @@ supported for DarwinSSL, NSS and OpenSSL.
Tells libcurl to disable certificate revocation checks for those SSL backends
where such behavior is present. This option is only supported for Schannel
(the native Windows SSL library), with an exception in the case of Windows'
-Untrusted Publishers blacklist which it seems can't be bypassed. (Added in
+Untrusted Publishers block list which it seems can't be bypassed. (Added in
7.44.0)
.IP CURLSSLOPT_NO_PARTIALCHAIN
Tells libcurl to not accept "partial" certificate chains, which it otherwise
@@ -55,6 +55,11 @@ offline distribution points for those SSL backends where such behavior is
present. This option is only supported for Schannel (the native Windows SSL
library). If combined with \fICURLSSLOPT_NO_REVOKE\fP, the latter takes
precedence. (Added in 7.70.0)
+.IP CURLSSLOPT_NATIVE_CA
+Tell libcurl to use the operating system's native CA store for certificate
+verification. Works only on Windows when built to use OpenSSL. This option is
+experimental and behavior is subject to change.
+(Added in 7.71.0)
.SH DEFAULT
0
.SH PROTOCOLS
diff --git a/docs/libcurl/opts/GNURLOPT_TLS13_CIPHERS.3 b/docs/libcurl/opts/GNURLOPT_TLS13_CIPHERS.3
index 7913f2a06..878e10806 100644
--- a/docs/libcurl/opts/GNURLOPT_TLS13_CIPHERS.3
+++ b/docs/libcurl/opts/GNURLOPT_TLS13_CIPHERS.3
@@ -28,7 +28,7 @@ CURLOPT_TLS13_CIPHERS \- specify ciphers suites to use for TLS 1.3
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLS13_CIPHERS, char *list);
.SH DESCRIPTION
-Pass a char *, pointing to a zero terminated string holding the list of cipher
+Pass a char *, pointing to a null-terminated string holding the list of cipher
suites to use for the TLS 1.3 connection. The list must be syntactically
correct, it consists of one or more cipher suite strings separated by colons.
diff --git a/docs/libcurl/opts/GNURLOPT_TLSAUTH_PASSWORD.3 b/docs/libcurl/opts/GNURLOPT_TLSAUTH_PASSWORD.3
index 7fe983e2e..7e67d3ee3 100644
--- a/docs/libcurl/opts/GNURLOPT_TLSAUTH_PASSWORD.3
+++ b/docs/libcurl/opts/GNURLOPT_TLSAUTH_PASSWORD.3
@@ -28,7 +28,7 @@ CURLOPT_TLSAUTH_PASSWORD \- password to use for TLS authentication
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_PASSWORD, char *pwd);
.SH DESCRIPTION
-Pass a char * as parameter, which should point to the zero terminated password
+Pass a char * as parameter, which should point to the null-terminated password
to use for the TLS authentication method specified with the
\fICURLOPT_TLSAUTH_TYPE(3)\fP option. Requires that the
\fICURLOPT_TLSAUTH_USERNAME(3)\fP option also be set.
diff --git a/docs/libcurl/opts/GNURLOPT_TLSAUTH_TYPE.3 b/docs/libcurl/opts/GNURLOPT_TLSAUTH_TYPE.3
index f480f341e..408c7569e 100644
--- a/docs/libcurl/opts/GNURLOPT_TLSAUTH_TYPE.3
+++ b/docs/libcurl/opts/GNURLOPT_TLSAUTH_TYPE.3
@@ -28,7 +28,7 @@ CURLOPT_TLSAUTH_TYPE \- set TLS authentication methods
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_TYPE, char *type);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. The string should be
+Pass a pointer to a null-terminated string as parameter. The string should be
the method of the TLS authentication. Supported method is "SRP".
.IP SRP
diff --git a/docs/libcurl/opts/GNURLOPT_TLSAUTH_USERNAME.3 b/docs/libcurl/opts/GNURLOPT_TLSAUTH_USERNAME.3
index 807ba9abb..1cf8d446e 100644
--- a/docs/libcurl/opts/GNURLOPT_TLSAUTH_USERNAME.3
+++ b/docs/libcurl/opts/GNURLOPT_TLSAUTH_USERNAME.3
@@ -28,7 +28,7 @@ CURLOPT_TLSAUTH_USERNAME \- user name to use for TLS authentication
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TLSAUTH_USERNAME, char *user);
.SH DESCRIPTION
-Pass a char * as parameter, which should point to the zero terminated username
+Pass a char * as parameter, which should point to the null-terminated username
to use for the TLS authentication method specified with the
\fICURLOPT_TLSAUTH_TYPE(3)\fP option. Requires that the
\fICURLOPT_TLSAUTH_PASSWORD(3)\fP option also be set.
diff --git a/docs/libcurl/opts/GNURLOPT_URL.3 b/docs/libcurl/opts/GNURLOPT_URL.3
index 25c52c25f..580438d3a 100644
--- a/docs/libcurl/opts/GNURLOPT_URL.3
+++ b/docs/libcurl/opts/GNURLOPT_URL.3
@@ -29,7 +29,7 @@ CURLOPT_URL \- provide the URL to use in the request
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_URL, char *URL);
.SH DESCRIPTION
Pass in a pointer to the \fIURL\fP to work with. The parameter should be a
-char * to a zero terminated string which must be URL-encoded in the following
+char * to a null-terminated string which must be URL-encoded in the following
format:
scheme://host:port/path
diff --git a/docs/libcurl/opts/GNURLOPT_USERAGENT.3 b/docs/libcurl/opts/GNURLOPT_USERAGENT.3
index 8bb754cc2..5b28bb322 100644
--- a/docs/libcurl/opts/GNURLOPT_USERAGENT.3
+++ b/docs/libcurl/opts/GNURLOPT_USERAGENT.3
@@ -28,7 +28,7 @@ CURLOPT_USERAGENT \- set HTTP user-agent header
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERAGENT, char *ua);
.SH DESCRIPTION
-Pass a pointer to a zero terminated string as parameter. It will be used to
+Pass a pointer to a null-terminated string as parameter. It will be used to
set the User-Agent: header in the HTTP request sent to the remote server. This
can be used to fool servers or scripts. You can also set any custom header
with \fICURLOPT_HTTPHEADER(3)\fP.
diff --git a/docs/libcurl/opts/GNURLOPT_USERNAME.3 b/docs/libcurl/opts/GNURLOPT_USERNAME.3
index 78f84782d..b4f36423c 100644
--- a/docs/libcurl/opts/GNURLOPT_USERNAME.3
+++ b/docs/libcurl/opts/GNURLOPT_USERNAME.3
@@ -30,7 +30,7 @@ CURLOPT_USERNAME \- user name to use in authentication
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERNAME,
char *username);
.SH DESCRIPTION
-Pass a char * as parameter, which should be pointing to the zero terminated
+Pass a char * as parameter, which should be pointing to the null-terminated
user name to use for the transfer.
\fICURLOPT_USERNAME(3)\fP sets the user name to be used in protocol
diff --git a/docs/libcurl/opts/GNURLOPT_USERPWD.3 b/docs/libcurl/opts/GNURLOPT_USERPWD.3
index 7c9cf215c..0fd4d394f 100644
--- a/docs/libcurl/opts/GNURLOPT_USERPWD.3
+++ b/docs/libcurl/opts/GNURLOPT_USERPWD.3
@@ -28,7 +28,7 @@ CURLOPT_USERPWD \- user name and password to use in authentication
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_USERPWD, char *userpwd);
.SH DESCRIPTION
-Pass a char * as parameter, pointing to a zero terminated login details string
+Pass a char * as parameter, pointing to a null-terminated login details string
for the connection. The format of which is: [user name]:[password].
When using Kerberos V5 authentication with a Windows based server, you should
diff --git a/docs/libcurl/opts/GNURLOPT_WRITEFUNCTION.3 b/docs/libcurl/opts/GNURLOPT_WRITEFUNCTION.3
index e76d26a6b..ba10cde52 100644
--- a/docs/libcurl/opts/GNURLOPT_WRITEFUNCTION.3
+++ b/docs/libcurl/opts/GNURLOPT_WRITEFUNCTION.3
@@ -52,7 +52,7 @@ means 100K.
This function may be called with zero bytes data if the transferred file is
empty.
-The data passed to this function will not be zero terminated!
+The data passed to this function will not be null-terminated!
Set the \fIuserdata\fP argument with the \fICURLOPT_WRITEDATA(3)\fP option.
diff --git a/docs/libcurl/opts/GNURLOPT_XOAUTH2_BEARER.3 b/docs/libcurl/opts/GNURLOPT_XOAUTH2_BEARER.3
index 60e4c88ee..d77dfa167 100644
--- a/docs/libcurl/opts/GNURLOPT_XOAUTH2_BEARER.3
+++ b/docs/libcurl/opts/GNURLOPT_XOAUTH2_BEARER.3
@@ -28,7 +28,7 @@ CURLOPT_XOAUTH2_BEARER \- specify OAuth 2.0 access token
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_XOAUTH2_BEARER, char *token);
.SH DESCRIPTION
-Pass a char * as parameter, which should point to the zero terminated OAuth
+Pass a char * as parameter, which should point to the null-terminated OAuth
2.0 Bearer Access Token for use with HTTP, IMAP, POP3 and SMTP servers
that support the OAuth 2.0 Authorization Framework.
diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc
index 1355df8ff..c60b486d1 100644
--- a/docs/libcurl/opts/Makefile.inc
+++ b/docs/libcurl/opts/Makefile.inc
@@ -22,354 +22,361 @@
# Shared between Makefile.am and CMakeLists.txt
man_MANS = \
- GNURLINFO_ACTIVESOCKET.3 \
- GNURLINFO_APPCONNECT_TIME.3 \
- GNURLINFO_APPCONNECT_TIME_T.3 \
- GNURLINFO_CERTINFO.3 \
- GNURLINFO_CONDITION_UNMET.3 \
- GNURLINFO_CONNECT_TIME.3 \
- GNURLINFO_CONNECT_TIME_T.3 \
- GNURLINFO_CONTENT_LENGTH_DOWNLOAD.3 \
- GNURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3 \
- GNURLINFO_CONTENT_LENGTH_UPLOAD.3 \
- GNURLINFO_CONTENT_LENGTH_UPLOAD_T.3 \
- GNURLINFO_CONTENT_TYPE.3 \
- GNURLINFO_COOKIELIST.3 \
- GNURLINFO_EFFECTIVE_URL.3 \
- GNURLINFO_FILETIME.3 \
- GNURLINFO_FILETIME_T.3 \
- GNURLINFO_FTP_ENTRY_PATH.3 \
- GNURLINFO_HEADER_SIZE.3 \
- GNURLINFO_HTTPAUTH_AVAIL.3 \
- GNURLINFO_HTTP_CONNECTCODE.3 \
- GNURLINFO_HTTP_VERSION.3 \
- GNURLINFO_LASTSOCKET.3 \
- GNURLINFO_LOCAL_IP.3 \
- GNURLINFO_LOCAL_PORT.3 \
- GNURLINFO_NAMELOOKUP_TIME.3 \
- GNURLINFO_NAMELOOKUP_TIME_T.3 \
- GNURLINFO_NUM_CONNECTS.3 \
- GNURLINFO_OS_ERRNO.3 \
- GNURLINFO_PRETRANSFER_TIME.3 \
- GNURLINFO_PRETRANSFER_TIME_T.3 \
- GNURLINFO_PRIMARY_IP.3 \
- GNURLINFO_PRIMARY_PORT.3 \
- GNURLINFO_PRIVATE.3 \
- GNURLINFO_PROTOCOL.3 \
- GNURLINFO_PROXYAUTH_AVAIL.3 \
- GNURLINFO_PROXY_SSL_VERIFYRESULT.3 \
- GNURLINFO_REDIRECT_COUNT.3 \
- GNURLINFO_REDIRECT_TIME.3 \
- GNURLINFO_REDIRECT_TIME_T.3 \
- GNURLINFO_REDIRECT_URL.3 \
- GNURLINFO_REQUEST_SIZE.3 \
- GNURLINFO_RESPONSE_CODE.3 \
- GNURLINFO_RETRY_AFTER.3 \
- GNURLINFO_RTSP_CLIENT_CSEQ.3 \
- GNURLINFO_RTSP_CSEQ_RECV.3 \
- GNURLINFO_RTSP_SERVER_CSEQ.3 \
- GNURLINFO_RTSP_SESSION_ID.3 \
- GNURLINFO_SCHEME.3 \
- GNURLINFO_SIZE_DOWNLOAD.3 \
- GNURLINFO_SIZE_DOWNLOAD_T.3 \
- GNURLINFO_SIZE_UPLOAD.3 \
- GNURLINFO_SIZE_UPLOAD_T.3 \
- GNURLINFO_SPEED_DOWNLOAD.3 \
- GNURLINFO_SPEED_DOWNLOAD_T.3 \
- GNURLINFO_SPEED_UPLOAD.3 \
- GNURLINFO_SPEED_UPLOAD_T.3 \
- GNURLINFO_SSL_ENGINES.3 \
- GNURLINFO_SSL_VERIFYRESULT.3 \
- GNURLINFO_STARTTRANSFER_TIME.3 \
- GNURLINFO_STARTTRANSFER_TIME_T.3 \
- GNURLINFO_TLS_SESSION.3 \
- GNURLINFO_TLS_SSL_PTR.3 \
- GNURLINFO_TOTAL_TIME.3 \
- GNURLINFO_TOTAL_TIME_T.3 \
- GNURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3 \
- GNURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3 \
- GNURLMOPT_MAXCONNECTS.3 \
- GNURLMOPT_MAX_CONCURRENT_STREAMS.3 \
- GNURLMOPT_MAX_HOST_CONNECTIONS.3 \
- GNURLMOPT_MAX_PIPELINE_LENGTH.3 \
- GNURLMOPT_MAX_TOTAL_CONNECTIONS.3 \
- GNURLMOPT_PIPELINING.3 \
- GNURLMOPT_PIPELINING_SERVER_BL.3 \
- GNURLMOPT_PIPELINING_SITE_BL.3 \
- GNURLMOPT_PUSHDATA.3 \
- GNURLMOPT_PUSHFUNCTION.3 \
- GNURLMOPT_SOCKETDATA.3 \
- GNURLMOPT_SOCKETFUNCTION.3 \
- GNURLMOPT_TIMERDATA.3 \
- GNURLMOPT_TIMERFUNCTION.3 \
- GNURLOPT_ABSTRACT_UNIX_SOCKET.3 \
- GNURLOPT_ACCEPTTIMEOUT_MS.3 \
- GNURLOPT_ACCEPT_ENCODING.3 \
- GNURLOPT_ADDRESS_SCOPE.3 \
- GNURLOPT_ALTSVC.3 \
- GNURLOPT_ALTSVC_CTRL.3 \
- GNURLOPT_APPEND.3 \
- GNURLOPT_AUTOREFERER.3 \
- GNURLOPT_BUFFERSIZE.3 \
- GNURLOPT_CAINFO.3 \
- GNURLOPT_CAPATH.3 \
- GNURLOPT_CERTINFO.3 \
- GNURLOPT_CHUNK_BGN_FUNCTION.3 \
- GNURLOPT_CHUNK_DATA.3 \
- GNURLOPT_CHUNK_END_FUNCTION.3 \
- GNURLOPT_CLOSESOCKETDATA.3 \
- GNURLOPT_CLOSESOCKETFUNCTION.3 \
- GNURLOPT_CONNECTTIMEOUT.3 \
- GNURLOPT_CONNECTTIMEOUT_MS.3 \
- GNURLOPT_CONNECT_ONLY.3 \
- GNURLOPT_CONNECT_TO.3 \
- GNURLOPT_CONV_FROM_NETWORK_FUNCTION.3 \
- GNURLOPT_CONV_FROM_UTF8_FUNCTION.3 \
- GNURLOPT_CONV_TO_NETWORK_FUNCTION.3 \
- GNURLOPT_COOKIE.3 \
- GNURLOPT_COOKIEFILE.3 \
- GNURLOPT_COOKIEJAR.3 \
- GNURLOPT_COOKIELIST.3 \
- GNURLOPT_COOKIESESSION.3 \
- GNURLOPT_COPYPOSTFIELDS.3 \
- GNURLOPT_CRLF.3 \
- GNURLOPT_CRLFILE.3 \
- GNURLOPT_CURLU.3 \
- GNURLOPT_CUSTOMREQUEST.3 \
- GNURLOPT_DEBUGDATA.3 \
- GNURLOPT_DEBUGFUNCTION.3 \
- GNURLOPT_DEFAULT_PROTOCOL.3 \
- GNURLOPT_DIRLISTONLY.3 \
- GNURLOPT_DISALLOW_USERNAME_IN_URL.3 \
- GNURLOPT_DNS_CACHE_TIMEOUT.3 \
- GNURLOPT_DNS_INTERFACE.3 \
- GNURLOPT_DNS_LOCAL_IP4.3 \
- GNURLOPT_DNS_LOCAL_IP6.3 \
- GNURLOPT_DNS_SERVERS.3 \
- GNURLOPT_DNS_SHUFFLE_ADDRESSES.3 \
- GNURLOPT_DNS_USE_GLOBAL_CACHE.3 \
- GNURLOPT_DOH_URL.3 \
- GNURLOPT_EGDSOCKET.3 \
- GNURLOPT_ERRORBUFFER.3 \
- GNURLOPT_EXPECT_100_TIMEOUT_MS.3 \
- GNURLOPT_FAILONERROR.3 \
- GNURLOPT_FILETIME.3 \
- GNURLOPT_FNMATCH_DATA.3 \
- GNURLOPT_FNMATCH_FUNCTION.3 \
- GNURLOPT_FOLLOWLOCATION.3 \
- GNURLOPT_FORBID_REUSE.3 \
- GNURLOPT_FRESH_CONNECT.3 \
- GNURLOPT_FTPPORT.3 \
- GNURLOPT_FTPSSLAUTH.3 \
- GNURLOPT_FTP_ACCOUNT.3 \
- GNURLOPT_FTP_ALTERNATIVE_TO_USER.3 \
- GNURLOPT_FTP_CREATE_MISSING_DIRS.3 \
- GNURLOPT_FTP_FILEMETHOD.3 \
- GNURLOPT_FTP_RESPONSE_TIMEOUT.3 \
- GNURLOPT_FTP_SKIP_PASV_IP.3 \
- GNURLOPT_FTP_SSL_CCC.3 \
- GNURLOPT_FTP_USE_EPRT.3 \
- GNURLOPT_FTP_USE_EPSV.3 \
- GNURLOPT_FTP_USE_PRET.3 \
- GNURLOPT_GSSAPI_DELEGATION.3 \
- GNURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 \
- GNURLOPT_HAPROXYPROTOCOL.3 \
- GNURLOPT_HEADER.3 \
- GNURLOPT_HEADERDATA.3 \
- GNURLOPT_HEADERFUNCTION.3 \
- GNURLOPT_HEADEROPT.3 \
- GNURLOPT_HTTP09_ALLOWED.3 \
- GNURLOPT_HTTP200ALIASES.3 \
- GNURLOPT_HTTPAUTH.3 \
- GNURLOPT_HTTPGET.3 \
- GNURLOPT_HTTPHEADER.3 \
- GNURLOPT_HTTPPOST.3 \
- GNURLOPT_HTTPPROXYTUNNEL.3 \
- GNURLOPT_HTTP_CONTENT_DECODING.3 \
- GNURLOPT_HTTP_TRANSFER_DECODING.3 \
- GNURLOPT_HTTP_VERSION.3 \
- GNURLOPT_IGNORE_CONTENT_LENGTH.3 \
- GNURLOPT_INFILESIZE.3 \
- GNURLOPT_INFILESIZE_LARGE.3 \
- GNURLOPT_INTERFACE.3 \
- GNURLOPT_INTERLEAVEDATA.3 \
- GNURLOPT_INTERLEAVEFUNCTION.3 \
- GNURLOPT_IOCTLDATA.3 \
- GNURLOPT_IOCTLFUNCTION.3 \
- GNURLOPT_IPRESOLVE.3 \
- GNURLOPT_ISSUERCERT.3 \
- GNURLOPT_KEEP_SENDING_ON_ERROR.3 \
- GNURLOPT_KEYPASSWD.3 \
- GNURLOPT_KRBLEVEL.3 \
- GNURLOPT_LOCALPORT.3 \
- GNURLOPT_LOCALPORTRANGE.3 \
- GNURLOPT_LOGIN_OPTIONS.3 \
- GNURLOPT_LOW_SPEED_LIMIT.3 \
- GNURLOPT_LOW_SPEED_TIME.3 \
- GNURLOPT_MAIL_AUTH.3 \
- GNURLOPT_MAIL_FROM.3 \
- GNURLOPT_MAIL_RCPT.3 \
- GNURLOPT_MAIL_RCPT_ALLLOWFAILS.3 \
- GNURLOPT_MAXAGE_CONN.3 \
- GNURLOPT_MAXCONNECTS.3 \
- GNURLOPT_MAXFILESIZE.3 \
- GNURLOPT_MAXFILESIZE_LARGE.3 \
- GNURLOPT_MAXREDIRS.3 \
- GNURLOPT_MAX_RECV_SPEED_LARGE.3 \
- GNURLOPT_MAX_SEND_SPEED_LARGE.3 \
- GNURLOPT_MIMEPOST.3 \
- GNURLOPT_NETRC.3 \
- GNURLOPT_NETRC_FILE.3 \
- GNURLOPT_NEW_DIRECTORY_PERMS.3 \
- GNURLOPT_NEW_FILE_PERMS.3 \
- GNURLOPT_NOBODY.3 \
- GNURLOPT_NOPROGRESS.3 \
- GNURLOPT_NOPROXY.3 \
- GNURLOPT_NOSIGNAL.3 \
- GNURLOPT_OPENSOCKETDATA.3 \
- GNURLOPT_OPENSOCKETFUNCTION.3 \
- GNURLOPT_PASSWORD.3 \
- GNURLOPT_PATH_AS_IS.3 \
- GNURLOPT_PINNEDPUBLICKEY.3 \
- GNURLOPT_PIPEWAIT.3 \
- GNURLOPT_PORT.3 \
- GNURLOPT_POST.3 \
- GNURLOPT_POSTFIELDS.3 \
- GNURLOPT_POSTFIELDSIZE.3 \
- GNURLOPT_POSTFIELDSIZE_LARGE.3 \
- GNURLOPT_POSTQUOTE.3 \
- GNURLOPT_POSTREDIR.3 \
- GNURLOPT_PREQUOTE.3 \
- GNURLOPT_PRE_PROXY.3 \
- GNURLOPT_PRIVATE.3 \
- GNURLOPT_PROGRESSDATA.3 \
- GNURLOPT_PROGRESSFUNCTION.3 \
- GNURLOPT_PROTOCOLS.3 \
- GNURLOPT_PROXY.3 \
- GNURLOPT_PROXYAUTH.3 \
- GNURLOPT_PROXYHEADER.3 \
- GNURLOPT_PROXYPASSWORD.3 \
- GNURLOPT_PROXYPORT.3 \
- GNURLOPT_PROXYTYPE.3 \
- GNURLOPT_PROXYUSERNAME.3 \
- GNURLOPT_PROXYUSERPWD.3 \
- GNURLOPT_PROXY_CAINFO.3 \
- GNURLOPT_PROXY_CAPATH.3 \
- GNURLOPT_PROXY_CRLFILE.3 \
- GNURLOPT_PROXY_KEYPASSWD.3 \
- GNURLOPT_PROXY_PINNEDPUBLICKEY.3 \
- GNURLOPT_PROXY_SERVICE_NAME.3 \
- GNURLOPT_PROXY_SSLCERT.3 \
- GNURLOPT_PROXY_SSLCERTTYPE.3 \
- GNURLOPT_PROXY_SSLKEY.3 \
- GNURLOPT_PROXY_SSLKEYTYPE.3 \
- GNURLOPT_PROXY_SSLVERSION.3 \
- GNURLOPT_PROXY_SSL_CIPHER_LIST.3 \
- GNURLOPT_PROXY_SSL_OPTIONS.3 \
- GNURLOPT_PROXY_SSL_VERIFYHOST.3 \
- GNURLOPT_PROXY_SSL_VERIFYPEER.3 \
- GNURLOPT_PROXY_TLS13_CIPHERS.3 \
- GNURLOPT_PROXY_TLSAUTH_PASSWORD.3 \
- GNURLOPT_PROXY_TLSAUTH_TYPE.3 \
- GNURLOPT_PROXY_TLSAUTH_USERNAME.3 \
- GNURLOPT_PROXY_TRANSFER_MODE.3 \
- GNURLOPT_PUT.3 \
- GNURLOPT_QUOTE.3 \
- GNURLOPT_RANDOM_FILE.3 \
- GNURLOPT_RANGE.3 \
- GNURLOPT_READDATA.3 \
- GNURLOPT_READFUNCTION.3 \
- GNURLOPT_REDIR_PROTOCOLS.3 \
- GNURLOPT_REFERER.3 \
- GNURLOPT_REQUEST_TARGET.3 \
- GNURLOPT_RESOLVE.3 \
- GNURLOPT_RESOLVER_START_DATA.3 \
- GNURLOPT_RESOLVER_START_FUNCTION.3 \
- GNURLOPT_RESUME_FROM.3 \
- GNURLOPT_RESUME_FROM_LARGE.3 \
- GNURLOPT_RTSP_CLIENT_CSEQ.3 \
- GNURLOPT_RTSP_REQUEST.3 \
- GNURLOPT_RTSP_SERVER_CSEQ.3 \
- GNURLOPT_RTSP_SESSION_ID.3 \
- GNURLOPT_RTSP_STREAM_URI.3 \
- GNURLOPT_RTSP_TRANSPORT.3 \
- GNURLOPT_SASL_AUTHZID.3 \
- GNURLOPT_SASL_IR.3 \
- GNURLOPT_SEEKDATA.3 \
- GNURLOPT_SEEKFUNCTION.3 \
- GNURLOPT_SERVICE_NAME.3 \
- GNURLOPT_SHARE.3 \
- GNURLOPT_SOCKOPTDATA.3 \
- GNURLOPT_SOCKOPTFUNCTION.3 \
- GNURLOPT_SOCKS5_AUTH.3 \
- GNURLOPT_SOCKS5_GSSAPI_NEC.3 \
- GNURLOPT_SOCKS5_GSSAPI_SERVICE.3 \
- GNURLOPT_SSH_AUTH_TYPES.3 \
- GNURLOPT_SSH_COMPRESSION.3 \
- GNURLOPT_SSH_HOST_PUBLIC_KEY_MD5.3 \
- GNURLOPT_SSH_KEYDATA.3 \
- GNURLOPT_SSH_KEYFUNCTION.3 \
- GNURLOPT_SSH_KNOWNHOSTS.3 \
- GNURLOPT_SSH_PRIVATE_KEYFILE.3 \
- GNURLOPT_SSH_PUBLIC_KEYFILE.3 \
- GNURLOPT_SSLCERT.3 \
- GNURLOPT_SSLCERTTYPE.3 \
- GNURLOPT_SSLENGINE.3 \
- GNURLOPT_SSLENGINE_DEFAULT.3 \
- GNURLOPT_SSLKEY.3 \
- GNURLOPT_SSLKEYTYPE.3 \
- GNURLOPT_SSLVERSION.3 \
- GNURLOPT_SSL_CIPHER_LIST.3 \
- GNURLOPT_SSL_CTX_DATA.3 \
- GNURLOPT_SSL_CTX_FUNCTION.3 \
- GNURLOPT_SSL_ENABLE_ALPN.3 \
- GNURLOPT_SSL_ENABLE_NPN.3 \
- GNURLOPT_SSL_FALSESTART.3 \
- GNURLOPT_SSL_OPTIONS.3 \
- GNURLOPT_SSL_SESSIONID_CACHE.3 \
- GNURLOPT_SSL_VERIFYHOST.3 \
- GNURLOPT_SSL_VERIFYPEER.3 \
- GNURLOPT_SSL_VERIFYSTATUS.3 \
- GNURLOPT_STDERR.3 \
- GNURLOPT_STREAM_DEPENDS.3 \
- GNURLOPT_STREAM_DEPENDS_E.3 \
- GNURLOPT_STREAM_WEIGHT.3 \
- GNURLOPT_SUPPRESS_CONNECT_HEADERS.3 \
- GNURLOPT_TCP_FASTOPEN.3 \
- GNURLOPT_TCP_KEEPALIVE.3 \
- GNURLOPT_TCP_KEEPIDLE.3 \
- GNURLOPT_TCP_KEEPINTVL.3 \
- GNURLOPT_TCP_NODELAY.3 \
- GNURLOPT_TELNETOPTIONS.3 \
- GNURLOPT_TFTP_BLKSIZE.3 \
- GNURLOPT_TFTP_NO_OPTIONS.3 \
- GNURLOPT_TIMECONDITION.3 \
- GNURLOPT_TIMEOUT.3 \
- GNURLOPT_TIMEOUT_MS.3 \
- GNURLOPT_TIMEVALUE.3 \
- GNURLOPT_TIMEVALUE_LARGE.3 \
- GNURLOPT_TLS13_CIPHERS.3 \
- GNURLOPT_TLSAUTH_PASSWORD.3 \
- GNURLOPT_TLSAUTH_TYPE.3 \
- GNURLOPT_TLSAUTH_USERNAME.3 \
- GNURLOPT_TRAILERDATA.3 \
- GNURLOPT_TRAILERFUNCTION.3 \
- GNURLOPT_TRANSFERTEXT.3 \
- GNURLOPT_TRANSFER_ENCODING.3 \
- GNURLOPT_UNIX_SOCKET_PATH.3 \
- GNURLOPT_UNRESTRICTED_AUTH.3 \
- GNURLOPT_UPKEEP_INTERVAL_MS.3 \
- GNURLOPT_UPLOAD.3 \
- GNURLOPT_UPLOAD_BUFFERSIZE.3 \
- GNURLOPT_URL.3 \
- GNURLOPT_USERAGENT.3 \
- GNURLOPT_USERNAME.3 \
- GNURLOPT_USERPWD.3 \
- GNURLOPT_USE_SSL.3 \
- GNURLOPT_VERBOSE.3 \
- GNURLOPT_WILDCARDMATCH.3 \
- GNURLOPT_WRITEDATA.3 \
- GNURLOPT_WRITEFUNCTION.3 \
- GNURLOPT_XFERINFODATA.3 \
- GNURLOPT_XFERINFOFUNCTION.3 \
- GNURLOPT_XOAUTH2_BEARER.3
+ CURLINFO_ACTIVESOCKET.3 \
+ CURLINFO_APPCONNECT_TIME.3 \
+ CURLINFO_APPCONNECT_TIME_T.3 \
+ CURLINFO_CERTINFO.3 \
+ CURLINFO_CONDITION_UNMET.3 \
+ CURLINFO_CONNECT_TIME.3 \
+ CURLINFO_CONNECT_TIME_T.3 \
+ CURLINFO_CONTENT_LENGTH_DOWNLOAD.3 \
+ CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.3 \
+ CURLINFO_CONTENT_LENGTH_UPLOAD.3 \
+ CURLINFO_CONTENT_LENGTH_UPLOAD_T.3 \
+ CURLINFO_CONTENT_TYPE.3 \
+ CURLINFO_COOKIELIST.3 \
+ CURLINFO_EFFECTIVE_URL.3 \
+ CURLINFO_FILETIME.3 \
+ CURLINFO_FILETIME_T.3 \
+ CURLINFO_FTP_ENTRY_PATH.3 \
+ CURLINFO_HEADER_SIZE.3 \
+ CURLINFO_HTTPAUTH_AVAIL.3 \
+ CURLINFO_HTTP_CONNECTCODE.3 \
+ CURLINFO_HTTP_VERSION.3 \
+ CURLINFO_LASTSOCKET.3 \
+ CURLINFO_LOCAL_IP.3 \
+ CURLINFO_LOCAL_PORT.3 \
+ CURLINFO_NAMELOOKUP_TIME.3 \
+ CURLINFO_NAMELOOKUP_TIME_T.3 \
+ CURLINFO_NUM_CONNECTS.3 \
+ CURLINFO_OS_ERRNO.3 \
+ CURLINFO_PRETRANSFER_TIME.3 \
+ CURLINFO_PRETRANSFER_TIME_T.3 \
+ CURLINFO_PRIMARY_IP.3 \
+ CURLINFO_PRIMARY_PORT.3 \
+ CURLINFO_PRIVATE.3 \
+ CURLINFO_PROTOCOL.3 \
+ CURLINFO_PROXYAUTH_AVAIL.3 \
+ CURLINFO_PROXY_SSL_VERIFYRESULT.3 \
+ CURLINFO_REDIRECT_COUNT.3 \
+ CURLINFO_REDIRECT_TIME.3 \
+ CURLINFO_REDIRECT_TIME_T.3 \
+ CURLINFO_REDIRECT_URL.3 \
+ CURLINFO_REQUEST_SIZE.3 \
+ CURLINFO_RESPONSE_CODE.3 \
+ CURLINFO_RETRY_AFTER.3 \
+ CURLINFO_RTSP_CLIENT_CSEQ.3 \
+ CURLINFO_RTSP_CSEQ_RECV.3 \
+ CURLINFO_RTSP_SERVER_CSEQ.3 \
+ CURLINFO_RTSP_SESSION_ID.3 \
+ CURLINFO_SCHEME.3 \
+ CURLINFO_SIZE_DOWNLOAD.3 \
+ CURLINFO_SIZE_DOWNLOAD_T.3 \
+ CURLINFO_SIZE_UPLOAD.3 \
+ CURLINFO_SIZE_UPLOAD_T.3 \
+ CURLINFO_SPEED_DOWNLOAD.3 \
+ CURLINFO_SPEED_DOWNLOAD_T.3 \
+ CURLINFO_SPEED_UPLOAD.3 \
+ CURLINFO_SPEED_UPLOAD_T.3 \
+ CURLINFO_SSL_ENGINES.3 \
+ CURLINFO_SSL_VERIFYRESULT.3 \
+ CURLINFO_STARTTRANSFER_TIME.3 \
+ CURLINFO_STARTTRANSFER_TIME_T.3 \
+ CURLINFO_TLS_SESSION.3 \
+ CURLINFO_TLS_SSL_PTR.3 \
+ CURLINFO_TOTAL_TIME.3 \
+ CURLINFO_TOTAL_TIME_T.3 \
+ CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.3 \
+ CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.3 \
+ CURLMOPT_MAXCONNECTS.3 \
+ CURLMOPT_MAX_CONCURRENT_STREAMS.3 \
+ CURLMOPT_MAX_HOST_CONNECTIONS.3 \
+ CURLMOPT_MAX_PIPELINE_LENGTH.3 \
+ CURLMOPT_MAX_TOTAL_CONNECTIONS.3 \
+ CURLMOPT_PIPELINING.3 \
+ CURLMOPT_PIPELINING_SERVER_BL.3 \
+ CURLMOPT_PIPELINING_SITE_BL.3 \
+ CURLMOPT_PUSHDATA.3 \
+ CURLMOPT_PUSHFUNCTION.3 \
+ CURLMOPT_SOCKETDATA.3 \
+ CURLMOPT_SOCKETFUNCTION.3 \
+ CURLMOPT_TIMERDATA.3 \
+ CURLMOPT_TIMERFUNCTION.3 \
+ CURLOPT_ABSTRACT_UNIX_SOCKET.3 \
+ CURLOPT_ACCEPTTIMEOUT_MS.3 \
+ CURLOPT_ACCEPT_ENCODING.3 \
+ CURLOPT_ADDRESS_SCOPE.3 \
+ CURLOPT_ALTSVC.3 \
+ CURLOPT_ALTSVC_CTRL.3 \
+ CURLOPT_APPEND.3 \
+ CURLOPT_AUTOREFERER.3 \
+ CURLOPT_BUFFERSIZE.3 \
+ CURLOPT_CAINFO.3 \
+ CURLOPT_CAPATH.3 \
+ CURLOPT_CERTINFO.3 \
+ CURLOPT_CHUNK_BGN_FUNCTION.3 \
+ CURLOPT_CHUNK_DATA.3 \
+ CURLOPT_CHUNK_END_FUNCTION.3 \
+ CURLOPT_CLOSESOCKETDATA.3 \
+ CURLOPT_CLOSESOCKETFUNCTION.3 \
+ CURLOPT_CONNECTTIMEOUT.3 \
+ CURLOPT_CONNECTTIMEOUT_MS.3 \
+ CURLOPT_CONNECT_ONLY.3 \
+ CURLOPT_CONNECT_TO.3 \
+ CURLOPT_CONV_FROM_NETWORK_FUNCTION.3 \
+ CURLOPT_CONV_FROM_UTF8_FUNCTION.3 \
+ CURLOPT_CONV_TO_NETWORK_FUNCTION.3 \
+ CURLOPT_COOKIE.3 \
+ CURLOPT_COOKIEFILE.3 \
+ CURLOPT_COOKIEJAR.3 \
+ CURLOPT_COOKIELIST.3 \
+ CURLOPT_COOKIESESSION.3 \
+ CURLOPT_COPYPOSTFIELDS.3 \
+ CURLOPT_CRLF.3 \
+ CURLOPT_CRLFILE.3 \
+ CURLOPT_CURLU.3 \
+ CURLOPT_CUSTOMREQUEST.3 \
+ CURLOPT_DEBUGDATA.3 \
+ CURLOPT_DEBUGFUNCTION.3 \
+ CURLOPT_DEFAULT_PROTOCOL.3 \
+ CURLOPT_DIRLISTONLY.3 \
+ CURLOPT_DISALLOW_USERNAME_IN_URL.3 \
+ CURLOPT_DNS_CACHE_TIMEOUT.3 \
+ CURLOPT_DNS_INTERFACE.3 \
+ CURLOPT_DNS_LOCAL_IP4.3 \
+ CURLOPT_DNS_LOCAL_IP6.3 \
+ CURLOPT_DNS_SERVERS.3 \
+ CURLOPT_DNS_SHUFFLE_ADDRESSES.3 \
+ CURLOPT_DNS_USE_GLOBAL_CACHE.3 \
+ CURLOPT_DOH_URL.3 \
+ CURLOPT_EGDSOCKET.3 \
+ CURLOPT_ERRORBUFFER.3 \
+ CURLOPT_EXPECT_100_TIMEOUT_MS.3 \
+ CURLOPT_FAILONERROR.3 \
+ CURLOPT_FILETIME.3 \
+ CURLOPT_FNMATCH_DATA.3 \
+ CURLOPT_FNMATCH_FUNCTION.3 \
+ CURLOPT_FOLLOWLOCATION.3 \
+ CURLOPT_FORBID_REUSE.3 \
+ CURLOPT_FRESH_CONNECT.3 \
+ CURLOPT_FTPPORT.3 \
+ CURLOPT_FTPSSLAUTH.3 \
+ CURLOPT_FTP_ACCOUNT.3 \
+ CURLOPT_FTP_ALTERNATIVE_TO_USER.3 \
+ CURLOPT_FTP_CREATE_MISSING_DIRS.3 \
+ CURLOPT_FTP_FILEMETHOD.3 \
+ CURLOPT_FTP_RESPONSE_TIMEOUT.3 \
+ CURLOPT_FTP_SKIP_PASV_IP.3 \
+ CURLOPT_FTP_SSL_CCC.3 \
+ CURLOPT_FTP_USE_EPRT.3 \
+ CURLOPT_FTP_USE_EPSV.3 \
+ CURLOPT_FTP_USE_PRET.3 \
+ CURLOPT_GSSAPI_DELEGATION.3 \
+ CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 \
+ CURLOPT_HAPROXYPROTOCOL.3 \
+ CURLOPT_HEADER.3 \
+ CURLOPT_HEADERDATA.3 \
+ CURLOPT_HEADERFUNCTION.3 \
+ CURLOPT_HEADEROPT.3 \
+ CURLOPT_HTTP09_ALLOWED.3 \
+ CURLOPT_HTTP200ALIASES.3 \
+ CURLOPT_HTTPAUTH.3 \
+ CURLOPT_HTTPGET.3 \
+ CURLOPT_HTTPHEADER.3 \
+ CURLOPT_HTTPPOST.3 \
+ CURLOPT_HTTPPROXYTUNNEL.3 \
+ CURLOPT_HTTP_CONTENT_DECODING.3 \
+ CURLOPT_HTTP_TRANSFER_DECODING.3 \
+ CURLOPT_HTTP_VERSION.3 \
+ CURLOPT_IGNORE_CONTENT_LENGTH.3 \
+ CURLOPT_INFILESIZE.3 \
+ CURLOPT_INFILESIZE_LARGE.3 \
+ CURLOPT_INTERFACE.3 \
+ CURLOPT_INTERLEAVEDATA.3 \
+ CURLOPT_INTERLEAVEFUNCTION.3 \
+ CURLOPT_IOCTLDATA.3 \
+ CURLOPT_IOCTLFUNCTION.3 \
+ CURLOPT_IPRESOLVE.3 \
+ CURLOPT_ISSUERCERT.3 \
+ CURLOPT_ISSUERCERT_BLOB.3 \
+ CURLOPT_KEEP_SENDING_ON_ERROR.3 \
+ CURLOPT_KEYPASSWD.3 \
+ CURLOPT_KRBLEVEL.3 \
+ CURLOPT_LOCALPORT.3 \
+ CURLOPT_LOCALPORTRANGE.3 \
+ CURLOPT_LOGIN_OPTIONS.3 \
+ CURLOPT_LOW_SPEED_LIMIT.3 \
+ CURLOPT_LOW_SPEED_TIME.3 \
+ CURLOPT_MAIL_AUTH.3 \
+ CURLOPT_MAIL_FROM.3 \
+ CURLOPT_MAIL_RCPT.3 \
+ CURLOPT_MAIL_RCPT_ALLLOWFAILS.3 \
+ CURLOPT_MAXAGE_CONN.3 \
+ CURLOPT_MAXCONNECTS.3 \
+ CURLOPT_MAXFILESIZE.3 \
+ CURLOPT_MAXFILESIZE_LARGE.3 \
+ CURLOPT_MAXREDIRS.3 \
+ CURLOPT_MAX_RECV_SPEED_LARGE.3 \
+ CURLOPT_MAX_SEND_SPEED_LARGE.3 \
+ CURLOPT_MIMEPOST.3 \
+ CURLOPT_NETRC.3 \
+ CURLOPT_NETRC_FILE.3 \
+ CURLOPT_NEW_DIRECTORY_PERMS.3 \
+ CURLOPT_NEW_FILE_PERMS.3 \
+ CURLOPT_NOBODY.3 \
+ CURLOPT_NOPROGRESS.3 \
+ CURLOPT_NOPROXY.3 \
+ CURLOPT_NOSIGNAL.3 \
+ CURLOPT_OPENSOCKETDATA.3 \
+ CURLOPT_OPENSOCKETFUNCTION.3 \
+ CURLOPT_PASSWORD.3 \
+ CURLOPT_PATH_AS_IS.3 \
+ CURLOPT_PINNEDPUBLICKEY.3 \
+ CURLOPT_PIPEWAIT.3 \
+ CURLOPT_PORT.3 \
+ CURLOPT_POST.3 \
+ CURLOPT_POSTFIELDS.3 \
+ CURLOPT_POSTFIELDSIZE.3 \
+ CURLOPT_POSTFIELDSIZE_LARGE.3 \
+ CURLOPT_POSTQUOTE.3 \
+ CURLOPT_POSTREDIR.3 \
+ CURLOPT_PREQUOTE.3 \
+ CURLOPT_PRE_PROXY.3 \
+ CURLOPT_PRIVATE.3 \
+ CURLOPT_PROGRESSDATA.3 \
+ CURLOPT_PROGRESSFUNCTION.3 \
+ CURLOPT_PROTOCOLS.3 \
+ CURLOPT_PROXY.3 \
+ CURLOPT_PROXYAUTH.3 \
+ CURLOPT_PROXYHEADER.3 \
+ CURLOPT_PROXYPASSWORD.3 \
+ CURLOPT_PROXYPORT.3 \
+ CURLOPT_PROXYTYPE.3 \
+ CURLOPT_PROXYUSERNAME.3 \
+ CURLOPT_PROXYUSERPWD.3 \
+ CURLOPT_PROXY_CAINFO.3 \
+ CURLOPT_PROXY_CAPATH.3 \
+ CURLOPT_PROXY_CRLFILE.3 \
+ CURLOPT_PROXY_KEYPASSWD.3 \
+ CURLOPT_PROXY_ISSUERCERT.3 \
+ CURLOPT_PROXY_ISSUERCERT_BLOB.3 \
+ CURLOPT_PROXY_PINNEDPUBLICKEY.3 \
+ CURLOPT_PROXY_SERVICE_NAME.3 \
+ CURLOPT_PROXY_SSLCERT.3 \
+ CURLOPT_PROXY_SSLCERT_BLOB.3 \
+ CURLOPT_PROXY_SSLCERTTYPE.3 \
+ CURLOPT_PROXY_SSLKEY.3 \
+ CURLOPT_PROXY_SSLKEY_BLOB.3 \
+ CURLOPT_PROXY_SSLKEYTYPE.3 \
+ CURLOPT_PROXY_SSLVERSION.3 \
+ CURLOPT_PROXY_SSL_CIPHER_LIST.3 \
+ CURLOPT_PROXY_SSL_OPTIONS.3 \
+ CURLOPT_PROXY_SSL_VERIFYHOST.3 \
+ CURLOPT_PROXY_SSL_VERIFYPEER.3 \
+ CURLOPT_PROXY_TLS13_CIPHERS.3 \
+ CURLOPT_PROXY_TLSAUTH_PASSWORD.3 \
+ CURLOPT_PROXY_TLSAUTH_TYPE.3 \
+ CURLOPT_PROXY_TLSAUTH_USERNAME.3 \
+ CURLOPT_PROXY_TRANSFER_MODE.3 \
+ CURLOPT_PUT.3 \
+ CURLOPT_QUOTE.3 \
+ CURLOPT_RANDOM_FILE.3 \
+ CURLOPT_RANGE.3 \
+ CURLOPT_READDATA.3 \
+ CURLOPT_READFUNCTION.3 \
+ CURLOPT_REDIR_PROTOCOLS.3 \
+ CURLOPT_REFERER.3 \
+ CURLOPT_REQUEST_TARGET.3 \
+ CURLOPT_RESOLVE.3 \
+ CURLOPT_RESOLVER_START_DATA.3 \
+ CURLOPT_RESOLVER_START_FUNCTION.3 \
+ CURLOPT_RESUME_FROM.3 \
+ CURLOPT_RESUME_FROM_LARGE.3 \
+ CURLOPT_RTSP_CLIENT_CSEQ.3 \
+ CURLOPT_RTSP_REQUEST.3 \
+ CURLOPT_RTSP_SERVER_CSEQ.3 \
+ CURLOPT_RTSP_SESSION_ID.3 \
+ CURLOPT_RTSP_STREAM_URI.3 \
+ CURLOPT_RTSP_TRANSPORT.3 \
+ CURLOPT_SASL_AUTHZID.3 \
+ CURLOPT_SASL_IR.3 \
+ CURLOPT_SEEKDATA.3 \
+ CURLOPT_SEEKFUNCTION.3 \
+ CURLOPT_SERVICE_NAME.3 \
+ CURLOPT_SHARE.3 \
+ CURLOPT_SOCKOPTDATA.3 \
+ CURLOPT_SOCKOPTFUNCTION.3 \
+ CURLOPT_SOCKS5_AUTH.3 \
+ CURLOPT_SOCKS5_GSSAPI_NEC.3 \
+ CURLOPT_SOCKS5_GSSAPI_SERVICE.3 \
+ CURLOPT_SSH_AUTH_TYPES.3 \
+ CURLOPT_SSH_COMPRESSION.3 \
+ CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.3 \
+ CURLOPT_SSH_KEYDATA.3 \
+ CURLOPT_SSH_KEYFUNCTION.3 \
+ CURLOPT_SSH_KNOWNHOSTS.3 \
+ CURLOPT_SSH_PRIVATE_KEYFILE.3 \
+ CURLOPT_SSH_PUBLIC_KEYFILE.3 \
+ CURLOPT_SSLCERT.3 \
+ CURLOPT_SSLCERT_BLOB.3 \
+ CURLOPT_SSLCERTTYPE.3 \
+ CURLOPT_SSLENGINE.3 \
+ CURLOPT_SSLENGINE_DEFAULT.3 \
+ CURLOPT_SSLKEY.3 \
+ CURLOPT_SSLKEY_BLOB.3 \
+ CURLOPT_SSLKEYTYPE.3 \
+ CURLOPT_SSLVERSION.3 \
+ CURLOPT_SSL_CIPHER_LIST.3 \
+ CURLOPT_SSL_CTX_DATA.3 \
+ CURLOPT_SSL_CTX_FUNCTION.3 \
+ CURLOPT_SSL_ENABLE_ALPN.3 \
+ CURLOPT_SSL_ENABLE_NPN.3 \
+ CURLOPT_SSL_FALSESTART.3 \
+ CURLOPT_SSL_OPTIONS.3 \
+ CURLOPT_SSL_SESSIONID_CACHE.3 \
+ CURLOPT_SSL_VERIFYHOST.3 \
+ CURLOPT_SSL_VERIFYPEER.3 \
+ CURLOPT_SSL_VERIFYSTATUS.3 \
+ CURLOPT_STDERR.3 \
+ CURLOPT_STREAM_DEPENDS.3 \
+ CURLOPT_STREAM_DEPENDS_E.3 \
+ CURLOPT_STREAM_WEIGHT.3 \
+ CURLOPT_SUPPRESS_CONNECT_HEADERS.3 \
+ CURLOPT_TCP_FASTOPEN.3 \
+ CURLOPT_TCP_KEEPALIVE.3 \
+ CURLOPT_TCP_KEEPIDLE.3 \
+ CURLOPT_TCP_KEEPINTVL.3 \
+ CURLOPT_TCP_NODELAY.3 \
+ CURLOPT_TELNETOPTIONS.3 \
+ CURLOPT_TFTP_BLKSIZE.3 \
+ CURLOPT_TFTP_NO_OPTIONS.3 \
+ CURLOPT_TIMECONDITION.3 \
+ CURLOPT_TIMEOUT.3 \
+ CURLOPT_TIMEOUT_MS.3 \
+ CURLOPT_TIMEVALUE.3 \
+ CURLOPT_TIMEVALUE_LARGE.3 \
+ CURLOPT_TLS13_CIPHERS.3 \
+ CURLOPT_TLSAUTH_PASSWORD.3 \
+ CURLOPT_TLSAUTH_TYPE.3 \
+ CURLOPT_TLSAUTH_USERNAME.3 \
+ CURLOPT_TRAILERDATA.3 \
+ CURLOPT_TRAILERFUNCTION.3 \
+ CURLOPT_TRANSFERTEXT.3 \
+ CURLOPT_TRANSFER_ENCODING.3 \
+ CURLOPT_UNIX_SOCKET_PATH.3 \
+ CURLOPT_UNRESTRICTED_AUTH.3 \
+ CURLOPT_UPKEEP_INTERVAL_MS.3 \
+ CURLOPT_UPLOAD.3 \
+ CURLOPT_UPLOAD_BUFFERSIZE.3 \
+ CURLOPT_URL.3 \
+ CURLOPT_USERAGENT.3 \
+ CURLOPT_USERNAME.3 \
+ CURLOPT_USERPWD.3 \
+ CURLOPT_USE_SSL.3 \
+ CURLOPT_VERBOSE.3 \
+ CURLOPT_WILDCARDMATCH.3 \
+ CURLOPT_WRITEDATA.3 \
+ CURLOPT_WRITEFUNCTION.3 \
+ CURLOPT_XFERINFODATA.3 \
+ CURLOPT_XFERINFOFUNCTION.3 \
+ CURLOPT_XOAUTH2_BEARER.3
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index 3b340ed8e..36126db09 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -347,6 +347,7 @@ CURLM_RECURSIVE_API_CALL 7.59.0
CURLM_UNKNOWN_OPTION 7.15.4
CURLM_WAKEUP_FAILURE 7.68.0
CURLOPT 7.69.0
+CURLOPTTYPE_BLOB 7.71.0
CURLOPTTYPE_FUNCTIONPOINT 7.1
CURLOPTTYPE_LONG 7.1
CURLOPTTYPE_OBJECTPOINT 7.1
@@ -459,6 +460,7 @@ CURLOPT_IOCTLDATA 7.12.3
CURLOPT_IOCTLFUNCTION 7.12.3
CURLOPT_IPRESOLVE 7.10.8
CURLOPT_ISSUERCERT 7.19.0
+CURLOPT_ISSUERCERT_BLOB 7.71.0
CURLOPT_KEEP_SENDING_ON_ERROR 7.51.0
CURLOPT_KEYPASSWD 7.17.0
CURLOPT_KRB4LEVEL 7.3 7.17.0
@@ -514,6 +516,8 @@ CURLOPT_PROGRESSDATA 7.1
CURLOPT_PROGRESSFUNCTION 7.1 7.32.0
CURLOPT_PROTOCOLS 7.19.4
CURLOPT_PROXY 7.1
+CURLOPT_PROXY_ISSUERCERT 7.71.0
+CURLOPT_PROXY_ISSUERCERT_BLOB 7.71.0
CURLOPT_PROXYAUTH 7.10.7
CURLOPT_PROXYHEADER 7.37.0
CURLOPT_PROXYPASSWORD 7.19.1
@@ -528,8 +532,10 @@ CURLOPT_PROXY_KEYPASSWD 7.52.0
CURLOPT_PROXY_PINNEDPUBLICKEY 7.52.0
CURLOPT_PROXY_SERVICE_NAME 7.43.0
CURLOPT_PROXY_SSLCERT 7.52.0
+CURLOPT_PROXY_SSLCERT_BLOB 7.71.0
CURLOPT_PROXY_SSLCERTTYPE 7.52.0
CURLOPT_PROXY_SSLKEY 7.52.0
+CURLOPT_PROXY_SSLKEY_BLOB 7.71.0
CURLOPT_PROXY_SSLKEYTYPE 7.52.0
CURLOPT_PROXY_SSLVERSION 7.52.0
CURLOPT_PROXY_SSL_CIPHER_LIST 7.52.0
@@ -591,11 +597,13 @@ CURLOPT_SSH_KNOWNHOSTS 7.19.6
CURLOPT_SSH_PRIVATE_KEYFILE 7.16.1
CURLOPT_SSH_PUBLIC_KEYFILE 7.16.1
CURLOPT_SSLCERT 7.1
+CURLOPT_SSLCERT_BLOB 7.71.0
CURLOPT_SSLCERTPASSWD 7.1.1 7.17.0
CURLOPT_SSLCERTTYPE 7.9.3
CURLOPT_SSLENGINE 7.9.3
CURLOPT_SSLENGINE_DEFAULT 7.9.3
CURLOPT_SSLKEY 7.9.3
+CURLOPT_SSLKEY_BLOB 7.71.0
CURLOPT_SSLKEYPASSWD 7.9.3 7.17.0
CURLOPT_SSLKEYTYPE 7.9.3
CURLOPT_SSLVERSION 7.1
@@ -743,6 +751,7 @@ CURLSSLBACKEND_SCHANNEL 7.34.0
CURLSSLBACKEND_SECURETRANSPORT 7.64.1
CURLSSLBACKEND_WOLFSSL 7.49.0
CURLSSLOPT_ALLOW_BEAST 7.25.0
+CURLSSLOPT_NATIVE_CA 7.71.0
CURLSSLOPT_NO_PARTIALCHAIN 7.68.0
CURLSSLOPT_NO_REVOKE 7.44.0
CURLSSLSET_NO_BACKENDS 7.56.0
diff --git a/docs/options-in-versions b/docs/options-in-versions
new file mode 100644
index 000000000..1a27306ae
--- /dev/null
+++ b/docs/options-in-versions
@@ -0,0 +1,244 @@
+ _ _ ____ _
+ ___| | | | _ \| |
+ / __| | | | |_) | |
+ | (__| |_| | _ <| |___
+ \___|\___/|_| \_\_____|
+
+ This document lists all command line options present in curl, together with
+ exact information about the first curl version that supports it. The options
+ are sorted alphabetically on the long name.
+
+ Long (short) Introduced
+
+--abstract-unix-socket 7.53.0
+--alt-svc 7.64.1
+--anyauth 7.10.6
+--append (-a) 4.8
+--basic 7.10.6
+--cacert 7.5
+--capath 7.9.8
+--cert (-E) 5.0
+--cert-status 7.41.0
+--cert-type 7.9.3
+--ciphers 7.9
+--compressed 7.10
+--compressed-ssh 7.56.0
+--config (-K) 4.10
+--connect-timeout 7.7
+--connect-to 7.49.0
+--continue-at (-C) 4.8
+--cookie (-b) 4.9
+--cookie-jar (-c) 7.9
+--create-dirs 7.10.3
+--crlf 5.7
+--crlfile 7.19.7
+--data (-d) 4.0
+--data-ascii 7.2
+--data-binary 7.2
+--data-raw 7.43.0
+--data-urlencode 7.18.0
+--delegation 7.22.0
+--digest 7.10.6
+--disable (-q) 5.0
+--disable-eprt 7.10.5
+--disable-epsv 7.9.2
+--disallow-username-in-url 7.61.0
+--dns-interface 7.33.0
+--dns-ipv4-addr 7.33.0
+--dns-ipv6-addr 7.33.0
+--dns-servers 7.33.0
+--doh-url 7.62.0
+--dump-header (-D) 5.7
+--egd-file 7.7
+--engine 7.9.3
+--etag-compare 7.68.0
+--etag-save 7.68.0
+--expect100-timeout 7.47.0
+--fail (-f) 4.0
+--fail-early 7.52.0
+--false-start 7.42.0
+--form (-F) 5.0
+--form-string 7.13.2
+--ftp-account 7.13.0
+--ftp-alternative-to-user 7.15.5
+--ftp-create-dirs 7.10.7
+--ftp-method 7.15.1
+--ftp-pasv 7.11.0
+--ftp-port (-P) 4.0
+--ftp-pret 7.20.0
+--ftp-skip-pasv-ip 7.14.2
+--ftp-ssl-ccc 7.16.1
+--ftp-ssl-ccc-mode 7.16.2
+--ftp-ssl-control 7.16.0
+--get (-G) 7.8.1
+--globoff (-g) 7.6
+--happy-eyeballs-timeout-ms 7.59.0
+--haproxy-protocol 7.60.0
+--head (-I) 4.0
+--header (-H) 5.0
+--help (-h) 4.0
+--hostpubmd5 7.17.1
+--http0.9 7.64.0
+--http1.0 (-0) 7.9.1
+--http1.1 7.33.0
+--http2 7.33.0
+--http2-prior-knowledge 7.49.0
+--http3 7.66.0
+--ignore-content-length 7.14.1
+--include (-i) 4.8
+--insecure (-k) 7.10
+--interface 7.3
+--ipv4 (-4) 7.10.8
+--ipv6 (-6) 7.10.8
+--junk-session-cookies (-j) 7.9.7
+--keepalive-time 7.18.0
+--key 7.9.3
+--key-type 7.9.3
+--krb 7.3
+--libcurl 7.16.1
+--limit-rate 7.10
+--list-only (-l) 4.0
+--local-port 7.15.2
+--location (-L) 4.9
+--location-trusted 7.10.4
+--login-options 7.34.0
+--mail-auth 7.25.0
+--mail-from 7.20.0
+--mail-rcpt 7.20.0
+--mail-rcpt-allowfails 7.69.0
+--manual (-M) 5.2
+--max-filesize 7.10.8
+--max-redirs 7.5
+--max-time (-m) 4.0
+--metalink 7.27.0
+--negotiate 7.10.6
+--netrc (-n) 4.6
+--netrc-file 7.21.5
+--netrc-optional 7.9.8
+--next (-:) 7.36.0
+--no-alpn 7.36.0
+--no-buffer (-N) 6.5
+--no-keepalive 7.18.0
+--no-npn 7.36.0
+--no-progress-meter 7.67.0
+--no-sessionid 7.16.0
+--noproxy 7.19.4
+--ntlm 7.10.6
+--ntlm-wb 7.22.0
+--oauth2-bearer 7.33.0
+--output (-o) 4.0
+--parallel (-Z) 7.66.0
+--parallel-immediate 7.68.0
+--parallel-max 7.66.0
+--pass 7.9.3
+--path-as-is 7.42.0
+--pinnedpubkey 7.39.0
+--post301 7.17.1
+--post302 7.19.1
+--post303 7.26.0
+--preproxy 7.52.0
+--progress-bar (-#) 5.10
+--proto 7.20.2
+--proto-default 7.45.0
+--proto-redir 7.20.2
+--proxy (-x) 4.0
+--proxy-anyauth 7.13.2
+--proxy-basic 7.12.0
+--proxy-cacert 7.52.0
+--proxy-capath 7.52.0
+--proxy-cert 7.52.0
+--proxy-cert-type 7.52.0
+--proxy-ciphers 7.52.0
+--proxy-crlfile 7.52.0
+--proxy-digest 7.12.0
+--proxy-header 7.37.0
+--proxy-insecure 7.52.0
+--proxy-key 7.52.0
+--proxy-key-type 7.52.0
+--proxy-negotiate 7.17.1
+--proxy-ntlm 7.10.7
+--proxy-pass 7.52.0
+--proxy-pinnedpubkey 7.59.0
+--proxy-service-name 7.43.0
+--proxy-ssl-allow-beast 7.52.0
+--proxy-tls13-ciphers 7.61.0
+--proxy-tlsauthtype 7.52.0
+--proxy-tlspassword 7.52.0
+--proxy-tlsuser 7.52.0
+--proxy-tlsv1 7.52.0
+--proxy-user (-U) 4.0
+--proxy1.0 7.19.4
+--proxytunnel (-p) 7.3
+--pubkey 7.16.2
+--quote (-Q) 5.3
+--random-file 7.7
+--range (-r) 4.0
+--raw 7.16.2
+--referer (-e) 4.0
+--remote-header-name (-J) 7.20.0
+--remote-name (-O) 4.0
+--remote-name-all 7.19.0
+--remote-time (-R) 7.9
+--request (-X) 6.0
+--request-target 7.55.0
+--resolve 7.21.3
+--retry 7.12.3
+--retry-all-errors 7.71.0
+--retry-connrefused 7.52.0
+--retry-delay 7.12.3
+--retry-max-time 7.12.3
+--sasl-authzid 7.66.0
+--sasl-ir 7.31.0
+--service-name 7.43.0
+--show-error (-S) 5.9
+--silent (-s) 4.0
+--socks4 7.15.2
+--socks4a 7.18.0
+--socks5 7.18.0
+--socks5-basic 7.55.0
+--socks5-gssapi 7.55.0
+--socks5-gssapi-nec 7.19.4
+--socks5-gssapi-service 7.19.4
+--socks5-hostname 7.18.0
+--speed-limit (-Y) 4.7
+--speed-time (-y) 4.7
+--ssl 7.20.0
+--ssl-allow-beast 7.25.0
+--ssl-no-revoke 7.44.0
+--ssl-reqd 7.20.0
+--ssl-revoke-best-effort 7.70.0
+--sslv2 (-2) 5.9
+--sslv3 (-3) 5.9
+--stderr 6.2
+--styled-output 7.61.0
+--suppress-connect-headers 7.54.0
+--tcp-fastopen 7.49.0
+--tcp-nodelay 7.11.2
+--telnet-option (-t) 7.7
+--tftp-blksize 7.20.0
+--tftp-no-options 7.48.0
+--time-cond (-z) 5.8
+--tls-max 7.54.0
+--tls13-ciphers 7.61.0
+--tlsauthtype 7.21.4
+--tlspassword 7.21.4
+--tlsuser 7.21.4
+--tlsv1 (-1) 7.9.2
+--tlsv1.0 7.34.0
+--tlsv1.1 7.34.0
+--tlsv1.2 7.34.0
+--tlsv1.3 7.52.0
+--tr-encoding 7.21.6
+--trace 7.9.7
+--trace-ascii 7.9.7
+--trace-time 7.14.0
+--unix-socket 7.40.0
+--upload-file (-T) 4.0
+--url 7.5
+--use-ascii (-B) 5.0
+--user (-u) 4.0
+--user-agent (-A) 4.5.1
+--verbose (-v) 4.0
+--version (-V) 4.0
+--write-out (-w) 6.5
+--xattr 7.21.3
diff --git a/gnurl-config.in b/gnurl-config.in
index 4e12de840..e5621da20 100644
--- a/gnurl-config.in
+++ b/gnurl-config.in
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2001 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 2001 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -160,7 +160,7 @@ while test $# -gt 0; do
else
CURLLIBDIR=""
fi
- if test "X@REQUIRE_LIB_DEPS@" = "Xyes"; then
+ if test "X@ENABLE_SHARED@" = "Xno" -o "X@REQUIRE_LIB_DEPS@" = "Xyes"; then
echo @LDFLAGS@ ${CURLLIBDIR}-lgnurl @LIBCURL_LIBS@
else
echo @LDFLAGS@ ${CURLLIBDIR}-lgnurl
diff --git a/include/gnurl/curl.h b/include/gnurl/curl.h
index 11246ea30..e3531f5df 100644
--- a/include/gnurl/curl.h
+++ b/include/gnurl/curl.h
@@ -774,7 +774,7 @@ enum curl_khtype {
};
struct curl_khkey {
- const char *key; /* points to a zero-terminated string encoded with base64
+ const char *key; /* points to a null-terminated string encoded with base64
if len is zero, otherwise to the "raw" data */
size_t len;
enum curl_khtype keytype;
@@ -838,6 +838,10 @@ typedef enum {
behavior is present. */
#define CURLSSLOPT_REVOKE_BEST_EFFORT (1<<3)
+/* - CURLSSLOPT_NATIVE_CA tells libcurl to use standard certificate store of
+ operating system. Currently implemented under MS-Windows. */
+#define CURLSSLOPT_NATIVE_CA (1<<4)
+
/* The default connection attempt delay in milliseconds for happy eyeballs.
CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.3 and happy-eyeballs-timeout-ms.d document
this value, keep them in sync. */
@@ -946,6 +950,7 @@ typedef enum {
#define CURLOPTTYPE_OBJECTPOINT 10000
#define CURLOPTTYPE_FUNCTIONPOINT 20000
#define CURLOPTTYPE_OFF_T 30000
+#define CURLOPTTYPE_BLOB 40000
/* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the
string options from the header file */
@@ -1441,7 +1446,7 @@ typedef enum {
/* 132 OBSOLETE. Gone in 7.16.0 */
/* 133 OBSOLETE. Gone in 7.16.0 */
- /* zero terminated string for pass on to the FTP server when asked for
+ /* null-terminated string for pass on to the FTP server when asked for
"account" info */
CURLOPT(CURLOPT_FTP_ACCOUNT, CURLOPTTYPE_STRINGPOINT, 134),
@@ -1955,6 +1960,17 @@ typedef enum {
/* allow RCPT TO command to fail for some recipients */
CURLOPT(CURLOPT_MAIL_RCPT_ALLLOWFAILS, CURLOPTTYPE_LONG, 290),
+ /* the private SSL-certificate as a "blob" */
+ CURLOPT(CURLOPT_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 291),
+ CURLOPT(CURLOPT_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 292),
+ CURLOPT(CURLOPT_PROXY_SSLCERT_BLOB, CURLOPTTYPE_BLOB, 293),
+ CURLOPT(CURLOPT_PROXY_SSLKEY_BLOB, CURLOPTTYPE_BLOB, 294),
+ CURLOPT(CURLOPT_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 295),
+
+ /* Issuer certificate for proxy */
+ CURLOPT(CURLOPT_PROXY_ISSUERCERT, CURLOPTTYPE_STRINGPOINT, 296),
+ CURLOPT(CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOPTTYPE_BLOB, 297),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -2102,7 +2118,7 @@ typedef enum {
CURL_TIMECOND_LAST
} curl_TimeCond;
-/* Special size_t value signaling a zero-terminated string. */
+/* Special size_t value signaling a null-terminated string. */
#define CURL_ZERO_TERMINATED ((size_t) -1)
/* curl_strequal() and curl_strnequal() are subject for removal in a future
@@ -2111,8 +2127,8 @@ CURL_EXTERN int curl_strequal(const char *s1, const char *s2);
CURL_EXTERN int curl_strnequal(const char *s1, const char *s2, size_t n);
/* Mime/form handling support. */
-typedef struct curl_mime_s curl_mime; /* Mime context. */
-typedef struct curl_mimepart_s curl_mimepart; /* Mime part context. */
+typedef struct curl_mime curl_mime; /* Mime context. */
+typedef struct curl_mimepart curl_mimepart; /* Mime part context. */
/*
* NAME curl_mime_init()
@@ -2486,10 +2502,11 @@ struct curl_slist {
* subsequent attempt to change it will result in a CURLSSLSET_TOO_LATE.
*/
-typedef struct {
+struct curl_ssl_backend {
curl_sslbackend id;
const char *name;
-} curl_ssl_backend;
+};
+typedef struct curl_ssl_backend curl_ssl_backend;
typedef enum {
CURLSSLSET_OK = 0,
@@ -2741,7 +2758,7 @@ typedef enum {
from above. */
#define CURLVERSION_NOW CURLVERSION_SEVENTH
-typedef struct {
+struct curl_version_info_data {
CURLversion age; /* age of the returned struct */
const char *version; /* LIBCURL_VERSION */
unsigned int version_num; /* LIBCURL_VERSION_NUM */
@@ -2785,7 +2802,8 @@ typedef struct {
const char *capath; /* the built-in default CURLOPT_CAPATH, might
be NULL */
-} curl_version_info_data;
+};
+typedef struct curl_version_info_data curl_version_info_data;
#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */
#define CURL_VERSION_KERBEROS4 (1<<1) /* Kerberos V4 auth is supported
diff --git a/include/gnurl/curlver.h b/include/gnurl/curlver.h
index 92c3fd84b..fe29f0fff 100644
--- a/include/gnurl/curlver.h
+++ b/include/gnurl/curlver.h
@@ -30,16 +30,16 @@
/* This is the version number of the libcurl package from which this header
file origins: */
-#define LIBCURL_VERSION "7.70.0-DEV"
+#define LIBCURL_VERSION "7.71.1-DEV"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
-#define LIBCURL_VERSION_MINOR 70
-#define LIBCURL_VERSION_PATCH 0
+#define LIBCURL_VERSION_MINOR 71
+#define LIBCURL_VERSION_PATCH 1
/* This is the numeric version of the libcurl version number, meant for easier
- parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
+ parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
always follow this syntax:
0xXXYYZZ
@@ -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 0x074600
+#define LIBCURL_VERSION_NUM 0x074701
/*
* This is the date and time when the full source package was created. The
diff --git a/include/gnurl/easy.h b/include/gnurl/easy.h
index 592f5d3c1..9aef13396 100644
--- a/include/gnurl/easy.h
+++ b/include/gnurl/easy.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,6 +25,17 @@
extern "C" {
#endif
+/* Flag bits in the curl_blob struct: */
+#define CURL_BLOB_COPY 1 /* tell libcurl to copy the data */
+#define CURL_BLOB_NOCOPY 0 /* tell libcurl to NOT copy the data */
+
+struct curl_blob {
+ void *data;
+ size_t len;
+ unsigned int flags; /* bit 0 is defined, the rest are reserved and should be
+ left zeroes */
+};
+
CURL_EXTERN CURL *curl_easy_init(void);
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
diff --git a/include/gnurl/multi.h b/include/gnurl/multi.h
index 04b2cf7f3..99dfa96d0 100644
--- a/include/gnurl/multi.h
+++ b/include/gnurl/multi.h
@@ -267,7 +267,7 @@ CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
* value into the equivalent human readable error string. This is
* useful for printing meaningful error messages.
*
- * Returns: A pointer to a zero-terminated error message.
+ * Returns: A pointer to a null-terminated error message.
*/
CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
@@ -377,12 +377,10 @@ typedef enum {
will not be considered for pipelining */
CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10),
- /* a list of site names(+port) that are blacklisted from
- pipelining */
+ /* a list of site names(+port) that are blocked from pipelining */
CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11),
- /* a list of server types that are blacklisted from
- pipelining */
+ /* a list of server types that are blocked from pipelining */
CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12),
/* maximum number of open connections in total */
diff --git a/include/gnurl/typecheck-gcc.h b/include/gnurl/typecheck-gcc.h
index 03c84fc85..f8cb921f2 100644
--- a/include/gnurl/typecheck-gcc.h
+++ b/include/gnurl/typecheck-gcc.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -248,7 +248,7 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
(0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
#define curlcheck_off_t_option(option) \
- ((option) > CURLOPTTYPE_OFF_T)
+ (((option) > CURLOPTTYPE_OFF_T) && ((option) < CURLOPTTYPE_BLOB))
/* evaluates to true if option takes a char* argument */
#define curlcheck_string_option(option) \
@@ -392,8 +392,9 @@ CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
/* groups of curl_easy_getinfo infos that take the same type of argument */
/* evaluates to true if info expects a pointer to char * argument */
-#define curlcheck_string_info(info) \
- (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
+#define curlcheck_string_info(info) \
+ (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG && \
+ (info) != CURLINFO_PRIVATE)
/* evaluates to true if info expects a pointer to long argument */
#define curlcheck_long_info(info) \
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index e3cf41891..723b826e9 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -27,18 +27,18 @@ LIB_VAUTH_CFILES = vauth/cleartext.c vauth/cram.c vauth/digest.c \
LIB_VAUTH_HFILES = vauth/digest.h vauth/ntlm.h vauth/vauth.h
-LIB_VTLS_CFILES = vtls/bearssl.c vtls/gskit.c vtls/gtls.c vtls/mbedtls.c \
- vtls/mbedtls_threadlock.c vtls/mesalink.c vtls/nss.c vtls/openssl.c \
- vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c vtls/vtls.c \
- vtls/wolfssl.c
+LIB_VTLS_CFILES = vtls/bearssl.c vtls/gskit.c vtls/gtls.c vtls/keylog.c \
+ vtls/mbedtls.c vtls/mbedtls_threadlock.c vtls/mesalink.c vtls/nss.c \
+ vtls/openssl.c vtls/schannel.c vtls/schannel_verify.c vtls/sectransp.c \
+ vtls/vtls.c vtls/wolfssl.c
-LIB_VTLS_HFILES = vtls/bearssl.h vtls/gskit.h vtls/gtls.h vtls/mbedtls.h \
- vtls/mbedtls_threadlock.h vtls/mesalink.h vtls/nssg.h vtls/openssl.h \
- vtls/schannel.h vtls/sectransp.h vtls/vtls.h vtls/wolfssl.h
+LIB_VTLS_HFILES = vtls/bearssl.h vtls/gskit.h vtls/gtls.h vtls/keylog.h \
+ vtls/mbedtls.h vtls/mbedtls_threadlock.h vtls/mesalink.h vtls/nssg.h \
+ vtls/openssl.h vtls/schannel.h vtls/sectransp.h vtls/vtls.h vtls/wolfssl.h
-LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c
+LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c vquic/vquic.c
-LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h
+LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h vquic/vquic.h
LIB_VSSH_CFILES = vssh/libssh.c vssh/libssh2.c vssh/wolfssh.c
@@ -60,7 +60,7 @@ LIB_CFILES = altsvc.c amigaos.c asyn-ares.c asyn-thread.c base64.c \
sendf.c setopt.c sha256.c share.c slist.c smb.c smtp.c socketpair.c socks.c \
socks_gssapi.c socks_sspi.c speedcheck.c splay.c strcase.c strdup.c \
strerror.c strtok.c strtoofft.c system_win32.c telnet.c tftp.c timeval.c \
- transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c
+ transfer.c urlapi.c version.c warnless.c wildcard.c x509asn1.c dynbuf.c
LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h \
content_encoding.h cookie.h curl_addrinfo.h curl_base64.h curl_ctype.h \
@@ -79,7 +79,7 @@ LIB_HFILES = altsvc.h amigaos.h arpa_telnet.h asyn.h conncache.h connect.h \
smb.h smtp.h sockaddr.h socketpair.h socks.h speedcheck.h splay.h strcase.h \
strdup.h strerror.h strtok.h strtoofft.h system_win32.h telnet.h tftp.h \
timeval.h transfer.h urlapi-int.h urldata.h warnless.h wildcard.h \
- x509asn1.h
+ x509asn1.h dynbuf.h
LIB_RCFILES = libcurl.rc
diff --git a/lib/altsvc.c b/lib/altsvc.c
index 9da0917a8..b1c5db833 100644
--- a/lib/altsvc.c
+++ b/lib/altsvc.c
@@ -50,8 +50,10 @@
#define MAX_ALTSVC_ALPNLENSTR "10"
#define MAX_ALTSVC_ALPNLEN 10
-#if (defined(USE_QUICHE) || defined(USE_NGTCP2)) && !defined(UNITTESTS)
-#define H3VERSION "h3-27"
+#if defined(USE_QUICHE) && !defined(UNITTESTS)
+#define H3VERSION "h3-29"
+#elif defined(USE_NGTCP2) && !defined(UNITTESTS)
+#define H3VERSION "h3-29"
#else
#define H3VERSION "h3"
#endif
@@ -167,7 +169,6 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, char *line)
as->prio = prio;
as->persist = persist ? 1 : 0;
Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
- asi->num++; /* one more entry */
}
}
@@ -408,7 +409,6 @@ static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
strcasecompare(srchost, as->src.host)) {
Curl_llist_remove(&asi->list, e, NULL);
altsvc_free(as);
- asi->num--;
}
}
}
@@ -429,6 +429,8 @@ static time_t debugtime(void *unused)
#define time(x) debugtime(x)
#endif
+#define ISNEWLINE(x) (((x) == '\n') || (x) == '\r')
+
/*
* Curl_altsvc_parse() takes an incoming alt-svc response header and stores
* the data correctly in the cache.
@@ -474,7 +476,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
dstalpnid = alpn2alpnid(alpnbuf);
p++;
if(*p == '\"') {
- const char *dsthost;
+ const char *dsthost = "";
const char *value_ptr;
char option[32];
unsigned long num;
@@ -518,12 +520,12 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
/* Handle the optional 'ma' and 'persist' flags. Unknown flags
are skipped. */
for(;;) {
- while(*p && ISBLANK(*p) && *p != ';' && *p != ',')
+ while(ISBLANK(*p))
p++;
- if(!*p || *p == ',')
+ if(*p != ';')
break;
p++; /* pass the semicolon */
- if(!*p)
+ if(!*p || ISNEWLINE(*p))
break;
result = getalnum(&p, option, sizeof(option));
if(result) {
@@ -573,7 +575,6 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
as->expires = maxage + time(NULL);
as->persist = persist;
Curl_llist_insert_next(&asi->list, asi->list.tail, as, &as->node);
- asi->num++; /* one more entry */
infof(data, "Added alt-svc: %s:%d over %s\n", dsthost, dstport,
Curl_alpnid2str(dstalpnid));
}
diff --git a/lib/altsvc.h b/lib/altsvc.h
index 4e1e77aa4..cdf137aff 100644
--- a/lib/altsvc.h
+++ b/lib/altsvc.h
@@ -52,7 +52,6 @@ struct altsvc {
struct altsvcinfo {
char *filename;
struct curl_llist list; /* list of entries */
- size_t num; /* number of alt-svc entries */
long flags; /* the publicly set bitmask */
};
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index b76e66548..ba5160b25 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -87,7 +87,8 @@
struct ResolverResults {
int num_pending; /* number of ares_gethostbyname() requests */
- Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */
+ struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares
+ parts */
int last_status;
struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */
};
@@ -285,7 +286,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
* return number of sockets it worked on
*/
-static int waitperform(struct connectdata *conn, int timeout_ms)
+static int waitperform(struct connectdata *conn, timediff_t timeout_ms)
{
struct Curl_easy *data = conn->data;
int nfds;
@@ -352,8 +353,8 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
conn->async.os_specific;
CURLcode result = CURLE_OK;
- if(dns)
- *dns = NULL;
+ DEBUGASSERT(dns);
+ *dns = NULL;
waitperform(conn, 0);
@@ -381,19 +382,18 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
}
if(res && !res->num_pending) {
- if(dns) {
- (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
- /* temp_ai ownership is moved to the connection, so we need not free-up
- them */
- res->temp_ai = NULL;
- }
+ (void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
+ /* temp_ai ownership is moved to the connection, so we need not free-up
+ them */
+ res->temp_ai = NULL;
+
if(!conn->async.dns) {
failf(data, "Could not resolve: %s (%s)",
conn->async.hostname, ares_strerror(conn->async.status));
result = conn->bits.proxy?CURLE_COULDNT_RESOLVE_PROXY:
CURLE_COULDNT_RESOLVE_HOST;
}
- else if(dns)
+ else
*dns = conn->async.dns;
destroy_async_data(&conn->async);
@@ -408,7 +408,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
* Waits for a resolve to finish. This function should be avoided since using
* this risk getting the multi interface to "hang".
*
- * If 'entry' is non-NULL, make it point to the resolved dns entry
+ * 'entry' MUST be non-NULL.
*
* Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved,
* CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors.
@@ -420,10 +420,9 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
struct Curl_easy *data = conn->data;
timediff_t timeout;
struct curltime now = Curl_now();
- struct Curl_dns_entry *temp_entry;
- if(entry)
- *entry = NULL; /* clear on entry */
+ DEBUGASSERT(entry);
+ *entry = NULL; /* clear on entry */
timeout = Curl_timeleft(data, &now, TRUE);
if(timeout < 0) {
@@ -438,9 +437,13 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
while(!result) {
struct timeval *tvp, tv, store;
int itimeout;
- int timeout_ms;
+ timediff_t timeout_ms;
- itimeout = (timeout > (long)INT_MAX) ? INT_MAX : (int)timeout;
+#if TIMEDIFF_T_MAX > INT_MAX
+ itimeout = (timeout > INT_MAX) ? INT_MAX : (int)timeout;
+#else
+ itimeout = (int)timeout;
+#endif
store.tv_sec = itimeout/1000;
store.tv_usec = (itimeout%1000)*1000;
@@ -451,12 +454,12 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
second is left, otherwise just use 1000ms to make sure the progress
callback gets called frequent enough */
if(!tvp->tv_sec)
- timeout_ms = (int)(tvp->tv_usec/1000);
+ timeout_ms = (timediff_t)(tvp->tv_usec/1000);
else
timeout_ms = 1000;
waitperform(conn, timeout_ms);
- result = Curl_resolver_is_resolved(conn, entry?&temp_entry:NULL);
+ result = Curl_resolver_is_resolved(conn, entry);
if(result || conn->async.done)
break;
@@ -471,7 +474,7 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
else if(timediff > timeout)
timeout = -1;
else
- timeout -= (long)timediff;
+ timeout -= timediff;
now = now2; /* for next loop */
}
if(timeout < 0)
@@ -496,9 +499,9 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
/* Connects results to the list */
static void compound_results(struct ResolverResults *res,
- Curl_addrinfo *ai)
+ struct Curl_addrinfo *ai)
{
- Curl_addrinfo *ai_tail;
+ struct Curl_addrinfo *ai_tail;
if(!ai)
return;
ai_tail = ai;
@@ -540,7 +543,7 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
res->num_pending--;
if(CURL_ASYNC_SUCCESS == status) {
- Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
+ struct Curl_addrinfo *ai = Curl_he2ai(hostent, conn->async.port);
if(ai) {
compound_results(res, ai);
}
@@ -619,10 +622,10 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
-Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
- const char *hostname,
- int port,
- int *waitp)
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
{
char *bufp;
struct Curl_easy *data = conn->data;
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index 68dcbb3ec..a60f4f066 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -158,7 +158,7 @@ static bool init_resolve_thread(struct connectdata *conn,
/* Data for synchronization between resolver thread and its parent */
struct thread_sync_data {
- curl_mutex_t * mtx;
+ curl_mutex_t *mtx;
int done;
char *hostname; /* hostname to resolve, Curl_async.hostname
@@ -169,7 +169,7 @@ struct thread_sync_data {
curl_socket_t sock_pair[2]; /* socket pair */
#endif
int sock_error;
- Curl_addrinfo *res;
+ struct Curl_addrinfo *res;
#ifdef HAVE_GETADDRINFO
struct addrinfo hints;
#endif
@@ -179,7 +179,7 @@ struct thread_sync_data {
struct thread_data {
curl_thread_t thread_hnd;
unsigned int poll_interval;
- time_t interval_end;
+ timediff_t interval_end;
struct thread_sync_data tsd;
};
@@ -190,7 +190,7 @@ static struct thread_sync_data *conn_thread_sync_data(struct connectdata *conn)
/* Destroy resolver thread synchronization data */
static
-void destroy_thread_sync_data(struct thread_sync_data * tsd)
+void destroy_thread_sync_data(struct thread_sync_data *tsd)
{
if(tsd->mtx) {
Curl_mutex_destroy(tsd->mtx);
@@ -216,7 +216,7 @@ void destroy_thread_sync_data(struct thread_sync_data * tsd)
/* Initialize resolver thread synchronization data */
static
-int init_thread_sync_data(struct thread_data * td,
+int init_thread_sync_data(struct thread_data *td,
const char *hostname,
int port,
const struct addrinfo *hints)
@@ -494,11 +494,14 @@ static CURLcode resolver_error(struct connectdata *conn)
const char *host_or_proxy;
CURLcode result;
+#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy) {
host_or_proxy = "proxy";
result = CURLE_COULDNT_RESOLVE_PROXY;
}
- else {
+ else
+#endif
+ {
host_or_proxy = "host";
result = CURLE_COULDNT_RESOLVE_HOST;
}
@@ -509,6 +512,9 @@ static CURLcode resolver_error(struct connectdata *conn)
return result;
}
+/*
+ * 'entry' may be NULL and then no data is returned
+ */
static CURLcode thread_wait_resolv(struct connectdata *conn,
struct Curl_dns_entry **entry,
bool report)
@@ -593,6 +599,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
int done = 0;
+ DEBUGASSERT(entry);
*entry = NULL;
if(!td) {
@@ -618,8 +625,8 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
else {
/* poll for name lookup done with exponential backoff up to 250ms */
/* should be fine even if this converts to 32 bit */
- time_t elapsed = (time_t)Curl_timediff(Curl_now(),
- data->progress.t_startsingle);
+ timediff_t elapsed = Curl_timediff(Curl_now(),
+ data->progress.t_startsingle);
if(elapsed < 0)
elapsed = 0;
@@ -644,7 +651,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
curl_socket_t *socks)
{
int ret_val = 0;
- time_t milli;
+ timediff_t milli;
timediff_t ms;
struct Curl_easy *data = conn->data;
struct resdata *reslv = (struct resdata *)data->state.resolver;
@@ -668,7 +675,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
if(ms < 3)
milli = 0;
else if(ms <= 50)
- milli = (time_t)ms/3;
+ milli = ms/3;
else if(ms <= 250)
milli = 50;
else
@@ -686,10 +693,10 @@ int Curl_resolver_getsock(struct connectdata *conn,
/*
* Curl_getaddrinfo() - for platforms without getaddrinfo
*/
-Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
- const char *hostname,
- int port,
- int *waitp)
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
{
struct Curl_easy *data = conn->data;
struct resdata *reslv = (struct resdata *)data->state.resolver;
@@ -714,10 +721,10 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
/*
* Curl_resolver_getaddrinfo() - for getaddrinfo
*/
-Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
- const char *hostname,
- int port,
- int *waitp)
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
{
struct addrinfo hints;
int pf = PF_INET;
diff --git a/lib/asyn.h b/lib/asyn.h
index 081c3fef0..be2796cf0 100644
--- a/lib/asyn.h
+++ b/lib/asyn.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -153,10 +153,10 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
* Each resolver backend must of course make sure to return data in the
* correct format to comply with this.
*/
-Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
- const char *hostname,
- int port,
- int *waitp);
+struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp);
#ifndef CURLRES_ASYNCH
/* convert these functions if an asynch resolver isn't used */
diff --git a/lib/checksrc.pl b/lib/checksrc.pl
index b074f2744..97b8f9e1d 100755
--- a/lib/checksrc.pl
+++ b/lib/checksrc.pl
@@ -31,14 +31,14 @@ my $warnings = 0;
my $swarnings = 0;
my $errors = 0;
my $serrors = 0;
-my $suppressed; # whitelisted problems
+my $suppressed; # skipped problems
my $file;
my $dir=".";
my $wlist="";
my @alist;
my $windows_os = $^O eq 'MSWin32' || $^O eq 'cygwin' || $^O eq 'msys';
my $verbose;
-my %whitelist;
+my %skiplist;
my %ignore;
my %ignore_set;
@@ -81,14 +81,15 @@ my %warnings = (
'SIZEOFNOPAREN' => 'use of sizeof without parentheses',
'SNPRINTF' => 'use of snprintf',
'ONELINECONDITION' => 'conditional block on the same line as the if()',
+ 'TYPEDEFSTRUCT' => 'typedefed struct',
);
-sub readwhitelist {
- open(W, "<$dir/checksrc.whitelist") or return;
+sub readskiplist {
+ open(W, "<$dir/checksrc.skip") or return;
my @all=<W>;
for(@all) {
$windows_os ? $_ =~ s/\r?\n$// : chomp;
- $whitelist{$_}=1;
+ $skiplist{$_}=1;
}
close(W);
}
@@ -116,10 +117,19 @@ sub readlocalfile {
}
$warnings{$1} = $warnings_extended{$1};
}
+ elsif (/^\s*disable ([A-Z]+)$/) {
+ if(!defined($warnings{$1})) {
+ print STDERR "invalid warning specified in .checksrc: \"$1\"\n";
+ next;
+ }
+ # Accept-list
+ push @alist, $1;
+ }
else {
die "Invalid format in $dir/.checksrc on line $i\n";
}
}
+ close($rcfile);
}
sub checkwarn {
@@ -132,8 +142,8 @@ sub checkwarn {
# print STDERR "Dev! there's no description for $name!\n";
#}
- # checksrc.whitelist
- if($whitelist{$line}) {
+ # checksrc.skip
+ if($skiplist{$line}) {
$nowarn = 1;
}
# !checksrc! controlled
@@ -218,7 +228,7 @@ if(!$file) {
print " -A[rule] Accept this violation, can be used multiple times\n";
print " -D[DIR] Directory to prepend file names\n";
print " -h Show help output\n";
- print " -W[file] Whitelist the given file - ignore all its flaws\n";
+ print " -W[file] Skip the given file - ignore all its flaws\n";
print " -i<n> Indent spaces. Default: 2\n";
print " -m<n> Maximum line length. Default: 79\n";
print "\nDetects and warns for these problems:\n";
@@ -228,7 +238,7 @@ if(!$file) {
exit;
}
-readwhitelist();
+readskiplist();
readlocalfile();
do {
@@ -639,10 +649,10 @@ sub scanfile {
}
# check for 'char * name'
- if(($l =~ /(^.*(char|int|long|void|curl_slist|CURL|CURLM|CURLMsg|curl_httppost) *(\*+)) (\w+)/) && ($4 ne "const")) {
- checkwarn("ASTERISKNOSPACE",
+ if(($l =~ /(^.*(char|int|long|void|CURL|CURLM|CURLMsg|[cC]url_[A-Za-z_]+|struct [a-zA-Z_]+) *(\*+)) (\w+)/) && ($4 !~ /^(const|volatile)$/)) {
+ checkwarn("ASTERISKSPACE",
$line, length($1), $file, $ol,
- "no space after declarative asterisk");
+ "space after declarative asterisk");
}
# check for 'char*'
if(($l =~ /(^.*(char|int|long|void|curl_slist|CURL|CURLM|CURLMsg|curl_httppost|sockaddr_in|FILE)\*)/)) {
@@ -697,6 +707,13 @@ sub scanfile {
"no space after semicolon");
}
+ # typedef struct ... {
+ if($nostr =~ /^(.*)typedef struct.*{/) {
+ checkwarn("TYPEDEFSTRUCT",
+ $line, length($1)+1, $file, $ol,
+ "typedef'ed struct");
+ }
+
# 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
diff --git a/lib/config-win32.h b/lib/config-win32.h
index 516baca02..76ee6b1a7 100644
--- a/lib/config-win32.h
+++ b/lib/config-win32.h
@@ -724,6 +724,7 @@ Vista
/* Replicating logic present in afunix.h of newer Windows 10 SDK versions */
# define UNIX_PATH_MAX 108
# include <ws2tcpip.h>
+ /* !checksrc! disable TYPEDEFSTRUCT 1 */
typedef struct sockaddr_un {
ADDRESS_FAMILY sun_family;
char sun_path[UNIX_PATH_MAX];
diff --git a/lib/conncache.c b/lib/conncache.c
index e7ba564b4..304b955f5 100644
--- a/lib/conncache.c
+++ b/lib/conncache.c
@@ -49,53 +49,51 @@ static void conn_llist_dtor(void *user, void *element)
conn->bundle = NULL;
}
-static CURLcode bundle_create(struct Curl_easy *data,
- struct connectbundle **cb_ptr)
+static CURLcode bundle_create(struct connectbundle **bundlep)
{
- (void)data;
- DEBUGASSERT(*cb_ptr == NULL);
- *cb_ptr = malloc(sizeof(struct connectbundle));
- if(!*cb_ptr)
+ DEBUGASSERT(*bundlep == NULL);
+ *bundlep = malloc(sizeof(struct connectbundle));
+ if(!*bundlep)
return CURLE_OUT_OF_MEMORY;
- (*cb_ptr)->num_connections = 0;
- (*cb_ptr)->multiuse = BUNDLE_UNKNOWN;
+ (*bundlep)->num_connections = 0;
+ (*bundlep)->multiuse = BUNDLE_UNKNOWN;
- Curl_llist_init(&(*cb_ptr)->conn_list, (curl_llist_dtor) conn_llist_dtor);
+ Curl_llist_init(&(*bundlep)->conn_list, (curl_llist_dtor) conn_llist_dtor);
return CURLE_OK;
}
-static void bundle_destroy(struct connectbundle *cb_ptr)
+static void bundle_destroy(struct connectbundle *bundle)
{
- if(!cb_ptr)
+ if(!bundle)
return;
- Curl_llist_destroy(&cb_ptr->conn_list, NULL);
+ Curl_llist_destroy(&bundle->conn_list, NULL);
- free(cb_ptr);
+ free(bundle);
}
/* Add a connection to a bundle */
-static void bundle_add_conn(struct connectbundle *cb_ptr,
+static void bundle_add_conn(struct connectbundle *bundle,
struct connectdata *conn)
{
- Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn,
+ Curl_llist_insert_next(&bundle->conn_list, bundle->conn_list.tail, conn,
&conn->bundle_node);
- conn->bundle = cb_ptr;
- cb_ptr->num_connections++;
+ conn->bundle = bundle;
+ bundle->num_connections++;
}
/* Remove a connection from a bundle */
-static int bundle_remove_conn(struct connectbundle *cb_ptr,
+static int bundle_remove_conn(struct connectbundle *bundle,
struct connectdata *conn)
{
struct curl_llist_element *curr;
- curr = cb_ptr->conn_list.head;
+ curr = bundle->conn_list.head;
while(curr) {
if(curr->ptr == conn) {
- Curl_llist_remove(&cb_ptr->conn_list, curr, NULL);
- cb_ptr->num_connections--;
+ Curl_llist_remove(&bundle->conn_list, curr, NULL);
+ bundle->num_connections--;
conn->bundle = NULL;
return 1; /* we removed a handle */
}
@@ -145,12 +143,15 @@ static void hashkey(struct connectdata *conn, char *buf,
const char *hostname;
long port = conn->remote_port;
+#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
hostname = conn->http_proxy.host.name;
port = conn->port;
}
- else if(conn->bits.conn_to_host)
- hostname = conn->conn_to_host.name;
+ else
+#endif
+ if(conn->bits.conn_to_host)
+ hostname = conn->conn_to_host.name;
else
hostname = conn->host.name;
@@ -162,20 +163,15 @@ static void hashkey(struct connectdata *conn, char *buf,
msnprintf(buf, len, "%ld%s", port, hostname);
}
-void Curl_conncache_unlock(struct Curl_easy *data)
-{
- CONN_UNLOCK(data);
-}
-
/* Returns number of connections currently held in the connection cache.
Locks/unlocks the cache itself!
*/
size_t Curl_conncache_size(struct Curl_easy *data)
{
size_t num;
- CONN_LOCK(data);
+ CONNCACHE_LOCK(data);
num = data->state.conn_cache->num_conn;
- CONN_UNLOCK(data);
+ CONNCACHE_UNLOCK(data);
return num;
}
@@ -188,7 +184,7 @@ struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
const char **hostp)
{
struct connectbundle *bundle = NULL;
- CONN_LOCK(conn->data);
+ CONNCACHE_LOCK(conn->data);
if(connc) {
char key[HASHKEY_SIZE];
hashkey(conn, key, sizeof(key), hostp);
@@ -235,8 +231,7 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- struct connectbundle *bundle;
- struct connectbundle *new_bundle = NULL;
+ struct connectbundle *bundle = NULL;
struct Curl_easy *data = conn->data;
/* *find_bundle() locks the connection cache */
@@ -245,20 +240,19 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
int rc;
char key[HASHKEY_SIZE];
- result = bundle_create(data, &new_bundle);
+ result = bundle_create(&bundle);
if(result) {
goto unlock;
}
hashkey(conn, key, sizeof(key), NULL);
- rc = conncache_add_bundle(data->state.conn_cache, key, new_bundle);
+ rc = conncache_add_bundle(data->state.conn_cache, key, bundle);
if(!rc) {
- bundle_destroy(new_bundle);
+ bundle_destroy(bundle);
result = CURLE_OUT_OF_MEMORY;
goto unlock;
}
- bundle = new_bundle;
}
bundle_add_conn(bundle, conn);
@@ -270,15 +264,17 @@ CURLcode Curl_conncache_add_conn(struct conncache *connc,
conn->connection_id, connc->num_conn));
unlock:
- CONN_UNLOCK(data);
+ CONNCACHE_UNLOCK(data);
return result;
}
/*
- * Removes the connectdata object from the connection cache *and* clears the
- * ->data pointer association. Pass TRUE/FALSE in the 'lock' argument
- * depending on if the parent function already holds the lock or not.
+ * Removes the connectdata object from the connection cache, but does *not*
+ * clear the conn->data association. The transfer still owns this connection.
+ *
+ * Pass TRUE/FALSE in the 'lock' argument depending on if the parent function
+ * already holds the lock or not.
*/
void Curl_conncache_remove_conn(struct Curl_easy *data,
struct connectdata *conn, bool lock)
@@ -290,7 +286,7 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
due to a failed connection attempt, before being added to a bundle */
if(bundle) {
if(lock) {
- CONN_LOCK(data);
+ CONNCACHE_LOCK(data);
}
bundle_remove_conn(bundle, conn);
if(bundle->num_connections == 0)
@@ -301,9 +297,8 @@ void Curl_conncache_remove_conn(struct Curl_easy *data,
DEBUGF(infof(data, "The cache now contains %zu members\n",
connc->num_conn));
}
- conn->data = NULL; /* clear the association */
if(lock) {
- CONN_UNLOCK(data);
+ CONNCACHE_UNLOCK(data);
}
}
}
@@ -332,7 +327,7 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
if(!connc)
return FALSE;
- CONN_LOCK(data);
+ CONNCACHE_LOCK(data);
Curl_hash_start_iterate(&connc->hash, &iter);
he = Curl_hash_next_element(&iter);
@@ -350,12 +345,12 @@ bool Curl_conncache_foreach(struct Curl_easy *data,
curr = curr->next;
if(1 == func(conn, param)) {
- CONN_UNLOCK(data);
+ CONNCACHE_UNLOCK(data);
return TRUE;
}
}
}
- CONN_UNLOCK(data);
+ CONNCACHE_UNLOCK(data);
return FALSE;
}
@@ -494,7 +489,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
now = Curl_now();
- CONN_LOCK(data);
+ CONNCACHE_LOCK(data);
Curl_hash_start_iterate(&connc->hash, &iter);
he = Curl_hash_next_element(&iter);
@@ -531,7 +526,7 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
connc->num_conn));
conn_candidate->data = data; /* associate! */
}
- CONN_UNLOCK(data);
+ CONNCACHE_UNLOCK(data);
return conn_candidate;
}
@@ -539,6 +534,11 @@ Curl_conncache_extract_oldest(struct Curl_easy *data)
void Curl_conncache_close_all_connections(struct conncache *connc)
{
struct connectdata *conn;
+ char buffer[READBUFFER_MIN + 1];
+ if(!connc->closure_handle)
+ return;
+ connc->closure_handle->state.buffer = buffer;
+ connc->closure_handle->set.buffer_size = READBUFFER_MIN;
conn = conncache_find_first_connection(connc);
while(conn) {
@@ -548,12 +548,14 @@ void Curl_conncache_close_all_connections(struct conncache *connc)
sigpipe_ignore(conn->data, &pipe_st);
/* This will remove the connection from the cache */
connclose(conn, "kill all");
+ Curl_conncache_remove_conn(conn->data, conn, TRUE);
(void)Curl_disconnect(connc->closure_handle, conn, FALSE);
sigpipe_restore(&pipe_st);
conn = conncache_find_first_connection(connc);
}
+ connc->closure_handle->state.buffer = NULL;
if(connc->closure_handle) {
SIGPIPE_VARIABLE(pipe_st);
sigpipe_ignore(connc->closure_handle, &pipe_st);
diff --git a/lib/conncache.h b/lib/conncache.h
index e3e4c9c28..3dda21cdc 100644
--- a/lib/conncache.h
+++ b/lib/conncache.h
@@ -45,21 +45,21 @@ struct conncache {
#ifdef CURLDEBUG
/* the debug versions of these macros make extra certain that the lock is
never doubly locked or unlocked */
-#define CONN_LOCK(x) if((x)->share) { \
+#define CONNCACHE_LOCK(x) if((x)->share) { \
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE); \
DEBUGASSERT(!(x)->state.conncache_lock); \
(x)->state.conncache_lock = TRUE; \
}
-#define CONN_UNLOCK(x) if((x)->share) { \
+#define CONNCACHE_UNLOCK(x) if((x)->share) { \
DEBUGASSERT((x)->state.conncache_lock); \
(x)->state.conncache_lock = FALSE; \
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT); \
}
#else
-#define CONN_LOCK(x) if((x)->share) \
+#define CONNCACHE_LOCK(x) if((x)->share) \
Curl_share_lock((x), CURL_LOCK_DATA_CONNECT, CURL_LOCK_ACCESS_SINGLE)
-#define CONN_UNLOCK(x) if((x)->share) \
+#define CONNCACHE_UNLOCK(x) if((x)->share) \
Curl_share_unlock((x), CURL_LOCK_DATA_CONNECT)
#endif
@@ -77,7 +77,6 @@ void Curl_conncache_destroy(struct conncache *connc);
struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn,
struct conncache *connc,
const char **hostp);
-void Curl_conncache_unlock(struct Curl_easy *data);
/* returns number of connections currently held in the connection cache */
size_t Curl_conncache_size(struct Curl_easy *data);
diff --git a/lib/connect.c b/lib/connect.c
index 421f90415..29293f087 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -166,7 +166,7 @@ tcpkeepalive(struct Curl_easy *data,
static CURLcode
singleipconnect(struct connectdata *conn,
- const Curl_addrinfo *ai, /* start connecting to this */
+ const struct Curl_addrinfo *ai, /* start connecting to this */
int tempindex); /* 0 or 1 among the temp ones */
/*
@@ -558,11 +558,11 @@ static bool verifyconnect(curl_socket_t sockfd, int *error)
/* update tempaddr[tempindex] (to the next entry), makes sure to stick
to the correct family */
-static Curl_addrinfo *ainext(struct connectdata *conn,
- int tempindex,
- bool next) /* use current or next entry */
+static struct Curl_addrinfo *ainext(struct connectdata *conn,
+ int tempindex,
+ bool next) /* use next entry? */
{
- Curl_addrinfo *ai = conn->tempaddr[tempindex];
+ struct Curl_addrinfo *ai = conn->tempaddr[tempindex];
if(ai && next)
ai = ai->ai_next;
while(ai && (ai->ai_family != conn->tempfamily[tempindex]))
@@ -571,7 +571,7 @@ static Curl_addrinfo *ainext(struct connectdata *conn,
return ai;
}
-/* Used within the multi interface. Try next IP address, return TRUE if no
+/* Used within the multi interface. Try next IP address, returns error if no
more address exists or error */
static CURLcode trynextip(struct connectdata *conn,
int sockindex,
@@ -587,7 +587,7 @@ static CURLcode trynextip(struct connectdata *conn,
conn->tempsock[tempindex] = CURL_SOCKET_BAD;
if(sockindex == FIRSTSOCKET) {
- Curl_addrinfo *ai = conn->tempaddr[tempindex];
+ struct Curl_addrinfo *ai = conn->tempaddr[tempindex];
while(ai) {
if(ai) {
@@ -747,8 +747,8 @@ static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
{
CURLcode result = CURLE_OK;
- if(conn->bits.socksproxy) {
#ifndef CURL_DISABLE_PROXY
+ if(conn->bits.socksproxy) {
/* for the secondary socket (FTP), use the "connect to host"
* but ignore the "connect to port" (use the secondary port)
*/
@@ -781,11 +781,12 @@ static CURLcode connect_SOCKS(struct connectdata *conn, int sockindex,
failf(conn->data, "unknown proxytype option given");
result = CURLE_COULDNT_CONNECT;
} /* switch proxytype */
-#else
- (void)sockindex;
-#endif /* CURL_DISABLE_PROXY */
}
else
+#else
+ (void)conn;
+ (void)sockindex;
+#endif /* CURL_DISABLE_PROXY */
*done = TRUE; /* no SOCKS proxy, so consider us connected */
return result;
@@ -822,8 +823,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
timediff_t allow;
int error = 0;
struct curltime now;
- int rc;
- int i;
+ int rc = 0;
+ unsigned int i;
DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
@@ -858,49 +859,50 @@ CURLcode Curl_is_connected(struct connectdata *conn,
const int other = i ^ 1;
if(conn->tempsock[i] == CURL_SOCKET_BAD)
continue;
-
+ error = 0;
#ifdef ENABLE_QUIC
if(conn->transport == TRNSPRT_QUIC) {
result = Curl_quic_is_connected(conn, i, connected);
- if(result) {
- error = SOCKERRNO;
- goto error;
- }
- if(*connected) {
+ if(!result && *connected) {
/* use this socket from now on */
conn->sock[sockindex] = conn->tempsock[i];
conn->ip_addr = conn->tempaddr[i];
conn->tempsock[i] = CURL_SOCKET_BAD;
post_SOCKS(conn, sockindex, connected);
connkeep(conn, "HTTP/3 default");
+ return CURLE_OK;
}
- return result;
+ if(result)
+ error = SOCKERRNO;
}
+ else
#endif
-
+ {
#ifdef mpeix
- /* Call this function once now, and ignore the results. We do this to
- "clear" the error state on the socket so that we can later read it
- reliably. This is reported necessary on the MPE/iX operating system. */
- (void)verifyconnect(conn->tempsock[i], NULL);
+ /* Call this function once now, and ignore the results. We do this to
+ "clear" the error state on the socket so that we can later read it
+ reliably. This is reported necessary on the MPE/iX operating
+ system. */
+ (void)verifyconnect(conn->tempsock[i], NULL);
#endif
- /* check socket for connect */
- rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
+ /* check socket for connect */
+ rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
+ }
if(rc == 0) { /* no connection yet */
- error = 0;
- if(Curl_timediff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
+ if(Curl_timediff(now, conn->connecttime) >=
+ conn->timeoutms_per_addr[i]) {
infof(data, "After %" CURL_FORMAT_TIMEDIFF_T
- "ms connect time, move on!\n", conn->timeoutms_per_addr);
+ "ms connect time, move on!\n", conn->timeoutms_per_addr[i]);
error = ETIMEDOUT;
}
/* should we try another protocol family? */
- if(i == 0 && !conn->parallel_connect &&
+ if(i == 0 && !conn->bits.parallel_connect &&
(Curl_timediff(now, conn->connecttime) >=
data->set.happy_eyeballs_timeout)) {
- conn->parallel_connect = TRUE; /* starting now */
+ conn->bits.parallel_connect = TRUE; /* starting now */
trynextip(conn, sockindex, 1);
}
}
@@ -937,9 +939,6 @@ CURLcode Curl_is_connected(struct connectdata *conn,
else if(rc & CURL_CSELECT_ERR)
(void)verifyconnect(conn->tempsock[i], &error);
-#ifdef ENABLE_QUIC
- error:
-#endif
/*
* The connection failed here, we should attempt to connect to the "next
* address" for the given host. But first remember the latest error.
@@ -952,13 +951,14 @@ CURLcode Curl_is_connected(struct connectdata *conn,
#ifndef CURL_DISABLE_VERBOSE_STRINGS
char ipaddress[MAX_IPADR_LEN];
char buffer[STRERROR_LEN];
- Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
-#endif
+ Curl_printable_address(conn->tempaddr[i], ipaddress,
+ sizeof(ipaddress));
infof(data, "connect to %s port %ld failed: %s\n",
ipaddress, conn->port,
Curl_strerror(error, buffer, sizeof(buffer)));
+#endif
- conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
+ conn->timeoutms_per_addr[i] = conn->tempaddr[i]->ai_next == NULL ?
allow : allow / 2;
ainext(conn, i, TRUE);
status = trynextip(conn, sockindex, i);
@@ -970,25 +970,28 @@ CURLcode Curl_is_connected(struct connectdata *conn,
}
}
- if(result) {
+ if(result &&
+ (conn->tempsock[0] == CURL_SOCKET_BAD) &&
+ (conn->tempsock[1] == CURL_SOCKET_BAD)) {
/* no more addresses to try */
const char *hostname;
char buffer[STRERROR_LEN];
- /* if the first address family runs out of addresses to try before
- the happy eyeball timeout, go ahead and try the next family now */
- {
- result = trynextip(conn, sockindex, 1);
- if(!result)
- return result;
- }
+ /* if the first address family runs out of addresses to try before the
+ happy eyeball timeout, go ahead and try the next family now */
+ result = trynextip(conn, sockindex, 1);
+ if(!result)
+ return result;
+#ifndef CURL_DISABLE_PROXY
if(conn->bits.socksproxy)
hostname = conn->socks_proxy.host.name;
else if(conn->bits.httpproxy)
hostname = conn->http_proxy.host.name;
- else if(conn->bits.conn_to_host)
- hostname = conn->conn_to_host.name;
+ else
+#endif
+ if(conn->bits.conn_to_host)
+ hostname = conn->conn_to_host.name;
else
hostname = conn->host.name;
@@ -996,6 +999,9 @@ CURLcode Curl_is_connected(struct connectdata *conn,
hostname, conn->port,
Curl_strerror(error, buffer, sizeof(buffer)));
+ Curl_quic_disconnect(conn, 0);
+ Curl_quic_disconnect(conn, 1);
+
#ifdef WSAETIMEDOUT
if(WSAETIMEDOUT == data->state.os_errno)
result = CURLE_OPERATION_TIMEDOUT;
@@ -1004,6 +1010,8 @@ CURLcode Curl_is_connected(struct connectdata *conn,
result = CURLE_OPERATION_TIMEDOUT;
#endif
}
+ else
+ result = CURLE_OK; /* still trying */
return result;
}
@@ -1105,7 +1113,7 @@ void Curl_sndbufset(curl_socket_t sockfd)
* having connected.
*/
static CURLcode singleipconnect(struct connectdata *conn,
- const Curl_addrinfo *ai,
+ const struct Curl_addrinfo *ai,
int tempindex)
{
struct Curl_sockaddr_ex addr;
@@ -1195,8 +1203,10 @@ static CURLcode singleipconnect(struct connectdata *conn,
(void)curlx_nonblock(sockfd, TRUE);
conn->connecttime = Curl_now();
- if(conn->num_addr > 1)
- Curl_expire(data, conn->timeoutms_per_addr, EXPIRE_DNS_PER_NAME);
+ if(conn->num_addr > 1) {
+ Curl_expire(data, conn->timeoutms_per_addr[0], EXPIRE_DNS_PER_NAME);
+ Curl_expire(data, conn->timeoutms_per_addr[1], EXPIRE_DNS_PER_NAME2);
+ }
/* Connect TCP and QUIC sockets */
if(!isconnected && (conn->transport != TRNSPRT_UDP)) {
@@ -1319,8 +1329,10 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
conn->tempsock[0] = conn->tempsock[1] = CURL_SOCKET_BAD;
/* Max time for the next connection attempt */
- conn->timeoutms_per_addr =
+ conn->timeoutms_per_addr[0] =
conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
+ conn->timeoutms_per_addr[1] =
+ conn->tempaddr[1]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
conn->tempfamily[0] = conn->tempaddr[0]?
conn->tempaddr[0]->ai_family:0;
@@ -1443,11 +1455,11 @@ int Curl_closesocket(struct connectdata *conn,
curl_socket_t sock)
{
if(conn && conn->fclosesocket) {
- if((sock == conn->sock[SECONDARYSOCKET]) && conn->sock_accepted)
+ if((sock == conn->sock[SECONDARYSOCKET]) && conn->bits.sock_accepted)
/* if this socket matches the second socket, and that was created with
accept, then we MUST NOT call the callback but clear the accepted
status */
- conn->sock_accepted = FALSE;
+ conn->bits.sock_accepted = FALSE;
else {
int rc;
Curl_multi_closed(conn->data, sock);
@@ -1477,7 +1489,7 @@ int Curl_closesocket(struct connectdata *conn,
*
*/
CURLcode Curl_socket(struct connectdata *conn,
- const Curl_addrinfo *ai,
+ const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd)
{
@@ -1559,6 +1571,7 @@ void Curl_conncontrol(struct connectdata *conn,
/* close if a connection, or a stream that isn't multiplexed */
bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
+ DEBUGASSERT(conn);
if((ctrl == CONNCTRL_STREAM) &&
(conn->handler->flags & PROTOPT_STREAM))
DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
@@ -1574,6 +1587,7 @@ void Curl_conncontrol(struct connectdata *conn,
bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
{
int readable;
+ DEBUGASSERT(conn);
if(Curl_ssl_data_pending(conn, sockindex) ||
Curl_recv_has_postponed_data(conn, sockindex))
diff --git a/lib/connect.h b/lib/connect.h
index b23085a98..6fd9ea878 100644
--- a/lib/connect.h
+++ b/lib/connect.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -105,7 +105,7 @@ struct Curl_sockaddr_ex {
*
*/
CURLcode Curl_socket(struct connectdata *conn,
- const Curl_addrinfo *ai,
+ const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd);
diff --git a/lib/content_encoding.c b/lib/content_encoding.c
index 5074b246e..19a55b7cd 100644
--- a/lib/content_encoding.c
+++ b/lib/content_encoding.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -81,11 +81,11 @@ typedef enum {
} zlibInitState;
/* Writer parameters. */
-typedef struct {
+struct zlib_params {
zlibInitState zlib_init; /* zlib init state */
uInt trailerlen; /* Remaining trailer byte count. */
z_stream z; /* State structure for zlib. */
-} zlib_params;
+};
static voidpf
@@ -133,7 +133,8 @@ exit_zlib(struct connectdata *conn,
return result;
}
-static CURLcode process_trailer(struct connectdata *conn, zlib_params *zp)
+static CURLcode process_trailer(struct connectdata *conn,
+ struct zlib_params *zp)
{
z_stream *z = &zp->z;
CURLcode result = CURLE_OK;
@@ -157,9 +158,10 @@ static CURLcode process_trailer(struct connectdata *conn, zlib_params *zp)
}
static CURLcode inflate_stream(struct connectdata *conn,
- contenc_writer *writer, zlibInitState started)
+ struct contenc_writer *writer,
+ zlibInitState started)
{
- zlib_params *zp = (zlib_params *) &writer->params;
+ struct zlib_params *zp = (struct zlib_params *) &writer->params;
z_stream *z = &zp->z; /* zlib state structure */
uInt nread = z->avail_in;
Bytef *orig_in = z->next_in;
@@ -259,9 +261,9 @@ static CURLcode inflate_stream(struct connectdata *conn,
/* Deflate handler. */
static CURLcode deflate_init_writer(struct connectdata *conn,
- contenc_writer *writer)
+ struct contenc_writer *writer)
{
- zlib_params *zp = (zlib_params *) &writer->params;
+ struct zlib_params *zp = (struct zlib_params *) &writer->params;
z_stream *z = &zp->z; /* zlib state structure */
if(!writer->downstream)
@@ -278,10 +280,10 @@ static CURLcode deflate_init_writer(struct connectdata *conn,
}
static CURLcode deflate_unencode_write(struct connectdata *conn,
- contenc_writer *writer,
+ struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- zlib_params *zp = (zlib_params *) &writer->params;
+ struct zlib_params *zp = (struct zlib_params *) &writer->params;
z_stream *z = &zp->z; /* zlib state structure */
/* Set the compressed input when this function is called */
@@ -296,29 +298,29 @@ static CURLcode deflate_unencode_write(struct connectdata *conn,
}
static void deflate_close_writer(struct connectdata *conn,
- contenc_writer *writer)
+ struct contenc_writer *writer)
{
- zlib_params *zp = (zlib_params *) &writer->params;
+ struct zlib_params *zp = (struct zlib_params *) &writer->params;
z_stream *z = &zp->z; /* zlib state structure */
exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
}
-static const content_encoding deflate_encoding = {
+static const struct content_encoding deflate_encoding = {
"deflate",
NULL,
deflate_init_writer,
deflate_unencode_write,
deflate_close_writer,
- sizeof(zlib_params)
+ sizeof(struct zlib_params)
};
/* Gzip handler. */
static CURLcode gzip_init_writer(struct connectdata *conn,
- contenc_writer *writer)
+ struct contenc_writer *writer)
{
- zlib_params *zp = (zlib_params *) &writer->params;
+ struct zlib_params *zp = (struct zlib_params *) &writer->params;
z_stream *z = &zp->z; /* zlib state structure */
if(!writer->downstream)
@@ -432,10 +434,10 @@ static enum {
#endif
static CURLcode gzip_unencode_write(struct connectdata *conn,
- contenc_writer *writer,
+ struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- zlib_params *zp = (zlib_params *) &writer->params;
+ struct zlib_params *zp = (struct zlib_params *) &writer->params;
z_stream *z = &zp->z; /* zlib state structure */
if(zp->zlib_init == ZLIB_INIT_GZIP) {
@@ -560,33 +562,31 @@ static CURLcode gzip_unencode_write(struct connectdata *conn,
}
static void gzip_close_writer(struct connectdata *conn,
- contenc_writer *writer)
+ struct contenc_writer *writer)
{
- zlib_params *zp = (zlib_params *) &writer->params;
+ struct zlib_params *zp = (struct zlib_params *) &writer->params;
z_stream *z = &zp->z; /* zlib state structure */
exit_zlib(conn, z, &zp->zlib_init, CURLE_OK);
}
-static const content_encoding gzip_encoding = {
+static const struct content_encoding gzip_encoding = {
"gzip",
"x-gzip",
gzip_init_writer,
gzip_unencode_write,
gzip_close_writer,
- sizeof(zlib_params)
+ sizeof(struct zlib_params)
};
#endif /* HAVE_LIBZ */
#ifdef HAVE_BROTLI
-
/* Writer parameters. */
-typedef struct {
+struct brotli_params {
BrotliDecoderState *br; /* State structure for brotli. */
-} brotli_params;
-
+};
static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
{
@@ -627,10 +627,9 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be)
}
static CURLcode brotli_init_writer(struct connectdata *conn,
- contenc_writer *writer)
+ struct contenc_writer *writer)
{
- brotli_params *bp = (brotli_params *) &writer->params;
-
+ struct brotli_params *bp = (struct brotli_params *) &writer->params;
(void) conn;
if(!writer->downstream)
@@ -641,10 +640,10 @@ static CURLcode brotli_init_writer(struct connectdata *conn,
}
static CURLcode brotli_unencode_write(struct connectdata *conn,
- contenc_writer *writer,
+ struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
- brotli_params *bp = (brotli_params *) &writer->params;
+ struct brotli_params *bp = (struct brotli_params *) &writer->params;
const uint8_t *src = (const uint8_t *) buf;
char *decomp;
uint8_t *dst;
@@ -689,10 +688,9 @@ static CURLcode brotli_unencode_write(struct connectdata *conn,
}
static void brotli_close_writer(struct connectdata *conn,
- contenc_writer *writer)
+ struct contenc_writer *writer)
{
- brotli_params *bp = (brotli_params *) &writer->params;
-
+ struct brotli_params *bp = (struct brotli_params *) &writer->params;
(void) conn;
if(bp->br) {
@@ -701,40 +699,40 @@ static void brotli_close_writer(struct connectdata *conn,
}
}
-static const content_encoding brotli_encoding = {
+static const struct content_encoding brotli_encoding = {
"br",
NULL,
brotli_init_writer,
brotli_unencode_write,
brotli_close_writer,
- sizeof(brotli_params)
+ sizeof(struct brotli_params)
};
#endif
/* Identity handler. */
static CURLcode identity_init_writer(struct connectdata *conn,
- contenc_writer *writer)
+ struct contenc_writer *writer)
{
(void) conn;
return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
}
static CURLcode identity_unencode_write(struct connectdata *conn,
- contenc_writer *writer,
+ struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
return Curl_unencode_write(conn, writer->downstream, buf, nbytes);
}
static void identity_close_writer(struct connectdata *conn,
- contenc_writer *writer)
+ struct contenc_writer *writer)
{
(void) conn;
(void) writer;
}
-static const content_encoding identity_encoding = {
+static const struct content_encoding identity_encoding = {
"identity",
"none",
identity_init_writer,
@@ -745,7 +743,7 @@ static const content_encoding identity_encoding = {
/* supported content encodings table. */
-static const content_encoding * const encodings[] = {
+static const struct content_encoding * const encodings[] = {
&identity_encoding,
#ifdef HAVE_LIBZ
&deflate_encoding,
@@ -762,8 +760,8 @@ static const content_encoding * const encodings[] = {
char *Curl_all_content_encodings(void)
{
size_t len = 0;
- const content_encoding * const *cep;
- const content_encoding *ce;
+ const struct content_encoding * const *cep;
+ const struct content_encoding *ce;
char *ace;
for(cep = encodings; *cep; cep++) {
@@ -796,14 +794,14 @@ char *Curl_all_content_encodings(void)
/* Real client writer: no downstream. */
static CURLcode client_init_writer(struct connectdata *conn,
- contenc_writer *writer)
+ struct contenc_writer *writer)
{
(void) conn;
return writer->downstream? CURLE_WRITE_ERROR: CURLE_OK;
}
static CURLcode client_unencode_write(struct connectdata *conn,
- contenc_writer *writer,
+ struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
struct Curl_easy *data = conn->data;
@@ -818,13 +816,13 @@ static CURLcode client_unencode_write(struct connectdata *conn,
}
static void client_close_writer(struct connectdata *conn,
- contenc_writer *writer)
+ struct contenc_writer *writer)
{
(void) conn;
(void) writer;
}
-static const content_encoding client_encoding = {
+static const struct content_encoding client_encoding = {
NULL,
NULL,
client_init_writer,
@@ -836,14 +834,14 @@ static const content_encoding client_encoding = {
/* Deferred error dummy writer. */
static CURLcode error_init_writer(struct connectdata *conn,
- contenc_writer *writer)
+ struct contenc_writer *writer)
{
(void) conn;
return writer->downstream? CURLE_OK: CURLE_WRITE_ERROR;
}
static CURLcode error_unencode_write(struct connectdata *conn,
- contenc_writer *writer,
+ struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
char *all = Curl_all_content_encodings();
@@ -861,13 +859,13 @@ static CURLcode error_unencode_write(struct connectdata *conn,
}
static void error_close_writer(struct connectdata *conn,
- contenc_writer *writer)
+ struct contenc_writer *writer)
{
(void) conn;
(void) writer;
}
-static const content_encoding error_encoding = {
+static const struct content_encoding error_encoding = {
NULL,
NULL,
error_init_writer,
@@ -877,12 +875,13 @@ static const content_encoding error_encoding = {
};
/* Create an unencoding writer stage using the given handler. */
-static contenc_writer *new_unencoding_writer(struct connectdata *conn,
- const content_encoding *handler,
- contenc_writer *downstream)
+static struct contenc_writer *
+new_unencoding_writer(struct connectdata *conn,
+ const struct content_encoding *handler,
+ struct contenc_writer *downstream)
{
- size_t sz = offsetof(contenc_writer, params) + handler->paramsize;
- contenc_writer *writer = (contenc_writer *) calloc(1, sz);
+ size_t sz = offsetof(struct contenc_writer, params) + handler->paramsize;
+ struct contenc_writer *writer = (struct contenc_writer *)calloc(1, sz);
if(writer) {
writer->handler = handler;
@@ -897,7 +896,8 @@ static contenc_writer *new_unencoding_writer(struct connectdata *conn,
}
/* Write data using an unencoding writer stack. */
-CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer,
+CURLcode Curl_unencode_write(struct connectdata *conn,
+ struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
if(!nbytes)
@@ -910,7 +910,7 @@ void Curl_unencode_cleanup(struct connectdata *conn)
{
struct Curl_easy *data = conn->data;
struct SingleRequest *k = &data->req;
- contenc_writer *writer = k->writer_stack;
+ struct contenc_writer *writer = k->writer_stack;
while(writer) {
k->writer_stack = writer->downstream;
@@ -921,12 +921,13 @@ void Curl_unencode_cleanup(struct connectdata *conn)
}
/* Find the content encoding by name. */
-static const content_encoding *find_encoding(const char *name, size_t len)
+static const struct content_encoding *find_encoding(const char *name,
+ size_t len)
{
- const content_encoding * const *cep;
+ const struct content_encoding * const *cep;
for(cep = encodings; *cep; cep++) {
- const content_encoding *ce = *cep;
+ const struct content_encoding *ce = *cep;
if((strncasecompare(name, ce->name, len) && !ce->name[len]) ||
(ce->alias && strncasecompare(name, ce->alias, len) && !ce->alias[len]))
return ce;
@@ -962,8 +963,8 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
Curl_httpchunk_init(conn); /* init our chunky engine. */
}
else if(namelen) {
- const content_encoding *encoding = find_encoding(name, namelen);
- contenc_writer *writer;
+ const struct content_encoding *encoding = find_encoding(name, namelen);
+ struct contenc_writer *writer;
if(!k->writer_stack) {
k->writer_stack = new_unencoding_writer(conn, &client_encoding, NULL);
@@ -997,7 +998,8 @@ CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
return CURLE_NOT_BUILT_IN;
}
-CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer,
+CURLcode Curl_unencode_write(struct connectdata *conn,
+ struct contenc_writer *writer,
const char *buf, size_t nbytes)
{
(void) conn;
diff --git a/lib/content_encoding.h b/lib/content_encoding.h
index 4cd52be62..bdd3f1c8c 100644
--- a/lib/content_encoding.h
+++ b/lib/content_encoding.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,31 +23,31 @@
***************************************************************************/
#include "curl_setup.h"
-/* Decoding writer. */
-typedef struct contenc_writer_s contenc_writer;
-typedef struct content_encoding_s content_encoding;
-
-struct contenc_writer_s {
- const content_encoding *handler; /* Encoding handler. */
- contenc_writer *downstream; /* Downstream writer. */
+struct contenc_writer {
+ const struct content_encoding *handler; /* Encoding handler. */
+ struct contenc_writer *downstream; /* Downstream writer. */
void *params; /* Encoding-specific storage (variable length). */
};
/* Content encoding writer. */
-struct content_encoding_s {
+struct content_encoding {
const char *name; /* Encoding name. */
const char *alias; /* Encoding name alias. */
- CURLcode (*init_writer)(struct connectdata *conn, contenc_writer *writer);
- CURLcode (*unencode_write)(struct connectdata *conn, contenc_writer *writer,
+ CURLcode (*init_writer)(struct connectdata *conn,
+ struct contenc_writer *writer);
+ CURLcode (*unencode_write)(struct connectdata *conn,
+ struct contenc_writer *writer,
const char *buf, size_t nbytes);
- void (*close_writer)(struct connectdata *conn, contenc_writer *writer);
+ void (*close_writer)(struct connectdata *conn,
+ struct contenc_writer *writer);
size_t paramsize;
};
CURLcode Curl_build_unencoding_stack(struct connectdata *conn,
const char *enclist, int maybechunked);
-CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer,
+CURLcode Curl_unencode_write(struct connectdata *conn,
+ struct contenc_writer *writer,
const char *buf, size_t nbytes);
void Curl_unencode_cleanup(struct connectdata *conn);
char *Curl_all_content_encodings(void);
diff --git a/lib/cookie.c b/lib/cookie.c
index 68054e1c4..cb7d94b10 100644
--- a/lib/cookie.c
+++ b/lib/cookie.c
@@ -755,7 +755,7 @@ Curl_cookie_add(struct Curl_easy *data,
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; /* null-terminate */
co->spath = sanitize_cookie_path(co->path);
if(!co->spath)
badcookie = TRUE; /* out of memory bad */
diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c
index a9daeeda6..038987fc8 100644
--- a/lib/curl_addrinfo.c
+++ b/lib/curl_addrinfo.c
@@ -78,16 +78,13 @@
#endif
void
-Curl_freeaddrinfo(Curl_addrinfo *cahead)
+Curl_freeaddrinfo(struct Curl_addrinfo *cahead)
{
- Curl_addrinfo *vqualifier canext;
- Curl_addrinfo *ca;
+ struct Curl_addrinfo *vqualifier canext;
+ struct Curl_addrinfo *ca;
- for(ca = cahead; ca != NULL; ca = canext) {
- free(ca->ai_addr);
- free(ca->ai_canonname);
+ for(ca = cahead; ca; ca = canext) {
canext = ca->ai_next;
-
free(ca);
}
}
@@ -112,13 +109,13 @@ int
Curl_getaddrinfo_ex(const char *nodename,
const char *servname,
const struct addrinfo *hints,
- Curl_addrinfo **result)
+ struct Curl_addrinfo **result)
{
const struct addrinfo *ai;
struct addrinfo *aihead;
- Curl_addrinfo *cafirst = NULL;
- Curl_addrinfo *calast = NULL;
- Curl_addrinfo *ca;
+ struct Curl_addrinfo *cafirst = NULL;
+ struct Curl_addrinfo *calast = NULL;
+ struct Curl_addrinfo *ca;
size_t ss_size;
int error;
@@ -131,7 +128,7 @@ Curl_getaddrinfo_ex(const char *nodename,
/* traverse the addrinfo list */
for(ai = aihead; ai != NULL; ai = ai->ai_next) {
-
+ size_t namelen = ai->ai_canonname ? strlen(ai->ai_canonname) + 1 : 0;
/* ignore elements with unsupported address family, */
/* settle family-specific sockaddr structure size. */
if(ai->ai_family == AF_INET)
@@ -151,7 +148,7 @@ Curl_getaddrinfo_ex(const char *nodename,
if((size_t)ai->ai_addrlen < ss_size)
continue;
- ca = malloc(sizeof(Curl_addrinfo));
+ ca = malloc(sizeof(struct Curl_addrinfo) + ss_size + namelen);
if(!ca) {
error = EAI_MEMORY;
break;
@@ -169,22 +166,12 @@ Curl_getaddrinfo_ex(const char *nodename,
ca->ai_canonname = NULL;
ca->ai_next = NULL;
- ca->ai_addr = malloc(ss_size);
- if(!ca->ai_addr) {
- error = EAI_MEMORY;
- free(ca);
- break;
- }
+ ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo));
memcpy(ca->ai_addr, ai->ai_addr, ss_size);
- if(ai->ai_canonname != NULL) {
- ca->ai_canonname = strdup(ai->ai_canonname);
- if(!ca->ai_canonname) {
- error = EAI_MEMORY;
- free(ca->ai_addr);
- free(ca);
- break;
- }
+ if(namelen) {
+ ca->ai_canonname = (void *)((char *)ca->ai_addr + ss_size);
+ memcpy(ca->ai_canonname, ai->ai_canonname, namelen);
}
/* if the return list is empty, this becomes the first element */
@@ -252,7 +239,6 @@ Curl_getaddrinfo_ex(const char *nodename,
* struct sockaddr *ai_addr;
* struct Curl_addrinfo *ai_next;
* };
- * typedef struct Curl_addrinfo Curl_addrinfo;
*
* hostent defined in <netdb.h>
*
@@ -269,12 +255,12 @@ Curl_getaddrinfo_ex(const char *nodename,
* #define h_addr h_addr_list[0]
*/
-Curl_addrinfo *
+struct Curl_addrinfo *
Curl_he2ai(const struct hostent *he, int port)
{
- Curl_addrinfo *ai;
- Curl_addrinfo *prevai = NULL;
- Curl_addrinfo *firstai = NULL;
+ struct Curl_addrinfo *ai;
+ struct Curl_addrinfo *prevai = NULL;
+ struct Curl_addrinfo *firstai = NULL;
struct sockaddr_in *addr;
#ifdef ENABLE_IPV6
struct sockaddr_in6 *addr6;
@@ -290,8 +276,8 @@ 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++) {
-
size_t ss_size;
+ size_t namelen = strlen(he->h_name) + 1; /* include zero termination */
#ifdef ENABLE_IPV6
if(he->h_addrtype == AF_INET6)
ss_size = sizeof(struct sockaddr_in6);
@@ -299,24 +285,17 @@ Curl_he2ai(const struct hostent *he, int port)
#endif
ss_size = sizeof(struct sockaddr_in);
- ai = calloc(1, sizeof(Curl_addrinfo));
+ /* allocate memory to told the struct, the address and the name */
+ ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + namelen);
if(!ai) {
result = CURLE_OUT_OF_MEMORY;
break;
}
- ai->ai_canonname = strdup(he->h_name);
- if(!ai->ai_canonname) {
- result = CURLE_OUT_OF_MEMORY;
- free(ai);
- break;
- }
- ai->ai_addr = calloc(1, ss_size);
- if(!ai->ai_addr) {
- result = CURLE_OUT_OF_MEMORY;
- free(ai->ai_canonname);
- free(ai);
- break;
- }
+ /* put the address after the struct */
+ ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
+ /* then put the name after the address */
+ ai->ai_canonname = (char *)ai->ai_addr + ss_size;
+ memcpy(ai->ai_canonname, he->h_name, namelen);
if(!firstai)
/* store the pointer we want to return from this function */
@@ -389,10 +368,10 @@ struct namebuff {
* given address/host
*/
-Curl_addrinfo *
+struct Curl_addrinfo *
Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
{
- Curl_addrinfo *ai;
+ struct Curl_addrinfo *ai;
#if defined(__VMS) && \
defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
@@ -465,7 +444,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
* Given an IPv4 or IPv6 dotted string address, this converts it to a proper
* allocated Curl_addrinfo struct and returns it.
*/
-Curl_addrinfo *Curl_str2addr(char *address, int port)
+struct Curl_addrinfo *Curl_str2addr(char *address, int port)
{
struct in_addr in;
if(Curl_inet_pton(AF_INET, address, &in) > 0)
@@ -488,22 +467,19 @@ Curl_addrinfo *Curl_str2addr(char *address, int port)
* struct initialized with this path.
* Set '*longpath' to TRUE if the error is a too long path.
*/
-Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
+struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath,
+ bool abstract)
{
- Curl_addrinfo *ai;
+ struct Curl_addrinfo *ai;
struct sockaddr_un *sa_un;
size_t path_len;
*longpath = FALSE;
- ai = calloc(1, sizeof(Curl_addrinfo));
+ ai = calloc(1, sizeof(struct Curl_addrinfo) + sizeof(struct sockaddr_un));
if(!ai)
return NULL;
- ai->ai_addr = calloc(1, sizeof(struct sockaddr_un));
- if(!ai->ai_addr) {
- free(ai);
- return NULL;
- }
+ ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
sa_un = (void *) ai->ai_addr;
sa_un->sun_family = AF_UNIX;
@@ -511,7 +487,6 @@ Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract)
/* sun_path must be able to store the NUL-terminated path */
path_len = strlen(path) + 1;
if(path_len > sizeof(sa_un->sun_path)) {
- free(ai->ai_addr);
free(ai);
*longpath = TRUE;
return NULL;
@@ -594,9 +569,9 @@ curl_dbg_getaddrinfo(const char *hostname,
* Work-arounds the sin6_port is always zero bug on iOS 9.3.2 and Mac OS X
* 10.11.5.
*/
-void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port)
+void Curl_addrinfo_set_port(struct Curl_addrinfo *addrinfo, int port)
{
- Curl_addrinfo *ca;
+ struct Curl_addrinfo *ca;
struct sockaddr_in *addr;
#ifdef ENABLE_IPV6
struct sockaddr_in6 *addr6;
diff --git a/lib/curl_addrinfo.h b/lib/curl_addrinfo.h
index 205e121ea..a0cade614 100644
--- a/lib/curl_addrinfo.h
+++ b/lib/curl_addrinfo.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,7 +40,6 @@
# include <stdlib.h>
#endif
-
/*
* Curl_addrinfo is our internal struct definition that we use to allow
* consistent internal handling of this data. We use this even when the
@@ -58,29 +57,29 @@ struct Curl_addrinfo {
struct sockaddr *ai_addr;
struct Curl_addrinfo *ai_next;
};
-typedef struct Curl_addrinfo Curl_addrinfo;
void
-Curl_freeaddrinfo(Curl_addrinfo *cahead);
+Curl_freeaddrinfo(struct Curl_addrinfo *cahead);
#ifdef HAVE_GETADDRINFO
int
Curl_getaddrinfo_ex(const char *nodename,
const char *servname,
const struct addrinfo *hints,
- Curl_addrinfo **result);
+ struct Curl_addrinfo **result);
#endif
-Curl_addrinfo *
+struct Curl_addrinfo *
Curl_he2ai(const struct hostent *he, int port);
-Curl_addrinfo *
+struct Curl_addrinfo *
Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
-Curl_addrinfo *Curl_str2addr(char *dotted, int port);
+struct Curl_addrinfo *Curl_str2addr(char *dotted, int port);
#ifdef USE_UNIX_SOCKETS
-Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract);
+struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath,
+ bool abstract);
#endif
#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \
@@ -98,7 +97,7 @@ curl_dbg_getaddrinfo(const char *hostname, const char *service,
#ifdef HAVE_GETADDRINFO
#ifdef USE_RESOLVE_ON_IPS
-void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port);
+void Curl_addrinfo_set_port(struct Curl_addrinfo *addrinfo, int port);
#else
#define Curl_addrinfo_set_port(x,y)
#endif
diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake
index 57a86e50a..05a5acb03 100644
--- a/lib/curl_config.h.cmake
+++ b/lib/curl_config.h.cmake
@@ -428,6 +428,9 @@
/* Define to 1 if you have the <libssh2.h> header file. */
#cmakedefine HAVE_LIBSSH2_H 1
+/* Define to 1 if you have the <libssh/libssh.h> header file. */
+#cmakedefine HAVE_LIBSSH_LIBSSH_H 1
+
/* if zlib is available */
#cmakedefine HAVE_LIBZ 1
@@ -969,6 +972,9 @@ ${SIZEOF_TIME_T_CODE}
/* if WolfSSL is enabled */
#cmakedefine USE_WOLFSSL 1
+/* if libSSH is in use */
+#cmakedefine USE_LIBSSH 1
+
/* if libSSH2 is in use */
#cmakedefine USE_LIBSSH2 1
@@ -990,9 +996,24 @@ ${SIZEOF_TIME_T_CODE}
/* to enable NGHTTP2 */
#cmakedefine USE_NGHTTP2 1
+/* to enable NGTCP2 */
+#cmakedefine USE_NGTCP2 1
+
+/* to enable NGHTTP3 */
+#cmakedefine USE_NGHTTP3 1
+
+/* to enable quiche */
+#cmakedefine USE_QUICHE 1
+
+/* Define to 1 if you have the quiche_conn_set_qlog_fd function. */
+#cmakedefine HAVE_QUICHE_CONN_SET_QLOG_FD 1
+
/* if Unix domain sockets are enabled */
#cmakedefine USE_UNIX_SOCKETS
+/* to enable alt-svc */
+#cmakedefine USE_ALTSVC 1
+
/* Define to 1 if you are building a Windows target with large file support. */
#cmakedefine USE_WIN32_LARGE_FILES 1
diff --git a/lib/curl_hmac.h b/lib/curl_hmac.h
index 3ff799bbd..9b70c8468 100644
--- a/lib/curl_hmac.h
+++ b/lib/curl_hmac.h
@@ -34,37 +34,35 @@ typedef void (* HMAC_hfinal_func)(unsigned char *result, void *context);
/* Per-hash function HMAC parameters. */
-
-typedef struct {
- HMAC_hinit_func hmac_hinit; /* Initialize context procedure. */
+struct HMAC_params {
+ HMAC_hinit_func
+ hmac_hinit; /* Initialize context procedure. */
HMAC_hupdate_func hmac_hupdate; /* Update context with data. */
HMAC_hfinal_func hmac_hfinal; /* Get final result procedure. */
unsigned int hmac_ctxtsize; /* Context structure size. */
unsigned int hmac_maxkeylen; /* Maximum key length (bytes). */
unsigned int hmac_resultlen; /* Result length (bytes). */
-} HMAC_params;
+};
/* HMAC computation context. */
-
-typedef struct {
- const HMAC_params *hmac_hash; /* Hash function definition. */
+struct HMAC_context {
+ const struct HMAC_params *hmac_hash; /* Hash function definition. */
void *hmac_hashctxt1; /* Hash function context 1. */
void *hmac_hashctxt2; /* Hash function context 2. */
-} HMAC_context;
+};
/* Prototypes. */
-
-HMAC_context * Curl_HMAC_init(const HMAC_params *hashparams,
- const unsigned char *key,
- unsigned int keylen);
-int Curl_HMAC_update(HMAC_context *context,
+struct HMAC_context *Curl_HMAC_init(const struct HMAC_params *hashparams,
+ const unsigned char *key,
+ unsigned int keylen);
+int Curl_HMAC_update(struct HMAC_context *context,
const unsigned char *data,
unsigned int len);
-int Curl_HMAC_final(HMAC_context *context, unsigned char *result);
+int Curl_HMAC_final(struct HMAC_context *context, unsigned char *result);
-CURLcode Curl_hmacit(const HMAC_params *hashparams,
+CURLcode Curl_hmacit(const struct HMAC_params *hashparams,
const unsigned char *key, const size_t keylen,
const unsigned char *data, const size_t datalen,
unsigned char *output);
diff --git a/lib/curl_md5.h b/lib/curl_md5.h
index dd464416a..e06c68edf 100644
--- a/lib/curl_md5.h
+++ b/lib/curl_md5.h
@@ -33,30 +33,30 @@ typedef void (* Curl_MD5_update_func)(void *context,
unsigned int len);
typedef void (* Curl_MD5_final_func)(unsigned char *result, void *context);
-typedef struct {
+struct MD5_params {
Curl_MD5_init_func md5_init_func; /* Initialize context procedure */
Curl_MD5_update_func md5_update_func; /* Update context with data */
Curl_MD5_final_func md5_final_func; /* Get final result procedure */
unsigned int md5_ctxtsize; /* Context structure size */
unsigned int md5_resultlen; /* Result length (bytes) */
-} MD5_params;
+};
-typedef struct {
- const MD5_params *md5_hash; /* Hash function definition */
+struct MD5_context {
+ const struct MD5_params *md5_hash; /* Hash function definition */
void *md5_hashctx; /* Hash function context */
-} MD5_context;
+};
-extern const MD5_params Curl_DIGEST_MD5[1];
-extern const HMAC_params Curl_HMAC_MD5[1];
+extern const struct MD5_params Curl_DIGEST_MD5[1];
+extern const struct HMAC_params Curl_HMAC_MD5[1];
void Curl_md5it(unsigned char *output, const unsigned char *input,
const size_t len);
-MD5_context * Curl_MD5_init(const MD5_params *md5params);
-CURLcode Curl_MD5_update(MD5_context *context,
+struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params);
+CURLcode Curl_MD5_update(struct MD5_context *context,
const unsigned char *data,
unsigned int len);
-CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result);
+CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result);
#endif
diff --git a/lib/curl_multibyte.c b/lib/curl_multibyte.c
index 9dfa6d027..2c8925b53 100644
--- a/lib/curl_multibyte.c
+++ b/lib/curl_multibyte.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -20,24 +20,21 @@
*
***************************************************************************/
-#include "curl_setup.h"
-
-#include <gnurl/curl.h>
+/*
+ * This file is 'mem-include-scan' clean. See test 1132.
+ */
-#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \
- defined(USE_WIN32_LDAP)) && defined(UNICODE))
+#include "curl_setup.h"
- /*
- * MultiByte conversions using Windows kernel32 library.
- */
+#if defined(WIN32)
#include "curl_multibyte.h"
-#include "curl_memory.h"
-/* The last #include file should be: */
-#include "memdebug.h"
+/*
+ * MultiByte conversions using Windows kernel32 library.
+ */
-wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8)
+wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8)
{
wchar_t *str_w = NULL;
@@ -59,7 +56,7 @@ wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8)
return str_w;
}
-char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w)
+char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w)
{
char *str_utf8 = NULL;
@@ -81,4 +78,76 @@ char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w)
return str_utf8;
}
-#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */
+#endif /* WIN32 */
+
+#if defined(USE_WIN32_LARGE_FILES) || defined(USE_WIN32_SMALL_FILES)
+
+FILE *curlx_win32_fopen(const char *filename, const char *mode)
+{
+#ifdef _UNICODE
+ FILE *result = NULL;
+ wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename);
+ wchar_t *mode_w = curlx_convert_UTF8_to_wchar(mode);
+ if(filename_w && mode_w)
+ result = _wfopen(filename_w, mode_w);
+ free(filename_w);
+ free(mode_w);
+ if(result)
+ return result;
+#endif
+
+ return (fopen)(filename, mode);
+}
+
+int curlx_win32_stat(const char *path, struct_stat *buffer)
+{
+ int result = -1;
+#ifdef _UNICODE
+ wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
+#endif /* _UNICODE */
+
+#if defined(USE_WIN32_SMALL_FILES)
+#if defined(_UNICODE)
+ if(path_w)
+ result = _wstat(path_w, buffer);
+ else
+#endif /* _UNICODE */
+ result = _stat(path, buffer);
+#else /* USE_WIN32_SMALL_FILES */
+#if defined(_UNICODE)
+ if(path_w)
+ result = _wstati64(path_w, buffer);
+ else
+#endif /* _UNICODE */
+ result = _stati64(path, buffer);
+#endif /* USE_WIN32_SMALL_FILES */
+
+#ifdef _UNICODE
+ free(path_w);
+#endif
+
+ return result;
+}
+
+int curlx_win32_access(const char *path, int mode)
+{
+ int result = -1;
+#ifdef _UNICODE
+ wchar_t *path_w = curlx_convert_UTF8_to_wchar(path);
+#endif /* _UNICODE */
+
+#if defined(_UNICODE)
+ if(path_w)
+ result = _waccess(path_w, mode);
+ else
+#endif /* _UNICODE */
+ result = _access(path, mode);
+
+#ifdef _UNICODE
+ free(path_w);
+#endif
+
+ return result;
+}
+
+#endif /* USE_WIN32_LARGE_FILES || USE_WIN32_SMALL_FILES */
diff --git a/lib/curl_multibyte.h b/lib/curl_multibyte.h
index 3becf41cf..5f8c05afc 100644
--- a/lib/curl_multibyte.h
+++ b/lib/curl_multibyte.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,48 +23,43 @@
***************************************************************************/
#include "curl_setup.h"
-#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \
- defined(USE_WIN32_LDAP)) && defined(UNICODE))
+#if defined(WIN32)
/*
* MultiByte conversions using Windows kernel32 library.
*/
-wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8);
-char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w);
+wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8);
+char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
-#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */
-
-
-#if defined(USE_WIN32_IDN) || defined(USE_WINDOWS_SSPI) || \
- defined(USE_WIN32_LDAP)
+#endif /* WIN32 */
/*
- * Macros Curl_convert_UTF8_to_tchar(), Curl_convert_tchar_to_UTF8()
- * and Curl_unicodefree() main purpose is to minimize the number of
+ * Macros curlx_convert_UTF8_to_tchar(), curlx_convert_tchar_to_UTF8()
+ * and curlx_unicodefree() main purpose is to minimize the number of
* preprocessor conditional directives needed by code using these
* to differentiate UNICODE from non-UNICODE builds.
*
- * When building with UNICODE defined, this two macros
- * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8()
+ * When building with UNICODE defined, these two macros
+ * curlx_convert_UTF8_to_tchar() and curlx_convert_tchar_to_UTF8()
* return a pointer to a newly allocated memory area holding result.
* When the result is no longer needed, allocated memory is intended
- * to be free'ed with Curl_unicodefree().
+ * to be free'ed with curlx_unicodefree().
*
* When building without UNICODE defined, this macros
- * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8()
- * return the pointer received as argument. Curl_unicodefree() does
+ * curlx_convert_UTF8_to_tchar() and curlx_convert_tchar_to_UTF8()
+ * return the pointer received as argument. curlx_unicodefree() does
* no actual free'ing of this pointer it is simply set to NULL.
*/
-#ifdef UNICODE
+#if defined(UNICODE) && defined(WIN32)
-#define Curl_convert_UTF8_to_tchar(ptr) Curl_convert_UTF8_to_wchar((ptr))
-#define Curl_convert_tchar_to_UTF8(ptr) Curl_convert_wchar_to_UTF8((ptr))
-#define Curl_unicodefree(ptr) \
+#define curlx_convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr))
+#define curlx_convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr))
+#define curlx_unicodefree(ptr) \
do { \
if(ptr) { \
- free(ptr); \
+ (free)(ptr); \
(ptr) = NULL; \
} \
} while(0)
@@ -78,9 +73,9 @@ typedef union {
#else
-#define Curl_convert_UTF8_to_tchar(ptr) (ptr)
-#define Curl_convert_tchar_to_UTF8(ptr) (ptr)
-#define Curl_unicodefree(ptr) \
+#define curlx_convert_UTF8_to_tchar(ptr) (ptr)
+#define curlx_convert_tchar_to_UTF8(ptr) (ptr)
+#define curlx_unicodefree(ptr) \
do {(ptr) = NULL;} while(0)
typedef union {
@@ -90,8 +85,6 @@ typedef union {
const unsigned char *const_tbyte_ptr;
} xcharp_u;
-#endif /* UNICODE */
-
-#endif /* USE_WIN32_IDN || USE_WINDOWS_SSPI || USE_WIN32_LDAP */
+#endif /* UNICODE && WIN32 */
#endif /* HEADER_CURL_MULTIBYTE_H */
diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c
index 32e29a933..0eefb1587 100644
--- a/lib/curl_ntlm_core.c
+++ b/lib/curl_ntlm_core.c
@@ -52,13 +52,18 @@
#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
-#ifdef USE_OPENSSL
+#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
+
+#ifdef USE_WOLFSSL
+#include <wolfssl/options.h>
+#endif
# include <openssl/des.h>
# include <openssl/md5.h>
# include <openssl/ssl.h>
# include <openssl/rand.h>
-# if (OPENSSL_VERSION_NUMBER < 0x00907001L)
+# if (defined(OPENSSL_VERSION_NUMBER) && \
+ (OPENSSL_VERSION_NUMBER < 0x00907001L)) && !defined(USE_WOLFSSL)
# define DES_key_schedule des_key_schedule
# define DES_cblock des_cblock
# define DES_set_odd_parity des_set_odd_parity
@@ -78,14 +83,12 @@
#elif defined(USE_GNUTLS)
# include <gcrypt.h>
-# define MD5_DIGEST_LENGTH 16
#elif defined(USE_NSS)
# include <nss.h>
# include <pk11pub.h>
# include <hasht.h>
-# define MD5_DIGEST_LENGTH MD5_LENGTH
#elif defined(USE_MBEDTLS)
@@ -138,7 +141,7 @@ static void extend_key_56_to_64(const unsigned char *key_56, char *key)
key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
}
-#ifdef USE_OPENSSL
+#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
/*
* Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
* key schedule ks is also set.
@@ -387,7 +390,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys,
const unsigned char *plaintext,
unsigned char *results)
{
-#ifdef USE_OPENSSL
+#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
DES_key_schedule ks;
setup_des_key(keys, DESKEY(ks));
@@ -462,7 +465,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
{
/* Create LanManager hashed password. */
-#ifdef USE_OPENSSL
+#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
DES_key_schedule ks;
setup_des_key(pw, DESKEY(ks));
diff --git a/lib/curl_ntlm_core.h b/lib/curl_ntlm_core.h
index e1643d627..7895b6470 100644
--- a/lib/curl_ntlm_core.h
+++ b/lib/curl_ntlm_core.h
@@ -29,6 +29,7 @@
/* 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_WOLFSSL) && \
!defined(USE_GNUTLS_NETTLE) && \
!defined(USE_GNUTLS) && \
defined(USE_NSS)
@@ -37,7 +38,10 @@
#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
-#ifdef USE_OPENSSL
+#if defined(USE_OPENSSL) || defined(USE_WOLFSSL)
+#ifdef USE_WOLFSSL
+# include <wolfssl/options.h>
+#endif
# include <openssl/ssl.h>
#endif
diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c
index f820b842e..17a92f8ca 100644
--- a/lib/curl_ntlm_wb.c
+++ b/lib/curl_ntlm_wb.c
@@ -261,15 +261,11 @@ done:
static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
const char *input, curlntlm state)
{
- char *buf = malloc(NTLM_BUFSIZE);
size_t len_in = strlen(input), len_out = 0;
-
-#if defined(CURL_DISABLE_VERBOSE_STRINGS)
- (void) data;
-#endif
-
- if(!buf)
- return CURLE_OUT_OF_MEMORY;
+ struct dynbuf b;
+ char *ptr = NULL;
+ unsigned char *buf = (unsigned char *)data->state.buffer;
+ Curl_dyn_init(&b, MAX_NTLM_WB_RESPONSE);
while(len_in > 0) {
ssize_t written = swrite(ntlm->ntlm_auth_hlpr_socket, input, len_in);
@@ -285,10 +281,8 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
}
/* Read one line */
while(1) {
- ssize_t size;
- char *newbuf;
-
- size = sread(ntlm->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE);
+ ssize_t size =
+ sread(ntlm->ntlm_auth_hlpr_socket, buf, data->set.buffer_size);
if(size == -1) {
if(errno == EINTR)
continue;
@@ -297,48 +291,41 @@ static CURLcode ntlm_wb_response(struct Curl_easy *data, struct ntlmdata *ntlm,
else if(size == 0)
goto done;
- len_out += size;
- if(buf[len_out - 1] == '\n') {
- buf[len_out - 1] = '\0';
- break;
- }
+ if(Curl_dyn_addn(&b, buf, size))
+ goto done;
- if(len_out > MAX_NTLM_WB_RESPONSE) {
- failf(data, "too large ntlm_wb response!");
- free(buf);
- return CURLE_OUT_OF_MEMORY;
+ len_out = Curl_dyn_len(&b);
+ ptr = Curl_dyn_ptr(&b);
+ if(len_out && ptr[len_out - 1] == '\n') {
+ ptr[len_out - 1] = '\0';
+ break; /* done! */
}
-
- newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE);
- if(!newbuf)
- return CURLE_OUT_OF_MEMORY;
-
- buf = newbuf;
+ /* loop */
}
/* Samba/winbind installed but not configured */
if(state == NTLMSTATE_TYPE1 &&
len_out == 3 &&
- buf[0] == 'P' && buf[1] == 'W')
+ ptr[0] == 'P' && ptr[1] == 'W')
goto done;
/* invalid response */
if(len_out < 4)
goto done;
if(state == NTLMSTATE_TYPE1 &&
- (buf[0]!='Y' || buf[1]!='R' || buf[2]!=' '))
+ (ptr[0]!='Y' || ptr[1]!='R' || ptr[2]!=' '))
goto done;
if(state == NTLMSTATE_TYPE2 &&
- (buf[0]!='K' || buf[1]!='K' || buf[2]!=' ') &&
- (buf[0]!='A' || buf[1]!='F' || buf[2]!=' '))
+ (ptr[0]!='K' || ptr[1]!='K' || ptr[2]!=' ') &&
+ (ptr[0]!='A' || ptr[1]!='F' || ptr[2]!=' '))
goto done;
- ntlm->response = aprintf("%.*s", len_out - 4, buf + 3);
- free(buf);
+ ntlm->response = strdup(ptr + 3);
+ Curl_dyn_free(&b);
if(!ntlm->response)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
done:
- free(buf);
+ Curl_dyn_free(&b);
return CURLE_REMOTE_ACCESS_DENIED;
}
@@ -389,8 +376,7 @@ CURLcode Curl_input_ntlm_wb(struct connectdata *conn,
* This is for creating ntlm header output by delegating challenge/response
* to Samba's winbind daemon helper ntlm_auth.
*/
-CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
- bool proxy)
+CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy)
{
/* point to the address of the pointer that holds the string to send to the
server, which is for a plain host or for a HTTP proxy */
@@ -400,6 +386,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
struct ntlmdata *ntlm;
curlntlm *state;
struct auth *authp;
+ struct Curl_easy *data = conn->data;
CURLcode res = CURLE_OK;
@@ -407,14 +394,18 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn,
DEBUGASSERT(conn->data);
if(proxy) {
- allocuserpwd = &conn->allocptr.proxyuserpwd;
+#ifndef CURL_DISABLE_PROXY
+ allocuserpwd = &data->state.aptr.proxyuserpwd;
userp = conn->http_proxy.user;
ntlm = &conn->proxyntlm;
state = &conn->proxy_ntlm_state;
authp = &conn->data->state.authproxy;
+#else
+ return CURLE_NOT_BUILT_IN;
+#endif
}
else {
- allocuserpwd = &conn->allocptr.userpwd;
+ allocuserpwd = &data->state.aptr.userpwd;
userp = conn->user;
ntlm = &conn->ntlm;
state = &conn->http_ntlm_state;
diff --git a/lib/curl_path.c b/lib/curl_path.c
index 1ae4082a8..1e216ecc0 100644
--- a/lib/curl_path.c
+++ b/lib/curl_path.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,7 +42,7 @@ CURLcode Curl_getworkingpath(struct connectdata *conn,
size_t working_path_len;
CURLcode result =
Curl_urldecode(data, data->state.up.path, 0, &working_path,
- &working_path_len, FALSE);
+ &working_path_len, REJECT_ZERO);
if(result)
return result;
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index f6d7ae007..9b467714d 100644
--- a/lib/curl_sasl.c
+++ b/lib/curl_sasl.c
@@ -264,9 +264,14 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
size_t len = 0;
saslstate state1 = SASL_STOP;
saslstate state2 = SASL_FINAL;
+#ifndef CURL_DISABLE_PROXY
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
+#else
+ const char * const hostname = conn->host.name;
+ const long int port = conn->remote_port;
+#endif
#if defined(USE_KERBEROS5) || defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
data->set.str[STRING_SERVICE_NAME] :
@@ -417,18 +422,23 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
struct Curl_easy *data = conn->data;
saslstate newstate = SASL_FINAL;
char *resp = NULL;
+#ifndef CURL_DISABLE_PROXY
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
+#else
+ const char * const hostname = conn->host.name;
+ const long int port = conn->remote_port;
+#endif
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
char *chlg = NULL;
size_t chlglen = 0;
#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
- defined(USE_NTLM)
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
+ defined(USE_NTLM)
const char *service = data->set.str[STRING_SERVICE_NAME] ?
- data->set.str[STRING_SERVICE_NAME] :
- sasl->params->service;
+ data->set.str[STRING_SERVICE_NAME] :
+ sasl->params->service;
char *serverdata;
#endif
size_t len = 0;
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index e09d6521e..e3b33b5c0 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -331,9 +331,14 @@
# undef fstat
# define fstat(fdes,stp) _fstati64(fdes, stp)
# undef stat
-# define stat(fname,stp) _stati64(fname, stp)
+# define stat(fname,stp) curlx_win32_stat(fname, stp)
# define struct_stat struct _stati64
# define LSEEK_ERROR (__int64)-1
+# define fopen(fname,mode) curlx_win32_fopen(fname, mode)
+# define access(fname,mode) curlx_win32_access(fname, mode)
+ int curlx_win32_stat(const char *path, struct_stat *buffer);
+ FILE *curlx_win32_fopen(const char *filename, const char *mode);
+ int curlx_win32_access(const char *path, int mode);
#endif
/*
@@ -348,8 +353,13 @@
# undef lseek
# define lseek(fdes,offset,whence) _lseek(fdes, (long)offset, whence)
# define fstat(fdes,stp) _fstat(fdes, stp)
-# define stat(fname,stp) _stat(fname, stp)
+# define stat(fname,stp) curlx_win32_stat(fname, stp)
# define struct_stat struct _stat
+# define fopen(fname,mode) curlx_win32_fopen(fname, mode)
+# define access(fname,mode) curlx_win32_access(fname, mode)
+ int curlx_win32_stat(const char *path, struct_stat *buffer);
+ FILE *curlx_win32_fopen(const char *filename, const char *mode);
+ int curlx_win32_access(const char *path, int mode);
# endif
# define LSEEK_ERROR (long)-1
#endif
@@ -627,10 +637,11 @@ int netware_init(void);
/* Single point where USE_NTLM definition might be defined */
#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
-#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
- defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
- defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
- defined(USE_MBEDTLS)
+#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
+ defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \
+ defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
+ defined(USE_MBEDTLS) || \
+ (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_SET_ODD_PARITY))
#define USE_NTLM
diff --git a/lib/curl_setup_once.h b/lib/curl_setup_once.h
index 8890f3890..e7c00deab 100644
--- a/lib/curl_setup_once.h
+++ b/lib/curl_setup_once.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -481,6 +481,8 @@ typedef int sig_atomic_t;
#ifdef __VMS
#define argv_item_t __char_ptr32
+#elif defined(_UNICODE)
+#define argv_item_t wchar_t *
#else
#define argv_item_t char *
#endif
diff --git a/lib/curl_sspi.c b/lib/curl_sspi.c
index a824d48f4..d5fcfa0e1 100644
--- a/lib/curl_sspi.c
+++ b/lib/curl_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -151,7 +151,7 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
/* Initialize the identity */
memset(identity, 0, sizeof(*identity));
- useranddomain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)userp);
+ useranddomain.tchar_ptr = curlx_convert_UTF8_to_tchar((char *)userp);
if(!useranddomain.tchar_ptr)
return CURLE_OUT_OF_MEMORY;
@@ -173,7 +173,7 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
/* Setup the identity's user and length */
dup_user.tchar_ptr = _tcsdup(user.tchar_ptr);
if(!dup_user.tchar_ptr) {
- Curl_unicodefree(useranddomain.tchar_ptr);
+ curlx_unicodefree(useranddomain.tchar_ptr);
return CURLE_OUT_OF_MEMORY;
}
identity->User = dup_user.tbyte_ptr;
@@ -183,7 +183,7 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
/* Setup the identity's domain and length */
dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1));
if(!dup_domain.tchar_ptr) {
- Curl_unicodefree(useranddomain.tchar_ptr);
+ curlx_unicodefree(useranddomain.tchar_ptr);
return CURLE_OUT_OF_MEMORY;
}
_tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen);
@@ -192,22 +192,22 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
identity->DomainLength = curlx_uztoul(domlen);
dup_domain.tchar_ptr = NULL;
- Curl_unicodefree(useranddomain.tchar_ptr);
+ curlx_unicodefree(useranddomain.tchar_ptr);
/* Setup the identity's password and length */
- passwd.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)passwdp);
+ passwd.tchar_ptr = curlx_convert_UTF8_to_tchar((char *)passwdp);
if(!passwd.tchar_ptr)
return CURLE_OUT_OF_MEMORY;
dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr);
if(!dup_passwd.tchar_ptr) {
- Curl_unicodefree(passwd.tchar_ptr);
+ curlx_unicodefree(passwd.tchar_ptr);
return CURLE_OUT_OF_MEMORY;
}
identity->Password = dup_passwd.tbyte_ptr;
identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr));
dup_passwd.tchar_ptr = NULL;
- Curl_unicodefree(passwd.tchar_ptr);
+ curlx_unicodefree(passwd.tchar_ptr);
/* Setup the identity's flags */
identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY;
diff --git a/lib/curl_threads.c b/lib/curl_threads.c
index 12a693fa3..64aa19ba7 100644
--- a/lib/curl_threads.c
+++ b/lib/curl_threads.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -48,7 +48,7 @@ struct curl_actual_call {
static void *curl_thread_create_thunk(void *arg)
{
- struct curl_actual_call * ac = arg;
+ struct curl_actual_call *ac = arg;
unsigned int (*func)(void *) = ac->func;
void *real_arg = ac->arg;
diff --git a/lib/curlx.h b/lib/curlx.h
index a81ddcdb5..4c42a6b05 100644
--- a/lib/curlx.h
+++ b/lib/curlx.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -53,6 +53,16 @@
curlx_uztosi()
*/
+#include "curl_multibyte.h"
+/* "curl_multibyte.h" provides these functions and macros:
+
+ curlx_convert_UTF8_to_wchar()
+ curlx_convert_wchar_to_UTF8()
+ curlx_convert_UTF8_to_tchar()
+ curlx_convert_tchar_to_UTF8()
+ curlx_unicodefree()
+*/
+
/* Now setup curlx_ * names for the functions that are to become curlx_ and
be removed from a future libcurl official API:
curlx_getenv
diff --git a/lib/dict.c b/lib/dict.c
index 20790d273..45fffce9f 100644
--- a/lib/dict.c
+++ b/lib/dict.c
@@ -99,7 +99,8 @@ static char *unescape_word(struct Curl_easy *data, const char *inputbuff)
char *dictp;
size_t len;
- CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len, FALSE);
+ CURLcode result = Curl_urldecode(data, inputbuff, 0, &newp, &len,
+ REJECT_NADA);
if(!newp || result)
return NULL;
diff --git a/lib/doh.c b/lib/doh.c
index 10867cc34..ebb2c243b 100644
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -35,13 +35,13 @@
#include "curl_base64.h"
#include "connect.h"
#include "strdup.h"
+#include "dynbuf.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
#define DNS_CLASS_IN 0x01
-#define DOH_MAX_RESPONSE_SIZE 3000 /* bytes */
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static const char * const errors[]={
@@ -177,20 +177,11 @@ static size_t
doh_write_cb(const void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
- struct dohresponse *mem = (struct dohresponse *)userp;
+ struct dynbuf *mem = (struct dynbuf *)userp;
- if((mem->size + realsize) > DOH_MAX_RESPONSE_SIZE)
- /* suspiciously much for us */
+ if(Curl_dyn_addn(mem, contents, realsize))
return 0;
- mem->memory = Curl_saferealloc(mem->memory, mem->size + realsize);
- if(!mem->memory)
- /* out of memory! */
- return 0;
-
- memcpy(&(mem->memory[mem->size]), contents, realsize);
- mem->size += realsize;
-
return realsize;
}
@@ -238,10 +229,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
}
p->dnstype = dnstype;
- p->serverdoh.memory = NULL;
- /* the memory will be grown as needed by realloc in the doh_write_cb
- function */
- p->serverdoh.size = 0;
+ Curl_dyn_init(&p->serverdoh, DYN_DOH_RESPONSE);
/* Note: this is code for sending the DoH request with GET but there's still
no logic that actually enables this. We should either add that ability or
@@ -272,7 +260,7 @@ static CURLcode dohprobe(struct Curl_easy *data,
if(!result) {
/* pass in the struct pointer via a local variable to please coverity and
the gcc typecheck helpers */
- struct dohresponse *resp = &p->serverdoh;
+ struct dynbuf *resp = &p->serverdoh;
ERROR_CHECK_SETOPT(CURLOPT_URL, url);
ERROR_CHECK_SETOPT(CURLOPT_WRITEFUNCTION, doh_write_cb);
ERROR_CHECK_SETOPT(CURLOPT_WRITEDATA, resp);
@@ -385,10 +373,10 @@ static CURLcode dohprobe(struct Curl_easy *data,
* 'Curl_addrinfo *' with the address information.
*/
-Curl_addrinfo *Curl_doh(struct connectdata *conn,
- const char *hostname,
- int port,
- int *waitp)
+struct Curl_addrinfo *Curl_doh(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
{
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
@@ -401,6 +389,7 @@ Curl_addrinfo *Curl_doh(struct connectdata *conn,
/* start clean, consider allocating this struct on demand */
memset(&data->req.doh, 0, sizeof(struct dohdata));
+ conn->bits.doh = TRUE;
data->req.doh.host = hostname;
data->req.doh.port = port;
data->req.doh.headers =
@@ -506,38 +495,12 @@ static DOHcode store_aaaa(const unsigned char *doh,
return DOH_OK;
}
-static DOHcode cnameappend(struct cnamestore *c,
- const unsigned char *src,
- size_t len)
-{
- if(!c->alloc) {
- c->allocsize = len + 1;
- c->alloc = malloc(c->allocsize);
- if(!c->alloc)
- return DOH_OUT_OF_MEM;
- }
- else if(c->allocsize < (c->allocsize + len + 1)) {
- char *ptr;
- c->allocsize += len + 1;
- ptr = realloc(c->alloc, c->allocsize);
- if(!ptr) {
- free(c->alloc);
- return DOH_OUT_OF_MEM;
- }
- c->alloc = ptr;
- }
- memcpy(&c->alloc[c->len], src, len);
- c->len += len;
- c->alloc[c->len] = 0; /* keep it zero terminated */
- return DOH_OK;
-}
-
static DOHcode store_cname(const unsigned char *doh,
size_t dohlen,
unsigned int index,
struct dohentry *d)
{
- struct cnamestore *c;
+ struct dynbuf *c;
unsigned int loop = 128; /* a valid DNS name can never loop this much */
unsigned char length;
@@ -566,18 +529,15 @@ static DOHcode store_cname(const unsigned char *doh,
index++;
if(length) {
- DOHcode rc;
- if(c->len) {
- rc = cnameappend(c, (unsigned char *)".", 1);
- if(rc)
- return rc;
+ if(Curl_dyn_len(c)) {
+ if(Curl_dyn_add(c, "."))
+ return DOH_OUT_OF_MEM;
}
if((index + length) > dohlen)
return DOH_DNS_BAD_LABEL;
- rc = cnameappend(c, &doh[index], length);
- if(rc)
- return rc;
+ if(Curl_dyn_addn(c, &doh[index], length))
+ return DOH_OUT_OF_MEM;
index += length;
}
} while(length && --loop);
@@ -630,10 +590,13 @@ static DOHcode rdata(const unsigned char *doh,
return DOH_OK;
}
-static void init_dohentry(struct dohentry *de)
+UNITTEST void de_init(struct dohentry *de)
{
+ int i;
memset(de, 0, sizeof(*de));
de->ttl = INT_MAX;
+ for(i = 0; i < DOH_MAX_CNAME; i++)
+ Curl_dyn_init(&de->cname[i], DYN_DOH_CNAME);
}
@@ -808,7 +771,7 @@ static void showdoh(struct Curl_easy *data,
}
}
for(i = 0; i < d->numcname; i++) {
- infof(data, "CNAME: %s\n", d->cname[i].alloc);
+ infof(data, "CNAME: %s\n", Curl_dyn_ptr(&d->cname[i]));
}
}
#else
@@ -828,18 +791,19 @@ static void showdoh(struct Curl_easy *data,
* must be an associated call later to Curl_freeaddrinfo().
*/
-static Curl_addrinfo *
+static struct Curl_addrinfo *
doh2ai(const struct dohentry *de, const char *hostname, int port)
{
- Curl_addrinfo *ai;
- Curl_addrinfo *prevai = NULL;
- Curl_addrinfo *firstai = NULL;
+ struct Curl_addrinfo *ai;
+ struct Curl_addrinfo *prevai = NULL;
+ struct Curl_addrinfo *firstai = NULL;
struct sockaddr_in *addr;
#ifdef ENABLE_IPV6
struct sockaddr_in6 *addr6;
#endif
CURLcode result = CURLE_OK;
int i;
+ size_t hostlen = strlen(hostname) + 1; /* include zero terminator */
if(!de)
/* no input == no output! */
@@ -862,24 +826,14 @@ doh2ai(const struct dohentry *de, const char *hostname, int port)
addrtype = AF_INET;
}
- ai = calloc(1, sizeof(Curl_addrinfo));
+ ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen);
if(!ai) {
result = CURLE_OUT_OF_MEMORY;
break;
}
- ai->ai_canonname = strdup(hostname);
- if(!ai->ai_canonname) {
- result = CURLE_OUT_OF_MEMORY;
- free(ai);
- break;
- }
- ai->ai_addr = calloc(1, ss_size);
- if(!ai->ai_addr) {
- result = CURLE_OUT_OF_MEMORY;
- free(ai->ai_canonname);
- free(ai);
- break;
- }
+ ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
+ ai->ai_canonname = (void *)((char *)ai->ai_addr + ss_size);
+ memcpy(ai->ai_canonname, hostname, hostlen);
if(!firstai)
/* store the pointer we want to return from this function */
@@ -941,7 +895,7 @@ UNITTEST void de_cleanup(struct dohentry *d)
{
int i = 0;
for(i = 0; i < d->numcname; i++) {
- free(d->cname[i].alloc);
+ Curl_dyn_free(&d->cname[i]);
}
}
@@ -959,7 +913,9 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
CURLE_COULDNT_RESOLVE_HOST;
}
else if(!data->req.doh.pending) {
- DOHcode rc[DOH_PROBE_SLOTS];
+ DOHcode rc[DOH_PROBE_SLOTS] = {
+ DOH_OK, DOH_OK
+ };
struct dohentry de;
int slot;
/* remove DOH handles from multi handle and close them */
@@ -968,17 +924,19 @@ CURLcode Curl_doh_is_resolved(struct connectdata *conn,
Curl_close(&data->req.doh.probe[slot].easy);
}
/* parse the responses, create the struct and return it! */
- init_dohentry(&de);
+ de_init(&de);
for(slot = 0; slot < DOH_PROBE_SLOTS; slot++) {
- rc[slot] = doh_decode(data->req.doh.probe[slot].serverdoh.memory,
- data->req.doh.probe[slot].serverdoh.size,
- data->req.doh.probe[slot].dnstype,
+ struct dnsprobe *p = &data->req.doh.probe[slot];
+ if(!p->dnstype)
+ continue;
+ rc[slot] = doh_decode(Curl_dyn_uptr(&p->serverdoh),
+ Curl_dyn_len(&p->serverdoh),
+ p->dnstype,
&de);
- Curl_safefree(data->req.doh.probe[slot].serverdoh.memory);
+ Curl_dyn_free(&p->serverdoh);
if(rc[slot]) {
infof(data, "DOH: %s type %s for %s\n", doh_strerror(rc[slot]),
- type2name(data->req.doh.probe[slot].dnstype),
- data->req.doh.host);
+ type2name(p->dnstype), data->req.doh.host);
}
} /* next slot */
diff --git a/lib/doh.h b/lib/doh.h
index f6154ffd4..bbd4c1a65 100644
--- a/lib/doh.h
+++ b/lib/doh.h
@@ -32,10 +32,10 @@
* and returns a 'Curl_addrinfo *' with the address information.
*/
-Curl_addrinfo *Curl_doh(struct connectdata *conn,
- const char *hostname,
- int port,
- int *waitp);
+struct Curl_addrinfo *Curl_doh(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp);
CURLcode Curl_doh_is_resolved(struct connectdata *conn,
struct Curl_dns_entry **dns);
@@ -70,12 +70,6 @@ typedef enum {
#define DOH_MAX_ADDR 24
#define DOH_MAX_CNAME 4
-struct cnamestore {
- size_t len; /* length of cname */
- char *alloc; /* allocated pointer */
- size_t allocsize; /* allocated size */
-};
-
struct dohaddr {
int type;
union {
@@ -85,11 +79,11 @@ struct dohaddr {
};
struct dohentry {
- unsigned int ttl;
- int numaddr;
+ struct dynbuf cname[DOH_MAX_CNAME];
struct dohaddr addr[DOH_MAX_ADDR];
+ int numaddr;
+ unsigned int ttl;
int numcname;
- struct cnamestore cname[DOH_MAX_CNAME];
};
@@ -103,6 +97,7 @@ DOHcode doh_decode(const unsigned char *doh,
size_t dohlen,
DNStype dnstype,
struct dohentry *d);
+void de_init(struct dohentry *d);
void de_cleanup(struct dohentry *d);
#endif
diff --git a/lib/dotdot.c b/lib/dotdot.c
index de1e1070e..7e2fed910 100644
--- a/lib/dotdot.c
+++ b/lib/dotdot.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -39,7 +39,7 @@
* Curl_dedotdotify()
* @unittest: 1395
*
- * This function gets a zero-terminated path with dot and dotdot sequences
+ * This function gets a null-terminated path with dot and dotdot sequences
* passed in and strips them off according to the rules in RFC 3986 section
* 5.2.4.
*
@@ -62,7 +62,7 @@ char *Curl_dedotdotify(const char *input)
if(!out)
return NULL; /* out of memory */
- *out = 0; /* zero terminates, for inputs like "./" */
+ *out = 0; /* null-terminates, for inputs like "./" */
/* get a cloned copy of the input */
clone = strdup(input);
@@ -129,7 +129,7 @@ char *Curl_dedotdotify(const char *input)
if(*outptr == '/')
break;
}
- *outptr = 0; /* zero-terminate where it stops */
+ *outptr = 0; /* null-terminate where it stops */
}
else if(!strcmp("/..", clone)) {
clone[2]='/';
@@ -141,7 +141,7 @@ char *Curl_dedotdotify(const char *input)
if(*outptr == '/')
break;
}
- *outptr = 0; /* zero-terminate where it stops */
+ *outptr = 0; /* null-terminate where it stops */
}
/* D. if the input buffer consists only of "." or "..", then remove
diff --git a/lib/dynbuf.c b/lib/dynbuf.c
new file mode 100644
index 000000000..38d370b07
--- /dev/null
+++ b/lib/dynbuf.c
@@ -0,0 +1,227 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+#include "strdup.h"
+#include "dynbuf.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define MIN_FIRST_ALLOC 32
+
+#define DYNINIT 0xbee51da /* random pattern */
+
+/*
+ * Init a dynbuf struct.
+ */
+void Curl_dyn_init(struct dynbuf *s, size_t toobig)
+{
+ DEBUGASSERT(s);
+ DEBUGASSERT(toobig);
+ s->bufr = NULL;
+ s->leng = 0;
+ s->allc = 0;
+ s->toobig = toobig;
+#ifdef DEBUGBUILD
+ s->init = DYNINIT;
+#endif
+}
+
+/*
+ * free the buffer and re-init the necessary fields. It doesn't touch the
+ * 'init' field and thus this buffer can be reused to add data to again.
+ */
+void Curl_dyn_free(struct dynbuf *s)
+{
+ DEBUGASSERT(s);
+ Curl_safefree(s->bufr);
+ s->leng = s->allc = 0;
+}
+
+/*
+ * Store/append an chunk of memory to the dynbuf.
+ */
+static CURLcode dyn_nappend(struct dynbuf *s,
+ const unsigned char *mem, size_t len)
+{
+ size_t indx = s->leng;
+ size_t a = s->allc;
+ size_t fit = len + indx + 1; /* new string + old string + zero byte */
+
+ /* try to detect if there's rubbish in the struct */
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(s->toobig);
+ DEBUGASSERT(indx < s->toobig);
+ DEBUGASSERT(!s->leng || s->bufr);
+
+ if(fit > s->toobig) {
+ Curl_dyn_free(s);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ else if(!a) {
+ DEBUGASSERT(!indx);
+ /* first invoke */
+ if(fit < MIN_FIRST_ALLOC)
+ a = MIN_FIRST_ALLOC;
+ else
+ a = fit;
+ }
+ else {
+ while(a < fit)
+ a *= 2;
+ }
+
+ if(a != s->allc) {
+ s->bufr = Curl_saferealloc(s->bufr, a);
+ if(!s->bufr) {
+ s->leng = s->allc = 0;
+ return CURLE_OUT_OF_MEMORY;
+ }
+ s->allc = a;
+ }
+
+ if(len)
+ memcpy(&s->bufr[indx], mem, len);
+ s->leng = indx + len;
+ s->bufr[s->leng] = 0;
+ return CURLE_OK;
+}
+
+/*
+ * Clears the string, keeps the allocation. This can also be called on a
+ * buffer that already was freed.
+ */
+void Curl_dyn_reset(struct dynbuf *s)
+{
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ if(s->leng)
+ s->bufr[0] = 0;
+ s->leng = 0;
+}
+
+#ifdef USE_NGTCP2
+/*
+ * Specify the size of the tail to keep (number of bytes from the end of the
+ * buffer). The rest will be dropped.
+ */
+CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail)
+{
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ if(trail > s->leng)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ else if(trail == s->leng)
+ return CURLE_OK;
+ else if(!trail) {
+ Curl_dyn_reset(s);
+ }
+ else {
+ memmove(&s->bufr[0], &s->bufr[s->leng - trail], trail);
+ s->leng = trail;
+ }
+ return CURLE_OK;
+
+}
+#endif
+
+/*
+ * Appends a buffer with length.
+ */
+CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
+{
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ return dyn_nappend(s, mem, len);
+}
+
+/*
+ * Append a null-terminated string at the end.
+ */
+CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
+{
+ size_t n = strlen(str);
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ return dyn_nappend(s, (unsigned char *)str, n);
+}
+
+/*
+ * Append a string printf()-style
+ */
+CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
+{
+ char *str;
+ va_list ap;
+ va_start(ap, fmt);
+ str = vaprintf(fmt, ap); /* this allocs a new string to append */
+ va_end(ap);
+
+ if(str) {
+ CURLcode result = dyn_nappend(s, (unsigned char *)str, strlen(str));
+ free(str);
+ return result;
+ }
+ /* If we failed, we cleanup the whole buffer and return error */
+ Curl_dyn_free(s);
+ return CURLE_OUT_OF_MEMORY;
+}
+
+/*
+ * Returns a pointer to the buffer.
+ */
+char *Curl_dyn_ptr(const struct dynbuf *s)
+{
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ return s->bufr;
+}
+
+/*
+ * Returns an unsigned pointer to the buffer.
+ */
+unsigned char *Curl_dyn_uptr(const struct dynbuf *s)
+{
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ return (unsigned char *)s->bufr;
+}
+
+/*
+ * Returns the length of the buffer.
+ */
+size_t Curl_dyn_len(const struct dynbuf *s)
+{
+ DEBUGASSERT(s);
+ DEBUGASSERT(s->init == DYNINIT);
+ DEBUGASSERT(!s->leng || s->bufr);
+ return s->leng;
+}
diff --git a/lib/dynbuf.h b/lib/dynbuf.h
new file mode 100644
index 000000000..c80239e29
--- /dev/null
+++ b/lib/dynbuf.h
@@ -0,0 +1,63 @@
+#ifndef HEADER_CURL_DYNBUF_H
+#define HEADER_CURL_DYNBUF_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+struct dynbuf {
+ char *bufr; /* point to a null-terminated allocated buffer */
+ size_t leng; /* number of bytes *EXCLUDING* the zero terminator */
+ size_t allc; /* size of the current allocation */
+ size_t toobig; /* size limit for the buffer */
+#ifdef DEBUGBUILD
+ int init; /* detect API usage mistakes */
+#endif
+};
+
+void Curl_dyn_init(struct dynbuf *s, size_t toobig);
+void Curl_dyn_free(struct dynbuf *s);
+CURLcode Curl_dyn_addn(struct dynbuf *s, const void *mem, size_t len)
+ WARN_UNUSED_RESULT;
+CURLcode Curl_dyn_add(struct dynbuf *s, const char *str)
+ WARN_UNUSED_RESULT;
+CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...)
+ WARN_UNUSED_RESULT;
+void Curl_dyn_reset(struct dynbuf *s);
+CURLcode Curl_dyn_tail(struct dynbuf *s, size_t trail);
+char *Curl_dyn_ptr(const struct dynbuf *s);
+unsigned char *Curl_dyn_uptr(const struct dynbuf *s);
+size_t Curl_dyn_len(const struct dynbuf *s);
+
+/* Dynamic buffer max sizes */
+#define DYN_DOH_RESPONSE 3000
+#define DYN_DOH_CNAME 256
+#define DYN_PAUSE_BUFFER (64 * 1024 * 1024)
+#define DYN_HAXPROXY 2048
+#define DYN_HTTP_REQUEST (128*1024)
+#define DYN_H2_HEADERS (128*1024)
+#define DYN_H2_TRAILER 4096
+#define DYN_APRINTF 8000000
+#define DYN_RTSP_REQ_HEADER (64*1024)
+#define DYN_TRAILERS (64*1024)
+#define DYN_PROXY_CONNECT_HEADERS 16384
+#define DYN_QLOG_NAME 1024
+#define DYN_H1_TRAILER DYN_H2_TRAILER
+#endif
diff --git a/lib/easy.c b/lib/easy.c
index 42b7b7181..e46e9c893 100644
--- a/lib/easy.c
+++ b/lib/easy.c
@@ -77,6 +77,7 @@
#include "http_digest.h"
#include "system_win32.h"
#include "http2.h"
+#include "dynbuf.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -509,7 +510,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
before = Curl_now();
/* wait for activity or timeout */
- pollrc = Curl_poll(fds, numfds, (int)ev->ms);
+ pollrc = Curl_poll(fds, numfds, ev->ms);
after = Curl_now();
@@ -680,6 +681,7 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events)
mcode = curl_multi_add_handle(multi, data);
if(mcode) {
curl_multi_cleanup(multi);
+ data->multi_easy = NULL;
if(mcode == CURLM_OUT_OF_MEMORY)
return CURLE_OUT_OF_MEMORY;
return CURLE_FAILED_INIT;
@@ -762,6 +764,7 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
{
CURLcode result = CURLE_OK;
enum dupstring i;
+ enum dupblob j;
/* Copy src->set into dst->set first, then deal with the strings
afterwards */
@@ -778,6 +781,16 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src)
return result;
}
+ /* clear all blob pointers first */
+ memset(dst->set.blobs, 0, BLOB_LAST * sizeof(struct curl_blob *));
+ /* duplicate all blobs */
+ for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
+ result = Curl_setblobopt(&dst->set.blobs[j], src->set.blobs[j]);
+ /* Curl_setstropt return CURLE_BAD_FUNCTION_ARGUMENT with blob */
+ if(result)
+ return result;
+ }
+
/* duplicate memory areas pointed to */
i = STRING_COPYPOSTFIELDS;
if(src->set.postfieldsize && src->set.str[i]) {
@@ -816,19 +829,13 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
* the likeliness of us forgetting to init a buffer here in the future.
*/
outcurl->set.buffer_size = data->set.buffer_size;
- outcurl->state.buffer = malloc(outcurl->set.buffer_size + 1);
- if(!outcurl->state.buffer)
- goto fail;
-
- outcurl->state.headerbuff = malloc(HEADERSIZE);
- if(!outcurl->state.headerbuff)
- goto fail;
- outcurl->state.headersize = HEADERSIZE;
/* copy all userdefined values */
if(dupset(outcurl, data))
goto fail;
+ Curl_dyn_init(&outcurl->state.headerb, CURL_MAX_HTTP_HEADER);
+
/* the connection cache is setup on demand */
outcurl->state.conn_cache = NULL;
@@ -921,7 +928,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
curl_slist_free_all(outcurl->change.cookielist);
outcurl->change.cookielist = NULL;
Curl_safefree(outcurl->state.buffer);
- Curl_safefree(outcurl->state.headerbuff);
+ Curl_dyn_free(&outcurl->state.headerb);
Curl_safefree(outcurl->change.url);
Curl_safefree(outcurl->change.referer);
Curl_freeset(outcurl);
@@ -937,8 +944,6 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
*/
void curl_easy_reset(struct Curl_easy *data)
{
- long old_buffer_size = data->set.buffer_size;
-
Curl_free_request_state(data);
/* zero out UserDefined data: */
@@ -962,18 +967,6 @@ void curl_easy_reset(struct Curl_easy *data)
#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
Curl_http_auth_cleanup_digest(data);
#endif
-
- /* resize receive buffer */
- if(old_buffer_size != data->set.buffer_size) {
- char *newbuff = realloc(data->state.buffer, data->set.buffer_size + 1);
- if(!newbuff) {
- DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
- /* nothing we can do here except use the old size */
- data->set.buffer_size = old_buffer_size;
- }
- else
- data->state.buffer = newbuff;
- }
}
/*
@@ -1040,7 +1033,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
/* copy the structs to allow for immediate re-pausing */
for(i = 0; i < data->state.tempcount; i++) {
writebuf[i] = data->state.tempwrite[i];
- data->state.tempwrite[i].buf = NULL;
+ Curl_dyn_init(&data->state.tempwrite[i].b, DYN_PAUSE_BUFFER);
}
data->state.tempcount = 0;
@@ -1054,9 +1047,10 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
/* even if one function returns error, this loops through and frees
all buffers */
if(!result)
- result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf,
- writebuf[i].len);
- free(writebuf[i].buf);
+ result = Curl_client_write(conn, writebuf[i].type,
+ Curl_dyn_ptr(&writebuf[i].b),
+ Curl_dyn_len(&writebuf[i].b));
+ Curl_dyn_free(&writebuf[i].b);
}
/* recover previous owner of the connection */
diff --git a/lib/easyif.h b/lib/easyif.h
index 8a309c55b..eda0d62e5 100644
--- a/lib/easyif.h
+++ b/lib/easyif.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/escape.c b/lib/escape.c
index a352b8cf6..eb8110f53 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -79,82 +79,83 @@ char *curl_unescape(const char *string, int length)
char *curl_easy_escape(struct Curl_easy *data, const char *string,
int inlength)
{
- size_t alloc;
- char *ns;
- char *testing_ptr = NULL;
- size_t newlen;
- size_t strindex = 0;
size_t length;
CURLcode result;
+ struct dynbuf d;
if(inlength < 0)
return NULL;
- alloc = (inlength?(size_t)inlength:strlen(string)) + 1;
- newlen = alloc;
+ Curl_dyn_init(&d, CURL_MAX_INPUT_LENGTH);
- ns = malloc(alloc);
- if(!ns)
- return NULL;
+ length = (inlength?(size_t)inlength:strlen(string));
+ if(!length)
+ return strdup("");
- length = alloc-1;
while(length--) {
unsigned char in = *string; /* we need to treat the characters unsigned */
- if(Curl_isunreserved(in))
- /* just copy this */
- ns[strindex++] = in;
+ if(Curl_isunreserved(in)) {
+ /* append this */
+ if(Curl_dyn_addn(&d, &in, 1))
+ return NULL;
+ }
else {
/* encode it */
- newlen += 2; /* the size grows with two, since this'll become a %XX */
- if(newlen > alloc) {
- alloc *= 2;
- testing_ptr = Curl_saferealloc(ns, alloc);
- if(!testing_ptr)
- return NULL;
- ns = testing_ptr;
- }
-
+ char encoded[4];
result = Curl_convert_to_network(data, (char *)&in, 1);
if(result) {
/* Curl_convert_to_network calls failf if unsuccessful */
- free(ns);
+ Curl_dyn_free(&d);
return NULL;
}
- msnprintf(&ns[strindex], 4, "%%%02X", in);
-
- strindex += 3;
+ msnprintf(encoded, sizeof(encoded), "%%%02X", in);
+ if(Curl_dyn_add(&d, encoded))
+ return NULL;
}
string++;
}
- ns[strindex] = 0; /* terminate it */
- return ns;
+
+ return Curl_dyn_ptr(&d);
}
/*
* Curl_urldecode() URL decodes the given string.
*
- * Optionally detects control characters (byte codes lower than 32) in the
- * data and rejects such data.
- *
* Returns a pointer to a malloced string in *ostring with length given in
* *olen. If length == 0, the length is assumed to be strlen(string).
*
* 'data' can be set to NULL but then this function can't convert network
* data to host for non-ascii.
+ *
+ * ctrl options:
+ * - REJECT_NADA: accept everything
+ * - REJECT_CTRL: rejects control characters (byte codes lower than 32) in
+ * the data
+ * - REJECT_ZERO: rejects decoded zero bytes
+ *
+ * The values for the enum starts at 2, to make the assert detect legacy
+ * invokes that used TRUE/FALSE (0 and 1).
*/
+
CURLcode Curl_urldecode(struct Curl_easy *data,
const char *string, size_t length,
char **ostring, size_t *olen,
- bool reject_ctrl)
+ enum urlreject ctrl)
{
- size_t alloc = (length?length:strlen(string)) + 1;
- char *ns = malloc(alloc);
+ size_t alloc;
+ char *ns;
size_t strindex = 0;
unsigned long hex;
CURLcode result = CURLE_OK;
+ DEBUGASSERT(string);
+ DEBUGASSERT(ctrl >= REJECT_NADA); /* crash on TRUE/FALSE */
+
+ alloc = (length?length:strlen(string)) + 1;
+ ns = malloc(alloc);
+
if(!ns)
return CURLE_OUT_OF_MEMORY;
@@ -186,7 +187,8 @@ CURLcode Curl_urldecode(struct Curl_easy *data,
alloc -= 2;
}
- if(reject_ctrl && (in < 0x20)) {
+ if(((ctrl == REJECT_CTRL) && (in < 0x20)) ||
+ ((ctrl == REJECT_ZERO) && (in == 0))) {
free(ns);
return CURLE_URL_MALFORMAT;
}
@@ -220,7 +222,7 @@ char *curl_easy_unescape(struct Curl_easy *data, const char *string,
size_t inputlen = length;
size_t outputlen;
CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen,
- FALSE);
+ REJECT_NADA);
if(res)
return NULL;
diff --git a/lib/escape.h b/lib/escape.h
index d8bbe5cb0..586db7e67 100644
--- a/lib/escape.h
+++ b/lib/escape.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,9 +25,16 @@
* allocated string or NULL if an error occurred. */
bool Curl_isunreserved(unsigned char in);
+
+enum urlreject {
+ REJECT_NADA = 2,
+ REJECT_CTRL,
+ REJECT_ZERO
+};
+
CURLcode Curl_urldecode(struct Curl_easy *data,
const char *string, size_t length,
char **ostring, size_t *olen,
- bool reject_crlf);
+ enum urlreject ctrl);
#endif /* HEADER_CURL_ESCAPE_H */
diff --git a/lib/file.c b/lib/file.c
index bb3923989..5be1c835c 100644
--- a/lib/file.c
+++ b/lib/file.c
@@ -144,7 +144,7 @@ static CURLcode file_connect(struct connectdata *conn, bool *done)
size_t real_path_len;
CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &real_path,
- &real_path_len, FALSE);
+ &real_path_len, REJECT_ZERO);
if(result)
return result;
diff --git a/lib/formdata.c b/lib/formdata.c
index 7a9a650de..5b3f3f014 100644
--- a/lib/formdata.c
+++ b/lib/formdata.c
@@ -122,11 +122,11 @@ AddHttpPost(char *name, size_t namelength,
* parent_form_info is NULL.
*
***************************************************************************/
-static FormInfo * AddFormInfo(char *value,
- char *contenttype,
- FormInfo *parent_form_info)
+static struct FormInfo *AddFormInfo(char *value,
+ char *contenttype,
+ struct FormInfo *parent_form_info)
{
- FormInfo *form_info;
+ struct FormInfo *form_info;
form_info = calloc(1, sizeof(struct FormInfo));
if(form_info) {
if(value)
@@ -203,7 +203,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
struct curl_httppost **last_post,
va_list params)
{
- FormInfo *first_form, *current_form, *form = NULL;
+ struct FormInfo *first_form, *current_form, *form = NULL;
CURLFORMcode return_value = CURL_FORMADD_OK;
const char *prevtype = NULL;
struct curl_httppost *post = NULL;
@@ -520,7 +520,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
if(CURL_FORMADD_OK != return_value) {
/* On error, free allocated fields for all nodes of the FormInfo linked
list without deallocating nodes. List nodes are deallocated later on */
- FormInfo *ptr;
+ struct FormInfo *ptr;
for(ptr = first_form; ptr != NULL; ptr = ptr->more) {
if(ptr->name_alloc) {
Curl_safefree(ptr->name);
@@ -601,7 +601,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
/* 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 not nul-terminated) */
+ /* copy name (without strdup; possibly not null-terminated) */
form->name = Curl_memdup(form->name, form->namelength?
form->namelength:
strlen(form->name) + 1);
@@ -649,7 +649,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
/* On error, free allocated fields for nodes of the FormInfo linked
list which are not already owned by the httppost linked list
without deallocating nodes. List nodes are deallocated later on */
- FormInfo *ptr;
+ struct FormInfo *ptr;
for(ptr = form; ptr != NULL; ptr = ptr->more) {
if(ptr->name_alloc) {
Curl_safefree(ptr->name);
@@ -675,7 +675,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost,
fields given that these have either been deallocated or are owned
now by the httppost linked list */
while(first_form) {
- FormInfo *ptr = first_form->more;
+ struct FormInfo *ptr = first_form->more;
free(first_form);
first_form = ptr;
}
@@ -770,7 +770,7 @@ void curl_formfree(struct curl_httppost *form)
}
-/* Set mime part name, taking care of non nul-terminated name string. */
+/* Set mime part name, taking care of non null-terminated name string. */
static CURLcode setname(curl_mimepart *part, const char *name, size_t len)
{
char *zname;
diff --git a/lib/formdata.h b/lib/formdata.h
index cb20805f5..3766d38f2 100644
--- a/lib/formdata.h
+++ b/lib/formdata.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,7 +27,7 @@
#ifndef CURL_DISABLE_MIME
/* used by FormAdd for temporary storage */
-typedef struct FormInfo {
+struct FormInfo {
char *name;
bool name_alloc;
size_t namelength;
@@ -45,7 +45,7 @@ typedef struct FormInfo {
char *userp; /* pointer for the read callback */
struct curl_slist *contentheader;
struct FormInfo *more;
-} FormInfo;
+};
CURLcode Curl_getformdata(struct Curl_easy *data,
curl_mimepart *,
diff --git a/lib/ftp.c b/lib/ftp.c
index 242c2d85c..3c549a111 100644
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -113,7 +113,7 @@ static CURLcode ftp_parse_url_path(struct connectdata *conn);
static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done);
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void ftp_pasv_verbose(struct connectdata *conn,
- Curl_addrinfo *ai,
+ struct Curl_addrinfo *ai,
char *newhost, /* ascii version */
int port);
#endif
@@ -136,7 +136,7 @@ static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks);
static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks);
static CURLcode ftp_doing(struct connectdata *conn,
bool *dophase_done);
-static CURLcode ftp_setup_connection(struct connectdata * conn);
+static CURLcode ftp_setup_connection(struct connectdata *conn);
static CURLcode init_wc_data(struct connectdata *conn);
static CURLcode wc_statemach(struct connectdata *conn);
@@ -221,6 +221,9 @@ static void close_secondarysocket(struct connectdata *conn)
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
}
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
+#ifndef CURL_DISABLE_PROXY
+ conn->bits.proxy_ssl_connected[SECONDARYSOCKET] = FALSE;
+#endif
}
/*
@@ -291,7 +294,7 @@ static CURLcode AcceptServerConnect(struct connectdata *conn)
conn->sock[SECONDARYSOCKET] = s;
(void)curlx_nonblock(s, TRUE); /* enable non-blocking */
- conn->sock_accepted = TRUE;
+ conn->bits.sock_accepted = TRUE;
if(data->set.fsockopt) {
int error = 0;
@@ -334,7 +337,7 @@ static timediff_t ftp_timeleft_accept(struct Curl_easy *data)
now = Curl_now();
/* check if the generic timeout possibly is set shorter */
- other = Curl_timeleft(data, &now, FALSE);
+ other = Curl_timeleft(data, &now, FALSE);
if(other && (other < timeout_ms))
/* note that this also works fine for when other happens to be negative
due to it already having elapsed */
@@ -386,7 +389,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
if(pp->cache_size && pp->cache && pp->cache[0] > '3') {
/* Data connection could not be established, let's return */
infof(data, "There is negative response in cache while serv connect\n");
- Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ (void)Curl_GetFTPResponse(&nread, conn, &ftpcode);
return CURLE_FTP_ACCEPT_FAILED;
}
@@ -408,7 +411,7 @@ static CURLcode ReceivedServerConnect(struct connectdata *conn, bool *received)
}
else if(result & CURL_CSELECT_IN) {
infof(data, "Ctrl conn has data while waiting for data conn\n");
- Curl_GetFTPResponse(&nread, conn, &ftpcode);
+ (void)Curl_GetFTPResponse(&nread, conn, &ftpcode);
if(ftpcode/100 > 3)
return CURLE_FTP_ACCEPT_FAILED;
@@ -632,8 +635,8 @@ CURLcode Curl_GetFTPResponse(ssize_t *nreadp, /* return number of bytes read */
while(!*ftpcode && !result) {
/* check and reset timeout value every lap */
- time_t timeout = Curl_pp_state_timeout(pp, FALSE);
- time_t interval_ms;
+ timediff_t timeout = Curl_pp_state_timeout(pp, FALSE);
+ timediff_t interval_ms;
if(timeout <= 0) {
failf(data, "FTP response timeout");
@@ -815,6 +818,7 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)
if(FTP_STOP == ftpc->state) {
int bits = GETSOCK_READSOCK(0);
+ bool any = FALSE;
/* if stopped and still in this state, then we're also waiting for a
connect on the secondary connection */
@@ -829,10 +833,11 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks)
if(conn->tempsock[i] != CURL_SOCKET_BAD) {
socks[s] = conn->tempsock[i];
bits |= GETSOCK_WRITESOCK(s++);
+ any = TRUE;
}
}
}
- else {
+ if(!any) {
socks[1] = conn->sock[SECONDARYSOCKET];
bits |= GETSOCK_WRITESOCK(1) | GETSOCK_READSOCK(1);
}
@@ -913,7 +918,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
char myhost[MAX_IPADR_LEN + 1] = "";
struct Curl_sockaddr_storage ss;
- Curl_addrinfo *res, *ai;
+ struct Curl_addrinfo *res, *ai;
curl_socklen_t sslen;
char hbuf[NI_MAXHOST];
struct sockaddr *sa = (struct sockaddr *)&ss;
@@ -1038,6 +1043,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
} /* data->set.ftpport */
if(!host) {
+ const char *r;
/* not an interface and not a host name, get default by extracting
the IP from the control connection */
sslen = sizeof(ss);
@@ -1050,13 +1056,15 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
switch(sa->sa_family) {
#ifdef ENABLE_IPV6
case AF_INET6:
- Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
+ r = Curl_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, sizeof(hbuf));
break;
#endif
default:
- Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
+ r = Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
break;
}
+ if(!r)
+ return CURLE_FTP_PORT_FAILED;
host = hbuf; /* use this host name */
possibly_non_local = FALSE; /* we know it is local now */
}
@@ -1293,7 +1301,7 @@ static CURLcode ftp_state_use_pasv(struct connectdata *conn)
struct ftp_conn *ftpc = &conn->proto.ftpc;
CURLcode result = CURLE_OK;
/*
- Here's the excecutive summary on what to do:
+ Here's the executive summary on what to do:
PASV is RFC959, expect:
227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)
@@ -1444,7 +1452,7 @@ static CURLcode ftp_state_list(struct connectdata *conn)
/* url-decode before evaluation: e.g. paths starting/ending with %2f */
const char *slashPos = NULL;
char *rawPath = NULL;
- result = Curl_urldecode(data, ftp->path, 0, &rawPath, NULL, TRUE);
+ result = Curl_urldecode(data, ftp->path, 0, &rawPath, NULL, REJECT_CTRL);
if(result)
return result;
@@ -1759,7 +1767,11 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
- if(conn->bits.ipv6 && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)) {
+ if(conn->bits.ipv6
+#ifndef CURL_DISABLE_PROXY
+ && !(conn->bits.tunnel_proxy || conn->bits.socksproxy)
+#endif
+ ) {
/* We can't disable EPSV when doing IPv6, so this is instead a fail */
failf(conn->data, "Failed EPSV attempt, exiting\n");
return CURLE_WEIRD_SERVER_REPLY;
@@ -1784,9 +1796,10 @@ static char *control_address(struct connectdata *conn)
If a proxy tunnel is used, returns the original host name instead, because
the effective control connection address is the proxy address,
not the ftp host. */
+#ifndef CURL_DISABLE_PROXY
if(conn->bits.tunnel_proxy || conn->bits.socksproxy)
return conn->host.name;
-
+#endif
return conn->ip_addr_str;
}
@@ -1903,6 +1916,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
return CURLE_FTP_WEIRD_PASV_REPLY;
}
+#ifndef CURL_DISABLE_PROXY
if(conn->bits.proxy) {
/*
* This connection uses a proxy and we need to connect to the proxy again
@@ -1925,7 +1939,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
return CURLE_COULDNT_RESOLVE_PROXY;
}
}
- else {
+ else
+#endif
+ {
/* normal, direct, ftp connection */
rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, FALSE, &addr);
if(rc == CURLRESOLV_PENDING)
@@ -2634,9 +2650,12 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
#endif
if(data->set.use_ssl &&
- (!conn->ssl[FIRSTSOCKET].use ||
- (conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
- !conn->proxy_ssl[FIRSTSOCKET].use))) {
+ (!conn->ssl[FIRSTSOCKET].use
+#ifndef CURL_DISABLE_PROXY
+ || (conn->bits.proxy_ssl_connected[FIRSTSOCKET] &&
+ !conn->proxy_ssl[FIRSTSOCKET].use)
+#endif
+ )) {
/* We don't have a SSL/TLS connection yet, but FTPS is
requested. Try a FTPS connection now */
@@ -2808,7 +2827,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
store++;
ptr++;
}
- *store = '\0'; /* zero terminate */
+ *store = '\0'; /* null-terminate */
}
if(entry_extracted) {
/* If the path name does not look like an absolute path (i.e.: it
@@ -2872,7 +2891,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
ptr++;
for(store = os; *ptr && *ptr != ' ';)
*store++ = *ptr++;
- *store = '\0'; /* zero terminate */
+ *store = '\0'; /* null-terminate */
/* Check for special servers here. */
@@ -3175,7 +3194,8 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
if(!result)
/* get the url-decoded "raw" path */
- result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, TRUE);
+ result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen,
+ REJECT_CTRL);
if(result) {
/* We can limp along anyway (and should try to since we may already be in
* the error path) */
@@ -3231,9 +3251,9 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
}
if(conn->ssl[SECONDARYSOCKET].use) {
- /* The secondary socket is using SSL so we must close down that part
- first before we close the socket for real */
- Curl_ssl_close(conn, SECONDARYSOCKET);
+ /* The secondary socket used SSL so we must close down that part first
+ before we close the socket for real */
+ result = Curl_ssl_shutdown(conn, SECONDARYSOCKET);
/* Note that we keep "use" set to TRUE since that (next) connection is
still requested to use SSL */
@@ -3249,7 +3269,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
* data has been transferred. This happens when doing through NATs etc that
* abandon old silent connections.
*/
- long old_time = pp->response_time;
+ timediff_t old_time = pp->response_time;
pp->response_time = 60*1000; /* give it only a minute for now */
pp->response = Curl_now(); /* timeout relative now */
@@ -3442,7 +3462,7 @@ static CURLcode ftp_nb_type(struct connectdata *conn,
#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void
ftp_pasv_verbose(struct connectdata *conn,
- Curl_addrinfo *ai,
+ struct Curl_addrinfo *ai,
char *newhost, /* ascii version */
int port)
{
@@ -3500,6 +3520,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
}
}
+#ifndef CURL_DISABLE_PROXY
result = Curl_proxy_connect(conn, SECONDARYSOCKET);
if(result)
return result;
@@ -3510,7 +3531,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
Curl_connect_ongoing(conn))
return result;
-
+#endif
if(ftpc->state) {
/* already in a state so skip the initial commands.
@@ -4090,7 +4111,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn)
ftpc->cwdfail = FALSE;
/* url-decode ftp path before further evaluation */
- result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, TRUE);
+ result = Curl_urldecode(data, ftp->path, 0, &rawPath, &pathLen, REJECT_CTRL);
if(result)
return result;
@@ -4337,7 +4358,6 @@ static CURLcode ftp_setup_connection(struct connectdata *conn)
char command;
*type = 0; /* it was in the middle of the hostname */
command = Curl_raw_toupper(type[6]);
- conn->bits.type_set = TRUE;
switch(command) {
case 'A': /* ASCII mode */
diff --git a/lib/getinfo.c b/lib/getinfo.c
index ae29a44f9..c4444f589 100644
--- a/lib/getinfo.c
+++ b/lib/getinfo.c
@@ -198,9 +198,11 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info,
case CURLINFO_SSL_VERIFYRESULT:
*param_longp = data->set.ssl.certverifyresult;
break;
+#ifndef CURL_DISABLE_PROXY
case CURLINFO_PROXY_SSL_VERIFYRESULT:
*param_longp = data->set.proxy_ssl.certverifyresult;
break;
+#endif
case CURLINFO_REDIRECT_COUNT:
*param_longp = data->set.followlocation;
break;
@@ -320,7 +322,7 @@ static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info,
*param_offt = data->progress.downloaded;
break;
case CURLINFO_SPEED_DOWNLOAD_T:
- *param_offt = data->progress.dlspeed;
+ *param_offt = data->progress.dlspeed;
break;
case CURLINFO_SPEED_UPLOAD_T:
*param_offt = data->progress.ulspeed;
@@ -408,13 +410,13 @@ static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info,
*param_doublep = DOUBLE_SECS(data->progress.t_starttransfer);
break;
case CURLINFO_SIZE_UPLOAD:
- *param_doublep = (double)data->progress.uploaded;
+ *param_doublep = (double)data->progress.uploaded;
break;
case CURLINFO_SIZE_DOWNLOAD:
*param_doublep = (double)data->progress.downloaded;
break;
case CURLINFO_SPEED_DOWNLOAD:
- *param_doublep = (double)data->progress.dlspeed;
+ *param_doublep = (double)data->progress.dlspeed;
break;
case CURLINFO_SPEED_UPLOAD:
*param_doublep = (double)data->progress.ulspeed;
diff --git a/lib/gopher.c b/lib/gopher.c
index 3b47b1803..fd10926b2 100644
--- a/lib/gopher.c
+++ b/lib/gopher.c
@@ -116,7 +116,7 @@ static CURLcode gopher_do(struct connectdata *conn, bool *done)
newp += 2;
/* ... and finally unescape */
- result = Curl_urldecode(data, newp, 0, &sel, &len, FALSE);
+ result = Curl_urldecode(data, newp, 0, &sel, &len, REJECT_ZERO);
free(gopherpath);
if(result)
return result;
diff --git a/lib/hmac.c b/lib/hmac.c
index e7b582621..c180b5963 100644
--- a/lib/hmac.c
+++ b/lib/hmac.c
@@ -48,13 +48,13 @@ static const unsigned char hmac_opad = 0x5C;
-HMAC_context *
-Curl_HMAC_init(const HMAC_params * hashparams,
+struct HMAC_context *
+Curl_HMAC_init(const struct HMAC_params *hashparams,
const unsigned char *key,
unsigned int keylen)
{
size_t i;
- HMAC_context *ctxt;
+ struct HMAC_context *ctxt;
unsigned char *hkey;
unsigned char b;
@@ -101,7 +101,7 @@ Curl_HMAC_init(const HMAC_params * hashparams,
return ctxt;
}
-int Curl_HMAC_update(HMAC_context * ctxt,
+int Curl_HMAC_update(struct HMAC_context *ctxt,
const unsigned char *data,
unsigned int len)
{
@@ -111,9 +111,9 @@ int Curl_HMAC_update(HMAC_context * ctxt,
}
-int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result)
+int Curl_HMAC_final(struct HMAC_context *ctxt, unsigned char *result)
{
- const HMAC_params * hashparams = ctxt->hmac_hash;
+ const struct HMAC_params *hashparams = ctxt->hmac_hash;
/* Do not get result if called with a null parameter: only release
storage. */
@@ -147,12 +147,13 @@ int Curl_HMAC_final(HMAC_context *ctxt, unsigned char *result)
*
* Returns CURLE_OK on success.
*/
-CURLcode Curl_hmacit(const HMAC_params *hashparams,
+CURLcode Curl_hmacit(const struct HMAC_params *hashparams,
const unsigned char *key, const size_t keylen,
const unsigned char *data, const size_t datalen,
unsigned char *output)
{
- HMAC_context *ctxt = Curl_HMAC_init(hashparams, key, curlx_uztoui(keylen));
+ struct HMAC_context *ctxt =
+ Curl_HMAC_init(hashparams, key, curlx_uztoui(keylen));
if(!ctxt)
return CURLE_OUT_OF_MEMORY;
diff --git a/lib/hostasyn.c b/lib/hostasyn.c
index 99d872b35..ed9190f4c 100644
--- a/lib/hostasyn.c
+++ b/lib/hostasyn.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -117,10 +117,10 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
* name resolve layers (selected at build-time). They all take this same set
* of arguments
*/
-Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
- const char *hostname,
- int port,
- int *waitp)
+struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
{
return Curl_resolver_getaddrinfo(conn, hostname, port, waitp);
}
diff --git a/lib/hostip.c b/lib/hostip.c
index c0feb79fb..dd5916e33 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -120,7 +120,7 @@ static void freednsentry(void *freethis);
/*
* Return # of addresses in a Curl_addrinfo struct
*/
-int Curl_num_addresses(const Curl_addrinfo *addr)
+int Curl_num_addresses(const struct Curl_addrinfo *addr)
{
int i = 0;
while(addr) {
@@ -131,39 +131,36 @@ int Curl_num_addresses(const Curl_addrinfo *addr)
}
/*
- * Curl_printable_address() returns a printable version of the 1st address
+ * Curl_printable_address() stores a printable version of the 1st address
* given in the 'ai' argument. The result will be stored in the buf that is
* bufsize bytes big.
*
- * If the conversion fails, it returns NULL.
+ * If the conversion fails, the target buffer is empty.
*/
-const char *
-Curl_printable_address(const Curl_addrinfo *ai, char *buf, size_t bufsize)
+void Curl_printable_address(const struct Curl_addrinfo *ai, char *buf,
+ size_t bufsize)
{
- const struct sockaddr_in *sa4;
- const struct in_addr *ipaddr4;
-#ifdef ENABLE_IPV6
- const struct sockaddr_in6 *sa6;
- const struct in6_addr *ipaddr6;
-#endif
+ DEBUGASSERT(bufsize);
+ buf[0] = 0;
switch(ai->ai_family) {
- case AF_INET:
- sa4 = (const void *)ai->ai_addr;
- ipaddr4 = &sa4->sin_addr;
- return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf,
- bufsize);
+ case AF_INET: {
+ const struct sockaddr_in *sa4 = (const void *)ai->ai_addr;
+ const struct in_addr *ipaddr4 = &sa4->sin_addr;
+ (void)Curl_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, bufsize);
+ break;
+ }
#ifdef ENABLE_IPV6
- case AF_INET6:
- sa6 = (const void *)ai->ai_addr;
- ipaddr6 = &sa6->sin6_addr;
- return Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf,
- bufsize);
+ case AF_INET6: {
+ const struct sockaddr_in6 *sa6 = (const void *)ai->ai_addr;
+ const struct in6_addr *ipaddr6 = &sa6->sin6_addr;
+ (void)Curl_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf, bufsize);
+ break;
+ }
#endif
- default:
- break;
+ default:
+ break;
}
- return NULL;
}
/*
@@ -337,7 +334,7 @@ Curl_fetch_addr(struct connectdata *conn,
#ifndef CURL_DISABLE_SHUFFLE_DNS
UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
- Curl_addrinfo **addr);
+ struct Curl_addrinfo **addr);
/*
* Curl_shuffle_addr() shuffles the order of addresses in a 'Curl_addrinfo'
* struct by re-linking its linked list.
@@ -351,13 +348,13 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
* @unittest: 1608
*/
UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
- Curl_addrinfo **addr)
+ struct Curl_addrinfo **addr)
{
CURLcode result = CURLE_OK;
const int num_addrs = Curl_num_addresses(*addr);
if(num_addrs > 1) {
- Curl_addrinfo **nodes;
+ struct Curl_addrinfo **nodes;
infof(data, "Shuffling %i addresses", num_addrs);
nodes = malloc(num_addrs*sizeof(*nodes));
@@ -376,7 +373,7 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
if(rnd) {
/* Fisher-Yates shuffle */
if(Curl_rand(data, (unsigned char *)rnd, rnd_size) == CURLE_OK) {
- Curl_addrinfo *swap_tmp;
+ struct Curl_addrinfo *swap_tmp;
for(i = num_addrs - 1; i > 0; i--) {
swap_tmp = nodes[rnd[i] % (i + 1)];
nodes[rnd[i] % (i + 1)] = nodes[i];
@@ -415,7 +412,7 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data,
*/
struct Curl_dns_entry *
Curl_cache_addr(struct Curl_easy *data,
- Curl_addrinfo *addr,
+ struct Curl_addrinfo *addr,
const char *hostname,
int port)
{
@@ -495,6 +492,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
enum resolve_t rc = CURLRESOLV_ERROR; /* default to failure */
*entry = NULL;
+ conn->bits.doh = FALSE; /* default is not */
if(data->share)
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
@@ -513,11 +511,13 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
if(!dns) {
/* The entry was not in the cache. Resolve it to IP address */
- Curl_addrinfo *addr = NULL;
+ struct Curl_addrinfo *addr = NULL;
int respwait = 0;
-#ifndef USE_RESOLVE_ON_IPS
struct in_addr in;
+#ifndef USE_RESOLVE_ON_IPS
+ const
#endif
+ bool ipnum = FALSE;
/* notify the resolver start callback */
if(data->set.resolver_start) {
@@ -544,6 +544,22 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
addr = Curl_ip2addr(AF_INET6, &in6, hostname, port);
}
#endif /* ENABLE_IPV6 */
+
+#else /* if USE_RESOLVE_ON_IPS */
+ /* First check if this is an IPv4 address string */
+ if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
+ /* This is a dotted IP address 123.123.123.123-style */
+ ipnum = TRUE;
+#ifdef ENABLE_IPV6
+ else {
+ struct in6_addr in6;
+ /* check if this is an IPv6 address string */
+ if(Curl_inet_pton(AF_INET6, hostname, &in6) > 0)
+ /* This is an IPv6 address literal */
+ ipnum = TRUE;
+ }
+#endif /* ENABLE_IPV6 */
+
#endif /* !USE_RESOLVE_ON_IPS */
if(!addr) {
@@ -552,7 +568,7 @@ enum resolve_t Curl_resolv(struct connectdata *conn,
if(!Curl_ipvalid(conn))
return CURLRESOLV_ERROR;
- if(allowDOH && data->set.doh) {
+ if(allowDOH && data->set.doh && !ipnum) {
addr = Curl_doh(conn, hostname, port, &respwait);
}
else {
@@ -890,7 +906,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
}
else {
struct Curl_dns_entry *dns;
- Curl_addrinfo *head = NULL, *tail = NULL;
+ struct Curl_addrinfo *head = NULL, *tail = NULL;
size_t entry_len;
char address[64];
#if !defined(CURL_DISABLE_VERBOSE_STRINGS)
@@ -924,7 +940,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data)
while(*end_ptr) {
size_t alen;
- Curl_addrinfo *ai;
+ struct Curl_addrinfo *ai;
addr_begin = end_ptr + 1;
addr_end = strchr(addr_begin, ',');
@@ -1047,7 +1063,7 @@ CURLcode Curl_resolv_check(struct connectdata *conn,
(void)dns;
#endif
- if(conn->data->set.doh)
+ if(conn->bits.doh)
return Curl_doh_is_resolved(conn, dns);
return Curl_resolver_is_resolved(conn, dns);
}
@@ -1056,7 +1072,7 @@ int Curl_resolv_getsock(struct connectdata *conn,
curl_socket_t *socks)
{
#ifdef CURLRES_ASYNCH
- if(conn->data->set.doh)
+ if(conn->bits.doh)
/* nothing to wait for during DOH resolve, those handles have their own
sockets */
return GETSOCK_BLANK;
@@ -1085,10 +1101,12 @@ CURLcode Curl_once_resolved(struct connectdata *conn,
result = Curl_setup_conn(conn, protocol_done);
- if(result)
- /* We're not allowed to return failure with memory left allocated
- in the connectdata struct, free those here */
- Curl_disconnect(conn->data, conn, TRUE); /* close the connection */
-
+ if(result) {
+ struct Curl_easy *data = conn->data;
+ DEBUGASSERT(data);
+ Curl_detach_connnection(data);
+ Curl_conncache_remove_conn(data, conn, TRUE);
+ Curl_disconnect(data, conn, TRUE);
+ }
return result;
}
diff --git a/lib/hostip.h b/lib/hostip.h
index baf1e5860..374b06c85 100644
--- a/lib/hostip.h
+++ b/lib/hostip.h
@@ -64,7 +64,7 @@ struct connectdata;
struct curl_hash *Curl_global_host_cache_init(void);
struct Curl_dns_entry {
- Curl_addrinfo *addr;
+ struct Curl_addrinfo *addr;
/* timestamp == 0 -- CURLOPT_RESOLVE entry, doesn't timeout */
time_t timestamp;
/* use-counter, use Curl_resolv_unlock to release reference */
@@ -117,10 +117,10 @@ bool Curl_ipvalid(struct connectdata *conn);
* name resolve layers (selected at build-time). They all take this same set
* of arguments
*/
-Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
- const char *hostname,
- int port,
- int *waitp);
+struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp);
/* unlock a previously resolved dns entry */
@@ -134,7 +134,7 @@ int Curl_mk_dnscache(struct curl_hash *hash);
void Curl_hostcache_prune(struct Curl_easy *data);
/* Return # of addresses in a Curl_addrinfo struct */
-int Curl_num_addresses(const Curl_addrinfo *addr);
+int Curl_num_addresses(const struct Curl_addrinfo *addr);
#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO)
int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
@@ -146,7 +146,7 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
#endif
/* IPv4 threadsafe resolve function used for synch and asynch builds */
-Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
+struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port);
CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect);
@@ -158,15 +158,15 @@ CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect);
*/
CURLcode Curl_addrinfo_callback(struct connectdata *conn,
int status,
- Curl_addrinfo *ai);
+ struct Curl_addrinfo *ai);
/*
* Curl_printable_address() returns a printable version of the 1st address
* given in the 'ip' argument. The result will be stored in the buf that is
* bufsize bytes big.
*/
-const char *Curl_printable_address(const Curl_addrinfo *ip,
- char *buf, size_t bufsize);
+void Curl_printable_address(const struct Curl_addrinfo *ip,
+ char *buf, size_t bufsize);
/*
* Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache.
@@ -187,7 +187,7 @@ Curl_fetch_addr(struct connectdata *conn,
* Returns the Curl_dns_entry entry pointer or NULL if the storage failed.
*/
struct Curl_dns_entry *
-Curl_cache_addr(struct Curl_easy *data, Curl_addrinfo *addr,
+Curl_cache_addr(struct Curl_easy *data, struct Curl_addrinfo *addr,
const char *hostname, int port);
#ifndef INADDR_NONE
diff --git a/lib/hostip4.c b/lib/hostip4.c
index d5009a3ef..eae941674 100644
--- a/lib/hostip4.c
+++ b/lib/hostip4.c
@@ -88,12 +88,12 @@ bool Curl_ipvalid(struct connectdata *conn)
* flavours have thread-safe versions of the plain gethostbyname() etc.
*
*/
-Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
- const char *hostname,
- int port,
- int *waitp)
+struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
{
- Curl_addrinfo *ai = NULL;
+ struct Curl_addrinfo *ai = NULL;
#ifdef CURL_DISABLE_VERBOSE_STRINGS
(void)conn;
@@ -119,13 +119,13 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
* implying that only threadsafe code and function calls may be used.
*
*/
-Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
- int port)
+struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
+ int port)
{
#if !defined(HAVE_GETADDRINFO_THREADSAFE) && defined(HAVE_GETHOSTBYNAME_R_3)
int res;
#endif
- Curl_addrinfo *ai = NULL;
+ struct Curl_addrinfo *ai = NULL;
struct hostent *h = NULL;
struct hostent *buf = NULL;
diff --git a/lib/hostip6.c b/lib/hostip6.c
index 41ff98696..11215758d 100644
--- a/lib/hostip6.c
+++ b/lib/hostip6.c
@@ -103,20 +103,16 @@ bool Curl_ipvalid(struct connectdata *conn)
#if defined(CURLRES_SYNCH)
#ifdef DEBUG_ADDRINFO
-static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
+static void dump_addrinfo(struct connectdata *conn,
+ const struct Curl_addrinfo *ai)
{
printf("dump_addrinfo:\n");
for(; ai; ai = ai->ai_next) {
char buf[INET6_ADDRSTRLEN];
printf(" fam %2d, CNAME %s, ",
ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
- if(Curl_printable_address(ai, buf, sizeof(buf)))
- printf("%s\n", buf);
- else {
- char buffer[STRERROR_LEN];
- printf("failed; %s\n",
- Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
- }
+ Curl_printable_address(ai, buf, sizeof(buf));
+ printf("%s\n", buf);
}
}
#else
@@ -132,13 +128,13 @@ static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
* memory we need to free after use. That memory *MUST* be freed with
* Curl_freeaddrinfo(), nothing else.
*/
-Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
- const char *hostname,
- int port,
- int *waitp)
+struct Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
+ const char *hostname,
+ int port,
+ int *waitp)
{
struct addrinfo hints;
- Curl_addrinfo *res;
+ struct Curl_addrinfo *res;
int error;
char sbuf[12];
char *sbufptr = NULL;
diff --git a/lib/http.c b/lib/http.c
index b27f1556f..3601015da 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -125,7 +125,8 @@ const struct Curl_handler Curl_handler_http = {
ZERO_NULL, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTP, /* protocol */
- PROTOPT_CREDSPERREQUEST /* flags */
+ PROTOPT_CREDSPERREQUEST | /* flags */
+ PROTOPT_USERPWDCTRL
};
#ifdef USE_SSL
@@ -150,7 +151,8 @@ const struct Curl_handler Curl_handler_https = {
ZERO_NULL, /* connection_check */
PORT_HTTPS, /* defport */
CURLPROTO_HTTPS, /* protocol */
- PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN /* flags */
+ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN | /* flags */
+ PROTOPT_USERPWDCTRL
};
#endif
@@ -268,7 +270,7 @@ char *Curl_copy_header_value(const char *header)
return NULL;
memcpy(value, start, len);
- value[len] = 0; /* zero terminate */
+ value[len] = 0; /* null-terminate */
return value;
}
@@ -292,17 +294,21 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
char *out;
if(proxy) {
- userp = &conn->allocptr.proxyuserpwd;
+#ifndef CURL_DISABLE_PROXY
+ userp = &data->state.aptr.proxyuserpwd;
user = conn->http_proxy.user;
pwd = conn->http_proxy.passwd;
+#else
+ return CURLE_NOT_BUILT_IN;
+#endif
}
else {
- userp = &conn->allocptr.userpwd;
+ userp = &data->state.aptr.userpwd;
user = conn->user;
pwd = conn->passwd;
}
- out = aprintf("%s:%s", user, pwd);
+ out = aprintf("%s:%s", user, pwd ? pwd : "");
if(!out)
return CURLE_OUT_OF_MEMORY;
@@ -340,8 +346,9 @@ static CURLcode http_output_bearer(struct connectdata *conn)
{
char **userp;
CURLcode result = CURLE_OK;
+ struct Curl_easy *data = conn->data;
- userp = &conn->allocptr.userpwd;
+ userp = &data->state.aptr.userpwd;
free(*userp);
*userp = aprintf("Authorization: Bearer %s\r\n",
conn->data->set.str[STRING_BEARER]);
@@ -427,7 +434,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
skip this rewinding stuff */
return CURLE_OK;
- switch(data->set.httpreq) {
+ switch(data->state.httpreq) {
case HTTPREQ_GET:
case HTTPREQ_HEAD:
return CURLE_OK;
@@ -448,7 +455,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
}
else {
/* figure out how much data we are expected to send */
- switch(data->set.httpreq) {
+ switch(data->state.httpreq) {
case HTTPREQ_POST:
case HTTPREQ_PUT:
if(data->state.infilesize != -1)
@@ -578,6 +585,7 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
conn->data->set.httpversion = CURL_HTTP_VERSION_1_1;
}
}
+#ifndef CURL_DISABLE_PROXY
if(conn->bits.proxy_user_passwd &&
((data->req.httpcode == 407) ||
(conn->bits.authneg && data->req.httpcode < 300))) {
@@ -586,10 +594,11 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
if(!pickproxy)
data->state.authproblem = TRUE;
}
+#endif
if(pickhost || pickproxy) {
- if((data->set.httpreq != HTTPREQ_GET) &&
- (data->set.httpreq != HTTPREQ_HEAD) &&
+ if((data->state.httpreq != HTTPREQ_GET) &&
+ (data->state.httpreq != HTTPREQ_HEAD) &&
!conn->bits.rewindaftersend) {
result = http_perhapsrewind(conn);
if(result)
@@ -610,8 +619,8 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
authentication is not "done" yet and
no authentication seems to be required and
we didn't try HEAD or GET */
- if((data->set.httpreq != HTTPREQ_GET) &&
- (data->set.httpreq != HTTPREQ_HEAD)) {
+ if((data->state.httpreq != HTTPREQ_GET) &&
+ (data->state.httpreq != HTTPREQ_HEAD)) {
data->req.newurl = strdup(data->change.url); /* clone URL */
if(!data->req.newurl)
return CURLE_OUT_OF_MEMORY;
@@ -689,10 +698,13 @@ output_auth_headers(struct connectdata *conn,
#endif
if(authstatus->picked == CURLAUTH_BASIC) {
/* Basic */
- if((proxy && conn->bits.proxy_user_passwd &&
- !Curl_checkProxyheaders(conn, "Proxy-authorization")) ||
- (!proxy && conn->bits.user_passwd &&
- !Curl_checkheaders(conn, "Authorization"))) {
+ if(
+#ifndef CURL_DISABLE_PROXY
+ (proxy && conn->bits.proxy_user_passwd &&
+ !Curl_checkProxyheaders(conn, "Proxy-authorization")) ||
+#endif
+ (!proxy && conn->bits.user_passwd &&
+ !Curl_checkheaders(conn, "Authorization"))) {
auth = "Basic";
result = http_output_basic(conn, proxy);
if(result)
@@ -719,10 +731,15 @@ output_auth_headers(struct connectdata *conn,
}
if(auth) {
+#ifndef CURL_DISABLE_PROXY
infof(data, "%s auth using %s with user '%s'\n",
proxy ? "Proxy" : "Server", auth,
proxy ? (conn->http_proxy.user ? conn->http_proxy.user : "") :
- (conn->user ? conn->user : ""));
+ (conn->user ? conn->user : ""));
+#else
+ infof(data, "Server auth using %s with user '%s'\n",
+ auth, conn->user ? conn->user : "");
+#endif
authstatus->multipass = (!authstatus->done) ? TRUE : FALSE;
}
else
@@ -762,7 +779,10 @@ Curl_http_output_auth(struct connectdata *conn,
authhost = &data->state.authhost;
authproxy = &data->state.authproxy;
- if((conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
+ if(
+#ifndef CURL_DISABLE_PROXY
+ (conn->bits.httpproxy && conn->bits.proxy_user_passwd) ||
+#endif
conn->bits.user_passwd || data->set.str[STRING_BEARER])
/* continue please */;
else {
@@ -1067,8 +1087,10 @@ static int http_should_fail(struct connectdata *conn)
*/
if((httpcode == 401) && !conn->bits.user_passwd)
return TRUE;
+#ifndef CURL_DISABLE_PROXY
if((httpcode == 407) && !conn->bits.proxy_user_passwd)
return TRUE;
+#endif
return data->state.authproblem;
}
@@ -1125,49 +1147,20 @@ static size_t readmoredata(char *buffer,
return fullsize;
}
-/* ------------------------------------------------------------------------- */
-/* add_buffer functions */
-
-/*
- * Curl_add_buffer_init() sets up and returns a fine buffer struct
- */
-Curl_send_buffer *Curl_add_buffer_init(void)
-{
- return calloc(1, sizeof(Curl_send_buffer));
-}
-
-/*
- * Curl_add_buffer_free() frees all associated resources.
- */
-void Curl_add_buffer_free(Curl_send_buffer **inp)
-{
- Curl_send_buffer *in;
- if(!inp)
- return;
- in = *inp;
- if(in) { /* deal with NULL input */
- free(in->buffer);
- free(in);
- }
- *inp = NULL;
-}
-
/*
- * Curl_add_buffer_send() sends a header buffer and frees all associated
+ * Curl_buffer_send() sends a header buffer and frees all associated
* memory. Body data may be appended to the header data if desired.
*
* Returns CURLcode
*/
-CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
- struct connectdata *conn,
-
- /* add the number of sent bytes to this
- counter */
- curl_off_t *bytes_written,
-
- /* how much of the buffer contains body data */
- size_t included_body_bytes,
- int socketindex)
+CURLcode Curl_buffer_send(struct dynbuf *in,
+ struct connectdata *conn,
+ /* add the number of sent bytes to this
+ counter */
+ curl_off_t *bytes_written,
+ /* how much of the buffer contains body data */
+ size_t included_body_bytes,
+ int socketindex)
{
ssize_t amount;
CURLcode result;
@@ -1178,7 +1171,6 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
size_t sendsize;
curl_socket_t sockfd;
size_t headersize;
- Curl_send_buffer *in = *inp;
DEBUGASSERT(socketindex <= SECONDARYSOCKET);
@@ -1187,8 +1179,8 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
/* The looping below is required since we use non-blocking sockets, but due
to the circumstances we will just loop and try again and again etc */
- ptr = in->buffer;
- size = in->size_used;
+ ptr = Curl_dyn_ptr(in);
+ size = Curl_dyn_len(in);
headersize = size - included_body_bytes; /* the initial part that isn't body
is header */
@@ -1199,12 +1191,15 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
/* Curl_convert_to_network calls failf if unsuccessful */
if(result) {
/* conversion failed, free memory and return to the caller */
- Curl_add_buffer_free(inp);
+ Curl_dyn_free(in);
return result;
}
- if((conn->handler->flags & PROTOPT_SSL ||
- conn->http_proxy.proxytype == CURLPROXY_HTTPS)
+ if((conn->handler->flags & PROTOPT_SSL
+#ifndef CURL_DISABLE_PROXY
+ || conn->http_proxy.proxytype == CURLPROXY_HTTPS
+#endif
+ )
&& conn->httpversion != 20) {
/* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
when we speak HTTPS, as if only a fraction of it is sent now, this data
@@ -1223,7 +1218,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
result = Curl_get_upload_buffer(data);
if(result) {
/* malloc failed, free memory and return to the caller */
- Curl_add_buffer_free(&in);
+ Curl_dyn_free(in);
return result;
}
memcpy(data->state.ulbuf, ptr, sendsize);
@@ -1286,7 +1281,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
size -= amount;
- ptr = in->buffer + amount;
+ ptr = Curl_dyn_ptr(in) + amount;
/* backup the currently set pointers */
http->backup.fread_func = data->state.fread_func;
@@ -1300,7 +1295,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
http->postdata = ptr;
http->postsize = (curl_off_t)size;
- http->send_buffer = in;
+ http->send_buffer = *in; /* copy the whole struct */
http->sending = HTTPSEND_REQUEST;
return CURLE_OK;
@@ -1320,87 +1315,11 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
return CURLE_SEND_ERROR;
}
}
- Curl_add_buffer_free(&in);
+ Curl_dyn_free(in);
return result;
}
-
-/*
- * add_bufferf() add the formatted input to the buffer.
- */
-CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...)
-{
- char *s;
- va_list ap;
- va_start(ap, fmt);
- s = vaprintf(fmt, ap); /* this allocs a new string to append */
- va_end(ap);
-
- if(s) {
- CURLcode result = Curl_add_buffer(inp, s, strlen(s));
- free(s);
- return result;
- }
- /* If we failed, we cleanup the whole buffer and return error */
- Curl_add_buffer_free(inp);
- return CURLE_OUT_OF_MEMORY;
-}
-
-/*
- * Curl_add_buffer() appends a memory chunk to the existing buffer
- */
-CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr,
- size_t size)
-{
- char *new_rb;
- Curl_send_buffer *in = *inp;
-
- if(~size < in->size_used) {
- /* If resulting used size of send buffer would wrap size_t, cleanup
- the whole buffer and return error. Otherwise the required buffer
- size will fit into a single allocatable memory chunk */
- Curl_add_buffer_free(inp);
- return CURLE_OUT_OF_MEMORY;
- }
-
- if(!in->buffer ||
- ((in->size_used + size) > (in->size_max - 1))) {
- /* If current buffer size isn't enough to hold the result, use a
- buffer size that doubles the required size. If this new size
- would wrap size_t, then just use the largest possible one */
- size_t new_size;
-
- if((size > (size_t)-1 / 2) || (in->size_used > (size_t)-1 / 2) ||
- (~(size * 2) < (in->size_used * 2)))
- new_size = (size_t)-1;
- else
- new_size = (in->size_used + size) * 2;
-
- if(in->buffer)
- /* we have a buffer, enlarge the existing one */
- new_rb = Curl_saferealloc(in->buffer, new_size);
- else
- /* create a new buffer */
- new_rb = malloc(new_size);
-
- if(!new_rb) {
- /* If we failed, we cleanup the whole buffer and return error */
- free(in);
- *inp = NULL;
- return CURLE_OUT_OF_MEMORY;
- }
-
- in->buffer = new_rb;
- in->size_max = new_size;
- }
- memcpy(&in->buffer[in->size_used], inptr, size);
-
- in->size_used += size;
-
- return CURLE_OK;
-}
-
/* end of the add_buffer functions */
/* ------------------------------------------------------------------------- */
@@ -1473,6 +1392,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
function to make the re-use checks properly be able to check this bit. */
connkeep(conn, "HTTP default");
+#ifndef CURL_DISABLE_PROXY
/* the CONNECT procedure might not have been completed */
result = Curl_proxy_connect(conn, FIRSTSOCKET);
if(result)
@@ -1489,7 +1409,6 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done)
/* nothing else to do except wait right now - we're not done here. */
return CURLE_OK;
-#ifndef CURL_DISABLE_PROXY
if(conn->data->set.haproxyprotocol) {
/* add HAProxy PROXY protocol header */
result = add_haproxy_protocol_header(conn);
@@ -1525,7 +1444,7 @@ static int http_getsock_do(struct connectdata *conn,
static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
{
char proxy_header[128];
- Curl_send_buffer *req_buffer;
+ struct dynbuf req;
CURLcode result;
char tcp_version[5];
@@ -1546,19 +1465,14 @@ static CURLcode add_haproxy_protocol_header(struct connectdata *conn)
conn->data->info.conn_local_port,
conn->data->info.conn_primary_port);
- req_buffer = Curl_add_buffer_init();
- if(!req_buffer)
- return CURLE_OUT_OF_MEMORY;
+ Curl_dyn_init(&req, DYN_HAXPROXY);
- result = Curl_add_bufferf(&req_buffer, proxy_header);
+ result = Curl_dyn_add(&req, proxy_header);
if(result)
return result;
- result = Curl_add_buffer_send(&req_buffer,
- conn,
- &conn->data->info.request_size,
- 0,
- FIRSTSOCKET);
+ result = Curl_buffer_send(&req, conn, &conn->data->info.request_size,
+ 0, FIRSTSOCKET);
return result;
}
@@ -1619,14 +1533,11 @@ CURLcode Curl_http_done(struct connectdata *conn,
if(!http)
return CURLE_OK;
- if(http->send_buffer) {
- Curl_add_buffer_free(&http->send_buffer);
- }
-
+ Curl_dyn_free(&http->send_buffer);
Curl_http2_done(data, premature);
Curl_quic_done(data, premature);
-
Curl_mime_cleanpart(&http->form);
+ Curl_dyn_reset(&data->state.headerb);
if(status)
return status;
@@ -1692,7 +1603,7 @@ static const char *get_http_string(const struct Curl_easy *data,
/* check and possibly add an Expect: header */
static CURLcode expect100(struct Curl_easy *data,
struct connectdata *conn,
- Curl_send_buffer *req_buffer)
+ struct dynbuf *req)
{
CURLcode result = CURLE_OK;
data->state.expect100header = FALSE; /* default to false unless it is set
@@ -1708,8 +1619,7 @@ static CURLcode expect100(struct Curl_easy *data,
Curl_compareheader(ptr, "Expect:", "100-continue");
}
else {
- result = Curl_add_bufferf(&req_buffer,
- "Expect: 100-continue\r\n");
+ result = Curl_dyn_add(req, "Expect: 100-continue\r\n");
if(!result)
data->state.expect100header = TRUE;
}
@@ -1728,7 +1638,7 @@ enum proxy_use {
will return an error code if one of the headers is
not formatted correctly */
CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
- Curl_send_buffer **buffer,
+ struct dynbuf *b,
struct Curl_easy *handle)
{
char *ptr = NULL;
@@ -1754,8 +1664,10 @@ CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
/* only add correctly formatted trailers */
ptr = strchr(trailers->data, ':');
if(ptr && *(ptr + 1) == ' ') {
- result = Curl_add_bufferf(buffer, "%s%s", trailers->data,
- endofline_native);
+ result = Curl_dyn_add(b, trailers->data);
+ if(result)
+ return result;
+ result = Curl_dyn_add(b, endofline_native);
if(result)
return result;
}
@@ -1763,14 +1675,13 @@ CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
infof(handle, "Malformatted trailing header ! Skipping trailer.");
trailers = trailers->next;
}
- result = Curl_add_buffer(buffer, endofline_network,
- strlen(endofline_network));
+ result = Curl_dyn_add(b, endofline_network);
return result;
}
CURLcode Curl_add_custom_headers(struct connectdata *conn,
bool is_connect,
- Curl_send_buffer *req_buffer)
+ struct dynbuf *req)
{
char *ptr;
struct curl_slist *h[2];
@@ -1779,6 +1690,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
struct Curl_easy *data = conn->data;
int i;
+#ifndef CURL_DISABLE_PROXY
enum proxy_use proxy;
if(is_connect)
@@ -1805,6 +1717,10 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
h[0] = data->set.headers;
break;
}
+#else
+ (void)is_connect;
+ h[0] = data->set.headers;
+#endif
/* loop through one or two lists */
for(i = 0; i < numlists; i++) {
@@ -1832,7 +1748,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
/* copy the source */
semicolonp = strdup(headers->data);
if(!semicolonp) {
- Curl_add_buffer_free(&req_buffer);
+ Curl_dyn_free(req);
return CURLE_OUT_OF_MEMORY;
}
/* put a colon where the semicolon is */
@@ -1856,16 +1772,16 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
CURLcode result = CURLE_OK;
char *compare = semicolonp ? semicolonp : headers->data;
- if(conn->allocptr.host &&
+ if(data->state.aptr.host &&
/* a Host: header was sent already, don't pass on any custom Host:
header as that will produce *two* in the same request! */
checkprefix("Host:", compare))
;
- else if(data->set.httpreq == HTTPREQ_POST_FORM &&
+ else if(data->state.httpreq == HTTPREQ_POST_FORM &&
/* this header (extended by formdata.c) is sent later */
checkprefix("Content-Type:", compare))
;
- else if(data->set.httpreq == HTTPREQ_POST_MIME &&
+ else if(data->state.httpreq == HTTPREQ_POST_MIME &&
/* this header is sent later */
checkprefix("Content-Type:", compare))
;
@@ -1874,7 +1790,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
we will force length zero then */
checkprefix("Content-Length:", compare))
;
- else if(conn->allocptr.te &&
+ else if(data->state.aptr.te &&
/* when asking for Transfer-Encoding, don't pass on a custom
Connection: */
checkprefix("Connection:", compare))
@@ -1893,7 +1809,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
!strcasecompare(data->state.first_host, conn->host.name)))
;
else {
- result = Curl_add_bufferf(&req_buffer, "%s\r\n", compare);
+ result = Curl_dyn_addf(req, "%s\r\n", compare);
}
if(semicolonp)
free(semicolonp);
@@ -1910,7 +1826,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
#ifndef CURL_DISABLE_PARSEDATE
CURLcode Curl_add_timecondition(const struct connectdata *conn,
- Curl_send_buffer *req_buffer)
+ struct dynbuf *req)
{
struct Curl_easy *data = conn->data;
const struct tm *tm;
@@ -1969,17 +1885,17 @@ CURLcode Curl_add_timecondition(const struct connectdata *conn,
tm->tm_min,
tm->tm_sec);
- result = Curl_add_buffer(&req_buffer, datestr, strlen(datestr));
+ result = Curl_dyn_add(req, datestr);
return result;
}
#else
/* disabled */
CURLcode Curl_add_timecondition(const struct connectdata *conn,
- Curl_send_buffer *req_buffer)
+ struct dynbuf *req)
{
(void)conn;
- (void)req_buffer;
+ (void)req;
return CURLE_OK;
}
#endif
@@ -2002,13 +1918,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
const char *te = ""; /* transfer-encoding */
const char *ptr;
const char *request;
- Curl_HttpReq httpreq = data->set.httpreq;
+ Curl_HttpReq httpreq = data->state.httpreq;
#if !defined(CURL_DISABLE_COOKIES)
char *addcookies = NULL;
#endif
curl_off_t included_body = 0;
const char *httpstring;
- Curl_send_buffer *req_buffer;
+ struct dynbuf req;
curl_off_t postsize = 0; /* curl_off_t to handle large file sizes */
char *altused = NULL;
@@ -2036,13 +1952,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
#ifdef USE_NGHTTP2
if(conn->data->set.httpversion ==
CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
+#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
/* We don't support HTTP/2 proxies yet. Also it's debatable
whether or not this setting should apply to HTTP/2 proxies. */
infof(data, "Ignoring HTTP/2 prior knowledge due to proxy\n");
break;
}
-
+#endif
DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
conn->httpversion = 20;
@@ -2116,8 +2033,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
with the user-agent string specified, we erase the previously made string
here. */
if(Curl_checkheaders(conn, "User-Agent")) {
- free(conn->allocptr.uagent);
- conn->allocptr.uagent = NULL;
+ free(data->state.aptr.uagent);
+ data->state.aptr.uagent = NULL;
}
/* setup the authentication headers */
@@ -2145,14 +2062,14 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
else
conn->bits.authneg = FALSE;
- Curl_safefree(conn->allocptr.ref);
+ Curl_safefree(data->state.aptr.ref);
if(data->change.referer && !Curl_checkheaders(conn, "Referer")) {
- conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
- if(!conn->allocptr.ref)
+ data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
+ if(!data->state.aptr.ref)
return CURLE_OUT_OF_MEMORY;
}
else
- conn->allocptr.ref = NULL;
+ data->state.aptr.ref = NULL;
#if !defined(CURL_DISABLE_COOKIES)
if(data->set.str[STRING_COOKIE] && !Curl_checkheaders(conn, "Cookie"))
@@ -2161,15 +2078,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(!Curl_checkheaders(conn, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
- Curl_safefree(conn->allocptr.accept_encoding);
- conn->allocptr.accept_encoding =
+ Curl_safefree(data->state.aptr.accept_encoding);
+ data->state.aptr.accept_encoding =
aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
- if(!conn->allocptr.accept_encoding)
+ if(!data->state.aptr.accept_encoding)
return CURLE_OUT_OF_MEMORY;
}
else {
- Curl_safefree(conn->allocptr.accept_encoding);
- conn->allocptr.accept_encoding = NULL;
+ Curl_safefree(data->state.aptr.accept_encoding);
+ data->state.aptr.accept_encoding = NULL;
}
#ifdef HAVE_LIBZ
@@ -2185,7 +2102,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
char *cptr = Curl_checkheaders(conn, "Connection");
#define TE_HEADER "TE: gzip\r\n"
- Curl_safefree(conn->allocptr.te);
+ Curl_safefree(data->state.aptr.te);
if(cptr) {
cptr = Curl_copy_header_value(cptr);
@@ -2194,11 +2111,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
/* Create the (updated) Connection: header */
- conn->allocptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
+ data->state.aptr.te = aprintf("Connection: %s%sTE\r\n" TE_HEADER,
cptr ? cptr : "", (cptr && *cptr) ? ", ":"");
free(cptr);
- if(!conn->allocptr.te)
+ if(!data->state.aptr.te)
return CURLE_OUT_OF_MEMORY;
}
#endif
@@ -2281,7 +2198,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
te = "Transfer-Encoding: chunked\r\n";
}
- Curl_safefree(conn->allocptr.host);
+ Curl_safefree(data->state.aptr.host);
ptr = Curl_checkheaders(conn, "Host");
if(ptr && (!data->state.this_is_a_follow ||
@@ -2316,19 +2233,19 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(colon)
*colon = 0; /* The host must not include an embedded port number */
}
- Curl_safefree(conn->allocptr.cookiehost);
- conn->allocptr.cookiehost = cookiehost;
+ Curl_safefree(data->state.aptr.cookiehost);
+ data->state.aptr.cookiehost = cookiehost;
}
#endif
if(strcmp("Host:", ptr)) {
- conn->allocptr.host = aprintf("Host:%s\r\n", &ptr[5]);
- if(!conn->allocptr.host)
+ data->state.aptr.host = aprintf("Host:%s\r\n", &ptr[5]);
+ if(!data->state.aptr.host)
return CURLE_OUT_OF_MEMORY;
}
else
/* when clearing the header */
- conn->allocptr.host = NULL;
+ data->state.aptr.host = NULL;
}
else {
/* When building Host: headers, we must put the host name within
@@ -2340,18 +2257,18 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
(conn->remote_port == PORT_HTTP)) )
/* if(HTTPS on port 443) OR (HTTP on port 80) then don't include
the port number in the host string */
- conn->allocptr.host = aprintf("Host: %s%s%s\r\n",
+ data->state.aptr.host = aprintf("Host: %s%s%s\r\n",
conn->bits.ipv6_ip?"[":"",
host,
conn->bits.ipv6_ip?"]":"");
else
- conn->allocptr.host = aprintf("Host: %s%s%s:%d\r\n",
+ data->state.aptr.host = aprintf("Host: %s%s%s:%d\r\n",
conn->bits.ipv6_ip?"[":"",
host,
conn->bits.ipv6_ip?"]":"",
conn->remote_port);
- if(!conn->allocptr.host)
+ if(!data->state.aptr.host)
/* without Host: we can't make a nice request */
return CURLE_OUT_OF_MEMORY;
}
@@ -2432,7 +2349,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
data->set.prefer_ascii ? 'a' : 'i');
}
}
- if(conn->bits.user_passwd && !conn->bits.userpwd_in_url)
+ if(conn->bits.user_passwd)
paste_ftp_userpwd = TRUE;
}
}
@@ -2522,21 +2439,21 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) &&
!Curl_checkheaders(conn, "Range")) {
/* if a line like this was already allocated, free the previous one */
- free(conn->allocptr.rangeline);
- conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n",
+ free(data->state.aptr.rangeline);
+ data->state.aptr.rangeline = aprintf("Range: bytes=%s\r\n",
data->state.range);
}
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 */
- free(conn->allocptr.rangeline);
+ free(data->state.aptr.rangeline);
if(data->set.set_resume_from < 0) {
/* Upload resume was asked for, but we don't know the size of the
remote part so we tell the server (and act accordingly) that we
upload the whole file (again) */
- conn->allocptr.rangeline =
+ data->state.aptr.rangeline =
aprintf("Content-Range: bytes 0-%" CURL_FORMAT_CURL_OFF_T
"/%" CURL_FORMAT_CURL_OFF_T "\r\n",
data->state.infilesize - 1, data->state.infilesize);
@@ -2546,7 +2463,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* This is because "resume" was selected */
curl_off_t total_expected_size =
data->state.resume_from + data->state.infilesize;
- conn->allocptr.rangeline =
+ data->state.aptr.rangeline =
aprintf("Content-Range: bytes %s%" CURL_FORMAT_CURL_OFF_T
"/%" CURL_FORMAT_CURL_OFF_T "\r\n",
data->state.range, total_expected_size-1,
@@ -2555,11 +2472,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
else {
/* Range was selected and then we just pass the incoming range and
append total size */
- conn->allocptr.rangeline =
+ data->state.aptr.rangeline =
aprintf("Content-Range: bytes %s/%" CURL_FORMAT_CURL_OFF_T "\r\n",
data->state.range, data->state.infilesize);
}
- if(!conn->allocptr.rangeline)
+ if(!data->state.aptr.rangeline)
return CURLE_OUT_OF_MEMORY;
}
}
@@ -2567,14 +2484,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
httpstring = get_http_string(data, conn);
/* initialize a dynamic send-buffer */
- req_buffer = Curl_add_buffer_init();
-
- if(!req_buffer)
- return CURLE_OUT_OF_MEMORY;
+ Curl_dyn_init(&req, DYN_HTTP_REQUEST);
/* add the main request stuff */
/* GET/HEAD/POST/PUT */
- result = Curl_add_bufferf(&req_buffer, "%s ", request);
+ result = Curl_dyn_addf(&req, "%s ", request);
if(result)
return result;
@@ -2587,21 +2501,20 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* url */
if(conn->bits.httpproxy && !conn->bits.tunnel_proxy) {
char *url = data->set.str[STRING_TEMP_URL];
- result = Curl_add_buffer(&req_buffer, url, strlen(url));
+ result = Curl_dyn_add(&req, url);
Curl_safefree(data->set.str[STRING_TEMP_URL]);
}
else
#endif
if(paste_ftp_userpwd)
- result = Curl_add_bufferf(&req_buffer, "ftp://%s:%s@%s",
- conn->user, conn->passwd,
- path + sizeof("ftp://") - 1);
+ result = Curl_dyn_addf(&req, "ftp://%s:%s@%s", conn->user, conn->passwd,
+ path + sizeof("ftp://") - 1);
else {
- result = Curl_add_buffer(&req_buffer, path, strlen(path));
+ result = Curl_dyn_add(&req, path);
if(result)
return result;
if(query)
- result = Curl_add_bufferf(&req_buffer, "?%s", query);
+ result = Curl_dyn_addf(&req, "?%s", query);
}
if(result)
return result;
@@ -2611,60 +2524,64 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
altused = aprintf("Alt-Used: %s:%d\r\n",
conn->conn_to_host.name, conn->conn_to_port);
if(!altused) {
- Curl_add_buffer_free(&req_buffer);
+ Curl_dyn_free(&req);
return CURLE_OUT_OF_MEMORY;
}
}
#endif
result =
- Curl_add_bufferf(&req_buffer,
- "%s" /* ftp typecode (;type=x) */
- " HTTP/%s\r\n" /* HTTP version */
- "%s" /* host */
- "%s" /* proxyuserpwd */
- "%s" /* userpwd */
- "%s" /* range */
- "%s" /* user agent */
- "%s" /* accept */
- "%s" /* TE: */
- "%s" /* accept-encoding */
- "%s" /* referer */
- "%s" /* Proxy-Connection */
- "%s" /* transfer-encoding */
- "%s",/* Alt-Used */
-
- ftp_typecode,
- httpstring,
- (conn->allocptr.host?conn->allocptr.host:""),
- conn->allocptr.proxyuserpwd?
- conn->allocptr.proxyuserpwd:"",
- conn->allocptr.userpwd?conn->allocptr.userpwd:"",
- (data->state.use_range && conn->allocptr.rangeline)?
- conn->allocptr.rangeline:"",
- (data->set.str[STRING_USERAGENT] &&
- *data->set.str[STRING_USERAGENT] &&
- conn->allocptr.uagent)?
- conn->allocptr.uagent:"",
- http->p_accept?http->p_accept:"",
- conn->allocptr.te?conn->allocptr.te:"",
- (data->set.str[STRING_ENCODING] &&
- *data->set.str[STRING_ENCODING] &&
- conn->allocptr.accept_encoding)?
- conn->allocptr.accept_encoding:"",
- (data->change.referer && conn->allocptr.ref)?
- conn->allocptr.ref:"" /* Referer: <data> */,
- (conn->bits.httpproxy &&
- !conn->bits.tunnel_proxy &&
- !Curl_checkProxyheaders(conn, "Proxy-Connection"))?
- "Proxy-Connection: Keep-Alive\r\n":"",
- te,
- altused ? altused : ""
+ Curl_dyn_addf(&req,
+ "%s" /* ftp typecode (;type=x) */
+ " HTTP/%s\r\n" /* HTTP version */
+ "%s" /* host */
+ "%s" /* proxyuserpwd */
+ "%s" /* userpwd */
+ "%s" /* range */
+ "%s" /* user agent */
+ "%s" /* accept */
+ "%s" /* TE: */
+ "%s" /* accept-encoding */
+ "%s" /* referer */
+ "%s" /* Proxy-Connection */
+ "%s" /* transfer-encoding */
+ "%s",/* Alt-Used */
+
+ ftp_typecode,
+ httpstring,
+ (data->state.aptr.host?data->state.aptr.host:""),
+ data->state.aptr.proxyuserpwd?
+ data->state.aptr.proxyuserpwd:"",
+ data->state.aptr.userpwd?data->state.aptr.userpwd:"",
+ (data->state.use_range && data->state.aptr.rangeline)?
+ data->state.aptr.rangeline:"",
+ (data->set.str[STRING_USERAGENT] &&
+ *data->set.str[STRING_USERAGENT] &&
+ data->state.aptr.uagent)?
+ data->state.aptr.uagent:"",
+ http->p_accept?http->p_accept:"",
+ data->state.aptr.te?data->state.aptr.te:"",
+ (data->set.str[STRING_ENCODING] &&
+ *data->set.str[STRING_ENCODING] &&
+ data->state.aptr.accept_encoding)?
+ data->state.aptr.accept_encoding:"",
+ (data->change.referer && data->state.aptr.ref)?
+ data->state.aptr.ref:"" /* Referer: <data> */,
+#ifndef CURL_DISABLE_PROXY
+ (conn->bits.httpproxy &&
+ !conn->bits.tunnel_proxy &&
+ !Curl_checkProxyheaders(conn, "Proxy-Connection"))?
+ "Proxy-Connection: Keep-Alive\r\n":"",
+#else
+ "",
+#endif
+ te,
+ altused ? altused : ""
);
/* clear userpwd and proxyuserpwd to avoid re-using old credentials
* from re-used connections */
- Curl_safefree(conn->allocptr.userpwd);
- Curl_safefree(conn->allocptr.proxyuserpwd);
+ Curl_safefree(data->state.aptr.userpwd);
+ Curl_safefree(data->state.aptr.proxyuserpwd);
free(altused);
if(result)
@@ -2675,7 +2592,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
(data->set.httpversion == CURL_HTTP_VERSION_2)) {
/* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
over SSL */
- result = Curl_http2_request_upgrade(req_buffer, conn);
+ result = Curl_http2_request_upgrade(&req, conn);
if(result)
return result;
}
@@ -2688,8 +2605,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(data->cookies && data->state.cookie_engine) {
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
co = Curl_cookie_getlist(data->cookies,
- conn->allocptr.cookiehost?
- conn->allocptr.cookiehost:host,
+ data->state.aptr.cookiehost?
+ data->state.aptr.cookiehost:host,
data->state.up.path,
(conn->handler->protocol&CURLPROTO_HTTPS)?
TRUE:FALSE);
@@ -2701,13 +2618,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
while(co) {
if(co->value) {
if(0 == count) {
- result = Curl_add_bufferf(&req_buffer, "Cookie: ");
+ result = Curl_dyn_add(&req, "Cookie: ");
if(result)
break;
}
- result = Curl_add_bufferf(&req_buffer,
- "%s%s=%s", count?"; ":"",
- co->name, co->value);
+ result = Curl_dyn_addf(&req, "%s%s=%s", count?"; ":"",
+ co->name, co->value);
if(result)
break;
count++;
@@ -2718,26 +2634,25 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
if(addcookies && !result) {
if(!count)
- result = Curl_add_bufferf(&req_buffer, "Cookie: ");
+ result = Curl_dyn_add(&req, "Cookie: ");
if(!result) {
- result = Curl_add_bufferf(&req_buffer, "%s%s", count?"; ":"",
- addcookies);
+ result = Curl_dyn_addf(&req, "%s%s", count?"; ":"", addcookies);
count++;
}
}
if(count && !result)
- result = Curl_add_buffer(&req_buffer, "\r\n", 2);
+ result = Curl_dyn_add(&req, "\r\n");
if(result)
return result;
}
#endif
- result = Curl_add_timecondition(conn, req_buffer);
+ result = Curl_add_timecondition(conn, &req);
if(result)
return result;
- result = Curl_add_custom_headers(conn, FALSE, req_buffer);
+ result = Curl_add_custom_headers(conn, FALSE, &req);
if(result)
return result;
@@ -2760,20 +2675,20 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
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", postsize);
+ result = Curl_dyn_addf(&req, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
+ "\r\n", postsize);
if(result)
return result;
}
if(postsize != 0) {
- result = expect100(data, conn, req_buffer);
+ result = expect100(data, conn, &req);
if(result)
return result;
}
- result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers */
+ /* end of headers */
+ result = Curl_dyn_add(&req, "\r\n");
if(result)
return result;
@@ -2781,8 +2696,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_pgrsSetUploadSize(data, postsize);
/* this sends the buffer and frees all the buffer resources */
- result = Curl_add_buffer_send(&req_buffer, conn,
- &data->info.request_size, 0, FIRSTSOCKET);
+ result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ FIRSTSOCKET);
if(result)
failf(data, "Failed sending PUT request");
else
@@ -2798,12 +2713,12 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* 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");
+ result = Curl_dyn_add(&req, "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);
+ result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ FIRSTSOCKET);
if(result)
failf(data, "Failed sending POST request");
else
@@ -2821,9 +2736,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* 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);
+ result = Curl_dyn_addf(&req,
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T
+ "\r\n", postsize);
if(result)
return result;
}
@@ -2834,7 +2749,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
struct curl_slist *hdr;
for(hdr = http->sendit->curlheaders; hdr; hdr = hdr->next) {
- result = Curl_add_bufferf(&req_buffer, "%s\r\n", hdr->data);
+ result = Curl_dyn_addf(&req, "%s\r\n", hdr->data);
if(result)
return result;
}
@@ -2851,7 +2766,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_compareheader(ptr, "Expect:", "100-continue");
}
else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) {
- result = expect100(data, conn, req_buffer);
+ result = expect100(data, conn, &req);
if(result)
return result;
}
@@ -2859,7 +2774,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
data->state.expect100header = FALSE;
/* make the request end in a true CRLF */
- result = Curl_add_buffer(&req_buffer, "\r\n", 2);
+ result = Curl_dyn_add(&req, "\r\n");
if(result)
return result;
@@ -2872,8 +2787,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
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);
+ result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ FIRSTSOCKET);
if(result)
failf(data, "Failed sending POST request");
else
@@ -2901,17 +2816,15 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
(conn->bits.authneg || !Curl_checkheaders(conn, "Content-Length"))) {
/* 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);
+ result = Curl_dyn_addf(&req, "Content-Length: %" CURL_FORMAT_CURL_OFF_T
+ "\r\n", postsize);
if(result)
return result;
}
if(!Curl_checkheaders(conn, "Content-Type")) {
- result = Curl_add_bufferf(&req_buffer,
- "Content-Type: application/"
- "x-www-form-urlencoded\r\n");
+ result = Curl_dyn_add(&req, "Content-Type: application/"
+ "x-www-form-urlencoded\r\n");
if(result)
return result;
}
@@ -2926,7 +2839,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
Curl_compareheader(ptr, "Expect:", "100-continue");
}
else if(postsize > EXPECT_100_THRESHOLD || postsize < 0) {
- result = expect100(data, conn, req_buffer);
+ result = expect100(data, conn, &req);
if(result)
return result;
}
@@ -2947,31 +2860,32 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
is no magic limit but only set to prevent really huge POSTs to
get the data duplicated with malloc() and family. */
- result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
+ /* end of headers! */
+ result = Curl_dyn_add(&req, "\r\n");
if(result)
return result;
if(!data->req.upload_chunky) {
/* We're not sending it 'chunked', append it to the request
already now to reduce the number if send() calls */
- result = Curl_add_buffer(&req_buffer, data->set.postfields,
- (size_t)postsize);
+ result = Curl_dyn_addn(&req, data->set.postfields,
+ (size_t)postsize);
included_body = postsize;
}
else {
if(postsize) {
/* Append the POST data chunky-style */
- result = Curl_add_bufferf(&req_buffer, "%x\r\n", (int)postsize);
+ result = Curl_dyn_addf(&req, "%x\r\n", (int)postsize);
if(!result) {
- result = Curl_add_buffer(&req_buffer, data->set.postfields,
- (size_t)postsize);
+ result = Curl_dyn_addn(&req, data->set.postfields,
+ (size_t)postsize);
if(!result)
- result = Curl_add_buffer(&req_buffer, "\r\n", 2);
+ result = Curl_dyn_add(&req, "\r\n");
included_body = postsize + 2;
}
}
if(!result)
- result = Curl_add_buffer(&req_buffer, "\x30\x0d\x0a\x0d\x0a", 5);
+ result = Curl_dyn_add(&req, "\x30\x0d\x0a\x0d\x0a");
/* 0 CR LF CR LF */
included_body += 5;
}
@@ -2993,21 +2907,22 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize);
- result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
+ /* end of headers! */
+ result = Curl_dyn_add(&req, "\r\n");
if(result)
return result;
}
}
else {
- result = Curl_add_buffer(&req_buffer, "\r\n", 2); /* end of headers! */
+ /* end of headers! */
+ result = Curl_dyn_add(&req, "\r\n");
if(result)
return result;
if(data->req.upload_chunky && conn->bits.authneg) {
/* Chunky upload is selected and we're negotiating auth still, send
end-of-data only */
- result = Curl_add_buffer(&req_buffer,
- "\x30\x0d\x0a\x0d\x0a", 5);
+ result = Curl_dyn_add(&req, (char *)"\x30\x0d\x0a\x0d\x0a");
/* 0 CR LF CR LF */
if(result)
return result;
@@ -3027,8 +2942,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
}
/* issue the request */
- result = Curl_add_buffer_send(&req_buffer, conn, &data->info.request_size,
- (size_t)included_body, FIRSTSOCKET);
+ result = Curl_buffer_send(&req, conn, &data->info.request_size,
+ (size_t)included_body, FIRSTSOCKET);
if(result)
failf(data, "Failed sending HTTP POST request");
@@ -3038,13 +2953,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
break;
default:
- result = Curl_add_buffer(&req_buffer, "\r\n", 2);
+ result = Curl_dyn_add(&req, "\r\n");
if(result)
return result;
/* issue the request */
- result = Curl_add_buffer_send(&req_buffer, conn,
- &data->info.request_size, 0, FIRSTSOCKET);
+ result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ FIRSTSOCKET);
if(result)
failf(data, "Failed sending HTTP request");
@@ -3189,55 +3104,10 @@ checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
return checkhttpprefix(data, s, len);
}
-/*
- * header_append() copies a chunk of data to the end of the already received
- * header. We make sure that the full string fit in the allocated header
- * buffer, or else we enlarge it.
- */
-static CURLcode header_append(struct Curl_easy *data,
- struct SingleRequest *k,
- size_t length)
-{
- /* length is at most the size of a full read buffer, for which the upper
- bound is CURL_MAX_READ_SIZE. There is thus no chance of overflow in this
- calculation. */
- size_t newsize = k->hbuflen + length;
- if(newsize > CURL_MAX_HTTP_HEADER) {
- /* The reason to have a max limit for this is to avoid the risk of a bad
- server feeding libcurl with a never-ending header that will cause
- reallocs infinitely */
- failf(data, "Rejected %zu bytes header (max is %d)!", newsize,
- CURL_MAX_HTTP_HEADER);
- return CURLE_OUT_OF_MEMORY;
- }
- if(newsize >= data->state.headersize) {
- /* We enlarge the header buffer as it is too small */
- char *newbuff;
- size_t hbufp_index;
-
- 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.headerbuff = newbuff;
- k->hbufp = data->state.headerbuff + hbufp_index;
- }
- memcpy(k->hbufp, k->str_start, length);
- k->hbufp += length;
- k->hbuflen += length;
- *k->hbufp = 0;
-
- return CURLE_OK;
-}
-
static void print_http_error(struct Curl_easy *data)
{
struct SingleRequest *k = &data->req;
- char *beg = k->p;
+ char *beg = Curl_dyn_ptr(&data->state.headerb);
/* make sure that data->req.p points to the HTTP status line */
if(!strncmp(beg, "HTTP", 4)) {
@@ -3275,14 +3145,17 @@ static void print_http_error(struct Curl_easy *data)
* Read any HTTP header lines from the server and pass them to the client app.
*/
CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
- struct connectdata *conn,
- ssize_t *nread,
- bool *stop_reading)
+ struct connectdata *conn,
+ ssize_t *nread,
+ bool *stop_reading)
{
CURLcode result;
struct SingleRequest *k = &data->req;
ssize_t onread = *nread;
char *ostr = k->str;
+ char *headp;
+ char *str_start;
+ char *end_ptr;
/* header line within buffer loop */
do {
@@ -3291,22 +3164,25 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
int writetype;
/* str_start is start of line within buf */
- k->str_start = k->str;
+ str_start = k->str;
/* data is in network encoding so use 0x0a instead of '\n' */
- k->end_ptr = memchr(k->str_start, 0x0a, *nread);
+ end_ptr = memchr(str_start, 0x0a, *nread);
- if(!k->end_ptr) {
+ if(!end_ptr) {
/* Not a complete header line within buffer, append the data to
the end of the headerbuff. */
- result = header_append(data, k, *nread);
+ result = Curl_dyn_addn(&data->state.headerb, str_start, *nread);
if(result)
return result;
if(!k->headerline) {
/* check if this looks like a protocol header */
- statusline st = checkprotoprefix(data, conn, data->state.headerbuff,
- k->hbuflen);
+ statusline st =
+ checkprotoprefix(data, conn,
+ Curl_dyn_ptr(&data->state.headerb),
+ Curl_dyn_len(&data->state.headerb));
+
if(st == STATUS_BAD) {
/* this is not the beginning of a protocol first header line */
k->header = FALSE;
@@ -3324,28 +3200,26 @@ 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 = (end_ptr - k->str) + 1;
*nread -= (ssize_t)rest_length;
- k->str = k->end_ptr + 1; /* move past new line */
+ k->str = end_ptr + 1; /* move past new line */
- full_length = k->str - k->str_start;
+ full_length = k->str - str_start;
- result = header_append(data, k, full_length);
+ result = Curl_dyn_addn(&data->state.headerb, str_start, full_length);
if(result)
return result;
- k->end_ptr = k->hbufp;
- k->p = data->state.headerbuff;
-
/****
- * We now have a FULL header line that p points to
+ * We now have a FULL header line in 'headerb'.
*****/
if(!k->headerline) {
/* the first read header */
- statusline st = checkprotoprefix(data, conn, data->state.headerbuff,
- k->hbuflen);
+ statusline st = checkprotoprefix(data, conn,
+ Curl_dyn_ptr(&data->state.headerb),
+ Curl_dyn_len(&data->state.headerb));
if(st == STATUS_BAD) {
streamclose(conn, "bad HTTP: No end-of-message indicator");
/* this is not the beginning of a protocol first header line */
@@ -3368,26 +3242,27 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
}
- /* headers are in network encoding so
- use 0x0a and 0x0d instead of '\n' and '\r' */
- if((0x0a == *k->p) || (0x0d == *k->p)) {
+ /* headers are in network encoding so use 0x0a and 0x0d instead of '\n'
+ and '\r' */
+ headp = Curl_dyn_ptr(&data->state.headerb);
+ if((0x0a == *headp) || (0x0d == *headp)) {
size_t headerlen;
/* Zero-length header line means end of headers! */
#ifdef CURL_DOES_CONVERSIONS
- if(0x0d == *k->p) {
- *k->p = '\r'; /* replace with CR in host encoding */
- k->p++; /* pass the CR byte */
+ if(0x0d == *headp) {
+ *headp = '\r'; /* replace with CR in host encoding */
+ headp++; /* pass the CR byte */
}
- if(0x0a == *k->p) {
- *k->p = '\n'; /* replace with LF in host encoding */
- k->p++; /* pass the LF byte */
+ if(0x0a == *headp) {
+ *headp = '\n'; /* replace with LF in host encoding */
+ headp++; /* pass the LF byte */
}
#else
- if('\r' == *k->p)
- k->p++; /* pass the \r byte */
- if('\n' == *k->p)
- k->p++; /* pass the \n byte */
+ if('\r' == *headp)
+ headp++; /* pass the \r byte */
+ if('\n' == *headp)
+ headp++; /* pass the \n byte */
#endif /* CURL_DOES_CONVERSIONS */
if(100 <= k->httpcode && 199 >= k->httpcode) {
@@ -3448,7 +3323,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if((k->size == -1) && !k->chunk && !conn->bits.close &&
(conn->httpversion == 11) &&
!(conn->handler->protocol & CURLPROTO_RTSP) &&
- data->set.httpreq != HTTPREQ_HEAD) {
+ data->state.httpreq != HTTPREQ_HEAD) {
/* On HTTP 1.1, when connection is not to get closed, but no
Content-Length nor Transfer-Encoding chunked have been
received, according to RFC2616 section 4.4 point 5, we
@@ -3506,10 +3381,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(data->set.include_header)
writetype |= CLIENTWRITE_BODY;
- headerlen = k->p - data->state.headerbuff;
-
+ headerlen = Curl_dyn_len(&data->state.headerb);
result = Curl_client_write(conn, writetype,
- data->state.headerbuff,
+ Curl_dyn_ptr(&data->state.headerb),
headerlen);
if(result)
return result;
@@ -3544,7 +3418,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* continue sending even if it gets discarded
*/
- switch(data->set.httpreq) {
+ switch(data->state.httpreq) {
case HTTPREQ_PUT:
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
@@ -3662,14 +3536,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(data->set.verbose)
Curl_debug(data, CURLINFO_HEADER_IN,
- k->str_start, headerlen);
+ str_start, headerlen);
break; /* exit header line loop */
}
- /* We continue reading headers, so reset the line-based
- header parsing variables hbufp && hbuflen */
- k->hbufp = data->state.headerbuff;
- k->hbuflen = 0;
+ /* We continue reading headers, reset the line-based header */
+ Curl_dyn_reset(&data->state.headerb);
continue;
}
@@ -3688,12 +3560,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
#define SCRATCHSIZE 21
CURLcode res;
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,
- leaving the data at k->p as-is.
+ /* 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, leaving the data at 'headp' as-is.
*/
- strncpy(&scratch[0], k->p, SCRATCHSIZE);
+ strncpy(&scratch[0], headp, SCRATCHSIZE);
scratch[SCRATCHSIZE] = 0; /* null terminate */
res = Curl_convert_from_network(data,
&scratch[0],
@@ -3702,7 +3573,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* Curl_convert_from_network calls failf if unsuccessful */
return res;
#else
-#define HEADER1 k->p /* no conversion needed, just use k->p */
+#define HEADER1 headp /* no conversion needed, just use headp */
#endif /* CURL_DOES_CONVERSIONS */
if(conn->handler->protocol & PROTO_FAMILY_HTTP) {
@@ -3753,7 +3624,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
compare header line against list of aliases
*/
if(!nc) {
- if(checkhttpprefix(data, k->p, k->hbuflen) == STATUS_DONE) {
+ statusline check =
+ checkhttpprefix(data,
+ Curl_dyn_ptr(&data->state.headerb),
+ Curl_dyn_len(&data->state.headerb));
+ if(check == STATUS_DONE) {
nc = 1;
k->httpcode = 200;
conn->httpversion = 10;
@@ -3799,15 +3674,18 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* depending on how authentication is working. Other codes
* are definitely errors, so give up here.
*/
- if(data->state.resume_from && data->set.httpreq == HTTPREQ_GET &&
+ if(data->state.resume_from && data->state.httpreq == HTTPREQ_GET &&
k->httpcode == 416) {
/* "Requested Range Not Satisfiable", just proceed and
pretend this is no error */
k->ignorebody = TRUE; /* Avoid appending error msg to good data. */
}
else if(data->set.http_fail_on_error && (k->httpcode >= 400) &&
- ((k->httpcode != 401) || !conn->bits.user_passwd) &&
- ((k->httpcode != 407) || !conn->bits.proxy_user_passwd) ) {
+ ((k->httpcode != 401) || !conn->bits.user_passwd)
+#ifndef CURL_DISABLE_PROXY
+ && ((k->httpcode != 407) || !conn->bits.proxy_user_passwd)
+#endif
+ ) {
/* serious error, go home! */
print_http_error(data);
return CURLE_HTTP_RETURNED_ERROR;
@@ -3823,9 +3701,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
else if(conn->httpversion == 20 ||
(k->upgr101 == UPGR101_REQUESTED && k->httpcode == 101)) {
DEBUGF(infof(data, "HTTP/2 found, allow multiplexing\n"));
-
- /* HTTP/2 cannot blacklist multiplexing since it is a core
- functionality of the protocol */
+ /* HTTP/2 cannot avoid multiplexing since it is a core functionality
+ of the protocol */
conn->bundle->multiuse = BUNDLE_MULTIPLEX;
}
else if(conn->httpversion >= 11 &&
@@ -3865,16 +3742,16 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
}
- result = Curl_convert_from_network(data, k->p, strlen(k->p));
+ result = Curl_convert_from_network(data, headp, strlen(headp));
/* Curl_convert_from_network calls failf if unsuccessful */
if(result)
return result;
/* Check for Content-Length: header lines to get size */
if(!k->http_bodyless &&
- !data->set.ignorecl && checkprefix("Content-Length:", k->p)) {
+ !data->set.ignorecl && checkprefix("Content-Length:", headp)) {
curl_off_t contentlength;
- CURLofft offt = curlx_strtoofft(k->p + 15, NULL, 10, &contentlength);
+ CURLofft offt = curlx_strtoofft(headp + 15, NULL, 10, &contentlength);
if(offt == CURL_OFFT_OK) {
if(data->set.max_filesize &&
@@ -3905,8 +3782,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
}
/* check for Content-Type: header lines to get the MIME-type */
- else if(checkprefix("Content-Type:", k->p)) {
- char *contenttype = Curl_copy_header_value(k->p);
+ else if(checkprefix("Content-Type:", headp)) {
+ char *contenttype = Curl_copy_header_value(headp);
if(!contenttype)
return CURLE_OUT_OF_MEMORY;
if(!*contenttype)
@@ -3917,10 +3794,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
data->info.contenttype = contenttype;
}
}
+#ifndef CURL_DISABLE_PROXY
else if((conn->httpversion == 10) &&
conn->bits.httpproxy &&
- Curl_compareheader(k->p,
- "Proxy-Connection:", "keep-alive")) {
+ Curl_compareheader(headp, "Proxy-Connection:", "keep-alive")) {
/*
* When a HTTP/1.0 reply comes when using a proxy, the
* 'Proxy-Connection: keep-alive' line tells us the
@@ -3932,8 +3809,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
else if((conn->httpversion == 11) &&
conn->bits.httpproxy &&
- Curl_compareheader(k->p,
- "Proxy-Connection:", "close")) {
+ Curl_compareheader(headp, "Proxy-Connection:", "close")) {
/*
* We get a HTTP/1.1 response from a proxy and it says it'll
* close down after this transfer.
@@ -3941,8 +3817,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
connclose(conn, "Proxy-Connection: asked to close after done");
infof(data, "HTTP/1.1 proxy connection set close!\n");
}
+#endif
else if((conn->httpversion == 10) &&
- Curl_compareheader(k->p, "Connection:", "keep-alive")) {
+ Curl_compareheader(headp, "Connection:", "keep-alive")) {
/*
* A HTTP/1.0 reply with the 'Connection: keep-alive' line
* tells us the connection will be kept alive for our
@@ -3952,7 +3829,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
connkeep(conn, "Connection keep-alive");
infof(data, "HTTP/1.0 connection set to keep alive!\n");
}
- else if(Curl_compareheader(k->p, "Connection:", "close")) {
+ else if(Curl_compareheader(headp, "Connection:", "close")) {
/*
* [RFC 2616, section 8.1.2.1]
* "Connection: close" is HTTP/1.1 language and means that
@@ -3961,7 +3838,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
*/
streamclose(conn, "Connection: close used");
}
- else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", k->p)) {
+ else if(!k->http_bodyless && checkprefix("Transfer-Encoding:", headp)) {
/* One or more encodings. We check for chunked and/or a compression
algorithm. */
/*
@@ -3973,11 +3850,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* of chunks, and a chunk-data set to zero signals the
* end-of-chunks. */
- result = Curl_build_unencoding_stack(conn, k->p + 18, TRUE);
+ result = Curl_build_unencoding_stack(conn, headp + 18, TRUE);
if(result)
return result;
}
- else if(!k->http_bodyless && checkprefix("Content-Encoding:", k->p) &&
+ else if(!k->http_bodyless && checkprefix("Content-Encoding:", headp) &&
data->set.str[STRING_ENCODING]) {
/*
* Process Content-Encoding. Look for the values: identity,
@@ -3986,24 +3863,24 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* 2616). zlib cannot handle compress. However, errors are
* handled further down when the response body is processed
*/
- result = Curl_build_unencoding_stack(conn, k->p + 17, FALSE);
+ result = Curl_build_unencoding_stack(conn, headp + 17, FALSE);
if(result)
return result;
}
- else if(checkprefix("Retry-After:", k->p)) {
+ else if(checkprefix("Retry-After:", headp)) {
/* Retry-After = HTTP-date / delay-seconds */
curl_off_t retry_after = 0; /* zero for unknown or "now" */
- time_t date = Curl_getdate_capped(&k->p[12]);
+ time_t date = Curl_getdate_capped(&headp[12]);
if(-1 == date) {
/* not a date, try it as a decimal number */
- (void)curlx_strtoofft(&k->p[12], NULL, 10, &retry_after);
+ (void)curlx_strtoofft(&headp[12], NULL, 10, &retry_after);
}
else
/* convert date to number of seconds into the future */
retry_after = date - time(NULL);
data->info.retry_after = retry_after; /* store it */
}
- else if(!k->http_bodyless && checkprefix("Content-Range:", k->p)) {
+ else if(!k->http_bodyless && checkprefix("Content-Range:", headp)) {
/* Content-Range: bytes [num]-
Content-Range: bytes: [num]-
Content-Range: [num]-
@@ -4015,7 +3892,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
The forth means the requested range was unsatisfied.
*/
- char *ptr = k->p + 14;
+ char *ptr = headp + 14;
/* Move forward until first digit or asterisk */
while(*ptr && !ISDIGIT(*ptr) && *ptr != '*')
@@ -4034,34 +3911,34 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
#if !defined(CURL_DISABLE_COOKIES)
else if(data->cookies && data->state.cookie_engine &&
- checkprefix("Set-Cookie:", k->p)) {
+ checkprefix("Set-Cookie:", headp)) {
Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
CURL_LOCK_ACCESS_SINGLE);
Curl_cookie_add(data,
- data->cookies, TRUE, FALSE, k->p + 11,
+ data->cookies, TRUE, FALSE, headp + 11,
/* If there is a custom-set Host: name, use it
here, or else use real peer host name. */
- conn->allocptr.cookiehost?
- conn->allocptr.cookiehost:conn->host.name,
+ data->state.aptr.cookiehost?
+ data->state.aptr.cookiehost:conn->host.name,
data->state.up.path,
(conn->handler->protocol&CURLPROTO_HTTPS)?
TRUE:FALSE);
Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
}
#endif
- else if(!k->http_bodyless && checkprefix("Last-Modified:", k->p) &&
+ else if(!k->http_bodyless && checkprefix("Last-Modified:", headp) &&
(data->set.timecondition || data->set.get_filetime) ) {
- k->timeofdoc = Curl_getdate_capped(k->p + strlen("Last-Modified:"));
+ k->timeofdoc = Curl_getdate_capped(headp + strlen("Last-Modified:"));
if(data->set.get_filetime)
data->info.filetime = k->timeofdoc;
}
- else if((checkprefix("WWW-Authenticate:", k->p) &&
+ else if((checkprefix("WWW-Authenticate:", headp) &&
(401 == k->httpcode)) ||
- (checkprefix("Proxy-authenticate:", k->p) &&
+ (checkprefix("Proxy-authenticate:", headp) &&
(407 == k->httpcode))) {
bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
- char *auth = Curl_copy_header_value(k->p);
+ char *auth = Curl_copy_header_value(headp);
if(!auth)
return CURLE_OUT_OF_MEMORY;
@@ -4073,11 +3950,11 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
return result;
}
#ifdef USE_SPNEGO
- else if(checkprefix("Persistent-Auth", k->p)) {
+ else if(checkprefix("Persistent-Auth", headp)) {
struct negotiatedata *negdata = &conn->negotiate;
struct auth *authp = &data->state.authhost;
if(authp->picked == CURLAUTH_NEGOTIATE) {
- char *persistentauth = Curl_copy_header_value(k->p);
+ char *persistentauth = Curl_copy_header_value(headp);
if(!persistentauth)
return CURLE_OUT_OF_MEMORY;
negdata->noauthpersist = checkprefix("false", persistentauth)?
@@ -4090,10 +3967,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
#endif
else if((k->httpcode >= 300 && k->httpcode < 400) &&
- checkprefix("Location:", k->p) &&
+ checkprefix("Location:", headp) &&
!data->req.location) {
/* this is the URL that the server advises us to use instead */
- char *location = Curl_copy_header_value(k->p);
+ char *location = Curl_copy_header_value(headp);
if(!location)
return CURLE_OUT_OF_MEMORY;
if(!*location)
@@ -4118,7 +3995,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
#ifdef USE_ALTSVC
/* If enabled, the header is incoming and this is over HTTPS */
- else if(data->asi && checkprefix("Alt-Svc:", k->p) &&
+ else if(data->asi && checkprefix("Alt-Svc:", headp) &&
((conn->handler->flags & PROTOPT_SSL) ||
#ifdef CURLDEBUG
/* allow debug builds to circumvent the HTTPS restriction */
@@ -4130,7 +4007,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
/* the ALPN of the current request */
enum alpnid id = (conn->httpversion == 20) ? ALPN_h2 : ALPN_h1;
result = Curl_altsvc_parse(data, data->asi,
- &k->p[ strlen("Alt-Svc:") ],
+ &headp[ strlen("Alt-Svc:") ],
id, conn->host.name,
curlx_uitous(conn->remote_port));
if(result)
@@ -4138,7 +4015,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
}
#endif
else if(conn->handler->protocol & CURLPROTO_RTSP) {
- result = Curl_rtsp_parseheader(conn, k->p);
+ result = Curl_rtsp_parseheader(conn, headp);
if(result)
return result;
}
@@ -4152,18 +4029,18 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
writetype |= CLIENTWRITE_BODY;
if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN, k->p, (size_t)k->hbuflen);
+ Curl_debug(data, CURLINFO_HEADER_IN, headp,
+ Curl_dyn_len(&data->state.headerb));
- result = Curl_client_write(conn, writetype, k->p, k->hbuflen);
+ result = Curl_client_write(conn, writetype, headp,
+ Curl_dyn_len(&data->state.headerb));
if(result)
return result;
- data->info.header_size += (long)k->hbuflen;
- data->req.headerbytecount += (long)k->hbuflen;
+ data->info.header_size += Curl_dyn_len(&data->state.headerb);
+ data->req.headerbytecount += Curl_dyn_len(&data->state.headerb);
- /* reset hbufp pointer && hbuflen */
- k->hbufp = data->state.headerbuff;
- k->hbuflen = 0;
+ Curl_dyn_reset(&data->state.headerb);
}
while(*k->str); /* header line within buffer */
diff --git a/lib/http.h b/lib/http.h
index e6b511c20..005f85092 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -44,38 +44,19 @@ char *Curl_copy_header_value(const char *header);
char *Curl_checkProxyheaders(const struct connectdata *conn,
const char *thisheader);
-/* ------------------------------------------------------------------------- */
-/*
- * The add_buffer series of functions are used to build one large memory chunk
- * from repeated function invokes. Used so that the entire HTTP request can
- * be sent in one go.
- */
-struct Curl_send_buffer {
- char *buffer;
- size_t size_max;
- size_t size_used;
-};
-typedef struct Curl_send_buffer Curl_send_buffer;
-
-Curl_send_buffer *Curl_add_buffer_init(void);
-void Curl_add_buffer_free(Curl_send_buffer **inp);
-CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...)
- WARN_UNUSED_RESULT;
-CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr,
- size_t size) WARN_UNUSED_RESULT;
-CURLcode Curl_add_buffer_send(Curl_send_buffer **inp,
- struct connectdata *conn,
- curl_off_t *bytes_written,
- size_t included_body_bytes,
- int socketindex);
+CURLcode Curl_buffer_send(struct dynbuf *in,
+ struct connectdata *conn,
+ curl_off_t *bytes_written,
+ size_t included_body_bytes,
+ int socketindex);
CURLcode Curl_add_timecondition(const struct connectdata *conn,
- Curl_send_buffer *buf);
+ struct dynbuf *buf);
CURLcode Curl_add_custom_headers(struct connectdata *conn,
bool is_connect,
- Curl_send_buffer *req_buffer);
+ struct dynbuf *req_buffer);
CURLcode Curl_http_compile_trailers(struct curl_slist *trailers,
- Curl_send_buffer **buffer,
+ struct dynbuf *buf,
struct Curl_easy *handle);
/* protocol-specific functions set up to be called by the main engine */
@@ -154,9 +135,9 @@ struct HTTP {
} sending;
#ifndef CURL_DISABLE_HTTP
- Curl_send_buffer *send_buffer; /* used if the request couldn't be sent in
- one chunk, points to an allocated
- send_buffer struct */
+ struct dynbuf send_buffer; /* used if the request couldn't be sent in one
+ chunk, points to an allocated send_buffer
+ struct */
#endif
#ifdef USE_NGHTTP2
/*********** for HTTP/2 we store stream-local data here *************/
@@ -164,10 +145,9 @@ struct HTTP {
bool bodystarted;
/* We store non-final and final response headers here, per-stream */
- Curl_send_buffer *header_recvbuf;
+ struct dynbuf header_recvbuf;
size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into
upper layer */
- Curl_send_buffer *trailer_recvbuf;
int status_code; /* HTTP status code */
const uint8_t *pausedata; /* pointer to data received in on_data_chunk */
size_t pauselen; /* the number of bytes left in data */
@@ -201,9 +181,7 @@ struct HTTP {
#ifdef USE_NGHTTP3
size_t unacked_window;
struct h3out *h3out; /* per-stream buffers for upload */
- char *overflow_buf; /* excess data received during a single Curl_read */
- size_t overflow_buflen; /* amount of data currently in overflow_buf */
- size_t overflow_bufsize; /* size of the overflow_buf allocation */
+ struct dynbuf overflow; /* excess data received during a single Curl_read */
#endif
};
diff --git a/lib/http2.c b/lib/http2.c
index 21d829922..08fba6764 100644
--- a/lib/http2.c
+++ b/lib/http2.c
@@ -36,6 +36,7 @@
#include "connect.h"
#include "strtoofft.h"
#include "strdup.h"
+#include "dynbuf.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@@ -124,8 +125,7 @@ static int http2_getsock(struct connectdata *conn,
static void http2_stream_free(struct HTTP *http)
{
if(http) {
- Curl_add_buffer_free(&http->header_recvbuf);
- Curl_add_buffer_free(&http->trailer_recvbuf);
+ Curl_dyn_free(&http->header_recvbuf);
for(; http->push_headers_used > 0; --http->push_headers_used) {
free(http->push_headers[http->push_headers_used - 1]);
}
@@ -258,16 +258,14 @@ static unsigned int http2_conncheck(struct connectdata *check,
void Curl_http2_setup_req(struct Curl_easy *data)
{
struct HTTP *http = data->req.protop;
-
- http->nread_header_recvbuf = 0;
http->bodystarted = FALSE;
http->status_code = -1;
http->pausedata = NULL;
http->pauselen = 0;
http->closed = FALSE;
http->close_handled = FALSE;
- http->mem = data->state.buffer;
- http->len = data->set.buffer_size;
+ http->mem = NULL;
+ http->len = 0;
http->memlen = 0;
}
@@ -463,20 +461,54 @@ static struct Curl_easy *duphandle(struct Curl_easy *data)
}
else {
second->req.protop = http;
- http->header_recvbuf = Curl_add_buffer_init();
- if(!http->header_recvbuf) {
- free(http);
- (void)Curl_close(&second);
- }
- else {
- Curl_http2_setup_req(second);
- second->state.stream_weight = data->state.stream_weight;
- }
+ Curl_dyn_init(&http->header_recvbuf, DYN_H2_HEADERS);
+ Curl_http2_setup_req(second);
+ second->state.stream_weight = data->state.stream_weight;
}
}
return second;
}
+static int set_transfer_url(struct Curl_easy *data,
+ struct curl_pushheaders *hp)
+{
+ const char *v;
+ CURLU *u = curl_url();
+ CURLUcode uc;
+ char *url;
+
+ v = curl_pushheader_byname(hp, ":scheme");
+ if(v) {
+ uc = curl_url_set(u, CURLUPART_SCHEME, v, 0);
+ if(uc)
+ return 1;
+ }
+
+ v = curl_pushheader_byname(hp, ":authority");
+ if(v) {
+ uc = curl_url_set(u, CURLUPART_HOST, v, 0);
+ if(uc)
+ return 2;
+ }
+
+ v = curl_pushheader_byname(hp, ":path");
+ if(v) {
+ uc = curl_url_set(u, CURLUPART_PATH, v, 0);
+ if(uc)
+ return 3;
+ }
+
+ uc = curl_url_get(u, CURLUPART_URL, &url, 0);
+ if(uc)
+ return 4;
+ curl_url_cleanup(u);
+
+ if(data->change.url_alloc)
+ free(data->change.url);
+ data->change.url_alloc = TRUE;
+ data->change.url = url;
+ return 0;
+}
static int push_promise(struct Curl_easy *data,
struct connectdata *conn,
@@ -513,6 +545,10 @@ static int push_promise(struct Curl_easy *data,
goto fail;
}
+ rv = set_transfer_url(newhandle, &heads);
+ if(rv)
+ goto fail;
+
Curl_set_in_callback(data, true);
rv = data->multi->push_cb(data, newhandle,
stream->push_headers_used, &heads,
@@ -668,15 +704,17 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
stream->status_code = -1;
}
- result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
+ result = Curl_dyn_add(&stream->header_recvbuf, "\r\n");
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- left = stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
+ left = Curl_dyn_len(&stream->header_recvbuf) -
+ stream->nread_header_recvbuf;
ncopy = CURLMIN(stream->len, left);
memcpy(&stream->mem[stream->memlen],
- stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
+ Curl_dyn_ptr(&stream->header_recvbuf) +
+ stream->nread_header_recvbuf,
ncopy);
stream->nread_header_recvbuf += ncopy;
@@ -852,12 +890,6 @@ static int on_begin_headers(nghttp2_session *session,
return 0;
}
- if(!stream->trailer_recvbuf) {
- stream->trailer_recvbuf = Curl_add_buffer_init();
- if(!stream->trailer_recvbuf) {
- return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
- }
- }
return 0;
}
@@ -973,26 +1005,19 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
}
if(stream->bodystarted) {
- /* This is trailer fields. */
- /* 4 is for ": " and "\r\n". */
- uint32_t n = (uint32_t)(namelen + valuelen + 4);
-
+ /* This is a trailer */
+ struct dynbuf trail;
H2BUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen,
value));
-
- result = Curl_add_buffer(&stream->trailer_recvbuf, &n, sizeof(n));
- if(result)
- return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->trailer_recvbuf, name, namelen);
- if(result)
- return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->trailer_recvbuf, ": ", 2);
- if(result)
- return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->trailer_recvbuf, value, valuelen);
- if(result)
- return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->trailer_recvbuf, "\r\n\0", 3);
+ Curl_dyn_init(&trail, DYN_H2_TRAILER);
+ result = Curl_dyn_addf(&trail,
+ "%.*s: %.*s\r\n", namelen, name,
+ valuelen, value);
+ if(!result)
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER,
+ Curl_dyn_ptr(&trail),
+ Curl_dyn_len(&trail));
+ Curl_dyn_free(&trail);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -1007,14 +1032,14 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
stream->status_code = decode_status_code(value, valuelen);
DEBUGASSERT(stream->status_code != -1);
- result = Curl_add_buffer(&stream->header_recvbuf, "HTTP/2 ", 7);
+ result = Curl_dyn_add(&stream->header_recvbuf, "HTTP/2 ");
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
+ result = Curl_dyn_addn(&stream->header_recvbuf, value, valuelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* the space character after the status code is mandatory */
- result = Curl_add_buffer(&stream->header_recvbuf, " \r\n", 3);
+ result = Curl_dyn_add(&stream->header_recvbuf, " \r\n");
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
@@ -1029,16 +1054,16 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
/* nghttp2 guarantees that namelen > 0, and :status was already
received, and this is not pseudo-header field . */
/* convert to a HTTP1-style header */
- result = Curl_add_buffer(&stream->header_recvbuf, name, namelen);
+ result = Curl_dyn_addn(&stream->header_recvbuf, name, namelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->header_recvbuf, ": ", 2);
+ result = Curl_dyn_add(&stream->header_recvbuf, ": ");
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->header_recvbuf, value, valuelen);
+ result = Curl_dyn_addn(&stream->header_recvbuf, value, valuelen);
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- result = Curl_add_buffer(&stream->header_recvbuf, "\r\n", 2);
+ result = Curl_dyn_add(&stream->header_recvbuf, "\r\n");
if(result)
return NGHTTP2_ERR_CALLBACK_FAILURE;
/* if we receive data for another handle, wake that up */
@@ -1139,17 +1164,14 @@ void Curl_http2_done(struct Curl_easy *data, bool premature)
/* there might be allocated resources done before this got the 'h2' pointer
setup */
- if(http->header_recvbuf) {
- Curl_add_buffer_free(&http->header_recvbuf);
- Curl_add_buffer_free(&http->trailer_recvbuf);
- if(http->push_headers) {
- /* if they weren't used and then freed before */
- for(; http->push_headers_used > 0; --http->push_headers_used) {
- free(http->push_headers[http->push_headers_used - 1]);
- }
- free(http->push_headers);
- http->push_headers = NULL;
+ Curl_dyn_free(&http->header_recvbuf);
+ if(http->push_headers) {
+ /* if they weren't used and then freed before */
+ for(; http->push_headers_used > 0; --http->push_headers_used) {
+ free(http->push_headers[http->push_headers_used - 1]);
}
+ free(http->push_headers);
+ http->push_headers = NULL;
}
if(!httpc->h2) /* not HTTP/2 ? */
@@ -1238,7 +1260,7 @@ static CURLcode http2_init(struct connectdata *conn)
/*
* Append headers to ask for a HTTP1.1 to HTTP2 upgrade.
*/
-CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
+CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
struct connectdata *conn)
{
CURLcode result;
@@ -1257,7 +1279,7 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
httpc->local_settings_num);
if(!binlen) {
failf(conn->data, "nghttp2 unexpectedly failed on pack_settings_payload");
- Curl_add_buffer_free(&req);
+ Curl_dyn_free(req);
return CURLE_FAILED_INIT;
}
conn->proto.httpc.binlen = binlen;
@@ -1265,15 +1287,15 @@ CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
result = Curl_base64url_encode(conn->data, (const char *)binsettings, binlen,
&base64, &blen);
if(result) {
- Curl_add_buffer_free(&req);
+ Curl_dyn_free(req);
return result;
}
- result = Curl_add_bufferf(&req,
- "Connection: Upgrade, HTTP2-Settings\r\n"
- "Upgrade: %s\r\n"
- "HTTP2-Settings: %s\r\n",
- NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
+ result = Curl_dyn_addf(req,
+ "Connection: Upgrade, HTTP2-Settings\r\n"
+ "Upgrade: %s\r\n"
+ "HTTP2-Settings: %s\r\n",
+ NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64);
free(base64);
k->upgr101 = UPGR101_REQUESTED;
@@ -1367,10 +1389,11 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
struct HTTP *stream = conn->data->req.protop;
+ struct http_conn *httpc = &conn->proto.httpc;
+ nghttp2_session *h2 = httpc->h2;
+
if(stream->upload_left) {
/* If the stream still thinks there's data left to upload. */
- struct http_conn *httpc = &conn->proto.httpc;
- nghttp2_session *h2 = httpc->h2;
stream->upload_left = 0; /* DONE! */
@@ -1380,6 +1403,23 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn)
(void)h2_process_pending_input(conn, httpc, &result);
}
+
+ /* If nghttp2 still has pending frames unsent */
+ if(nghttp2_session_want_write(h2)) {
+ struct Curl_easy *data = conn->data;
+ struct SingleRequest *k = &data->req;
+ int rv;
+
+ H2BUGF(infof(data, "HTTP/2 still wants to send data (easy %p)\n", data));
+
+ /* re-set KEEP_SEND to make sure we are called again */
+ k->keepon |= KEEP_SEND;
+
+ /* and attempt to send the pending frames */
+ rv = h2_session_send(data, h2);
+ if(rv != 0)
+ result = CURLE_SEND_ERROR;
+ }
}
return result;
}
@@ -1388,8 +1428,6 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
struct Curl_easy *data,
struct HTTP *stream, CURLcode *err)
{
- char *trailer_pos, *trailer_end;
- CURLcode result;
struct http_conn *httpc = &conn->proto.httpc;
if(httpc->pause_stream_id == stream->stream_id) {
@@ -1432,25 +1470,6 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn,
return -1;
}
- if(stream->trailer_recvbuf && stream->trailer_recvbuf->buffer) {
- trailer_pos = stream->trailer_recvbuf->buffer;
- trailer_end = trailer_pos + stream->trailer_recvbuf->size_used;
-
- for(; trailer_pos < trailer_end;) {
- uint32_t n;
- memcpy(&n, trailer_pos, sizeof(n));
- trailer_pos += sizeof(n);
-
- result = Curl_client_write(conn, CLIENTWRITE_HEADER, trailer_pos, n);
- if(result) {
- *err = result;
- return -1;
- }
-
- trailer_pos += n + 1;
- }
- }
-
stream->close_handled = TRUE;
H2BUGF(infof(data, "http2_recv returns 0, http2_handle_stream_close\n"));
@@ -1541,13 +1560,13 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
*/
if(stream->bodystarted &&
- stream->nread_header_recvbuf < stream->header_recvbuf->size_used) {
- /* If there is body data pending for this stream to return, do that */
+ stream->nread_header_recvbuf < Curl_dyn_len(&stream->header_recvbuf)) {
+ /* If there is header data pending for this stream to return, do that */
size_t left =
- stream->header_recvbuf->size_used - stream->nread_header_recvbuf;
+ Curl_dyn_len(&stream->header_recvbuf) - stream->nread_header_recvbuf;
size_t ncopy = CURLMIN(len, left);
- memcpy(mem, stream->header_recvbuf->buffer + stream->nread_header_recvbuf,
- ncopy);
+ memcpy(mem, Curl_dyn_ptr(&stream->header_recvbuf) +
+ stream->nread_header_recvbuf, ncopy);
stream->nread_header_recvbuf += ncopy;
H2BUGF(infof(data, "http2_recv: Got %d bytes from header_recvbuf\n",
@@ -2056,7 +2075,7 @@ static ssize_t http2_send(struct connectdata *conn, int sockindex,
h2_pri_spec(conn->data, &pri_spec);
- switch(conn->data->set.httpreq) {
+ switch(conn->data->state.httpreq) {
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
case HTTPREQ_POST_MIME:
@@ -2127,13 +2146,11 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
struct http_conn *httpc = &conn->proto.httpc;
struct HTTP *stream = conn->data->req.protop;
+ DEBUGASSERT(conn->data->state.buffer);
+
stream->stream_id = -1;
- if(!stream->header_recvbuf) {
- stream->header_recvbuf = Curl_add_buffer_init();
- if(!stream->header_recvbuf)
- return CURLE_OUT_OF_MEMORY;
- }
+ Curl_dyn_init(&stream->header_recvbuf, DYN_H2_HEADERS);
if((conn->handler == &Curl_handler_http2_ssl) ||
(conn->handler == &Curl_handler_http2))
@@ -2146,7 +2163,7 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
result = http2_init(conn);
if(result) {
- Curl_add_buffer_free(&stream->header_recvbuf);
+ Curl_dyn_free(&stream->header_recvbuf);
return result;
}
@@ -2154,6 +2171,8 @@ CURLcode Curl_http2_setup(struct connectdata *conn)
stream->upload_left = 0;
stream->upload_mem = NULL;
stream->upload_len = 0;
+ stream->mem = conn->data->state.buffer;
+ stream->len = conn->data->set.buffer_size;
httpc->inbuflen = 0;
httpc->nread_inbuf = 0;
diff --git a/lib/http2.h b/lib/http2.h
index 1989aff82..e82b21280 100644
--- a/lib/http2.h
+++ b/lib/http2.h
@@ -42,7 +42,7 @@ const char *Curl_http2_strerror(uint32_t err);
CURLcode Curl_http2_init(struct connectdata *conn);
void Curl_http2_init_state(struct UrlState *state);
void Curl_http2_init_userset(struct UserDefined *set);
-CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req,
+CURLcode Curl_http2_request_upgrade(struct dynbuf *req,
struct connectdata *conn);
CURLcode Curl_http2_setup(struct connectdata *conn);
CURLcode Curl_http2_switched(struct connectdata *conn,
diff --git a/lib/http_chunks.c b/lib/http_chunks.c
index b6ffa4185..767f806c8 100644
--- a/lib/http_chunks.c
+++ b/lib/http_chunks.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,7 +26,7 @@
#include "urldata.h" /* it includes http_chunks.h */
#include "sendf.h" /* for the client write stuff */
-
+#include "dynbuf.h"
#include "content_encoding.h"
#include "http.h"
#include "non-ascii.h" /* for Curl_convert_to_network prototype */
@@ -93,6 +93,7 @@ void Curl_httpchunk_init(struct connectdata *conn)
chunk->hexindex = 0; /* start at 0 */
chunk->dataleft = 0; /* no data left yet! */
chunk->state = CHUNK_HEX; /* we get hex first! */
+ Curl_dyn_init(&conn->trailer, DYN_H1_TRAILER);
}
/*
@@ -177,7 +178,6 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
/* we're now expecting data to come, unless size was zero! */
if(0 == ch->datasize) {
ch->state = CHUNK_TRAILER; /* now check for trailers */
- conn->trlPos = 0;
}
else
ch->state = CHUNK_DATA;
@@ -229,32 +229,33 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
case CHUNK_TRAILER:
if((*datap == 0x0d) || (*datap == 0x0a)) {
+ char *tr = Curl_dyn_ptr(&conn->trailer);
/* this is the end of a trailer, but if the trailer was zero bytes
there was no trailer and we move on */
- if(conn->trlPos) {
- /* we allocate trailer with 3 bytes extra room to fit this */
- conn->trailer[conn->trlPos++] = 0x0d;
- conn->trailer[conn->trlPos++] = 0x0a;
- conn->trailer[conn->trlPos] = 0;
+ if(tr) {
+ size_t trlen;
+ result = Curl_dyn_add(&conn->trailer, (char *)"\x0d\x0a");
+ if(result)
+ return CHUNKE_OUT_OF_MEMORY;
+ tr = Curl_dyn_ptr(&conn->trailer);
+ trlen = Curl_dyn_len(&conn->trailer);
/* Convert to host encoding before calling Curl_client_write */
- result = Curl_convert_from_network(conn->data, conn->trailer,
- conn->trlPos);
+ result = Curl_convert_from_network(conn->data, tr, trlen);
if(result)
/* Curl_convert_from_network calls failf if unsuccessful */
/* Treat it as a bad chunk */
return CHUNKE_BAD_CHUNK;
if(!data->set.http_te_skip) {
- result = Curl_client_write(conn, CLIENTWRITE_HEADER,
- conn->trailer, conn->trlPos);
+ result = Curl_client_write(conn, CLIENTWRITE_HEADER, tr, trlen);
if(result) {
*extrap = result;
return CHUNKE_PASSTHRU_ERROR;
}
}
- conn->trlPos = 0;
+ Curl_dyn_reset(&conn->trailer);
ch->state = CHUNK_TRAILER_CR;
if(*datap == 0x0a)
/* already on the LF */
@@ -267,25 +268,9 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn,
}
}
else {
- /* conn->trailer is assumed to be freed in url.c on a
- connection basis */
- if(conn->trlPos >= conn->trlMax) {
- /* we always allocate three extra bytes, just because when the full
- header has been received we append CRLF\0 */
- char *ptr;
- if(conn->trlMax) {
- conn->trlMax *= 2;
- ptr = realloc(conn->trailer, conn->trlMax + 3);
- }
- else {
- conn->trlMax = 128;
- ptr = malloc(conn->trlMax + 3);
- }
- if(!ptr)
- return CHUNKE_OUT_OF_MEMORY;
- conn->trailer = ptr;
- }
- conn->trailer[conn->trlPos++]=*datap;
+ result = Curl_dyn_addn(&conn->trailer, datap, 1);
+ if(result)
+ return CHUNKE_OUT_OF_MEMORY;
}
datap++;
length--;
diff --git a/lib/http_digest.c b/lib/http_digest.c
index 9616c30ed..b06dc0d82 100644
--- a/lib/http_digest.c
+++ b/lib/http_digest.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -94,15 +94,19 @@ CURLcode Curl_output_digest(struct connectdata *conn,
struct auth *authp;
if(proxy) {
+#ifdef CURL_DISABLE_PROXY
+ return CURLE_NOT_BUILT_IN;
+#else
digest = &data->state.proxydigest;
- allocuserpwd = &conn->allocptr.proxyuserpwd;
+ allocuserpwd = &data->state.aptr.proxyuserpwd;
userp = conn->http_proxy.user;
passwdp = conn->http_proxy.passwd;
authp = &data->state.authproxy;
+#endif
}
else {
digest = &data->state.digest;
- allocuserpwd = &conn->allocptr.userpwd;
+ allocuserpwd = &data->state.aptr.userpwd;
userp = conn->user;
passwdp = conn->passwd;
authp = &data->state.authhost;
diff --git a/lib/http_digest.h b/lib/http_digest.h
index 73410ae88..96e39a7dc 100644
--- a/lib/http_digest.h
+++ b/lib/http_digest.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c
index 8e1f3bf68..0a19ec2af 100644
--- a/lib/http_negotiate.c
+++ b/lib/http_negotiate.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -52,6 +52,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
curlnegotiate state;
if(proxy) {
+#ifndef CURL_DISABLE_PROXY
userp = conn->http_proxy.user;
passwdp = conn->http_proxy.passwd;
service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
@@ -59,6 +60,9 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
host = conn->http_proxy.host.name;
neg_ctx = &conn->proxyneg;
state = conn->proxy_negotiate_state;
+#else
+ return CURLE_NOT_BUILT_IN;
+#endif
}
else {
userp = conn->user;
@@ -119,7 +123,8 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
struct auth *authp = proxy ? &conn->data->state.authproxy :
&conn->data->state.authhost;
curlnegotiate *state = proxy ? &conn->proxy_negotiate_state :
- &conn->http_negotiate_state;
+ &conn->http_negotiate_state;
+ struct Curl_easy *data = conn->data;
char *base64 = NULL;
size_t len = 0;
char *userp;
@@ -164,15 +169,15 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
return result;
userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
- base64);
+ base64);
if(proxy) {
- Curl_safefree(conn->allocptr.proxyuserpwd);
- conn->allocptr.proxyuserpwd = userp;
+ Curl_safefree(data->state.aptr.proxyuserpwd);
+ data->state.aptr.proxyuserpwd = userp;
}
else {
- Curl_safefree(conn->allocptr.userpwd);
- conn->allocptr.userpwd = userp;
+ Curl_safefree(data->state.aptr.userpwd);
+ data->state.aptr.userpwd = userp;
}
free(base64);
diff --git a/lib/http_negotiate.h b/lib/http_negotiate.h
index 4f0ac1686..a737f6f78 100644
--- a/lib/http_negotiate.h
+++ b/lib/http_negotiate.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -33,6 +33,8 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
void Curl_http_auth_cleanup_negotiate(struct connectdata *conn);
-#endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
+#else /* !CURL_DISABLE_HTTP && USE_SPNEGO */
+#define Curl_http_auth_cleanup_negotiate(x)
+#endif
#endif /* HEADER_CURL_HTTP_NEGOTIATE_H */
diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c
index 342b2424f..cab543c75 100644
--- a/lib/http_ntlm.c
+++ b/lib/http_ntlm.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -131,12 +131,15 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
struct ntlmdata *ntlm;
curlntlm *state;
struct auth *authp;
+ struct Curl_easy *data = conn->data;
+
DEBUGASSERT(conn);
- DEBUGASSERT(conn->data);
+ DEBUGASSERT(data);
if(proxy) {
- allocuserpwd = &conn->allocptr.proxyuserpwd;
+#ifndef CURL_DISABLE_PROXY
+ allocuserpwd = &data->state.aptr.proxyuserpwd;
userp = conn->http_proxy.user;
passwdp = conn->http_proxy.passwd;
service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ?
@@ -145,9 +148,12 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
ntlm = &conn->proxyntlm;
state = &conn->proxy_ntlm_state;
authp = &conn->data->state.authproxy;
+#else
+ return CURLE_NOT_BUILT_IN;
+#endif
}
else {
- allocuserpwd = &conn->allocptr.userpwd;
+ allocuserpwd = &data->state.aptr.userpwd;
userp = conn->user;
passwdp = conn->passwd;
service = conn->data->set.str[STRING_SERVICE_NAME] ?
diff --git a/lib/http_ntlm.h b/lib/http_ntlm.h
index 003714dbd..3ebdf979e 100644
--- a/lib/http_ntlm.h
+++ b/lib/http_ntlm.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,6 +35,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy);
void Curl_http_auth_cleanup_ntlm(struct connectdata *conn);
-#endif /* !CURL_DISABLE_HTTP && USE_NTLM */
+#else /* !CURL_DISABLE_HTTP && USE_NTLM */
+#define Curl_http_auth_cleanup_ntlm(x)
+#endif
#endif /* HEADER_CURL_HTTP_NTLM_H */
diff --git a/lib/http_proxy.c b/lib/http_proxy.c
index 440405460..76c6ecbbb 100644
--- a/lib/http_proxy.c
+++ b/lib/http_proxy.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -72,6 +72,7 @@ static CURLcode https_proxy_connect(struct connectdata *conn, int sockindex)
CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
{
+ struct Curl_easy *data = conn->data;
if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
const CURLcode result = https_proxy_connect(conn, sockindex);
if(result)
@@ -127,7 +128,7 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
conn->data->req.protop = prot_save;
if(CURLE_OK != result)
return result;
- Curl_safefree(conn->allocptr.proxyuserpwd);
+ Curl_safefree(data->state.aptr.proxyuserpwd);
#else
return CURLE_NOT_BUILT_IN;
#endif
@@ -158,15 +159,15 @@ static CURLcode connect_init(struct connectdata *conn, bool reinit)
return CURLE_OUT_OF_MEMORY;
infof(conn->data, "allocate connect buffer!\n");
conn->connect_state = s;
+ Curl_dyn_init(&s->rcvbuf, DYN_PROXY_CONNECT_HEADERS);
}
else {
DEBUGASSERT(conn->connect_state);
s = conn->connect_state;
+ Curl_dyn_reset(&s->rcvbuf);
}
s->tunnel_state = TUNNEL_INIT;
s->keepon = TRUE;
- s->line_start = s->connect_buffer;
- s->ptr = s->line_start;
s->cl = 0;
s->close_connection = FALSE;
return CURLE_OK;
@@ -176,6 +177,7 @@ static void connect_done(struct connectdata *conn)
{
struct http_connect_state *s = conn->connect_state;
s->tunnel_state = TUNNEL_COMPLETE;
+ Curl_dyn_free(&s->rcvbuf);
infof(conn->data, "CONNECT phase completed!\n");
}
@@ -190,6 +192,8 @@ static CURLcode CONNECT(struct connectdata *conn,
CURLcode result;
curl_socket_t tunnelsocket = conn->sock[sockindex];
struct http_connect_state *s = conn->connect_state;
+ char *linep;
+ size_t perline;
#define SELECT_OK 0
#define SELECT_ERROR 1
@@ -204,7 +208,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(TUNNEL_INIT == s->tunnel_state) {
/* BEGIN CONNECT PHASE */
char *host_port;
- Curl_send_buffer *req_buffer;
+ struct dynbuf req;
infof(data, "Establish HTTP proxy tunnel to %s:%d\n",
hostname, remote_port);
@@ -215,17 +219,12 @@ static CURLcode CONNECT(struct connectdata *conn,
free(data->req.newurl);
data->req.newurl = NULL;
- /* initialize a dynamic send-buffer */
- req_buffer = Curl_add_buffer_init();
-
- if(!req_buffer)
- return CURLE_OUT_OF_MEMORY;
-
host_port = aprintf("%s:%d", hostname, remote_port);
- if(!host_port) {
- Curl_add_buffer_free(&req_buffer);
+ if(!host_port)
return CURLE_OUT_OF_MEMORY;
- }
+
+ /* initialize a dynamic send-buffer */
+ Curl_dyn_init(&req, DYN_HTTP_REQUEST);
/* Setup the proxy-authorization header, if any */
result = Curl_http_output_auth(conn, "CONNECT", host_port, TRUE);
@@ -236,8 +235,8 @@ static CURLcode CONNECT(struct connectdata *conn,
char *host = NULL;
const char *proxyconn = "";
const char *useragent = "";
- const char *http = (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ?
- "1.0" : "1.1";
+ const char *httpv =
+ (conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0) ? "1.0" : "1.1";
bool ipv6_ip = conn->bits.ipv6_ip;
char *hostheader;
@@ -248,7 +247,7 @@ static CURLcode CONNECT(struct connectdata *conn,
aprintf("%s%s%s:%d", ipv6_ip?"[":"", hostname, ipv6_ip?"]":"",
remote_port);
if(!hostheader) {
- Curl_add_buffer_free(&req_buffer);
+ Curl_dyn_free(&req);
return CURLE_OUT_OF_MEMORY;
}
@@ -256,7 +255,7 @@ static CURLcode CONNECT(struct connectdata *conn,
host = aprintf("Host: %s\r\n", hostheader);
if(!host) {
free(hostheader);
- Curl_add_buffer_free(&req_buffer);
+ Curl_dyn_free(&req);
return CURLE_OUT_OF_MEMORY;
}
}
@@ -265,52 +264,49 @@ static CURLcode CONNECT(struct connectdata *conn,
if(!Curl_checkProxyheaders(conn, "User-Agent") &&
data->set.str[STRING_USERAGENT])
- useragent = conn->allocptr.uagent;
+ useragent = data->state.aptr.uagent;
result =
- Curl_add_bufferf(&req_buffer,
- "CONNECT %s HTTP/%s\r\n"
- "%s" /* Host: */
- "%s" /* Proxy-Authorization */
- "%s" /* User-Agent */
- "%s", /* Proxy-Connection */
- hostheader,
- http,
- host?host:"",
- conn->allocptr.proxyuserpwd?
- conn->allocptr.proxyuserpwd:"",
- useragent,
- proxyconn);
+ Curl_dyn_addf(&req,
+ "CONNECT %s HTTP/%s\r\n"
+ "%s" /* Host: */
+ "%s" /* Proxy-Authorization */
+ "%s" /* User-Agent */
+ "%s", /* Proxy-Connection */
+ hostheader,
+ httpv,
+ host?host:"",
+ data->state.aptr.proxyuserpwd?
+ data->state.aptr.proxyuserpwd:"",
+ useragent,
+ proxyconn);
if(host)
free(host);
free(hostheader);
if(!result)
- result = Curl_add_custom_headers(conn, TRUE, req_buffer);
+ result = Curl_add_custom_headers(conn, TRUE, &req);
if(!result)
/* CRLF terminate the request */
- result = Curl_add_bufferf(&req_buffer, "\r\n");
+ result = Curl_dyn_add(&req, "\r\n");
if(!result) {
/* Send the connect request to the proxy */
/* BLOCKING */
- result =
- Curl_add_buffer_send(&req_buffer, conn,
- &data->info.request_size, 0, sockindex);
+ result = Curl_buffer_send(&req, conn, &data->info.request_size, 0,
+ sockindex);
}
- req_buffer = NULL;
if(result)
failf(data, "Failed sending CONNECT to proxy");
}
- Curl_add_buffer_free(&req_buffer);
+ Curl_dyn_free(&req);
if(result)
return result;
s->tunnel_state = TUNNEL_CONNECT;
- s->perline = 0;
} /* END CONNECT PHASE */
check = Curl_timeleft(data, NULL, TRUE);
@@ -330,16 +326,11 @@ static CURLcode CONNECT(struct connectdata *conn,
while(s->keepon) {
ssize_t gotbytes;
-
- /* make sure we have space to read more data */
- if(s->ptr >= &s->connect_buffer[CONNECT_BUFFER_SIZE]) {
- failf(data, "CONNECT response too large!");
- return CURLE_RECV_ERROR;
- }
+ char byte;
/* Read one byte at a time to avoid a race condition. Wait at most one
second before looping to ensure continuous pgrsUpdates. */
- result = Curl_read(conn, tunnelsocket, s->ptr, 1, &gotbytes);
+ result = Curl_read(conn, tunnelsocket, &byte, 1, &gotbytes);
if(result == CURLE_AGAIN)
/* socket buffer drained, return */
return CURLE_OK;
@@ -366,11 +357,9 @@ static CURLcode CONNECT(struct connectdata *conn,
break;
}
-
if(s->keepon > TRUE) {
/* This means we are currently ignoring a response-body */
- s->ptr = s->connect_buffer;
if(s->cl) {
/* A Content-Length based body: simply count down the counter
and make sure to break out of the loop when we're done! */
@@ -390,7 +379,7 @@ static CURLcode CONNECT(struct connectdata *conn,
/* now parse the chunked piece of data so that we can
properly tell when the stream ends */
- r = Curl_httpchunk_read(conn, s->ptr, 1, &tookcareof, &extra);
+ r = Curl_httpchunk_read(conn, &byte, 1, &tookcareof, &extra);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
infof(data, "chunk reading DONE\n");
@@ -402,25 +391,27 @@ static CURLcode CONNECT(struct connectdata *conn,
continue;
}
- s->perline++; /* amount of bytes in this line so far */
+ if(Curl_dyn_addn(&s->rcvbuf, &byte, 1)) {
+ failf(data, "CONNECT response too large!");
+ return CURLE_RECV_ERROR;
+ }
/* if this is not the end of a header line then continue */
- if(*s->ptr != 0x0a) {
- s->ptr++;
+ if(byte != 0x0a)
continue;
- }
+
+ linep = Curl_dyn_ptr(&s->rcvbuf);
+ perline = Curl_dyn_len(&s->rcvbuf); /* amount of bytes in this line */
/* convert from the network encoding */
- result = Curl_convert_from_network(data, s->line_start,
- (size_t)s->perline);
+ result = Curl_convert_from_network(data, linep, perline);
/* Curl_convert_from_network calls failf if unsuccessful */
if(result)
return result;
/* output debug if that is requested */
if(data->set.verbose)
- Curl_debug(data, CURLINFO_HEADER_IN,
- s->line_start, (size_t)s->perline);
+ Curl_debug(data, CURLINFO_HEADER_IN, linep, perline);
if(!data->set.suppress_connect_headers) {
/* send the header to the callback */
@@ -428,23 +419,22 @@ static CURLcode CONNECT(struct connectdata *conn,
if(data->set.include_header)
writetype |= CLIENTWRITE_BODY;
- result = Curl_client_write(conn, writetype,
- s->line_start, s->perline);
+ result = Curl_client_write(conn, writetype, linep, perline);
if(result)
return result;
}
- data->info.header_size += (long)s->perline;
- data->req.headerbytecount += (long)s->perline;
+ data->info.header_size += (long)perline;
+ data->req.headerbytecount += (long)perline;
/* Newlines are CRLF, so the CR is ignored as the line isn't
really terminated until the LF comes. Treat a following CR
as end-of-headers as well.*/
- if(('\r' == s->line_start[0]) ||
- ('\n' == s->line_start[0])) {
+ if(('\r' == linep[0]) ||
+ ('\n' == linep[0])) {
/* end of response-headers from the proxy */
- s->ptr = s->connect_buffer;
+
if((407 == k->httpcode) && !data->state.authproblem) {
/* If we get a 407 response code with content length
when we have no auth problem, we must ignore the
@@ -461,21 +451,18 @@ static CURLcode CONNECT(struct connectdata *conn,
infof(data, "Ignore chunked response-body\n");
- /* We set ignorebody true here since the chunked
- decoder function will acknowledge that. Pay
- attention so that this is cleared again when this
- function returns! */
+ /* We set ignorebody true here since the chunked decoder
+ function will acknowledge that. Pay attention so that this is
+ cleared again when this function returns! */
k->ignorebody = TRUE;
- if(s->line_start[1] == '\n') {
- /* this can only be a LF if the letter at index 0
- was a CR */
- s->line_start++;
- }
+ if(linep[1] == '\n')
+ /* this can only be a LF if the letter at index 0 was a CR */
+ linep++;
- /* now parse the chunked piece of data so that we can
- properly tell when the stream ends */
- r = Curl_httpchunk_read(conn, s->line_start + 1, 1, &gotbytes,
+ /* now parse the chunked piece of data so that we can properly
+ tell when the stream ends */
+ r = Curl_httpchunk_read(conn, linep + 1, 1, &gotbytes,
&extra);
if(r == CHUNKE_STOP) {
/* we're done reading chunks! */
@@ -500,14 +487,13 @@ static CURLcode CONNECT(struct connectdata *conn,
continue;
}
- s->line_start[s->perline] = 0; /* zero terminate the buffer */
- if((checkprefix("WWW-Authenticate:", s->line_start) &&
+ if((checkprefix("WWW-Authenticate:", linep) &&
(401 == k->httpcode)) ||
- (checkprefix("Proxy-authenticate:", s->line_start) &&
+ (checkprefix("Proxy-authenticate:", linep) &&
(407 == k->httpcode))) {
bool proxy = (k->httpcode == 407) ? TRUE : FALSE;
- char *auth = Curl_copy_header_value(s->line_start);
+ char *auth = Curl_copy_header_value(linep);
if(!auth)
return CURLE_OUT_OF_MEMORY;
@@ -518,7 +504,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(result)
return result;
}
- else if(checkprefix("Content-Length:", s->line_start)) {
+ else if(checkprefix("Content-Length:", linep)) {
if(k->httpcode/100 == 2) {
/* A client MUST ignore any Content-Length or Transfer-Encoding
header fields received in a successful response to CONNECT.
@@ -527,13 +513,13 @@ static CURLcode CONNECT(struct connectdata *conn,
k->httpcode);
}
else {
- (void)curlx_strtoofft(s->line_start +
+ (void)curlx_strtoofft(linep +
strlen("Content-Length:"), NULL, 10, &s->cl);
}
}
- else if(Curl_compareheader(s->line_start, "Connection:", "close"))
+ else if(Curl_compareheader(linep, "Connection:", "close"))
s->close_connection = TRUE;
- else if(checkprefix("Transfer-Encoding:", s->line_start)) {
+ else if(checkprefix("Transfer-Encoding:", linep)) {
if(k->httpcode/100 == 2) {
/* A client MUST ignore any Content-Length or Transfer-Encoding
header fields received in a successful response to CONNECT.
@@ -541,7 +527,7 @@ static CURLcode CONNECT(struct connectdata *conn,
infof(data, "Ignoring Transfer-Encoding in "
"CONNECT %03d response\n", k->httpcode);
}
- else if(Curl_compareheader(s->line_start,
+ else if(Curl_compareheader(linep,
"Transfer-Encoding:", "chunked")) {
infof(data, "CONNECT responded chunked\n");
s->chunked_encoding = TRUE;
@@ -549,19 +535,16 @@ static CURLcode CONNECT(struct connectdata *conn,
Curl_httpchunk_init(conn);
}
}
- else if(Curl_compareheader(s->line_start,
- "Proxy-Connection:", "close"))
+ else if(Curl_compareheader(linep, "Proxy-Connection:", "close"))
s->close_connection = TRUE;
- else if(2 == sscanf(s->line_start, "HTTP/1.%d %d",
+ else if(2 == sscanf(linep, "HTTP/1.%d %d",
&subversion,
&k->httpcode)) {
/* store the HTTP code from the proxy */
data->info.httpproxycode = k->httpcode;
}
- s->perline = 0; /* line starts over here */
- s->ptr = s->connect_buffer;
- s->line_start = s->ptr;
+ Curl_dyn_reset(&s->rcvbuf);
} /* while there's buffer left and loop is requested */
if(Curl_pgrsUpdate(conn))
@@ -622,6 +605,7 @@ static CURLcode CONNECT(struct connectdata *conn,
if(conn->bits.proxy_connect_closed)
/* this is not an error, just part of the connection negotiation */
return CURLE_OK;
+ Curl_dyn_free(&s->rcvbuf);
failf(data, "Received HTTP code %d from proxy after CONNECT",
data->req.httpcode);
return CURLE_RECV_ERROR;
@@ -632,8 +616,8 @@ static CURLcode CONNECT(struct connectdata *conn,
/* If a proxy-authorization header was used for the proxy, then we should
make sure that it isn't accidentally used for the document request
after we've connected. So let's free and clear it here. */
- Curl_safefree(conn->allocptr.proxyuserpwd);
- conn->allocptr.proxyuserpwd = NULL;
+ Curl_safefree(data->state.aptr.proxyuserpwd);
+ data->state.aptr.proxyuserpwd = NULL;
data->state.authproxy.done = TRUE;
data->state.authproxy.multipass = FALSE;
@@ -643,6 +627,7 @@ static CURLcode CONNECT(struct connectdata *conn,
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 */
+ Curl_dyn_free(&s->rcvbuf);
return CURLE_OK;
}
diff --git a/lib/http_proxy.h b/lib/http_proxy.h
index e19fa859a..29988a696 100644
--- a/lib/http_proxy.h
+++ b/lib/http_proxy.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,5 +47,6 @@ bool Curl_connect_ongoing(struct connectdata *conn);
#endif
void Curl_connect_free(struct Curl_easy *data);
+void Curl_connect_done(struct Curl_easy *data);
#endif /* HEADER_CURL_HTTP_PROXY_H */
diff --git a/lib/idn_win32.c b/lib/idn_win32.c
index 8dc300b36..2f5850dd0 100644
--- a/lib/idn_win32.c
+++ b/lib/idn_win32.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -72,13 +72,13 @@ bool curl_win32_idn_to_ascii(const char *in, char **out)
{
bool success = FALSE;
- wchar_t *in_w = Curl_convert_UTF8_to_wchar(in);
+ wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
if(in_w) {
wchar_t punycode[IDN_MAX_LENGTH];
int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH);
free(in_w);
if(chars) {
- *out = Curl_convert_wchar_to_UTF8(punycode);
+ *out = curlx_convert_wchar_to_UTF8(punycode);
if(*out)
success = TRUE;
}
@@ -91,7 +91,7 @@ bool curl_win32_ascii_to_idn(const char *in, char **out)
{
bool success = FALSE;
- wchar_t *in_w = Curl_convert_UTF8_to_wchar(in);
+ wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
if(in_w) {
size_t in_len = wcslen(in_w) + 1;
wchar_t unicode[IDN_MAX_LENGTH];
@@ -99,7 +99,7 @@ bool curl_win32_ascii_to_idn(const char *in, char **out)
unicode, IDN_MAX_LENGTH);
free(in_w);
if(chars) {
- *out = Curl_convert_wchar_to_UTF8(unicode);
+ *out = curlx_convert_wchar_to_UTF8(unicode);
if(*out)
success = TRUE;
}
diff --git a/lib/if2ip.c b/lib/if2ip.c
index b283f67f8..39388692e 100644
--- a/lib/if2ip.c
+++ b/lib/if2ip.c
@@ -118,7 +118,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
if(iface->ifa_addr->sa_family == af) {
if(strcasecompare(iface->ifa_name, interf)) {
void *addr;
- char *ip;
+ const char *ip;
char scope[12] = "";
char ipstr[64];
#ifdef ENABLE_IPV6
@@ -153,15 +153,15 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
}
if(scopeid)
- msnprintf(scope, sizeof(scope), "%%%u", scopeid);
+ msnprintf(scope, sizeof(scope), "%%%u", scopeid);
#endif
}
else
#endif
addr =
- &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
+ &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr;
res = IF2IP_FOUND;
- ip = (char *) Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
+ ip = Curl_inet_ntop(af, addr, ipstr, sizeof(ipstr));
msnprintf(buf, buf_size, "%s%s", ip, scope);
break;
}
@@ -190,6 +190,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
struct sockaddr_in *s;
curl_socket_t dummy;
size_t len;
+ const char *r;
(void)remote_scope;
(void)local_scope_id;
@@ -219,9 +220,11 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
s = (struct sockaddr_in *)(void *)&req.ifr_addr;
memcpy(&in, &s->sin_addr, sizeof(in));
- Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
+ r = Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
sclose(dummy);
+ if(!r)
+ return IF2IP_NOT_FOUND;
return IF2IP_FOUND;
}
diff --git a/lib/imap.c b/lib/imap.c
index 40d804be9..ce8e1f259 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -187,7 +187,7 @@ static void imap_to_imaps(struct connectdata *conn)
conn->handler = &Curl_handler_imaps;
/* Set the connection's upgraded to TLS flag */
- conn->tls_upgraded = TRUE;
+ conn->bits.tls_upgraded = TRUE;
}
#else
#define imap_to_imaps(x) Curl_nop_stmt
@@ -1710,7 +1710,7 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
return result;
/* Clear the TLS upgraded flag */
- conn->tls_upgraded = FALSE;
+ conn->bits.tls_upgraded = FALSE;
return CURLE_OK;
}
@@ -1957,7 +1957,7 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
end--;
result = Curl_urldecode(data, begin, end - begin, &imap->mailbox, NULL,
- TRUE);
+ REJECT_CTRL);
if(result)
return result;
}
@@ -1979,7 +1979,8 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
return CURLE_URL_MALFORMAT;
/* Decode the name parameter */
- result = Curl_urldecode(data, begin, ptr - begin, &name, NULL, TRUE);
+ result = Curl_urldecode(data, begin, ptr - begin, &name, NULL,
+ REJECT_CTRL);
if(result)
return result;
@@ -1989,7 +1990,8 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
ptr++;
/* Decode the value parameter */
- result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen, TRUE);
+ result = Curl_urldecode(data, begin, ptr - begin, &value, &valuelen,
+ REJECT_CTRL);
if(result) {
free(name);
return result;
@@ -2077,7 +2079,7 @@ static CURLcode imap_parse_custom_request(struct connectdata *conn)
if(custom) {
/* URL decode the custom request */
- result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, TRUE);
+ result = Curl_urldecode(data, custom, 0, &imap->custom, NULL, REJECT_CTRL);
/* Extract the parameters if specified */
if(!result) {
diff --git a/lib/ldap.c b/lib/ldap.c
index 60a423d45..401c7613e 100644
--- a/lib/ldap.c
+++ b/lib/ldap.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -75,7 +75,7 @@
/* Use our own implementation. */
-typedef struct {
+struct ldap_urldesc {
char *lud_host;
int lud_port;
#if defined(USE_WIN32_LDAP)
@@ -95,10 +95,10 @@ typedef struct {
size_t lud_attrs_dups; /* how many were dup'ed, this field is not in the
"real" struct so can only be used in code
without HAVE_LDAP_URL_PARSE defined */
-} CURL_LDAPURLDesc;
+};
#undef LDAPURLDesc
-#define LDAPURLDesc CURL_LDAPURLDesc
+#define LDAPURLDesc struct ldap_urldesc
static int _ldap_url_parse(const struct connectdata *conn,
LDAPURLDesc **ludp);
@@ -239,13 +239,13 @@ static int ldap_win_bind(struct connectdata *conn, LDAP *server,
PTCHAR inpass = NULL;
if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) {
- inuser = Curl_convert_UTF8_to_tchar((char *) user);
- inpass = Curl_convert_UTF8_to_tchar((char *) passwd);
+ inuser = curlx_convert_UTF8_to_tchar((char *) user);
+ inpass = curlx_convert_UTF8_to_tchar((char *) passwd);
rc = ldap_simple_bind_s(server, inuser, inpass);
- Curl_unicodefree(inuser);
- Curl_unicodefree(inpass);
+ curlx_unicodefree(inuser);
+ curlx_unicodefree(inpass);
}
#if defined(USE_WINDOWS_SSPI)
else {
@@ -306,7 +306,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
ldap_ssl ? "encrypted" : "cleartext");
#if defined(USE_WIN32_LDAP)
- host = Curl_convert_UTF8_to_tchar(conn->host.name);
+ host = curlx_convert_UTF8_to_tchar(conn->host.name);
if(!host) {
result = CURLE_OUT_OF_MEMORY;
@@ -517,7 +517,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
size_t name_len;
#if defined(USE_WIN32_LDAP)
TCHAR *dn = ldap_get_dn(server, entryIterator);
- name = Curl_convert_tchar_to_UTF8(dn);
+ name = curlx_convert_tchar_to_UTF8(dn);
if(!name) {
ldap_memfree(dn);
@@ -533,7 +533,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
if(result) {
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(name);
+ curlx_unicodefree(name);
#endif
ldap_memfree(dn);
@@ -544,7 +544,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
name_len);
if(result) {
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(name);
+ curlx_unicodefree(name);
#endif
ldap_memfree(dn);
@@ -554,7 +554,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result) {
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(name);
+ curlx_unicodefree(name);
#endif
ldap_memfree(dn);
@@ -564,7 +564,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
dlsize += name_len + 5;
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(name);
+ curlx_unicodefree(name);
#endif
ldap_memfree(dn);
}
@@ -576,7 +576,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
BerValue **vals;
size_t attr_len;
#if defined(USE_WIN32_LDAP)
- char *attr = Curl_convert_tchar_to_UTF8(attribute);
+ char *attr = curlx_convert_tchar_to_UTF8(attribute);
if(!attr) {
if(ber)
ber_free(ber, 0);
@@ -597,7 +597,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) {
ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(attr);
+ curlx_unicodefree(attr);
#endif
ldap_memfree(attribute);
if(ber)
@@ -611,7 +611,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) {
ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(attr);
+ curlx_unicodefree(attr);
#endif
ldap_memfree(attribute);
if(ber)
@@ -624,7 +624,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) {
ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(attr);
+ curlx_unicodefree(attr);
#endif
ldap_memfree(attribute);
if(ber)
@@ -646,7 +646,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) {
ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(attr);
+ curlx_unicodefree(attr);
#endif
ldap_memfree(attribute);
if(ber)
@@ -662,7 +662,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) {
ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(attr);
+ curlx_unicodefree(attr);
#endif
ldap_memfree(attribute);
if(ber)
@@ -680,7 +680,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) {
ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(attr);
+ curlx_unicodefree(attr);
#endif
ldap_memfree(attribute);
if(ber)
@@ -696,7 +696,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) {
ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(attr);
+ curlx_unicodefree(attr);
#endif
ldap_memfree(attribute);
if(ber)
@@ -714,7 +714,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
/* Free the attribute as we are done with it */
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(attr);
+ curlx_unicodefree(attr);
#endif
ldap_memfree(attribute);
@@ -746,7 +746,7 @@ quit:
#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(host);
+ curlx_unicodefree(host);
#endif
/* no data to transfer */
@@ -883,7 +883,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
LDAP_TRACE(("DN '%s'\n", dn));
/* Unescape the DN */
- result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, FALSE);
+ result = Curl_urldecode(conn->data, dn, 0, &unescaped, NULL, REJECT_ZERO);
if(result) {
rc = LDAP_NO_MEMORY;
@@ -892,10 +892,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
#if defined(USE_WIN32_LDAP)
/* Convert the unescaped string to a tchar */
- ludp->lud_dn = Curl_convert_UTF8_to_tchar(unescaped);
+ ludp->lud_dn = curlx_convert_UTF8_to_tchar(unescaped);
/* Free the unescaped string as we are done with it */
- Curl_unicodefree(unescaped);
+ curlx_unicodefree(unescaped);
if(!ludp->lud_dn) {
rc = LDAP_NO_MEMORY;
@@ -949,7 +949,7 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
/* Unescape the attribute */
result = Curl_urldecode(conn->data, attributes[i], 0, &unescaped, NULL,
- FALSE);
+ REJECT_ZERO);
if(result) {
free(attributes);
@@ -960,10 +960,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
#if defined(USE_WIN32_LDAP)
/* Convert the unescaped string to a tchar */
- ludp->lud_attrs[i] = Curl_convert_UTF8_to_tchar(unescaped);
+ ludp->lud_attrs[i] = curlx_convert_UTF8_to_tchar(unescaped);
/* Free the unescaped string as we are done with it */
- Curl_unicodefree(unescaped);
+ curlx_unicodefree(unescaped);
if(!ludp->lud_attrs[i]) {
free(attributes);
@@ -1018,7 +1018,8 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
LDAP_TRACE(("filter '%s'\n", filter));
/* Unescape the filter */
- result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL, FALSE);
+ result = Curl_urldecode(conn->data, filter, 0, &unescaped, NULL,
+ REJECT_ZERO);
if(result) {
rc = LDAP_NO_MEMORY;
@@ -1027,10 +1028,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
#if defined(USE_WIN32_LDAP)
/* Convert the unescaped string to a tchar */
- ludp->lud_filter = Curl_convert_UTF8_to_tchar(unescaped);
+ ludp->lud_filter = curlx_convert_UTF8_to_tchar(unescaped);
/* Free the unescaped string as we are done with it */
- Curl_unicodefree(unescaped);
+ curlx_unicodefree(unescaped);
if(!ludp->lud_filter) {
rc = LDAP_NO_MEMORY;
diff --git a/lib/md4.c b/lib/md4.c
index 10e6fc537..0fab52def 100644
--- a/lib/md4.c
+++ b/lib/md4.c
@@ -139,10 +139,11 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
/* The last #include file should be: */
#include "memdebug.h"
-typedef struct {
+struct md4_ctx {
HCRYPTPROV hCryptProv;
HCRYPTHASH hHash;
-} MD4_CTX;
+};
+typedef struct md4_ctx MD4_CTX;
static void MD4_Init(MD4_CTX *ctx)
{
@@ -184,10 +185,11 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
/* The last #include file should be: */
#include "memdebug.h"
-typedef struct {
+struct md4_ctx {
void *data;
unsigned long size;
-} MD4_CTX;
+};
+typedef struct md4_ctx MD4_CTX;
static void MD4_Init(MD4_CTX *ctx)
{
@@ -266,12 +268,13 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx)
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD4_u32plus;
-typedef struct {
+struct md4_ctx {
MD4_u32plus lo, hi;
MD4_u32plus a, b, c, d;
unsigned char buffer[64];
MD4_u32plus block[16];
-} MD4_CTX;
+};
+typedef struct md4_ctx MD4_CTX;
static void MD4_Init(MD4_CTX *ctx);
static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size);
diff --git a/lib/md5.c b/lib/md5.c
index 0fec32bc3..5271f4145 100644
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -179,10 +179,11 @@ static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
/* The last #include file should be: */
#include "memdebug.h"
-typedef struct {
+struct md5_ctx {
HCRYPTPROV hCryptProv;
HCRYPTHASH hHash;
-} MD5_CTX;
+};
+typedef struct md5_ctx MD5_CTX;
static void MD5_Init(MD5_CTX *ctx)
{
@@ -261,12 +262,13 @@ static void MD5_Final(unsigned char *digest, MD5_CTX *ctx)
/* Any 32-bit or wider unsigned integer data type will do */
typedef unsigned int MD5_u32plus;
-typedef struct {
+struct md5_ctx {
MD5_u32plus lo, hi;
MD5_u32plus a, b, c, d;
unsigned char buffer[64];
MD5_u32plus block[16];
-} MD5_CTX;
+};
+typedef struct md5_ctx MD5_CTX;
static void MD5_Init(MD5_CTX *ctx);
static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
@@ -528,7 +530,7 @@ static void MD5_Final(unsigned char *result, MD5_CTX *ctx)
#endif /* CRYPTO LIBS */
-const HMAC_params Curl_HMAC_MD5[] = {
+const struct HMAC_params Curl_HMAC_MD5[] = {
{
/* Hash initialization function. */
CURLX_FUNCTION_CAST(HMAC_hinit_func, MD5_Init),
@@ -545,7 +547,7 @@ const HMAC_params Curl_HMAC_MD5[] = {
}
};
-const MD5_params Curl_DIGEST_MD5[] = {
+const struct MD5_params Curl_DIGEST_MD5[] = {
{
/* Digest initialization function */
CURLX_FUNCTION_CAST(Curl_MD5_init_func, MD5_Init),
@@ -573,9 +575,9 @@ void Curl_md5it(unsigned char *outbuffer, const unsigned char *input,
MD5_Final(outbuffer, &ctx);
}
-MD5_context *Curl_MD5_init(const MD5_params *md5params)
+struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params)
{
- MD5_context *ctxt;
+ struct MD5_context *ctxt;
/* Create MD5 context */
ctxt = malloc(sizeof(*ctxt));
@@ -597,7 +599,7 @@ MD5_context *Curl_MD5_init(const MD5_params *md5params)
return ctxt;
}
-CURLcode Curl_MD5_update(MD5_context *context,
+CURLcode Curl_MD5_update(struct MD5_context *context,
const unsigned char *data,
unsigned int len)
{
@@ -606,7 +608,7 @@ CURLcode Curl_MD5_update(MD5_context *context,
return CURLE_OK;
}
-CURLcode Curl_MD5_final(MD5_context *context, unsigned char *result)
+CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result)
{
(*context->md5_hash->md5_final_func)(result, context->md5_hashctx);
diff --git a/lib/mime.c b/lib/mime.c
index 7518c029e..88448edc6 100644
--- a/lib/mime.c
+++ b/lib/mime.c
@@ -71,7 +71,7 @@ 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[] = {
+static const struct mime_encoder encoders[] = {
{"binary", encoder_nop_read, encoder_nop_size},
{"8bit", encoder_nop_read, encoder_nop_size},
{"7bit", encoder_7bit_read, encoder_nop_size},
@@ -269,7 +269,8 @@ static char *Curl_basename(char *path)
/* Set readback state. */
-static void mimesetstate(mime_state *state, enum mimestate tok, void *ptr)
+static void mimesetstate(struct mime_state *state,
+ enum mimestate tok, void *ptr)
{
state->state = tok;
state->ptr = ptr;
@@ -342,7 +343,7 @@ static char *strippath(const char *fullfile)
}
/* Initialize data encoder state. */
-static void cleanup_encoder_state(mime_encoder_state *p)
+static void cleanup_encoder_state(struct mime_encoder_state *p)
{
p->pos = 0;
p->bufbeg = 0;
@@ -352,9 +353,9 @@ static void cleanup_encoder_state(mime_encoder_state *p)
/* 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)
+ struct curl_mimepart *part)
{
- mime_encoder_state *st = &part->encstate;
+ struct mime_encoder_state *st = &part->encstate;
size_t insize = st->bufend - st->bufbeg;
(void) ateof;
@@ -382,7 +383,7 @@ 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)
{
- mime_encoder_state *st = &part->encstate;
+ struct mime_encoder_state *st = &part->encstate;
size_t cursize = st->bufend - st->bufbeg;
(void) ateof;
@@ -408,7 +409,7 @@ static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof,
static size_t encoder_base64_read(char *buffer, size_t size, bool ateof,
curl_mimepart *part)
{
- mime_encoder_state *st = &part->encstate;
+ struct mime_encoder_state *st = &part->encstate;
size_t cursize = 0;
int i;
char *ptr = buffer;
@@ -512,7 +513,7 @@ static curl_off_t encoder_base64_size(curl_mimepart *part)
* Check if a CRLF or end of data is in input buffer at current position + n.
* Return -1 if more data needed, 1 if CRLF or end of data, else 0.
*/
-static int qp_lookahead_eol(mime_encoder_state *st, int ateof, size_t n)
+static int qp_lookahead_eol(struct mime_encoder_state *st, int ateof, size_t n)
{
n += st->bufbeg;
if(n >= st->bufend && ateof)
@@ -529,7 +530,7 @@ static int qp_lookahead_eol(mime_encoder_state *st, int ateof, size_t n)
static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
curl_mimepart *part)
{
- mime_encoder_state *st = &part->encstate;
+ struct mime_encoder_state *st = &part->encstate;
char *ptr = buffer;
size_t cursize = 0;
int softlinebreak;
@@ -594,7 +595,6 @@ static size_t encoder_qp_read(char *buffer, size_t size, bool ateof,
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;
@@ -685,7 +685,7 @@ static void mime_mem_free(void *ptr)
/* Named file callbacks. */
/* Argument is a pointer to the mime part. */
-static int mime_open_file(curl_mimepart * part)
+static int mime_open_file(curl_mimepart *part)
{
/* Open a MIMEKIND_FILE part. */
@@ -740,7 +740,7 @@ static void mime_file_free(void *ptr)
/* Argument is a pointer to the mime structure. */
/* Readback a byte string segment. */
-static size_t readback_bytes(mime_state *state,
+static size_t readback_bytes(struct mime_state *state,
char *buffer, size_t bufsize,
const char *bytes, size_t numbytes,
const char *trail)
@@ -839,7 +839,7 @@ static size_t read_part_content(curl_mimepart *part,
static size_t read_encoded_part_content(curl_mimepart *part, char *buffer,
size_t bufsize, bool *hasread)
{
- mime_encoder_state *st = &part->encstate;
+ struct mime_encoder_state *st = &part->encstate;
size_t cursize = 0;
size_t sz;
bool ateof = FALSE;
@@ -1419,7 +1419,7 @@ CURLcode curl_mime_data(curl_mimepart *part,
if(datasize)
memcpy(part->data, data, datasize);
- part->data[datasize] = '\0'; /* Set a nul terminator as sentinel. */
+ part->data[datasize] = '\0'; /* Set a null terminator as sentinel. */
part->readfunc = mime_mem_read;
part->seekfunc = mime_mem_seek;
@@ -1502,7 +1502,7 @@ CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype)
CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding)
{
CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
- const mime_encoder *mep;
+ const struct mime_encoder *mep;
if(!part)
return result;
diff --git a/lib/mime.h b/lib/mime.h
index d7f25132e..50b7ea6b0 100644
--- a/lib/mime.h
+++ b/lib/mime.h
@@ -69,43 +69,43 @@ enum mimestrategy {
};
/* Content transfer encoder. */
-typedef struct {
+struct mime_encoder {
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 {
+struct mime_encoder_state {
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 {
+struct mime_state {
enum mimestate state; /* Current state token. */
void *ptr; /* State-dependent pointer. */
curl_off_t offset; /* State-dependent offset. */
-} mime_state;
+};
/* minimum buffer size for the boundary string */
#define MIME_BOUNDARY_LEN (24 + MIME_RAND_BOUNDARY_CHARS + 1)
/* A mime multipart. */
-struct curl_mime_s {
+struct curl_mime {
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[MIME_BOUNDARY_LEN]; /* The part boundary. */
- mime_state state; /* Current readback state. */
+ struct mime_state state; /* Current readback state. */
};
/* A mime part. */
-struct curl_mimepart_s {
+struct curl_mimepart {
struct Curl_easy *easy; /* The associated easy handle. */
curl_mime *parent; /* Parent mime structure. */
curl_mimepart *nextpart; /* Forward linked list. */
@@ -123,9 +123,9 @@ struct curl_mimepart_s {
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. */
+ struct mime_state state; /* Current readback state. */
+ const struct mime_encoder *encoder; /* Content data encoder. */
+ struct mime_encoder_state encstate; /* Data encoder state. */
size_t lastreadstatus; /* Last read callback returned status. */
};
@@ -135,21 +135,23 @@ CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
!defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
/* Prototypes. */
-void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy);
-void Curl_mime_cleanpart(curl_mimepart *part);
-CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src);
-CURLcode Curl_mime_set_subparts(curl_mimepart *part,
- curl_mime *subparts, int take_ownership);
-CURLcode Curl_mime_prepare_headers(curl_mimepart *part,
+void Curl_mime_initpart(struct curl_mimepart *part, struct Curl_easy *easy);
+void Curl_mime_cleanpart(struct curl_mimepart *part);
+CURLcode Curl_mime_duppart(struct curl_mimepart *dst,
+ const curl_mimepart *src);
+CURLcode Curl_mime_set_subparts(struct curl_mimepart *part,
+ struct curl_mime *subparts,
+ int take_ownership);
+CURLcode Curl_mime_prepare_headers(struct curl_mimepart *part,
const char *contenttype,
const char *disposition,
enum mimestrategy strategy);
-curl_off_t Curl_mime_size(curl_mimepart *part);
+curl_off_t Curl_mime_size(struct curl_mimepart *part);
size_t Curl_mime_read(char *buffer, size_t size, size_t nitems,
void *instream);
-CURLcode Curl_mime_rewind(curl_mimepart *part);
+CURLcode Curl_mime_rewind(struct curl_mimepart *part);
const char *Curl_mime_contenttype(const char *filename);
-void Curl_mime_unpause(curl_mimepart *part);
+void Curl_mime_unpause(struct curl_mimepart *part);
#else
/* if disabled */
diff --git a/lib/mprintf.c b/lib/mprintf.c
index 726853312..9458a9d1a 100644
--- a/lib/mprintf.c
+++ b/lib/mprintf.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1999 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1999 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -36,6 +36,7 @@
*/
#include "curl_setup.h"
+#include "dynbuf.h"
#include <gnurl/mprintf.h>
#include "curl_memory.h"
@@ -145,7 +146,7 @@ enum {
FLAGS_FLOATG = 1<<19 /* %g or %G */
};
-typedef struct {
+struct va_stack {
FormatType type;
int flags;
long width; /* width OR width parameter number */
@@ -159,7 +160,7 @@ typedef struct {
} num;
double dnum;
} data;
-} va_stack_t;
+};
struct nsprintf {
char *buffer;
@@ -168,11 +169,9 @@ struct nsprintf {
};
struct asprintf {
- char *buffer; /* allocated buffer */
- size_t len; /* length of string */
- size_t alloc; /* length of alloc */
- int fail; /* (!= 0) if an alloc has failed and thus
- the output is not the complete data */
+ struct dynbuf b;
+ bool fail; /* if an alloc has failed and thus the output is not the complete
+ data */
};
static long dprintf_DollarString(char *input, char **end)
@@ -224,8 +223,8 @@ static bool dprintf_IsQualifierNoDollar(const char *fmt)
*
******************************************************************/
-static int dprintf_Pass1(const char *format, va_stack_t *vto, char **endpos,
- va_list arglist)
+static int dprintf_Pass1(const char *format, struct va_stack *vto,
+ char **endpos, va_list arglist)
{
char *fmt = (char *)format;
int param_num = 0;
@@ -571,13 +570,11 @@ static int dprintf_formatf(
long param; /* current parameter to read */
long param_num = 0; /* parameter counter */
- va_stack_t vto[MAX_PARAMETERS];
+ struct va_stack vto[MAX_PARAMETERS];
char *endpos[MAX_PARAMETERS];
char **end;
-
char work[BUFFSIZE];
-
- va_stack_t *p;
+ struct va_stack *p;
/* 'workend' points to the final buffer byte position, but with an extra
byte as margin to avoid the (false?) warning Coverity gives us
@@ -1031,35 +1028,10 @@ static int alloc_addbyter(int output, FILE *data)
struct asprintf *infop = (struct asprintf *)data;
unsigned char outc = (unsigned char)output;
- if(!infop->buffer) {
- infop->buffer = malloc(32);
- if(!infop->buffer) {
- infop->fail = 1;
- return -1; /* fail */
- }
- infop->alloc = 32;
- infop->len = 0;
- }
- else if(infop->len + 1 >= infop->alloc) {
- char *newptr = NULL;
- size_t newsize = infop->alloc*2;
-
- /* detect wrap-around or other overflow problems */
- if(newsize > infop->alloc)
- newptr = realloc(infop->buffer, newsize);
-
- if(!newptr) {
- infop->fail = 1;
- return -1; /* fail */
- }
- infop->buffer = newptr;
- infop->alloc = newsize;
+ if(Curl_dyn_addn(&infop->b, &outc, 1)) {
+ infop->fail = 1;
+ return -1; /* fail */
}
-
- infop->buffer[ infop->len ] = outc;
-
- infop->len++;
-
return outc; /* fputc() returns like this on success */
}
@@ -1068,24 +1040,18 @@ char *curl_maprintf(const char *format, ...)
va_list ap_save; /* argument pointer */
int retcode;
struct asprintf info;
-
- info.buffer = NULL;
- info.len = 0;
- info.alloc = 0;
+ Curl_dyn_init(&info.b, DYN_APRINTF);
info.fail = 0;
va_start(ap_save, format);
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
va_end(ap_save);
if((-1 == retcode) || info.fail) {
- if(info.alloc)
- free(info.buffer);
+ Curl_dyn_free(&info.b);
return NULL;
}
- if(info.alloc) {
- info.buffer[info.len] = 0; /* we terminate this with a zero byte */
- return info.buffer;
- }
+ if(Curl_dyn_len(&info.b))
+ return Curl_dyn_ptr(&info.b);
return strdup("");
}
@@ -1093,23 +1059,16 @@ char *curl_mvaprintf(const char *format, va_list ap_save)
{
int retcode;
struct asprintf info;
-
- info.buffer = NULL;
- info.len = 0;
- info.alloc = 0;
+ Curl_dyn_init(&info.b, DYN_APRINTF);
info.fail = 0;
retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save);
if((-1 == retcode) || info.fail) {
- if(info.alloc)
- free(info.buffer);
+ Curl_dyn_free(&info.b);
return NULL;
}
-
- if(info.alloc) {
- info.buffer[info.len] = 0; /* we terminate this with a zero byte */
- return info.buffer;
- }
+ if(Curl_dyn_len(&info.b))
+ return Curl_dyn_ptr(&info.b);
return strdup("");
}
diff --git a/lib/mqtt.c b/lib/mqtt.c
index 73ccf4a82..0baffe2a7 100644
--- a/lib/mqtt.c
+++ b/lib/mqtt.c
@@ -211,7 +211,8 @@ static CURLcode mqtt_get_topic(struct connectdata *conn,
char *path = conn->data->state.up.path;
if(strlen(path) > 1) {
- result = Curl_urldecode(conn->data, path + 1, 0, topic, topiclen, FALSE);
+ result = Curl_urldecode(conn->data, path + 1, 0, topic, topiclen,
+ REJECT_NADA);
}
else {
failf(conn->data, "Error: No topic specified.");
@@ -591,7 +592,7 @@ static CURLcode mqtt_doing(struct connectdata *conn, bool *done)
if(result)
break;
- if(conn->data->set.httpreq == HTTPREQ_POST) {
+ if(conn->data->state.httpreq == HTTPREQ_POST) {
result = mqtt_publish(conn);
if(!result) {
result = mqtt_disconnect(conn);
diff --git a/lib/multi.c b/lib/multi.c
index 36cf5f346..e1d193d78 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -79,7 +79,6 @@ static CURLMcode add_next_timeout(struct curltime now,
static CURLMcode multi_timeout(struct Curl_multi *multi,
long *timeout_ms);
static void process_pending_handles(struct Curl_multi *multi);
-static void detach_connnection(struct Curl_easy *data);
#ifdef DEBUGBUILD
static const char * const statename[]={
@@ -112,7 +111,7 @@ static void Curl_init_completed(struct Curl_easy *data)
/* Important: reset the conn pointer so that we don't point to memory
that could be freed anytime */
- detach_connnection(data);
+ Curl_detach_connnection(data);
Curl_expire_clear(data); /* stop all timers */
}
@@ -169,9 +168,11 @@ static void mstate(struct Curl_easy *data, CURLMstate state
}
#endif
- if(state == CURLM_STATE_COMPLETED)
+ if(state == CURLM_STATE_COMPLETED) {
/* changing to COMPLETED means there's one less easy handle 'alive' */
+ DEBUGASSERT(data->multi->num_alive > 0);
data->multi->num_alive--;
+ }
/* if this state has an init-function, run it */
if(finit[state])
@@ -506,6 +507,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
easy handle is added */
memset(&multi->timer_lastcall, 0, sizeof(multi->timer_lastcall));
+ CONNCACHE_LOCK(data);
/* The closure handle only ever has default timeouts set. To improve the
state somewhat we clone the timeouts from each added handle so that the
closure handle always has the same timeouts as the most recently added
@@ -515,6 +517,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
data->set.server_response_timeout;
data->state.conn_cache->closure_handle->set.no_signal =
data->set.no_signal;
+ CONNCACHE_UNLOCK(data);
Curl_update_timer(multi);
return CURLM_OK;
@@ -589,14 +592,14 @@ static CURLcode multi_done(struct Curl_easy *data,
process_pending_handles(data->multi); /* connection / multiplex */
- CONN_LOCK(data);
- detach_connnection(data);
+ CONNCACHE_LOCK(data);
+ Curl_detach_connnection(data);
if(CONN_INUSE(conn)) {
/* Stop if still used. */
/* conn->data must not remain pointing to this transfer since it is going
away! Find another to own it! */
conn->data = conn->easyq.head->ptr;
- CONN_UNLOCK(data);
+ CONNCACHE_UNLOCK(data);
DEBUGF(infof(data, "Connection still in use %zu, "
"no more multi_done now!\n",
conn->easyq.size));
@@ -615,7 +618,7 @@ static CURLcode multi_done(struct Curl_easy *data,
/* 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++) {
- free(data->state.tempwrite[i].buf);
+ Curl_dyn_free(&data->state.tempwrite[i].b);
}
data->state.tempcount = 0;
@@ -647,7 +650,8 @@ static CURLcode multi_done(struct Curl_easy *data,
|| (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
CURLcode res2;
connclose(conn, "disconnecting");
- CONN_UNLOCK(data);
+ Curl_conncache_remove_conn(data, conn, FALSE);
+ CONNCACHE_UNLOCK(data);
res2 = Curl_disconnect(data, conn, premature);
/* If we had an error already, make sure we return that one. But
@@ -657,16 +661,20 @@ static CURLcode multi_done(struct Curl_easy *data,
}
else {
char buffer[256];
+ const char *host =
+#ifndef CURL_DISABLE_PROXY
+ conn->bits.socksproxy ?
+ conn->socks_proxy.host.dispname :
+ conn->bits.httpproxy ? conn->http_proxy.host.dispname :
+#endif
+ conn->bits.conn_to_host ? conn->conn_to_host.dispname :
+ conn->host.dispname;
/* create string before returning the connection */
msnprintf(buffer, sizeof(buffer),
"Connection #%ld to host %s left intact",
- conn->connection_id,
- conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
- conn->bits.httpproxy ? conn->http_proxy.host.dispname :
- conn->bits.conn_to_host ? conn->conn_to_host.dispname :
- conn->host.dispname);
+ conn->connection_id, host);
/* the connection is no longer in use by this transfer */
- CONN_UNLOCK(data);
+ CONNCACHE_UNLOCK(data);
if(Curl_conncache_return_conn(data, conn)) {
/* remember the most recently used connection */
data->state.lastconnect = conn;
@@ -676,6 +684,7 @@ static CURLcode multi_done(struct Curl_easy *data,
data->state.lastconnect = NULL;
}
+ Curl_safefree(data->state.buffer);
Curl_free_request_state(data);
return result;
}
@@ -778,8 +787,7 @@ CURLMcode curl_multi_remove_handle(struct Curl_multi *multi,
vanish with this handle */
/* Remove the association between the connection and the handle */
- if(data->conn)
- detach_connnection(data);
+ Curl_detach_connnection(data);
#ifdef USE_LIBPSL
/* Remove the PSL association. */
@@ -828,9 +836,13 @@ bool Curl_multiplex_wanted(const struct Curl_multi *multi)
return (multi && (multi->multiplexing));
}
-/* This is the only function that should clear data->conn. This will
- occasionally be called with the pointer already cleared. */
-static void detach_connnection(struct Curl_easy *data)
+/*
+ * Curl_detach_connnection() removes the given transfer from the connection.
+ *
+ * This is the only function that should clear data->conn. This will
+ * occasionally be called with the data->conn pointer already cleared.
+ */
+void Curl_detach_connnection(struct Curl_easy *data)
{
struct connectdata *conn = data->conn;
if(conn)
@@ -838,7 +850,11 @@ static void detach_connnection(struct Curl_easy *data)
data->conn = NULL;
}
-/* This is the only function that should assign data->conn */
+/*
+ * Curl_attach_connnection() attaches this transfer to this connection.
+ *
+ * This is the only function that should assign data->conn
+ */
void Curl_attach_connnection(struct Curl_easy *data,
struct connectdata *conn)
{
@@ -857,9 +873,11 @@ static int waitconnect_getsock(struct connectdata *conn,
int rc = 0;
#ifdef USE_SSL
+#ifndef CURL_DISABLE_PROXY
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
return Curl_ssl_getsock(conn, sock);
#endif
+#endif
if(SOCKS_STATE(conn->cnnct.state))
return Curl_SOCKS_getsock(conn, sock, FIRSTSOCKET);
@@ -1239,7 +1257,7 @@ static CURLMcode Curl_multi_wait(struct Curl_multi *multi,
timeout */
else if((sleep_ms < 0) && extrawait)
sleep_ms = timeout_ms;
- Curl_wait_ms((int)sleep_ms);
+ Curl_wait_ms(sleep_ms);
}
}
@@ -1480,7 +1498,7 @@ static CURLcode protocol_connect(struct connectdata *conn,
}
if(!conn->bits.protoconnstart) {
-
+#ifndef CURL_DISABLE_PROXY
result = Curl_proxy_connect(conn, FIRSTSOCKET);
if(result)
return result;
@@ -1494,7 +1512,7 @@ static CURLcode protocol_connect(struct connectdata *conn,
/* when using an HTTP tunnel proxy, await complete tunnel establishment
before proceeding further. Return CURLE_OK so we'll be called again */
return CURLE_OK;
-
+#endif
if(conn->handler->connect_it) {
/* is there a protocol-specific connect() procedure? */
@@ -1513,6 +1531,21 @@ static CURLcode protocol_connect(struct connectdata *conn,
return result; /* pass back status */
}
+/*
+ * Curl_preconnect() is called immediately before a connect starts. When a
+ * redirect is followed, this is then called multiple times during a single
+ * transfer.
+ */
+CURLcode Curl_preconnect(struct Curl_easy *data)
+{
+ if(!data->state.buffer) {
+ data->state.buffer = malloc(data->set.buffer_size + 1);
+ if(!data->state.buffer)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ return CURLE_OK;
+}
+
static CURLMcode multi_runsingle(struct Curl_multi *multi,
struct curltime now,
@@ -1540,19 +1573,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
bool stream_error = FALSE;
rc = CURLM_OK;
- DEBUGASSERT((data->mstate <= CURLM_STATE_CONNECT) ||
- (data->mstate >= CURLM_STATE_DONE) ||
- data->conn);
- if(!data->conn &&
- data->mstate > CURLM_STATE_CONNECT &&
- data->mstate < CURLM_STATE_DONE) {
- /* In all these states, the code will blindly access 'data->conn'
- so this is precaution that it isn't NULL. And it silences static
- analyzers. */
- failf(data, "In state %d with no conn, bail out!\n", data->mstate);
- return CURLM_INTERNAL_ERROR;
- }
-
if(multi_ischanged(multi, TRUE)) {
DEBUGF(infof(data, "multi changed, check CONNECT_PEND queue!\n"));
process_pending_handles(multi); /* multiplexed */
@@ -1633,6 +1653,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
case CURLM_STATE_CONNECT:
/* Connect. We want to get a connection identifier filled in. */
+ /* init this transfer. */
+ result = Curl_preconnect(data);
+ if(result)
+ break;
+
Curl_pgrsTime(data, TIMER_STARTSINGLE);
if(data->set.timeout)
Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
@@ -1690,9 +1715,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
const char *hostname;
DEBUGASSERT(conn);
+#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy)
hostname = conn->http_proxy.host.name;
- else if(conn->bits.conn_to_host)
+ else
+#endif
+ if(conn->bits.conn_to_host)
hostname = conn->conn_to_host.name;
else
hostname = conn->host.name;
@@ -1758,7 +1786,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */
DEBUGASSERT(data->conn);
result = Curl_http_connect(data->conn, &protocol_connected);
-
+#ifndef CURL_DISABLE_PROXY
if(data->conn->bits.proxy_connect_closed) {
rc = CURLM_CALL_MULTI_PERFORM;
/* connect back to proxy again */
@@ -1766,15 +1794,20 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multi_done(data, CURLE_OK, FALSE);
multistate(data, CURLM_STATE_CONNECT);
}
- else if(!result) {
- if((data->conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
- data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
- Curl_connect_complete(data->conn)) {
- rc = CURLM_CALL_MULTI_PERFORM;
- /* initiate protocol connect phase */
- multistate(data, CURLM_STATE_SENDPROTOCONNECT);
+ else
+#endif
+ if(!result) {
+ if(
+#ifndef CURL_DISABLE_PROXY
+ (data->conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
+ data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
+#endif
+ Curl_connect_complete(data->conn)) {
+ rc = CURLM_CALL_MULTI_PERFORM;
+ /* initiate protocol connect phase */
+ multistate(data, CURLM_STATE_SENDPROTOCONNECT);
+ }
}
- }
else if(result)
stream_error = TRUE;
break;
@@ -1786,17 +1819,25 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
result = Curl_is_connected(data->conn, FIRSTSOCKET, &connected);
if(connected && !result) {
#ifndef CURL_DISABLE_HTTP
- if((data->conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
- !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
- Curl_connect_ongoing(data->conn)) {
+ if(
+#ifndef CURL_DISABLE_PROXY
+ (data->conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
+ !data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
+#endif
+ Curl_connect_ongoing(data->conn)) {
multistate(data, CURLM_STATE_WAITPROXYCONNECT);
break;
}
#endif
rc = CURLM_CALL_MULTI_PERFORM;
- multistate(data, data->conn->bits.tunnel_proxy?
+#ifndef CURL_DISABLE_PROXY
+ multistate(data,
+ data->conn->bits.tunnel_proxy?
CURLM_STATE_WAITPROXYCONNECT:
CURLM_STATE_SENDPROTOCONNECT);
+#else
+ multistate(data, CURLM_STATE_SENDPROTOCONNECT);
+#endif
}
else if(result) {
/* failure detected */
@@ -2062,7 +2103,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
char *newurl = NULL;
bool retry = FALSE;
bool comeback = FALSE;
-
+ DEBUGASSERT(data->state.buffer);
/* check if over send speed */
send_timeout_ms = 0;
if(data->set.max_send_speed > 0)
@@ -2235,8 +2276,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
* access free'd data, if the connection is free'd and the handle
* removed before we perform the processing in CURLM_STATE_COMPLETED
*/
- if(data->conn)
- detach_connnection(data);
+ Curl_detach_connnection(data);
}
#ifndef CURL_DISABLE_FTP
@@ -2288,7 +2328,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* This is where we make sure that the conn pointer is reset.
We don't have to do this in every case block above where a
failure is detected */
- detach_connnection(data);
+ Curl_detach_connnection(data);
+
+ /* remove connection from cache */
+ Curl_conncache_remove_conn(data, conn, TRUE);
/* disconnect properly */
Curl_disconnect(data, conn, dead_connection);
diff --git a/lib/multiif.h b/lib/multiif.h
index bde755ee0..7d574df92 100644
--- a/lib/multiif.h
+++ b/lib/multiif.h
@@ -33,9 +33,11 @@ void Curl_expire_done(struct Curl_easy *data, expire_id id);
void Curl_update_timer(struct Curl_multi *multi);
void Curl_attach_connnection(struct Curl_easy *data,
struct connectdata *conn);
+void Curl_detach_connnection(struct Curl_easy *data);
bool Curl_multiplex_wanted(const struct Curl_multi *multi);
void Curl_set_in_callback(struct Curl_easy *data, bool value);
bool Curl_is_in_callback(struct Curl_easy *easy);
+CURLcode Curl_preconnect(struct Curl_easy *data);
/* Internal version of curl_multi_init() accepts size parameters for the
socket and connection hashes */
diff --git a/lib/nwlib.c b/lib/nwlib.c
index 7bf5f51c3..beec0b388 100644
--- a/lib/nwlib.c
+++ b/lib/nwlib.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -36,21 +36,19 @@
/* The last #include file should be: */
#include "memdebug.h"
-typedef struct
-{
+struct libthreaddata {
int _errno;
void *twentybytes;
-} libthreaddata_t;
+};
-typedef struct
-{
+struct libdata {
int x;
int y;
int z;
void *tenbytes;
NXKey_t perthreadkey; /* if -1, no key obtained... */
NXMutex_t *lock;
-} libdata_t;
+};
int gLibId = -1;
void *gLibHandle = (void *) NULL;
@@ -60,7 +58,8 @@ NXMutex_t *gLibLock = (NXMutex_t *) NULL;
/* internal library function prototypes... */
int DisposeLibraryData(void *);
void DisposeThreadData(void *);
-int GetOrSetUpData(int id, libdata_t **data, libthreaddata_t **threaddata);
+int GetOrSetUpData(int id, struct libdata **data,
+ struct libthreaddata **threaddata);
int _NonAppStart(void *NLMHandle,
@@ -154,24 +153,24 @@ int _NonAppCheckUnload(void)
return 0;
}
-int GetOrSetUpData(int id, libdata_t **appData,
- libthreaddata_t **threadData)
+int GetOrSetUpData(int id, struct libdata **appData,
+ struct libthreaddata **threadData)
{
int err;
- libdata_t *app_data;
- libthreaddata_t *thread_data;
+ struct libdata *app_data;
+ struct libthreaddata *thread_data;
NXKey_t key;
NX_LOCK_INFO_ALLOC(liblock, "Application Data Lock", 0);
err = 0;
- thread_data = (libthreaddata_t *) NULL;
+ thread_data = (struct libthreaddata_t *) NULL;
/*
* Attempt to get our data for the application calling us. This is where we
* store whatever application-specific information we need to carry in
* support of calling applications.
*/
- app_data = (libdata_t *) get_app_data(id);
+ app_data = (struct libdata *) get_app_data(id);
if(!app_data) {
/*
@@ -184,9 +183,9 @@ int GetOrSetUpData(int id, libdata_t **appData,
*/
NXLock(gLibLock);
- app_data = (libdata_t *) get_app_data(id);
+ app_data = (struct libdata *) get_app_data(id);
if(!app_data) {
- app_data = calloc(1, sizeof(libdata_t));
+ app_data = calloc(1, sizeof(struct libdata));
if(app_data) {
app_data->tenbytes = malloc(10);
@@ -249,7 +248,7 @@ int GetOrSetUpData(int id, libdata_t **appData,
* a pointer is not very important, this just helps to demonstrate that
* we can have arbitrarily complex per-thread data.
*/
- thread_data = malloc(sizeof(libthreaddata_t));
+ thread_data = malloc(sizeof(struct libthreaddata));
if(thread_data) {
thread_data->_errno = 0;
@@ -257,7 +256,7 @@ int GetOrSetUpData(int id, libdata_t **appData,
if(!thread_data->twentybytes) {
free(thread_data);
- thread_data = (libthreaddata_t *) NULL;
+ thread_data = (struct libthreaddata *) NULL;
err = ENOMEM;
}
@@ -265,7 +264,7 @@ int GetOrSetUpData(int id, libdata_t **appData,
if(err) {
free(thread_data->twentybytes);
free(thread_data);
- thread_data = (libthreaddata_t *) NULL;
+ thread_data = (struct libthreaddata *) NULL;
}
}
}
@@ -295,7 +294,7 @@ int DisposeLibraryData(void *data)
void DisposeThreadData(void *data)
{
if(data) {
- void *twentybytes = ((libthreaddata_t *) data)->twentybytes;
+ void *twentybytes = ((struct libthreaddata *) data)->twentybytes;
free(twentybytes);
free(data);
diff --git a/lib/openldap.c b/lib/openldap.c
index 2b2ecb235..e50f8de14 100644
--- a/lib/openldap.c
+++ b/lib/openldap.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
- * Copyright (C) 2011 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2011 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -162,10 +162,10 @@ struct ldapconninfo {
bool didbind;
};
-typedef struct ldapreqinfo {
+struct ldapreqinfo {
int msgid;
int nument;
-} ldapreqinfo;
+};
static CURLcode ldap_setup_connection(struct connectdata *conn)
{
@@ -374,7 +374,7 @@ static CURLcode ldap_disconnect(struct connectdata *conn, bool dead_connection)
static CURLcode ldap_do(struct connectdata *conn, bool *done)
{
struct ldapconninfo *li = conn->proto.ldapc;
- ldapreqinfo *lr;
+ struct ldapreqinfo *lr;
CURLcode status = CURLE_OK;
int rc = 0;
LDAPURLDesc *ludp = NULL;
@@ -406,7 +406,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc));
return CURLE_LDAP_SEARCH_FAILED;
}
- lr = calloc(1, sizeof(ldapreqinfo));
+ lr = calloc(1, sizeof(struct ldapreqinfo));
if(!lr)
return CURLE_OUT_OF_MEMORY;
lr->msgid = msgid;
@@ -419,7 +419,7 @@ static CURLcode ldap_do(struct connectdata *conn, bool *done)
static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
bool premature)
{
- ldapreqinfo *lr = conn->data->req.protop;
+ struct ldapreqinfo *lr = conn->data->req.protop;
(void)res;
(void)premature;
@@ -443,7 +443,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
{
struct ldapconninfo *li = conn->proto.ldapc;
struct Curl_easy *data = conn->data;
- ldapreqinfo *lr = data->req.protop;
+ struct ldapreqinfo *lr = data->req.protop;
int rc, ret;
LDAPMessage *msg = NULL;
LDAPMessage *ent;
diff --git a/lib/pingpong.c b/lib/pingpong.c
index d0710053b..314331521 100644
--- a/lib/pingpong.c
+++ b/lib/pingpong.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,12 +44,12 @@
/* Returns timeout in ms. 0 or negative number means the timeout has already
triggered */
-time_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting)
+timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting)
{
struct connectdata *conn = pp->conn;
struct Curl_easy *data = conn->data;
- time_t timeout_ms; /* in milliseconds */
- long response_time = (data->set.server_response_timeout)?
+ timediff_t timeout_ms; /* in milliseconds */
+ timediff_t 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
@@ -60,12 +60,12 @@ time_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting)
/* Without a requested timeout, we only wait 'response_time' seconds for the
full response to arrive before we bail out */
timeout_ms = response_time -
- (time_t)Curl_timediff(Curl_now(), pp->response); /* spent time */
+ Curl_timediff(Curl_now(), pp->response); /* spent time */
if(data->set.timeout && !disconnecting) {
/* if timeout is requested, find out how much remaining time we have */
- time_t timeout2_ms = data->set.timeout - /* timeout time */
- (time_t)Curl_timediff(Curl_now(), conn->now); /* spent time */
+ timediff_t timeout2_ms = data->set.timeout - /* timeout time */
+ Curl_timediff(Curl_now(), conn->now); /* spent time */
/* pick the lowest number */
timeout_ms = CURLMIN(timeout_ms, timeout2_ms);
@@ -83,8 +83,8 @@ CURLcode Curl_pp_statemach(struct pingpong *pp, bool block,
struct connectdata *conn = pp->conn;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
int rc;
- time_t interval_ms;
- time_t timeout_ms = Curl_pp_state_timeout(pp, disconnecting);
+ timediff_t interval_ms;
+ timediff_t timeout_ms = Curl_pp_state_timeout(pp, disconnecting);
struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
@@ -384,10 +384,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
if(pp->endofresp(conn, pp->linestart_resp, perline, code)) {
/* This is the end of the last line, copy the last line to the
- start of the buffer and zero terminate, for old times sake */
+ start of the buffer and null-terminate, for old times sake */
size_t n = ptr - pp->linestart_resp;
memmove(buf, pp->linestart_resp, n);
- buf[n] = 0; /* zero terminate */
+ buf[n] = 0; /* null-terminate */
keepon = FALSE;
pp->linestart_resp = ptr + 1; /* advance pointer */
i++; /* skip this before getting out */
diff --git a/lib/pingpong.h b/lib/pingpong.h
index 849a7c0ff..e874799d4 100644
--- a/lib/pingpong.h
+++ b/lib/pingpong.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -60,9 +60,8 @@ struct pingpong {
size_t sendsize; /* total size of the sendthis buffer */
struct curltime response; /* set to Curl_now() when a command has been sent
off, used to time-out response reading */
- long response_time; /* When no timeout is given, this is the amount of
- milliseconds we await for a server response. */
-
+ timediff_t response_time; /* When no timeout is given, this is the amount of
+ milliseconds we await for a server response. */
struct connectdata *conn; /* points to the connectdata struct that this
belongs to */
@@ -89,7 +88,7 @@ void Curl_pp_init(struct pingpong *pp);
/* Returns timeout in ms. 0 or negative number means the timeout has already
triggered */
-time_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting);
+timediff_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting);
/***********************************************************************
diff --git a/lib/pop3.c b/lib/pop3.c
index bc1560061..cc88df756 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -178,7 +178,7 @@ static void pop3_to_pop3s(struct connectdata *conn)
conn->handler = &Curl_handler_pop3s;
/* Set the connection's upgraded to TLS flag */
- conn->tls_upgraded = TRUE;
+ conn->bits.tls_upgraded = TRUE;
}
#else
#define pop3_to_pop3s(x) Curl_nop_stmt
@@ -412,7 +412,7 @@ static CURLcode pop3_perform_apop(struct connectdata *conn)
CURLcode result = CURLE_OK;
struct pop3_conn *pop3c = &conn->proto.pop3c;
size_t i;
- MD5_context *ctxt;
+ struct MD5_context *ctxt;
unsigned char digest[MD5_DIGEST_LEN];
char secret[2 * MD5_DIGEST_LEN + 1];
@@ -1312,7 +1312,7 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
return result;
/* Clear the TLS upgraded flag */
- conn->tls_upgraded = FALSE;
+ conn->bits.tls_upgraded = FALSE;
return CURLE_OK;
}
@@ -1390,7 +1390,7 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
const char *path = &data->state.up.path[1]; /* skip leading path */
/* URL decode the path for the message ID */
- return Curl_urldecode(data, path, 0, &pop3->id, NULL, TRUE);
+ return Curl_urldecode(data, path, 0, &pop3->id, NULL, REJECT_CTRL);
}
/***********************************************************************
@@ -1408,7 +1408,7 @@ static CURLcode pop3_parse_custom_request(struct connectdata *conn)
/* URL decode the custom request */
if(custom)
- result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, TRUE);
+ result = Curl_urldecode(data, custom, 0, &pop3->custom, NULL, REJECT_CTRL);
return result;
}
diff --git a/lib/progress.c b/lib/progress.c
index 60a941ab2..895138448 100644
--- a/lib/progress.c
+++ b/lib/progress.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -282,9 +282,9 @@ timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize,
* stay below 'limit'.
*/
if(size < CURL_OFF_T_MAX/1000)
- minimum = (time_t) (CURL_OFF_T_C(1000) * size / limit);
+ minimum = (timediff_t) (CURL_OFF_T_C(1000) * size / limit);
else {
- minimum = (time_t) (size / limit);
+ minimum = (timediff_t) (size / limit);
if(minimum < TIMEDIFF_T_MAX/1000)
minimum *= 1000;
else
diff --git a/lib/quic.h b/lib/quic.h
index 1eb23e976..8e7df90ea 100644
--- a/lib/quic.h
+++ b/lib/quic.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -47,11 +47,13 @@ int Curl_quic_ver(char *p, size_t len);
CURLcode Curl_quic_done_sending(struct connectdata *conn);
void Curl_quic_done(struct Curl_easy *data, bool premature);
bool Curl_quic_data_pending(const struct Curl_easy *data);
+void Curl_quic_disconnect(struct connectdata *conn, int tempindex);
#else /* ENABLE_QUIC */
#define Curl_quic_done_sending(x)
#define Curl_quic_done(x,y)
#define Curl_quic_data_pending(x)
+#define Curl_quic_disconnect(x,y)
#endif /* !ENABLE_QUIC */
#endif /* HEADER_CURL_QUIC_H */
diff --git a/lib/rtsp.c b/lib/rtsp.c
index ee375456b..02cae53c7 100644
--- a/lib/rtsp.c
+++ b/lib/rtsp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -233,7 +233,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
CURLcode result = CURLE_OK;
Curl_RtspReq rtspreq = data->set.rtspreq;
struct RTSP *rtsp = data->req.protop;
- Curl_send_buffer *req_buffer;
+ struct dynbuf req_buffer;
curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */
curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */
@@ -333,12 +333,12 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_SETUP && !p_transport) {
/* New Transport: setting? */
if(data->set.str[STRING_RTSP_TRANSPORT]) {
- Curl_safefree(conn->allocptr.rtsp_transport);
+ Curl_safefree(data->state.aptr.rtsp_transport);
- conn->allocptr.rtsp_transport =
+ data->state.aptr.rtsp_transport =
aprintf("Transport: %s\r\n",
data->set.str[STRING_RTSP_TRANSPORT]);
- if(!conn->allocptr.rtsp_transport)
+ if(!data->state.aptr.rtsp_transport)
return CURLE_OUT_OF_MEMORY;
}
else {
@@ -347,7 +347,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- p_transport = conn->allocptr.rtsp_transport;
+ p_transport = data->state.aptr.rtsp_transport;
}
/* Accept Headers for DESCRIBE requests */
@@ -359,14 +359,14 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Accept-Encoding header */
if(!Curl_checkheaders(conn, "Accept-Encoding") &&
data->set.str[STRING_ENCODING]) {
- Curl_safefree(conn->allocptr.accept_encoding);
- conn->allocptr.accept_encoding =
+ Curl_safefree(data->state.aptr.accept_encoding);
+ data->state.aptr.accept_encoding =
aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]);
- if(!conn->allocptr.accept_encoding)
+ if(!data->state.aptr.accept_encoding)
return CURLE_OUT_OF_MEMORY;
- p_accept_encoding = conn->allocptr.accept_encoding;
+ p_accept_encoding = data->state.aptr.accept_encoding;
}
}
@@ -374,13 +374,13 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
it might have been used in the proxy connect, but if we have got a header
with the user-agent string specified, we erase the previously made string
here. */
- if(Curl_checkheaders(conn, "User-Agent") && conn->allocptr.uagent) {
- Curl_safefree(conn->allocptr.uagent);
- conn->allocptr.uagent = NULL;
+ if(Curl_checkheaders(conn, "User-Agent") && data->state.aptr.uagent) {
+ Curl_safefree(data->state.aptr.uagent);
+ data->state.aptr.uagent = NULL;
}
else if(!Curl_checkheaders(conn, "User-Agent") &&
data->set.str[STRING_USERAGENT]) {
- p_uagent = conn->allocptr.uagent;
+ p_uagent = data->state.aptr.uagent;
}
/* setup the authentication headers */
@@ -388,17 +388,17 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(result)
return result;
- p_proxyuserpwd = conn->allocptr.proxyuserpwd;
- p_userpwd = conn->allocptr.userpwd;
+ p_proxyuserpwd = data->state.aptr.proxyuserpwd;
+ p_userpwd = data->state.aptr.userpwd;
/* Referrer */
- Curl_safefree(conn->allocptr.ref);
+ Curl_safefree(data->state.aptr.ref);
if(data->change.referer && !Curl_checkheaders(conn, "Referer"))
- conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
+ data->state.aptr.ref = aprintf("Referer: %s\r\n", data->change.referer);
else
- conn->allocptr.ref = NULL;
+ data->state.aptr.ref = NULL;
- p_referrer = conn->allocptr.ref;
+ p_referrer = data->state.aptr.ref;
/*
* Range Header
@@ -411,9 +411,9 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* Check to see if there is a range set in the custom headers */
if(!Curl_checkheaders(conn, "Range") && data->state.range) {
- Curl_safefree(conn->allocptr.rangeline);
- conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
- p_range = conn->allocptr.rangeline;
+ Curl_safefree(data->state.aptr.rangeline);
+ data->state.aptr.rangeline = aprintf("Range: %s\r\n", data->state.range);
+ p_range = data->state.aptr.rangeline;
}
}
@@ -430,16 +430,13 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
/* Initialize a dynamic send buffer */
- req_buffer = Curl_add_buffer_init();
-
- if(!req_buffer)
- return CURLE_OUT_OF_MEMORY;
+ Curl_dyn_init(&req_buffer, DYN_RTSP_REQ_HEADER);
result =
- Curl_add_bufferf(&req_buffer,
- "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */
- "CSeq: %ld\r\n", /* CSeq */
- p_request, p_stream_uri, rtsp->CSeq_sent);
+ Curl_dyn_addf(&req_buffer,
+ "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */
+ "CSeq: %ld\r\n", /* CSeq */
+ p_request, p_stream_uri, rtsp->CSeq_sent);
if(result)
return result;
@@ -448,7 +445,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
* to make comparison easier
*/
if(p_session_id) {
- result = Curl_add_bufferf(&req_buffer, "Session: %s\r\n", p_session_id);
+ result = Curl_dyn_addf(&req_buffer, "Session: %s\r\n", p_session_id);
if(result)
return result;
}
@@ -456,42 +453,42 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/*
* Shared HTTP-like options
*/
- result = Curl_add_bufferf(&req_buffer,
- "%s" /* transport */
- "%s" /* accept */
- "%s" /* accept-encoding */
- "%s" /* range */
- "%s" /* referrer */
- "%s" /* user-agent */
- "%s" /* proxyuserpwd */
- "%s" /* userpwd */
- ,
- p_transport ? p_transport : "",
- p_accept ? p_accept : "",
- p_accept_encoding ? p_accept_encoding : "",
- p_range ? p_range : "",
- p_referrer ? p_referrer : "",
- p_uagent ? p_uagent : "",
- p_proxyuserpwd ? p_proxyuserpwd : "",
- p_userpwd ? p_userpwd : "");
+ result = Curl_dyn_addf(&req_buffer,
+ "%s" /* transport */
+ "%s" /* accept */
+ "%s" /* accept-encoding */
+ "%s" /* range */
+ "%s" /* referrer */
+ "%s" /* user-agent */
+ "%s" /* proxyuserpwd */
+ "%s" /* userpwd */
+ ,
+ p_transport ? p_transport : "",
+ p_accept ? p_accept : "",
+ p_accept_encoding ? p_accept_encoding : "",
+ p_range ? p_range : "",
+ p_referrer ? p_referrer : "",
+ p_uagent ? p_uagent : "",
+ p_proxyuserpwd ? p_proxyuserpwd : "",
+ p_userpwd ? p_userpwd : "");
/*
* Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM
* with basic and digest, it will be freed anyway by the next request
*/
- Curl_safefree(conn->allocptr.userpwd);
- conn->allocptr.userpwd = NULL;
+ Curl_safefree(data->state.aptr.userpwd);
+ data->state.aptr.userpwd = NULL;
if(result)
return result;
if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) {
- result = Curl_add_timecondition(conn, req_buffer);
+ result = Curl_add_timecondition(conn, &req_buffer);
if(result)
return result;
}
- result = Curl_add_custom_headers(conn, FALSE, req_buffer);
+ result = Curl_add_custom_headers(conn, FALSE, &req_buffer);
if(result)
return result;
@@ -501,14 +498,14 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(data->set.upload) {
putsize = data->state.infilesize;
- data->set.httpreq = HTTPREQ_PUT;
+ data->state.httpreq = HTTPREQ_PUT;
}
else {
postsize = (data->state.infilesize != -1)?
data->state.infilesize:
(data->set.postfields? (curl_off_t)strlen(data->set.postfields):0);
- data->set.httpreq = HTTPREQ_POST;
+ data->state.httpreq = HTTPREQ_POST;
}
if(putsize > 0 || postsize > 0) {
@@ -516,9 +513,9 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
* actually set a custom Content-Length in the headers */
if(!Curl_checkheaders(conn, "Content-Length")) {
result =
- Curl_add_bufferf(&req_buffer,
- "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
- (data->set.upload ? putsize : postsize));
+ Curl_dyn_addf(&req_buffer,
+ "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n",
+ (data->set.upload ? putsize : postsize));
if(result)
return result;
}
@@ -526,8 +523,8 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_SET_PARAMETER ||
rtspreq == RTSPREQ_GET_PARAMETER) {
if(!Curl_checkheaders(conn, "Content-Type")) {
- result = Curl_add_bufferf(&req_buffer,
- "Content-Type: text/parameters\r\n");
+ result = Curl_dyn_addf(&req_buffer,
+ "Content-Type: text/parameters\r\n");
if(result)
return result;
}
@@ -535,8 +532,8 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
if(rtspreq == RTSPREQ_ANNOUNCE) {
if(!Curl_checkheaders(conn, "Content-Type")) {
- result = Curl_add_bufferf(&req_buffer,
- "Content-Type: application/sdp\r\n");
+ result = Curl_dyn_addf(&req_buffer,
+ "Content-Type: application/sdp\r\n");
if(result)
return result;
}
@@ -546,7 +543,7 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
}
else if(rtspreq == RTSPREQ_GET_PARAMETER) {
/* Check for an empty GET_PARAMETER (heartbeat) request */
- data->set.httpreq = HTTPREQ_HEAD;
+ data->state.httpreq = HTTPREQ_HEAD;
data->set.opt_no_body = TRUE;
}
}
@@ -554,20 +551,20 @@ static CURLcode rtsp_do(struct connectdata *conn, bool *done)
/* RTSP never allows chunked transfer */
data->req.forbidchunk = TRUE;
/* Finish the request buffer */
- result = Curl_add_buffer(&req_buffer, "\r\n", 2);
+ result = Curl_dyn_add(&req_buffer, "\r\n");
if(result)
return result;
if(postsize > 0) {
- result = Curl_add_buffer(&req_buffer, data->set.postfields,
- (size_t)postsize);
+ result = Curl_dyn_addn(&req_buffer, data->set.postfields,
+ (size_t)postsize);
if(result)
return result;
}
/* issue the request */
- result = Curl_add_buffer_send(&req_buffer, conn,
- &data->info.request_size, 0, FIRSTSOCKET);
+ result = Curl_buffer_send(&req_buffer, conn,
+ &data->info.request_size, 0, FIRSTSOCKET);
if(result) {
failf(data, "Failed sending RTSP request");
return result;
diff --git a/lib/select.c b/lib/select.c
index 2ff95e1f4..e2c97efe6 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -22,6 +22,8 @@
#include "curl_setup.h"
+#include <limits.h>
+
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#elif defined(HAVE_UNISTD_H)
@@ -50,11 +52,9 @@
#include "urldata.h"
#include "connect.h"
#include "select.h"
+#include "timeval.h"
#include "warnless.h"
-/* Convenience local macros */
-#define ELAPSED_MS() (int)Curl_timediff(Curl_now(), initial_tv)
-
/*
* Internal function used for waiting a specific amount of ms
* in Curl_socket_check() and Curl_poll() when no file descriptor
@@ -71,7 +71,7 @@
* -1 = system call error, invalid timeout value, or interrupted
* 0 = specified timeout has elapsed
*/
-int Curl_wait_ms(int timeout_ms)
+int Curl_wait_ms(timediff_t timeout_ms)
{
int r = 0;
@@ -83,16 +83,44 @@ int Curl_wait_ms(int timeout_ms)
}
#if defined(MSDOS)
delay(timeout_ms);
-#elif defined(USE_WINSOCK)
- Sleep(timeout_ms);
+#elif defined(WIN32)
+ /* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */
+#if TIMEDIFF_T_MAX >= ULONG_MAX
+ if(timeout_ms >= ULONG_MAX)
+ timeout_ms = ULONG_MAX-1;
+ /* don't use ULONG_MAX, because that is equal to INFINITE */
+#endif
+ Sleep((ULONG)timeout_ms);
#else
#if defined(HAVE_POLL_FINE)
- r = poll(NULL, 0, timeout_ms);
+ /* prevent overflow, timeout_ms is typecast to int. */
+#if TIMEDIFF_T_MAX > INT_MAX
+ if(timeout_ms > INT_MAX)
+ timeout_ms = INT_MAX;
+#endif
+ r = poll(NULL, 0, (int)timeout_ms);
#else
{
struct timeval pending_tv;
- pending_tv.tv_sec = timeout_ms / 1000;
- pending_tv.tv_usec = (timeout_ms % 1000) * 1000;
+ timediff_t tv_sec = timeout_ms / 1000;
+ timediff_t tv_usec = (timeout_ms % 1000) * 1000; /* max=999999 */
+#ifdef HAVE_SUSECONDS_T
+#if TIMEDIFF_T_MAX > TIME_T_MAX
+ /* tv_sec overflow check in case time_t is signed */
+ if(tv_sec > TIME_T_MAX)
+ tv_sec = TIME_T_MAX;
+#endif
+ pending_tv.tv_sec = (time_t)tv_sec;
+ pending_tv.tv_usec = (suseconds_t)tv_usec;
+#else
+#if TIMEDIFF_T_MAX > INT_MAX
+ /* tv_sec overflow check in case time_t is signed */
+ if(tv_sec > INT_MAX)
+ tv_sec = INT_MAX;
+#endif
+ pending_tv.tv_sec = (int)tv_sec;
+ pending_tv.tv_usec = (int)tv_usec;
+#endif
r = select(0, NULL, NULL, NULL, &pending_tv);
}
#endif /* HAVE_POLL_FINE */
@@ -113,44 +141,60 @@ int Curl_wait_ms(int timeout_ms)
* 0 = timeout
* N = number of signalled file descriptors
*/
-int Curl_select(curl_socket_t maxfd,
- fd_set *fds_read,
- fd_set *fds_write,
- fd_set *fds_err,
- time_t timeout_ms) /* milliseconds to wait */
+int Curl_select(curl_socket_t maxfd, /* highest socket number */
+ fd_set *fds_read, /* sockets ready for reading */
+ fd_set *fds_write, /* sockets ready for writing */
+ fd_set *fds_err, /* sockets with errors */
+ timediff_t timeout_ms) /* milliseconds to wait */
{
struct timeval pending_tv;
struct timeval *ptimeout;
- int pending_ms;
int r;
-#if SIZEOF_TIME_T != SIZEOF_INT
- /* wrap-around precaution */
- if(timeout_ms >= INT_MAX)
- timeout_ms = INT_MAX;
-#endif
-
#ifdef USE_WINSOCK
/* WinSock select() can't handle zero events. See the comment below. */
if((!fds_read || fds_read->fd_count == 0) &&
(!fds_write || fds_write->fd_count == 0) &&
(!fds_err || fds_err->fd_count == 0)) {
- r = Curl_wait_ms((int)timeout_ms);
+ r = Curl_wait_ms(timeout_ms);
return r;
}
#endif
ptimeout = &pending_tv;
-
if(timeout_ms < 0) {
ptimeout = NULL;
}
else if(timeout_ms > 0) {
- pending_ms = (int)timeout_ms;
- pending_tv.tv_sec = pending_ms / 1000;
- pending_tv.tv_usec = (pending_ms % 1000) * 1000;
+ timediff_t tv_sec = timeout_ms / 1000;
+ timediff_t tv_usec = (timeout_ms % 1000) * 1000; /* max=999999 */
+#ifdef HAVE_SUSECONDS_T
+#if TIMEDIFF_T_MAX > TIME_T_MAX
+ /* tv_sec overflow check in case time_t is signed */
+ if(tv_sec > TIME_T_MAX)
+ tv_sec = TIME_T_MAX;
+#endif
+ pending_tv.tv_sec = (time_t)tv_sec;
+ pending_tv.tv_usec = (suseconds_t)tv_usec;
+#elif defined(WIN32) /* maybe also others in the future */
+#if TIMEDIFF_T_MAX > LONG_MAX
+ /* tv_sec overflow check on Windows there we know it is long */
+ if(tv_sec > LONG_MAX)
+ tv_sec = LONG_MAX;
+#endif
+ pending_tv.tv_sec = (long)tv_sec;
+ pending_tv.tv_usec = (long)tv_usec;
+#else
+#if TIMEDIFF_T_MAX > INT_MAX
+ /* tv_sec overflow check in case time_t is signed */
+ if(tv_sec > INT_MAX)
+ tv_sec = INT_MAX;
+#endif
+ pending_tv.tv_sec = (int)tv_sec;
+ pending_tv.tv_usec = (int)tv_usec;
+#endif
}
- else if(!timeout_ms) {
+ else {
pending_tv.tv_sec = 0;
pending_tv.tv_usec = 0;
}
@@ -201,11 +245,10 @@ int Curl_select(curl_socket_t maxfd,
int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
curl_socket_t readfd1,
curl_socket_t writefd, /* socket to write to */
- timediff_t timeout_ms) /* milliseconds to wait */
+ timediff_t timeout_ms) /* milliseconds to wait */
{
#ifdef HAVE_POLL_FINE
struct pollfd pfd[3];
- int pending_ms;
int num;
#else
fd_set fds_read;
@@ -216,16 +259,10 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
int r;
int ret;
-#if SIZEOF_TIME_T != SIZEOF_INT
- /* wrap-around precaution */
- if(timeout_ms >= INT_MAX)
- timeout_ms = INT_MAX;
-#endif
-
if((readfd0 == CURL_SOCKET_BAD) && (readfd1 == CURL_SOCKET_BAD) &&
(writefd == CURL_SOCKET_BAD)) {
/* no sockets, just wait */
- r = Curl_wait_ms((int)timeout_ms);
+ r = Curl_wait_ms(timeout_ms);
return r;
}
@@ -256,18 +293,9 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
num++;
}
- if(timeout_ms > 0)
- pending_ms = (int)timeout_ms;
- else if(timeout_ms < 0)
- pending_ms = -1;
- else
- pending_ms = 0;
- r = poll(pfd, num, pending_ms);
-
- if(r < 0)
- return -1;
- if(r == 0)
- return 0;
+ r = Curl_poll(pfd, num, timeout_ms);
+ if(r <= 0)
+ return r;
ret = 0;
num = 0;
@@ -333,7 +361,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
curl_socket_t is unsigned in such cases and thus -1 is the largest
value).
*/
- r = Curl_select(maxfd, &fds_read, &fds_write, &fds_err, (time_t)timeout_ms);
+ r = Curl_select(maxfd, &fds_read, &fds_write, &fds_err, timeout_ms);
if(r < 0)
return -1;
@@ -379,7 +407,7 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */
* 0 = timeout
* N = number of structures with non zero revent fields
*/
-int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
+int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms)
{
#ifdef HAVE_POLL_FINE
int pending_ms;
@@ -402,6 +430,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
}
}
if(fds_none) {
+ /* no sockets, just wait */
r = Curl_wait_ms(timeout_ms);
return r;
}
@@ -413,8 +442,13 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms)
#ifdef HAVE_POLL_FINE
+ /* prevent overflow, timeout_ms is typecast to int. */
+#if TIMEDIFF_T_MAX > INT_MAX
+ if(timeout_ms > INT_MAX)
+ timeout_ms = INT_MAX;
+#endif
if(timeout_ms > 0)
- pending_ms = timeout_ms;
+ pending_ms = (int)timeout_ms;
else if(timeout_ms < 0)
pending_ms = -1;
else
diff --git a/lib/select.h b/lib/select.h
index 0fd8ed515..95181f467 100644
--- a/lib/select.h
+++ b/lib/select.h
@@ -76,7 +76,7 @@ int Curl_select(curl_socket_t maxfd,
fd_set *fds_read,
fd_set *fds_write,
fd_set *fds_err,
- time_t timeout_ms);
+ timediff_t timeout_ms);
int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
curl_socket_t writefd,
@@ -86,12 +86,12 @@ int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2,
#define SOCKET_WRITABLE(x,z) \
Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, x, z)
-int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms);
-int Curl_wait_ms(int timeout_ms);
+int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms);
+int Curl_wait_ms(timediff_t timeout_ms);
#ifdef TPF
int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes,
- fd_set* excepts, struct timeval* tv);
+ fd_set* excepts, struct timeval *tv);
#endif
/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1], which
diff --git a/lib/sendf.c b/lib/sendf.c
index fe106e7f3..8ac46db0c 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -267,7 +267,7 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
size_t len;
char error[CURL_ERROR_SIZE + 2];
va_start(ap, fmt);
- mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
+ (void)mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
len = strlen(error);
if(data->set.errorbuffer && !data->state.errorbuf) {
@@ -498,7 +498,6 @@ static CURLcode pausewrite(struct Curl_easy *data,
is again enabled */
struct SingleRequest *k = &data->req;
struct UrlState *s = &data->state;
- char *dupl;
unsigned int i;
bool newtype = TRUE;
@@ -518,44 +517,21 @@ static CURLcode pausewrite(struct Curl_easy *data,
else
i = 0;
- if(!newtype) {
- /* append new data to old data */
-
- /* figure out the new size of the data to save */
- size_t newlen = len + s->tempwrite[i].len;
- /* allocate the new memory area */
- char *newptr = realloc(s->tempwrite[i].buf, newlen);
- if(!newptr)
- return CURLE_OUT_OF_MEMORY;
- /* copy the new data to the end of the new area */
- memcpy(newptr + s->tempwrite[i].len, ptr, len);
-
- /* update the pointer and the size */
- s->tempwrite[i].buf = newptr;
- s->tempwrite[i].len = newlen;
-
- len = newlen; /* for the debug output below */
- }
- else {
- dupl = Curl_memdup(ptr, len);
- if(!dupl)
- return CURLE_OUT_OF_MEMORY;
-
+ if(newtype) {
/* store this information in the state struct for later use */
- s->tempwrite[i].buf = dupl;
- s->tempwrite[i].len = len;
+ Curl_dyn_init(&s->tempwrite[i].b, DYN_PAUSE_BUFFER);
s->tempwrite[i].type = type;
if(newtype)
s->tempcount++;
}
+ if(Curl_dyn_addn(&s->tempwrite[i].b, (unsigned char *)ptr, len))
+ return CURLE_OUT_OF_MEMORY;
+
/* mark the connection as RECV paused */
k->keepon |= KEEP_RECV_PAUSE;
- DEBUGF(infof(data, "Paused %zu bytes in buffer for type %02x\n",
- len, type));
-
return CURLE_OK;
}
@@ -617,7 +593,7 @@ static CURLcode chop_write(struct connectdata *conn,
return pausewrite(data, type, ptr, len);
}
if(wrote != chunklen) {
- failf(data, "Failed writing body (%zu != %zu)", wrote, chunklen);
+ failf(data, "Failure writing output to destination");
return CURLE_WRITE_ERROR;
}
}
diff --git a/lib/setopt.c b/lib/setopt.c
index 12ed72ea6..b8fb98ef6 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -77,6 +77,37 @@ CURLcode Curl_setstropt(char **charp, const char *s)
return CURLE_OK;
}
+CURLcode Curl_setblobopt(struct curl_blob **blobp,
+ const struct curl_blob *blob)
+{
+ /* free the previous storage at `blobp' and replace by a dynamic storage
+ copy of blob. If CURL_BLOB_COPY is set, the data is copied. */
+
+ Curl_safefree(*blobp);
+
+ if(blob) {
+ struct curl_blob *nblob;
+ if(blob->len > CURL_MAX_INPUT_LENGTH)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ nblob = (struct curl_blob *)
+ malloc(sizeof(struct curl_blob) +
+ ((blob->flags & CURL_BLOB_COPY) ? blob->len : 0));
+ if(!nblob)
+ return CURLE_OUT_OF_MEMORY;
+ *nblob = *blob;
+ if(blob->flags & CURL_BLOB_COPY) {
+ /* put the data after the blob struct in memory */
+ nblob->data = (char *)nblob + sizeof(struct curl_blob);
+ memcpy(nblob->data, blob->data, blob->len);
+ }
+
+ *blobp = nblob;
+ return CURLE_OK;
+ }
+
+ return CURLE_OK;
+}
+
static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
{
CURLcode result = CURLE_OK;
@@ -240,6 +271,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Do not include the body part in the output data stream.
*/
data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
+ if(data->set.opt_no_body)
+ /* in HTTP lingo, no body means using the HEAD request... */
+ data->set.method = HTTPREQ_HEAD;
break;
case CURLOPT_FAILONERROR:
/*
@@ -261,13 +295,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE;
if(data->set.upload) {
/* If this is HTTP, PUT is what's needed to "upload" */
- data->set.httpreq = HTTPREQ_PUT;
+ data->set.method = HTTPREQ_PUT;
data->set.opt_no_body = FALSE; /* this is implied */
}
else
/* In HTTP, the opposite of upload is GET (unless NOBODY is true as
then this can be changed to HEAD later on) */
- data->set.httpreq = HTTPREQ_GET;
+ data->set.method = HTTPREQ_GET;
break;
case CURLOPT_REQUEST_TARGET:
result = Curl_setstropt(&data->set.str[STRING_TARGET],
@@ -363,7 +397,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
case CURLOPT_SSLVERSION:
+#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_SSLVERSION:
+#endif
/*
* Set explicit SSL version to try to connect with, as some SSL
* implementations are lame.
@@ -371,9 +407,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
#ifdef USE_SSL
{
long version, version_max;
- struct ssl_primary_config *primary = (option == CURLOPT_SSLVERSION ?
- &data->set.ssl.primary :
- &data->set.proxy_ssl.primary);
+ struct ssl_primary_config *primary = &data->set.ssl.primary;
+#ifndef CURL_DISABLE_PROXY
+ if(option != CURLOPT_SSLVERSION)
+ primary = &data->set.proxy_ssl.primary;
+#endif
arg = va_arg(param, long);
@@ -481,11 +519,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
CURLOPT_POSTFIELDS isn't used and the POST data is read off the
callback! */
if(va_arg(param, long)) {
- data->set.httpreq = HTTPREQ_POST;
+ data->set.method = HTTPREQ_POST;
data->set.opt_no_body = FALSE; /* this is implied */
}
else
- data->set.httpreq = HTTPREQ_GET;
+ data->set.method = HTTPREQ_GET;
break;
case CURLOPT_COPYPOSTFIELDS:
@@ -532,7 +570,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
}
data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
- data->set.httpreq = HTTPREQ_POST;
+ data->set.method = HTTPREQ_POST;
break;
case CURLOPT_POSTFIELDS:
@@ -542,7 +580,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.postfields = va_arg(param, void *);
/* Release old copied data. */
(void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
- data->set.httpreq = HTTPREQ_POST;
+ data->set.method = HTTPREQ_POST;
break;
case CURLOPT_POSTFIELDSIZE:
@@ -588,7 +626,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set to make us do HTTP POST
*/
data->set.httppost = va_arg(param, struct curl_httppost *);
- data->set.httpreq = HTTPREQ_POST_FORM;
+ data->set.method = HTTPREQ_POST_FORM;
data->set.opt_no_body = FALSE; /* this is implied */
break;
#endif /* CURL_DISABLE_HTTP */
@@ -600,7 +638,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
result = Curl_mime_set_subparts(&data->set.mimepost,
va_arg(param, curl_mime *), FALSE);
if(!result) {
- data->set.httpreq = HTTPREQ_POST_MIME;
+ data->set.method = HTTPREQ_POST_MIME;
data->set.opt_no_body = FALSE; /* this is implied */
}
break;
@@ -795,7 +833,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
* Set to force us do HTTP GET
*/
if(va_arg(param, long)) {
- data->set.httpreq = HTTPREQ_GET;
+ data->set.method = HTTPREQ_GET;
data->set.upload = FALSE; /* switch off upload */
data->set.opt_no_body = FALSE; /* this is implied */
}
@@ -905,7 +943,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
va_arg(param, char *));
/* we don't set
- data->set.httpreq = HTTPREQ_CUSTOM;
+ data->set.method = HTTPREQ_CUSTOM;
here, we continue as if we were using the already set type
and this just changes the actual request keyword */
break;
@@ -1606,6 +1644,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
result = Curl_setstropt(&data->set.str[STRING_CERT_ORIG],
va_arg(param, char *));
break;
+ case CURLOPT_SSLCERT_BLOB:
+ /*
+ * Blob that holds file name of the SSL certificate to use
+ */
+ result = Curl_setblobopt(&data->set.blobs[BLOB_CERT_ORIG],
+ va_arg(param, struct curl_blob *));
+ break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_SSLCERT:
/*
@@ -1614,6 +1659,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
result = Curl_setstropt(&data->set.str[STRING_CERT_PROXY],
va_arg(param, char *));
break;
+ case CURLOPT_PROXY_SSLCERT_BLOB:
+ /*
+ * Blob that holds file name of the SSL certificate to use for proxy
+ */
+ result = Curl_setblobopt(&data->set.blobs[BLOB_CERT_PROXY],
+ va_arg(param, struct curl_blob *));
+ break;
#endif
case CURLOPT_SSLCERTTYPE:
/*
@@ -1638,6 +1690,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
result = Curl_setstropt(&data->set.str[STRING_KEY_ORIG],
va_arg(param, char *));
break;
+ case CURLOPT_SSLKEY_BLOB:
+ /*
+ * Blob that holds file name of the SSL key to use
+ */
+ result = Curl_setblobopt(&data->set.blobs[BLOB_KEY_ORIG],
+ va_arg(param, struct curl_blob *));
+ break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_SSLKEY:
/*
@@ -1646,6 +1705,13 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
result = Curl_setstropt(&data->set.str[STRING_KEY_PROXY],
va_arg(param, char *));
break;
+ case CURLOPT_PROXY_SSLKEY_BLOB:
+ /*
+ * Blob that holds file name of the SSL key to use for proxy
+ */
+ result = Curl_setblobopt(&data->set.blobs[BLOB_KEY_PROXY],
+ va_arg(param, struct curl_blob *));
+ break;
#endif
case CURLOPT_SSLKEYTYPE:
/*
@@ -1970,6 +2036,30 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
va_arg(param, char *));
break;
+ case CURLOPT_ISSUERCERT_BLOB:
+ /*
+ * Blob that holds Issuer certificate to check certificates issuer
+ */
+ result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG],
+ va_arg(param, struct curl_blob *));
+ break;
+#ifndef CURL_DISABLE_PROXY
+ case CURLOPT_PROXY_ISSUERCERT:
+ /*
+ * Set Issuer certificate file
+ * to check certificates issuer
+ */
+ result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_PROXY],
+ va_arg(param, char *));
+ break;
+ case CURLOPT_PROXY_ISSUERCERT_BLOB:
+ /*
+ * Blob that holds Issuer certificate to check certificates issuer
+ */
+ result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY],
+ va_arg(param, struct curl_blob *));
+ break;
+#endif
#ifndef CURL_DISABLE_TELNET
case CURLOPT_TELNETOPTIONS:
/*
@@ -1993,7 +2083,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
arg = READBUFFER_MIN;
/* Resize if new size */
- if(arg != data->set.buffer_size) {
+ if((arg != data->set.buffer_size) && data->state.buffer) {
char *newbuff = realloc(data->state.buffer, arg + 1);
if(!newbuff) {
DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
@@ -2135,6 +2225,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
data->set.ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
data->set.ssl.revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
+ data->set.ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
break;
#ifndef CURL_DISABLE_PROXY
@@ -2144,6 +2235,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
(bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE);
data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
data->set.proxy_ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
+ data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
data->set.proxy_ssl.revoke_best_effort =
!!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
break;
@@ -2248,7 +2340,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_SSL_SESSIONID_CACHE:
data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ?
TRUE : FALSE;
+#ifndef CURL_DISABLE_PROXY
data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
+#endif
break;
#ifdef USE_SSH
@@ -2550,9 +2644,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_PROXY_TLSAUTH_USERNAME:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
va_arg(param, char *));
+#ifndef CURL_DISABLE_PROXY
if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
!data->set.proxy_ssl.authtype)
data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+#endif
break;
case CURLOPT_TLSAUTH_PASSWORD:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
@@ -2563,9 +2659,11 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
case CURLOPT_PROXY_TLSAUTH_PASSWORD:
result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
va_arg(param, char *));
+#ifndef CURL_DISABLE_PROXY
if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
!data->set.proxy_ssl.authtype)
data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
+#endif
break;
case CURLOPT_TLSAUTH_TYPE:
argptr = va_arg(param, char *);
@@ -2575,6 +2673,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
else
data->set.ssl.authtype = CURL_TLSAUTH_NONE;
break;
+#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXY_TLSAUTH_TYPE:
argptr = va_arg(param, char *);
if(!argptr ||
@@ -2584,6 +2683,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
break;
#endif
+#endif
#ifdef USE_ARES
case CURLOPT_DNS_SERVERS:
result = Curl_setstropt(&data->set.str[STRING_DNS_SERVERS],
diff --git a/lib/setopt.h b/lib/setopt.h
index 5e347dd66..5fc4368dc 100644
--- a/lib/setopt.h
+++ b/lib/setopt.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -23,6 +23,8 @@
***************************************************************************/
CURLcode Curl_setstropt(char **charp, const char *s);
+CURLcode Curl_setblobopt(struct curl_blob **blobp,
+ const struct curl_blob *blob);
CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list arg);
#endif /* HEADER_CURL_SETOPT_H */
diff --git a/lib/setup-os400.h b/lib/setup-os400.h
index 629fd94c4..b693cb3b3 100644
--- a/lib/setup-os400.h
+++ b/lib/setup-os400.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -200,10 +200,10 @@ extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
/* Some socket functions must be wrapped to process textual addresses
like AF_UNIX. */
-extern int Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen);
-extern int Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen);
+extern int Curl_os400_connect(int sd, struct sockaddr *destaddr, int addrlen);
+extern int Curl_os400_bind(int sd, struct sockaddr *localaddr, int addrlen);
extern int Curl_os400_sendto(int sd, char *buffer, int buflen, int flags,
- struct sockaddr * dstaddr, int addrlen);
+ struct sockaddr *dstaddr, int addrlen);
extern int Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags,
struct sockaddr *fromaddr, int *addrlen);
extern int Curl_os400_getpeername(int sd, struct sockaddr *addr, int *addrlen);
diff --git a/lib/setup-vms.h b/lib/setup-vms.h
index 6c454aee6..0e39c9f6b 100644
--- a/lib/setup-vms.h
+++ b/lib/setup-vms.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -73,7 +73,7 @@ char *decc$getenv(const char *__name);
# endif
#endif
- struct passwd * decc_getpwuid(uid_t uid);
+ struct passwd *decc_getpwuid(uid_t uid);
#ifdef __DECC
# if __INITIAL_POINTER_SIZE == 32
@@ -138,9 +138,9 @@ static char *vms_getenv(const char *envvar)
static struct passwd vms_passwd_cache;
-static struct passwd * vms_getpwuid(uid_t uid)
+static struct passwd *vms_getpwuid(uid_t uid)
{
- struct passwd * my_passwd;
+ struct passwd *my_passwd;
/* Hack needed to support 64 bit builds, decc_getpwnam is 32 bit only */
#ifdef __DECC
diff --git a/lib/sha256.c b/lib/sha256.c
index 00d98ce46..ee5d273c4 100644
--- a/lib/sha256.c
+++ b/lib/sha256.c
@@ -196,10 +196,11 @@ static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx)
#include <wincrypt.h>
-typedef struct {
+struct sha256_ctx {
HCRYPTPROV hCryptProv;
HCRYPTHASH hHash;
-} SHA256_CTX;
+};
+typedef struct sha256_ctx SHA256_CTX;
#if !defined(CALG_SHA_256)
#define CALG_SHA_256 0x0000800c
@@ -222,7 +223,7 @@ static void SHA256_Update(SHA256_CTX *ctx,
static void SHA256_Final(unsigned char *digest, SHA256_CTX *ctx)
{
- unsigned long length;
+ unsigned long length = 0;
CryptGetHashParam(ctx->hHash, HP_HASHVAL, NULL, &length, 0);
if(length == SHA256_DIGEST_LENGTH)
@@ -280,7 +281,7 @@ do { \
} while(0)
#endif
-typedef struct sha256_state {
+struct sha256_state {
#ifdef HAVE_LONGLONG
unsigned long long length;
#else
@@ -288,7 +289,8 @@ typedef struct sha256_state {
#endif
unsigned long state[8], curlen;
unsigned char buf[64];
-} SHA256_CTX;
+};
+typedef struct sha256_state SHA256_CTX;
/* The K array */
static const unsigned long K[64] = {
diff --git a/lib/share.c b/lib/share.c
index 7d51eebf1..70c6e025f 100644
--- a/lib/share.c
+++ b/lib/share.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -70,7 +70,7 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
case CURLSHOPT_SHARE:
/* this is a type this share will share */
type = va_arg(param, int);
- share->specifier |= (1<<type);
+
switch(type) {
case CURL_LOCK_DATA_DNS:
break;
@@ -102,7 +102,7 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
#endif
break;
- case CURL_LOCK_DATA_CONNECT: /* not supported (yet) */
+ case CURL_LOCK_DATA_CONNECT:
if(Curl_conncache_init(&share->conn_cache, 103))
res = CURLSHE_NOMEM;
break;
@@ -116,6 +116,8 @@ curl_share_setopt(struct Curl_share *share, CURLSHoption option, ...)
default:
res = CURLSHE_BAD_OPTION;
}
+ if(!res)
+ share->specifier |= (1<<type);
break;
case CURLSHOPT_UNSHARE:
diff --git a/lib/smb.c b/lib/smb.c
index 12f99257f..d493adcc0 100644
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
- * Copyright (C) 2016-2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2016-2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -964,7 +964,7 @@ static CURLcode smb_parse_url_path(struct connectdata *conn)
/* URL decode the path */
CURLcode result = Curl_urldecode(data, data->state.up.path, 0, &path, NULL,
- TRUE);
+ REJECT_CTRL);
if(result)
return result;
diff --git a/lib/smtp.c b/lib/smtp.c
index dc511292b..231e6c79b 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -183,7 +183,7 @@ static void smtp_to_smtps(struct connectdata *conn)
conn->handler = &Curl_handler_smtps;
/* Set the connection's upgraded to TLS flag */
- conn->tls_upgraded = TRUE;
+ conn->bits.tls_upgraded = TRUE;
}
#else
#define smtp_to_smtps(x) Curl_nop_stmt
@@ -1617,7 +1617,7 @@ static CURLcode smtp_setup_connection(struct connectdata *conn)
CURLcode result;
/* Clear the TLS upgraded flag */
- conn->tls_upgraded = FALSE;
+ conn->bits.tls_upgraded = FALSE;
/* Initialise the SMTP layer */
result = smtp_init(conn);
@@ -1689,7 +1689,8 @@ static CURLcode smtp_parse_url_path(struct connectdata *conn)
}
/* URL decode the path and use it as the domain in our EHLO */
- return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL, TRUE);
+ return Curl_urldecode(conn->data, path, 0, &smtpc->domain, NULL,
+ REJECT_CTRL);
}
/***********************************************************************
@@ -1707,7 +1708,7 @@ static CURLcode smtp_parse_custom_request(struct connectdata *conn)
/* URL decode the custom request */
if(custom)
- result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, TRUE);
+ result = Curl_urldecode(data, custom, 0, &smtp->custom, NULL, REJECT_CTRL);
return result;
}
diff --git a/lib/socks.c b/lib/socks.c
index 18affbc96..b2215fef3 100644
--- a/lib/socks.c
+++ b/lib/socks.c
@@ -69,7 +69,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
break;
}
if(!timeout_ms)
- timeout_ms = TIME_T_MAX;
+ timeout_ms = TIMEDIFF_T_MAX;
if(SOCKET_READABLE(sockfd, timeout_ms) <= 0) {
result = ~CURLE_OK;
break;
@@ -271,7 +271,7 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
/* FALLTHROUGH */
CONNECT_RESOLVED:
case CONNECT_RESOLVED: {
- Curl_addrinfo *hp = NULL;
+ struct Curl_addrinfo *hp = NULL;
char buf[64];
/*
* We cannot use 'hostent' as a struct that Curl_resolv() returns. It
@@ -382,6 +382,11 @@ CURLcode Curl_SOCKS4(const char *proxy_user,
curl_easy_strerror(result));
return CURLE_COULDNT_CONNECT;
}
+ else if(!result && !actualread) {
+ /* connection closed */
+ failf(data, "connection to proxy closed");
+ return CURLE_COULDNT_CONNECT;
+ }
else if(actualread != sx->outstanding) {
/* remain in reading state */
sx->outstanding -= actualread;
@@ -592,6 +597,11 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
failf(data, "Unable to receive initial SOCKS5 response.");
return CURLE_COULDNT_CONNECT;
}
+ else if(!result && !actualread) {
+ /* connection closed */
+ failf(data, "Connection to proxy closed");
+ return CURLE_COULDNT_CONNECT;
+ }
else if(actualread != sx->outstanding) {
/* remain in reading state */
sx->outstanding -= actualread;
@@ -633,11 +643,10 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
failf(data, "No authentication method was acceptable.");
return CURLE_COULDNT_CONNECT;
}
- failf(data,
- "Undocumented SOCKS5 mode attempted to be used by server.");
- return CURLE_COULDNT_CONNECT;
}
- break;
+ failf(data,
+ "Undocumented SOCKS5 mode attempted to be used by server.");
+ return CURLE_COULDNT_CONNECT;
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
case CONNECT_GSSAPI_INIT:
/* GSSAPI stuff done non-blocking */
@@ -718,15 +727,19 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
failf(data, "Unable to receive SOCKS5 sub-negotiation response.");
return CURLE_COULDNT_CONNECT;
}
- if(actualread != sx->outstanding) {
+ else if(!result && !actualread) {
+ /* connection closed */
+ failf(data, "connection to proxy closed");
+ return CURLE_COULDNT_CONNECT;
+ }
+ else if(actualread != sx->outstanding) {
/* remain in state */
sx->outstanding -= actualread;
sx->outp += actualread;
return CURLE_OK;
}
-
/* ignore the first (VER) byte */
- if(socksreq[1] != 0) { /* status */
+ else if(socksreq[1] != 0) { /* status */
failf(data, "User was rejected by the SOCKS5 server (%d %d).",
socksreq[0], socksreq[1]);
return CURLE_COULDNT_CONNECT;
@@ -773,7 +786,8 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
/* FALLTHROUGH */
CONNECT_RESOLVED:
case CONNECT_RESOLVED: {
- Curl_addrinfo *hp = NULL;
+ struct Curl_addrinfo *hp = NULL;
+ size_t destlen;
if(dns)
hp = dns->addr;
if(!hp) {
@@ -782,13 +796,9 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
return CURLE_COULDNT_RESOLVE_HOST;
}
- if(Curl_printable_address(hp, dest, sizeof(dest))) {
- size_t destlen = strlen(dest);
- msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", remote_port);
- }
- else {
- strcpy(dest, "unknown");
- }
+ Curl_printable_address(hp, dest, sizeof(dest));
+ destlen = strlen(dest);
+ msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", remote_port);
len = 0;
socksreq[len++] = 5; /* version (SOCKS5) */
@@ -894,6 +904,11 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
failf(data, "Failed to receive SOCKS5 connect request ack.");
return CURLE_COULDNT_CONNECT;
}
+ else if(!result && !actualread) {
+ /* connection closed */
+ failf(data, "connection to proxy closed");
+ return CURLE_COULDNT_CONNECT;
+ }
else if(actualread != sx->outstanding) {
/* remain in state */
sx->outstanding -= actualread;
@@ -938,6 +953,13 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
/* IPv6 */
len = 4 + 16 + 2;
}
+ else if(socksreq[3] == 1) {
+ len = 4 + 4 + 2;
+ }
+ else {
+ failf(data, "SOCKS5 reply has wrong address type.");
+ return CURLE_COULDNT_CONNECT;
+ }
/* At this point we already read first 10 bytes */
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
@@ -964,7 +986,12 @@ CURLcode Curl_SOCKS5(const char *proxy_user,
failf(data, "Failed to receive SOCKS5 connect request ack.");
return CURLE_COULDNT_CONNECT;
}
- if(actualread != sx->outstanding) {
+ else if(!result && !actualread) {
+ /* connection closed */
+ failf(data, "connection to proxy closed");
+ return CURLE_COULDNT_CONNECT;
+ }
+ else if(actualread != sx->outstanding) {
/* remain in state */
sx->outstanding -= actualread;
sx->outp += actualread;
diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c
index 7f66675fc..2e36b9940 100644
--- a/lib/socks_gssapi.c
+++ b/lib/socks_gssapi.c
@@ -115,7 +115,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
gss_buffer_desc gss_send_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc gss_recv_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc gss_w_token = GSS_C_EMPTY_BUFFER;
- gss_buffer_desc* gss_token = GSS_C_NO_BUFFER;
+ gss_buffer_desc *gss_token = GSS_C_NO_BUFFER;
gss_name_t server = GSS_C_NO_NAME;
gss_name_t gss_client_name = GSS_C_NO_NAME;
unsigned short us_length;
@@ -328,7 +328,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
user[gss_send_token.length] = '\0';
gss_release_name(&gss_status, &gss_client_name);
gss_release_buffer(&gss_status, &gss_send_token);
- infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",user);
+ infof(data, "SOCKS5 server authenticated user %s with GSS-API.\n",user);
free(user);
user = NULL;
diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c
index d5be64a3c..2f1fd36fa 100644
--- a/lib/socks_sspi.c
+++ b/lib/socks_sspi.c
@@ -160,7 +160,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
for(;;) {
TCHAR *sname;
- sname = Curl_convert_UTF8_to_tchar(service_name);
+ sname = curlx_convert_UTF8_to_tchar(service_name);
if(!sname)
return CURLE_OUT_OF_MEMORY;
@@ -180,7 +180,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
&sspi_ret_flags,
&expiry);
- Curl_unicodefree(sname);
+ curlx_unicodefree(sname);
if(sspi_recv_token.pvBuffer) {
s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
@@ -327,7 +327,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
failf(data, "Failed to determine user name.");
return CURLE_COULDNT_CONNECT;
}
- infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",
+ infof(data, "SOCKS5 server authenticated user %s with GSS-API.\n",
names.sUserName);
s_pSecFn->FreeContextBuffer(names.sUserName);
diff --git a/lib/strerror.c b/lib/strerror.c
index 3ac447089..f9f5a8415 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -795,7 +795,7 @@ const char *Curl_strerror(int err, char *buf, size_t buflen)
#endif /* end of not Windows */
- buf[max] = '\0'; /* make sure the string is zero terminated */
+ buf[max] = '\0'; /* make sure the string is null-terminated */
/* strip trailing '\r\n' or '\n'. */
p = strrchr(buf, '\n');
diff --git a/lib/strtok.c b/lib/strtok.c
index be8f48128..ba6e0258a 100644
--- a/lib/strtok.c
+++ b/lib/strtok.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -52,7 +52,7 @@ Curl_strtok_r(char *ptr, const char *sep, char **end)
if(**end) {
/* the end is not a null byte */
- **end = '\0'; /* zero terminate it! */
+ **end = '\0'; /* null-terminate it! */
++*end; /* advance the last pointer to beyond the null byte */
}
diff --git a/lib/telnet.c b/lib/telnet.c
index e270c2273..e43f5dd1e 100644
--- a/lib/telnet.c
+++ b/lib/telnet.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -1315,7 +1315,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
DWORD readfile_read;
int err;
#else
- int interval_ms;
+ timediff_t interval_ms;
struct pollfd pfd[2];
int poll_cnt;
curl_off_t total_dl = 0;
diff --git a/lib/tftp.c b/lib/tftp.c
index 9b6ba72d2..7659fd40e 100644
--- a/lib/tftp.c
+++ b/lib/tftp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -115,11 +115,11 @@ typedef enum {
TFTP_ERR_NORESPONSE
} tftp_error_t;
-typedef struct tftp_packet {
+struct tftp_packet {
unsigned char *data;
-} tftp_packet_t;
+};
-typedef struct tftp_state_data {
+struct tftp_state_data {
tftp_state_t state;
tftp_mode_t mode;
tftp_error_t error;
@@ -140,21 +140,21 @@ typedef struct tftp_state_data {
int sbytes;
int blksize;
int requested_blksize;
- tftp_packet_t rpacket;
- tftp_packet_t spacket;
-} tftp_state_data_t;
+ struct tftp_packet rpacket;
+ struct tftp_packet spacket;
+};
/* Forward declarations */
-static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event);
-static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event);
+static CURLcode tftp_rx(struct tftp_state_data *state, tftp_event_t event);
+static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event);
static CURLcode tftp_connect(struct connectdata *conn, bool *done);
static CURLcode tftp_disconnect(struct connectdata *conn,
bool dead_connection);
static CURLcode tftp_do(struct connectdata *conn, bool *done);
static CURLcode tftp_done(struct connectdata *conn,
CURLcode, bool premature);
-static CURLcode tftp_setup_connection(struct connectdata * conn);
+static CURLcode tftp_setup_connection(struct connectdata *conn);
static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done);
static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done);
static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks);
@@ -196,7 +196,7 @@ const struct Curl_handler Curl_handler_tftp = {
*
*
**********************************************************/
-static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
+static CURLcode tftp_set_timeouts(struct tftp_state_data *state)
{
time_t maxtime, timeout;
timediff_t timeout_ms;
@@ -279,25 +279,25 @@ static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
*
**********************************************************/
-static void setpacketevent(tftp_packet_t *packet, unsigned short num)
+static void setpacketevent(struct tftp_packet *packet, unsigned short num)
{
packet->data[0] = (unsigned char)(num >> 8);
packet->data[1] = (unsigned char)(num & 0xff);
}
-static void setpacketblock(tftp_packet_t *packet, unsigned short num)
+static void setpacketblock(struct tftp_packet *packet, unsigned short num)
{
packet->data[2] = (unsigned char)(num >> 8);
packet->data[3] = (unsigned char)(num & 0xff);
}
-static unsigned short getrpacketevent(const tftp_packet_t *packet)
+static unsigned short getrpacketevent(const struct tftp_packet *packet)
{
return (unsigned short)((packet->data[0] << 8) | packet->data[1]);
}
-static unsigned short getrpacketblock(const tftp_packet_t *packet)
+static unsigned short getrpacketblock(const struct tftp_packet *packet)
{
return (unsigned short)((packet->data[2] << 8) | packet->data[3]);
}
@@ -330,7 +330,7 @@ static const char *tftp_option_get(const char *buf, size_t len,
return &buf[loc];
}
-static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
+static CURLcode tftp_parse_option_ack(struct tftp_state_data *state,
const char *ptr, int len)
{
const char *tmp = ptr;
@@ -403,7 +403,7 @@ static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
return CURLE_OK;
}
-static CURLcode tftp_option_add(tftp_state_data_t *state, size_t *csize,
+static CURLcode tftp_option_add(struct tftp_state_data *state, size_t *csize,
char *buf, const char *option)
{
if(( strlen(option) + *csize + 1) > (size_t)state->blksize)
@@ -413,7 +413,7 @@ static CURLcode tftp_option_add(tftp_state_data_t *state, size_t *csize,
return CURLE_OK;
}
-static CURLcode tftp_connect_for_tx(tftp_state_data_t *state,
+static CURLcode tftp_connect_for_tx(struct tftp_state_data *state,
tftp_event_t event)
{
CURLcode result;
@@ -429,7 +429,7 @@ static CURLcode tftp_connect_for_tx(tftp_state_data_t *state,
return tftp_tx(state, event);
}
-static CURLcode tftp_connect_for_rx(tftp_state_data_t *state,
+static CURLcode tftp_connect_for_rx(struct tftp_state_data *state,
tftp_event_t event)
{
CURLcode result;
@@ -445,7 +445,8 @@ static CURLcode tftp_connect_for_rx(tftp_state_data_t *state,
return tftp_rx(state, event);
}
-static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
+static CURLcode tftp_send_first(struct tftp_state_data *state,
+ tftp_event_t event)
{
size_t sbytes;
ssize_t senddata;
@@ -486,7 +487,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
file name so we skip the always-present first letter of the path
string. */
result = Curl_urldecode(data, &state->conn->data->state.up.path[1], 0,
- &filename, NULL, FALSE);
+ &filename, NULL, REJECT_ZERO);
if(result)
return result;
@@ -598,7 +599,8 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
* Event handler for the RX state
*
**********************************************************/
-static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
+static CURLcode tftp_rx(struct tftp_state_data *state,
+ tftp_event_t event)
{
ssize_t sbytes;
int rblock;
@@ -720,7 +722,7 @@ static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
* Event handler for the TX state
*
**********************************************************/
-static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
+static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event)
{
struct Curl_easy *data = state->conn->data;
ssize_t sbytes;
@@ -920,7 +922,7 @@ static CURLcode tftp_translate_code(tftp_error_t error)
* The tftp state machine event dispatcher
*
**********************************************************/
-static CURLcode tftp_state_machine(tftp_state_data_t *state,
+static CURLcode tftp_state_machine(struct tftp_state_data *state,
tftp_event_t event)
{
CURLcode result = CURLE_OK;
@@ -961,7 +963,7 @@ static CURLcode tftp_state_machine(tftp_state_data_t *state,
**********************************************************/
static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
{
- tftp_state_data_t *state = conn->proto.tftpc;
+ struct tftp_state_data *state = conn->proto.tftpc;
(void) dead_connection;
/* done, free dynamically allocated pkt buffers */
@@ -983,13 +985,13 @@ static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
**********************************************************/
static CURLcode tftp_connect(struct connectdata *conn, bool *done)
{
- tftp_state_data_t *state;
+ struct tftp_state_data *state;
int blksize;
int need_blksize;
blksize = TFTP_BLKSIZE_DEFAULT;
- state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t));
+ state = conn->proto.tftpc = calloc(1, sizeof(struct tftp_state_data));
if(!state)
return CURLE_OUT_OF_MEMORY;
@@ -1078,7 +1080,7 @@ static CURLcode tftp_done(struct connectdata *conn, CURLcode status,
bool premature)
{
CURLcode result = CURLE_OK;
- tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+ struct tftp_state_data *state = conn->proto.tftpc;
(void)status; /* unused */
(void)premature; /* not used */
@@ -1119,7 +1121,7 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
curl_socklen_t fromlen;
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
- tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+ struct tftp_state_data *state = conn->proto.tftpc;
struct SingleRequest *k = &data->req;
/* Receive the packet */
@@ -1206,8 +1208,8 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
**********************************************************/
static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
{
- time_t current;
- tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+ time_t current;
+ struct tftp_state_data *state = conn->proto.tftpc;
if(event)
*event = TFTP_EVENT_NONE;
@@ -1244,7 +1246,7 @@ static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
tftp_event_t event;
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
- tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+ struct tftp_state_data *state = conn->proto.tftpc;
long timeout_ms = tftp_state_timeout(conn, &event);
*done = FALSE;
@@ -1328,7 +1330,7 @@ static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
{
CURLcode result = CURLE_OK;
- tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
+ struct tftp_state_data *state = conn->proto.tftpc;
*dophase_done = FALSE;
@@ -1358,7 +1360,7 @@ static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
static CURLcode tftp_do(struct connectdata *conn, bool *done)
{
- tftp_state_data_t *state;
+ struct tftp_state_data *state;
CURLcode result;
*done = FALSE;
@@ -1369,7 +1371,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
return result;
}
- state = (tftp_state_data_t *)conn->proto.tftpc;
+ state = conn->proto.tftpc;
if(!state)
return CURLE_TFTP_ILLEGAL;
@@ -1384,7 +1386,7 @@ static CURLcode tftp_do(struct connectdata *conn, bool *done)
return result;
}
-static CURLcode tftp_setup_connection(struct connectdata * conn)
+static CURLcode tftp_setup_connection(struct connectdata *conn)
{
struct Curl_easy *data = conn->data;
char *type;
diff --git a/lib/transfer.c b/lib/transfer.c
index fe61dc1f1..9fe47ab1f 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -128,12 +128,13 @@ static size_t Curl_trailers_read(char *buffer, size_t size, size_t nitems,
void *raw)
{
struct Curl_easy *data = (struct Curl_easy *)raw;
- Curl_send_buffer *trailers_buf = data->state.trailers_buf;
- size_t bytes_left = trailers_buf->size_used-data->state.trailers_bytes_sent;
+ struct dynbuf *trailers_buf = &data->state.trailers_buf;
+ size_t bytes_left = Curl_dyn_len(trailers_buf) -
+ data->state.trailers_bytes_sent;
size_t to_copy = (size*nitems < bytes_left) ? size*nitems : bytes_left;
if(to_copy) {
memcpy(buffer,
- &trailers_buf->buffer[data->state.trailers_bytes_sent],
+ Curl_dyn_ptr(trailers_buf) + data->state.trailers_bytes_sent,
to_copy);
data->state.trailers_bytes_sent += to_copy;
}
@@ -143,8 +144,8 @@ static size_t Curl_trailers_read(char *buffer, size_t size, size_t nitems,
static size_t Curl_trailers_left(void *raw)
{
struct Curl_easy *data = (struct Curl_easy *)raw;
- Curl_send_buffer *trailers_buf = data->state.trailers_buf;
- return trailers_buf->size_used - data->state.trailers_bytes_sent;
+ struct dynbuf *trailers_buf = &data->state.trailers_buf;
+ return Curl_dyn_len(trailers_buf) - data->state.trailers_bytes_sent;
}
#endif
@@ -186,11 +187,8 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
infof(data,
"Moving trailers state machine from initialized to sending.\n");
data->state.trailers_state = TRAILERS_SENDING;
- data->state.trailers_buf = Curl_add_buffer_init();
- if(!data->state.trailers_buf) {
- failf(data, "Unable to allocate trailing headers buffer !");
- return CURLE_OUT_OF_MEMORY;
- }
+ Curl_dyn_init(&data->state.trailers_buf, DYN_TRAILERS);
+
data->state.trailers_bytes_sent = 0;
Curl_set_in_callback(data, true);
trailers_ret_code = data->set.trailer_callback(&trailers,
@@ -206,7 +204,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
result = CURLE_ABORTED_BY_CALLBACK;
}
if(result) {
- Curl_add_buffer_free(&data->state.trailers_buf);
+ Curl_dyn_free(&data->state.trailers_buf);
curl_slist_free_all(trailers);
return result;
}
@@ -369,7 +367,7 @@ CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes,
#ifndef CURL_DISABLE_HTTP
if(data->state.trailers_state == TRAILERS_SENDING &&
!Curl_trailers_left(data)) {
- Curl_add_buffer_free(&data->state.trailers_buf);
+ Curl_dyn_free(&data->state.trailers_buf);
data->state.trailers_state = TRAILERS_DONE;
data->set.trailer_data = NULL;
data->set.trailer_callback = NULL;
@@ -435,8 +433,8 @@ CURLcode Curl_readrewind(struct connectdata *conn)
}
if(data->set.postfields)
; /* do nothing */
- else if(data->set.httpreq == HTTPREQ_POST_MIME ||
- data->set.httpreq == HTTPREQ_POST_FORM) {
+ else if(data->state.httpreq == HTTPREQ_POST_MIME ||
+ data->state.httpreq == HTTPREQ_POST_FORM) {
if(Curl_mime_rewind(mimepart)) {
failf(data, "Cannot rewind mime/post data");
return CURLE_SEND_FAIL_REWIND;
@@ -560,6 +558,8 @@ static CURLcode readwrite_data(struct Curl_easy *data,
size_t excess = 0; /* excess bytes read */
bool readmore = FALSE; /* used by RTP to signal for more data */
int maxloops = 100;
+ char *buf = data->state.buffer;
+ DEBUGASSERT(buf);
*done = FALSE;
*comeback = FALSE;
@@ -594,7 +594,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
if(bytestoread) {
/* receive data from the network! */
- result = Curl_read(conn, conn->sockfd, k->buf, bytestoread, &nread);
+ result = Curl_read(conn, conn->sockfd, buf, bytestoread, &nread);
/* read would've blocked */
if(CURLE_AGAIN == result)
@@ -621,9 +621,8 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* indicates data of zero size, i.e. empty file */
is_empty_data = ((nread == 0) && (k->bodywrites == 0)) ? TRUE : FALSE;
- /* NUL terminate, allowing string ops to be used */
if(0 < nread || is_empty_data) {
- k->buf[nread] = 0;
+ buf[nread] = 0;
}
else {
/* if we receive 0 or less here, either the http2 stream is closed or the
@@ -640,7 +639,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* Default buffer to use when we write the buffer, it may be changed
in the flow below before the actual storing is done. */
- k->str = k->buf;
+ k->str = buf;
if(conn->handler->readwrite) {
result = conn->handler->readwrite(data, conn, &nread, &readmore);
@@ -689,7 +688,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* This is not an 'else if' since it may be a rest from the header
parsing, where the beginning of the buffer is headers and the end
is non-headers. */
- if(k->str && !k->header && (nread > 0 || is_empty_data)) {
+ if(!k->header && (nread > 0 || is_empty_data)) {
if(data->set.opt_no_body) {
/* data arrives although we want none, bail out */
@@ -720,7 +719,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->state.httpreq == HTTPREQ_GET) &&
!k->ignorebody) {
if(k->size == data->state.resume_from) {
@@ -770,8 +769,9 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* pass data to the debug function before it gets "dechunked" */
if(data->set.verbose) {
if(k->badheader) {
- Curl_debug(data, CURLINFO_DATA_IN, data->state.headerbuff,
- (size_t)k->hbuflen);
+ Curl_debug(data, CURLINFO_DATA_IN,
+ Curl_dyn_ptr(&data->state.headerb),
+ Curl_dyn_len(&data->state.headerb));
if(k->badheader == HEADER_PARTHEADER)
Curl_debug(data, CURLINFO_DATA_IN,
k->str, (size_t)nread);
@@ -822,9 +822,9 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* Account for body content stored in the header buffer */
if((k->badheader == HEADER_PARTHEADER) && !k->ignorebody) {
- DEBUGF(infof(data, "Increasing bytecount by %zu from hbuflen\n",
- k->hbuflen));
- k->bytecount += k->hbuflen;
+ size_t headlen = Curl_dyn_len(&data->state.headerb);
+ DEBUGF(infof(data, "Increasing bytecount by %zu\n", headlen));
+ k->bytecount += headlen;
}
if((-1 != k->maxdownload) &&
@@ -839,6 +839,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
", maxdownload = %" CURL_FORMAT_CURL_OFF_T
", bytecount = %" CURL_FORMAT_CURL_OFF_T "\n",
excess, k->size, k->maxdownload, k->bytecount);
+ connclose(conn, "excess found in a read");
}
nread = (ssize_t) (k->maxdownload - k->bytecount);
@@ -858,15 +859,16 @@ static CURLcode readwrite_data(struct Curl_easy *data,
if(k->badheader && !k->ignorebody) {
/* we parsed a piece of data wrongly assuming it was a header
and now we output it as body instead */
+ size_t headlen = Curl_dyn_len(&data->state.headerb);
/* Don't let excess data pollute body writes */
- if(k->maxdownload == -1 || (curl_off_t)k->hbuflen <= k->maxdownload)
+ if(k->maxdownload == -1 || (curl_off_t)headlen <= k->maxdownload)
result = Curl_client_write(conn, CLIENTWRITE_BODY,
- data->state.headerbuff,
- k->hbuflen);
+ Curl_dyn_ptr(&data->state.headerb),
+ headlen);
else
result = Curl_client_write(conn, CLIENTWRITE_BODY,
- data->state.headerbuff,
+ Curl_dyn_ptr(&data->state.headerb),
(size_t)k->maxdownload);
if(result)
@@ -904,10 +906,10 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* Parse the excess data */
k->str += nread;
- if(&k->str[excess] > &k->buf[data->set.buffer_size]) {
+ if(&k->str[excess] > &buf[data->set.buffer_size]) {
/* the excess amount was too excessive(!), make sure
it doesn't read out of buffer */
- excess = &k->buf[data->set.buffer_size] - k->str;
+ excess = &buf[data->set.buffer_size] - k->str;
}
nread = (ssize_t)excess;
@@ -1447,6 +1449,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
}
}
+ data->state.httpreq = data->set.method;
data->change.url = data->set.str[STRING_SET_URL];
/* Init the SSL session ID cache here. We do it here since we want to do it
@@ -1466,12 +1469,11 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
data->state.authhost.want = data->set.httpauth;
data->state.authproxy.want = data->set.proxyauth;
Curl_safefree(data->info.wouldredirect);
- data->info.wouldredirect = NULL;
- if(data->set.httpreq == HTTPREQ_PUT)
+ if(data->state.httpreq == HTTPREQ_PUT)
data->state.infilesize = data->set.filesize;
- else if((data->set.httpreq != HTTPREQ_GET) &&
- (data->set.httpreq != HTTPREQ_HEAD)) {
+ else if((data->state.httpreq != HTTPREQ_GET) &&
+ (data->state.httpreq != HTTPREQ_HEAD)) {
data->state.infilesize = data->set.postfieldsize;
if(data->set.postfields && (data->state.infilesize == -1))
data->state.infilesize = (curl_off_t)strlen(data->set.postfields);
@@ -1682,12 +1684,12 @@ CURLcode Curl_follow(struct Curl_easy *data,
* This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and
* can be overridden with CURLOPT_POSTREDIR.
*/
- if((data->set.httpreq == HTTPREQ_POST
- || data->set.httpreq == HTTPREQ_POST_FORM
- || data->set.httpreq == HTTPREQ_POST_MIME)
+ if((data->state.httpreq == HTTPREQ_POST
+ || data->state.httpreq == HTTPREQ_POST_FORM
+ || data->state.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;
+ data->state.httpreq = HTTPREQ_GET;
}
break;
case 302: /* Found */
@@ -1707,12 +1709,12 @@ CURLcode Curl_follow(struct Curl_easy *data,
* This behaviour is forbidden by RFC1945 and the obsolete RFC2616, and
* can be overridden with CURLOPT_POSTREDIR.
*/
- if((data->set.httpreq == HTTPREQ_POST
- || data->set.httpreq == HTTPREQ_POST_FORM
- || data->set.httpreq == HTTPREQ_POST_MIME)
+ if((data->state.httpreq == HTTPREQ_POST
+ || data->state.httpreq == HTTPREQ_POST_FORM
+ || data->state.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;
+ data->state.httpreq = HTTPREQ_GET;
}
break;
@@ -1722,12 +1724,12 @@ CURLcode Curl_follow(struct Curl_easy *data,
* method is POST and the user specified to keep it as POST.
* https://github.com/curl/curl/issues/5237#issuecomment-614641049
*/
- if(data->set.httpreq != HTTPREQ_GET &&
- ((data->set.httpreq != HTTPREQ_POST &&
- data->set.httpreq != HTTPREQ_POST_FORM &&
- data->set.httpreq != HTTPREQ_POST_MIME) ||
+ if(data->state.httpreq != HTTPREQ_GET &&
+ ((data->state.httpreq != HTTPREQ_POST &&
+ data->state.httpreq != HTTPREQ_POST_FORM &&
+ data->state.httpreq != HTTPREQ_POST_MIME) ||
!(data->set.keep_post & CURL_REDIR_POST_303))) {
- data->set.httpreq = HTTPREQ_GET;
+ data->state.httpreq = HTTPREQ_GET;
data->set.upload = false;
infof(data, "Switch to %s\n",
data->set.opt_no_body?"HEAD":"GET");
diff --git a/lib/url.c b/lib/url.c
index 03c274438..a1a6b6910 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -122,6 +122,7 @@ bool curl_win32_idn_to_ascii(const char *in, char **out);
#include "strdup.h"
#include "setopt.h"
#include "altsvc.h"
+#include "dynbuf.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -141,19 +142,21 @@ static unsigned int get_protocol_family(unsigned int protocol);
/*
- * Protocol table.
+ * Protocol table. Schemes (roughly) in 2019 popularity order:
+ *
+ * HTTPS, HTTP, FTP, FTPS, SFTP, FILE, SCP, SMTP, LDAP, IMAPS, TELNET, IMAP,
+ * LDAPS, SMTPS, TFTP, SMB, POP3, GOPHER POP3S, RTSP, RTMP, SMBS, DICT
*/
-
static const struct Curl_handler * const protocols[] = {
-#ifndef CURL_DISABLE_HTTP
- &Curl_handler_http,
-#endif
-
#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
&Curl_handler_https,
#endif
+#ifndef CURL_DISABLE_HTTP
+ &Curl_handler_http,
+#endif
+
#ifndef CURL_DISABLE_FTP
&Curl_handler_ftp,
#endif
@@ -162,12 +165,23 @@ static const struct Curl_handler * const protocols[] = {
&Curl_handler_ftps,
#endif
-#ifndef CURL_DISABLE_TELNET
- &Curl_handler_telnet,
+#if defined(USE_SSH)
+ &Curl_handler_sftp,
#endif
-#ifndef CURL_DISABLE_DICT
- &Curl_handler_dict,
+#ifndef CURL_DISABLE_FILE
+ &Curl_handler_file,
+#endif
+
+#if defined(USE_SSH) && !defined(USE_WOLFSSH)
+ &Curl_handler_scp,
+#endif
+
+#ifndef CURL_DISABLE_SMTP
+ &Curl_handler_smtp,
+#ifdef USE_SSL
+ &Curl_handler_smtps,
+#endif
#endif
#ifndef CURL_DISABLE_LDAP
@@ -179,22 +193,6 @@ static const struct Curl_handler * const protocols[] = {
#endif
#endif
-#ifndef CURL_DISABLE_FILE
- &Curl_handler_file,
-#endif
-
-#ifndef CURL_DISABLE_TFTP
- &Curl_handler_tftp,
-#endif
-
-#if defined(USE_SSH) && !defined(USE_WOLFSSH)
- &Curl_handler_scp,
-#endif
-
-#if defined(USE_SSH)
- &Curl_handler_sftp,
-#endif
-
#ifndef CURL_DISABLE_IMAP
&Curl_handler_imap,
#ifdef USE_SSL
@@ -202,6 +200,14 @@ static const struct Curl_handler * const protocols[] = {
#endif
#endif
+#ifndef CURL_DISABLE_TELNET
+ &Curl_handler_telnet,
+#endif
+
+#ifndef CURL_DISABLE_TFTP
+ &Curl_handler_tftp,
+#endif
+
#ifndef CURL_DISABLE_POP3
&Curl_handler_pop3,
#ifdef USE_SSL
@@ -218,25 +224,18 @@ static const struct Curl_handler * const protocols[] = {
#endif
#endif
-#ifndef CURL_DISABLE_SMTP
- &Curl_handler_smtp,
-#ifdef USE_SSL
- &Curl_handler_smtps,
-#endif
-#endif
-
#ifndef CURL_DISABLE_RTSP
&Curl_handler_rtsp,
#endif
-#ifndef CURL_DISABLE_GOPHER
- &Curl_handler_gopher,
-#endif
-
#ifdef CURL_ENABLE_MQTT
&Curl_handler_mqtt,
#endif
+#ifndef CURL_DISABLE_GOPHER
+ &Curl_handler_gopher,
+#endif
+
#ifdef USE_LIBRTMP
&Curl_handler_rtmp,
&Curl_handler_rtmpt,
@@ -246,6 +245,10 @@ static const struct Curl_handler * const protocols[] = {
&Curl_handler_rtmpts,
#endif
+#ifndef CURL_DISABLE_DICT
+ &Curl_handler_dict,
+#endif
+
(struct Curl_handler *) NULL
};
@@ -278,10 +281,16 @@ void Curl_freeset(struct Curl_easy *data)
{
/* Free all dynamic strings stored in the data->set substructure. */
enum dupstring i;
+ enum dupblob j;
+
for(i = (enum dupstring)0; i < STRING_LAST; i++) {
Curl_safefree(data->set.str[i]);
}
+ for(j = (enum dupblob)0; j < BLOB_LAST; j++) {
+ Curl_safefree(data->set.blobs[j]);
+ }
+
if(data->change.referer_alloc) {
Curl_safefree(data->change.referer);
data->change.referer_alloc = FALSE;
@@ -380,7 +389,7 @@ CURLcode Curl_close(struct Curl_easy **datap)
up_free(data);
Curl_safefree(data->state.buffer);
- Curl_safefree(data->state.headerbuff);
+ Curl_dyn_free(&data->state.headerb);
Curl_safefree(data->state.ulbuf);
Curl_flush_cookies(data, TRUE);
#ifdef USE_ALTSVC
@@ -407,9 +416,20 @@ CURLcode Curl_close(struct Curl_easy **datap)
Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
}
+ Curl_safefree(data->state.aptr.proxyuserpwd);
+ Curl_safefree(data->state.aptr.uagent);
+ Curl_safefree(data->state.aptr.userpwd);
+ Curl_safefree(data->state.aptr.accept_encoding);
+ Curl_safefree(data->state.aptr.te);
+ Curl_safefree(data->state.aptr.rangeline);
+ Curl_safefree(data->state.aptr.ref);
+ Curl_safefree(data->state.aptr.host);
+ Curl_safefree(data->state.aptr.cookiehost);
+ Curl_safefree(data->state.aptr.rtsp_transport);
+
#ifndef CURL_DISABLE_DOH
- free(data->req.doh.probe[0].serverdoh.memory);
- free(data->req.doh.probe[1].serverdoh.memory);
+ Curl_dyn_free(&data->req.doh.probe[0].serverdoh);
+ Curl_dyn_free(&data->req.doh.probe[1].serverdoh);
curl_slist_free_all(data->req.doh.headers);
#endif
@@ -453,7 +473,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->postfieldsize = -1; /* unknown size */
set->maxredirs = -1; /* allow any amount by default */
- set->httpreq = HTTPREQ_GET; /* Default HTTP request */
+ set->method = HTTPREQ_GET; /* Default HTTP request */
set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
#ifndef CURL_DISABLE_FTP
set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
@@ -492,7 +512,9 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
type */
set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by
default */
+#ifndef CURL_DISABLE_PROXY
set->proxy_ssl = set->ssl;
+#endif
set->new_file_perms = 0644; /* Default permissions */
set->new_directory_perms = 0755; /* Default permissions */
@@ -601,38 +623,22 @@ CURLcode Curl_open(struct Curl_easy **curl)
return result;
}
- /* We do some initial setup here, all those fields that can't be just 0 */
-
- data->state.buffer = malloc(READBUFFER_SIZE + 1);
- if(!data->state.buffer) {
- DEBUGF(fprintf(stderr, "Error: malloc of buffer failed\n"));
- result = CURLE_OUT_OF_MEMORY;
- }
- else {
- data->state.headerbuff = malloc(HEADERSIZE);
- if(!data->state.headerbuff) {
- DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
- result = CURLE_OUT_OF_MEMORY;
- }
- else {
- result = Curl_init_userdefined(data);
-
- data->state.headersize = HEADERSIZE;
- Curl_convert_init(data);
- Curl_initinfo(data);
+ result = Curl_init_userdefined(data);
+ if(!result) {
+ Curl_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER);
+ Curl_convert_init(data);
+ Curl_initinfo(data);
- /* most recent connection is not yet defined */
- data->state.lastconnect = NULL;
+ /* most recent connection is not yet defined */
+ data->state.lastconnect = NULL;
- data->progress.flags |= PGRS_HIDE;
- data->state.current_speed = -1; /* init to negative == impossible */
- }
+ data->progress.flags |= PGRS_HIDE;
+ data->state.current_speed = -1; /* init to negative == impossible */
}
if(result) {
Curl_resolver_cleanup(data->state.resolver);
- free(data->state.buffer);
- free(data->state.headerbuff);
+ Curl_dyn_free(&data->state.headerb);
Curl_freeset(data);
free(data);
data = NULL;
@@ -684,9 +690,7 @@ static void conn_reset_all_postponed_data(struct connectdata *conn)
static void conn_shutdown(struct connectdata *conn)
{
- if(!conn)
- return;
-
+ DEBUGASSERT(conn);
infof(conn->data, "Closing connection %ld\n", conn->connection_id);
DEBUGASSERT(conn->data);
@@ -707,54 +711,40 @@ static void conn_shutdown(struct connectdata *conn)
Curl_closesocket(conn, conn->tempsock[0]);
if(CURL_SOCKET_BAD != conn->tempsock[1])
Curl_closesocket(conn, conn->tempsock[1]);
-
- /* unlink ourselves. this should be called last since other shutdown
- procedures need a valid conn->data and this may clear it. */
- Curl_conncache_remove_conn(conn->data, conn, TRUE);
}
static void conn_free(struct connectdata *conn)
{
- if(!conn)
- return;
+ DEBUGASSERT(conn);
Curl_free_idnconverted_hostname(&conn->host);
Curl_free_idnconverted_hostname(&conn->conn_to_host);
+#ifndef CURL_DISABLE_PROXY
Curl_free_idnconverted_hostname(&conn->http_proxy.host);
Curl_free_idnconverted_hostname(&conn->socks_proxy.host);
-
- Curl_safefree(conn->user);
- Curl_safefree(conn->passwd);
- Curl_safefree(conn->sasl_authzid);
- Curl_safefree(conn->options);
Curl_safefree(conn->http_proxy.user);
Curl_safefree(conn->socks_proxy.user);
Curl_safefree(conn->http_proxy.passwd);
Curl_safefree(conn->socks_proxy.passwd);
- Curl_safefree(conn->allocptr.proxyuserpwd);
- Curl_safefree(conn->allocptr.uagent);
- Curl_safefree(conn->allocptr.userpwd);
- Curl_safefree(conn->allocptr.accept_encoding);
- Curl_safefree(conn->allocptr.te);
- Curl_safefree(conn->allocptr.rangeline);
- Curl_safefree(conn->allocptr.ref);
- Curl_safefree(conn->allocptr.host);
- Curl_safefree(conn->allocptr.cookiehost);
- Curl_safefree(conn->allocptr.rtsp_transport);
- Curl_safefree(conn->trailer);
+ Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
+ Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
+ Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
+#endif
+ Curl_safefree(conn->user);
+ Curl_safefree(conn->passwd);
+ Curl_safefree(conn->sasl_authzid);
+ Curl_safefree(conn->options);
+ Curl_dyn_free(&conn->trailer);
Curl_safefree(conn->host.rawalloc); /* host name buffer */
Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
Curl_safefree(conn->hostname_resolve);
Curl_safefree(conn->secondaryhostname);
- Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
- Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
Curl_safefree(conn->connect_state);
conn_reset_all_postponed_data(conn);
Curl_llist_destroy(&conn->easyq, NULL);
Curl_safefree(conn->localdev);
Curl_free_primary_ssl_config(&conn->ssl_config);
- Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
#ifdef USE_UNIX_SOCKETS
Curl_safefree(conn->unix_domain_socket);
@@ -783,13 +773,17 @@ static void conn_free(struct connectdata *conn)
CURLcode Curl_disconnect(struct Curl_easy *data,
struct connectdata *conn, bool dead_connection)
{
- if(!conn)
- return CURLE_OK; /* this is closed and fine already */
+ /* there must be a connection to close */
+ DEBUGASSERT(conn);
- if(!data) {
- DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n"));
- return CURLE_OK;
- }
+ /* it must be removed from the connection cache */
+ DEBUGASSERT(!conn->bundle);
+
+ /* there must be an associated transfer */
+ DEBUGASSERT(data);
+
+ /* the transfer must be detached from the connection */
+ DEBUGASSERT(!data->conn);
/*
* If this connection isn't marked to force-close, leave it open if there
@@ -805,16 +799,11 @@ CURLcode Curl_disconnect(struct Curl_easy *data,
conn->dns_entry = NULL;
}
- Curl_hostcache_prune(data); /* kill old DNS cache entries */
-
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
/* Cleanup NTLM connection-related data */
Curl_http_auth_cleanup_ntlm(conn);
-#endif
-#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
+
/* Cleanup NEGOTIATE connection-related data */
Curl_http_auth_cleanup_negotiate(conn);
-#endif
/* the protocol specific disconnect handler and conn_shutdown need a transfer
for the connection! */
@@ -876,8 +865,8 @@ static int IsMultiplexingPossible(const struct Curl_easy *handle,
#ifndef CURL_DISABLE_PROXY
static bool
-proxy_info_matches(const struct proxy_info* data,
- const struct proxy_info* needle)
+proxy_info_matches(const struct proxy_info *data,
+ const struct proxy_info *needle)
{
if((data->proxytype == needle->proxytype) &&
(data->port == needle->port) &&
@@ -888,8 +877,8 @@ proxy_info_matches(const struct proxy_info* data,
}
static bool
-socks_proxy_info_matches(const struct proxy_info* data,
- const struct proxy_info* needle)
+socks_proxy_info_matches(const struct proxy_info *data,
+ const struct proxy_info *needle)
{
if(!proxy_info_matches(data, needle))
return FALSE;
@@ -1011,8 +1000,12 @@ static int call_extract_if_dead(struct connectdata *conn, void *param)
static void prune_dead_connections(struct Curl_easy *data)
{
struct curltime now = Curl_now();
- timediff_t elapsed =
+ timediff_t elapsed;
+
+ CONNCACHE_LOCK(data);
+ elapsed =
Curl_timediff(now, data->state.conn_cache->last_cleanup);
+ CONNCACHE_UNLOCK(data);
if(elapsed >= 1000L) {
struct prunedead prune;
@@ -1020,10 +1013,17 @@ static void prune_dead_connections(struct Curl_easy *data)
prune.extracted = NULL;
while(Curl_conncache_foreach(data, data->state.conn_cache, &prune,
call_extract_if_dead)) {
+ /* unlocked */
+
+ /* remove connection from cache */
+ Curl_conncache_remove_conn(data, prune.extracted, TRUE);
+
/* disconnect it */
(void)Curl_disconnect(data, prune.extracted, /* dead_connection */TRUE);
}
+ CONNCACHE_LOCK(data);
data->state.conn_cache->last_cleanup = now;
+ CONNCACHE_UNLOCK(data);
}
}
@@ -1056,10 +1056,14 @@ ConnectionExists(struct Curl_easy *data,
bool wantNTLMhttp = ((data->state.authhost.want &
(CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
(needle->handler->protocol & PROTO_FAMILY_HTTP));
+#ifndef CURL_DISABLE_PROXY
bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
((data->state.authproxy.want &
(CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
(needle->handler->protocol & PROTO_FAMILY_HTTP)));
+#else
+ bool wantProxyNTLMhttp = FALSE;
+#endif
#endif
*force_reuse = FALSE;
@@ -1083,7 +1087,7 @@ ConnectionExists(struct Curl_easy *data,
if(data->set.pipewait) {
infof(data, "Server doesn't support multiplex yet, wait\n");
*waitpipe = TRUE;
- Curl_conncache_unlock(data);
+ CONNCACHE_UNLOCK(data);
return FALSE; /* no re-use */
}
@@ -1156,7 +1160,8 @@ ConnectionExists(struct Curl_easy *data,
continue;
if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
continue;
- if(needle->abstract_unix_socket != check->abstract_unix_socket)
+ if(needle->bits.abstract_unix_socket !=
+ check->bits.abstract_unix_socket)
continue;
}
else if(check->unix_domain_socket)
@@ -1167,10 +1172,11 @@ ConnectionExists(struct Curl_easy *data,
(check->handler->flags&PROTOPT_SSL))
/* don't do mixed SSL and non-SSL connections */
if(get_protocol_family(check->handler->protocol) !=
- needle->handler->protocol || !check->tls_upgraded)
+ needle->handler->protocol || !check->bits.tls_upgraded)
/* except protocols that have been upgraded via TLS */
continue;
+#ifndef CURL_DISABLE_PROXY
if(needle->bits.httpproxy != check->bits.httpproxy ||
needle->bits.socksproxy != check->bits.socksproxy)
continue;
@@ -1179,7 +1185,7 @@ ConnectionExists(struct Curl_easy *data,
!socks_proxy_info_matches(&needle->socks_proxy,
&check->socks_proxy))
continue;
-
+#endif
if(needle->bits.conn_to_host != check->bits.conn_to_host)
/* don't mix connections that use the "connect to host" feature and
* connections that don't use this feature */
@@ -1190,6 +1196,7 @@ ConnectionExists(struct Curl_easy *data,
* connections that don't use this feature */
continue;
+#ifndef CURL_DISABLE_PROXY
if(needle->bits.httpproxy) {
if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
continue;
@@ -1216,6 +1223,7 @@ ConnectionExists(struct Curl_easy *data,
}
}
}
+#endif
DEBUGASSERT(!check->data || GOOD_EASY_HANDLE(check->data));
@@ -1258,15 +1266,18 @@ ConnectionExists(struct Curl_easy *data,
}
}
- if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) ||
- needle->bits.tunnel_proxy) {
+ if((needle->handler->flags&PROTOPT_SSL)
+#ifndef CURL_DISABLE_PROXY
+ || !needle->bits.httpproxy || needle->bits.tunnel_proxy
+#endif
+ ) {
/* The requested connection does not use a HTTP proxy or it uses SSL or
it is a non-SSL protocol tunneled or it is a non-SSL protocol which
is allowed to be upgraded via TLS */
if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
(get_protocol_family(check->handler->protocol) ==
- needle->handler->protocol && check->tls_upgraded)) &&
+ needle->handler->protocol && check->bits.tls_upgraded)) &&
(!needle->bits.conn_to_host || strcasecompare(
needle->conn_to_host.name, check->conn_to_host.name)) &&
(!needle->bits.conn_to_port ||
@@ -1328,6 +1339,7 @@ ConnectionExists(struct Curl_easy *data,
continue;
}
+#ifndef CURL_DISABLE_PROXY
/* Same for Proxy NTLM authentication */
if(wantProxyNTLMhttp) {
/* Both check->http_proxy.user and check->http_proxy.passwd can be
@@ -1343,7 +1355,7 @@ ConnectionExists(struct Curl_easy *data,
/* Proxy connection is using NTLM auth but we don't want NTLM */
continue;
}
-
+#endif
if(wantNTLMhttp || wantProxyNTLMhttp) {
/* Credentials are already checked, we can use this connection */
chosen = check;
@@ -1407,11 +1419,12 @@ ConnectionExists(struct Curl_easy *data,
if(chosen) {
/* mark it as used before releasing the lock */
chosen->data = data; /* own it! */
- Curl_conncache_unlock(data);
+ Curl_attach_connnection(data, chosen);
+ CONNCACHE_UNLOCK(data);
*usethis = chosen;
return TRUE; /* yes, we found one to use! */
}
- Curl_conncache_unlock(data);
+ CONNCACHE_UNLOCK(data);
if(foundPendingCandidate && data->set.pipewait) {
infof(data,
@@ -1430,8 +1443,10 @@ void Curl_verboseconnect(struct connectdata *conn)
{
if(conn->data->set.verbose)
infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
+#ifndef CURL_DISABLE_PROXY
conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
conn->bits.httpproxy ? conn->http_proxy.host.dispname :
+#endif
conn->bits.conn_to_host ? conn->conn_to_host.dispname :
conn->host.dispname,
conn->ip_addr_str, conn->port, conn->connection_id);
@@ -1578,8 +1593,10 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->ssl_extra = ssl;
conn->ssl[0].backend = (void *)ssl;
conn->ssl[1].backend = (void *)(ssl + sslsize);
+#ifndef CURL_DISABLE_PROXY
conn->proxy_ssl[0].backend = (void *)(ssl + 2 * sslsize);
conn->proxy_ssl[1].backend = (void *)(ssl + 3 * sslsize);
+#endif
}
#endif
@@ -1618,10 +1635,10 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->data = data; /* Setup the association between this connection
and the Curl_easy */
+#ifndef CURL_DISABLE_PROXY
conn->http_proxy.proxytype = data->set.proxytype;
conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
-#if !defined(CURL_DISABLE_PROXY)
/* note that these two proxy bits are now just on what looks to be
requested, they may be altered down the road */
conn->bits.proxy = (data->set.str[STRING_PROXY] &&
@@ -1652,10 +1669,12 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
+#ifndef CURL_DISABLE_PROXY
conn->proxy_ssl_config.verifystatus =
data->set.proxy_ssl.primary.verifystatus;
conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
+#endif
conn->ip_version = data->set.ipver;
conn->bits.connect_only = data->set.connect_only;
conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
@@ -1875,23 +1894,32 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
if(result)
return result;
- uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user,
- CURLU_URLDECODE);
+ /* we don't use the URL API's URL decoder option here since it rejects
+ control codes and we want to allow them for some schemes in the user and
+ password fields */
+ uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user, 0);
if(!uc) {
- conn->user = strdup(data->state.up.user);
- if(!conn->user)
- return CURLE_OUT_OF_MEMORY;
+ char *decoded;
+ result = Curl_urldecode(NULL, data->state.up.user, 0, &decoded, NULL,
+ conn->handler->flags&PROTOPT_USERPWDCTRL ?
+ REJECT_ZERO : REJECT_CTRL);
+ if(result)
+ return result;
+ conn->user = decoded;
conn->bits.user_passwd = TRUE;
}
else if(uc != CURLUE_NO_USER)
return Curl_uc_to_curlcode(uc);
- uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password,
- CURLU_URLDECODE);
+ uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password, 0);
if(!uc) {
- conn->passwd = strdup(data->state.up.password);
- if(!conn->passwd)
- return CURLE_OUT_OF_MEMORY;
+ char *decoded;
+ result = Curl_urldecode(NULL, data->state.up.password, 0, &decoded, NULL,
+ conn->handler->flags&PROTOPT_USERPWDCTRL ?
+ REJECT_ZERO : REJECT_CTRL);
+ if(result)
+ return result;
+ conn->passwd = decoded;
conn->bits.user_passwd = TRUE;
}
else if(uc != CURLUE_NO_PASSWORD)
@@ -2001,7 +2029,7 @@ static CURLcode setup_range(struct Curl_easy *data)
*/
static CURLcode setup_connection_internals(struct connectdata *conn)
{
- const struct Curl_handler * p;
+ const struct Curl_handler *p;
CURLcode result;
/* Perform setup complement if some. */
@@ -2348,26 +2376,16 @@ static CURLcode parse_proxy(struct Curl_easy *data,
static CURLcode parse_proxy_auth(struct Curl_easy *data,
struct connectdata *conn)
{
- char proxyuser[MAX_CURL_USER_LENGTH]="";
- char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
- CURLcode result;
-
- if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
- strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
- MAX_CURL_USER_LENGTH);
- proxyuser[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/
- }
- if(data->set.str[STRING_PROXYPASSWORD] != NULL) {
- strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD],
- MAX_CURL_PASSWORD_LENGTH);
- proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
- }
+ char *proxyuser = data->set.str[STRING_PROXYUSERNAME];
+ char *proxypasswd = data->set.str[STRING_PROXYPASSWORD];
+ CURLcode result = CURLE_OK;
- result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
- FALSE);
- if(!result)
+ if(proxyuser)
+ result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
+ REJECT_ZERO);
+ if(!result && proxypasswd)
result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
- NULL, FALSE);
+ NULL, REJECT_ZERO);
return result;
}
@@ -2585,6 +2603,12 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len,
size_t plen;
size_t olen;
+ /* the input length check is because this is called directcly from setopt
+ and isn't going through the regular string length check */
+ size_t llen = strlen(login);
+ if(llen > CURL_MAX_INPUT_LENGTH)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
/* Attempt to find the password separator */
if(passwdp) {
psep = strchr(login, ':');
@@ -2781,12 +2805,14 @@ static CURLcode override_login(struct Curl_easy *data,
/* for updated strings, we update them in the URL */
if(user_changed) {
- uc = curl_url_set(data->state.uh, CURLUPART_USER, *userp, 0);
+ uc = curl_url_set(data->state.uh, CURLUPART_USER, *userp,
+ CURLU_URLENCODE);
if(uc)
return Curl_uc_to_curlcode(uc);
}
if(passwd_changed) {
- uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, *passwdp, 0);
+ uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, *passwdp,
+ CURLU_URLENCODE);
if(uc)
return Curl_uc_to_curlcode(uc);
}
@@ -3159,7 +3185,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
else {
bool longpath = FALSE;
hostaddr->addr = Curl_unix2addr(path, &longpath,
- conn->abstract_unix_socket);
+ conn->bits.abstract_unix_socket);
if(hostaddr->addr)
hostaddr->inuse++;
else {
@@ -3177,6 +3203,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
}
else
#endif
+
if(!conn->bits.proxy) {
struct hostname *connhost;
if(conn->bits.conn_to_host)
@@ -3205,10 +3232,11 @@ static CURLcode resolve_server(struct Curl_easy *data,
else if(!hostaddr) {
failf(data, "Couldn't resolve host '%s'", connhost->dispname);
- result = CURLE_COULDNT_RESOLVE_HOST;
+ result = CURLE_COULDNT_RESOLVE_HOST;
/* don't return yet, we need to clean up the timeout first */
}
}
+#ifndef CURL_DISABLE_PROXY
else {
/* This is a proxy that hasn't been resolved yet. */
@@ -3234,6 +3262,7 @@ static CURLcode resolve_server(struct Curl_easy *data,
/* don't return yet, we need to clean up the timeout first */
}
}
+#endif
DEBUGASSERT(conn->dns_entry == NULL);
conn->dns_entry = hostaddr;
}
@@ -3249,16 +3278,17 @@ static CURLcode resolve_server(struct Curl_easy *data,
static void reuse_conn(struct connectdata *old_conn,
struct connectdata *conn)
{
+#ifndef CURL_DISABLE_PROXY
Curl_free_idnconverted_hostname(&old_conn->http_proxy.host);
Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host);
free(old_conn->http_proxy.host.rawalloc);
free(old_conn->socks_proxy.host.rawalloc);
-
+ Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
+#endif
/* free the SSL config struct from this connection struct as this was
allocated in vain and is targeted for destruction */
Curl_free_primary_ssl_config(&old_conn->ssl_config);
- Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
conn->data = old_conn->data;
@@ -3275,6 +3305,7 @@ static void reuse_conn(struct connectdata *old_conn,
old_conn->passwd = NULL;
}
+#ifndef CURL_DISABLE_PROXY
conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
if(conn->bits.proxy_user_passwd) {
/* use the new proxy user name and proxy password though */
@@ -3291,6 +3322,11 @@ static void reuse_conn(struct connectdata *old_conn,
old_conn->http_proxy.passwd = NULL;
old_conn->socks_proxy.passwd = NULL;
}
+ Curl_safefree(old_conn->http_proxy.user);
+ Curl_safefree(old_conn->socks_proxy.user);
+ Curl_safefree(old_conn->http_proxy.passwd);
+ Curl_safefree(old_conn->socks_proxy.passwd);
+#endif
/* host can change, when doing keepalive with a proxy or if the case is
different this time etc */
@@ -3318,10 +3354,6 @@ static void reuse_conn(struct connectdata *old_conn,
Curl_safefree(old_conn->user);
Curl_safefree(old_conn->passwd);
Curl_safefree(old_conn->options);
- Curl_safefree(old_conn->http_proxy.user);
- Curl_safefree(old_conn->socks_proxy.user);
- Curl_safefree(old_conn->http_proxy.passwd);
- Curl_safefree(old_conn->socks_proxy.passwd);
Curl_safefree(old_conn->localdev);
Curl_llist_destroy(&old_conn->easyq, NULL);
@@ -3406,7 +3438,7 @@ static CURLcode create_conn(struct Curl_easy *data,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
- conn->abstract_unix_socket = data->set.abstract_unix_socket;
+ conn->bits.abstract_unix_socket = data->set.abstract_unix_socket;
}
#endif
@@ -3416,7 +3448,6 @@ static CURLcode create_conn(struct Curl_easy *data,
result = create_conn_helper_init_proxy(conn);
if(result)
goto out;
-#endif
/*************************************************************
* If the protocol is using SSL and HTTP proxy is used, we set
@@ -3424,6 +3455,7 @@ static CURLcode create_conn(struct Curl_easy *data,
*************************************************************/
if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
conn->bits.tunnel_proxy = TRUE;
+#endif
/*************************************************************
* Figure out the remote port number and fix it in the URL
@@ -3462,6 +3494,7 @@ static CURLcode create_conn(struct Curl_easy *data,
if(result)
goto out;
}
+#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy) {
result = Curl_idnconvert_hostname(conn, &conn->http_proxy.host);
if(result)
@@ -3472,6 +3505,7 @@ static CURLcode create_conn(struct Curl_easy *data,
if(result)
goto out;
}
+#endif
/*************************************************************
* Check whether the host and the "connect to host" are equal.
@@ -3490,6 +3524,7 @@ static CURLcode create_conn(struct Curl_easy *data,
conn->bits.conn_to_port = FALSE;
}
+#ifndef CURL_DISABLE_PROXY
/*************************************************************
* If the "connect to" feature is used with an HTTP proxy,
* we set the tunnel_proxy bit.
@@ -3497,6 +3532,7 @@ static CURLcode create_conn(struct Curl_easy *data,
if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
conn->bits.httpproxy)
conn->bits.tunnel_proxy = TRUE;
+#endif
/*************************************************************
* Setup internals depending on protocol. Needs to be done after
@@ -3529,6 +3565,7 @@ static CURLcode create_conn(struct Curl_easy *data,
if(!result) {
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
+ Curl_attach_connnection(data, conn);
result = Curl_conncache_add_conn(data->state.conn_cache, conn);
if(result)
goto out;
@@ -3543,7 +3580,6 @@ static CURLcode create_conn(struct Curl_easy *data,
(void)conn->handler->done(conn, result, FALSE);
goto out;
}
- Curl_attach_connnection(data, conn);
Curl_setup_transfer(data, -1, -1, FALSE, -1);
}
@@ -3564,61 +3600,75 @@ static CURLcode create_conn(struct Curl_easy *data,
copies will be separately allocated.
*/
data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
- data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
- data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
- data->set.proxy_ssl.primary.random_file =
- data->set.str[STRING_SSL_RANDOM_FILE];
data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
- data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
data->set.ssl.primary.cipher_list =
data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
- data->set.proxy_ssl.primary.cipher_list =
- data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
data->set.ssl.primary.cipher_list13 =
data->set.str[STRING_SSL_CIPHER13_LIST_ORIG];
- data->set.proxy_ssl.primary.cipher_list13 =
- data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
data->set.ssl.primary.pinned_key =
data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ data->set.ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_ORIG];
+
+#ifndef CURL_DISABLE_PROXY
+ data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
+ data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
+ data->set.proxy_ssl.primary.random_file =
+ data->set.str[STRING_SSL_RANDOM_FILE];
+ data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
+ data->set.proxy_ssl.primary.cipher_list =
+ data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
+ data->set.proxy_ssl.primary.cipher_list13 =
+ data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
data->set.proxy_ssl.primary.pinned_key =
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
-
- data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
+ data->set.proxy_ssl.primary.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
- data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
- data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
- data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
- data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
- data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
- data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
- data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
+ data->set.proxy_ssl.cert_blob = data->set.blobs[BLOB_CERT_PROXY];
+ data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
+#endif
+ data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
+ data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
+ data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
+ data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
+ data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
+ data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
+ data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
+ data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
#ifdef USE_TLS_SRP
data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
- data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
+#ifndef CURL_DISABLE_PROXY
+ data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
#endif
+#endif
+
+ data->set.ssl.cert_blob = data->set.blobs[BLOB_CERT_ORIG];
+ data->set.ssl.key_blob = data->set.blobs[BLOB_KEY_ORIG];
+ data->set.ssl.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT_ORIG];
if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
- &conn->ssl_config)) {
+ &conn->ssl_config)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
+#ifndef CURL_DISABLE_PROXY
if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
&conn->proxy_ssl_config)) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
+#endif
prune_dead_connections(data);
@@ -3656,12 +3706,17 @@ static CURLcode create_conn(struct Curl_easy *data,
conn = conn_temp;
*in_connect = conn;
+#ifndef CURL_DISABLE_PROXY
infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
conn->connection_id,
conn->bits.proxy?"proxy":"host",
conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
- conn->host.dispname);
+ conn->host.dispname);
+#else
+ infof(data, "Re-using existing connection! (#%ld) with host %s\n",
+ conn->connection_id, conn->host.dispname);
+#endif
}
else {
/* We have decided that we want a new connection. However, we may not
@@ -3693,7 +3748,7 @@ static CURLcode create_conn(struct Curl_easy *data,
/* The bundle is full. Extract the oldest connection. */
conn_candidate = Curl_conncache_extract_bundle(data, bundle);
- Curl_conncache_unlock(data);
+ CONNCACHE_UNLOCK(data);
if(conn_candidate)
(void)Curl_disconnect(data, conn_candidate,
@@ -3705,7 +3760,7 @@ static CURLcode create_conn(struct Curl_easy *data,
}
}
else
- Curl_conncache_unlock(data);
+ CONNCACHE_UNLOCK(data);
}
@@ -3739,6 +3794,8 @@ static CURLcode create_conn(struct Curl_easy *data,
* This is a brand new connection, so let's store it in the connection
* cache of ours!
*/
+ Curl_attach_connnection(data, conn);
+
result = Curl_conncache_add_conn(data->state.conn_cache, conn);
if(result)
goto out;
@@ -3790,10 +3847,12 @@ static CURLcode create_conn(struct Curl_easy *data,
/* Strip trailing dots. resolve_server copied the name. */
strip_trailing_dot(&conn->host);
+#ifndef CURL_DISABLE_PROXY
if(conn->bits.httpproxy)
strip_trailing_dot(&conn->http_proxy.host);
if(conn->bits.socksproxy)
strip_trailing_dot(&conn->socks_proxy.host);
+#endif
if(conn->bits.conn_to_host)
strip_trailing_dot(&conn->conn_to_host);
@@ -3824,22 +3883,23 @@ CURLcode Curl_setup_conn(struct connectdata *conn,
}
*protocol_done = FALSE; /* default to not done */
+#ifndef CURL_DISABLE_PROXY
/* set proxy_connect_closed to false unconditionally already here since it
is used strictly to provide extra information to a parent function in the
case of proxy CONNECT failures and we must make sure we don't have it
lingering set from a previous invoke */
conn->bits.proxy_connect_closed = FALSE;
-
+#endif
/*
* Set user-agent. Used for HTTP, but since we can attempt to tunnel
* basically anything through a http proxy we can't limit this based on
* protocol.
*/
if(data->set.str[STRING_USERAGENT]) {
- Curl_safefree(conn->allocptr.uagent);
- conn->allocptr.uagent =
+ Curl_safefree(data->state.aptr.uagent);
+ data->state.aptr.uagent =
aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
- if(!conn->allocptr.uagent)
+ if(!data->state.aptr.uagent)
return CURLE_OUT_OF_MEMORY;
}
@@ -3893,7 +3953,7 @@ CURLcode Curl_connect(struct Curl_easy *data,
result = create_conn(data, &conn, asyncp);
if(!result) {
- if(CONN_INUSE(conn))
+ if(CONN_INUSE(conn) > 1)
/* multiplexed */
*protocol_done = TRUE;
else if(!*asyncp) {
@@ -3910,11 +3970,10 @@ CURLcode Curl_connect(struct Curl_easy *data,
else if(result && conn) {
/* We're not allowed to return failure with memory left allocated in the
connectdata struct, free those here */
+ Curl_detach_connnection(data);
+ Curl_conncache_remove_conn(data, conn, TRUE);
Curl_disconnect(data, conn, TRUE);
}
- else if(!result && !data->conn)
- /* FILE: transfers already have the connection attached */
- Curl_attach_connnection(data, conn);
return result;
}
@@ -3933,6 +3992,11 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
{
struct SingleRequest *k = &data->req;
+ /* if this is a pushed stream, we need this: */
+ CURLcode result = Curl_preconnect(data);
+ if(result)
+ return result;
+
if(conn) {
conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
use */
@@ -3945,30 +4009,17 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
data->state.done = FALSE; /* *_done() is not called yet */
data->state.expect100header = FALSE;
-
if(data->set.opt_no_body)
/* in HTTP lingo, no body means using the HEAD request... */
- data->set.httpreq = HTTPREQ_HEAD;
- else if(HTTPREQ_HEAD == data->set.httpreq)
- /* ... but if unset there really is no perfect method that is the
- "opposite" of HEAD but in reality most people probably think GET
- then. The important thing is that we can't let it remain HEAD if the
- opt_no_body is set FALSE since then we'll behave wrong when getting
- HTTP. */
- data->set.httpreq = HTTPREQ_GET;
+ data->state.httpreq = HTTPREQ_HEAD;
k->start = Curl_now(); /* start time */
k->now = k->start; /* current time is now */
k->header = TRUE; /* assume header */
-
k->bytecount = 0;
-
- k->buf = data->state.buffer;
- k->hbufp = data->state.headerbuff;
k->ignorebody = FALSE;
Curl_speedinit(data);
-
Curl_pgrsSetUploadCounter(data, 0);
Curl_pgrsSetDownloadCounter(data, 0);
diff --git a/lib/url.h b/lib/url.h
index 5000c512a..1941dc6a4 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -47,7 +47,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn);
CURLcode Curl_open(struct Curl_easy **curl);
CURLcode Curl_init_userdefined(struct Curl_easy *data);
-void Curl_freeset(struct Curl_easy * data);
+void Curl_freeset(struct Curl_easy *data);
CURLcode Curl_uc_to_curlcode(CURLUcode uc);
CURLcode Curl_close(struct Curl_easy **datap); /* opposite of curl_open() */
CURLcode Curl_connect(struct Curl_easy *, bool *async, bool *protocol_connect);
@@ -77,6 +77,10 @@ void Curl_free_idnconverted_hostname(struct hostname *host);
void Curl_verboseconnect(struct connectdata *conn);
#endif
+#ifdef CURL_DISABLE_PROXY
+#define CONNECT_PROXY_SSL() FALSE
+#else
+
#define CONNECT_PROXY_SSL()\
(conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
!conn->bits.proxy_ssl_connected[sockindex])
@@ -88,5 +92,6 @@ void Curl_verboseconnect(struct connectdata *conn);
#define CONNECT_SECONDARYSOCKET_PROXY_SSL()\
(conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
!conn->bits.proxy_ssl_connected[SECONDARYSOCKET])
+#endif /* !CURL_DISABLE_PROXY */
#endif /* HEADER_CURL_URL_H */
diff --git a/lib/urlapi.c b/lib/urlapi.c
index 506e244dc..acbfb8287 100644
--- a/lib/urlapi.c
+++ b/lib/urlapi.c
@@ -225,7 +225,7 @@ static void strcpy_url(char *output, const char *url, bool relative)
break;
}
}
- *optr = 0; /* zero terminate output buffer */
+ *optr = 0; /* null-terminate output buffer */
}
@@ -584,7 +584,7 @@ static CURLUcode junkscan(const char *part)
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x7f,
- 0x00 /* zero terminate */
+ 0x00 /* null-terminate */
};
size_t n = strlen(part);
size_t nfine = strcspn(part, badbytes);
@@ -606,7 +606,7 @@ static CURLUcode hostname_check(struct Curl_URL *u, char *hostname)
char dest[16]; /* fits a binary IPv6 address */
#endif
const char *l = "0123456789abcdefABCDEF:.";
- if(hlen < 5) /* '[::1]' is the shortest possible valid string */
+ if(hlen < 4) /* '[::]' is the shortest possible valid string */
return CURLUE_MALFORMED_INPUT;
hostname++;
hlen -= 2;
@@ -1185,7 +1185,10 @@ CURLUcode curl_url_get(CURLU *u, CURLUPart what,
if(urldecode) {
char *decoded;
size_t dlen;
- CURLcode res = Curl_urldecode(NULL, *part, 0, &decoded, &dlen, TRUE);
+ /* this unconditional rejection of control bytes is documented
+ API behavior */
+ CURLcode res = Curl_urldecode(NULL, *part, 0, &decoded, &dlen,
+ REJECT_CTRL);
free(*part);
if(res) {
*part = NULL;
@@ -1395,7 +1398,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
i = (const unsigned char *)part;
for(o = enc; *i; ++o, ++i)
*o = (*i == ' ') ? '+' : *i;
- *o = 0; /* zero terminate */
+ *o = 0; /* null-terminate */
part = strdup(enc);
if(!part) {
free(enc);
@@ -1419,7 +1422,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what,
o += 3;
}
}
- *o = 0; /* zero terminate */
+ *o = 0; /* null-terminate */
newp = enc;
if(free_part)
free((char *)part);
diff --git a/lib/urldata.h b/lib/urldata.h
index 23e7ffe71..5c5be331e 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -81,7 +81,7 @@
*/
#define RESP_TIMEOUT (120*1000)
-/* Max string intput length is a precaution against abuse and to detect junk
+/* Max string input length is a precaution against abuse and to detect junk
input easier and better. */
#define CURL_MAX_INPUT_LENGTH 8000000
@@ -104,6 +104,7 @@
#include "hostip.h"
#include "hash.h"
#include "splay.h"
+#include "dynbuf.h"
/* return the count of bytes sent, or -1 on error */
typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
@@ -152,10 +153,6 @@ typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */
#include <libssh2_sftp.h>
#endif /* HAVE_LIBSSH2_H */
-/* Initial size of the buffer to store headers in, it'll be enlarged in case
- of need. */
-#define HEADERSIZE 256
-
#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU
#define GOOD_EASY_HANDLE(x) \
((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))
@@ -233,6 +230,7 @@ struct ssl_primary_config {
char *cipher_list; /* list of ciphers to use */
char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
char *pinned_key;
+ struct curl_blob *cert_blob;
BIT(verifypeer); /* set TRUE if this is desired */
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
BIT(verifystatus); /* set TRUE if certificate status must be checked */
@@ -244,11 +242,14 @@ struct ssl_config_data {
long certverifyresult; /* result from the certificate verification */
char *CRLfile; /* CRL to check certificate revocation */
char *issuercert;/* optional issuer certificate filename */
+ struct curl_blob *issuercert_blob;
curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */
void *fsslctxp; /* parameter for call back */
char *cert; /* client certificate file name */
+ struct curl_blob *cert_blob;
char *cert_type; /* format for certificate (default: PEM)*/
char *key; /* private key file name */
+ struct curl_blob *key_blob;
char *key_type; /* format for private key (default: PEM) */
char *key_passwd; /* plain text private key password */
#ifdef USE_TLS_SRP
@@ -263,6 +264,7 @@ struct ssl_config_data {
BIT(no_partialchain); /* don't accept partial certificate chains */
BIT(revoke_best_effort); /* ignore SSL revocation offline/missing revocation
list errors */
+ BIT(native_ca_store); /* use the native ca store of operating system */
};
struct ssl_general_config {
@@ -420,11 +422,23 @@ struct negotiatedata {
* Boolean values that concerns this connection.
*/
struct ConnectBits {
- /* always modify bits.close with the connclose() and connkeep() macros! */
- bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy
- is complete */
bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set
the first time on the first connect function call */
+#ifndef CURL_DISABLE_PROXY
+ bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy
+ is complete */
+ BIT(httpproxy); /* if set, this transfer is done through a http proxy */
+ BIT(socksproxy); /* if set, this transfer is done through a socks proxy */
+ BIT(proxy_user_passwd); /* user+password for the proxy? */
+ BIT(tunnel_proxy); /* if CONNECT is used to "tunnel" through the proxy.
+ This is implicit when SSL-protocols are used through
+ proxies, but can also be enabled explicitly by
+ apps */
+ BIT(proxy_connect_closed); /* TRUE if a proxy disconnected the connection
+ in a CONNECT request with auth, so that
+ libcurl should reconnect and continue. */
+#endif
+ /* always modify bits.close with the connclose() and connkeep() macros! */
BIT(close); /* if set, we close the connection after this request */
BIT(reuse); /* if set, this is a re-used connection */
BIT(altused); /* this is an alt-svc "redirect" */
@@ -433,10 +447,7 @@ struct ConnectBits {
BIT(conn_to_port); /* if set, this connection has a "connect to port"
that overrides the port in the URL (remote port) */
BIT(proxy); /* if set, this transfer is done through a proxy - any type */
- BIT(httpproxy); /* if set, this transfer is done through a http proxy */
- BIT(socksproxy); /* if set, this transfer is done through a socks proxy */
BIT(user_passwd); /* do we use user+password for this connection? */
- BIT(proxy_user_passwd); /* user+password for the proxy? */
BIT(ipv6_ip); /* we communicate with a remote site specified with pure IPv6
IP address */
BIT(ipv6); /* we communicate with a site using an IPv6 address */
@@ -446,10 +457,6 @@ struct ConnectBits {
the TCP layer connect */
BIT(retry); /* this connection is about to get closed and then
re-attempted at another connection. */
- BIT(tunnel_proxy); /* if CONNECT is used to "tunnel" through the proxy.
- This is implicit when SSL-protocols are used through
- proxies, but can also be enabled explicitly by
- apps */
BIT(authneg); /* TRUE when the auth phase has started, which means
that we are creating a request with an auth header,
but it is not the final request in the auth
@@ -468,18 +475,22 @@ struct ConnectBits {
BIT(ftp_use_data_ssl); /* Enabled SSL for the data connection */
#endif
BIT(netrc); /* name+password provided by netrc */
- BIT(userpwd_in_url); /* name+password found in url */
- BIT(proxy_connect_closed); /* TRUE if a proxy disconnected the connection
- in a CONNECT request with auth, so that
- libcurl should reconnect and continue. */
BIT(bound); /* set true if bind() has already been done on this socket/
connection */
- BIT(type_set); /* type= was used in the URL */
BIT(multiplex); /* connection is multiplexed */
BIT(tcp_fastopen); /* use TCP Fast Open */
BIT(tls_enable_npn); /* TLS NPN extension? */
BIT(tls_enable_alpn); /* TLS ALPN extension? */
BIT(connect_only);
+ BIT(doh);
+#ifdef USE_UNIX_SOCKETS
+ BIT(abstract_unix_socket);
+#endif
+ BIT(tls_upgraded);
+ BIT(sock_accepted); /* TRUE if the SECONDARYSOCKET was created with
+ accept() */
+ BIT(parallel_connect); /* set TRUE when a parallel connect attempt has
+ started (happy eyeballs) */
};
struct hostname {
@@ -557,18 +568,13 @@ enum doh_slots {
DOH_PROBE_SLOTS
};
-struct dohresponse {
- unsigned char *memory;
- size_t size;
-};
-
/* one of these for each DoH request */
struct dnsprobe {
CURL *easy;
int dnstype;
unsigned char dohbuffer[512];
size_t dohlen;
- struct dohresponse serverdoh;
+ struct dynbuf serverdoh;
};
struct dohdata {
@@ -612,12 +618,7 @@ struct SingleRequest {
written as body */
int headerline; /* counts header lines to better track the
first one */
- char *hbufp; /* points at *end* of header line */
- size_t hbuflen;
char *str; /* within buf */
- char *str_start; /* within buf */
- char *end_ptr; /* within buf */
- char *p; /* within headerbuff */
curl_off_t offset; /* possible resume offset read from the
Content-Range: header */
int httpcode; /* error code from the 'HTTP/1.? XXX' or
@@ -626,11 +627,10 @@ struct SingleRequest {
enum expect100 exp100; /* expect 100 continue state */
enum upgrade101 upgr101; /* 101 upgrade state */
- struct contenc_writer_s *writer_stack; /* Content unencoding stack. */
- /* See sec 3.5, RFC2616. */
+ /* Content unencoding stack. See sec 3.5, RFC2616. */
+ struct contenc_writer *writer_stack;
time_t timeofdoc;
long bodywrites;
- char *buf;
int keepon;
char *location; /* This points to an allocated version of the Location:
header data */
@@ -768,6 +768,8 @@ struct Curl_handler {
HTTP proxy as HTTP proxies may know
this protocol and act as a gateway */
#define PROTOPT_WILDCARD (1<<12) /* protocol supports wildcard matching */
+#define PROTOPT_USERPWDCTRL (1<<13) /* Allow "control bytes" (< 32 ascii) in
+ user name and password */
#define CONNCHECK_NONE 0 /* No checks */
#define CONNCHECK_ISDEAD (1<<0) /* Check if the connection is dead. */
@@ -798,15 +800,10 @@ struct proxy_info {
char *passwd; /* proxy password string, allocated */
};
-#define CONNECT_BUFFER_SIZE 16384
-
/* struct for HTTP CONNECT state data */
struct http_connect_state {
- char connect_buffer[CONNECT_BUFFER_SIZE];
- int perline; /* count bytes per line */
+ struct dynbuf rcvbuf;
int keepon;
- char *line_start;
- char *ptr; /* where to store more data */
curl_off_t cl; /* size of content to read and ignore */
enum {
TUNNEL_INIT, /* init/default/no tunnel state */
@@ -886,15 +883,15 @@ struct connectdata {
/* 'dns_entry' is the particular host we use. This points to an entry in the
DNS cache and it will not get pruned while locked. It gets unlocked in
- Curl_done(). This entry will be NULL if the connection is re-used as then
+ multi_done(). This entry will be NULL if the connection is re-used as then
there is no name resolve done. */
struct Curl_dns_entry *dns_entry;
/* 'ip_addr' is the particular IP we connected to. It points to a struct
within the DNS cache, so this pointer is only valid as long as the DNS
- cache entry remains locked. It gets unlocked in Curl_done() */
- Curl_addrinfo *ip_addr;
- Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */
+ cache entry remains locked. It gets unlocked in multi_done() */
+ struct Curl_addrinfo *ip_addr;
+ struct Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */
/* 'ip_addr_str' is the ip_addr data as a human readable string.
It remains available as long as the connection does, which is longer than
@@ -919,10 +916,10 @@ struct connectdata {
char *secondaryhostname; /* secondary socket host name (ftp) */
struct hostname conn_to_host; /* the host to connect to. valid only if
bits.conn_to_host is set */
-
+#ifndef CURL_DISABLE_PROXY
struct proxy_info socks_proxy;
struct proxy_info http_proxy;
-
+#endif
long port; /* which port to use locally */
int remote_port; /* the remote port, not the proxy port! */
int conn_to_port; /* the remote port to connect to. valid only if
@@ -970,12 +967,16 @@ struct connectdata {
struct postponed_data postponed[2]; /* two buffers for two sockets */
#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */
struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
+#ifndef CURL_DISABLE_PROXY
struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */
+#endif
#ifdef USE_SSL
void *ssl_extra; /* separately allocated backend-specific data */
#endif
struct ssl_primary_config ssl_config;
+#ifndef CURL_DISABLE_PROXY
struct ssl_primary_config proxy_ssl_config;
+#endif
struct ConnectBits bits; /* various state-flags for this connection */
/* connecttime: when connect() is called on the current IP address. Used to
@@ -984,8 +985,10 @@ struct connectdata {
struct curltime connecttime;
/* The two fields below get set in Curl_connecthost */
int num_addr; /* number of addresses to try to connect to */
- timediff_t timeoutms_per_addr; /* how long time in milliseconds to spend on
- trying to connect to each IP address */
+
+ /* how long time in milliseconds to spend on trying to connect to each IP
+ address, per family */
+ timediff_t timeoutms_per_addr[2];
const struct Curl_handler *handler; /* Connection's protocol handler */
const struct Curl_handler *given; /* The protocol first given */
@@ -1006,21 +1009,6 @@ struct connectdata {
well be the same we read from.
CURL_SOCKET_BAD disables */
- /** Dynamically allocated strings, MUST be freed before this **/
- /** struct is killed. **/
- struct dynamically_allocated_data {
- char *proxyuserpwd;
- char *uagent;
- char *accept_encoding;
- char *userpwd;
- char *rangeline;
- char *ref;
- char *host;
- char *cookiehost;
- char *rtsp_transport;
- char *te; /* TE: request header */
- } allocptr;
-
#ifdef HAVE_GSSAPI
BIT(sec_complete); /* if Kerberos is enabled for this connection */
enum protection_level command_prot;
@@ -1067,10 +1055,8 @@ struct connectdata {
/* data used for the asynch name resolve callback */
struct Curl_async async;
- /* These three are used for chunked-encoding trailer support */
- char *trailer; /* allocated buffer to store trailer in */
- int trlMax; /* allocated buffer size */
- int trlPos; /* index of where to store data */
+ /* for chunked-encoded trailer */
+ struct dynbuf trailer;
union {
struct ftp_conn ftpc;
@@ -1108,20 +1094,7 @@ struct connectdata {
int retrycount; /* number of retries on a new connection */
#ifdef USE_UNIX_SOCKETS
char *unix_domain_socket;
- BIT(abstract_unix_socket);
#endif
- BIT(tls_upgraded);
- /* the two following *_inuse fields are only flags, not counters in any way.
- If TRUE it means the channel is in use, and if FALSE it means the channel
- is up for grabs by one. */
- BIT(readchannel_inuse); /* whether the read channel is in use by an easy
- handle */
- BIT(writechannel_inuse); /* whether the write channel is in use by an easy
- handle */
- BIT(sock_accepted); /* TRUE if the SECONDARYSOCKET was created with
- accept() */
- BIT(parallel_connect); /* set TRUE when a parallel connect attempt has
- started (happy eyeballs) */
};
/* The end of connectdata. */
@@ -1243,17 +1216,6 @@ typedef enum {
RTSPREQ_LAST /* last in list */
} Curl_RtspReq;
-/*
- * Values that are generated, temporary or calculated internally for a
- * "session handle" must be defined within the 'struct UrlState'. This struct
- * will be used within the Curl_easy struct. When the 'Curl_easy'
- * struct is cloned, this data MUST NOT be copied.
- *
- * Remember that any "state" information goes globally for the curl handle.
- * Session-data MUST be put in the connectdata struct and here. */
-#define MAX_CURL_USER_LENGTH 256
-#define MAX_CURL_PASSWORD_LENGTH 256
-
struct auth {
unsigned long want; /* Bitmask set to the authentication methods wanted by
app (with CURLOPT_HTTPAUTH or CURLOPT_PROXYAUTH). */
@@ -1279,9 +1241,7 @@ struct Curl_http2_dep {
* BODY).
*/
struct tempbuf {
- char *buf; /* allocated buffer to keep data in when a write callback
- returns to make the connection paused */
- size_t len; /* size of the 'tempwrite' allocated buffer */
+ struct dynbuf b;
int type; /* type of the 'tempwrite' buffer as a bitmask that is used with
Curl_client_write() */
};
@@ -1291,7 +1251,8 @@ typedef enum {
EXPIRE_100_TIMEOUT,
EXPIRE_ASYNC_NAME,
EXPIRE_CONNECTTIMEOUT,
- EXPIRE_DNS_PER_NAME,
+ EXPIRE_DNS_PER_NAME, /* family1 */
+ EXPIRE_DNS_PER_NAME2, /* family2 */
EXPIRE_HAPPY_EYEBALLS_DNS, /* See asyn-ares.c */
EXPIRE_HAPPY_EYEBALLS,
EXPIRE_MULTI_PENDING,
@@ -1341,9 +1302,7 @@ struct UrlState {
struct curltime keeps_speed; /* for the progress meter really */
struct connectdata *lastconnect; /* The last connection, NULL if undefined */
-
- char *headerbuff; /* allocated buffer to store headers in */
- size_t headersize; /* size of the allocation */
+ struct dynbuf headerb; /* buffer to store headers in */
char *buffer; /* download buffer */
char *ulbuf; /* allocated upload buffer or NULL */
@@ -1421,13 +1380,30 @@ struct UrlState {
int stream_weight;
CURLU *uh; /* URL handle for the current parsed URL */
struct urlpieces up;
+ Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
#ifndef CURL_DISABLE_HTTP
size_t trailers_bytes_sent;
- Curl_send_buffer *trailers_buf; /* a buffer containing the compiled trailing
- headers */
+ struct dynbuf trailers_buf; /* a buffer containing the compiled trailing
+ headers */
#endif
trailers_state trailers_state; /* whether we are sending trailers
and what stage are we at */
+
+ /* Dynamically allocated strings, MUST be freed before this struct is
+ killed. */
+ struct dynamically_allocated_data {
+ char *proxyuserpwd;
+ char *uagent;
+ char *accept_encoding;
+ char *userpwd;
+ char *rangeline;
+ char *ref;
+ char *host;
+ char *cookiehost;
+ char *rtsp_transport;
+ char *te; /* TE: request header */
+ } aptr;
+
#ifdef CURLDEBUG
BIT(conncache_lock);
#endif
@@ -1590,7 +1566,7 @@ enum dupstring {
STRING_DNS_LOCAL_IP4,
STRING_DNS_LOCAL_IP6,
- /* -- end of zero-terminated strings -- */
+ /* -- end of null-terminated strings -- */
STRING_LASTZEROTERMINATED,
@@ -1602,6 +1578,16 @@ enum dupstring {
STRING_LAST /* not used, just an end-of-list marker */
};
+enum dupblob {
+ BLOB_CERT_ORIG,
+ BLOB_CERT_PROXY,
+ BLOB_KEY_ORIG,
+ BLOB_KEY_PROXY,
+ BLOB_SSL_ISSUERCERT_ORIG,
+ BLOB_SSL_ISSUERCERT_PROXY,
+ BLOB_LAST
+};
+
/* callback that gets called when this easy handle is completed within a multi
handle. Only used for internally created transfers, like for example
DoH. */
@@ -1699,11 +1685,13 @@ struct UserDefined {
the hostname and port to connect to */
curl_TimeCond timecondition; /* kind of time/date comparison */
time_t timevalue; /* what time to compare with */
- Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
+ Curl_HttpReq method; /* what kind of HTTP request (if any) is this */
long httpversion; /* when non-zero, a specific HTTP version requested to
be used in the library's request(s) */
struct ssl_config_data ssl; /* user defined SSL stuff */
+#ifndef CURL_DISABLE_PROXY
struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */
+#endif
struct ssl_general_config general_ssl; /* general user defined SSL stuff */
curl_proxytype proxytype; /* what kind of proxy that is in use */
long dns_cache_timeout; /* DNS cache timeout */
@@ -1733,6 +1721,7 @@ struct UserDefined {
long new_directory_perms; /* Permissions to use when creating remote dirs */
long ssh_auth_types; /* allowed SSH auth types */
char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */
+ struct curl_blob *blobs[BLOB_LAST];
unsigned int scope_id; /* Scope id for IPv6 */
long allowed_protocols;
long redir_protocols;
diff --git a/lib/vauth/cleartext.c b/lib/vauth/cleartext.c
index d17ceaed3..27a10e793 100644
--- a/lib/vauth/cleartext.c
+++ b/lib/vauth/cleartext.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -81,7 +81,8 @@ CURLcode Curl_auth_create_plain_message(struct Curl_easy *data,
plen = strlen(passwd);
/* Compute binary message length. Check for overflows. */
- if(((zlen + clen) > SIZE_T_MAX/4) || (plen > (SIZE_T_MAX/2 - 2)))
+ if((zlen > SIZE_T_MAX/4) || (clen > SIZE_T_MAX/4) ||
+ (plen > (SIZE_T_MAX/2 - 2)))
return CURLE_OUT_OF_MEMORY;
plainlen = zlen + clen + plen + 2;
diff --git a/lib/vauth/cram.c b/lib/vauth/cram.c
index d2a0e28b8..e7ab1366f 100644
--- a/lib/vauth/cram.c
+++ b/lib/vauth/cram.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -96,7 +96,7 @@ CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data,
{
CURLcode result = CURLE_OK;
size_t chlglen = 0;
- HMAC_context *ctxt;
+ struct HMAC_context *ctxt;
unsigned char digest[MD5_DIGEST_LEN];
char *response;
diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c
index ae4097217..9768ab617 100644
--- a/lib/vauth/digest.c
+++ b/lib/vauth/digest.c
@@ -358,7 +358,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
char **outptr, size_t *outlen)
{
size_t i;
- MD5_context *ctxt;
+ struct MD5_context *ctxt;
char *response = NULL;
unsigned char digest[MD5_DIGEST_LEN];
char HA1_hex[2 * MD5_DIGEST_LEN + 1];
diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c
index a9016928e..0792757b7 100644
--- a/lib/vauth/digest_sspi.c
+++ b/lib/vauth/digest_sspi.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2014 - 2016, Steve Holme, <steve_holme@hotmail.com>.
- * Copyright (C) 2015 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2015 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -134,7 +134,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
if(status != SEC_E_OK) {
free(input_token);
- return CURLE_NOT_BUILT_IN;
+ failf(data, "SSPI: couldn't get auth info\n");
+ return CURLE_AUTH_ERROR;
}
token_max = SecurityPackage->cbMaxToken;
@@ -288,13 +289,13 @@ CURLcode Curl_override_sspi_http_realm(const char *chlg,
if(strcasecompare(value, "realm")) {
/* Setup identity's domain and length */
- domain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *) content);
+ domain.tchar_ptr = curlx_convert_UTF8_to_tchar((char *) content);
if(!domain.tchar_ptr)
return CURLE_OUT_OF_MEMORY;
dup_domain.tchar_ptr = _tcsdup(domain.tchar_ptr);
if(!dup_domain.tchar_ptr) {
- Curl_unicodefree(domain.tchar_ptr);
+ curlx_unicodefree(domain.tchar_ptr);
return CURLE_OUT_OF_MEMORY;
}
@@ -303,7 +304,7 @@ CURLcode Curl_override_sspi_http_realm(const char *chlg,
identity->DomainLength = curlx_uztoul(_tcslen(dup_domain.tchar_ptr));
dup_domain.tchar_ptr = NULL;
- Curl_unicodefree(domain.tchar_ptr);
+ curlx_unicodefree(domain.tchar_ptr);
}
else {
/* Unknown specifier, ignore it! */
@@ -431,8 +432,10 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
/* Query the security package for DigestSSP */
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_DIGEST),
&SecurityPackage);
- if(status != SEC_E_OK)
- return CURLE_NOT_BUILT_IN;
+ if(status != SEC_E_OK) {
+ failf(data, "SSPI: couldn't get auth info\n");
+ return CURLE_AUTH_ERROR;
+ }
token_max = SecurityPackage->cbMaxToken;
@@ -580,7 +583,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
resp_buf.pvBuffer = output_token;
resp_buf.cbBuffer = curlx_uztoul(token_max);
- spn = Curl_convert_UTF8_to_tchar((char *) uripath);
+ spn = curlx_convert_UTF8_to_tchar((char *) uripath);
if(!spn) {
s_pSecFn->FreeCredentialsHandle(&credentials);
@@ -602,7 +605,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
&chlg_desc, 0,
digest->http_context,
&resp_desc, &attrs, &expiry);
- Curl_unicodefree(spn);
+ curlx_unicodefree(spn);
if(status == SEC_I_COMPLETE_NEEDED ||
status == SEC_I_COMPLETE_AND_CONTINUE)
diff --git a/lib/vauth/krb5_sspi.c b/lib/vauth/krb5_sspi.c
index 44dda135f..b2efdb43d 100644
--- a/lib/vauth/krb5_sspi.c
+++ b/lib/vauth/krb5_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2019, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2014 - 2020, Steve Holme, <steve_holme@hotmail.com>.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -125,7 +125,8 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data,
TEXT(SP_NAME_KERBEROS),
&SecurityPackage);
if(status != SEC_E_OK) {
- return CURLE_NOT_BUILT_IN;
+ failf(data, "SSPI: couldn't get auth info\n");
+ return CURLE_AUTH_ERROR;
}
krb5->token_max = SecurityPackage->cbMaxToken;
@@ -395,7 +396,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY;
/* Convert the user name to UTF8 when operating with Unicode */
- user_name = Curl_convert_tchar_to_UTF8(names.sUserName);
+ user_name = curlx_convert_tchar_to_UTF8(names.sUserName);
if(!user_name) {
free(trailer);
@@ -407,7 +408,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
message = malloc(messagelen);
if(!message) {
free(trailer);
- Curl_unicodefree(user_name);
+ curlx_unicodefree(user_name);
return CURLE_OUT_OF_MEMORY;
}
@@ -420,7 +421,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
outdata = htonl(max_size) | sec_layer;
memcpy(message, &outdata, sizeof(outdata));
strcpy((char *) message + sizeof(outdata), user_name);
- Curl_unicodefree(user_name);
+ curlx_unicodefree(user_name);
/* Allocate the padding */
padding = malloc(sizes.cbBlockSize);
diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c
index 8f9103806..3b46e1a46 100644
--- a/lib/vauth/ntlm.c
+++ b/lib/vauth/ntlm.c
@@ -600,11 +600,14 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
#endif
#if defined(USE_NTRESPONSES) && defined(USE_NTLM2SESSION)
+
+#define CURL_MD5_DIGEST_LENGTH 16 /* fixed size */
+
/* We don't support NTLM2 if we don't have USE_NTRESPONSES */
if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) {
unsigned char ntbuffer[0x18];
unsigned char tmp[0x18];
- unsigned char md5sum[MD5_DIGEST_LENGTH];
+ unsigned char md5sum[CURL_MD5_DIGEST_LENGTH];
unsigned char entropy[8];
/* Need to create 8 bytes random data */
diff --git a/lib/vauth/ntlm_sspi.c b/lib/vauth/ntlm_sspi.c
index f086e52b8..e747abb75 100644
--- a/lib/vauth/ntlm_sspi.c
+++ b/lib/vauth/ntlm_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -105,8 +105,10 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
/* Query the security package for NTLM */
status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM),
&SecurityPackage);
- if(status != SEC_E_OK)
- return CURLE_NOT_BUILT_IN;
+ if(status != SEC_E_OK) {
+ failf(data, "SSPI: couldn't get auth info\n");
+ return CURLE_AUTH_ERROR;
+ }
ntlm->token_max = SecurityPackage->cbMaxToken;
diff --git a/lib/vauth/spnego_sspi.c b/lib/vauth/spnego_sspi.c
index 82b96b8c1..97220a5ad 100644
--- a/lib/vauth/spnego_sspi.c
+++ b/lib/vauth/spnego_sspi.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -129,8 +129,10 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
nego->status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
TEXT(SP_NAME_NEGOTIATE),
&SecurityPackage);
- if(nego->status != SEC_E_OK)
- return CURLE_NOT_BUILT_IN;
+ if(nego->status != SEC_E_OK) {
+ failf(data, "SSPI: couldn't get auth info\n");
+ return CURLE_AUTH_ERROR;
+ }
nego->token_max = SecurityPackage->cbMaxToken;
diff --git a/lib/vauth/vauth.c b/lib/vauth/vauth.c
index 54b34861b..1b3ff5ada 100644
--- a/lib/vauth/vauth.c
+++ b/lib/vauth/vauth.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2014 - 2019, Steve Holme, <steve_holme@hotmail.com>.
+ * Copyright (C) 2014 - 2020, Steve Holme, <steve_holme@hotmail.com>.
*
* 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 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
}
/* Allocate our TCHAR based SPN */
- tchar_spn = Curl_convert_UTF8_to_tchar(utf8_spn);
+ tchar_spn = curlx_convert_UTF8_to_tchar(utf8_spn);
if(!tchar_spn) {
free(utf8_spn);
@@ -97,7 +97,7 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
}
/* Release the UTF8 variant when operating with Unicode */
- Curl_unicodefree(utf8_spn);
+ curlx_unicodefree(utf8_spn);
/* Return our newly allocated SPN */
return tchar_spn;
diff --git a/lib/vquic/ngtcp2.c b/lib/vquic/ngtcp2.c
index 5f7b6e2e0..d29cb378d 100644
--- a/lib/vquic/ngtcp2.c
+++ b/lib/vquic/ngtcp2.c
@@ -38,6 +38,9 @@
#include "strcase.h"
#include "connect.h"
#include "strerror.h"
+#include "dynbuf.h"
+#include "vquic.h"
+#include "vtls/keylog.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -147,21 +150,24 @@ quic_from_gtls_level(gnutls_record_encryption_level_t gtls_level)
}
#endif
-static int setup_initial_crypto_context(struct quicsocket *qs)
+static void qlog_callback(void *user_data, const void *data, size_t datalen)
{
- const ngtcp2_cid *dcid = ngtcp2_conn_get_dcid(qs->qconn);
-
- if(ngtcp2_crypto_derive_and_install_initial_key(
- qs->qconn, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- dcid) != 0)
- return -1;
+ struct quicsocket *qs = (struct quicsocket *)user_data;
+ if(qs->qlogfd != -1) {
+ ssize_t rc = write(qs->qlogfd, data, datalen);
+ if(rc == -1) {
+ /* on write error, stop further write attempts */
+ close(qs->qlogfd);
+ qs->qlogfd = -1;
+ }
+ }
- return 0;
}
-static void quic_settings(ngtcp2_settings *s,
+static void quic_settings(struct quicsocket *qs,
uint64_t stream_buffer_size)
{
+ ngtcp2_settings *s = &qs->settings;
ngtcp2_settings_default(s);
#ifdef DEBUG_NGTCP2
s->log_printf = quic_printf;
@@ -176,16 +182,16 @@ static void quic_settings(ngtcp2_settings *s,
s->transport_params.initial_max_streams_bidi = 1;
s->transport_params.initial_max_streams_uni = 3;
s->transport_params.max_idle_timeout = QUIC_IDLE_TIMEOUT;
+ if(qs->qlogfd != -1) {
+ s->qlog.write = qlog_callback;
+ }
}
-static FILE *keylog_file; /* not thread-safe */
#ifdef USE_OPENSSL
static void keylog_callback(const SSL *ssl, const char *line)
{
(void)ssl;
- fputs(line, keylog_file);
- fputc('\n', keylog_file);
- fflush(keylog_file);
+ Curl_tls_keylog_write_line(line);
}
#elif defined(USE_GNUTLS)
static int keylog_callback(gnutls_session_t session, const char *label,
@@ -193,36 +199,14 @@ static int keylog_callback(gnutls_session_t session, const char *label,
{
gnutls_datum_t crandom;
gnutls_datum_t srandom;
- gnutls_datum_t crandom_hex = { NULL, 0 };
- gnutls_datum_t secret_hex = { NULL, 0 };
- int rc = 0;
gnutls_session_get_random(session, &crandom, &srandom);
if(crandom.size != 32) {
return -1;
}
- rc = gnutls_hex_encode2(&crandom, &crandom_hex);
- if(rc < 0) {
- fprintf(stderr, "gnutls_hex_encode2 failed: %s\n",
- gnutls_strerror(rc));
- goto out;
- }
-
- rc = gnutls_hex_encode2(secret, &secret_hex);
- if(rc < 0) {
- fprintf(stderr, "gnutls_hex_encode2 failed: %s\n",
- gnutls_strerror(rc));
- goto out;
- }
-
- fprintf(keylog_file, "%s %s %s\n", label, crandom_hex.data, secret_hex.data);
- fflush(keylog_file);
-
- out:
- gnutls_free(crandom_hex.data);
- gnutls_free(secret_hex.data);
- return rc;
+ Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
+ return 0;
}
#endif
@@ -271,13 +255,12 @@ static int quic_set_encryption_secrets(SSL *ssl,
struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl);
int level = quic_from_ossl_level(ossl_level);
- if(level != NGTCP2_CRYPTO_LEVEL_EARLY &&
- ngtcp2_crypto_derive_and_install_rx_key(
- qs->qconn, ssl, NULL, NULL, NULL, level, rx_secret, secretlen) != 0)
+ if(ngtcp2_crypto_derive_and_install_rx_key(
+ qs->qconn, NULL, NULL, NULL, level, rx_secret, secretlen) != 0)
return 0;
if(ngtcp2_crypto_derive_and_install_tx_key(
- qs->qconn, ssl, NULL, NULL, NULL, level, tx_secret, secretlen) != 0)
+ qs->qconn, NULL, NULL, NULL, level, tx_secret, secretlen) != 0)
return 0;
if(level == NGTCP2_CRYPTO_LEVEL_APP) {
@@ -320,7 +303,6 @@ static SSL_QUIC_METHOD quic_method = {quic_set_encryption_secrets,
static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
{
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
- const char *keylog_filename;
SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION);
@@ -341,12 +323,10 @@ static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
SSL_CTX_set_quic_method(ssl_ctx, &quic_method);
- keylog_filename = getenv("SSLKEYLOGFILE");
- if(keylog_filename) {
- keylog_file = fopen(keylog_filename, "wb");
- if(keylog_file) {
- SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
- }
+ /* Open the file if a TLS or QUIC backend has not done this before. */
+ Curl_tls_keylog_open();
+ if(Curl_tls_keylog_enabled()) {
+ SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
}
return ssl_ctx;
@@ -361,9 +341,7 @@ static int quic_init_ssl(struct quicsocket *qs)
/* this will need some attention when HTTPS proxy over QUIC get fixed */
const char * const hostname = qs->conn->host.name;
- if(qs->ssl)
- SSL_free(qs->ssl);
-
+ DEBUGASSERT(!qs->ssl);
qs->ssl = SSL_new(qs->sslctx);
SSL_set_app_data(qs->ssl, qs);
@@ -372,8 +350,8 @@ static int quic_init_ssl(struct quicsocket *qs)
switch(qs->version) {
#ifdef NGTCP2_PROTO_VER
case NGTCP2_PROTO_VER:
- alpn = (const uint8_t *)NGTCP2_ALPN_H3;
- alpnlen = sizeof(NGTCP2_ALPN_H3) - 1;
+ alpn = (const uint8_t *)NGHTTP3_ALPN_H3;
+ alpnlen = sizeof(NGHTTP3_ALPN_H3) - 1;
break;
#endif
}
@@ -395,11 +373,11 @@ static int secret_func(gnutls_session_t ssl,
if(level != NGTCP2_CRYPTO_LEVEL_EARLY &&
ngtcp2_crypto_derive_and_install_rx_key(
- qs->qconn, ssl, NULL, NULL, NULL, level, rx_secret, secretlen) != 0)
+ qs->qconn, NULL, NULL, NULL, level, rx_secret, secretlen) != 0)
return 0;
if(ngtcp2_crypto_derive_and_install_tx_key(
- qs->qconn, ssl, NULL, NULL, NULL, level, tx_secret, secretlen) != 0)
+ qs->qconn, NULL, NULL, NULL, level, tx_secret, secretlen) != 0)
return 0;
if(level == NGTCP2_CRYPTO_LEVEL_APP) {
@@ -449,8 +427,8 @@ static int tp_recv_func(gnutls_session_t ssl, const uint8_t *data,
ngtcp2_transport_params params;
if(ngtcp2_decode_transport_params(
- &params, NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS,
- data, data_size) != 0)
+ &params, NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS,
+ data, data_size) != 0)
return -1;
if(ngtcp2_conn_set_remote_transport_params(qs->qconn, &params) != 0)
@@ -472,8 +450,8 @@ static int tp_send_func(gnutls_session_t ssl, gnutls_buffer_t extdata)
paramsbuf, sizeof(paramsbuf), NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO,
&params);
if(nwrite < 0) {
- fprintf(stderr, "ngtcp2_encode_transport_params: %s\n",
- ngtcp2_strerror((int)nwrite));
+ H3BUGF(fprintf(stderr, "ngtcp2_encode_transport_params: %s\n",
+ ngtcp2_strerror((int)nwrite)));
return -1;
}
@@ -489,19 +467,17 @@ static int quic_init_ssl(struct quicsocket *qs)
gnutls_datum_t alpn = {NULL, 0};
/* this will need some attention when HTTPS proxy over QUIC get fixed */
const char * const hostname = qs->conn->host.name;
- const char *keylog_filename;
int rc;
- if(qs->ssl)
- gnutls_deinit(qs->ssl);
+ DEBUGASSERT(!qs->ssl);
gnutls_init(&qs->ssl, GNUTLS_CLIENT);
gnutls_session_set_ptr(qs->ssl, qs);
rc = gnutls_priority_set_direct(qs->ssl, QUIC_PRIORITY, NULL);
if(rc < 0) {
- fprintf(stderr, "gnutls_priority_set_direct failed: %s\n",
- gnutls_strerror(rc));
+ H3BUGF(fprintf(stderr, "gnutls_priority_set_direct failed: %s\n",
+ gnutls_strerror(rc)));
return 1;
}
@@ -517,17 +493,15 @@ static int quic_init_ssl(struct quicsocket *qs)
GNUTLS_EXT_FLAG_CLIENT_HELLO |
GNUTLS_EXT_FLAG_EE);
if(rc < 0) {
- fprintf(stderr, "gnutls_session_ext_register failed: %s\n",
- gnutls_strerror(rc));
+ H3BUGF(fprintf(stderr, "gnutls_session_ext_register failed: %s\n",
+ gnutls_strerror(rc)));
return 1;
}
- keylog_filename = getenv("SSLKEYLOGFILE");
- if(keylog_filename) {
- keylog_file = fopen(keylog_filename, "wb");
- if(keylog_file) {
- gnutls_session_set_keylog_function(qs->ssl, keylog_callback);
- }
+ /* Open the file if a TLS or QUIC backend has not done this before. */
+ Curl_tls_keylog_open();
+ if(Curl_tls_keylog_enabled()) {
+ gnutls_session_set_keylog_function(qs->ssl, keylog_callback);
}
if(qs->cred)
@@ -535,31 +509,33 @@ static int quic_init_ssl(struct quicsocket *qs)
rc = gnutls_certificate_allocate_credentials(&qs->cred);
if(rc < 0) {
- fprintf(stderr, "gnutls_certificate_allocate_credentials failed: %s\n",
- gnutls_strerror(rc));
+ H3BUGF(fprintf(stderr,
+ "gnutls_certificate_allocate_credentials failed: %s\n",
+ gnutls_strerror(rc)));
return 1;
}
rc = gnutls_certificate_set_x509_system_trust(qs->cred);
if(rc < 0) {
- fprintf(stderr, "gnutls_certificate_set_x509_system_trust failed: %s\n",
- gnutls_strerror(rc));
+ H3BUGF(fprintf(stderr,
+ "gnutls_certificate_set_x509_system_trust failed: %s\n",
+ gnutls_strerror(rc)));
return 1;
}
rc = gnutls_credentials_set(qs->ssl, GNUTLS_CRD_CERTIFICATE, qs->cred);
if(rc < 0) {
- fprintf(stderr, "gnutls_credentials_set failed: %s\n",
- gnutls_strerror(rc));
+ H3BUGF(fprintf(stderr, "gnutls_credentials_set failed: %s\n",
+ gnutls_strerror(rc)));
return 1;
}
switch(qs->version) {
#ifdef NGTCP2_PROTO_VER
case NGTCP2_PROTO_VER:
- /* strip the first byte from NGTCP2_ALPN_H3 */
- alpn.data = (unsigned char *)NGTCP2_ALPN_H3 + 1;
- alpn.size = sizeof(NGTCP2_ALPN_H3) - 2;
+ /* strip the first byte (the length) from NGHTTP3_ALPN_H3 */
+ alpn.data = (unsigned char *)NGHTTP3_ALPN_H3 + 1;
+ alpn.size = sizeof(NGHTTP3_ALPN_H3) - 2;
break;
#endif
}
@@ -572,27 +548,16 @@ static int quic_init_ssl(struct quicsocket *qs)
}
#endif
-static int cb_initial(ngtcp2_conn *quic, void *user_data)
-{
- struct quicsocket *qs = (struct quicsocket *)user_data;
-
- if(ngtcp2_crypto_read_write_crypto_data(
- quic, qs->ssl, NGTCP2_CRYPTO_LEVEL_INITIAL, NULL, 0) != 0)
- return NGTCP2_ERR_CALLBACK_FAILURE;
-
- return 0;
-}
-
static int
cb_recv_crypto_data(ngtcp2_conn *tconn, ngtcp2_crypto_level crypto_level,
uint64_t offset,
const uint8_t *data, size_t datalen,
void *user_data)
{
- struct quicsocket *qs = (struct quicsocket *)user_data;
(void)offset;
+ (void)user_data;
- if(ngtcp2_crypto_read_write_crypto_data(tconn, qs->ssl, crypto_level, data,
+ if(ngtcp2_crypto_read_write_crypto_data(tconn, crypto_level, data,
datalen) != 0)
return NGTCP2_ERR_CRYPTO;
@@ -618,13 +583,14 @@ static void extend_stream_window(ngtcp2_conn *tconn,
}
-static int cb_recv_stream_data(ngtcp2_conn *tconn, int64_t stream_id,
- int fin, uint64_t offset,
+static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
+ int64_t stream_id, uint64_t offset,
const uint8_t *buf, size_t buflen,
void *user_data, void *stream_user_data)
{
struct quicsocket *qs = (struct quicsocket *)user_data;
ssize_t nconsumed;
+ int fin = flags & NGTCP2_STREAM_DATA_FLAG_FIN ? 1 : 0;
(void)offset;
(void)stream_user_data;
@@ -710,20 +676,6 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
return 0;
}
-static int cb_recv_retry(ngtcp2_conn *tconn, const ngtcp2_pkt_hd *hd,
- const ngtcp2_pkt_retry *retry, void *user_data)
-{
- /* Re-generate handshake secrets here because connection ID might change. */
- struct quicsocket *qs = (struct quicsocket *)user_data;
- (void)tconn;
- (void)hd;
- (void)retry;
-
- setup_initial_crypto_context(qs);
-
- return 0;
-}
-
static int cb_extend_max_local_streams_bidi(ngtcp2_conn *tconn,
uint64_t max_streams,
void *user_data)
@@ -776,7 +728,7 @@ static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid,
}
static ngtcp2_conn_callbacks ng_callbacks = {
- cb_initial,
+ ngtcp2_crypto_client_initial_cb,
NULL, /* recv_client_initial */
cb_recv_crypto_data,
cb_handshake_completed,
@@ -790,7 +742,7 @@ static ngtcp2_conn_callbacks ng_callbacks = {
NULL, /* stream_open */
cb_stream_close,
NULL, /* recv_stateless_reset */
- cb_recv_retry,
+ ngtcp2_crypto_recv_retry_cb,
cb_extend_max_local_streams_bidi,
NULL, /* extend_max_local_streams_uni */
NULL, /* rand */
@@ -804,7 +756,10 @@ static ngtcp2_conn_callbacks ng_callbacks = {
NULL, /* extend_max_remote_streams_uni */
cb_extend_max_stream_data,
NULL, /* dcid_status */
- NULL /* handshake_confirmed */
+ NULL, /* handshake_confirmed */
+ NULL, /* recv_new_token */
+ ngtcp2_crypto_delete_crypto_aead_ctx_cb,
+ ngtcp2_crypto_delete_crypto_cipher_ctx_cb
};
/*
@@ -824,12 +779,10 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
struct quicsocket *qs = &conn->hequic[sockindex];
char ipbuf[40];
long port;
-#ifdef USE_OPENSSL
- uint8_t paramsbuf[64];
- ngtcp2_transport_params params;
- ssize_t nwrite;
-#endif
+ int qfd;
+ if(qs->conn)
+ Curl_quic_disconnect(conn, sockindex);
qs->conn = conn;
/* extract the used address as a string */
@@ -863,7 +816,9 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
if(result)
return result;
- quic_settings(&qs->settings, data->set.buffer_size);
+ (void)Curl_qlogdir(data, qs->scid.data, NGTCP2_MAX_CIDLEN, &qfd);
+ qs->qlogfd = qfd; /* -1 if failure above */
+ quic_settings(qs, data->set.buffer_size);
qs->local_addrlen = sizeof(qs->local_addr);
rv = getsockname(sockfd, (struct sockaddr *)&qs->local_addr,
@@ -885,24 +840,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
if(rc)
return CURLE_QUIC_CONNECT_ERROR;
-#ifdef USE_OPENSSL
- ngtcp2_conn_get_local_transport_params(qs->qconn, &params);
- nwrite = ngtcp2_encode_transport_params(
- paramsbuf, sizeof(paramsbuf), NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO,
- &params);
- if(nwrite < 0) {
- failf(data, "ngtcp2_encode_transport_params: %s\n",
- ngtcp2_strerror((int)nwrite));
- return CURLE_QUIC_CONNECT_ERROR;
- }
-
- if(!SSL_set_quic_transport_params(qs->ssl, paramsbuf, nwrite))
- return CURLE_QUIC_CONNECT_ERROR;
-#endif
-
- rc = setup_initial_crypto_context(qs);
- if(rc)
- return CURLE_QUIC_CONNECT_ERROR;
+ ngtcp2_conn_set_tls_native_handle(qs->qconn, qs->ssl);
return CURLE_OK;
}
@@ -943,29 +881,49 @@ static int ng_perform_getsock(const struct connectdata *conn,
return ng_getsock((struct connectdata *)conn, socks);
}
-static CURLcode ng_disconnect(struct connectdata *conn,
- bool dead_connection)
+static void qs_disconnect(struct quicsocket *qs)
{
int i;
- struct quicsocket *qs = &conn->hequic[0];
- (void)dead_connection;
+ if(!qs->conn) /* already closed */
+ return;
+ qs->conn = NULL;
+ if(qs->qlogfd != -1) {
+ close(qs->qlogfd);
+ qs->qlogfd = -1;
+ }
if(qs->ssl)
#ifdef USE_OPENSSL
SSL_free(qs->ssl);
#elif defined(USE_GNUTLS)
gnutls_deinit(qs->ssl);
#endif
+ qs->ssl = NULL;
#ifdef USE_GNUTLS
if(qs->cred)
gnutls_certificate_free_credentials(qs->cred);
#endif
for(i = 0; i < 3; i++)
- free(qs->crypto_data[i].buf);
+ Curl_safefree(qs->crypto_data[i].buf);
nghttp3_conn_del(qs->h3conn);
ngtcp2_conn_del(qs->qconn);
#ifdef USE_OPENSSL
SSL_CTX_free(qs->sslctx);
#endif
+}
+
+void Curl_quic_disconnect(struct connectdata *conn,
+ int tempindex)
+{
+ if(conn->transport == TRNSPRT_QUIC)
+ qs_disconnect(&conn->hequic[tempindex]);
+}
+
+static CURLcode ng_disconnect(struct connectdata *conn,
+ bool dead_connection)
+{
+ (void)dead_connection;
+ Curl_quic_disconnect(conn, 0);
+ Curl_quic_disconnect(conn, 1);
return CURLE_OK;
}
@@ -1018,57 +976,12 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
return 0;
}
-/* Minimum size of the overflow buffer */
-#define OVERFLOWSIZE 1024
-
-/*
- * allocate_overflow() ensures that there is room for incoming data in the
- * overflow buffer, growing it to accommodate the new data if necessary. We
- * may need to use the overflow buffer because we can't precisely limit the
- * amount of HTTP/3 header data we receive using QUIC flow control mechanisms.
- */
-static CURLcode allocate_overflow(struct Curl_easy *data,
- struct HTTP *stream,
- size_t length)
-{
- size_t maxleft;
- size_t newsize;
- /* length can be arbitrarily large, so take care not to overflow newsize */
- maxleft = CURL_MAX_READ_SIZE - stream->overflow_buflen;
- if(length > maxleft) {
- /* The reason to have a max limit for this is to avoid the risk of a bad
- server feeding libcurl with a highly compressed list of headers that
- will cause our overflow buffer to grow too large */
- failf(data, "Rejected %zu bytes of overflow data (max is %d)!",
- stream->overflow_buflen + length, CURL_MAX_READ_SIZE);
- return CURLE_OUT_OF_MEMORY;
- }
- newsize = stream->overflow_buflen + length;
- if(newsize > stream->overflow_bufsize) {
- /* We enlarge the overflow buffer as it is too small */
- char *newbuff;
- newsize = CURLMAX(newsize * 3 / 2, stream->overflow_bufsize*2);
- newsize = CURLMIN(CURLMAX(OVERFLOWSIZE, newsize), CURL_MAX_READ_SIZE);
- newbuff = realloc(stream->overflow_buf, newsize);
- if(!newbuff) {
- failf(data, "Failed to alloc memory for overflow buffer!");
- return CURLE_OUT_OF_MEMORY;
- }
- stream->overflow_buf = newbuff;
- stream->overflow_bufsize = newsize;
- infof(data, "Grew HTTP/3 overflow buffer to %zu bytes\n", newsize);
- }
- return CURLE_OK;
-}
-
/*
* write_data() copies data to the stream's receive buffer. If not enough
* space is available in the receive buffer, it copies the rest to the
* stream's overflow buffer.
*/
-static CURLcode write_data(struct Curl_easy *data,
- struct HTTP *stream,
- const void *mem, size_t memlen)
+static CURLcode write_data(struct HTTP *stream, const void *mem, size_t memlen)
{
CURLcode result = CURLE_OK;
const char *buf = mem;
@@ -1076,10 +989,6 @@ static CURLcode write_data(struct Curl_easy *data,
/* copy as much as possible to the receive buffer */
if(stream->len) {
size_t len = CURLMIN(ncopy, stream->len);
-#if 0 /* extra debugging of incoming h3 data */
- fprintf(stderr, "!! Copies %zd bytes to %p (total %zd)\n",
- len, stream->mem, stream->memlen);
-#endif
memcpy(stream->mem, buf, len);
stream->len -= len;
stream->memlen += len;
@@ -1088,26 +997,8 @@ static CURLcode write_data(struct Curl_easy *data,
ncopy -= len;
}
/* copy the rest to the overflow buffer */
- if(ncopy) {
- result = allocate_overflow(data, stream, ncopy);
- if(result) {
- return result;
- }
-#if 0 /* extra debugging of incoming h3 data */
- fprintf(stderr, "!! Copies %zd overflow bytes to %p (total %zd)\n",
- ncopy, stream->overflow_buf, stream->overflow_buflen);
-#endif
- memcpy(stream->overflow_buf + stream->overflow_buflen, buf, ncopy);
- stream->overflow_buflen += ncopy;
- }
-#if 0 /* extra debugging of incoming h3 data */
- {
- size_t i;
- for(i = 0; i < memlen; i++) {
- fprintf(stderr, "!! data[%d]: %02x '%c'\n", i, buf[i], buf[i]);
- }
- }
-#endif
+ if(ncopy)
+ result = Curl_dyn_addn(&stream->overflow, buf, ncopy);
return result;
}
@@ -1120,7 +1011,7 @@ static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream_id,
CURLcode result = CURLE_OK;
(void)conn;
- result = write_data(data, stream, buf, buflen);
+ result = write_data(stream, buf, buflen);
if(result) {
return -1;
}
@@ -1183,7 +1074,7 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
/* add a CRLF only if we've received some headers */
if(stream->firstheader) {
- result = write_data(data, stream, "\r\n", 2);
+ result = write_data(stream, "\r\n", 2);
if(result) {
return -1;
}
@@ -1214,26 +1105,26 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
int status = decode_status_code(h3val.base, h3val.len);
DEBUGASSERT(status != -1);
ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n", status);
- result = write_data(data, stream, line, ncopy);
+ result = write_data(stream, line, ncopy);
if(result) {
return -1;
}
}
else {
/* store as a HTTP1-style header */
- result = write_data(data, stream, h3name.base, h3name.len);
+ result = write_data(stream, h3name.base, h3name.len);
if(result) {
return -1;
}
- result = write_data(data, stream, ": ", 2);
+ result = write_data(stream, ": ", 2);
if(result) {
return -1;
}
- result = write_data(data, stream, h3val.base, h3val.len);
+ result = write_data(stream, h3val.base, h3val.len);
if(result) {
return -1;
}
- result = write_data(data, stream, "\r\n", 2);
+ result = write_data(stream, "\r\n", 2);
if(result) {
return -1;
}
@@ -1341,15 +1232,16 @@ static Curl_send ngh3_stream_send;
static size_t drain_overflow_buffer(struct HTTP *stream)
{
- size_t ncopy = CURLMIN(stream->overflow_buflen, stream->len);
+ size_t overlen = Curl_dyn_len(&stream->overflow);
+ size_t ncopy = CURLMIN(overlen, stream->len);
if(ncopy > 0) {
- memcpy(stream->mem, stream->overflow_buf, ncopy);
+ memcpy(stream->mem, Curl_dyn_ptr(&stream->overflow), ncopy);
stream->len -= ncopy;
stream->mem += ncopy;
stream->memlen += ncopy;
- stream->overflow_buflen -= ncopy;
- memmove(stream->overflow_buf, stream->overflow_buf + ncopy,
- stream->overflow_buflen);
+ if(ncopy != overlen)
+ /* make the buffer only keep the tail */
+ (void)Curl_dyn_tail(&stream->overflow, overlen - ncopy);
}
return ncopy;
}
@@ -1528,6 +1420,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
stream->stream3_id = stream3_id;
stream->h3req = TRUE; /* senf off! */
+ Curl_dyn_init(&stream->overflow, CURL_MAX_READ_SIZE);
/* Calculate number of headers contained in [mem, mem + len). Assumes a
correctly generated HTTP header field block. */
@@ -1684,7 +1577,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
}
}
- switch(data->set.httpreq) {
+ switch(data->state.httpreq) {
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
case HTTPREQ_POST_MIME:
@@ -1806,11 +1699,11 @@ CURLcode Curl_quic_is_connected(struct connectdata *conn,
result = ng_process_ingress(conn, sockfd, qs);
if(result)
- return result;
+ goto error;
result = ng_flush_egress(conn, sockfd, qs);
if(result)
- return result;
+ goto error;
if(ngtcp2_conn_get_handshake_completed(qs->qconn)) {
*done = TRUE;
@@ -1818,6 +1711,10 @@ CURLcode Curl_quic_is_connected(struct connectdata *conn,
}
return result;
+ error:
+ (void)qs_disconnect(qs);
+ return result;
+
}
static CURLcode ng_process_ingress(struct connectdata *conn, int sockfd,
@@ -1914,11 +1811,12 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
return CURLE_SEND_ERROR;
}
else if(veccnt > 0) {
+ uint32_t flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
+ (fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
outlen =
ngtcp2_conn_writev_stream(qs->qconn, &ps.path,
out, pktlen, &ndatalen,
- NGTCP2_WRITE_STREAM_FLAG_MORE,
- stream_id, fin,
+ flags, stream_id,
(const ngtcp2_vec *)vec, veccnt, ts);
if(outlen == 0) {
break;
@@ -1926,6 +1824,7 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
if(outlen < 0) {
if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED ||
outlen == NGTCP2_ERR_STREAM_SHUT_WR) {
+ assert(ndatalen == -1);
rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
if(rv != 0) {
failf(conn->data,
@@ -1948,19 +1847,14 @@ static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
continue;
}
else {
+ assert(ndatalen == -1);
failf(conn->data, "ngtcp2_conn_writev_stream returned error: %s\n",
ngtcp2_strerror((int)outlen));
return CURLE_SEND_ERROR;
}
}
- else if(ndatalen >= 0) {
- rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
- if(rv != 0) {
- failf(conn->data,
- "nghttp3_conn_add_write_offset returned error: %s\n",
- nghttp3_strerror(rv));
- return CURLE_SEND_ERROR;
- }
+ else {
+ assert(ndatalen == -1);
}
}
}
@@ -2032,7 +1926,7 @@ void Curl_quic_done(struct Curl_easy *data, bool premature)
if(data->conn->handler == &Curl_handler_http3) {
/* only for HTTP/3 transfers */
struct HTTP *stream = data->req.protop;
- Curl_safefree(stream->overflow_buf);
+ Curl_dyn_free(&stream->overflow);
}
}
@@ -2047,7 +1941,7 @@ bool Curl_quic_data_pending(const struct Curl_easy *data)
there's no more data coming on the socket, we need to keep reading
until the overflow buffer is empty. */
const struct HTTP *stream = data->req.protop;
- return stream->overflow_buflen > 0;
+ return Curl_dyn_len(&stream->overflow) > 0;
}
#endif
diff --git a/lib/vquic/ngtcp2.h b/lib/vquic/ngtcp2.h
index 06337f6f9..e2f8b5600 100644
--- a/lib/vquic/ngtcp2.h
+++ b/lib/vquic/ngtcp2.h
@@ -63,6 +63,7 @@ struct quicsocket {
nghttp3_conn *h3conn;
nghttp3_conn_settings h3settings;
+ int qlogfd;
};
#include "urldata.h"
diff --git a/lib/vquic/quiche.c b/lib/vquic/quiche.c
index c40e5e937..be6f15c19 100644
--- a/lib/vquic/quiche.c
+++ b/lib/vquic/quiche.c
@@ -34,6 +34,7 @@
#include "multiif.h"
#include "connect.h"
#include "strerror.h"
+#include "vquic.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
@@ -64,7 +65,6 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
static Curl_recv h3_stream_recv;
static Curl_send h3_stream_send;
-
static int quiche_getsock(struct connectdata *conn, curl_socket_t *socks)
{
struct SingleRequest *k = &conn->data->req;
@@ -89,16 +89,30 @@ static int quiche_perform_getsock(const struct connectdata *conn,
return quiche_getsock((struct connectdata *)conn, socks);
}
+static CURLcode qs_disconnect(struct quicsocket *qs)
+{
+ if(qs->h3config)
+ quiche_h3_config_free(qs->h3config);
+ if(qs->h3c)
+ quiche_h3_conn_free(qs->h3c);
+ quiche_config_free(qs->cfg);
+ quiche_conn_free(qs->conn);
+ return CURLE_OK;
+}
+
static CURLcode quiche_disconnect(struct connectdata *conn,
bool dead_connection)
{
struct quicsocket *qs = conn->quic;
(void)dead_connection;
- quiche_h3_config_free(qs->h3config);
- quiche_h3_conn_free(qs->h3c);
- quiche_config_free(qs->cfg);
- quiche_conn_free(qs->conn);
- return CURLE_OK;
+ return qs_disconnect(qs);
+}
+
+void Curl_quic_disconnect(struct connectdata *conn,
+ int tempindex)
+{
+ if(conn->transport == TRNSPRT_QUIC)
+ qs_disconnect(&conn->hequic[tempindex]);
}
static unsigned int quiche_conncheck(struct connectdata *conn,
@@ -152,6 +166,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
CURLcode result;
struct quicsocket *qs = &conn->hequic[sockindex];
struct Curl_easy *data = conn->data;
+ char *keylog_file = NULL;
#ifdef DEBUG_QUICHE
/* initialize debug log callback only once */
@@ -189,7 +204,9 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
if(result)
return result;
- if(getenv("SSLKEYLOGFILE"))
+ keylog_file = getenv("SSLKEYLOGFILE");
+
+ if(keylog_file)
quiche_config_log_keys(qs->cfg);
qs->conn = quiche_connect(conn->host.name, (const uint8_t *) qs->scid,
@@ -199,6 +216,20 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
return CURLE_OUT_OF_MEMORY;
}
+ if(keylog_file)
+ quiche_conn_set_keylog_path(qs->conn, keylog_file);
+
+ /* Known to not work on Windows */
+#if !defined(WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD)
+ {
+ int qfd;
+ (void)Curl_qlogdir(data, qs->scid, sizeof(qs->scid), &qfd);
+ if(qfd != -1)
+ quiche_conn_set_qlog_fd(qs->conn, qfd,
+ "qlog title", "curl qlog");
+ }
+#endif
+
result = flush_egress(conn, sockfd, qs);
if(result)
return result;
@@ -217,8 +248,20 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
/* for connection reuse purposes: */
conn->ssl[FIRSTSOCKET].state = ssl_connection_complete;
- infof(data, "Sent QUIC client Initial, ALPN: %s\n",
- QUICHE_H3_APPLICATION_PROTOCOL + 1);
+ {
+ unsigned char alpn_protocols[] = QUICHE_H3_APPLICATION_PROTOCOL;
+ unsigned alpn_len, offset = 0;
+
+ /* Replace each ALPN length prefix by a comma. */
+ while(offset < sizeof(alpn_protocols) - 1) {
+ alpn_len = alpn_protocols[offset];
+ alpn_protocols[offset] = ',';
+ offset += 1 + alpn_len;
+ }
+
+ infof(data, "Sent QUIC client Initial, ALPN: %s\n",
+ alpn_protocols + 1);
+ }
return CURLE_OK;
}
@@ -273,11 +316,11 @@ CURLcode Curl_quic_is_connected(struct connectdata *conn, int sockindex,
result = process_ingress(conn, sockfd, qs);
if(result)
- return result;
+ goto error;
result = flush_egress(conn, sockfd, qs);
if(result)
- return result;
+ goto error;
if(quiche_conn_is_established(qs->conn)) {
*done = TRUE;
@@ -286,6 +329,9 @@ CURLcode Curl_quic_is_connected(struct connectdata *conn, int sockindex,
}
return result;
+ error:
+ qs_disconnect(qs);
+ return result;
}
static CURLcode process_ingress(struct connectdata *conn, int sockfd,
@@ -714,7 +760,7 @@ static CURLcode http_request(struct connectdata *conn, const void *mem,
}
}
- switch(data->set.httpreq) {
+ switch(data->state.httpreq) {
case HTTPREQ_POST:
case HTTPREQ_POST_FORM:
case HTTPREQ_POST_MIME:
diff --git a/lib/vquic/vquic.c b/lib/vquic/vquic.c
new file mode 100644
index 000000000..aae8e0951
--- /dev/null
+++ b/lib/vquic/vquic.c
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef ENABLE_QUIC
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include "urldata.h"
+#include "dynbuf.h"
+#include "curl_printf.h"
+#include "vquic.h"
+
+#ifdef O_BINARY
+#define QLOGMODE O_WRONLY|O_CREAT|O_BINARY
+#else
+#define QLOGMODE O_WRONLY|O_CREAT
+#endif
+
+/*
+ * If the QLOGDIR environment variable is set, open and return a file
+ * descriptor to write the log to.
+ *
+ * This function returns error if something failed outside of failing to
+ * create the file. Open file success is deemed by seeing if the returned fd
+ * is != -1.
+ */
+CURLcode Curl_qlogdir(struct Curl_easy *data,
+ unsigned char *scid,
+ size_t scidlen,
+ int *qlogfdp)
+{
+ const char *qlog_dir = getenv("QLOGDIR");
+ *qlogfdp = -1;
+ if(qlog_dir) {
+ struct dynbuf fname;
+ CURLcode result;
+ unsigned int i;
+ Curl_dyn_init(&fname, DYN_QLOG_NAME);
+ result = Curl_dyn_add(&fname, qlog_dir);
+ if(!result)
+ result = Curl_dyn_add(&fname, "/");
+ for(i = 0; (i < scidlen) && !result; i++) {
+ char hex[3];
+ msnprintf(hex, 3, "%02x", scid[i]);
+ result = Curl_dyn_add(&fname, hex);
+ }
+ if(!result)
+ result = Curl_dyn_add(&fname, ".qlog");
+
+ if(!result) {
+ int qlogfd = open(Curl_dyn_ptr(&fname), QLOGMODE,
+ data->set.new_file_perms);
+ if(qlogfd != -1)
+ *qlogfdp = qlogfd;
+ }
+ Curl_dyn_free(&fname);
+ if(result)
+ return result;
+ }
+
+ return CURLE_OK;
+}
+#endif
diff --git a/lib/vquic/vquic.h b/lib/vquic/vquic.h
new file mode 100644
index 000000000..ecff0edf4
--- /dev/null
+++ b/lib/vquic/vquic.h
@@ -0,0 +1,34 @@
+#ifndef HEADER_CURL_VQUIC_QUIC_H
+#define HEADER_CURL_VQUIC_QUIC_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef ENABLE_QUIC
+CURLcode Curl_qlogdir(struct Curl_easy *data,
+ unsigned char *scid,
+ size_t scidlen,
+ int *qlogfdp);
+#endif
+
+#endif /* HEADER_CURL_VQUIC_QUIC_H */
diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c
index ed8986e21..8c3944d8b 100644
--- a/lib/vssh/libssh2.c
+++ b/lib/vssh/libssh2.c
@@ -93,15 +93,12 @@
#define HAS_STATVFS_SUPPORT 1
#endif
-#define sftp_libssh2_last_error(s) curlx_ultosi(libssh2_sftp_last_error(s))
-
-#define sftp_libssh2_realpath(s,p,t,m) \
- libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
- (t), (m), LIBSSH2_SFTP_REALPATH)
-
+#define sftp_libssh2_realpath(s,p,t,m) \
+ libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
+ (t), (m), LIBSSH2_SFTP_REALPATH)
/* Local functions: */
-static const char *sftp_libssh2_strerror(int err);
+static const char *sftp_libssh2_strerror(unsigned long err);
static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
static LIBSSH2_FREE_FUNC(my_libssh2_free);
@@ -213,7 +210,7 @@ kbd_callback(const char *name, int name_len, const char *instruction,
(void)abstract;
} /* kbd_callback */
-static CURLcode sftp_libssh2_error_to_CURLE(int err)
+static CURLcode sftp_libssh2_error_to_CURLE(unsigned long err)
{
switch(err) {
case LIBSSH2_FX_OK:
@@ -795,10 +792,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
struct SSHPROTO *sftp_scp = data->req.protop;
struct ssh_conn *sshc = &conn->proto.sshc;
curl_socket_t sock = conn->sock[FIRSTSOCKET];
- char *new_readdir_line;
int rc = LIBSSH2_ERROR_NONE;
- int err;
+ int ssherr;
+ unsigned long sftperr;
int seekerr = CURL_SEEKFUNC_OK;
+ size_t readdir_len;
*block = 0; /* we're not blocking by default */
do {
@@ -874,12 +872,12 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
state(conn, SSH_AUTH_DONE);
break;
}
- err = libssh2_session_last_errno(sshc->ssh_session);
- if(err == LIBSSH2_ERROR_EAGAIN)
+ ssherr = libssh2_session_last_errno(sshc->ssh_session);
+ if(ssherr == LIBSSH2_ERROR_EAGAIN)
rc = LIBSSH2_ERROR_EAGAIN;
else {
state(conn, SSH_SESSION_FREE);
- sshc->actualcode = libssh2_session_error_to_CURLE(err);
+ sshc->actualcode = libssh2_session_error_to_CURLE(ssherr);
}
break;
}
@@ -1249,16 +1247,16 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
else {
/* Return the error type */
- err = sftp_libssh2_last_error(sshc->sftp_session);
- if(err)
- result = sftp_libssh2_error_to_CURLE(err);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ if(sftperr)
+ result = sftp_libssh2_error_to_CURLE(sftperr);
else
/* in this case, the error wasn't in the SFTP level but for example
a time-out or similar */
result = CURLE_SSH;
sshc->actualcode = result;
DEBUGF(infof(data, "error = %d makes libcurl = %d\n",
- err, (int)result));
+ ssherr, (int)result));
state(conn, SSH_STOP);
break;
}
@@ -1360,7 +1358,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
*/
cp = strchr(cmd, ' ');
if(cp == NULL) {
- failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
+ failf(data, "Syntax error command '%s'. Missing parameter!",
+ cmd);
state(conn, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
@@ -1376,7 +1375,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(result == CURLE_OUT_OF_MEMORY)
failf(data, "Out of memory");
else
- failf(data, "Syntax error: Bad first parameter");
+ failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
state(conn, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = result;
@@ -1401,8 +1400,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(result == CURLE_OUT_OF_MEMORY)
failf(data, "Out of memory");
else
- failf(data, "Syntax error in chgrp/chmod/chown: "
- "Bad second parameter");
+ failf(data, "Syntax error in %s: Bad second parameter", cmd);
Curl_safefree(sshc->quote_path1);
state(conn, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
@@ -1533,11 +1531,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
- err = sftp_libssh2_last_error(sshc->sftp_session);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to get SFTP stats failed: %s",
- sftp_libssh2_strerror(err));
+ sftp_libssh2_strerror(sftperr));
state(conn, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
@@ -1604,11 +1602,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc != 0 && !sshc->acceptfail) {
- err = sftp_libssh2_last_error(sshc->sftp_session);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "Attempt to set SFTP stats failed: %s",
- sftp_libssh2_strerror(err));
+ sftp_libssh2_strerror(sftperr));
state(conn, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
@@ -1627,11 +1625,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc != 0 && !sshc->acceptfail) {
- err = sftp_libssh2_last_error(sshc->sftp_session);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
failf(data, "symlink command failed: %s",
- sftp_libssh2_strerror(err));
+ sftp_libssh2_strerror(sftperr));
state(conn, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
@@ -1648,9 +1646,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc != 0 && !sshc->acceptfail) {
- err = sftp_libssh2_last_error(sshc->sftp_session);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
- failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
+ failf(data, "mkdir command failed: %s",
+ sftp_libssh2_strerror(sftperr));
state(conn, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
@@ -1672,10 +1671,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc != 0 && !sshc->acceptfail) {
- err = sftp_libssh2_last_error(sshc->sftp_session);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
Curl_safefree(sshc->quote_path2);
- failf(data, "rename command failed: %s", sftp_libssh2_strerror(err));
+ failf(data, "rename command failed: %s",
+ sftp_libssh2_strerror(sftperr));
state(conn, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
@@ -1691,9 +1691,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc != 0 && !sshc->acceptfail) {
- err = sftp_libssh2_last_error(sshc->sftp_session);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
- failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
+ failf(data, "rmdir command failed: %s",
+ sftp_libssh2_strerror(sftperr));
state(conn, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
@@ -1709,9 +1710,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc != 0 && !sshc->acceptfail) {
- err = sftp_libssh2_last_error(sshc->sftp_session);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
- failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
+ failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr));
state(conn, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
@@ -1732,9 +1733,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc != 0 && !sshc->acceptfail) {
- err = sftp_libssh2_last_error(sshc->sftp_session);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
Curl_safefree(sshc->quote_path1);
- failf(data, "statvfs command failed: %s", sftp_libssh2_strerror(err));
+ failf(data, "statvfs command failed: %s",
+ sftp_libssh2_strerror(sftperr));
state(conn, SSH_SFTP_CLOSE);
sshc->nextstate = SSH_NO_STATE;
sshc->actualcode = CURLE_QUOTE_ERROR;
@@ -1871,21 +1873,21 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
/* only when there was an SFTP protocol error can we extract
the sftp error! */
- err = sftp_libssh2_last_error(sshc->sftp_session);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
else
- err = -1; /* not an sftp error at all */
+ sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */
if(sshc->secondCreateDirs) {
state(conn, SSH_SFTP_CLOSE);
- sshc->actualcode = err>= LIBSSH2_FX_OK?
- sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
+ sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
+ sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH;
failf(data, "Creating the dir/file failed: %s",
- sftp_libssh2_strerror(err));
+ sftp_libssh2_strerror(sftperr));
break;
}
- if(((err == LIBSSH2_FX_NO_SUCH_FILE) ||
- (err == LIBSSH2_FX_FAILURE) ||
- (err == LIBSSH2_FX_NO_SUCH_PATH)) &&
+ if(((sftperr == LIBSSH2_FX_NO_SUCH_FILE) ||
+ (sftperr == LIBSSH2_FX_FAILURE) ||
+ (sftperr == LIBSSH2_FX_NO_SUCH_PATH)) &&
(data->set.ftp_create_missing_dirs &&
(strlen(sftp_scp->path) > 1))) {
/* try to create the path remotely */
@@ -1895,18 +1897,19 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
state(conn, SSH_SFTP_CLOSE);
- sshc->actualcode = err>= LIBSSH2_FX_OK?
- sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
+ sshc->actualcode = sftperr != LIBSSH2_FX_OK ?
+ sftp_libssh2_error_to_CURLE(sftperr):CURLE_SSH;
if(!sshc->actualcode) {
- /* Sometimes, for some reason libssh2_sftp_last_error() returns
- zero even though libssh2_sftp_open() failed previously! We need
- to work around that! */
+ /* Sometimes, for some reason libssh2_sftp_last_error() returns zero
+ even though libssh2_sftp_open() failed previously! We need to
+ work around that! */
sshc->actualcode = CURLE_SSH;
- err = -1;
+ sftperr = LIBSSH2_FX_OK;
}
failf(data, "Upload failed: %s (%d/%d)",
- err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error",
- err, rc);
+ sftperr != LIBSSH2_FX_OK ?
+ sftp_libssh2_strerror(sftperr):"ssh error",
+ sftperr, rc);
break;
}
@@ -2033,11 +2036,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
* permission was denied (creation might succeed further down the
* path) - retry on unspecific FAILURE also
*/
- err = sftp_libssh2_last_error(sshc->sftp_session);
- if((err != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
- (err != LIBSSH2_FX_FAILURE) &&
- (err != LIBSSH2_FX_PERMISSION_DENIED)) {
- result = sftp_libssh2_error_to_CURLE(err);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ if((sftperr != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
+ (sftperr != LIBSSH2_FX_FAILURE) &&
+ (sftperr != LIBSSH2_FX_PERMISSION_DENIED)) {
+ result = sftp_libssh2_error_to_CURLE(sftperr);
state(conn, SSH_SFTP_CLOSE);
sshc->actualcode = result?result:CURLE_SSH;
break;
@@ -2069,11 +2072,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
rc = LIBSSH2_ERROR_EAGAIN;
break;
}
- err = sftp_libssh2_last_error(sshc->sftp_session);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
failf(data, "Could not open directory for reading: %s",
- sftp_libssh2_strerror(err));
+ sftp_libssh2_strerror(sftperr));
state(conn, SSH_SFTP_CLOSE);
- result = sftp_libssh2_error_to_CURLE(err);
+ result = sftp_libssh2_error_to_CURLE(sftperr);
sshc->actualcode = result?result:CURLE_SSH;
break;
}
@@ -2090,6 +2093,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->actualcode = CURLE_OUT_OF_MEMORY;
break;
}
+ Curl_dyn_init(&sshc->readdir, PATH_MAX * 2);
state(conn, SSH_SFTP_READDIR);
break;
@@ -2104,68 +2108,51 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
if(rc > 0) {
- sshc->readdir_len = (size_t) rc;
- sshc->readdir_filename[sshc->readdir_len] = '\0';
+ readdir_len = (size_t) rc;
+ sshc->readdir_filename[readdir_len] = '\0';
if(data->set.ftp_list_only) {
- char *tmpLine;
-
- tmpLine = aprintf("%s\n", sshc->readdir_filename);
- if(tmpLine == NULL) {
- state(conn, SSH_SFTP_CLOSE);
- sshc->actualcode = CURLE_OUT_OF_MEMORY;
- break;
- }
result = Curl_client_write(conn, CLIENTWRITE_BODY,
- tmpLine, sshc->readdir_len + 1);
- free(tmpLine);
-
+ sshc->readdir_filename,
+ readdir_len);
+ if(!result)
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ (char *)"\n", 1);
if(result) {
state(conn, SSH_STOP);
break;
}
/* 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 += readdir_len + 1;
/* output debug output if that is requested */
if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename,
- sshc->readdir_len);
+ Curl_debug(data, CURLINFO_DATA_IN, sshc->readdir_filename,
+ readdir_len);
+ Curl_debug(data, CURLINFO_DATA_IN, (char *)"\n", 1);
}
}
else {
- sshc->readdir_currLen = strlen(sshc->readdir_longentry);
- sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
- sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
- if(!sshc->readdir_line) {
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
- state(conn, SSH_SFTP_CLOSE);
- sshc->actualcode = CURLE_OUT_OF_MEMORY;
- break;
- }
-
- memcpy(sshc->readdir_line, sshc->readdir_longentry,
- sshc->readdir_currLen);
- if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
- ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
- LIBSSH2_SFTP_S_IFLNK)) {
- sshc->readdir_linkPath = malloc(PATH_MAX + 1);
- if(sshc->readdir_linkPath == NULL) {
- Curl_safefree(sshc->readdir_filename);
- Curl_safefree(sshc->readdir_longentry);
- state(conn, SSH_SFTP_CLOSE);
- sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ result = Curl_dyn_add(&sshc->readdir, sshc->readdir_longentry);
+
+ if(!result) {
+ if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
+ ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
+ LIBSSH2_SFTP_S_IFLNK)) {
+ Curl_dyn_init(&sshc->readdir_link, PATH_MAX);
+ result = Curl_dyn_add(&sshc->readdir_link, sftp_scp->path);
+ state(conn, SSH_SFTP_READDIR_LINK);
+ if(!result)
+ break;
+ }
+ else {
+ state(conn, SSH_SFTP_READDIR_BOTTOM);
break;
}
-
- msnprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
- sshc->readdir_filename);
- state(conn, SSH_SFTP_READDIR_LINK);
- break;
}
- state(conn, SSH_SFTP_READDIR_BOTTOM);
+ sshc->actualcode = result;
+ state(conn, SSH_SFTP_CLOSE);
break;
}
}
@@ -2176,11 +2163,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
break;
}
else if(rc < 0) {
- err = sftp_libssh2_last_error(sshc->sftp_session);
- result = sftp_libssh2_error_to_CURLE(err);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
+ result = sftp_libssh2_error_to_CURLE(sftperr);
sshc->actualcode = result?result:CURLE_SSH;
failf(data, "Could not open remote file for reading: %s :: %d",
- sftp_libssh2_strerror(err),
+ sftp_libssh2_strerror(sftperr),
libssh2_session_last_errno(sshc->ssh_session));
Curl_safefree(sshc->readdir_filename);
Curl_safefree(sshc->readdir_longentry);
@@ -2192,64 +2179,56 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
case SSH_SFTP_READDIR_LINK:
rc =
libssh2_sftp_symlink_ex(sshc->sftp_session,
- sshc->readdir_linkPath,
- curlx_uztoui(strlen(sshc->readdir_linkPath)),
+ Curl_dyn_ptr(&sshc->readdir_link),
+ (int)Curl_dyn_len(&sshc->readdir_link),
sshc->readdir_filename,
PATH_MAX, LIBSSH2_SFTP_READLINK);
if(rc == LIBSSH2_ERROR_EAGAIN) {
break;
}
- sshc->readdir_len = (size_t) rc;
- Curl_safefree(sshc->readdir_linkPath);
+ readdir_len = (size_t) rc;
+ Curl_dyn_free(&sshc->readdir_link);
+
+ /* append filename and extra output */
+ result = Curl_dyn_addf(&sshc->readdir, " -> %s", sshc->readdir_filename);
- /* get room for the filename and extra output */
- sshc->readdir_totalLen += 4 + sshc->readdir_len;
- new_readdir_line = Curl_saferealloc(sshc->readdir_line,
- sshc->readdir_totalLen);
- if(!new_readdir_line) {
+ if(result) {
sshc->readdir_line = NULL;
Curl_safefree(sshc->readdir_filename);
Curl_safefree(sshc->readdir_longentry);
state(conn, SSH_SFTP_CLOSE);
- sshc->actualcode = CURLE_OUT_OF_MEMORY;
+ sshc->actualcode = result;
break;
}
- sshc->readdir_line = new_readdir_line;
-
- sshc->readdir_currLen += msnprintf(sshc->readdir_line +
- sshc->readdir_currLen,
- sshc->readdir_totalLen -
- sshc->readdir_currLen,
- " -> %s",
- sshc->readdir_filename);
state(conn, SSH_SFTP_READDIR_BOTTOM);
break;
case SSH_SFTP_READDIR_BOTTOM:
- sshc->readdir_currLen += msnprintf(sshc->readdir_line +
- sshc->readdir_currLen,
- sshc->readdir_totalLen -
- sshc->readdir_currLen, "\n");
- result = Curl_client_write(conn, CLIENTWRITE_BODY,
- sshc->readdir_line,
- sshc->readdir_currLen);
+ result = Curl_dyn_addn(&sshc->readdir, "\n", 1);
+ if(!result)
+ result = Curl_client_write(conn, CLIENTWRITE_BODY,
+ Curl_dyn_ptr(&sshc->readdir),
+ Curl_dyn_len(&sshc->readdir));
if(!result) {
/* output debug output if that is requested */
if(data->set.verbose) {
- Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
- sshc->readdir_currLen);
+ Curl_debug(data, CURLINFO_DATA_IN,
+ Curl_dyn_ptr(&sshc->readdir),
+ Curl_dyn_len(&sshc->readdir));
}
- data->req.bytecount += sshc->readdir_currLen;
+ data->req.bytecount += Curl_dyn_len(&sshc->readdir);
}
- Curl_safefree(sshc->readdir_line);
if(result) {
+ Curl_dyn_free(&sshc->readdir);
state(conn, SSH_STOP);
}
- else
+ else {
+ Curl_dyn_reset(&sshc->readdir);
state(conn, SSH_SFTP_READDIR);
+ }
break;
case SSH_SFTP_READDIR_DONE:
@@ -2282,11 +2261,11 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
rc = LIBSSH2_ERROR_EAGAIN;
break;
}
- err = sftp_libssh2_last_error(sshc->sftp_session);
+ sftperr = libssh2_sftp_last_error(sshc->sftp_session);
failf(data, "Could not open remote file for reading: %s",
- sftp_libssh2_strerror(err));
+ sftp_libssh2_strerror(sftperr));
state(conn, SSH_SFTP_CLOSE);
- result = sftp_libssh2_error_to_CURLE(err);
+ result = sftp_libssh2_error_to_CURLE(sftperr);
sshc->actualcode = result?result:CURLE_SSH;
break;
}
@@ -2551,7 +2530,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
/* upload data */
- Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET);
+ data->req.size = data->state.infilesize;
+ Curl_pgrsSetUploadSize(data, data->state.infilesize);
+ Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
/* not set by Curl_setup_transfer to preserve keepon bits */
conn->sockfd = conn->writesockfd;
@@ -2621,7 +2602,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* download data */
bytecount = (curl_off_t)sb.st_size;
- data->req.maxdownload = (curl_off_t)sb.st_size;
+ data->req.maxdownload = (curl_off_t)sb.st_size;
Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1);
/* not set by Curl_setup_transfer to preserve keepon bits */
@@ -2828,7 +2809,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_safefree(sshc->readdir_filename);
Curl_safefree(sshc->readdir_longentry);
Curl_safefree(sshc->readdir_line);
- Curl_safefree(sshc->readdir_linkPath);
+ Curl_dyn_free(&sshc->readdir);
/* the code we are about to return */
result = sshc->actualcode;
@@ -2952,7 +2933,7 @@ static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
}
static CURLcode ssh_block_statemach(struct connectdata *conn,
- bool disconnect)
+ bool duringconnect)
{
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
@@ -2967,19 +2948,17 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
if(result)
break;
- if(!disconnect) {
- if(Curl_pgrsUpdate(conn))
- return CURLE_ABORTED_BY_CALLBACK;
+ if(Curl_pgrsUpdate(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
- result = Curl_speedcheck(data, now);
- if(result)
- break;
+ result = Curl_speedcheck(data, now);
+ if(result)
+ break;
- left = Curl_timeleft(data, NULL, FALSE);
- if(left < 0) {
- failf(data, "Operation timed out");
- return CURLE_OPERATION_TIMEDOUT;
- }
+ left = Curl_timeleft(data, NULL, duringconnect);
+ if(left < 0) {
+ failf(data, "Operation timed out");
+ return CURLE_OPERATION_TIMEDOUT;
}
#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
@@ -2994,7 +2973,7 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
fd_write = sock;
/* wait for the socket to become ready */
(void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
- left>1000?1000:(time_t)left);
+ left>1000?1000:left);
}
#endif
@@ -3202,7 +3181,7 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
state(conn, SSH_SESSION_DISCONNECT);
- result = ssh_block_statemach(conn, TRUE);
+ result = ssh_block_statemach(conn, FALSE);
}
return result;
@@ -3351,7 +3330,7 @@ static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */
state(conn, SSH_SFTP_SHUTDOWN);
- result = ssh_block_statemach(conn, TRUE);
+ result = ssh_block_statemach(conn, FALSE);
}
DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
@@ -3426,7 +3405,7 @@ static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
return nread;
}
-static const char *sftp_libssh2_strerror(int err)
+static const char *sftp_libssh2_strerror(unsigned long err)
{
switch(err) {
case LIBSSH2_FX_NO_SUCH_FILE:
diff --git a/lib/vssh/ssh.h b/lib/vssh/ssh.h
index 0d4ee521d..9e49993e9 100644
--- a/lib/vssh/ssh.h
+++ b/lib/vssh/ssh.h
@@ -134,9 +134,7 @@ struct ssh_conn {
quote command fails) */
char *homedir; /* when doing SFTP we figure out home dir in the
connect phase */
- size_t readdir_len, readdir_totalLen, readdir_currLen;
char *readdir_line;
- char *readdir_linkPath;
/* end of READDIR stuff */
int secondCreateDirs; /* counter use by the code to see if the
@@ -147,6 +145,8 @@ struct ssh_conn {
int orig_waitfor; /* default READ/WRITE bits wait for */
#if defined(USE_LIBSSH)
+ char *readdir_linkPath;
+ size_t readdir_len, readdir_totalLen, readdir_currLen;
/* our variables */
unsigned kbd_state; /* 0 or 1 */
ssh_key privkey;
@@ -168,6 +168,8 @@ struct ssh_conn {
const char *readdir_longentry;
char *readdir_tmp;
#elif defined(USE_LIBSSH2)
+ struct dynbuf readdir_link;
+ struct dynbuf readdir;
char *readdir_filename;
char *readdir_longentry;
diff --git a/lib/vssh/wolfssh.c b/lib/vssh/wolfssh.c
index 363a52c77..dcbbab6c3 100644
--- a/lib/vssh/wolfssh.c
+++ b/lib/vssh/wolfssh.c
@@ -241,8 +241,8 @@ static ssize_t wsftp_send(struct connectdata *conn, int sockindex,
int rc;
(void)sockindex;
- offset[0] = (word32)sshc->offset&0xFFFFFFFF;
- offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF;
+ offset[0] = (word32)sshc->offset&0xFFFFFFFF;
+ offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF;
rc = wolfSSH_SFTP_SendWritePacket(sshc->ssh_session, sshc->handle,
sshc->handleSz,
@@ -284,8 +284,8 @@ static ssize_t wsftp_recv(struct connectdata *conn, int sockindex,
word32 offset[2];
(void)sockindex;
- offset[0] = (word32)sshc->offset&0xFFFFFFFF;
- offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF;
+ offset[0] = (word32)sshc->offset&0xFFFFFFFF;
+ offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF;
rc = wolfSSH_SFTP_SendReadPacket(sshc->ssh_session, sshc->handle,
sshc->handleSz,
diff --git a/lib/vtls/bearssl.c b/lib/vtls/bearssl.c
index 1a6530c81..628e16a12 100644
--- a/lib/vtls/bearssl.c
+++ b/lib/vtls/bearssl.c
@@ -642,7 +642,7 @@ static CURLcode bearssl_connect_common(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
- time_t timeout_ms;
+ timediff_t timeout_ms;
int what;
/* check if the connection has already been established */
diff --git a/lib/vtls/gskit.c b/lib/vtls/gskit.c
index 96db9364d..2998a8eb4 100644
--- a/lib/vtls/gskit.c
+++ b/lib/vtls/gskit.c
@@ -108,13 +108,13 @@ struct ssl_backend_data {
#define BACKEND connssl->backend
/* Supported ciphers. */
-typedef struct {
+struct gskit_cipher {
const char *name; /* Cipher name. */
const char *gsktoken; /* Corresponding token for GSKit String. */
unsigned int versions; /* SSL version flags. */
-} gskit_cipher;
+};
-static const gskit_cipher ciphertable[] = {
+static const struct gskit_cipher ciphertable[] = {
{ "null-md5", "01",
CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
@@ -307,7 +307,7 @@ static CURLcode set_ciphers(struct connectdata *conn,
struct Curl_easy *data = conn->data;
const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
const char *clp;
- const gskit_cipher *ctp;
+ const struct gskit_cipher *ctp;
int i;
int l;
bool unsupported;
@@ -819,7 +819,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
if(!result) {
/* Compute the handshake timeout. Since GSKit granularity is 1 second,
we round up the required value. */
- long timeout = Curl_timeleft(data, NULL, TRUE);
+ timediff_t timeout = Curl_timeleft(data, NULL, TRUE);
if(timeout < 0)
result = CURLE_OPERATION_TIMEDOUT;
else
@@ -932,7 +932,7 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
/* Poll or wait for end of SSL asynchronous handshake. */
for(;;) {
- long timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
+ timediff_t timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0)
timeout_ms = 0;
stmv.tv_sec = timeout_ms / 1000;
diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
index 4ed3ea5cf..9b4c3659a 100644
--- a/lib/vtls/gtls.c
+++ b/lib/vtls/gtls.c
@@ -235,7 +235,7 @@ static CURLcode handshake(struct connectdata *conn,
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
nonblocking?0:
- timeout_ms?(time_t)timeout_ms:1000);
+ timeout_ms?timeout_ms:1000);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -401,6 +401,8 @@ gtls_connect_step1(struct connectdata *conn,
const char *err = NULL;
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
+ long * const certverifyresult = SSL_IS_PROXY() ?
+ &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
if(connssl->state == ssl_connection_complete)
/* to make us tolerant against being called more than once for the
@@ -410,6 +412,9 @@ gtls_connect_step1(struct connectdata *conn,
if(!gtls_inited)
Curl_gtls_init();
+ /* Initialize certverifyresult to OK */
+ *certverifyresult = 0;
+
if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
failf(data, "GnuTLS does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
@@ -458,8 +463,10 @@ gtls_connect_step1(struct connectdata *conn,
if(rc < 0) {
infof(data, "error reading ca cert file %s (%s)\n",
SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
- if(SSL_CONN_CONFIG(verifypeer))
+ if(SSL_CONN_CONFIG(verifypeer)) {
+ *certverifyresult = rc;
return CURLE_SSL_CACERT_BADFILE;
+ }
}
else
infof(data, "found %d certificates in %s\n", rc,
@@ -474,8 +481,10 @@ gtls_connect_step1(struct connectdata *conn,
if(rc < 0) {
infof(data, "error reading ca cert file %s (%s)\n",
SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
- if(SSL_CONN_CONFIG(verifypeer))
+ if(SSL_CONN_CONFIG(verifypeer)) {
+ *certverifyresult = rc;
return CURLE_SSL_CACERT_BADFILE;
+ }
}
else
infof(data, "found %d certificates in %s\n",
@@ -821,6 +830,8 @@ gtls_connect_step3(struct connectdata *conn,
#endif
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
+ long * const certverifyresult = SSL_IS_PROXY() ?
+ &data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
/* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
@@ -852,6 +863,7 @@ gtls_connect_step3(struct connectdata *conn,
else {
#endif
failf(data, "failed to get server cert");
+ *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
return CURLE_PEER_FAILED_VERIFICATION;
#ifdef USE_TLS_SRP
}
@@ -888,9 +900,12 @@ gtls_connect_step3(struct connectdata *conn,
rc = gnutls_certificate_verify_peers2(session, &verify_status);
if(rc < 0) {
failf(data, "server cert verify failed: %d", rc);
+ *certverifyresult = rc;
return CURLE_SSL_CONNECT_ERROR;
}
+ *certverifyresult = verify_status;
+
/* verify_status is a bitmask of gnutls_certificate_status bits */
if(verify_status & GNUTLS_CERT_INVALID) {
if(SSL_CONN_CONFIG(verifypeer)) {
@@ -1119,6 +1134,7 @@ gtls_connect_step3(struct connectdata *conn,
if(certclock == (time_t)-1) {
if(SSL_CONN_CONFIG(verifypeer)) {
failf(data, "server cert expiration date verify failed");
+ *certverifyresult = GNUTLS_CERT_EXPIRED;
gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_CONNECT_ERROR;
}
@@ -1129,6 +1145,7 @@ gtls_connect_step3(struct connectdata *conn,
if(certclock < time(NULL)) {
if(SSL_CONN_CONFIG(verifypeer)) {
failf(data, "server certificate expiration date has passed.");
+ *certverifyresult = GNUTLS_CERT_EXPIRED;
gnutls_x509_crt_deinit(x509_cert);
return CURLE_PEER_FAILED_VERIFICATION;
}
@@ -1144,6 +1161,7 @@ gtls_connect_step3(struct connectdata *conn,
if(certclock == (time_t)-1) {
if(SSL_CONN_CONFIG(verifypeer)) {
failf(data, "server cert activation date verify failed");
+ *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_CONNECT_ERROR;
}
@@ -1154,6 +1172,7 @@ gtls_connect_step3(struct connectdata *conn,
if(certclock > time(NULL)) {
if(SSL_CONN_CONFIG(verifypeer)) {
failf(data, "server certificate not activated yet.");
+ *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
gnutls_x509_crt_deinit(x509_cert);
return CURLE_PEER_FAILED_VERIFICATION;
}
diff --git a/lib/vtls/keylog.c b/lib/vtls/keylog.c
new file mode 100644
index 000000000..70d22ecf0
--- /dev/null
+++ b/lib/vtls/keylog.c
@@ -0,0 +1,156 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+#include "keylog.h"
+
+/* The last #include files should be: */
+#include "curl_memory.h"
+#include "memdebug.h"
+
+#define KEYLOG_LABEL_MAXLEN (sizeof("CLIENT_HANDSHAKE_TRAFFIC_SECRET") - 1)
+
+#define CLIENT_RANDOM_SIZE 32
+
+/*
+ * The master secret in TLS 1.2 and before is always 48 bytes. In TLS 1.3, the
+ * secret size depends on the cipher suite's hash function which is 32 bytes
+ * for SHA-256 and 48 bytes for SHA-384.
+ */
+#define SECRET_MAXLEN 48
+
+
+/* The fp for the open SSLKEYLOGFILE, or NULL if not open */
+static FILE *keylog_file_fp;
+
+void
+Curl_tls_keylog_open(void)
+{
+ char *keylog_file_name;
+
+ if(!keylog_file_fp) {
+ keylog_file_name = curl_getenv("SSLKEYLOGFILE");
+ if(keylog_file_name) {
+ keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT);
+ if(keylog_file_fp) {
+#ifdef WIN32
+ if(setvbuf(keylog_file_fp, NULL, _IONBF, 0))
+#else
+ if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096))
+#endif
+ {
+ fclose(keylog_file_fp);
+ keylog_file_fp = NULL;
+ }
+ }
+ Curl_safefree(keylog_file_name);
+ }
+ }
+}
+
+void
+Curl_tls_keylog_close(void)
+{
+ if(keylog_file_fp) {
+ fclose(keylog_file_fp);
+ keylog_file_fp = NULL;
+ }
+}
+
+bool
+Curl_tls_keylog_enabled(void)
+{
+ return keylog_file_fp != NULL;
+}
+
+bool
+Curl_tls_keylog_write_line(const char *line)
+{
+ /* The current maximum valid keylog line length LF and NUL is 195. */
+ size_t linelen;
+ char buf[256];
+
+ if(!keylog_file_fp || !line) {
+ return false;
+ }
+
+ linelen = strlen(line);
+ if(linelen == 0 || linelen > sizeof(buf) - 2) {
+ /* Empty line or too big to fit in a LF and NUL. */
+ return false;
+ }
+
+ memcpy(buf, line, linelen);
+ if(line[linelen - 1] != '\n') {
+ buf[linelen++] = '\n';
+ }
+ buf[linelen] = '\0';
+
+ /* Using fputs here instead of fprintf since libcurl's fprintf replacement
+ may not be thread-safe. */
+ fputs(buf, keylog_file_fp);
+ return true;
+}
+
+bool
+Curl_tls_keylog_write(const char *label,
+ const unsigned char client_random[CLIENT_RANDOM_SIZE],
+ const unsigned char *secret, size_t secretlen)
+{
+ const char *hex = "0123456789ABCDEF";
+ size_t pos, i;
+ char line[KEYLOG_LABEL_MAXLEN + 1 + 2 * CLIENT_RANDOM_SIZE + 1 +
+ 2 * SECRET_MAXLEN + 1 + 1];
+
+ if(!keylog_file_fp) {
+ return false;
+ }
+
+ pos = strlen(label);
+ if(pos > KEYLOG_LABEL_MAXLEN || !secretlen || secretlen > SECRET_MAXLEN) {
+ /* Should never happen - sanity check anyway. */
+ return false;
+ }
+
+ memcpy(line, label, pos);
+ line[pos++] = ' ';
+
+ /* Client Random */
+ for(i = 0; i < CLIENT_RANDOM_SIZE; i++) {
+ line[pos++] = hex[client_random[i] >> 4];
+ line[pos++] = hex[client_random[i] & 0xF];
+ }
+ line[pos++] = ' ';
+
+ /* Secret */
+ for(i = 0; i < secretlen; i++) {
+ line[pos++] = hex[secret[i] >> 4];
+ line[pos++] = hex[secret[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);
+ return true;
+}
diff --git a/lib/vtls/keylog.h b/lib/vtls/keylog.h
new file mode 100644
index 000000000..c6b99db93
--- /dev/null
+++ b/lib/vtls/keylog.h
@@ -0,0 +1,56 @@
+#ifndef HEADER_CURL_KEYLOG_H
+#define HEADER_CURL_KEYLOG_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+/*
+ * Opens the TLS key log file if requested by the user. The SSLKEYLOGFILE
+ * environment variable specifies the output file.
+ */
+void Curl_tls_keylog_open(void);
+
+/*
+ * Closes the TLS key log file if not already.
+ */
+void Curl_tls_keylog_close(void);
+
+/*
+ * Returns true if the user successfully enabled the TLS key log file.
+ */
+bool Curl_tls_keylog_enabled(void);
+
+/*
+ * Appends a key log file entry.
+ * Returns true iff the key log file is open and a valid entry was provided.
+ */
+bool Curl_tls_keylog_write(const char *label,
+ const unsigned char client_random[32],
+ const unsigned char *secret, size_t secretlen);
+
+/*
+ * Appends a line to the key log file, ensure it is terminated by a LF.
+ * Returns true iff the key log file is open and a valid line was provided.
+ */
+bool Curl_tls_keylog_write_line(const char *line);
+
+#endif /* HEADER_CURL_KEYLOG_H */
diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
index cbf3d3dec..545f824c6 100644
--- a/lib/vtls/mbedtls.c
+++ b/lib/vtls/mbedtls.c
@@ -239,16 +239,21 @@ mbed_connect_step1(struct connectdata *conn,
int sockindex)
{
struct Curl_easy *data = conn->data;
- struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
char * const ssl_cert = SSL_SET_OPTION(cert);
const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
+#ifndef CURL_DISABLE_PROXY
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
+#else
+ const char * const hostname = conn->host.name;
+ const long int port = conn->remote_port;
+#endif
int ret = -1;
char errorbuf[128];
errorbuf[0] = 0;
@@ -535,12 +540,17 @@ mbed_connect_step2(struct connectdata *conn,
{
int ret;
struct Curl_easy *data = conn->data;
- struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
const mbedtls_x509_crt *peercert;
+#ifndef CURL_DISABLE_PROXY
const char * const pinnedpubkey = SSL_IS_PROXY() ?
data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+#else
+ const char * const pinnedpubkey =
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+#endif
conn->recv[sockindex] = mbed_recv;
conn->send[sockindex] = mbed_send;
@@ -938,7 +948,7 @@ mbed_connect_common(struct connectdata *conn,
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
- nonblocking ? 0 : (time_t)timeout_ms);
+ nonblocking ? 0 : timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
diff --git a/lib/vtls/mesalink.c b/lib/vtls/mesalink.c
index cab1e390b..7132bdfd2 100644
--- a/lib/vtls/mesalink.c
+++ b/lib/vtls/mesalink.c
@@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2017 - 2018, Yiming Jing, <jingyiming@baidu.com>
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -542,9 +542,8 @@ mesalink_connect_common(struct connectdata *conn, int sockindex,
? sockfd
: CURL_SOCKET_BAD;
- what = Curl_socket_check(
- readfd, CURL_SOCKET_BAD, writefd,
- nonblocking ? 0 : (time_t)timeout_ms);
+ what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
+ nonblocking ? 0 : timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index 16ec409e9..fca292613 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -101,10 +101,10 @@ struct ptr_list_wrap {
struct curl_llist_element node;
};
-typedef struct {
+struct cipher_s {
const char *name;
int num;
-} cipher_s;
+};
#define PK11_SETATTRS(_attr, _idx, _type, _val, _len) do { \
CK_ATTRIBUTE *ptr = (_attr) + ((_idx)++); \
@@ -116,7 +116,7 @@ typedef struct {
#define CERT_NewTempCertificate __CERT_NewTempCertificate
#define NUM_OF_CIPHERS sizeof(cipherlist)/sizeof(cipherlist[0])
-static const cipher_s cipherlist[] = {
+static const struct cipher_s cipherlist[] = {
/* SSL2 cipher suites */
{"rc4", SSL_EN_RC4_128_WITH_MD5},
{"rc4-md5", SSL_EN_RC4_128_WITH_MD5},
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
index 176fa522a..2e9f900da 100644
--- a/lib/vtls/openssl.c
+++ b/lib/vtls/openssl.c
@@ -31,6 +31,11 @@
#include <limits.h>
+/* Wincrypt must be included before anything that could include OpenSSL. */
+#if defined(USE_WIN32_CRYPTO)
+#include <wincrypt.h>
+#endif
+
#include "urldata.h"
#include "sendf.h"
#include "formdata.h" /* for the boundary function */
@@ -41,11 +46,13 @@
#include "slist.h"
#include "select.h"
#include "vtls.h"
+#include "keylog.h"
#include "strcase.h"
#include "hostcheck.h"
#include "multiif.h"
#include "strerror.h"
#include "curl_printf.h"
+
#include <openssl/ssl.h>
#include <openssl/rand.h>
#include <openssl/x509v3.h>
@@ -207,24 +214,14 @@
"ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH"
#endif
-#define ENABLE_SSLKEYLOGFILE
-
-#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;
+#ifndef HAVE_KEYLOG_CALLBACK
+ /* Set to true once a valid keylog entry has been created to avoid dupes. */
+ bool keylog_done;
#endif
};
@@ -236,57 +233,27 @@ struct ssl_backend_data {
*/
#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;
- }
- memcpy(buf, line, linelen);
- buf[linelen] = '\n';
- buf[linelen + 1] = '\0';
-
- fputs(buf, keylog_file_fp);
- if(buf != stackbuf)
- free(buf);
- }
+ Curl_tls_keylog_write_line(line);
}
#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.
+ * ossl_log_tls12_secret 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)
+static void
+ossl_log_tls12_secret(const SSL *ssl, bool *keylog_done)
{
- 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)
+ if(!session || *keylog_done)
return;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
@@ -305,44 +272,17 @@ static void tap_ssl_key(const SSL *ssl, ssl_tap_state_t *state)
}
#endif
+ /* The handshake has not progressed sufficiently yet, or this is a TLS 1.3
+ * session (when curl was built with older OpenSSL headers and running with
+ * newer OpenSSL runtime libraries). */
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);
+ *keylog_done = true;
+ Curl_tls_keylog_write("CLIENT_RANDOM", client_random,
+ master_key, master_key_length);
}
#endif /* !HAVE_KEYLOG_CALLBACK */
-#endif /* ENABLE_SSLKEYLOGFILE */
static const char *SSL_ERROR_to_str(int err)
{
@@ -616,12 +556,136 @@ static bool is_pkcs11_uri(const char *string)
static CURLcode Curl_ossl_set_engine(struct Curl_easy *data,
const char *engine);
+static int
+SSL_CTX_use_certificate_bio(SSL_CTX *ctx, BIO *in, int type,
+ const char *key_passwd)
+{
+ int ret = 0;
+ X509 *x = NULL;
+
+ if(type == SSL_FILETYPE_ASN1) {
+ /* j = ERR_R_ASN1_LIB; */
+ x = d2i_X509_bio(in, NULL);
+ }
+ else if(type == SSL_FILETYPE_PEM) {
+ /* ERR_R_PEM_LIB; */
+ x = PEM_read_bio_X509(in, NULL,
+ passwd_callback, (void *)key_passwd);
+ }
+ else {
+ ret = 0;
+ goto end;
+ }
+
+ if(x == NULL) {
+ ret = 0;
+ goto end;
+ }
+
+ ret = SSL_CTX_use_certificate(ctx, x);
+ end:
+ X509_free(x);
+ return ret;
+}
+
+static int
+SSL_CTX_use_PrivateKey_bio(SSL_CTX *ctx, BIO* in, int type,
+ const char *key_passwd)
+{
+ int ret = 0;
+ EVP_PKEY *pkey = NULL;
+
+ if(type == SSL_FILETYPE_PEM)
+ pkey = PEM_read_bio_PrivateKey(in, NULL, passwd_callback,
+ (void *)key_passwd);
+ else if(type == SSL_FILETYPE_ASN1)
+ pkey = d2i_PrivateKey_bio(in, NULL);
+ else {
+ ret = 0;
+ goto end;
+ }
+ if(pkey == NULL) {
+ ret = 0;
+ goto end;
+ }
+ ret = SSL_CTX_use_PrivateKey(ctx, pkey);
+ EVP_PKEY_free(pkey);
+ end:
+ return ret;
+}
+
+static int
+SSL_CTX_use_certificate_chain_bio(SSL_CTX *ctx, BIO* in,
+ const char *key_passwd)
+{
+/* SSL_CTX_add1_chain_cert introduced in OpenSSL 1.0.2 */
+#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) /* 1.0.2 or later */
+ int ret = 0;
+ X509 *x = NULL;
+ void *passwd_callback_userdata = (void *)key_passwd;
+
+ ERR_clear_error();
+
+ x = PEM_read_bio_X509_AUX(in, NULL,
+ passwd_callback, (void *)key_passwd);
+
+ if(x == NULL) {
+ ret = 0;
+ goto end;
+ }
+
+ ret = SSL_CTX_use_certificate(ctx, x);
+
+ if(ERR_peek_error() != 0)
+ ret = 0;
+
+ if(ret) {
+ X509 *ca;
+ unsigned long err;
+
+ if(!SSL_CTX_clear_chain_certs(ctx)) {
+ ret = 0;
+ goto end;
+ }
+
+ while((ca = PEM_read_bio_X509(in, NULL, passwd_callback,
+ passwd_callback_userdata))
+ != NULL) {
+
+ if(!SSL_CTX_add0_chain_cert(ctx, ca)) {
+ X509_free(ca);
+ ret = 0;
+ goto end;
+ }
+ }
+
+ err = ERR_peek_last_error();
+ if((ERR_GET_LIB(err) == ERR_LIB_PEM) &&
+ (ERR_GET_REASON(err) == PEM_R_NO_START_LINE))
+ ERR_clear_error();
+ else
+ ret = 0;
+ }
+
+ end:
+ X509_free(x);
+ return ret;
+#else
+ (void)ctx; /* unused */
+ (void)in; /* unused */
+ (void)key_passwd; /* unused */
+ return 0;
+#endif
+}
+
static
int cert_stuff(struct connectdata *conn,
SSL_CTX* ctx,
char *cert_file,
+ BIO *cert_bio,
const char *cert_type,
char *key_file,
+ BIO* key_bio,
const char *key_type,
char *key_passwd)
{
@@ -631,10 +695,11 @@ int cert_stuff(struct connectdata *conn,
int file_type = do_file_type(cert_type);
- if(cert_file || (file_type == SSL_FILETYPE_ENGINE)) {
+ if(cert_file || cert_bio || (file_type == SSL_FILETYPE_ENGINE)) {
SSL *ssl;
X509 *x509;
int cert_done = 0;
+ int cert_use_result;
if(key_passwd) {
/* set the password in the callback userdata */
@@ -647,8 +712,10 @@ int cert_stuff(struct connectdata *conn,
switch(file_type) {
case SSL_FILETYPE_PEM:
/* SSL_CTX_use_certificate_chain_file() only works on PEM files */
- if(SSL_CTX_use_certificate_chain_file(ctx,
- cert_file) != 1) {
+ cert_use_result = cert_bio ?
+ SSL_CTX_use_certificate_chain_bio(ctx, cert_bio, key_passwd) :
+ SSL_CTX_use_certificate_chain_file(ctx, cert_file);
+ if(cert_use_result != 1) {
failf(data,
"could not load PEM client certificate, " OSSL_PACKAGE
" error %s, "
@@ -663,9 +730,12 @@ int cert_stuff(struct connectdata *conn,
/* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but
we use the case above for PEM so this can only be performed with
ASN1 files. */
- if(SSL_CTX_use_certificate_file(ctx,
- cert_file,
- file_type) != 1) {
+
+ cert_use_result = cert_bio ?
+ SSL_CTX_use_certificate_bio(ctx, cert_bio,
+ file_type, key_passwd) :
+ SSL_CTX_use_certificate_file(ctx, cert_file, file_type);
+ if(cert_use_result != 1) {
failf(data,
"could not load ASN1 client certificate, " OSSL_PACKAGE
" error %s, "
@@ -745,27 +815,31 @@ int cert_stuff(struct connectdata *conn,
PKCS12 *p12 = NULL;
EVP_PKEY *pri;
STACK_OF(X509) *ca = NULL;
+ if(!cert_bio) {
+ fp = BIO_new(BIO_s_file());
+ if(fp == NULL) {
+ failf(data,
+ "BIO_new return NULL, " OSSL_PACKAGE
+ " error %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
+ return 0;
+ }
- fp = BIO_new(BIO_s_file());
- if(fp == NULL) {
- failf(data,
- "BIO_new return NULL, " OSSL_PACKAGE
- " error %s",
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)) );
- return 0;
+ if(BIO_read_filename(fp, cert_file) <= 0) {
+ failf(data, "could not open PKCS12 file '%s'", cert_file);
+ BIO_free(fp);
+ return 0;
+ }
}
- if(BIO_read_filename(fp, cert_file) <= 0) {
- failf(data, "could not open PKCS12 file '%s'", cert_file);
+ p12 = d2i_PKCS12_bio(cert_bio ? cert_bio : fp, NULL);
+ if(fp)
BIO_free(fp);
- return 0;
- }
- p12 = d2i_PKCS12_bio(fp, NULL);
- BIO_free(fp);
if(!p12) {
- failf(data, "error reading PKCS12 file '%s'", cert_file);
+ failf(data, "error reading PKCS12 file '%s'",
+ cert_bio ? "(memory blob)" : cert_file);
return 0;
}
@@ -846,8 +920,10 @@ int cert_stuff(struct connectdata *conn,
return 0;
}
- if(!key_file)
+ if((!key_file) && (!key_bio)) {
key_file = cert_file;
+ key_bio = cert_bio;
+ }
else
file_type = do_file_type(key_type);
@@ -857,9 +933,12 @@ int cert_stuff(struct connectdata *conn,
break;
/* FALLTHROUGH */
case SSL_FILETYPE_ASN1:
- if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) {
+ cert_use_result = key_bio ?
+ SSL_CTX_use_PrivateKey_bio(ctx, key_bio, file_type, key_passwd) :
+ SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type);
+ if(cert_use_result != 1) {
failf(data, "unable to set private key file: '%s' type %s",
- key_file, key_type?key_type:"PEM");
+ key_file?key_file:"(memory blob)", key_type?key_type:"PEM");
return 0;
}
break;
@@ -1019,10 +1098,6 @@ static int x509_name_oneline(X509_NAME *a, char *buf, size_t size)
*/
static int Curl_ossl_init(void)
{
-#ifdef ENABLE_SSLKEYLOGFILE
- char *keylog_file_name;
-#endif
-
OPENSSL_load_builtin_modules();
#ifdef USE_OPENSSL_ENGINE
@@ -1055,26 +1130,7 @@ static int Curl_ossl_init(void)
OpenSSL_add_all_algorithms();
#endif
-#ifdef ENABLE_SSLKEYLOGFILE
- if(!keylog_file_fp) {
- keylog_file_name = curl_getenv("SSLKEYLOGFILE");
- if(keylog_file_name) {
- keylog_file_fp = fopen(keylog_file_name, FOPEN_APPENDTEXT);
- if(keylog_file_fp) {
-#ifdef WIN32
- if(setvbuf(keylog_file_fp, NULL, _IONBF, 0))
-#else
- if(setvbuf(keylog_file_fp, NULL, _IOLBF, 4096))
-#endif
- {
- fclose(keylog_file_fp);
- keylog_file_fp = NULL;
- }
- }
- Curl_safefree(keylog_file_name);
- }
- }
-#endif
+ Curl_tls_keylog_open();
/* Initialize the extra data indexes */
if(ossl_get_ssl_conn_index() < 0 || ossl_get_ssl_sockindex_index() < 0)
@@ -1117,12 +1173,7 @@ static void Curl_ossl_cleanup(void)
#endif
#endif
-#ifdef ENABLE_SSLKEYLOGFILE
- if(keylog_file_fp) {
- fclose(keylog_file_fp);
- keylog_file_fp = NULL;
- }
-#endif
+ Curl_tls_keylog_close();
}
/*
@@ -1289,7 +1340,9 @@ static void ossl_close(struct ssl_connect_data *connssl)
static void Curl_ossl_close(struct connectdata *conn, int sockindex)
{
ossl_close(&conn->ssl[sockindex]);
+#ifndef CURL_DISABLE_PROXY
ossl_close(&conn->proxy_ssl[sockindex]);
+#endif
}
/*
@@ -1516,10 +1569,16 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
CURLcode result = CURLE_OK;
bool dNSName = FALSE; /* if a dNSName field exists in the cert */
bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */
- const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
- conn->host.name;
+#ifndef CURL_DISABLE_PROXY
+ const char * const hostname = SSL_IS_PROXY() ?
+ conn->http_proxy.host.name : conn->host.name;
const char * const dispname = SSL_IS_PROXY() ?
conn->http_proxy.host.dispname : conn->host.dispname;
+#else
+ /* disabled proxy support */
+ const char * const hostname = conn->host.name;
+ const char * const dispname = conn->host.dispname;
+#endif
#ifdef ENABLE_IPV6
if(conn->bits.ipv6_ip &&
@@ -1577,7 +1636,7 @@ static CURLcode verifyhost(struct connectdata *conn, X509 *server_cert)
type itself: for example for an IA5String the data will be ASCII"
It has been however verified that in 0.9.6 and 0.9.7, IA5String
- is always zero-terminated.
+ is always null-terminated.
*/
if((altlen == strlen(altptr)) &&
/* if this isn't true, there was an embedded zero in the name
@@ -2398,21 +2457,31 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
bool sni;
+#ifndef CURL_DISABLE_PROXY
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
+#else
+ const char * const hostname = conn->host.name;
+#endif
+
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
struct in_addr addr;
#endif
#endif
+#ifndef CURL_DISABLE_PROXY
long * const certverifyresult = SSL_IS_PROXY() ?
&data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
+#else
+ long * const certverifyresult = &data->set.ssl.certverifyresult;
+#endif
const long int ssl_version = SSL_CONN_CONFIG(version);
#ifdef USE_TLS_SRP
const enum CURL_TLSAUTH ssl_authtype = SSL_SET_OPTION(authtype);
#endif
char * const ssl_cert = SSL_SET_OPTION(cert);
+ const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(cert_blob);
const char * const ssl_cert_type = SSL_SET_OPTION(cert_type);
const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
@@ -2420,6 +2489,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
char error_buffer[256];
struct ssl_backend_data *backend = connssl->backend;
+ bool imported_native_ca = false;
DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
@@ -2634,8 +2704,11 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
unsigned char protocols[128];
#ifdef USE_NGHTTP2
- if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
- (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
+ if(data->set.httpversion >= CURL_HTTP_VERSION_2
+#ifndef CURL_DISABLE_PROXY
+ && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
+#endif
+ ) {
protocols[cur++] = NGHTTP2_PROTO_VERSION_ID_LEN;
memcpy(&protocols[cur], NGHTTP2_PROTO_VERSION_ID,
@@ -2657,10 +2730,33 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
}
#endif
- if(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))) {
+ if(ssl_cert || ssl_cert_blob || ssl_cert_type) {
+ BIO *ssl_cert_bio = NULL;
+ BIO *ssl_key_bio = NULL;
+ int result_cert_stuff;
+ if(ssl_cert_blob) {
+ /* the typecast of blob->len is fine since it is guaranteed to never be
+ larger than CURL_MAX_INPUT_LENGTH */
+ ssl_cert_bio = BIO_new_mem_buf(ssl_cert_blob->data,
+ (int)ssl_cert_blob->len);
+ if(!ssl_cert_bio)
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ if(SSL_SET_OPTION(key_blob)) {
+ ssl_key_bio = BIO_new_mem_buf(SSL_SET_OPTION(key_blob)->data,
+ (int)SSL_SET_OPTION(key_blob)->len);
+ if(!ssl_key_bio)
+ return CURLE_SSL_CERTPROBLEM;
+ }
+ result_cert_stuff = cert_stuff(conn, backend->ctx,
+ ssl_cert, ssl_cert_bio, ssl_cert_type,
+ SSL_SET_OPTION(key), ssl_key_bio,
+ SSL_SET_OPTION(key_type), SSL_SET_OPTION(key_passwd));
+ if(ssl_cert_bio)
+ BIO_free(ssl_cert_bio);
+ if(ssl_key_bio)
+ BIO_free(ssl_key_bio);
+ if(!result_cert_stuff) {
/* failf() is already done in cert_stuff() */
return CURLE_SSL_CERTPROBLEM;
}
@@ -2720,38 +2816,186 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
}
#endif
+
+#if defined(USE_WIN32_CRYPTO)
+ /* Import certificates from the Windows root certificate store if requested.
+ https://stackoverflow.com/questions/9507184/
+ https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037
+ https://tools.ietf.org/html/rfc5280 */
+ if((SSL_CONN_CONFIG(verifypeer) || SSL_CONN_CONFIG(verifyhost)) &&
+ (SSL_SET_OPTION(native_ca_store))) {
+ X509_STORE *store = SSL_CTX_get_cert_store(backend->ctx);
+ HCERTSTORE hStore = CertOpenSystemStoreA((HCRYPTPROV_LEGACY)NULL, "ROOT");
+
+ if(hStore) {
+ PCCERT_CONTEXT pContext = NULL;
+ /* The array of enhanced key usage OIDs will vary per certificate and is
+ declared outside of the loop so that rather than malloc/free each
+ iteration we can grow it with realloc, when necessary. */
+ CERT_ENHKEY_USAGE *enhkey_usage = NULL;
+ DWORD enhkey_usage_size = 0;
+
+ /* This loop makes a best effort to import all valid certificates from
+ the MS root store. If a certificate cannot be imported it is skipped.
+ 'result' is used to store only hard-fail conditions (such as out of
+ memory) that cause an early break. */
+ result = CURLE_OK;
+ for(;;) {
+ X509 *x509;
+ FILETIME now;
+ BYTE key_usage[2];
+ DWORD req_size;
+ const unsigned char *encoded_cert;
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ char cert_name[256];
+#endif
+
+ pContext = CertEnumCertificatesInStore(hStore, pContext);
+ if(!pContext)
+ break;
+
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
+ NULL, cert_name, sizeof(cert_name))) {
+ strcpy(cert_name, "Unknown");
+ }
+ infof(data, "SSL: Checking cert \"%s\"\n", cert_name);
+#endif
+
+ encoded_cert = (const unsigned char *)pContext->pbCertEncoded;
+ if(!encoded_cert)
+ continue;
+
+ GetSystemTimeAsFileTime(&now);
+ if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 ||
+ CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0)
+ continue;
+
+ /* If key usage exists check for signing attribute */
+ if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType,
+ pContext->pCertInfo,
+ key_usage, sizeof(key_usage))) {
+ if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
+ continue;
+ }
+ else if(GetLastError())
+ continue;
+
+ /* If enhanced key usage exists check for server auth attribute.
+ *
+ * Note "In a Microsoft environment, a certificate might also have EKU
+ * extended properties that specify valid uses for the certificate."
+ * The call below checks both, and behavior varies depending on what is
+ * found. For more details see CertGetEnhancedKeyUsage doc.
+ */
+ if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) {
+ if(req_size && req_size > enhkey_usage_size) {
+ void *tmp = realloc(enhkey_usage, req_size);
+
+ if(!tmp) {
+ failf(data, "SSL: Out of memory allocating for OID list");
+ result = CURLE_OUT_OF_MEMORY;
+ break;
+ }
+
+ enhkey_usage = (CERT_ENHKEY_USAGE *)tmp;
+ enhkey_usage_size = req_size;
+ }
+
+ if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) {
+ if(!enhkey_usage->cUsageIdentifier) {
+ /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate is
+ good for all uses. If it returns zero, the certificate has no
+ valid uses." */
+ if(GetLastError() != CRYPT_E_NOT_FOUND)
+ continue;
+ }
+ else {
+ DWORD i;
+ bool found = false;
+
+ for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) {
+ if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */,
+ enhkey_usage->rgpszUsageIdentifier[i])) {
+ found = true;
+ break;
+ }
+ }
+
+ if(!found)
+ continue;
+ }
+ }
+ else
+ continue;
+ }
+ else
+ continue;
+
+ x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
+ if(!x509)
+ continue;
+
+ /* Try to import the certificate. This may fail for legitimate reasons
+ such as duplicate certificate, which is allowed by MS but not
+ OpenSSL. */
+ if(X509_STORE_add_cert(store, x509) == 1) {
+#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
+ infof(data, "SSL: Imported cert \"%s\"\n", cert_name);
+#endif
+ imported_native_ca = true;
+ }
+ X509_free(x509);
+ }
+
+ free(enhkey_usage);
+ CertFreeCertificateContext(pContext);
+ CertCloseStore(hStore, 0);
+
+ if(result)
+ return result;
+ }
+ if(imported_native_ca)
+ infof(data, "successfully imported windows ca store\n");
+ else
+ infof(data, "error importing windows ca store, continuing anyway\n");
+ }
+#endif
+
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
/* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
- if(ssl_cafile) {
- if(!SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) {
- if(verifypeer) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate file: %s", ssl_cafile);
- return CURLE_SSL_CACERT_BADFILE;
+ {
+ if(ssl_cafile) {
+ if(!SSL_CTX_load_verify_file(backend->ctx, ssl_cafile)) {
+ if(verifypeer) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate file: %s", ssl_cafile);
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ /* Continue with a warning if no certificate verif is required. */
+ infof(data, "error setting certificate file, continuing anyway\n");
}
- /* Continue with a warning if no certificate verification is required. */
- infof(data, "error setting certificate file, continuing anyway\n");
+ infof(data, " CAfile: %s\n", ssl_cafile);
}
- infof(data, " CAfile: %s\n", ssl_cafile);
- }
- if(ssl_capath) {
- if(!SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
- if(verifypeer) {
- /* Fail if we insist on successfully verifying the server. */
- failf(data, "error setting certificate path: %s", ssl_capath);
- return CURLE_SSL_CACERT_BADFILE;
+ if(ssl_capath) {
+ if(!SSL_CTX_load_verify_dir(backend->ctx, ssl_capath)) {
+ if(verifypeer) {
+ /* Fail if we insist on successfully verifying the server. */
+ failf(data, "error setting certificate path: %s", ssl_capath);
+ return CURLE_SSL_CACERT_BADFILE;
+ }
+ /* Continue with a warning if no certificate verif is required. */
+ infof(data, "error setting certificate path, continuing anyway\n");
}
- /* Continue with a warning if no certificate verification is required. */
- infof(data, "error setting certificate path, continuing anyway\n");
+ infof(data, " CApath: %s\n", ssl_capath);
}
- infof(data, " CApath: %s\n", ssl_capath);
}
#else
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(backend->ctx, ssl_cafile, ssl_capath)) {
- if(verifypeer) {
+ if(verifypeer && !imported_native_ca) {
/* Fail if we insist on successfully verifying the server. */
failf(data, "error setting certificate verify locations:\n"
" CAfile: %s\n CApath: %s",
@@ -2759,7 +3003,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
ssl_capath ? ssl_capath : "none");
return CURLE_SSL_CACERT_BADFILE;
}
- /* Just continue with a warning if no strict certificate verification
+ /* Just continue with a warning if no strict certificate verification
is required. */
infof(data, "error setting certificate verify locations,"
" continuing anyway:\n");
@@ -2777,7 +3021,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
#endif
#ifdef CURL_CA_FALLBACK
- else if(verifypeer) {
+ if(verifypeer && !ssl_cafile && !ssl_capath && !imported_native_ca) {
/* verifying the peer without any CA certificates won't
work so use openssl's built in default as fallback */
SSL_CTX_set_default_verify_paths(backend->ctx);
@@ -2805,21 +3049,24 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
if(verifypeer) {
/* Try building a chain using issuers in the trusted store first to avoid
problems with server-sent legacy intermediates. Newer versions of
- OpenSSL do alternate chain checking by default which gives us the same
- fix without as much of a performance hit (slight), so we prefer that if
- available.
+ OpenSSL do alternate chain checking by default but we do not know how to
+ determine that in a reliable manner.
https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest
*/
-#if defined(X509_V_FLAG_TRUSTED_FIRST) && !defined(X509_V_FLAG_NO_ALT_CHAINS)
+#if defined(X509_V_FLAG_TRUSTED_FIRST)
X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
X509_V_FLAG_TRUSTED_FIRST);
#endif
#ifdef X509_V_FLAG_PARTIAL_CHAIN
- if(!SSL_SET_OPTION(no_partialchain)) {
+ if(!SSL_SET_OPTION(no_partialchain) && !ssl_crlfile) {
/* Have intermediate certificates in the trust store be treated as
trust-anchors, in the same way as self-signed root CA certificates
are. This allows users to verify servers using the intermediate cert
- only, instead of needing the whole chain. */
+ only, instead of needing the whole chain.
+
+ Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we
+ cannot do partial chains with CRL check.
+ */
X509_STORE_set_flags(SSL_CTX_get_cert_store(backend->ctx),
X509_V_FLAG_PARTIAL_CHAIN);
}
@@ -2834,8 +3081,8 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
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_fp) {
+#ifdef HAVE_KEYLOG_CALLBACK
+ if(Curl_tls_keylog_enabled()) {
SSL_CTX_set_keylog_callback(backend->ctx, ossl_keylog_callback);
}
#endif
@@ -2922,6 +3169,7 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
Curl_ssl_sessionid_unlock(conn);
}
+#ifndef CURL_DISABLE_PROXY
if(conn->proxy_ssl[sockindex].use) {
BIO *const bio = BIO_new(BIO_f_ssl());
SSL *handle = conn->proxy_ssl[sockindex].backend->handle;
@@ -2931,7 +3179,9 @@ static CURLcode ossl_connect_step1(struct connectdata *conn, int sockindex)
BIO_set_ssl(bio, handle, FALSE);
SSL_set_bio(backend->handle, bio, bio);
}
- else if(!SSL_set_fd(backend->handle, (int)sockfd)) {
+ else
+#endif
+ 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)));
@@ -2948,8 +3198,12 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
struct Curl_easy *data = conn->data;
int err;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+#ifndef CURL_DISABLE_PROXY
long * const certverifyresult = SSL_IS_PROXY() ?
&data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
+#else
+ long * const certverifyresult = &data->set.ssl.certverifyresult;
+#endif
struct ssl_backend_data *backend = connssl->backend;
DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
|| ssl_connect_2_reading == connssl->connecting_state
@@ -2958,10 +3212,13 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
ERR_clear_error();
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);
+#ifndef HAVE_KEYLOG_CALLBACK
+ if(Curl_tls_keylog_enabled()) {
+ /* If key logging is enabled, wait for the handshake to complete and then
+ * proceed with logging secrets (for TLS 1.2 or older).
+ */
+ ossl_log_tls12_secret(backend->handle, &backend->keylog_done);
+ }
#endif
/* 1 is fine
@@ -3032,9 +3289,14 @@ static CURLcode ossl_connect_step2(struct connectdata *conn, int sockindex)
* the SO_ERROR is also lost.
*/
if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
+#ifndef CURL_DISABLE_PROXY
const char * const hostname = SSL_IS_PROXY() ?
conn->http_proxy.host.name : conn->host.name;
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
+#else
+ const char * const hostname = conn->host.name;
+ const long int port = conn->remote_port;
+#endif
char extramsg[80]="";
int sockerr = SOCKERRNO;
if(sockerr && detail == SSL_ERROR_SYSCALL)
@@ -3487,8 +3749,12 @@ static CURLcode servercert(struct connectdata *conn,
char error_buffer[256]="";
char buffer[2048];
const char *ptr;
+#ifndef CURL_DISABLE_PROXY
long * const certverifyresult = SSL_IS_PROXY() ?
&data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
+#else
+ long * const certverifyresult = &data->set.ssl.certverifyresult;
+#endif
BIO *mem = BIO_new(BIO_s_mem());
struct ssl_backend_data *backend = connssl->backend;
@@ -3552,27 +3818,32 @@ static CURLcode servercert(struct connectdata *conn,
deallocating the certificate. */
/* e.g. match issuer name with provided issuer certificate */
- if(SSL_SET_OPTION(issuercert)) {
- fp = BIO_new(BIO_s_file());
- if(fp == NULL) {
- failf(data,
- "BIO_new return NULL, " OSSL_PACKAGE
- " error %s",
- ossl_strerror(ERR_get_error(), error_buffer,
- sizeof(error_buffer)) );
- X509_free(backend->server_cert);
- backend->server_cert = NULL;
- return CURLE_OUT_OF_MEMORY;
- }
+ if(SSL_SET_OPTION(issuercert) || SSL_SET_OPTION(issuercert_blob)) {
+ if(SSL_SET_OPTION(issuercert_blob))
+ fp = BIO_new_mem_buf(SSL_SET_OPTION(issuercert_blob)->data,
+ (int)SSL_SET_OPTION(issuercert_blob)->len);
+ else {
+ fp = BIO_new(BIO_s_file());
+ if(fp == NULL) {
+ failf(data,
+ "BIO_new return NULL, " OSSL_PACKAGE
+ " error %s",
+ ossl_strerror(ERR_get_error(), error_buffer,
+ sizeof(error_buffer)) );
+ X509_free(backend->server_cert);
+ backend->server_cert = NULL;
+ return CURLE_OUT_OF_MEMORY;
+ }
- if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) {
- if(strict)
- failf(data, "SSL: Unable to open issuer cert (%s)",
- SSL_SET_OPTION(issuercert));
- BIO_free(fp);
- X509_free(backend->server_cert);
- backend->server_cert = NULL;
- return CURLE_SSL_ISSUER_ERROR;
+ if(BIO_read_filename(fp, SSL_SET_OPTION(issuercert)) <= 0) {
+ if(strict)
+ failf(data, "SSL: Unable to open issuer cert (%s)",
+ SSL_SET_OPTION(issuercert));
+ BIO_free(fp);
+ X509_free(backend->server_cert);
+ backend->server_cert = NULL;
+ return CURLE_SSL_ISSUER_ERROR;
+ }
}
issuer = PEM_read_bio_X509(fp, NULL, ZERO_NULL, NULL);
@@ -3690,7 +3961,6 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
- timediff_t timeout_ms;
int what;
/* check if the connection has already been established */
@@ -3701,7 +3971,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
if(ssl_connect_1 == connssl->connecting_state) {
/* Find out how much more time we're allowed */
- timeout_ms = Curl_timeleft(data, NULL, TRUE);
+ const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
@@ -3719,7 +3989,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
ssl_connect_2_writing == connssl->connecting_state) {
/* check allowed time left */
- timeout_ms = Curl_timeleft(data, NULL, TRUE);
+ const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
@@ -3737,7 +4007,7 @@ static CURLcode ossl_connect_common(struct connectdata *conn,
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
- nonblocking?0:(time_t)timeout_ms);
+ nonblocking?0:timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
@@ -3816,14 +4086,15 @@ static bool Curl_ossl_data_pending(const struct connectdata *conn,
int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
- const struct ssl_connect_data *proxyssl = &conn->proxy_ssl[connindex];
-
if(connssl->backend->handle && SSL_pending(connssl->backend->handle))
return TRUE;
-
- if(proxyssl->backend->handle && SSL_pending(proxyssl->backend->handle))
- return TRUE;
-
+#ifndef CURL_DISABLE_PROXY
+ {
+ const struct ssl_connect_data *proxyssl = &conn->proxy_ssl[connindex];
+ if(proxyssl->backend->handle && SSL_pending(proxyssl->backend->handle))
+ return TRUE;
+ }
+#endif
return FALSE;
}
@@ -3884,8 +4155,11 @@ static ssize_t ossl_send(struct connectdata *conn,
sslerror = ERR_get_error();
if(ERR_GET_LIB(sslerror) == ERR_LIB_SSL &&
ERR_GET_REASON(sslerror) == SSL_R_BIO_NOT_SET &&
- conn->ssl[sockindex].state == ssl_connection_complete &&
- conn->proxy_ssl[sockindex].state == ssl_connection_complete) {
+ conn->ssl[sockindex].state == ssl_connection_complete
+#ifndef CURL_DISABLE_PROXY
+ && conn->proxy_ssl[sockindex].state == ssl_connection_complete
+#endif
+ ) {
char ver[120];
Curl_ossl_version(ver, 120);
failf(conn->data, "Error: %s does not support double SSL tunneling.",
@@ -4109,7 +4383,7 @@ static CURLcode Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
unsigned int len = 0;
(void) unused;
- mdctx = EVP_MD_CTX_create();
+ mdctx = EVP_MD_CTX_create();
EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
EVP_DigestUpdate(mdctx, tmp, tmplen);
EVP_DigestFinal_ex(mdctx, sha256sum, &len);
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index 49659bb7a..199652606 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -39,10 +39,11 @@
#include "schannel.h"
#include "vtls.h"
+#include "strcase.h"
#include "sendf.h"
#include "connect.h" /* for the connect timeout */
#include "strerror.h"
-#include "select.h" /* for the socket readyness */
+#include "select.h" /* for the socket readiness */
#include "inet_pton.h" /* for IP addr SNI check */
#include "curl_multibyte.h"
#include "warnless.h"
@@ -51,7 +52,7 @@
#include "multiif.h"
#include "system_win32.h"
- /* The last #include file should be: */
+/* The last #include file should be: */
#include "curl_memory.h"
#include "memdebug.h"
@@ -169,25 +170,25 @@ set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
long i = ssl_version;
switch(ssl_version_max) {
- case CURL_SSLVERSION_MAX_NONE:
- case CURL_SSLVERSION_MAX_DEFAULT:
- ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
- break;
+ case CURL_SSLVERSION_MAX_NONE:
+ case CURL_SSLVERSION_MAX_DEFAULT:
+ ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
+ break;
}
for(; i <= (ssl_version_max >> 16); ++i) {
switch(i) {
- case CURL_SSLVERSION_TLSv1_0:
- schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT;
- break;
- case CURL_SSLVERSION_TLSv1_1:
- schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT;
- break;
- case CURL_SSLVERSION_TLSv1_2:
- schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT;
- break;
- case CURL_SSLVERSION_TLSv1_3:
- failf(data, "schannel: TLS 1.3 is not yet supported");
- return CURLE_SSL_CONNECT_ERROR;
+ case CURL_SSLVERSION_TLSv1_0:
+ schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_0_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_1:
+ schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_1_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_2:
+ schannel_cred->grbitEnabledProtocols |= SP_PROT_TLS1_2_CLIENT;
+ break;
+ case CURL_SSLVERSION_TLSv1_3:
+ failf(data, "schannel: TLS 1.3 is not yet supported");
+ return CURLE_SSL_CONNECT_ERROR;
}
}
return CURLE_OK;
@@ -195,9 +196,9 @@ set_ssl_version_min_max(SCHANNEL_CRED *schannel_cred, struct connectdata *conn)
/*longest is 26, buffer is slightly bigger*/
#define LONGEST_ALG_ID 32
-#define CIPHEROPTION(X) \
-if(strcmp(#X, tmp) == 0) \
- return X
+#define CIPHEROPTION(X) \
+ if(strcmp(#X, tmp) == 0) \
+ return X
static int
get_alg_id_by_name(char *name)
@@ -273,11 +274,11 @@ get_alg_id_by_name(char *name)
#ifdef CALG_HMAC
CIPHEROPTION(CALG_HMAC);
#endif
-#if !defined(__W32API_MAJOR_VERSION) || \
- !defined(__W32API_MINOR_VERSION) || \
- defined(__MINGW64_VERSION_MAJOR) || \
- (__W32API_MAJOR_VERSION > 5) || \
- ((__W32API_MAJOR_VERSION == 5) && (__W32API_MINOR_VERSION > 0))
+#if !defined(__W32API_MAJOR_VERSION) || \
+ !defined(__W32API_MINOR_VERSION) || \
+ defined(__MINGW64_VERSION_MAJOR) || \
+ (__W32API_MAJOR_VERSION > 5) || \
+ ((__W32API_MAJOR_VERSION == 5) && (__W32API_MINOR_VERSION > 0))
/* CALG_TLS1PRF has a syntax error in MinGW's w32api up to version 5.0,
see https://osdn.net/projects/mingw/ticket/38391 */
CIPHEROPTION(CALG_TLS1PRF);
@@ -339,7 +340,7 @@ set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers)
if(startCur)
startCur++;
}
- schannel_cred->palgSupportedAlgs = algIds;
+ schannel_cred->palgSupportedAlgs = algIds;
schannel_cred->cSupportedAlgs = algCount;
return CURLE_OK;
}
@@ -424,8 +425,12 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
#endif
TCHAR *host_name;
CURLcode result;
+#ifndef CURL_DISABLE_PROXY
char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
+#else
+ char * const hostname = conn->host.name;
+#endif
DEBUGF(infof(data,
"schannel: SSL/TLS connection with %s port %hu (step 1/3)\n",
@@ -433,20 +438,20 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
if(Curl_verify_windows_version(5, 1, PLATFORM_WINNT,
VERSION_LESS_THAN_EQUAL)) {
- /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and
- algorithms that may not be supported by all servers. */
- infof(data, "schannel: Windows version is old and may not be able to "
- "connect to some servers due to lack of SNI, algorithms, etc.\n");
+ /* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and
+ algorithms that may not be supported by all servers. */
+ infof(data, "schannel: Windows version is old and may not be able to "
+ "connect to some servers due to lack of SNI, algorithms, etc.\n");
}
#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. */
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);
+ !GetProcAddress(GetModuleHandleA("ntdll"),
+ "wine_get_version") &&
+ Curl_verify_windows_version(6, 3, PLATFORM_WINNT,
+ VERSION_GREATER_THAN_EQUAL);
#else
BACKEND->use_alpn = false;
#endif
@@ -555,12 +560,12 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
case CURL_SSLVERSION_TLSv1_1:
case CURL_SSLVERSION_TLSv1_2:
case CURL_SSLVERSION_TLSv1_3:
- {
- result = set_ssl_version_min_max(&schannel_cred, conn);
- if(result != CURLE_OK)
- return result;
- break;
- }
+ {
+ result = set_ssl_version_min_max(&schannel_cred, conn);
+ if(result != CURLE_OK)
+ return result;
+ break;
+ }
case CURL_SSLVERSION_SSLv3:
schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT;
break;
@@ -583,105 +588,133 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
#ifdef HAS_CLIENT_CERT_PATH
/* client certificate */
- if(data->set.ssl.cert) {
- DWORD cert_store_name;
+ if(data->set.ssl.cert || data->set.ssl.cert_blob) {
+ DWORD cert_store_name = 0;
TCHAR *cert_store_path = NULL;
- TCHAR *cert_thumbprint_str;
+ TCHAR *cert_thumbprint_str = NULL;
CRYPT_HASH_BLOB cert_thumbprint;
BYTE cert_thumbprint_data[CERT_THUMBPRINT_DATA_LEN];
- HCERTSTORE cert_store;
+ HCERTSTORE cert_store = NULL;
FILE *fInCert = NULL;
+ void *certdata = NULL;
+ size_t certsize = 0;
+ bool blob = data->set.ssl.cert_blob != NULL;
+ TCHAR *cert_path = NULL;
+ if(blob) {
+ certdata = data->set.ssl.cert_blob->data;
+ certsize = data->set.ssl.cert_blob->len;
+ }
+ else {
+ cert_path = curlx_convert_UTF8_to_tchar(data->set.ssl.cert);
+ if(!cert_path)
+ return CURLE_OUT_OF_MEMORY;
- TCHAR *cert_path = Curl_convert_UTF8_to_tchar(data->set.ssl.cert);
- if(!cert_path)
- return CURLE_OUT_OF_MEMORY;
+ result = get_cert_location(cert_path, &cert_store_name,
+ &cert_store_path, &cert_thumbprint_str);
- result = get_cert_location(cert_path, &cert_store_name,
- &cert_store_path, &cert_thumbprint_str);
- if((result != CURLE_OK) && (data->set.ssl.cert[0]!='\0'))
- fInCert = fopen(data->set.ssl.cert, "rb");
+ if(result && (data->set.ssl.cert[0]!='\0'))
+ fInCert = fopen(data->set.ssl.cert, "rb");
- if((result != CURLE_OK) && (fInCert == NULL)) {
- failf(data, "schannel: Failed to get certificate location"
- " or file for %s",
- data->set.ssl.cert);
- Curl_unicodefree(cert_path);
- return result;
+ if(result && !fInCert) {
+ failf(data, "schannel: Failed to get certificate location"
+ " or file for %s",
+ data->set.ssl.cert);
+ curlx_unicodefree(cert_path);
+ return result;
+ }
}
- if(fInCert) {
+ if((fInCert || blob) && (data->set.ssl.cert_type) &&
+ (!strcasecompare(data->set.ssl.cert_type, "P12"))) {
+ failf(data, "schannel: certificate format compatibility error "
+ " for %s",
+ blob ? "(memory blob)" : data->set.ssl.cert);
+ curlx_unicodefree(cert_path);
+ return CURLE_SSL_CERTPROBLEM;
+ }
+
+ if(fInCert || blob) {
/* Reading a .P12 or .pfx file, like the example at bottom of
- https://social.msdn.microsoft.com/Forums/windowsdesktop/
- en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5
+ https://social.msdn.microsoft.com/Forums/windowsdesktop/
+ en-US/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5
*/
- void *certdata = NULL;
- long filesize = 0;
CRYPT_DATA_BLOB datablob;
WCHAR* pszPassword;
size_t pwd_len = 0;
int str_w_len = 0;
- int continue_reading = fseek(fInCert, 0, SEEK_END) == 0;
- if(continue_reading)
- filesize = ftell(fInCert);
- if(filesize < 0)
- continue_reading = 0;
- if(continue_reading)
- continue_reading = fseek(fInCert, 0, SEEK_SET) == 0;
- if(continue_reading)
- certdata = malloc(((size_t)filesize) + 1);
- if((certdata == NULL) ||
- ((int) fread(certdata, (size_t)filesize, 1, fInCert) != 1))
- continue_reading = 0;
- fclose(fInCert);
- Curl_unicodefree(cert_path);
-
- if(!continue_reading) {
- failf(data, "schannel: Failed to read cert file %s",
+ const char *cert_showfilename_error = blob ?
+ "(memory blob)" : data->set.ssl.cert;
+ curlx_unicodefree(cert_path);
+ if(fInCert) {
+ long cert_tell = 0;
+ bool continue_reading = fseek(fInCert, 0, SEEK_END) == 0;
+ if(continue_reading)
+ cert_tell = ftell(fInCert);
+ if(cert_tell < 0)
+ continue_reading = FALSE;
+ else
+ certsize = (size_t)cert_tell;
+ if(continue_reading)
+ continue_reading = fseek(fInCert, 0, SEEK_SET) == 0;
+ if(continue_reading)
+ certdata = malloc(certsize + 1);
+ if((!certdata) ||
+ ((int) fread(certdata, certsize, 1, fInCert) != 1))
+ continue_reading = FALSE;
+ fclose(fInCert);
+ if(!continue_reading) {
+ failf(data, "schannel: Failed to read cert file %s",
data->set.ssl.cert);
- free(certdata);
- return CURLE_SSL_CERTPROBLEM;
+ free(certdata);
+ return CURLE_SSL_CERTPROBLEM;
+ }
}
/* Convert key-pair data to the in-memory certificate store */
datablob.pbData = (BYTE*)certdata;
- datablob.cbData = (DWORD)filesize;
+ datablob.cbData = (DWORD)certsize;
if(data->set.ssl.key_passwd != NULL)
pwd_len = strlen(data->set.ssl.key_passwd);
pszPassword = (WCHAR*)malloc(sizeof(WCHAR)*(pwd_len + 1));
- if(pwd_len > 0)
- str_w_len =
- MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
- data->set.ssl.key_passwd, (int)pwd_len,
- pszPassword, (int)(pwd_len + 1));
-
- if((str_w_len >= 0) && (str_w_len <= (int)pwd_len))
- pszPassword[str_w_len] = 0;
- else
- pszPassword[0] = 0;
-
- cert_store = PFXImportCertStore(&datablob, pszPassword, 0);
- free(pszPassword);
- free(certdata);
+ if(pszPassword) {
+ if(pwd_len > 0)
+ str_w_len = MultiByteToWideChar(CP_UTF8,
+ MB_ERR_INVALID_CHARS,
+ data->set.ssl.key_passwd, (int)pwd_len,
+ pszPassword, (int)(pwd_len + 1));
+
+ if((str_w_len >= 0) && (str_w_len <= (int)pwd_len))
+ pszPassword[str_w_len] = 0;
+ else
+ pszPassword[0] = 0;
+
+ cert_store = PFXImportCertStore(&datablob, pszPassword, 0);
+ free(pszPassword);
+ }
+ if(!blob)
+ free(certdata);
if(cert_store == NULL) {
DWORD errorcode = GetLastError();
if(errorcode == ERROR_INVALID_PASSWORD)
failf(data, "schannel: Failed to import cert file %s, "
- "password is bad", data->set.ssl.cert);
+ "password is bad",
+ cert_showfilename_error);
else
failf(data, "schannel: Failed to import cert file %s, "
- "last error is 0x%x", data->set.ssl.cert, errorcode);
+ "last error is 0x%x",
+ cert_showfilename_error, errorcode);
return CURLE_SSL_CERTPROBLEM;
}
client_certs[0] = CertFindCertificateInStore(
- cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
- CERT_FIND_ANY, NULL, NULL);
+ cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
+ CERT_FIND_ANY, NULL, NULL);
if(client_certs[0] == NULL) {
failf(data, "schannel: Failed to get certificate from file %s"
", last error is 0x%x",
- data->set.ssl.cert, GetLastError());
+ cert_showfilename_error, GetLastError());
CertCloseStore(cert_store, 0);
return CURLE_SSL_CERTPROBLEM;
}
@@ -700,7 +733,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
"last error is 0x%x",
cert_store_name, cert_store_path, GetLastError());
free(cert_store_path);
- Curl_unicodefree(cert_path);
+ curlx_unicodefree(cert_path);
return CURLE_SSL_CERTPROBLEM;
}
free(cert_store_path);
@@ -714,7 +747,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
cert_thumbprint_data,
&cert_thumbprint.cbData,
NULL, NULL)) {
- Curl_unicodefree(cert_path);
+ curlx_unicodefree(cert_path);
CertCloseStore(cert_store, 0);
return CURLE_SSL_CERTPROBLEM;
}
@@ -723,7 +756,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
CERT_FIND_HASH, &cert_thumbprint, NULL);
- Curl_unicodefree(cert_path);
+ curlx_unicodefree(cert_path);
if(client_certs[0]) {
schannel_cred.cCreds = 1;
@@ -758,7 +791,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
BACKEND->cred->refcount = 1;
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx
- */
+ */
sspi_status =
s_pSecFn->AcquireCredentialsHandle(NULL, (TCHAR *)UNISP_NAME,
SECPKG_CRED_OUTBOUND, NULL,
@@ -775,15 +808,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
Curl_safefree(BACKEND->cred);
switch(sspi_status) {
- case SEC_E_INSUFFICIENT_MEMORY:
- return CURLE_OUT_OF_MEMORY;
- case SEC_E_NO_CREDENTIALS:
- case SEC_E_SECPKG_NOT_FOUND:
- case SEC_E_NOT_OWNER:
- case SEC_E_UNKNOWN_CREDENTIALS:
- case SEC_E_INTERNAL_ERROR:
- default:
- return CURLE_SSL_CONNECT_ERROR;
+ case SEC_E_INSUFFICIENT_MEMORY:
+ return CURLE_OUT_OF_MEMORY;
+ case SEC_E_NO_CREDENTIALS:
+ case SEC_E_SECPKG_NOT_FOUND:
+ case SEC_E_NOT_OWNER:
+ case SEC_E_UNKNOWN_CREDENTIALS:
+ case SEC_E_INTERNAL_ERROR:
+ default:
+ return CURLE_SSL_CONNECT_ERROR;
}
}
}
@@ -867,7 +900,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_OUT_OF_MEMORY;
}
- host_name = Curl_convert_UTF8_to_tchar(hostname);
+ host_name = curlx_convert_UTF8_to_tchar(hostname);
if(!host_name)
return CURLE_OUT_OF_MEMORY;
@@ -884,35 +917,35 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
0, &BACKEND->ctxt->ctxt_handle,
&outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
- Curl_unicodefree(host_name);
+ curlx_unicodefree(host_name);
if(sspi_status != SEC_I_CONTINUE_NEEDED) {
char buffer[STRERROR_LEN];
Curl_safefree(BACKEND->ctxt);
switch(sspi_status) {
- case SEC_E_INSUFFICIENT_MEMORY:
- failf(data, "schannel: initial InitializeSecurityContext failed: %s",
- Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
- return CURLE_OUT_OF_MEMORY;
- case SEC_E_WRONG_PRINCIPAL:
- failf(data, "schannel: SNI or certificate check failed: %s",
- Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
- return CURLE_PEER_FAILED_VERIFICATION;
- /*
- case SEC_E_INVALID_HANDLE:
- case SEC_E_INVALID_TOKEN:
- case SEC_E_LOGON_DENIED:
- case SEC_E_TARGET_UNKNOWN:
- case SEC_E_NO_AUTHENTICATING_AUTHORITY:
- case SEC_E_INTERNAL_ERROR:
- case SEC_E_NO_CREDENTIALS:
- case SEC_E_UNSUPPORTED_FUNCTION:
- case SEC_E_APPLICATION_PROTOCOL_MISMATCH:
- */
- default:
- failf(data, "schannel: initial InitializeSecurityContext failed: %s",
- Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
- return CURLE_SSL_CONNECT_ERROR;
+ case SEC_E_INSUFFICIENT_MEMORY:
+ failf(data, "schannel: initial InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
+ return CURLE_OUT_OF_MEMORY;
+ case SEC_E_WRONG_PRINCIPAL:
+ failf(data, "schannel: SNI or certificate check failed: %s",
+ Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
+ return CURLE_PEER_FAILED_VERIFICATION;
+ /*
+ case SEC_E_INVALID_HANDLE:
+ case SEC_E_INVALID_TOKEN:
+ case SEC_E_LOGON_DENIED:
+ case SEC_E_TARGET_UNKNOWN:
+ case SEC_E_NO_AUTHENTICATING_AUTHORITY:
+ case SEC_E_INTERNAL_ERROR:
+ case SEC_E_NO_CREDENTIALS:
+ case SEC_E_UNSUPPORTED_FUNCTION:
+ case SEC_E_APPLICATION_PROTOCOL_MISMATCH:
+ */
+ default:
+ failf(data, "schannel: initial InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
+ return CURLE_SSL_CONNECT_ERROR;
}
}
@@ -958,8 +991,12 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
SECURITY_STATUS sspi_status = SEC_E_OK;
CURLcode result;
bool doread;
+#ifndef CURL_DISABLE_PROXY
char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
+#else
+ char * const hostname = conn->host.name;
+#endif
const char *pubkey_ptr;
doread = (connssl->connecting_state != ssl_connect_2_writing) ? TRUE : FALSE;
@@ -1067,18 +1104,18 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
memcpy(inbuf[0].pvBuffer, BACKEND->encdata_buffer,
BACKEND->encdata_offset);
- host_name = Curl_convert_UTF8_to_tchar(hostname);
+ host_name = curlx_convert_UTF8_to_tchar(hostname);
if(!host_name)
return CURLE_OUT_OF_MEMORY;
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx
- */
+ */
sspi_status = s_pSecFn->InitializeSecurityContext(
&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);
+ curlx_unicodefree(host_name);
/* free buffer for received handshake data */
Curl_safefree(inbuf[0].pvBuffer);
@@ -1133,29 +1170,29 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
else {
char buffer[STRERROR_LEN];
switch(sspi_status) {
- case SEC_E_INSUFFICIENT_MEMORY:
- failf(data, "schannel: next InitializeSecurityContext failed: %s",
- Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
- return CURLE_OUT_OF_MEMORY;
- case SEC_E_WRONG_PRINCIPAL:
- failf(data, "schannel: SNI or certificate check failed: %s",
- Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
- return CURLE_PEER_FAILED_VERIFICATION;
- /*
- case SEC_E_INVALID_HANDLE:
- case SEC_E_INVALID_TOKEN:
- case SEC_E_LOGON_DENIED:
- case SEC_E_TARGET_UNKNOWN:
- case SEC_E_NO_AUTHENTICATING_AUTHORITY:
- case SEC_E_INTERNAL_ERROR:
- case SEC_E_NO_CREDENTIALS:
- case SEC_E_UNSUPPORTED_FUNCTION:
- case SEC_E_APPLICATION_PROTOCOL_MISMATCH:
- */
- default:
- failf(data, "schannel: next InitializeSecurityContext failed: %s",
- Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
- return CURLE_SSL_CONNECT_ERROR;
+ case SEC_E_INSUFFICIENT_MEMORY:
+ failf(data, "schannel: next InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
+ return CURLE_OUT_OF_MEMORY;
+ case SEC_E_WRONG_PRINCIPAL:
+ failf(data, "schannel: SNI or certificate check failed: %s",
+ Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
+ return CURLE_PEER_FAILED_VERIFICATION;
+ /*
+ case SEC_E_INVALID_HANDLE:
+ case SEC_E_INVALID_TOKEN:
+ case SEC_E_LOGON_DENIED:
+ case SEC_E_TARGET_UNKNOWN:
+ case SEC_E_NO_AUTHENTICATING_AUTHORITY:
+ case SEC_E_INTERNAL_ERROR:
+ case SEC_E_NO_CREDENTIALS:
+ case SEC_E_UNSUPPORTED_FUNCTION:
+ case SEC_E_APPLICATION_PROTOCOL_MISMATCH:
+ */
+ default:
+ failf(data, "schannel: next InitializeSecurityContext failed: %s",
+ Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
+ return CURLE_SSL_CONNECT_ERROR;
}
}
@@ -1324,8 +1361,10 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
#ifdef HAS_ALPN
if(BACKEND->use_alpn) {
- sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
- SECPKG_ATTR_APPLICATION_PROTOCOL, &alpn_result);
+ sspi_status =
+ s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
+ SECPKG_ATTR_APPLICATION_PROTOCOL,
+ &alpn_result);
if(sspi_status != SEC_E_OK) {
failf(data, "schannel: failed to retrieve ALPN result");
@@ -1336,21 +1375,21 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
SecApplicationProtocolNegotiationStatus_Success) {
infof(data, "schannel: ALPN, server accepted to use %.*s\n",
- alpn_result.ProtocolIdSize, alpn_result.ProtocolId);
+ alpn_result.ProtocolIdSize, alpn_result.ProtocolId);
#ifdef USE_NGHTTP2
if(alpn_result.ProtocolIdSize == NGHTTP2_PROTO_VERSION_ID_LEN &&
!memcmp(NGHTTP2_PROTO_VERSION_ID, alpn_result.ProtocolId,
- NGHTTP2_PROTO_VERSION_ID_LEN)) {
+ NGHTTP2_PROTO_VERSION_ID_LEN)) {
conn->negnpn = CURL_HTTP_VERSION_2;
}
else
#endif
- if(alpn_result.ProtocolIdSize == ALPN_HTTP_1_1_LENGTH &&
- !memcmp(ALPN_HTTP_1_1, alpn_result.ProtocolId,
- ALPN_HTTP_1_1_LENGTH)) {
- conn->negnpn = CURL_HTTP_VERSION_1_1;
- }
+ if(alpn_result.ProtocolIdSize == ALPN_HTTP_1_1_LENGTH &&
+ !memcmp(ALPN_HTTP_1_1, alpn_result.ProtocolId,
+ ALPN_HTTP_1_1_LENGTH)) {
+ conn->negnpn = CURL_HTTP_VERSION_1_1;
+ }
}
else
infof(data, "ALPN, server did not agree to a protocol\n");
@@ -1397,8 +1436,10 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
if(data->set.ssl.certinfo) {
int certs_count = 0;
- sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
- SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context);
+ 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)) {
failf(data, "schannel: failed to retrieve remote cert context");
@@ -1481,7 +1522,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
connssl->connecting_state ? sockfd : CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
- nonblocking ? 0 : (time_t)timeout_ms);
+ nonblocking ? 0 : timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL/TLS socket, errno: %d", SOCKERRNO);
@@ -1630,13 +1671,9 @@ schannel_send(struct connectdata *conn, int sockindex,
/* send entire message or fail */
while(len > (size_t)written) {
- ssize_t this_write;
- timediff_t timeout_ms;
+ ssize_t this_write = 0;
int what;
-
- this_write = 0;
-
- timeout_ms = Curl_timeleft(conn->data, NULL, FALSE);
+ timediff_t timeout_ms = Curl_timeleft(conn->data, NULL, FALSE);
if(timeout_ms < 0) {
/* we already got the timeout */
failf(conn->data, "schannel: timed out sending data "
@@ -1645,7 +1682,7 @@ schannel_send(struct connectdata *conn, int sockindex,
written = -1;
break;
}
- if(!timeout_ms)
+ else if(!timeout_ms)
timeout_ms = TIMEDIFF_T_MAX;
what = SOCKET_WRITABLE(conn->sock[sockindex], timeout_ms);
if(what < 0) {
@@ -1741,8 +1778,8 @@ schannel_recv(struct connectdata *conn, int sockindex,
}
else if(!len) {
/* It's debatable what to return when !len. Regardless we can't return
- immediately because there may be data to decrypt (in the case we want to
- decrypt all encrypted cached data) so handle !len later in cleanup.
+ immediately because there may be data to decrypt (in the case we want to
+ decrypt all encrypted cached data) so handle !len later in cleanup.
*/
; /* do nothing */
}
@@ -1752,7 +1789,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
if(size < CURL_SCHANNEL_BUFFER_FREE_SIZE ||
BACKEND->encdata_length < min_encdata_length) {
reallocated_length = BACKEND->encdata_offset +
- CURL_SCHANNEL_BUFFER_FREE_SIZE;
+ CURL_SCHANNEL_BUFFER_FREE_SIZE;
if(reallocated_length < min_encdata_length) {
reallocated_length = min_encdata_length;
}
@@ -1820,7 +1857,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
InitSecBufferDesc(&inbuf_desc, inbuf, 4);
/* https://msdn.microsoft.com/en-us/library/windows/desktop/aa375348.aspx
- */
+ */
sspi_status = s_pSecFn->DecryptMessage(&BACKEND->ctxt->ctxt_handle,
&inbuf_desc, 0, NULL);
@@ -1836,7 +1873,7 @@ 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;
+ inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_FREE_SIZE;
if(BACKEND->decdata_length - BACKEND->decdata_offset < size ||
BACKEND->decdata_length < len) {
/* increase internal decrypted data buffer */
@@ -1906,7 +1943,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
if(BACKEND->encdata_offset) {
*err = CURLE_RECV_ERROR;
infof(data, "schannel: can't renogotiate, "
- "encrypted data available\n");
+ "encrypted data available\n");
goto cleanup;
}
/* begin renegotiation */
@@ -1961,17 +1998,20 @@ schannel_recv(struct connectdata *conn, int sockindex,
"schannel: decrypted data buffer: offset %zu length %zu\n",
BACKEND->decdata_offset, BACKEND->decdata_length));
-cleanup:
+ cleanup:
/* Warning- there is no guarantee the encdata state is valid at this point */
DEBUGF(infof(data, "schannel: schannel_recv cleanup\n"));
/* Error if the connection has closed without a close_notify.
- Behavior here is a matter of debate. We don't want to be vulnerable to a
- truncation attack however there's some browser precedent for ignoring the
- close_notify for compatibility reasons.
- Additionally, Windows 2000 (v5.0) is a special case since it seems it doesn't
- 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.
+
+ The behavior here is a matter of debate. We don't want to be vulnerable
+ to a truncation attack however there's some browser precedent for
+ ignoring the close_notify for compatibility reasons.
+
+ Additionally, Windows 2000 (v5.0) is a special case since it seems it
+ doesn't 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 && !BACKEND->decdata_offset && BACKEND->recv_connection_closed &&
!BACKEND->recv_sspi_close_notify) {
@@ -1988,7 +2028,7 @@ cleanup:
/* Any error other than CURLE_AGAIN is an unrecoverable error. */
if(*err && *err != CURLE_AGAIN)
- BACKEND->recv_unrecoverable_err = *err;
+ BACKEND->recv_unrecoverable_err = *err;
size = len < BACKEND->decdata_offset ? len : BACKEND->decdata_offset;
if(size) {
@@ -2005,10 +2045,11 @@ cleanup:
}
if(!*err && !BACKEND->recv_connection_closed)
- *err = CURLE_AGAIN;
+ *err = CURLE_AGAIN;
- /* It's debatable what to return when !len. We could return whatever error we
- got from decryption but instead we override here so the return is consistent.
+ /* It's debatable what to return when !len. We could return whatever error
+ we got from decryption but instead we override here so the return is
+ consistent.
*/
if(!len)
*err = CURLE_OK;
@@ -2074,8 +2115,12 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
*/
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+#ifndef CURL_DISABLE_PROXY
char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
+#else
+ char * const hostname = conn->host.name;
+#endif
DEBUGASSERT(data);
@@ -2104,7 +2149,7 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
}
- host_name = Curl_convert_UTF8_to_tchar(hostname);
+ host_name = curlx_convert_UTF8_to_tchar(hostname);
if(!host_name)
return CURLE_OUT_OF_MEMORY;
@@ -2126,7 +2171,7 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
&BACKEND->ret_flags,
&BACKEND->ctxt->time_stamp);
- Curl_unicodefree(host_name);
+ curlx_unicodefree(host_name);
if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
/* send close message which is in output buffer */
@@ -2235,8 +2280,8 @@ static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
SECURITY_STATUS sspi_status;
const char *x509_der;
DWORD x509_der_len;
- curl_X509certificate x509_parsed;
- curl_asn1Element *pubkey;
+ struct Curl_X509certificate x509_parsed;
+ struct Curl_asn1Element *pubkey;
sspi_status =
s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
@@ -2252,7 +2297,7 @@ static CURLcode pkp_pin_peer_pubkey(struct connectdata *conn, int sockindex,
if(!(((pCertContextServer->dwCertEncodingType & X509_ASN_ENCODING) != 0) &&
- (pCertContextServer->cbCertEncoded > 0)))
+ (pCertContextServer->cbCertEncoded > 0)))
break;
x509_der = (const char *)pCertContextServer->pbCertEncoded;
@@ -2343,9 +2388,9 @@ static CURLcode Curl_schannel_md5sum(unsigned char *input,
}
static CURLcode Curl_schannel_sha256sum(const unsigned char *input,
- size_t inputlen,
- unsigned char *sha256sum,
- size_t sha256len)
+ size_t inputlen,
+ unsigned char *sha256sum,
+ size_t sha256len)
{
Curl_schannel_checksum(input, inputlen, sha256sum, sha256len,
PROV_RSA_AES, CALG_SHA_256);
diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c
index 3dbc11f05..bdd7199e4 100644
--- a/lib/vtls/schannel_verify.c
+++ b/lib/vtls/schannel_verify.c
@@ -57,7 +57,7 @@
#define BEGIN_CERT "-----BEGIN CERTIFICATE-----"
#define END_CERT "\n-----END CERTIFICATE-----"
-typedef struct {
+struct cert_chain_engine_config_win7 {
DWORD cbSize;
HCERTSTORE hRestrictedRoot;
HCERTSTORE hRestrictedTrust;
@@ -70,7 +70,7 @@ typedef struct {
DWORD CycleDetectionModulus;
HCERTSTORE hExclusiveRoot;
HCERTSTORE hExclusiveTrustedPeople;
-} CERT_CHAIN_ENGINE_CONFIG_WIN7, *PCERT_CHAIN_ENGINE_CONFIG_WIN7;
+};
static int is_cr_or_lf(char c)
{
@@ -94,7 +94,7 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
int num_certs = 0;
size_t END_CERT_LEN;
- ca_file_tstr = Curl_convert_UTF8_to_tchar((char *)ca_file);
+ ca_file_tstr = curlx_convert_UTF8_to_tchar((char *)ca_file);
if(!ca_file_tstr) {
char buffer[STRERROR_LEN];
failf(data,
@@ -288,7 +288,7 @@ cleanup:
CloseHandle(ca_file_handle);
}
Curl_safefree(ca_file_buffer);
- Curl_unicodefree(ca_file_tstr);
+ curlx_unicodefree(ca_file_tstr);
return result;
}
@@ -361,7 +361,7 @@ static DWORD cert_get_name_string(struct Curl_easy *data,
return actual_length;
}
- decode_para.cbSize = sizeof(CRYPT_DECODE_PARA);
+ decode_para.cbSize = sizeof(CRYPT_DECODE_PARA);
ret_val =
CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
@@ -476,7 +476,7 @@ static CURLcode verify_host(struct Curl_easy *data,
* is acceptable since both values are assumed to use ASCII
* (or some equivalent) encoding
*/
- cert_hostname = Curl_convert_tchar_to_UTF8(
+ cert_hostname = curlx_convert_tchar_to_UTF8(
&cert_hostname_buff[cert_hostname_buff_index]);
if(!cert_hostname) {
result = CURLE_OUT_OF_MEMORY;
@@ -508,7 +508,7 @@ static CURLcode verify_host(struct Curl_easy *data,
result = CURLE_PEER_FAILED_VERIFICATION;
}
- Curl_unicodefree(cert_hostname);
+ curlx_unicodefree(cert_hostname);
}
}
@@ -522,7 +522,7 @@ static CURLcode verify_host(struct Curl_easy *data,
failf(data, "schannel: server certificate name verification failed");
cleanup:
- Curl_unicodefree(cert_hostname_buff);
+ curlx_unicodefree(cert_hostname_buff);
return result;
}
@@ -537,9 +537,13 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
const CERT_CHAIN_CONTEXT *pChainContext = NULL;
HCERTCHAINENGINE cert_chain_engine = NULL;
HCERTSTORE trust_store = NULL;
+#ifndef CURL_DISABLE_PROXY
const char * const conn_hostname = SSL_IS_PROXY() ?
conn->http_proxy.host.name :
conn->host.name;
+#else
+ const char * const conn_hostname = conn->host.name;
+#endif
sspi_status =
s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
@@ -585,7 +589,7 @@ CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex)
}
if(result == CURLE_OK) {
- CERT_CHAIN_ENGINE_CONFIG_WIN7 engine_config;
+ struct cert_chain_engine_config_win7 engine_config;
BOOL create_engine_result;
memset(&engine_config, 0, sizeof(engine_config));
diff --git a/lib/vtls/sectransp.c b/lib/vtls/sectransp.c
index 6b2d436fc..2627aff16 100644
--- a/lib/vtls/sectransp.c
+++ b/lib/vtls/sectransp.c
@@ -1126,12 +1126,12 @@ static OSStatus CopyIdentityWithLabel(char *label,
}
static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
+ const struct curl_blob *blob,
const char *cPassword,
SecIdentityRef *out_cert_and_key)
{
OSStatus status = errSecItemNotFound;
- CFURLRef pkcs_url = CFURLCreateFromFileSystemRepresentation(NULL,
- (const UInt8 *)cPath, strlen(cPath), false);
+ CFURLRef pkcs_url = NULL;
CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
cPassword, kCFStringEncodingUTF8) : NULL;
CFDataRef pkcs_data = NULL;
@@ -1140,8 +1140,26 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
/* These constants are documented as having first appeared in 10.6 but they
raise linker errors when used on that cat for some reason. */
#if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
- if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data,
- NULL, NULL, &status)) {
+ bool resource_imported;
+
+ if(blob) {
+ pkcs_data = CFDataCreate(kCFAllocatorDefault,
+ (const unsigned char *)blob->data, blob->len);
+ status = (pkcs_data != NULL) ? errSecSuccess : errSecAllocate;
+ resource_imported = (pkcs_data != NULL);
+ }
+ else {
+ pkcs_url =
+ CFURLCreateFromFileSystemRepresentation(NULL,
+ (const UInt8 *)cPath,
+ strlen(cPath), false);
+ resource_imported =
+ CFURLCreateDataAndPropertiesFromResource(NULL,
+ pkcs_url, &pkcs_data,
+ NULL, NULL, &status);
+ }
+
+ if(resource_imported) {
CFArrayRef items = NULL;
/* On iOS SecPKCS12Import will never add the client certificate to the
@@ -1219,7 +1237,8 @@ static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
#endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
if(password)
CFRelease(password);
- CFRelease(pkcs_url);
+ if(pkcs_url)
+ CFRelease(pkcs_url);
return status;
}
@@ -1376,8 +1395,10 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
+ const struct curl_blob *ssl_cablob = NULL;
const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
char * const ssl_cert = SSL_SET_OPTION(cert);
+ const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(cert_blob);
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
@@ -1612,15 +1633,16 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
"Transport. The private key must be in the Keychain.\n");
}
- if(ssl_cert) {
+ if(ssl_cert || ssl_cert_blob) {
+ bool is_cert_data = ssl_cert_blob != NULL;
+ bool is_cert_file = (!is_cert_data) && is_file(ssl_cert);
SecIdentityRef cert_and_key = NULL;
- bool is_cert_file = is_file(ssl_cert);
/* User wants to authenticate with a client cert. Look for it:
If we detect that this is a file on disk, then let's load it.
Otherwise, assume that the user wants to use an identity loaded
from the Keychain. */
- if(is_cert_file) {
+ if(is_cert_file || is_cert_data) {
if(!SSL_SET_OPTION(cert_type))
infof(data, "WARNING: SSL: Certificate type not set, assuming "
"PKCS#12 format.\n");
@@ -1629,7 +1651,7 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
infof(data, "WARNING: SSL: The Security framework only supports "
"loading identities that are in PKCS#12 format.\n");
- err = CopyIdentityFromPKCS12File(ssl_cert,
+ err = CopyIdentityFromPKCS12File(ssl_cert, ssl_cert_blob,
SSL_SET_OPTION(key_passwd), &cert_and_key);
}
else
@@ -1669,27 +1691,30 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
CFRelease(cert_and_key);
}
else {
+ const char *cert_showfilename_error =
+ is_cert_data ? "(memory blob)" : ssl_cert;
+
switch(err) {
case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
failf(data, "SSL: Incorrect password for the certificate \"%s\" "
- "and its private key.", ssl_cert);
+ "and its private key.", cert_showfilename_error);
break;
case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
failf(data, "SSL: Couldn't make sense of the data in the "
"certificate \"%s\" and its private key.",
- ssl_cert);
+ cert_showfilename_error);
break;
case -25260: /* errSecPassphraseRequired */
failf(data, "SSL The certificate \"%s\" requires a password.",
- ssl_cert);
+ cert_showfilename_error);
break;
case errSecItemNotFound:
failf(data, "SSL: Can't find the certificate \"%s\" and its private "
- "key in the Keychain.", ssl_cert);
+ "key in the Keychain.", cert_showfilename_error);
break;
default:
failf(data, "SSL: Can't load the certificate \"%s\" and its private "
- "key: OSStatus %d", ssl_cert, err);
+ "key: OSStatus %d", cert_showfilename_error, err);
break;
}
return CURLE_SSL_CERTPROBLEM;
@@ -1721,7 +1746,8 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
#else
if(SSLSetSessionOption != NULL) {
#endif /* CURL_BUILD_MAC */
- bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile;
+ bool break_on_auth = !conn->ssl_config.verifypeer ||
+ ssl_cafile || ssl_cablob;
err = SSLSetSessionOption(backend->ssl_ctx,
kSSLSessionOptionBreakOnServerAuth,
break_on_auth);
@@ -1749,10 +1775,11 @@ static CURLcode sectransp_connect_step1(struct connectdata *conn,
}
#endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
- if(ssl_cafile && verifypeer) {
- bool is_cert_file = is_file(ssl_cafile);
+ if((ssl_cafile || ssl_cablob) && verifypeer) {
+ bool is_cert_data = ssl_cablob != NULL;
+ bool is_cert_file = (!is_cert_data) && is_file(ssl_cafile);
- if(!is_cert_file) {
+ if(!(is_cert_file || is_cert_data)) {
failf(data, "SSL: can't load CA certificate file %s", ssl_cafile);
return CURLE_SSL_CACERT_BADFILE;
}
@@ -2809,7 +2836,6 @@ sectransp_connect_common(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
- timediff_t timeout_ms;
int what;
/* check if the connection has already been established */
@@ -2820,7 +2846,7 @@ sectransp_connect_common(struct connectdata *conn,
if(ssl_connect_1 == connssl->connecting_state) {
/* Find out how much more time we're allowed */
- timeout_ms = Curl_timeleft(data, NULL, TRUE);
+ const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
@@ -2838,7 +2864,7 @@ sectransp_connect_common(struct connectdata *conn,
ssl_connect_2_writing == connssl->connecting_state) {
/* check allowed time left */
- timeout_ms = Curl_timeleft(data, NULL, TRUE);
+ const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
@@ -2856,7 +2882,7 @@ sectransp_connect_common(struct connectdata *conn,
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
- nonblocking?0:(time_t)timeout_ms);
+ nonblocking ? 0 : timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
index f1b525227..c3a55fb1c 100644
--- a/lib/vtls/vtls.c
+++ b/lib/vtls/vtls.c
@@ -63,6 +63,7 @@
#include "warnless.h"
#include "curl_base64.h"
#include "curl_printf.h"
+#include "strdup.h"
/* The last #include files should be: */
#include "curl_memory.h"
@@ -82,15 +83,54 @@
else \
dest->var = NULL;
+#define CLONE_BLOB(var) \
+ if(blobdup(&dest->var, source->var)) \
+ return FALSE;
+
+static CURLcode blobdup(struct curl_blob **dest,
+ struct curl_blob *src)
+{
+ DEBUGASSERT(dest);
+ DEBUGASSERT(!*dest);
+ if(src) {
+ /* only if there's data to dupe! */
+ struct curl_blob *d;
+ d = malloc(sizeof(struct curl_blob) + src->len);
+ if(!d)
+ return CURLE_OUT_OF_MEMORY;
+ d->len = src->len;
+ /* Always duplicate because the connection may survive longer than the
+ handle that passed in the blob. */
+ d->flags = CURL_BLOB_COPY;
+ d->data = (void *)((char *)d + sizeof(struct curl_blob));
+ memcpy(d->data, src->data, src->len);
+ *dest = d;
+ }
+ return CURLE_OK;
+}
+
+/* returns TRUE if the blobs are identical */
+static bool blobcmp(struct curl_blob *first, struct curl_blob *second)
+{
+ if(!first && !second) /* both are NULL */
+ return TRUE;
+ if(!first || !second) /* one is NULL */
+ return FALSE;
+ if(first->len != second->len) /* different sizes */
+ return FALSE;
+ return !memcmp(first->data, second->data, first->len); /* same data */
+}
+
bool
-Curl_ssl_config_matches(struct ssl_primary_config* data,
- struct ssl_primary_config* needle)
+Curl_ssl_config_matches(struct ssl_primary_config *data,
+ struct ssl_primary_config *needle)
{
if((data->version == needle->version) &&
(data->version_max == needle->version_max) &&
(data->verifypeer == needle->verifypeer) &&
(data->verifyhost == needle->verifyhost) &&
(data->verifystatus == needle->verifystatus) &&
+ blobcmp(data->cert_blob, needle->cert_blob) &&
Curl_safe_strcasecompare(data->CApath, needle->CApath) &&
Curl_safe_strcasecompare(data->CAfile, needle->CAfile) &&
Curl_safe_strcasecompare(data->clientcert, needle->clientcert) &&
@@ -115,6 +155,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
dest->verifystatus = source->verifystatus;
dest->sessionid = source->sessionid;
+ CLONE_BLOB(cert_blob);
CLONE_STRING(CApath);
CLONE_STRING(CAfile);
CLONE_STRING(clientcert);
@@ -127,7 +168,7 @@ Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
return TRUE;
}
-void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
+void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
{
Curl_safefree(sslc->CApath);
Curl_safefree(sslc->CAfile);
@@ -137,6 +178,7 @@ void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc)
Curl_safefree(sslc->cipher_list);
Curl_safefree(sslc->cipher_list13);
Curl_safefree(sslc->pinned_key);
+ Curl_safefree(sslc->cert_blob);
}
#ifdef USE_SSL
@@ -215,6 +257,7 @@ static bool ssl_prefs_check(struct Curl_easy *data)
return TRUE;
}
+#ifndef CURL_DISABLE_PROXY
static CURLcode
ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
{
@@ -238,17 +281,20 @@ ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
}
return CURLE_OK;
}
+#endif
CURLcode
Curl_ssl_connect(struct connectdata *conn, int sockindex)
{
CURLcode result;
+#ifndef CURL_DISABLE_PROXY
if(conn->bits.proxy_ssl_connected[sockindex]) {
result = ssl_connect_init_proxy(conn, sockindex);
if(result)
return result;
}
+#endif
if(!ssl_prefs_check(conn->data))
return CURLE_SSL_CONNECT_ERROR;
@@ -270,12 +316,13 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
bool *done)
{
CURLcode result;
+#ifndef CURL_DISABLE_PROXY
if(conn->bits.proxy_ssl_connected[sockindex]) {
result = ssl_connect_init_proxy(conn, sockindex);
if(result)
return result;
}
-
+#endif
if(!ssl_prefs_check(conn->data))
return CURLE_SSL_CONNECT_ERROR;
@@ -321,13 +368,21 @@ bool Curl_ssl_getsessionid(struct connectdata *conn,
long *general_age;
bool no_match = TRUE;
+#ifndef CURL_DISABLE_PROXY
const bool isProxy = CONNECT_PROXY_SSL();
struct ssl_primary_config * const ssl_config = isProxy ?
&conn->proxy_ssl_config :
&conn->ssl_config;
- const char * const name = isProxy ? conn->http_proxy.host.name :
- conn->host.name;
+ const char * const name = isProxy ?
+ conn->http_proxy.host.name : conn->host.name;
int port = isProxy ? (int)conn->port : conn->remote_port;
+#else
+ /* no proxy support */
+ struct ssl_primary_config * const ssl_config = &conn->ssl_config;
+ const char * const name = conn->host.name;
+ int port = conn->remote_port;
+ (void)sockindex;
+#endif
*ssl_sessionid = NULL;
DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
@@ -429,14 +484,23 @@ CURLcode Curl_ssl_addsessionid(struct connectdata *conn,
char *clone_conn_to_host;
int conn_to_port;
long *general_age;
+#ifndef CURL_DISABLE_PROXY
const bool isProxy = CONNECT_PROXY_SSL();
struct ssl_primary_config * const ssl_config = isProxy ?
&conn->proxy_ssl_config :
&conn->ssl_config;
-
+ const char *hostname = isProxy ? conn->http_proxy.host.name :
+ conn->host.name;
+#else
+ /* proxy support disabled */
+ const bool isProxy = FALSE;
+ struct ssl_primary_config * const ssl_config = &conn->ssl_config;
+ const char *hostname = conn->host.name;
+ (void)sockindex;
+#endif
DEBUGASSERT(SSL_SET_OPTION(primary.sessionid));
- clone_host = strdup(isProxy ? conn->http_proxy.host.name : conn->host.name);
+ clone_host = strdup(hostname);
if(!clone_host)
return CURLE_OUT_OF_MEMORY; /* bail out */
@@ -684,7 +748,7 @@ CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num)
}
/*
- * 'value' is NOT a zero terminated string
+ * 'value' is NOT a null-terminated string
*/
CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
int certnum,
@@ -706,10 +770,10 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data,
/* sprintf the label and colon */
msnprintf(output, outlen, "%s:", label);
- /* memcpy the value (it might not be zero terminated) */
+ /* memcpy the value (it might not be null-terminated) */
memcpy(&output[labellen + 1], value, valuelen);
- /* zero terminate the output */
+ /* null-terminate the output */
output[labellen + 1 + valuelen] = 0;
nl = Curl_slist_append_nodup(ci->certinfo[certnum], output);
@@ -1084,7 +1148,7 @@ bool Curl_none_false_start(void)
CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
unsigned char *md5sum, size_t md5len UNUSED_PARAM)
{
- MD5_context *MD5pw;
+ struct MD5_context *MD5pw;
(void)md5len;
diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h
index a81b2f22d..bcc844416 100644
--- a/lib/vtls/vtls.h
+++ b/lib/vtls/vtls.h
@@ -113,12 +113,6 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
#define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */
#endif
-#ifndef MD5_DIGEST_LENGTH
-#ifndef LIBWOLFSSL_VERSION_HEX /* because WolfSSL borks this */
-#define MD5_DIGEST_LENGTH 16 /* fixed size */
-#endif
-#endif
-
#ifndef CURL_SHA256_DIGEST_LENGTH
#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */
#endif
@@ -129,20 +123,27 @@ CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen,
/* set of helper macros for the backends to access the correct fields. For the
proxy or for the remote host - to properly support HTTPS proxy */
+#ifndef CURL_DISABLE_PROXY
+#define SSL_IS_PROXY() \
+ (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \
+ ssl_connection_complete != \
+ conn->proxy_ssl[conn->sock[SECONDARYSOCKET] == \
+ CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state)
+#define SSL_SET_OPTION(var) \
+ (SSL_IS_PROXY() ? data->set.proxy_ssl.var : data->set.ssl.var)
+#define SSL_CONN_CONFIG(var) \
+ (SSL_IS_PROXY() ? conn->proxy_ssl_config.var : conn->ssl_config.var)
+#else
+#define SSL_IS_PROXY() FALSE
+#define SSL_SET_OPTION(var) data->set.ssl.var
+#define SSL_CONN_CONFIG(var) conn->ssl_config.var
+#endif
-#define SSL_IS_PROXY() (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \
- ssl_connection_complete != conn->proxy_ssl[conn->sock[SECONDARYSOCKET] == \
- CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state)
-#define SSL_SET_OPTION(var) (SSL_IS_PROXY() ? data->set.proxy_ssl.var : \
- data->set.ssl.var)
-#define SSL_CONN_CONFIG(var) (SSL_IS_PROXY() ? \
- conn->proxy_ssl_config.var : conn->ssl_config.var)
-
-bool Curl_ssl_config_matches(struct ssl_primary_config* data,
- struct ssl_primary_config* needle);
+bool Curl_ssl_config_matches(struct ssl_primary_config *data,
+ struct ssl_primary_config *needle);
bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
struct ssl_primary_config *dest);
-void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc);
+void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc);
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks);
int Curl_ssl_backend(void);
diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c
index 5040b0592..7b2a124e4 100644
--- a/lib/vtls/wolfssl.c
+++ b/lib/vtls/wolfssl.c
@@ -63,6 +63,7 @@
#include "sendf.h"
#include "inet_pton.h"
#include "vtls.h"
+#include "keylog.h"
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
@@ -99,6 +100,107 @@ struct ssl_backend_data {
static Curl_recv wolfssl_recv;
static Curl_send wolfssl_send;
+#ifdef OPENSSL_EXTRA
+/*
+ * Availability note:
+ * The TLS 1.3 secret callback (wolfSSL_set_tls13_secret_cb) was added in
+ * WolfSSL 4.4.0, but requires the -DHAVE_SECRET_CALLBACK build option. If that
+ * option is not set, then TLS 1.3 will not be logged.
+ * For TLS 1.2 and before, we use wolfSSL_get_keys().
+ * SSL_get_client_random and wolfSSL_get_keys require OPENSSL_EXTRA
+ * (--enable-opensslextra or --enable-all).
+ */
+#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
+static int
+wolfssl_tls13_secret_callback(SSL *ssl, int id, const unsigned char *secret,
+ int secretSz, void *ctx)
+{
+ const char *label;
+ unsigned char client_random[SSL3_RANDOM_SIZE];
+ (void)ctx;
+
+ if(!ssl || !Curl_tls_keylog_enabled()) {
+ return 0;
+ }
+
+ switch(id) {
+ case CLIENT_EARLY_TRAFFIC_SECRET:
+ label = "CLIENT_EARLY_TRAFFIC_SECRET";
+ break;
+ case CLIENT_HANDSHAKE_TRAFFIC_SECRET:
+ label = "CLIENT_HANDSHAKE_TRAFFIC_SECRET";
+ break;
+ case SERVER_HANDSHAKE_TRAFFIC_SECRET:
+ label = "SERVER_HANDSHAKE_TRAFFIC_SECRET";
+ break;
+ case CLIENT_TRAFFIC_SECRET:
+ label = "CLIENT_TRAFFIC_SECRET_0";
+ break;
+ case SERVER_TRAFFIC_SECRET:
+ label = "SERVER_TRAFFIC_SECRET_0";
+ break;
+ case EARLY_EXPORTER_SECRET:
+ label = "EARLY_EXPORTER_SECRET";
+ break;
+ case EXPORTER_SECRET:
+ label = "EXPORTER_SECRET";
+ break;
+ default:
+ return 0;
+ }
+
+ if(SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE) == 0) {
+ /* Should never happen as wolfSSL_KeepArrays() was called before. */
+ return 0;
+ }
+
+ Curl_tls_keylog_write(label, client_random, secret, secretSz);
+ return 0;
+}
+#endif /* defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) */
+
+static void
+wolfssl_log_tls12_secret(SSL *ssl)
+{
+ unsigned char *ms, *sr, *cr;
+ unsigned int msLen, srLen, crLen, i, x = 0;
+
+#if LIBWOLFSSL_VERSION_HEX >= 0x0300d000 /* >= 3.13.0 */
+ /* wolfSSL_GetVersion is available since 3.13, we use it instead of
+ * SSL_version since the latter relies on OPENSSL_ALL (--enable-opensslall or
+ * --enable-all). Failing to perform this check could result in an unusable
+ * key log line when TLS 1.3 is actually negotiated. */
+ switch(wolfSSL_GetVersion(ssl)) {
+ case WOLFSSL_SSLV3:
+ case WOLFSSL_TLSV1:
+ case WOLFSSL_TLSV1_1:
+ case WOLFSSL_TLSV1_2:
+ break;
+ default:
+ /* TLS 1.3 does not use this mechanism, the "master secret" returned below
+ * is not directly usable. */
+ return;
+ }
+#endif
+
+ if(SSL_get_keys(ssl, &ms, &msLen, &sr, &srLen, &cr, &crLen) != SSL_SUCCESS) {
+ return;
+ }
+
+ /* Check for a missing master secret and skip logging. That can happen if
+ * curl rejects the server certificate and aborts the handshake.
+ */
+ for(i = 0; i < msLen; i++) {
+ x |= ms[i];
+ }
+ if(x == 0) {
+ return;
+ }
+
+ Curl_tls_keylog_write("CLIENT_RANDOM", cr, ms, msLen);
+}
+#endif /* OPENSSL_EXTRA */
+
static int do_file_type(const char *type)
{
if(!type || !type[0])
@@ -120,7 +222,7 @@ wolfssl_connect_step1(struct connectdata *conn,
{
char *ciphers;
struct Curl_easy *data = conn->data;
- struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
SSL_METHOD* req_method = NULL;
curl_socket_t sockfd = conn->sock[sockindex];
@@ -314,8 +416,12 @@ wolfssl_connect_step1(struct connectdata *conn,
#ifdef ENABLE_IPV6
struct in6_addr addr6;
#endif
+#ifndef CURL_DISABLE_PROXY
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
+#else
+ const char * const hostname = conn->host.name;
+#endif
size_t hostname_len = strlen(hostname);
if((hostname_len < USHRT_MAX) &&
(0 == Curl_inet_pton(AF_INET, hostname, &addr4)) &&
@@ -385,6 +491,17 @@ wolfssl_connect_step1(struct connectdata *conn,
}
#endif /* HAVE_ALPN */
+#ifdef OPENSSL_EXTRA
+ if(Curl_tls_keylog_enabled()) {
+ /* Ensure the Client Random is preserved. */
+ wolfSSL_KeepArrays(backend->handle);
+#if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
+ wolfSSL_set_tls13_secret_cb(backend->handle,
+ wolfssl_tls13_secret_callback, NULL);
+#endif
+ }
+#endif /* OPENSSL_EXTRA */
+
/* Check if there's a cached ID we can/should use here! */
if(SSL_SET_OPTION(primary.sessionid)) {
void *ssl_sessionid = NULL;
@@ -423,15 +540,22 @@ wolfssl_connect_step2(struct connectdata *conn,
{
int ret = -1;
struct Curl_easy *data = conn->data;
- struct ssl_connect_data* connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = &conn->ssl[sockindex];
struct ssl_backend_data *backend = connssl->backend;
+#ifndef CURL_DISABLE_PROXY
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
conn->host.name;
const char * const dispname = SSL_IS_PROXY() ?
conn->http_proxy.host.dispname : conn->host.dispname;
const char * const pinnedpubkey = SSL_IS_PROXY() ?
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
- data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+#else
+ const char * const hostname = conn->host.name;
+ const char * const dispname = conn->host.dispname;
+ const char * const pinnedpubkey =
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
+#endif
conn->recv[sockindex] = wolfssl_recv;
conn->send[sockindex] = wolfssl_send;
@@ -444,6 +568,31 @@ wolfssl_connect_step2(struct connectdata *conn,
}
ret = SSL_connect(backend->handle);
+
+#ifdef OPENSSL_EXTRA
+ if(Curl_tls_keylog_enabled()) {
+ /* If key logging is enabled, wait for the handshake to complete and then
+ * proceed with logging secrets (for TLS 1.2 or older).
+ *
+ * During the handshake (ret==-1), wolfSSL_want_read() is true as it waits
+ * for the server response. At that point the master secret is not yet
+ * available, so we must not try to read it.
+ * To log the secret on completion with a handshake failure, detect
+ * completion via the observation that there is nothing to read or write.
+ * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever
+ * changes, the worst case is that no key is logged on error.
+ */
+ if(ret == SSL_SUCCESS ||
+ (!wolfSSL_want_read(backend->handle) &&
+ !wolfSSL_want_write(backend->handle))) {
+ wolfssl_log_tls12_secret(backend->handle);
+ /* Client Random and master secrets are no longer needed, erase these.
+ * Ignored while the handshake is still in progress. */
+ wolfSSL_FreeArrays(backend->handle);
+ }
+ }
+#endif /* OPENSSL_EXTRA */
+
if(ret != 1) {
char error_buffer[WOLFSSL_MAX_ERROR_SZ];
int detail = SSL_get_error(backend->handle, ret);
@@ -511,8 +660,8 @@ wolfssl_connect_step2(struct connectdata *conn,
X509 *x509;
const char *x509_der;
int x509_der_len;
- curl_X509certificate x509_parsed;
- curl_asn1Element *pubkey;
+ struct Curl_X509certificate x509_parsed;
+ struct Curl_asn1Element *pubkey;
CURLcode result;
x509 = SSL_get_peer_certificate(backend->handle);
@@ -750,6 +899,9 @@ static size_t Curl_wolfssl_version(char *buffer, size_t size)
static int Curl_wolfssl_init(void)
{
+#ifdef OPENSSL_EXTRA
+ Curl_tls_keylog_open();
+#endif
return (wolfSSL_Init() == SSL_SUCCESS);
}
@@ -757,10 +909,13 @@ static int Curl_wolfssl_init(void)
static void Curl_wolfssl_cleanup(void)
{
wolfSSL_Cleanup();
+#ifdef OPENSSL_EXTRA
+ Curl_tls_keylog_close();
+#endif
}
-static bool Curl_wolfssl_data_pending(const struct connectdata* conn,
+static bool Curl_wolfssl_data_pending(const struct connectdata *conn,
int connindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[connindex];
@@ -800,7 +955,6 @@ wolfssl_connect_common(struct connectdata *conn,
struct Curl_easy *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_socket_t sockfd = conn->sock[sockindex];
- time_t timeout_ms;
int what;
/* check if the connection has already been established */
@@ -811,7 +965,7 @@ wolfssl_connect_common(struct connectdata *conn,
if(ssl_connect_1 == connssl->connecting_state) {
/* Find out how much more time we're allowed */
- timeout_ms = Curl_timeleft(data, NULL, TRUE);
+ const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
@@ -829,7 +983,7 @@ wolfssl_connect_common(struct connectdata *conn,
ssl_connect_2_writing == connssl->connecting_state) {
/* check allowed time left */
- timeout_ms = Curl_timeleft(data, NULL, TRUE);
+ const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
if(timeout_ms < 0) {
/* no need to continue if time already is up */
diff --git a/lib/x509asn1.c b/lib/x509asn1.c
index 026a76950..a0b167a94 100644
--- a/lib/x509asn1.c
+++ b/lib/x509asn1.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -44,7 +44,7 @@
static const char cnOID[] = "2.5.4.3"; /* Common name. */
static const char sanOID[] = "2.5.29.17"; /* Subject alternative name. */
-static const curl_OID OIDtable[] = {
+static const struct Curl_OID OIDtable[] = {
{ "1.2.840.10040.4.1", "dsa" },
{ "1.2.840.10040.4.3", "dsa-with-sha1" },
{ "1.2.840.10045.2.1", "ecPublicKey" },
@@ -103,16 +103,16 @@ static const curl_OID OIDtable[] = {
* Please note there is no pretention here to rewrite a full SSL library.
*/
-static const char *getASN1Element(curl_asn1Element *elem,
+static const char *getASN1Element(struct Curl_asn1Element *elem,
const char *beg, const char *end)
WARN_UNUSED_RESULT;
-static const char *getASN1Element(curl_asn1Element *elem,
+static const char *getASN1Element(struct Curl_asn1Element *elem,
const char *beg, const char *end)
{
unsigned char b;
unsigned long len;
- curl_asn1Element lelem;
+ struct Curl_asn1Element lelem;
/* Get a single ASN.1 element into `elem', parse ASN.1 string at `beg'
ending at `end'.
@@ -176,9 +176,9 @@ static const char *getASN1Element(curl_asn1Element *elem,
* Search the null terminated OID or OID identifier in local table.
* Return the table entry pointer or NULL if not found.
*/
-static const curl_OID * searchOID(const char *oid)
+static const struct Curl_OID *searchOID(const char *oid)
{
- const curl_OID *op;
+ const struct Curl_OID *op;
for(op = OIDtable; op->numoid; op++)
if(!strcmp(op->numoid, oid) || strcasecompare(op->textoid, oid))
return op;
@@ -445,7 +445,7 @@ static const char *OID2str(const char *beg, const char *end, bool symbolic)
buf[buflen] = '\0';
if(symbolic) {
- const curl_OID *op = searchOID(buf);
+ const struct Curl_OID *op = searchOID(buf);
if(op) {
free(buf);
buf = strdup(op->textoid);
@@ -565,7 +565,7 @@ static const char *UTime2str(const char *beg, const char *end)
* Convert an ASN.1 element to a printable string.
* Return the dynamically allocated string, or NULL if an error occurs.
*/
-static const char *ASN1tostr(curl_asn1Element *elem, int type)
+static const char *ASN1tostr(struct Curl_asn1Element *elem, int type)
{
if(elem->constructed)
return NULL; /* No conversion of structured elements. */
@@ -609,12 +609,12 @@ static const char *ASN1tostr(curl_asn1Element *elem, int type)
* ASCII encode distinguished name at `dn' into the `buflen'-sized buffer at
* `buf'. Return the total string length, even if larger than `buflen'.
*/
-static ssize_t encodeDN(char *buf, size_t buflen, curl_asn1Element *dn)
+static ssize_t encodeDN(char *buf, size_t buflen, struct Curl_asn1Element *dn)
{
- curl_asn1Element rdn;
- curl_asn1Element atv;
- curl_asn1Element oid;
- curl_asn1Element value;
+ struct Curl_asn1Element rdn;
+ struct Curl_asn1Element atv;
+ struct Curl_asn1Element oid;
+ struct Curl_asn1Element value;
size_t l = 0;
const char *p1;
const char *p2;
@@ -683,7 +683,7 @@ static ssize_t encodeDN(char *buf, size_t buflen, curl_asn1Element *dn)
* Convert an ASN.1 distinguished name into a printable string.
* Return the dynamically allocated string, or NULL if an error occurs.
*/
-static const char *DNtostr(curl_asn1Element *dn)
+static const char *DNtostr(struct Curl_asn1Element *dn)
{
char *buf = NULL;
ssize_t buflen = encodeDN(NULL, 0, dn);
@@ -703,11 +703,11 @@ static const char *DNtostr(curl_asn1Element *dn)
* Syntax is assumed to have already been checked by the SSL backend.
* See RFC 5280.
*/
-int Curl_parseX509(curl_X509certificate *cert,
+int Curl_parseX509(struct Curl_X509certificate *cert,
const char *beg, const char *end)
{
- curl_asn1Element elem;
- curl_asn1Element tbsCertificate;
+ struct Curl_asn1Element elem;
+ struct Curl_asn1Element tbsCertificate;
const char *ccp;
static const char defaultVersion = 0; /* v1. */
@@ -835,10 +835,10 @@ static size_t copySubstring(char *to, const char *from)
return i;
}
-static const char *dumpAlgo(curl_asn1Element *param,
+static const char *dumpAlgo(struct Curl_asn1Element *param,
const char *beg, const char *end)
{
- curl_asn1Element oid;
+ struct Curl_asn1Element oid;
/* Get algorithm parameters and return algorithm name. */
@@ -855,7 +855,7 @@ static const char *dumpAlgo(curl_asn1Element *param,
}
static void do_pubkey_field(struct Curl_easy *data, int certnum,
- const char *label, curl_asn1Element *elem)
+ const char *label, struct Curl_asn1Element *elem)
{
const char *output;
@@ -872,11 +872,11 @@ static void do_pubkey_field(struct Curl_easy *data, int certnum,
}
static void do_pubkey(struct Curl_easy *data, int certnum,
- const char *algo, curl_asn1Element *param,
- curl_asn1Element *pubkey)
+ const char *algo, struct Curl_asn1Element *param,
+ struct Curl_asn1Element *pubkey)
{
- curl_asn1Element elem;
- curl_asn1Element pk;
+ struct Curl_asn1Element elem;
+ struct Curl_asn1Element pk;
const char *p;
/* Generate all information records for the public key. */
@@ -950,9 +950,9 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
const char *beg,
const char *end)
{
- curl_X509certificate cert;
+ struct Curl_X509certificate cert;
struct Curl_easy *data = conn->data;
- curl_asn1Element param;
+ struct Curl_asn1Element param;
const char *ccp;
char *cp1;
size_t cl1;
@@ -1111,7 +1111,7 @@ CURLcode Curl_extract_certinfo(struct connectdata *conn,
static const char *checkOID(const char *beg, const char *end,
const char *oid)
{
- curl_asn1Element e;
+ struct Curl_asn1Element e;
const char *ccp;
const char *p;
bool matched;
@@ -1136,22 +1136,21 @@ CURLcode Curl_verifyhost(struct connectdata *conn,
const char *beg, const char *end)
{
struct Curl_easy *data = conn->data;
- curl_X509certificate cert;
- curl_asn1Element dn;
- curl_asn1Element elem;
- curl_asn1Element ext;
- curl_asn1Element name;
+ struct Curl_X509certificate cert;
+ struct Curl_asn1Element dn;
+ struct Curl_asn1Element elem;
+ struct Curl_asn1Element ext;
+ struct Curl_asn1Element name;
const char *p;
const char *q;
char *dnsname;
int matched = -1;
size_t addrlen = (size_t) -1;
ssize_t len;
- const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
- conn->host.name;
- const char * const dispname = SSL_IS_PROXY()?
- conn->http_proxy.host.dispname:
- conn->host.dispname;
+ const char *const hostname = SSL_IS_PROXY()?
+ conn->http_proxy.host.name : conn->host.name;
+ const char *const dispname = SSL_IS_PROXY()?
+ conn->http_proxy.host.dispname : conn->host.dispname;
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
diff --git a/lib/x509asn1.h b/lib/x509asn1.h
index 205fdc0d7..0b7fb8817 100644
--- a/lib/x509asn1.h
+++ b/lib/x509asn1.h
@@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -79,52 +79,51 @@
*/
/* ASN.1 parsed element. */
-typedef struct {
- const char * header; /* Pointer to header byte. */
- const char * beg; /* Pointer to element data. */
- const char * end; /* Pointer to 1st byte after element. */
- unsigned char class; /* ASN.1 element class. */
- unsigned char tag; /* ASN.1 element tag. */
- bool constructed; /* Element is constructed. */
-} curl_asn1Element;
+struct Curl_asn1Element {
+ const char *header; /* Pointer to header byte. */
+ const char *beg; /* Pointer to element data. */
+ const char *end; /* Pointer to 1st byte after element. */
+ unsigned char class; /* ASN.1 element class. */
+ unsigned char tag; /* ASN.1 element tag. */
+ bool constructed; /* Element is constructed. */
+};
/* ASN.1 OID table entry. */
-typedef struct {
- const char * numoid; /* Dotted-numeric OID. */
- const char * textoid; /* OID name. */
-} curl_OID;
+struct Curl_OID {
+ const char *numoid; /* Dotted-numeric OID. */
+ const char *textoid; /* OID name. */
+};
/* X509 certificate: RFC 5280. */
-typedef struct {
- curl_asn1Element certificate;
- curl_asn1Element version;
- curl_asn1Element serialNumber;
- curl_asn1Element signatureAlgorithm;
- curl_asn1Element signature;
- curl_asn1Element issuer;
- curl_asn1Element notBefore;
- curl_asn1Element notAfter;
- curl_asn1Element subject;
- curl_asn1Element subjectPublicKeyInfo;
- curl_asn1Element subjectPublicKeyAlgorithm;
- curl_asn1Element subjectPublicKey;
- curl_asn1Element issuerUniqueID;
- curl_asn1Element subjectUniqueID;
- curl_asn1Element extensions;
-} curl_X509certificate;
-
+struct Curl_X509certificate {
+ struct Curl_asn1Element certificate;
+ struct Curl_asn1Element version;
+ struct Curl_asn1Element serialNumber;
+ struct Curl_asn1Element signatureAlgorithm;
+ struct Curl_asn1Element signature;
+ struct Curl_asn1Element issuer;
+ struct Curl_asn1Element notBefore;
+ struct Curl_asn1Element notAfter;
+ struct Curl_asn1Element subject;
+ struct Curl_asn1Element subjectPublicKeyInfo;
+ struct Curl_asn1Element subjectPublicKeyAlgorithm;
+ struct Curl_asn1Element subjectPublicKey;
+ struct Curl_asn1Element issuerUniqueID;
+ struct Curl_asn1Element subjectUniqueID;
+ struct Curl_asn1Element extensions;
+};
/*
* Prototypes.
*/
-const char *Curl_getASN1Element(curl_asn1Element *elem,
- const char *beg, const char *end);
-const char *Curl_ASN1tostr(curl_asn1Element *elem, int type);
-const char *Curl_DNtostr(curl_asn1Element *dn);
-int Curl_parseX509(curl_X509certificate *cert,
+const char *Curl_getASN1Element(struct Curl_asn1Element *elem,
+ const char *beg, const char *end);
+const char *Curl_ASN1tostr(struct Curl_asn1Element *elem, int type);
+const char *Curl_DNtostr(struct Curl_asn1Element *dn);
+int Curl_parseX509(struct Curl_X509certificate *cert,
const char *beg, const char *end);
CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum,
const char *beg, const char *end);
diff --git a/libgnurl.pc.in b/libgnurl.pc.in
index 1d3bce263..c41c73026 100644
--- a/libgnurl.pc.in
+++ b/libgnurl.pc.in
@@ -34,6 +34,6 @@ Name: libgnurl
URL: https://gnunet.org/gnurl/
Description: Library to transfer files with http or https
Version: @CURLVERSION@
-Libs: -L${libdir} -lgnurl
+Libs: -L${libdir} -lgnurl @LIBCURL_NO_SHARED@
Libs.private: @LIBCURL_LIBS@
Cflags: -I${includedir} @CPPFLAG_CURL_STATICLIB@
diff --git a/packages/OS400/makefile.sh b/packages/OS400/makefile.sh
index 3ff151202..29ba506e0 100644
--- a/packages/OS400/makefile.sh
+++ b/packages/OS400/makefile.sh
@@ -53,7 +53,7 @@ fi
for TEXT in "${TOPDIR}/COPYING" "${SCRIPTDIR}/README.OS400" \
"${TOPDIR}/CHANGES" "${TOPDIR}/docs/THANKS" "${TOPDIR}/docs/FAQ" \
"${TOPDIR}/docs/FEATURES" "${TOPDIR}/docs/SSLCERTS.md" \
- "${TOPDIR}/docs/RESOURCES" "${TOPDIR}/docs/VERSIONS" \
+ "${TOPDIR}/docs/RESOURCES" "${TOPDIR}/docs/VERSIONS.md" \
"${TOPDIR}/docs/HISTORY.md"
do MEMBER="`basename \"${TEXT}\" .OS400`"
MEMBER="`basename \"${MEMBER}\" .md`"
diff --git a/packages/vms/build_vms.com b/packages/vms/build_vms.com
index e21e57c47..1b023649f 100644
--- a/packages/vms/build_vms.com
+++ b/packages/vms/build_vms.com
@@ -133,7 +133,7 @@ $! for non-VAX architectures that triggered link failure.
$! Replaced curl_sys_inc with sys_inc.
$! 19-Mar-2013, John Malmberg
$! symbol tool_main needs to be quoted when parse style is
-$! set to exended in versions of VMS greater than 7.3-1.
+$! set to extended in versions of VMS greater than 7.3-1.
$! Remove curlbuild.h generation as it should be pre-built
$! in the curl release or daily tarball.
$! 12-Jul-2013, John Malmberg
diff --git a/scripts/copyright.pl b/scripts/copyright.pl
index bdf23dd7a..7c3296fa3 100755
--- a/scripts/copyright.pl
+++ b/scripts/copyright.pl
@@ -28,13 +28,13 @@
#
# regexes of files to not scan
-my @whitelist=(
+my @skiplist=(
'^tests\/data\/test(\d+)$', # test case data
'^docs\/cmdline-opts\/[a-z]+(.*)\.d$', # curl.1 pieces
'(\/|^)[A-Z0-9_.-]+$', # all uppercase file name, possibly with dot and dash
'(\/|^)[A-Z0-9_-]+\.md$', # all uppercase file name with .md extension
- '.gitignore', # whereever they are
- '.gitattributes', # whereever they are
+ '.gitignore', # wherever they are
+ '.gitattributes', # wherever they are
'^tests/certs/.*', # generated certs
'^tests/stunnel.pem', # generated cert
'^tests/valgrind.supp', # valgrind suppressions
@@ -47,6 +47,7 @@ my @whitelist=(
'^winbuild/BUILD.WINDOWS.txt$', # instructions
'\/readme',
'^.github/', # github instruction files
+ '^.dcignore', # deepcode.ai instruction file
# docs/ files we're okay with without copyright
'INSTALL.cmake',
@@ -55,6 +56,7 @@ my @whitelist=(
'curl_multi_socket_all.3',
'curl_strnequal.3',
'symbols-in-versions',
+ 'options-in-versions',
# macos-framework files
'^lib\/libcurl.plist',
@@ -84,6 +86,9 @@ my @whitelist=(
'^src\/macos\/curl.mcp.xml.sit.hqx',
'^src\/macos\/src\/curl_GUSIConfig.cpp',
+ # checksrc control files
+ '\.checksrc$',
+
);
sub scanfile {
@@ -164,10 +169,10 @@ else {
for my $f (@all) {
chomp $f;
my $skipped = 0;
- for my $skip (@whitelist) {
+ for my $skip (@skiplist) {
#print "$f matches $skip ?\n";
if($f =~ /$skip/) {
- $whitelisted++;
+ $skiplisted++;
$skipped = 1;
#print "$f: SKIPPED ($skip)\n";
last;
@@ -182,6 +187,6 @@ for my $f (@all) {
print STDERR "$missing files have no copyright\n" if($missing);
print STDERR "$wrong files have wrong copyright year\n" if ($wrong);
-print STDERR "$whitelisted files are whitelisted\n" if ($whitelisted);
+print STDERR "$skiplisted files are skipped\n" if ($skiplisted);
exit 1 if($missing || $wrong);
diff --git a/scripts/release-notes.pl b/scripts/release-notes.pl
index 2be0eab8f..d26c045a2 100755
--- a/scripts/release-notes.pl
+++ b/scripts/release-notes.pl
@@ -65,7 +65,7 @@ for my $l (@releasenotes) {
$refused[$1]=1;
}
elsif($l =~ /^ \[(\d+)\] = (.*)/) {
- # listed in a refernce, set bit 1
+ # listed in a reference, set bit 1
$refused[$1] |= 2;
$refs[$1] = $2;
}
diff --git a/scripts/travis/script.sh b/scripts/travis/script.sh
index dc694881b..d1088838b 100755
--- a/scripts/travis/script.sh
+++ b/scripts/travis/script.sh
@@ -85,8 +85,6 @@ if [ "$T" = "normal" ]; then
make test-nonflaky
fi
if [ -n $CHECKSRC ]; then
- echo "enable COPYRIGHTYEAR" > ./docs/examples/.checksrc
- echo "enable COPYRIGHTYEAR" > ./include/gnurl/.checksrc
make checksrc
fi
fi
@@ -106,13 +104,8 @@ if [ "$T" = "iconv" ]; then
fi
if [ "$T" = "cmake" ]; then
- if [ $TRAVIS_OS_NAME = linux ]; then
- cmake -H. -Bbuild -DCURL_WERROR=ON
- cmake --build build
- else
- cmake -H. -Bbuild -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DCURL_DISABLE_LDAP=ON -DCURL_DISABLE_LDAPS=ON
- cmake --build build
- fi
+ cmake -H. -Bbuild -DCURL_WERROR=ON $C
+ cmake --build build
fi
if [ "$T" = "distcheck" ]; then
diff --git a/src/Makefile.inc b/src/Makefile.inc
index e90e6d670..559b9983c 100644
--- a/src/Makefile.inc
+++ b/src/Makefile.inc
@@ -34,14 +34,16 @@ GNURLX_CFILES = \
../lib/strtoofft.c \
../lib/nonblock.c \
../lib/warnless.c \
- ../lib/curl_ctype.c
+ ../lib/curl_ctype.c \
+ ../lib/curl_multibyte.c
GNURLX_HFILES = \
../lib/curl_setup.h \
../lib/strtoofft.h \
../lib/nonblock.h \
../lib/warnless.h \
- ../lib/curl_ctype.h
+ ../lib/curl_ctype.h \
+ ../lib/curl_multibyte.h
GNURL_CFILES = \
slist_wc.c \
diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c
index 3b1023888..5741f0aba 100644
--- a/src/tool_cb_hdr.c
+++ b/src/tool_cb_hdr.c
@@ -119,8 +119,8 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
if(!first) {
warnf(per->config->global,
- "\nReceived header etag is missing double quote/s\n");
- return 1;
+ "Received header etag is missing double quote/s\n");
+ return failure;
}
else {
/* discard first double quote */
@@ -132,8 +132,8 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
if(!last) {
warnf(per->config->global,
- "\nReceived header etag is missing double quote/s\n");
- return 1;
+ "Received header etag is missing double quote/s\n");
+ return failure;
}
/* get length of desired etag */
@@ -186,25 +186,11 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata)
filename = parse_filename(p, len);
if(filename) {
if(outs->stream) {
- int rc;
- /* already opened and possibly written to */
- if(outs->fopened)
- fclose(outs->stream);
- outs->stream = NULL;
-
- /* rename the initial file name to the new file name */
- rc = rename(outs->filename, filename);
- if(rc != 0) {
- warnf(per->config->global, "Failed to rename %s -> %s: %s\n",
- outs->filename, filename, strerror(errno));
- }
- if(outs->alloc_filename)
- Curl_safefree(outs->filename);
- if(rc != 0) {
- free(filename);
- return failure;
- }
+ /* indication of problem, get out! */
+ free(filename);
+ return failure;
}
+
outs->is_cd_filename = TRUE;
outs->s_isreg = TRUE;
outs->fopened = FALSE;
diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c
index f802a5a31..63bdeaa46 100644
--- a/src/tool_cfgable.c
+++ b/src/tool_cfgable.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -26,7 +26,7 @@
#include "memdebug.h" /* keep this as LAST include */
-void config_init(struct OperationConfig* config)
+void config_init(struct OperationConfig *config)
{
memset(config, 0, sizeof(struct OperationConfig));
@@ -112,6 +112,7 @@ static void free_config_fields(struct OperationConfig *config)
Curl_safefree(config->cert_type);
Curl_safefree(config->proxy_cert_type);
Curl_safefree(config->cacert);
+ Curl_safefree(config->login_options);
Curl_safefree(config->proxy_cacert);
Curl_safefree(config->capath);
Curl_safefree(config->proxy_capath);
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index 2ae7944e3..4a90d0b72 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -37,8 +37,8 @@ struct GlobalConfig;
struct State {
struct getout *urlnode;
- URLGlob *inglob;
- URLGlob *urls;
+ struct URLGlob *inglob;
+ struct URLGlob *urls;
char *outfiles;
char *httpgetfields;
char *uploadfile;
@@ -194,8 +194,8 @@ struct OperationConfig {
curl_off_t condtime;
struct curl_slist *headers;
struct curl_slist *proxyheaders;
- tool_mime *mimeroot;
- tool_mime *mimecurrent;
+ struct tool_mime *mimeroot;
+ struct tool_mime *mimecurrent;
curl_mime *mimepost;
struct curl_slist *telnet_options;
struct curl_slist *resolve;
@@ -223,6 +223,7 @@ struct OperationConfig {
bool tcp_nodelay;
bool tcp_fastopen;
long req_retry; /* number of retries */
+ bool retry_all_errors; /* retry on any error */
bool retry_connrefused; /* set connection refused as a transient error */
long retry_delay; /* delay between retries (in seconds) */
long retry_maxtime; /* maximum time to keep retrying */
@@ -257,9 +258,11 @@ struct OperationConfig {
bool ssl_revoke_best_effort; /* ignore SSL revocation offline/missing
revocation list errors */
+ bool native_ca_store; /* use the native os ca store */
+
bool use_metalink; /* process given URLs as metalink XML file */
- metalinkfile *metalinkfile_list; /* point to the first node */
- metalinkfile *metalinkfile_last; /* point to the last/current node */
+ struct metalinkfile *metalinkfile_list; /* point to the first node */
+ struct metalinkfile *metalinkfile_last; /* point to the last/current node */
char *oauth_bearer; /* OAuth 2.0 bearer token */
bool nonpn; /* enable/disable TLS NPN extension */
bool noalpn; /* enable/disable TLS ALPN extension */
diff --git a/src/tool_formparse.c b/src/tool_formparse.c
index 74d1533e4..8e8fe874e 100644
--- a/src/tool_formparse.c
+++ b/src/tool_formparse.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -42,9 +42,10 @@
#define CONST_SAFEFREE(x) Curl_safefree(*((void **) &(x)))
/* tool_mime functions. */
-static tool_mime *tool_mime_new(tool_mime *parent, toolmimekind kind)
+static struct tool_mime *tool_mime_new(struct tool_mime *parent,
+ toolmimekind kind)
{
- tool_mime *m = (tool_mime *) calloc(1, sizeof(*m));
+ struct tool_mime *m = (struct tool_mime *) calloc(1, sizeof(*m));
if(m) {
m->kind = kind;
@@ -57,14 +58,15 @@ static tool_mime *tool_mime_new(tool_mime *parent, toolmimekind kind)
return m;
}
-static tool_mime *tool_mime_new_parts(tool_mime *parent)
+static struct tool_mime *tool_mime_new_parts(struct tool_mime *parent)
{
return tool_mime_new(parent, TOOLMIME_PARTS);
}
-static tool_mime *tool_mime_new_data(tool_mime *parent, const char *data)
+static struct tool_mime *tool_mime_new_data(struct tool_mime *parent,
+ const char *data)
{
- tool_mime *m = NULL;
+ struct tool_mime *m = NULL;
data = strdup(data);
if(data) {
@@ -77,13 +79,13 @@ static tool_mime *tool_mime_new_data(tool_mime *parent, const char *data)
return m;
}
-static tool_mime *tool_mime_new_filedata(tool_mime *parent,
- const char *filename,
- bool isremotefile,
- CURLcode *errcode)
+static struct tool_mime *tool_mime_new_filedata(struct tool_mime *parent,
+ const char *filename,
+ bool isremotefile,
+ CURLcode *errcode)
{
CURLcode result = CURLE_OK;
- tool_mime *m = NULL;
+ struct tool_mime *m = NULL;
*errcode = CURLE_OUT_OF_MEMORY;
if(strcmp(filename, "-")) {
@@ -159,7 +161,7 @@ static tool_mime *tool_mime_new_filedata(tool_mime *parent,
return m;
}
-void tool_mime_free(tool_mime *mime)
+void tool_mime_free(struct tool_mime *mime)
{
if(mime) {
if(mime->subparts)
@@ -181,7 +183,7 @@ void tool_mime_free(tool_mime *mime)
size_t tool_mime_stdin_read(char *buffer,
size_t size, size_t nitems, void *arg)
{
- tool_mime *sip = (tool_mime *) arg;
+ struct tool_mime *sip = (struct tool_mime *) arg;
curl_off_t bytesleft;
(void) size; /* Always 1: ignored. */
@@ -216,7 +218,7 @@ size_t tool_mime_stdin_read(char *buffer,
int tool_mime_stdin_seek(void *instream, curl_off_t offset, int whence)
{
- tool_mime *sip = (tool_mime *) instream;
+ struct tool_mime *sip = (struct tool_mime *) instream;
switch(whence) {
case SEEK_CUR:
@@ -238,7 +240,8 @@ int tool_mime_stdin_seek(void *instream, curl_off_t offset, int whence)
/* Translate an internal mime tree into a libcurl mime tree. */
-static CURLcode tool2curlparts(CURL *curl, tool_mime *m, curl_mime *mime)
+static CURLcode tool2curlparts(CURL *curl, struct tool_mime *m,
+ curl_mime *mime)
{
CURLcode ret = CURLE_OK;
curl_mimepart *part = NULL;
@@ -323,7 +326,7 @@ static CURLcode tool2curlparts(CURL *curl, tool_mime *m, curl_mime *mime)
return ret;
}
-CURLcode tool2curlmime(CURL *curl, tool_mime *m, curl_mime **mime)
+CURLcode tool2curlmime(CURL *curl, struct tool_mime *m, curl_mime **mime)
{
CURLcode ret = CURLE_OK;
@@ -733,8 +736,8 @@ static int get_param_part(struct OperationConfig *config, char endchar,
int formparse(struct OperationConfig *config,
const char *input,
- tool_mime **mimeroot,
- tool_mime **mimecurrent,
+ struct tool_mime **mimeroot,
+ struct tool_mime **mimecurrent,
bool literal_value)
{
/* input MUST be a string in the format 'name=contents' and we'll
@@ -747,7 +750,7 @@ int formparse(struct OperationConfig *config,
char *filename = NULL;
char *encoder = NULL;
struct curl_slist *headers = NULL;
- tool_mime *part = NULL;
+ struct tool_mime *part = NULL;
CURLcode res;
/* Allocate the main mime structure if needed. */
@@ -794,7 +797,7 @@ int formparse(struct OperationConfig *config,
/* we use the @-letter to indicate file name(s) */
- tool_mime *subparts = NULL;
+ struct tool_mime *subparts = NULL;
do {
/* since this was a file, it may have a content-type specifier
diff --git a/src/tool_formparse.h b/src/tool_formparse.h
index 750fe451f..5c1525e67 100644
--- a/src/tool_formparse.h
+++ b/src/tool_formparse.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,12 +35,11 @@ typedef enum {
TOOLMIME_STDINDATA
} toolmimekind;
-typedef struct tool_mime tool_mime;
struct tool_mime {
/* Structural fields. */
toolmimekind kind; /* Part kind. */
- tool_mime *parent; /* Parent item. */
- tool_mime *prev; /* Previous sibling (reverse order link). */
+ struct tool_mime *parent; /* Parent item. */
+ struct tool_mime *prev; /* Previous sibling (reverse order link). */
/* Common fields. */
const char *data; /* Actual data or data filename. */
const char *name; /* Part name. */
@@ -49,7 +48,7 @@ struct tool_mime {
const char *encoder; /* Part's requested encoding. */
struct curl_slist *headers; /* User-defined headers. */
/* TOOLMIME_PARTS fields. */
- tool_mime *subparts; /* Part's subparts. */
+ struct tool_mime *subparts; /* Part's subparts. */
/* TOOLMIME_STDIN/TOOLMIME_STDINDATA fields. */
curl_off_t origin; /* Stdin read origin offset. */
curl_off_t size; /* Stdin data size. */
@@ -63,10 +62,10 @@ int tool_mime_stdin_seek(void *instream, curl_off_t offset, int whence);
int formparse(struct OperationConfig *config,
const char *input,
- tool_mime **mimeroot,
- tool_mime **mimecurrent,
+ struct tool_mime **mimeroot,
+ struct tool_mime **mimecurrent,
bool literal_value);
-CURLcode tool2curlmime(CURL *curl, tool_mime *m, curl_mime **mime);
-void tool_mime_free(tool_mime *mime);
+CURLcode tool2curlmime(CURL *curl, struct tool_mime *m, curl_mime **mime);
+void tool_mime_free(struct tool_mime *mime);
#endif /* HEADER_CURL_TOOL_FORMPARSE_H */
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index 0252ee029..340962145 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -197,6 +197,7 @@ static const struct LongShort aliases[]= {
{"$Y", "suppress-connect-headers", ARG_BOOL},
{"$Z", "compressed-ssh", ARG_BOOL},
{"$~", "happy-eyeballs-timeout-ms", ARG_STRING},
+ {"$!", "retry-all-errors", ARG_BOOL},
{"0", "http1.0", ARG_NONE},
{"01", "http1.1", ARG_NONE},
{"02", "http2", ARG_NONE},
@@ -927,6 +928,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
if(err)
return err;
break;
+ case '!': /* --retry-all-errors */
+ config->retry_all_errors = toggle;
+ break;
case 'k': /* --proxy-negotiate */
if(curlinfo->features & CURL_VERSION_SPNEGO)
@@ -962,7 +966,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
if(*p) {
/* if there's anything more than a plain decimal number */
rc = sscanf(p, " - %6s", lrange);
- *p = 0; /* zero terminate to make str2unum() work below */
+ *p = 0; /* null-terminate to make str2unum() work below */
}
else
rc = 0;
@@ -1513,7 +1517,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
/* Automatic referer requested, this may be combined with a
set initial one */
config->autoreferer = TRUE;
- *ptr = 0; /* zero terminate here */
+ *ptr = 0; /* null-terminate here */
}
else
config->autoreferer = FALSE;
@@ -1813,6 +1817,11 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
}
break;
case 'i':
+ if(config->content_disposition) {
+ warnf(global,
+ "--include and --remote-header-name cannot be combined.\n");
+ return PARAM_BAD_USE;
+ }
config->show_headers = toggle; /* show the headers as well in the
general output stream */
break;
@@ -2244,20 +2253,22 @@ ParameterError parse_args(struct GlobalConfig *global, int argc,
struct OperationConfig *config = global->first;
for(i = 1, stillflags = TRUE; i < argc && !result; i++) {
- orig_opt = argv[i];
+ orig_opt = curlx_convert_tchar_to_UTF8(argv[i]);
- if(stillflags && ('-' == argv[i][0])) {
+ if(stillflags && ('-' == orig_opt[0])) {
bool passarg;
- char *flag = argv[i];
- if(!strcmp("--", argv[i]))
+ if(!strcmp("--", orig_opt))
/* This indicates the end of the flags and thus enables the
following (URL) argument to start with -. */
stillflags = FALSE;
else {
- char *nextarg = (i < (argc - 1)) ? argv[i + 1] : NULL;
+ char *nextarg = (i < (argc - 1))
+ ? curlx_convert_tchar_to_UTF8(argv[i + 1])
+ : NULL;
- result = getparameter(flag, nextarg, &passarg, global, config);
+ result = getparameter(orig_opt, nextarg, &passarg, global, config);
+ curlx_unicodefree(nextarg);
config = global->last;
if(result == PARAM_NEXT_OPERATION) {
/* Reset result as PARAM_NEXT_OPERATION is only used here and not
@@ -2293,9 +2304,12 @@ ParameterError parse_args(struct GlobalConfig *global, int argc,
bool used;
/* Just add the URL please */
- result = getparameter((char *)"--url", argv[i], &used, global,
+ result = getparameter("--url", orig_opt, &used, global,
config);
}
+
+ if(!result)
+ curlx_unicodefree(orig_opt);
}
if(result && result != PARAM_HELP_REQUESTED &&
@@ -2310,5 +2324,6 @@ ParameterError parse_args(struct GlobalConfig *global, int argc,
helpf(global->errors, "%s\n", reason);
}
+ curlx_unicodefree(orig_opt);
return result;
}
diff --git a/src/tool_getpass.c b/src/tool_getpass.c
index dfe363b21..d3bd4e688 100644
--- a/src/tool_getpass.c
+++ b/src/tool_getpass.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -238,7 +238,7 @@ char *getpass_r(const char *prompt, /* prompt to display */
fputs(prompt, stderr);
nread = read(fd, password, buflen);
if(nread > 0)
- password[--nread] = '\0'; /* zero terminate where enter is stored */
+ password[--nread] = '\0'; /* null-terminate where enter is stored */
else
password[0] = '\0'; /* got nothing */
diff --git a/src/tool_help.c b/src/tool_help.c
index 5afaf822e..ae319271c 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -48,6 +48,7 @@ struct helptxt {
const char *desc;
};
+
static const struct helptxt helptext[] = {
{" --abstract-unix-socket <path>",
"Connect via abstract Unix domain socket"},
@@ -68,7 +69,7 @@ static const struct helptxt helptext[] = {
{" --cert-status",
"Verify the status of the server certificate"},
{" --cert-type <type>",
- "Certificate file type (DER/PEM/ENG)"},
+ "Certificate type (DER/PEM/ENG)"},
{" --ciphers <list of ciphers>",
"SSL ciphers to use"},
{" --compressed",
@@ -131,10 +132,10 @@ static const struct helptxt helptext[] = {
"EGD socket path for random data"},
{" --engine <name>",
"Crypto engine to use"},
- {" --etag-save <file>",
- "Get an ETag from response header and save it to a FILE"},
{" --etag-compare <file>",
- "Get an ETag from a file and send a conditional request"},
+ "Pass an ETag from a file as a custom header"},
+ {" --etag-save <file>",
+ "Parse ETag from a request and save it to a file"},
{" --expect100-timeout <seconds>",
"How long to wait for 100-continue"},
{"-f, --fail",
@@ -174,7 +175,7 @@ static const struct helptxt helptext[] = {
{"-g, --globoff",
"Disable URL sequences and ranges using {} and []"},
{" --happy-eyeballs-timeout-ms <milliseconds>",
- "How long to wait in milliseconds for IPv6 before trying IPv4"},
+ "Time for IPv6 before trying IPv4"},
{" --haproxy-protocol",
"Send HAProxy PROXY protocol v1 header"},
{"-I, --head",
@@ -351,8 +352,8 @@ static const struct helptxt helptext[] = {
"SPNEGO proxy service name"},
{" --proxy-ssl-allow-beast",
"Allow security flaw for interop for HTTPS proxy"},
- {" --proxy-tls13-ciphers <list>",
- "TLS 1.3 ciphersuites for proxy (OpenSSL)"},
+ {" --proxy-tls13-ciphers <ciphersuite list>",
+ "TLS 1.3 proxy cipher suites"},
{" --proxy-tlsauthtype <type>",
"TLS authentication type for HTTPS proxy"},
{" --proxy-tlspassword <string>",
@@ -391,18 +392,20 @@ static const struct helptxt helptext[] = {
"Specify request command to use"},
{" --request-target",
"Specify the target for this request"},
- {" --resolve <host:port:address[,address]...>",
+ {" --resolve <host:port:addr[,addr]...>",
"Resolve the host+port to this address"},
{" --retry <num>",
"Retry request if transient problems occur"},
+ {" --retry-all-errors",
+ "Retry all errors (use with --retry)"},
{" --retry-connrefused",
"Retry on connection refused (use with --retry)"},
{" --retry-delay <seconds>",
"Wait time between retries"},
{" --retry-max-time <seconds>",
"Retry only within this period"},
- {" --sasl-authzid <identity> ",
- "Use this identity to act as during SASL PLAIN authentication"},
+ {" --sasl-authzid <identity>",
+ "Identity for SASL PLAIN authentication"},
{" --sasl-ir",
"Enable initial response in SASL authentication"},
{" --service-name <name>",
@@ -437,10 +440,10 @@ static const struct helptxt helptext[] = {
"Allow security flaw to improve interop"},
{" --ssl-no-revoke",
"Disable cert revocation checks (Schannel)"},
- {" --ssl-revoke-best-effort",
- "Ignore revocation offline or missing revocation list errors (Schannel)"},
{" --ssl-reqd",
"Require SSL/TLS"},
+ {" --ssl-revoke-best-effort",
+ "Ignore missing/offline cert CRL dist points"},
{"-2, --sslv2",
"Use SSLv2"},
{"-3, --sslv3",
@@ -465,8 +468,8 @@ static const struct helptxt helptext[] = {
"Transfer based on a time condition"},
{" --tls-max <VERSION>",
"Set maximum allowed TLS version"},
- {" --tls13-ciphers <list>",
- "TLS 1.3 ciphersuites (OpenSSL)"},
+ {" --tls13-ciphers <ciphersuite list>",
+ "TLS 1.3 cipher suites to use"},
{" --tlsauthtype <type>",
"TLS authentication type"},
{" --tlspassword",
diff --git a/src/tool_main.c b/src/tool_main.c
index 25042895f..ccf098e94 100644
--- a/src/tool_main.c
+++ b/src/tool_main.c
@@ -273,22 +273,28 @@ static void restore_terminal(void)
/*
** curl tool main function.
*/
+#ifdef _UNICODE
+int wmain(int argc, wchar_t *argv[])
+#else
int main(int argc, char *argv[])
+#endif
{
CURLcode result = CURLE_OK;
struct GlobalConfig global;
memset(&global, 0, sizeof(global));
#ifdef WIN32
+#ifdef _tcscmp
/* Undocumented diagnostic option to list the full paths of all loaded
modules. This is purposely pre-init. */
- if(argc == 2 && !strcmp(argv[1], "--dump-module-paths")) {
+ if(argc == 2 && !_tcscmp(argv[1], _T("--dump-module-paths"))) {
struct curl_slist *item, *head = GetLoadedModulePaths();
for(item = head; item; item = item->next)
printf("%s\n", item->data);
curl_slist_free_all(head);
return head ? 0 : 1;
}
+#endif /* _tcscmp */
/* win32_init must be called before other init routines. */
result = win32_init();
if(result) {
diff --git a/src/tool_metalink.c b/src/tool_metalink.c
index fce18d5a4..2ad7115db 100644
--- a/src/tool_metalink.c
+++ b/src/tool_metalink.c
@@ -399,7 +399,7 @@ static void SHA256_Final(unsigned char digest[32], SHA256_CTX *ctx)
#endif /* CRYPTO LIBS */
-const digest_params MD5_DIGEST_PARAMS[] = {
+const struct digest_params MD5_DIGEST_PARAMS[] = {
{
CURLX_FUNCTION_CAST(digest_init_func, MD5_Init),
CURLX_FUNCTION_CAST(digest_update_func, MD5_Update),
@@ -409,7 +409,7 @@ const digest_params MD5_DIGEST_PARAMS[] = {
}
};
-const digest_params SHA1_DIGEST_PARAMS[] = {
+const struct digest_params SHA1_DIGEST_PARAMS[] = {
{
CURLX_FUNCTION_CAST(digest_init_func, SHA1_Init),
CURLX_FUNCTION_CAST(digest_update_func, SHA1_Update),
@@ -419,7 +419,7 @@ const digest_params SHA1_DIGEST_PARAMS[] = {
}
};
-const digest_params SHA256_DIGEST_PARAMS[] = {
+const struct digest_params SHA256_DIGEST_PARAMS[] = {
{
CURLX_FUNCTION_CAST(digest_init_func, SHA256_Init),
CURLX_FUNCTION_CAST(digest_update_func, SHA256_Update),
@@ -429,15 +429,15 @@ const digest_params SHA256_DIGEST_PARAMS[] = {
}
};
-static const metalink_digest_def SHA256_DIGEST_DEF[] = {
+static const struct metalink_digest_def SHA256_DIGEST_DEF[] = {
{"sha-256", SHA256_DIGEST_PARAMS}
};
-static const metalink_digest_def SHA1_DIGEST_DEF[] = {
+static const struct metalink_digest_def SHA1_DIGEST_DEF[] = {
{"sha-1", SHA1_DIGEST_PARAMS}
};
-static const metalink_digest_def MD5_DIGEST_DEF[] = {
+static const struct metalink_digest_def MD5_DIGEST_DEF[] = {
{"md5", MD5_DIGEST_PARAMS}
};
@@ -448,7 +448,7 @@ static const metalink_digest_def MD5_DIGEST_DEF[] = {
* "Hash Function Textual Names". The latter is widely (and
* historically) used in Metalink version 3.
*/
-static const metalink_digest_alias digest_aliases[] = {
+static const struct metalink_digest_alias digest_aliases[] = {
{"sha-256", SHA256_DIGEST_DEF},
{"sha256", SHA256_DIGEST_DEF},
{"sha-1", SHA1_DIGEST_DEF},
@@ -457,13 +457,9 @@ static const metalink_digest_alias digest_aliases[] = {
{NULL, NULL}
};
-static digest_context *digest_init(const digest_params *dparams)
+static struct digest_context *digest_init(const struct digest_params *dparams)
{
- digest_context *ctxt;
-
- /* Create digest context */
- ctxt = malloc(sizeof(*ctxt));
-
+ struct digest_context *ctxt = malloc(sizeof(*ctxt));
if(!ctxt)
return ctxt;
@@ -485,7 +481,7 @@ static digest_context *digest_init(const digest_params *dparams)
return ctxt;
}
-static int digest_update(digest_context *context,
+static int digest_update(struct digest_context *context,
const unsigned char *data,
unsigned int len)
{
@@ -494,7 +490,7 @@ static int digest_update(digest_context *context,
return 0;
}
-static int digest_final(digest_context *context, unsigned char *result)
+static int digest_final(struct digest_context *context, unsigned char *result)
{
if(result)
(*context->digest_hash->digest_final)(result, context->digest_hashctx);
@@ -531,11 +527,11 @@ static unsigned char hex_to_uint(const char *s)
* Hash algorithm not available.
*/
static int check_hash(const char *filename,
- const metalink_digest_def *digest_def,
+ const struct metalink_digest_def *digest_def,
const unsigned char *digest, FILE *error)
{
unsigned char *result;
- digest_context *dctx;
+ struct digest_context *dctx;
int check_ok, flags, fd;
flags = O_RDONLY;
@@ -597,7 +593,7 @@ static int check_hash(const char *filename,
}
int metalink_check_hash(struct GlobalConfig *config,
- metalinkfile *mlfile,
+ struct metalinkfile *mlfile,
const char *filename)
{
int rv;
@@ -612,11 +608,11 @@ int metalink_check_hash(struct GlobalConfig *config,
return rv;
}
-static metalink_checksum *
-checksum_from_hex_digest(const metalink_digest_def *digest_def,
+static struct metalink_checksum *
+checksum_from_hex_digest(const struct metalink_digest_def *digest_def,
const char *hex_digest)
{
- metalink_checksum *chksum;
+ struct metalink_checksum *chksum;
unsigned char *digest;
size_t i;
size_t len = strlen(hex_digest);
@@ -627,7 +623,7 @@ checksum_from_hex_digest(const metalink_digest_def *digest_def,
for(i = 0; i < len; i += 2) {
digest[i/2] = hex_to_uint(hex_digest + i);
}
- chksum = malloc(sizeof(metalink_checksum));
+ chksum = malloc(sizeof(struct metalink_checksum));
if(chksum) {
chksum->digest_def = digest_def;
chksum->digest = digest;
@@ -637,10 +633,9 @@ checksum_from_hex_digest(const metalink_digest_def *digest_def,
return chksum;
}
-static metalink_resource *new_metalink_resource(const char *url)
+static struct metalink_resource *new_metalink_resource(const char *url)
{
- metalink_resource *res;
- res = malloc(sizeof(metalink_resource));
+ struct metalink_resource *res = malloc(sizeof(struct metalink_resource));
if(res) {
res->next = NULL;
res->url = strdup(url);
@@ -656,7 +651,7 @@ static metalink_resource *new_metalink_resource(const char *url)
letter is in [0-9A-Za-z] and the length of the string equals to the
result length of digest * 2. */
static int check_hex_digest(const char *hex_digest,
- const metalink_digest_def *digest_def)
+ const struct metalink_digest_def *digest_def)
{
size_t i;
for(i = 0; hex_digest[i]; ++i) {
@@ -669,10 +664,9 @@ static int check_hex_digest(const char *hex_digest,
return digest_def->dparams->digest_resultlen * 2 == i;
}
-static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo)
+static struct metalinkfile *new_metalinkfile(metalink_file_t *fileinfo)
{
- metalinkfile *f;
- f = (metalinkfile*)malloc(sizeof(metalinkfile));
+ struct metalinkfile *f = malloc(sizeof(struct metalinkfile));
if(!f)
return NULL;
@@ -685,7 +679,7 @@ static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo)
f->checksum = NULL;
f->resource = NULL;
if(fileinfo->checksums) {
- const metalink_digest_alias *digest_alias;
+ const struct metalink_digest_alias *digest_alias;
for(digest_alias = digest_aliases; digest_alias->alias_name;
++digest_alias) {
metalink_checksum_t **p;
@@ -705,11 +699,11 @@ static metalinkfile *new_metalinkfile(metalink_file_t *fileinfo)
}
if(fileinfo->resources) {
metalink_resource_t **p;
- metalink_resource root, *tail;
+ struct metalink_resource root, *tail;
root.next = NULL;
tail = &root;
for(p = fileinfo->resources; *p; ++p) {
- metalink_resource *res;
+ struct metalink_resource *res;
/* Filter by type if it is non-NULL. In Metalink v3, type
includes the type of the resource. In curl, we are only
interested in HTTP, HTTPS and FTP. In addition to them,
@@ -798,7 +792,7 @@ int parse_metalink(struct OperationConfig *config, struct OutStruct *outs,
url = new_getout(config);
if(url) {
- metalinkfile *mlfile = new_metalinkfile(*files);
+ struct metalinkfile *mlfile = new_metalinkfile(*files);
if(!mlfile)
break;
@@ -876,24 +870,23 @@ int check_metalink_content_type(const char *content_type)
return check_content_type(content_type, "application/metalink+xml");
}
-int count_next_metalink_resource(metalinkfile *mlfile)
+int count_next_metalink_resource(struct metalinkfile *mlfile)
{
int count = 0;
- metalink_resource *res;
+ struct metalink_resource *res;
for(res = mlfile->resource; res; res = res->next, ++count);
return count;
}
-static void delete_metalink_checksum(metalink_checksum *chksum)
+static void delete_metalink_checksum(struct metalink_checksum *chksum)
{
- if(chksum == NULL) {
+ if(!chksum)
return;
- }
Curl_safefree(chksum->digest);
Curl_safefree(chksum);
}
-static void delete_metalink_resource(metalink_resource *res)
+static void delete_metalink_resource(struct metalink_resource *res)
{
if(res == NULL) {
return;
@@ -902,16 +895,16 @@ static void delete_metalink_resource(metalink_resource *res)
Curl_safefree(res);
}
-void delete_metalinkfile(metalinkfile *mlfile)
+void delete_metalinkfile(struct metalinkfile *mlfile)
{
- metalink_resource *res;
+ struct metalink_resource *res;
if(mlfile == NULL) {
return;
}
Curl_safefree(mlfile->filename);
delete_metalink_checksum(mlfile->checksum);
for(res = mlfile->resource; res;) {
- metalink_resource *next;
+ struct metalink_resource *next;
next = res->next;
delete_metalink_resource(res);
res = next;
@@ -923,7 +916,7 @@ void clean_metalink(struct OperationConfig *config)
{
if(config) {
while(config->metalinkfile_list) {
- metalinkfile *mlfile = config->metalinkfile_list;
+ struct metalinkfile *mlfile = config->metalinkfile_list;
config->metalinkfile_list = config->metalinkfile_list->next;
delete_metalinkfile(mlfile);
}
diff --git a/src/tool_metalink.h b/src/tool_metalink.h
index db2f702e5..abf75dd17 100644
--- a/src/tool_metalink.h
+++ b/src/tool_metalink.h
@@ -35,46 +35,46 @@ typedef void (*digest_update_func)(void *context,
unsigned int len);
typedef void (*digest_final_func)(unsigned char *result, void *context);
-typedef struct {
+struct digest_params {
digest_init_func digest_init; /* Initialize context procedure */
digest_update_func digest_update; /* Update context with data */
digest_final_func digest_final; /* Get final result procedure */
unsigned int digest_ctxtsize; /* Context structure size */
unsigned int digest_resultlen; /* Result length (bytes) */
-} digest_params;
+};
-typedef struct {
- const digest_params *digest_hash; /* Hash function definition */
+struct digest_context {
+ const struct digest_params *digest_hash; /* Hash function definition */
void *digest_hashctx; /* Hash function context */
-} digest_context;
+};
-typedef struct {
+struct metalink_digest_def {
const char *hash_name;
- const digest_params *dparams;
-} metalink_digest_def;
+ const struct digest_params *dparams;
+};
-typedef struct {
+struct metalink_digest_alias {
const char *alias_name;
- const metalink_digest_def *digest_def;
-} metalink_digest_alias;
+ const struct metalink_digest_def *digest_def;
+};
-typedef struct metalink_checksum {
- const metalink_digest_def *digest_def;
+struct metalink_checksum {
+ const struct metalink_digest_def *digest_def;
/* raw digest value, not ascii hex digest */
unsigned char *digest;
-} metalink_checksum;
+};
-typedef struct metalink_resource {
+struct metalink_resource {
struct metalink_resource *next;
char *url;
-} metalink_resource;
+};
-typedef struct metalinkfile {
+struct metalinkfile {
struct metalinkfile *next;
char *filename;
- metalink_checksum *checksum;
- metalink_resource *resource;
-} metalinkfile;
+ struct metalink_checksum *checksum;
+ struct metalink_resource *resource;
+};
#ifdef USE_METALINK
@@ -89,18 +89,18 @@ typedef struct metalinkfile {
(CURL_REQ_LIBMETALINK_MINOR * 100) + \
CURL_REQ_LIBMETALINK_PATCH)
-extern const digest_params MD5_DIGEST_PARAMS[1];
-extern const digest_params SHA1_DIGEST_PARAMS[1];
-extern const digest_params SHA256_DIGEST_PARAMS[1];
+extern const struct digest_params MD5_DIGEST_PARAMS[1];
+extern const struct digest_params SHA1_DIGEST_PARAMS[1];
+extern const struct digest_params SHA256_DIGEST_PARAMS[1];
#include <metalink/metalink.h>
/*
* Counts the resource in the metalinkfile.
*/
-int count_next_metalink_resource(metalinkfile *mlfile);
+int count_next_metalink_resource(struct metalinkfile *mlfile);
-void delete_metalinkfile(metalinkfile *mlfile);
+void delete_metalinkfile(struct metalinkfile *mlfile);
void clean_metalink(struct OperationConfig *config);
/*
@@ -143,7 +143,7 @@ int check_metalink_content_type(const char *content_type);
* Metalink does not contain checksum.
*/
int metalink_check_hash(struct GlobalConfig *config,
- metalinkfile *mlfile,
+ struct metalinkfile *mlfile,
const char *filename);
/*
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 3f83136af..922d81e4d 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -425,10 +425,6 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
metalink_parser_context_delete(outs->metalink_parser);
#endif /* USE_METALINK */
- if(outs->is_cd_filename && outs->stream && !global->mute &&
- outs->filename)
- printf("curl: Saved to filename '%s'\n", outs->filename);
-
/* if retry-max-time is non-zero, make sure we haven't exceeded the
time */
if(per->retry_numretries &&
@@ -437,13 +433,14 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
config->retry_maxtime*1000L)) ) {
enum {
RETRY_NO,
+ RETRY_ALL_ERRORS,
RETRY_TIMEOUT,
RETRY_CONNREFUSED,
RETRY_HTTP,
RETRY_FTP,
RETRY_LAST /* not used */
} retry = RETRY_NO;
- long response;
+ long response = 0;
if((CURLE_OPERATION_TIMEDOUT == result) ||
(CURLE_COULDNT_RESOLVE_HOST == result) ||
(CURLE_COULDNT_RESOLVE_PROXY == result) ||
@@ -452,7 +449,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
retry = RETRY_TIMEOUT;
else if(config->retry_connrefused &&
(CURLE_COULDNT_CONNECT == result)) {
- long oserrno;
+ long oserrno = 0;
curl_easy_getinfo(curl, CURLINFO_OS_ERRNO, &oserrno);
if(ECONNREFUSED == oserrno)
retry = RETRY_CONNREFUSED;
@@ -463,7 +460,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
/* If it returned OK. _or_ failonerror was enabled and it
returned due to such an error, check for HTTP transient
errors to retry on. */
- long protocol;
+ long protocol = 0;
curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
if((protocol == CURLPROTO_HTTP) || (protocol == CURLPROTO_HTTPS)) {
/* This was HTTP(S) */
@@ -491,7 +488,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
}
} /* if CURLE_OK */
else if(result) {
- long protocol;
+ long protocol = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol);
@@ -506,11 +503,15 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
retry = RETRY_FTP;
}
+ if(result && !retry && config->retry_all_errors)
+ retry = RETRY_ALL_ERRORS;
+
if(retry) {
long sleeptime = 0;
curl_off_t retry_after = 0;
static const char * const m[]={
NULL,
+ "(retrying all errors)",
"timeout",
"connection refused",
"HTTP error",
@@ -584,7 +585,7 @@ static CURLcode post_per_transfer(struct GlobalConfig *global,
else if(per->metalink) {
/* Metalink: Decide to try the next resource or not. Try the next resource
if download was not successful. */
- long response;
+ long response = 0;
if(CURLE_OK == result) {
/* TODO We want to try next resource when download was
not successful. How to know that? */
@@ -694,7 +695,7 @@ static CURLcode single_transfer(struct GlobalConfig *global,
{
CURLcode result = CURLE_OK;
struct getout *urlnode;
- metalinkfile *mlfile_last = NULL;
+ struct metalinkfile *mlfile_last = NULL;
bool orig_noprogress = global->noprogress;
bool orig_isatty = global->isatty;
struct State *state = &config->state;
@@ -735,10 +736,10 @@ static CURLcode single_transfer(struct GlobalConfig *global,
while(config->state.urlnode) {
char *infiles; /* might be a glob pattern */
- URLGlob *inglob = state->inglob;
+ struct URLGlob *inglob = state->inglob;
bool metalink = FALSE; /* metalink download? */
- metalinkfile *mlfile;
- metalink_resource *mlres;
+ struct metalinkfile *mlfile;
+ struct metalink_resource *mlres;
urlnode = config->state.urlnode;
if(urlnode->flags & GETOUT_METALINK) {
@@ -1551,11 +1552,90 @@ static CURLcode single_transfer(struct GlobalConfig *global,
}
}
+ /* In debug build of curl tool, using
+ * --cert loadmem=<filename>:<password> --cert-type p12
+ * must do the same thing than classic:
+ * --cert <filename>:<password> --cert-type p12
+ * but is designed to test blob */
+#if defined(CURLDEBUG) || defined(DEBUGBUILD)
+ if(config->cert && (strlen(config->cert) > 8) &&
+ (memcmp(config->cert, "loadmem=",8) == 0)) {
+ FILE *fInCert = fopen(config->cert + 8, "rb");
+ void *certdata = NULL;
+ long filesize = 0;
+ bool continue_reading = fInCert != NULL;
+ if(continue_reading)
+ continue_reading = fseek(fInCert, 0, SEEK_END) == 0;
+ if(continue_reading)
+ filesize = ftell(fInCert);
+ if(filesize < 0)
+ continue_reading = FALSE;
+ if(continue_reading)
+ continue_reading = fseek(fInCert, 0, SEEK_SET) == 0;
+ if(continue_reading)
+ certdata = malloc(((size_t)filesize) + 1);
+ if((!certdata) ||
+ ((int)fread(certdata, (size_t)filesize, 1, fInCert) != 1))
+ continue_reading = FALSE;
+ if(fInCert)
+ fclose(fInCert);
+ if((filesize > 0) && continue_reading) {
+ struct curl_blob structblob;
+ structblob.data = certdata;
+ structblob.len = (size_t)filesize;
+ structblob.flags = CURL_BLOB_COPY;
+ my_setopt_str(curl, CURLOPT_SSLCERT_BLOB, &structblob);
+ /* if test run well, we are sure we don't reuse
+ * original mem pointer */
+ memset(certdata, 0, (size_t)filesize);
+ }
+ free(certdata);
+ }
+ else
+#endif
my_setopt_str(curl, CURLOPT_SSLCERT, config->cert);
my_setopt_str(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert);
my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
my_setopt_str(curl, CURLOPT_PROXY_SSLCERTTYPE,
config->proxy_cert_type);
+
+
+#if defined(CURLDEBUG) || defined(DEBUGBUILD)
+ if(config->key && (strlen(config->key) > 8) &&
+ (memcmp(config->key, "loadmem=",8) == 0)) {
+ FILE *fInCert = fopen(config->key + 8, "rb");
+ void *certdata = NULL;
+ long filesize = 0;
+ bool continue_reading = fInCert != NULL;
+ if(continue_reading)
+ continue_reading = fseek(fInCert, 0, SEEK_END) == 0;
+ if(continue_reading)
+ filesize = ftell(fInCert);
+ if(filesize < 0)
+ continue_reading = FALSE;
+ if(continue_reading)
+ continue_reading = fseek(fInCert, 0, SEEK_SET) == 0;
+ if(continue_reading)
+ certdata = malloc(((size_t)filesize) + 1);
+ if((!certdata) ||
+ ((int)fread(certdata, (size_t)filesize, 1, fInCert) != 1))
+ continue_reading = FALSE;
+ if(fInCert)
+ fclose(fInCert);
+ if((filesize > 0) && continue_reading) {
+ struct curl_blob structblob;
+ structblob.data = certdata;
+ structblob.len = (size_t)filesize;
+ structblob.flags = CURL_BLOB_COPY;
+ my_setopt_str(curl, CURLOPT_SSLKEY_BLOB, &structblob);
+ /* if test run well, we are sure we don't reuse
+ * original mem pointer */
+ memset(certdata, 0, (size_t)filesize);
+ }
+ free(certdata);
+ }
+ else
+#endif
my_setopt_str(curl, CURLOPT_SSLKEY, config->key);
my_setopt_str(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key);
my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
@@ -1589,7 +1669,25 @@ static CURLcode single_transfer(struct GlobalConfig *global,
config->ssl_version | config->ssl_version_max);
my_setopt_enum(curl, CURLOPT_PROXY_SSLVERSION,
config->proxy_ssl_version);
+
+ {
+ long mask =
+ (config->ssl_allow_beast ? CURLSSLOPT_ALLOW_BEAST : 0) |
+ (config->ssl_revoke_best_effort ?
+ CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
+ (config->native_ca_store ?
+ CURLSSLOPT_NATIVE_CA : 0) |
+ (config->ssl_no_revoke ? CURLSSLOPT_NO_REVOKE : 0);
+
+ if(mask)
+ my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask);
+ }
+
+ if(config->proxy_ssl_allow_beast)
+ my_setopt(curl, CURLOPT_PROXY_SSL_OPTIONS,
+ (long)CURLSSLOPT_ALLOW_BEAST);
}
+
if(config->path_as_is)
my_setopt(curl, CURLOPT_PATH_AS_IS, 1L);
@@ -1900,20 +1998,6 @@ static CURLcode single_transfer(struct GlobalConfig *global,
my_setopt_str(curl, CURLOPT_GSSAPI_DELEGATION,
config->gssapi_delegation);
- /* new in 7.25.0, 7.44.0 and 7.70.0 */
- {
- long mask = (config->ssl_allow_beast ? CURLSSLOPT_ALLOW_BEAST : 0) |
- (config->ssl_revoke_best_effort ?
- CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
- (config->ssl_no_revoke ? CURLSSLOPT_NO_REVOKE : 0);
- if(mask)
- my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask);
- }
-
- if(config->proxy_ssl_allow_beast)
- my_setopt(curl, CURLOPT_PROXY_SSL_OPTIONS,
- (long)CURLSSLOPT_ALLOW_BEAST);
-
if(config->mail_auth)
my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
@@ -2410,6 +2494,7 @@ static CURLcode run_all_transfers(struct GlobalConfig *global,
CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[])
{
CURLcode result = CURLE_OK;
+ char *first_arg = curlx_convert_tchar_to_UTF8(argv[1]);
/* Setup proper locale from environment */
#ifdef HAVE_SETLOCALE
@@ -2418,8 +2503,8 @@ CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[])
/* Parse .curlrc if necessary */
if((argc == 1) ||
- (!curl_strequal(argv[1], "-q") &&
- !curl_strequal(argv[1], "--disable"))) {
+ (!curl_strequal(first_arg, "-q") &&
+ !curl_strequal(first_arg, "--disable"))) {
parseconfig(NULL, global); /* ignore possible failure */
/* If we had no arguments then make sure a url was specified in .curlrc */
@@ -2429,6 +2514,8 @@ CURLcode operate(struct GlobalConfig *global, int argc, argv_item_t argv[])
}
}
+ curlx_unicodefree(first_arg);
+
if(!result) {
/* Parse the command line arguments */
ParameterError res = parse_args(global, argc, argv);
diff --git a/src/tool_operate.h b/src/tool_operate.h
index 39227c0f3..0fa5adee5 100644
--- a/src/tool_operate.h
+++ b/src/tool_operate.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -38,8 +38,8 @@ struct per_transfer {
struct timeval retrystart;
bool metalink; /* nonzero for metalink download. */
bool metalink_next_res;
- metalinkfile *mlfile;
- metalink_resource *mlres;
+ struct metalinkfile *mlfile;
+ struct metalink_resource *mlres;
char *this_url;
char *outfile;
bool infdopen; /* TRUE if infd needs closing */
diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c
index 67702ebe2..c375bcc82 100644
--- a/src/tool_paramhlp.c
+++ b/src/tool_paramhlp.c
@@ -180,7 +180,7 @@ void cleanarg(char *str)
ParameterError str2num(long *val, const char *str)
{
if(str) {
- char *endptr;
+ char *endptr = NULL;
long num;
errno = 0;
num = strtol(str, &endptr, 10);
diff --git a/src/tool_parsecfg.c b/src/tool_parsecfg.c
index efb9159e7..5aeb2eebf 100644
--- a/src/tool_parsecfg.c
+++ b/src/tool_parsecfg.c
@@ -173,7 +173,7 @@ int parseconfig(const char *filename, struct GlobalConfig *global)
/* ... and has ended here */
if(*line)
- *line++ = '\0'; /* zero terminate, we have a local copy of the data */
+ *line++ = '\0'; /* null-terminate, we have a local copy of the data */
#ifdef DEBUG_CONFIG
fprintf(stderr, "GOT: %s\n", option);
@@ -203,7 +203,7 @@ int parseconfig(const char *filename, struct GlobalConfig *global)
line++;
if(*line) {
- *line = '\0'; /* zero terminate */
+ *line = '\0'; /* null-terminate */
/* to detect mistakes better, see if there's data following */
line++;
@@ -329,7 +329,7 @@ static const char *unslashquote(const char *line, char *param)
else
*param++ = *line++;
}
- *param = '\0'; /* always zero terminate */
+ *param = '\0'; /* always null-terminate */
return line;
}
diff --git a/src/tool_setopt.c b/src/tool_setopt.c
index f244ba490..9858d49c9 100644
--- a/src/tool_setopt.c
+++ b/src/tool_setopt.c
@@ -43,7 +43,7 @@
#define NV1(e, v) {#e, (v)}
#define NVEND {NULL, 0} /* sentinel to mark end of list */
-const NameValue setopt_nv_CURLPROXY[] = {
+const struct NameValue setopt_nv_CURLPROXY[] = {
NV(CURLPROXY_HTTP),
NV(CURLPROXY_HTTP_1_0),
NV(CURLPROXY_HTTPS),
@@ -54,7 +54,7 @@ const NameValue setopt_nv_CURLPROXY[] = {
NVEND,
};
-const NameValue setopt_nv_CURL_SOCKS_PROXY[] = {
+const struct NameValue setopt_nv_CURL_SOCKS_PROXY[] = {
NV(CURLPROXY_SOCKS4),
NV(CURLPROXY_SOCKS5),
NV(CURLPROXY_SOCKS4A),
@@ -62,7 +62,7 @@ const NameValue setopt_nv_CURL_SOCKS_PROXY[] = {
NVEND,
};
-const NameValueUnsigned setopt_nv_CURLAUTH[] = {
+const struct NameValueUnsigned setopt_nv_CURLAUTH[] = {
NV(CURLAUTH_ANY), /* combination */
NV(CURLAUTH_ANYSAFE), /* combination */
NV(CURLAUTH_BASIC),
@@ -76,7 +76,7 @@ const NameValueUnsigned setopt_nv_CURLAUTH[] = {
NVEND,
};
-const NameValue setopt_nv_CURL_HTTP_VERSION[] = {
+const struct NameValue setopt_nv_CURL_HTTP_VERSION[] = {
NV(CURL_HTTP_VERSION_NONE),
NV(CURL_HTTP_VERSION_1_0),
NV(CURL_HTTP_VERSION_1_1),
@@ -86,7 +86,7 @@ const NameValue setopt_nv_CURL_HTTP_VERSION[] = {
NVEND,
};
-const NameValue setopt_nv_CURL_SSLVERSION[] = {
+const struct NameValue setopt_nv_CURL_SSLVERSION[] = {
NV(CURL_SSLVERSION_DEFAULT),
NV(CURL_SSLVERSION_TLSv1),
NV(CURL_SSLVERSION_SSLv2),
@@ -98,7 +98,7 @@ const NameValue setopt_nv_CURL_SSLVERSION[] = {
NVEND,
};
-const NameValue setopt_nv_CURL_TIMECOND[] = {
+const struct NameValue setopt_nv_CURL_TIMECOND[] = {
NV(CURL_TIMECOND_IFMODSINCE),
NV(CURL_TIMECOND_IFUNMODSINCE),
NV(CURL_TIMECOND_LASTMOD),
@@ -106,14 +106,14 @@ const NameValue setopt_nv_CURL_TIMECOND[] = {
NVEND,
};
-const NameValue setopt_nv_CURLFTPSSL_CCC[] = {
+const struct NameValue setopt_nv_CURLFTPSSL_CCC[] = {
NV(CURLFTPSSL_CCC_NONE),
NV(CURLFTPSSL_CCC_PASSIVE),
NV(CURLFTPSSL_CCC_ACTIVE),
NVEND,
};
-const NameValue setopt_nv_CURLUSESSL[] = {
+const struct NameValue setopt_nv_CURLUSESSL[] = {
NV(CURLUSESSL_NONE),
NV(CURLUSESSL_TRY),
NV(CURLUSESSL_CONTROL),
@@ -121,15 +121,16 @@ const NameValue setopt_nv_CURLUSESSL[] = {
NVEND,
};
-const NameValueUnsigned setopt_nv_CURLSSLOPT[] = {
+const struct NameValueUnsigned setopt_nv_CURLSSLOPT[] = {
NV(CURLSSLOPT_ALLOW_BEAST),
NV(CURLSSLOPT_NO_REVOKE),
NV(CURLSSLOPT_NO_PARTIALCHAIN),
NV(CURLSSLOPT_REVOKE_BEST_EFFORT),
+ NV(CURLSSLOPT_NATIVE_CA),
NVEND,
};
-const NameValue setopt_nv_CURL_NETRC[] = {
+const struct NameValue setopt_nv_CURL_NETRC[] = {
NV(CURL_NETRC_IGNORED),
NV(CURL_NETRC_OPTIONAL),
NV(CURL_NETRC_REQUIRED),
@@ -138,7 +139,7 @@ const NameValue setopt_nv_CURL_NETRC[] = {
/* These mappings essentially triplicated - see
* tool_libinfo.c and tool_paramhlp.c */
-const NameValue setopt_nv_CURLPROTO[] = {
+const struct NameValue setopt_nv_CURLPROTO[] = {
NV(CURLPROTO_ALL), /* combination */
NV(CURLPROTO_DICT),
NV(CURLPROTO_FILE),
@@ -166,7 +167,7 @@ const NameValue setopt_nv_CURLPROTO[] = {
};
/* These options have non-zero default values. */
-static const NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
+static const struct NameValue setopt_nv_CURLNONZERODEFAULTS[] = {
NV1(CURLOPT_SSL_VERIFYPEER, 1),
NV1(CURLOPT_SSL_VERIFYHOST, 1),
NV1(CURLOPT_SSL_ENABLE_NPN, 1),
@@ -272,7 +273,7 @@ static char *c_escape(const char *str, size_t len)
/* setopt wrapper for enum types */
CURLcode tool_setopt_enum(CURL *curl, struct GlobalConfig *config,
const char *name, CURLoption tag,
- const NameValue *nvlist, long lval)
+ const struct NameValue *nvlist, long lval)
{
CURLcode ret = CURLE_OK;
bool skip = FALSE;
@@ -283,7 +284,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;
+ const struct NameValue *nv = NULL;
for(nv = nvlist; nv->name; nv++) {
if(nv->value == lval)
break; /* found it */
@@ -306,7 +307,7 @@ CURLcode tool_setopt_enum(CURL *curl, struct GlobalConfig *config,
/* setopt wrapper for flags */
CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
const char *name, CURLoption tag,
- const NameValue *nvlist, long lval)
+ const struct NameValue *nvlist, long lval)
{
CURLcode ret = CURLE_OK;
bool skip = FALSE;
@@ -319,7 +320,7 @@ CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
/* we only use this for real if --libcurl was used */
char preamble[80]; /* should accommodate any symbol name */
long rest = lval; /* bits not handled yet */
- const NameValue *nv = NULL;
+ const struct NameValue *nv = NULL;
msnprintf(preamble, sizeof(preamble),
"curl_easy_setopt(hnd, %s, ", name);
for(nv = nvlist; nv->name; nv++) {
@@ -348,7 +349,7 @@ CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
/* setopt wrapper for bitmasks */
CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
const char *name, CURLoption tag,
- const NameValueUnsigned *nvlist,
+ const struct NameValueUnsigned *nvlist,
long lval)
{
CURLcode ret = CURLE_OK;
@@ -362,7 +363,7 @@ CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
/* we only use this for real if --libcurl was used */
char preamble[80];
unsigned long rest = (unsigned long)lval;
- const NameValueUnsigned *nv = NULL;
+ const struct NameValueUnsigned *nv = NULL;
msnprintf(preamble, sizeof(preamble),
"curl_easy_setopt(hnd, %s, ", name);
for(nv = nvlist; nv->name; nv++) {
@@ -417,13 +418,13 @@ static CURLcode libcurl_generate_slist(struct curl_slist *slist, int *slistno)
static CURLcode libcurl_generate_mime(CURL *curl,
struct GlobalConfig *config,
- tool_mime *toolmime,
+ struct tool_mime *toolmime,
int *mimeno); /* Forward. */
/* Wrapper to generate source code for a mime part. */
static CURLcode libcurl_generate_mime_part(CURL *curl,
struct GlobalConfig *config,
- tool_mime *part,
+ struct tool_mime *part,
int mimeno)
{
CURLcode ret = CURLE_OK;
@@ -556,7 +557,7 @@ nomem:
/* Wrapper to generate source code for a mime structure. */
static CURLcode libcurl_generate_mime(CURL *curl,
struct GlobalConfig *config,
- tool_mime *toolmime,
+ struct tool_mime *toolmime,
int *mimeno)
{
CURLcode ret = CURLE_OK;
@@ -640,7 +641,7 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
/* Value is expected to be a long */
long lval = va_arg(arg, long);
long defval = 0L;
- const NameValue *nv = NULL;
+ const struct NameValue *nv = NULL;
for(nv = setopt_nv_CURLNONZERODEFAULTS; nv->name; nv++) {
if(!strcmp(name, nv->name)) {
defval = nv->value;
@@ -682,7 +683,7 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
ret = curl_easy_setopt(curl, tag, pval);
}
- else {
+ else if(tag < CURLOPTTYPE_BLOB) {
/* Value is expected to be curl_off_t */
curl_off_t oval = va_arg(arg, curl_off_t);
msnprintf(buf, sizeof(buf),
@@ -693,6 +694,20 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *config,
if(!oval)
skip = TRUE;
}
+ else {
+ /* Value is a blob */
+ void *pblob = va_arg(arg, void *);
+
+ /* blobs are never printable */
+ if(pblob) {
+ value = "blobpointer";
+ remark = TRUE;
+ }
+ else
+ skip = TRUE;
+
+ ret = curl_easy_setopt(curl, tag, pblob);
+ }
va_end(arg);
diff --git a/src/tool_setopt.h b/src/tool_setopt.h
index 48e9e818d..9fe142cf1 100644
--- a/src/tool_setopt.h
+++ b/src/tool_setopt.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -43,27 +43,27 @@ bool tool_setopt_skip(CURLoption tag);
#ifndef CURL_DISABLE_LIBCURL_OPTION
/* Associate symbolic names with option values */
-typedef struct {
+struct NameValue {
const char *name;
long value;
-} NameValue;
+};
-typedef struct {
+struct NameValueUnsigned {
const char *name;
unsigned long value;
-} NameValueUnsigned;
-
-extern const NameValue setopt_nv_CURLPROXY[];
-extern const NameValue setopt_nv_CURL_SOCKS_PROXY[];
-extern const NameValue setopt_nv_CURL_HTTP_VERSION[];
-extern const NameValue setopt_nv_CURL_SSLVERSION[];
-extern const NameValue setopt_nv_CURL_TIMECOND[];
-extern const NameValue setopt_nv_CURLFTPSSL_CCC[];
-extern const NameValue setopt_nv_CURLUSESSL[];
-extern const NameValueUnsigned setopt_nv_CURLSSLOPT[];
-extern const NameValue setopt_nv_CURL_NETRC[];
-extern const NameValue setopt_nv_CURLPROTO[];
-extern const NameValueUnsigned setopt_nv_CURLAUTH[];
+};
+
+extern const struct NameValue setopt_nv_CURLPROXY[];
+extern const struct NameValue setopt_nv_CURL_SOCKS_PROXY[];
+extern const struct NameValue setopt_nv_CURL_HTTP_VERSION[];
+extern const struct NameValue setopt_nv_CURL_SSLVERSION[];
+extern const struct NameValue setopt_nv_CURL_TIMECOND[];
+extern const struct NameValue setopt_nv_CURLFTPSSL_CCC[];
+extern const struct NameValue setopt_nv_CURLUSESSL[];
+extern const struct NameValueUnsigned setopt_nv_CURLSSLOPT[];
+extern const struct NameValue setopt_nv_CURL_NETRC[];
+extern const struct NameValue setopt_nv_CURLPROTO[];
+extern const struct NameValueUnsigned setopt_nv_CURLAUTH[];
/* Map options to NameValue sets */
#define setopt_nv_CURLOPT_HTTP_VERSION setopt_nv_CURL_HTTP_VERSION
@@ -85,13 +85,13 @@ extern const NameValueUnsigned setopt_nv_CURLAUTH[];
CURLcode tool_setopt_enum(CURL *curl, struct GlobalConfig *config,
const char *name, CURLoption tag,
- const NameValue *nv, long lval);
+ const struct NameValue *nv, long lval);
CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
const char *name, CURLoption tag,
- const NameValue *nv, long lval);
+ const struct NameValue *nv, long lval);
CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
const char *name, CURLoption tag,
- const NameValueUnsigned *nv, long lval);
+ const struct NameValueUnsigned *nv, long lval);
CURLcode tool_setopt_mimepost(CURL *curl, struct GlobalConfig *config,
const char *name, CURLoption tag,
curl_mime *mimepost);
diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c
index 6c8716104..430ca88ba 100644
--- a/src/tool_urlglob.c
+++ b/src/tool_urlglob.c
@@ -34,9 +34,9 @@
#define GLOBERROR(string, column, code) \
glob->error = string, glob->pos = column, code
-static CURLcode glob_fixed(URLGlob *glob, char *fixed, size_t len)
+static CURLcode glob_fixed(struct URLGlob *glob, char *fixed, size_t len)
{
- URLPattern *pat = &glob->pattern[glob->size];
+ struct URLPattern *pat = &glob->pattern[glob->size];
pat->type = UPTSet;
pat->content.Set.size = 1;
pat->content.Set.ptr_s = 0;
@@ -74,14 +74,14 @@ static int multiply(unsigned long *amount, long with)
return 0;
}
-static CURLcode glob_set(URLGlob *glob, char **patternp,
+static CURLcode glob_set(struct URLGlob *glob, char **patternp,
size_t *posp, unsigned long *amount,
int globindex)
{
/* processes a set expression with the point behind the opening '{'
','-separated elements are collected until the next closing '}'
*/
- URLPattern *pat;
+ struct URLPattern *pat;
bool done = FALSE;
char *buf = glob->glob_buffer;
char *pattern = *patternp;
@@ -168,7 +168,7 @@ static CURLcode glob_set(URLGlob *glob, char **patternp,
return CURLE_OK;
}
-static CURLcode glob_range(URLGlob *glob, char **patternp,
+static CURLcode glob_range(struct URLGlob *glob, char **patternp,
size_t *posp, unsigned long *amount,
int globindex)
{
@@ -178,7 +178,7 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
- num range with leading zeros: e.g. "001-999]"
expression is checked for well-formedness and collected until the next ']'
*/
- URLPattern *pat;
+ struct URLPattern *pat;
int rc;
char *pattern = *patternp;
char *c;
@@ -319,6 +319,8 @@ static CURLcode glob_range(URLGlob *glob, char **patternp,
return CURLE_OK;
}
+#define MAX_IP6LEN 128
+
static bool peek_ipv6(const char *str, size_t *skip)
{
/*
@@ -326,30 +328,35 @@ static bool peek_ipv6(const char *str, size_t *skip)
* - Valid globs contain a hyphen and <= 1 colon.
* - IPv6 literals contain no hyphens and >= 2 colons.
*/
- size_t i = 0;
- size_t colons = 0;
- if(str[i++] != '[') {
+ char hostname[MAX_IP6LEN];
+ CURLU *u;
+ char *endbr = strchr(str, ']');
+ size_t hlen;
+ CURLUcode rc;
+ if(!endbr)
return FALSE;
- }
- for(;;) {
- const char c = str[i++];
- if(ISALNUM(c) || c == '.' || c == '%') {
- /* ok */
- }
- else if(c == ':') {
- colons++;
- }
- else if(c == ']') {
- *skip = i;
- return colons >= 2 ? TRUE : FALSE;
- }
- else {
- return FALSE;
- }
- }
+
+ hlen = endbr - str + 1;
+ if(hlen >= MAX_IP6LEN)
+ return FALSE;
+
+ u = curl_url();
+ if(!u)
+ return FALSE;
+
+ memcpy(hostname, str, hlen);
+ hostname[hlen] = 0;
+
+ /* ask to "guess scheme" as then it works without a https:// prefix */
+ rc = curl_url_set(u, CURLUPART_URL, hostname, CURLU_GUESS_SCHEME);
+
+ curl_url_cleanup(u);
+ if(!rc)
+ *skip = hlen;
+ return rc ? FALSE : TRUE;
}
-static CURLcode glob_parse(URLGlob *glob, char *pattern,
+static CURLcode glob_parse(struct URLGlob *glob, char *pattern,
size_t pos, unsigned long *amount)
{
/* processes a literal string component of a URL
@@ -427,14 +434,14 @@ static CURLcode glob_parse(URLGlob *glob, char *pattern,
return res;
}
-CURLcode glob_url(URLGlob **glob, char *url, unsigned long *urlnum,
+CURLcode glob_url(struct URLGlob **glob, char *url, unsigned long *urlnum,
FILE *error)
{
/*
* We can deal with any-size, just make a buffer with the same length
* as the specified URL!
*/
- URLGlob *glob_expand;
+ struct URLGlob *glob_expand;
unsigned long amount = 0;
char *glob_buffer;
CURLcode res;
@@ -446,7 +453,7 @@ CURLcode glob_url(URLGlob **glob, char *url, unsigned long *urlnum,
return CURLE_OUT_OF_MEMORY;
glob_buffer[0] = 0;
- glob_expand = calloc(1, sizeof(URLGlob));
+ glob_expand = calloc(1, sizeof(struct URLGlob));
if(!glob_expand) {
Curl_safefree(glob_buffer);
return CURLE_OUT_OF_MEMORY;
@@ -483,7 +490,7 @@ CURLcode glob_url(URLGlob **glob, char *url, unsigned long *urlnum,
return CURLE_OK;
}
-void glob_cleanup(URLGlob* glob)
+void glob_cleanup(struct URLGlob *glob)
{
size_t i;
int elem;
@@ -506,9 +513,9 @@ void glob_cleanup(URLGlob* glob)
Curl_safefree(glob);
}
-CURLcode glob_next_url(char **globbed, URLGlob *glob)
+CURLcode glob_next_url(char **globbed, struct URLGlob *glob)
{
- URLPattern *pat;
+ struct URLPattern *pat;
size_t i;
size_t len;
size_t buflen = glob->urllen + 1;
@@ -600,7 +607,7 @@ CURLcode glob_next_url(char **globbed, URLGlob *glob)
return CURLE_OK;
}
-CURLcode glob_match_url(char **result, char *filename, URLGlob *glob)
+CURLcode glob_match_url(char **result, char *filename, struct URLGlob *glob)
{
char *target;
size_t allocsize;
@@ -625,7 +632,7 @@ CURLcode glob_match_url(char **result, char *filename, URLGlob *glob)
if(*filename == '#' && ISDIGIT(filename[1])) {
char *ptr = filename;
unsigned long num = strtoul(&filename[1], &filename, 10);
- URLPattern *pat = NULL;
+ struct URLPattern *pat = NULL;
if(num && (num < glob->size)) {
unsigned long i;
diff --git a/src/tool_urlglob.h b/src/tool_urlglob.h
index 82326c0a0..5ed76671e 100644
--- a/src/tool_urlglob.h
+++ b/src/tool_urlglob.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -29,7 +29,7 @@ typedef enum {
UPTNumRange
} URLPatternType;
-typedef struct {
+struct URLPattern {
URLPatternType type;
int globindex; /* the number of this particular glob or -1 if not used
within {} or [] */
@@ -53,24 +53,24 @@ typedef struct {
unsigned long step;
} NumRange;
} content;
-} URLPattern;
+};
/* the total number of globs supported */
#define GLOB_PATTERN_NUM 100
-typedef struct {
- URLPattern pattern[GLOB_PATTERN_NUM];
+struct URLGlob {
+ struct URLPattern pattern[GLOB_PATTERN_NUM];
size_t size;
size_t urllen;
char *glob_buffer;
char beenhere;
const char *error; /* error message */
size_t pos; /* column position of error or 0 */
-} URLGlob;
+};
-CURLcode glob_url(URLGlob**, char *, unsigned long *, FILE *);
-CURLcode glob_next_url(char **, URLGlob *);
-CURLcode glob_match_url(char **, char *, URLGlob *);
-void glob_cleanup(URLGlob* glob);
+CURLcode glob_url(struct URLGlob**, char *, unsigned long *, FILE *);
+CURLcode glob_next_url(char **, struct URLGlob *);
+CURLcode glob_match_url(char **, char *, struct URLGlob *);
+void glob_cleanup(struct URLGlob *glob);
#endif /* HEADER_CURL_TOOL_URLGLOB_H */
diff --git a/src/tool_vms.c b/src/tool_vms.c
index 7fa0dd62b..7871b20f3 100644
--- a/src/tool_vms.c
+++ b/src/tool_vms.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -122,13 +122,13 @@ void vms_special_exit(int code, int vms_show)
*/
/* Structure to hold a DECC$* feature name and its desired value. */
-typedef struct {
+struct decc_feat_t {
char *name;
int value;
-} decc_feat_t;
+};
/* Array of DECC$* feature names and their desired values. */
-static decc_feat_t decc_feat_array[] = {
+static struct decc_feat_t decc_feat_array[] = {
/* Preserve command-line case with SET PROCESS/PARSE_STYLE=EXTENDED */
{ "DECC$ARGV_PARSE_STYLE", 1 },
/* Preserve case for file names on ODS5 disks. */
diff --git a/src/tool_writeout.c b/src/tool_writeout.c
index 32c95b45f..d8ccbcbda 100644
--- a/src/tool_writeout.c
+++ b/src/tool_writeout.c
@@ -131,7 +131,7 @@ void ourWriteOut(CURL *curl, struct OutStruct *outs, const char *writeinfo)
continue;
}
keepit = *end;
- *end = 0; /* zero terminate */
+ *end = 0; /* null-terminate */
for(i = 0; variables[i].name; i++) {
if(curl_strequal(ptr, variables[i].name)) {
match = TRUE;
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index a145b2b04..60ce5c262 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -19,7 +19,33 @@
# KIND, either express or implied.
#
###########################################################################
+add_custom_target(testdeps)
add_subdirectory(data)
add_subdirectory(libtest)
add_subdirectory(server)
add_subdirectory(unit)
+
+function(add_runtests targetname test_flags)
+ # Use a special '${TFLAGS}' placeholder as last argument which will be
+ # replaced by the contents of the environment variable in runtests.pl.
+ # This is a workaround for CMake's limitation where commands executed by
+ # 'make' or 'ninja' cannot portably reference environment variables.
+ string(REPLACE " " ";" test_flags_list "${test_flags}")
+ add_custom_target(${targetname}
+ COMMAND
+ "${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/runtests.pl"
+ ${test_flags_list}
+ "\${TFLAGS}"
+ DEPENDS testdeps
+ VERBATIM USES_TERMINAL
+ )
+endfunction()
+
+add_runtests(test "")
+add_runtests(test-quiet "-a -s")
+add_runtests(test-am "-a -am")
+add_runtests(test-full "-a -p -r")
+# !flaky means that it'll skip all tests using the flaky keyword
+add_runtests(test-nonflaky "-a -p !flaky")
+add_runtests(test-torture "-a -t")
+add_runtests(test-event "-a -e")
diff --git a/tests/FILEFORMAT.md b/tests/FILEFORMAT.md
index 034b1a73c..62cddd1a7 100644
--- a/tests/FILEFORMAT.md
+++ b/tests/FILEFORMAT.md
@@ -10,16 +10,74 @@ are syntactically valid XML, although a few files are not (lack of support for
character entities and the preservation of CR/LF characters at the end of
lines are the biggest differences).
-Each test case exists as a file matching the format `tests/data/testNUM`,
-where NUM is considered the unique test number.
+Each test case source exists as a file matching the format
+`tests/data/testNUM`, where NUM is the unique test number, and must begin with
+a 'testcase' tag, which encompasses the remainder of the file.
-The file begins with a 'testcase' tag, which encompasses the remainder of the
-file.
+# Preprocessing
+
+When a test is to be executed, the source file is first preprocessed and
+variables are substituted by the their respective contents and the output
+version of the test file is stored as `log/testNUM`. That version is what will
+be read and used by the test servers.
+
+# Variables
+
+When the test is preprocessed, a range of "variables" in the test file will be
+replaced by their content at that time.
+
+Available substitute variables include:
+
+- `%CLIENT6IP` - IPv6 address of the client running curl
+- `%CLIENTIP` - IPv4 address of the client running curl
+- `%CURL` - Path to the curl executable
+- `%FILE_PWD` - Current directory, on windows prefixed with a slash
+- `%FTP6PORT` - IPv6 port number of the FTP server
+- `%FTPPORT` - Port number of the FTP server
+- `%FTPSPORT` - Port number of the FTPS server
+- `%FTPTIME2` - Timeout in seconds that should be just sufficient to receive a
+ response from the test FTP server
+- `%FTPTIME3` - Even longer than %FTPTIME2
+- `%GOPHER6PORT` - IPv6 port number of the Gopher server
+- `%GOPHERPORT` - Port number of the Gopher server
+- `%HOST6IP` - IPv6 address of the host running this test
+- `%HOSTIP` - IPv4 address of the host running this test
+- `%HTTP6PORT` - IPv6 port number of the HTTP server
+- `%HTTPPORT` - Port number of the HTTP server
+- `%HTTPSPORT` - Port number of the HTTPS server
+- `%HTTPSPROXYPORT` - Port number of the HTTPS-proxy
+- `%HTTPTLS6PORT` - IPv6 port number of the HTTP TLS server
+- `%HTTPTLSPORT` - Port number of the HTTP TLS server
+- `%HTTPUNIXPATH` - Path to the Unix socket of the HTTP server
+- `%IMAP6PORT` - IPv6 port number of the IMAP server
+- `%IMAPPORT` - Port number of the IMAP server
+- `%MQTTPORT` - Port number of the MQTT server
+- `%NEGTELNETPORT` - Port number of the telnet server
+- `%NOLISTENPORT` - Port number where no service is listening
+- `%POP36PORT` - IPv6 port number of the POP3 server
+- `%POP3PORT` - Port number of the POP3 server
+- `%POSIX_PWD` - Current directory somewhat mingw friendly
+- `%PROXYPORT` - Port number of the HTTP proxy
+- `%PWD` - Current directory
+- `%RTSP6PORT` - IPv6 port number of the RTSP server
+- `%RTSPPORT` - Port number of the RTSP server
+- `%SMBPORT` - Port number of the SMB server
+- `%SMBSPORT` - Port number of the SMBS server
+- `%SMTP6PORT` - IPv6 port number of the SMTP server
+- `%SMTPPORT` - Port number of the SMTP server
+- `%SOCKSPORT` - Port number of the SOCKS4/5 server
+- `%SRCDIR` - Full path to the source dir
+- `%SSHPORT` - Port number of the SCP/SFTP server
+- `%SSHSRVMD5` - MD5 of SSH server's public key
+- `%SSH_PWD` - Current directory friendly for the SSH server
+- `%TFTP6PORT` - IPv6 port number of the TFTP server
+- `%TFTPPORT` - Port number of the TFTP server
+- `%USER` - Login ID of the user running the test
# `<testcase>`
-Each test is always within the testcase tag. Each test case is split up in
-four main sections: `info`, `reply`, `client` and `verify`.
+Each test is always specified entirely within the testcase tag. Each test case
+is split up in four main sections: `info`, `reply`, `client` and `verify`.
- **info** provides information about the test case
@@ -225,11 +283,14 @@ SKIPPED.
Features testable here are:
- `alt-svc`
+- `cookies`
- `crypto`
- `debug`
+- `DoH`
- `getrlimit`
- `GnuTLS`
- `GSS-API`
+- `HTTP-auth`
- `http/2`
- `idn`
- `ipv6`
@@ -239,10 +300,15 @@ Features testable here are:
- `libz`
- `manual`
- `Metalink`
+- `Mime`
+- `netrc`
- `NSS`
- `NTLM`
- `OpenSSL`
+- `parsedate`
+- `proxy`
- `PSL`
+- `shuffle-dns`
- `socks`
- `SPNEGO`
- `SSL`
@@ -251,8 +317,10 @@ Features testable here are:
- `threaded-resolver`
- `TLS-SRP`
- `TrackMemory`
+- `typecheck`
- `unittest`
- `unix-sockets`
+- `verbose-strings`
- `win32`
- `WinSSL`
@@ -270,13 +338,12 @@ restart servers.
A command line that if set gets run by the test script before the test. If an
output is displayed by the command or if the return code is non-zero, the test
will be skipped and the (single-line) output will be displayed as reason for
-not running the test. Variables are substituted as in the `<command>`
- section.
+not running the test.
### `<postcheck>`
A command line that if set gets run by the test script after the test. If
the command exists with a non-zero status code, the test will be considered
-to have failed. Variables are substituted as in the `<command>` section.
+to have failed.
### `<tool>`
Name of tool to invoke instead of "curl". This tool must be built and exist
@@ -292,10 +359,9 @@ Brief test case description, shown when the test runs.
Set the given environment variables to the specified value before the actual
command is run. They are cleared again after the command has been run.
-Variables are first substituted as in the `<command>` section.
+
### `<command [option="no-output/no-include/force-output/binary-trace"] [timeout="secs"][delay="secs"][type="perl"]>`
-Command line to run. There's a bunch of %variables that get replaced
-accordingly.
+Command line to run.
Note that the URL that gets passed to the server actually controls what data
that is returned. The last slash in the URL must be followed by a number. That
@@ -339,56 +405,9 @@ parameter is the not negative integer number of seconds for the delay. This
'delay' attribute is intended for very specific test cases, and normally not
needed.
-Available substitute variables include:
-
-- `%CLIENT6IP` - IPv6 address of the client running curl
-- `%CLIENTIP` - IPv4 address of the client running curl
-- `%CURL` - Path to the curl executable
-- `%FILE_PWD` - Current directory, on windows prefixed with a slash
-- `%FTP2PORT` - Port number of the FTP server 2
-- `%FTP6PORT` - IPv6 port number of the FTP server
-- `%FTPPORT` - Port number of the FTP server
-- `%FTPSPORT` - Port number of the FTPS server
-- `%FTPTIME2` - Timeout in seconds that should be just sufficient to receive a response from the test FTP server
-- `%FTPTIME3` - Even longer than %FTPTIME2
-- `%GOPHER6PORT` - IPv6 port number of the Gopher server
-- `%GOPHERPORT` - Port number of the Gopher server
-- `%HOST6IP` - IPv6 address of the host running this test
-- `%HOSTIP` - IPv4 address of the host running this test
-- `%HTTP6PORT` - IPv6 port number of the HTTP server
-- `%HTTPPORT` - Port number of the HTTP server
-- `%HTTPSPORT` - Port number of the HTTPS server
-- `%HTTPTLS6PORT` - IPv6 port number of the HTTP TLS server
-- `%HTTPTLSPORT` - Port number of the HTTP TLS server
-- `%HTTPUNIXPATH` - Path to the Unix socket of the HTTP server
-- `%IMAP6PORT` - IPv6 port number of the IMAP server
-- `%IMAPPORT` - Port number of the IMAP server
-- `%MQTTPORT` - Port number of the MQTT server
-- `%NEGTELNETPORT` - Port number of the telnet server
-- `%NOLISTENPORT` - Port number where no service is listening
-- `%POP36PORT` - IPv6 port number of the POP3 server
-- `%POP3PORT` - Port number of the POP3 server
-- `%POSIX_PWD` - Current directory somewhat mingw friendly
-- `%PROXYPORT` - Port number of the HTTP proxy
-- `%PWD` - Current directory
-- `%RTSP6PORT` - IPv6 port number of the RTSP server
-- `%RTSPPORT` - Port number of the RTSP server
-- `%SMBPORT` - Port number of the SMB server
-- `%SMBSPORT` - Port number of the SMBS server
-- `%SMTP6PORT` - IPv6 port number of the SMTP server
-- `%SMTPPORT` - Port number of the SMTP server
-- `%SOCKSPORT` - Port number of the SOCKS4/5 server
-- `%SRCDIR` - Full path to the source dir
-- `%SSHPORT` - Port number of the SCP/SFTP server
-- `%SSHSRVMD5` - MD5 of SSH server's public key
-- `%TFTP6PORT` - IPv6 port number of the TFTP server
-- `%TFTPPORT` - Port number of the TFTP server
-- `%USER` - Login ID of the user running the test
-
### `<file name="log/filename">`
This creates the named file with this content before the test case is run,
-which is useful if the test case needs a file to act on. Variables are
-substituted on the contents of the file as in the `<command>` section.
+which is useful if the test case needs a file to act on.
### `<stdin [nonewline="yes"]>`
Pass this given data on stdin to the tool.
@@ -415,20 +434,27 @@ advanced. Example: `s/^EPRT .*/EPRT stripped/`.
the protocol dump curl should transmit, if 'nonewline' is set, we will cut off
the trailing newline of this given data before comparing with the one actually
-sent by the client Variables are substituted as in the `<command>` section.
-The `<strip>` and `<strippart>` rules are applied before comparisons are made.
+sent by the client The `<strip>` and `<strippart>` rules are applied before
+comparisons are made.
### `<proxy [nonewline="yes"]>`
The protocol dump curl should transmit to a HTTP proxy (when the http-proxy
server is used), if 'nonewline' is set, we will cut off the trailing newline
of this given data before comparing with the one actually sent by the client
-Variables are substituted as in the `<command>` section. The `<strip>` and
-`<strippart>` rules are applied before comparisons are made.
+The `<strip>` and `<strippart>` rules are applied before comparisons are made.
+
+### `<stderr [mode="text"] [nonewline="yes"]>`
+This verifies that this data was passed to stderr.
+
+Use the mode="text" attribute if the output is in text mode on platforms that
+have a text/binary difference.
+
+If 'nonewline' is set, we will cut off the trailing newline of this given data
+before comparing with the one actually received by the client
### `<stdout [mode="text"] [nonewline="yes"]>`
-This verifies that this data was passed to stdout. Variables are
-substituted as in the `<command>` section.
+This verifies that this data was passed to stdout.
Use the mode="text" attribute if the output is in text mode on platforms that
have a text/binary difference.
@@ -439,8 +465,7 @@ before comparing with the one actually received by the client
### `<file name="log/filename" [mode="text"]>`
The file's contents must be identical to this after the test is complete. Use
the mode="text" attribute if the output is in text mode on platforms that have
-a text/binary difference. Variables are substituted as in the `<command>`
-section.
+a text/binary difference.
### `<file1>`
1 to 4 can be appended to 'file' to compare more files.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index af76cf3d5..349c60942 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -28,11 +28,12 @@ ED_3 = valgrind.pm ftp.pm sshserver.pl.in sshhelp.pm pathhelp.pm testcurl.1 runt
ED_4 = serverhelp.pm tftpserver.pl.in rtspserver.pl.in directories.pm symbol-scan.pl.in
ED_5 = CMakeLists.txt mem-include-scan.pl.in valgrind.supp extern-scan.pl.in
ED_6 = manpage-scan.pl.in nroff-scan.pl.in http2-server.pl.in dictserver.py.in
-ED_7 = negtelnetserver.py.in smbserver.py.in curl_test_data.py.in objnames-test08.sh objnames-test10.sh
-ED_8 = objnames.inc disable-scan.pl.in error-codes.pl.in
-ED_9 = badsymbols.pl.in azure.pm appveyor.pm version-scan.pl.in
+ED_7 = negtelnetserver.py.in smbserver.py.in curl_test_data.py.in
+ED_8 = objnames-test08.sh objnames-test10.sh objnames.inc
+ED_9 = disable-scan.pl.in error-codes.pl.in badsymbols.pl.in
+ED_10 = azure.pm appveyor.pm version-scan.pl.in options-scan.pl
-EXTRA_DIST = $(ED_1) $(ED_2) $(ED_3) $(ED_4) $(ED_5) $(ED_6) $(ED_7) $(ED_8) $(ED_9)
+EXTRA_DIST = $(ED_1) $(ED_2) $(ED_3) $(ED_4) $(ED_5) $(ED_6) $(ED_7) $(ED_8) $(ED_9) $(ED_10)
check_SCRIPTS = smbserver.py curl_test_data.py negtelnetserver.py dictserver.py
diff --git a/tests/badsymbols.pl.in b/tests/badsymbols.pl.in
index 2d1032e09..1ecc4f669 100755
--- a/tests/badsymbols.pl.in
+++ b/tests/badsymbols.pl.in
@@ -76,7 +76,8 @@ sub scanenums {
next;
}
# parse this!
- $skipit = 0,
+ $skipit = 0;
+ next;
}
if($skipit) {
next;
@@ -88,8 +89,7 @@ sub scanenums {
if(($_ !~ /\}(;|)/) &&
($_ ne "typedef") &&
($_ ne "enum") &&
- ($_ !~ /^[ \t]*$/) &&
- ($_ ne "#")) {
+ ($_ !~ /^[ \t]*$/)) {
push @syms, $_;
}
}
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index c9ae94056..6319d78f2 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -58,7 +58,7 @@ test307 test308 test309 test310 test311 test312 test313 test314 test315 \
test316 test317 test318 test319 test320 test321 test322 test323 test324 \
test325 test326 test327 test328 test329 test330 test331 test332 test333 \
test334 test335 test336 test337 test338 test339 test340 test341 test342 \
-test343 test344 test345 \
+test343 test344 test345 test346 \
test350 test351 test352 test353 test354 test355 test356 test357 test358 \
test359 \
test393 test394 test395 \
@@ -99,12 +99,12 @@ 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 test846 test847 test848 test849 \
-test850 test851 test852 test853 test854 test855 test856 test857 test858 \
-test859 test860 test861 test862 test863 test864 test865 test866 test867 \
-test868 test869 test870 test871 test872 test873 test874 test875 test876 \
-test877 test878 test879 test880 test881 test882 test883 test884 test885 \
-test886 test887 test888 test889 test890 test891 test892 test893 test894 \
+test845 test846 test847 test848 test849 test850 test851 test852 test853 \
+test854 test855 test856 test857 test858 test859 test860 test861 test862 \
+test863 test864 test865 test866 test867 test868 test869 test870 test871 \
+test872 test873 test874 test875 test876 test877 test878 test879 test880 \
+test881 test882 test883 test884 test885 test886 test887 test888 test889 \
+test890 test891 test892 test893 test894 test895 test896 \
\
test900 test901 test902 test903 test904 test905 test906 test907 test908 \
test909 test910 test911 test912 test913 test914 test915 test916 test917 \
@@ -113,7 +113,7 @@ test927 test928 test929 test930 test931 test932 test933 test934 test935 \
test936 test937 test938 test939 test940 test941 test942 test943 test944 \
test945 test946 test947 test948 test949 test950 test951 test952 test953 \
test954 test955 test956 test957 test958 test959 test960 test961 test962 \
-test963 test964 test965 test966 test967 test968 test969 test970 \
+test963 test964 test965 test966 test967 test968 test969 test970 test971 \
\
test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
@@ -136,8 +136,10 @@ test1136 test1137 test1138 test1141 test1142 test1143 \
test1144 test1145 test1146 test1147 test1148 test1149 test1150 test1151 \
test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 \
test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 \
+test1168 \
\
test1170 test1171 test1172 test1173 test1174 test1175 test1176 test1177 \
+test1178 test1179 \
\
test1190 test1191 test1192 test1193 test1194 test1195 test1196 \
\
@@ -154,6 +156,7 @@ test1268 test1269 test1270 test1271 \
\
test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 \
test1288 test1289 test1290 test1291 test1292 test1293 test1294 test1295 \
+test1296 \
\
test1298 test1299 test1300 test1301 test1302 test1303 test1304 test1305 \
test1306 test1307 test1308 test1309 test1310 test1311 test1312 test1313 \
@@ -175,14 +178,15 @@ test1426 test1427 test1428 test1429 test1430 test1431 test1432 test1433 \
test1434 test1435 test1436 test1437 test1438 test1439 test1440 test1441 \
test1442 test1443 test1444 test1445 test1446 test1447 test1448 test1449 \
test1450 test1451 test1452 test1453 test1454 test1455 test1456 test1457 \
-test1458 test1459 test1500 test1501 test1502 test1503 test1504 test1505 \
-test1506 test1507 test1508 test1509 test1510 test1511 test1512 test1513 \
-test1514 test1515 test1516 test1517 test1518 test1519 test1520 test1521 \
-test1522 test1523 test1524 \
+test1458 test1459 test1460 \
\
-test1525 test1526 test1527 test1528 test1529 test1530 test1531 test1532 \
-test1533 test1534 test1535 test1536 test1537 test1538 \
+test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
+test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \
+test1516 test1517 test1518 test1519 test1520 test1521 test1522 test1523 \
+test1524 test1525 test1526 test1527 test1528 test1529 test1530 test1531 \
+test1532 test1533 test1534 test1535 test1536 test1537 test1538 test1539 \
test1540 test1541 \
+\
test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \
test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \
test1566 \
@@ -194,6 +198,8 @@ test1608 test1609 test1610 test1611 test1612 \
\
test1620 test1621 \
\
+test1630 test1631 test1632 test1633 \
+\
test1650 test1651 test1652 test1653 test1654 test1655 \
\
test1700 test1701 test1702 \
@@ -201,7 +207,7 @@ test1700 test1701 test1702 \
test1800 test1801 \
\
test1900 test1901 test1902 test1903 test1904 test1905 test1906 test1907 \
-test1908 \
+test1908 test1909 test1910 \
\
test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \
diff --git a/tests/data/test1034 b/tests/data/test1034
index b4ffc8a98..89083a294 100644
--- a/tests/data/test1034
+++ b/tests/data/test1034
@@ -43,7 +43,7 @@ HTTP over proxy with malformatted IDN host name
url = "http://invalid-utf8-â.local/page/1034"
</stdin>
<command>
--K - -x %HOSTIP:%HTTPPORT
+-K - -x %HOSTIP:%NOLISTENPORT
</command>
</client>
diff --git a/tests/data/test1035 b/tests/data/test1035
index a316c51e1..62f9d7ae8 100644
--- a/tests/data/test1035
+++ b/tests/data/test1035
@@ -35,7 +35,7 @@ perl -MI18N::Langinfo=langinfo,CODESET -e 'die "Needs a UTF-8 locale" if (lc(lan
HTTP over proxy with too long IDN host name
</name>
<command>
-http://too-long-IDN-name-cürl-rüles-la-la-la-dee-da-flooby-nooby.local/page/1035 -x %HOSTIP:%HTTPPORT
+http://too-long-IDN-name-cürl-rüles-la-la-la-dee-da-flooby-nooby.local/page/1035 -x %HOSTIP:%NOLISTENPORT
</command>
</client>
diff --git a/tests/data/test1084 b/tests/data/test1084
index 1cfab68dc..db6ab5e94 100644
--- a/tests/data/test1084
+++ b/tests/data/test1084
@@ -27,7 +27,7 @@ none
HTTP GET with invalid --interface
</name>
<command>
-http://%HOSTIP:%HTTPPORT/1084 --interface non-existing-host.haxx.se.
+http://%HOSTIP:%NOLISTENPORT/1084 --interface non-existing-host.haxx.se.
</command>
</client>
diff --git a/tests/data/test1085 b/tests/data/test1085
index db02e6033..ac1f0629c 100644
--- a/tests/data/test1085
+++ b/tests/data/test1085
@@ -29,7 +29,7 @@ none
HTTP-IPv6 GET with invalid --interface
</name>
<command>
--g "http://%HOST6IP:%HTTP6PORT/1085" --interface non-existing-host.haxx.se.
+-g "http://%HOST6IP:%NOLISTENPORT/1085" --interface non-existing-host.haxx.se.
</command>
# Ensure the IPv6 stack is operational before running this test (other tests
# use the startup of the IPv6 test server as a substitute check for this).
diff --git a/tests/data/test1097 b/tests/data/test1097
index 70a89908d..82f23846d 100644
--- a/tests/data/test1097
+++ b/tests/data/test1097
@@ -47,6 +47,7 @@ https
NTLM
SSL
!SSPI
+proxy
</features>
<name>
HTTP POST using CONNECT with --proxy-ntlm but no auth is required
diff --git a/tests/data/test1168 b/tests/data/test1168
new file mode 100644
index 000000000..283e91e01
--- /dev/null
+++ b/tests/data/test1168
@@ -0,0 +1,78 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+followlocation
+</keywords>
+</info>
+# Server-side
+<reply>
+<data>
+HTTP/1.1 301 This is a weirdo text message swsclose
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Location: /data/11680002.txt
+Connection: close
+
+This server reply is for testing a simple Location: following
+
+</data>
+<data2>
+HTTP/1.1 200 Followed here fine swsclose
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 52
+
+If this is received, the location following worked
+
+</data2>
+<datacheck>
+HTTP/1.1 301 This is a weirdo text message swsclose
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Location: /data/11680002.txt
+Connection: close
+
+HTTP/1.1 200 Followed here fine swsclose
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 52
+
+If this is received, the location following worked
+
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP redirect with credentials using # in user and password
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/want/1168 -L -u "catmai#d:#DZaRJYrixKE*gFY"
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /want/1168 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic Y2F0bWFpI2Q6I0RaYVJKWXJpeEtFKmdGWQ==
+Accept: */*
+
+GET /data/11680002.txt HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic Y2F0bWFpI2Q6I0RaYVJKWXJpeEtFKmdGWQ==
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1177 b/tests/data/test1177
index 2747223cc..3bb68d152 100644
--- a/tests/data/test1177
+++ b/tests/data/test1177
@@ -18,7 +18,7 @@ Verify that CURL_VERSION_* in headers and docs are in sync
</name>
<command type="perl">
-%SRCDIR/version-scan.pl %SRCDIR/../docs/libcurl/curl_version_info.3 ../include/gnurl/curl.h
+%SRCDIR/version-scan.pl %SRCDIR/../docs/libcurl/curl_version_info.3 %SRCDIR/../include/gnurl/curl.h
</command>
</client>
diff --git a/tests/data/test1178 b/tests/data/test1178
new file mode 100644
index 000000000..6d1264c35
--- /dev/null
+++ b/tests/data/test1178
@@ -0,0 +1,55 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTP proxy
+</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
+
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP proxy auth with credentials longer than 256 bytes
+ </name>
+# 400 x 'A' : 600 x 'B' ...
+ <command>
+http://%HOSTIP:%HTTPPORT/we/want/that/page/1178 -x http://%HOSTIP:%HTTPPORT -U AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+</command>
+<features>
+proxy
+</features>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET http://%HOSTIP:%HTTPPORT/we/want/that/page/1178 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Proxy-Authorization: Basic QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQTpCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkI=
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1179 b/tests/data/test1179
new file mode 100644
index 000000000..206ee7cae
--- /dev/null
+++ b/tests/data/test1179
@@ -0,0 +1,43 @@
+<testcase>
+<info>
+<keywords>
+cmdline
+wrong option
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+# make this test require manual as the error message is different without it
+<features>
+manual
+</features>
+<name>
+error when using unknown command line option
+</name>
+<command>
+--never-implemented http://never.use.this.example.com/1179
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+2
+</errorcode>
+<stderr mode="text">
+curl: option --never-implemented: is unknown
+curl: try 'curl --help' or 'curl --manual' for more information
+</stderr>
+</verify>
+</testcase>
diff --git a/tests/data/test1234 b/tests/data/test1234
index 41c4bc06d..577ba51aa 100644
--- a/tests/data/test1234
+++ b/tests/data/test1234
@@ -19,7 +19,7 @@ none
abusing {}-globbing
</name>
<command>
-"%HOSTIP:%HTTPPORT/1234[0-1]{" "%HOSTIP:%HTTPPORT/{}{}{}{"
+"%HOSTIP:%NOLISTENPORT/1234[0-1]{" "%HOSTIP:%NOLISTENPORT/{}{}{}{"
</command>
</client>
diff --git a/tests/data/test1236 b/tests/data/test1236
index 0829be313..7408a7bae 100644
--- a/tests/data/test1236
+++ b/tests/data/test1236
@@ -19,7 +19,7 @@ none
</name>
# 2^62 == 4611686018427387904
<command>
-"%HOSTIP:%HTTPPORT/1234[0-1]{" "%HOSTIP:%HTTPPORT/[1-4611686018427387904][1-4611686018427387904]"
+"%HOSTIP:%NOLISTENPORT/1234[0-1]{" "%HOSTIP:%NOLISTENPORT/[1-4611686018427387904][1-4611686018427387904]"
</command>
</client>
diff --git a/tests/data/test1238 b/tests/data/test1238
index a0eef417d..88c9a5b3b 100644
--- a/tests/data/test1238
+++ b/tests/data/test1238
@@ -24,6 +24,14 @@ writedelay: 2
<server>
tftp
</server>
+# Always kill the TFTP server to not affect following tests, due
+# to this test potentially keeping the TFTP server busy waiting
+# for another 5 seconds after this test has already terminated.
+# On some platforms and CI not enough time passes between this
+# test and the next tests 1242 and 1243, causing them to fail.
+<killserver>
+tftp
+</killserver>
<name>
slow TFTP retrieve cancel due to -Y and -y
</name>
diff --git a/tests/data/test1244 b/tests/data/test1244
index d0769ad85..0912c0947 100644
--- a/tests/data/test1244
+++ b/tests/data/test1244
@@ -32,10 +32,13 @@ wrong
http
https
</server>
- <name>
+<features>
+proxy
+</features>
+<name>
HTTP GET same URL - different proxy ports
- </name>
- <command>
+</name>
+<command>
http://%HOSTIP:%HTTPPORT/1244 -x %HOSTIP:%HTTPPORT --next http://%HOSTIP:%HTTPPORT/124400001 -x %HOSTIP:%HTTPSPORT
</command>
</client>
diff --git a/tests/data/test1248 b/tests/data/test1248
index 28e7a8527..02dacfc8b 100644
--- a/tests/data/test1248
+++ b/tests/data/test1248
@@ -29,7 +29,7 @@ http
Access a non-proxied host with using the combination of --proxy option and --noproxy option
</name>
<command>
-http://user:secret@%HOSTIP:%HTTPPORT/1248 --proxy http://dummy:%PROXYPORT/ --noproxy %HOSTIP --max-time 5
+http://user:secret@%HOSTIP:%HTTPPORT/1248 --proxy http://dummy:%NOLISTENPORT/ --noproxy %HOSTIP --max-time 5
</command>
</client>
diff --git a/tests/data/test1249 b/tests/data/test1249
index ab5614068..1bc3cfe59 100644
--- a/tests/data/test1249
+++ b/tests/data/test1249
@@ -32,7 +32,7 @@ Access a non-proxied host with using the combination of --proxy option and NO_PR
NO_PROXY=%HOSTIP
</setenv>
<command>
-http://user:secret@%HOSTIP:%HTTPPORT/1249 --proxy http://dummy:%PROXYPORT/ --max-time 5
+http://user:secret@%HOSTIP:%HTTPPORT/1249 --proxy http://dummy:%NOLISTENPORT/ --max-time 5
</command>
</client>
diff --git a/tests/data/test1260 b/tests/data/test1260
index 1d86ecd4e..b246882cb 100644
--- a/tests/data/test1260
+++ b/tests/data/test1260
@@ -22,7 +22,7 @@ http
HTTP URL with rubbish after port number
</name>
<command>
--g "http://[%HOSTIP]:%HTTPPORT:80/we/want/1260" "http://%HOSTIP:%HTTPPORT:80/we/want/1260" "http://user@example.com:80@localhost"
+-g "http://[%HOSTIP]:%NOLISTENPORT:80/we/want/1260" "http://%HOSTIP:%NOLISTENPORT:80/we/want/1260" "http://user@example.com:80@localhost"
</command>
</client>
diff --git a/tests/data/test1263 b/tests/data/test1263
index 7462db4d4..88b13775e 100644
--- a/tests/data/test1263
+++ b/tests/data/test1263
@@ -23,7 +23,7 @@ http
HTTP URL with rubbish after IPv6 bracket
</name>
<command>
--g "http://[%HOSTIP]test:%HTTPPORT/we/want/1263" "http://[%HOSTIP][%HOSTIP]:%HTTPPORT/we/want/1263" "http://user@[::1]@localhost"
+-g "http://[%HOSTIP]test:%NOLISTENPORT/we/want/1263" "http://[%HOSTIP][%HOSTIP]:%NOLISTENPORT/we/want/1263" "http://user@[::1]@localhost"
</command>
</client>
diff --git a/tests/data/test1269 b/tests/data/test1269
index c77663633..7cf86cab3 100644
--- a/tests/data/test1269
+++ b/tests/data/test1269
@@ -20,7 +20,7 @@ none
too large --retry-delay value
</name>
<command>
---retry 3 --retry-delay 9223372036854776 http://%HOSTIP:%HTTPPORT/1269
+--retry 3 --retry-delay 9223372036854776 http://%HOSTIP:%NOLISTENPORT/1269
</command>
</client>
diff --git a/tests/data/test1296 b/tests/data/test1296
new file mode 100644
index 000000000..386eb18fc
--- /dev/null
+++ b/tests/data/test1296
@@ -0,0 +1,56 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP Basic
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+
+<name>
+HTTP URL with %0a in name part
+</name>
+
+<command>
+http://user%0aname:password@%HOSTIP:%HTTPPORT/1296
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /1296 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic dXNlcgpuYW1lOnBhc3N3b3Jk
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
+
diff --git a/tests/data/test1340 b/tests/data/test1340
index 81f1ed68d..644fb2b51 100644
--- a/tests/data/test1340
+++ b/tests/data/test1340
@@ -40,7 +40,7 @@ HTTP GET with -O -J and Content-Disposition, -D file
CURL_TESTDIR=%PWD/log
</setenv>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/1340 -J -O -D log/heads1340
+http://%HOSTIP:%HTTPPORT/1340 -J -O -D log/heads1340 -w "curl: Saved to filename %{filename_effective}\n"
</command>
</client>
@@ -73,7 +73,7 @@ Content-Disposition: filename=name1340; charset=funny; option=strange
</file2>
<file3 name="log/stdout1340" mode="text">
-curl: Saved to filename '%PWD/log/name1340'
+curl: Saved to filename %PWD/log/name1340
</file3>
</verify>
diff --git a/tests/data/test1341 b/tests/data/test1341
index b364edeb1..ae226744c 100644
--- a/tests/data/test1341
+++ b/tests/data/test1341
@@ -40,7 +40,7 @@ HTTP GET with -O -J and Content-Disposition, -D stdout
CURL_TESTDIR=%PWD/log
</setenv>
<command option="no-output,no-include">
-http://%HOSTIP:%HTTPPORT/1341 -J -O -D -
+http://%HOSTIP:%HTTPPORT/1341 -J -O -D - -w "curl: Saved to filename %{filename_effective}\n"
</command>
</client>
@@ -70,7 +70,7 @@ Connection: close
Content-Type: text/html
Content-Disposition: filename=name1341; charset=funny; option=strange
-curl: Saved to filename '%PWD/log/name1341'
+curl: Saved to filename %PWD/log/name1341
</file2>
</verify>
diff --git a/tests/data/test1409 b/tests/data/test1409
index 5ceb53be3..8d54b4c95 100644
--- a/tests/data/test1409
+++ b/tests/data/test1409
@@ -17,7 +17,7 @@ none
Pass in string to -C
</name>
<command>
-http://%HOSTIP:%HTTPPORT/1409 -C wrong
+http://%HOSTIP:%NOLISTENPORT/1409 -C wrong
</command>
</client>
diff --git a/tests/data/test1410 b/tests/data/test1410
index 97ad05698..a8b89db3f 100644
--- a/tests/data/test1410
+++ b/tests/data/test1410
@@ -17,7 +17,7 @@ none
Pass in negative number to --max-time
</name>
<command>
-http://%HOSTIP:%HTTPPORT/1410 --max-time -4
+http://%HOSTIP:%NOLISTENPORT/1410 --max-time -4
</command>
</client>
diff --git a/tests/data/test1427 b/tests/data/test1427
index 03cab4b93..648b1da56 100644
--- a/tests/data/test1427
+++ b/tests/data/test1427
@@ -15,7 +15,7 @@ none
too large -m timeout value
</name>
<command>
-http://%HOSTIP:%HTTPPORT/1427 -m 184467440737095510
+http://%HOSTIP:%NOLISTENPORT/1427 -m 184467440737095510
</command>
</client>
diff --git a/tests/data/test1446 b/tests/data/test1446
index 96d634e1c..637df583f 100644
--- a/tests/data/test1446
+++ b/tests/data/test1446
@@ -24,7 +24,7 @@ perl %SRCDIR/libtest/test613.pl prepare %PWD/log/test1446.dir
SFTP with --remote-time
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/test1446.dir/rofile.txt --insecure --remote-time
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test1446.dir/rofile.txt --insecure --remote-time
</command>
<postcheck>
perl %SRCDIR/libtest/test613.pl postprocess %PWD/log/test1446.dir && \
diff --git a/tests/data/test1447 b/tests/data/test1447
index d1182942e..8a651f009 100644
--- a/tests/data/test1447
+++ b/tests/data/test1447
@@ -24,7 +24,7 @@ proxy
Provide illegal proxy name
</name>
<command>
---proxy "http://a:b@/x" http://%HOSTIP:%HTTPPORT
+--proxy "http://a:b@/x" http://%HOSTIP:%NOLISTENPORT
</command>
</client>
diff --git a/tests/data/test1453 b/tests/data/test1453
index eaf9dd3b9..76b5acda4 100644
--- a/tests/data/test1453
+++ b/tests/data/test1453
@@ -23,7 +23,7 @@ tftp
Too long tftp filename
</name>
<command>
-tftp://%HOSTIP:%TFTPPORT/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz
+tftp://%HOSTIP:%NOLISTENPORT/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz
</command>
</client>
diff --git a/tests/data/test1460 b/tests/data/test1460
new file mode 100644
index 000000000..d7b30c5e8
--- /dev/null
+++ b/tests/data/test1460
@@ -0,0 +1,62 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+-J
+</keywords>
+</info>
+
+#
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 swsclose
+ 12345
+fooo
+54 3 2 1
+Content-Disposition: filename=name1460; charset=funny; option=strange
+
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+# this relies on the debug feature to allow us to set directory to store the
+# -J output in
+<features>
+debug
+</features>
+<server>
+http
+</server>
+<name>
+HTTP GET with -Ji and Content-Disposition with existing file
+</name>
+<setenv>
+CURL_TESTDIR=%PWD/log
+</setenv>
+<command option="no-output,no-include">
+http://%HOSTIP:%HTTPPORT/1460 -Ji -O
+</command>
+<file name="log/name1460">
+initial content
+</file>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+# Warning: --include and --remote-header-name cannot be combined.
+<errorcode>
+2
+</errorcode>
+<file name="log/name1460">
+initial content
+</file>
+
+</verify>
+</testcase>
diff --git a/tests/data/test1508 b/tests/data/test1508
index b276b8b31..fbdc322a0 100644
--- a/tests/data/test1508
+++ b/tests/data/test1508
@@ -18,7 +18,7 @@ lib1508
Close a multi handle without using it
</name>
<command>
-http://%HOSTIP:%HTTPPORT/path/1508
+http://%HOSTIP:%NOLISTENPORT/path/1508
</command>
</client>
diff --git a/tests/data/test1539 b/tests/data/test1539
new file mode 100644
index 000000000..b8546f270
--- /dev/null
+++ b/tests/data/test1539
@@ -0,0 +1,43 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP POST
+Content-Length
+chunked Transfer-Encoding
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK
+Date: Sun, 19 Jan 2014 18:50:58 GMT
+Server: test-server/fake swsclose
+Connection: close
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<tool>
+lib1539
+</tool>
+<name>
+HTTP 1.0 POST with read callback and unknown data size
+</name>
+<command>
+http://%HOSTIP:%HTTPPORT/1539
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<errorcode>
+25
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test1550 b/tests/data/test1550
index b78756e9a..c305dd6f2 100644
--- a/tests/data/test1550
+++ b/tests/data/test1550
@@ -20,10 +20,10 @@ lib1550
</tool>
<name>
-verify setting pipeling blacklisting options
+verify setting pipeling blocklisting options
</name>
<command>
-http://%HOSTIP:%HTTPPORT/1550
+http://%HOSTIP:%NOLISTENPORT/1550
</command>
</client>
</testcase>
diff --git a/tests/data/test1554 b/tests/data/test1554
index 06f189724..d3926d916 100644
--- a/tests/data/test1554
+++ b/tests/data/test1554
@@ -29,6 +29,12 @@ run 1: foobar and so on fun!
<- Mutex unlock
-> Mutex lock
<- Mutex unlock
+-> Mutex lock
+<- Mutex unlock
+-> Mutex lock
+<- Mutex unlock
+-> Mutex lock
+<- Mutex unlock
run 1: foobar and so on fun!
-> Mutex lock
<- Mutex unlock
@@ -40,6 +46,10 @@ run 1: foobar and so on fun!
<- Mutex unlock
-> Mutex lock
<- Mutex unlock
+-> Mutex lock
+<- Mutex unlock
+-> Mutex lock
+<- Mutex unlock
run 1: foobar and so on fun!
-> Mutex lock
<- Mutex unlock
@@ -51,6 +61,10 @@ run 1: foobar and so on fun!
<- Mutex unlock
-> Mutex lock
<- Mutex unlock
+-> Mutex lock
+<- Mutex unlock
+-> Mutex lock
+<- Mutex unlock
run 1: foobar and so on fun!
-> Mutex lock
<- Mutex unlock
diff --git a/tests/data/test1630 b/tests/data/test1630
new file mode 100644
index 000000000..1d381c7b0
--- /dev/null
+++ b/tests/data/test1630
@@ -0,0 +1,56 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+HTTPS-proxy
+HTTPS-proxy Basic auth
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<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
+Content-Length: 22
+
+the content goes here
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+https-proxy
+</server>
+ <name>
+HTTPS-proxy with Basic auth to HTTP without auth
+ </name>
+ <command>
+ -U fake@user:loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong -x https://%HOSTIP:%HTTPSPROXYPORT http://we.want.that.site.com/1630 --proxy-insecure
+</command>
+<features>
+proxy
+</features>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<proxy>
+GET http://we.want.that.site.com/1630 HTTP/1.1
+Host: we.want.that.site.com
+Proxy-Authorization: Basic ZmFrZUB1c2VyOmxvb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29uZw==
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</proxy>
+</verify>
+</testcase>
diff --git a/tests/data/test1631 b/tests/data/test1631
new file mode 100644
index 000000000..cd36b1d9b
--- /dev/null
+++ b/tests/data/test1631
@@ -0,0 +1,87 @@
+<testcase>
+<info>
+<keywords>
+FTP
+HTTPS-proxy
+</keywords>
+</info>
+
+# Server-side
+<reply>
+
+# This is the HTTPS proxy response
+<connect>
+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
+Content-Length: 0
+
+</connect>
+
+# This is the FTP server response. The Life and Adventures of Robinson Crusoe
+<data>
+I was born in the year 1632, in the city of York, of a good family, though not
+of that country, myfather being a foreigner of Bremen, who settled first at
+Hull. He got a good estate by merchandise,and leaving off his trade, lived
+afterwards at York, from whence he had married my mother, whoserelations were
+named Robinson, a very good family in that country, and from whom I was
+calledRobinson Kreutznaer; but, by the usual corruption of words in England,
+we are now called—nay wecall ourselves and write our name—Crusoe; and so my
+companions always called me.
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+ftp
+https-proxy
+</server>
+ <name>
+FTP through HTTPS-proxy
+ </name>
+ <command>
+-p -x https://%HOSTIP:%HTTPSPROXYPORT ftp://ftp.site.thru.https.proxy:%FTPPORT/1631 --proxy-insecure
+</command>
+<features>
+proxy
+</features>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+
+# The second CONNECT will be made to the dynamic port number the FTP server
+# opens for us, so we can't compare with a known pre-existing number!
+<strippart>
+s/((https.proxy):(\d+))/$2:12345/
+s/^(User-Agent: curl).*/$1/
+</strippart>
+<proxy>
+CONNECT ftp.site.thru.https.proxy:12345 HTTP/1.1
+Host: ftp.site.thru.https.proxy:12345
+User-Agent: curl
+Proxy-Connection: Keep-Alive
+
+CONNECT ftp.site.thru.https.proxy:12345 HTTP/1.1
+Host: ftp.site.thru.https.proxy:12345
+User-Agent: curl
+Proxy-Connection: Keep-Alive
+
+</proxy>
+<protocol>
+USER anonymous
+PASS ftp@example.com
+PBSZ 0
+PROT P
+PWD
+EPSV
+TYPE I
+SIZE 1631
+RETR 1631
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1632 b/tests/data/test1632
new file mode 100644
index 000000000..b10b2a68a
--- /dev/null
+++ b/tests/data/test1632
@@ -0,0 +1,105 @@
+<testcase>
+<info>
+<keywords>
+FTP
+HTTPS-proxy
+</keywords>
+</info>
+
+# Server-side
+<reply>
+
+# This is the HTTPS proxy response
+<connect>
+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
+Content-Length: 0
+
+</connect>
+
+# This is the FTP server response. The Life and Adventures of Robinson Crusoe
+<data>
+I was born in the year 1632, in the city of York, of a good family, though not
+of that country, myfather being a foreigner of Bremen, who settled first at
+Hull. He got a good estate by merchandise,and leaving off his trade, lived
+afterwards at York, from whence he had married my mother, whoserelations were
+named Robinson, a very good family in that country, and from whom I was
+calledRobinson Kreutznaer; but, by the usual corruption of words in England,
+we are now called—nay wecall ourselves and write our name—Crusoe; and so my
+companions always called me.
+</data>
+
+<data2>
+I had two elder brothers, one of whom was lieutenant-colonel to an
+English regiment of foot inFlanders, formerly commanded by the famous Colonel
+Lockhart, and was killed at the battle nearDunkirk against the Spaniards.
+What became of my second brother I never knew, any more thanmy father or
+mother knew what became of me.
+</data2>
+
+</reply>
+
+# Client-side
+<client>
+<server>
+ftp
+https-proxy
+</server>
+ <name>
+FTP through HTTPS-proxy, with connection re-use
+ </name>
+ <command>
+-p -x https://%HOSTIP:%HTTPSPROXYPORT ftp://ftp.site.thru.https.proxy:%FTPPORT/1632 --proxy-insecure ftp://ftp.site.thru.https.proxy:%FTPPORT/16320002
+</command>
+<features>
+proxy
+</features>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+
+# The second and third CONNECT will be made to the dynamic port number the FTP
+# server opens for us, so we can't compare with known pre-existing numbers!
+
+<strippart>
+s/((https.proxy):(\d+))/$2:12345/
+s/^(User-Agent: curl).*/$1/
+</strippart>
+<proxy>
+CONNECT ftp.site.thru.https.proxy:12345 HTTP/1.1
+Host: ftp.site.thru.https.proxy:12345
+User-Agent: curl
+Proxy-Connection: Keep-Alive
+
+CONNECT ftp.site.thru.https.proxy:12345 HTTP/1.1
+Host: ftp.site.thru.https.proxy:12345
+User-Agent: curl
+Proxy-Connection: Keep-Alive
+
+CONNECT ftp.site.thru.https.proxy:12345 HTTP/1.1
+Host: ftp.site.thru.https.proxy:12345
+User-Agent: curl
+Proxy-Connection: Keep-Alive
+
+</proxy>
+<protocol>
+USER anonymous
+PASS ftp@example.com
+PBSZ 0
+PROT P
+PWD
+EPSV
+TYPE I
+SIZE 1632
+RETR 1632
+EPSV
+SIZE 16320002
+RETR 16320002
+QUIT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1633 b/tests/data/test1633
new file mode 100644
index 000000000..5d29ef139
--- /dev/null
+++ b/tests/data/test1633
@@ -0,0 +1,97 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 301 OK
+Accept-Ranges: bytes
+Content-Length: 0
+Connection: close
+Location: /16330002
+
+</data>
+<data2>
+HTTP/1.1 429 too many requests
+Retry-After: 1
+Content-Length: 0
+Connection: close
+
+</data2>
+
+<datacheck>
+HTTP/1.1 301 OK
+Accept-Ranges: bytes
+Content-Length: 0
+Connection: close
+Location: /16330002
+
+HTTP/1.1 429 too many requests
+Retry-After: 1
+Content-Length: 0
+Connection: close
+
+HTTP/1.1 301 OK
+Accept-Ranges: bytes
+Content-Length: 0
+Connection: close
+Location: /16330002
+
+HTTP/1.1 429 too many requests
+Retry-After: 1
+Content-Length: 0
+Connection: close
+
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP GET
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/1633 -d moo --retry 1 -L
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+POST /1633 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+
+mooGET /16330002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+POST /1633 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+Content-Length: 3
+Content-Type: application/x-www-form-urlencoded
+
+mooGET /16330002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test1901 b/tests/data/test1901
index 83cdf7290..793bd667a 100644
--- a/tests/data/test1901
+++ b/tests/data/test1901
@@ -40,13 +40,13 @@ http
lib1900
</tool>
<name>
-HTTP GET using pipelining, blacklisted site
+HTTP GET using pipelining, blocklisted site
</name>
<command>
http://%HOSTIP:%HTTPPIPEPORT/ log/urls1901.txt
</command>
<file name="log/urls1901.txt">
-blacklist_site 127.0.0.1:%HTTPPIPEPORT
+blocklist_site 127.0.0.1:%HTTPPIPEPORT
0 1k.txt
1000 100k.txt
0 1k.txt
diff --git a/tests/data/test1909 b/tests/data/test1909
new file mode 100644
index 000000000..bde0e5e0f
--- /dev/null
+++ b/tests/data/test1909
@@ -0,0 +1,65 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+retry
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 200 OK swsclose swsbounce
+Content-Length: 5
+Connection: close
+
+bbb
+</data>
+<data1>
+HTTP/1.1 200 OK
+Content-Length: 5
+Connection: close
+
+data
+</data1>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP GET --retry-all-errors to overcome partial transfer
+ </name>
+ <command option="no-output,no-include">
+--retry 1 --retry-all-errors -o log/outfile1909 http://%HOSTIP:%HTTPPORT/1909
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /1909 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /1909 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+
+<file1 name="log/outfile1909">
+data
+</file1>
+
+</verify>
+</testcase>
diff --git a/tests/data/test1910 b/tests/data/test1910
new file mode 100644
index 000000000..a1b3f5756
--- /dev/null
+++ b/tests/data/test1910
@@ -0,0 +1,68 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP Basic
+CURLOPT_FOLLOWLOCATION
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data nocheck="yes">
+HTTP/1.1 302 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 0
+Location: /19100002
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Type: text/html
+Content-Length: 4
+
+hej
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+
+<name>
+HTTP credentials with newline and redirect
+</name>
+<tool>
+lib1910
+</tool>
+
+<command>
+%HOSTIP:%HTTPPORT/1910
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /1910 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic dXNlcgpuYW1lOnBhc3MKd29yZA==
+Accept: */*
+
+GET /19100002 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Authorization: Basic dXNlcgpuYW1lOnBhc3MKd29yZA==
+Accept: */*
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test2004 b/tests/data/test2004
index 5b3b68d0c..f9add83d5 100644
--- a/tests/data/test2004
+++ b/tests/data/test2004
@@ -30,7 +30,7 @@ sftp
TFTP RRQ followed by SFTP retrieval followed by FILE followed by SCP retrieval then again in reverse order
</name>
<command option="no-include">
---key curl_client_key --pubkey curl_client_key.pub -u %USER: tftp://%HOSTIP:%TFTPPORT//2004 sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/test2004.txt file://localhost%FILE_PWD/log/test2004.txt scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/test2004.txt file://localhost%FILE_PWD/log/test2004.txt sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/test2004.txt tftp://%HOSTIP:%TFTPPORT//2004 --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: tftp://%HOSTIP:%TFTPPORT//2004 sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test2004.txt file://localhost%FILE_PWD/log/test2004.txt scp://%HOSTIP:%SSHPORT%SSH_PWD/log/test2004.txt file://localhost%FILE_PWD/log/test2004.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test2004.txt tftp://%HOSTIP:%TFTPPORT//2004 --insecure
</command>
<file name="log/test2004.txt">
This is test data
diff --git a/tests/data/test2036 b/tests/data/test2036
index 0ab8b66c5..4b2ec43a8 100644
--- a/tests/data/test2036
+++ b/tests/data/test2036
@@ -22,7 +22,7 @@ http
HTTP, -O with no slash at all in the URL
</name>
<command option="no-output">
-%HOSTIP:%HTTPPORT -O
+%HOSTIP:%NOLISTENPORT -O
</command>
</client>
diff --git a/tests/data/test2047 b/tests/data/test2047
index d3654c785..1471d0051 100644
--- a/tests/data/test2047
+++ b/tests/data/test2047
@@ -40,6 +40,7 @@ http
</server>
<features>
idn
+proxy
</features>
<setenv>
LC_ALL=en_US.UTF-8
diff --git a/tests/data/test219 b/tests/data/test219
index 49f17e43f..2b638950e 100644
--- a/tests/data/test219
+++ b/tests/data/test219
@@ -24,7 +24,7 @@ proxy
try using proxy with unsupported scheme
</name>
<command>
--x foo://%HOSTIP:%HTTPPORT/219 http://%HOSTIP:%HTTPPORT/219
+-x foo://%HOSTIP:%NOLISTENPORT/219 http://%HOSTIP:%NOLISTENPORT/219
</command>
</client>
diff --git a/tests/data/test288 b/tests/data/test288
index e62eabd3c..26e1b842a 100644
--- a/tests/data/test288
+++ b/tests/data/test288
@@ -28,7 +28,7 @@ file
file:// with (unsupported) proxy, authentication and range
</name>
<setenv>
-all_proxy=http://fake:user@%HOSTIP:%HTTPPORT/
+all_proxy=http://fake:user@%HOSTIP:%NOLISTENPORT/
</setenv>
<command option="no-include">
file://localhost%FILE_PWD/log/test288.txt
diff --git a/tests/data/test302 b/tests/data/test302
index 7bb162b41..3eb9e7aee 100644
--- a/tests/data/test302
+++ b/tests/data/test302
@@ -24,6 +24,7 @@ And you should ignore this data.
<client>
<features>
SSL
+proxy
</features>
<server>
https
diff --git a/tests/data/test333 b/tests/data/test333
index 198af9c86..0fd0591e8 100644
--- a/tests/data/test333
+++ b/tests/data/test333
@@ -20,7 +20,7 @@ none
Try a non-boolean command line option with --no-
</name>
<command>
---no-proxy "hey" http://%HOSTIP:%HTTPPORT/333
+--no-proxy "hey" http://%HOSTIP:%NOLISTENPORT/333
</command>
</client>
diff --git a/tests/data/test346 b/tests/data/test346
new file mode 100644
index 000000000..64923117e
--- /dev/null
+++ b/tests/data/test346
@@ -0,0 +1,60 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+proxy
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Content-Type: text/html
+Funny-head: yesyes
+
+-foo-
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<features>
+proxy
+</features>
+<server>
+http
+</server>
+<name>
+HTTP GET over proxy with credentials using blank passwords
+</name>
+<command>
+-x http://%HOSTIP:%HTTPPORT/346 -U puser: -u suser: http://remote.example/346
+</command>
+</client>
+
+#
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET http://remote.example/346 HTTP/1.1
+Host: remote.example
+Proxy-Authorization: Basic cHVzZXI6
+Authorization: Basic c3VzZXI6
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test501 b/tests/data/test501
index 674bc43b4..8b3dac7ed 100644
--- a/tests/data/test501
+++ b/tests/data/test501
@@ -26,7 +26,7 @@ lib501
simple libcurl attempt operation without URL set
</name>
<command>
-http://%HOSTIP:%HTTPPORT/501
+http://%HOSTIP:%NOLISTENPORT/501
</command>
</client>
diff --git a/tests/data/test504 b/tests/data/test504
index be8f95e2b..351ae749f 100644
--- a/tests/data/test504
+++ b/tests/data/test504
@@ -32,7 +32,7 @@ lib504
simple multi through local proxy without listener
</name>
<command>
-http://%HOSTIP:%HTTPSPORT/504 %HOSTIP:%NOLISTENPORT
+http://%HOSTIP:%NOLISTENPORT/504 %HOSTIP:%NOLISTENPORT
</command>
</client>
diff --git a/tests/data/test509 b/tests/data/test509
index 5de1599e1..0e0dd212b 100644
--- a/tests/data/test509
+++ b/tests/data/test509
@@ -34,10 +34,7 @@ nothing
# Verify data after the test has been "shot"
<verify>
<stdout>
-seen custom_calloc()
-seen custom_malloc()
-seen custom_realloc()
-seen custom_free()
+Callbacks were invoked!
</stdout>
</verify>
diff --git a/tests/data/test543 b/tests/data/test543
index 455633037..f7e687c46 100644
--- a/tests/data/test543
+++ b/tests/data/test543
@@ -30,6 +30,8 @@ curl_easy_escape
<verify>
<stdout>
%9C%26K%3DI%04%A1%01%E0%D8%7C%20%B7%EFS%29%FA%1DW%E1
+IN: '' OUT: ''
+IN: ' 12' OUT: '%2012'
</stdout>
</verify>
</testcase>
diff --git a/tests/data/test552 b/tests/data/test552
index 47dd41abb..a02023a59 100644
--- a/tests/data/test552
+++ b/tests/data/test552
Binary files differ
diff --git a/tests/data/test558 b/tests/data/test558
index dccb8080a..946979677 100644
--- a/tests/data/test558
+++ b/tests/data/test558
@@ -38,7 +38,6 @@ nothing
<file name="log/memdump">
MEM lib558.c: malloc()
MEM lib558.c: free()
-MEM escape.c: malloc()
MEM strdup.c: realloc()
MEM strdup.c: realloc()
MEM escape.c: free()
diff --git a/tests/data/test582 b/tests/data/test582
index 65d85b232..8ac6bc86a 100644
--- a/tests/data/test582
+++ b/tests/data/test582
@@ -24,7 +24,7 @@ lib582
SFTP upload using multi interface
</name>
<command>
-Sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/upload582.txt %PWD/log/file582.txt %USER:
+Sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/upload582.txt %PWD/log/file582.txt %USER:
</command>
<file name="log/file582.txt">
Moooooooooooo
diff --git a/tests/data/test583 b/tests/data/test583
index 2c41ca1d2..e7d95960b 100644
--- a/tests/data/test583
+++ b/tests/data/test583
@@ -29,7 +29,7 @@ SFTP with multi interface, remove handle early
# name resolve will cause it to return rather quickly and thus we could trigger
# the problem we're looking to verify.
<command>
-sftp://localhost:%SSHPORT%POSIX_PWD/log/upload583.txt %USER:
+sftp://localhost:%SSHPORT%SSH_PWD/log/upload583.txt %USER:
</command>
</client>
diff --git a/tests/data/test600 b/tests/data/test600
index 2a139b817..f9415e0e0 100644
--- a/tests/data/test600
+++ b/tests/data/test600
@@ -24,7 +24,7 @@ sftp
SFTP retrieval
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file600.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file600.txt --insecure
</command>
<file name="log/file600.txt">
Test data
diff --git a/tests/data/test601 b/tests/data/test601
index 544a88068..c89b64535 100644
--- a/tests/data/test601
+++ b/tests/data/test601
@@ -24,7 +24,7 @@ scp
SCP retrieval
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file601.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file601.txt --insecure
</command>
<file name="log/file601.txt">
Test data
diff --git a/tests/data/test602 b/tests/data/test602
index 6bb0df3f4..dd300c74d 100644
--- a/tests/data/test602
+++ b/tests/data/test602
@@ -21,7 +21,7 @@ sftp
SFTP put
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file602.txt sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/upload.602 --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file602.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/upload.602 --insecure
</command>
<file name="log/file602.txt">
Test data
diff --git a/tests/data/test603 b/tests/data/test603
index 879e4c0f7..b96c4057f 100644
--- a/tests/data/test603
+++ b/tests/data/test603
@@ -21,7 +21,7 @@ scp
SCP upload
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file603.txt scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/upload.603 --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file603.txt scp://%HOSTIP:%SSHPORT%SSH_PWD/log/upload.603 --insecure
</command>
<file name="log/file603.txt">
Test data
diff --git a/tests/data/test604 b/tests/data/test604
index f76a7fb23..f503e669e 100644
--- a/tests/data/test604
+++ b/tests/data/test604
@@ -16,7 +16,7 @@ sftp
SFTP retrieval of nonexistent file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/not-a-valid-file-moooo --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure
</command>
</client>
diff --git a/tests/data/test605 b/tests/data/test605
index a18ab2997..29555fa82 100644
--- a/tests/data/test605
+++ b/tests/data/test605
@@ -16,7 +16,7 @@ scp
SCP retrieval of nonexistent file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%POSIX_PWD/not-a-valid-file-moooo --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure
</command>
</client>
diff --git a/tests/data/test606 b/tests/data/test606
index 37e21086c..c790bd685 100644
--- a/tests/data/test606
+++ b/tests/data/test606
@@ -16,7 +16,7 @@ sftp
SFTP invalid user login
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u not-a-valid-user: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/not-a-valid-file-moooo --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u not-a-valid-user: sftp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure
</command>
</client>
diff --git a/tests/data/test607 b/tests/data/test607
index e42245151..8c13e5844 100644
--- a/tests/data/test607
+++ b/tests/data/test607
@@ -16,7 +16,7 @@ scp
SCP invalid user login
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u not-a-valid-user: scp://%HOSTIP:%SSHPORT%POSIX_PWD/not-a-valid-file-moooo --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u not-a-valid-user: scp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure
</command>
</client>
diff --git a/tests/data/test608 b/tests/data/test608
index 86391f085..b4d010556 100644
--- a/tests/data/test608
+++ b/tests/data/test608
@@ -24,7 +24,7 @@ sftp
SFTP post-quote rename
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-rename %PWD/log/file608.txt %PWD/log/file608-renamed.txt" sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file608.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-rename %PWD/log/file608.txt %PWD/log/file608-renamed.txt" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file608.txt --insecure
</command>
# Verify that the file was renamed properly, then rename the file back to what
# it was so the verify section works and the file can be cleaned up.
diff --git a/tests/data/test609 b/tests/data/test609
index 4a9da1a94..5aa9eecfc 100644
--- a/tests/data/test609
+++ b/tests/data/test609
@@ -25,7 +25,7 @@ sftp
SFTP post-quote mkdir failure
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-mkdir %PWD/log/file609.txt" sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file609.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-mkdir %PWD/log/file609.txt" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file609.txt --insecure
</command>
<file name="log/file609.txt">
Test file for mkdir test
diff --git a/tests/data/test610 b/tests/data/test610
index 179146419..d09742151 100644
--- a/tests/data/test610
+++ b/tests/data/test610
@@ -27,7 +27,7 @@ perl %SRCDIR/libtest/test610.pl mkdir %PWD/log/test610.dir
SFTP post-quote rmdir
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-rmdir %PWD/log/test610.dir" sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file610.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-rmdir %PWD/log/test610.dir" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file610.txt --insecure
</command>
<postcheck>
perl %SRCDIR/libtest/test610.pl gone %PWD/log/test610.dir
diff --git a/tests/data/test611 b/tests/data/test611
index f40a4bda3..6362002e3 100644
--- a/tests/data/test611
+++ b/tests/data/test611
@@ -27,7 +27,7 @@ perl %SRCDIR/libtest/test610.pl mkdir %PWD/log/test611.dir
SFTP post-quote rename
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-rename %PWD/log/test611.dir %PWD/log/test611.new" sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file611.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-rename %PWD/log/test611.dir %PWD/log/test611.new" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file611.txt --insecure
</command>
<postcheck>
perl %SRCDIR/libtest/test610.pl rmdir %PWD/log/test611.new
diff --git a/tests/data/test612 b/tests/data/test612
index 4fed660d7..ae18afbc1 100644
--- a/tests/data/test612
+++ b/tests/data/test612
@@ -24,7 +24,7 @@ sftp
SFTP post-quote remove file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file612.txt -Q "-rm %PWD/log/file612.txt" sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/upload.612 --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file612.txt -Q "-rm %PWD/log/file612.txt" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/upload.612 --insecure
</command>
<postcheck>
perl %SRCDIR/libtest/test610.pl gone %PWD/log/test612.txt
diff --git a/tests/data/test613 b/tests/data/test613
index c4d82fbf0..0383987e5 100644
--- a/tests/data/test613
+++ b/tests/data/test613
@@ -10,8 +10,6 @@ directory
# Server-side
<reply>
<datacheck>
-d????????? N U U N ??? N NN:NN .
-d????????? N U U N ??? N NN:NN ..
d????????? N U U N ??? N NN:NN asubdir
-rw?rw?rw? 1 U U 37 Jan 1 2000 plainfile.txt
-r-?r-?r-? 1 U U 47 Dec 31 2000 rofile.txt
@@ -31,7 +29,7 @@ perl %SRCDIR/libtest/test613.pl prepare %PWD/log/test613.dir
SFTP directory retrieval
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/test613.dir/ --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test613.dir/ --insecure
</command>
<postcheck>
perl %SRCDIR/libtest/test613.pl postprocess %PWD/log/test613.dir %PWD/log/curl613.out
diff --git a/tests/data/test614 b/tests/data/test614
index bcc07275e..c6fe4919d 100644
--- a/tests/data/test614
+++ b/tests/data/test614
@@ -11,8 +11,6 @@ directory
# Server-side
<reply>
<datacheck>
-d????????? N U U N ??? N NN:NN .
-d????????? N U U N ??? N NN:NN ..
d????????? N U U N ??? N NN:NN asubdir
-r-?r-?r-? 1 U U 37 Jan 1 2000 plainfile.txt
-r-?r-?r-? 1 U U 47 Dec 31 2000 rofile.txt
@@ -32,7 +30,7 @@ perl %SRCDIR/libtest/test613.pl prepare %PWD/log/test614.dir
SFTP pre-quote chmod
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "chmod 444 %PWD/log/test614.dir/plainfile.txt" sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/test614.dir/ --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "chmod 444 %PWD/log/test614.dir/plainfile.txt" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test614.dir/ --insecure
</command>
<postcheck>
perl %SRCDIR/libtest/test613.pl postprocess %PWD/log/test614.dir %PWD/log/curl614.out
diff --git a/tests/data/test615 b/tests/data/test615
index 7c50a28b1..5f4859c2f 100644
--- a/tests/data/test615
+++ b/tests/data/test615
@@ -20,7 +20,7 @@ perl %SRCDIR/libtest/test613.pl prepare %PWD/log/test615.dir
SFTP put remote failure
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file615.txt sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/test615.dir/rofile.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file615.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test615.dir/rofile.txt --insecure
</command>
<postcheck>
perl %SRCDIR/libtest/test613.pl postprocess %PWD/log/test615.dir
diff --git a/tests/data/test616 b/tests/data/test616
index 5b464b06d..14c3d3376 100644
--- a/tests/data/test616
+++ b/tests/data/test616
@@ -23,7 +23,7 @@ sftp
SFTP retrieval of empty file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file616.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file616.txt --insecure
</command>
<file name="log/file616.txt">
</file>
diff --git a/tests/data/test617 b/tests/data/test617
index 21c1e3b3e..67f0c9a16 100644
--- a/tests/data/test617
+++ b/tests/data/test617
@@ -23,7 +23,7 @@ scp
SCP retrieval of empty file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file617.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file617.txt --insecure
</command>
<file name="log/file617.txt">
</file>
diff --git a/tests/data/test618 b/tests/data/test618
index 23f03ac68..feb095ebe 100644
--- a/tests/data/test618
+++ b/tests/data/test618
@@ -15,7 +15,7 @@ sftp
SFTP retrieval of two files
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file618.txt sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file618.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file618.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file618.txt --insecure
</command>
<file name="log/file618.txt">
Test data
diff --git a/tests/data/test619 b/tests/data/test619
index 3397c1f1a..6c1273c04 100644
--- a/tests/data/test619
+++ b/tests/data/test619
@@ -15,7 +15,7 @@ scp
SCP retrieval of two files
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file619.txt scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file619.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file619.txt scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file619.txt --insecure
</command>
<file name="log/file619.txt">
Test data
diff --git a/tests/data/test620 b/tests/data/test620
index 28019e792..463825513 100644
--- a/tests/data/test620
+++ b/tests/data/test620
@@ -16,7 +16,7 @@ sftp
SFTP retrieval of missing file followed by good file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/not-a-valid-file-moooo sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file620.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/not-a-valid-file-moooo sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file620.txt --insecure
</command>
<file name="log/file620.txt">
Test data
diff --git a/tests/data/test621 b/tests/data/test621
index 2b39e9f7d..f0ac9b728 100644
--- a/tests/data/test621
+++ b/tests/data/test621
@@ -16,7 +16,7 @@ scp
SCP retrieval of missing file followed by good file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/not-a-valid-file-moooo scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file621.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/not-a-valid-file-moooo scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file621.txt --insecure
</command>
<file name="log/file621.txt">
Test data
diff --git a/tests/data/test622 b/tests/data/test622
index 8f1a6e46c..7b5fd5b2e 100644
--- a/tests/data/test622
+++ b/tests/data/test622
@@ -22,7 +22,7 @@ sftp
SFTP put failure
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file622.txt sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/nonexistent-directory/nonexistent-file --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file622.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/nonexistent-directory/nonexistent-file --insecure
</command>
<file name="log/file622.txt">
Test data
diff --git a/tests/data/test623 b/tests/data/test623
index 2c6a4381d..e2914c9d0 100644
--- a/tests/data/test623
+++ b/tests/data/test623
@@ -22,7 +22,7 @@ scp
SCP upload failure
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file623.txt scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/nonexistent-directory/nonexistent-file --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file623.txt scp://%HOSTIP:%SSHPORT%SSH_PWD/log/nonexistent-directory/nonexistent-file --insecure
</command>
<file name="log/file623.txt">
Test data
diff --git a/tests/data/test624 b/tests/data/test624
index 15b65a8da..8aaf527e5 100644
--- a/tests/data/test624
+++ b/tests/data/test624
@@ -22,7 +22,7 @@ sftp
SFTP put with --ftp-create-dirs
</name>
<command>
---ftp-create-dirs --key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file624.txt sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/test624.dir/upload.624 --insecure
+--ftp-create-dirs --key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file624.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test624.dir/upload.624 --insecure
</command>
<postcheck>
perl %SRCDIR/libtest/test610.pl move %PWD/log/test624.dir/upload.624 %PWD/log/upload.624 rmdir %PWD/log/test624.dir
diff --git a/tests/data/test625 b/tests/data/test625
index 8a5a2ae39..1fe9b55c0 100644
--- a/tests/data/test625
+++ b/tests/data/test625
@@ -22,7 +22,7 @@ sftp
SFTP put with --ftp-create-dirs twice
</name>
<command>
---ftp-create-dirs --key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file625.txt sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/test625.a/upload.625 -T log/file625.txt sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/test625.b/upload.625 --insecure
+--ftp-create-dirs --key curl_client_key --pubkey curl_client_key.pub -u %USER: -T log/file625.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test625.a/upload.625 -T log/file625.txt sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/test625.b/upload.625 --insecure
</command>
<postcheck>
perl %SRCDIR/libtest/test610.pl move %PWD/log/test625.a/upload.625 %PWD/log/upload.625 rmdir %PWD/log/test625.a rm %PWD/log/test625.b/upload.625 rmdir %PWD/log/test625.b
diff --git a/tests/data/test626 b/tests/data/test626
index fd955692b..edf2aa520 100644
--- a/tests/data/test626
+++ b/tests/data/test626
@@ -22,7 +22,7 @@ sftp
SFTP invalid quote command
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "invalid-command foo bar" sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file626.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "invalid-command foo bar" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file626.txt --insecure
</command>
<file name="log/file626.txt">
Test file for rename test
diff --git a/tests/data/test628 b/tests/data/test628
index b5aaec6a8..86c00f16d 100644
--- a/tests/data/test628
+++ b/tests/data/test628
@@ -16,7 +16,7 @@ sftp
SFTP invalid user login (password authentication)
</name>
<command>
--u not-a-valid-user: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/irrelevant-file --insecure
+-u not-a-valid-user: sftp://%HOSTIP:%SSHPORT%SSH_PWD/irrelevant-file --insecure
</command>
</client>
diff --git a/tests/data/test629 b/tests/data/test629
index 7ce5e3005..07ac767ab 100644
--- a/tests/data/test629
+++ b/tests/data/test629
@@ -16,7 +16,7 @@ scp
SCP invalid user login (password authentication)
</name>
<command>
--u not-a-valid-user: scp://%HOSTIP:%SSHPORT%POSIX_PWD/irrelevant-file --insecure
+-u not-a-valid-user: scp://%HOSTIP:%SSHPORT%SSH_PWD/irrelevant-file --insecure
</command>
</client>
diff --git a/tests/data/test630 b/tests/data/test630
index ffde8ea54..f678528b0 100644
--- a/tests/data/test630
+++ b/tests/data/test630
@@ -17,7 +17,7 @@ sftp
SFTP incorrect host key
</name>
<command>
---hostpubmd5 00000000000000000000000000000000 --key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/irrelevant-file --insecure
+--hostpubmd5 00000000000000000000000000000000 --key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/irrelevant-file --insecure
</command>
</client>
diff --git a/tests/data/test631 b/tests/data/test631
index ddb7d280d..720f3716f 100644
--- a/tests/data/test631
+++ b/tests/data/test631
@@ -17,7 +17,7 @@ scp
SCP incorrect host key
</name>
<command>
---hostpubmd5 00000000000000000000000000000000 --key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/irrelevant-file --insecure
+--hostpubmd5 00000000000000000000000000000000 --key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/irrelevant-file --insecure
</command>
</client>
diff --git a/tests/data/test632 b/tests/data/test632
index 63f5630ad..70cfe515a 100644
--- a/tests/data/test632
+++ b/tests/data/test632
@@ -20,7 +20,7 @@ sftp
SFTP syntactically invalid host key
</name>
<command>
---hostpubmd5 00 --key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/irrelevant-file --insecure
+--hostpubmd5 00 --key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%NOLISTENPORT%SSH_PWD/log/irrelevant-file --insecure
</command>
</client>
diff --git a/tests/data/test633 b/tests/data/test633
index d87bfb991..913d981f5 100644
--- a/tests/data/test633
+++ b/tests/data/test633
@@ -24,7 +24,7 @@ sftp
SFTP retrieval with byte range
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file633.txt -r 5-9 --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file633.txt -r 5-9 --insecure
</command>
<file name="log/file633.txt">
Test data
diff --git a/tests/data/test634 b/tests/data/test634
index c93e09e5c..fc250f9c9 100644
--- a/tests/data/test634
+++ b/tests/data/test634
@@ -25,7 +25,7 @@ sftp
SFTP retrieval with byte range past end of file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file634.txt -r 5-99 --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file634.txt -r 5-99 --insecure
</command>
<file name="log/file634.txt">
Test data
diff --git a/tests/data/test635 b/tests/data/test635
index e572567f1..16ef66c0f 100644
--- a/tests/data/test635
+++ b/tests/data/test635
@@ -24,7 +24,7 @@ sftp
SFTP retrieval with byte range relative to end of file
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file635.txt -r -9 --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file635.txt -r -9 --insecure
</command>
<file name="log/file635.txt">
Test data
diff --git a/tests/data/test636 b/tests/data/test636
index 29f165710..0ea350904 100644
--- a/tests/data/test636
+++ b/tests/data/test636
@@ -25,7 +25,7 @@ sftp
SFTP retrieval with X- byte range
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file636.txt -r 5- --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file636.txt -r 5- --insecure
</command>
<file name="log/file636.txt">
Test data
diff --git a/tests/data/test637 b/tests/data/test637
index c0f760fec..71b81268b 100644
--- a/tests/data/test637
+++ b/tests/data/test637
@@ -23,7 +23,7 @@ sftp
SFTP retrieval with invalid X- range
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file637.txt -r 99- --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file637.txt -r 99- --insecure
</command>
<file name="log/file637.txt">
Test data
diff --git a/tests/data/test638 b/tests/data/test638
index 1e42596a5..fdc140c6f 100644
--- a/tests/data/test638
+++ b/tests/data/test638
@@ -29,7 +29,7 @@ perl %SRCDIR/libtest/test610.pl mkdir %PWD/log/test638.dir
SFTP post-quote rename * asterisk accept-fail
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-*rename %PWD/log/test638.dir %PWD/log/test638.new" sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file638.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-*rename %PWD/log/test638.dir %PWD/log/test638.new" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file638.txt --insecure
</command>
<postcheck>
perl %SRCDIR/libtest/test610.pl rmdir %PWD/log/test638.new
diff --git a/tests/data/test639 b/tests/data/test639
index bb06be756..d80c8c14c 100644
--- a/tests/data/test639
+++ b/tests/data/test639
@@ -29,7 +29,7 @@ perl %SRCDIR/libtest/test610.pl mkdir %PWD/log/test639.dir
SFTP post-quote rename * asterisk accept-fail
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-*rename %PWD/log/test639-not-exists-dir %PWD/log/test639.new" sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file639.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: -Q "-*rename %PWD/log/test639-not-exists-dir %PWD/log/test639.new" sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file639.txt --insecure
</command>
<postcheck>
perl %SRCDIR/libtest/test610.pl rmdir %PWD/log/test639.dir
diff --git a/tests/data/test640 b/tests/data/test640
index 979ac2ba7..9d1ade4c0 100644
--- a/tests/data/test640
+++ b/tests/data/test640
@@ -23,7 +23,7 @@ sftp
SFTP --head retrieval
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file640.txt --insecure --head
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file640.txt --insecure --head
</command>
<file name="log/file640.txt">
Test data
diff --git a/tests/data/test641 b/tests/data/test641
index cc1da944e..9f168aaef 100644
--- a/tests/data/test641
+++ b/tests/data/test641
@@ -23,7 +23,7 @@ scp
SCP --head retrieval
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file641.txt --insecure --head
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file641.txt --insecure --head
</command>
<file name="log/file641.txt">
Test data
diff --git a/tests/data/test642 b/tests/data/test642
index 084626f04..6ae52bb82 100644
--- a/tests/data/test642
+++ b/tests/data/test642
@@ -24,7 +24,7 @@ sftp
SFTP retrieval
</name>
<command>
---key curl_client_key --pubkey curl_client_key.pub -u %USER: --compressed-ssh sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file642.txt --insecure
+--key curl_client_key --pubkey curl_client_key.pub -u %USER: --compressed-ssh sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file642.txt --insecure
</command>
<file name="log/file642.txt">
Test data
diff --git a/tests/data/test656 b/tests/data/test656
index 8591490ed..fb0f27fb9 100644
--- a/tests/data/test656
+++ b/tests/data/test656
@@ -16,7 +16,7 @@ sftp
SFTP retrieval with nonexistent private key file
</name>
<command>
---key DOES_NOT_EXIST --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/not-a-valid-file-moooo --insecure --connect-timeout 8
+--key DOES_NOT_EXIST --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/not-a-valid-file-moooo --insecure --connect-timeout 8
</command>
</client>
diff --git a/tests/data/test664 b/tests/data/test664
index cb73b248b..6bea4ed1a 100644
--- a/tests/data/test664
+++ b/tests/data/test664
@@ -24,7 +24,7 @@ sftp
SFTP correct host key
</name>
<command>
---hostpubmd5 %SSHSRVMD5 --key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file664.txt
+--hostpubmd5 %SSHSRVMD5 --key curl_client_key --pubkey curl_client_key.pub -u %USER: sftp://%HOSTIP:%SSHPORT%SSH_PWD/log/file664.txt
</command>
<file name="log/file664.txt">
test
diff --git a/tests/data/test665 b/tests/data/test665
index 830adb8f6..689fa31b6 100644
--- a/tests/data/test665
+++ b/tests/data/test665
@@ -24,7 +24,7 @@ scp
SCP correct host key
</name>
<command>
---hostpubmd5 %SSHSRVMD5 --key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%POSIX_PWD/log/file665.txt
+--hostpubmd5 %SSHSRVMD5 --key curl_client_key --pubkey curl_client_key.pub -u %USER: scp://%HOSTIP:%SSHPORT%SSH_PWD/log/file665.txt
</command>
<file name="log/file665.txt">
test
diff --git a/tests/data/test75 b/tests/data/test75
index 115963dfa..62aeb119d 100644
--- a/tests/data/test75
+++ b/tests/data/test75
@@ -27,11 +27,6 @@ HTTP, urlglob retrieval with bad range
<command option="no-output">
"http://a-site-never-accessed.example.org/[2-1]" -o "log/weee#1.dump" --stderr -
</command>
-# The error message on stdout implicitly depends on the length of the
-# URL, so refuse to run if the length is unexpected.
-<precheck>
-perl %SRCDIR/libtest/test75.pl http://%HOSTIP:%HTTPPORT/ 22
-</precheck>
</client>
#
diff --git a/tests/data/test76 b/tests/data/test76
index ada3a3359..b6c47cd88 100644
--- a/tests/data/test76
+++ b/tests/data/test76
@@ -22,7 +22,7 @@ http
HTTP, -O with no file name part in the URL
</name>
<command option="no-output">
-http://%HOSTIP:%HTTPPORT/76/ -O
+http://%HOSTIP:%NOLISTENPORT/76/ -O
</command>
</client>
diff --git a/tests/data/test895 b/tests/data/test895
new file mode 100644
index 000000000..78d48c475
--- /dev/null
+++ b/tests/data/test895
@@ -0,0 +1,50 @@
+<testcase>
+<info>
+<keywords>
+IMAP
+Clear Text
+FETCH
+--login-options
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+From: me@somewhere
+To: fake@nowhere
+
+body
+
+--
+ yours sincerely
+</data>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+imap
+</server>
+ <name>
+IMAP with --login-options 'AUTH=*'
+ </name>
+ <command>
+'imap://%HOSTIP:%IMAPPORT/895/;MAILINDEX=1' -u '"user:sec"ret{' --login-options 'AUTH=*'
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+A001 CAPABILITY
+A002 LOGIN "\"user" "sec\"ret{"
+A003 SELECT 895
+A004 FETCH 1 BODY[]
+A005 LOGOUT
+</protocol>
+</verify>
+</testcase>
diff --git a/tests/data/test896 b/tests/data/test896
new file mode 100644
index 000000000..c972906a4
--- /dev/null
+++ b/tests/data/test896
@@ -0,0 +1,38 @@
+<testcase>
+<info>
+<keywords>
+IMAP
+Clear Text
+FETCH
+--login-options
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+imap
+</server>
+ <name>
+IMAP with --login-options 'AUTH=dummy' (failing)
+ </name>
+ <command>
+'imap://%HOSTIP:%IMAPPORT/895/;MAILINDEX=1' -u '"user:sec"ret{' --login-options 'AUTH=dummy'
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+# 3 == CURLE_URL_MALFORMAT
+<errorcode>
+3
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test970 b/tests/data/test970
index 54e34cc5b..e6d138f49 100644
--- a/tests/data/test970
+++ b/tests/data/test970
@@ -33,6 +33,7 @@ http
</server>
<features>
debug
+proxy
</features>
<setenv>
CURL_TIME=13
diff --git a/tests/data/test971 b/tests/data/test971
new file mode 100644
index 000000000..de134e8e6
--- /dev/null
+++ b/tests/data/test971
@@ -0,0 +1,25 @@
+<testcase>
+<info>
+<keywords>
+source analysis
+options-in-versions
+</keywords>
+</info>
+
+#
+# Client-side
+<client>
+<server>
+none
+</server>
+
+ <name>
+Verify that options-in-versions and docs/cmdline-opts are in sync
+ </name>
+
+<command type="perl">
+%SRCDIR/options-scan.pl %SRCDIR/../docs/options-in-versions %SRCDIR/../docs/cmdline-opts
+</command>
+</client>
+
+</testcase>
diff --git a/tests/libtest/.checksrc b/tests/libtest/.checksrc
new file mode 100644
index 000000000..24677d53e
--- /dev/null
+++ b/tests/libtest/.checksrc
@@ -0,0 +1 @@
+disable TYPEDEFSTRUCT
diff --git a/tests/libtest/CMakeLists.txt b/tests/libtest/CMakeLists.txt
index 380580690..43ec8446e 100644
--- a/tests/libtest/CMakeLists.txt
+++ b/tests/libtest/CMakeLists.txt
@@ -22,7 +22,8 @@
set(TARGET_LABEL_PREFIX "Test ")
function(setup_test TEST_NAME) # ARGN are the files in the test
- add_executable( ${TEST_NAME} ${ARGN} )
+ add_executable(${TEST_NAME} EXCLUDE_FROM_ALL ${ARGN})
+ add_dependencies(testdeps ${TEST_NAME})
string(TOUPPER ${TEST_NAME} UPPER_TEST_NAME)
include_directories(
@@ -58,7 +59,8 @@ endforeach()
# Allows for hostname override to make tests machine independent.
# TODO this cmake build assumes a shared build, detect static linking here!
if(NOT WIN32)
- add_library(hostname MODULE sethostname.c sethostname.h)
+ add_library(hostname MODULE EXCLUDE_FROM_ALL sethostname.c sethostname.h)
+ add_dependencies(testdeps hostname)
# Output to .libs for compatibility with autotools, the test data expects a
# library at (tests)/libtest/.libs/libhostname.so
set_target_properties(hostname PROPERTIES
@@ -79,79 +81,3 @@ add_custom_command(
set_property(TARGET chkdecimalpoint
APPEND PROPERTY COMPILE_DEFINITIONS "CURLX_NO_MEMORY_CALLBACKS;CURL_STATICLIB")
-
- # # files used only in some libcurl test programs
-# SET(TESTUTIL testutil.c testutil.h)
-
-# # these files are used in every single test program below
-# SET(SUPPORTFILES first.c test.h)
-
-# # These are all libcurl test programs
-# SET(noinst_PROGRAMS
-# lib500 lib501 lib502 lib503 lib504 lib505 lib506
-# lib507 lib508 lib510 lib511 lib512 lib513 lib514 lib515 lib516
-# lib517 lib518 lib519 lib520 lib521 lib523 lib524 lib525 lib526
-# #lib527
-# #lib529
-# lib530
-# #lib532
-# lib533 lib536 lib537 lib540 lib541 lib542 lib543
-# lib544
-# #lib545
-# lib547
-# #lib548
-# lib549 lib552 lib553 lib554 lib555 lib556
-# lib539 lib557
-# lib560
-# )
-
-# SET(noinst_PROGRAMS_USE_TESTUTIL
-# lib502 lib503 lib504
-# lib507
-# lib525 lib526 lib527
-# lib529
-# lib530
-# lib532
-# lib533 lib536
-# lib555
-# )
-
-# MACRO(ADD_TESTUTIL_IF_NECESSARY TEST_NAME)
-# LIST(FIND noinst_PROGRAMS_USE_TESTUTIL ${TEST_NAME} USES_TESTUTIL)
-# IF(NOT ${USES_TESTUTIL} EQUAL -1)
-# LIST(APPEND SOURCE ${TESTUTIL}) # Need TestUtil
-# ENDIF()
-# ENDMACRO()
-
-# # General case
-# FOREACH(TEST_NAME ${noinst_PROGRAMS})
-# SET(SOURCE "${TEST_NAME}.c" ${SUPPORTFILES})
-# ADD_TESTUTIL_IF_NECESSARY(${TEST_NAME})
-# SETUP_TEST(${TEST_NAME} ${SOURCE})
-# ENDFOREACH()
-
-# # Special cases
-# SET(TEST_NAME lib527)
-# SET(SOURCE "lib526.c" ${SUPPORTFILES})
-# ADD_TESTUTIL_IF_NECESSARY(${TEST_NAME})
-# SETUP_TEST(${TEST_NAME} ${SOURCE})
-
-# SET(TEST_NAME lib529)
-# SET(SOURCE "lib525.c" ${SUPPORTFILES})
-# ADD_TESTUTIL_IF_NECESSARY(${TEST_NAME})
-# SETUP_TEST(${TEST_NAME} ${SOURCE})
-
-# SET(TEST_NAME lib532)
-# SET(SOURCE "lib526.c" ${SUPPORTFILES})
-# ADD_TESTUTIL_IF_NECESSARY(${TEST_NAME})
-# SETUP_TEST(${TEST_NAME} ${SOURCE})
-
-# SET(TEST_NAME lib545)
-# SET(SOURCE "lib544.c" ${SUPPORTFILES})
-# ADD_TESTUTIL_IF_NECESSARY(${TEST_NAME})
-# SETUP_TEST(${TEST_NAME} ${SOURCE})
-
-# SET(TEST_NAME lib548)
-# SET(SOURCE "lib547.c" ${SUPPORTFILES})
-# ADD_TESTUTIL_IF_NECESSARY(${TEST_NAME})
-# SETUP_TEST(${TEST_NAME} ${SOURCE})
diff --git a/tests/libtest/Makefile.am b/tests/libtest/Makefile.am
index 0b0c67775..eea1ff3ce 100644
--- a/tests/libtest/Makefile.am
+++ b/tests/libtest/Makefile.am
@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -38,7 +38,8 @@ else
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/lib -I$(top_srcdir)/lib
endif
-EXTRA_DIST = test75.pl test307.pl test610.pl test613.pl test1013.pl test1022.pl Makefile.inc notexists.pl mk-lib1521.pl
+EXTRA_DIST = test307.pl test610.pl test613.pl test1013.pl \
+ test1022.pl Makefile.inc notexists.pl CMakeLists.txt mk-lib1521.pl
CFLAG_CURL_SYMBOL_HIDING = @CFLAG_CURL_SYMBOL_HIDING@
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
index 1651308b1..f29bf6aee 100644
--- a/tests/libtest/Makefile.inc
+++ b/tests/libtest/Makefile.inc
@@ -28,6 +28,9 @@ TSTTRACE = testtrace.c testtrace.h
# files used only in some libcurl test programs
WARNLESS = ../../lib/warnless.c ../../lib/warnless.h
+# files used only in some libcurl test programs
+MULTIBYTE = ../../lib/curl_multibyte.c ../../lib/curl_multibyte.h
+
# these files are used in every single test program below
SUPPORTFILES = first.c test.h
@@ -50,16 +53,16 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \
lib1509 lib1510 lib1511 lib1512 lib1513 lib1514 lib1515 lib1517 \
lib1518 lib1520 lib1521 lib1522 lib1523 \
lib1525 lib1526 lib1527 lib1528 lib1529 lib1530 lib1531 lib1532 lib1533 \
- lib1534 lib1535 lib1536 lib1537 lib1538 \
+ lib1534 lib1535 lib1536 lib1537 lib1538 lib1539 \
lib1540 lib1541 \
lib1550 lib1551 lib1552 lib1553 lib1554 lib1555 lib1556 lib1557 \
lib1558 lib1559 lib1560 lib1564 lib1565 \
lib1591 lib1592 lib1593 lib1594 lib1596 \
- lib1900 lib1905 lib1906 lib1907 lib1908 \
+ lib1900 lib1905 lib1906 lib1907 lib1908 lib1910 \
lib2033
chkdecimalpoint_SOURCES = chkdecimalpoint.c ../../lib/mprintf.c \
- ../../lib/curl_ctype.c
+ ../../lib/curl_ctype.c ../../lib/dynbuf.c ../../lib/strdup.c
chkdecimalpoint_LDADD =
chkdecimalpoint_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB \
-DCURLX_NO_MEMORY_CALLBACKS
@@ -76,7 +79,7 @@ libntlmconnect_CPPFLAGS = $(AM_CPPFLAGS)
libauthretry_SOURCES = libauthretry.c $(SUPPORTFILES)
libauthretry_CPPFLAGS = $(AM_CPPFLAGS)
-lib500_SOURCES = lib500.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE)
+lib500_SOURCES = lib500.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(MULTIBYTE)
lib500_LDADD = $(TESTUTIL_LIBS)
lib500_CPPFLAGS = $(AM_CPPFLAGS)
@@ -95,7 +98,7 @@ lib504_SOURCES = lib504.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib504_LDADD = $(TESTUTIL_LIBS)
lib504_CPPFLAGS = $(AM_CPPFLAGS)
-lib505_SOURCES = lib505.c $(SUPPORTFILES)
+lib505_SOURCES = lib505.c $(SUPPORTFILES) $(MULTIBYTE)
lib505_CPPFLAGS = $(AM_CPPFLAGS)
lib506_SOURCES = lib506.c $(SUPPORTFILES)
@@ -135,7 +138,7 @@ lib516_CPPFLAGS = $(AM_CPPFLAGS)
lib517_SOURCES = lib517.c $(SUPPORTFILES)
lib517_CPPFLAGS = $(AM_CPPFLAGS)
-lib518_SOURCES = lib518.c $(SUPPORTFILES) $(WARNLESS)
+lib518_SOURCES = lib518.c $(SUPPORTFILES) $(WARNLESS) $(MULTIBYTE)
lib518_CPPFLAGS = $(AM_CPPFLAGS)
lib519_SOURCES = lib519.c $(SUPPORTFILES)
@@ -153,7 +156,7 @@ lib523_CPPFLAGS = $(AM_CPPFLAGS)
lib524_SOURCES = lib524.c $(SUPPORTFILES)
lib524_CPPFLAGS = $(AM_CPPFLAGS)
-lib525_SOURCES = lib525.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib525_SOURCES = lib525.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib525_LDADD = $(TESTUTIL_LIBS)
lib525_CPPFLAGS = $(AM_CPPFLAGS)
@@ -165,7 +168,7 @@ lib527_SOURCES = lib526.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib527_LDADD = $(TESTUTIL_LIBS)
lib527_CPPFLAGS = $(AM_CPPFLAGS) -DLIB527
-lib529_SOURCES = lib525.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib529_SOURCES = lib525.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib529_LDADD = $(TESTUTIL_LIBS)
lib529_CPPFLAGS = $(AM_CPPFLAGS) -DLIB529
@@ -181,7 +184,7 @@ lib533_SOURCES = lib533.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib533_LDADD = $(TESTUTIL_LIBS)
lib533_CPPFLAGS = $(AM_CPPFLAGS)
-lib537_SOURCES = lib537.c $(SUPPORTFILES) $(WARNLESS)
+lib537_SOURCES = lib537.c $(SUPPORTFILES) $(WARNLESS) $(MULTIBYTE)
lib537_CPPFLAGS = $(AM_CPPFLAGS)
lib539_SOURCES = lib539.c $(SUPPORTFILES)
@@ -191,7 +194,7 @@ lib540_SOURCES = lib540.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib540_LDADD = $(TESTUTIL_LIBS)
lib540_CPPFLAGS = $(AM_CPPFLAGS)
-lib541_SOURCES = lib541.c $(SUPPORTFILES)
+lib541_SOURCES = lib541.c $(SUPPORTFILES) $(MULTIBYTE)
lib541_CPPFLAGS = $(AM_CPPFLAGS)
lib542_SOURCES = lib542.c $(SUPPORTFILES)
@@ -254,25 +257,25 @@ lib564_CPPFLAGS = $(AM_CPPFLAGS)
lib565_SOURCES = lib510.c $(SUPPORTFILES)
lib565_CPPFLAGS = $(AM_CPPFLAGS) -DLIB565
-lib566_SOURCES = lib566.c $(SUPPORTFILES)
+lib566_SOURCES = lib566.c $(SUPPORTFILES) $(MULTIBYTE)
lib566_CPPFLAGS = $(AM_CPPFLAGS)
lib567_SOURCES = lib567.c $(SUPPORTFILES)
lib567_CPPFLAGS = $(AM_CPPFLAGS)
-lib568_SOURCES = lib568.c $(SUPPORTFILES)
+lib568_SOURCES = lib568.c $(SUPPORTFILES) $(MULTIBYTE)
lib568_CPPFLAGS = $(AM_CPPFLAGS)
-lib569_SOURCES = lib569.c $(SUPPORTFILES)
+lib569_SOURCES = lib569.c $(SUPPORTFILES) $(MULTIBYTE)
lib569_CPPFLAGS = $(AM_CPPFLAGS)
lib570_SOURCES = lib570.c $(SUPPORTFILES)
lib570_CPPFLAGS = $(AM_CPPFLAGS)
-lib571_SOURCES = lib571.c $(SUPPORTFILES) $(WARNLESS)
+lib571_SOURCES = lib571.c $(SUPPORTFILES) $(WARNLESS) $(MULTIBYTE)
lib571_CPPFLAGS = $(AM_CPPFLAGS)
-lib572_SOURCES = lib572.c $(SUPPORTFILES)
+lib572_SOURCES = lib572.c $(SUPPORTFILES) $(MULTIBYTE)
lib572_CPPFLAGS = $(AM_CPPFLAGS)
lib573_SOURCES = lib573.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(TSTTRACE)
@@ -289,20 +292,20 @@ lib575_CPPFLAGS = $(AM_CPPFLAGS)
lib576_SOURCES = lib576.c $(SUPPORTFILES)
lib576_CPPFLAGS = $(AM_CPPFLAGS)
-lib578_SOURCES = lib578.c $(SUPPORTFILES)
+lib578_SOURCES = lib578.c $(SUPPORTFILES) $(MULTIBYTE)
lib578_CPPFLAGS = $(AM_CPPFLAGS)
-lib579_SOURCES = lib579.c $(SUPPORTFILES)
+lib579_SOURCES = lib579.c $(SUPPORTFILES) $(MULTIBYTE)
lib579_CPPFLAGS = $(AM_CPPFLAGS)
-lib582_SOURCES = lib582.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib582_SOURCES = lib582.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib582_LDADD = $(TESTUTIL_LIBS)
lib582_CPPFLAGS = $(AM_CPPFLAGS)
lib583_SOURCES = lib583.c $(SUPPORTFILES)
lib583_CPPFLAGS = $(AM_CPPFLAGS)
-lib585_SOURCES = lib500.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE)
+lib585_SOURCES = lib500.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(MULTIBYTE)
lib585_LDADD = $(TESTUTIL_LIBS)
lib585_CPPFLAGS = $(AM_CPPFLAGS) -DLIB585
@@ -318,7 +321,7 @@ lib589_CPPFLAGS = $(AM_CPPFLAGS)
lib590_SOURCES = lib590.c $(SUPPORTFILES)
lib590_CPPFLAGS = $(AM_CPPFLAGS)
-lib591_SOURCES = lib591.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib591_SOURCES = lib591.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib591_LDADD = $(TESTUTIL_LIBS)
lib591_CPPFLAGS = $(AM_CPPFLAGS)
@@ -329,7 +332,7 @@ lib597_CPPFLAGS = $(AM_CPPFLAGS)
lib598_SOURCES = lib598.c $(SUPPORTFILES)
lib598_CPPFLAGS = $(AM_CPPFLAGS)
-lib599_SOURCES = lib599.c $(SUPPORTFILES)
+lib599_SOURCES = lib599.c $(SUPPORTFILES) $(MULTIBYTE)
lib599_CPPFLAGS = $(AM_CPPFLAGS)
lib643_SOURCES = lib643.c $(SUPPORTFILES)
@@ -539,6 +542,10 @@ lib1538_SOURCES = lib1538.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1538_LDADD = $(TESTUTIL_LIBS)
lib1538_CPPFLAGS = $(AM_CPPFLAGS)
+lib1539_SOURCES = lib1514.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1539_LDADD = $(TESTUTIL_LIBS)
+lib1539_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1539
+
lib1540_SOURCES = lib1540.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1540_LDADD = $(TESTUTIL_LIBS)
lib1540_CPPFLAGS = $(AM_CPPFLAGS)
@@ -611,7 +618,7 @@ lib1596_SOURCES = lib1594.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1596_LDADD = $(TESTUTIL_LIBS)
lib1596_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1596
-lib1900_SOURCES = lib1900.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1900_SOURCES = lib1900.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) $(MULTIBYTE)
lib1900_LDADD = $(TESTUTIL_LIBS)
lib1900_CPPFLAGS = $(AM_CPPFLAGS)
@@ -631,6 +638,10 @@ lib1908_SOURCES = lib1908.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib1908_LDADD = $(TESTUTIL_LIBS)
lib1908_CPPFLAGS = $(AM_CPPFLAGS)
+lib1910_SOURCES = lib1910.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1910_LDADD = $(TESTUTIL_LIBS)
+lib1910_CPPFLAGS = $(AM_CPPFLAGS)
+
lib2033_SOURCES = libntlmconnect.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
lib2033_LDADD = $(TESTUTIL_LIBS)
lib2033_CPPFLAGS = $(AM_CPPFLAGS) -DUSE_PIPELINING
diff --git a/tests/libtest/lib1156.c b/tests/libtest/lib1156.c
index df6062c56..ff94d9cfd 100644
--- a/tests/libtest/lib1156.c
+++ b/tests/libtest/lib1156.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,12 +40,12 @@
#define F_CONTENTRANGE (1 << 3) /* Server sends content-range hdr. */
#define F_IGNOREBODY (1 << 4) /* Body should be ignored. */
-typedef struct {
+struct testparams {
unsigned int flags; /* ORed flags as above. */
CURLcode result; /* Code that should be returned by curl_easy_perform(). */
-} testparams;
+};
-static const testparams params[] = {
+static const struct testparams params[] = {
{ 0, CURLE_OK },
{ F_CONTENTRANGE, CURLE_OK },
{ F_FAIL, CURLE_OK },
@@ -82,7 +82,7 @@ static size_t writedata(char *data, size_t size, size_t nmemb, void *userdata)
return size * nmemb;
}
-static int onetest(CURL *curl, const char *url, const testparams *p)
+static int onetest(CURL *curl, const char *url, const struct testparams *p)
{
CURLcode res;
unsigned int replyselector;
diff --git a/tests/libtest/lib1514.c b/tests/libtest/lib1514.c
index d01a5d4fb..dd84d109f 100644
--- a/tests/libtest/lib1514.c
+++ b/tests/libtest/lib1514.c
@@ -68,6 +68,10 @@ int test(char *URL)
/* Purposely omit to set CURLOPT_POSTFIELDSIZE */
easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
easy_setopt(curl, CURLOPT_READDATA, &pooh);
+#ifdef LIB1539
+ /* speak HTTP 1.0 - no chunked! */
+ easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+#endif
result = curl_easy_perform(curl);
diff --git a/tests/libtest/lib1560.c b/tests/libtest/lib1560.c
index fbe642c20..d158534d7 100644
--- a/tests/libtest/lib1560.c
+++ b/tests/libtest/lib1560.c
@@ -129,13 +129,22 @@ struct querycase {
};
static struct testcase get_parts_list[] ={
- {"user:moo@ftp.example.com/color/#green?no-black",
+ {"[::1]",
+ "http | [11] | [12] | [13] | [::1] | [15] | / | [16] | [17]",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK },
+ {"[::]",
+ "http | [11] | [12] | [13] | [::] | [15] | / | [16] | [17]",
+ CURLU_GUESS_SCHEME, 0, CURLUE_OK },
+ {"https://[::1]",
+ "https | [11] | [12] | [13] | [::1] | [15] | / | [16] | [17]",
+ 0, 0, CURLUE_OK },
+ {"user:moo@ftp.example.com/color/#green?no-red",
"ftp | user | moo | [13] | ftp.example.com | [15] | /color/ | [16] | "
- "green?no-black",
+ "green?no-red",
CURLU_GUESS_SCHEME, 0, CURLUE_OK },
- {"ftp.user:moo@example.com/color/#green?no-black",
+ {"ftp.user:moo@example.com/color/#green?no-red",
"http | ftp.user | moo | [13] | example.com | [15] | /color/ | [16] | "
- "green?no-black",
+ "green?no-red",
CURLU_GUESS_SCHEME, 0, CURLUE_OK },
#ifdef WIN32
{"file:/C:\\programs\\foo",
@@ -148,25 +157,25 @@ static struct testcase get_parts_list[] ={
"file | [11] | [12] | [13] | [14] | [15] | C:\\programs\\foo | [16] | [17]",
CURLU_DEFAULT_SCHEME, 0, CURLUE_OK},
#endif
- {"https://example.com/color/#green?no-black",
+ {"https://example.com/color/#green?no-red",
"https | [11] | [12] | [13] | example.com | [15] | /color/ | [16] | "
- "green?no-black",
+ "green?no-red",
CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
- {"https://example.com/color/#green#no-black",
+ {"https://example.com/color/#green#no-red",
"https | [11] | [12] | [13] | example.com | [15] | /color/ | [16] | "
- "green#no-black",
+ "green#no-red",
CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
- {"https://example.com/color/?green#no-black",
+ {"https://example.com/color/?green#no-red",
"https | [11] | [12] | [13] | example.com | [15] | /color/ | green | "
- "no-black",
+ "no-red",
CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
- {"https://example.com/#color/?green#no-black",
+ {"https://example.com/#color/?green#no-red",
"https | [11] | [12] | [13] | example.com | [15] | / | [16] | "
- "color/?green#no-black",
+ "color/?green#no-red",
CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
- {"https://example.#com/color/?green#no-black",
+ {"https://example.#com/color/?green#no-red",
"https | [11] | [12] | [13] | example. | [15] | / | [16] | "
- "com/color/?green#no-black",
+ "com/color/?green#no-red",
CURLU_DEFAULT_SCHEME, 0, CURLUE_OK },
{"http://[ab.be:1]/x", "",
CURLU_DEFAULT_SCHEME, 0, CURLUE_MALFORMED_INPUT},
diff --git a/tests/libtest/lib1900.c b/tests/libtest/lib1900.c
index 2a70f8eba..fd7e5bc62 100644
--- a/tests/libtest/lib1900.c
+++ b/tests/libtest/lib1900.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2013 - 2019, Linus Nielsen Feltzing, <linus@haxx.se>
+ * Copyright (C) 2013 - 2020, Linus Nielsen Feltzing, <linus@haxx.se>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,16 +27,16 @@
#define TEST_HANG_TIMEOUT 60 * 1000
#define MAX_URLS 200
-#define MAX_BLACKLIST 20
+#define MAX_BLOCKLIST 20
static int urltime[MAX_URLS];
static char *urlstring[MAX_URLS];
static CURL *handles[MAX_URLS];
-static char *site_blacklist[MAX_BLACKLIST];
-static char *server_blacklist[MAX_BLACKLIST];
+static char *site_blocklist[MAX_BLOCKLIST];
+static char *server_blocklist[MAX_BLOCKLIST];
static int num_handles;
-static int blacklist_num_servers;
-static int blacklist_num_sites;
+static int blocklist_num_servers;
+static int blocklist_num_sites;
static size_t
write_callback(void *contents, size_t size, size_t nmemb, void *userp)
@@ -55,8 +55,8 @@ static int parse_url_file(const char *filename)
char buf[200];
num_handles = 0;
- blacklist_num_sites = 0;
- blacklist_num_servers = 0;
+ blocklist_num_sites = 0;
+ blocklist_num_servers = 0;
f = fopen(filename, "rb");
if(!f)
@@ -70,9 +70,9 @@ static int parse_url_file(const char *filename)
continue;
}
- if(fscanf(f, "blacklist_site %199s\n", buf)) {
- site_blacklist[blacklist_num_sites] = strdup(buf);
- blacklist_num_sites++;
+ if(fscanf(f, "blocklist_site %199s\n", buf)) {
+ site_blocklist[blocklist_num_sites] = strdup(buf);
+ blocklist_num_sites++;
continue;
}
@@ -80,8 +80,8 @@ static int parse_url_file(const char *filename)
}
fclose(f);
- site_blacklist[blacklist_num_sites] = NULL;
- server_blacklist[blacklist_num_servers] = NULL;
+ site_blocklist[blocklist_num_sites] = NULL;
+ server_blocklist[blocklist_num_servers] = NULL;
return num_handles;
}
@@ -91,11 +91,11 @@ static void free_urls(void)
for(i = 0; i < num_handles; i++) {
Curl_safefree(urlstring[i]);
}
- for(i = 0; i < blacklist_num_servers; i++) {
- Curl_safefree(server_blacklist[i]);
+ for(i = 0; i < blocklist_num_servers; i++) {
+ Curl_safefree(server_blocklist[i]);
}
- for(i = 0; i < blacklist_num_sites; i++) {
- Curl_safefree(site_blacklist[i]);
+ for(i = 0; i < blocklist_num_sites; i++) {
+ Curl_safefree(site_blocklist[i]);
}
}
@@ -159,8 +159,8 @@ int test(char *URL)
multi_setopt(m, CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, 15000L);
multi_setopt(m, CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, 10000L);
- multi_setopt(m, CURLMOPT_PIPELINING_SITE_BL, site_blacklist);
- multi_setopt(m, CURLMOPT_PIPELINING_SERVER_BL, server_blacklist);
+ multi_setopt(m, CURLMOPT_PIPELINING_SITE_BL, site_blocklist);
+ multi_setopt(m, CURLMOPT_PIPELINING_SERVER_BL, server_blocklist);
last_handle_add = tutil_tvnow();
diff --git a/tests/libtest/lib1910.c b/tests/libtest/lib1910.c
new file mode 100644
index 000000000..1e25db5a4
--- /dev/null
+++ b/tests/libtest/lib1910.c
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 2013 - 2020, Linus Nielsen Feltzing, <linus@haxx.se>
+ *
+ * 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 "testutil.h"
+#include "warnless.h"
+#include "memdebug.h"
+
+int test(char *URL)
+{
+ CURLcode ret = CURLE_OK;
+ CURL *hnd;
+ start_test_timing();
+
+ curl_global_init(CURL_GLOBAL_ALL);
+
+ hnd = curl_easy_init();
+ if(hnd) {
+ curl_easy_setopt(hnd, CURLOPT_URL, URL);
+ curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L);
+ curl_easy_setopt(hnd, CURLOPT_FOLLOWLOCATION, 1L);
+ curl_easy_setopt(hnd, CURLOPT_USERPWD, "user\nname:pass\nword");
+ ret = curl_easy_perform(hnd);
+ curl_easy_cleanup(hnd);
+ }
+ curl_global_cleanup();
+ return (int)ret;
+}
diff --git a/tests/libtest/lib509.c b/tests/libtest/lib509.c
index e8e803ffc..1fb2d3445 100644
--- a/tests/libtest/lib509.c
+++ b/tests/libtest/lib509.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -34,70 +34,35 @@
* memory callbacks which should be calling 'the real thing'.
*/
-/*
-#include "memdebug.h"
-*/
-
-static int seen_malloc = 0;
-static int seen_free = 0;
-static int seen_realloc = 0;
-static int seen_strdup = 0;
-static int seen_calloc = 0;
-
-void *custom_malloc(size_t size);
-void custom_free(void *ptr);
-void *custom_realloc(void *ptr, size_t size);
-char *custom_strdup(const char *ptr);
-void *custom_calloc(size_t nmemb, size_t size);
+static int seen;
-
-void *custom_calloc(size_t nmemb, size_t size)
+static void *custom_calloc(size_t nmemb, size_t size)
{
- if(!seen_calloc) {
- printf("seen custom_calloc()\n");
- seen_calloc = 1;
- }
+ seen++;
return (calloc)(nmemb, size);
}
-void *custom_malloc(size_t size)
+static void *custom_malloc(size_t size)
{
- if(!seen_malloc && seen_calloc) {
- printf("seen custom_malloc()\n");
- seen_malloc = 1;
- }
+ seen++;
return (malloc)(size);
}
-char *custom_strdup(const char *ptr)
+static char *custom_strdup(const char *ptr)
{
- if(!seen_strdup && seen_malloc) {
- /* currently (2013.03.13), memory tracking enabled builds do not call
- the strdup callback, in this case malloc callback and memcpy are used
- instead. If some day this is changed the following printf() should be
- uncommented, and a line added to test definition.
- printf("seen custom_strdup()\n");
- */
- seen_strdup = 1;
- }
+ seen++;
return (strdup)(ptr);
}
-void *custom_realloc(void *ptr, size_t size)
+static void *custom_realloc(void *ptr, size_t size)
{
- if(!seen_realloc && seen_malloc) {
- printf("seen custom_realloc()\n");
- seen_realloc = 1;
- }
+ seen++;
return (realloc)(ptr, size);
}
-void custom_free(void *ptr)
+static void custom_free(void *ptr)
{
- if(!seen_free && seen_realloc) {
- printf("seen custom_free()\n");
- seen_free = 1;
- }
+ seen++;
(free)(ptr);
}
@@ -110,7 +75,6 @@ int test(char *URL)
CURL *curl;
int asize;
char *str = NULL;
-
(void)URL;
res = curl_global_init_mem(CURL_GLOBAL_ALL,
@@ -136,6 +100,9 @@ int test(char *URL)
asize = (int)sizeof(a);
str = curl_easy_escape(curl, (char *)a, asize); /* uses realloc() */
+ if(seen)
+ printf("Callbacks were invoked!\n");
+
test_cleanup:
if(str)
diff --git a/tests/libtest/lib543.c b/tests/libtest/lib543.c
index 5fe5cd1ce..c494d3d83 100644
--- a/tests/libtest/lib543.c
+++ b/tests/libtest/lib543.c
@@ -49,11 +49,21 @@ int test(char *URL)
s = curl_easy_escape(easy, (const char *)a, asize);
- if(s)
+ if(s) {
printf("%s\n", s);
+ curl_free(s);
+ }
- if(s)
+ s = curl_easy_escape(easy, "", 0);
+ if(s) {
+ printf("IN: '' OUT: '%s'\n", s);
curl_free(s);
+ }
+ s = curl_easy_escape(easy, " 123", 3);
+ if(s) {
+ printf("IN: ' 12' OUT: '%s'\n", s);
+ curl_free(s);
+ }
curl_easy_cleanup(easy);
curl_global_cleanup();
diff --git a/tests/libtest/lib547.c b/tests/libtest/lib547.c
index 85e8e0c1e..1416f895c 100644
--- a/tests/libtest/lib547.c
+++ b/tests/libtest/lib547.c
@@ -101,7 +101,7 @@ int test(char *URL)
test_setopt(curl, CURLOPT_VERBOSE, 1L);
test_setopt(curl, CURLOPT_HEADER, 1L);
#ifdef LIB548
- /* set the data to POST with a mere pointer to a zero-terminated string */
+ /* set the data to POST with a mere pointer to a null-terminated string */
test_setopt(curl, CURLOPT_POSTFIELDS, UPLOADTHIS);
#else
/* 547 style, which means reading the POST data from a callback */
diff --git a/tests/libtest/lib553.c b/tests/libtest/lib553.c
index 95b5ac393..015bf29ac 100644
--- a/tests/libtest/lib553.c
+++ b/tests/libtest/lib553.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -77,7 +77,7 @@ int test(char *URL)
for(i = 0; i < NUM_HEADERS; i++) {
int len = msnprintf(buf, sizeof(buf), "Header%d: ", i);
memset(&buf[len], 'A', SIZE_HEADERS);
- buf[len + SIZE_HEADERS] = 0; /* zero terminate */
+ buf[len + SIZE_HEADERS] = 0; /* null-terminate */
hl = curl_slist_append(headerlist, buf);
if(!hl)
goto test_cleanup;
diff --git a/tests/libtest/lib576.c b/tests/libtest/lib576.c
index 3b9a9001d..f66825895 100644
--- a/tests/libtest/lib576.c
+++ b/tests/libtest/lib576.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,10 +24,10 @@
#include "testutil.h"
#include "memdebug.h"
-typedef struct {
+struct chunk_data {
int remains;
int print_content;
-} chunk_data_t;
+};
static
long chunk_bgn(const struct curl_fileinfo *finfo, void *ptr, int remains);
@@ -37,7 +37,7 @@ long chunk_end(void *ptr);
static
long chunk_bgn(const struct curl_fileinfo *finfo, void *ptr, int remains)
{
- chunk_data_t *ch_d = ptr;
+ struct chunk_data *ch_d = ptr;
ch_d->remains = remains;
printf("=============================================================\n");
@@ -87,7 +87,7 @@ long chunk_bgn(const struct curl_fileinfo *finfo, void *ptr, int remains)
static
long chunk_end(void *ptr)
{
- chunk_data_t *ch_d = ptr;
+ struct chunk_data *ch_d = ptr;
if(ch_d->print_content) {
ch_d->print_content = 0;
printf("-------------------------------------------------------------\n");
@@ -101,7 +101,7 @@ int test(char *URL)
{
CURL *handle = NULL;
CURLcode res = CURLE_OK;
- chunk_data_t chunk_data = {0, 0};
+ struct chunk_data chunk_data = {0, 0};
curl_global_init(CURL_GLOBAL_ALL);
handle = curl_easy_init();
if(!handle) {
diff --git a/tests/libtest/lib582.c b/tests/libtest/lib582.c
index c0678b0e5..96841052b 100644
--- a/tests/libtest/lib582.c
+++ b/tests/libtest/lib582.c
@@ -44,7 +44,7 @@ struct ReadWriteSockets
/**
* Remove a file descriptor from a sockets array.
*/
-static void removeFd(struct Sockets* sockets, curl_socket_t fd, int mention)
+static void removeFd(struct Sockets *sockets, curl_socket_t fd, int mention)
{
int i;
@@ -64,7 +64,7 @@ static void removeFd(struct Sockets* sockets, curl_socket_t fd, int mention)
/**
* Add a file descriptor to a sockets array.
*/
-static void addFd(struct Sockets* sockets, curl_socket_t fd, const char *what)
+static void addFd(struct Sockets *sockets, curl_socket_t fd, const char *what)
{
/**
* To ensure we only have each file descriptor once, we remove it then add
@@ -105,7 +105,7 @@ static void addFd(struct Sockets* sockets, curl_socket_t fd, const char *what)
static int curlSocketCallback(CURL *easy, curl_socket_t s, int action,
void *userp, void *socketp)
{
- struct ReadWriteSockets* sockets = userp;
+ struct ReadWriteSockets *sockets = userp;
(void)easy; /* unused */
(void)socketp; /* unused */
@@ -129,7 +129,7 @@ static int curlSocketCallback(CURL *easy, curl_socket_t s, int action,
*/
static int curlTimerCallback(CURLM *multi, long timeout_ms, void *userp)
{
- struct timeval* timeout = userp;
+ struct timeval *timeout = userp;
(void)multi; /* unused */
if(timeout_ms != -1) {
@@ -169,7 +169,7 @@ static int checkForCompletion(CURLM *curl, int *success)
return result;
}
-static int getMicroSecondTimeout(struct timeval* timeout)
+static int getMicroSecondTimeout(struct timeval *timeout)
{
struct timeval now;
ssize_t result;
@@ -185,7 +185,7 @@ static int getMicroSecondTimeout(struct timeval* timeout)
/**
* Update a fd_set with all of the sockets in use.
*/
-static void updateFdSet(struct Sockets* sockets, fd_set* fdset,
+static void updateFdSet(struct Sockets *sockets, fd_set* fdset,
curl_socket_t *maxFd)
{
int i;
diff --git a/tests/libtest/lib651.c b/tests/libtest/lib651.c
index 18bcaae83..777f6f59b 100644
--- a/tests/libtest/lib651.c
+++ b/tests/libtest/lib651.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -40,7 +40,7 @@ int test(char *URL)
for(i = 0; i < size ; i++)
memset(&buffer[i * 1000], 65 + i, 1000);
- buffer[ sizeof(buffer)-1] = 0; /* zero terminate */
+ buffer[ sizeof(buffer)-1] = 0; /* null-terminate */
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed\n");
diff --git a/tests/libtest/mk-lib1521.pl b/tests/libtest/mk-lib1521.pl
index 27fadcfce..14b222098 100755
--- a/tests/libtest/mk-lib1521.pl
+++ b/tests/libtest/mk-lib1521.pl
@@ -158,6 +158,7 @@ int test(char *URL)
curl_socket_t sockfd;
struct curl_certinfo *certinfo;
struct curl_tlssessioninfo *tlssession;
+ struct curl_blob blob = { (void *)"silly", 5, 0};
CURLcode res = CURLE_OK;
(void)URL; /* not used */
global_init(CURL_GLOBAL_ALL);
@@ -239,8 +240,12 @@ while(<STDIN>) {
print "${pref} OFF_HI);\n$check";
print "${pref} OFF_LO);\n$check";
}
+ elsif($type eq "CURLOPTTYPE_BLOB") {
+ print "${pref} &blob);\n$check";
+ }
else {
print STDERR "\n---- $type\n";
+ exit; # exit to make this noticed!
}
}
elsif($_ =~ /^ CURLINFO_NONE/) {
diff --git a/tests/libtest/test613.pl b/tests/libtest/test613.pl
index ead1159ff..8efc05ca0 100755
--- a/tests/libtest/test613.pl
+++ b/tests/libtest/test613.pl
@@ -97,15 +97,29 @@ elsif ($ARGV[0] eq "postprocess")
my @canondir;
open(IN, "<$logfile") || die "$!";
while (<IN>) {
- /^(.)(..).(..).(..).\s*(\S+)\s+\S+\s+\S+\s+(\S+)\s+(\S+\s+\S+\s+\S+)(.*)$/;
+ /^(.)(..).(..).(..).\s*(\S+)\s+\S+\s+\S+\s+(\S+)\s+(\S+\s+\S+\s+\S+)\s+(.*)$/;
if ($1 eq "d") {
+ # Skip current and parent directory listing, because some SSH
+ # servers (eg. OpenSSH for Windows) are not listing those
+ if ($8 eq "." || $8 eq "..") {
+ next;
+ }
# Erase all directory metadata except for the name, as it is not
# consistent for across all test systems and filesystems
- push @canondir, "d????????? N U U N ??? N NN:NN$8\n";
+ push @canondir, "d????????? N U U N ??? N NN:NN $8\n";
} elsif ($1 eq "-") {
+ # Replace missing group and other permissions with user
+ # permissions (eg. on Windows) due to them being shown as *
+ my ($u, $g, $o) = ($2, $3, $4);
+ if($g eq "**") {
+ $g = $u;
+ }
+ if($o eq "**") {
+ $o = $u;
+ }
# Erase user and group names, as they are not consistent across
# all test systems
- my $line = sprintf("%s%s?%s?%s?%5d U U %15d %s%s\n", $1,$2,$3,$4,$5,$6,$7,$8);
+ my $line = sprintf("%s%s?%s?%s?%5d U U %15d %s %s\n", $1,$u,$g,$o,$5,$6,$7,$8);
push @canondir, $line;
} else {
# Unexpected format; just pass it through and let the test fail
diff --git a/tests/libtest/test75.pl b/tests/libtest/test75.pl
deleted file mode 100755
index 2182f5304..000000000
--- a/tests/libtest/test75.pl
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env perl
-#***************************************************************************
-# _ _ ____ _
-# Project ___| | | | _ \| |
-# / __| | | | |_) | |
-# | (__| |_| | _ <| |___
-# \___|\___/|_| \_\_____|
-#
-# Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at https://curl.haxx.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-###########################################################################
-# Check that the length of a given URL is correct
-if ( $#ARGV != 1 )
-{
- print "Usage: $0 string length\n";
- exit 3;
-}
-if (length(@ARGV[0]) != @ARGV[1])
-{
- print "Given host IP and port not supported\n";
- exit 1;
-}
-exit 0;
diff --git a/tests/manpage-scan.pl.in b/tests/manpage-scan.pl.in
index 6402adf02..cb8301528 100755
--- a/tests/manpage-scan.pl.in
+++ b/tests/manpage-scan.pl.in
@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
-# Copyright (C) 2016 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+# Copyright (C) 2016 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -130,7 +130,7 @@ scanmanpage("$root/docs/libcurl/gnurl_easy_setopt.3", @curlopt);
scanmanpage("$root/docs/libcurl/gnurl_easy_getinfo.3", @curlinfo);
scanmanpage("$root/docs/libcurl/gnurl_multi_setopt.3", @curlmopt);
-# using this hash array, we can whitelist specific options
+# using this hash array, we can skip specific options
my %opts = (
# pretend these --no options exists in tool_getparam.c
'--no-alpn' => 1,
diff --git a/tests/options-scan.pl b/tests/options-scan.pl
new file mode 100644
index 000000000..d49352b40
--- /dev/null
+++ b/tests/options-scan.pl
@@ -0,0 +1,120 @@
+#!/usr/bin/env perl
+#***************************************************************************
+# _ _ ____ _
+# Project ___| | | | _ \| |
+# / __| | | | |_) | |
+# | (__| |_| | _ <| |___
+# \___|\___/|_| \_\_____|
+#
+# Copyright (C) 2010 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at https://curl.haxx.se/docs/copyright.html.
+#
+# You may opt to use, copy, modify, merge, publish, distribute and/or sell
+# copies of the Software, and permit persons to whom the Software is
+# furnished to do so, under the terms of the COPYING file.
+#
+# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+# KIND, either express or implied.
+#
+###########################################################################
+#
+#
+# - Get all options mentioned in the $cmddir.
+# - Make sure they're all mentioned in the $opts document
+# - Make usre that the version in $opts matches the version in the file in
+# $cmddir
+#
+
+my $opts = $ARGV[0];
+my $cmddir = $ARGV[1];
+
+sub cmdfiles {
+ my ($dir)=@_;
+
+ opendir(my $dh, $dir) || die "Can't opendir $dir: $!";
+ my @opts = grep { /\.d$/ && -f "$dir/$_" } readdir($dh);
+ closedir $dh;
+
+ for(@opts) {
+ $_ =~ s/\.d$//;
+ $file{$_}=1;
+ }
+ return @opts;
+}
+
+sub mentions {
+ my ($f) = @_;
+ my @options;
+ open(F, "<$f");
+ while(<F>) {
+ chomp;
+ if(/(.*) +([0-9.]+)/) {
+ my ($flag, $version)=($1, $2);
+
+ # store the name without the leading dashes
+ $flag =~ s/^--//;
+
+ # cut out short option (if present)
+ $flag =~ s/ \(-.\)//;
+
+ # store the name without trailing space
+ $flag =~ s/ +$//;
+
+ push @options, $flag;
+
+ # options-in-versions says...
+ $oiv{$flag} = $version;
+ }
+ }
+ return @options;
+}
+
+sub versioncheck {
+ my ($f, $v)=@_;
+ open(F, "<$cmddir/$f.d");
+ while(<F>) {
+ chomp;
+ if(/^Added: ([0-9.]+)/) {
+ if($1 ne $v) {
+ print STDERR "$f lists $v in doc but $1 in file\n";
+ $error++;
+ }
+ last;
+ }
+ }
+ close(F);
+}
+
+# get all the files
+my @cmdopts = cmdfiles($cmddir);
+
+# get all the options mentioned in $o
+my @veropts = mentions($opts);
+
+# check if all files are in the doc
+for my $c (sort @cmdopts) {
+ if($oiv{$c}) {
+ # present, but at same version?
+ versioncheck($c, $oiv{$c});
+ }
+ else {
+ print STDERR "$c is in the directory but not in file!\n";
+ $error++;
+ }
+}
+
+# check if the all options in the doc have files
+for my $v (sort @veropts) {
+ if($file{$v}) {
+ # present
+ }
+ else {
+ print STDERR "$v is in the doc but NOT as a file!\n";
+ $error++;
+ }
+}
+
+exit $error;
diff --git a/tests/runtests.1 b/tests/runtests.1
index 26cd3afb9..46ebd6275 100644
--- a/tests/runtests.1
+++ b/tests/runtests.1
@@ -43,7 +43,7 @@ runs all available tests except number 66.
Prefix a test number with a tilde (~) to still run it, but ignore the results.
It is also possible to specify tests based on a keyword describing the test(s)
-to run, like "FTPS". The keywords are strings used in the indiviual tests.
+to run, like "FTPS". The keywords are strings used in the individual tests.
You can also specify keywords with a leading exclamation point and the keyword
or phrase, like "!HTTP NTLM auth" to run all tests \fBexcept\fP those using
diff --git a/tests/runtests.pl.in b/tests/runtests.pl.in
index 2b9650b69..72113e895 100755
--- a/tests/runtests.pl.in
+++ b/tests/runtests.pl.in
@@ -56,8 +56,14 @@
# These should be the only variables that might be needed to get edited:
BEGIN {
- push(@INC, $ENV{'srcdir'}) if(defined $ENV{'srcdir'});
- push(@INC, ".");
+ # Define srcdir to the location of the tests source directory. This is
+ # usually set by the Makefile, but for out-of-tree builds with direct
+ # invocation of runtests.pl, it may not be set.
+ if(!defined $ENV{'srcdir'}) {
+ use File::Basename;
+ $ENV{'srcdir'} = dirname(__FILE__);
+ }
+ push(@INC, $ENV{'srcdir'});
# run time statistics needs Time::HiRes
eval {
no warnings "all";
@@ -131,8 +137,8 @@ my $MQTTPORT=$noport; # MQTT server port
my $HTTPPORT=$noport; # HTTP server port
my $HTTP6PORT=$noport; # HTTP IPv6 server port
my $HTTPSPORT=$noport; # HTTPS (stunnel) server port
+my $HTTPSPROXYPORT = $noport; # HTTPS-proxy (stunnel) port
my $FTPPORT=$noport; # FTP server port
-my $FTP2PORT=$noport; # FTP server 2 port
my $FTPSPORT=$noport; # FTPS (stunnel) server port
my $FTP6PORT=$noport; # FTP IPv6 server port
my $TFTPPORT=$noport; # TFTP
@@ -245,6 +251,7 @@ my $has_charconv; # set if libcurl is built with CharConv support
my $has_tls_srp; # set if libcurl is built with TLS-SRP support
my $has_metalink; # set if curl is built with Metalink support
my $has_http2; # set if libcurl is built with HTTP2 support
+my $has_httpsproxy; # set if libcurl is built with HTTPS-proxy support
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
@@ -560,7 +567,11 @@ sub checkcmd {
#
my $disttests;
sub get_disttests {
- my @dist = `cd data && make show`;
+ my $makeCmd = 'make';
+ if(-f "../CMakeCache.txt") {
+ $makeCmd = 'cmake --build ../.. --target';
+ }
+ my @dist = `cd data && $makeCmd show`;
$disttests = join("", @dist);
}
@@ -1572,8 +1583,6 @@ sub runhttpserver {
logmsg "RUN: $srvrname server is on PID $httppid port $port\n";
}
- sleep(1);
-
return ($httppid, $pid2, $port);
}
@@ -1581,7 +1590,7 @@ sub runhttpserver {
# start the https stunnel based server
#
sub runhttpsserver {
- my ($verbose, $ipv6, $certfile) = @_;
+ my ($verbose, $ipv6, $proxy, $certfile) = @_;
my $proto = 'https';
my $ip = ($ipv6 && ($ipv6 =~ /6$/)) ? "$HOST6IP" : "$HOSTIP";
my $ipvnum = ($ipv6 && ($ipv6 =~ /6$/)) ? 6 : 4;
@@ -1592,6 +1601,11 @@ sub runhttpsserver {
my $logfile;
my $flags = "";
+ if($proxy eq "proxy") {
+ # the https-proxy runs as https2
+ $idnum = 2;
+ }
+
if(!$stunnel) {
return (0,0);
}
@@ -1623,41 +1637,56 @@ sub runhttpsserver {
$flags .= "--ipv$ipvnum --proto $proto ";
$flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
$flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";
- $flags .= "--connect $HTTPPORT --accept $HTTPSPORT";
-
- my $cmd = "$perl $srcdir/secureserver.pl $flags";
- my ($httpspid, $pid2) = startnew($cmd, $pidfile, 15, 0);
-
- if($httpspid <= 0 || !pidexists($httpspid)) {
- # it is NOT alive
- logmsg "RUN: failed to start the $srvrname server\n";
- stopserver($server, "$pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- return(0,0);
+ if(!$proxy) {
+ $flags .= "--connect $HTTPPORT";
}
+ else {
+ # for HTTPS-proxy we connect to the HTTP proxy
+ $flags .= "--connect $HTTPPROXYPORT";
+ }
+
+ my $pid2;
+ my $pid3;
+ my $httpspid;
+ my $port = 24512; # start attempt
+ for (1 .. 10) {
+ $port += int(rand(600));
+ my $options = "$flags --accept $port";
+
+ my $cmd = "$perl $srcdir/secureserver.pl $options";
+ ($httpspid, $pid2) = startnew($cmd, $pidfile, 15, 0);
+
+ if($httpspid <= 0 || !pidexists($httpspid)) {
+ # it is NOT alive
+ logmsg "RUN: failed to start the $srvrname server\n";
+ stopserver($server, "$pid2");
+ displaylogs($testnumcheck);
+ $doesntrun{$pidfile} = 1;
+ next;
+ }
- # Server is up. Verify that we can speak to it.
- my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $HTTPSPORT);
- if(!$pid3) {
- logmsg "RUN: $srvrname server failed verification\n";
- # failed to talk to it properly. Kill the server and return failure
- stopserver($server, "$httpspid $pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- return (0,0);
+ # Server is up. Verify that we can speak to it.
+ $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
+ if(!$pid3) {
+ logmsg "RUN: $srvrname server failed verification\n";
+ # failed to talk to it properly. Kill the server and return failure
+ stopserver($server, "$httpspid $pid2");
+ displaylogs($testnumcheck);
+ $doesntrun{$pidfile} = 1;
+ next;
+ }
+ # we have a server!
+ last;
}
# Here pid3 is actually the pid returned by the unsecure-http server.
$runcert{$server} = $certfile;
if($verbose) {
- logmsg "RUN: $srvrname server is now running PID $httpspid\n";
+ logmsg "RUN: $srvrname server is PID $httpspid port $port\n";
}
- sleep(1);
-
- return ($httpspid, $pid2);
+ return ($httpspid, $pid2, $port);
}
#######################################################################
@@ -1734,8 +1763,6 @@ sub runhttptlsserver {
logmsg "RUN: $srvrname server is now running PID $httptlspid\n";
}
- sleep(1);
-
return ($httptlspid, $pid2);
}
@@ -1819,9 +1846,6 @@ sub runpingpongserver {
# if IPv6, use a different setup
$FTP6PORT = $port;
}
- elsif($idnum>1) {
- $FTP2PORT = $port;
- }
else {
$FTPPORT = $port;
}
@@ -1855,8 +1879,6 @@ sub runpingpongserver {
return 0;
}
- sleep(1);
-
return ($pid2, $ftppid);
}
@@ -1906,41 +1928,47 @@ sub runftpsserver {
$flags .= "--ipv$ipvnum --proto $proto ";
$flags .= "--certfile \"$certfile\" " if($certfile ne 'stunnel.pem');
$flags .= "--stunnel \"$stunnel\" --srcdir \"$srcdir\" ";
- $flags .= "--connect $FTPPORT --accept $FTPSPORT";
-
- my $cmd = "$perl $srcdir/secureserver.pl $flags";
- my ($ftpspid, $pid2) = startnew($cmd, $pidfile, 15, 0);
-
- if($ftpspid <= 0 || !pidexists($ftpspid)) {
- # it is NOT alive
- logmsg "RUN: failed to start the $srvrname server\n";
- stopserver($server, "$pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- return(0,0);
- }
+ $flags .= "--connect $FTPPORT";
+
+ my $port = 26713;
+ my $pid2;
+ my $pid3;
+ my $ftpspid;
+ for (1 .. 10) {
+ $port += int(rand(700));
+ my $options = "$flags --accept $port";
+ my $cmd = "$perl $srcdir/secureserver.pl $options";
+ ($ftpspid, $pid2) = startnew($cmd, $pidfile, 15, 0);
+
+ if($ftpspid <= 0 || !pidexists($ftpspid)) {
+ # it is NOT alive
+ logmsg "RUN: failed to start the $srvrname server\n";
+ stopserver($server, "$pid2");
+ displaylogs($testnumcheck);
+ $doesntrun{$pidfile} = 1;
+ next;
+ }
- # Server is up. Verify that we can speak to it.
- my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $FTPSPORT);
- if(!$pid3) {
- logmsg "RUN: $srvrname server failed verification\n";
- # failed to talk to it properly. Kill the server and return failure
- stopserver($server, "$ftpspid $pid2");
- displaylogs($testnumcheck);
- $doesntrun{$pidfile} = 1;
- return (0,0);
- }
- # Here pid3 is actually the pid returned by the unsecure-ftp server.
+ $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
+ if(!$pid3) {
+ logmsg "RUN: $srvrname server failed verification\n";
+ # failed to talk to it properly. Kill the server and return failure
+ stopserver($server, "$ftpspid $pid2");
+ displaylogs($testnumcheck);
+ $doesntrun{$pidfile} = 1;
+ next;
+ }
+ # Here pid3 is actually the pid returned by the unsecure-ftp server.
- $runcert{$server} = $certfile;
+ $runcert{$server} = $certfile;
- if($verbose) {
- logmsg "RUN: $srvrname server is now running PID $ftpspid\n";
+ if($verbose) {
+ logmsg "RUN: $srvrname server is PID $ftpspid port $port\n";
+ }
+ last;
}
- sleep(1);
-
- return ($ftpspid, $pid2);
+ return ($ftpspid, $pid2, $port);
}
#######################################################################
@@ -2021,8 +2049,6 @@ sub runtftpserver {
logmsg "RUN: $srvrname server on PID $tftppid port $port\n";
}
- sleep(1);
-
return ($pid2, $tftppid, $port);
}
@@ -2105,8 +2131,6 @@ sub runrtspserver {
logmsg "RUN: $srvrname server PID $rtsppid port $port\n";
}
- sleep(1);
-
return ($rtsppid, $pid2, $port);
}
@@ -2117,7 +2141,6 @@ sub runrtspserver {
sub runsshserver {
my ($id, $verbose, $ipv6) = @_;
my $ip=$HOSTIP;
- my $port = $SSHPORT;
my $proto = 'ssh';
my $ipvnum = 4;
my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
@@ -2125,7 +2148,7 @@ sub runsshserver {
my $srvrname;
my $pidfile;
my $logfile;
- my $flags = "";
+ my $port = 20000; # no lower port
$server = servername_id($proto, $ipvnum, $idnum);
@@ -2136,6 +2159,11 @@ sub runsshserver {
return (0,0);
}
+ my $sshd = find_sshd();
+ if($sshd) {
+ ($sshdid,$sshdvernum,$sshdverstr,$sshderror) = sshversioninfo($sshd);
+ }
+
my $pid = processexists($pidfile);
if($pid > 0) {
stopserver($server, "$pid");
@@ -2146,60 +2174,87 @@ sub runsshserver {
$logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum);
+ my $flags = "";
$flags .= "--verbose " if($verbose);
$flags .= "--debugprotocol " if($debugprotocol);
$flags .= "--pidfile \"$pidfile\" ";
$flags .= "--id $idnum " if($idnum > 1);
$flags .= "--ipv$ipvnum --addr \"$ip\" ";
- $flags .= "--sshport $port ";
$flags .= "--user \"$USER\"";
- my $cmd = "$perl $srcdir/sshserver.pl $flags";
- my ($sshpid, $pid2) = startnew($cmd, $pidfile, 60, 0);
+ my $sshpid;
+ my $pid2;
+
+ my $wport = 0,
+ my @tports;
+ for(1 .. 10) {
+
+ # sshd doesn't have a way to pick an unused random port number, so
+ # instead we iterate over possible port numbers to use until we find
+ # one that works
+ $port += int(rand(500));
+ push @tports, $port;
+
+ my $options = "$flags --sshport $port";
+
+ my $cmd = "$perl $srcdir/sshserver.pl $options";
+ ($sshpid, $pid2) = startnew($cmd, $pidfile, 60, 0);
+
+ # on loaded systems sshserver start up can take longer than the
+ # timeout passed to startnew, when this happens startnew completes
+ # without being able to read the pidfile and consequently returns a
+ # zero pid2 above.
+ if($sshpid <= 0 || !pidexists($sshpid)) {
+ # it is NOT alive
+ logmsg "RUN: failed to start the $srvrname server on $port\n";
+ stopserver($server, "$pid2");
+ $doesntrun{$pidfile} = 1;
+ next;
+ }
- # on loaded systems sshserver start up can take longer than the timeout
- # passed to startnew, when this happens startnew completes without being
- # able to read the pidfile and consequently returns a zero pid2 above.
+ # ssh server verification allows some extra time for the server to
+ # start up and gives us the opportunity of recovering the pid from the
+ # pidfile, when this verification succeeds the recovered pid is
+ # assigned to pid2.
- if($sshpid <= 0 || !pidexists($sshpid)) {
- # it is NOT alive
- logmsg "RUN: failed to start the $srvrname server\n";
- stopserver($server, "$pid2");
- $doesntrun{$pidfile} = 1;
- return (0,0);
+ my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
+ if(!$pid3) {
+ logmsg "RUN: $srvrname server failed verification\n";
+ # failed to fetch server pid. Kill the server and return failure
+ stopserver($server, "$sshpid $pid2");
+ $doesntrun{$pidfile} = 1;
+ next;
+ }
+ $pid2 = $pid3;
+
+ # once it is known that the ssh server is alive, sftp server
+ # verification is performed actually connecting to it, authenticating
+ # and performing a very simple remote command. This verification is
+ # tried only one time.
+
+ $sshdlog = server_logfilename($LOGDIR, 'ssh', $ipvnum, $idnum);
+ $sftplog = server_logfilename($LOGDIR, 'sftp', $ipvnum, $idnum);
+
+ if(verifysftp('sftp', $ipvnum, $idnum, $ip, $port) < 1) {
+ logmsg "RUN: SFTP server failed verification\n";
+ # failed to talk to it properly. Kill the server and return failure
+ display_sftplog();
+ display_sftpconfig();
+ display_sshdlog();
+ display_sshdconfig();
+ stopserver($server, "$sshpid $pid2");
+ $doesntrun{$pidfile} = 1;
+ next;
+ }
+ # we're happy, no need to loop anymore!
+ $wport = $port;
+ last;
}
- # ssh server verification allows some extra time for the server to start up
- # and gives us the opportunity of recovering the pid from the pidfile, when
- # this verification succeeds the recovered pid is assigned to pid2.
-
- my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port);
- if(!$pid3) {
- logmsg "RUN: $srvrname server failed verification\n";
- # failed to fetch server pid. Kill the server and return failure
- stopserver($server, "$sshpid $pid2");
- $doesntrun{$pidfile} = 1;
- return (0,0);
- }
- $pid2 = $pid3;
-
- # once it is known that the ssh server is alive, sftp server verification
- # is performed actually connecting to it, authenticating and performing a
- # very simple remote command. This verification is tried only one time.
-
- $sshdlog = server_logfilename($LOGDIR, 'ssh', $ipvnum, $idnum);
- $sftplog = server_logfilename($LOGDIR, 'sftp', $ipvnum, $idnum);
-
- if(verifysftp('sftp', $ipvnum, $idnum, $ip, $port) < 1) {
- logmsg "RUN: SFTP server failed verification\n";
- # failed to talk to it properly. Kill the server and return failure
- display_sftplog();
- display_sftpconfig();
- display_sshdlog();
- display_sshdconfig();
- stopserver($server, "$sshpid $pid2");
- $doesntrun{$pidfile} = 1;
- return (0,0);
+ if(!$wport) {
+ logmsg "RUN: couldn't start $srvrname. Tried these ports:";
+ logmsg "RUN: ".join(", ", @tports);
+ return (0,0,0);
}
my $hstpubmd5f = "curl_host_rsa_key.pub_md5";
@@ -2214,11 +2269,9 @@ sub runsshserver {
die $msg;
}
- if($verbose) {
- logmsg "RUN: $srvrname server is now running PID $pid2\n";
- }
+ logmsg "RUN: $srvrname on PID $pid2 port $wport\n" if($verbose);
- return ($pid2, $sshpid);
+ return ($pid2, $sshpid, $wport);
}
#######################################################################
@@ -2415,8 +2468,6 @@ sub rundictserver {
logmsg "RUN: $srvrname server is now running PID $dictpid\n";
}
- sleep(1);
-
return ($dictpid, $pid2);
}
@@ -2492,8 +2543,6 @@ sub runsmbserver {
logmsg "RUN: $srvrname server is now running PID $smbpid\n";
}
- sleep(1);
-
return ($smbpid, $pid2);
}
@@ -2568,8 +2617,6 @@ sub runnegtelnetserver {
logmsg "RUN: $srvrname server is now running PID $ntelpid\n";
}
- sleep(1);
-
return ($ntelpid, $pid2);
}
@@ -2612,7 +2659,7 @@ sub responsive_pingpong_server {
my $idnum = ($id && ($id =~ /^(\d+)$/) && ($id > 1)) ? $id : 1;
if($proto eq "ftp") {
- $port = ($idnum>1)?$FTP2PORT:$FTPPORT;
+ $port = $FTPPORT;
if($ipvnum==6) {
# if IPv6, use a different setup
@@ -2746,43 +2793,44 @@ sub compare {
}
sub setupfeatures {
- $feature{"SSL"} = $has_ssl;
- $feature{"MultiSSL"} = $has_multissl;
- $feature{"SSLpinning"} = $has_sslpinning;
- $feature{"OpenSSL"} = $has_openssl;
- $feature{"GnuTLS"} = $has_gnutls;
- $feature{"NSS"} = $has_nss;
- $feature{"WinSSL"} = $has_winssl;
- $feature{"Schannel"} = $has_winssl; # alias
- $feature{"sectransp"} = $has_darwinssl;
+ $feature{"alt-svc"} = $has_altsvc;
+ $feature{"brotli"} = $has_brotli;
+ $feature{"crypto"} = $has_crypto;
$feature{"DarwinSSL"} = $has_darwinssl; # alias
- $feature{"ld_preload"} = ($has_ldpreload && !$debug_build);
- $feature{"unittest"} = $debug_build;
$feature{"debug"} = $debug_build;
- $feature{"TrackMemory"} = $has_memory_tracking;
- $feature{"large_file"} = $has_largefile;
+ $feature{"getrlimit"} = $has_getrlimit;
+ $feature{"GnuTLS"} = $has_gnutls;
+ $feature{"GSS-API"} = $has_gssapi;
+ $feature{"http/2"} = $has_http2;
+ $feature{"https-proxy"} = $has_httpsproxy;
$feature{"idn"} = $has_idn;
$feature{"ipv6"} = $has_ipv6;
+ $feature{"Kerberos"} = $has_kerberos;
+ $feature{"large_file"} = $has_largefile;
+ $feature{"ld_preload"} = ($has_ldpreload && !$debug_build);
$feature{"libz"} = $has_libz;
- $feature{"brotli"} = $has_brotli;
+ $feature{"manual"} = $has_manual;
+ $feature{"Metalink"} = $has_metalink;
+ $feature{"MinGW"} = $has_mingw;
+ $feature{"MultiSSL"} = $has_multissl;
+ $feature{"NSS"} = $has_nss;
$feature{"NTLM"} = $has_ntlm;
$feature{"NTLM_WB"} = $has_ntlm_wb;
- $feature{"SSPI"} = $has_sspi;
- $feature{"GSS-API"} = $has_gssapi;
- $feature{"Kerberos"} = $has_kerberos;
+ $feature{"OpenSSL"} = $has_openssl;
+ $feature{"PSL"} = $has_psl;
+ $feature{"Schannel"} = $has_winssl; # alias
+ $feature{"sectransp"} = $has_darwinssl;
$feature{"SPNEGO"} = $has_spnego;
- $feature{"getrlimit"} = $has_getrlimit;
- $feature{"crypto"} = $has_crypto;
- $feature{"TLS-SRP"} = $has_tls_srp;
- $feature{"Metalink"} = $has_metalink;
- $feature{"http/2"} = $has_http2;
+ $feature{"SSL"} = $has_ssl;
+ $feature{"SSLpinning"} = $has_sslpinning;
+ $feature{"SSPI"} = $has_sspi;
$feature{"threaded-resolver"} = $has_threadedres;
- $feature{"PSL"} = $has_psl;
- $feature{"alt-svc"} = $has_altsvc;
- $feature{"manual"} = $has_manual;
+ $feature{"TLS-SRP"} = $has_tls_srp;
+ $feature{"TrackMemory"} = $has_memory_tracking;
+ $feature{"unittest"} = $debug_build;
$feature{"unix-sockets"} = $has_unix;
$feature{"win32"} = $has_win32;
- $feature{"MinGW"} = $has_mingw;
+ $feature{"WinSSL"} = $has_winssl;
# make each protocol an enabled "feature"
for my $p (@protocols) {
@@ -3029,6 +3077,12 @@ sub checksystem {
push @protocols, 'http/2';
}
+ if($feat =~ /HTTPS-proxy/) {
+ $has_httpsproxy=1;
+
+ # 'https-proxy' is used as "server" so consider it a protocol
+ push @protocols, 'https-proxy';
+ }
}
#
# Test harness currently uses a non-stunnel server in order to
@@ -3164,11 +3218,6 @@ sub checksystem {
if($verbose) {
logmsg "* Ports: ";
- if($stunnel) {
- logmsg sprintf("FTPS/%d ", $FTPSPORT);
- logmsg sprintf("HTTPS/%d ", $HTTPSPORT);
- }
- logmsg sprintf("\n* SSH/%d ", $SSHPORT);
if($httptlssrv) {
logmsg sprintf("HTTPTLS/%d ", $HTTPTLSPORT);
if($has_ipv6) {
@@ -3207,7 +3256,6 @@ sub subVariables {
# test server ports
$$thing =~ s/${prefix}FTP6PORT/$FTP6PORT/g;
- $$thing =~ s/${prefix}FTP2PORT/$FTP2PORT/g;
$$thing =~ s/${prefix}FTPSPORT/$FTPSPORT/g;
$$thing =~ s/${prefix}FTPPORT/$FTPPORT/g;
$$thing =~ s/${prefix}GOPHER6PORT/$GOPHER6PORT/g;
@@ -3216,6 +3264,7 @@ sub subVariables {
$$thing =~ s/${prefix}HTTPTLSPORT/$HTTPTLSPORT/g;
$$thing =~ s/${prefix}HTTP6PORT/$HTTP6PORT/g;
$$thing =~ s/${prefix}HTTPSPORT/$HTTPSPORT/g;
+ $$thing =~ s/${prefix}HTTPSPROXYPORT/$HTTPSPROXYPORT/g;
$$thing =~ s/${prefix}HTTP2PORT/$HTTP2PORT/g;
$$thing =~ s/${prefix}HTTPPORT/$HTTPPORT/g;
$$thing =~ s/${prefix}PROXYPORT/$HTTPPROXYPORT/g;
@@ -3258,8 +3307,13 @@ sub subVariables {
if($file_pwd !~ /^\//) {
$file_pwd = "/$file_pwd";
}
+ my $ssh_pwd = $posix_pwd;
+ if ($sshdid && $sshdid =~ /OpenSSH-Windows/) {
+ $ssh_pwd = $file_pwd;
+ }
$$thing =~ s/${prefix}FILE_PWD/$file_pwd/g;
+ $$thing =~ s/${prefix}SSH_PWD/$ssh_pwd/g;
$$thing =~ s/${prefix}SRCDIR/$srcdir/g;
$$thing =~ s/${prefix}USER/$USER/g;
@@ -3718,8 +3772,7 @@ sub singletest {
return -1;
}
my $fileContent = join('', @inputfile);
- subVariables \$fileContent;
-# logmsg "DEBUG: writing file " . $filename . "\n";
+ subVariables(\$fileContent);
open(OUTFILE, ">$filename");
binmode OUTFILE; # for crapage systems, use binary
print OUTFILE $fileContent;
@@ -3987,7 +4040,7 @@ sub singletest {
if(@postcheck) {
$cmd = join("", @postcheck);
chomp $cmd;
- subVariables \$cmd;
+ subVariables(\$cmd);
if($cmd) {
logmsg "postcheck $cmd\n" if($verbose);
my $rc = runclient("$cmd");
@@ -4446,7 +4499,7 @@ sub singletest {
my $duration = sprintf("duration: %02d:%02d",
$sofar/60, $sofar%60);
if(!$automakestyle) {
- logmsg sprintf("OK (%-3d out of %-3d, %s, took %.1fs, %s)\n",
+ logmsg sprintf("OK (%-3d out of %-3d, %s, took %.3fs, %s)\n",
$count, $total, $left, $took, $duration);
}
else {
@@ -4541,20 +4594,6 @@ sub startservers {
$run{$what}="$pid $pid2";
}
}
- elsif($what eq "ftp2") {
- if($torture && $run{'ftp2'} &&
- !responsive_pingpong_server("ftp", "2", $verbose)) {
- stopserver('ftp2');
- }
- if(!$run{'ftp2'}) {
- ($pid, $pid2) = runpingpongserver("ftp", "2", $verbose);
- if($pid <= 0) {
- return "failed starting FTP2 server";
- }
- printf ("* pid ftp2 => %d %d\n", $pid, $pid2) if($verbose);
- $run{'ftp2'}="$pid $pid2";
- }
- }
elsif($what eq "ftp-ipv6") {
if($torture && $run{'ftp-ipv6'} &&
!responsive_pingpong_server("ftp", "", $verbose, "ipv6")) {
@@ -4714,7 +4753,8 @@ sub startservers {
$run{'ftp'}="$pid $pid2";
}
if(!$run{'ftps'}) {
- ($pid, $pid2) = runftpsserver($verbose, "", $certfile);
+ ($pid, $pid2, $FTPSPORT) =
+ runftpsserver($verbose, "", $certfile);
if($pid <= 0) {
return "failed starting FTPS server (stunnel)";
}
@@ -4749,7 +4789,8 @@ sub startservers {
$run{'http'}="$pid $pid2";
}
if(!$run{'https'}) {
- ($pid, $pid2) = runhttpsserver($verbose, "", $certfile);
+ ($pid, $pid2, $HTTPSPORT) =
+ runhttpsserver($verbose, "", "", $certfile);
if($pid <= 0) {
return "failed starting HTTPS server (stunnel)";
}
@@ -4758,6 +4799,35 @@ sub startservers {
$run{'https'}="$pid $pid2";
}
}
+ elsif($what eq "https-proxy") {
+ if(!$stunnel) {
+ # we can't run https-proxy tests without stunnel
+ return "no stunnel";
+ }
+ if($runcert{'https-proxy'} &&
+ ($runcert{'https-proxy'} ne $certfile)) {
+ # stop server when running and using a different cert
+ stopserver('https-proxy');
+ }
+
+ # we front the http-proxy with stunnel so we need to make sure the
+ # proxy runs as well
+ my $f = startservers("http-proxy");
+ if($f) {
+ return $f;1
+ }
+
+ if(!$run{'https-proxy'}) {
+ ($pid, $pid2, $HTTPSPROXYPORT) =
+ runhttpsserver($verbose, "", "proxy", $certfile);
+ if($pid <= 0) {
+ return "failed starting HTTPS-proxy (stunnel)";
+ }
+ logmsg sprintf("* pid https-proxy => %d %d\n", $pid, $pid2)
+ if($verbose);
+ $run{'https-proxy'}="$pid $pid2";
+ }
+ }
elsif($what eq "httptls") {
if(!$httptlssrv) {
# for now, we can't run http TLS-EXT tests without gnutls-serv
@@ -4828,7 +4898,7 @@ sub startservers {
}
elsif($what eq "sftp" || $what eq "scp") {
if(!$run{'ssh'}) {
- ($pid, $pid2) = runsshserver("", $verbose);
+ ($pid, $pid2, $SSHPORT) = runsshserver("", $verbose);
if($pid <= 0) {
return "failed starting SSH server";
}
@@ -5110,6 +5180,13 @@ disabledtests("$TESTDIR/DISABLED.local");
# Check options to this test program
#
+# Special case for CMake: replace '${TFLAGS}' by the contents of the
+# environment variable (if any).
+if(@ARGV && $ARGV[-1] eq '${TFLAGS}') {
+ pop @ARGV;
+ push(@ARGV, split(' ', $ENV{'TFLAGS'})) if defined($ENV{'TFLAGS'});
+}
+
my $number=0;
my $fromnum=-1;
my @testthis;
@@ -5394,9 +5471,6 @@ if ($gdbthis) {
}
$minport = $base; # original base port number
-$HTTPSPORT = $base++; # HTTPS (stunnel) server port
-$FTPSPORT = $base++; # FTPS (stunnel) server port
-$SSHPORT = $base++; # SSH (SCP/SFTP) port
$HTTPTLSPORT = $base++; # HTTP TLS (non-stunnel) server port
$HTTPTLS6PORT = $base++; # HTTP TLS (non-stunnel) IPv6 server port
$HTTP2PORT = $base++; # HTTP/2 port
@@ -5447,7 +5521,7 @@ sub disabledtests {
my ($n) = $1;
$disabled{$n}=$n; # disable this test number
if(! -f "$srcdir/data/test$n") {
- print STDERR "WARNING! Non-exiting test $n in DISABLED!\n";
+ print STDERR "WARNING! Non-existing test $n in DISABLED!\n";
# fail hard to make user notice
exit 1;
}
diff --git a/tests/secureserver.pl.in b/tests/secureserver.pl.in
index 59234aed1..bf6fc079a 100755
--- a/tests/secureserver.pl.in
+++ b/tests/secureserver.pl.in
@@ -344,7 +344,7 @@ if($tstunnel_windows) {
# Put an "exec" in front of the command so that the child process
# keeps this child's process ID by being tied to the spawned shell.
exec("exec $cmd") || die "Can't exec() $cmd: $!";
- # exec() will create a new process, but ties the existance of the
+ # exec() will create a new process, but ties the existence of the
# new process to the parent waiting perl.exe and sh.exe processes.
# exec() should never return back here to this process. We protect
diff --git a/tests/server/CMakeLists.txt b/tests/server/CMakeLists.txt
index 71054a462..e07abf6fa 100644
--- a/tests/server/CMakeLists.txt
+++ b/tests/server/CMakeLists.txt
@@ -26,7 +26,8 @@ if(MSVC)
endif()
function(SETUP_EXECUTABLE TEST_NAME) # ARGN are the files in the test
- add_executable(${TEST_NAME} ${ARGN})
+ add_executable(${TEST_NAME} EXCLUDE_FROM_ALL ${ARGN})
+ add_dependencies(testdeps ${TEST_NAME})
string(TOUPPER ${TEST_NAME} UPPER_TEST_NAME)
include_directories(
diff --git a/tests/server/Makefile.inc b/tests/server/Makefile.inc
index fb13d79cb..55bc3a737 100644
--- a/tests/server/Makefile.inc
+++ b/tests/server/Makefile.inc
@@ -28,14 +28,20 @@ CURLX_SRCS = \
../../lib/nonblock.c \
../../lib/strtoofft.c \
../../lib/warnless.c \
- ../../lib/curl_ctype.c
+ ../../lib/curl_ctype.c \
+ ../../lib/dynbuf.c \
+ ../../lib/strdup.c \
+ ../../lib/curl_multibyte.c
CURLX_HDRS = \
../../lib/curlx.h \
../../lib/nonblock.h \
../../lib/strtoofft.h \
../../lib/warnless.h \
- ../../lib/curl_ctype.h
+ ../../lib/curl_ctype.h \
+ ../../lib/dynbuf.h \
+ ../../lib/strdup.h \
+ ../../lib/curl_multibyte.h
USEFUL = \
getpart.c \
diff --git a/tests/server/sockfilt.c b/tests/server/sockfilt.c
index 84c72f960..6b3758c94 100644
--- a/tests/server/sockfilt.c
+++ b/tests/server/sockfilt.c
@@ -75,7 +75,7 @@
* structured and well behaved manner to achieve proper program cleanup and
* termination.
*
- * Even with the above mechanism implemented it is worthwile to note that
+ * Even with the above mechanism implemented it is worthwhile to note that
* other signals might still be received, or that there might be systems on
* which it is not possible to trap and ignore some of the above signals.
* This implies that for increased portability and reliability the program
@@ -676,7 +676,7 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
}
/* allocate internal array for the internal event handles */
- handles = calloc(nfds, sizeof(HANDLE));
+ handles = calloc(nfds + 1, sizeof(HANDLE));
if(handles == NULL) {
CloseHandle(abort);
CloseHandle(mutex);
@@ -687,7 +687,7 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
/* loop over the handles in the input descriptor sets */
nfd = 0; /* number of handled file descriptors */
- nth = 0; /* number of interal waiting threads */
+ nth = 0; /* number of internal waiting threads */
nws = 0; /* number of handled WINSOCK sockets */
for(fd = 0; fd < nfds; fd++) {
wsasock = curlx_sitosk(fd);
@@ -785,8 +785,18 @@ static int select_ws(int nfds, fd_set *readfds, fd_set *writefds,
}
}
+ /* wait on the number of handles */
+ wait = nfd;
+
+ /* make sure we stop waiting on exit signal event */
+ if(exit_event) {
+ /* we allocated handles nfds + 1 for this */
+ handles[nfd] = exit_event;
+ wait += 1;
+ }
+
/* wait for one of the internal handles to trigger */
- wait = WaitForMultipleObjectsEx(nfd, handles, FALSE, timeout_ms, FALSE);
+ wait = WaitForMultipleObjectsEx(wait, handles, FALSE, timeout_ms, FALSE);
/* wait for internal mutex to lock event handling in threads */
WaitForSingleObjectEx(mutex, INFINITE, FALSE);
diff --git a/tests/server/sws.c b/tests/server/sws.c
index 48ea26d5e..b0f2a83d6 100644
--- a/tests/server/sws.c
+++ b/tests/server/sws.c
@@ -154,6 +154,10 @@ const char *serverlogfile = DEFAULT_LOGFILE;
#define REQUEST_PROXY_DUMP "log/proxy.input"
#define RESPONSE_PROXY_DUMP "log/proxy.response"
+/* file in which additional instructions may be found */
+#define DEFAULT_CMDFILE "log/ftpserver.cmd"
+const char *cmdfile = DEFAULT_CMDFILE;
+
/* very-big-path support */
#define MAXDOCNAMELEN 140000
#define MAXDOCNAMELEN_TXT "139999"
@@ -231,6 +235,24 @@ static bool socket_domain_is_ip(void)
}
}
+/* parse the file on disk that might have a test number for us */
+static int parse_cmdfile(struct httprequest *req)
+{
+ int testnum = DOCNUMBER_NOTHING;
+ char buf[256];
+ FILE *f = fopen(cmdfile, FOPEN_READTEXT);
+ if(f) {
+ while(fgets(buf, sizeof(buf), f)) {
+ if(1 == sscanf(buf, "Testnum %d", &testnum)) {
+ logmsg("[%s] cmdfile says testnum %d", cmdfile, testnum);
+ req->testno = testnum;
+ }
+ }
+ fclose(f);
+ }
+ return 0;
+}
+
/* based on the testno, parse the correct server commands */
static int parse_servercmd(struct httprequest *req)
{
@@ -488,34 +510,41 @@ static int ProcessRequest(struct httprequest *req)
/* get the number after it */
if(ptr) {
+ long num;
ptr++; /* skip the dot */
- req->testno = strtol(ptr, &ptr, 10);
+ num = strtol(ptr, &ptr, 10);
- if(req->testno > 10000) {
- req->partno = req->testno % 10000;
- req->testno /= 10000;
+ if(num) {
+ req->testno = num;
+ if(req->testno > 10000) {
+ req->partno = req->testno % 10000;
+ req->testno /= 10000;
- logmsg("found test %d in requested host name", req->testno);
+ logmsg("found test %d in requested host name", req->testno);
+ }
+ else
+ req->partno = 0;
}
- else
- req->partno = 0;
-
- msnprintf(logbuf, sizeof(logbuf),
- "Requested test number %ld part %ld (from host name)",
- req->testno, req->partno);
- logmsg("%s", logbuf);
+ if(req->testno != DOCNUMBER_NOTHING) {
+ logmsg("Requested test number %ld part %ld (from host name)",
+ req->testno, req->partno);
+ }
}
+ }
- if(!req->testno) {
- logmsg("Did not find test number in PATH");
- req->testno = DOCNUMBER_404;
- }
- else
- parse_servercmd(req);
+ if(req->testno == DOCNUMBER_NOTHING)
+ /* might get the test number */
+ parse_cmdfile(req);
+
+ if(req->testno == DOCNUMBER_NOTHING) {
+ logmsg("Did not find test number in PATH");
+ req->testno = DOCNUMBER_404;
}
+ else
+ parse_servercmd(req);
}
else if((req->offset >= 3) && (req->testno == DOCNUMBER_NOTHING)) {
logmsg("** Unusual request. Starts with %02x %02x %02x (%c%c%c)",
@@ -1886,6 +1915,11 @@ int main(int argc, char *argv[])
if(argc>arg)
serverlogfile = argv[arg++];
}
+ else if(!strcmp("--cmdfile", argv[arg])) {
+ arg++;
+ if(argc>arg)
+ cmdfile = argv[arg++];
+ }
else if(!strcmp("--gopher", argv[arg])) {
arg++;
use_gopher = TRUE;
@@ -2172,6 +2206,7 @@ int main(int argc, char *argv[])
fd_set output;
struct timeval timeout = {0, 250000L}; /* 250 ms */
curl_socket_t maxfd = (curl_socket_t)-1;
+ int active;
/* Clear out closed sockets */
for(socket_idx = num_sockets - 1; socket_idx >= 1; --socket_idx) {
@@ -2219,6 +2254,7 @@ int main(int argc, char *argv[])
/* Timed out - try again */
continue;
}
+ active = rc; /* a positive number */
/* Check if the listening socket is ready to accept */
if(FD_ISSET(all_sockets[0], &input)) {
@@ -2230,11 +2266,13 @@ int main(int argc, char *argv[])
if(CURL_SOCKET_BAD == msgsock)
goto sws_cleanup;
} while(msgsock > 0);
+ active--;
}
/* Service all connections that are ready */
- for(socket_idx = 1; socket_idx < num_sockets; ++socket_idx) {
+ for(socket_idx = 1; (socket_idx < num_sockets) && active; ++socket_idx) {
if(FD_ISSET(all_sockets[socket_idx], &input)) {
+ active--;
if(got_exit_signal)
goto sws_cleanup;
diff --git a/tests/server/tftpd.c b/tests/server/tftpd.c
index 0c0e9bedf..4215bfe4a 100644
--- a/tests/server/tftpd.c
+++ b/tests/server/tftpd.c
@@ -78,7 +78,9 @@
#include <sys/filio.h>
#endif
+#ifdef HAVE_SETJMP_H
#include <setjmp.h>
+#endif
#ifdef HAVE_PWD_H
#include <pwd.h>
@@ -1183,8 +1185,9 @@ static void sendtftp(struct testcase *test, struct formats *pf)
}
send_data:
+ logmsg("write");
if(swrite(peer, sdp, size + 4) != size + 4) {
- logmsg("write");
+ logmsg("write: fail");
return;
}
read_ahead(test, pf->f_convert);
@@ -1192,7 +1195,9 @@ static void sendtftp(struct testcase *test, struct formats *pf)
#ifdef HAVE_ALARM
alarm(rexmtval); /* read the ack */
#endif
+ logmsg("read");
n = sread(peer, &ackbuf.storage[0], sizeof(ackbuf.storage));
+ logmsg("read: %zd", n);
#ifdef HAVE_ALARM
alarm(0);
#endif
@@ -1252,8 +1257,9 @@ static void recvtftp(struct testcase *test, struct formats *pf)
(void) sigsetjmp(timeoutbuf, 1);
#endif
send_ack:
+ logmsg("write");
if(swrite(peer, &ackbuf.storage[0], 4) != 4) {
- logmsg("write: fail\n");
+ logmsg("write: fail");
goto abort;
}
write_behind(test, pf->f_convert);
@@ -1261,14 +1267,16 @@ send_ack:
#ifdef HAVE_ALARM
alarm(rexmtval);
#endif
+ logmsg("read");
n = sread(peer, rdp, PKTSIZE);
+ logmsg("read: %zd", n);
#ifdef HAVE_ALARM
alarm(0);
#endif
if(got_exit_signal)
goto abort;
if(n < 0) { /* really? */
- logmsg("read: fail\n");
+ logmsg("read: fail");
goto abort;
}
rdp->th_opcode = ntohs((unsigned short)rdp->th_opcode);
diff --git a/tests/server/util.c b/tests/server/util.c
index f576b9c23..577a56cb2 100644
--- a/tests/server/util.c
+++ b/tests/server/util.c
@@ -199,7 +199,7 @@ FILE *test2fopen(long testno)
FILE *stream;
char filename[256];
/* first try the alternative, preprocessed, file */
- msnprintf(filename, sizeof(filename), ALTTEST_DATA_PATH, path, testno);
+ msnprintf(filename, sizeof(filename), ALTTEST_DATA_PATH, ".", testno);
stream = fopen(filename, "rb");
if(stream)
return stream;
@@ -290,7 +290,7 @@ int write_pidfile(const char *filename)
#endif
fprintf(pidfile, "%" CURL_FORMAT_CURL_OFF_T "\n", pid);
fclose(pidfile);
- logmsg("Wrote pid %ld to %s", pid, filename);
+ logmsg("Wrote pid %" CURL_FORMAT_CURL_OFF_T " to %s", pid, filename);
return 1; /* success */
}
@@ -580,6 +580,11 @@ volatile int got_exit_signal = 0;
/* if next is set indicates the first signal handled in exit_signal_handler */
volatile int exit_signal = 0;
+#ifdef WIN32
+/* event which if set indicates that the program should finish */
+HANDLE exit_event = NULL;
+#endif
+
/* signal handler that will be triggered to indicate that the program
* should finish its execution in a controlled manner as soon as possible.
* The first time this is called it will set got_exit_signal to one and
@@ -592,6 +597,10 @@ static RETSIGTYPE exit_signal_handler(int signum)
if(got_exit_signal == 0) {
got_exit_signal = 1;
exit_signal = signum;
+#ifdef WIN32
+ if(exit_event)
+ (void)SetEvent(exit_event);
+#endif
}
(void)signal(signum, exit_signal_handler);
errno = old_errno;
@@ -632,7 +641,7 @@ static BOOL WINAPI ctrl_event_handler(DWORD dwCtrlType)
}
if(signum) {
logmsg("ctrl_event_handler: %d -> %d", dwCtrlType, signum);
- exit_signal_handler(signum);
+ raise(signum);
}
return TRUE;
}
@@ -656,7 +665,7 @@ static LRESULT CALLBACK main_window_proc(HWND hwnd, UINT uMsg,
}
if(signum) {
logmsg("main_window_proc: %d -> %d", uMsg, signum);
- exit_signal_handler(signum);
+ raise(signum);
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
@@ -712,6 +721,12 @@ static DWORD WINAPI main_window_loop(LPVOID lpParameter)
void install_signal_handlers(bool keep_sigalrm)
{
+#ifdef WIN32
+ /* setup windows exit event before any signal can trigger */
+ exit_event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if(!exit_event)
+ logmsg("cannot create exit event");
+#endif
#ifdef SIGHUP
/* ignore SIGHUP signal */
old_sighup_handler = signal(SIGHUP, SIG_IGN);
@@ -803,8 +818,19 @@ void restore_signal_handlers(bool keep_sigalrm)
#ifdef WIN32
(void)SetConsoleCtrlHandler(ctrl_event_handler, FALSE);
if(thread_main_window && thread_main_id) {
- if(PostThreadMessage(thread_main_id, WM_APP, 0, 0))
- (void)WaitForSingleObjectEx(thread_main_window, INFINITE, TRUE);
+ if(PostThreadMessage(thread_main_id, WM_APP, 0, 0)) {
+ if(WaitForSingleObjectEx(thread_main_window, INFINITE, TRUE)) {
+ if(CloseHandle(thread_main_window)) {
+ thread_main_window = NULL;
+ thread_main_id = 0;
+ }
+ }
+ }
+ }
+ if(exit_event) {
+ if(CloseHandle(exit_event)) {
+ exit_event = NULL;
+ }
}
#endif
}
diff --git a/tests/server/util.h b/tests/server/util.h
index 73f5f45f6..629539205 100644
--- a/tests/server/util.h
+++ b/tests/server/util.h
@@ -38,6 +38,8 @@ extern const char *path;
/* global variable, log file name */
extern const char *serverlogfile;
+extern const char *cmdfile;
+
#if defined(WIN32) || defined(_WIN32)
#include <process.h>
#include <fcntl.h>
@@ -70,6 +72,11 @@ extern volatile int got_exit_signal;
/* global variable which if set indicates the first signal handled */
extern volatile int exit_signal;
+#ifdef WIN32
+/* global event which if set indicates that the program should finish */
+extern HANDLE exit_event;
+#endif
+
void install_signal_handlers(bool keep_sigalrm);
void restore_signal_handlers(bool keep_sigalrm);
diff --git a/tests/sshserver.pl.in b/tests/sshserver.pl.in
index 0190281c2..a976bb4b6 100644
--- a/tests/sshserver.pl.in
+++ b/tests/sshserver.pl.in
@@ -1120,7 +1120,7 @@ if ($sshdid =~ /OpenSSH-Windows/) {
# Put an "exec" in front of the command so that the child process
# keeps this child's process ID by being tied to the spawned shell.
exec("exec $cmd") || die "Can't exec() $cmd: $!";
- # exec() will create a new process, but ties the existance of the
+ # exec() will create a new process, but ties the existence of the
# new process to the parent waiting perl.exe and sh.exe processes.
# exec() should never return back here to this process. We protect
diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index 51a642f39..c5def5328 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -20,6 +20,9 @@
#
###########################################################################
+# TODO build a special libcurlu library for unittests.
+return()
+
set(UT_SRC
unit1300.c
unit1301.c
@@ -58,20 +61,9 @@ include_directories(
foreach(_testfile ${UT_SRC})
get_filename_component(_testname ${_testfile} NAME_WE)
- add_executable(${_testname} ${_testfile} ${UT_COMMON_FILES})
+ add_executable(${_testname} EXCLUDE_FROM_ALL ${_testfile} ${UT_COMMON_FILES})
+ #add_dependencies(testdeps ${_testname})
target_link_libraries(${_testname} libgnurl ${CURL_LIBS})
set_target_properties(${_testname}
PROPERTIES COMPILE_DEFINITIONS "UNITTESTS")
-
- if(HIDES_CURL_PRIVATE_SYMBOLS)
- set_target_properties(${_testname}
- PROPERTIES
- EXCLUDE_FROM_ALL TRUE
- EXCLUDE_FROM_DEFAULT_BUILD TRUE
- )
- else()
- add_test(NAME ${_testname}
- COMMAND ${_testname} "http://www.google.com"
- )
- endif()
endforeach()
diff --git a/tests/unit/unit1305.c b/tests/unit/unit1305.c
index 6e4bbb861..50f6da8bb 100644
--- a/tests/unit/unit1305.c
+++ b/tests/unit/unit1305.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -73,26 +73,21 @@ static void unit_stop(void)
curl_global_cleanup();
}
-static Curl_addrinfo *fake_ai(void)
+static struct Curl_addrinfo *fake_ai(void)
{
- static Curl_addrinfo *ai;
+ static struct Curl_addrinfo *ai;
+ static const char dummy[]="dummy";
+ size_t namelen = sizeof(dummy); /* including the zero terminator */
- ai = calloc(1, sizeof(Curl_addrinfo));
+ ai = calloc(1, sizeof(struct Curl_addrinfo) + sizeof(struct sockaddr_in) +
+ namelen);
if(!ai)
return NULL;
- ai->ai_canonname = strdup("dummy");
- if(!ai->ai_canonname) {
- free(ai);
- return NULL;
- }
-
- ai->ai_addr = calloc(1, sizeof(struct sockaddr_in));
- if(!ai->ai_addr) {
- free(ai->ai_canonname);
- free(ai);
- return NULL;
- }
+ ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
+ ai->ai_canonname = (void *)((char *)ai->ai_addr +
+ sizeof(struct sockaddr_in));
+ memcpy(ai->ai_canonname, dummy, namelen);
ai->ai_family = AF_INET;
ai->ai_addrlen = sizeof(struct sockaddr_in);
diff --git a/tests/unit/unit1309.c b/tests/unit/unit1309.c
index 9d885389d..880530313 100644
--- a/tests/unit/unit1309.c
+++ b/tests/unit/unit1309.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -35,7 +35,7 @@ static void unit_stop(void)
}
-static void splayprint(struct Curl_tree * t, int d, char output)
+static void splayprint(struct Curl_tree *t, int d, char output)
{
struct Curl_tree *node;
int i;
diff --git a/tests/unit/unit1604.c b/tests/unit/unit1604.c
index c285ced43..9c4f77670 100644
--- a/tests/unit/unit1604.c
+++ b/tests/unit/unit1604.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -78,7 +78,7 @@ struct data {
const char *input;
int flags;
const char *expected_output;
- CURLcode expected_result;
+ SANITIZEcode expected_result;
};
UNITTEST_START
@@ -304,8 +304,9 @@ UNITTEST_START
char *flagstr = NULL;
char *received_ccstr = NULL;
char *expected_ccstr = NULL;
+ SANITIZEcode res;
- CURLcode res = sanitize_file_name(&output, data[i].input, data[i].flags);
+ res = sanitize_file_name(&output, data[i].input, data[i].flags);
if(res == data[i].expected_result &&
((!output && !data[i].expected_output) ||
diff --git a/tests/unit/unit1608.c b/tests/unit/unit1608.c
index 38d5cb278..fc767d1d5 100644
--- a/tests/unit/unit1608.c
+++ b/tests/unit/unit1608.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -24,7 +24,7 @@
#include "hostip.h"
CURLcode Curl_shuffle_addr(struct Curl_easy *data,
- Curl_addrinfo **addr);
+ struct Curl_addrinfo **addr);
#define NUM_ADDRS 8
static struct Curl_addrinfo addrs[NUM_ADDRS];
@@ -48,7 +48,7 @@ UNITTEST_START
{
int i;
CURLcode code;
- struct Curl_addrinfo* addrhead = addrs;
+ struct Curl_addrinfo *addrhead = addrs;
struct Curl_easy *easy = curl_easy_init();
abort_unless(easy, "out of memory");
diff --git a/tests/unit/unit1620.c b/tests/unit/unit1620.c
index 6e572c648..b23e5b912 100644
--- a/tests/unit/unit1620.c
+++ b/tests/unit/unit1620.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -73,10 +73,6 @@ UNITTEST_START
fail_unless(rc == CURLE_OK,
"Curl_parse_login_details() failed");
- rc = Curl_disconnect(empty, empty->conn, FALSE);
- fail_unless(rc == CURLE_OK,
- "Curl_disconnect() with dead_connection set FALSE failed");
-
Curl_freeset(empty);
for(i = (enum dupstring)0; i < STRING_LAST; i++) {
fail_unless(empty->set.str[i] == NULL,
diff --git a/tests/unit/unit1650.c b/tests/unit/unit1650.c
index e656c073a..b2fc89efa 100644
--- a/tests/unit/unit1650.c
+++ b/tests/unit/unit1650.c
@@ -22,6 +22,7 @@
#include "curlcheck.h"
#include "doh.h"
+#include "dynbuf.h"
static CURLcode unit_setup(void)
{
@@ -184,7 +185,7 @@ UNITTEST_START
char *ptr;
size_t len;
int u;
- memset(&d, 0, sizeof(d));
+ de_init(&d);
rc = doh_decode((const unsigned char *)resp[i].packet, resp[i].size,
resp[i].type, &d);
if(rc != resp[i].rc) {
@@ -222,7 +223,7 @@ UNITTEST_START
}
for(u = 0; u < d.numcname; u++) {
size_t o;
- msnprintf(ptr, len, "%s ", d.cname[u].alloc);
+ msnprintf(ptr, len, "%s ", Curl_dyn_ptr(&d.cname[u]));
o = strlen(ptr);
len -= o;
ptr += o;
diff --git a/tests/unit/unit1654.c b/tests/unit/unit1654.c
index d05d0b214..79e97631c 100644
--- a/tests/unit/unit1654.c
+++ b/tests/unit/unit1654.c
@@ -60,69 +60,72 @@ UNITTEST_START
curl = curl_easy_init();
if(!curl)
goto fail;
- fail_unless(asi->num == 4, "wrong number of entries");
+ fail_unless(asi->list.size == 4, "wrong number of entries");
msnprintf(outname, sizeof(outname), "%s-out", arg);
- result = Curl_altsvc_parse(curl, asi, "h2=\"example.com:8080\"",
+ result = Curl_altsvc_parse(curl, asi, "h2=\"example.com:8080\"\r\n",
ALPN_h1, "example.org", 8080);
if(result) {
fprintf(stderr, "Curl_altsvc_parse() failed!\n");
unitfail++;
}
- fail_unless(asi->num == 5, "wrong number of entries");
+ fail_unless(asi->list.size == 5, "wrong number of entries");
- result = Curl_altsvc_parse(curl, asi, "h3=\":8080\"",
+ result = Curl_altsvc_parse(curl, asi, "h3=\":8080\"\r\n",
ALPN_h1, "2.example.org", 8080);
if(result) {
fprintf(stderr, "Curl_altsvc_parse(2) failed!\n");
unitfail++;
}
- fail_unless(asi->num == 6, "wrong number of entries");
+ fail_unless(asi->list.size == 6, "wrong number of entries");
result = Curl_altsvc_parse(curl, asi,
- "h2=\"example.com:8080\", h3=\"yesyes.com\"",
+ "h2=\"example.com:8080\", h3=\"yesyes.com\"\r\n",
ALPN_h1, "3.example.org", 8080);
if(result) {
fprintf(stderr, "Curl_altsvc_parse(3) failed!\n");
unitfail++;
}
/* that one should make two entries */
- fail_unless(asi->num == 8, "wrong number of entries");
+ fail_unless(asi->list.size == 8, "wrong number of entries");
- result = Curl_altsvc_parse(curl, asi, "h2=\"example.com:443\"; ma = 120;",
+ result = Curl_altsvc_parse(curl, asi,
+ "h2=\"example.com:443\"; ma = 120;\r\n",
ALPN_h2, "example.org", 80);
if(result) {
fprintf(stderr, "Curl_altsvc_parse(4) failed!\n");
unitfail++;
}
- fail_unless(asi->num == 9, "wrong number of entries");
+ fail_unless(asi->list.size == 9, "wrong number of entries");
/* quoted 'ma' value */
- result = Curl_altsvc_parse(curl, asi, "h2=\"example.net:443\"; ma=\"180\";",
+ result = Curl_altsvc_parse(curl, asi,
+ "h2=\"example.net:443\"; ma=\"180\";\r\n",
ALPN_h2, "example.net", 80);
if(result) {
fprintf(stderr, "Curl_altsvc_parse(4) failed!\n");
unitfail++;
}
- fail_unless(asi->num == 10, "wrong number of entries");
+ fail_unless(asi->list.size == 10, "wrong number of entries");
- result = Curl_altsvc_parse(curl, asi,
- "h2=\":443\", h3=\":443\"; ma = 120; persist = 1",
- ALPN_h1, "curl.haxx.se", 80);
+ result =
+ Curl_altsvc_parse(curl, asi,
+ "h2=\":443\", h3=\":443\"; ma = 120; persist = 1\r\n",
+ ALPN_h1, "curl.haxx.se", 80);
if(result) {
fprintf(stderr, "Curl_altsvc_parse(5) failed!\n");
unitfail++;
}
- fail_unless(asi->num == 12, "wrong number of entries");
+ fail_unless(asi->list.size == 12, "wrong number of entries");
/* clear that one again and decrease the counter */
- result = Curl_altsvc_parse(curl, asi, "clear;",
+ result = Curl_altsvc_parse(curl, asi, "clear;\r\n",
ALPN_h1, "curl.haxx.se", 80);
if(result) {
fprintf(stderr, "Curl_altsvc_parse(6) failed!\n");
unitfail++;
}
- fail_unless(asi->num == 10, "wrong number of entries");
+ fail_unless(asi->list.size == 10, "wrong number of entries");
Curl_altsvc_save(curl, asi, outname);